Leaked source code of windows server 2003
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.

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