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.

1228 lines
27 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. rconvert.c
  5. Abstract:
  6. Domain Name System (DNS) Server -- Admin Client Library
  7. RPC record conversion routines.
  8. Convert records in RPC buffer to DNS_RECORD type.
  9. Author:
  10. Jim Gilroy (jamesg) April, 1997
  11. Revision History:
  12. --*/
  13. #include "dnsclip.h"
  14. #define IS_COMPLETE_NODE( pRpcNode ) \
  15. (!!((pRpcNode)->dwFlags & DNS_RPC_NODE_FLAG_COMPLETE))
  16. //
  17. // Copy-convert string from RPC format (UTF8) into DNS_RECORD buffer
  18. // - assume previously allocated required buffer
  19. //
  20. // Note: no difference between string and name conversion as we're
  21. // going FROM UTF8
  22. //
  23. #define COPY_UTF8_STR_TO_BUFFER( buf, psz, len, charSet ) \
  24. Dns_StringCopy( \
  25. (buf), \
  26. NULL, \
  27. (psz), \
  28. (len), \
  29. DnsCharSetUtf8, \
  30. (charSet) )
  31. #if 0
  32. Dns_StringCopy( \
  33. (buf), \ // result DNS_RECORD buffer
  34. NULL, \ // buffer has required length
  35. (psz), \ // in UTF8 string
  36. (len), \ // string length (if known)
  37. DnsCharSetUtf8, \ // string is UTF8
  38. (charSet) ) // converting to this char set
  39. #endif
  40. //
  41. // RPC record to DNS_RECORD conversion routines
  42. //
  43. PDNS_RECORD
  44. ARpcRecordConvert(
  45. IN PDNS_RPC_RECORD pRpcRR,
  46. IN DNS_CHARSET CharSet
  47. )
  48. /*++
  49. Routine Description:
  50. Read A record data from packet.
  51. Arguments:
  52. pRpcRR - message being read
  53. Return Value:
  54. Ptr to new record if successful.
  55. NULL on failure.
  56. --*/
  57. {
  58. PDNS_RECORD precord;
  59. DNS_ASSERT( pRpcRR->wDataLength == sizeof(IP_ADDRESS) );
  60. precord = Dns_AllocateRecord( sizeof(IP_ADDRESS) );
  61. if ( !precord )
  62. {
  63. return( NULL );
  64. }
  65. precord->Data.A.IpAddress = pRpcRR->Data.A.ipAddress;
  66. return( precord );
  67. }
  68. PDNS_RECORD
  69. PtrRpcRecordConvert(
  70. IN PDNS_RPC_RECORD pRpcRR,
  71. IN DNS_CHARSET CharSet
  72. )
  73. /*++
  74. Routine Description:
  75. Process PTR compatible record from wire.
  76. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
  77. Arguments:
  78. pRpcRR - message being read
  79. CharSet - character set for resulting record
  80. Return Value:
  81. Ptr to new record if successful.
  82. NULL on failure.
  83. --*/
  84. {
  85. PDNS_RECORD precord;
  86. PDNS_RPC_NAME pname = &pRpcRR->Data.PTR.nameNode;
  87. WORD bufLength;
  88. //
  89. // PTR data is another domain name
  90. //
  91. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pname) )
  92. {
  93. DNS_ASSERT( FALSE );
  94. return NULL;
  95. }
  96. //
  97. // determine required buffer length and allocate
  98. //
  99. bufLength = sizeof( DNS_PTR_DATA )
  100. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname->cchNameLength, CharSet );
  101. precord = Dns_AllocateRecord( bufLength );
  102. if ( !precord )
  103. {
  104. return( NULL );
  105. }
  106. //
  107. // write hostname into buffer, immediately following PTR data struct
  108. //
  109. precord->Data.PTR.pNameHost = (PCHAR)&precord->Data + sizeof(DNS_PTR_DATA);
  110. COPY_UTF8_STR_TO_BUFFER(
  111. precord->Data.PTR.pNameHost,
  112. pname->achName,
  113. pname->cchNameLength,
  114. CharSet
  115. );
  116. return( precord );
  117. }
  118. PDNS_RECORD
  119. SoaRpcRecordConvert(
  120. IN PDNS_RPC_RECORD pRpcRR,
  121. IN DNS_CHARSET CharSet
  122. )
  123. /*++
  124. Routine Description:
  125. Read SOA record from wire.
  126. Arguments:
  127. pRR - ptr to record with RR set context
  128. pRpcRR - message being read
  129. pchData - ptr to RR data field
  130. pchEnd - ptr to byte after data field
  131. Return Value:
  132. Ptr to new record if successful.
  133. NULL on failure.
  134. --*/
  135. {
  136. PDNS_RECORD precord;
  137. WORD bufLength;
  138. DWORD dwLength;
  139. PDNS_RPC_NAME pnamePrimary = &pRpcRR->Data.SOA.namePrimaryServer;
  140. PDNS_RPC_NAME pnameAdmin;
  141. //
  142. // verify names in SOA record
  143. //
  144. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pnamePrimary) )
  145. {
  146. DNS_ASSERT( FALSE );
  147. return NULL;
  148. }
  149. pnameAdmin = DNS_GET_NEXT_NAME(pnamePrimary);
  150. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pnameAdmin) )
  151. {
  152. DNS_ASSERT( FALSE );
  153. return NULL;
  154. }
  155. //
  156. // determine required buffer length and allocate
  157. //
  158. bufLength = sizeof( DNS_SOA_DATA )
  159. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pnamePrimary->cchNameLength, CharSet )
  160. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pnameAdmin->cchNameLength, CharSet );
  161. precord = Dns_AllocateRecord( bufLength );
  162. if ( !precord )
  163. {
  164. return( NULL );
  165. }
  166. //
  167. // copy fixed fields
  168. //
  169. RtlCopyMemory(
  170. (PCHAR) & precord->Data.SOA.dwSerialNo,
  171. (PCHAR) & pRpcRR->Data.SOA.dwSerialNo,
  172. SIZEOF_SOA_FIXED_DATA );
  173. //
  174. // copy names into RR buffer
  175. // - primary server immediately follows SOA data struct
  176. // - responsible party follows primary server
  177. //
  178. precord->Data.SOA.pNamePrimaryServer = (PCHAR)&precord->Data
  179. + sizeof(DNS_SOA_DATA);
  180. dwLength =
  181. COPY_UTF8_STR_TO_BUFFER(
  182. precord->Data.SOA.pNamePrimaryServer,
  183. pnamePrimary->achName,
  184. (DWORD)pnamePrimary->cchNameLength,
  185. CharSet );
  186. precord->Data.SOA.pNameAdministrator = precord->Data.SOA.pNamePrimaryServer + dwLength;
  187. COPY_UTF8_STR_TO_BUFFER(
  188. precord->Data.SOA.pNameAdministrator,
  189. pnameAdmin->achName,
  190. (DWORD)pnameAdmin->cchNameLength,
  191. CharSet );
  192. return( precord );
  193. }
  194. PDNS_RECORD
  195. TxtRpcRecordConvert(
  196. IN PDNS_RPC_RECORD pRpcRR,
  197. IN DNS_CHARSET CharSet
  198. )
  199. /*++
  200. Routine Description:
  201. Read TXT compatible record from wire.
  202. Includes: TXT, X25, HINFO, ISDN
  203. Arguments:
  204. pRpcRR - message being read
  205. Return Value:
  206. Ptr to new record if successful.
  207. NULL on failure.
  208. --*/
  209. {
  210. PDNS_RECORD precord;
  211. DWORD bufLength = 0;
  212. DWORD length = 0;
  213. INT count = 0;
  214. PCHAR pch;
  215. PCHAR pchend;
  216. PCHAR pchbuffer;
  217. PCHAR * ppstring;
  218. PDNS_RPC_NAME pname = &pRpcRR->Data.TXT.stringData;
  219. //
  220. // determine required buffer length and allocate
  221. // - allocate space for each string
  222. // - and ptr for each string
  223. //
  224. pch = (PCHAR)&pRpcRR->Data.TXT;
  225. pchend = pch + pRpcRR->wDataLength;
  226. while ( pch < pchend )
  227. {
  228. length = (UCHAR) *pch++;
  229. pch += length;
  230. count++;
  231. bufLength += STR_BUF_SIZE_GIVEN_UTF8_LEN( length, CharSet );
  232. }
  233. if ( pch != pchend )
  234. {
  235. DNS_PRINT((
  236. "ERROR: Invalid RPCstring data.\n"
  237. "\tpch = %p\n"
  238. "\tpchEnd = %p\n"
  239. "\tcount = %d\n"
  240. "\tlength = %d\n",
  241. pch, pchend, count, length
  242. ));
  243. SetLastError( ERROR_INVALID_DATA );
  244. return( NULL );
  245. }
  246. // allocate
  247. bufLength += (WORD) DNS_TEXT_RECORD_LENGTH(count);
  248. precord = Dns_AllocateRecord( (WORD)bufLength );
  249. if ( !precord )
  250. {
  251. return( NULL );
  252. }
  253. precord->Data.TXT.dwStringCount = count;
  254. //
  255. // go back through list copying strings to buffer
  256. // - ptrs to strings are saved to argv like data section
  257. // ppstring walks through this section
  258. // - first string written immediately following data section
  259. // - each subsequent string immediately follows predecessor
  260. // pchbuffer keeps ptr to position to write strings
  261. //
  262. pch = (PCHAR)&pRpcRR->Data.TXT;
  263. ppstring = precord->Data.TXT.pStringArray;
  264. pchbuffer = (PCHAR)ppstring + (count * sizeof(PCHAR));
  265. while ( pch < pchend )
  266. {
  267. length = (DWORD)((UCHAR) *pch++);
  268. *ppstring++ = pchbuffer;
  269. pchbuffer += COPY_UTF8_STR_TO_BUFFER(
  270. pchbuffer,
  271. pch,
  272. length,
  273. CharSet );
  274. pch += length;
  275. #if DBG
  276. DNS_PRINT((
  277. "Read text string %s\n",
  278. * (ppstring - 1)
  279. ));
  280. count--;
  281. #endif
  282. }
  283. DNS_ASSERT( pch == pchend && count == 0 );
  284. return( precord );
  285. }
  286. PDNS_RECORD
  287. MinfoRpcRecordConvert(
  288. IN PDNS_RPC_RECORD pRpcRR,
  289. IN DNS_CHARSET CharSet
  290. )
  291. /*++
  292. Routine Description:
  293. Read MINFO record from wire.
  294. Arguments:
  295. pRpcRR - message being read
  296. Return Value:
  297. Ptr to new record if successful.
  298. NULL on failure.
  299. --*/
  300. {
  301. PDNS_RECORD precord;
  302. WORD bufLength;
  303. DWORD dwLength;
  304. PDNS_RPC_NAME pname1 = &pRpcRR->Data.MINFO.nameMailBox;
  305. PDNS_RPC_NAME pname2;
  306. //
  307. // verify names in MINFO record
  308. //
  309. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pname1) )
  310. {
  311. DNS_ASSERT( FALSE );
  312. return NULL;
  313. }
  314. pname2 = DNS_GET_NEXT_NAME(pname1);
  315. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pname2) )
  316. {
  317. DNS_ASSERT( FALSE );
  318. return NULL;
  319. }
  320. //
  321. // determine required buffer length and allocate
  322. //
  323. bufLength = (WORD)
  324. ( sizeof( DNS_MINFO_DATA )
  325. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname1->cchNameLength, CharSet )
  326. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname2->cchNameLength, CharSet ) );
  327. precord = Dns_AllocateRecord( bufLength );
  328. if ( !precord )
  329. {
  330. return( NULL );
  331. }
  332. //
  333. // copy names into RR buffer
  334. // - mailbox immediately follows MINFO data struct
  335. // - errors mailbox immediately follows primary server
  336. //
  337. precord->Data.MINFO.pNameMailbox
  338. = (PCHAR)&precord->Data + sizeof( DNS_MINFO_DATA );
  339. dwLength =
  340. COPY_UTF8_STR_TO_BUFFER(
  341. precord->Data.MINFO.pNameMailbox,
  342. pname1->achName,
  343. (DWORD)pname1->cchNameLength,
  344. CharSet );
  345. precord->Data.MINFO.pNameErrorsMailbox = precord->Data.MINFO.pNameMailbox + dwLength;
  346. COPY_UTF8_STR_TO_BUFFER(
  347. precord->Data.MINFO.pNameErrorsMailbox,
  348. pname2->achName,
  349. (DWORD)pname2->cchNameLength,
  350. CharSet );
  351. return( precord );
  352. }
  353. PDNS_RECORD
  354. MxRpcRecordConvert(
  355. IN PDNS_RPC_RECORD pRpcRR,
  356. IN DNS_CHARSET CharSet
  357. )
  358. /*++
  359. Routine Description:
  360. Read MX compatible record from wire.
  361. Includes: MX, RT, AFSDB
  362. Arguments:
  363. pRpcRR - message being read
  364. Return Value:
  365. Ptr to new record if successful.
  366. NULL on failure.
  367. --*/
  368. {
  369. PDNS_RECORD precord;
  370. PDNS_RPC_NAME pname = &pRpcRR->Data.MX.nameExchange;
  371. WORD bufLength;
  372. //
  373. // MX exchange is another DNS name
  374. //
  375. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pname) )
  376. {
  377. DNS_ASSERT( FALSE );
  378. return NULL;
  379. }
  380. //
  381. // determine required buffer length and allocate
  382. //
  383. bufLength = sizeof( DNS_MX_DATA )
  384. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname->cchNameLength, CharSet );
  385. precord = Dns_AllocateRecord( bufLength );
  386. if ( !precord )
  387. {
  388. return( NULL );
  389. }
  390. //
  391. // copy preference
  392. //
  393. precord->Data.MX.wPreference = pRpcRR->Data.MX.wPreference;
  394. //
  395. // write hostname into buffer, immediately following MX struct
  396. //
  397. precord->Data.MX.pNameExchange = (PCHAR)&precord->Data + sizeof( DNS_MX_DATA );
  398. COPY_UTF8_STR_TO_BUFFER(
  399. precord->Data.MX.pNameExchange,
  400. pname->achName,
  401. pname->cchNameLength,
  402. CharSet );
  403. return( precord );
  404. }
  405. PDNS_RECORD
  406. FlatRpcRecordConvert(
  407. IN PDNS_RPC_RECORD pRpcRR,
  408. IN DNS_CHARSET CharSet
  409. )
  410. /*++
  411. Routine Description:
  412. Read memory copy compatible record from wire.
  413. Includes AAAA and WINS types.
  414. Arguments:
  415. pRpcRR - message being read
  416. Return Value:
  417. Ptr to new record if successful.
  418. NULL on failure.
  419. --*/
  420. {
  421. PDNS_RECORD precord;
  422. WORD bufLength;
  423. //
  424. // determine required buffer length and allocate
  425. //
  426. bufLength = pRpcRR->wDataLength;
  427. precord = Dns_AllocateRecord( bufLength );
  428. if ( !precord )
  429. {
  430. return( NULL );
  431. }
  432. //
  433. // copy packet data to record
  434. //
  435. RtlCopyMemory(
  436. & precord->Data,
  437. (PCHAR) &pRpcRR->Data.A,
  438. bufLength );
  439. return( precord );
  440. }
  441. PDNS_RECORD
  442. SrvRpcRecordConvert(
  443. IN PDNS_RPC_RECORD pRpcRR,
  444. IN DNS_CHARSET CharSet
  445. )
  446. /*++
  447. Routine Description:
  448. Read SRV record from wire.
  449. Arguments:
  450. pRpcRR - message being read
  451. Return Value:
  452. Ptr to new record if successful.
  453. NULL on failure.
  454. --*/
  455. {
  456. PDNS_RECORD precord;
  457. PDNS_RPC_NAME pname = &pRpcRR->Data.SRV.nameTarget;
  458. WORD bufLength;
  459. //
  460. // SRV target host is another DNS name
  461. //
  462. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pname) )
  463. {
  464. DNS_ASSERT( FALSE );
  465. return NULL;
  466. }
  467. //
  468. // determine required buffer length and allocate
  469. //
  470. bufLength = sizeof( DNS_SRV_DATA )
  471. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname->cchNameLength, CharSet );
  472. precord = Dns_AllocateRecord( bufLength );
  473. if ( !precord )
  474. {
  475. return( NULL );
  476. }
  477. //
  478. // copy SRV fixed fields
  479. //
  480. precord->Data.SRV.wPriority = pRpcRR->Data.SRV.wPriority;
  481. precord->Data.SRV.wWeight = pRpcRR->Data.SRV.wWeight;
  482. precord->Data.SRV.wPort = pRpcRR->Data.SRV.wPort;
  483. //
  484. // write hostname into buffer, immediately following SRV struct
  485. //
  486. precord->Data.SRV.pNameTarget = (PCHAR)&precord->Data + sizeof( DNS_SRV_DATA );
  487. COPY_UTF8_STR_TO_BUFFER(
  488. precord->Data.SRV.pNameTarget,
  489. pname->achName,
  490. pname->cchNameLength,
  491. CharSet );
  492. return( precord );
  493. }
  494. PDNS_RECORD
  495. NbstatRpcRecordConvert(
  496. IN PDNS_RPC_RECORD pRpcRR,
  497. IN DNS_CHARSET CharSet
  498. )
  499. /*++
  500. Routine Description:
  501. Read WINSR record from wire.
  502. Arguments:
  503. pRpcRR - message being read
  504. Return Value:
  505. Ptr to new record if successful.
  506. NULL on failure.
  507. --*/
  508. {
  509. PDNS_RECORD precord;
  510. PDNS_RPC_NAME pname = &pRpcRR->Data.WINSR.nameResultDomain;
  511. WORD bufLength;
  512. //
  513. // WINSR target host is another DNS name
  514. //
  515. if ( ! DNS_IS_NAME_IN_RECORD(pRpcRR, pname) )
  516. {
  517. DNS_ASSERT( FALSE );
  518. return NULL;
  519. }
  520. //
  521. // determine required buffer length and allocate
  522. //
  523. bufLength = sizeof( DNS_WINSR_DATA )
  524. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname->cchNameLength, CharSet );
  525. precord = Dns_AllocateRecord( bufLength );
  526. if ( !precord )
  527. {
  528. return( NULL );
  529. }
  530. //
  531. // copy WINSR fixed fields
  532. //
  533. precord->Data.WINSR.dwMappingFlag = pRpcRR->Data.WINSR.dwMappingFlag;
  534. precord->Data.WINSR.dwLookupTimeout = pRpcRR->Data.WINSR.dwLookupTimeout;
  535. precord->Data.WINSR.dwCacheTimeout = pRpcRR->Data.WINSR.dwCacheTimeout;
  536. //
  537. // write hostname into buffer, immediately following WINSR struct
  538. //
  539. precord->Data.WINSR.pNameResultDomain
  540. = (PCHAR)&precord->Data + sizeof( DNS_WINSR_DATA );
  541. COPY_UTF8_STR_TO_BUFFER(
  542. precord->Data.WINSR.pNameResultDomain,
  543. pname->achName,
  544. pname->cchNameLength,
  545. CharSet );
  546. return( precord );
  547. }
  548. //
  549. // RR conversion from RPC buffer to DNS_RECORD
  550. //
  551. typedef PDNS_RECORD (* RR_CONVERT_FUNCTION)( PDNS_RPC_RECORD, DNS_CHARSET );
  552. RR_CONVERT_FUNCTION RRRpcConvertTable[] =
  553. {
  554. NULL, // ZERO
  555. ARpcRecordConvert, // A
  556. PtrRpcRecordConvert, // NS
  557. PtrRpcRecordConvert, // MD
  558. PtrRpcRecordConvert, // MF
  559. PtrRpcRecordConvert, // CNAME
  560. SoaRpcRecordConvert, // SOA
  561. PtrRpcRecordConvert, // MB
  562. PtrRpcRecordConvert, // MG
  563. PtrRpcRecordConvert, // MR
  564. NULL, // NULL
  565. FlatRpcRecordConvert, // WKS
  566. PtrRpcRecordConvert, // PTR
  567. TxtRpcRecordConvert, // HINFO
  568. MinfoRpcRecordConvert, // MINFO
  569. MxRpcRecordConvert, // MX
  570. TxtRpcRecordConvert, // TXT
  571. MinfoRpcRecordConvert, // RP
  572. MxRpcRecordConvert, // AFSDB
  573. TxtRpcRecordConvert, // X25
  574. TxtRpcRecordConvert, // ISDN
  575. MxRpcRecordConvert, // RT
  576. NULL, // NSAP
  577. NULL, // NSAPPTR
  578. NULL, // SIG
  579. NULL, // KEY
  580. NULL, // PX
  581. NULL, // GPOS
  582. FlatRpcRecordConvert, // AAAA
  583. NULL, // 29
  584. NULL, // 30
  585. NULL, // 31
  586. NULL, // 32
  587. SrvRpcRecordConvert, // SRV
  588. NULL, // ATMA
  589. NULL, // 35
  590. NULL, // 36
  591. NULL, // 37
  592. NULL, // 38
  593. NULL, // 39
  594. NULL, // 40
  595. NULL, // OPT
  596. NULL, // 42
  597. NULL, // 43
  598. NULL, // 44
  599. NULL, // 45
  600. NULL, // 46
  601. NULL, // 47
  602. NULL, // 48
  603. //
  604. // NOTE: last type indexed by type ID MUST be set
  605. // as MAX_SELF_INDEXED_TYPE #define in record.h
  606. // (see note above in record info table)
  607. // note these follow, but require OFFSET_TO_WINS_RR subtraction
  608. // from actual type value
  609. NULL, // TKEY
  610. NULL, // TSIG
  611. FlatRpcRecordConvert, // WINS
  612. NbstatRpcRecordConvert // WINS-R
  613. };
  614. //
  615. // API for doing conversion
  616. //
  617. PDNS_RECORD
  618. DnsConvertRpcBufferToRecords(
  619. IN PBYTE * ppByte,
  620. IN PBYTE pStopByte,
  621. IN DWORD cRecords,
  622. IN PDNS_NAME pszNodeName,
  623. IN BOOLEAN fUnicode
  624. )
  625. /*++
  626. Routine Description:
  627. Convert RPC buffer records to standard DNS records.
  628. Arguments:
  629. ppByte -- addr of ptr into buffer where records start
  630. pStopByte -- stop byte of buffer
  631. cRecords -- number of records to convert
  632. pszNodeName -- node name (in desired format, not converted)
  633. fUnicode -- flag, write records into unicode
  634. Return Value:
  635. Ptr to new record(s) if successful.
  636. NULL on failure.
  637. --*/
  638. {
  639. PDNS_RPC_RECORD prpcRecord = (PDNS_RPC_RECORD)*ppByte;
  640. PDNS_RECORD precord;
  641. DNS_RRSET rrset;
  642. WORD index;
  643. WORD type;
  644. DNS_CHARSET charSet;
  645. RR_CONVERT_FUNCTION pFunc;
  646. DNS_ASSERT( DNS_IS_DWORD_ALIGNED(prpcRecord) );
  647. IF_DNSDBG( RPC2 )
  648. {
  649. DNS_PRINT((
  650. "Enter DnsConvertRpcBufferToRecords()\n"
  651. "\tpRpcRecord = %p\n"
  652. "\tCount = %d\n"
  653. "\tNodename = %s%S\n",
  654. prpcRecord,
  655. cRecords,
  656. DNSSTRING_UTF8( fUnicode, pszNodeName ),
  657. DNSSTRING_WIDE( fUnicode, pszNodeName ) ));
  658. }
  659. DNS_RRSET_INIT( rrset );
  660. //
  661. // loop until out of nodes
  662. //
  663. while( cRecords-- )
  664. {
  665. if ( (PBYTE)prpcRecord >= pStopByte ||
  666. (PBYTE)&prpcRecord->Data + prpcRecord->wDataLength > pStopByte )
  667. {
  668. DNS_PRINT((
  669. "ERROR: Bogus buffer at %p\n"
  670. "\tRecord leads past buffer end at %p\n"
  671. "\twith %d records remaining.\n",
  672. prpcRecord,
  673. pStopByte,
  674. cRecords+1 ));
  675. DNS_ASSERT( FALSE );
  676. return NULL;
  677. }
  678. //
  679. // convert record
  680. // set unicode flag if converting
  681. //
  682. charSet = DnsCharSetUtf8;
  683. if ( fUnicode )
  684. {
  685. charSet = DnsCharSetUnicode;
  686. }
  687. type = prpcRecord->wType;
  688. index = INDEX_FOR_TYPE( type );
  689. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  690. if ( !index || !(pFunc = RRRpcConvertTable[ index ]) )
  691. {
  692. // if unknown type try flat record copy -- best we can
  693. // do to protect if server added new types since admin built
  694. DNS_PRINT((
  695. "ERROR: no RPC to DNS_RECORD conversion routine for type %d.\n"
  696. "\tusing flat conversion routine.\n",
  697. type ));
  698. pFunc = FlatRpcRecordConvert;
  699. }
  700. precord = (*pFunc)( prpcRecord, charSet );
  701. if ( ! precord )
  702. {
  703. DNS_PRINT((
  704. "ERROR: Record build routine failure for record type %d.\n"
  705. "\tstatus = %p\n\n",
  706. type,
  707. GetLastError() ));
  708. prpcRecord = DNS_GET_NEXT_RPC_RECORD(prpcRecord);
  709. continue;
  710. }
  711. //
  712. // fill out record structure
  713. //
  714. precord->pName = pszNodeName;
  715. precord->wType = type;
  716. RECORD_CHARSET( precord ) = charSet;
  717. //
  718. // DEVNOTE: data types (root hint, glue set)
  719. // - need way to default that works for NT4
  720. // JJW: this is probably an obsolete B*GB*G
  721. //
  722. if ( prpcRecord->dwFlags & DNS_RPC_RECORD_FLAG_CACHE_DATA )
  723. {
  724. precord->Flags.S.Section = DNSREC_CACHE_DATA;
  725. }
  726. else
  727. {
  728. precord->Flags.S.Section = DNSREC_ZONE_DATA;
  729. }
  730. IF_DNSDBG( INIT )
  731. {
  732. DnsDbg_Record(
  733. "New record built\n",
  734. precord );
  735. }
  736. //
  737. // link into RR set
  738. //
  739. DNS_RRSET_ADD( rrset, precord );
  740. prpcRecord = DNS_GET_NEXT_RPC_RECORD(prpcRecord);
  741. }
  742. IF_DNSDBG( RPC2 )
  743. {
  744. DnsDbg_RecordSet(
  745. "Finished DnsConvertRpcBufferToRecords() ",
  746. rrset.pFirstRR );
  747. }
  748. // reset ptr in buffer
  749. *ppByte = (PBYTE) prpcRecord;
  750. return( rrset.pFirstRR );
  751. }
  752. PDNS_NODE
  753. DnsConvertRpcBufferNode(
  754. IN PDNS_RPC_NODE pRpcNode,
  755. IN PBYTE pStopByte,
  756. IN BOOLEAN fUnicode
  757. )
  758. /*++
  759. Routine Description:
  760. Convert RPC buffer records to standard DNS records.
  761. Arguments:
  762. pRpcNode -- ptr to RPC node in buffer
  763. pStopByte -- stop byte of buffer
  764. fUnicode -- flag, write records into unicode
  765. Return Value:
  766. Ptr to new node if successful.
  767. NULL on failure.
  768. --*/
  769. {
  770. PDNS_NODE pnode;
  771. PDNS_RPC_NAME pname;
  772. PBYTE pendNode;
  773. IF_DNSDBG( RPC2 )
  774. {
  775. DnsDbg_RpcNode(
  776. "Enter DnsConvertRpcBufferNode() ",
  777. pRpcNode );
  778. }
  779. //
  780. // validate node
  781. //
  782. DNS_ASSERT( DNS_IS_DWORD_ALIGNED(pRpcNode) );
  783. pendNode = (PBYTE)pRpcNode + pRpcNode->wLength;
  784. if ( pendNode > pStopByte )
  785. {
  786. DNS_ASSERT( FALSE );
  787. return( NULL );
  788. }
  789. pname = &pRpcNode->dnsNodeName;
  790. if ( (PBYTE)DNS_GET_NEXT_NAME(pname) > pendNode )
  791. {
  792. DNS_ASSERT( FALSE );
  793. return( NULL );
  794. }
  795. //
  796. // create node
  797. //
  798. pnode = (PDNS_NODE) ALLOCATE_HEAP( sizeof(DNS_NODE)
  799. + STR_BUF_SIZE_GIVEN_UTF8_LEN( pname->cchNameLength, fUnicode ) );
  800. if ( !pnode )
  801. {
  802. return( NULL );
  803. }
  804. pnode->pNext = NULL;
  805. pnode->pRecord = NULL;
  806. pnode->Flags.W = 0;
  807. //
  808. // copy owner name, starts directly after node structure
  809. //
  810. pnode->pName = (PWCHAR) ((PBYTE)pnode + sizeof(DNS_NODE));
  811. if ( ! Dns_StringCopy(
  812. (PCHAR) pnode->pName,
  813. NULL,
  814. pname->achName,
  815. pname->cchNameLength,
  816. DnsCharSetUtf8, // UTF8 in
  817. fUnicode ? DnsCharSetUnicode : DnsCharSetUtf8
  818. ) )
  819. {
  820. // name conversion error
  821. DNS_ASSERT( FALSE );
  822. FREE_HEAP( pnode );
  823. return( NULL );
  824. }
  825. IF_DNSDBG( RPC2 )
  826. {
  827. DnsDbg_RpcName(
  828. "Node name in RPC buffer: ",
  829. pname,
  830. "\n" );
  831. DnsDbg_String(
  832. "Converted name ",
  833. (PCHAR) pnode->pName,
  834. fUnicode,
  835. "\n" );
  836. }
  837. //
  838. // set flags
  839. // - name always internal
  840. // - catch domain roots
  841. //
  842. pnode->Flags.S.Unicode = fUnicode;
  843. if ( pRpcNode->dwChildCount ||
  844. (pRpcNode->dwFlags & DNS_RPC_NODE_FLAG_STICKY) )
  845. {
  846. pnode->Flags.S.Domain = TRUE;
  847. }
  848. IF_DNSDBG( RPC2 )
  849. {
  850. DnsDbg_Node(
  851. "Finished DnsConvertRpcBufferNode() ",
  852. pnode,
  853. TRUE // view the records
  854. );
  855. }
  856. return( pnode );
  857. }
  858. PDNS_NODE
  859. DnsConvertRpcBuffer(
  860. OUT PDNS_NODE * ppNodeLast,
  861. IN DWORD dwBufferLength,
  862. IN BYTE abBuffer[],
  863. IN BOOLEAN fUnicode
  864. )
  865. {
  866. PBYTE pbyte;
  867. PBYTE pstopByte;
  868. INT countRecords;
  869. PDNS_NODE pnode;
  870. PDNS_NODE pnodeFirst = NULL;
  871. PDNS_NODE pnodeLast = NULL;
  872. PDNS_RECORD precord;
  873. IF_DNSDBG( RPC2 )
  874. {
  875. DNS_PRINT((
  876. "DnsConvertRpcBuffer( %p ), len = %d\n",
  877. abBuffer,
  878. dwBufferLength ));
  879. }
  880. //
  881. // find stop byte
  882. //
  883. DNS_ASSERT( DNS_IS_DWORD_ALIGNED(abBuffer) );
  884. pstopByte = abBuffer + dwBufferLength;
  885. pbyte = abBuffer;
  886. //
  887. // loop until out of nodes
  888. //
  889. while( pbyte < pstopByte )
  890. {
  891. //
  892. // build owner node
  893. // - only build complete nodes
  894. // - add to list
  895. //
  896. if ( !IS_COMPLETE_NODE( (PDNS_RPC_NODE)pbyte ) )
  897. {
  898. break;
  899. }
  900. pnode = DnsConvertRpcBufferNode(
  901. (PDNS_RPC_NODE)pbyte,
  902. pstopByte,
  903. fUnicode );
  904. if ( !pnode )
  905. {
  906. DNS_ASSERT( FALSE );
  907. // DEVNOTE: cleanup
  908. return( NULL );
  909. }
  910. if ( !pnodeFirst )
  911. {
  912. pnodeFirst = pnode;
  913. pnodeLast = pnode;
  914. }
  915. else
  916. {
  917. pnodeLast->pNext = pnode;
  918. pnodeLast = pnode;
  919. }
  920. countRecords = ((PDNS_RPC_NODE)pbyte)->wRecordCount;
  921. pbyte += ((PDNS_RPC_NODE)pbyte)->wLength;
  922. pbyte = DNS_NEXT_DWORD_PTR(pbyte);
  923. //
  924. // for each node, build all records
  925. //
  926. if ( countRecords )
  927. {
  928. precord = DnsConvertRpcBufferToRecords(
  929. & pbyte,
  930. pstopByte,
  931. countRecords,
  932. (PCHAR) pnode->pName,
  933. fUnicode );
  934. if ( !precord )
  935. {
  936. DNS_ASSERT( FALSE );
  937. }
  938. pnode->pRecord = precord;
  939. }
  940. }
  941. // set last node and return first node
  942. *ppNodeLast = pnodeLast;
  943. return( pnodeFirst );
  944. }
  945. //
  946. // End rconvert.c
  947. //