/*++ Copyright (c) 1994 Microsoft Corporation Module Name: iplist9x.c Abstract: Domain Name System (DNS) Library NT4 version of routines to get IP addresses of stack. Contents: Dns_GetIpAddressesWin9X Dns_GetLocalIpAddressArrayWin9X Author: Glenn A. Curtis (glennc) 05-May-1997 Revision History: 05-May-1997 glennc Copied from the (NT4 SP3) winsock2 directory --*/ // // includes // #include "local.h" #define WIN95_TCPIP_PARAMETERS_KEY "System\\CurrentControlSet\\Services\\VxD\\MSTCP" #define WIN95_DHCP_KEY "System\\CurrentControlSet\\Services\\VxD\\DHCP" #define WIN95_NET_TRANS_KEY "System\\CurrentControlSet\\Services\\Class\\NetTrans" #define DHCP_IP_ADDRESS_VALUE_WIN95 "DhcpIPAddress" #define DHCP_SUBNET_VALUE_WIN95 "DhcpSubnetMask" #define STATIC_ADDRESS_VALUE "IPAddress" #define STATIC_SUBNET_VALUE "IPMask" #define DHCP_INFO_VALUE "DhcpInfo" #define DRIVER_DESCRIPTION_VALUE "DriverDesc" #define TCPIP_DRIVER_DESCRIPTION "TCP/IP" #define NDISWAN_DRIVER_DESCRIPTION "NDISWAN" #define KEY_CONNECT "\\" #define KEY_CONNECT_CHAR '\\' #define DHCP_IP_ADDRESS_VALUE_TYPE_WIN95 REG_DWORD #define DHCP_SUBNET_VALUE_TYPE_WIN95 REG_DWORD #define STATIC_ADDRESS_VALUE_TYPE REG_SZ #define STATIC_SUBNET_VALUE_TYPE REG_SZ #define DHCP_INFO_VALUE_TYPE REG_BINARY #define DRIVER_DESCRIPTION_VALUE_TYPE REG_SZ typedef DWORD IP_ADDRESS, *PIP_ADDRESS; typedef struct _ADAPTER_INFO_ { BOOL IsDhcpEnabled; PIP_ARRAY pipAddresses; PIP_ARRAY pipSubnetMasks; } ADAPTER_INFO, *LPADAPTER_INFO; // // Heap operations // #define ALLOCATE_HEAP(size) Dns_AllocZero( size ) #define REALLOCATE_HEAP(p,size) Dns_Realloc( (p), (size) ) #define FREE_HEAP(p) Dns_Free( p ) #define ALLOCATE_HEAP_ZERO(size) Dns_AllocZero( size ) // // functions // PIP_ARRAY GetIpArray( BOOL IsMultiSzString, LPSTR IpAddressString ) { DWORD NumberOfAddresses; DWORD StringLen; LPSTR StringPtr; DWORD iter; PIP_ARRAY pIpArray = NULL; // // determine number of strings in IpAddressString, that many // addresses are assigned. // StringPtr = IpAddressString; NumberOfAddresses = 0; while ( ( StringLen = strlen( StringPtr ) ) != 0 ) { // // found another NET. // NumberOfAddresses++; if ( IsMultiSzString ) StringPtr += (StringLen + 1); else StringPtr += StringLen; } // // allocate memory for the ADAPTER_INFO array. // pIpArray = ALLOCATE_HEAP_ZERO( sizeof(IP_ADDRESS) * NumberOfAddresses + sizeof(IP_ARRAY) ); if( pIpArray == NULL ) { return NULL; } // // enum the addresses. // StringPtr = IpAddressString; NumberOfAddresses = 0; while ( ( StringLen = strlen( StringPtr ) ) != 0 ) { IP_ADDRESS ip; ip = inet_addr( StringPtr ); if( ip != INADDR_ANY && ip != INADDR_NONE ) { pIpArray->AddrArray[NumberOfAddresses] = ip; NumberOfAddresses++; } if ( IsMultiSzString ) StringPtr += (StringLen + 1); else StringPtr += StringLen; } pIpArray->AddrCount = NumberOfAddresses; if ( pIpArray->AddrCount == 0 ) { FREE_HEAP( pIpArray ); pIpArray = NULL; } return pIpArray; } PIP_ARRAY GetMaskArray( BOOL IsMultiSzString, LPSTR SubnetMaskString ) { DWORD NumberOfAddresses; DWORD StringLen; LPSTR StringPtr; DWORD iter; PIP_ARRAY pIpArray = NULL; // // determine number of strings in SubnetMaskString, that many // addresses are assigned. // StringPtr = SubnetMaskString; NumberOfAddresses = 0; while ( ( StringLen = strlen( StringPtr ) ) != 0 ) { // // found another NET. // NumberOfAddresses++; if ( IsMultiSzString ) StringPtr += (StringLen + 1); else StringPtr += StringLen; } // // allocate memory for the ADAPTER_INFO array. // pIpArray = ALLOCATE_HEAP_ZERO( sizeof(IP_ADDRESS) * NumberOfAddresses + sizeof(IP_ARRAY) ); if( pIpArray == NULL ) { return NULL; } // // enum the addresses. // StringPtr = SubnetMaskString; NumberOfAddresses = 0; while ( ( StringLen = strlen( StringPtr ) ) != 0 ) { IP_ADDRESS ip; ip = inet_addr( StringPtr ); if( ip != INADDR_ANY ) { pIpArray->AddrArray[NumberOfAddresses] = ip; NumberOfAddresses++; } if ( IsMultiSzString ) StringPtr += (StringLen + 1); else StringPtr += StringLen; } pIpArray->AddrCount = NumberOfAddresses; if ( pIpArray->AddrCount == 0 ) { FREE_HEAP( pIpArray ); pIpArray = NULL; } return pIpArray; } /******************************************************************************* * * Dns_GetIpAddressesWin9X * * Retrieves all active IP addresses from all active adapters on this machine. * Returns them as an array * * ENTRY IpAddressList - pointer to array of IP addresses * ListCount - number of IP address IpAddressList can hold * * EXIT IpAddressList - filled with retrieved IP addresses * * RETURNS number of IP addresses retrieved, or 0 if error * * ASSUMES 1. an IP address can be represented in a DWORD * 2. ListCount > 0 * ******************************************************************************/ DWORD Dns_GetIpAddressesWin9X( IN OUT PDNS_ADDRESS_INFO IpAddressInfoList, IN DWORD ListCount ) { DWORD status = NO_ERROR; DWORD addressCount = 0; DWORD iter, iter2; DWORD TotalNumberOfNets; HKEY AdapterKeyHandle = NULL; LPADAPTER_INFO AdapterInfoList = NULL; RtlZeroMemory( IpAddressInfoList, sizeof( DNS_ADDRESS_INFO ) * 10 ); // // allocate memory for the ADAPTER_INFO array. // AdapterInfoList = ALLOCATE_HEAP( sizeof(ADAPTER_INFO) * 10 ); if( !AdapterInfoList ) return 0; // // enum the static and WAN networks. // TotalNumberOfNets = 0; for ( iter = 0; iter < 10; iter++ ) { char AdapterParamKey[256]; DWORD dwFlags = 0; char szCount[4]; LPSTR DriverDescription = NULL; LPSTR IpAddressString = NULL; // // open Parameter key of the adapter that is bound to TCPIP. // sprintf( szCount, "%d", iter ); strcpy( AdapterParamKey, WIN95_NET_TRANS_KEY ); strcat( AdapterParamKey, "\\000" ); strcat( AdapterParamKey, szCount ); status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AdapterParamKey, 0, KEY_QUERY_VALUE, &AdapterKeyHandle ); if ( status != ERROR_SUCCESS ) { AdapterKeyHandle = NULL; goto Skip1; } // // See if this is a TCPIP adapter // status = GetRegistryValue( AdapterKeyHandle, TRUE, DRIVER_DESCRIPTION_VALUE, DRIVER_DESCRIPTION_VALUE_TYPE, (LPBYTE)&DriverDescription ); if ( status != ERROR_SUCCESS || !DriverDescription ) goto Skip1; if ( DriverDescription && strlen( DriverDescription ) == 0 ) { FREE_HEAP( DriverDescription ); goto Skip1; } if ( strcmp( DriverDescription, TCPIP_DRIVER_DESCRIPTION ) ) { FREE_HEAP( DriverDescription ); goto Skip1; } FREE_HEAP( DriverDescription ); // // This is a TCP/IP adapter, now see if there is an address // assigned to it // status = GetRegistryValue( AdapterKeyHandle, TRUE, STATIC_ADDRESS_VALUE, STATIC_ADDRESS_VALUE_TYPE, (LPBYTE)&IpAddressString ); if ( status != ERROR_SUCCESS ) goto Skip1; AdapterInfoList[TotalNumberOfNets].IsDhcpEnabled = FALSE; AdapterInfoList[TotalNumberOfNets].pipAddresses = GetIpArray( FALSE, IpAddressString ); FREE_HEAP( IpAddressString ); IpAddressString = NULL; if ( !AdapterInfoList[TotalNumberOfNets].pipAddresses ) goto Skip1; status = GetRegistryValue( AdapterKeyHandle, TRUE, STATIC_SUBNET_VALUE, STATIC_SUBNET_VALUE_TYPE, (LPBYTE)&IpAddressString ); if ( status != ERROR_SUCCESS ) { FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses ); AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL; goto Skip1; } AdapterInfoList[TotalNumberOfNets].pipSubnetMasks = GetMaskArray( FALSE, IpAddressString ); FREE_HEAP( IpAddressString ); IpAddressString = NULL; if ( !AdapterInfoList[TotalNumberOfNets].pipSubnetMasks ) { FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses ); AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL; goto Skip1; } TotalNumberOfNets++; Skip1 : status = ERROR_SUCCESS; if ( AdapterKeyHandle ) { RegCloseKey( AdapterKeyHandle ); AdapterKeyHandle = NULL; } } if ( TotalNumberOfNets ) goto Exit; // // Loop through each DHCP binding to read the adapter information. // for ( iter = 0; iter < 8; iter++ ) { char AdapterParamKey[256]; DWORD dwFlags = 0; char szCount[4]; DWORD IpAddress = 0; DWORD SubnetMask = 0; // // open Parameter key of the adapter that is bound to DHCP. // sprintf( szCount, "0%d", iter ); strcpy( AdapterParamKey, WIN95_DHCP_KEY ); strcat( AdapterParamKey, "\\DhcpInfo" ); strcat( AdapterParamKey, szCount ); status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AdapterParamKey, 0, KEY_QUERY_VALUE, &AdapterKeyHandle ); if ( status != ERROR_SUCCESS ) { AdapterKeyHandle = NULL; goto Skip2; } status = GetRegistryValue( AdapterKeyHandle, TRUE, DHCP_IP_ADDRESS_VALUE_WIN95, DHCP_IP_ADDRESS_VALUE_TYPE_WIN95, (LPBYTE)&IpAddress ); if ( status != ERROR_SUCCESS ) IpAddress = 0; if ( IpAddress == 0xffffffff ) IpAddress = 0; if ( IpAddress ) { // // It is active, now read the subnet mask // status = GetRegistryValue( AdapterKeyHandle, TRUE, DHCP_SUBNET_VALUE_WIN95, DHCP_SUBNET_VALUE_TYPE_WIN95, (LPBYTE)&SubnetMask ); if ( status != ERROR_SUCCESS ) SubnetMask = 0; } else { LPBYTE DhcpInfo = NULL; // // This may be a Win95 machine, the adapter IP address // is stored in the DhcpInfo blob. // status = GetRegistryValue( AdapterKeyHandle, TRUE, DHCP_INFO_VALUE, DHCP_INFO_VALUE_TYPE, (LPBYTE)&DhcpInfo ); if ( status != ERROR_SUCCESS ) goto Skip2; if ( !DhcpInfo ) goto Skip2; IpAddress = *((LPDWORD)(DhcpInfo+sizeof(DWORD))); SubnetMask = *((LPDWORD)(DhcpInfo+sizeof(DWORD)+sizeof(DWORD))); FREE_HEAP( DhcpInfo ); } if ( IpAddress == 0x00000000 || IpAddress == 0xffffffff ) goto Skip2; AdapterInfoList[TotalNumberOfNets].IsDhcpEnabled = TRUE; AdapterInfoList[TotalNumberOfNets].pipAddresses = Dns_CreateIpArray( 1 ); if ( !AdapterInfoList[TotalNumberOfNets].pipAddresses ) goto Skip2; AdapterInfoList[TotalNumberOfNets].pipAddresses->AddrArray[0] = IpAddress; AdapterInfoList[TotalNumberOfNets].pipSubnetMasks = Dns_CreateIpArray( 1 ); if ( !AdapterInfoList[TotalNumberOfNets].pipSubnetMasks ) { FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses ); AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL; goto Skip2; } AdapterInfoList[TotalNumberOfNets].pipSubnetMasks->AddrArray[0] = SubnetMask; TotalNumberOfNets++; Skip2 : status = ERROR_SUCCESS; if ( AdapterKeyHandle ) { RegCloseKey( AdapterKeyHandle ); AdapterKeyHandle = NULL; } } Exit : // // We now have a data structure that represents the current // net adapters and assigned IP addresses based on the binding // order described by the adapter protocol bindings for TCPIP. // // Now stuff as many as we can into the users buffer provided. // // // Start by putting the first address from each adapter into the // IP list. // for ( iter = 0; iter < TotalNumberOfNets && ListCount; iter++ ) { IpAddressInfoList[addressCount].ipAddress = AdapterInfoList[iter].pipAddresses->AddrArray[0]; IpAddressInfoList[addressCount++].subnetMask = AdapterInfoList[iter].pipSubnetMasks->AddrArray[0]; ListCount--; } for ( iter = 0; iter < TotalNumberOfNets && ListCount; iter++ ) { for ( iter2 = 1; iter2 < AdapterInfoList[iter].pipAddresses->AddrCount; iter2++ ) { IpAddressInfoList[addressCount].ipAddress = AdapterInfoList[iter].pipAddresses->AddrArray[iter2]; IpAddressInfoList[addressCount++].subnetMask = AdapterInfoList[iter].pipSubnetMasks->AddrArray[iter2]; ListCount--; } } if( AdapterKeyHandle ) RegCloseKey( AdapterKeyHandle ); for ( iter = 0; iter < TotalNumberOfNets; iter++ ) { if( AdapterInfoList[iter].pipAddresses ) FREE_HEAP( AdapterInfoList[iter].pipAddresses ); if( AdapterInfoList[iter].pipSubnetMasks ) FREE_HEAP( AdapterInfoList[iter].pipSubnetMasks ); } FREE_HEAP( AdapterInfoList ); AdapterInfoList = NULL; return addressCount; } // // End iplist9x.c //