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.
1802 lines
42 KiB
1802 lines
42 KiB
/*++
|
|
|
|
Copyright (c) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rrread.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) Library
|
|
|
|
Read resource record from packet routines.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) January, 1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
A_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read A record data from packet.
|
|
|
|
Arguments:
|
|
|
|
pRR - RR context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to packet RR data
|
|
|
|
wLength - length of RR data in packet
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
|
|
if ( pchEnd - pchData != sizeof(IP4_ADDRESS) )
|
|
{
|
|
SetLastError( ERROR_INVALID_DATA );
|
|
return( NULL );
|
|
}
|
|
precord = Dns_AllocateRecord( sizeof(IP4_ADDRESS) );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
precord->Data.A.IpAddress = *(UNALIGNED DWORD *) pchData;
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Ptr_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process PTR compatible record from wire.
|
|
Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
WORD nameLength;
|
|
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
//
|
|
// PTR data is another domain name
|
|
//
|
|
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer,
|
|
& nameLength,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
if ( pchData != pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = sizeof( DNS_PTR_DATA );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength, OutCharSet );
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// write hostname into buffer, immediately following PTR data struct
|
|
//
|
|
|
|
precord->Data.PTR.pNameHost = (PCHAR)&precord->Data + sizeof( DNS_PTR_DATA );
|
|
|
|
Dns_NameCopy(
|
|
precord->Data.PTR.pNameHost,
|
|
NULL, // no buffer length
|
|
nameBuffer,
|
|
nameLength,
|
|
DnsCharSetWire,
|
|
OutCharSet
|
|
);
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Soa_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read SOA record from wire.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
PCHAR pchendFixed;
|
|
PDWORD pdword;
|
|
WORD nameLength1;
|
|
WORD nameLength2;
|
|
CHAR nameBuffer1[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
CHAR nameBuffer2[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
//
|
|
// read DNS names
|
|
//
|
|
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer1,
|
|
& nameLength1,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
if ( !pchData || pchData >= pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer2,
|
|
& nameLength2,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
pchendFixed = pchData + SIZEOF_SOA_FIXED_DATA;
|
|
if ( pchendFixed != pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = sizeof( DNS_SOA_DATA );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength1, OutCharSet );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength2, OutCharSet );
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy fixed fields
|
|
//
|
|
|
|
pdword = &precord->Data.SOA.dwSerialNo;
|
|
while ( pchData < pchendFixed )
|
|
{
|
|
*pdword++ = FlipUnalignedDword( pchData );
|
|
pchData += sizeof(DWORD);
|
|
}
|
|
|
|
//
|
|
// copy names into RR buffer
|
|
// - primary server immediately follows SOA data struct
|
|
// - responsible party follows primary server
|
|
//
|
|
|
|
precord->Data.SOA.pNamePrimaryServer =
|
|
(PCHAR)&precord->Data + sizeof(DNS_SOA_DATA);
|
|
|
|
precord->Data.SOA.pNameAdministrator =
|
|
precord->Data.SOA.pNamePrimaryServer +
|
|
Dns_NameCopy(
|
|
precord->Data.SOA.pNamePrimaryServer,
|
|
NULL, // no buffer length
|
|
nameBuffer1,
|
|
nameLength1,
|
|
DnsCharSetWire,
|
|
OutCharSet );
|
|
|
|
Dns_NameCopy(
|
|
precord->Data.SOA.pNameAdministrator,
|
|
NULL, // no buffer length
|
|
nameBuffer2,
|
|
nameLength2,
|
|
DnsCharSetWire,
|
|
OutCharSet
|
|
);
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Txt_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read TXT compatible record from wire.
|
|
Includes: TXT, X25, HINFO, ISDN
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
WORD length;
|
|
INT count;
|
|
PCHAR pch;
|
|
PCHAR pchbuffer;
|
|
PCHAR * ppstring;
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
// - allocate space for each string
|
|
// - and ptr for each string
|
|
//
|
|
|
|
bufLength = 0;
|
|
count = 0;
|
|
pch = pchData;
|
|
|
|
while ( pch < pchEnd )
|
|
{
|
|
length = (UCHAR) *pch++;
|
|
pch += length;
|
|
count++;
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( length, OutCharSet );
|
|
}
|
|
if ( pch != pchEnd )
|
|
{
|
|
DNS_PRINT((
|
|
"ERROR: Invalid packet string data.\n"
|
|
"\tpch = %p\n"
|
|
"\tpchEnd = %p\n"
|
|
"\tcount = %d\n"
|
|
"\tlength = %d\n",
|
|
pch, pchEnd, count, length
|
|
));
|
|
SetLastError( ERROR_INVALID_DATA );
|
|
return( NULL );
|
|
}
|
|
|
|
// allocate
|
|
|
|
bufLength += (WORD) DNS_TEXT_RECORD_LENGTH(count);
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
precord->Data.TXT.dwStringCount = count;
|
|
|
|
//
|
|
// DCR: if separate HINFO type -- handle this here
|
|
// - set pointer differently
|
|
// - validate string count found
|
|
//
|
|
|
|
//
|
|
// go back through list copying strings to buffer
|
|
// - ptrs to strings are saved to argv like data section
|
|
// ppstring walks through this section
|
|
// - first string written immediately following data section
|
|
// - each subsequent string immediately follows predecessor
|
|
// pchbuffer keeps ptr to position to write strings
|
|
//
|
|
|
|
pch = pchData;
|
|
ppstring = (PCHAR *) precord->Data.TXT.pStringArray;
|
|
pchbuffer = (PBYTE)ppstring + (count * sizeof(PCHAR));
|
|
|
|
while ( pch < pchEnd )
|
|
{
|
|
length = (UCHAR) *pch++;
|
|
#if DBG
|
|
DNS_PRINT((
|
|
"Reading text at %p (len %d), to buffer at %p\n"
|
|
"\tsave text ptr[%d] at %p in precord (%p)\n",
|
|
pch,
|
|
length,
|
|
pchbuffer,
|
|
(PCHAR *) ppstring - (PCHAR *) precord->Data.TXT.pStringArray,
|
|
ppstring,
|
|
precord ));
|
|
#endif
|
|
*ppstring++ = pchbuffer;
|
|
pchbuffer += Dns_StringCopy(
|
|
pchbuffer,
|
|
NULL,
|
|
pch,
|
|
length,
|
|
DnsCharSetWire,
|
|
OutCharSet );
|
|
pch += length;
|
|
#if DBG
|
|
DNS_PRINT((
|
|
"Read text string %s\n",
|
|
* (ppstring - 1)
|
|
));
|
|
count--;
|
|
#endif
|
|
}
|
|
DNS_ASSERT( pch == pchEnd && count == 0 );
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Minfo_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read MINFO record from wire.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
WORD nameLength1;
|
|
WORD nameLength2;
|
|
CHAR nameBuffer1[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
CHAR nameBuffer2[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
//
|
|
// read DNS names
|
|
//
|
|
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer1,
|
|
& nameLength1,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
if ( !pchData || pchData >= pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer2,
|
|
& nameLength2,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
if ( pchData != pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = sizeof( DNS_MINFO_DATA );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength1, OutCharSet );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength2, OutCharSet );
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy names into RR buffer
|
|
// - primary server immediately follows MINFO data struct
|
|
// - responsible party follows primary server
|
|
//
|
|
|
|
precord->Data.MINFO.pNameMailbox =
|
|
(PCHAR)&precord->Data + sizeof( DNS_MINFO_DATA );
|
|
|
|
precord->Data.MINFO.pNameErrorsMailbox =
|
|
precord->Data.MINFO.pNameMailbox +
|
|
Dns_NameCopy(
|
|
precord->Data.MINFO.pNameMailbox,
|
|
NULL, // no buffer length
|
|
nameBuffer1,
|
|
nameLength1,
|
|
DnsCharSetWire,
|
|
OutCharSet );
|
|
|
|
Dns_NameCopy(
|
|
precord->Data.MINFO.pNameErrorsMailbox,
|
|
NULL, // no buffer length
|
|
nameBuffer2,
|
|
nameLength2,
|
|
DnsCharSetWire,
|
|
OutCharSet
|
|
);
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Mx_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read MX compatible record from wire.
|
|
Includes: MX, RT, AFSDB
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
WORD nameLength;
|
|
WORD wpreference;
|
|
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
// read preference value
|
|
|
|
wpreference = FlipUnalignedWord( pchData );
|
|
pchData += sizeof(WORD);
|
|
|
|
// read mail exchange
|
|
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer,
|
|
& nameLength,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
if ( pchData != pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = sizeof( DNS_MX_DATA );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength, OutCharSet );
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
// copy preference
|
|
|
|
precord->Data.MX.wPreference = wpreference;
|
|
|
|
//
|
|
// write exchange name into buffer, immediately following MX data struct
|
|
//
|
|
|
|
precord->Data.MX.pNameExchange = (PCHAR)&precord->Data + sizeof( DNS_MX_DATA );
|
|
|
|
Dns_NameCopy(
|
|
precord->Data.MX.pNameExchange,
|
|
NULL, // no buffer length
|
|
nameBuffer,
|
|
nameLength,
|
|
DnsCharSetWire,
|
|
OutCharSet
|
|
);
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Flat_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read memory copy compatible record from wire.
|
|
Includes AAAA type.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = (WORD)(pchEnd - pchData);
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy packet data to record
|
|
//
|
|
|
|
memcpy(
|
|
& precord->Data,
|
|
pchData,
|
|
bufLength );
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Srv_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read SRV record from wire.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
WORD nameLength;
|
|
PCHAR pchstart;
|
|
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
//
|
|
// read SRV target name
|
|
// - name is after fixed length integer data
|
|
|
|
pchstart = pchData;
|
|
pchData += SIZEOF_SRV_FIXED_DATA;
|
|
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer,
|
|
& nameLength,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
if ( pchData != pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = sizeof( DNS_SRV_DATA );
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength, OutCharSet );
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy integer fields
|
|
//
|
|
|
|
precord->Data.SRV.wPriority = FlipUnalignedWord( pchstart );
|
|
pchstart += sizeof( WORD );
|
|
precord->Data.SRV.wWeight = FlipUnalignedWord( pchstart );
|
|
pchstart += sizeof( WORD );
|
|
precord->Data.SRV.wPort = FlipUnalignedWord( pchstart );
|
|
|
|
//
|
|
// copy target host name into RR buffer
|
|
// - write target host immediately following SRV data struct
|
|
//
|
|
|
|
precord->Data.SRV.pNameTarget = (PCHAR)&precord->Data + sizeof( DNS_SRV_DATA );
|
|
|
|
Dns_NameCopy(
|
|
precord->Data.SRV.pNameTarget,
|
|
NULL, // no buffer length
|
|
nameBuffer,
|
|
nameLength,
|
|
DnsCharSetWire,
|
|
OutCharSet
|
|
);
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
PDNS_RECORD
|
|
Atma_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read ATMA record from wire.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
PCHAR pchstart;
|
|
WORD wLen = (WORD) (pchEnd - pchData);
|
|
|
|
pchstart = pchData;
|
|
|
|
precord = Dns_AllocateRecord( sizeof( DNS_ATMA_DATA ) +
|
|
DNS_ATMA_MAX_ADDR_LENGTH );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy ATMA integer fields
|
|
//
|
|
|
|
precord->Data.ATMA.AddressType = *pchstart;
|
|
pchstart += sizeof( BYTE );
|
|
|
|
if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 )
|
|
{
|
|
precord->wDataLength = wLen;
|
|
|
|
if ( precord->wDataLength > DNS_ATMA_MAX_ADDR_LENGTH )
|
|
precord->wDataLength = DNS_ATMA_MAX_ADDR_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
precord->wDataLength = DNS_ATMA_MAX_ADDR_LENGTH;
|
|
}
|
|
|
|
//
|
|
// copy ATMA address field
|
|
//
|
|
memcpy( (PCHAR)&precord->Data.ATMA.Address,
|
|
pchstart,
|
|
precord->wDataLength - sizeof( BYTE ) );
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Wks_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read Wks record data from packet.
|
|
|
|
Arguments:
|
|
|
|
pRR - RR context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to packet RR data field
|
|
|
|
pchEnd - ptr to end of the data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
Author:
|
|
Cameron Etezadi (camerone) - 1 May 1997
|
|
- for NS Lookup purposes, must add this function
|
|
|
|
NOTE:
|
|
NONE of the getXXXbyYYY calls return unicode in their
|
|
structures! If we want the returned record to be unicode,
|
|
then we must translate. I am leaving it as char* for now,
|
|
can go back later and fix this.
|
|
--*/
|
|
{
|
|
PDNS_RECORD pRecord;
|
|
WORD wLength;
|
|
PCHAR pStart;
|
|
UCHAR cProto;
|
|
struct protoent * proto;
|
|
struct servent * serv;
|
|
IP4_ADDRESS ipAddress;
|
|
char * szListOfServices;
|
|
int nSize;
|
|
char * szProtoName;
|
|
BYTE cMask = 0x80; // is this right? Left to right?
|
|
BYTE cByteToCheck;
|
|
int i;
|
|
int j = 0;
|
|
int nPortNumToQuery;
|
|
int nCurLength = 1;
|
|
char * szTemp;
|
|
|
|
pStart = pchData;
|
|
if (! pStart)
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS did not get a record.\n" ));
|
|
SetLastError( ERROR_INVALID_DATA );
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Check size. Must at least be an IP Address + a protocol
|
|
//
|
|
|
|
if ((pchEnd - pchData) < (sizeof(IP4_ADDRESS) + sizeof(UCHAR)))
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS packet was too small for any data.\n" ));
|
|
SetLastError( ERROR_INVALID_DATA );
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Fill in the ip and protocol
|
|
//
|
|
|
|
ipAddress = *(UNALIGNED DWORD *)pStart;
|
|
pStart += sizeof(IP4_ADDRESS);
|
|
cProto = *(UCHAR *)pStart;
|
|
pStart += sizeof(UCHAR);
|
|
|
|
//
|
|
// Redefined the WKS structure to contain a listing
|
|
// of space separated monikers for the services
|
|
//
|
|
// Get the protocol
|
|
//
|
|
|
|
proto = getprotobynumber(cProto);
|
|
if (!proto)
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS failed to resolve protocol number to name.\n" ));
|
|
SetLastError(ERROR_INVALID_DATA);
|
|
return(NULL);
|
|
}
|
|
|
|
nSize = strlen(proto->p_name);
|
|
szProtoName = ALLOCATE_HEAP((nSize + 1) * sizeof(char));
|
|
|
|
if (!szProtoName)
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS could not allocate space for proto name\n"));
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return(NULL);
|
|
}
|
|
strcpy(szProtoName, proto->p_name);
|
|
|
|
//
|
|
// Now, the tricky part. This is a bitmask.
|
|
// I must translate to a string for each bit marked in the bitmask
|
|
//
|
|
|
|
DNS_PRINT(( "Now checking bitmask bits.\n"));
|
|
|
|
szTemp = NULL;
|
|
|
|
szListOfServices = ALLOCATE_HEAP(sizeof(char));
|
|
if (!szListOfServices)
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS could not allocate space for services name\n"));
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
FREE_HEAP(szProtoName);
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
*szListOfServices = '\0';
|
|
}
|
|
|
|
while (pStart < pchEnd)
|
|
{
|
|
cByteToCheck = *(BYTE *)pStart;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (cByteToCheck & cMask)
|
|
{
|
|
// This is a service that is valid
|
|
nPortNumToQuery = i + (8 * j);
|
|
serv = getservbyport(htons((USHORT)nPortNumToQuery), szProtoName);
|
|
if (! serv)
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS found a port that could not be translated\n"));
|
|
SetLastError(ERROR_INVALID_DATA);
|
|
FREE_HEAP(szProtoName);
|
|
FREE_HEAP(szListOfServices);
|
|
return(NULL);
|
|
}
|
|
nSize = strlen(serv->s_name);
|
|
nCurLength = nCurLength + nSize + 1;
|
|
|
|
//
|
|
// Allocate more memory. We need the + 1 here
|
|
// because we will overwrite the existing null with a strcat
|
|
// (removing the need) but use a space to separate items
|
|
//
|
|
|
|
szTemp = ALLOCATE_HEAP( nCurLength);
|
|
|
|
if (! szTemp)
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS alloc space for services name\n" ));
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
FREE_HEAP(szProtoName);
|
|
FREE_HEAP(szListOfServices);
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
strcpy( szTemp, szListOfServices );
|
|
FREE_HEAP( szListOfServices );
|
|
szListOfServices = szTemp;
|
|
szTemp = NULL;
|
|
}
|
|
|
|
//
|
|
// Append the retrieved service name to the end of the list
|
|
//
|
|
|
|
strcat(szListOfServices, serv->s_name);
|
|
strcat(szListOfServices, " ");
|
|
}
|
|
cByteToCheck <<= 1;
|
|
}
|
|
|
|
//
|
|
// Increment the "how many bytes have we done" offset counter
|
|
//
|
|
|
|
j++;
|
|
pStart += sizeof(BYTE);
|
|
}
|
|
FREE_HEAP(szProtoName);
|
|
|
|
//
|
|
// Allocate a record and fill it in.
|
|
//
|
|
|
|
wLength = (WORD)(sizeof(IP4_ADDRESS) + sizeof(UCHAR) + sizeof(int)
|
|
+ (sizeof(char) * ++nCurLength));
|
|
|
|
pRecord = Dns_AllocateRecord(wLength);
|
|
if ( !pRecord )
|
|
{
|
|
DNS_PRINT(( "ERROR: WKS failed to allocate record\n" ));
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
FREE_HEAP(szListOfServices);
|
|
return(NULL);
|
|
}
|
|
|
|
pRecord->Data.WKS.IpAddress = ipAddress;
|
|
pRecord->Data.WKS.chProtocol = cProto;
|
|
|
|
strcpy((char *)pRecord->Data.WKS.BitMask, szListOfServices);
|
|
FREE_HEAP(szListOfServices);
|
|
|
|
return(pRecord);
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Tkey_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
{
|
|
PCHAR pch;
|
|
PDNS_RECORD prr;
|
|
WORD bufLength;
|
|
WORD keyLength;
|
|
PCHAR pchstart;
|
|
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
//
|
|
// allocate record
|
|
//
|
|
|
|
bufLength = sizeof( DNS_TKEY_DATA );
|
|
|
|
prr = Dns_AllocateRecord( bufLength );
|
|
if ( !prr )
|
|
{
|
|
return( NULL );
|
|
}
|
|
prr->wType = DNS_TYPE_TKEY;
|
|
|
|
//
|
|
// algorithm name
|
|
//
|
|
|
|
pch = Dns_SkipPacketName(
|
|
pchData,
|
|
pchEnd );
|
|
if ( !pch )
|
|
{
|
|
goto Formerr;
|
|
}
|
|
prr->Data.TKEY.pAlgorithmPacket = (PDNS_NAME) pchData;
|
|
prr->Data.TKEY.cAlgNameLength = (UCHAR)(pch - pchData);
|
|
prr->Data.TKEY.pNameAlgorithm = NULL;
|
|
|
|
#if 0
|
|
//
|
|
// DEVNOTE: currently not allocating data for TKEY, using internal pointers
|
|
//
|
|
// allocated version
|
|
// note for this we won't have compression pointer which is fine
|
|
// since no name compression in data
|
|
// however function may need dummy to do the right thing
|
|
// should perhaps just pass in pchStart which can be dummy to
|
|
// real header
|
|
//
|
|
|
|
pch = Dns_ReadPacketNameAllocate(
|
|
& prr->Data.TKEY.pNameAlgorithm,
|
|
& nameLength,
|
|
NULL, // no previous name
|
|
NULL, // no previous name
|
|
pchData,
|
|
//pchStart, // have no packet context
|
|
NULL,
|
|
pchEnd );
|
|
if ( !pch )
|
|
{
|
|
DNSDBG( SECURITY, (
|
|
"WARNING: invalid TKEY algorithm name at %p.\n",
|
|
pch ));
|
|
goto Formerr;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// read fixed fields
|
|
//
|
|
|
|
if ( pch + SIZEOF_TKEY_FIXED_DATA >= pchEnd )
|
|
{
|
|
goto Formerr;
|
|
}
|
|
prr->Data.TKEY.dwCreateTime = InlineFlipUnalignedDword( pch );
|
|
pch += sizeof(DWORD);
|
|
prr->Data.TKEY.dwExpireTime = InlineFlipUnalignedDword( pch );
|
|
pch += sizeof(DWORD);
|
|
prr->Data.TKEY.wMode = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
prr->Data.TKEY.wError = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
prr->Data.TKEY.wKeyLength = keyLength = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
// now have key and other length to read
|
|
|
|
if ( pch + keyLength + sizeof(WORD) > pchEnd )
|
|
{
|
|
goto Formerr;
|
|
}
|
|
|
|
//
|
|
// save ptr to key
|
|
//
|
|
|
|
prr->Data.TKEY.pKey = pch;
|
|
pch += keyLength;
|
|
|
|
#if 0
|
|
//
|
|
// copy key
|
|
//
|
|
|
|
pkey = ALLOCATE_HEAP( keyLength );
|
|
if ( !pkey )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Failed;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
pkey,
|
|
pch,
|
|
keyLength );
|
|
|
|
pch += keyLength;
|
|
#endif
|
|
|
|
//
|
|
// other data
|
|
//
|
|
|
|
prr->Data.TKEY.wOtherLength = keyLength = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
if ( pch + keyLength > pchEnd )
|
|
{
|
|
goto Formerr;
|
|
}
|
|
if ( !keyLength )
|
|
{
|
|
prr->Data.TKEY.pOtherData = NULL;
|
|
}
|
|
else
|
|
{
|
|
prr->Data.TKEY.pOtherData = pch;
|
|
}
|
|
|
|
// DCR_ENHANCE: TKEY end-of-data verification
|
|
|
|
// returning TKEY with packet pointers as only point is processing
|
|
|
|
prr->Data.TKEY.bPacketPointers = TRUE;
|
|
|
|
//
|
|
// DCR_ENHANCE: copied subfields, best to get here with stack record, then
|
|
// allocate RR containing subfields and copy everything
|
|
|
|
return( prr );
|
|
|
|
Formerr:
|
|
|
|
DNSDBG( ANY, (
|
|
"ERROR: FOMERR processing TKEY at %p in message\n",
|
|
pchData ));
|
|
|
|
// free record
|
|
// if switch to allocated subfields need
|
|
|
|
FREE_HEAP( prr );
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Tsig_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read SRV record from wire.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - [OLD SEMANTICS, UNUSED] start of DNS message
|
|
|
|
OVERLOAD pchStart!!
|
|
Since we're stuck w/ this function signature, we'll overload
|
|
the unused param pchStart to get the iKeyVersion.
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PCHAR pch;
|
|
PDNS_RECORD prr;
|
|
WORD bufLength;
|
|
WORD sigLength;
|
|
PCHAR pchstart;
|
|
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
#if 0
|
|
// currently do not need versioning info
|
|
// if had to do again, should extract version then pass
|
|
// in another pRR field; or send entire packet context
|
|
//
|
|
// extract current TSIG version (from key string)
|
|
//
|
|
|
|
ASSERT( pRR );
|
|
iKeyVersion = Dns_GetKeyVersion( pRR->pName );
|
|
#endif
|
|
|
|
//
|
|
// allocate record
|
|
//
|
|
|
|
bufLength = sizeof( DNS_TSIG_DATA );
|
|
|
|
prr = Dns_AllocateRecord( bufLength );
|
|
if ( !prr )
|
|
{
|
|
return( NULL );
|
|
}
|
|
prr->wType = DNS_TYPE_TSIG;
|
|
|
|
//
|
|
// algorithm name
|
|
//
|
|
|
|
pch = Dns_SkipPacketName(
|
|
pchData,
|
|
pchEnd );
|
|
if ( !pch )
|
|
{
|
|
DNSDBG( SECURITY, (
|
|
"WARNING: invalid TSIG RR algorithm name.\n" ));
|
|
goto Formerr;
|
|
}
|
|
|
|
prr->Data.TSIG.pAlgorithmPacket = (PDNS_NAME) pchData;
|
|
prr->Data.TSIG.cAlgNameLength = (UCHAR)(pch - pchData);
|
|
|
|
#if 0
|
|
// allocated version
|
|
// note for this we won't have compression pointer which is fine
|
|
// since no name compression in data
|
|
// however function may need dummy to do the right thing
|
|
// should perhaps just pass in pchStart which can be dummy
|
|
// to real header
|
|
//
|
|
|
|
pch = Dns_ReadPacketNameAllocate(
|
|
& prr->Data.TSIG.pNameAlgorithm,
|
|
& nameLength,
|
|
NULL, // no previous name
|
|
NULL, // no previous name
|
|
pchData,
|
|
//pchStart, // have no packet context
|
|
NULL,
|
|
pchEnd );
|
|
if ( !pch )
|
|
{
|
|
DNSDBG( SECURITY, (
|
|
"WARNING: invalid TSIG RR algorithm name at %p.\n",
|
|
pch ));
|
|
goto Formerr;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// read fixed fields
|
|
//
|
|
|
|
if ( pch + SIZEOF_TSIG_FIXED_DATA >= pchEnd )
|
|
{
|
|
DNSDBG( SECURITY, (
|
|
"ERROR: TSIG has inadequate length for fixed fields.\n" ));
|
|
goto Formerr;
|
|
}
|
|
|
|
//
|
|
// read time fields
|
|
// - 48 bit create time
|
|
// - 16 bit fudge
|
|
//
|
|
|
|
prr->Data.TSIG.i64CreateTime = InlineFlipUnaligned48Bits( pch );
|
|
pch += sizeof(DWORD) + sizeof(WORD);
|
|
|
|
prr->Data.TSIG.wFudgeTime = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
//
|
|
// save sig length and sig pointer
|
|
//
|
|
|
|
prr->Data.TSIG.wSigLength = sigLength = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
prr->Data.TSIG.pSignature = pch;
|
|
pch += sigLength;
|
|
|
|
//
|
|
// verify rest of fields within packet
|
|
// - signature
|
|
// - original XID
|
|
// - extended RCODE
|
|
// - other data length field
|
|
// - other data
|
|
//
|
|
|
|
if ( pch + SIZEOF_TSIG_POST_SIG_FIXED_DATA > pchEnd )
|
|
{
|
|
DNSDBG( SECURITY, (
|
|
"ERROR: TSIG has inadequate length for post-sig fixed fields.\n" ));
|
|
goto Formerr;
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// note: if this activated, would need to validate length pull
|
|
// sig ptr thing above and change validation to include sig length
|
|
//
|
|
// copy sig
|
|
//
|
|
|
|
psig = ALLOCATE_HEAP( sigLength );
|
|
if ( !psig )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Failed;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
psig,
|
|
pch,
|
|
sigLength );
|
|
|
|
pch += sigLength;
|
|
#endif
|
|
|
|
// original XID
|
|
// - leave in net order, as just replace in message for signing
|
|
|
|
prr->Data.TSIG.wOriginalXid = READ_PACKET_NET_WORD( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
DNSDBG( SECURITY, (
|
|
"Read original XID <== 0x%x.\n",
|
|
prr->Data.TSIG.wOriginalXid ));
|
|
|
|
// error field
|
|
|
|
prr->Data.TSIG.wError = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
//
|
|
// other data
|
|
//
|
|
|
|
prr->Data.TSIG.wOtherLength = sigLength = InlineFlipUnalignedWord( pch );
|
|
pch += sizeof(WORD);
|
|
|
|
if ( pch + sigLength > pchEnd )
|
|
{
|
|
DNSDBG( SECURITY, (
|
|
"WARNING: invalid TSIG RR sigLength %p.\n",
|
|
pch ));
|
|
goto Formerr;
|
|
}
|
|
if ( !sigLength )
|
|
{
|
|
prr->Data.TSIG.pOtherData = NULL;
|
|
}
|
|
else
|
|
{
|
|
prr->Data.TSIG.pOtherData = pch;
|
|
}
|
|
|
|
// DCR_ENHANCE: TSIG end-of-data verification
|
|
|
|
// returning TSIG with packet pointers as only point is processing
|
|
|
|
prr->Data.TSIG.bPacketPointers = TRUE;
|
|
|
|
//
|
|
// DCR_ENHANCE: copied subfields, best to get here with stack record, then
|
|
// allocate RR containing subfields and copy everything
|
|
|
|
return( prr );
|
|
|
|
Formerr:
|
|
|
|
DNSDBG( ANY, (
|
|
"ERROR: FOMERR processing TSIG in message at %p\n" ));
|
|
|
|
// free record
|
|
// if switch to allocated subfields need
|
|
|
|
FREE_HEAP( prr );
|
|
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Wins_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read WINS record from wire.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = (WORD)(pchEnd - pchData);
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy packet data to record
|
|
//
|
|
|
|
memcpy(
|
|
& precord->Data,
|
|
pchData,
|
|
bufLength );
|
|
|
|
precord->Data.WINS.dwMappingFlag =
|
|
FlipUnalignedDword( &precord->Data.Wins.dwMappingFlag );
|
|
precord->Data.WINS.dwLookupTimeout =
|
|
FlipUnalignedDword( &precord->Data.Wins.dwLookupTimeout );
|
|
precord->Data.WINS.dwCacheTimeout =
|
|
FlipUnalignedDword( &precord->Data.Wins.dwCacheTimeout );
|
|
precord->Data.WINS.cWinsServerCount =
|
|
FlipUnalignedDword( &precord->Data.Wins.cWinsServerCount );
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
PDNS_RECORD
|
|
Winsr_RecordRead(
|
|
IN OUT PDNS_RECORD pRR,
|
|
IN DNS_CHARSET OutCharSet,
|
|
IN OUT PCHAR pchStart,
|
|
IN PCHAR pchData,
|
|
IN PCHAR pchEnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read WINSR record.
|
|
|
|
Arguments:
|
|
|
|
pRR - ptr to record with RR set context
|
|
|
|
pchStart - start of DNS message
|
|
|
|
pchData - ptr to RR data field
|
|
|
|
pchEnd - ptr to byte after data field
|
|
|
|
Return Value:
|
|
|
|
Ptr to new record if successful.
|
|
NULL on failure.
|
|
|
|
--*/
|
|
{
|
|
#define SIZEOF_WINSR_FIXED_DATA (sizeof(DNS_WINSR_DATA)-sizeof(PCHAR))
|
|
|
|
PDNS_RECORD precord;
|
|
WORD bufLength;
|
|
WORD nameLength;
|
|
CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
PCHAR pchstart;
|
|
|
|
//
|
|
// read WINSR domain name
|
|
// - name is after fixed length integer data
|
|
|
|
pchstart = pchData;
|
|
pchData += SIZEOF_WINSR_FIXED_DATA;
|
|
|
|
pchData = Dns_ReadPacketName(
|
|
nameBuffer,
|
|
& nameLength,
|
|
NULL,
|
|
NULL,
|
|
pchData,
|
|
pchStart,
|
|
pchEnd );
|
|
|
|
if ( pchData != pchEnd )
|
|
{
|
|
DNS_PRINT(( "ERROR: bad packet name.\n" ));
|
|
SetLastError( DNS_ERROR_INVALID_NAME );
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// determine required buffer length and allocate
|
|
//
|
|
|
|
bufLength = sizeof(DNS_WINSR_DATA);
|
|
bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( nameLength, OutCharSet );
|
|
|
|
precord = Dns_AllocateRecord( bufLength );
|
|
if ( !precord )
|
|
{
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// copy fixed data
|
|
// - copy first so flipping is aligned
|
|
|
|
memcpy(
|
|
& precord->Data,
|
|
pchstart,
|
|
SIZEOF_WINSR_FIXED_DATA );
|
|
|
|
precord->Data.WINSR.dwMappingFlag = ntohl( precord->Data.WINSR.dwMappingFlag );
|
|
precord->Data.WINSR.dwLookupTimeout = ntohl( precord->Data.WINSR.dwLookupTimeout );
|
|
precord->Data.WINSR.dwCacheTimeout = ntohl( precord->Data.WINSR.dwCacheTimeout );
|
|
|
|
//
|
|
// write hostname into buffer, immediately following PTR data struct
|
|
//
|
|
|
|
precord->Data.WINSR.pNameResultDomain = (PCHAR)&precord->Data + sizeof(DNS_WINSR_DATA);
|
|
|
|
Dns_NameCopy(
|
|
precord->Data.WINSR.pNameResultDomain,
|
|
NULL, // no buffer length
|
|
nameBuffer,
|
|
nameLength,
|
|
DnsCharSetUtf8,
|
|
OutCharSet
|
|
);
|
|
|
|
return( precord );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// RR read to packet jump table
|
|
//
|
|
|
|
RR_READ_FUNCTION RR_ReadTable[] =
|
|
{
|
|
NULL, // ZERO
|
|
A_RecordRead, // A
|
|
Ptr_RecordRead, // NS
|
|
Ptr_RecordRead, // MD
|
|
Ptr_RecordRead, // MF
|
|
Ptr_RecordRead, // CNAME
|
|
Soa_RecordRead, // SOA
|
|
Ptr_RecordRead, // MB
|
|
Ptr_RecordRead, // MG
|
|
Ptr_RecordRead, // MR
|
|
Flat_RecordRead, // NULL
|
|
Wks_RecordRead, // WKS
|
|
Ptr_RecordRead, // PTR
|
|
Txt_RecordRead, // HINFO
|
|
Minfo_RecordRead, // MINFO
|
|
Mx_RecordRead, // MX
|
|
Txt_RecordRead, // TXT
|
|
Minfo_RecordRead, // RP
|
|
Mx_RecordRead, // AFSDB
|
|
Txt_RecordRead, // X25
|
|
Txt_RecordRead, // ISDN
|
|
Mx_RecordRead, // RT
|
|
NULL, // NSAP
|
|
NULL, // NSAPPTR
|
|
NULL, // SIG
|
|
NULL, // KEY
|
|
NULL, // PX
|
|
NULL, // GPOS
|
|
Flat_RecordRead, // AAAA
|
|
NULL, // LOC
|
|
NULL, // NXT
|
|
NULL, // EID
|
|
NULL, // NIMLOC
|
|
Srv_RecordRead, // SRV
|
|
Atma_RecordRead, // ATMA
|
|
NULL, // NAPTR
|
|
NULL, // KX
|
|
NULL, // CERT
|
|
NULL, // A6
|
|
NULL, // DNAME
|
|
NULL, // SINK
|
|
NULL, // OPT
|
|
NULL, // 42
|
|
NULL, // 43
|
|
NULL, // 44
|
|
NULL, // 45
|
|
NULL, // 46
|
|
NULL, // 47
|
|
NULL, // 48
|
|
|
|
//
|
|
// NOTE: last type indexed by type ID MUST be set
|
|
// as MAX_SELF_INDEXED_TYPE #define in record.h
|
|
// (see note above in record info table)
|
|
|
|
//
|
|
// Pseudo record types
|
|
//
|
|
|
|
Tkey_RecordRead, // TKEY
|
|
Tsig_RecordRead, // TSIG
|
|
|
|
//
|
|
// MS only types
|
|
//
|
|
|
|
Wins_RecordRead, // WINS
|
|
Winsr_RecordRead, // WINSR
|
|
|
|
};
|
|
|
|
//
|
|
// End rrread.c
|
|
//
|