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.
2145 lines
43 KiB
2145 lines
43 KiB
/*++
|
|
|
|
Copyright (c) 2002-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sablob.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) Library
|
|
|
|
Sockaddr blob routines.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) May 25, 2002
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
#include "ws2atm.h" // ATM address
|
|
|
|
|
|
//
|
|
// Max number of aliases
|
|
//
|
|
|
|
#define DNS_MAX_ALIAS_COUNT (8)
|
|
|
|
//
|
|
// Min size of sablob address buffer
|
|
// - enough for one address of largest type
|
|
//
|
|
|
|
#define MIN_ADDR_BUF_SIZE (sizeof(ATM_ADDRESS))
|
|
|
|
|
|
|
|
//
|
|
// SockaddrResults utilities
|
|
//
|
|
|
|
|
|
BOOL
|
|
SaBlob_IsSupportedAddrType(
|
|
IN WORD wType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Is this a supported address type for sablob.
|
|
|
|
Arguments:
|
|
|
|
wType -- type in question
|
|
|
|
Return Value:
|
|
|
|
TRUE if type supported
|
|
FALSE otherwise
|
|
|
|
--*/
|
|
{
|
|
return ( wType == DNS_TYPE_A ||
|
|
wType == DNS_TYPE_AAAA ||
|
|
wType == DNS_TYPE_ATMA );
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
DWORD
|
|
SaBlob_WriteLocalIp4Array(
|
|
IN OUT PSABLOB pBlob,
|
|
OUT PCHAR pAddrBuf,
|
|
IN DWORD MaxBufCount,
|
|
IN PIP4_ARRAY pIpArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write local IP list into sablob.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob
|
|
|
|
pAddrBuf -- buffer to hold addresses
|
|
|
|
MaxBufCount -- max IPs buffer can hold
|
|
|
|
pIpArray -- IP4 array of local addresses
|
|
|
|
Return Value:
|
|
|
|
Count of addresses written
|
|
|
|
--*/
|
|
{
|
|
DWORD count = 0;
|
|
|
|
//
|
|
// write array
|
|
//
|
|
|
|
if ( pIpArray )
|
|
{
|
|
count = SaBlob_WriteIp4Addrs(
|
|
pBlob,
|
|
pAddrBuf,
|
|
MaxBufCount,
|
|
pIpArray->AddrArray,
|
|
pIpArray->AddrCount,
|
|
TRUE // screen out zeros
|
|
);
|
|
}
|
|
|
|
//
|
|
// if no addresses written, write loopback
|
|
//
|
|
|
|
if ( count==0 )
|
|
{
|
|
pBlob->h_addr_list[0] = pAddrBuf;
|
|
pBlob->h_addr_list[1] = NULL;
|
|
*((IP4_ADDRESS*)pAddrBuf) = DNS_NET_ORDER_LOOPBACK;
|
|
count = 1;
|
|
}
|
|
|
|
// count of addresses written
|
|
|
|
return( count );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
SaBlob_SetToSingleAddress(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PDNS_ADDR pAddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set address in sablob.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob to set to addr
|
|
|
|
pAddr -- ptr to address
|
|
|
|
Return Value:
|
|
|
|
TRUE if address successfully copied into sablob.
|
|
FALSE otherwise (no sablob, wrong length, sablob empty)
|
|
|
|
--*/
|
|
{
|
|
PCHAR paddrSockaddrResults;
|
|
|
|
//
|
|
// validate
|
|
// - must have sablob
|
|
// - length must match
|
|
//
|
|
|
|
if ( !pBlob ||
|
|
AddrLength != (DWORD)pBlob->h_length )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// slam address in on top of existing
|
|
// - NULL 2nd addr pointer to terminate list
|
|
//
|
|
|
|
paddrSockaddrResults = pBlob->h_addr_list[0];
|
|
if ( !paddrSockaddrResults )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
paddrSockaddrResults,
|
|
pAddr,
|
|
AddrLength );
|
|
|
|
pBlob->h_addr_list[1] = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
SaBlob_IsAddressInSockaddrResults(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PCHAR pAddr,
|
|
IN DWORD AddrLength,
|
|
IN INT Family OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does sablob contain this address.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob to check
|
|
|
|
pAddr -- ptr to address to check
|
|
|
|
AddrLength -- address length
|
|
|
|
Family -- address family
|
|
|
|
Return Value:
|
|
|
|
TRUE if address is in sablob.
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
BOOL freturn = FALSE;
|
|
DWORD i;
|
|
PCHAR paddrSockaddrResults;
|
|
|
|
//
|
|
// validate
|
|
// - must have sablob
|
|
// - must have address
|
|
// - if family given, must match
|
|
// - length must match
|
|
//
|
|
|
|
if ( !pBlob ||
|
|
!pAddr ||
|
|
AddrLength != (DWORD)pBlob->h_length ||
|
|
( Family && Family != pBlob->h_addrtype ) )
|
|
{
|
|
return freturn;
|
|
}
|
|
|
|
//
|
|
// search for address -- if found return TRUE
|
|
//
|
|
|
|
i = 0;
|
|
|
|
while ( paddrSockaddrResults = pBlob->h_addr_list[i++] )
|
|
{
|
|
freturn = RtlEqualMemory(
|
|
paddrSockaddrResults,
|
|
pAddr,
|
|
AddrLength );
|
|
if ( freturn )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return freturn;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
SaBlob_IsIp4AddressInSockaddrResults(
|
|
IN OUT PSABLOB pBlob,
|
|
IN IP4_ADDRESS Ip4Addr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does sablob contain this address.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob to check
|
|
|
|
pAddr -- ptr to address to check
|
|
|
|
AddrLength -- address length
|
|
|
|
Family -- address family
|
|
|
|
Return Value:
|
|
|
|
TRUE if address is in sablob.
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
PCHAR paddrSockaddrResults;
|
|
|
|
//
|
|
// validate
|
|
// - must have sablob
|
|
// - length must match
|
|
//
|
|
|
|
if ( !pBlob ||
|
|
sizeof(IP4_ADDRESS) != (DWORD)pBlob->h_length )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// search for address -- if found return TRUE
|
|
//
|
|
|
|
i = 0;
|
|
|
|
while ( paddrSockaddrResults = pBlob->h_addr_list[i++] )
|
|
{
|
|
if ( Ip4Addr == *(PIP4_ADDRESS)paddrSockaddrResults )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//
|
|
// SaBlob routines
|
|
//
|
|
|
|
PSABLOB
|
|
SaBlob_Create(
|
|
IN DWORD AddrCount
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create sablob, optionally creating DnsAddrArray for it.
|
|
|
|
Arguments:
|
|
|
|
AddrCount -- address count
|
|
|
|
Return Value:
|
|
|
|
Ptr to new sablob.
|
|
NULL on error, GetLastError() contains error.
|
|
|
|
--*/
|
|
{
|
|
PSABLOB pblob;
|
|
|
|
DNSDBG( SABLOB, ( "SaBlob_Create( %d )\n", AddrCount ));
|
|
|
|
//
|
|
// allocate blob
|
|
//
|
|
|
|
pblob = (PSABLOB) ALLOCATE_HEAP_ZERO( sizeof(SABLOB) );
|
|
if ( !pblob )
|
|
{
|
|
goto Failed;
|
|
}
|
|
|
|
//
|
|
// alloc addr array
|
|
//
|
|
|
|
if ( AddrCount )
|
|
{
|
|
PDNS_ADDR_ARRAY parray = DnsAddrArray_Create( AddrCount );
|
|
if ( !parray )
|
|
{
|
|
goto Failed;
|
|
}
|
|
pblob->pAddrArray = parray;
|
|
}
|
|
|
|
DNSDBG( SABLOB, ( "SaBlob_Create() successful.\n" ));
|
|
|
|
return( pblob );
|
|
|
|
|
|
Failed:
|
|
|
|
SaBlob_Free( pblob );
|
|
|
|
DNSDBG( SABLOB, ( "SockaddrResults Blob create failed!\n" ));
|
|
|
|
SetLastError( DNS_ERROR_NO_MEMORY );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SaBlob_Free(
|
|
IN OUT PSABLOB pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free sablob blob.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- blob to free
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( pBlob )
|
|
{
|
|
FREE_HEAP( pBlob->pName );
|
|
|
|
// free every alias as resetting alias count is
|
|
// used to ignore them
|
|
|
|
//for ( i=0; i<pBlob->AliasCount; i++ )
|
|
for ( i=0; i<DNS_MAX_ALIAS_COUNT; i++ )
|
|
{
|
|
FREE_HEAP( pBlob->AliasArray[i] );
|
|
}
|
|
|
|
DnsAddrArray_Free( pBlob->pAddrArray );
|
|
|
|
FREE_HEAP( pBlob );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PSABLOB
|
|
SaBlob_CreateFromIp4(
|
|
IN PWSTR pName,
|
|
IN DWORD AddrCount,
|
|
IN PIP4_ADDRESS pIpArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create sablob from IP4 addresses.
|
|
|
|
Use this to build from results of non-DNS queries.
|
|
Specifically NBT lookup.
|
|
|
|
Arguments:
|
|
|
|
pName -- name for sablob
|
|
|
|
AddrCount -- address count
|
|
|
|
pIpArray -- array of addresses
|
|
|
|
Return Value:
|
|
|
|
Ptr to blob if successful.
|
|
NULL on error; GetLastError() has error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = DNS_ERROR_NO_MEMORY;
|
|
PSABLOB pblob = NULL;
|
|
DWORD i;
|
|
|
|
DNSDBG( SABLOB, (
|
|
"SaBlob_CreateFromIp4()\n"
|
|
"\tpname = %S\n"
|
|
"\tcount = %d\n"
|
|
"\tpArray = %p\n",
|
|
pName,
|
|
AddrCount,
|
|
pIpArray ));
|
|
|
|
|
|
//
|
|
// create blob
|
|
//
|
|
|
|
pblob = SaBlob_Create( AddrCount );
|
|
if ( !pblob )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// copy name
|
|
//
|
|
|
|
if ( pName )
|
|
{
|
|
PWSTR pname = Dns_CreateStringCopy_W( pName );
|
|
if ( !pname )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
pblob->pName = pname;
|
|
}
|
|
|
|
//
|
|
// copy addresses
|
|
//
|
|
|
|
for ( i=0; i<AddrCount; i++ )
|
|
{
|
|
DnsAddrArray_AddIp4(
|
|
pblob->pAddrArray,
|
|
pIpArray[ i ],
|
|
DNSADDR_MATCH_IP
|
|
);
|
|
}
|
|
status = NO_ERROR;
|
|
|
|
IF_DNSDBG( SABLOB )
|
|
{
|
|
DnsDbg_SaBlob(
|
|
"Leaving SaBlob_CreateFromIp4():",
|
|
pblob );
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
SaBlob_Free( pblob );
|
|
pblob = NULL;
|
|
SetLastError( status );
|
|
}
|
|
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_CreateFromIp4() => status = %d\n",
|
|
status ));
|
|
|
|
return( pblob );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SaBlob_AttachHostent(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PHOSTENT pHostent
|
|
)
|
|
{
|
|
DNSDBG( SABLOB, ( "SaBlob_AttachHostent()\n" ));
|
|
|
|
//
|
|
// attach existing hostent to sablob
|
|
//
|
|
|
|
pBlob->pHostent = pHostent;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
SaBlob_WriteAddress(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PDNS_ADDR pAddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write address to sablob.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob
|
|
|
|
pAddr - address to write
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ERROR_MORE_DATA if out of buffer space
|
|
ERROR_INVALID_DATA if address doesn't match sablob
|
|
|
|
--*/
|
|
{
|
|
PDNS_ADDR_ARRAY parray;
|
|
|
|
//
|
|
// if no address array -- create one
|
|
//
|
|
|
|
parray = pBlob->pAddrArray;
|
|
|
|
if ( !parray )
|
|
{
|
|
parray = DnsAddrArray_Create( 1 );
|
|
if ( !parray )
|
|
{
|
|
return DNS_ERROR_NO_MEMORY;
|
|
}
|
|
pBlob->pAddrArray = parray;
|
|
}
|
|
|
|
//
|
|
// slap address into array
|
|
// - fail if array too full
|
|
//
|
|
|
|
if ( DnsAddrArray_AddAddr(
|
|
parray,
|
|
pAddr,
|
|
0, // no family check
|
|
0 // no match flag
|
|
) )
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
return ERROR_MORE_DATA;
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
DNS_STATUS
|
|
SaBlob_WriteAddressArray(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PVOID pAddrArray,
|
|
IN DWORD AddrCount,
|
|
IN DWORD AddrSize,
|
|
IN DWORD AddrType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write address array to sablob blob.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob build blob
|
|
|
|
pAddrArray - address array to write
|
|
|
|
AddrCount - address count
|
|
|
|
AddrSize - address size
|
|
|
|
AddrType - address type (sablob type, e.g. AF_INET)
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ERROR_MORE_DATA if out of buffer space
|
|
ERROR_INVALID_DATA if address doesn't match sablob
|
|
|
|
--*/
|
|
{
|
|
DWORD count = AddrCount;
|
|
PCHAR pcurrent;
|
|
DWORD totalSize;
|
|
DWORD i;
|
|
DWORD bytesLeft;
|
|
|
|
// verify type
|
|
// - set if empty or no addresses written
|
|
|
|
if ( phost->h_addrtype != (SHORT)AddrType )
|
|
{
|
|
if ( phost->h_addrtype != 0 )
|
|
{
|
|
return( ERROR_INVALID_DATA );
|
|
}
|
|
phost->h_addrtype = (SHORT) AddrType;
|
|
phost->h_length = (SHORT) AddrSize;
|
|
}
|
|
|
|
// verify space
|
|
|
|
if ( count > pBlob->MaxAddrCount )
|
|
{
|
|
return( ERROR_MORE_DATA );
|
|
}
|
|
|
|
// align - to DWORD
|
|
//
|
|
// note: we are assuming that pAddrArray is internally
|
|
// aligned adequately, otherwise we wouldn't be
|
|
// getting an intact array and would have to add serially
|
|
|
|
pcurrent = DWORD_ALIGN( pBlob->pCurrent );
|
|
bytesLeft = pBlob->BytesLeft;
|
|
bytesLeft -= (DWORD)(pcurrent - pBlob->pCurrent);
|
|
|
|
totalSize = count * AddrSize;
|
|
|
|
if ( bytesLeft < totalSize )
|
|
{
|
|
return( ERROR_MORE_DATA );
|
|
}
|
|
|
|
// copy
|
|
// - copy address array to buffer
|
|
// - set pointer to each address in array
|
|
// - NULL following pointer
|
|
|
|
RtlCopyMemory(
|
|
pcurrent,
|
|
pAddrArray,
|
|
totalSize );
|
|
|
|
for ( i=0; i<count; i++ )
|
|
{
|
|
phost->h_addr_list[i] = pcurrent;
|
|
pcurrent += AddrSize;
|
|
}
|
|
phost->h_addr_list[count] = NULL;
|
|
pBlob->AddrCount = count;
|
|
|
|
pBlob->pCurrent = pcurrent;
|
|
pBlob->BytesLeft = bytesLeft - totalSize;
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
SaBlob_WriteNameOrAlias(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PWSTR pszName,
|
|
IN BOOL fAlias
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write name or alias to sablob
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob build blob
|
|
|
|
pszName -- name to write
|
|
|
|
fAlias -- TRUE for alias; FALSE for name
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ERROR_MORE_DATA if out of buffer space
|
|
ERROR_INVALID_DATA if address doesn't match sablob
|
|
|
|
--*/
|
|
{
|
|
DWORD count = pBlob->AliasCount;
|
|
PWSTR pcopy;
|
|
|
|
//
|
|
// verify space
|
|
// included ptr space
|
|
// - skip if already written name
|
|
// or exhausted alias array
|
|
//
|
|
|
|
if ( fAlias )
|
|
{
|
|
if ( count >= DNS_MAX_ALIAS_COUNT )
|
|
{
|
|
return( ERROR_MORE_DATA );
|
|
}
|
|
}
|
|
else if ( pBlob->pName )
|
|
{
|
|
return( ERROR_MORE_DATA );
|
|
}
|
|
|
|
//
|
|
// copy
|
|
// - copy name
|
|
// - set ptr in blob
|
|
|
|
pcopy = Dns_CreateStringCopy_W( pszName );
|
|
if ( !pcopy )
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
if ( fAlias )
|
|
{
|
|
pBlob->AliasArray[count++] = pcopy;
|
|
pBlob->AliasCount = count;
|
|
}
|
|
else
|
|
{
|
|
pBlob->pName = pcopy;
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
SaBlob_WriteRecords(
|
|
IN OUT PSABLOB pBlob,
|
|
IN PDNS_RECORD pRecords,
|
|
IN BOOL fWriteName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write name or alias to sablob
|
|
|
|
Arguments:
|
|
|
|
pBlob -- sablob build blob
|
|
|
|
pRecords -- records to convert to sablob
|
|
|
|
fWriteName -- write name
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ERROR_MORE_DATA if out of buffer space
|
|
ERROR_INVALID_DATA if address doesn't match sablob
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
PDNS_RECORD prr = pRecords;
|
|
DNS_ADDR dnsAddr;
|
|
BOOL fwroteName = FALSE;
|
|
|
|
|
|
DNSDBG( SABLOB, (
|
|
"SaBlob_WriteRecords( %p, %p, %d )\n",
|
|
pBlob,
|
|
pRecords,
|
|
fWriteName ));
|
|
|
|
//
|
|
// write each record in turn to sablob
|
|
//
|
|
|
|
while ( prr )
|
|
{
|
|
WORD wtype;
|
|
|
|
if ( prr->Flags.S.Section != DNSREC_ANSWER &&
|
|
prr->Flags.S.Section != 0 )
|
|
{
|
|
prr = prr->pNext;
|
|
continue;
|
|
}
|
|
|
|
wtype = prr->wType;
|
|
|
|
switch( wtype )
|
|
{
|
|
case DNS_TYPE_A:
|
|
case DNS_TYPE_AAAA:
|
|
case DNS_TYPE_ATMA:
|
|
|
|
DnsAddr_BuildFromDnsRecord(
|
|
& dnsAddr,
|
|
prr );
|
|
|
|
status = SaBlob_WriteAddress(
|
|
pBlob,
|
|
& dnsAddr );
|
|
|
|
// write name
|
|
|
|
if ( fWriteName &&
|
|
!fwroteName &&
|
|
!pBlob->pName &&
|
|
prr->pName )
|
|
{
|
|
status = SaBlob_WriteNameOrAlias(
|
|
pBlob,
|
|
(PWSTR) prr->pName,
|
|
FALSE // name
|
|
);
|
|
fwroteName = TRUE;
|
|
}
|
|
break;
|
|
|
|
case DNS_TYPE_CNAME:
|
|
|
|
// record name is an alias
|
|
|
|
status = SaBlob_WriteNameOrAlias(
|
|
pBlob,
|
|
(PWSTR) prr->pName,
|
|
TRUE // alias
|
|
);
|
|
break;
|
|
|
|
case DNS_TYPE_PTR:
|
|
|
|
// target name is the sablob name
|
|
// but if already wrote name, PTR target becomes alias
|
|
|
|
status = SaBlob_WriteNameOrAlias(
|
|
pBlob,
|
|
(PWSTR) prr->Data.PTR.pNameHost,
|
|
(pBlob->pName != NULL)
|
|
);
|
|
break;
|
|
|
|
default:
|
|
|
|
DNSDBG( ANY, (
|
|
"Error record of type = %d while building sablob!\n",
|
|
wtype ));
|
|
status = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
DNSDBG( ANY, (
|
|
"ERROR: failed writing record to sablob!\n"
|
|
"\tprr = %p\n"
|
|
"\ttype = %d\n"
|
|
"\tstatus = %d\n",
|
|
prr,
|
|
wtype,
|
|
status ));
|
|
}
|
|
|
|
prr = prr->pNext;
|
|
}
|
|
|
|
IF_DNSDBG( SABLOB )
|
|
{
|
|
DnsDbg_SaBlob(
|
|
"SaBlob after WriteRecords():",
|
|
pBlob );
|
|
}
|
|
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
PSABLOB
|
|
SaBlob_CreateFromRecords(
|
|
IN PDNS_RECORD pRecords,
|
|
IN BOOL fWriteName,
|
|
IN WORD wType OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create sablob from records
|
|
|
|
Arguments:
|
|
|
|
pRecords -- records to convert to sablob
|
|
|
|
fWriteName -- write name to sablob
|
|
|
|
wType -- query type, if known
|
|
|
|
Return Value:
|
|
|
|
Ptr to blob if successful.
|
|
NULL on error; GetLastError() has error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
PDNS_RECORD prrFirstAddr = NULL;
|
|
PDNS_RECORD prr;
|
|
DWORD addrCount = 0;
|
|
WORD addrType = 0;
|
|
PSABLOB pblob = NULL;
|
|
|
|
DNSDBG( SABLOB, (
|
|
"SaBlob_CreateFromRecords()\n"
|
|
"\tpblob = %p\n"
|
|
"\tprr = %p\n",
|
|
pblob,
|
|
pRecords ));
|
|
|
|
//
|
|
// count addresses
|
|
//
|
|
// DCR: fix up section hack when hosts file records get ANSWER section
|
|
//
|
|
|
|
prr = pRecords;
|
|
|
|
while ( prr )
|
|
{
|
|
if ( ( prr->Flags.S.Section == 0 ||
|
|
prr->Flags.S.Section == DNSREC_ANSWER )
|
|
&&
|
|
SaBlob_IsSupportedAddrType( prr->wType ) )
|
|
{
|
|
addrCount++;
|
|
if ( !prrFirstAddr )
|
|
{
|
|
prrFirstAddr = prr;
|
|
addrType = prr->wType;
|
|
}
|
|
}
|
|
prr = prr->pNext;
|
|
}
|
|
|
|
//
|
|
// create sa-blob of desired size
|
|
//
|
|
|
|
pblob = SaBlob_Create( addrCount );
|
|
if ( !pblob )
|
|
{
|
|
status = GetLastError();
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// build sablob from answer records
|
|
//
|
|
// note: if manage to extract any useful data => continue
|
|
// this protects against new unwriteable records breaking us
|
|
//
|
|
|
|
status = SaBlob_WriteRecords(
|
|
pblob,
|
|
pRecords,
|
|
TRUE // write name
|
|
);
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
if ( pblob->pName ||
|
|
pblob->AliasCount ||
|
|
( pblob->pAddrArray &&
|
|
pblob->pAddrArray->AddrCount ) )
|
|
{
|
|
status = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// write address from PTR record
|
|
// - first record PTR
|
|
// OR
|
|
// - queried for PTR and got CNAME answer, which can happen
|
|
// in classless reverse lookup case
|
|
//
|
|
// DCR: add PTR address lookup to SaBlob_WriteRecords()
|
|
// - natural place
|
|
// - but would have to figure out handling of multiple PTRs
|
|
//
|
|
|
|
if ( pRecords &&
|
|
( pRecords->wType == DNS_TYPE_PTR ||
|
|
( wType == DNS_TYPE_PTR &&
|
|
pRecords->wType == DNS_TYPE_CNAME &&
|
|
pRecords->Flags.S.Section == DNSREC_ANSWER ) ) )
|
|
{
|
|
DNS_ADDR dnsAddr;
|
|
|
|
DNSDBG( SABLOB, (
|
|
"Writing address for PTR record %S\n",
|
|
pRecords->pName ));
|
|
|
|
// convert reverse name to IP
|
|
|
|
if ( Dns_ReverseNameToDnsAddr_W(
|
|
& dnsAddr,
|
|
(PWSTR) pRecords->pName ) )
|
|
{
|
|
status = SaBlob_WriteAddress(
|
|
pblob,
|
|
& dnsAddr );
|
|
|
|
ASSERT( status == NO_ERROR );
|
|
status = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// write name?
|
|
// - write name from first address record
|
|
//
|
|
|
|
if ( !pblob->pName &&
|
|
fWriteName &&
|
|
prrFirstAddr )
|
|
{
|
|
status = SaBlob_WriteNameOrAlias(
|
|
pblob,
|
|
(PWSTR) prrFirstAddr->pName,
|
|
FALSE // name
|
|
);
|
|
}
|
|
|
|
IF_DNSDBG( SABLOB )
|
|
{
|
|
DnsDbg_SaBlob(
|
|
"SaBlob after CreateFromRecords():",
|
|
pblob );
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_CreateFromRecords() => status=%d\n",
|
|
status ));
|
|
|
|
SaBlob_Free( pblob );
|
|
pblob = NULL;
|
|
SetLastError( status );
|
|
}
|
|
else
|
|
{
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_CreateFromRecords() => %p\n",
|
|
pblob ));
|
|
}
|
|
|
|
return( pblob );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// SockaddrResults Query
|
|
//
|
|
|
|
PSABLOB
|
|
SaBlob_Query(
|
|
IN PWSTR pwsName,
|
|
IN WORD wType,
|
|
IN DWORD Flags,
|
|
IN OUT PVOID * ppMsg, OPTIONAL
|
|
IN INT AddrFamily OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query DNS to get sockaddr results.
|
|
|
|
Arguments:
|
|
|
|
pwsName -- name to query
|
|
|
|
wType -- query type
|
|
|
|
Flags -- query flags
|
|
|
|
ppResults -- addr to receive pointer to results
|
|
|
|
AddrType -- address type (family) to reserve space for if querying
|
|
for PTR records
|
|
|
|
Return Value:
|
|
|
|
Ptr to blob if successful.
|
|
NULL on error; GetLastError() has error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
PDNS_RECORD prrQuery = NULL;
|
|
PSABLOB pblob = NULL;
|
|
PVOID pmsg = NULL;
|
|
|
|
|
|
DNSDBG( SABLOB, (
|
|
"SaBlob_Query()\n"
|
|
"\tname = %S\n"
|
|
"\ttype = %d\n"
|
|
"\tflags = %08x\n",
|
|
pwsName,
|
|
wType,
|
|
Flags ));
|
|
|
|
|
|
//
|
|
// query
|
|
// - if fails, dump any message before return
|
|
//
|
|
|
|
if ( ppMsg )
|
|
{
|
|
*ppMsg = NULL;
|
|
}
|
|
|
|
status = DnsQuery_W(
|
|
pwsName,
|
|
wType,
|
|
Flags,
|
|
NULL,
|
|
& prrQuery,
|
|
ppMsg );
|
|
|
|
// if failed, dump any message
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
if ( ppMsg && *ppMsg )
|
|
{
|
|
DnsApiFree( *ppMsg );
|
|
*ppMsg = NULL;
|
|
}
|
|
if ( status == RPC_S_SERVER_UNAVAILABLE )
|
|
{
|
|
status = WSATRY_AGAIN;
|
|
}
|
|
goto Done;
|
|
}
|
|
|
|
if ( !prrQuery )
|
|
{
|
|
ASSERT( FALSE );
|
|
status = DNS_ERROR_RCODE_NAME_ERROR;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// build sablob
|
|
//
|
|
|
|
pblob = SaBlob_CreateFromRecords(
|
|
prrQuery,
|
|
TRUE, // write name from first answer
|
|
wType
|
|
);
|
|
if ( !pblob )
|
|
{
|
|
status = GetLastError();
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// devnote: if don't have these checks
|
|
// -- nameless hostent can blow up gethostbyname()
|
|
// -- NO_ERROR, no address responses can confuse applications
|
|
|
|
//
|
|
// failed name write
|
|
// - queries that CNAME but don't find record of query type can hit here
|
|
//
|
|
|
|
if ( !pblob->pName )
|
|
{
|
|
status = DNS_INFO_NO_RECORDS;
|
|
goto Done;
|
|
}
|
|
|
|
#if 0
|
|
// note: because SVCID_HOSTNAME query is currently treated as
|
|
// simply A record query, we can't do no-address screening here;
|
|
// this screening can be done at higher level for all GUIDs
|
|
// except HOSTNAME
|
|
|
|
//
|
|
// for address query must get answer
|
|
//
|
|
// DCR: DnsQuery() should convert to no-records on empty CNAME chain?
|
|
// DCR: should we go ahead and build sablob?
|
|
//
|
|
|
|
if ( !pblob->pAddrArray && SaBlob_IsSupportedAddrType(wType) )
|
|
{
|
|
status = DNS_INFO_NO_RECORDS;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// set returned name to FQDN for loopback lookups
|
|
// this is for compatibility with previous OS versions
|
|
//
|
|
|
|
if ( DnsNameCompare_W( pblob->pName, L"localhost" ) ||
|
|
DnsNameCompare_W( pblob->pName, L"loopback" ) )
|
|
{
|
|
PWSTR pname;
|
|
PWSTR pnameFqdn;
|
|
|
|
pname = DnsQueryConfigAlloc(
|
|
DnsConfigFullHostName_W,
|
|
NULL );
|
|
if ( pname )
|
|
{
|
|
pnameFqdn = Dns_CreateStringCopy_W( pname );
|
|
if ( pnameFqdn )
|
|
{
|
|
FREE_HEAP( pblob->pName );
|
|
pblob->pName = pnameFqdn;
|
|
}
|
|
DnsApiFree( pname );
|
|
}
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( prrQuery )
|
|
{
|
|
DnsRecordListFree(
|
|
prrQuery,
|
|
DnsFreeRecordListDeep );
|
|
}
|
|
|
|
if ( status != NO_ERROR && pblob )
|
|
{
|
|
SaBlob_Free( pblob );
|
|
pblob = NULL;
|
|
}
|
|
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_Query()\n"
|
|
"\tpblob = %p\n"
|
|
"\tstatus = %d\n",
|
|
pblob,
|
|
status ));
|
|
|
|
SetLastError( status );
|
|
|
|
return( pblob );
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Special sablobs
|
|
//
|
|
|
|
#if 0
|
|
PSABLOB
|
|
SaBlob_Localhost(
|
|
IN INT Family
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create sablob from records
|
|
|
|
Arguments:
|
|
|
|
AddrFamily -- address family
|
|
|
|
Return Value:
|
|
|
|
Ptr to blob if successful.
|
|
NULL on error; GetLastError() has error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
PDNS_RECORD prrFirstAddr = NULL;
|
|
PDNS_RECORD prr;
|
|
DWORD addrCount = 0;
|
|
DWORD addrSize;
|
|
CHAR addrBuf[ sizeof(IP6_ADDRESS ) ];
|
|
SABLOB_INIT request;
|
|
PSABLOB pblob = NULL;
|
|
|
|
DNSDBG( SABLOB, ( "SaBlob_Localhost()\n" ));
|
|
|
|
//
|
|
// create sablob blob
|
|
//
|
|
|
|
RtlZeroMemory( &request, sizeof(request) );
|
|
|
|
request.AliasCount = 1;
|
|
request.AddrCount = 1;
|
|
request.AddrFamily = Family;
|
|
request.fUnicode = TRUE;
|
|
|
|
status = SaBlob_Create(
|
|
& pblob,
|
|
& request );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// write in loopback address
|
|
//
|
|
|
|
if ( Family == AF_INET )
|
|
{
|
|
* (PIP4_ADDRESS) addrBuf = DNS_NET_ORDER_LOOPBACK;
|
|
addrSize = sizeof(IP4_ADDRESS);
|
|
}
|
|
else if ( Family == AF_INET6 )
|
|
{
|
|
IP6_SET_ADDR_LOOPBACK( (PIP6_ADDRESS)addrBuf );
|
|
addrSize = sizeof(IN6_ADDR);
|
|
}
|
|
else
|
|
{
|
|
status = DNS_ERROR_INVALID_DATA;
|
|
goto Done;
|
|
}
|
|
|
|
status = SaBlob_WriteAddress(
|
|
pblob,
|
|
addrBuf,
|
|
addrSize,
|
|
Family );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// write localhost
|
|
//
|
|
|
|
status = SaBlob_WriteNameOrAlias(
|
|
pblob,
|
|
L"localhost",
|
|
FALSE // name
|
|
);
|
|
|
|
IF_DNSDBG( SABLOB )
|
|
{
|
|
DnsDbg_SaBlob(
|
|
"SaBlob after localhost create:",
|
|
pblob );
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( status != NO_ERROR && pblob )
|
|
{
|
|
SaBlob_Free( pblob );
|
|
pblob = NULL;
|
|
}
|
|
|
|
SetLastError( status );
|
|
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_Localhost() => status = %d\n",
|
|
status ));
|
|
|
|
return( pblob );
|
|
}
|
|
|
|
|
|
|
|
PSABLOB
|
|
SaBlob_CreateFromIpArray(
|
|
IN INT AddrFamily,
|
|
IN INT AddrSize,
|
|
IN INT AddrCount,
|
|
IN PCHAR pArray,
|
|
IN PSTR pName,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create sablob from records
|
|
|
|
Arguments:
|
|
|
|
ppBlob -- ptr with or to recv sablob blob
|
|
|
|
AddrFamily -- addr family use if PTR records and no addr
|
|
|
|
pArray -- array of addresses
|
|
|
|
pName -- name for sablob
|
|
|
|
fUnicode --
|
|
TRUE if name is and sablob will be in unicode
|
|
FALSE for narrow name and sablob
|
|
|
|
Return Value:
|
|
|
|
Ptr to blob if successful.
|
|
NULL on error; GetLastError() has error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
SABLOB_INIT request;
|
|
PSABLOB pblob = *ppBlob;
|
|
|
|
DNSDBG( SABLOB, (
|
|
"SaBlob_CreateFromIpArray()\n"
|
|
"\tppBlob = %p\n"
|
|
"\tfamily = %d\n"
|
|
"\tsize = %d\n"
|
|
"\tcount = %d\n"
|
|
"\tpArray = %p\n",
|
|
ppBlob,
|
|
AddrFamily,
|
|
AddrSize,
|
|
AddrCount,
|
|
pArray ));
|
|
|
|
|
|
//
|
|
// create or reinit sablob blob
|
|
//
|
|
|
|
RtlZeroMemory( &request, sizeof(request) );
|
|
|
|
request.AliasCount = DNS_MAX_ALIAS_COUNT;
|
|
request.AddrCount = AddrCount;
|
|
request.AddrFamily = AddrFamily;
|
|
request.fUnicode = fUnicode;
|
|
request.pName = pName;
|
|
|
|
status = SaBlob_Create(
|
|
& pblob,
|
|
& request );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// write in array
|
|
//
|
|
|
|
if ( AddrCount )
|
|
{
|
|
status = SaBlob_WriteAddressArray(
|
|
pblob,
|
|
pArray,
|
|
AddrCount,
|
|
AddrSize,
|
|
AddrFamily
|
|
);
|
|
if ( status != NO_ERROR )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// write name?
|
|
//
|
|
|
|
if ( pName )
|
|
{
|
|
status = SaBlob_WriteNameOrAlias(
|
|
pblob,
|
|
pName,
|
|
FALSE, // name not alias
|
|
fUnicode
|
|
);
|
|
}
|
|
|
|
IF_DNSDBG( SABLOB )
|
|
{
|
|
DnsDbg_SaBlob(
|
|
"Leaving SaBlob_CreateFromIpArray():",
|
|
pblob );
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( status != NO_ERROR && pblob )
|
|
{
|
|
SaBlob_Free( pblob );
|
|
pblob = NULL;
|
|
}
|
|
|
|
*ppBlob = pblob;
|
|
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_CreateFromIpArray() => status = %d\n",
|
|
status ));
|
|
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
PSABLOB
|
|
SaBlob_CreateLocal(
|
|
IN INT AddrFamily,
|
|
IN BOOL fLoopback,
|
|
IN BOOL fZero,
|
|
IN BOOL fHostnameOnly
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create sablob from records
|
|
|
|
Arguments:
|
|
|
|
ppBlob -- ptr with or to recv sablob blob
|
|
|
|
AddrFamily -- addr family use if PTR records and no addr
|
|
|
|
Return Value:
|
|
|
|
Ptr to blob if successful.
|
|
NULL on error; GetLastError() has error.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = NO_ERROR;
|
|
PSABLOB pblob = NULL;
|
|
WORD wtype;
|
|
INT size;
|
|
IP6_ADDRESS ip;
|
|
|
|
|
|
DNSDBG( SABLOB, (
|
|
"SaBlob_CreateLocal()\n"
|
|
"\tppBlob = %p\n"
|
|
"\tfamily = %d\n"
|
|
"\tfLoopback = %d\n"
|
|
"\tfZero = %d\n"
|
|
"\tfHostname = %d\n",
|
|
ppBlob,
|
|
AddrFamily,
|
|
fLoopback,
|
|
fZero,
|
|
fHostnameOnly
|
|
));
|
|
|
|
//
|
|
// get family info
|
|
// - start with override IP = 0
|
|
// - if loopback switch to appropriate loopback
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
&ip,
|
|
sizeof(ip) );
|
|
|
|
if ( AddrFamily == AF_INET )
|
|
{
|
|
wtype = DNS_TYPE_A;
|
|
size = sizeof(IP4_ADDRESS);
|
|
|
|
if ( fLoopback )
|
|
{
|
|
* (PIP4_ADDRESS) &ip = DNS_NET_ORDER_LOOPBACK;
|
|
}
|
|
}
|
|
else if ( AddrFamily == AF_INET6 )
|
|
{
|
|
wtype = DNS_TYPE_AAAA;
|
|
size = sizeof(IP6_ADDRESS);
|
|
|
|
if ( fLoopback )
|
|
{
|
|
IP6_SET_ADDR_LOOPBACK( &ip );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// query for local host info
|
|
//
|
|
|
|
pblob = SaBlob_Query(
|
|
NULL, // NULL name gets local host data
|
|
wtype,
|
|
0, // standard query
|
|
NULL, // no message
|
|
AddrFamily );
|
|
if ( !pblob )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
status = GetLastError();
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// overwrite with specific address
|
|
//
|
|
|
|
if ( fLoopback || fZero )
|
|
{
|
|
if ( ! SaBlob_SetToSingleAddress(
|
|
pblob->pBlob,
|
|
(PCHAR) &ip,
|
|
size ) )
|
|
{
|
|
DNS_ASSERT( pblob->AddrCount == 0 );
|
|
|
|
pblob->AddrCount = 0;
|
|
|
|
status = SaBlob_WriteAddress(
|
|
pblob,
|
|
& ip,
|
|
size,
|
|
AddrFamily );
|
|
if ( status != NO_ERROR )
|
|
{
|
|
DNS_ASSERT( status!=NO_ERROR );
|
|
goto Done;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// for gethostname()
|
|
// - chop name down to just hostname
|
|
// - kill off aliases
|
|
//
|
|
|
|
if ( fHostnameOnly )
|
|
{
|
|
PWSTR pname = (PWSTR) pblob->pName;
|
|
PWSTR pdomain;
|
|
|
|
DNS_ASSERT( pname );
|
|
if ( pname )
|
|
{
|
|
pdomain = Dns_GetDomainNameW( pname );
|
|
if ( pdomain )
|
|
{
|
|
DNS_ASSERT( pdomain > pname+1 );
|
|
DNS_ASSERT( *(pdomain-1) == L'.' );
|
|
|
|
*(pdomain-1) = 0;
|
|
}
|
|
}
|
|
pblob->AliasCount = 0;
|
|
}
|
|
|
|
IF_DNSDBG( SABLOB )
|
|
{
|
|
DnsDbg_SaBlob(
|
|
"Leaving SaBlob_CreateLocal():",
|
|
pblob );
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( status != NO_ERROR && pblob )
|
|
{
|
|
SaBlob_Free( pblob );
|
|
pblob = NULL;
|
|
}
|
|
|
|
DNSDBG( SABLOB, (
|
|
"Leave SaBlob_CreateLocal() => %p\n"
|
|
"\tstatus = %d\n",
|
|
pblob,
|
|
status ));
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
SetLastError( status );
|
|
}
|
|
|
|
return( pblob );
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PHOSTENT
|
|
SaBlob_CreateHostent(
|
|
IN OUT PBYTE * ppBuffer,
|
|
IN OUT PINT pBufferSize,
|
|
OUT PINT pHostentSize,
|
|
IN PSABLOB pBlob,
|
|
IN DNS_CHARSET CharSetTarget,
|
|
IN BOOL fOffsets,
|
|
IN BOOL fAlloc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy a hostent.
|
|
|
|
Arguments:
|
|
|
|
ppBuffer -- addr with ptr to buffer to write to;
|
|
if no buffer then hostent is allocated
|
|
updated with ptr to position in buffer after hostent
|
|
|
|
pBufferSize -- addr containing size of buffer;
|
|
updated with bytes left after hostent written
|
|
(even if out of space, it contains missing number of
|
|
bytes as negative number)
|
|
|
|
pHostentSize -- addr to recv total size of hostent written
|
|
|
|
pBlob -- sockaddr blob to create hostent for
|
|
|
|
CharSetTarget -- charset of target hostent
|
|
|
|
fOffsets -- write hostent with offsets
|
|
|
|
fAlloc -- allocate copy
|
|
|
|
Return Value:
|
|
|
|
Ptr to new hostent.
|
|
NULL on error. See GetLastError().
|
|
|
|
--*/
|
|
{
|
|
PBYTE pch;
|
|
PHOSTENT phost = NULL;
|
|
DWORD sizeTotal;
|
|
DWORD bytesLeft;
|
|
DWORD i;
|
|
DWORD size;
|
|
DWORD family = 0;
|
|
DWORD aliasCount;
|
|
DWORD addrCount = 0;
|
|
DWORD addrLength = 0;
|
|
PCHAR * pptrArrayOut;
|
|
DWORD sizeAliasPtrs;
|
|
DWORD sizeAddrPtrs;
|
|
DWORD sizeAddrs;
|
|
DWORD sizeAliasNames = 0;
|
|
DWORD sizeName = 0;
|
|
PFAMILY_INFO pfamilyInfo = NULL;
|
|
PDNS_ADDR_ARRAY paddrArray;
|
|
|
|
|
|
DNSDBG( HOSTENT, (
|
|
"SaBlob_CreateHostent( %p )\n",
|
|
pBlob ));
|
|
|
|
//
|
|
// get family, count info to size hostent
|
|
//
|
|
|
|
#if 0
|
|
if ( pBlob->Family != 0 )
|
|
{
|
|
pfamilyInfo = FamilyInfo_GetForFamily( pBlob->Family );
|
|
}
|
|
#endif
|
|
|
|
aliasCount = pBlob->AliasCount;
|
|
|
|
paddrArray = pBlob->pAddrArray;
|
|
if ( paddrArray )
|
|
{
|
|
family = paddrArray->AddrArray[0].Sockaddr.sa_family;
|
|
|
|
pfamilyInfo = FamilyInfo_GetForFamily( family );
|
|
if ( !pfamilyInfo )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
}
|
|
else
|
|
{
|
|
addrCount = paddrArray->AddrCount;
|
|
addrLength = pfamilyInfo->LengthAddr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// size hostent
|
|
// - struct
|
|
// - alias and addr ptr arrays (both NULL terminated)
|
|
// - addresses
|
|
// - name
|
|
// - aliases
|
|
//
|
|
// note: only aligning strings to WORD (for unicode) as we'll build
|
|
// them into buffer AFTER the addresses (which require DWORD)
|
|
// alignment
|
|
//
|
|
|
|
sizeAliasPtrs = (aliasCount+1) * sizeof(PCHAR);
|
|
sizeAddrPtrs = (addrCount+1) * sizeof(PCHAR);
|
|
sizeAddrs = addrCount * addrLength;
|
|
|
|
if ( pBlob->pName )
|
|
{
|
|
sizeName = Dns_GetBufferLengthForStringCopy(
|
|
(PCHAR) pBlob->pName,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
CharSetTarget );
|
|
|
|
sizeName = WORD_ALIGN_DWORD( sizeName );
|
|
}
|
|
|
|
for ( i=0; i<aliasCount; i++ )
|
|
{
|
|
sizeAliasNames += Dns_GetBufferLengthForStringCopy(
|
|
(PCHAR) pBlob->AliasArray[i],
|
|
0,
|
|
DnsCharSetUnicode,
|
|
CharSetTarget );
|
|
|
|
sizeAliasNames = WORD_ALIGN_DWORD( sizeAliasNames );
|
|
}
|
|
|
|
sizeTotal = POINTER_ALIGN_DWORD( sizeof(HOSTENT) ) +
|
|
sizeAliasPtrs +
|
|
sizeAddrPtrs +
|
|
sizeAddrs +
|
|
sizeName +
|
|
sizeAliasNames;
|
|
|
|
DNSDBG( HOSTENT, (
|
|
"SaBlob Hostent create:\n"
|
|
"\tsize = %d\n"
|
|
"\tsizeAliasPtrs = %d\n"
|
|
"\tsizeAddrPtrs = %d\n"
|
|
"\tsizeAddrs = %d\n"
|
|
"\tsizeName = %d\n"
|
|
"\tsizeAliasNames = %d\n",
|
|
sizeTotal,
|
|
sizeAliasPtrs,
|
|
sizeAddrPtrs,
|
|
sizeAddrs,
|
|
sizeName,
|
|
sizeAliasNames ));
|
|
|
|
|
|
//
|
|
// alloc or reserve size in buffer
|
|
//
|
|
|
|
if ( fAlloc )
|
|
{
|
|
pch = ALLOCATE_HEAP( sizeTotal );
|
|
if ( !pch )
|
|
{
|
|
goto Failed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pch = FlatBuf_Arg_ReserveAlignPointer(
|
|
ppBuffer,
|
|
pBufferSize,
|
|
sizeTotal
|
|
);
|
|
if ( !pch )
|
|
{
|
|
goto Failed;
|
|
}
|
|
}
|
|
|
|
//
|
|
// note: assuming from here on down that we have adequate space
|
|
//
|
|
// reason we aren't building with FlatBuf routines is that
|
|
// a) we believe we have adequate space
|
|
// b) i haven't built FlatBuf string conversion routines
|
|
// which we need below (for RnR unicode to ANSI)
|
|
//
|
|
// we could reset buf pointers here and build directly with FlatBuf
|
|
// routines; this isn't directly necessary
|
|
//
|
|
|
|
//
|
|
// init hostent struct
|
|
//
|
|
|
|
phost = Hostent_Init(
|
|
& pch,
|
|
family,
|
|
addrLength,
|
|
addrCount,
|
|
aliasCount );
|
|
|
|
DNS_ASSERT( pch > (PBYTE)phost );
|
|
|
|
//
|
|
// copy addresses
|
|
// - no need to align as previous is address
|
|
//
|
|
|
|
pptrArrayOut = phost->h_addr_list;
|
|
|
|
if ( paddrArray && pfamilyInfo )
|
|
{
|
|
DWORD offset = pfamilyInfo->OffsetToAddrInSockaddr;
|
|
|
|
for ( i=0; i<paddrArray->AddrCount; i++ )
|
|
{
|
|
*pptrArrayOut++ = pch;
|
|
|
|
RtlCopyMemory(
|
|
pch,
|
|
((PBYTE)&paddrArray->AddrArray[i]) + offset,
|
|
addrLength );
|
|
|
|
pch += addrLength;
|
|
}
|
|
}
|
|
*pptrArrayOut = NULL;
|
|
|
|
//
|
|
// copy the name
|
|
//
|
|
|
|
if ( pBlob->pName )
|
|
{
|
|
pch = WORD_ALIGN( pch );
|
|
|
|
phost->h_name = pch;
|
|
|
|
size = Dns_StringCopy(
|
|
pch,
|
|
NULL, // buffer is adequate
|
|
(PCHAR)pBlob->pName,
|
|
0, // unknown length
|
|
DnsCharSetUnicode,
|
|
CharSetTarget
|
|
);
|
|
pch += size;
|
|
}
|
|
|
|
//
|
|
// copy the aliases
|
|
//
|
|
|
|
pptrArrayOut = phost->h_aliases;
|
|
|
|
if ( aliasCount )
|
|
{
|
|
for ( i=0; i<aliasCount; i++ )
|
|
{
|
|
pch = WORD_ALIGN( pch );
|
|
|
|
*pptrArrayOut++ = pch;
|
|
|
|
size = Dns_StringCopy(
|
|
pch,
|
|
NULL, // buffer is adequate
|
|
(PCHAR) pBlob->AliasArray[i],
|
|
0, // unknown length
|
|
DnsCharSetUnicode,
|
|
CharSetTarget
|
|
);
|
|
pch += size;
|
|
}
|
|
}
|
|
*pptrArrayOut = NULL;
|
|
|
|
//
|
|
// copy is complete
|
|
// - verify our write functions work
|
|
//
|
|
|
|
ASSERT( (DWORD)(pch-(PBYTE)phost) <= sizeTotal );
|
|
|
|
if ( pHostentSize )
|
|
{
|
|
*pHostentSize = (INT)( pch - (PBYTE)phost );
|
|
}
|
|
|
|
if ( !fAlloc )
|
|
{
|
|
PBYTE pnext = *ppBuffer;
|
|
|
|
// if we sized too small --
|
|
// fix up the buf pointer and bytes left
|
|
|
|
if ( pnext < pch )
|
|
{
|
|
ASSERT( FALSE );
|
|
*ppBuffer = pch;
|
|
*pBufferSize -= (INT)(pch - pnext);
|
|
}
|
|
}
|
|
|
|
IF_DNSDBG( HOSTENT )
|
|
{
|
|
DnsDbg_Hostent(
|
|
"Sablob Hostent:",
|
|
phost,
|
|
(CharSetTarget == DnsCharSetUnicode) );
|
|
}
|
|
|
|
//
|
|
// convert to offsets?
|
|
//
|
|
|
|
if ( fOffsets )
|
|
{
|
|
Hostent_ConvertToOffsets( phost );
|
|
}
|
|
|
|
|
|
Failed:
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave SaBlob_CreateHostent() => %p\n",
|
|
phost ));
|
|
|
|
return phost;
|
|
}
|
|
|
|
//
|
|
// End sablob.c
|
|
//
|
|
|