/*++ 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 RR build routine prototypes // PDNS_RECORD ARecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD ARecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD PtrRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD PtrRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD MxRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD MxRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD SoaRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD SoaRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD TxtRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD TxtRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD MinfoRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD MinfoRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD SrvRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD SrvRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD AtmaRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD AtmaRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD AaaaRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD AaaaRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD WinsRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD WinsRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD WinsrRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD WinsrRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD WksRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD WksRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD SigRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD SigRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD KeyRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD KeyRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); PDNS_RECORD NxtRecordBuild( IN DWORD Argc, IN PCHAR * Argv ); PDNS_RECORD NxtRecordBuildW( IN DWORD Argc, IN PWCHAR * Argv ); // // RR build routines jump table // RR_BUILD_FUNCTION RRBuildTable[] = { NULL, // ZERO ARecordBuild, // A PtrRecordBuild, // NS PtrRecordBuild, // MD PtrRecordBuild, // MF PtrRecordBuild, // CNAME SoaRecordBuild, // SOA PtrRecordBuild, // MB PtrRecordBuild, // MG PtrRecordBuild, // MR NULL, // NULL WksRecordBuild, // WKS PtrRecordBuild, // PTR TxtRecordBuild, // HINFO MinfoRecordBuild, // MINFO MxRecordBuild, // MX TxtRecordBuild, // TXT MinfoRecordBuild, // RP MxRecordBuild, // AFSDB TxtRecordBuild, // X25 TxtRecordBuild, // ISDN MxRecordBuild, // RT NULL, // NSAP NULL, // NSAPPTR SigRecordBuild, // SIG KeyRecordBuild, // KEY NULL, // PX NULL, // GPOS AaaaRecordBuild, // AAAA NULL, // LOC NxtRecordBuild, // NXT NULL, // EID NULL, // NIMLOC SrvRecordBuild, // SRV AtmaRecordBuild, // 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 // WinsRecordBuild, // WINS WinsrRecordBuild, // WINSR }; RR_BUILD_FUNCTION_W RRBuildTableW[] = { NULL, // ZERO ARecordBuildW, // A PtrRecordBuildW, // NS PtrRecordBuildW, // MD PtrRecordBuildW, // MF PtrRecordBuildW, // CNAME SoaRecordBuildW, // SOA PtrRecordBuildW, // MB PtrRecordBuildW, // MG PtrRecordBuildW, // MR NULL, // NULL WksRecordBuildW, // WKS PtrRecordBuildW, // PTR TxtRecordBuildW, // HINFO MinfoRecordBuildW, // MINFO MxRecordBuildW, // MX TxtRecordBuildW, // TXT MinfoRecordBuildW, // RP MxRecordBuildW, // AFSDB TxtRecordBuildW, // X25 TxtRecordBuildW, // ISDN MxRecordBuildW, // RT NULL, // NSAP NULL, // NSAPPTR SigRecordBuildW, // SIG KeyRecordBuildW, // KEY NULL, // PX NULL, // GPOS AaaaRecordBuildW, // AAAA NULL, // LOC NxtRecordBuildW, // NXT NULL, // EID NULL, // NIMLOC SrvRecordBuildW, // SRV AtmaRecordBuildW, // 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 // WinsRecordBuildW, // WINS WinsrRecordBuildW, // WINSR }; PDNS_RECORD ARecordBuild( 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 ARecordBuildW( 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 PtrRecordBuild( 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 PtrRecordBuildW( 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 MxRecordBuild( 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 MxRecordBuildW( 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 SoaRecordBuild( 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 SoaRecordBuildW( 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 MinfoRecordBuild( 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 MinfoRecordBuildW( 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 TxtRecordBuild( 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 TxtRecordBuildW( 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 AaaaRecordBuild( 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 AaaaRecordBuildW( 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 SrvRecordBuild( 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 SrvRecordBuildW( 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 AtmaRecordBuild( 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 AtmaRecordBuildW( 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 WinsRecordBuild( 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; PIP_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 WinsRecordBuildW( 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; PIP_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 WinsrRecordBuild( 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 WinsrRecordBuildW( 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 WksRecordBuild( 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 WksRecordBuildW( 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 KeyRecordBuild( 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; } // KeyRecordBuild PDNS_RECORD KeyRecordBuildW( 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; } // KeyRecordBuildW PDNS_RECORD SigRecordBuild( 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; } // SigRecordBuild PDNS_RECORD SigRecordBuildW( 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; } // SigRecordBuildW PDNS_RECORD NxtRecordBuild( 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; } // NxtRecordBuild PDNS_RECORD NxtRecordBuildW( 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; } // NxtRecordBuildW // // 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 //