windows-nt/Source/XPSP1/NT/ds/dns/dnsapi/iplist9x.c
2020-09-26 16:20:57 +08:00

593 lines
15 KiB
C

/*++
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
//