You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
896 lines
18 KiB
896 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 2001-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
iphelp.c
|
|
|
|
Abstract:
|
|
|
|
IP help API routines.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) January 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
|
|
|
|
|
|
BOOL
|
|
IpHelp_Initialize(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Startup IP Help API
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if started successfully.
|
|
FALSE on error.
|
|
|
|
--*/
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
IpHelp_Cleanup(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleanup IP Help API
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
IpHelp_GetAdaptersInfo(
|
|
OUT PIP_ADAPTER_INFO * ppAdapterInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call IP Help GetAdaptersInfo()
|
|
|
|
Arguments:
|
|
|
|
ppAdapterInfo -- addr to receive pointer to adapter info retrieved
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
DWORD bufferSize;
|
|
INT fretry;
|
|
PIP_ADAPTER_INFO pbuf;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"GetAdaptersInfo( %p )\n",
|
|
ppAdapterInfo ));
|
|
|
|
//
|
|
// init IP Help (no-op) if already done
|
|
//
|
|
|
|
*ppAdapterInfo = NULL;
|
|
|
|
//
|
|
// call down to get buffer size
|
|
//
|
|
// start with reasonable alloc, then bump up if too small
|
|
//
|
|
|
|
fretry = 0;
|
|
bufferSize = 1000;
|
|
|
|
while ( fretry < 2 )
|
|
{
|
|
pbuf = (PIP_ADAPTER_INFO) ALLOCATE_HEAP( bufferSize );
|
|
if ( !pbuf )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Unlock;
|
|
}
|
|
|
|
status = (DNS_STATUS) GetAdaptersInfo(
|
|
pbuf,
|
|
&bufferSize );
|
|
if ( status == NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
FREE_HEAP( pbuf );
|
|
pbuf = NULL;
|
|
|
|
// if buf too small on first try,
|
|
// continue to retry with suggested buffer size
|
|
|
|
if ( status == ERROR_BUFFER_OVERFLOW ||
|
|
status == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
fretry++;
|
|
continue;
|
|
}
|
|
|
|
// any other error is terminal
|
|
|
|
DNSDBG( ANY, (
|
|
"ERROR: GetAdapterInfo() failed with error %d\n",
|
|
status ));
|
|
status = DNS_ERROR_NO_DNS_SERVERS;
|
|
break;
|
|
}
|
|
|
|
DNS_ASSERT( !pbuf || status==NO_ERROR );
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
*ppAdapterInfo = pbuf;
|
|
}
|
|
|
|
Unlock:
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave GetAdaptersInfo() => %d\n",
|
|
status ));
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
IpHelp_GetPerAdapterInfo(
|
|
IN DWORD AdapterIndex,
|
|
OUT PIP_PER_ADAPTER_INFO * ppPerAdapterInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call IP Help GetPerAdapterInfo()
|
|
|
|
Arguments:
|
|
|
|
AdapterIndex -- index of adapter to get info for
|
|
|
|
ppPerAdapterInfo -- addr to receive pointer to per adapter info
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
DWORD bufferSize;
|
|
INT fretry;
|
|
PIP_PER_ADAPTER_INFO pbuf;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"GetPerAdapterInfo( %d, %p )\n",
|
|
AdapterIndex,
|
|
ppPerAdapterInfo ));
|
|
|
|
//
|
|
// init IP Help (no-op) if already done
|
|
//
|
|
|
|
*ppPerAdapterInfo = NULL;
|
|
|
|
//
|
|
// call down to get buffer size
|
|
//
|
|
// start with reasonable alloc, then bump up if too small
|
|
//
|
|
|
|
fretry = 0;
|
|
bufferSize = 1000;
|
|
|
|
while ( fretry < 2 )
|
|
{
|
|
pbuf = (PIP_PER_ADAPTER_INFO) ALLOCATE_HEAP( bufferSize );
|
|
if ( !pbuf )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Unlock;
|
|
}
|
|
|
|
status = (DNS_STATUS) GetPerAdapterInfo(
|
|
AdapterIndex,
|
|
pbuf,
|
|
&bufferSize );
|
|
if ( status == NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
FREE_HEAP( pbuf );
|
|
pbuf = NULL;
|
|
|
|
// if buf too small on first try,
|
|
// continue to retry with suggested buffer size
|
|
|
|
if ( status == ERROR_BUFFER_OVERFLOW ||
|
|
status == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
fretry++;
|
|
continue;
|
|
}
|
|
|
|
// any other error is terminal
|
|
|
|
DNSDBG( ANY, (
|
|
"ERROR: GetAdapterInfo() failed with error %d\n",
|
|
status ));
|
|
status = DNS_ERROR_NO_DNS_SERVERS;
|
|
break;
|
|
}
|
|
|
|
DNS_ASSERT( !pbuf || status==NO_ERROR );
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
*ppPerAdapterInfo = pbuf;
|
|
}
|
|
|
|
Unlock:
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave GetPerAdapterInfo() => %d\n",
|
|
status ));
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
IpHelp_GetBestInterface(
|
|
IN IP4_ADDRESS Ip4Addr,
|
|
OUT PDWORD pdwInterfaceIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call IP Help GetBestInterface()
|
|
|
|
Arguments:
|
|
|
|
Ip4Addr -- IP address to check
|
|
|
|
pdwInterfaceIndex -- addr to recv interface index
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
|
|
DNSDBG( TRACE, (
|
|
"GetBestInterface( %08x, %p )\n",
|
|
Ip4Addr,
|
|
pdwInterfaceIndex ));
|
|
|
|
//
|
|
// init IP Help (no-op) if already done
|
|
//
|
|
|
|
status = (DNS_STATUS) GetBestInterface(
|
|
Ip4Addr,
|
|
pdwInterfaceIndex );
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave GetBestInterface() => %d\n"
|
|
"\tip = %s\n"
|
|
"\tinterface = %d\n",
|
|
status,
|
|
IP4_STRING( Ip4Addr ),
|
|
*pdwInterfaceIndex ));
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
IpHelp_ParseIpAddressString(
|
|
IN OUT PIP4_ARRAY pIpArray,
|
|
IN PIP_ADDR_STRING pIpAddrString,
|
|
IN BOOL fGetSubnetMask,
|
|
IN BOOL fReverse
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build IP array from IP help IP_ADDR_STRING structure.
|
|
|
|
Arguments:
|
|
|
|
pIpArray -- IP array of DNS servers
|
|
|
|
pIpAddrString -- pointer to address info with address data
|
|
|
|
fGetSubnetMask -- get subnet masks
|
|
|
|
fReverse -- reverse the IP array
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
DNS_ERROR_NO_DNS_SERVERS if nothing parsed.
|
|
|
|
--*/
|
|
{
|
|
PIP_ADDR_STRING pipBlob = pIpAddrString;
|
|
IP4_ADDRESS ip;
|
|
DWORD countServers = pIpArray->AddrCount;
|
|
|
|
DNSDBG( TRACE, (
|
|
"IpHelp_ParseIpAddressString()\n"
|
|
"\tout IP array = %p\n"
|
|
"\tIP string = %p\n"
|
|
"\tsubnet? = %d\n"
|
|
"\treverse? = %d\n",
|
|
pIpArray,
|
|
pIpAddrString,
|
|
fGetSubnetMask,
|
|
fReverse ));
|
|
|
|
//
|
|
// loop reading IP or subnet
|
|
//
|
|
// DCR_FIX0: address and subnet will be misaligned if read separately
|
|
//
|
|
// DCR: move to count\allocate model and if getting subnets get together
|
|
//
|
|
|
|
while ( pipBlob &&
|
|
countServers < DNS_MAX_IP_INTERFACE_COUNT )
|
|
{
|
|
if ( fGetSubnetMask )
|
|
{
|
|
ip = inet_addr( pipBlob->IpMask.String );
|
|
|
|
if ( ip != INADDR_ANY )
|
|
{
|
|
pIpArray->AddrArray[ countServers ] = ip;
|
|
countServers++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ip = inet_addr( pipBlob->IpAddress.String );
|
|
|
|
if ( ip != INADDR_ANY && ip != INADDR_NONE )
|
|
{
|
|
pIpArray->AddrArray[ countServers ] = ip;
|
|
countServers++;
|
|
}
|
|
}
|
|
|
|
pipBlob = pipBlob->Next;
|
|
}
|
|
|
|
// reset IP count
|
|
|
|
pIpArray->AddrCount = countServers;
|
|
|
|
// reverse array if desired
|
|
|
|
if ( fReverse )
|
|
{
|
|
Dns_ReverseOrderOfIpArray( pIpArray );
|
|
}
|
|
|
|
DNSDBG( NETINFO, (
|
|
"Leave IpHelp_ParseIpAddressString()\n"
|
|
"\tcount = %d\n"
|
|
"\tfirst IP = %s\n",
|
|
countServers,
|
|
countServers
|
|
? IP_STRING( pIpArray->AddrArray[0] )
|
|
: "" ));
|
|
|
|
return ( pIpArray->AddrCount ) ? ERROR_SUCCESS : DNS_ERROR_NO_DNS_SERVERS;
|
|
}
|
|
|
|
|
|
|
|
PIP_ADAPTER_ADDRESSES
|
|
IpHelp_GetAdaptersAddresses(
|
|
IN ULONG Family,
|
|
IN DWORD Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call IP Help GetAdaptersAddresses
|
|
|
|
Arguments:
|
|
|
|
Family -- address family
|
|
|
|
Flags -- flags
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
INT retry;
|
|
PIP_ADAPTER_ADDRESSES pbuf = NULL;
|
|
DWORD bufSize = 0x1000; // start with 4K
|
|
HMODULE hlib = NULL;
|
|
FARPROC proc;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"GetAdaptersAddresses()\n"
|
|
"\tFamily = %d\n"
|
|
"\tFlags = %08x\n",
|
|
Family,
|
|
Flags ));
|
|
|
|
//
|
|
// init IP Help (no-op) if already done
|
|
//
|
|
|
|
hlib = LoadLibrary( L"iphlpapi.dll" );
|
|
if ( !hlib )
|
|
{
|
|
goto Failed;
|
|
}
|
|
proc = GetProcAddress( hlib, "GetAdaptersAddresses" );
|
|
if ( !proc )
|
|
{
|
|
goto Failed;
|
|
}
|
|
|
|
//
|
|
// call down in loop to allow one buffer resizing
|
|
//
|
|
|
|
retry = 0;
|
|
|
|
while ( 1 )
|
|
{
|
|
// allocate a buffer to hold results
|
|
|
|
if ( pbuf )
|
|
{
|
|
FREE_HEAP( pbuf );
|
|
}
|
|
pbuf = ALLOCATE_HEAP( bufSize );
|
|
if ( !pbuf )
|
|
{
|
|
goto Failed;
|
|
}
|
|
|
|
// call down
|
|
|
|
status = (DNS_STATUS) (*proc)(
|
|
Family,
|
|
Flags,
|
|
NULL, // no reserved,
|
|
pbuf,
|
|
& bufSize );
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
else if ( status != ERROR_BUFFER_OVERFLOW )
|
|
{
|
|
goto Failed;
|
|
}
|
|
|
|
DNSDBG( NETINFO, (
|
|
"Retrying GetAdaptersAddresses() with buffer length %d\n",
|
|
bufSize ));
|
|
|
|
if ( retry != 0 )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
goto Failed;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// success
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave GetAdaptersAddresses() = %p\n",
|
|
pbuf ));
|
|
|
|
IF_DNSDBG( NETINFO )
|
|
{
|
|
DnsDbg_IpAdapterList(
|
|
"IP Help Adapter List",
|
|
pbuf,
|
|
TRUE, // print addrs
|
|
TRUE // print list
|
|
);
|
|
}
|
|
|
|
return pbuf;
|
|
|
|
Failed:
|
|
|
|
FREE_HEAP( pbuf );
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
status = GetLastError();
|
|
}
|
|
DNSDBG( ANY, (
|
|
"Failed GetAdaptersAddresses() => %d\n",
|
|
status ));
|
|
|
|
SetLastError( status );
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
IpHelp_ReadAddrsFromList(
|
|
IN PVOID pAddrList,
|
|
IN BOOL fUnicast,
|
|
IN DWORD ScreenMask, OPTIONAL
|
|
IN DWORD ScreenFlags, OPTIONAL
|
|
OUT PDNS_ADDR_ARRAY * ppComboArray, OPTIONAL
|
|
OUT PDNS_ADDR_ARRAY * pp6OnlyArray, OPTIONAL
|
|
OUT PDNS_ADDR_ARRAY * pp4OnlyArray, OPTIONAL
|
|
OUT PDWORD pCount6, OPTIONAL
|
|
OUT PDWORD pCount4 OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read IP addres from IP help IP_ADAPTER_XXX_ADDRESS list.
|
|
|
|
Arguments:
|
|
|
|
pAddrList -- any IP address list
|
|
PIP_ADAPTER_UNICAST_ADDRESS
|
|
PIP_ADAPTER_ANYCAST_ADDRESS
|
|
PIP_ADAPTER_MULTICAST_ADDRESS
|
|
PIP_ADAPTER_DNS_SERVER_ADDRESS
|
|
|
|
fUnicast -- this is unicast address list
|
|
|
|
ScreenMask -- mask of address flags we care about
|
|
example:
|
|
IP_ADAPTER_ADDRESS_DNS_ELIGIBLE | IP_ADAPTER_ADDRESS_TRANSIENT
|
|
|
|
ScreenFlags -- required state of flags within mask
|
|
example:
|
|
IP_ADAPTER_ADDRESS_DNS_ELIGIBLE
|
|
this (with above mask) would screen for eligible non-cluster addresses
|
|
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
PIP_ADAPTER_UNICAST_ADDRESS pnextAddr;
|
|
PIP_ADAPTER_UNICAST_ADDRESS paddr;
|
|
DNS_STATUS status = NO_ERROR;
|
|
DWORD count4 = 0;
|
|
DWORD count6 = 0;
|
|
DWORD countAll = 0;
|
|
PADDR_ARRAY parrayCombo = NULL;
|
|
PADDR_ARRAY parray6 = NULL;
|
|
PADDR_ARRAY parray4 = NULL;
|
|
DNS_ADDR dnsAddr;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"IpHelp_ReadAddrsFromList( %p )\n",
|
|
pAddrList ));
|
|
|
|
//
|
|
// count
|
|
//
|
|
|
|
pnextAddr = (PIP_ADAPTER_UNICAST_ADDRESS) pAddrList;
|
|
|
|
while ( paddr = pnextAddr )
|
|
{
|
|
PSOCKADDR psa;
|
|
|
|
pnextAddr = paddr->Next;
|
|
|
|
if ( ScreenMask &&
|
|
(ScreenMask & paddr->Flags) != ScreenFlags )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// screen off expired, invalid, bogus
|
|
|
|
if ( fUnicast && paddr->DadState != IpDadStatePreferred )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
psa = paddr->Address.lpSockaddr;
|
|
if ( !psa )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
continue;
|
|
}
|
|
#if 0
|
|
// DCR: temphack -- screen link-local
|
|
if ( SOCKADDR_IS_IP6(psa) )
|
|
{
|
|
if ( IP6_IS_ADDR_LINKLOCAL( (PIP6_ADDRESS)&((PSOCKADDR_IN6)psa)->sin6_addr ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
#endif
|
|
if ( fUnicast && SOCKADDR_IS_LOOPBACK(psa) )
|
|
{
|
|
continue;
|
|
}
|
|
else if ( SOCKADDR_IS_IP6(psa) )
|
|
{
|
|
count6++;
|
|
countAll++;
|
|
}
|
|
else if ( SOCKADDR_IS_IP4(psa) )
|
|
{
|
|
count4++;
|
|
countAll++;
|
|
}
|
|
ELSE_ASSERT_FALSE;
|
|
}
|
|
|
|
//
|
|
// alloc arrays
|
|
//
|
|
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
|
|
if ( ppComboArray )
|
|
{
|
|
if ( countAll )
|
|
{
|
|
parrayCombo = DnsAddrArray_Create( countAll );
|
|
}
|
|
*ppComboArray = parrayCombo;
|
|
if ( !parrayCombo && (countAll) )
|
|
{
|
|
goto Failed;
|
|
}
|
|
}
|
|
if ( pp6OnlyArray )
|
|
{
|
|
if ( count6 )
|
|
{
|
|
parray6 = DnsAddrArray_Create( count6 );
|
|
}
|
|
*pp6OnlyArray = parray6;
|
|
if ( !parray6 && count6 )
|
|
{
|
|
goto Failed;
|
|
}
|
|
}
|
|
if ( pp4OnlyArray )
|
|
{
|
|
if ( count4 )
|
|
{
|
|
parray4 = DnsAddrArray_Create( count4 );
|
|
}
|
|
*pp4OnlyArray = parray4;
|
|
if ( !parray4 && count4 )
|
|
{
|
|
goto Failed;
|
|
}
|
|
}
|
|
|
|
//
|
|
// read addrs into array
|
|
//
|
|
|
|
pnextAddr = (PIP_ADAPTER_UNICAST_ADDRESS) pAddrList;
|
|
|
|
while ( paddr = pnextAddr )
|
|
{
|
|
PSOCKADDR psa;
|
|
DWORD flags = 0;
|
|
DWORD subnetLen = 0;
|
|
|
|
pnextAddr = paddr->Next;
|
|
|
|
if ( ScreenMask &&
|
|
(ScreenMask & paddr->Flags) != ScreenFlags )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// screen off expired, invalid, bogus
|
|
|
|
if ( fUnicast && paddr->DadState != IpDadStatePreferred )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
psa = paddr->Address.lpSockaddr;
|
|
if ( !psa )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
continue;
|
|
}
|
|
|
|
#if 0
|
|
// DCR: temphack -- screen link local
|
|
|
|
if ( SOCKADDR_IS_IP6(psa) &&
|
|
IP6_IS_ADDR_LINKLOCAL( (PIP6_ADDRESS)&((PSOCKADDR_IN6)psa)->sin6_addr ) )
|
|
{
|
|
continue;
|
|
}
|
|
#endif
|
|
// screen off loopback
|
|
|
|
if ( fUnicast && SOCKADDR_IS_LOOPBACK(psa) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// build DNS_ADDR
|
|
//
|
|
// DCR: FIX6: fix subnet length once DaveThaler is in
|
|
//
|
|
|
|
if ( fUnicast )
|
|
{
|
|
flags = paddr->Flags;
|
|
subnetLen = 0;
|
|
#if 0
|
|
// TEST HACK: make transients
|
|
if ( g_DnsTestMode )
|
|
{
|
|
flags |= IP_ADAPTER_ADDRESS_TRANSIENT;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( !DnsAddr_Build(
|
|
& dnsAddr,
|
|
psa,
|
|
0, // any family
|
|
subnetLen,
|
|
flags ) )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// AddrArray_AddSockaddrEx() with flag to choose types to add
|
|
//
|
|
// DCR: not sure we want local IP6 array as DNS_ADDR --
|
|
// maybe just plain IP6
|
|
//
|
|
|
|
if ( parrayCombo )
|
|
{
|
|
DnsAddrArray_AddAddr(
|
|
parrayCombo,
|
|
& dnsAddr,
|
|
0, // any family
|
|
0 // no dup screen
|
|
);
|
|
}
|
|
if ( parray6 )
|
|
{
|
|
DnsAddrArray_AddAddr(
|
|
parray6,
|
|
& dnsAddr,
|
|
AF_INET6, // any family
|
|
0 // no dup screen
|
|
);
|
|
}
|
|
if ( parray4 )
|
|
{
|
|
DnsAddrArray_AddAddr(
|
|
parray4,
|
|
& dnsAddr,
|
|
AF_INET, // any family
|
|
0 // no dup screen
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// set counts
|
|
//
|
|
|
|
if ( pCount6 )
|
|
{
|
|
*pCount6 = count6;
|
|
}
|
|
if ( pCount4 )
|
|
{
|
|
*pCount4 = count4;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
|
|
|
|
Failed:
|
|
|
|
//
|
|
// cleanup any partial allocs
|
|
//
|
|
|
|
DnsAddrArray_Free( parrayCombo );
|
|
DnsAddrArray_Free( parray6 );
|
|
Dns_Free( parray4 );
|
|
|
|
DNS_ASSERT( status != NO_ERROR );
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// End iphelp.c
|
|
//
|
|
|
|
|
|
|