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.

866 lines
17 KiB

  1. /*++
  2. Copyright (c) 2001-2001 Microsoft Corporation
  3. Module Name:
  4. rrstrw.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Record to string routines.
  8. Author:
  9. Jim Gilroy (jamesg) October 2001
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. //
  14. // Min string lengths
  15. // - in chars
  16. // - includes spacing and terminating NULL
  17. // - excludes name lengths
  18. // - they are "rough" lengths
  19. //
  20. #define MIN_SRV_STRING_LENGTH (20) // 3*5u
  21. #define MIN_MX_STRING_LENGTH (10) // 1*5u
  22. #define MIN_SOA_STRING_LENGTH (60) // 5*10u
  23. #define MIN_NAME_LENGTH (3) // space, name, NULL
  24. //
  25. // String writing context
  26. //
  27. // Blob to pass through write routines to preserve extensibility.
  28. // For name\string writing must have access to record charset
  29. // (so need record). If we ever want to use in context of
  30. // zone file writing then would need zone context info.
  31. //
  32. typedef struct _RecordStringWriteContext
  33. {
  34. PDNS_RECORD pRecord;
  35. PSTR pZoneName;
  36. DWORD Flags;
  37. DNS_CHARSET CharSet;
  38. }
  39. STR_WRITE_CONTEXT, *PSTR_WRITE_CONTEXT;
  40. //
  41. // Private prototypes
  42. //
  43. //
  44. // Record to string utilities
  45. //
  46. PCHAR
  47. WriteRecordDataNameToString(
  48. IN OUT PCHAR pBuf,
  49. IN PCHAR pBufEnd,
  50. IN PCHAR pString,
  51. IN PSTR_WRITE_CONTEXT pContext
  52. )
  53. /*++
  54. Routine Description:
  55. Write record name\string to string.
  56. Arguments:
  57. pBuf - position in to write record
  58. pBufEnd - end of buffer
  59. pString - record name\string
  60. pContext - write context
  61. Return Value:
  62. Ptr to next location in buffer.
  63. NULL if out of space in buffer.
  64. --*/
  65. {
  66. DWORD count;
  67. DWORD length = (DWORD) (pBufEnd - pBuf);
  68. count = Dns_StringCopy(
  69. pBuf,
  70. & length,
  71. pString,
  72. 0, // string length unknown
  73. RECORD_CHARSET( pContext->pRecord ),
  74. pContext->CharSet
  75. );
  76. if ( count )
  77. {
  78. return pBuf+count-1;
  79. }
  80. else
  81. {
  82. return NULL;
  83. }
  84. }
  85. //
  86. // Record to string type specific functions
  87. //
  88. PCHAR
  89. A_StringWrite(
  90. IN PDNS_RECORD pRR,
  91. IN OUT PCHAR pBuf,
  92. IN PCHAR pBufEnd,
  93. IN PVOID pContext
  94. )
  95. /*++
  96. Routine Description:
  97. Write A record.
  98. Arguments:
  99. pRR - ptr to database record
  100. pBuf - position in to write record
  101. pBufEnd - end of buffer
  102. pContext - write context
  103. Return Value:
  104. Ptr to next location in buffer.
  105. NULL if out of space in buffer.
  106. --*/
  107. {
  108. //if ( pRecord->wDataLength != sizeof(IP_ADDRESS) )
  109. //{
  110. // return NULL;
  111. //}
  112. if ( pBufEnd - pBuf < IP4_ADDRESS_STRING_BUFFER_LENGTH )
  113. {
  114. return NULL;
  115. }
  116. pBuf += sprintf(
  117. pBuf,
  118. "%d.%d.%d.%d",
  119. * ( (PUCHAR) &(pRR->Data.A) + 0 ),
  120. * ( (PUCHAR) &(pRR->Data.A) + 1 ),
  121. * ( (PUCHAR) &(pRR->Data.A) + 2 ),
  122. * ( (PUCHAR) &(pRR->Data.A) + 3 )
  123. );
  124. return( pBuf );
  125. }
  126. PCHAR
  127. Aaaa_StringWrite(
  128. IN PDNS_RECORD pRR,
  129. IN OUT PCHAR pBuf,
  130. IN PCHAR pBufEnd,
  131. IN PVOID pContext
  132. )
  133. /*++
  134. Routine Description:
  135. Write AAAA record.
  136. Arguments:
  137. pRR - ptr to database record
  138. pBuf - position in to write record
  139. pBufEnd - end of buffer
  140. pContext - write context
  141. Return Value:
  142. Ptr to next location in buffer.
  143. NULL if out of space in buffer.
  144. --*/
  145. {
  146. if ( pBufEnd - pBuf < IP6_ADDRESS_STRING_BUFFER_LENGTH )
  147. {
  148. return NULL;
  149. }
  150. pBuf = Dns_Ip6AddressToString_A(
  151. pBuf,
  152. & pRR->Data.AAAA.Ip6Address );
  153. ASSERT( pBuf );
  154. return( pBuf );
  155. }
  156. PCHAR
  157. Ptr_StringWrite(
  158. IN PDNS_RECORD pRR,
  159. IN OUT PCHAR pBuf,
  160. IN PCHAR pBufEnd,
  161. IN PVOID pContext
  162. )
  163. /*++
  164. Routine Description:
  165. Write PTR compatible record.
  166. Includes: PTR, NS, CNAME, MB, MR, MG, MD, MF
  167. Arguments:
  168. pRR - ptr to database record
  169. pBuf - position in to write record
  170. pBufEnd - end of buffer
  171. pContext - write context
  172. Return Value:
  173. Ptr to next location in buffer.
  174. NULL if out of space in buffer.
  175. --*/
  176. {
  177. // target host
  178. return WriteRecordDataNameToString(
  179. pBuf,
  180. pBufEnd,
  181. pRR->Data.PTR.pNameHost,
  182. pContext );
  183. }
  184. PCHAR
  185. Mx_StringWrite(
  186. IN PDNS_RECORD pRR,
  187. IN OUT PCHAR pBuf,
  188. IN PCHAR pBufEnd,
  189. IN PVOID pContext
  190. )
  191. /*++
  192. Routine Description:
  193. Write SRV record.
  194. Arguments:
  195. pRR - ptr to database record
  196. pBuf - position in to write record
  197. pBufEnd - end of buffer
  198. pContext - write context
  199. Return Value:
  200. Ptr to next location in buffer.
  201. NULL if out of space in buffer.
  202. --*/
  203. {
  204. // fixed fields
  205. if ( pBufEnd - pBuf < 7 )
  206. {
  207. return NULL;
  208. }
  209. pBuf += sprintf(
  210. pBuf,
  211. "%d ",
  212. pRR->Data.MX.wPreference
  213. );
  214. // target host
  215. return WriteRecordDataNameToString(
  216. pBuf,
  217. pBufEnd,
  218. pRR->Data.MX.pNameExchange,
  219. pContext );
  220. }
  221. PCHAR
  222. Srv_StringWrite(
  223. IN PDNS_RECORD pRR,
  224. IN OUT PCHAR pBuf,
  225. IN PCHAR pBufEnd,
  226. IN PVOID pContext
  227. )
  228. /*++
  229. Routine Description:
  230. Write SRV record.
  231. Arguments:
  232. pRR - ptr to database record
  233. pBuf - position in to write record
  234. pBufEnd - end of buffer
  235. pContext - write context
  236. Return Value:
  237. Ptr to next location in buffer.
  238. NULL if out of space in buffer.
  239. --*/
  240. {
  241. // fixed fields
  242. if ( pBufEnd - pBuf < MIN_SRV_STRING_LENGTH )
  243. {
  244. return NULL;
  245. }
  246. pBuf += sprintf(
  247. pBuf,
  248. "%d %d %d ",
  249. pRR->Data.SRV.wPriority,
  250. pRR->Data.SRV.wWeight,
  251. pRR->Data.SRV.wPort
  252. );
  253. // target host
  254. return WriteRecordDataNameToString(
  255. pBuf,
  256. pBufEnd,
  257. pRR->Data.SRV.pNameTarget,
  258. pContext );
  259. }
  260. PCHAR
  261. Soa_StringWrite(
  262. IN PDNS_RECORD pRR,
  263. IN OUT PCHAR pBuf,
  264. IN PCHAR pBufEnd,
  265. IN PVOID pContext
  266. )
  267. /*++
  268. Routine Description:
  269. Write SOA record.
  270. Arguments:
  271. pRR - ptr to database record
  272. pBuf - position in to write record
  273. pBufEnd - end of buffer
  274. pContext - write context
  275. Return Value:
  276. Ptr to next location in buffer.
  277. NULL if out of space in buffer.
  278. --*/
  279. {
  280. // primary server
  281. pBuf = WriteRecordDataNameToString(
  282. pBuf,
  283. pBufEnd,
  284. pRR->Data.SOA.pNamePrimaryServer,
  285. pContext );
  286. if ( !pBuf ||
  287. pBufEnd - pBuf < MIN_SOA_STRING_LENGTH )
  288. {
  289. return NULL;
  290. }
  291. // admin
  292. pBuf += sprintf( pBuf, " " );
  293. pBuf = WriteRecordDataNameToString(
  294. pBuf,
  295. pBufEnd,
  296. pRR->Data.SOA.pNameAdministrator,
  297. pContext );
  298. if ( !pBuf ||
  299. pBufEnd - pBuf < MIN_SOA_STRING_LENGTH )
  300. {
  301. return NULL;
  302. }
  303. // fixed fields
  304. pBuf += sprintf(
  305. pBuf,
  306. " %u %u %u %u %u",
  307. pRR->Data.SOA.dwSerialNo,
  308. pRR->Data.SOA.dwRefresh,
  309. pRR->Data.SOA.dwRetry,
  310. pRR->Data.SOA.dwExpire,
  311. pRR->Data.SOA.dwDefaultTtl
  312. );
  313. return( pBuf );
  314. }
  315. PCHAR
  316. Minfo_StringWrite(
  317. IN PDNS_RECORD pRR,
  318. IN OUT PCHAR pBuf,
  319. IN PCHAR pBufEnd,
  320. IN PVOID pContext
  321. )
  322. /*++
  323. Routine Description:
  324. Write MINFO type record.
  325. Arguments:
  326. pRR - ptr to database record
  327. pBuf - position in to write record
  328. pBufEnd - end of buffer
  329. pContext - write context
  330. Return Value:
  331. Ptr to next location in buffer.
  332. NULL if out of space in buffer.
  333. --*/
  334. {
  335. // primary server
  336. pBuf = WriteRecordDataNameToString(
  337. pBuf,
  338. pBufEnd,
  339. pRR->Data.MINFO.pNameMailbox,
  340. pContext );
  341. if ( !pBuf ||
  342. pBufEnd - pBuf < MIN_NAME_LENGTH + 1 )
  343. {
  344. return NULL;
  345. }
  346. // admin
  347. pBuf += sprintf( pBuf, " " );
  348. pBuf = WriteRecordDataNameToString(
  349. pBuf,
  350. pBufEnd,
  351. pRR->Data.MINFO.pNameErrorsMailbox,
  352. pContext );
  353. return pBuf;
  354. }
  355. PCHAR
  356. Txt_StringWrite(
  357. IN PDNS_RECORD pRR,
  358. IN OUT PCHAR pBuf,
  359. IN PCHAR pBufEnd,
  360. IN PVOID pContext
  361. )
  362. /*++
  363. Routine Description:
  364. Write TXT record.
  365. Includes: TXT, X25, HINFO, ISDN
  366. Arguments:
  367. pRR - ptr to database record
  368. pBuf - position in to write record
  369. pBufEnd - end of buffer
  370. pContext - write context
  371. Return Value:
  372. Ptr to next location in buffer.
  373. NULL if out of space in buffer.
  374. --*/
  375. {
  376. PSTR * ppstring;
  377. INT i;
  378. INT count;
  379. //
  380. // loop through all strings in count
  381. //
  382. count = pRR->Data.TXT.dwStringCount;
  383. ppstring = pRR->Data.TXT.pStringArray;
  384. for( i=0; i<count; i++ )
  385. {
  386. // separator
  387. if ( i > 0 )
  388. {
  389. if ( pBufEnd - pBuf < MIN_NAME_LENGTH + 1 )
  390. {
  391. return NULL;
  392. }
  393. pBuf += sprintf( pBuf, " " );
  394. }
  395. // string
  396. pBuf = WriteRecordDataNameToString(
  397. pBuf,
  398. pBufEnd,
  399. *ppstring,
  400. pContext );
  401. ppstring++;
  402. if ( !pBuf );
  403. {
  404. break;
  405. }
  406. }
  407. return pBuf;
  408. }
  409. //
  410. // Write RR to file dispatch table
  411. //
  412. typedef PCHAR (* RR_STRING_WRITE_FUNCTION)(
  413. PDNS_RECORD,
  414. PCHAR,
  415. PCHAR,
  416. PVOID );
  417. RR_STRING_WRITE_FUNCTION RR_StringWriteTable[] =
  418. {
  419. //RawRecord_StringWrite, // ZERO -- default for unknown types
  420. NULL,
  421. A_StringWrite, // A
  422. Ptr_StringWrite, // NS
  423. Ptr_StringWrite, // MD
  424. Ptr_StringWrite, // MF
  425. Ptr_StringWrite, // CNAME
  426. Soa_StringWrite, // SOA
  427. Ptr_StringWrite, // MB
  428. Ptr_StringWrite, // MG
  429. Ptr_StringWrite, // MR
  430. //RawRecord_StringWrite, // NULL
  431. NULL, // NULL
  432. NULL, // WKS
  433. Ptr_StringWrite, // PTR
  434. Txt_StringWrite, // HINFO
  435. Minfo_StringWrite, // MINFO
  436. Mx_StringWrite, // MX
  437. Txt_StringWrite, // TXT
  438. Minfo_StringWrite, // RP
  439. Mx_StringWrite, // AFSDB
  440. Txt_StringWrite, // X25
  441. Txt_StringWrite, // ISDN
  442. Mx_StringWrite, // RT
  443. NULL, // NSAP
  444. NULL, // NSAPPTR
  445. NULL, // SIG
  446. NULL, // KEY
  447. NULL, // PX
  448. NULL, // GPOS
  449. Aaaa_StringWrite, // AAAA
  450. NULL, // LOC
  451. NULL, // NXT
  452. NULL, // EID
  453. NULL, // NIMLOC
  454. Srv_StringWrite, // SRV
  455. NULL, // ATMA
  456. NULL, // NAPTR
  457. NULL, // KX
  458. NULL, // CERT
  459. NULL, // A6
  460. NULL, // DNAME
  461. NULL, // SINK
  462. NULL, // OPT
  463. NULL, // 42
  464. NULL, // 43
  465. NULL, // 44
  466. NULL, // 45
  467. NULL, // 46
  468. NULL, // 47
  469. NULL, // 48
  470. //
  471. // NOTE: last type indexed by type ID MUST be set
  472. // as MAX_SELF_INDEXED_TYPE #define in record.h
  473. // (see note above in record info table)
  474. // note these follow, but require OFFSET_TO_WINS_RR subtraction
  475. // from actual type value
  476. NULL, // WINS
  477. NULL // WINS-R
  478. };
  479. //
  480. // Record to string functions.
  481. //
  482. DNS_STATUS
  483. Dns_WriteRecordToString(
  484. OUT PCHAR pBuffer,
  485. IN DWORD BufferLength,
  486. IN PDNS_RECORD pRecord,
  487. IN DNS_CHARSET CharSet,
  488. IN DWORD Flags
  489. )
  490. /*++
  491. Routine Description:
  492. Write record to string.
  493. Arguments:
  494. pBuffer -- string buffer to write to
  495. BufferLength -- buffer length (bytes)
  496. pRecord -- record to print
  497. CharSet -- char set for string
  498. Flags -- flags
  499. Return Value:
  500. NO_ERROR if successful.
  501. ErrorCode on failure:
  502. ERROR_INSUFFICIENT_BUFFER -- buffer too small.
  503. ERROR_INVALID_DATA -- bad record.
  504. --*/
  505. {
  506. DNS_STATUS status = NO_ERROR;
  507. PCHAR pch = pBuffer;
  508. PCHAR pend = pBuffer + BufferLength;
  509. WORD type = pRecord->wType;
  510. DWORD index;
  511. CHAR typeNameBuf[ MAX_RECORD_NAME_LENGTH+1 ];
  512. STR_WRITE_CONTEXT context;
  513. //
  514. // validity check
  515. //
  516. if ( !pRecord )
  517. {
  518. return ERROR_INVALID_DATA;
  519. }
  520. //
  521. // DCR: currently can only write narrow char set record strings
  522. //
  523. if ( CharSet == DnsCharSetUnicode )
  524. {
  525. return ERROR_INVALID_DATA;
  526. }
  527. // setup context
  528. RtlZeroMemory( &context, sizeof(context) );
  529. context.pRecord = pRecord;
  530. context.Flags = Flags;
  531. context.CharSet = CharSet;
  532. //
  533. // print record name
  534. //
  535. pch = WriteRecordDataNameToString(
  536. pch,
  537. pend,
  538. pRecord->pName,
  539. & context );
  540. //
  541. // write record type
  542. //
  543. if ( !pch || pend-pch < MAX_RECORD_NAME_LENGTH+1 )
  544. {
  545. status = ERROR_INSUFFICIENT_BUFFER;
  546. goto Done;
  547. }
  548. Dns_WriteStringForType_A(
  549. typeNameBuf,
  550. type );
  551. pch += sprintf(
  552. pch,
  553. " %s ",
  554. typeNameBuf );
  555. //
  556. // write no-exist record?
  557. //
  558. if ( !pRecord->wDataLength )
  559. {
  560. if ( pend-pch < MAX_RECORD_NAME_LENGTH+1 )
  561. {
  562. status = ERROR_INSUFFICIENT_BUFFER;
  563. goto Done;
  564. }
  565. pch += sprintf( pch, "NOEXIST" );
  566. status = NO_ERROR;
  567. goto Done;
  568. }
  569. //
  570. // write data
  571. //
  572. index = INDEX_FOR_TYPE( type );
  573. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  574. if ( index && RR_StringWriteTable[index] )
  575. {
  576. pch = RR_StringWriteTable[index](
  577. pRecord,
  578. pch,
  579. pend,
  580. & context
  581. );
  582. if ( !pch )
  583. {
  584. //status = GetLastError();
  585. status = ERROR_INSUFFICIENT_BUFFER;
  586. }
  587. }
  588. else //if ( !index )
  589. {
  590. // DCR: could do an unknown type print
  591. status = ERROR_INVALID_DATA;
  592. goto Done;
  593. }
  594. Done:
  595. DNSDBG( WRITE, (
  596. "Leaving Dns_WriteRecordToString() => %d\n"
  597. "\tstring = %s\n",
  598. status,
  599. (status == NO_ERROR)
  600. ? pBuffer
  601. : "" ));
  602. return status;
  603. }
  604. PDNS_RECORD
  605. Dns_CreateRecordFromString(
  606. IN PSTR pString,
  607. IN DNS_CHARSET CharSet,
  608. IN DWORD Flags
  609. )
  610. /*++
  611. Routine Description:
  612. Create record from string.
  613. Arguments:
  614. pString -- record string to parse
  615. CharSet -- char set of result
  616. Flags -- flags
  617. Return Value:
  618. Ptr to record if successful.
  619. Null on failure. GetLastError() returns error.
  620. --*/
  621. {
  622. SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
  623. return NULL;
  624. }
  625. //
  626. // End rrstrw.c
  627. //