Source code of Windows XP (NT5)
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.

2801 lines
50 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. rrbuild.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Build resource record routines.
  8. Author:
  9. Jim Gilroy (jamesg) January, 1997
  10. Revision History:
  11. Jing Chen (t-jingc) June, 1998
  12. --*/
  13. #include "local.h"
  14. //
  15. // Type specific RR build routine prototypes
  16. //
  17. PDNS_RECORD
  18. ARecordBuild(
  19. IN DWORD Argc,
  20. IN PCHAR * Argv
  21. );
  22. PDNS_RECORD
  23. ARecordBuildW(
  24. IN DWORD Argc,
  25. IN PWCHAR * Argv
  26. );
  27. PDNS_RECORD
  28. PtrRecordBuild(
  29. IN DWORD Argc,
  30. IN PCHAR * Argv
  31. );
  32. PDNS_RECORD
  33. PtrRecordBuildW(
  34. IN DWORD Argc,
  35. IN PWCHAR * Argv
  36. );
  37. PDNS_RECORD
  38. MxRecordBuild(
  39. IN DWORD Argc,
  40. IN PCHAR * Argv
  41. );
  42. PDNS_RECORD
  43. MxRecordBuildW(
  44. IN DWORD Argc,
  45. IN PWCHAR * Argv
  46. );
  47. PDNS_RECORD
  48. SoaRecordBuild(
  49. IN DWORD Argc,
  50. IN PCHAR * Argv
  51. );
  52. PDNS_RECORD
  53. SoaRecordBuildW(
  54. IN DWORD Argc,
  55. IN PWCHAR * Argv
  56. );
  57. PDNS_RECORD
  58. TxtRecordBuild(
  59. IN DWORD Argc,
  60. IN PCHAR * Argv
  61. );
  62. PDNS_RECORD
  63. TxtRecordBuildW(
  64. IN DWORD Argc,
  65. IN PWCHAR * Argv
  66. );
  67. PDNS_RECORD
  68. MinfoRecordBuild(
  69. IN DWORD Argc,
  70. IN PCHAR * Argv
  71. );
  72. PDNS_RECORD
  73. MinfoRecordBuildW(
  74. IN DWORD Argc,
  75. IN PWCHAR * Argv
  76. );
  77. PDNS_RECORD
  78. SrvRecordBuild(
  79. IN DWORD Argc,
  80. IN PCHAR * Argv
  81. );
  82. PDNS_RECORD
  83. SrvRecordBuildW(
  84. IN DWORD Argc,
  85. IN PWCHAR * Argv
  86. );
  87. PDNS_RECORD
  88. AtmaRecordBuild(
  89. IN DWORD Argc,
  90. IN PCHAR * Argv
  91. );
  92. PDNS_RECORD
  93. AtmaRecordBuildW(
  94. IN DWORD Argc,
  95. IN PWCHAR * Argv
  96. );
  97. PDNS_RECORD
  98. AaaaRecordBuild(
  99. IN DWORD Argc,
  100. IN PCHAR * Argv
  101. );
  102. PDNS_RECORD
  103. AaaaRecordBuildW(
  104. IN DWORD Argc,
  105. IN PWCHAR * Argv
  106. );
  107. PDNS_RECORD
  108. WinsRecordBuild(
  109. IN DWORD Argc,
  110. IN PCHAR * Argv
  111. );
  112. PDNS_RECORD
  113. WinsRecordBuildW(
  114. IN DWORD Argc,
  115. IN PWCHAR * Argv
  116. );
  117. PDNS_RECORD
  118. WinsrRecordBuild(
  119. IN DWORD Argc,
  120. IN PCHAR * Argv
  121. );
  122. PDNS_RECORD
  123. WinsrRecordBuildW(
  124. IN DWORD Argc,
  125. IN PWCHAR * Argv
  126. );
  127. PDNS_RECORD
  128. WksRecordBuild(
  129. IN DWORD Argc,
  130. IN PCHAR * Argv
  131. );
  132. PDNS_RECORD
  133. WksRecordBuildW(
  134. IN DWORD Argc,
  135. IN PWCHAR * Argv
  136. );
  137. PDNS_RECORD
  138. SigRecordBuild(
  139. IN DWORD Argc,
  140. IN PCHAR * Argv
  141. );
  142. PDNS_RECORD
  143. SigRecordBuildW(
  144. IN DWORD Argc,
  145. IN PWCHAR * Argv
  146. );
  147. PDNS_RECORD
  148. KeyRecordBuild(
  149. IN DWORD Argc,
  150. IN PCHAR * Argv
  151. );
  152. PDNS_RECORD
  153. KeyRecordBuildW(
  154. IN DWORD Argc,
  155. IN PWCHAR * Argv
  156. );
  157. PDNS_RECORD
  158. NxtRecordBuild(
  159. IN DWORD Argc,
  160. IN PCHAR * Argv
  161. );
  162. PDNS_RECORD
  163. NxtRecordBuildW(
  164. IN DWORD Argc,
  165. IN PWCHAR * Argv
  166. );
  167. //
  168. // RR build routines jump table
  169. //
  170. RR_BUILD_FUNCTION RRBuildTable[] =
  171. {
  172. NULL, // ZERO
  173. ARecordBuild, // A
  174. PtrRecordBuild, // NS
  175. PtrRecordBuild, // MD
  176. PtrRecordBuild, // MF
  177. PtrRecordBuild, // CNAME
  178. SoaRecordBuild, // SOA
  179. PtrRecordBuild, // MB
  180. PtrRecordBuild, // MG
  181. PtrRecordBuild, // MR
  182. NULL, // NULL
  183. WksRecordBuild, // WKS
  184. PtrRecordBuild, // PTR
  185. TxtRecordBuild, // HINFO
  186. MinfoRecordBuild, // MINFO
  187. MxRecordBuild, // MX
  188. TxtRecordBuild, // TXT
  189. MinfoRecordBuild, // RP
  190. MxRecordBuild, // AFSDB
  191. TxtRecordBuild, // X25
  192. TxtRecordBuild, // ISDN
  193. MxRecordBuild, // RT
  194. NULL, // NSAP
  195. NULL, // NSAPPTR
  196. SigRecordBuild, // SIG
  197. KeyRecordBuild, // KEY
  198. NULL, // PX
  199. NULL, // GPOS
  200. AaaaRecordBuild, // AAAA
  201. NULL, // LOC
  202. NxtRecordBuild, // NXT
  203. NULL, // EID
  204. NULL, // NIMLOC
  205. SrvRecordBuild, // SRV
  206. AtmaRecordBuild, // ATMA
  207. NULL, // NAPTR
  208. NULL, // KX
  209. NULL, // CERT
  210. NULL, // A6
  211. NULL, // DNAME
  212. NULL, // SINK
  213. NULL, // OPT
  214. NULL, // 42
  215. NULL, // 43
  216. NULL, // 44
  217. NULL, // 45
  218. NULL, // 46
  219. NULL, // 47
  220. NULL, // 48
  221. //
  222. // NOTE: last type indexed by type ID MUST be set
  223. // as MAX_SELF_INDEXED_TYPE #define in record.h
  224. // (see note above in record info table)
  225. //
  226. // Pseudo record types
  227. //
  228. NULL, // TKEY
  229. NULL, // TSIG
  230. //
  231. // MS only types
  232. //
  233. WinsRecordBuild, // WINS
  234. WinsrRecordBuild, // WINSR
  235. };
  236. RR_BUILD_FUNCTION_W RRBuildTableW[] =
  237. {
  238. NULL, // ZERO
  239. ARecordBuildW, // A
  240. PtrRecordBuildW, // NS
  241. PtrRecordBuildW, // MD
  242. PtrRecordBuildW, // MF
  243. PtrRecordBuildW, // CNAME
  244. SoaRecordBuildW, // SOA
  245. PtrRecordBuildW, // MB
  246. PtrRecordBuildW, // MG
  247. PtrRecordBuildW, // MR
  248. NULL, // NULL
  249. WksRecordBuildW, // WKS
  250. PtrRecordBuildW, // PTR
  251. TxtRecordBuildW, // HINFO
  252. MinfoRecordBuildW, // MINFO
  253. MxRecordBuildW, // MX
  254. TxtRecordBuildW, // TXT
  255. MinfoRecordBuildW, // RP
  256. MxRecordBuildW, // AFSDB
  257. TxtRecordBuildW, // X25
  258. TxtRecordBuildW, // ISDN
  259. MxRecordBuildW, // RT
  260. NULL, // NSAP
  261. NULL, // NSAPPTR
  262. SigRecordBuildW, // SIG
  263. KeyRecordBuildW, // KEY
  264. NULL, // PX
  265. NULL, // GPOS
  266. AaaaRecordBuildW, // AAAA
  267. NULL, // LOC
  268. NxtRecordBuildW, // NXT
  269. NULL, // EID
  270. NULL, // NIMLOC
  271. SrvRecordBuildW, // SRV
  272. AtmaRecordBuildW, // ATMA
  273. NULL, // NAPTR
  274. NULL, // KX
  275. NULL, // CERT
  276. NULL, // A6
  277. NULL, // DNAME
  278. NULL, // SINK
  279. NULL, // OPT
  280. NULL, // 42
  281. NULL, // 43
  282. NULL, // 44
  283. NULL, // 45
  284. NULL, // 46
  285. NULL, // 47
  286. NULL, // 48
  287. //
  288. // NOTE: last type indexed by type ID MUST be set
  289. // as MAX_SELF_INDEXED_TYPE #define in record.h
  290. // (see note above in record info table)
  291. //
  292. // Pseudo record types
  293. //
  294. NULL, // TKEY
  295. NULL, // TSIG
  296. //
  297. // MS only types
  298. //
  299. WinsRecordBuildW, // WINS
  300. WinsrRecordBuildW, // WINSR
  301. };
  302. PDNS_RECORD
  303. ARecordBuild(
  304. IN DWORD Argc,
  305. IN PCHAR * Argv
  306. )
  307. /*++
  308. Routine Description:
  309. Build A record from string data.
  310. Arguments:
  311. Argc -- count of data arguments
  312. Argv -- argv array of data string pointers
  313. Return Value:
  314. Ptr to new record if successful.
  315. NULL on failure.
  316. --*/
  317. {
  318. PDNS_RECORD precord;
  319. if ( Argc != 1 )
  320. {
  321. SetLastError( ERROR_INVALID_DATA );
  322. return( NULL );
  323. }
  324. precord = Dns_AllocateRecord( sizeof(DNS_A_DATA) );
  325. if ( !precord )
  326. {
  327. return( NULL );
  328. }
  329. if ( ! Dns_Ip4StringToAddress_A(
  330. &precord->Data.A.IpAddress,
  331. Argv[0] ) )
  332. {
  333. Dns_RecordFree( precord );
  334. SetLastError( ERROR_INVALID_DATA );
  335. return NULL;
  336. }
  337. return( precord );
  338. }
  339. PDNS_RECORD
  340. ARecordBuildW(
  341. IN DWORD Argc,
  342. IN PWCHAR * Argv
  343. )
  344. /*++
  345. Routine Description:
  346. Build A record from string data.
  347. Arguments:
  348. Argc -- count of data arguments
  349. Argv -- argv array of data string pointers
  350. Return Value:
  351. Ptr to new record if successful.
  352. NULL on failure.
  353. --*/
  354. {
  355. PDNS_RECORD precord;
  356. if ( Argc != 1 )
  357. {
  358. SetLastError( ERROR_INVALID_DATA );
  359. return( NULL );
  360. }
  361. precord = Dns_AllocateRecord( sizeof(DNS_A_DATA) );
  362. if ( !precord )
  363. {
  364. return( NULL );
  365. }
  366. if ( ! Dns_Ip4StringToAddress_W(
  367. &precord->Data.A.IpAddress,
  368. Argv[0] ) )
  369. {
  370. Dns_RecordFree( precord );
  371. SetLastError( ERROR_INVALID_DATA );
  372. return NULL;
  373. }
  374. return( precord );
  375. }
  376. PDNS_RECORD
  377. PtrRecordBuild(
  378. IN DWORD Argc,
  379. IN PCHAR * Argv
  380. )
  381. /*++
  382. Routine Description:
  383. Build PTR compatible record from string data.
  384. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
  385. Arguments:
  386. Argc -- count of data arguments
  387. Argv -- argv array of data string pointers
  388. Return Value:
  389. Ptr to new record if successful.
  390. NULL on failure.
  391. --*/
  392. {
  393. PDNS_RECORD precord;
  394. if ( Argc != 1 )
  395. {
  396. SetLastError( ERROR_INVALID_DATA );
  397. return( NULL );
  398. }
  399. precord = Dns_AllocateRecord( sizeof(DNS_PTR_DATA) );
  400. if ( !precord )
  401. {
  402. return( NULL );
  403. }
  404. precord->Data.PTR.pNameHost = Argv[0];
  405. return( precord );
  406. }
  407. PDNS_RECORD
  408. PtrRecordBuildW(
  409. IN DWORD Argc,
  410. IN PWCHAR * Argv
  411. )
  412. /*++
  413. Routine Description:
  414. Build PTR compatible record from string data.
  415. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
  416. Arguments:
  417. Argc -- count of data arguments
  418. Argv -- argv array of data string pointers
  419. Return Value:
  420. Ptr to new record if successful.
  421. NULL on failure.
  422. --*/
  423. {
  424. PDNS_RECORD precord;
  425. if ( Argc != 1 )
  426. {
  427. SetLastError( ERROR_INVALID_DATA );
  428. return( NULL );
  429. }
  430. precord = Dns_AllocateRecord( sizeof(DNS_PTR_DATA) );
  431. if ( !precord )
  432. {
  433. return( NULL );
  434. }
  435. precord->Data.PTR.pNameHost = (PDNS_NAME) Argv[0];
  436. return( precord );
  437. }
  438. PDNS_RECORD
  439. MxRecordBuild(
  440. IN DWORD Argc,
  441. IN PCHAR * Argv
  442. )
  443. /*++
  444. Routine Description:
  445. Build MX compatible record from string data.
  446. Includes: MX, RT, AFSDB
  447. Arguments:
  448. Argc -- count of data arguments
  449. Argv -- argv array of data string pointers
  450. Return Value:
  451. Ptr to new record if successful.
  452. NULL on failure.
  453. --*/
  454. {
  455. PDNS_RECORD precord;
  456. DWORD temp;
  457. if ( Argc != 2 )
  458. {
  459. SetLastError( ERROR_INVALID_DATA );
  460. return( NULL );
  461. }
  462. precord = Dns_AllocateRecord( sizeof(DNS_MX_DATA) );
  463. if ( !precord )
  464. {
  465. return( NULL );
  466. }
  467. //
  468. // MX preference value
  469. // RT preference
  470. // AFSDB subtype
  471. //
  472. temp = strtoul( Argv[0], NULL, 10 );
  473. if ( temp > MAXWORD )
  474. {
  475. temp = MAXWORD;
  476. }
  477. precord->Data.MX.wPreference = (USHORT) temp;
  478. //
  479. // MX exchange
  480. // RT exchange
  481. // AFSDB hostname
  482. //
  483. precord->Data.MX.pNameExchange = Argv[1];
  484. return( precord );
  485. }
  486. PDNS_RECORD
  487. MxRecordBuildW(
  488. IN DWORD Argc,
  489. IN PWCHAR * Argv
  490. )
  491. /*++
  492. Routine Description:
  493. Build MX compatible record from string data.
  494. Includes: MX, RT, AFSDB
  495. Arguments:
  496. Argc -- count of data arguments
  497. Argv -- argv array of data string pointers
  498. Return Value:
  499. Ptr to new record if successful.
  500. NULL on failure.
  501. --*/
  502. {
  503. PDNS_RECORD precord;
  504. DWORD temp;
  505. if ( Argc != 2 )
  506. {
  507. SetLastError( ERROR_INVALID_DATA );
  508. return( NULL );
  509. }
  510. precord = Dns_AllocateRecord( sizeof(DNS_MX_DATA) );
  511. if ( !precord )
  512. {
  513. return( NULL );
  514. }
  515. //
  516. // MX preference value
  517. // RT preference
  518. // AFSDB subtype
  519. //
  520. temp = wcstoul( Argv[0], NULL, 10 );
  521. if ( temp > MAXWORD )
  522. {
  523. temp = MAXWORD;
  524. }
  525. precord->Data.MX.wPreference = (USHORT) temp;
  526. //
  527. // MX exchange
  528. // RT exchange
  529. // AFSDB hostname
  530. //
  531. precord->Data.MX.pNameExchange = (PDNS_NAME) Argv[1];
  532. return( precord );
  533. }
  534. PDNS_RECORD
  535. SoaRecordBuild(
  536. IN DWORD Argc,
  537. IN PCHAR * Argv
  538. )
  539. /*++
  540. Routine Description:
  541. Build SOA record from string data.
  542. Arguments:
  543. Argc -- count of data arguments
  544. Argv -- argv array of data string pointers
  545. Return Value:
  546. Ptr to new record if successful.
  547. NULL on failure.
  548. --*/
  549. {
  550. PDNS_RECORD precord;
  551. PDWORD pdword;
  552. if ( Argc != 7 )
  553. {
  554. SetLastError( ERROR_INVALID_DATA );
  555. return( NULL );
  556. }
  557. precord = Dns_AllocateRecord( sizeof(DNS_SOA_DATA) );
  558. if ( !precord )
  559. {
  560. return( NULL );
  561. }
  562. //
  563. // read primary server and responsible party
  564. //
  565. precord->Data.SOA.pNamePrimaryServer = Argv[0];
  566. Argc--;
  567. Argv++;
  568. precord->Data.SOA.pNameAdministrator = Argv[0];
  569. Argc--;
  570. Argv++;
  571. //
  572. // read integer data
  573. //
  574. pdword = &precord->Data.SOA.dwSerialNo;
  575. while( Argc-- )
  576. {
  577. *pdword = strtoul( Argv[0], NULL, 10 );
  578. pdword++;
  579. Argv++;
  580. }
  581. return( precord );
  582. }
  583. PDNS_RECORD
  584. SoaRecordBuildW(
  585. IN DWORD Argc,
  586. IN PWCHAR * Argv
  587. )
  588. /*++
  589. Routine Description:
  590. Build SOA record from string data.
  591. Arguments:
  592. Argc -- count of data arguments
  593. Argv -- argv array of data string pointers
  594. Return Value:
  595. Ptr to new record if successful.
  596. NULL on failure.
  597. --*/
  598. {
  599. PDNS_RECORD precord;
  600. PDWORD pdword;
  601. if ( Argc != 7 )
  602. {
  603. SetLastError( ERROR_INVALID_DATA );
  604. return( NULL );
  605. }
  606. precord = Dns_AllocateRecord( sizeof(DNS_SOA_DATA) );
  607. if ( !precord )
  608. {
  609. return( NULL );
  610. }
  611. //
  612. // read primary server and responsible party
  613. //
  614. precord->Data.SOA.pNamePrimaryServer = (PDNS_NAME) Argv[0];
  615. Argc--;
  616. Argv++;
  617. precord->Data.SOA.pNameAdministrator = (PDNS_NAME) Argv[0];
  618. Argc--;
  619. Argv++;
  620. //
  621. // read integer data
  622. //
  623. pdword = &precord->Data.SOA.dwSerialNo;
  624. while( Argc-- )
  625. {
  626. *pdword = wcstoul( Argv[0], NULL, 10 );
  627. pdword++;
  628. Argv++;
  629. }
  630. return( precord );
  631. }
  632. PDNS_RECORD
  633. MinfoRecordBuild(
  634. IN DWORD Argc,
  635. IN PCHAR * Argv
  636. )
  637. /*++
  638. Routine Description:
  639. Build MINFO and RP records from string data.
  640. Arguments:
  641. Argc -- count of data Arguments
  642. Argv -- argv array of data string pointers
  643. Return Value:
  644. Ptr to new record if successful.
  645. NULL on failure.
  646. --*/
  647. {
  648. PDNS_RECORD precord;
  649. if ( Argc != 2 )
  650. {
  651. SetLastError( ERROR_INVALID_DATA );
  652. return( NULL );
  653. }
  654. precord = Dns_AllocateRecord( sizeof(DNS_MINFO_DATA) );
  655. if ( !precord )
  656. {
  657. return( NULL );
  658. }
  659. //
  660. // MINFO responsible mailbox
  661. // RP responsible person mailbox
  662. precord->Data.MINFO.pNameMailbox = Argv[0];
  663. Argc--;
  664. Argv++;
  665. //
  666. // MINFO errors to mailbox
  667. // RP text RR location
  668. precord->Data.MINFO.pNameErrorsMailbox = Argv[0];
  669. Argc--;
  670. Argv++;
  671. return( precord );
  672. }
  673. PDNS_RECORD
  674. MinfoRecordBuildW(
  675. IN DWORD Argc,
  676. IN PWCHAR * Argv
  677. )
  678. /*++
  679. Routine Description:
  680. Build MINFO and RP records from string data.
  681. Arguments:
  682. Argc -- count of data Arguments
  683. Argv -- argv array of data string pointers
  684. Return Value:
  685. Ptr to new record if successful.
  686. NULL on failure.
  687. --*/
  688. {
  689. PDNS_RECORD precord;
  690. if ( Argc != 2 )
  691. {
  692. SetLastError( ERROR_INVALID_DATA );
  693. return( NULL );
  694. }
  695. precord = Dns_AllocateRecord( sizeof(DNS_MINFO_DATA) );
  696. if ( !precord )
  697. {
  698. return( NULL );
  699. }
  700. //
  701. // MINFO responsible mailbox
  702. // RP responsible person mailbox
  703. precord->Data.MINFO.pNameMailbox = (PDNS_NAME) Argv[0];
  704. Argc--;
  705. Argv++;
  706. //
  707. // MINFO errors to mailbox
  708. // RP text RR location
  709. precord->Data.MINFO.pNameErrorsMailbox = (PDNS_NAME) Argv[0];
  710. Argc--;
  711. Argv++;
  712. return( precord );
  713. }
  714. PDNS_RECORD
  715. TxtRecordBuild(
  716. IN DWORD Argc,
  717. IN PCHAR * Argv
  718. )
  719. /*++
  720. Routine Description:
  721. Build TXT compatible records from string data.
  722. Includes: TXT, X25, HINFO, ISDN
  723. Arguments:
  724. Argc -- count of data Arguments
  725. Argv -- argv array of data string pointers
  726. Return Value:
  727. Ptr to new record if successful.
  728. NULL on failure.
  729. --*/
  730. {
  731. PDNS_RECORD precord;
  732. WORD dataLength;
  733. PCHAR * pstringPtr;
  734. if ( Argc < 1 )
  735. {
  736. SetLastError( ERROR_INVALID_DATA );
  737. return( NULL );
  738. }
  739. //
  740. // allocate space for a pointer for each data string
  741. //
  742. precord = Dns_AllocateRecord( (WORD)DNS_TEXT_RECORD_LENGTH(Argc) );
  743. if ( !precord )
  744. {
  745. return( NULL );
  746. }
  747. precord->Data.TXT.dwStringCount = Argc;
  748. //
  749. // read as many strings as we have
  750. //
  751. // DCR_FIX: no checking for string limits
  752. // - string count limits on HINFO, X25, ISDN
  753. // - 256 length on strings
  754. // - 64K on overall size
  755. //
  756. pstringPtr = (PCHAR *) precord->Data.TXT.pStringArray;
  757. while ( Argc-- )
  758. {
  759. *pstringPtr = Argv[0];
  760. pstringPtr++;
  761. Argv++;
  762. }
  763. return( precord );
  764. }
  765. PDNS_RECORD
  766. TxtRecordBuildW(
  767. IN DWORD Argc,
  768. IN PWCHAR * Argv
  769. )
  770. /*++
  771. Routine Description:
  772. Build TXT compatible records from string data.
  773. Includes: TXT, X25, HINFO, ISDN
  774. Arguments:
  775. Argc -- count of data Arguments
  776. Argv -- argv array of data string pointers
  777. Return Value:
  778. Ptr to new record if successful.
  779. NULL on failure.
  780. --*/
  781. {
  782. PDNS_RECORD precord;
  783. WORD dataLength;
  784. LPWSTR * pstringPtr;
  785. if ( Argc < 1 )
  786. {
  787. SetLastError( ERROR_INVALID_DATA );
  788. return( NULL );
  789. }
  790. //
  791. // allocate space for a pointer for each data string
  792. //
  793. precord = Dns_AllocateRecord( (WORD)DNS_TEXT_RECORD_LENGTH(Argc) );
  794. if ( !precord )
  795. {
  796. return( NULL );
  797. }
  798. precord->Data.TXT.dwStringCount = Argc;
  799. //
  800. // read as many strings as we have
  801. //
  802. // DCR_FIX: no checking for string limits
  803. // - string count limits on HINFO, X25, ISDN
  804. // - 256 length on strings
  805. // - 64K on overall size
  806. //
  807. pstringPtr = (LPWSTR *) precord->Data.TXT.pStringArray;
  808. while ( Argc-- )
  809. {
  810. *pstringPtr = Argv[0];
  811. pstringPtr++;
  812. Argv++;
  813. }
  814. return( precord );
  815. }
  816. PDNS_RECORD
  817. AaaaRecordBuild(
  818. IN DWORD Argc,
  819. IN PCHAR * Argv
  820. )
  821. /*++
  822. Routine Description:
  823. Build AAAA record from string data.
  824. Arguments:
  825. Argc -- count of data Arguments
  826. Argv -- argv array of data string pointers
  827. Return Value:
  828. Ptr to new record if successful.
  829. NULL on failure.
  830. --*/
  831. {
  832. PDNS_RECORD precord;
  833. if ( Argc != 1 )
  834. {
  835. SetLastError( ERROR_INVALID_DATA );
  836. return( NULL );
  837. }
  838. precord = Dns_AllocateRecord( sizeof(DNS_AAAA_DATA) );
  839. if ( !precord )
  840. {
  841. return( NULL );
  842. }
  843. //
  844. // read IP6 address
  845. //
  846. if ( ! Dns_Ip6StringToAddress_A(
  847. (PIP6_ADDRESS) &precord->Data.AAAA.Ip6Address,
  848. Argv[0] ) )
  849. {
  850. Dns_RecordFree( precord );
  851. SetLastError( ERROR_INVALID_DATA );
  852. return NULL;
  853. }
  854. return( precord );
  855. }
  856. PDNS_RECORD
  857. AaaaRecordBuildW(
  858. IN DWORD Argc,
  859. IN PWCHAR * Argv
  860. )
  861. /*++
  862. Routine Description:
  863. Build AAAA record from string data.
  864. Arguments:
  865. Argc -- count of data Arguments
  866. Argv -- argv array of data string pointers
  867. Return Value:
  868. Ptr to new record if successful.
  869. NULL on failure.
  870. --*/
  871. {
  872. PDNS_RECORD precord;
  873. if ( Argc != 1 )
  874. {
  875. SetLastError( ERROR_INVALID_DATA );
  876. return( NULL );
  877. }
  878. precord = Dns_AllocateRecord( sizeof(DNS_AAAA_DATA) );
  879. if ( !precord )
  880. {
  881. return( NULL );
  882. }
  883. //
  884. // convert IPv6 string to address
  885. //
  886. if ( ! Dns_Ip6StringToAddress_W(
  887. &precord->Data.AAAA.Ip6Address,
  888. Argv[0]
  889. ) )
  890. {
  891. SetLastError( ERROR_INVALID_DATA );
  892. Dns_RecordFree( precord );
  893. return NULL;
  894. }
  895. return( precord );
  896. }
  897. PDNS_RECORD
  898. SrvRecordBuild(
  899. IN DWORD Argc,
  900. IN PCHAR * Argv
  901. )
  902. /*++
  903. Routine Description:
  904. Build SRV record from string data.
  905. Arguments:
  906. Argc -- count of data Arguments
  907. Argv -- argv array of data string pointers
  908. Return Value:
  909. Ptr to new record if successful.
  910. NULL on failure.
  911. --*/
  912. {
  913. PDNS_RECORD precord;
  914. PWORD pword;
  915. if ( Argc != 4 )
  916. {
  917. SetLastError( ERROR_INVALID_DATA );
  918. return( NULL );
  919. }
  920. precord = Dns_AllocateRecord( sizeof(DNS_SRV_DATA) );
  921. if ( !precord )
  922. {
  923. return( NULL );
  924. }
  925. //
  926. // read integer data
  927. //
  928. pword = &precord->Data.SRV.wPriority;
  929. while( Argc-- > 1 )
  930. {
  931. DWORD temp;
  932. temp = strtoul( Argv[0], NULL, 10 );
  933. if ( temp > MAXWORD )
  934. {
  935. temp = MAXWORD;
  936. }
  937. *pword++ = (WORD) temp;
  938. Argv++;
  939. }
  940. //
  941. // target host
  942. //
  943. precord->Data.SRV.pNameTarget = Argv[0];
  944. return( precord );
  945. }
  946. PDNS_RECORD
  947. SrvRecordBuildW(
  948. IN DWORD Argc,
  949. IN PWCHAR * Argv
  950. )
  951. /*++
  952. Routine Description:
  953. Build SRV record from string data.
  954. Arguments:
  955. Argc -- count of data Arguments
  956. Argv -- argv array of data string pointers
  957. Return Value:
  958. Ptr to new record if successful.
  959. NULL on failure.
  960. --*/
  961. {
  962. PDNS_RECORD precord;
  963. PWORD pword;
  964. if ( Argc != 4 )
  965. {
  966. SetLastError( ERROR_INVALID_DATA );
  967. return( NULL );
  968. }
  969. precord = Dns_AllocateRecord( sizeof(DNS_SRV_DATA) );
  970. if ( !precord )
  971. {
  972. return( NULL );
  973. }
  974. //
  975. // read integer data
  976. //
  977. pword = &precord->Data.SRV.wPriority;
  978. while( Argc-- > 1 )
  979. {
  980. DWORD temp;
  981. temp = wcstoul( Argv[0], NULL, 10 );
  982. if ( temp > MAXWORD )
  983. {
  984. temp = MAXWORD;
  985. }
  986. *pword++ = (WORD) temp;
  987. Argv++;
  988. }
  989. //
  990. // target host
  991. //
  992. precord->Data.SRV.pNameTarget = (PDNS_NAME) Argv[0];
  993. return( precord );
  994. }
  995. PDNS_RECORD
  996. AtmaRecordBuild(
  997. IN DWORD Argc,
  998. IN PCHAR * Argv
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Build ATMA record from string data.
  1003. Arguments:
  1004. Argc -- count of data Arguments
  1005. Argv -- argv array of data string pointers
  1006. Return Value:
  1007. Ptr to new record if successful.
  1008. NULL on failure.
  1009. --*/
  1010. {
  1011. PDNS_RECORD precord;
  1012. PBYTE pbyte;
  1013. if ( Argc != 2 )
  1014. {
  1015. SetLastError( ERROR_INVALID_DATA );
  1016. return( NULL );
  1017. }
  1018. precord = Dns_AllocateRecord( sizeof(DNS_ATMA_DATA) +
  1019. DNS_ATMA_MAX_ADDR_LENGTH );
  1020. if ( !precord )
  1021. {
  1022. return( NULL );
  1023. }
  1024. //
  1025. // read integer data
  1026. //
  1027. pbyte = &precord->Data.ATMA.AddressType;
  1028. *pbyte = (BYTE) strtoul( Argv[0], NULL, 10 );
  1029. pbyte++;
  1030. Argv++;
  1031. if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 )
  1032. {
  1033. UINT length = strlen( Argv[0] );
  1034. UINT iter;
  1035. if ( length > DNS_ATMA_MAX_ADDR_LENGTH )
  1036. {
  1037. length = DNS_ATMA_MAX_ADDR_LENGTH;
  1038. }
  1039. for ( iter = 0; iter < length; iter++ )
  1040. {
  1041. precord->Data.ATMA.Address[iter] = Argv[0][iter];
  1042. }
  1043. precord->wDataLength = (WORD) length;
  1044. }
  1045. else
  1046. {
  1047. UINT length = strlen( Argv[0] );
  1048. UINT iter;
  1049. length /= 2;
  1050. if ( length != DNS_ATMA_MAX_ADDR_LENGTH )
  1051. {
  1052. Dns_RecordListFree( precord );
  1053. return NULL;
  1054. }
  1055. for ( iter = 0; iter < length; iter++ )
  1056. {
  1057. char temp[3];
  1058. temp[0] = Argv[0][(2*iter)];
  1059. temp[1] = Argv[0][(2*iter) + 1];
  1060. temp[2] = 0;
  1061. precord->Data.ATMA.Address[iter] = (char) strtoul( temp, NULL, 16 );
  1062. }
  1063. precord->wDataLength = (WORD) length;
  1064. }
  1065. return( precord );
  1066. }
  1067. PDNS_RECORD
  1068. AtmaRecordBuildW(
  1069. IN DWORD Argc,
  1070. IN PWCHAR * Argv
  1071. )
  1072. /*++
  1073. Routine Description:
  1074. Build ATMA record from string data.
  1075. Arguments:
  1076. Argc -- count of data Arguments
  1077. Argv -- argv array of data string pointers
  1078. Return Value:
  1079. Ptr to new record if successful.
  1080. NULL on failure.
  1081. --*/
  1082. {
  1083. PDNS_RECORD precord;
  1084. PBYTE pbyte;
  1085. CHAR addrBuffer[256];
  1086. DWORD bufLength;
  1087. if ( Argc != 2 )
  1088. {
  1089. SetLastError( ERROR_INVALID_DATA );
  1090. return( NULL );
  1091. }
  1092. precord = Dns_AllocateRecord( sizeof(DNS_ATMA_DATA) +
  1093. DNS_ATMA_MAX_ADDR_LENGTH );
  1094. if ( !precord )
  1095. {
  1096. return( NULL );
  1097. }
  1098. //
  1099. // read integer data
  1100. //
  1101. pbyte = &precord->Data.ATMA.AddressType;
  1102. *pbyte = (BYTE) wcstoul( Argv[0], NULL, 10 );
  1103. pbyte++;
  1104. Argv++;
  1105. //
  1106. // copy ATMA address string to wire
  1107. //
  1108. bufLength = DNS_ATMA_MAX_ADDR_LENGTH+1;
  1109. if ( ! Dns_StringCopy(
  1110. addrBuffer,
  1111. & bufLength,
  1112. (PCHAR) Argv[0],
  1113. 0, // length unknown
  1114. DnsCharSetUnicode,
  1115. DnsCharSetWire
  1116. ) )
  1117. {
  1118. Dns_RecordListFree( precord );
  1119. SetLastError( ERROR_INVALID_DATA );
  1120. return NULL;
  1121. }
  1122. //
  1123. // read address into record buffer
  1124. //
  1125. // DCR_CLEANUP: this is duplicate code with above function,
  1126. // functionalize and fix; also remove this loop
  1127. // and do a memcopy
  1128. //
  1129. if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 )
  1130. {
  1131. UINT length = strlen( addrBuffer );
  1132. UINT iter;
  1133. if ( length > DNS_ATMA_MAX_ADDR_LENGTH )
  1134. {
  1135. length = DNS_ATMA_MAX_ADDR_LENGTH;
  1136. }
  1137. for ( iter = 0; iter < length; iter++ )
  1138. {
  1139. precord->Data.ATMA.Address[iter] = addrBuffer[iter];
  1140. }
  1141. precord->wDataLength = (WORD) length;
  1142. }
  1143. else
  1144. {
  1145. UINT length = strlen( addrBuffer );
  1146. UINT iter;
  1147. length /= 2;
  1148. if ( length != DNS_ATMA_MAX_ADDR_LENGTH )
  1149. {
  1150. Dns_RecordListFree( precord );
  1151. return NULL;
  1152. }
  1153. for ( iter = 0; iter < length; iter++ )
  1154. {
  1155. char temp[3];
  1156. temp[0] = addrBuffer[(2*iter)];
  1157. temp[1] = addrBuffer[(2*iter) + 1];
  1158. temp[2] = 0;
  1159. precord->Data.ATMA.Address[iter] = (char) strtoul( temp, NULL, 16 );
  1160. }
  1161. precord->wDataLength = (WORD) length;
  1162. }
  1163. return( precord );
  1164. }
  1165. PDNS_RECORD
  1166. WinsRecordBuild(
  1167. IN DWORD Argc,
  1168. IN PCHAR * Argv
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. Build WINS record from string data.
  1173. Arguments:
  1174. Argc -- count of data Arguments
  1175. Argv -- argv array of data string pointers
  1176. Return Value:
  1177. Ptr to new record if successful.
  1178. NULL on failure.
  1179. --*/
  1180. {
  1181. PDNS_RECORD precord;
  1182. DWORD ipCount = Argc - 3;
  1183. PDWORD pdword;
  1184. PIP_ADDRESS pip;
  1185. if ( Argc < 4 )
  1186. {
  1187. SetLastError( ERROR_INVALID_DATA );
  1188. return( NULL );
  1189. }
  1190. precord = Dns_AllocateRecord( (WORD) DNS_WINS_RECORD_LENGTH((WORD) ipCount) );
  1191. if ( !precord )
  1192. {
  1193. return( NULL );
  1194. }
  1195. //
  1196. // read integer data
  1197. //
  1198. // DCR_ENHANCE: could check for non-conversion in strtoul
  1199. //
  1200. pdword = &precord->Data.WINS.dwMappingFlag;
  1201. while ( Argc > ipCount )
  1202. {
  1203. *pdword = (DWORD) strtoul( Argv[0], NULL, 10 );
  1204. pdword++;
  1205. Argv++;
  1206. Argc--;
  1207. }
  1208. *pdword = ipCount;
  1209. //
  1210. // convert IP addresses
  1211. //
  1212. pip = precord->Data.WINS.WinsServers;
  1213. while ( Argc-- )
  1214. {
  1215. if ( ! Dns_Ip4StringToAddress_A(
  1216. pip,
  1217. Argv[0] ) )
  1218. {
  1219. Dns_RecordFree( precord );
  1220. SetLastError( ERROR_INVALID_DATA );
  1221. return NULL;
  1222. }
  1223. pip++;
  1224. Argv++;
  1225. }
  1226. return( precord );
  1227. }
  1228. PDNS_RECORD
  1229. WinsRecordBuildW(
  1230. IN DWORD Argc,
  1231. IN PWCHAR * Argv
  1232. )
  1233. /*++
  1234. Routine Description:
  1235. Build WINS record from string data.
  1236. Arguments:
  1237. Argc -- count of data Arguments
  1238. Argv -- argv array of data string pointers
  1239. Return Value:
  1240. Ptr to new record if successful.
  1241. NULL on failure.
  1242. --*/
  1243. {
  1244. PDNS_RECORD precord;
  1245. DWORD ipCount = Argc - 3;
  1246. PDWORD pdword;
  1247. PIP_ADDRESS pip;
  1248. char szAddr[256];
  1249. if ( Argc < 4 )
  1250. {
  1251. SetLastError( ERROR_INVALID_DATA );
  1252. return( NULL );
  1253. }
  1254. precord = Dns_AllocateRecord( (WORD) DNS_WINS_RECORD_LENGTH((WORD) ipCount) );
  1255. if ( !precord )
  1256. {
  1257. return( NULL );
  1258. }
  1259. //
  1260. // read integer data
  1261. //
  1262. // DCR_ENHANCE: could check for non-conversion in strtoul
  1263. //
  1264. pdword = &precord->Data.WINS.dwMappingFlag;
  1265. while ( Argc-- > 1 )
  1266. {
  1267. *pdword = (DWORD) wcstoul( Argv[0], NULL, 10 );
  1268. pdword++;
  1269. Argv++;
  1270. }
  1271. *pdword = ipCount;
  1272. //
  1273. // convert IP addresses
  1274. //
  1275. pip = precord->Data.WINS.WinsServers;
  1276. while ( Argc-- )
  1277. {
  1278. if ( ! Dns_Ip4StringToAddress_W(
  1279. pip,
  1280. Argv[0] ) )
  1281. {
  1282. Dns_RecordFree( precord );
  1283. SetLastError( ERROR_INVALID_DATA );
  1284. return NULL;
  1285. }
  1286. pip++;
  1287. Argv++;
  1288. }
  1289. return( precord );
  1290. }
  1291. PDNS_RECORD
  1292. WinsrRecordBuild(
  1293. IN DWORD Argc,
  1294. IN PCHAR * Argv
  1295. )
  1296. /*++
  1297. Routine Description:
  1298. Build WINSR record from string data.
  1299. Arguments:
  1300. Argc -- count of data Arguments
  1301. Argv -- argv array of data string pointers
  1302. Return Value:
  1303. Ptr to new record if successful.
  1304. NULL on failure.
  1305. --*/
  1306. {
  1307. PDNS_RECORD precord;
  1308. PDWORD pdword;
  1309. if ( Argc != 4 )
  1310. {
  1311. SetLastError( ERROR_INVALID_DATA );
  1312. return( NULL );
  1313. }
  1314. precord = Dns_AllocateRecord( sizeof(DNS_WINSR_DATA) );
  1315. if ( !precord )
  1316. {
  1317. return( NULL );
  1318. }
  1319. //
  1320. // read integer data
  1321. //
  1322. // DCR_ENHANCE: could check for non-conversion in strtoul
  1323. //
  1324. pdword = &precord->Data.WINSR.dwMappingFlag;
  1325. while( Argc-- > 1 )
  1326. {
  1327. *pdword = (WORD) strtoul( Argv[0], NULL, 10 );
  1328. pdword++;
  1329. Argv++;
  1330. }
  1331. //
  1332. // result domain
  1333. //
  1334. precord->Data.WINSR.pNameResultDomain = Argv[0];
  1335. return( precord );
  1336. }
  1337. PDNS_RECORD
  1338. WinsrRecordBuildW(
  1339. IN DWORD Argc,
  1340. IN PWCHAR * Argv
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. Build WINSR record from string data.
  1345. Arguments:
  1346. Argc -- count of data Arguments
  1347. Argv -- argv array of data string pointers
  1348. Return Value:
  1349. Ptr to new record if successful.
  1350. NULL on failure.
  1351. --*/
  1352. {
  1353. PDNS_RECORD precord;
  1354. PDWORD pdword;
  1355. if ( Argc != 4 )
  1356. {
  1357. SetLastError( ERROR_INVALID_DATA );
  1358. return( NULL );
  1359. }
  1360. precord = Dns_AllocateRecord( sizeof(DNS_WINSR_DATA) );
  1361. if ( !precord )
  1362. {
  1363. return( NULL );
  1364. }
  1365. //
  1366. // read integer data
  1367. //
  1368. // DCR_ENHANCE: could check for non-conversion in strtoul
  1369. //
  1370. pdword = &precord->Data.WINSR.dwMappingFlag;
  1371. while( Argc-- > 1 )
  1372. {
  1373. *pdword = (WORD) wcstoul( Argv[0], NULL, 10 );
  1374. pdword++;
  1375. Argv++;
  1376. }
  1377. //
  1378. // result domain
  1379. //
  1380. precord->Data.WINSR.pNameResultDomain = (PDNS_NAME) Argv[0];
  1381. return( precord );
  1382. }
  1383. PDNS_RECORD
  1384. WksRecordBuild(
  1385. IN DWORD Argc,
  1386. IN PCHAR * Argv
  1387. )
  1388. /*++
  1389. Routine Description:
  1390. Build WKS record from string data.
  1391. Arguments:
  1392. Argc -- count of data Arguments
  1393. Argv -- argv array of data string pointers
  1394. Return Value:
  1395. Ptr to new record if successful.
  1396. NULL on failure.
  1397. --*/
  1398. {
  1399. PDNS_RECORD precord;
  1400. DWORD byteCount = 0;
  1401. DWORD i;
  1402. PCHAR pch;
  1403. WSADATA wsaData;
  1404. DNS_STATUS status;
  1405. struct protoent * pProtoent;
  1406. if ( Argc < 3 )
  1407. {
  1408. SetLastError( ERROR_INVALID_DATA );
  1409. return( NULL );
  1410. }
  1411. i = 2;
  1412. while ( i < Argc)
  1413. {
  1414. byteCount += strlen( Argv[i] ) + 1;
  1415. i++;
  1416. }
  1417. byteCount++; //bBitMasks[0] : string length
  1418. //
  1419. // allocate space for WKS
  1420. //
  1421. precord = Dns_AllocateRecord( (WORD)DNS_WKS_RECORD_LENGTH(byteCount) );
  1422. if ( !precord )
  1423. {
  1424. return( NULL );
  1425. }
  1426. //
  1427. // get protocol number:
  1428. //
  1429. // start winsock:
  1430. //
  1431. // DCR: this is busted, winsock should be started by now
  1432. status = WSAStartup( DNS_WINSOCK_VERSION, &wsaData );
  1433. if ( status == SOCKET_ERROR )
  1434. {
  1435. Dns_RecordFree( precord );
  1436. status = WSAGetLastError();
  1437. SetLastError( status );
  1438. return( NULL );
  1439. }
  1440. pProtoent = getprotobyname( Argv[0] );
  1441. if ( ! pProtoent || pProtoent->p_proto >= MAXUCHAR )
  1442. {
  1443. Dns_RecordFree( precord );
  1444. status = WSAGetLastError();
  1445. SetLastError( status );
  1446. return( NULL );
  1447. }
  1448. precord->Data.WKS.chProtocol = (UCHAR) pProtoent->p_proto;
  1449. //
  1450. // get ipAddresss:
  1451. //
  1452. precord->Data.WKS.IpAddress = inet_addr( Argv[1] );
  1453. //
  1454. // get the services, put all in one string
  1455. //
  1456. pch = precord->Data.WKS.BitMask;
  1457. (UCHAR) *pch = (UCHAR) byteCount-1; //string length
  1458. pch++;
  1459. i = 2;
  1460. strcpy( pch, Argv[i] );
  1461. while ( ++i < Argc )
  1462. {
  1463. strcat( pch, " " );
  1464. strcat( pch, Argv[i] );
  1465. }
  1466. return( precord );
  1467. }
  1468. PDNS_RECORD
  1469. WksRecordBuildW(
  1470. IN DWORD Argc,
  1471. IN PWCHAR * Argv
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. Build WKS record from string data.
  1476. Arguments:
  1477. Argc -- count of data Arguments
  1478. Argv -- argv array of data string pointers
  1479. Return Value:
  1480. Ptr to new record if successful.
  1481. NULL on failure.
  1482. --*/
  1483. {
  1484. PDNS_RECORD precord;
  1485. DWORD byteCount = 0;
  1486. DWORD i;
  1487. PWCHAR pch;
  1488. WSADATA wsaData;
  1489. DNS_STATUS status;
  1490. struct protoent * pProtoent;
  1491. char szAddr[256];
  1492. WCHAR tcpStr[4], udpStr[4], space[2];
  1493. if ( Argc < 3 )
  1494. {
  1495. SetLastError( ERROR_INVALID_DATA );
  1496. return( NULL );
  1497. }
  1498. i = 2;
  1499. while ( i < Argc)
  1500. {
  1501. byteCount += wcslen( Argv[i] ) + 1;
  1502. i++;
  1503. }
  1504. byteCount++; //bBitMasks[0] : string length
  1505. //
  1506. // allocate space for WKS
  1507. //
  1508. precord = Dns_AllocateRecord( (WORD)DNS_WKS_RECORD_LENGTH(byteCount) );
  1509. if ( !precord )
  1510. {
  1511. return( NULL );
  1512. }
  1513. //
  1514. // get protocol number
  1515. //
  1516. status = WSAStartup( DNS_WINSOCK_VERSION, &wsaData );
  1517. if ( status == SOCKET_ERROR )
  1518. {
  1519. Dns_RecordFree( precord );
  1520. status = WSAGetLastError();
  1521. SetLastError( status );
  1522. return( NULL );
  1523. }
  1524. #if 0
  1525. //
  1526. // DCR_FIX: WKS build
  1527. //
  1528. if ( ! Dns_CopyStringEx( szAddr, 0, (PCHAR) Argv[0], 0, TRUE, FALSE ) )
  1529. {
  1530. Dns_RecordListFree( precord );
  1531. return NULL;
  1532. }
  1533. pProtoent = getprotobyname( szAddr );
  1534. if ( ! pProtoent || pProtoent->p_proto >= MAXUCHAR )
  1535. {
  1536. Dns_RecordFree( precord );
  1537. status = WSAGetLastError();
  1538. SetLastError( status );
  1539. return( NULL );
  1540. }
  1541. precord->Data.WKS.chProtocol = (UCHAR) pProtoent->p_proto;
  1542. //
  1543. // IP Address
  1544. //
  1545. if ( ! Dns_CopyStringEx( szAddr, 0, (PCHAR) Argv[0], 0, TRUE, FALSE ) )
  1546. {
  1547. Dns_RecordListFree( precord );
  1548. return NULL;
  1549. }
  1550. precord->Data.WKS.IpAddress = inet_addr( szAddr );
  1551. //
  1552. // get the services, put all in one string
  1553. //
  1554. pch = (PWCHAR) precord->Data.WKS.bBitMask;
  1555. (UCHAR) *pch = (UCHAR) byteCount-1;
  1556. pch++;
  1557. i = 2;
  1558. if ( ! Dns_NameCopy(
  1559. (PBYTE) space,
  1560. 0,
  1561. " ",
  1562. 0,
  1563. DnsCharSetUnicode,
  1564. DnsCharSetWire ) )
  1565. {
  1566. Dns_RecordListFree( precord );
  1567. return NULL;
  1568. }
  1569. wcscpy( pch, Argv[i] );
  1570. while ( ++i < Argc )
  1571. {
  1572. wcscat( pch, space );
  1573. wcscat( pch, Argv[i] );
  1574. }
  1575. #endif
  1576. return( precord );
  1577. }
  1578. PDNS_RECORD
  1579. KeyRecordBuild(
  1580. IN DWORD Argc,
  1581. IN PCHAR * Argv
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. Build KEY record from string data.
  1586. Arguments:
  1587. Argc -- count of data Arguments
  1588. Argv -- argv array of data string pointers
  1589. Return Value:
  1590. Ptr to new record if successful.
  1591. NULL on failure.
  1592. --*/
  1593. {
  1594. PDNS_RECORD prec;
  1595. int keyStringLength;
  1596. DWORD keyLength = 0;
  1597. if ( Argc != 4 )
  1598. {
  1599. SetLastError( ERROR_INVALID_DATA );
  1600. return NULL;
  1601. }
  1602. keyStringLength = strlen( Argv[ 3 ] );
  1603. prec = Dns_AllocateRecord( ( WORD )
  1604. sizeof( DNS_KEY_DATA ) + keyStringLength );
  1605. if ( !prec )
  1606. {
  1607. return NULL;
  1608. }
  1609. prec->Data.KEY.wFlags = ( WORD ) strtoul( *( Argv++ ), NULL, 0 );
  1610. prec->Data.KEY.chProtocol = ( BYTE ) strtoul( *( Argv++ ), NULL, 10 );
  1611. prec->Data.KEY.chAlgorithm = ( BYTE ) strtoul( *( Argv++ ), NULL, 10 );
  1612. Argc -= 3;
  1613. Dns_SecurityBase64StringToKey(
  1614. prec->Data.KEY.Key,
  1615. &keyLength,
  1616. *Argv,
  1617. keyStringLength );
  1618. Argc--;
  1619. Argv++;
  1620. prec->wDataLength = ( WORD ) ( SIZEOF_KEY_FIXED_DATA + keyLength );
  1621. return prec;
  1622. } // KeyRecordBuild
  1623. PDNS_RECORD
  1624. KeyRecordBuildW(
  1625. IN DWORD Argc,
  1626. IN PWCHAR * Argv
  1627. )
  1628. /*++
  1629. Routine Description:
  1630. Build KEY record from string data.
  1631. Arguments:
  1632. Argc -- count of data Arguments
  1633. Argv -- argv array of data string pointers
  1634. Return Value:
  1635. Ptr to new record if successful.
  1636. NULL on failure.
  1637. --*/
  1638. {
  1639. PDNS_RECORD prec;
  1640. int keyStringLength;
  1641. DWORD keyLength = 0;
  1642. if ( Argc != 4 )
  1643. {
  1644. SetLastError( ERROR_INVALID_DATA );
  1645. return NULL;
  1646. }
  1647. keyStringLength = wcslen( Argv[ 3 ] );
  1648. prec = Dns_AllocateRecord( ( WORD )
  1649. sizeof( DNS_KEY_DATA ) + keyStringLength / 2 );
  1650. if ( !prec )
  1651. {
  1652. return NULL;
  1653. }
  1654. prec->Data.KEY.wFlags = ( WORD ) wcstoul( *( Argv++ ), NULL, 0 );
  1655. prec->Data.KEY.chProtocol = ( BYTE ) wcstoul( *( Argv++ ), NULL, 10 );
  1656. prec->Data.KEY.chAlgorithm = ( BYTE ) wcstoul( *( Argv++ ), NULL, 10 );
  1657. Argc -= 3;
  1658. #if 0
  1659. // JJW: MUST COPY BUFFER???
  1660. Dns_SecurityBase64StringToKey(
  1661. prec->Data.KEY.Key,
  1662. &keyLength,
  1663. *Argv,
  1664. keyStringLength );
  1665. #endif
  1666. Argc--;
  1667. Argv++;
  1668. prec->wDataLength = ( WORD ) ( SIZEOF_KEY_FIXED_DATA + keyLength );
  1669. return prec;
  1670. } // KeyRecordBuildW
  1671. PDNS_RECORD
  1672. SigRecordBuild(
  1673. IN DWORD Argc,
  1674. IN PCHAR * Argv
  1675. )
  1676. /*++
  1677. Routine Description:
  1678. Build SIG record from string data.
  1679. Arguments:
  1680. Argc -- count of data Arguments
  1681. Argv -- argv array of data string pointers
  1682. Return Value:
  1683. Ptr to new record if successful.
  1684. NULL on failure.
  1685. --*/
  1686. {
  1687. PDNS_RECORD prec;
  1688. int sigStringLength;
  1689. DWORD sigLength = 0;
  1690. if ( Argc != 9 )
  1691. {
  1692. SetLastError( ERROR_INVALID_DATA );
  1693. return NULL;
  1694. }
  1695. sigStringLength = strlen( Argv[ 8 ] );
  1696. prec = Dns_AllocateRecord( ( WORD )
  1697. ( sizeof( DNS_SIG_DATA ) + sigStringLength ) );
  1698. if ( !prec )
  1699. {
  1700. return NULL;
  1701. }
  1702. prec->Data.SIG.wTypeCovered = Dns_RecordTypeForName( *( Argv++ ), 0 );
  1703. prec->Data.SIG.chAlgorithm = ( BYTE ) strtoul( *( Argv++ ), NULL, 10 );
  1704. prec->Data.Sig.chLabelCount = ( BYTE ) strtoul( *( Argv++ ), NULL, 10 );
  1705. prec->Data.SIG.dwOriginalTtl = ( DWORD ) strtoul( *( Argv++ ), NULL, 10 );
  1706. prec->Data.SIG.dwExpiration = Dns_ParseSigTime( *( Argv++ ), 0 );
  1707. prec->Data.SIG.dwTimeSigned = Dns_ParseSigTime( *( Argv++ ), 0 );
  1708. prec->Data.SIG.wKeyTag = ( WORD ) strtoul( *( Argv++ ), NULL, 10 );
  1709. prec->Data.SIG.pNameSigner = *( Argv++ );
  1710. Argc -= 8;
  1711. //
  1712. // Validate signature times.
  1713. //
  1714. if ( prec->Data.SIG.dwExpiration == 0 ||
  1715. prec->Data.SIG.dwTimeSigned == 0 ||
  1716. prec->Data.SIG.dwTimeSigned >= prec->Data.SIG.dwExpiration )
  1717. {
  1718. Dns_RecordFree( prec );
  1719. SetLastError( ERROR_INVALID_DATA );
  1720. return NULL;
  1721. }
  1722. //
  1723. // Parse signature.
  1724. //
  1725. if ( Dns_SecurityBase64StringToKey(
  1726. prec->Data.SIG.Signature,
  1727. &sigLength,
  1728. *Argv,
  1729. sigStringLength ) != ERROR_SUCCESS )
  1730. {
  1731. Dns_RecordFree( prec );
  1732. SetLastError( ERROR_INVALID_DATA );
  1733. return NULL;
  1734. }
  1735. Argc--;
  1736. Argv++;
  1737. prec->wDataLength = ( WORD ) ( sizeof( DNS_SIG_DATA ) - 4 + sigLength );
  1738. return prec;
  1739. } // SigRecordBuild
  1740. PDNS_RECORD
  1741. SigRecordBuildW(
  1742. IN DWORD Argc,
  1743. IN PWCHAR * Argv
  1744. )
  1745. /*++
  1746. Routine Description:
  1747. Build SIG record from string data.
  1748. Arguments:
  1749. Argc -- count of data Arguments
  1750. Argv -- argv array of data string pointers
  1751. Return Value:
  1752. Ptr to new record if successful.
  1753. NULL on failure.
  1754. --*/
  1755. {
  1756. PDNS_RECORD prec;
  1757. int sigStringLength;
  1758. DWORD sigLength = 0;
  1759. PCHAR pch;
  1760. if ( Argc != 8 )
  1761. {
  1762. SetLastError( ERROR_INVALID_DATA );
  1763. return NULL;
  1764. }
  1765. sigStringLength = wcslen( Argv[ 7 ] );
  1766. prec = Dns_AllocateRecord( ( WORD )
  1767. ( sizeof( DNS_SIG_DATA ) + sigStringLength ) );
  1768. if ( !prec )
  1769. {
  1770. return NULL;
  1771. }
  1772. #if 0
  1773. // JJW: how to convert all args here???
  1774. prec->Data.SIG.wTypeCovered = Dns_RecordTypeForName( *( Argv++ ), 0 );
  1775. prec->Data.SIG.chAlgorithm = ( BYTE ) strtoul( *( Argv++ ), NULL, 10 );
  1776. prec->Data.Sig.chLabelCount = ( BYTE ) strtoul( *( Argv++ ), NULL, 10 );
  1777. prec->Data.SIG.dwOriginalTtl = ( DWORD ) strtoul( *( Argv++ ), NULL, 10 );
  1778. prec->Data.SIG.dwExpiration = Dns_ParseSigTime( *( Argv++ ), 0 );
  1779. prec->Data.SIG.dwTimeSigned = Dns_ParseSigTime( *( Argv++ ), 0 );
  1780. prec->Data.SIG.wKeyTag = ( WORD ) strtoul( *( Argv++ ), NULL, 10 );
  1781. prec->Data.SIG.pNameSigner = *( Argv++ );
  1782. Argc -= 8;
  1783. Dns_SecurityBase64StringToKey(
  1784. prec->Data.SIG.Signature,
  1785. &sigLength,
  1786. *Argv,
  1787. sigStringLength );
  1788. #endif
  1789. Argc--;
  1790. Argv++;
  1791. prec->wDataLength = ( WORD ) ( sizeof( DNS_SIG_DATA ) - 4 + sigLength );
  1792. return prec;
  1793. } // SigRecordBuildW
  1794. PDNS_RECORD
  1795. NxtRecordBuild(
  1796. IN DWORD Argc,
  1797. IN PCHAR * Argv
  1798. )
  1799. /*++
  1800. Routine Description:
  1801. Build NXT record from string data.
  1802. First arg is next name, followed by list of record types at that name.
  1803. Arguments:
  1804. Argc -- count of data Arguments
  1805. Argv -- argv array of data string pointers
  1806. Return Value:
  1807. Ptr to new record if successful.
  1808. NULL on failure.
  1809. --*/
  1810. {
  1811. PDNS_RECORD prec;
  1812. int typeIdx = 0;
  1813. if ( Argc < 2 )
  1814. {
  1815. SetLastError( ERROR_INVALID_DATA );
  1816. return NULL;
  1817. }
  1818. prec = Dns_AllocateRecord( ( WORD ) (
  1819. sizeof( LPTSTR ) + sizeof( WORD ) * Argc ) );
  1820. if ( !prec )
  1821. {
  1822. return NULL;
  1823. }
  1824. prec->Data.NXT.pNameNext = *( Argv++ );
  1825. --Argc;
  1826. prec->Data.NXT.wNumTypes = 0;
  1827. while ( Argc-- )
  1828. {
  1829. ++prec->Data.NXT.wNumTypes;
  1830. prec->Data.NXT.wTypes[ typeIdx++ ] =
  1831. Dns_RecordTypeForName( *( Argv++ ), 0 );
  1832. }
  1833. return prec;
  1834. } // NxtRecordBuild
  1835. PDNS_RECORD
  1836. NxtRecordBuildW(
  1837. IN DWORD Argc,
  1838. IN PWCHAR * Argv
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. Build NXT record from string data.
  1843. First arg is next name, followed by list of record types at that name.
  1844. Arguments:
  1845. Argc -- count of data Arguments
  1846. Argv -- argv array of data string pointers
  1847. Return Value:
  1848. Ptr to new record if successful.
  1849. NULL on failure.
  1850. --*/
  1851. {
  1852. PDNS_RECORD prec;
  1853. int typeIdx = 0;
  1854. if ( Argc < 2 )
  1855. {
  1856. SetLastError( ERROR_INVALID_DATA );
  1857. return NULL;
  1858. }
  1859. prec = Dns_AllocateRecord( ( WORD ) (
  1860. sizeof( LPTSTR ) + sizeof( WORD ) * ( Argc - 1 ) ) );
  1861. if ( !prec )
  1862. {
  1863. return NULL;
  1864. }
  1865. prec->Data.NXT.pNameNext = ( PDNS_NAME ) ( *( Argv++ ) );
  1866. --Argc;
  1867. #if 0
  1868. // JJW: convert type string???
  1869. while ( Argc-- )
  1870. {
  1871. prec->Data.NXT.wTypes[ typeIdx++ ] =
  1872. Dns_RecordTypeForName( *( Argv++ ), 0 );
  1873. }
  1874. #endif
  1875. return prec;
  1876. } // NxtRecordBuildW
  1877. //
  1878. // Public build routine
  1879. //
  1880. PDNS_RECORD
  1881. Dns_RecordBuild_A(
  1882. IN OUT PDNS_RRSET pRRSet,
  1883. IN LPSTR pszOwner,
  1884. IN WORD wType,
  1885. IN BOOL fAdd,
  1886. IN UCHAR Section,
  1887. IN INT Argc,
  1888. IN PCHAR * Argv
  1889. )
  1890. /*++
  1891. Routine Description:
  1892. Build record from data strings.
  1893. Arguments:
  1894. pRRSet -- ptr to RR set structure being built
  1895. pszOwner -- DNS name of RR owner
  1896. wType -- record type
  1897. fAdd -- add\delete, exist\no-exist flag
  1898. Section -- RR section for record
  1899. Argc -- count of data strings
  1900. Argv -- argv array of ptrs to data strings
  1901. Return Value:
  1902. Ptr to record built.
  1903. NULL on error.
  1904. --*/
  1905. {
  1906. PDNS_RECORD precord;
  1907. WORD index;
  1908. IF_DNSDBG( INIT )
  1909. {
  1910. DNS_PRINT((
  1911. "Dns_RecordBuild()\n"
  1912. "\trrset = %p\n"
  1913. "\towner = %s\n"
  1914. "\ttype = %d\n"
  1915. "\tfAdd = %d\n"
  1916. "\tsection = %d\n"
  1917. "\targc = %d\n",
  1918. pRRSet,
  1919. pszOwner,
  1920. wType,
  1921. fAdd,
  1922. Section,
  1923. Argc ));
  1924. }
  1925. //
  1926. // every record MUST have owner name
  1927. //
  1928. if ( !pszOwner )
  1929. {
  1930. SetLastError( ERROR_INVALID_DATA );
  1931. return( NULL );
  1932. }
  1933. //
  1934. // if no data, no dispatch required
  1935. //
  1936. if ( Argc == 0 )
  1937. {
  1938. precord = Dns_AllocateRecord( 0 );
  1939. if ( ! precord )
  1940. {
  1941. return( NULL );
  1942. }
  1943. }
  1944. // have data, dispatch to type specific build routine
  1945. else
  1946. {
  1947. index = INDEX_FOR_TYPE( wType );
  1948. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  1949. if ( !index || !RRBuildTable[ index ] )
  1950. {
  1951. // can NOT build unknown types
  1952. SetLastError( DNS_ERROR_INVALID_TYPE );
  1953. DNS_PRINT((
  1954. "ERROR: can not build record of type %d\n",
  1955. wType ));
  1956. return( NULL );
  1957. }
  1958. precord = RRBuildTable[ index ](
  1959. Argc,
  1960. Argv );
  1961. if ( ! precord )
  1962. {
  1963. DNS_PRINT((
  1964. "ERROR: Record build routine failure for record type %d.\n"
  1965. "\tstatus = %d\n\n",
  1966. wType,
  1967. GetLastError() ));
  1968. if ( !GetLastError() )
  1969. {
  1970. SetLastError( ERROR_INVALID_DATA );
  1971. }
  1972. return( NULL );
  1973. }
  1974. }
  1975. //
  1976. // fill out record structure
  1977. //
  1978. precord->pName = pszOwner;
  1979. precord->wType = wType;
  1980. precord->Flags.S.Section = Section;
  1981. precord->Flags.S.Delete = !fAdd;
  1982. precord->Flags.S.CharSet = DnsCharSetAnsi;
  1983. IF_DNSDBG( INIT )
  1984. {
  1985. DnsDbg_Record(
  1986. "New record built\n",
  1987. precord );
  1988. }
  1989. //
  1990. // link into existing RR set (if any)
  1991. //
  1992. if ( pRRSet )
  1993. {
  1994. DNS_RRSET_ADD( *pRRSet, precord );
  1995. }
  1996. return( precord );
  1997. }
  1998. PDNS_RECORD
  1999. Dns_RecordBuild_W(
  2000. IN OUT PDNS_RRSET pRRSet,
  2001. IN LPWSTR pszOwner,
  2002. IN WORD wType,
  2003. IN BOOL fAdd,
  2004. IN UCHAR Section,
  2005. IN INT Argc,
  2006. IN PWCHAR * Argv
  2007. )
  2008. /*++
  2009. Routine Description:
  2010. Build record from data strings.
  2011. Arguments:
  2012. pRRSet -- ptr to RR set structure being built
  2013. pszOwner -- DNS name of RR owner
  2014. wType -- record type
  2015. fAdd -- add\delete, exist\no-exist flag
  2016. Section -- RR section for record
  2017. Argc -- count of data strings
  2018. Argv -- argv array of ptrs to data strings
  2019. Return Value:
  2020. Ptr to record built.
  2021. NULL on error.
  2022. --*/
  2023. {
  2024. PDNS_RECORD precord;
  2025. WORD index;
  2026. DNSDBG( INIT, (
  2027. "Dns_RecordBuild()\n"
  2028. "\trrset = %p\n"
  2029. "\towner = %S\n"
  2030. "\ttype = %d\n"
  2031. "\tfAdd = %d\n"
  2032. "\tsection = %d\n"
  2033. "\targc = %d\n",
  2034. pRRSet,
  2035. pszOwner,
  2036. wType,
  2037. fAdd,
  2038. Section,
  2039. Argc ));
  2040. //
  2041. // every record MUST have owner name
  2042. //
  2043. if ( !pszOwner )
  2044. {
  2045. SetLastError( ERROR_INVALID_DATA );
  2046. return( NULL );
  2047. }
  2048. //
  2049. // if no data, no dispatch required
  2050. //
  2051. if ( Argc == 0 )
  2052. {
  2053. precord = Dns_AllocateRecord( 0 );
  2054. if ( ! precord )
  2055. {
  2056. return( NULL );
  2057. }
  2058. }
  2059. // have data, dispatch to type specific build routine
  2060. else
  2061. {
  2062. index = INDEX_FOR_TYPE( wType );
  2063. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  2064. if ( !index || !RRBuildTableW[ index ] )
  2065. {
  2066. // can NOT build unknown types
  2067. SetLastError( DNS_ERROR_INVALID_TYPE );
  2068. DNS_PRINT((
  2069. "ERROR: can not build record of type %d\n",
  2070. wType ));
  2071. return( NULL );
  2072. }
  2073. precord = RRBuildTableW[ index ](
  2074. Argc,
  2075. Argv );
  2076. if ( ! precord )
  2077. {
  2078. DNS_PRINT((
  2079. "ERROR: Record build routine failure for record type %d.\n"
  2080. "\tstatus = %d\n\n",
  2081. wType,
  2082. GetLastError() ));
  2083. if ( !GetLastError() )
  2084. {
  2085. SetLastError( ERROR_INVALID_DATA );
  2086. }
  2087. return( NULL );
  2088. }
  2089. }
  2090. //
  2091. // fill out record structure
  2092. //
  2093. precord->pName = (PDNS_NAME) pszOwner;
  2094. precord->wType = wType;
  2095. precord->Flags.S.Section = Section;
  2096. precord->Flags.S.Delete = !fAdd;
  2097. precord->Flags.S.CharSet = DnsCharSetUnicode;
  2098. IF_DNSDBG( INIT )
  2099. {
  2100. DnsDbg_Record(
  2101. "New record built\n",
  2102. precord );
  2103. }
  2104. //
  2105. // link into existing RR set (if any)
  2106. //
  2107. if ( pRRSet )
  2108. {
  2109. DNS_RRSET_ADD( *pRRSet, precord );
  2110. }
  2111. return( precord );
  2112. }
  2113. //
  2114. // End rrbuild.c
  2115. //