1178 lines
22 KiB
C
1178 lines
22 KiB
C
/*++
|
||
|
||
Copyright (c) 1996-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rralloc.c
|
||
|
||
Abstract:
|
||
|
||
Domain Name System (DNS) Library
|
||
|
||
Resource record allocation \ creation routines.
|
||
|
||
Author:
|
||
|
||
Jim Gilroy (jamesg) January, 1997
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "local.h"
|
||
|
||
#define SET_FLAGS(Flags, value) \
|
||
( *(PWORD)&(Flags) = value )
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
WINAPI
|
||
Dns_AllocateRecord(
|
||
IN WORD wBufferLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allocate record structure.
|
||
|
||
Arguments:
|
||
|
||
wBufferLength - desired buffer length (beyond structure header)
|
||
|
||
Return Value:
|
||
|
||
Ptr to message buffer.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr;
|
||
|
||
prr = ALLOCATE_HEAP( SIZEOF_DNS_RECORD_HEADER + wBufferLength );
|
||
if ( prr == NULL )
|
||
{
|
||
SetLastError( DNS_ERROR_NO_MEMORY );
|
||
return( NULL );
|
||
}
|
||
RtlZeroMemory(
|
||
prr,
|
||
SIZEOF_DNS_RECORD_HEADER );
|
||
|
||
// as first cut, set datalength to buffer length
|
||
|
||
prr->wDataLength = wBufferLength;
|
||
return( prr );
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
WINAPI
|
||
Dns_RecordFree(
|
||
IN OUT PDNS_RECORD pRecord
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Free a record
|
||
|
||
Arguments:
|
||
|
||
pRecord -- record list to free
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
DNSDBG( HEAP, ( "Dns_RecordFree( %p )\n", pRecord ));
|
||
|
||
// handle NULL for convenience
|
||
|
||
if ( !pRecord )
|
||
{
|
||
return;
|
||
}
|
||
|
||
// free owner name?
|
||
|
||
if ( FLAG_FreeOwner( pRecord ) )
|
||
{
|
||
FREE_HEAP( pRecord->pName );
|
||
}
|
||
|
||
//
|
||
// free data -- but only if flag set
|
||
//
|
||
// note: even if we fix copy functions to do atomic
|
||
// allocations, we'll still have to have free to
|
||
// handle RPC allocations
|
||
// (unless we very cleverly, treated RPC as flat blob, then
|
||
// did fix up (to offsets before and afterward)
|
||
//
|
||
|
||
if ( FLAG_FreeData( pRecord ) )
|
||
{
|
||
switch( pRecord->wType )
|
||
{
|
||
case DNS_TYPE_A:
|
||
break;
|
||
|
||
case DNS_TYPE_PTR:
|
||
case DNS_TYPE_NS:
|
||
case DNS_TYPE_CNAME:
|
||
case DNS_TYPE_MB:
|
||
case DNS_TYPE_MD:
|
||
case DNS_TYPE_MF:
|
||
case DNS_TYPE_MG:
|
||
case DNS_TYPE_MR:
|
||
|
||
if ( pRecord->Data.PTR.pNameHost )
|
||
{
|
||
FREE_HEAP( pRecord->Data.PTR.pNameHost );
|
||
}
|
||
break;
|
||
|
||
case DNS_TYPE_SOA:
|
||
|
||
if ( pRecord->Data.SOA.pNamePrimaryServer )
|
||
{
|
||
FREE_HEAP( pRecord->Data.SOA.pNamePrimaryServer );
|
||
}
|
||
if ( pRecord->Data.SOA.pNameAdministrator )
|
||
{
|
||
FREE_HEAP( pRecord->Data.SOA.pNameAdministrator );
|
||
}
|
||
break;
|
||
|
||
case DNS_TYPE_MINFO:
|
||
case DNS_TYPE_RP:
|
||
|
||
if ( pRecord->Data.MINFO.pNameMailbox )
|
||
{
|
||
FREE_HEAP( pRecord->Data.MINFO.pNameMailbox );
|
||
}
|
||
if ( pRecord->Data.MINFO.pNameErrorsMailbox )
|
||
{
|
||
FREE_HEAP( pRecord->Data.MINFO.pNameErrorsMailbox );
|
||
}
|
||
break;
|
||
|
||
case DNS_TYPE_MX:
|
||
case DNS_TYPE_AFSDB:
|
||
case DNS_TYPE_RT:
|
||
|
||
if ( pRecord->Data.MX.pNameExchange )
|
||
{
|
||
FREE_HEAP( pRecord->Data.MX.pNameExchange );
|
||
}
|
||
break;
|
||
|
||
case DNS_TYPE_HINFO:
|
||
case DNS_TYPE_ISDN:
|
||
case DNS_TYPE_TEXT:
|
||
case DNS_TYPE_X25:
|
||
|
||
{
|
||
DWORD iter;
|
||
DWORD count = pRecord->Data.TXT.dwStringCount;
|
||
|
||
for ( iter = 0; iter < count; iter++ )
|
||
{
|
||
if ( pRecord->Data.TXT.pStringArray[iter] )
|
||
{
|
||
FREE_HEAP( pRecord->Data.TXT.pStringArray[iter] );
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case DNS_TYPE_SRV:
|
||
|
||
if ( pRecord->Data.SRV.pNameTarget )
|
||
{
|
||
FREE_HEAP( pRecord->Data.SRV.pNameTarget );
|
||
}
|
||
break;
|
||
|
||
case DNS_TYPE_WINSR:
|
||
|
||
if ( pRecord->Data.WINSR.pNameResultDomain )
|
||
{
|
||
FREE_HEAP( pRecord->Data.WINSR.pNameResultDomain );
|
||
}
|
||
break;
|
||
|
||
default:
|
||
|
||
// other types -- A, AAAA, ATMA, WINS, NULL,
|
||
// have no internal pointers
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
// for catching heap problems
|
||
|
||
pRecord->pNext = DNS_BAD_PTR;
|
||
pRecord->pName = DNS_BAD_PTR;
|
||
|
||
FREE_HEAP( pRecord );
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
WINAPI
|
||
Dns_RecordListFree(
|
||
IN OUT PDNS_RECORD pRecord
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Free list of records.
|
||
|
||
Arguments:
|
||
|
||
pRecord -- record list to free
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD pnext;
|
||
|
||
DNSDBG( TRACE, (
|
||
"Dns_RecordListFree( %p )\n",
|
||
pRecord ));
|
||
|
||
//
|
||
// loop through and free every RR in list
|
||
//
|
||
|
||
while ( pRecord )
|
||
{
|
||
pnext = pRecord->pNext;
|
||
|
||
Dns_RecordFree( pRecord );
|
||
|
||
pRecord = pnext;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
WINAPI
|
||
Dns_RecordListFreeEx(
|
||
IN OUT PDNS_RECORD pRecord,
|
||
IN BOOL fFreeOwner
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Free list of records.
|
||
|
||
DCR: RecordListFreeEx (no free owner option) is probably useless
|
||
|
||
Note: owner name is freed ONLY when indicated by flag;
|
||
other ptrs are considered to be either
|
||
1) internal as when records read from wire or copied
|
||
2) external and to be freed by record creator
|
||
|
||
Arguments:
|
||
|
||
pRecord -- record list to free
|
||
|
||
fFreeOwner -- flag indicating owner name should be freed
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD pnext;
|
||
|
||
DNSDBG( TRACE, (
|
||
"Dns_RecordListFreeEx( %p, %d )\n",
|
||
pRecord,
|
||
fFreeOwner ));
|
||
|
||
//
|
||
// loop through and free every RR in list
|
||
//
|
||
|
||
while ( pRecord )
|
||
{
|
||
pnext = pRecord->pNext;
|
||
|
||
// free owner name?
|
||
// - if "FreeOwner" flag NOT set, then don't free
|
||
|
||
if ( !fFreeOwner )
|
||
{
|
||
FLAG_FreeOwner( pRecord ) = FALSE;
|
||
}
|
||
|
||
// free record
|
||
|
||
Dns_RecordFree( pRecord );
|
||
|
||
pRecord = pnext;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Special record type creation routines
|
||
//
|
||
|
||
PDNS_RECORD
|
||
CreateRecordBasic(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN BOOL fCopyName,
|
||
IN WORD wType,
|
||
IN WORD wDataLength,
|
||
IN DWORD AllocLength,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create record of arbitary type.
|
||
|
||
Helper function to wrap up
|
||
- record alloc
|
||
- name alloc
|
||
- basic setup
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
fCopyName -- TRUE - make copy of owner name
|
||
FALSE - use directly
|
||
|
||
wType -- type
|
||
|
||
AllocLength -- allocaction length, including any imbedded data
|
||
|
||
wDataLength -- data length to set
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
PDNS_RECORD prr;
|
||
PCHAR pname;
|
||
DWORD bufLength;
|
||
|
||
//
|
||
// alloc record
|
||
//
|
||
|
||
prr = Dns_AllocateRecord( (WORD)AllocLength );
|
||
if ( !prr )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// copy owner name
|
||
//
|
||
|
||
if ( fCopyName && pOwnerName )
|
||
{
|
||
pname = Dns_NameCopyAllocate(
|
||
pOwnerName,
|
||
0, // length unknown
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( prr );
|
||
return( NULL );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pname = pOwnerName;
|
||
}
|
||
|
||
//
|
||
// set fields
|
||
// - name, type and charset
|
||
// - TTL, section left zero
|
||
// - FreeData is specifically off
|
||
//
|
||
|
||
prr->pName = pname;
|
||
prr->wType = wType;
|
||
prr->wDataLength = wDataLength;
|
||
SET_FREE_OWNER(prr);
|
||
prr->Flags.S.CharSet = RecordCharSet;
|
||
prr->dwTtl = Ttl;
|
||
|
||
return( prr );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreateFlatRecord(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN WORD wType,
|
||
IN PCHAR pData,
|
||
IN DWORD DataLength,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create flat record.
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
wType -- record type
|
||
|
||
pData -- ptr to data for record
|
||
|
||
DataLength -- length (in bytes) of data
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr;
|
||
|
||
//
|
||
// determine record size
|
||
// - record buffer will include hostname
|
||
//
|
||
|
||
prr = CreateRecordBasic(
|
||
pOwnerName,
|
||
TRUE, // copy name
|
||
wType,
|
||
(WORD) DataLength, // datalength
|
||
DataLength, // alloc datalength
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
if ( !prr )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// copy in data
|
||
//
|
||
|
||
RtlCopyMemory(
|
||
(PBYTE) &prr->Data,
|
||
pData,
|
||
DataLength );
|
||
|
||
return( prr );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreatePtrTypeRecord(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN BOOL fCopyName,
|
||
IN PDNS_NAME pTargetName,
|
||
IN WORD wType,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create PTR type (single-indirection) record.
|
||
|
||
This can be used to create any "PTR-type" record:
|
||
PTR, CNAME, NS, etc.
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
fCopyName -- TRUE - make copy of owner name
|
||
FALSE - use directly
|
||
|
||
pTargetName -- target name
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
PDNS_RECORD prr;
|
||
PCHAR pname;
|
||
DWORD bufLength;
|
||
|
||
//
|
||
// determine record size
|
||
// - record buffer will include hostname
|
||
//
|
||
|
||
bufLength = Dns_GetBufferLengthForNameCopy(
|
||
pTargetName,
|
||
0, // length unknown
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
if ( !bufLength )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// create record
|
||
//
|
||
|
||
prr = CreateRecordBasic(
|
||
pOwnerName,
|
||
fCopyName,
|
||
wType,
|
||
sizeof(DNS_PTR_DATA), // data length
|
||
(sizeof(DNS_PTR_DATA) + bufLength), // alloc length
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
if ( !prr )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// write target name into buffer, immediately following PTR data struct
|
||
//
|
||
|
||
prr->Data.PTR.pNameHost = (PCHAR)&prr->Data + sizeof(DNS_PTR_DATA);
|
||
|
||
Dns_NameCopy(
|
||
prr->Data.PTR.pNameHost,
|
||
NULL,
|
||
pTargetName,
|
||
0,
|
||
NameCharSet,
|
||
RecordCharSet
|
||
);
|
||
|
||
return( prr );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreatePtrRecordEx(
|
||
IN PIP_UNION pIp,
|
||
IN PDNS_NAME pszHostName,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create PTR record from IP address and hostname.
|
||
|
||
Arguments:
|
||
|
||
pIp -- IP union (IP4 or IP6)
|
||
|
||
pszHostName -- host name, FULL FQDN
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PCHAR pname;
|
||
|
||
//
|
||
// create reverse lookup name
|
||
// - note this is external allocation
|
||
//
|
||
|
||
if ( IPUNION_IS_IP4( pIp ) )
|
||
{
|
||
IP4_ADDRESS ip = IPUNION_GET_IP4(pIp);
|
||
|
||
if ( RecordCharSet == DnsCharSetUnicode )
|
||
{
|
||
pname = (PCHAR) Dns_Ip4AddressToReverseNameAlloc_W( ip );
|
||
}
|
||
else
|
||
{
|
||
pname = Dns_Ip4AddressToReverseNameAlloc_A( ip );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
IP6_ADDRESS ip = IPUNION_GET_IP6(pIp);
|
||
|
||
if ( RecordCharSet == DnsCharSetUnicode )
|
||
{
|
||
pname = (PCHAR) Dns_Ip6AddressToReverseNameAlloc_W( ip );
|
||
}
|
||
else
|
||
{
|
||
pname = Dns_Ip6AddressToReverseNameAlloc_A( ip );
|
||
}
|
||
}
|
||
|
||
if ( !pname )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// build record
|
||
//
|
||
|
||
return Dns_CreatePtrTypeRecord(
|
||
pname,
|
||
FALSE, // don't copy IP
|
||
pszHostName, // target name
|
||
DNS_TYPE_PTR,
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreatePtrRecordExEx(
|
||
IN PIP_UNION pIp,
|
||
IN PSTR pszHostName,
|
||
IN PSTR pszDomainName,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create PTR record from hostname and domain name.
|
||
|
||
Helper function for DHCP registrations when hostname
|
||
and domain name are separate and both required.
|
||
|
||
Arguments:
|
||
|
||
pIp -- IP union (IP4 or IP6)
|
||
|
||
pszHostName -- host name (single label)
|
||
|
||
pszDomainName -- domain name
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
WCHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
||
|
||
DNSDBG( TRACE, (
|
||
"Dns_CreatePtrRecordExEx()\n" ));
|
||
|
||
//
|
||
// build appended name
|
||
//
|
||
// DCR: could require just host name and check that
|
||
// either domain exists or hostname is full
|
||
//
|
||
|
||
if ( !pszHostName || !pszDomainName )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
if ( NameCharSet != DnsCharSetUnicode )
|
||
{
|
||
if ( ! Dns_NameAppend_A(
|
||
(PCHAR) nameBuffer,
|
||
DNS_MAX_NAME_BUFFER_LENGTH,
|
||
pszHostName,
|
||
pszDomainName ) )
|
||
{
|
||
DNS_ASSERT( FALSE );
|
||
return NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ( ! Dns_NameAppend_W(
|
||
(PWCHAR) nameBuffer,
|
||
DNS_MAX_NAME_BUFFER_LENGTH,
|
||
(PWSTR) pszHostName,
|
||
(PWSTR) pszDomainName ) )
|
||
{
|
||
DNS_ASSERT( FALSE );
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
//
|
||
// build record
|
||
//
|
||
|
||
return Dns_CreatePtrRecordEx(
|
||
pIp,
|
||
(PCHAR) nameBuffer,
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet
|
||
);
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreateARecord(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN IP_ADDRESS Ip4Addr,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create A record.
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
Ip4Addr -- IP address
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr;
|
||
|
||
//
|
||
// determine record size
|
||
// - record buffer will include hostname
|
||
//
|
||
|
||
prr = CreateRecordBasic(
|
||
pOwnerName,
|
||
TRUE, // copy name
|
||
DNS_TYPE_A,
|
||
sizeof(DNS_A_DATA),
|
||
sizeof(DNS_A_DATA),
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
if ( !prr )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// set IP
|
||
//
|
||
|
||
prr->Data.A.IpAddress = Ip4Addr;
|
||
|
||
return( prr );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreateAAAARecord(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN IP6_ADDRESS Ip6Addr,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create A record.
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
Ip6Addr -- IP6 address
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr;
|
||
|
||
//
|
||
// determine record size
|
||
// - record buffer will include hostname
|
||
//
|
||
|
||
prr = CreateRecordBasic(
|
||
pOwnerName,
|
||
TRUE, // copy name
|
||
DNS_TYPE_AAAA,
|
||
sizeof(DNS_AAAA_DATA),
|
||
sizeof(DNS_AAAA_DATA),
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
if ( !prr )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// set IP
|
||
//
|
||
|
||
prr->Data.AAAA.Ip6Address = Ip6Addr;
|
||
|
||
return( prr );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreateForwardRecord(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN PIP_UNION pIp,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create forward lookup record.
|
||
|
||
This is just a shim to avoid duplicating selection logic.
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
pIp -- IP address union
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// build desired type
|
||
//
|
||
// DCR: must add\choose A6
|
||
//
|
||
|
||
if ( IPUNION_IS_IP4( pIp ) )
|
||
{
|
||
return Dns_CreateARecord(
|
||
pOwnerName,
|
||
IPUNION_GET_IP4(pIp),
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
}
|
||
else
|
||
{
|
||
return Dns_CreateAAAARecord(
|
||
pOwnerName,
|
||
IPUNION_GET_IP6(pIp),
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
}
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreateForwardRecordForSockaddr(
|
||
IN PDNS_NAME pOwnerName,
|
||
IN PSOCKADDR pSockaddr,
|
||
IN DWORD Ttl,
|
||
IN DNS_CHARSET NameCharSet,
|
||
IN DNS_CHARSET RecordCharSet
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create forward lookup record.
|
||
|
||
This is just a shim to avoid duplicating selection logic.
|
||
|
||
Arguments:
|
||
|
||
pOwnerName -- owner name
|
||
|
||
pSockaddr -- ptr to sockaddr
|
||
|
||
Ttl -- TTL
|
||
|
||
NameCharSet -- character set of name
|
||
|
||
RecordCharSet -- character set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to PTR record.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PFAMILY_INFO pinfo;
|
||
|
||
DNSDBG( TRACE, (
|
||
"Dns_CreateForwardRecordForSockaddr()\n" ));
|
||
|
||
pinfo = FamilyInfo_GetForSockaddr( pSockaddr );
|
||
if ( !pinfo )
|
||
{
|
||
SetLastError( ERROR_INVALID_DATA );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// build flat record of desired type
|
||
//
|
||
|
||
return Dns_CreateFlatRecord(
|
||
pOwnerName,
|
||
pinfo->DnsType,
|
||
(PBYTE)pSockaddr + pinfo->OffsetToAddrInSockaddr,
|
||
pinfo->LengthAddr,
|
||
Ttl,
|
||
NameCharSet,
|
||
RecordCharSet );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_CreateRecordForIpString_W(
|
||
IN PCWSTR pwsName,
|
||
IN WORD wType,
|
||
IN DWORD Ttl
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create record for IP string query.
|
||
|
||
Arguments:
|
||
|
||
pwsName -- name that may be IP string query
|
||
|
||
wType -- type of query
|
||
|
||
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;
|
||
|
||
|
||
DNSDBG( TRACE, (
|
||
"\nDns_CreateRecordForIpString( %S, wType = %d )\n",
|
||
pwsName,
|
||
wType ));
|
||
|
||
if ( !pwsName )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// support A or AAAA queries for IP strings
|
||
// - IP4 strings must be in w.x.y.z form otherwise
|
||
// we convert the all numeric names also
|
||
//
|
||
// DCR: need A6 support for direct query
|
||
//
|
||
|
||
if ( wType == DNS_TYPE_A )
|
||
{
|
||
IP4_ADDRESS ip4;
|
||
PCWSTR pdot;
|
||
DWORD count;
|
||
|
||
if ( ! Dns_Ip4StringToAddress_W(
|
||
& ip4,
|
||
(PWSTR) pwsName ) )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
// verify three dot form w.x.y.z
|
||
|
||
pdot = pwsName;
|
||
count = 3;
|
||
while ( count-- )
|
||
{
|
||
pdot = wcschr( pdot, L'.' );
|
||
if ( !pdot || !*++pdot )
|
||
{
|
||
return( NULL );
|
||
}
|
||
}
|
||
|
||
IPUNION_SET_IP4( &ipUnion, ip4 );
|
||
}
|
||
else if ( wType == DNS_TYPE_AAAA )
|
||
{
|
||
IP6_ADDRESS ip6;
|
||
|
||
if ( ! Dns_Ip6StringToAddress_W(
|
||
& ip6,
|
||
(PWSTR) pwsName ) )
|
||
{
|
||
return NULL;
|
||
}
|
||
IPUNION_SET_IP6( &ipUnion, ip6 );
|
||
}
|
||
else
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// name is IP string -- build record
|
||
//
|
||
|
||
prr = Dns_CreateForwardRecord(
|
||
(PDNS_NAME) pwsName,
|
||
& ipUnion,
|
||
Ttl,
|
||
DnsCharSetUnicode,
|
||
DnsCharSetUnicode );
|
||
|
||
DNSDBG( TRACE, (
|
||
"Create record %p for IP string %S type %d.\n",
|
||
prr,
|
||
pwsName,
|
||
wType ));
|
||
|
||
return prr;
|
||
}
|
||
|
||
//
|
||
// End rralloc.c
|
||
//
|