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

474 lines
14 KiB
C

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
iplist4.c
Abstract:
Domain Name System (DNS) Library
NT4 version of routines to get IP addresses of stack.
Contents:
Dns_GetIpAddressesNT4
Dns_GetLocalIpAddressArrayNt4
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 SERVICES_KEY "System\\CurrentControlSet\\Services\\"
#define ADAPTER_TCPIP_PARMS_KEY "Parameters\\TCPIP"
#define BIND_VALUE "Bind"
#define DHCP_ENABLED_VALUE "EnableDHCP"
#define DHCP_ADDRESS_VALUE "DhcpIPAddress"
#define DHCP_SUBNET_VALUE "DhcpSubnetMask"
#define STATIC_ADDRESS_VALUE "IPAddress"
#define STATIC_SUBNET_VALUE "SubnetMask"
#define KEY_CONNECT "\\"
#define KEY_CONNECT_CHAR '\\'
#define LINKAGE_KEY "System\\CurrentControlSet\\Services\\Tcpip\\Linkage"
#define BIND_VALUE_TYPE REG_MULTI_SZ
#define DHCP_ENABLED_VALUE_TYPE REG_DWORD
#define DHCP_ADDRESS_VALUE_TYPE REG_SZ
#define DHCP_SUBNET_VALUE_TYPE REG_SZ
#define STATIC_ADDRESS_VALUE_TYPE REG_MULTI_SZ
#define STATIC_SUBNET_VALUE_TYPE REG_MULTI_SZ
typedef DWORD IP_ADDRESS, *PIP_ADDRESS;
typedef struct _ADAPTER_INFO_
{
BOOL IsDhcpEnabled;
PIP_ARRAY pipAddresses;
PIP_ARRAY pipSubnetMasks;
} ADAPTER_INFO, *LPADAPTER_INFO;
extern PIP_ARRAY GetIpArray( BOOL, LPSTR );
extern PIP_ARRAY GetMaskArray( BOOL, LPSTR );
//
// 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
//
/*******************************************************************************
*
* Dns_GetIpAddressesNT4
*
* 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_GetIpAddressesNT4(
IN OUT PDNS_ADDRESS_INFO IpAddressInfoList,
IN DWORD ListCount
)
{
DWORD Error;
DWORD addressCount = 0;
HKEY LinkageKeyHandle = NULL;
LPSTR BindString = NULL;
LPSTR StringPtr;
DWORD StringLen;
DWORD iter, iter2;
DWORD NumberOfNets;
DWORD TotalNumberOfNets;
HKEY AdapterKeyHandle = NULL;
LPSTR IpAddressString = NULL;
LPADAPTER_INFO AdapterInfoList = NULL;
RtlZeroMemory( IpAddressInfoList, sizeof( DNS_ADDRESS_INFO ) * ListCount );
//
// open linkage key in the to determine the the nets we are bound
// to.
//
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
LINKAGE_KEY,
0,
KEY_QUERY_VALUE,
&LinkageKeyHandle );
if( Error != ERROR_SUCCESS )
goto Cleanup;
//
// read BIND value.
//
Error = GetRegistryValue( LinkageKeyHandle,
FALSE,
BIND_VALUE,
BIND_VALUE_TYPE,
(LPBYTE)&BindString );
if ( Error != ERROR_SUCCESS )
goto Cleanup;
RegCloseKey( LinkageKeyHandle );
LinkageKeyHandle = NULL;
//
// determine number of string in BindStrings, that many NETs are
// bound.
//
StringPtr = BindString;
NumberOfNets = 0;
while ( (StringLen = strlen(StringPtr)) != 0 )
{
//
// found another NET.
//
NumberOfNets++;
StringPtr += (StringLen + 1); // move to next string.
}
//
// allocate memory for the ADAPTER_INFO array.
//
AdapterInfoList =
ALLOCATE_HEAP( sizeof(ADAPTER_INFO) * NumberOfNets );
if( AdapterInfoList == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// enum the NETs.
//
TotalNumberOfNets = 0;
for ( iter = 0, StringPtr = BindString;
( ( StringLen = strlen( StringPtr ) ) != 0 );
iter++, StringPtr += ( StringLen + 1 ) )
{
LPSTR AdapterName;
char AdapterParamKey[256];
DWORD EnableDHCPFlag;
//
// open Parameter key of the adapter that is bound to DHCP.
//
AdapterName = strrchr( StringPtr, KEY_CONNECT_CHAR);
if( AdapterName == NULL )
continue;
//
// skip CONNECT_CHAR
//
AdapterName += 1;
if( AdapterName == '\0' )
continue;
strcpy( AdapterParamKey, SERVICES_KEY);
strcat( AdapterParamKey, AdapterName);
strcat( AdapterParamKey, KEY_CONNECT);
strcat( AdapterParamKey, ADAPTER_TCPIP_PARMS_KEY );
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
AdapterParamKey,
0,
KEY_QUERY_VALUE,
&AdapterKeyHandle );
if( Error != ERROR_SUCCESS )
goto Skip;
//
// read DHCPEnableFlag.
//
Error = GetRegistryValue( AdapterKeyHandle,
FALSE,
DHCP_ENABLED_VALUE,
DHCP_ENABLED_VALUE_TYPE,
(LPBYTE)&EnableDHCPFlag );
if ( Error == ERROR_SUCCESS )
{
if ( EnableDHCPFlag )
{
AdapterInfoList[TotalNumberOfNets].IsDhcpEnabled = TRUE;
TryRas:
//
// Get the DHCP IP address value
//
Error = GetRegistryValue( AdapterKeyHandle,
FALSE,
DHCP_ADDRESS_VALUE,
DHCP_ADDRESS_VALUE_TYPE,
(LPBYTE)&IpAddressString );
if( Error != ERROR_SUCCESS )
goto Skip;
AdapterInfoList[TotalNumberOfNets].pipAddresses =
GetIpArray( FALSE, IpAddressString );
if ( IpAddressString )
{
FREE_HEAP( IpAddressString );
IpAddressString = NULL;
}
//
// Get the DHCP subnet mask value
//
Error = GetRegistryValue( AdapterKeyHandle,
FALSE,
DHCP_SUBNET_VALUE,
DHCP_SUBNET_VALUE_TYPE,
(LPBYTE)&IpAddressString );
if ( Error != ERROR_SUCCESS )
{
if ( AdapterInfoList[TotalNumberOfNets].pipAddresses )
{
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
}
goto Skip;
}
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks =
GetMaskArray( FALSE, IpAddressString );
//
// add this adpter to the list only if the ip address is
// non-zero.
//
if ( AdapterInfoList[TotalNumberOfNets].pipAddresses &&
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks )
{
TotalNumberOfNets++;
}
else
{
if ( AdapterInfoList[TotalNumberOfNets].pipAddresses )
{
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
}
if ( AdapterInfoList[TotalNumberOfNets].pipSubnetMasks )
{
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipSubnetMasks );
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks = NULL;
}
}
}
else
{
AdapterInfoList[TotalNumberOfNets].IsDhcpEnabled = FALSE;
//
// Get the Static IP address value(s)
//
Error = GetRegistryValue( AdapterKeyHandle,
FALSE,
STATIC_ADDRESS_VALUE,
STATIC_ADDRESS_VALUE_TYPE,
(LPBYTE)&IpAddressString );
if ( Error != ERROR_SUCCESS )
goto TryRas;
AdapterInfoList[TotalNumberOfNets].pipAddresses =
GetIpArray( TRUE, IpAddressString );
if ( IpAddressString )
{
FREE_HEAP( IpAddressString );
IpAddressString = NULL;
}
//
// Get the Static subnet mask value
//
Error = GetRegistryValue( AdapterKeyHandle,
FALSE,
STATIC_SUBNET_VALUE,
STATIC_SUBNET_VALUE_TYPE,
(LPBYTE)&IpAddressString );
if ( Error != ERROR_SUCCESS )
{
if ( AdapterInfoList[TotalNumberOfNets].pipAddresses )
{
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
}
goto Skip;
}
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks =
GetMaskArray( TRUE, IpAddressString );
//
// add this adpter to the list only if the ip address is
// non-zero.
//
if ( AdapterInfoList[TotalNumberOfNets].pipAddresses &&
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks )
{
TotalNumberOfNets++;
}
else
{
FREE_HEAP( IpAddressString );
IpAddressString = NULL;
if ( AdapterInfoList[TotalNumberOfNets].pipAddresses )
{
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
}
if ( AdapterInfoList[TotalNumberOfNets].pipSubnetMasks )
{
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipSubnetMasks );
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks = NULL;
}
goto TryRas;
}
}
}
Skip :
if ( AdapterKeyHandle )
{
RegCloseKey( AdapterKeyHandle );
AdapterKeyHandle = NULL;
}
if ( IpAddressString )
{
FREE_HEAP( IpAddressString );
IpAddressString = NULL;
}
}
//
// 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--;
}
}
Cleanup:
if( LinkageKeyHandle )
RegCloseKey( LinkageKeyHandle );
if( BindString )
FREE_HEAP( BindString );
if( AdapterKeyHandle )
RegCloseKey( AdapterKeyHandle );
if( IpAddressString )
FREE_HEAP( IpAddressString );
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 iplist4.c
//