1223 lines
24 KiB
C
1223 lines
24 KiB
C
/*++
|
||
|
||
Copyright (c) 2000-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
localip.c
|
||
|
||
Abstract:
|
||
|
||
Local IP address routines.
|
||
|
||
Author:
|
||
|
||
Jim Gilroy October 2000
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "local.h"
|
||
|
||
//
|
||
// TTL on local records
|
||
//
|
||
// Use registration TTL
|
||
//
|
||
|
||
#define LOCAL_IP_TTL (g_RegistrationTtl)
|
||
|
||
|
||
|
||
|
||
PDNS_ADDR_ARRAY
|
||
GetLocalAddrArrayFromResolver(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get local address info from resolver.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Ptr to address info array from resolver.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
DNS_STATUS rpcStatus;
|
||
PDNS_ADDR_ARRAY paddrArray = NULL;
|
||
ENVAR_DWORD_INFO filterInfo;
|
||
|
||
//
|
||
// get config including environment variable
|
||
//
|
||
|
||
Reg_ReadDwordEnvar(
|
||
RegIdFilterClusterIp,
|
||
&filterInfo );
|
||
|
||
//
|
||
// query resolver
|
||
//
|
||
|
||
RpcTryExcept
|
||
{
|
||
rpcStatus = NO_ERROR;
|
||
R_ResolverGetLocalAddrInfoArray(
|
||
NULL,
|
||
& paddrArray,
|
||
filterInfo
|
||
);
|
||
}
|
||
RpcExcept( DNS_RPC_EXCEPTION_FILTER )
|
||
{
|
||
rpcStatus = RpcExceptionCode();
|
||
}
|
||
RpcEndExcept
|
||
|
||
// return array
|
||
|
||
DNS_ASSERT( !rpcStatus || !paddrArray );
|
||
|
||
return paddrArray;
|
||
}
|
||
|
||
|
||
|
||
PIP4_ARRAY
|
||
LocalIp_GetIp4Array(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get local IP4 address array.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
Ptr to IP4 addresses.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_ADDR_ARRAY paddrArray = NULL;
|
||
PIP4_ARRAY pipArray = NULL;
|
||
DWORD count;
|
||
DWORD i;
|
||
|
||
//
|
||
// addr info array from resolver
|
||
// => build IP array from IPs
|
||
//
|
||
|
||
paddrArray = GetLocalAddrArrayFromResolver();
|
||
if ( paddrArray )
|
||
{
|
||
count = paddrArray->AddrCount;
|
||
if ( count > 0 )
|
||
{
|
||
pipArray = (PIP4_ARRAY) DnsCreateIpArray( count );
|
||
if ( pipArray )
|
||
{
|
||
for ( i=0; i < count; i++ )
|
||
{
|
||
pipArray->AddrArray[i] = paddrArray->AddrArray[i].IpAddr;
|
||
}
|
||
goto Done;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// no array from resolver -- build directly
|
||
// - no chance to filter
|
||
//
|
||
|
||
count = 0;
|
||
pipArray = (PIP4_ARRAY) Dns_GetLocalIpAddressArray();
|
||
if ( pipArray )
|
||
{
|
||
count = pipArray->AddrCount;
|
||
if ( count == 0 )
|
||
{
|
||
FREE_HEAP( pipArray );
|
||
pipArray = NULL;
|
||
}
|
||
}
|
||
|
||
Done:
|
||
|
||
// free blob from resolver
|
||
|
||
if ( paddrArray )
|
||
{
|
||
FREE_HEAP( paddrArray );
|
||
}
|
||
|
||
// set out param
|
||
|
||
return( pipArray );
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
DnsGetIpAddressInfoList(
|
||
OUT PDNS_ADDRESS_INFO * ppAddrInfo
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get local IP4 address info -- include IP and subnet mask.
|
||
|
||
DCR: good to get rid of old DNS_ADDRESS_INFO function
|
||
|
||
Only use of this function is in DHCP, which is calling here rather
|
||
than IP help API for some reason.
|
||
|
||
Arguments:
|
||
|
||
ppAddrInfo -- addr to recv ptr to addr info array;
|
||
caller must free
|
||
|
||
Return Value:
|
||
|
||
Count of IP addresses in array.
|
||
Zero on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_ADDR_ARRAY paddrArray = NULL;
|
||
PDNS_ADDRESS_INFO pnew = NULL;
|
||
PDNS_ADDRESS_INFO pinfo;
|
||
DWORD count;
|
||
DNS_ADDRESS_INFO infoBuffer[256];
|
||
|
||
//
|
||
// addr info array from resolver
|
||
// => build IP array from IPs
|
||
//
|
||
// DCR_WARNING: ADDR_INFO to ADDRESS_INFO conversion
|
||
// if keep this function and change ADDR_INFO for IP6
|
||
// then this quicky hack breaks
|
||
//
|
||
|
||
paddrArray = GetLocalAddrArrayFromResolver();
|
||
if ( paddrArray )
|
||
{
|
||
count = paddrArray->AddrCount;
|
||
pinfo = (PDNS_ADDRESS_INFO) paddrArray->AddrArray;
|
||
}
|
||
|
||
//
|
||
// no array from resolver -- build directly
|
||
//
|
||
|
||
else
|
||
{
|
||
count = Dns_GetIpAddresses( infoBuffer, 256 );
|
||
pinfo = infoBuffer;
|
||
}
|
||
|
||
//
|
||
// allocate result buffer
|
||
// copy addr info array to buffer
|
||
//
|
||
|
||
if ( count )
|
||
{
|
||
DWORD size = count * sizeof(DNS_ADDRESS_INFO);
|
||
|
||
pnew = (PDNS_ADDRESS_INFO) ALLOCATE_HEAP( size );
|
||
if ( !pnew )
|
||
{
|
||
count = 0;
|
||
goto Done;
|
||
}
|
||
RtlCopyMemory(
|
||
pnew,
|
||
pinfo,
|
||
size );
|
||
}
|
||
|
||
Done:
|
||
|
||
// free blob from resolver
|
||
|
||
if ( paddrArray )
|
||
{
|
||
FREE_HEAP( paddrArray );
|
||
}
|
||
|
||
// set out param
|
||
|
||
*ppAddrInfo = pnew;
|
||
return( count );
|
||
}
|
||
|
||
|
||
|
||
PDNS_ADDR_ARRAY
|
||
DnsGetLocalAddrArray(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get local address info array.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Ptr to new addr info array. Caller MUST free.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_ADDR_ARRAY paddrArray;
|
||
|
||
DNSDBG( TRACE, ( "DnsGetLocalAddrArray()\n" ));
|
||
|
||
//
|
||
// addr info array from resolver
|
||
// => build IP array from IPs
|
||
//
|
||
|
||
paddrArray = GetLocalAddrArrayFromResolver();
|
||
if ( paddrArray )
|
||
{
|
||
return paddrArray;
|
||
}
|
||
|
||
//
|
||
// no array from resolver -- build directly
|
||
//
|
||
|
||
return DnsGetLocalAddrArrayDirect();
|
||
}
|
||
|
||
|
||
|
||
|
||
//
|
||
// Direct routines -- build the IP info
|
||
//
|
||
|
||
PDNS_ADDR_ARRAY
|
||
DnsGetLocalAddrArrayDirect(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get local address info array.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Ptr to addr info array.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_ADDRESS_INFO pqueryBuf;
|
||
PDNS_ADDR_ARRAY pnew = NULL;
|
||
DWORD count;
|
||
DWORD size;
|
||
|
||
DNSDBG( TRACE, ( "DnsGetLocalAddrArrayDirect()\n" ));
|
||
|
||
//
|
||
// create big buffer IP help call
|
||
//
|
||
|
||
pqueryBuf = ALLOCATE_HEAP( sizeof(DNS_ADDRESS_INFO) *
|
||
DNS_MAX_IP_INTERFACE_COUNT );
|
||
if ( !pqueryBuf )
|
||
{
|
||
SetLastError( DNS_ERROR_NO_MEMORY );
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// get IP addresses
|
||
// - if zero, determine is error or really no IPs
|
||
//
|
||
|
||
count = Dns_GetIpAddresses(
|
||
pqueryBuf,
|
||
DNS_MAX_IP_INTERFACE_COUNT );
|
||
#if 0
|
||
// don't really need this
|
||
// if can't get count -- it's zero
|
||
// to use this on Win2K would have to change
|
||
// Dns_GetIpAddresses() which is in lib
|
||
if ( count == 0 )
|
||
{
|
||
if ( GetLastError() != NO_ERROR )
|
||
{
|
||
goto Cleanup;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// build correctly sized array
|
||
//
|
||
|
||
size = SIZE_FOR_ADDR_ARRAY( count );
|
||
|
||
pnew = (PDNS_ADDR_ARRAY) ALLOCATE_HEAP( size );
|
||
if ( !pnew )
|
||
{
|
||
SetLastError( DNS_ERROR_NO_MEMORY );
|
||
goto Cleanup;
|
||
}
|
||
|
||
pnew->AddrCount = count;
|
||
|
||
RtlCopyMemory(
|
||
pnew->AddrArray,
|
||
pqueryBuf,
|
||
count * sizeof(DNS_ADDR_INFO)
|
||
);
|
||
|
||
|
||
Cleanup:
|
||
|
||
FREE_HEAP( pqueryBuf );
|
||
|
||
return( pnew );
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Build local records
|
||
//
|
||
|
||
PDNS_RECORD
|
||
GetLocalPtrRecord(
|
||
IN OUT PQUERY_BLOB pBlob
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get pointer record for local IP.
|
||
|
||
Arguments:
|
||
|
||
pBlob -- query blob
|
||
|
||
Uses:
|
||
pNameOrig
|
||
wType
|
||
pNetInfo
|
||
|
||
Sets:
|
||
NameBufferWide -- used as local storage
|
||
|
||
Return Value:
|
||
|
||
Ptr to record for query, if query name\type is IP.
|
||
NULL if query not for IP.
|
||
|
||
--*/
|
||
{
|
||
IP_UNION ipUnion;
|
||
PDNS_RECORD prr;
|
||
IP4_ADDRESS ip4;
|
||
PSTR pnameHost = NULL;
|
||
PSTR pnameDomain;
|
||
PDNS_ADAPTER padapter = NULL;
|
||
DWORD iter;
|
||
DWORD jter;
|
||
DWORD bufLength;
|
||
INT family;
|
||
PSTR pnameQuery = pBlob->pNameOrigWire;
|
||
PDNS_NETINFO pnetInfo = pBlob->pNetworkInfo;
|
||
|
||
|
||
DNSDBG( TRACE, (
|
||
"\nGetLocalPtrRecord( %s )\n",
|
||
pnameQuery ));
|
||
|
||
if ( !pnameQuery )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// convert reverse name to IP
|
||
//
|
||
|
||
bufLength = sizeof(IP6_ADDRESS);
|
||
family = 0;
|
||
|
||
if ( ! Dns_ReverseNameToAddress_A(
|
||
(PCHAR) & ipUnion.Addr,
|
||
& bufLength,
|
||
pnameQuery,
|
||
& family ) )
|
||
{
|
||
DNSDBG( ANY, (
|
||
"WARNING: Ptr lookup name %s is not reverse name!\n",
|
||
pnameQuery ));
|
||
return NULL;
|
||
}
|
||
ipUnion.IsIp6 = (family == AF_INET6 );
|
||
|
||
//
|
||
// check for IP match
|
||
// - first loopback or any
|
||
//
|
||
|
||
if ( ipUnion.IsIp6 )
|
||
{
|
||
if ( IP6_IS_ADDR_UNSPECIFIED( (PIP6_ADDRESS)&ipUnion.Addr ) ||
|
||
IP6_IS_ADDR_LOOPBACK( (PIP6_ADDRESS)&ipUnion.Addr ) )
|
||
{
|
||
goto Matched;
|
||
}
|
||
|
||
// DCR: no IP6 local addresses
|
||
|
||
DNSDBG( QUERY, (
|
||
"Local PTR lookup -- no local IP6 info -- quiting.\n" ));
|
||
return NULL;
|
||
}
|
||
|
||
ip4 = ipUnion.Addr.Ip4;
|
||
|
||
if ( ip4 == DNS_NET_ORDER_LOOPBACK ||
|
||
ip4 == 0 )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Local PTR lookup matched loopback or any.\n" ));
|
||
|
||
goto Matched;
|
||
}
|
||
|
||
//
|
||
// check for cluster match
|
||
//
|
||
// if cluster match, allow query to go to wire
|
||
//
|
||
// DCR: cluster record PTR build for cluster name
|
||
//
|
||
|
||
if ( pBlob->pfnIsClusterIp )
|
||
{
|
||
if ( (pBlob->pfnIsClusterIp)(
|
||
pBlob,
|
||
&ipUnion ) )
|
||
{
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
//
|
||
// check for specific IP match
|
||
//
|
||
|
||
for ( iter = 0;
|
||
iter < pnetInfo->AdapterCount;
|
||
iter ++ )
|
||
{
|
||
PIP_ARRAY parray;
|
||
|
||
padapter = pnetInfo->AdapterArray[iter];
|
||
if ( !padapter )
|
||
{
|
||
continue;
|
||
}
|
||
parray = padapter->pAdapterIPAddresses;
|
||
if ( !parray )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Local PTR lookup -- no IPs for adapter name (%s).\n",
|
||
padapter->pszAdapterDomain ));
|
||
continue;
|
||
}
|
||
|
||
for ( jter = 0;
|
||
jter < parray->AddrCount;
|
||
jter++ )
|
||
{
|
||
if ( parray->AddrArray[jter] == ip4 )
|
||
{
|
||
goto Matched;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// no IP match
|
||
//
|
||
|
||
DNSDBG( QUERY, (
|
||
"Leave local PTR lookup. No local IP match.\n"
|
||
"\treverse name = %s\n",
|
||
pnameQuery ));
|
||
|
||
return NULL;
|
||
|
||
Matched:
|
||
|
||
//
|
||
// create hostname
|
||
// preference order:
|
||
// - full PDN
|
||
// - full adapter domain name from adapter with IP
|
||
// - hostname (single label)
|
||
// - "localhost"
|
||
//
|
||
|
||
{
|
||
PCHAR pnameBuf = (PCHAR) pBlob->NameBufferWide;
|
||
|
||
pnameHost = pnetInfo->pszHostName;
|
||
if ( !pnameHost )
|
||
{
|
||
pnameHost = "localhost";
|
||
goto Build;
|
||
}
|
||
|
||
pnameDomain = pnetInfo->pszDomainName;
|
||
if ( !pnameDomain )
|
||
{
|
||
// use the adapter name even if NOT set for registration
|
||
// if ( !padapter ||
|
||
// !(padapter->InfoFlags & DNS_FLAG_REGISTER_DOMAIN_NAME) )
|
||
if ( !padapter )
|
||
{
|
||
goto Build;
|
||
}
|
||
pnameDomain = padapter->pszAdapterDomain;
|
||
if ( !pnameDomain )
|
||
{
|
||
goto Build;
|
||
}
|
||
}
|
||
|
||
if ( ! Dns_NameAppend_A(
|
||
pnameBuf,
|
||
DNS_MAX_NAME_BUFFER_LENGTH,
|
||
pnameHost,
|
||
pnameDomain ) )
|
||
{
|
||
DNS_ASSERT( FALSE );
|
||
goto Build;
|
||
}
|
||
pnameHost = pnameBuf;
|
||
|
||
|
||
Build:
|
||
//
|
||
// create record
|
||
//
|
||
|
||
prr = Dns_CreatePtrRecordEx(
|
||
& ipUnion,
|
||
pnameHost,
|
||
LOCAL_IP_TTL,
|
||
DnsCharSetUtf8,
|
||
DnsCharSetUnicode );
|
||
if ( !prr )
|
||
{
|
||
DNSDBG( ANY, (
|
||
"Local PTR record creation failed for name %s!\n",
|
||
pnameHost ));
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
DNSDBG( QUERY, (
|
||
"Created local PTR record %p with hostname %s.\n"
|
||
"\treverse name = %S\n",
|
||
prr,
|
||
pnameHost,
|
||
pnameQuery ));
|
||
|
||
return prr;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
BuildRecordForLocalIp4(
|
||
IN PSTR pszName,
|
||
IN IP4_ADDRESS IpAddr,
|
||
IN IS_CLUSTER_IP_FUNC pfnIsClusterIp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Build local IP record.
|
||
|
||
Wraps up default cluster filtering and record
|
||
building.
|
||
|
||
Arguments:
|
||
|
||
pszName -- name of record
|
||
|
||
IpAddr -- IP4 address
|
||
|
||
pfnIsClusterIp -- filtering function
|
||
|
||
Return Value:
|
||
|
||
TRUE if created record.
|
||
FALSE on error (cluster IP or mem alloc failure).
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr;
|
||
|
||
DNSDBG( TRACE, (
|
||
"BuildRecordForLocalIp4( %s, %s )\n",
|
||
pszName,
|
||
IP_STRING(IpAddr) ));
|
||
|
||
// filter off cluster IP -- if desired
|
||
|
||
if ( pfnIsClusterIp )
|
||
{
|
||
IP_UNION ipUnion;
|
||
|
||
IPUNION_SET_IP4( &ipUnion, IpAddr );
|
||
|
||
if ( pfnIsClusterIp(
|
||
NULL, // no blob required
|
||
&ipUnion ) )
|
||
{
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
// create the record
|
||
|
||
return Dns_CreateARecord(
|
||
pszName,
|
||
IpAddr,
|
||
LOCAL_IP_TTL,
|
||
DnsCharSetUtf8,
|
||
DnsCharSetUnicode );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
GetLocalAddressRecord(
|
||
IN OUT PQUERY_BLOB pBlob
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get address record for local IP.
|
||
|
||
Arguments:
|
||
|
||
pBlob -- query blob
|
||
|
||
Uses:
|
||
pNameOrig
|
||
wType
|
||
pNetInfo
|
||
|
||
Sets:
|
||
fNoIpLocal
|
||
TRUE -- no IP of type found, defaulted record
|
||
FALSE -- records valid
|
||
|
||
NameBufferWide -- used as local storage
|
||
|
||
Return Value:
|
||
|
||
Ptr to record for query, if query name\type is IP.
|
||
NULL if query not for IP.
|
||
|
||
--*/
|
||
{
|
||
IP_UNION ipUnion;
|
||
IP4_ADDRESS ip4;
|
||
IP6_ADDRESS ip6;
|
||
PDNS_RECORD prr;
|
||
BOOL fmatchedName = FALSE;
|
||
PSTR pnameRecord = NULL;
|
||
PWSTR pnameRecordWide = NULL;
|
||
DWORD iter;
|
||
DWORD jter;
|
||
DWORD bufLength;
|
||
PSTR pnameDomain;
|
||
DNS_RRSET rrset;
|
||
WORD wtype = pBlob->wType;
|
||
PSTR pnameBuf = (PCHAR) pBlob->NameBufferWide;
|
||
PWSTR pnameQuery = pBlob->pNameOrig;
|
||
PDNS_NETINFO pnetInfo = pBlob->pNetworkInfo;
|
||
IS_CLUSTER_IP_FUNC pfnClusterFilter;
|
||
|
||
|
||
DNSDBG( TRACE, (
|
||
"GetLocalAddressRecord( %S, %d )\n",
|
||
pnameQuery,
|
||
wtype ));
|
||
|
||
// clear out param
|
||
|
||
pBlob->fNoIpLocal = FALSE;
|
||
|
||
//
|
||
// NULL treated as local PDN
|
||
//
|
||
|
||
if ( !pnameQuery )
|
||
{
|
||
DNSDBG( QUERY, ( "Local lookup -- no query name, treat as PDN.\n" ));
|
||
goto MatchedPdn;
|
||
}
|
||
|
||
//
|
||
// loopback or localhost
|
||
//
|
||
|
||
if ( Dns_NameCompare_W(
|
||
pnameQuery,
|
||
L"loopback" )
|
||
||
|
||
Dns_NameCompare_W(
|
||
pnameQuery,
|
||
L"localhost" ) )
|
||
{
|
||
pnameRecord = (PSTR) pnameQuery,
|
||
IP6_SET_ADDR_LOOPBACK( &ip6 );
|
||
ip4 = DNS_NET_ORDER_LOOPBACK;
|
||
goto SingleIp;
|
||
}
|
||
|
||
//
|
||
// if no hostname -- done
|
||
//
|
||
|
||
if ( !pnetInfo->pszHostName )
|
||
{
|
||
DNSDBG( QUERY, ( "No hostname configured!\n" ));
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// copy wire format name
|
||
//
|
||
|
||
if ( ! Dns_NameCopyStandard_A(
|
||
pnameBuf,
|
||
pBlob->pNameOrigWire ) )
|
||
{
|
||
DNSDBG( ANY, (
|
||
"Invalid name %S to local address query.\n",
|
||
pnameQuery ));
|
||
return NULL;
|
||
}
|
||
|
||
// split query name into hostname and domain name
|
||
|
||
pnameDomain = Dns_SplitHostFromDomainName_A( pnameBuf );
|
||
|
||
// must have hostname match
|
||
|
||
if ( !Dns_NameCompare_UTF8(
|
||
pnameBuf,
|
||
pnetInfo->pszHostName ) )
|
||
{
|
||
DNSDBG( ANY, (
|
||
"Local lookup, failed hostname match!\n",
|
||
pnameQuery ));
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// hostname's match
|
||
// - no domain name => PDN equivalent
|
||
// - match PDN => all addresses
|
||
// - match adapter name => adapter addresses
|
||
// - no match
|
||
//
|
||
// first setup
|
||
// - RR set builder
|
||
// - filtering function
|
||
//
|
||
|
||
DNS_RRSET_INIT( rrset );
|
||
|
||
pfnClusterFilter = pBlob->pfnIsClusterIp;
|
||
if ( pfnClusterFilter &&
|
||
!(pBlob->Flags & DNSP_QUERY_FILTER_CLUSTER) )
|
||
{
|
||
pfnClusterFilter = NULL;
|
||
}
|
||
|
||
if ( !pnameDomain )
|
||
{
|
||
DNSDBG( QUERY, ( "Local lookup -- no domain, treat as PDN!\n" ));
|
||
goto MatchedPdn;
|
||
}
|
||
|
||
// check PDN match
|
||
|
||
if ( Dns_NameCompare_UTF8(
|
||
pnameDomain,
|
||
pnetInfo->pszDomainName ) )
|
||
{
|
||
DNSDBG( QUERY, ( "Local lookup -- matched PDN!\n" ));
|
||
goto MatchedPdn;
|
||
}
|
||
|
||
//
|
||
// check adapter name match
|
||
//
|
||
|
||
for ( iter = 0;
|
||
iter < pnetInfo->AdapterCount;
|
||
iter ++ )
|
||
{
|
||
PDNS_ADAPTER padapter = pnetInfo->AdapterArray[iter];
|
||
PIP_ARRAY parray;
|
||
|
||
if ( !padapter ||
|
||
!(padapter->InfoFlags & DNS_FLAG_REGISTER_DOMAIN_NAME) )
|
||
{
|
||
continue;
|
||
}
|
||
if ( ! Dns_NameCompare_UTF8(
|
||
pnameDomain,
|
||
padapter->pszAdapterDomain ) )
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// build name if we haven't built it before
|
||
// we stay in the loop in case more than one
|
||
// adapter has the same domain name
|
||
|
||
if ( !fmatchedName )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Local lookup -- matched adapter name %s\n",
|
||
padapter->pszAdapterDomain ));
|
||
|
||
if ( ! Dns_NameAppend_A(
|
||
pnameBuf,
|
||
DNS_MAX_NAME_BUFFER_LENGTH,
|
||
pnetInfo->pszHostName,
|
||
padapter->pszAdapterDomain ) )
|
||
{
|
||
DNS_ASSERT( FALSE );
|
||
return NULL;
|
||
}
|
||
pnameRecord = pnameBuf;
|
||
fmatchedName = TRUE;
|
||
}
|
||
|
||
// build forward records for all IPs in list
|
||
//
|
||
// DCR: IP6 addresses missing
|
||
|
||
if ( wtype == DNS_TYPE_AAAA )
|
||
{
|
||
goto NoIp;
|
||
}
|
||
|
||
// no IP for adapter?
|
||
|
||
parray = padapter->pAdapterIPAddresses;
|
||
if ( !parray )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Local lookup -- no IPs for adapter name (%s) matched!\n",
|
||
padapter->pszAdapterDomain ));
|
||
}
|
||
|
||
// build records for adapter IPs
|
||
|
||
for ( jter = 0;
|
||
jter < parray->AddrCount;
|
||
jter++ )
|
||
{
|
||
prr = BuildRecordForLocalIp4(
|
||
pnameRecord,
|
||
parray->AddrArray[jter],
|
||
pfnClusterFilter );
|
||
if ( prr )
|
||
{
|
||
pnameRecord = NULL;
|
||
DNS_RRSET_ADD( rrset, prr );
|
||
}
|
||
}
|
||
}
|
||
|
||
// done with adapter name
|
||
// either
|
||
// - no match
|
||
// - match but didn't get IPs
|
||
// - match
|
||
|
||
if ( !fmatchedName )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Leave GetLocalAddressRecord() => no domain name match.\n" ));
|
||
return NULL;
|
||
}
|
||
|
||
prr = rrset.pFirstRR;
|
||
if ( prr )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Leave GetLocalAddressRecord() => %p matched adapter name.\n",
|
||
prr ));
|
||
return prr;
|
||
}
|
||
goto NoIp;
|
||
|
||
|
||
MatchedPdn:
|
||
|
||
//
|
||
// matched PDN
|
||
//
|
||
// must build in specific order
|
||
// - first IP in each adapter
|
||
// - remainder of IPs on adapters
|
||
//
|
||
|
||
fmatchedName = TRUE;
|
||
|
||
if ( ! Dns_NameAppend_A(
|
||
pnameBuf,
|
||
DNS_MAX_NAME_BUFFER_LENGTH,
|
||
pnetInfo->pszHostName,
|
||
pnetInfo->pszDomainName ) )
|
||
{
|
||
DNS_ASSERT( FALSE );
|
||
return NULL;
|
||
}
|
||
pnameRecord = pnameBuf;
|
||
|
||
// DCR: IP6 addresses missing
|
||
|
||
if ( wtype == DNS_TYPE_AAAA )
|
||
{
|
||
goto NoIp;
|
||
}
|
||
|
||
// get first IP in each adapter
|
||
|
||
for ( iter = 0;
|
||
iter < pnetInfo->AdapterCount;
|
||
iter ++ )
|
||
{
|
||
PDNS_ADAPTER padapter = pnetInfo->AdapterArray[iter];
|
||
PIP_ARRAY parray;
|
||
|
||
if ( !padapter ||
|
||
!(parray = padapter->pAdapterIPAddresses) )
|
||
{
|
||
continue;
|
||
}
|
||
prr = BuildRecordForLocalIp4(
|
||
pnameRecord,
|
||
parray->AddrArray[0],
|
||
pfnClusterFilter );
|
||
if ( prr )
|
||
{
|
||
pnameRecord = NULL;
|
||
DNS_RRSET_ADD( rrset, prr );
|
||
}
|
||
}
|
||
|
||
// get rest of IPs in each adapter
|
||
|
||
for ( iter = 0;
|
||
iter < pnetInfo->AdapterCount;
|
||
iter ++ )
|
||
{
|
||
PDNS_ADAPTER padapter = pnetInfo->AdapterArray[iter];
|
||
PIP_ARRAY parray;
|
||
|
||
if ( !padapter ||
|
||
!(parray = padapter->pAdapterIPAddresses) )
|
||
{
|
||
continue;
|
||
}
|
||
for ( jter = 1;
|
||
jter < parray->AddrCount;
|
||
jter++ )
|
||
{
|
||
prr = BuildRecordForLocalIp4(
|
||
pnameRecord,
|
||
parray->AddrArray[jter],
|
||
pfnClusterFilter );
|
||
if ( prr )
|
||
{
|
||
pnameRecord = NULL;
|
||
DNS_RRSET_ADD( rrset, prr );
|
||
}
|
||
}
|
||
}
|
||
|
||
// if successfully built -- done
|
||
|
||
prr = rrset.pFirstRR;
|
||
if ( prr )
|
||
{
|
||
DNSDBG( QUERY, (
|
||
"Leave GetLocalAddressRecord() => %p matched PDN name.\n",
|
||
prr ));
|
||
return prr;
|
||
}
|
||
|
||
// matched name but found no records
|
||
// fall through to NoIp section
|
||
//
|
||
//goto NoIp;
|
||
|
||
NoIp:
|
||
|
||
//
|
||
// matched name -- but no IP
|
||
// use loopback address; assume this is a lookup prior to
|
||
// connect which happens to be the local name, rather than an
|
||
// explict local lookup to get binding IPs
|
||
//
|
||
// DCR: fix IP6 hack for local names
|
||
|
||
DNSDBG( ANY, (
|
||
"WARNING: local name match but no IP -- using loopback\n" ));
|
||
|
||
IP6_SET_ADDR_LOOPBACK( &ip6 );
|
||
ip4 = DNS_NET_ORDER_LOOPBACK;
|
||
pBlob->fNoIpLocal = TRUE;
|
||
|
||
// fall through to single IP
|
||
|
||
SingleIp:
|
||
|
||
// single IP
|
||
// - loopback address and be unicode queried name
|
||
// - no IP failure (zero IP) and be UTF8 PDN name
|
||
|
||
if ( wtype == DNS_TYPE_A )
|
||
{
|
||
IPUNION_SET_IP4( &ipUnion, ip4 );
|
||
}
|
||
else
|
||
{
|
||
IPUNION_SET_IP6( &ipUnion, ip6 );
|
||
}
|
||
|
||
prr = Dns_CreateForwardRecord(
|
||
(PSTR) pnameRecord,
|
||
& ipUnion,
|
||
LOCAL_IP_TTL,
|
||
(pnameRecord == (PSTR)pnameQuery)
|
||
? DnsCharSetUnicode
|
||
: DnsCharSetUtf8,
|
||
DnsCharSetUnicode );
|
||
|
||
return prr;
|
||
}
|
||
|
||
|
||
|
||
DNS_STATUS
|
||
GetRecordsForLocalName(
|
||
IN OUT PQUERY_BLOB pBlob
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get local address info array.
|
||
|
||
Arguments:
|
||
|
||
pBlob -- query blob
|
||
|
||
Uses:
|
||
pNameOrig
|
||
wType
|
||
pNetInfo
|
||
|
||
Sets:
|
||
pLocalRecords
|
||
fNoIpLocal if local name without records
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
DNS_ERROR_RCODE_NAME_ERROR on failure.
|
||
|
||
--*/
|
||
{
|
||
WORD wtype = pBlob->wType;
|
||
PDNS_RECORD prr = NULL;
|
||
|
||
if ( wtype == DNS_TYPE_A ||
|
||
wtype == DNS_TYPE_AAAA )
|
||
{
|
||
prr = GetLocalAddressRecord( pBlob );
|
||
}
|
||
|
||
else if ( wtype == DNS_TYPE_PTR )
|
||
{
|
||
prr = GetLocalPtrRecord( pBlob );
|
||
}
|
||
|
||
// set local records
|
||
// - if not NO IP situation then this
|
||
// is final query result also
|
||
|
||
if ( prr )
|
||
{
|
||
pBlob->pLocalRecords = prr;
|
||
if ( !pBlob->fNoIpLocal )
|
||
{
|
||
pBlob->pRecords = prr;
|
||
}
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
return DNS_ERROR_RCODE_NAME_ERROR;
|
||
}
|
||
|
||
//
|
||
// End localip.c
|
||
//
|
||
|