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.

1177 lines
22 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. PDNS_RECORD
  374. Dns_CreatePtrTypeRecord(
  375. IN PDNS_NAME pOwnerName,
  376. IN BOOL fCopyName,
  377. IN PDNS_NAME pTargetName,
  378. IN WORD wType,
  379. IN DWORD Ttl,
  380. IN DNS_CHARSET NameCharSet,
  381. IN DNS_CHARSET RecordCharSet
  382. )
  383. /*++
  384. Routine Description:
  385. Create PTR type (single-indirection) record.
  386. This can be used to create any "PTR-type" record:
  387. PTR, CNAME, NS, etc.
  388. Arguments:
  389. pOwnerName -- owner name
  390. fCopyName -- TRUE - make copy of owner name
  391. FALSE - use directly
  392. pTargetName -- target name
  393. Ttl -- TTL
  394. NameCharSet -- character set of name
  395. RecordCharSet -- character set for resulting record
  396. Return Value:
  397. Ptr to PTR record.
  398. NULL on error.
  399. --*/
  400. {
  401. PDNS_RECORD precord;
  402. PDNS_RECORD prr;
  403. PCHAR pname;
  404. DWORD bufLength;
  405. //
  406. // determine record size
  407. // - record buffer will include hostname
  408. //
  409. bufLength = Dns_GetBufferLengthForNameCopy(
  410. pTargetName,
  411. 0, // length unknown
  412. NameCharSet,
  413. RecordCharSet );
  414. if ( !bufLength )
  415. {
  416. return( NULL );
  417. }
  418. //
  419. // create record
  420. //
  421. prr = CreateRecordBasic(
  422. pOwnerName,
  423. fCopyName,
  424. wType,
  425. sizeof(DNS_PTR_DATA), // data length
  426. (sizeof(DNS_PTR_DATA) + bufLength), // alloc length
  427. Ttl,
  428. NameCharSet,
  429. RecordCharSet );
  430. if ( !prr )
  431. {
  432. return( NULL );
  433. }
  434. //
  435. // write target name into buffer, immediately following PTR data struct
  436. //
  437. prr->Data.PTR.pNameHost = (PCHAR)&prr->Data + sizeof(DNS_PTR_DATA);
  438. Dns_NameCopy(
  439. prr->Data.PTR.pNameHost,
  440. NULL,
  441. pTargetName,
  442. 0,
  443. NameCharSet,
  444. RecordCharSet
  445. );
  446. return( prr );
  447. }
  448. PDNS_RECORD
  449. Dns_CreatePtrRecordEx(
  450. IN PIP_UNION pIp,
  451. IN PDNS_NAME pszHostName,
  452. IN DWORD Ttl,
  453. IN DNS_CHARSET NameCharSet,
  454. IN DNS_CHARSET RecordCharSet
  455. )
  456. /*++
  457. Routine Description:
  458. Create PTR record from IP address and hostname.
  459. Arguments:
  460. pIp -- IP union (IP4 or IP6)
  461. pszHostName -- host name, FULL FQDN
  462. Ttl -- TTL
  463. NameCharSet -- character set of name
  464. RecordCharSet -- character set for resulting record
  465. Return Value:
  466. Ptr to PTR record.
  467. NULL on error.
  468. --*/
  469. {
  470. PCHAR pname;
  471. //
  472. // create reverse lookup name
  473. // - note this is external allocation
  474. //
  475. if ( IPUNION_IS_IP4( pIp ) )
  476. {
  477. IP4_ADDRESS ip = IPUNION_GET_IP4(pIp);
  478. if ( RecordCharSet == DnsCharSetUnicode )
  479. {
  480. pname = (PCHAR) Dns_Ip4AddressToReverseNameAlloc_W( ip );
  481. }
  482. else
  483. {
  484. pname = Dns_Ip4AddressToReverseNameAlloc_A( ip );
  485. }
  486. }
  487. else
  488. {
  489. IP6_ADDRESS ip = IPUNION_GET_IP6(pIp);
  490. if ( RecordCharSet == DnsCharSetUnicode )
  491. {
  492. pname = (PCHAR) Dns_Ip6AddressToReverseNameAlloc_W( ip );
  493. }
  494. else
  495. {
  496. pname = Dns_Ip6AddressToReverseNameAlloc_A( ip );
  497. }
  498. }
  499. if ( !pname )
  500. {
  501. return( NULL );
  502. }
  503. //
  504. // build record
  505. //
  506. return Dns_CreatePtrTypeRecord(
  507. pname,
  508. FALSE, // don't copy IP
  509. pszHostName, // target name
  510. DNS_TYPE_PTR,
  511. Ttl,
  512. NameCharSet,
  513. RecordCharSet );
  514. }
  515. PDNS_RECORD
  516. Dns_CreatePtrRecordExEx(
  517. IN PIP_UNION pIp,
  518. IN PSTR pszHostName,
  519. IN PSTR pszDomainName,
  520. IN DWORD Ttl,
  521. IN DNS_CHARSET NameCharSet,
  522. IN DNS_CHARSET RecordCharSet
  523. )
  524. /*++
  525. Routine Description:
  526. Create PTR record from hostname and domain name.
  527. Helper function for DHCP registrations when hostname
  528. and domain name are separate and both required.
  529. Arguments:
  530. pIp -- IP union (IP4 or IP6)
  531. pszHostName -- host name (single label)
  532. pszDomainName -- domain name
  533. Ttl -- TTL
  534. NameCharSet -- character set of name
  535. RecordCharSet -- character set for resulting record
  536. Return Value:
  537. Ptr to PTR record.
  538. NULL on error.
  539. --*/
  540. {
  541. WCHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  542. DNSDBG( TRACE, (
  543. "Dns_CreatePtrRecordExEx()\n" ));
  544. //
  545. // build appended name
  546. //
  547. // DCR: could require just host name and check that
  548. // either domain exists or hostname is full
  549. //
  550. if ( !pszHostName || !pszDomainName )
  551. {
  552. return NULL;
  553. }
  554. if ( NameCharSet != DnsCharSetUnicode )
  555. {
  556. if ( ! Dns_NameAppend_A(
  557. (PCHAR) nameBuffer,
  558. DNS_MAX_NAME_BUFFER_LENGTH,
  559. pszHostName,
  560. pszDomainName ) )
  561. {
  562. DNS_ASSERT( FALSE );
  563. return NULL;
  564. }
  565. }
  566. else
  567. {
  568. if ( ! Dns_NameAppend_W(
  569. (PWCHAR) nameBuffer,
  570. DNS_MAX_NAME_BUFFER_LENGTH,
  571. (PWSTR) pszHostName,
  572. (PWSTR) pszDomainName ) )
  573. {
  574. DNS_ASSERT( FALSE );
  575. return NULL;
  576. }
  577. }
  578. //
  579. // build record
  580. //
  581. return Dns_CreatePtrRecordEx(
  582. pIp,
  583. (PCHAR) nameBuffer,
  584. Ttl,
  585. NameCharSet,
  586. RecordCharSet
  587. );
  588. }
  589. PDNS_RECORD
  590. Dns_CreateARecord(
  591. IN PDNS_NAME pOwnerName,
  592. IN IP_ADDRESS Ip4Addr,
  593. IN DWORD Ttl,
  594. IN DNS_CHARSET NameCharSet,
  595. IN DNS_CHARSET RecordCharSet
  596. )
  597. /*++
  598. Routine Description:
  599. Create A record.
  600. Arguments:
  601. pOwnerName -- owner name
  602. Ip4Addr -- IP address
  603. Ttl -- TTL
  604. NameCharSet -- character set of name
  605. RecordCharSet -- character set for resulting record
  606. Return Value:
  607. Ptr to PTR record.
  608. NULL on error.
  609. --*/
  610. {
  611. PDNS_RECORD prr;
  612. //
  613. // determine record size
  614. // - record buffer will include hostname
  615. //
  616. prr = CreateRecordBasic(
  617. pOwnerName,
  618. TRUE, // copy name
  619. DNS_TYPE_A,
  620. sizeof(DNS_A_DATA),
  621. sizeof(DNS_A_DATA),
  622. Ttl,
  623. NameCharSet,
  624. RecordCharSet );
  625. if ( !prr )
  626. {
  627. return( NULL );
  628. }
  629. //
  630. // set IP
  631. //
  632. prr->Data.A.IpAddress = Ip4Addr;
  633. return( prr );
  634. }
  635. PDNS_RECORD
  636. Dns_CreateAAAARecord(
  637. IN PDNS_NAME pOwnerName,
  638. IN IP6_ADDRESS Ip6Addr,
  639. IN DWORD Ttl,
  640. IN DNS_CHARSET NameCharSet,
  641. IN DNS_CHARSET RecordCharSet
  642. )
  643. /*++
  644. Routine Description:
  645. Create A record.
  646. Arguments:
  647. pOwnerName -- owner name
  648. Ip6Addr -- IP6 address
  649. Ttl -- TTL
  650. NameCharSet -- character set of name
  651. RecordCharSet -- character set for resulting record
  652. Return Value:
  653. Ptr to PTR record.
  654. NULL on error.
  655. --*/
  656. {
  657. PDNS_RECORD prr;
  658. //
  659. // determine record size
  660. // - record buffer will include hostname
  661. //
  662. prr = CreateRecordBasic(
  663. pOwnerName,
  664. TRUE, // copy name
  665. DNS_TYPE_AAAA,
  666. sizeof(DNS_AAAA_DATA),
  667. sizeof(DNS_AAAA_DATA),
  668. Ttl,
  669. NameCharSet,
  670. RecordCharSet );
  671. if ( !prr )
  672. {
  673. return( NULL );
  674. }
  675. //
  676. // set IP
  677. //
  678. prr->Data.AAAA.Ip6Address = Ip6Addr;
  679. return( prr );
  680. }
  681. PDNS_RECORD
  682. Dns_CreateForwardRecord(
  683. IN PDNS_NAME pOwnerName,
  684. IN PIP_UNION pIp,
  685. IN DWORD Ttl,
  686. IN DNS_CHARSET NameCharSet,
  687. IN DNS_CHARSET RecordCharSet
  688. )
  689. /*++
  690. Routine Description:
  691. Create forward lookup record.
  692. This is just a shim to avoid duplicating selection logic.
  693. Arguments:
  694. pOwnerName -- owner name
  695. pIp -- IP address union
  696. Ttl -- TTL
  697. NameCharSet -- character set of name
  698. RecordCharSet -- character set for resulting record
  699. Return Value:
  700. Ptr to PTR record.
  701. NULL on error.
  702. --*/
  703. {
  704. //
  705. // build desired type
  706. //
  707. // DCR: must add\choose A6
  708. //
  709. if ( IPUNION_IS_IP4( pIp ) )
  710. {
  711. return Dns_CreateARecord(
  712. pOwnerName,
  713. IPUNION_GET_IP4(pIp),
  714. Ttl,
  715. NameCharSet,
  716. RecordCharSet );
  717. }
  718. else
  719. {
  720. return Dns_CreateAAAARecord(
  721. pOwnerName,
  722. IPUNION_GET_IP6(pIp),
  723. Ttl,
  724. NameCharSet,
  725. RecordCharSet );
  726. }
  727. }
  728. PDNS_RECORD
  729. Dns_CreateForwardRecordForSockaddr(
  730. IN PDNS_NAME pOwnerName,
  731. IN PSOCKADDR pSockaddr,
  732. IN DWORD Ttl,
  733. IN DNS_CHARSET NameCharSet,
  734. IN DNS_CHARSET RecordCharSet
  735. )
  736. /*++
  737. Routine Description:
  738. Create forward lookup record.
  739. This is just a shim to avoid duplicating selection logic.
  740. Arguments:
  741. pOwnerName -- owner name
  742. pSockaddr -- ptr to sockaddr
  743. Ttl -- TTL
  744. NameCharSet -- character set of name
  745. RecordCharSet -- character set for resulting record
  746. Return Value:
  747. Ptr to PTR record.
  748. NULL on error.
  749. --*/
  750. {
  751. PFAMILY_INFO pinfo;
  752. DNSDBG( TRACE, (
  753. "Dns_CreateForwardRecordForSockaddr()\n" ));
  754. pinfo = FamilyInfo_GetForSockaddr( pSockaddr );
  755. if ( !pinfo )
  756. {
  757. SetLastError( ERROR_INVALID_DATA );
  758. return NULL;
  759. }
  760. //
  761. // build flat record of desired type
  762. //
  763. return Dns_CreateFlatRecord(
  764. pOwnerName,
  765. pinfo->DnsType,
  766. (PBYTE)pSockaddr + pinfo->OffsetToAddrInSockaddr,
  767. pinfo->LengthAddr,
  768. Ttl,
  769. NameCharSet,
  770. RecordCharSet );
  771. }
  772. PDNS_RECORD
  773. Dns_CreateRecordForIpString_W(
  774. IN PCWSTR pwsName,
  775. IN WORD wType,
  776. IN DWORD Ttl
  777. )
  778. /*++
  779. Routine Description:
  780. Create record for IP string query.
  781. Arguments:
  782. pwsName -- name that may be IP string query
  783. wType -- type of query
  784. Return Value:
  785. Ptr to record for query, if query name\type is IP.
  786. NULL if query not for IP.
  787. --*/
  788. {
  789. IP_UNION ipUnion;
  790. PDNS_RECORD prr;
  791. DNSDBG( TRACE, (
  792. "\nDns_CreateRecordForIpString( %S, wType = %d )\n",
  793. pwsName,
  794. wType ));
  795. if ( !pwsName )
  796. {
  797. return NULL;
  798. }
  799. //
  800. // support A or AAAA queries for IP strings
  801. // - IP4 strings must be in w.x.y.z form otherwise
  802. // we convert the all numeric names also
  803. //
  804. // DCR: need A6 support for direct query
  805. //
  806. if ( wType == DNS_TYPE_A )
  807. {
  808. IP4_ADDRESS ip4;
  809. PCWSTR pdot;
  810. DWORD count;
  811. if ( ! Dns_Ip4StringToAddress_W(
  812. & ip4,
  813. (PWSTR) pwsName ) )
  814. {
  815. return NULL;
  816. }
  817. // verify three dot form w.x.y.z
  818. pdot = pwsName;
  819. count = 3;
  820. while ( count-- )
  821. {
  822. pdot = wcschr( pdot, L'.' );
  823. if ( !pdot || !*++pdot )
  824. {
  825. return( NULL );
  826. }
  827. }
  828. IPUNION_SET_IP4( &ipUnion, ip4 );
  829. }
  830. else if ( wType == DNS_TYPE_AAAA )
  831. {
  832. IP6_ADDRESS ip6;
  833. if ( ! Dns_Ip6StringToAddress_W(
  834. & ip6,
  835. (PWSTR) pwsName ) )
  836. {
  837. return NULL;
  838. }
  839. IPUNION_SET_IP6( &ipUnion, ip6 );
  840. }
  841. else
  842. {
  843. return NULL;
  844. }
  845. //
  846. // name is IP string -- build record
  847. //
  848. prr = Dns_CreateForwardRecord(
  849. (PDNS_NAME) pwsName,
  850. & ipUnion,
  851. Ttl,
  852. DnsCharSetUnicode,
  853. DnsCharSetUnicode );
  854. DNSDBG( TRACE, (
  855. "Create record %p for IP string %S type %d.\n",
  856. prr,
  857. pwsName,
  858. wType ));
  859. return prr;
  860. }
  861. //
  862. // End rralloc.c
  863. //