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.

1222 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. localip.c
  5. Abstract:
  6. Local IP address routines.
  7. Author:
  8. Jim Gilroy October 2000
  9. Revision History:
  10. --*/
  11. #include "local.h"
  12. //
  13. // TTL on local records
  14. //
  15. // Use registration TTL
  16. //
  17. #define LOCAL_IP_TTL (g_RegistrationTtl)
  18. PDNS_ADDR_ARRAY
  19. GetLocalAddrArrayFromResolver(
  20. VOID
  21. )
  22. /*++
  23. Routine Description:
  24. Get local address info from resolver.
  25. Arguments:
  26. None
  27. Return Value:
  28. Ptr to address info array from resolver.
  29. NULL on failure.
  30. --*/
  31. {
  32. DNS_STATUS rpcStatus;
  33. PDNS_ADDR_ARRAY paddrArray = NULL;
  34. ENVAR_DWORD_INFO filterInfo;
  35. //
  36. // get config including environment variable
  37. //
  38. Reg_ReadDwordEnvar(
  39. RegIdFilterClusterIp,
  40. &filterInfo );
  41. //
  42. // query resolver
  43. //
  44. RpcTryExcept
  45. {
  46. rpcStatus = NO_ERROR;
  47. R_ResolverGetLocalAddrInfoArray(
  48. NULL,
  49. & paddrArray,
  50. filterInfo
  51. );
  52. }
  53. RpcExcept( DNS_RPC_EXCEPTION_FILTER )
  54. {
  55. rpcStatus = RpcExceptionCode();
  56. }
  57. RpcEndExcept
  58. // return array
  59. DNS_ASSERT( !rpcStatus || !paddrArray );
  60. return paddrArray;
  61. }
  62. PIP4_ARRAY
  63. LocalIp_GetIp4Array(
  64. VOID
  65. )
  66. /*++
  67. Routine Description:
  68. Get local IP4 address array.
  69. Arguments:
  70. None
  71. Return Value:
  72. Ptr to IP4 addresses.
  73. NULL on failure.
  74. --*/
  75. {
  76. PDNS_ADDR_ARRAY paddrArray = NULL;
  77. PIP4_ARRAY pipArray = NULL;
  78. DWORD count;
  79. DWORD i;
  80. //
  81. // addr info array from resolver
  82. // => build IP array from IPs
  83. //
  84. paddrArray = GetLocalAddrArrayFromResolver();
  85. if ( paddrArray )
  86. {
  87. count = paddrArray->AddrCount;
  88. if ( count > 0 )
  89. {
  90. pipArray = (PIP4_ARRAY) DnsCreateIpArray( count );
  91. if ( pipArray )
  92. {
  93. for ( i=0; i < count; i++ )
  94. {
  95. pipArray->AddrArray[i] = paddrArray->AddrArray[i].IpAddr;
  96. }
  97. goto Done;
  98. }
  99. }
  100. }
  101. //
  102. // no array from resolver -- build directly
  103. // - no chance to filter
  104. //
  105. count = 0;
  106. pipArray = (PIP4_ARRAY) Dns_GetLocalIpAddressArray();
  107. if ( pipArray )
  108. {
  109. count = pipArray->AddrCount;
  110. if ( count == 0 )
  111. {
  112. FREE_HEAP( pipArray );
  113. pipArray = NULL;
  114. }
  115. }
  116. Done:
  117. // free blob from resolver
  118. if ( paddrArray )
  119. {
  120. FREE_HEAP( paddrArray );
  121. }
  122. // set out param
  123. return( pipArray );
  124. }
  125. DWORD
  126. DnsGetIpAddressInfoList(
  127. OUT PDNS_ADDRESS_INFO * ppAddrInfo
  128. )
  129. /*++
  130. Routine Description:
  131. Get local IP4 address info -- include IP and subnet mask.
  132. DCR: good to get rid of old DNS_ADDRESS_INFO function
  133. Only use of this function is in DHCP, which is calling here rather
  134. than IP help API for some reason.
  135. Arguments:
  136. ppAddrInfo -- addr to recv ptr to addr info array;
  137. caller must free
  138. Return Value:
  139. Count of IP addresses in array.
  140. Zero on failure.
  141. --*/
  142. {
  143. PDNS_ADDR_ARRAY paddrArray = NULL;
  144. PDNS_ADDRESS_INFO pnew = NULL;
  145. PDNS_ADDRESS_INFO pinfo;
  146. DWORD count;
  147. DNS_ADDRESS_INFO infoBuffer[256];
  148. //
  149. // addr info array from resolver
  150. // => build IP array from IPs
  151. //
  152. // DCR_WARNING: ADDR_INFO to ADDRESS_INFO conversion
  153. // if keep this function and change ADDR_INFO for IP6
  154. // then this quicky hack breaks
  155. //
  156. paddrArray = GetLocalAddrArrayFromResolver();
  157. if ( paddrArray )
  158. {
  159. count = paddrArray->AddrCount;
  160. pinfo = (PDNS_ADDRESS_INFO) paddrArray->AddrArray;
  161. }
  162. //
  163. // no array from resolver -- build directly
  164. //
  165. else
  166. {
  167. count = Dns_GetIpAddresses( infoBuffer, 256 );
  168. pinfo = infoBuffer;
  169. }
  170. //
  171. // allocate result buffer
  172. // copy addr info array to buffer
  173. //
  174. if ( count )
  175. {
  176. DWORD size = count * sizeof(DNS_ADDRESS_INFO);
  177. pnew = (PDNS_ADDRESS_INFO) ALLOCATE_HEAP( size );
  178. if ( !pnew )
  179. {
  180. count = 0;
  181. goto Done;
  182. }
  183. RtlCopyMemory(
  184. pnew,
  185. pinfo,
  186. size );
  187. }
  188. Done:
  189. // free blob from resolver
  190. if ( paddrArray )
  191. {
  192. FREE_HEAP( paddrArray );
  193. }
  194. // set out param
  195. *ppAddrInfo = pnew;
  196. return( count );
  197. }
  198. PDNS_ADDR_ARRAY
  199. DnsGetLocalAddrArray(
  200. VOID
  201. )
  202. /*++
  203. Routine Description:
  204. Get local address info array.
  205. Arguments:
  206. None.
  207. Return Value:
  208. Ptr to new addr info array. Caller MUST free.
  209. NULL on error.
  210. --*/
  211. {
  212. PDNS_ADDR_ARRAY paddrArray;
  213. DNSDBG( TRACE, ( "DnsGetLocalAddrArray()\n" ));
  214. //
  215. // addr info array from resolver
  216. // => build IP array from IPs
  217. //
  218. paddrArray = GetLocalAddrArrayFromResolver();
  219. if ( paddrArray )
  220. {
  221. return paddrArray;
  222. }
  223. //
  224. // no array from resolver -- build directly
  225. //
  226. return DnsGetLocalAddrArrayDirect();
  227. }
  228. //
  229. // Direct routines -- build the IP info
  230. //
  231. PDNS_ADDR_ARRAY
  232. DnsGetLocalAddrArrayDirect(
  233. VOID
  234. )
  235. /*++
  236. Routine Description:
  237. Get local address info array.
  238. Arguments:
  239. None.
  240. Return Value:
  241. Ptr to addr info array.
  242. NULL on failure.
  243. --*/
  244. {
  245. PDNS_ADDRESS_INFO pqueryBuf;
  246. PDNS_ADDR_ARRAY pnew = NULL;
  247. DWORD count;
  248. DWORD size;
  249. DNSDBG( TRACE, ( "DnsGetLocalAddrArrayDirect()\n" ));
  250. //
  251. // create big buffer IP help call
  252. //
  253. pqueryBuf = ALLOCATE_HEAP( sizeof(DNS_ADDRESS_INFO) *
  254. DNS_MAX_IP_INTERFACE_COUNT );
  255. if ( !pqueryBuf )
  256. {
  257. SetLastError( DNS_ERROR_NO_MEMORY );
  258. return( NULL );
  259. }
  260. //
  261. // get IP addresses
  262. // - if zero, determine is error or really no IPs
  263. //
  264. count = Dns_GetIpAddresses(
  265. pqueryBuf,
  266. DNS_MAX_IP_INTERFACE_COUNT );
  267. #if 0
  268. // don't really need this
  269. // if can't get count -- it's zero
  270. // to use this on Win2K would have to change
  271. // Dns_GetIpAddresses() which is in lib
  272. if ( count == 0 )
  273. {
  274. if ( GetLastError() != NO_ERROR )
  275. {
  276. goto Cleanup;
  277. }
  278. }
  279. #endif
  280. //
  281. // build correctly sized array
  282. //
  283. size = SIZE_FOR_ADDR_ARRAY( count );
  284. pnew = (PDNS_ADDR_ARRAY) ALLOCATE_HEAP( size );
  285. if ( !pnew )
  286. {
  287. SetLastError( DNS_ERROR_NO_MEMORY );
  288. goto Cleanup;
  289. }
  290. pnew->AddrCount = count;
  291. RtlCopyMemory(
  292. pnew->AddrArray,
  293. pqueryBuf,
  294. count * sizeof(DNS_ADDR_INFO)
  295. );
  296. Cleanup:
  297. FREE_HEAP( pqueryBuf );
  298. return( pnew );
  299. }
  300. //
  301. // Build local records
  302. //
  303. PDNS_RECORD
  304. GetLocalPtrRecord(
  305. IN OUT PQUERY_BLOB pBlob
  306. )
  307. /*++
  308. Routine Description:
  309. Get pointer record for local IP.
  310. Arguments:
  311. pBlob -- query blob
  312. Uses:
  313. pNameOrig
  314. wType
  315. pNetInfo
  316. Sets:
  317. NameBufferWide -- used as local storage
  318. Return Value:
  319. Ptr to record for query, if query name\type is IP.
  320. NULL if query not for IP.
  321. --*/
  322. {
  323. IP_UNION ipUnion;
  324. PDNS_RECORD prr;
  325. IP4_ADDRESS ip4;
  326. PSTR pnameHost = NULL;
  327. PSTR pnameDomain;
  328. PDNS_ADAPTER padapter = NULL;
  329. DWORD iter;
  330. DWORD jter;
  331. DWORD bufLength;
  332. INT family;
  333. PSTR pnameQuery = pBlob->pNameOrigWire;
  334. PDNS_NETINFO pnetInfo = pBlob->pNetworkInfo;
  335. DNSDBG( TRACE, (
  336. "\nGetLocalPtrRecord( %s )\n",
  337. pnameQuery ));
  338. if ( !pnameQuery )
  339. {
  340. return NULL;
  341. }
  342. //
  343. // convert reverse name to IP
  344. //
  345. bufLength = sizeof(IP6_ADDRESS);
  346. family = 0;
  347. if ( ! Dns_ReverseNameToAddress_A(
  348. (PCHAR) & ipUnion.Addr,
  349. & bufLength,
  350. pnameQuery,
  351. & family ) )
  352. {
  353. DNSDBG( ANY, (
  354. "WARNING: Ptr lookup name %s is not reverse name!\n",
  355. pnameQuery ));
  356. return NULL;
  357. }
  358. ipUnion.IsIp6 = (family == AF_INET6 );
  359. //
  360. // check for IP match
  361. // - first loopback or any
  362. //
  363. if ( ipUnion.IsIp6 )
  364. {
  365. if ( IP6_IS_ADDR_UNSPECIFIED( (PIP6_ADDRESS)&ipUnion.Addr ) ||
  366. IP6_IS_ADDR_LOOPBACK( (PIP6_ADDRESS)&ipUnion.Addr ) )
  367. {
  368. goto Matched;
  369. }
  370. // DCR: no IP6 local addresses
  371. DNSDBG( QUERY, (
  372. "Local PTR lookup -- no local IP6 info -- quiting.\n" ));
  373. return NULL;
  374. }
  375. ip4 = ipUnion.Addr.Ip4;
  376. if ( ip4 == DNS_NET_ORDER_LOOPBACK ||
  377. ip4 == 0 )
  378. {
  379. DNSDBG( QUERY, (
  380. "Local PTR lookup matched loopback or any.\n" ));
  381. goto Matched;
  382. }
  383. //
  384. // check for cluster match
  385. //
  386. // if cluster match, allow query to go to wire
  387. //
  388. // DCR: cluster record PTR build for cluster name
  389. //
  390. if ( pBlob->pfnIsClusterIp )
  391. {
  392. if ( (pBlob->pfnIsClusterIp)(
  393. pBlob,
  394. &ipUnion ) )
  395. {
  396. return NULL;
  397. }
  398. }
  399. //
  400. // check for specific IP match
  401. //
  402. for ( iter = 0;
  403. iter < pnetInfo->AdapterCount;
  404. iter ++ )
  405. {
  406. PIP_ARRAY parray;
  407. padapter = pnetInfo->AdapterArray[iter];
  408. if ( !padapter )
  409. {
  410. continue;
  411. }
  412. parray = padapter->pAdapterIPAddresses;
  413. if ( !parray )
  414. {
  415. DNSDBG( QUERY, (
  416. "Local PTR lookup -- no IPs for adapter name (%s).\n",
  417. padapter->pszAdapterDomain ));
  418. continue;
  419. }
  420. for ( jter = 0;
  421. jter < parray->AddrCount;
  422. jter++ )
  423. {
  424. if ( parray->AddrArray[jter] == ip4 )
  425. {
  426. goto Matched;
  427. }
  428. }
  429. }
  430. //
  431. // no IP match
  432. //
  433. DNSDBG( QUERY, (
  434. "Leave local PTR lookup. No local IP match.\n"
  435. "\treverse name = %s\n",
  436. pnameQuery ));
  437. return NULL;
  438. Matched:
  439. //
  440. // create hostname
  441. // preference order:
  442. // - full PDN
  443. // - full adapter domain name from adapter with IP
  444. // - hostname (single label)
  445. // - "localhost"
  446. //
  447. {
  448. PCHAR pnameBuf = (PCHAR) pBlob->NameBufferWide;
  449. pnameHost = pnetInfo->pszHostName;
  450. if ( !pnameHost )
  451. {
  452. pnameHost = "localhost";
  453. goto Build;
  454. }
  455. pnameDomain = pnetInfo->pszDomainName;
  456. if ( !pnameDomain )
  457. {
  458. // use the adapter name even if NOT set for registration
  459. // if ( !padapter ||
  460. // !(padapter->InfoFlags & DNS_FLAG_REGISTER_DOMAIN_NAME) )
  461. if ( !padapter )
  462. {
  463. goto Build;
  464. }
  465. pnameDomain = padapter->pszAdapterDomain;
  466. if ( !pnameDomain )
  467. {
  468. goto Build;
  469. }
  470. }
  471. if ( ! Dns_NameAppend_A(
  472. pnameBuf,
  473. DNS_MAX_NAME_BUFFER_LENGTH,
  474. pnameHost,
  475. pnameDomain ) )
  476. {
  477. DNS_ASSERT( FALSE );
  478. goto Build;
  479. }
  480. pnameHost = pnameBuf;
  481. Build:
  482. //
  483. // create record
  484. //
  485. prr = Dns_CreatePtrRecordEx(
  486. & ipUnion,
  487. pnameHost,
  488. LOCAL_IP_TTL,
  489. DnsCharSetUtf8,
  490. DnsCharSetUnicode );
  491. if ( !prr )
  492. {
  493. DNSDBG( ANY, (
  494. "Local PTR record creation failed for name %s!\n",
  495. pnameHost ));
  496. return NULL;
  497. }
  498. }
  499. DNSDBG( QUERY, (
  500. "Created local PTR record %p with hostname %s.\n"
  501. "\treverse name = %S\n",
  502. prr,
  503. pnameHost,
  504. pnameQuery ));
  505. return prr;
  506. }
  507. PDNS_RECORD
  508. BuildRecordForLocalIp4(
  509. IN PSTR pszName,
  510. IN IP4_ADDRESS IpAddr,
  511. IN IS_CLUSTER_IP_FUNC pfnIsClusterIp
  512. )
  513. /*++
  514. Routine Description:
  515. Build local IP record.
  516. Wraps up default cluster filtering and record
  517. building.
  518. Arguments:
  519. pszName -- name of record
  520. IpAddr -- IP4 address
  521. pfnIsClusterIp -- filtering function
  522. Return Value:
  523. TRUE if created record.
  524. FALSE on error (cluster IP or mem alloc failure).
  525. --*/
  526. {
  527. PDNS_RECORD prr;
  528. DNSDBG( TRACE, (
  529. "BuildRecordForLocalIp4( %s, %s )\n",
  530. pszName,
  531. IP_STRING(IpAddr) ));
  532. // filter off cluster IP -- if desired
  533. if ( pfnIsClusterIp )
  534. {
  535. IP_UNION ipUnion;
  536. IPUNION_SET_IP4( &ipUnion, IpAddr );
  537. if ( pfnIsClusterIp(
  538. NULL, // no blob required
  539. &ipUnion ) )
  540. {
  541. return NULL;
  542. }
  543. }
  544. // create the record
  545. return Dns_CreateARecord(
  546. pszName,
  547. IpAddr,
  548. LOCAL_IP_TTL,
  549. DnsCharSetUtf8,
  550. DnsCharSetUnicode );
  551. }
  552. PDNS_RECORD
  553. GetLocalAddressRecord(
  554. IN OUT PQUERY_BLOB pBlob
  555. )
  556. /*++
  557. Routine Description:
  558. Get address record for local IP.
  559. Arguments:
  560. pBlob -- query blob
  561. Uses:
  562. pNameOrig
  563. wType
  564. pNetInfo
  565. Sets:
  566. fNoIpLocal
  567. TRUE -- no IP of type found, defaulted record
  568. FALSE -- records valid
  569. NameBufferWide -- used as local storage
  570. Return Value:
  571. Ptr to record for query, if query name\type is IP.
  572. NULL if query not for IP.
  573. --*/
  574. {
  575. IP_UNION ipUnion;
  576. IP4_ADDRESS ip4;
  577. IP6_ADDRESS ip6;
  578. PDNS_RECORD prr;
  579. BOOL fmatchedName = FALSE;
  580. PSTR pnameRecord = NULL;
  581. PWSTR pnameRecordWide = NULL;
  582. DWORD iter;
  583. DWORD jter;
  584. DWORD bufLength;
  585. PSTR pnameDomain;
  586. DNS_RRSET rrset;
  587. WORD wtype = pBlob->wType;
  588. PSTR pnameBuf = (PCHAR) pBlob->NameBufferWide;
  589. PWSTR pnameQuery = pBlob->pNameOrig;
  590. PDNS_NETINFO pnetInfo = pBlob->pNetworkInfo;
  591. IS_CLUSTER_IP_FUNC pfnClusterFilter;
  592. DNSDBG( TRACE, (
  593. "GetLocalAddressRecord( %S, %d )\n",
  594. pnameQuery,
  595. wtype ));
  596. // clear out param
  597. pBlob->fNoIpLocal = FALSE;
  598. //
  599. // NULL treated as local PDN
  600. //
  601. if ( !pnameQuery )
  602. {
  603. DNSDBG( QUERY, ( "Local lookup -- no query name, treat as PDN.\n" ));
  604. goto MatchedPdn;
  605. }
  606. //
  607. // loopback or localhost
  608. //
  609. if ( Dns_NameCompare_W(
  610. pnameQuery,
  611. L"loopback" )
  612. ||
  613. Dns_NameCompare_W(
  614. pnameQuery,
  615. L"localhost" ) )
  616. {
  617. pnameRecord = (PSTR) pnameQuery,
  618. IP6_SET_ADDR_LOOPBACK( &ip6 );
  619. ip4 = DNS_NET_ORDER_LOOPBACK;
  620. goto SingleIp;
  621. }
  622. //
  623. // if no hostname -- done
  624. //
  625. if ( !pnetInfo->pszHostName )
  626. {
  627. DNSDBG( QUERY, ( "No hostname configured!\n" ));
  628. return NULL;
  629. }
  630. //
  631. // copy wire format name
  632. //
  633. if ( ! Dns_NameCopyStandard_A(
  634. pnameBuf,
  635. pBlob->pNameOrigWire ) )
  636. {
  637. DNSDBG( ANY, (
  638. "Invalid name %S to local address query.\n",
  639. pnameQuery ));
  640. return NULL;
  641. }
  642. // split query name into hostname and domain name
  643. pnameDomain = Dns_SplitHostFromDomainName_A( pnameBuf );
  644. // must have hostname match
  645. if ( !Dns_NameCompare_UTF8(
  646. pnameBuf,
  647. pnetInfo->pszHostName ) )
  648. {
  649. DNSDBG( ANY, (
  650. "Local lookup, failed hostname match!\n",
  651. pnameQuery ));
  652. return NULL;
  653. }
  654. //
  655. // hostname's match
  656. // - no domain name => PDN equivalent
  657. // - match PDN => all addresses
  658. // - match adapter name => adapter addresses
  659. // - no match
  660. //
  661. // first setup
  662. // - RR set builder
  663. // - filtering function
  664. //
  665. DNS_RRSET_INIT( rrset );
  666. pfnClusterFilter = pBlob->pfnIsClusterIp;
  667. if ( pfnClusterFilter &&
  668. !(pBlob->Flags & DNSP_QUERY_FILTER_CLUSTER) )
  669. {
  670. pfnClusterFilter = NULL;
  671. }
  672. if ( !pnameDomain )
  673. {
  674. DNSDBG( QUERY, ( "Local lookup -- no domain, treat as PDN!\n" ));
  675. goto MatchedPdn;
  676. }
  677. // check PDN match
  678. if ( Dns_NameCompare_UTF8(
  679. pnameDomain,
  680. pnetInfo->pszDomainName ) )
  681. {
  682. DNSDBG( QUERY, ( "Local lookup -- matched PDN!\n" ));
  683. goto MatchedPdn;
  684. }
  685. //
  686. // check adapter name match
  687. //
  688. for ( iter = 0;
  689. iter < pnetInfo->AdapterCount;
  690. iter ++ )
  691. {
  692. PDNS_ADAPTER padapter = pnetInfo->AdapterArray[iter];
  693. PIP_ARRAY parray;
  694. if ( !padapter ||
  695. !(padapter->InfoFlags & DNS_FLAG_REGISTER_DOMAIN_NAME) )
  696. {
  697. continue;
  698. }
  699. if ( ! Dns_NameCompare_UTF8(
  700. pnameDomain,
  701. padapter->pszAdapterDomain ) )
  702. {
  703. continue;
  704. }
  705. // build name if we haven't built it before
  706. // we stay in the loop in case more than one
  707. // adapter has the same domain name
  708. if ( !fmatchedName )
  709. {
  710. DNSDBG( QUERY, (
  711. "Local lookup -- matched adapter name %s\n",
  712. padapter->pszAdapterDomain ));
  713. if ( ! Dns_NameAppend_A(
  714. pnameBuf,
  715. DNS_MAX_NAME_BUFFER_LENGTH,
  716. pnetInfo->pszHostName,
  717. padapter->pszAdapterDomain ) )
  718. {
  719. DNS_ASSERT( FALSE );
  720. return NULL;
  721. }
  722. pnameRecord = pnameBuf;
  723. fmatchedName = TRUE;
  724. }
  725. // build forward records for all IPs in list
  726. //
  727. // DCR: IP6 addresses missing
  728. if ( wtype == DNS_TYPE_AAAA )
  729. {
  730. goto NoIp;
  731. }
  732. // no IP for adapter?
  733. parray = padapter->pAdapterIPAddresses;
  734. if ( !parray )
  735. {
  736. DNSDBG( QUERY, (
  737. "Local lookup -- no IPs for adapter name (%s) matched!\n",
  738. padapter->pszAdapterDomain ));
  739. }
  740. // build records for adapter IPs
  741. for ( jter = 0;
  742. jter < parray->AddrCount;
  743. jter++ )
  744. {
  745. prr = BuildRecordForLocalIp4(
  746. pnameRecord,
  747. parray->AddrArray[jter],
  748. pfnClusterFilter );
  749. if ( prr )
  750. {
  751. pnameRecord = NULL;
  752. DNS_RRSET_ADD( rrset, prr );
  753. }
  754. }
  755. }
  756. // done with adapter name
  757. // either
  758. // - no match
  759. // - match but didn't get IPs
  760. // - match
  761. if ( !fmatchedName )
  762. {
  763. DNSDBG( QUERY, (
  764. "Leave GetLocalAddressRecord() => no domain name match.\n" ));
  765. return NULL;
  766. }
  767. prr = rrset.pFirstRR;
  768. if ( prr )
  769. {
  770. DNSDBG( QUERY, (
  771. "Leave GetLocalAddressRecord() => %p matched adapter name.\n",
  772. prr ));
  773. return prr;
  774. }
  775. goto NoIp;
  776. MatchedPdn:
  777. //
  778. // matched PDN
  779. //
  780. // must build in specific order
  781. // - first IP in each adapter
  782. // - remainder of IPs on adapters
  783. //
  784. fmatchedName = TRUE;
  785. if ( ! Dns_NameAppend_A(
  786. pnameBuf,
  787. DNS_MAX_NAME_BUFFER_LENGTH,
  788. pnetInfo->pszHostName,
  789. pnetInfo->pszDomainName ) )
  790. {
  791. DNS_ASSERT( FALSE );
  792. return NULL;
  793. }
  794. pnameRecord = pnameBuf;
  795. // DCR: IP6 addresses missing
  796. if ( wtype == DNS_TYPE_AAAA )
  797. {
  798. goto NoIp;
  799. }
  800. // get first IP in each adapter
  801. for ( iter = 0;
  802. iter < pnetInfo->AdapterCount;
  803. iter ++ )
  804. {
  805. PDNS_ADAPTER padapter = pnetInfo->AdapterArray[iter];
  806. PIP_ARRAY parray;
  807. if ( !padapter ||
  808. !(parray = padapter->pAdapterIPAddresses) )
  809. {
  810. continue;
  811. }
  812. prr = BuildRecordForLocalIp4(
  813. pnameRecord,
  814. parray->AddrArray[0],
  815. pfnClusterFilter );
  816. if ( prr )
  817. {
  818. pnameRecord = NULL;
  819. DNS_RRSET_ADD( rrset, prr );
  820. }
  821. }
  822. // get rest of IPs in each adapter
  823. for ( iter = 0;
  824. iter < pnetInfo->AdapterCount;
  825. iter ++ )
  826. {
  827. PDNS_ADAPTER padapter = pnetInfo->AdapterArray[iter];
  828. PIP_ARRAY parray;
  829. if ( !padapter ||
  830. !(parray = padapter->pAdapterIPAddresses) )
  831. {
  832. continue;
  833. }
  834. for ( jter = 1;
  835. jter < parray->AddrCount;
  836. jter++ )
  837. {
  838. prr = BuildRecordForLocalIp4(
  839. pnameRecord,
  840. parray->AddrArray[jter],
  841. pfnClusterFilter );
  842. if ( prr )
  843. {
  844. pnameRecord = NULL;
  845. DNS_RRSET_ADD( rrset, prr );
  846. }
  847. }
  848. }
  849. // if successfully built -- done
  850. prr = rrset.pFirstRR;
  851. if ( prr )
  852. {
  853. DNSDBG( QUERY, (
  854. "Leave GetLocalAddressRecord() => %p matched PDN name.\n",
  855. prr ));
  856. return prr;
  857. }
  858. // matched name but found no records
  859. // fall through to NoIp section
  860. //
  861. //goto NoIp;
  862. NoIp:
  863. //
  864. // matched name -- but no IP
  865. // use loopback address; assume this is a lookup prior to
  866. // connect which happens to be the local name, rather than an
  867. // explict local lookup to get binding IPs
  868. //
  869. // DCR: fix IP6 hack for local names
  870. DNSDBG( ANY, (
  871. "WARNING: local name match but no IP -- using loopback\n" ));
  872. IP6_SET_ADDR_LOOPBACK( &ip6 );
  873. ip4 = DNS_NET_ORDER_LOOPBACK;
  874. pBlob->fNoIpLocal = TRUE;
  875. // fall through to single IP
  876. SingleIp:
  877. // single IP
  878. // - loopback address and be unicode queried name
  879. // - no IP failure (zero IP) and be UTF8 PDN name
  880. if ( wtype == DNS_TYPE_A )
  881. {
  882. IPUNION_SET_IP4( &ipUnion, ip4 );
  883. }
  884. else
  885. {
  886. IPUNION_SET_IP6( &ipUnion, ip6 );
  887. }
  888. prr = Dns_CreateForwardRecord(
  889. (PSTR) pnameRecord,
  890. & ipUnion,
  891. LOCAL_IP_TTL,
  892. (pnameRecord == (PSTR)pnameQuery)
  893. ? DnsCharSetUnicode
  894. : DnsCharSetUtf8,
  895. DnsCharSetUnicode );
  896. return prr;
  897. }
  898. DNS_STATUS
  899. GetRecordsForLocalName(
  900. IN OUT PQUERY_BLOB pBlob
  901. )
  902. /*++
  903. Routine Description:
  904. Get local address info array.
  905. Arguments:
  906. pBlob -- query blob
  907. Uses:
  908. pNameOrig
  909. wType
  910. pNetInfo
  911. Sets:
  912. pLocalRecords
  913. fNoIpLocal if local name without records
  914. Return Value:
  915. ERROR_SUCCESS if successful.
  916. DNS_ERROR_RCODE_NAME_ERROR on failure.
  917. --*/
  918. {
  919. WORD wtype = pBlob->wType;
  920. PDNS_RECORD prr = NULL;
  921. if ( wtype == DNS_TYPE_A ||
  922. wtype == DNS_TYPE_AAAA )
  923. {
  924. prr = GetLocalAddressRecord( pBlob );
  925. }
  926. else if ( wtype == DNS_TYPE_PTR )
  927. {
  928. prr = GetLocalPtrRecord( pBlob );
  929. }
  930. // set local records
  931. // - if not NO IP situation then this
  932. // is final query result also
  933. if ( prr )
  934. {
  935. pBlob->pLocalRecords = prr;
  936. if ( !pBlob->fNoIpLocal )
  937. {
  938. pBlob->pRecords = prr;
  939. }
  940. return ERROR_SUCCESS;
  941. }
  942. return DNS_ERROR_RCODE_NAME_ERROR;
  943. }
  944. //
  945. // End localip.c
  946. //