|
|
/*++
Copyright (c) 1997-2001 Microsoft Corporation
Module Name:
rrbuild.c
Abstract:
Domain Name System (DNS) Library
Build resource record routines.
Author:
Jim Gilroy (jamesg) January, 1997
Revision History:
Jing Chen (t-jingc) June, 1998
--*/
#include "local.h"
//
// Type specific record build routines
//
PDNS_RECORD A_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build A record from string data.
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_A_DATA) ); if ( !precord ) { return( NULL ); }
if ( ! Dns_Ip4StringToAddress_A( &precord->Data.A.IpAddress, Argv[0] ) ) { Dns_RecordFree( precord ); SetLastError( ERROR_INVALID_DATA ); return NULL; }
return( precord ); }
PDNS_RECORD A_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build A record from string data.
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_A_DATA) ); if ( !precord ) { return( NULL ); }
if ( ! Dns_Ip4StringToAddress_W( &precord->Data.A.IpAddress, Argv[0] ) ) { Dns_RecordFree( precord ); SetLastError( ERROR_INVALID_DATA ); return NULL; }
return( precord ); }
PDNS_RECORD Ptr_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build PTR compatible record from string data. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_PTR_DATA) ); if ( !precord ) { return( NULL ); } precord->Data.PTR.pNameHost = Argv[0];
return( precord ); }
PDNS_RECORD Ptr_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build PTR compatible record from string data. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_PTR_DATA) ); if ( !precord ) { return( NULL ); } precord->Data.PTR.pNameHost = (PDNS_NAME) Argv[0];
return( precord ); }
PDNS_RECORD Mx_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build MX compatible record from string data. Includes: MX, RT, AFSDB
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; DWORD temp;
if ( Argc != 2 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_MX_DATA) ); if ( !precord ) { return( NULL ); }
//
// MX preference value
// RT preference
// AFSDB subtype
//
temp = strtoul( Argv[0], NULL, 10 ); if ( temp > MAXWORD ) { temp = MAXWORD; } precord->Data.MX.wPreference = (USHORT) temp;
//
// MX exchange
// RT exchange
// AFSDB hostname
//
precord->Data.MX.pNameExchange = Argv[1];
return( precord ); }
PDNS_RECORD Mx_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build MX compatible record from string data. Includes: MX, RT, AFSDB
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; DWORD temp;
if ( Argc != 2 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_MX_DATA) ); if ( !precord ) { return( NULL ); }
//
// MX preference value
// RT preference
// AFSDB subtype
//
temp = wcstoul( Argv[0], NULL, 10 ); if ( temp > MAXWORD ) { temp = MAXWORD; } precord->Data.MX.wPreference = (USHORT) temp;
//
// MX exchange
// RT exchange
// AFSDB hostname
//
precord->Data.MX.pNameExchange = (PDNS_NAME) Argv[1];
return( precord ); }
PDNS_RECORD Soa_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build SOA record from string data.
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PDWORD pdword;
if ( Argc != 7 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_SOA_DATA) ); if ( !precord ) { return( NULL ); }
//
// read primary server and responsible party
//
precord->Data.SOA.pNamePrimaryServer = Argv[0]; Argc--; Argv++; precord->Data.SOA.pNameAdministrator = Argv[0]; Argc--; Argv++;
//
// read integer data
//
pdword = &precord->Data.SOA.dwSerialNo;
while( Argc-- ) { *pdword = strtoul( Argv[0], NULL, 10 ); pdword++; Argv++; }
return( precord ); }
PDNS_RECORD Soa_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build SOA record from string data.
Arguments:
Argc -- count of data arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PDWORD pdword;
if ( Argc != 7 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_SOA_DATA) ); if ( !precord ) { return( NULL ); }
//
// read primary server and responsible party
//
precord->Data.SOA.pNamePrimaryServer = (PDNS_NAME) Argv[0]; Argc--; Argv++; precord->Data.SOA.pNameAdministrator = (PDNS_NAME) Argv[0]; Argc--; Argv++;
//
// read integer data
//
pdword = &precord->Data.SOA.dwSerialNo;
while( Argc-- ) { *pdword = wcstoul( Argv[0], NULL, 10 ); pdword++; Argv++; }
return( precord ); }
PDNS_RECORD Minfo_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build MINFO and RP records from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 2 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_MINFO_DATA) ); if ( !precord ) { return( NULL ); }
//
// MINFO responsible mailbox
// RP responsible person mailbox
precord->Data.MINFO.pNameMailbox = Argv[0]; Argc--; Argv++;
//
// MINFO errors to mailbox
// RP text RR location
precord->Data.MINFO.pNameErrorsMailbox = Argv[0]; Argc--; Argv++;
return( precord ); }
PDNS_RECORD Minfo_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build MINFO and RP records from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 2 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_MINFO_DATA) ); if ( !precord ) { return( NULL ); }
//
// MINFO responsible mailbox
// RP responsible person mailbox
precord->Data.MINFO.pNameMailbox = (PDNS_NAME) Argv[0]; Argc--; Argv++;
//
// MINFO errors to mailbox
// RP text RR location
precord->Data.MINFO.pNameErrorsMailbox = (PDNS_NAME) Argv[0]; Argc--; Argv++;
return( precord ); }
PDNS_RECORD Txt_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build TXT compatible records from string data. Includes: TXT, X25, HINFO, ISDN
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; WORD dataLength; PCHAR * pstringPtr;
if ( Argc < 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
//
// allocate space for a pointer for each data string
//
precord = Dns_AllocateRecord( (WORD)DNS_TEXT_RECORD_LENGTH(Argc) ); if ( !precord ) { return( NULL ); } precord->Data.TXT.dwStringCount = Argc;
//
// read as many strings as we have
//
// DCR_FIX: no checking for string limits
// - string count limits on HINFO, X25, ISDN
// - 256 length on strings
// - 64K on overall size
//
pstringPtr = (PCHAR *) precord->Data.TXT.pStringArray; while ( Argc-- ) { *pstringPtr = Argv[0]; pstringPtr++; Argv++; } return( precord ); }
PDNS_RECORD Txt_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build TXT compatible records from string data. Includes: TXT, X25, HINFO, ISDN
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; WORD dataLength; LPWSTR * pstringPtr;
if ( Argc < 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
//
// allocate space for a pointer for each data string
//
precord = Dns_AllocateRecord( (WORD)DNS_TEXT_RECORD_LENGTH(Argc) ); if ( !precord ) { return( NULL ); } precord->Data.TXT.dwStringCount = Argc;
//
// read as many strings as we have
//
// DCR_FIX: no checking for string limits
// - string count limits on HINFO, X25, ISDN
// - 256 length on strings
// - 64K on overall size
//
pstringPtr = (LPWSTR *) precord->Data.TXT.pStringArray; while ( Argc-- ) { *pstringPtr = Argv[0]; pstringPtr++; Argv++; } return( precord ); }
PDNS_RECORD Aaaa_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build AAAA record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_AAAA_DATA) ); if ( !precord ) { return( NULL ); }
//
// read IP6 address
//
if ( ! Dns_Ip6StringToAddress_A( (PIP6_ADDRESS) &precord->Data.AAAA.Ip6Address, Argv[0] ) ) { Dns_RecordFree( precord ); SetLastError( ERROR_INVALID_DATA ); return NULL; } return( precord ); }
PDNS_RECORD Aaaa_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build AAAA record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord;
if ( Argc != 1 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_AAAA_DATA) ); if ( !precord ) { return( NULL ); }
//
// convert IPv6 string to address
//
if ( ! Dns_Ip6StringToAddress_W( &precord->Data.AAAA.Ip6Address, Argv[0] ) ) { SetLastError( ERROR_INVALID_DATA ); Dns_RecordFree( precord ); return NULL; }
return( precord ); }
PDNS_RECORD Srv_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build SRV record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PWORD pword;
if ( Argc != 4 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_SRV_DATA) ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
pword = &precord->Data.SRV.wPriority;
while( Argc-- > 1 ) { DWORD temp;
temp = strtoul( Argv[0], NULL, 10 ); if ( temp > MAXWORD ) { temp = MAXWORD; } *pword++ = (WORD) temp; Argv++; }
//
// target host
//
precord->Data.SRV.pNameTarget = Argv[0];
return( precord ); }
PDNS_RECORD Srv_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build SRV record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PWORD pword;
if ( Argc != 4 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_SRV_DATA) ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
pword = &precord->Data.SRV.wPriority;
while( Argc-- > 1 ) { DWORD temp;
temp = wcstoul( Argv[0], NULL, 10 ); if ( temp > MAXWORD ) { temp = MAXWORD; } *pword++ = (WORD) temp; Argv++; }
//
// target host
//
precord->Data.SRV.pNameTarget = (PDNS_NAME) Argv[0];
return( precord ); }
PDNS_RECORD Atma_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build ATMA record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PBYTE pbyte;
if ( Argc != 2 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_ATMA_DATA) + DNS_ATMA_MAX_ADDR_LENGTH ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
pbyte = &precord->Data.ATMA.AddressType;
*pbyte = (BYTE) strtoul( Argv[0], NULL, 10 ); pbyte++; Argv++;
if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 ) { UINT length = strlen( Argv[0] ); UINT iter;
if ( length > DNS_ATMA_MAX_ADDR_LENGTH ) { length = DNS_ATMA_MAX_ADDR_LENGTH; } for ( iter = 0; iter < length; iter++ ) { precord->Data.ATMA.Address[iter] = Argv[0][iter]; }
precord->wDataLength = (WORD) length; } else { UINT length = strlen( Argv[0] ); UINT iter;
length /= 2;
if ( length != DNS_ATMA_MAX_ADDR_LENGTH ) { Dns_RecordListFree( precord ); return NULL; }
for ( iter = 0; iter < length; iter++ ) { char temp[3];
temp[0] = Argv[0][(2*iter)]; temp[1] = Argv[0][(2*iter) + 1]; temp[2] = 0;
precord->Data.ATMA.Address[iter] = (char) strtoul( temp, NULL, 16 ); }
precord->wDataLength = (WORD) length; }
return( precord );
}
PDNS_RECORD Atma_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build ATMA record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PBYTE pbyte; CHAR addrBuffer[256]; DWORD bufLength;
if ( Argc != 2 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); } precord = Dns_AllocateRecord( sizeof(DNS_ATMA_DATA) + DNS_ATMA_MAX_ADDR_LENGTH ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
pbyte = &precord->Data.ATMA.AddressType;
*pbyte = (BYTE) wcstoul( Argv[0], NULL, 10 ); pbyte++; Argv++;
//
// copy ATMA address string to wire
//
bufLength = DNS_ATMA_MAX_ADDR_LENGTH+1;
if ( ! Dns_StringCopy( addrBuffer, & bufLength, (PCHAR) Argv[0], 0, // length unknown
DnsCharSetUnicode, DnsCharSetWire ) ) { Dns_RecordListFree( precord ); SetLastError( ERROR_INVALID_DATA ); return NULL; }
//
// read address into record buffer
//
// DCR_CLEANUP: this is duplicate code with above function,
// functionalize and fix; also remove this loop
// and do a memcopy
//
if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 ) { UINT length = strlen( addrBuffer ); UINT iter;
if ( length > DNS_ATMA_MAX_ADDR_LENGTH ) { length = DNS_ATMA_MAX_ADDR_LENGTH; }
for ( iter = 0; iter < length; iter++ ) { precord->Data.ATMA.Address[iter] = addrBuffer[iter]; }
precord->wDataLength = (WORD) length; } else { UINT length = strlen( addrBuffer ); UINT iter;
length /= 2;
if ( length != DNS_ATMA_MAX_ADDR_LENGTH ) { Dns_RecordListFree( precord ); return NULL; }
for ( iter = 0; iter < length; iter++ ) { char temp[3];
temp[0] = addrBuffer[(2*iter)]; temp[1] = addrBuffer[(2*iter) + 1]; temp[2] = 0;
precord->Data.ATMA.Address[iter] = (char) strtoul( temp, NULL, 16 ); }
precord->wDataLength = (WORD) length; }
return( precord ); }
PDNS_RECORD Wins_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build WINS record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; DWORD ipCount = Argc - 3; PDWORD pdword; PIP4_ADDRESS pip;
if ( Argc < 4 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( (WORD) DNS_WINS_RECORD_LENGTH((WORD) ipCount) ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
// DCR_ENHANCE: could check for non-conversion in strtoul
//
pdword = &precord->Data.WINS.dwMappingFlag;
while ( Argc > ipCount ) { *pdword = (DWORD) strtoul( Argv[0], NULL, 10 ); pdword++; Argv++; Argc--; }
*pdword = ipCount;
//
// convert IP addresses
//
pip = precord->Data.WINS.WinsServers;
while ( Argc-- ) { if ( ! Dns_Ip4StringToAddress_A( pip, Argv[0] ) ) { Dns_RecordFree( precord ); SetLastError( ERROR_INVALID_DATA ); return NULL; } pip++; Argv++; }
return( precord ); }
PDNS_RECORD Wins_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build WINS record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; DWORD ipCount = Argc - 3; PDWORD pdword; PIP4_ADDRESS pip; char szAddr[256];
if ( Argc < 4 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( (WORD) DNS_WINS_RECORD_LENGTH((WORD) ipCount) ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
// DCR_ENHANCE: could check for non-conversion in strtoul
//
pdword = &precord->Data.WINS.dwMappingFlag;
while ( Argc-- > 1 ) { *pdword = (DWORD) wcstoul( Argv[0], NULL, 10 ); pdword++; Argv++; }
*pdword = ipCount;
//
// convert IP addresses
//
pip = precord->Data.WINS.WinsServers;
while ( Argc-- ) { if ( ! Dns_Ip4StringToAddress_W( pip, Argv[0] ) ) { Dns_RecordFree( precord ); SetLastError( ERROR_INVALID_DATA ); return NULL; } pip++; Argv++; }
return( precord ); }
PDNS_RECORD Winsr_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build WINSR record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PDWORD pdword;
if ( Argc != 4 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_WINSR_DATA) ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
// DCR_ENHANCE: could check for non-conversion in strtoul
//
pdword = &precord->Data.WINSR.dwMappingFlag;
while( Argc-- > 1 ) { *pdword = (WORD) strtoul( Argv[0], NULL, 10 ); pdword++; Argv++; }
//
// result domain
//
precord->Data.WINSR.pNameResultDomain = Argv[0];
return( precord ); }
PDNS_RECORD Winsr_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build WINSR record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; PDWORD pdword;
if ( Argc != 4 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
precord = Dns_AllocateRecord( sizeof(DNS_WINSR_DATA) ); if ( !precord ) { return( NULL ); }
//
// read integer data
//
// DCR_ENHANCE: could check for non-conversion in strtoul
//
pdword = &precord->Data.WINSR.dwMappingFlag;
while( Argc-- > 1 ) { *pdword = (WORD) wcstoul( Argv[0], NULL, 10 ); pdword++; Argv++; }
//
// result domain
//
precord->Data.WINSR.pNameResultDomain = (PDNS_NAME) Argv[0];
return( precord ); }
PDNS_RECORD Wks_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build WKS record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; DWORD byteCount = 0; DWORD i; PCHAR pch; WSADATA wsaData; DNS_STATUS status; struct protoent * pProtoent;
if ( Argc < 3 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
i = 2; while ( i < Argc) { byteCount += strlen( Argv[i] ) + 1; i++; } byteCount++; //bBitMasks[0] : string length
//
// allocate space for WKS
//
precord = Dns_AllocateRecord( (WORD)DNS_WKS_RECORD_LENGTH(byteCount) ); if ( !precord ) { return( NULL ); }
//
// get protocol number:
//
// start winsock:
//
// DCR: this is busted, winsock should be started by now
status = WSAStartup( DNS_WINSOCK_VERSION, &wsaData ); if ( status == SOCKET_ERROR ) { Dns_RecordFree( precord ); status = WSAGetLastError(); SetLastError( status ); return( NULL ); }
pProtoent = getprotobyname( Argv[0] );
if ( ! pProtoent || pProtoent->p_proto >= MAXUCHAR ) { Dns_RecordFree( precord ); status = WSAGetLastError(); SetLastError( status ); return( NULL ); }
precord->Data.WKS.chProtocol = (UCHAR) pProtoent->p_proto;
//
// get ipAddresss:
//
precord->Data.WKS.IpAddress = inet_addr( Argv[1] );
//
// get the services, put all in one string
//
pch = precord->Data.WKS.BitMask;
(UCHAR) *pch = (UCHAR) byteCount-1; //string length
pch++;
i = 2; strcpy( pch, Argv[i] ); while ( ++i < Argc ) { strcat( pch, " " ); strcat( pch, Argv[i] ); }
return( precord ); }
PDNS_RECORD Wks_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build WKS record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD precord; DWORD byteCount = 0; DWORD i; PWCHAR pch; WSADATA wsaData; DNS_STATUS status; struct protoent * pProtoent; char szAddr[256]; WCHAR tcpStr[4], udpStr[4], space[2];
if ( Argc < 3 ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
i = 2; while ( i < Argc) { byteCount += wcslen( Argv[i] ) + 1; i++; } byteCount++; //bBitMasks[0] : string length
//
// allocate space for WKS
//
precord = Dns_AllocateRecord( (WORD)DNS_WKS_RECORD_LENGTH(byteCount) ); if ( !precord ) { return( NULL ); }
//
// get protocol number
//
status = WSAStartup( DNS_WINSOCK_VERSION, &wsaData ); if ( status == SOCKET_ERROR ) { Dns_RecordFree( precord ); status = WSAGetLastError(); SetLastError( status ); return( NULL ); }
#if 0
//
// DCR_FIX: WKS build
//
if ( ! Dns_CopyStringEx( szAddr, 0, (PCHAR) Argv[0], 0, TRUE, FALSE ) ) { Dns_RecordListFree( precord ); return NULL; }
pProtoent = getprotobyname( szAddr );
if ( ! pProtoent || pProtoent->p_proto >= MAXUCHAR ) { Dns_RecordFree( precord ); status = WSAGetLastError(); SetLastError( status ); return( NULL ); }
precord->Data.WKS.chProtocol = (UCHAR) pProtoent->p_proto;
//
// IP Address
//
if ( ! Dns_CopyStringEx( szAddr, 0, (PCHAR) Argv[0], 0, TRUE, FALSE ) ) { Dns_RecordListFree( precord ); return NULL; }
precord->Data.WKS.IpAddress = inet_addr( szAddr );
//
// get the services, put all in one string
//
pch = (PWCHAR) precord->Data.WKS.bBitMask;
(UCHAR) *pch = (UCHAR) byteCount-1; pch++;
i = 2; if ( ! Dns_NameCopy( (PBYTE) space, 0, " ", 0, DnsCharSetUnicode, DnsCharSetWire ) ) { Dns_RecordListFree( precord ); return NULL; }
wcscpy( pch, Argv[i] ); while ( ++i < Argc ) { wcscat( pch, space ); wcscat( pch, Argv[i] ); } #endif
return( precord ); }
PDNS_RECORD Key_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build KEY record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD prec; int keyStringLength; DWORD keyLength = 0;
if ( Argc != 4 ) { SetLastError( ERROR_INVALID_DATA ); return NULL; }
keyStringLength = strlen( Argv[ 3 ] );
prec = Dns_AllocateRecord( (WORD) sizeof( DNS_KEY_DATA ) + keyStringLength ); if ( !prec ) { return NULL; }
prec->Data.KEY.wFlags = (WORD) strtoul( *( Argv++ ), NULL, 0 ); prec->Data.KEY.chProtocol = (BYTE) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.KEY.chAlgorithm = (BYTE) strtoul( *( Argv++ ), NULL, 10 ); Argc -= 3;
Dns_SecurityBase64StringToKey( prec->Data.KEY.Key, &keyLength, *Argv, keyStringLength ); Argc--; Argv++;
prec->wDataLength = (WORD) ( SIZEOF_KEY_FIXED_DATA + keyLength );
return prec; } // Key_RecordBuild
PDNS_RECORD Key_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build KEY record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD prec; int keyStringLength; DWORD keyLength = 0;
if ( Argc != 4 ) { SetLastError( ERROR_INVALID_DATA ); return NULL; }
keyStringLength = wcslen( Argv[ 3 ] );
prec = Dns_AllocateRecord( (WORD) sizeof( DNS_KEY_DATA ) + keyStringLength / 2 ); if ( !prec ) { return NULL; }
prec->Data.KEY.wFlags = (WORD) wcstoul( *( Argv++ ), NULL, 0 ); prec->Data.KEY.chProtocol = (BYTE) wcstoul( *( Argv++ ), NULL, 10 ); prec->Data.KEY.chAlgorithm = (BYTE) wcstoul( *( Argv++ ), NULL, 10 ); Argc -= 3;
#if 0
// JJW: MUST COPY BUFFER???
Dns_SecurityBase64StringToKey( prec->Data.KEY.Key, &keyLength, *Argv, keyStringLength ); #endif
Argc--; Argv++;
prec->wDataLength = (WORD) ( SIZEOF_KEY_FIXED_DATA + keyLength );
return prec; } // Key_RecordBuildW
PDNS_RECORD Sig_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build SIG record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD prec; int sigStringLength; DWORD sigLength = 0;
if ( Argc != 9 ) { SetLastError( ERROR_INVALID_DATA ); return NULL; }
sigStringLength = strlen( Argv[8] );
prec = Dns_AllocateRecord( (WORD) ( sizeof(DNS_SIG_DATA) + sigStringLength ) ); if ( !prec ) { return NULL; }
prec->Data.SIG.wTypeCovered = Dns_RecordTypeForName( *( Argv++ ), 0 ); prec->Data.SIG.chAlgorithm = (BYTE) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.Sig.chLabelCount = (BYTE) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.SIG.dwOriginalTtl = ( DWORD ) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.SIG.dwExpiration = Dns_ParseSigTime( *( Argv++ ), 0 ); prec->Data.SIG.dwTimeSigned = Dns_ParseSigTime( *( Argv++ ), 0 ); prec->Data.SIG.wKeyTag = (WORD) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.SIG.pNameSigner = *( Argv++ );
Argc -= 8;
//
// Validate signature times.
//
if ( prec->Data.SIG.dwExpiration == 0 || prec->Data.SIG.dwTimeSigned == 0 || prec->Data.SIG.dwTimeSigned >= prec->Data.SIG.dwExpiration ) { Dns_RecordFree( prec ); SetLastError( ERROR_INVALID_DATA ); return NULL; }
//
// Parse signature.
//
if ( Dns_SecurityBase64StringToKey( prec->Data.SIG.Signature, &sigLength, *Argv, sigStringLength ) != ERROR_SUCCESS ) { Dns_RecordFree( prec ); SetLastError( ERROR_INVALID_DATA ); return NULL; }
Argc--; Argv++;
prec->wDataLength = (WORD) ( sizeof( DNS_SIG_DATA ) - 4 + sigLength );
return prec; } // Sig_RecordBuild
PDNS_RECORD Sig_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build SIG record from string data.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD prec; int sigStringLength; DWORD sigLength = 0; PCHAR pch;
if ( Argc != 8 ) { SetLastError( ERROR_INVALID_DATA ); return NULL; }
sigStringLength = wcslen( Argv[ 7 ] );
prec = Dns_AllocateRecord( (WORD) ( sizeof( DNS_SIG_DATA ) + sigStringLength ) ); if ( !prec ) { return NULL; }
#if 0
// JJW: how to convert all args here???
prec->Data.SIG.wTypeCovered = Dns_RecordTypeForName( *( Argv++ ), 0 ); prec->Data.SIG.chAlgorithm = (BYTE) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.Sig.chLabelCount = (BYTE) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.SIG.dwOriginalTtl = ( DWORD ) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.SIG.dwExpiration = Dns_ParseSigTime( *( Argv++ ), 0 ); prec->Data.SIG.dwTimeSigned = Dns_ParseSigTime( *( Argv++ ), 0 ); prec->Data.SIG.wKeyTag = (WORD) strtoul( *( Argv++ ), NULL, 10 ); prec->Data.SIG.pNameSigner = *( Argv++ );
Argc -= 8;
Dns_SecurityBase64StringToKey( prec->Data.SIG.Signature, &sigLength, *Argv, sigStringLength ); #endif
Argc--; Argv++;
prec->wDataLength = (WORD) ( sizeof( DNS_SIG_DATA ) - 4 + sigLength );
return prec; } // Sig_RecordBuildW
PDNS_RECORD Nxt_RecordBuild( IN DWORD Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build NXT record from string data.
First arg is next name, followed by list of record types at that name.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD prec; int typeIdx = 0;
if ( Argc < 2 ) { SetLastError( ERROR_INVALID_DATA ); return NULL; } prec = Dns_AllocateRecord( (WORD) ( sizeof( LPTSTR ) + sizeof(WORD) * Argc ) ); if ( !prec ) { return NULL; }
prec->Data.NXT.pNameNext = *( Argv++ ); --Argc;
prec->Data.NXT.wNumTypes = 0; while ( Argc-- ) { ++prec->Data.NXT.wNumTypes; prec->Data.NXT.wTypes[ typeIdx++ ] = Dns_RecordTypeForName( *( Argv++ ), 0 ); }
return prec; } // Nxt_RecordBuild
PDNS_RECORD Nxt_RecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build NXT record from string data.
First arg is next name, followed by list of record types at that name.
Arguments:
Argc -- count of data Arguments
Argv -- argv array of data string pointers
Return Value:
Ptr to new record if successful. NULL on failure.
--*/ { PDNS_RECORD prec; int typeIdx = 0;
if ( Argc < 2 ) { SetLastError( ERROR_INVALID_DATA ); return NULL; } prec = Dns_AllocateRecord( (WORD) ( sizeof( LPTSTR ) + sizeof(WORD) * ( Argc - 1 ) ) ); if ( !prec ) { return NULL; }
prec->Data.NXT.pNameNext = ( PDNS_NAME ) ( *( Argv++ ) ); --Argc;
#if 0
// JJW: convert type string???
while ( Argc-- ) { prec->Data.NXT.wTypes[ typeIdx++ ] = Dns_RecordTypeForName( *( Argv++ ), 0 ); } #endif
return prec; } // Nxt_RecordBuildW
//
// RR build routines jump table
//
typedef PDNS_RECORD (* RR_BUILD_FUNCTION)( DWORD, PCHAR * );
//extern RR_BUILD_FUNCTION RRBuildTable[];
typedef PDNS_RECORD (* RR_BUILD_FUNCTION_W)( DWORD, PWCHAR * );
//extern RR_BUILD_FUNCTION_W RRBuildTableW[];
RR_BUILD_FUNCTION RRBuildTable[] = { NULL, // ZERO
A_RecordBuild, // A
Ptr_RecordBuild, // NS
Ptr_RecordBuild, // MD
Ptr_RecordBuild, // MF
Ptr_RecordBuild, // CNAME
Soa_RecordBuild, // SOA
Ptr_RecordBuild, // MB
Ptr_RecordBuild, // MG
Ptr_RecordBuild, // MR
NULL, // NULL
Wks_RecordBuild, // WKS
Ptr_RecordBuild, // PTR
Txt_RecordBuild, // HINFO
Minfo_RecordBuild, // MINFO
Mx_RecordBuild, // MX
Txt_RecordBuild, // TXT
Minfo_RecordBuild, // RP
Mx_RecordBuild, // AFSDB
Txt_RecordBuild, // X25
Txt_RecordBuild, // ISDN
Mx_RecordBuild, // RT
NULL, // NSAP
NULL, // NSAPPTR
Sig_RecordBuild, // SIG
Key_RecordBuild, // KEY
NULL, // PX
NULL, // GPOS
Aaaa_RecordBuild, // AAAA
NULL, // LOC
Nxt_RecordBuild, // NXT
NULL, // EID
NULL, // NIMLOC
Srv_RecordBuild, // SRV
Atma_RecordBuild, // 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
//
NULL, // TKEY
NULL, // TSIG
//
// MS only types
//
Wins_RecordBuild, // WINS
Winsr_RecordBuild, // WINSR
};
RR_BUILD_FUNCTION_W RRBuildTableW[] = { NULL, // ZERO
A_RecordBuildW, // A
Ptr_RecordBuildW, // NS
Ptr_RecordBuildW, // MD
Ptr_RecordBuildW, // MF
Ptr_RecordBuildW, // CNAME
Soa_RecordBuildW, // SOA
Ptr_RecordBuildW, // MB
Ptr_RecordBuildW, // MG
Ptr_RecordBuildW, // MR
NULL, // NULL
Wks_RecordBuildW, // WKS
Ptr_RecordBuildW, // PTR
Txt_RecordBuildW, // HINFO
Minfo_RecordBuildW, // MINFO
Mx_RecordBuildW, // MX
Txt_RecordBuildW, // TXT
Minfo_RecordBuildW, // RP
Mx_RecordBuildW, // AFSDB
Txt_RecordBuildW, // X25
Txt_RecordBuildW, // ISDN
Mx_RecordBuildW, // RT
NULL, // NSAP
NULL, // NSAPPTR
Sig_RecordBuildW, // SIG
Key_RecordBuildW, // KEY
NULL, // PX
NULL, // GPOS
Aaaa_RecordBuildW, // AAAA
NULL, // LOC
Nxt_RecordBuildW, // NXT
NULL, // EID
NULL, // NIMLOC
Srv_RecordBuildW, // SRV
Atma_RecordBuildW, // 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
//
NULL, // TKEY
NULL, // TSIG
//
// MS only types
//
Wins_RecordBuildW, // WINS
Winsr_RecordBuildW, // WINSR
};
//
// Public build routine
//
PDNS_RECORD Dns_RecordBuild_A( IN OUT PDNS_RRSET pRRSet, IN LPSTR pszOwner, IN WORD wType, IN BOOL fAdd, IN UCHAR Section, IN INT Argc, IN PCHAR * Argv ) /*++
Routine Description:
Build record from data strings.
Arguments:
pRRSet -- ptr to RR set structure being built
pszOwner -- DNS name of RR owner
wType -- record type
fAdd -- add\delete, exist\no-exist flag
Section -- RR section for record
Argc -- count of data strings
Argv -- argv array of ptrs to data strings
Return Value:
Ptr to record built. NULL on error.
--*/ { PDNS_RECORD precord; WORD index;
IF_DNSDBG( INIT ) { DNS_PRINT(( "Dns_RecordBuild()\n" "\trrset = %p\n" "\towner = %s\n" "\ttype = %d\n" "\tfAdd = %d\n" "\tsection = %d\n" "\targc = %d\n", pRRSet, pszOwner, wType, fAdd, Section, Argc )); }
//
// every record MUST have owner name
//
if ( !pszOwner ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
//
// if no data, no dispatch required
//
if ( Argc == 0 ) { precord = Dns_AllocateRecord( 0 ); if ( ! precord ) { return( NULL ); } }
// have data, dispatch to type specific build routine
else { index = INDEX_FOR_TYPE( wType ); DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
if ( !index || !RRBuildTable[ index ] ) { // can NOT build unknown types
SetLastError( DNS_ERROR_INVALID_TYPE ); DNS_PRINT(( "ERROR: can not build record of type %d\n", wType )); return( NULL ); }
precord = RRBuildTable[ index ]( Argc, Argv ); if ( ! precord ) { DNS_PRINT(( "ERROR: Record build routine failure for record type %d.\n" "\tstatus = %d\n\n", wType, GetLastError() )); if ( !GetLastError() ) { SetLastError( ERROR_INVALID_DATA ); } return( NULL ); } }
//
// fill out record structure
//
precord->pName = pszOwner; precord->wType = wType; precord->Flags.S.Section = Section; precord->Flags.S.Delete = !fAdd; precord->Flags.S.CharSet = DnsCharSetAnsi;
IF_DNSDBG( INIT ) { DnsDbg_Record( "New record built\n", precord ); }
//
// link into existing RR set (if any)
//
if ( pRRSet ) { DNS_RRSET_ADD( *pRRSet, precord ); } return( precord ); }
PDNS_RECORD Dns_RecordBuild_W( IN OUT PDNS_RRSET pRRSet, IN LPWSTR pszOwner, IN WORD wType, IN BOOL fAdd, IN UCHAR Section, IN INT Argc, IN PWCHAR * Argv ) /*++
Routine Description:
Build record from data strings.
Arguments:
pRRSet -- ptr to RR set structure being built
pszOwner -- DNS name of RR owner
wType -- record type
fAdd -- add\delete, exist\no-exist flag
Section -- RR section for record
Argc -- count of data strings
Argv -- argv array of ptrs to data strings
Return Value:
Ptr to record built. NULL on error.
--*/ { PDNS_RECORD precord; WORD index;
DNSDBG( INIT, ( "Dns_RecordBuild()\n" "\trrset = %p\n" "\towner = %S\n" "\ttype = %d\n" "\tfAdd = %d\n" "\tsection = %d\n" "\targc = %d\n", pRRSet, pszOwner, wType, fAdd, Section, Argc ));
//
// every record MUST have owner name
//
if ( !pszOwner ) { SetLastError( ERROR_INVALID_DATA ); return( NULL ); }
//
// if no data, no dispatch required
//
if ( Argc == 0 ) { precord = Dns_AllocateRecord( 0 ); if ( ! precord ) { return( NULL ); } }
// have data, dispatch to type specific build routine
else { index = INDEX_FOR_TYPE( wType ); DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
if ( !index || !RRBuildTableW[ index ] ) { // can NOT build unknown types
SetLastError( DNS_ERROR_INVALID_TYPE ); DNS_PRINT(( "ERROR: can not build record of type %d\n", wType )); return( NULL ); }
precord = RRBuildTableW[ index ]( Argc, Argv ); if ( ! precord ) { DNS_PRINT(( "ERROR: Record build routine failure for record type %d.\n" "\tstatus = %d\n\n", wType, GetLastError() ));
if ( !GetLastError() ) { SetLastError( ERROR_INVALID_DATA ); } return( NULL ); } }
//
// fill out record structure
//
precord->pName = (PDNS_NAME) pszOwner; precord->wType = wType; precord->Flags.S.Section = Section; precord->Flags.S.Delete = !fAdd; precord->Flags.S.CharSet = DnsCharSetUnicode;
IF_DNSDBG( INIT ) { DnsDbg_Record( "New record built\n", precord ); }
//
// link into existing RR set (if any)
//
if ( pRRSet ) { DNS_RRSET_ADD( *pRRSet, precord ); } return( precord ); }
//
// End rrbuild.c
//
|