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.

887 lines
19 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. dconvert.c
  5. Abstract:
  6. Domain Name System (DNS) Server -- Admin Client Library
  7. RPC record conversion routines.
  8. Convert DNS_RECORD records into RPC buffer.
  9. Author:
  10. Jing Chen (t-jingc) June, 1998
  11. reverse functions of rconvert.c
  12. Revision History:
  13. --*/
  14. #include "dnsclip.h"
  15. //
  16. // size of string in RPC format
  17. //
  18. #define STRING_UTF8_BUF_SIZE( string, fUnicode ) \
  19. Dns_GetBufferLengthForStringCopy( \
  20. (string), \
  21. 0, \
  22. ((fUnicode) ? DnsCharSetUnicode : DnsCharSetUtf8), \
  23. DnsCharSetUtf8 )
  24. //
  25. // Writing strings to RPC buffer format
  26. //
  27. #define WRITE_STRING_TO_RPC_BUF(buf, psz, len, funicode) \
  28. Dns_StringCopy( \
  29. (buf), \
  30. NULL, \
  31. (psz), \
  32. (len), \
  33. ((funicode) ? DnsCharSetUnicode : DnsCharSetUtf8), \
  34. DnsCharSetUtf8 )
  35. //
  36. // size of name in RPC format
  37. //
  38. #define NAME_UTF8_BUF_SIZE( string, fUnicode ) \
  39. Dns_GetBufferLengthForStringCopy( \
  40. (string), \
  41. 0, \
  42. ((fUnicode) ? DnsCharSetUnicode : DnsCharSetUtf8), \
  43. DnsCharSetUtf8 )
  44. //
  45. // Writing names to RPC buffer format
  46. //
  47. #define WRITE_NAME_TO_RPC_BUF(buf, psz, len, funicode) \
  48. Dns_StringCopy( \
  49. (buf), \
  50. NULL, \
  51. (psz), \
  52. (len), \
  53. ((funicode) ? DnsCharSetUnicode : DnsCharSetUtf8), \
  54. DnsCharSetUtf8 )
  55. //
  56. // Private protos
  57. //
  58. PDNS_RPC_RECORD
  59. Rpc_AllocateRecord(
  60. IN DWORD BufferLength
  61. );
  62. //
  63. // RPC buffer conversion functions
  64. //
  65. PDNS_RPC_RECORD
  66. ADnsRecordConvert(
  67. IN PDNS_RECORD pRR
  68. )
  69. /*++
  70. Routine Description:
  71. Convert A record from DNS Record to RPC buffer.
  72. Arguments:
  73. pRR - record being read
  74. Return Value:
  75. Ptr to new RPC buffer if successful.
  76. NULL on failure.
  77. --*/
  78. {
  79. PDNS_RPC_RECORD prpcRR;
  80. DNS_ASSERT( pRR->wDataLength == sizeof(IP_ADDRESS) );
  81. prpcRR = Rpc_AllocateRecord( sizeof(IP_ADDRESS) );
  82. if ( !prpcRR )
  83. {
  84. return NULL;
  85. }
  86. prpcRR->Data.A.ipAddress = pRR->Data.A.IpAddress;
  87. return prpcRR;
  88. }
  89. PDNS_RPC_RECORD
  90. PtrDnsRecordConvert(
  91. IN PDNS_RECORD pRR
  92. )
  93. /*++
  94. Routine Description:
  95. Process PTR compatible record from wire.
  96. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
  97. Arguments:
  98. pRR - record being read
  99. Return Value:
  100. Ptr to new RPC buffer if successful.
  101. NULL on failure.
  102. --*/
  103. {
  104. PDNS_RPC_RECORD prpcRR;
  105. DWORD length;
  106. BOOL funicode = IS_UNICODE_RECORD( pRR );
  107. //
  108. // PTR data is another domain name
  109. //
  110. // determine required buffer length and allocate
  111. //
  112. length = NAME_UTF8_BUF_SIZE(pRR->Data.PTR.pNameHost, funicode);
  113. prpcRR = Rpc_AllocateRecord( sizeof(DNS_RPC_NAME) + length );
  114. if ( !prpcRR )
  115. {
  116. return NULL;
  117. }
  118. //
  119. // write hostname into buffer, immediately following PTR data struct
  120. //
  121. prpcRR->Data.PTR.nameNode.cchNameLength = (UCHAR)length;
  122. WRITE_NAME_TO_RPC_BUF(
  123. prpcRR->Data.PTR.nameNode.achName, // buffer
  124. pRR->Data.PTR.pNameHost,
  125. 0,
  126. funicode );
  127. return prpcRR;
  128. }
  129. PDNS_RPC_RECORD
  130. SoaDnsRecordConvert(
  131. IN PDNS_RECORD pRR
  132. )
  133. /*++
  134. Routine Description:
  135. Convert SOA record from DNS Record to RPC buffer.
  136. Arguments:
  137. pRR - ptr to record being read
  138. Return Value:
  139. Ptr to new RPC buffer if successful.
  140. NULL on failure.
  141. --*/
  142. {
  143. PDNS_RPC_RECORD prpcRR;
  144. DWORD length1;
  145. DWORD length2;
  146. PDNS_RPC_NAME pnamePrimary;
  147. PDNS_RPC_NAME pnameAdmin;
  148. BOOL funicode = IS_UNICODE_RECORD( pRR );
  149. //
  150. // determine required buffer length and allocate
  151. //
  152. length1 = NAME_UTF8_BUF_SIZE( pRR->Data.SOA.pNamePrimaryServer, funicode );
  153. length2 = NAME_UTF8_BUF_SIZE( pRR->Data.SOA.pNameAdministrator, funicode );
  154. prpcRR = Rpc_AllocateRecord(
  155. SIZEOF_SOA_FIXED_DATA + sizeof(DNS_RPC_NAME) * 2 +
  156. length1 + length2 );
  157. if ( !prpcRR )
  158. {
  159. return NULL;
  160. }
  161. //
  162. // copy fixed fields
  163. //
  164. RtlCopyMemory(
  165. (PCHAR) & prpcRR->Data.SOA.dwSerialNo,
  166. (PCHAR) & pRR->Data.SOA.dwSerialNo,
  167. SIZEOF_SOA_FIXED_DATA );
  168. //
  169. // copy names into RR buffer
  170. // - primary server immediately follows SOA data struct
  171. // - responsible party follows primary server
  172. //
  173. pnamePrimary = &prpcRR->Data.SOA.namePrimaryServer;
  174. pnamePrimary->cchNameLength = (UCHAR) length1;
  175. pnameAdmin = DNS_GET_NEXT_NAME( pnamePrimary );
  176. pnameAdmin->cchNameLength = (UCHAR) length2;
  177. WRITE_NAME_TO_RPC_BUF(
  178. pnamePrimary->achName,
  179. pRR->Data.Soa.pNamePrimaryServer,
  180. 0,
  181. funicode );
  182. WRITE_NAME_TO_RPC_BUF(
  183. pnameAdmin->achName,
  184. pRR->Data.Soa.pNameAdministrator,
  185. 0,
  186. funicode );
  187. return prpcRR;
  188. }
  189. PDNS_RPC_RECORD
  190. TxtDnsRecordConvert(
  191. IN PDNS_RECORD pRR
  192. )
  193. /*++
  194. Routine Description:
  195. Read TXT compatible record from wire.
  196. Includes: TXT, X25, HINFO, ISDN
  197. Arguments:
  198. pRR - record being read
  199. Return Value:
  200. Ptr to new RPC buffer if successful.
  201. NULL on failure.
  202. --*/
  203. {
  204. PDNS_RPC_RECORD prpcRR;
  205. DWORD bufLength;
  206. DWORD length;
  207. INT count;
  208. PCHAR pch;
  209. PCHAR * ppstring;
  210. BOOL funicode = IS_UNICODE_RECORD( pRR );
  211. //
  212. // determine required buffer length and allocate
  213. // - allocate space for each string
  214. // - and ptr for each string
  215. //
  216. bufLength = 0;
  217. count = pRR->Data.TXT.dwStringCount;
  218. ppstring = pRR->Data.TXT.pStringArray;
  219. while ( count-- )
  220. {
  221. length = STRING_UTF8_BUF_SIZE( *ppstring++, funicode );
  222. bufLength += sizeof(DNS_RPC_NAME) + length;
  223. }
  224. // allocate
  225. prpcRR = Rpc_AllocateRecord( bufLength );
  226. if ( !prpcRR )
  227. {
  228. return NULL;
  229. }
  230. //
  231. // go back through list copying strings to buffer
  232. // - ptrs to strings are saved to argv like data section
  233. // ppstring walks through this section
  234. // - first string written immediately following data section
  235. // - each subsequent string immediately follows predecessor
  236. // pchbuffer keeps ptr to position to write strings
  237. //
  238. // JBUGBUG: a mess
  239. //
  240. pch = (PCHAR) &prpcRR->Data.TXT;
  241. ppstring = pRR->Data.TXT.pStringArray;
  242. count = pRR->Data.TXT.dwStringCount;
  243. while ( count-- )
  244. {
  245. length = STRING_UTF8_BUF_SIZE( *ppstring, funicode );
  246. (UCHAR) *pch++ += (UCHAR) length; //+1 for TXT type only
  247. length = WRITE_STRING_TO_RPC_BUF(
  248. pch,
  249. *ppstring++,
  250. 0,
  251. funicode );
  252. pch += length;
  253. #if DBG
  254. DNS_PRINT((
  255. "Read text string %s\n",
  256. * (ppstring - 1) ));
  257. #endif
  258. }
  259. return prpcRR;
  260. }
  261. PDNS_RPC_RECORD
  262. MinfoDnsRecordConvert(
  263. IN PDNS_RECORD pRR
  264. )
  265. /*++
  266. Routine Description:
  267. Read MINFO record from wire.
  268. Arguments:
  269. pRR - record being read
  270. Return Value:
  271. Ptr to new RPC buffer if successful.
  272. NULL on failure.
  273. --*/
  274. {
  275. PDNS_RPC_RECORD prpcRR;
  276. DWORD length1;
  277. DWORD length2;
  278. PDNS_RPC_NAME prpcName1;
  279. PDNS_RPC_NAME prpcName2;
  280. BOOL funicode = IS_UNICODE_RECORD( pRR );
  281. //
  282. // determine required buffer length and allocate
  283. //
  284. length1 = NAME_UTF8_BUF_SIZE( pRR->Data.MINFO.pNameMailbox, funicode );
  285. length2 = NAME_UTF8_BUF_SIZE( pRR->Data.MINFO.pNameErrorsMailbox, funicode );
  286. prpcRR = Rpc_AllocateRecord( sizeof(DNS_RPC_NAME) * 2 + length1 + length2 );
  287. if ( !prpcRR )
  288. {
  289. return NULL;
  290. }
  291. //
  292. // copy names into RR buffer
  293. // - mailbox immediately follows MINFO data struct
  294. // - errors mailbox immediately follows primary server
  295. //
  296. prpcName1 = &prpcRR->Data.MINFO.nameMailBox;
  297. prpcName1->cchNameLength = (UCHAR) length1;
  298. prpcName2 = DNS_GET_NEXT_NAME( prpcName1);
  299. prpcName2->cchNameLength = (UCHAR) length2;
  300. WRITE_NAME_TO_RPC_BUF(
  301. prpcName1->achName,
  302. pRR->Data.MINFO.pNameMailbox,
  303. 0,
  304. funicode );
  305. WRITE_NAME_TO_RPC_BUF(
  306. prpcName2->achName,
  307. pRR->Data.MINFO.pNameErrorsMailbox,
  308. 0,
  309. funicode );
  310. return prpcRR;
  311. }
  312. PDNS_RPC_RECORD
  313. MxDnsRecordConvert(
  314. IN PDNS_RECORD pRR
  315. )
  316. /*++
  317. Routine Description:
  318. convert MX compatible record.
  319. Includes: MX, RT, AFSDB
  320. Arguments:
  321. pRR - record being read
  322. Return Value:
  323. Ptr to new RPC buffer if successful.
  324. NULL on failure.
  325. --*/
  326. {
  327. PDNS_RPC_RECORD prpcRR;
  328. PDNS_RPC_NAME prpcName;
  329. DWORD length;
  330. BOOL funicode = IS_UNICODE_RECORD( pRR );
  331. //
  332. // determine required buffer length and allocate
  333. //
  334. length = NAME_UTF8_BUF_SIZE( pRR->Data.MX.pNameExchange, funicode );
  335. prpcRR = Rpc_AllocateRecord(
  336. SIZEOF_MX_FIXED_DATA + sizeof(DNS_RPC_NAME) + length );
  337. if ( !prpcRR )
  338. {
  339. return NULL;
  340. }
  341. //
  342. // copy preference
  343. //
  344. prpcRR->Data.MX.wPreference = pRR->Data.MX.wPreference;
  345. //
  346. // write hostname into buffer, immediately following MX struct
  347. //
  348. prpcName = &prpcRR->Data.MX.nameExchange;
  349. prpcName->cchNameLength = (UCHAR) length;
  350. WRITE_NAME_TO_RPC_BUF(
  351. prpcName->achName,
  352. pRR->Data.MX.pNameExchange,
  353. 0,
  354. funicode );
  355. return prpcRR;
  356. }
  357. PDNS_RPC_RECORD
  358. FlatDnsRecordConvert(
  359. IN PDNS_RECORD pRR
  360. )
  361. /*++
  362. Routine Description:
  363. Convert memory copy compatible record.
  364. Includes AAAA and WINS types.
  365. Arguments:
  366. pRR - record being read
  367. Return Value:
  368. Ptr to new RPC buffer if successful.
  369. NULL on failure.
  370. --*/
  371. {
  372. PDNS_RPC_RECORD prpcRR;
  373. DWORD bufLength;
  374. //
  375. // determine required buffer length and allocate
  376. //
  377. bufLength = pRR->wDataLength;
  378. prpcRR = Rpc_AllocateRecord( bufLength );
  379. if ( !prpcRR )
  380. {
  381. return NULL;
  382. }
  383. //
  384. // copy packet data to record
  385. //
  386. RtlCopyMemory(
  387. & prpcRR->Data,
  388. & pRR->Data,
  389. bufLength );
  390. return prpcRR;
  391. }
  392. PDNS_RPC_RECORD
  393. SrvDnsRecordConvert(
  394. IN PDNS_RECORD pRR
  395. )
  396. /*++
  397. Routine Description:
  398. convert SRV record.
  399. Arguments:
  400. pRR - record being read
  401. Return Value:
  402. Ptr to new RPC buffer if successful.
  403. NULL on failure.
  404. --*/
  405. {
  406. PDNS_RPC_RECORD prpcRR;
  407. PDNS_RPC_NAME prpcName;
  408. DWORD length;
  409. BOOL funicode = IS_UNICODE_RECORD( pRR );
  410. //
  411. // determine required buffer length and allocate
  412. //
  413. length = NAME_UTF8_BUF_SIZE( pRR->Data.SRV.pNameTarget, funicode );
  414. prpcRR = Rpc_AllocateRecord(
  415. SIZEOF_SRV_FIXED_DATA + sizeof(DNS_RPC_NAME) + length );
  416. if ( !prpcRR )
  417. {
  418. return NULL;
  419. }
  420. //
  421. // copy SRV fixed fields
  422. //
  423. prpcRR->Data.SRV.wPriority = pRR->Data.SRV.wPriority;
  424. prpcRR->Data.SRV.wWeight = pRR->Data.SRV.wWeight;
  425. prpcRR->Data.SRV.wPort = pRR->Data.SRV.wPort;
  426. //
  427. // write hostname into buffer, immediately following SRV struct
  428. //
  429. prpcName = &prpcRR->Data.SRV.nameTarget;
  430. prpcName->cchNameLength = (UCHAR) length;
  431. WRITE_NAME_TO_RPC_BUF(
  432. prpcName->achName,
  433. pRR->Data.SRV.pNameTarget,
  434. 0,
  435. funicode );
  436. return prpcRR;
  437. }
  438. PDNS_RPC_RECORD
  439. NbstatDnsRecordConvert(
  440. IN PDNS_RECORD pRR
  441. )
  442. /*++
  443. Routine Description:
  444. Read WINSR record from wire.
  445. Arguments:
  446. pRR - record being read
  447. Return Value:
  448. Ptr to new RPC buffer if successful.
  449. NULL on failure.
  450. --*/
  451. {
  452. PDNS_RPC_RECORD prpcRR;
  453. PDNS_RPC_NAME prpcName;
  454. DWORD length;
  455. BOOL funicode = IS_UNICODE_RECORD( pRR );
  456. //
  457. // determine required buffer length and allocate
  458. //
  459. length = NAME_UTF8_BUF_SIZE( pRR->Data.WINSR.pNameResultDomain, funicode );
  460. prpcRR = Rpc_AllocateRecord(
  461. SIZEOF_NBSTAT_FIXED_DATA + sizeof(DNS_RPC_NAME) + length );
  462. if ( !prpcRR )
  463. {
  464. return NULL;
  465. }
  466. //
  467. // copy WINSR fixed fields
  468. //
  469. prpcRR->Data.WINSR.dwMappingFlag = pRR->Data.WINSR.dwMappingFlag;
  470. prpcRR->Data.WINSR.dwLookupTimeout = pRR->Data.WINSR.dwLookupTimeout;
  471. prpcRR->Data.WINSR.dwCacheTimeout = pRR->Data.WINSR.dwCacheTimeout;
  472. //
  473. // write hostname into buffer, immediately following WINSR struct
  474. //
  475. prpcName = &prpcRR->Data.WINSR.nameResultDomain;
  476. prpcName->cchNameLength = (UCHAR) length;
  477. WRITE_NAME_TO_RPC_BUF(
  478. prpcName->achName,
  479. pRR->Data.WINSR.pNameResultDomain,
  480. 0,
  481. funicode );
  482. return prpcRR;
  483. }
  484. //
  485. // Jump table for DNS_RECORD => RPC buffer conversion.
  486. //
  487. typedef PDNS_RPC_RECORD (* RECORD_TO_RPC_CONVERT_FUNCTION)( PDNS_RECORD );
  488. RECORD_TO_RPC_CONVERT_FUNCTION RecordToRpcConvertTable[] =
  489. {
  490. NULL, // ZERO
  491. ADnsRecordConvert, // A
  492. PtrDnsRecordConvert, // NS
  493. PtrDnsRecordConvert, // MD
  494. PtrDnsRecordConvert, // MF
  495. PtrDnsRecordConvert, // CNAME
  496. SoaDnsRecordConvert, // SOA
  497. PtrDnsRecordConvert, // MB
  498. PtrDnsRecordConvert, // MG
  499. PtrDnsRecordConvert, // MR
  500. NULL, // NULL
  501. FlatDnsRecordConvert, // WKS
  502. PtrDnsRecordConvert, // PTR
  503. TxtDnsRecordConvert, // HINFO
  504. MinfoDnsRecordConvert, // MINFO
  505. MxDnsRecordConvert, // MX
  506. TxtDnsRecordConvert, // TXT
  507. MinfoDnsRecordConvert, // RP
  508. MxDnsRecordConvert, // AFSDB
  509. TxtDnsRecordConvert, // X25
  510. TxtDnsRecordConvert, // ISDN
  511. MxDnsRecordConvert, // RT
  512. NULL, // NSAP
  513. NULL, // NSAPPTR
  514. NULL, // SIG
  515. NULL, // KEY
  516. NULL, // PX
  517. NULL, // GPOS
  518. FlatDnsRecordConvert, // AAAA
  519. NULL, // 29
  520. NULL, // 30
  521. NULL, // 31
  522. NULL, // 32
  523. SrvDnsRecordConvert, // SRV
  524. //
  525. // NOTE: last type indexed by type ID MUST be set
  526. // as MAX_SELF_INDEXED_TYPE #define in record.h
  527. // (see note above in record info table)
  528. // note these follow, but require OFFSET_TO_WINS_RR subtraction
  529. // from actual type value
  530. NULL, // DNS_TYPE_ATMA
  531. NULL, // 0x0023
  532. NULL, // 0x0024
  533. NULL, // 0x0025
  534. NULL, // 0x0026
  535. NULL, // 0x0027
  536. NULL, // 0x0028
  537. NULL, // DNS_TYPE_TKEY
  538. NULL, // DNS_TYPE_TSIG
  539. FlatDnsRecordConvert, // WINS
  540. NbstatDnsRecordConvert // WINS-R
  541. };
  542. PDNS_RPC_RECORD
  543. Rpc_AllocateRecord(
  544. IN DWORD BufferLength
  545. )
  546. /*++
  547. Routine Description:
  548. Allocate RPC record structure.
  549. Arguments:
  550. wBufferLength - desired buffer length (beyond structure header)
  551. Return Value:
  552. Ptr to buffer.
  553. NULL on error.
  554. --*/
  555. {
  556. PDNS_RPC_RECORD prr;
  557. if ( BufferLength > MAXWORD )
  558. {
  559. return NULL;
  560. }
  561. prr = ALLOCATE_HEAP( SIZEOF_DNS_RPC_RECORD_HEADER + BufferLength );
  562. if ( !prr )
  563. {
  564. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  565. return NULL;
  566. }
  567. // set datalength to buffer length
  568. prr->wDataLength = (WORD) BufferLength;
  569. return( prr );
  570. }
  571. PDNS_RPC_RECORD
  572. DnsConvertRecordToRpcBuffer(
  573. IN PDNS_RECORD pRecord
  574. )
  575. /*++
  576. Routine Description:
  577. Convert standard DNS record to RPC buffer.
  578. Arguments:
  579. pRecord -- DNS Record to be converted.
  580. //fUnicode -- flag, write records into unicode
  581. Return Value:
  582. Ptr to new RPC buffer if successful.
  583. NULL on failure.
  584. --*/
  585. {
  586. PDNS_RPC_RECORD prpcRecord;
  587. WORD index;
  588. WORD type;
  589. RECORD_TO_RPC_CONVERT_FUNCTION pFunc;
  590. DNS_ASSERT( DNS_IS_DWORD_ALIGNED(pRecord) );
  591. IF_DNSDBG( RPC2 )
  592. {
  593. DNS_PRINT((
  594. "Enter DnsConvertRecordToRpcBuffer()\n"
  595. " pRecord = %p\n",
  596. pRecord ));
  597. }
  598. //
  599. // convert record
  600. // set unicode flag if converting
  601. //
  602. type = pRecord->wType;
  603. index = INDEX_FOR_TYPE( type );
  604. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  605. if ( !index || !(pFunc = RecordToRpcConvertTable[ index ]) )
  606. {
  607. // if unknown type try flat record copy -- best we can
  608. // do to protect if server added new types since admin built
  609. DNS_PRINT((
  610. "ERROR: no DNS_RECORD to RPC conversion routine for type %d.\n"
  611. " using flat conversion routine.\n",
  612. type ));
  613. pFunc = FlatDnsRecordConvert;
  614. }
  615. prpcRecord = (*pFunc)( pRecord );
  616. if ( ! prpcRecord )
  617. {
  618. DNS_PRINT((
  619. "ERROR: Record build routine failure for record type %d.\n"
  620. " status = %p\n\n",
  621. type,
  622. GetLastError() ));
  623. return NULL;
  624. }
  625. //
  626. // fill out record structure
  627. //
  628. prpcRecord->wType = type;
  629. prpcRecord->dwTtlSeconds = pRecord->dwTtl;
  630. IF_DNSDBG( INIT )
  631. {
  632. DNS_PRINT(( "New RPC buffer built\n" ));
  633. }
  634. IF_DNSDBG( RPC2 )
  635. {
  636. DNS_PRINT((
  637. "Finished DnsConvertRpcBufferToRecords()" ));
  638. }
  639. return prpcRecord;
  640. }
  641. //
  642. // End dconvert.c
  643. //