/*++ Copyright (c) 1996-2000 Microsoft Corporation Module Name: dnsapi.c Abstract: Domain Name System (DNS) API Dnsapi.dll infrastructure (init, shutdown, etc) Routines to access DNS resolver Author: GlennC 22-Jan-1997 Revision History: Jim Gilroy (jamesg) March 2000 cleanup --*/ #include "local.h" #include #define DNS_NET_FAILURE_CACHE_TIME 30 // Seconds // // Global Definitions // // // Globals // CRITICAL_SECTION g_RegistrationListCS; CRITICAL_SECTION g_RegistrationThreadCS; CRITICAL_SECTION g_QueueCS; CRITICAL_SECTION g_NetFailureCS; DWORD g_NetFailureTime; DNS_STATUS g_NetFailureStatus; IP_ADDRESS g_LastDNSServerUpdated = 0; // // Local Function Prototypes // BOOL DnsInitialize( VOID ); VOID DnsCleanup( VOID ); VOID ClearDnsCacheEntry_A ( IN LPSTR, IN WORD ); VOID ClearDnsCacheEntry_W ( IN LPWSTR, IN WORD ); VOID FreeRpcIpAddressList( IN PDNS_IP_ADDR_LIST ); // // System public Network Information // // The dnsapi.dll interface is in config.c // PDNS_NETWORK_INFORMATION CreateNetworkInformation( IN DWORD cAdapterCount ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { PDNS_NETWORK_INFORMATION pNetworkInfo = NULL; DWORD dwAdapterListBufLen = sizeof( DNS_NETWORK_INFORMATION ) - sizeof( PDNS_ADAPTER_INFORMATION ) + ( sizeof( PDNS_ADAPTER_INFORMATION ) * cAdapterCount ); pNetworkInfo = (PDNS_NETWORK_INFORMATION) ALLOCATE_HEAP_ZERO( dwAdapterListBufLen ); return pNetworkInfo; } PDNS_SEARCH_INFORMATION CreateSearchInformation( IN DWORD cNameCount, IN LPSTR pszName ) { PDNS_SEARCH_INFORMATION pSearchInfo = NULL; DWORD dwSearchInfoBufLen = sizeof( DNS_SEARCH_INFORMATION ) - sizeof( LPSTR ) + ( sizeof( LPSTR ) * cNameCount ); if ( ( cNameCount == 0 ) && ( ! pszName ) ) { return NULL; } pSearchInfo = (PDNS_SEARCH_INFORMATION) ALLOCATE_HEAP_ZERO( dwSearchInfoBufLen ); if ( ! pSearchInfo ) { return NULL; } if ( pszName ) { pSearchInfo->pszPrimaryDomainName = Dns_NameCopyAllocate( pszName, 0, DnsCharSetUtf8, DnsCharSetUtf8 ); if ( ! pSearchInfo->pszPrimaryDomainName ) { FREE_HEAP( pSearchInfo ); return NULL; } } return pSearchInfo; } PDNS_SEARCH_INFORMATION CreateSearchInformationCopyFromList( IN PSEARCH_LIST pSearchList ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { PDNS_SEARCH_INFORMATION pSearchInformation; DWORD iter; if ( ! pSearchList ) { return NULL; } pSearchInformation = CreateSearchInformation( pSearchList->NameCount, pSearchList->pszDomainOrZoneName ); if ( ! pSearchInformation ) { return NULL; } for ( iter = 0; iter < pSearchList->NameCount; iter++ ) { if ( pSearchList->SearchNameArray[iter].pszName ) { pSearchInformation->aSearchListNames[iter] = Dns_NameCopyAllocate( pSearchList->SearchNameArray[iter].pszName, 0, DnsCharSetUtf8, DnsCharSetUtf8 ); } if ( pSearchInformation->aSearchListNames[iter] ) { pSearchInformation->cNameCount++; } } return pSearchInformation; } PDNS_ADAPTER_INFORMATION CreateAdapterInformation( IN DWORD cServerCount, IN DWORD dwFlags, IN LPSTR pszDomain, IN LPSTR pszGuidName ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { PDNS_ADAPTER_INFORMATION pAdapter = NULL; DWORD dwAdapterInfoBufLen = sizeof( DNS_ADAPTER_INFORMATION ) - sizeof( DNS_SERVER_INFORMATION ) + ( sizeof( DNS_SERVER_INFORMATION ) * cServerCount ); pAdapter = (PDNS_ADAPTER_INFORMATION) ALLOCATE_HEAP_ZERO( dwAdapterInfoBufLen ); if ( ! pAdapter ) { return NULL; } pAdapter->InfoFlags = dwFlags; pAdapter->cServerCount = 0; if ( pszDomain ) { pAdapter->pszDomain = Dns_NameCopyAllocate( pszDomain, 0, DnsCharSetUtf8, DnsCharSetUtf8 ); } if ( pszGuidName ) { pAdapter->pszAdapterGuidName = Dns_NameCopyAllocate( pszGuidName, 0, DnsCharSetUtf8, DnsCharSetUtf8 ); } return pAdapter; } PDNS_ADAPTER_INFORMATION CreateAdapterInformationCopyFromList( IN PDNS_ADAPTER pAdapter ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { PDNS_ADAPTER_INFORMATION pAdapterInformation; DWORD iter; if ( ! pAdapter ) { return NULL; } pAdapterInformation = CreateAdapterInformation( pAdapter->ServerCount, pAdapter->InfoFlags, pAdapter->pszAdapterDomain, pAdapter->pszAdapterGuidName ); if ( ! pAdapterInformation ) { return NULL; } pAdapterInformation->pIPAddresses = Dns_CreateIpArrayCopy( pAdapter->pAdapterIPAddresses ); pAdapterInformation->pIPSubnetMasks = Dns_CreateIpArrayCopy( pAdapter->pAdapterIPSubnetMasks ); for ( iter = 0; iter < pAdapter->ServerCount; iter++ ) { pAdapterInformation->aipServers[iter].ipAddress = pAdapter->ServerArray[iter].IpAddress; pAdapterInformation->aipServers[iter].Priority = pAdapter->ServerArray[iter].Priority; } pAdapterInformation->cServerCount = pAdapter->ServerCount; return pAdapterInformation ; } PDNS_NETWORK_INFORMATION WINAPI GetNetworkInformation( VOID ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { PDNS_NETINFO pNetInfo = GetNetworkInfo(); DWORD iter; PDNS_NETWORK_INFORMATION pNetworkInformation = NULL; if ( !pNetInfo ) { return NULL; } // // create Network Information of desired size // then copy entire structure // pNetworkInformation = CreateNetworkInformation( pNetInfo->AdapterCount ); if ( ! pNetworkInformation ) { goto Done; } pNetworkInformation->pSearchInformation = CreateSearchInformationCopyFromList( pNetInfo->pSearchList ); for ( iter = 0; iter < pNetInfo->AdapterCount; iter++ ) { pNetworkInformation->aAdapterInfoList[iter] = CreateAdapterInformationCopyFromList( pNetInfo->AdapterArray[iter] ); if ( pNetworkInformation->aAdapterInfoList[iter] ) { pNetworkInformation->cAdapterCount += 1; } } Done: NetInfo_Free( pNetInfo ); return pNetworkInformation; } PDNS_SEARCH_INFORMATION WINAPI GetSearchInformation( VOID ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { PDNS_NETINFO pNetInfo = GetNetworkInfo(); PDNS_SEARCH_INFORMATION pSearchInformation = NULL; if ( !pNetInfo ) { return NULL; } pSearchInformation = CreateSearchInformationCopyFromList( pNetInfo->pSearchList ); NetInfo_Free( pNetInfo ); return pSearchInformation; } VOID WINAPI FreeAdapterInformation( IN PDNS_ADAPTER_INFORMATION pAdapterInformation ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { if ( pAdapterInformation ) { if ( pAdapterInformation->pszAdapterGuidName ) { FREE_HEAP( pAdapterInformation->pszAdapterGuidName ); } if ( pAdapterInformation->pszDomain ) { FREE_HEAP( pAdapterInformation->pszDomain ); } if ( pAdapterInformation->pIPAddresses ) { FREE_HEAP( pAdapterInformation->pIPAddresses ); } if ( pAdapterInformation->pIPSubnetMasks ) { FREE_HEAP( pAdapterInformation->pIPSubnetMasks ); } FREE_HEAP( pAdapterInformation ); } } VOID WINAPI FreeSearchInformation( IN PDNS_SEARCH_INFORMATION pSearchInformation ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { DWORD iter; if ( pSearchInformation ) { if ( pSearchInformation->pszPrimaryDomainName ) { FREE_HEAP( pSearchInformation->pszPrimaryDomainName ); } for ( iter = 0; iter < pSearchInformation->cNameCount; iter++ ) { if ( pSearchInformation->aSearchListNames[iter] ) { FREE_HEAP( pSearchInformation->aSearchListNames[iter] ); } } FREE_HEAP( pSearchInformation ); } } VOID WINAPI FreeNetworkInformation( IN PDNS_NETWORK_INFORMATION pNetworkInformation ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { DWORD iter; if ( pNetworkInformation ) { FreeSearchInformation( pNetworkInformation->pSearchInformation ); for ( iter = 0; iter < pNetworkInformation->cAdapterCount; iter++ ) { FreeAdapterInformation( pNetworkInformation -> aAdapterInfoList[iter] ); } FREE_HEAP( pNetworkInformation ); } } // // Net failure caching // BOOL IsKnownNetFailure( VOID ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { BOOL flag = FALSE; DNSDBG( TRACE, ( "IsKnownNetFailure()\n" )); EnterCriticalSection( &g_NetFailureCS ); if ( g_NetFailureStatus ) { if ( g_NetFailureTime < Dns_GetCurrentTimeInSeconds() ) { g_NetFailureTime = 0; g_NetFailureStatus = ERROR_SUCCESS; flag = FALSE; } else { SetLastError( g_NetFailureStatus ); flag = TRUE; } } LeaveCriticalSection( &g_NetFailureCS ); return flag; } VOID SetKnownNetFailure( IN DNS_STATUS Status ) /*++ Routine Description: None. Arguments: None. Return Value: None. --*/ { DNSDBG( TRACE, ( "SetKnownNetFailure()\n" )); EnterCriticalSection( &g_NetFailureCS ); g_NetFailureTime = Dns_GetCurrentTimeInSeconds() + DNS_NET_FAILURE_CACHE_TIME; g_NetFailureStatus = Status; LeaveCriticalSection( &g_NetFailureCS ); } BOOL WINAPI DnsGetCacheDataTable( OUT PDNS_CACHE_TABLE * ppTable ) /*++ Routine Description: Get cache data table. Arguments: ppTable -- address to receive ptr to cache data table Return Value: ERROR_SUCCES if successful. Error code on failure. --*/ { DNS_STATUS status = ERROR_SUCCESS; DWORD rpcStatus = ERROR_SUCCESS; PDNS_RPC_CACHE_TABLE pcacheTable = NULL; DNSDBG( TRACE, ( "DnsGetCacheDataTable()\n" )); if ( ! ppTable ) { return FALSE; } #if DNSBUILDOLD if ( g_IsWin9X ) { return FALSE; } #endif RpcTryExcept { status = CRrReadCache( NULL, &pcacheTable ); } RpcExcept( DNS_RPC_EXCEPTION_FILTER ) { status = RpcExceptionCode(); } RpcEndExcept // set out param *ppTable = (PDNS_CACHE_TABLE) pcacheTable; #if DBG if ( status != ERROR_SUCCESS ) { DNSDBG( RPC, ( "DnsGetCacheDataTable() status = %d\n", status )); } #endif return( pcacheTable && status == ERROR_SUCCESS ); } BOOL IsLocalIpAddress( IN IP_ADDRESS IpAddress ) // // DCR_FIX: this has no customers other than debug code in update.c // // If wanted this API it should be remoteable -- we could avoid alloc // and include IP6 // { BOOL bfound = FALSE; PIP_ARRAY ipList = Dns_GetLocalIpAddressArray(); DWORD iter; if ( !ipList ) { return bfound; } // // check if IpAddress is in local list // for ( iter = 0; iter < ipList->AddrCount; iter++ ) { if ( IpAddress == ipList->AddrArray[iter] ) { bfound = TRUE; } } FREE_HEAP( ipList ); return bfound; } // // End dnsapi.c //