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.

1338 lines
26 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. rralloc.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Resource record allocation \ creation routines.
  8. Author:
  9. Jim Gilroy (jamesg) January, 1997
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include "local.h"
  15. #define SET_FLAGS(Flags, value) \
  16. ( *(PWORD)&(Flags) = value )
  17. PDNS_RECORD
  18. WINAPI
  19. Dns_AllocateRecord(
  20. IN WORD wBufferLength
  21. )
  22. /*++
  23. Routine Description:
  24. Allocate record structure.
  25. Arguments:
  26. wBufferLength - desired buffer length (beyond structure header)
  27. Return Value:
  28. Ptr to message buffer.
  29. NULL on error.
  30. --*/
  31. {
  32. PDNS_RECORD prr;
  33. prr = ALLOCATE_HEAP( SIZEOF_DNS_RECORD_HEADER + wBufferLength );
  34. if ( prr == NULL )
  35. {
  36. SetLastError( DNS_ERROR_NO_MEMORY );
  37. return( NULL );
  38. }
  39. RtlZeroMemory(
  40. prr,
  41. SIZEOF_DNS_RECORD_HEADER );
  42. // as first cut, set datalength to buffer length
  43. prr->wDataLength = wBufferLength;
  44. return( prr );
  45. }
  46. VOID
  47. WINAPI
  48. Dns_RecordFree(
  49. IN OUT PDNS_RECORD pRecord
  50. )
  51. /*++
  52. Routine Description:
  53. Free a record
  54. Arguments:
  55. pRecord -- record list to free
  56. Return Value:
  57. None.
  58. --*/
  59. {
  60. DNSDBG( HEAP, ( "Dns_RecordFree( %p )\n", pRecord ));
  61. // handle NULL for convenience
  62. if ( !pRecord )
  63. {
  64. return;
  65. }
  66. // free owner name?
  67. if ( FLAG_FreeOwner( pRecord ) )
  68. {
  69. FREE_HEAP( pRecord->pName );
  70. }
  71. //
  72. // free data -- but only if flag set
  73. //
  74. // note: even if we fix copy functions to do atomic
  75. // allocations, we'll still have to have free to
  76. // handle RPC allocations
  77. // (unless we very cleverly, treated RPC as flat blob, then
  78. // did fix up (to offsets before and afterward)
  79. //
  80. if ( FLAG_FreeData( pRecord ) )
  81. {
  82. switch( pRecord->wType )
  83. {
  84. case DNS_TYPE_A:
  85. break;
  86. case DNS_TYPE_PTR:
  87. case DNS_TYPE_NS:
  88. case DNS_TYPE_CNAME:
  89. case DNS_TYPE_MB:
  90. case DNS_TYPE_MD:
  91. case DNS_TYPE_MF:
  92. case DNS_TYPE_MG:
  93. case DNS_TYPE_MR:
  94. if ( pRecord->Data.PTR.pNameHost )
  95. {
  96. FREE_HEAP( pRecord->Data.PTR.pNameHost );
  97. }
  98. break;
  99. case DNS_TYPE_SOA:
  100. if ( pRecord->Data.SOA.pNamePrimaryServer )
  101. {
  102. FREE_HEAP( pRecord->Data.SOA.pNamePrimaryServer );
  103. }
  104. if ( pRecord->Data.SOA.pNameAdministrator )
  105. {
  106. FREE_HEAP( pRecord->Data.SOA.pNameAdministrator );
  107. }
  108. break;
  109. case DNS_TYPE_MINFO:
  110. case DNS_TYPE_RP:
  111. if ( pRecord->Data.MINFO.pNameMailbox )
  112. {
  113. FREE_HEAP( pRecord->Data.MINFO.pNameMailbox );
  114. }
  115. if ( pRecord->Data.MINFO.pNameErrorsMailbox )
  116. {
  117. FREE_HEAP( pRecord->Data.MINFO.pNameErrorsMailbox );
  118. }
  119. break;
  120. case DNS_TYPE_MX:
  121. case DNS_TYPE_AFSDB:
  122. case DNS_TYPE_RT:
  123. if ( pRecord->Data.MX.pNameExchange )
  124. {
  125. FREE_HEAP( pRecord->Data.MX.pNameExchange );
  126. }
  127. break;
  128. case DNS_TYPE_HINFO:
  129. case DNS_TYPE_ISDN:
  130. case DNS_TYPE_TEXT:
  131. case DNS_TYPE_X25:
  132. {
  133. DWORD iter;
  134. DWORD count = pRecord->Data.TXT.dwStringCount;
  135. for ( iter = 0; iter < count; iter++ )
  136. {
  137. if ( pRecord->Data.TXT.pStringArray[iter] )
  138. {
  139. FREE_HEAP( pRecord->Data.TXT.pStringArray[iter] );
  140. }
  141. }
  142. break;
  143. }
  144. case DNS_TYPE_SRV:
  145. if ( pRecord->Data.SRV.pNameTarget )
  146. {
  147. FREE_HEAP( pRecord->Data.SRV.pNameTarget );
  148. }
  149. break;
  150. case DNS_TYPE_WINSR:
  151. if ( pRecord->Data.WINSR.pNameResultDomain )
  152. {
  153. FREE_HEAP( pRecord->Data.WINSR.pNameResultDomain );
  154. }
  155. break;
  156. default:
  157. // other types -- A, AAAA, ATMA, WINS, NULL,
  158. // have no internal pointers
  159. break;
  160. }
  161. }
  162. // for catching heap problems
  163. pRecord->pNext = DNS_BAD_PTR;
  164. pRecord->pName = DNS_BAD_PTR;
  165. FREE_HEAP( pRecord );
  166. }
  167. VOID
  168. WINAPI
  169. Dns_RecordListFree(
  170. IN OUT PDNS_RECORD pRecord
  171. )
  172. /*++
  173. Routine Description:
  174. Free list of records.
  175. Arguments:
  176. pRecord -- record list to free
  177. Return Value:
  178. None.
  179. --*/
  180. {
  181. PDNS_RECORD pnext;
  182. DNSDBG( TRACE, (
  183. "Dns_RecordListFree( %p )\n",
  184. pRecord ));
  185. //
  186. // loop through and free every RR in list
  187. //
  188. while ( pRecord )
  189. {
  190. pnext = pRecord->pNext;
  191. Dns_RecordFree( pRecord );
  192. pRecord = pnext;
  193. }
  194. }
  195. VOID
  196. WINAPI
  197. Dns_RecordListFreeEx(
  198. IN OUT PDNS_RECORD pRecord,
  199. IN BOOL fFreeOwner
  200. )
  201. /*++
  202. Routine Description:
  203. Free list of records.
  204. DCR: RecordListFreeEx (no free owner option) is probably useless
  205. Note: owner name is freed ONLY when indicated by flag;
  206. other ptrs are considered to be either
  207. 1) internal as when records read from wire or copied
  208. 2) external and to be freed by record creator
  209. Arguments:
  210. pRecord -- record list to free
  211. fFreeOwner -- flag indicating owner name should be freed
  212. Return Value:
  213. None.
  214. --*/
  215. {
  216. PDNS_RECORD pnext;
  217. DNSDBG( TRACE, (
  218. "Dns_RecordListFreeEx( %p, %d )\n",
  219. pRecord,
  220. fFreeOwner ));
  221. //
  222. // loop through and free every RR in list
  223. //
  224. while ( pRecord )
  225. {
  226. pnext = pRecord->pNext;
  227. // free owner name?
  228. // - if "FreeOwner" flag NOT set, then don't free
  229. if ( !fFreeOwner )
  230. {
  231. FLAG_FreeOwner( pRecord ) = FALSE;
  232. }
  233. // free record
  234. Dns_RecordFree( pRecord );
  235. pRecord = pnext;
  236. }
  237. }
  238. //
  239. // Special record type creation routines
  240. //
  241. PDNS_RECORD
  242. CreateRecordBasic(
  243. IN PDNS_NAME pOwnerName,
  244. IN BOOL fCopyName,
  245. IN WORD wType,
  246. IN WORD wDataLength,
  247. IN DWORD AllocLength,
  248. IN DWORD Ttl,
  249. IN DNS_CHARSET NameCharSet,
  250. IN DNS_CHARSET RecordCharSet
  251. )
  252. /*++
  253. Routine Description:
  254. Create record of arbitary type.
  255. Helper function to wrap up
  256. - record alloc
  257. - name alloc
  258. - basic setup
  259. Arguments:
  260. pOwnerName -- owner name
  261. fCopyName -- TRUE - make copy of owner name
  262. FALSE - use directly
  263. wType -- type
  264. AllocLength -- allocaction length, including any imbedded data
  265. wDataLength -- data length to set
  266. Ttl -- TTL
  267. NameCharSet -- character set of name
  268. RecordCharSet -- character set for resulting record
  269. Return Value:
  270. Ptr to PTR record.
  271. NULL on error.
  272. --*/
  273. {
  274. PDNS_RECORD precord;
  275. PDNS_RECORD prr;
  276. PCHAR pname;
  277. DWORD bufLength;
  278. //
  279. // alloc record
  280. //
  281. prr = Dns_AllocateRecord( (WORD)AllocLength );
  282. if ( !prr )
  283. {
  284. return( NULL );
  285. }
  286. //
  287. // copy owner name
  288. //
  289. if ( fCopyName && pOwnerName )
  290. {
  291. pname = Dns_NameCopyAllocate(
  292. pOwnerName,
  293. 0, // length unknown
  294. NameCharSet,
  295. RecordCharSet );
  296. if ( !pname )
  297. {
  298. FREE_HEAP( prr );
  299. return( NULL );
  300. }
  301. }
  302. else
  303. {
  304. pname = pOwnerName;
  305. }
  306. //
  307. // set fields
  308. // - name, type and charset
  309. // - TTL, section left zero
  310. // - FreeData is specifically off
  311. //
  312. prr->pName = pname;
  313. prr->wType = wType;
  314. prr->wDataLength = wDataLength;
  315. SET_FREE_OWNER(prr);
  316. prr->Flags.S.CharSet = RecordCharSet;
  317. prr->dwTtl = Ttl;
  318. return( prr );
  319. }
  320. PDNS_RECORD
  321. Dns_CreateFlatRecord(
  322. IN PDNS_NAME pOwnerName,
  323. IN WORD wType,
  324. IN PCHAR pData,
  325. IN DWORD DataLength,
  326. IN DWORD Ttl,
  327. IN DNS_CHARSET NameCharSet,
  328. IN DNS_CHARSET RecordCharSet
  329. )
  330. /*++
  331. Routine Description:
  332. Create flat record.
  333. Arguments:
  334. pOwnerName -- owner name
  335. wType -- record type
  336. pData -- ptr to data for record
  337. DataLength -- length (in bytes) of data
  338. Ttl -- TTL
  339. NameCharSet -- character set of name
  340. RecordCharSet -- character set for resulting record
  341. Return Value:
  342. Ptr to PTR record.
  343. NULL on error.
  344. --*/
  345. {
  346. PDNS_RECORD prr;
  347. //
  348. // determine record size
  349. // - record buffer will include hostname
  350. //
  351. prr = CreateRecordBasic(
  352. pOwnerName,
  353. TRUE, // copy name
  354. wType,
  355. (WORD) DataLength, // datalength
  356. DataLength, // alloc datalength
  357. Ttl,
  358. NameCharSet,
  359. RecordCharSet );
  360. if ( !prr )
  361. {
  362. return( NULL );
  363. }
  364. //
  365. // copy in data
  366. //
  367. RtlCopyMemory(
  368. (PBYTE) &prr->Data,
  369. pData,
  370. DataLength );
  371. return( prr );
  372. }
  373. //
  374. // Reverse record creation
  375. //
  376. PDNS_RECORD
  377. Dns_CreatePtrTypeRecord(
  378. IN PDNS_NAME pOwnerName,
  379. IN BOOL fCopyName,
  380. IN PDNS_NAME pTargetName,
  381. IN WORD wType,
  382. IN DWORD Ttl,
  383. IN DNS_CHARSET NameCharSet,
  384. IN DNS_CHARSET RecordCharSet
  385. )
  386. /*++
  387. Routine Description:
  388. Create PTR type (single-indirection) record.
  389. This can be used to create any "PTR-type" record:
  390. PTR, CNAME, NS, etc.
  391. Arguments:
  392. pOwnerName -- owner name
  393. fCopyName -- TRUE - make copy of owner name
  394. FALSE - use directly
  395. pTargetName -- target name
  396. Ttl -- TTL
  397. NameCharSet -- character set of name
  398. RecordCharSet -- character set for resulting record
  399. Return Value:
  400. Ptr to PTR record.
  401. NULL on error.
  402. --*/
  403. {
  404. PDNS_RECORD precord;
  405. PDNS_RECORD prr;
  406. PCHAR pname;
  407. DWORD bufLength;
  408. //
  409. // determine record size
  410. // - record buffer will include hostname
  411. //
  412. bufLength = Dns_GetBufferLengthForNameCopy(
  413. pTargetName,
  414. 0, // length unknown
  415. NameCharSet,
  416. RecordCharSet );
  417. if ( !bufLength )
  418. {
  419. return( NULL );
  420. }
  421. //
  422. // create record
  423. //
  424. prr = CreateRecordBasic(
  425. pOwnerName,
  426. fCopyName,
  427. wType,
  428. sizeof(DNS_PTR_DATA), // data length
  429. (sizeof(DNS_PTR_DATA) + bufLength), // alloc length
  430. Ttl,
  431. NameCharSet,
  432. RecordCharSet );
  433. if ( !prr )
  434. {
  435. return( NULL );
  436. }
  437. //
  438. // write target name into buffer, immediately following PTR data struct
  439. //
  440. prr->Data.PTR.pNameHost = (PCHAR)&prr->Data + sizeof(DNS_PTR_DATA);
  441. Dns_NameCopy(
  442. prr->Data.PTR.pNameHost,
  443. NULL,
  444. pTargetName,
  445. 0,
  446. NameCharSet,
  447. RecordCharSet
  448. );
  449. return( prr );
  450. }
  451. PDNS_RECORD
  452. Dns_CreatePtrRecordEx(
  453. IN PDNS_ADDR pAddr,
  454. IN PDNS_NAME pszHostName,
  455. IN DWORD Ttl,
  456. IN DNS_CHARSET NameCharSet,
  457. IN DNS_CHARSET RecordCharSet
  458. )
  459. /*++
  460. Routine Description:
  461. Create PTR record from IP address and hostname.
  462. Arguments:
  463. pAddr -- addr (IP4 or IP6) to map into PTR
  464. pszHostName -- host name, FULL FQDN
  465. Ttl -- TTL
  466. NameCharSet -- character set of name
  467. RecordCharSet -- character set for resulting record
  468. Return Value:
  469. Ptr to PTR record.
  470. NULL on error.
  471. --*/
  472. {
  473. PCHAR pname = NULL;
  474. DWORD family;
  475. //
  476. // create reverse lookup name
  477. // - note this is external allocation
  478. //
  479. family = DnsAddr_Family( pAddr );
  480. if ( family == AF_INET )
  481. {
  482. IP4_ADDRESS ip = DnsAddr_GetIp4(pAddr);
  483. if ( RecordCharSet == DnsCharSetUnicode )
  484. {
  485. pname = (PCHAR) Dns_Ip4AddressToReverseNameAlloc_W( ip );
  486. }
  487. else
  488. {
  489. pname = Dns_Ip4AddressToReverseNameAlloc_A( ip );
  490. }
  491. }
  492. else if ( family == AF_INET6 )
  493. {
  494. PIP6_ADDRESS p6 = DnsAddr_GetIp6Ptr(pAddr);
  495. if ( RecordCharSet == DnsCharSetUnicode )
  496. {
  497. pname = (PCHAR) Dns_Ip6AddressToReverseNameAlloc_W( *p6 );
  498. }
  499. else
  500. {
  501. pname = Dns_Ip6AddressToReverseNameAlloc_A( *p6 );
  502. }
  503. }
  504. if ( !pname )
  505. {
  506. return( NULL );
  507. }
  508. //
  509. // build record
  510. //
  511. return Dns_CreatePtrTypeRecord(
  512. pname,
  513. FALSE, // don't copy IP
  514. pszHostName, // target name
  515. DNS_TYPE_PTR,
  516. Ttl,
  517. NameCharSet,
  518. RecordCharSet );
  519. }
  520. PDNS_RECORD
  521. Dns_CreatePtrRecordExEx(
  522. IN PDNS_ADDR pAddr,
  523. IN PSTR pszHostName,
  524. IN PSTR pszDomainName,
  525. IN DWORD Ttl,
  526. IN DNS_CHARSET NameCharSet,
  527. IN DNS_CHARSET RecordCharSet
  528. )
  529. /*++
  530. Routine Description:
  531. Create PTR record from hostname and domain name.
  532. Helper function for DHCP registrations when hostname
  533. and domain name are separate and both required.
  534. Arguments:
  535. pAddr -- addr (IP4 or IP6) to map into PTR
  536. pszHostName -- host name (single label)
  537. pszDomainName -- domain name
  538. Ttl -- TTL
  539. NameCharSet -- character set of name
  540. RecordCharSet -- character set for resulting record
  541. Return Value:
  542. Ptr to PTR record.
  543. NULL on error.
  544. --*/
  545. {
  546. WCHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  547. DNSDBG( TRACE, (
  548. "Dns_CreatePtrRecordExEx()\n" ));
  549. //
  550. // build appended name
  551. //
  552. // DCR: could require just host name and check that
  553. // either domain exists or hostname is full
  554. //
  555. if ( !pszHostName || !pszDomainName )
  556. {
  557. return NULL;
  558. }
  559. if ( NameCharSet != DnsCharSetUnicode )
  560. {
  561. if ( ! Dns_NameAppend_A(
  562. (PCHAR) nameBuffer,
  563. DNS_MAX_NAME_BUFFER_LENGTH,
  564. pszHostName,
  565. pszDomainName ) )
  566. {
  567. DNS_ASSERT( FALSE );
  568. return NULL;
  569. }
  570. }
  571. else
  572. {
  573. if ( ! Dns_NameAppend_W(
  574. (PWCHAR) nameBuffer,
  575. DNS_MAX_NAME_BUFFER_LENGTH,
  576. (PWSTR) pszHostName,
  577. (PWSTR) pszDomainName ) )
  578. {
  579. DNS_ASSERT( FALSE );
  580. return NULL;
  581. }
  582. }
  583. //
  584. // build record
  585. //
  586. return Dns_CreatePtrRecordEx(
  587. pAddr,
  588. (PCHAR) nameBuffer,
  589. Ttl,
  590. NameCharSet,
  591. RecordCharSet
  592. );
  593. }
  594. //
  595. // Forward record creation
  596. //
  597. PDNS_RECORD
  598. Dns_CreateARecord(
  599. IN PDNS_NAME pOwnerName,
  600. IN IP4_ADDRESS Ip4Addr,
  601. IN DWORD Ttl,
  602. IN DNS_CHARSET NameCharSet,
  603. IN DNS_CHARSET RecordCharSet
  604. )
  605. /*++
  606. Routine Description:
  607. Create A record.
  608. Arguments:
  609. pOwnerName -- owner name
  610. Ip4Addr -- IP address
  611. Ttl -- TTL
  612. NameCharSet -- character set of name
  613. RecordCharSet -- character set for resulting record
  614. Return Value:
  615. Ptr to PTR record.
  616. NULL on error.
  617. --*/
  618. {
  619. PDNS_RECORD prr;
  620. //
  621. // determine record size
  622. // - record buffer will include hostname
  623. //
  624. prr = CreateRecordBasic(
  625. pOwnerName,
  626. TRUE, // copy name
  627. DNS_TYPE_A,
  628. sizeof(DNS_A_DATA),
  629. sizeof(DNS_A_DATA),
  630. Ttl,
  631. NameCharSet,
  632. RecordCharSet );
  633. if ( !prr )
  634. {
  635. return( NULL );
  636. }
  637. //
  638. // set IP
  639. //
  640. prr->Data.A.IpAddress = Ip4Addr;
  641. return( prr );
  642. }
  643. PDNS_RECORD
  644. Dns_CreateAAAARecord(
  645. IN PDNS_NAME pOwnerName,
  646. IN IP6_ADDRESS Ip6Addr,
  647. IN DWORD Ttl,
  648. IN DNS_CHARSET NameCharSet,
  649. IN DNS_CHARSET RecordCharSet
  650. )
  651. /*++
  652. Routine Description:
  653. Create A record.
  654. Arguments:
  655. pOwnerName -- owner name
  656. Ip6Addr -- IP6 address
  657. Ttl -- TTL
  658. NameCharSet -- character set of name
  659. RecordCharSet -- character set for resulting record
  660. Return Value:
  661. Ptr to PTR record.
  662. NULL on error.
  663. --*/
  664. {
  665. PDNS_RECORD prr;
  666. //
  667. // determine record size
  668. // - record buffer will include hostname
  669. //
  670. prr = CreateRecordBasic(
  671. pOwnerName,
  672. TRUE, // copy name
  673. DNS_TYPE_AAAA,
  674. sizeof(DNS_AAAA_DATA),
  675. sizeof(DNS_AAAA_DATA),
  676. Ttl,
  677. NameCharSet,
  678. RecordCharSet );
  679. if ( !prr )
  680. {
  681. return( NULL );
  682. }
  683. //
  684. // set IP
  685. //
  686. prr->Data.AAAA.Ip6Address = Ip6Addr;
  687. return( prr );
  688. }
  689. PDNS_RECORD
  690. Dns_CreateAAAARecordFromDnsAddr(
  691. IN PDNS_NAME pOwnerName,
  692. IN PDNS_ADDR pAddr,
  693. IN DWORD Ttl,
  694. IN DNS_CHARSET NameCharSet,
  695. IN DNS_CHARSET RecordCharSet
  696. )
  697. /*++
  698. Routine Description:
  699. Create A record.
  700. Arguments:
  701. pOwnerName -- owner name
  702. pAddr -- Ptr to DNS_ADDR
  703. Ttl -- TTL
  704. NameCharSet -- character set of name
  705. RecordCharSet -- character set for resulting record
  706. Return Value:
  707. Ptr to PTR record.
  708. NULL on error.
  709. --*/
  710. {
  711. PDNS_RECORD prr;
  712. //
  713. // determine record size
  714. // - record buffer will include hostname
  715. //
  716. prr = Dns_CreateAAAARecord(
  717. pOwnerName,
  718. * (PIP6_ADDRESS) &pAddr->SockaddrIn6.sin6_addr,
  719. Ttl,
  720. NameCharSet,
  721. RecordCharSet
  722. );
  723. if ( !prr )
  724. {
  725. return( NULL );
  726. }
  727. //
  728. // slap scope into reserved field
  729. //
  730. prr->dwReserved = pAddr->SockaddrIn6.sin6_scope_id;
  731. return( prr );
  732. }
  733. PDNS_RECORD
  734. Dns_CreateForwardRecord(
  735. IN PDNS_NAME pOwnerName,
  736. IN WORD wType, OPTIONAL
  737. IN PDNS_ADDR pAddr,
  738. IN DWORD Ttl,
  739. IN DNS_CHARSET NameCharSet,
  740. IN DNS_CHARSET RecordCharSet
  741. )
  742. /*++
  743. Routine Description:
  744. Create forward lookup record.
  745. This is just a shim to avoid duplicating selection logic.
  746. Arguments:
  747. pOwnerName -- owner name
  748. wType -- type, if specified; zero for getting type from pAddr
  749. pAddr -- ptr to DNS_ADDR
  750. Ttl -- TTL
  751. NameCharSet -- character set of name
  752. RecordCharSet -- character set for resulting record
  753. Return Value:
  754. Ptr to PTR record.
  755. NULL on error.
  756. --*/
  757. {
  758. //
  759. // build desired type
  760. //
  761. if ( DnsAddr_IsIp4( pAddr ) )
  762. {
  763. if ( wType == 0 || wType == DNS_TYPE_A )
  764. {
  765. return Dns_CreateARecord(
  766. pOwnerName,
  767. DnsAddr_GetIp4( pAddr ),
  768. Ttl,
  769. NameCharSet,
  770. RecordCharSet );
  771. }
  772. }
  773. else if ( DnsAddr_IsIp6( pAddr ) )
  774. {
  775. if ( wType == 0 || wType == DNS_TYPE_AAAA )
  776. {
  777. return Dns_CreateAAAARecordFromDnsAddr(
  778. pOwnerName,
  779. pAddr,
  780. Ttl,
  781. NameCharSet,
  782. RecordCharSet );
  783. }
  784. }
  785. return NULL;
  786. }
  787. PDNS_RECORD
  788. Dns_CreateForwardRecordFromIp6(
  789. IN PDNS_NAME pOwnerName,
  790. IN PIP6_ADDRESS pIp,
  791. IN DWORD Ttl,
  792. IN DNS_CHARSET NameCharSet,
  793. IN DNS_CHARSET RecordCharSet
  794. )
  795. /*++
  796. Routine Description:
  797. Create forward lookup record.
  798. This is just a shim to avoid duplicating selection logic.
  799. Arguments:
  800. pOwnerName -- owner name
  801. pIp -- IP6 address
  802. Ttl -- TTL
  803. NameCharSet -- character set of name
  804. RecordCharSet -- character set for resulting record
  805. Return Value:
  806. Ptr to PTR record.
  807. NULL on error.
  808. --*/
  809. {
  810. //
  811. // build desired type
  812. //
  813. if ( IP6_IS_ADDR_V4MAPPED( pIp ) )
  814. {
  815. return Dns_CreateARecord(
  816. pOwnerName,
  817. IP6_GET_V4_ADDR( pIp ),
  818. Ttl,
  819. NameCharSet,
  820. RecordCharSet );
  821. }
  822. else
  823. {
  824. return Dns_CreateAAAARecord(
  825. pOwnerName,
  826. *pIp,
  827. Ttl,
  828. NameCharSet,
  829. RecordCharSet );
  830. }
  831. }
  832. PDNS_RECORD
  833. Dns_CreateForwardRecordForSockaddr(
  834. IN PDNS_NAME pOwnerName,
  835. IN PSOCKADDR pSockaddr,
  836. IN DWORD Ttl,
  837. IN DNS_CHARSET NameCharSet,
  838. IN DNS_CHARSET RecordCharSet
  839. )
  840. /*++
  841. Routine Description:
  842. Create forward lookup record.
  843. This is just a shim to avoid duplicating selection logic.
  844. Arguments:
  845. pOwnerName -- owner name
  846. pSockaddr -- ptr to sockaddr
  847. Ttl -- TTL
  848. NameCharSet -- character set of name
  849. RecordCharSet -- character set for resulting record
  850. Return Value:
  851. Ptr to PTR record.
  852. NULL on error.
  853. --*/
  854. {
  855. PFAMILY_INFO pinfo;
  856. DNSDBG( TRACE, (
  857. "Dns_CreateForwardRecordForSockaddr()\n" ));
  858. pinfo = FamilyInfo_GetForSockaddr( pSockaddr );
  859. if ( !pinfo )
  860. {
  861. SetLastError( ERROR_INVALID_DATA );
  862. return NULL;
  863. }
  864. //
  865. // build flat record of desired type
  866. //
  867. return Dns_CreateFlatRecord(
  868. pOwnerName,
  869. pinfo->DnsType,
  870. (PBYTE)pSockaddr + pinfo->OffsetToAddrInSockaddr,
  871. pinfo->LengthAddr,
  872. Ttl,
  873. NameCharSet,
  874. RecordCharSet );
  875. }
  876. PDNS_RECORD
  877. Dns_CreateRecordForIpString_W(
  878. IN PCWSTR pwsName,
  879. IN WORD wType, OPTIONAL
  880. IN DWORD Ttl
  881. )
  882. /*++
  883. Routine Description:
  884. Create record for IP string query.
  885. Arguments:
  886. pwsName -- name that may be IP string query
  887. wType -- type of query; OPTIONAL, if zero type
  888. derived from string
  889. Return Value:
  890. Ptr to record for query, if query name\type is IP.
  891. NULL if query not for IP.
  892. --*/
  893. {
  894. DNS_ADDR addr;
  895. PDNS_RECORD prr;
  896. DNSDBG( TRACE, (
  897. "\nDns_CreateRecordForIpString( %S, wType = %d )\n",
  898. pwsName,
  899. wType ));
  900. if ( !pwsName )
  901. {
  902. return NULL;
  903. }
  904. //
  905. // support A or AAAA queries for IP strings
  906. // - IP4 strings must be in w.x.y.z form otherwise
  907. // we convert the all numeric names also
  908. //
  909. if ( wType == DNS_TYPE_A ||
  910. wType == 0 )
  911. {
  912. IP4_ADDRESS ip4;
  913. PCWSTR pdot;
  914. DWORD count;
  915. if ( ! Dns_Ip4StringToAddress_W(
  916. & ip4,
  917. (PWSTR) pwsName ) )
  918. {
  919. goto Try6;
  920. }
  921. // verify three dot form w.x.y.z
  922. pdot = pwsName;
  923. count = 3;
  924. while ( count-- )
  925. {
  926. pdot = wcschr( pdot, L'.' );
  927. if ( !pdot || !*++pdot )
  928. {
  929. goto Try6;
  930. }
  931. }
  932. DnsAddr_BuildFromIp4(
  933. &addr,
  934. ip4,
  935. 0 );
  936. wType = DNS_TYPE_A;
  937. goto Build;
  938. }
  939. Try6:
  940. if ( wType == DNS_TYPE_AAAA ||
  941. wType == 0 )
  942. {
  943. // this will convert any form,
  944. // but set type==AAAA to fail record build if
  945. // did NOT build IP6
  946. if ( Dns_StringToDnsAddr_W(
  947. & addr,
  948. (PWSTR) pwsName ) )
  949. {
  950. wType = DNS_TYPE_AAAA;
  951. goto Build;
  952. }
  953. }
  954. return NULL; // no match
  955. Build:
  956. //
  957. // name is IP string -- build record
  958. //
  959. prr = Dns_CreateForwardRecord(
  960. (PDNS_NAME) pwsName,
  961. wType,
  962. & addr,
  963. Ttl,
  964. DnsCharSetUnicode,
  965. DnsCharSetUnicode );
  966. DNSDBG( TRACE, (
  967. "Create record %p for IP string %S type %d.\n",
  968. prr,
  969. pwsName,
  970. wType ));
  971. return prr;
  972. }
  973. //
  974. // End rralloc.c
  975. //