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.

3354 lines
61 KiB

  1. /*++
  2. Copyright (c) 2001-2002 Microsoft Corporation
  3. Module Name:
  4. dnsaddr.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. DNS_ADDR routines.
  8. Author:
  9. Jim Gilroy (jamesg) November 2001
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. //
  14. // DNS_ADDR routines
  15. //
  16. WORD
  17. DnsAddr_DnsType(
  18. IN PDNS_ADDR pAddr
  19. )
  20. /*++
  21. Routine Description:
  22. Get DNS type corresponding to DNS_ADDR.
  23. DCR: DnsAddr_DnsType could be a macro
  24. currently a function simply because Family_X
  25. are in lower-pri header file; once determine
  26. if Family_X available everywhere we want DNS_ADDR
  27. routines, then can macroize
  28. Arguments:
  29. pAddr -- first addr
  30. Return Value:
  31. TRUE if loopback.
  32. FALSE otherwise.
  33. --*/
  34. {
  35. return Family_DnsType( DnsAddr_Family(pAddr) );
  36. }
  37. BOOL
  38. DnsAddr_IsEqual(
  39. IN PDNS_ADDR pAddr1,
  40. IN PDNS_ADDR pAddr2,
  41. IN DWORD MatchFlag
  42. )
  43. /*++
  44. Routine Description:
  45. Test if DNS_ADDRs are equal.
  46. Arguments:
  47. pAddr1 -- first addr
  48. pAddr2 -- second addr
  49. MatchFlag -- level of match
  50. Return Value:
  51. TRUE if loopback.
  52. FALSE otherwise.
  53. --*/
  54. {
  55. if ( MatchFlag == 0 ||
  56. MatchFlag == DNSADDR_MATCH_ALL )
  57. {
  58. return RtlEqualMemory(
  59. pAddr1,
  60. pAddr2,
  61. sizeof(*pAddr1) );
  62. }
  63. else if ( MatchFlag == DNSADDR_MATCH_SOCKADDR )
  64. {
  65. return RtlEqualMemory(
  66. pAddr1,
  67. pAddr2,
  68. DNS_ADDR_MAX_SOCKADDR_LENGTH );
  69. }
  70. //
  71. // DCR: currently no separate match to include scope
  72. // could dispatch to separate match routines for AF
  73. // compare families, then dispatch
  74. //
  75. else if ( MatchFlag & DNSADDR_MATCH_IP )
  76. // else if ( MatchFlag == DNSADDR_MATCH_IP )
  77. {
  78. if ( DnsAddr_IsIp4( pAddr1 ) )
  79. {
  80. return( DnsAddr_IsIp4( pAddr2 )
  81. &&
  82. DnsAddr_GetIp4(pAddr1) == DnsAddr_GetIp4(pAddr2) );
  83. }
  84. else if ( DnsAddr_IsIp6( pAddr1 ) )
  85. {
  86. return( DnsAddr_IsIp6( pAddr2 )
  87. &&
  88. IP6_ARE_ADDRS_EQUAL(
  89. DnsAddr_GetIp6Ptr(pAddr1),
  90. DnsAddr_GetIp6Ptr(pAddr2) ) );
  91. }
  92. return FALSE;
  93. }
  94. ELSE_ASSERT_FALSE;
  95. return RtlEqualMemory(
  96. pAddr1,
  97. pAddr2,
  98. DNS_ADDR_MAX_SOCKADDR_LENGTH );
  99. }
  100. BOOL
  101. DnsAddr_MatchesIp4(
  102. IN PDNS_ADDR pAddr,
  103. IN IP4_ADDRESS Ip4
  104. )
  105. /*++
  106. Routine Description:
  107. Test if DNS_ADDR is a given IP4.
  108. Arguments:
  109. pAddr -- first addr
  110. Ip4 -- IP4 address
  111. Return Value:
  112. TRUE if loopback.
  113. FALSE otherwise.
  114. --*/
  115. {
  116. return ( DnsAddr_IsIp4( pAddr )
  117. &&
  118. Ip4 == DnsAddr_GetIp4(pAddr) );
  119. }
  120. BOOL
  121. DnsAddr_MatchesIp6(
  122. IN PDNS_ADDR pAddr,
  123. IN PIP6_ADDRESS pIp6
  124. )
  125. /*++
  126. Routine Description:
  127. Test if DNS_ADDR is a given IP6.
  128. Arguments:
  129. pAddr -- first addr
  130. pIp6 -- IP6 address
  131. Return Value:
  132. TRUE if loopback.
  133. FALSE otherwise.
  134. --*/
  135. {
  136. return ( DnsAddr_IsIp6( pAddr )
  137. &&
  138. IP6_ARE_ADDRS_EQUAL(
  139. DnsAddr_GetIp6Ptr(pAddr),
  140. pIp6 ) );
  141. }
  142. BOOL
  143. DnsAddr_IsLoopback(
  144. IN PDNS_ADDR pAddr,
  145. IN DWORD Family
  146. )
  147. /*++
  148. Routine Description:
  149. Test if DNS_ADDR is loopback.
  150. Arguments:
  151. pAddr -- addr to set with IP6 address
  152. Family --
  153. AF_INET6 to only accept if 6
  154. AF_INET4 to only accept if 4
  155. 0 to extract always
  156. Return Value:
  157. TRUE if loopback.
  158. FALSE otherwise.
  159. --*/
  160. {
  161. DWORD addrFam = DnsAddr_Family(pAddr);
  162. if ( Family == 0 ||
  163. Family == addrFam )
  164. {
  165. if ( addrFam == AF_INET6 )
  166. {
  167. return IP6_IS_ADDR_LOOPBACK(
  168. (PIP6_ADDRESS)&pAddr->SockaddrIn6.sin6_addr );
  169. }
  170. else if ( addrFam == AF_INET )
  171. {
  172. return (pAddr->SockaddrIn.sin_addr.s_addr == DNS_NET_ORDER_LOOPBACK);
  173. }
  174. }
  175. return FALSE;
  176. }
  177. BOOL
  178. DnsAddr_IsUnspec(
  179. IN PDNS_ADDR pAddr,
  180. IN DWORD Family
  181. )
  182. /*++
  183. Routine Description:
  184. Test if DNS_ADDR is unspecied.
  185. Arguments:
  186. pAddr -- addr to test
  187. Family --
  188. AF_INET6 to only accept if 6
  189. AF_INET4 to only accept if 4
  190. 0 to extract always
  191. Return Value:
  192. TRUE if unspecified.
  193. FALSE otherwise.
  194. --*/
  195. {
  196. DWORD family = DnsAddr_Family(pAddr);
  197. if ( Family == 0 ||
  198. Family == family )
  199. {
  200. if ( family == AF_INET6 )
  201. {
  202. return IP6_IS_ADDR_ZERO( (PIP6_ADDRESS)&pAddr->SockaddrIn6.sin6_addr );
  203. }
  204. else if ( family == AF_INET )
  205. {
  206. return (pAddr->SockaddrIn.sin_addr.s_addr == 0);
  207. }
  208. }
  209. return FALSE;
  210. }
  211. BOOL
  212. DnsAddr_IsClear(
  213. IN PDNS_ADDR pAddr
  214. )
  215. /*++
  216. Routine Description:
  217. Test if DNS_ADDR is clear. This is similar to unspecified but includes
  218. invalid addresses (where family is zero) also.
  219. Arguments:
  220. pAddr -- addr test
  221. Return Value:
  222. TRUE if clear.
  223. FALSE otherwise.
  224. --*/
  225. {
  226. DWORD family = DnsAddr_Family( pAddr );
  227. if ( family == AF_INET6 )
  228. {
  229. return IP6_IS_ADDR_ZERO( (PIP6_ADDRESS)&pAddr->SockaddrIn6.sin6_addr );
  230. }
  231. else if ( family == AF_INET )
  232. {
  233. return pAddr->SockaddrIn.sin_addr.s_addr == 0;
  234. }
  235. else if ( family == 0 )
  236. {
  237. return TRUE;
  238. }
  239. ASSERT( FALSE ); // Family is invalid - not good.
  240. return FALSE;
  241. }
  242. BOOL
  243. DnsAddr_IsIp6DefaultDns(
  244. IN PDNS_ADDR pAddr
  245. )
  246. /*++
  247. Routine Description:
  248. Test if DNS_ADDR is IP6 default DNS addr.
  249. Arguments:
  250. pAddr -- addr to check
  251. Return Value:
  252. TRUE if IP6 default DNS.
  253. FALSE otherwise.
  254. --*/
  255. {
  256. if ( !DnsAddr_IsIp6( pAddr ) )
  257. {
  258. return FALSE;
  259. }
  260. return IP6_IS_ADDR_DEFAULT_DNS( (PIP6_ADDRESS)&pAddr->SockaddrIn6.sin6_addr );
  261. }
  262. //
  263. // DNS_ADDR to other types
  264. //
  265. DWORD
  266. DnsAddr_WriteSockaddr(
  267. OUT PSOCKADDR pSockaddr,
  268. IN DWORD SockaddrLength,
  269. IN PDNS_ADDR pAddr
  270. )
  271. /*++
  272. Routine Description:
  273. Write sockaddr with IP6 or IP4 address.
  274. Arguments:
  275. pSockaddr -- ptr to sockaddr
  276. pSockaddrLength -- ptr to DWORD
  277. input: holds length of pSockaddr buffer
  278. output: set to sockaddr length
  279. pAddr -- addr
  280. Return Value:
  281. Sockaddr length written.
  282. Zero if unable to write (bad sockaddr or inadequate length.
  283. --*/
  284. {
  285. DWORD length;
  286. DNSDBG( SOCKET, (
  287. "DnsAddr_WriteSockaddr( %p, %u, %p )\n",
  288. pSockaddr,
  289. SockaddrLength,
  290. pAddr ));
  291. // out length
  292. length = pAddr->SockaddrLength;
  293. // zero
  294. RtlZeroMemory( pSockaddr, SockaddrLength );
  295. //
  296. // fill in sockaddr for IP4 or IP6
  297. //
  298. if ( SockaddrLength >= length )
  299. {
  300. RtlCopyMemory(
  301. pSockaddr,
  302. & pAddr->Sockaddr,
  303. length );
  304. }
  305. else
  306. {
  307. length = 0;
  308. }
  309. return length;
  310. }
  311. BOOL
  312. DnsAddr_WriteIp6(
  313. OUT PIP6_ADDRESS pIp,
  314. IN PDNS_ADDR pAddr
  315. )
  316. /*++
  317. Routine Description:
  318. Write IP6 address.
  319. Arguments:
  320. pIp -- addr to write IP6 to
  321. pAddr -- DNS addr
  322. Return Value:
  323. TRUE if successful.
  324. FALSE on bad DNS_ADDR for IP6 write.
  325. --*/
  326. {
  327. WORD family;
  328. DWORD len;
  329. DNSDBG( SOCKET, (
  330. "DnsAddr_WriteIp6Addr( %p, %p )\n",
  331. pIp,
  332. pAddr ));
  333. //
  334. // check family
  335. //
  336. if ( DnsAddr_IsIp6(pAddr) )
  337. {
  338. IP6_ADDR_COPY(
  339. pIp,
  340. (PIP6_ADDRESS) &pAddr->SockaddrIn6.sin6_addr );
  341. return TRUE;
  342. }
  343. return FALSE;
  344. }
  345. IP4_ADDRESS
  346. DnsAddr_GetIp4(
  347. IN PDNS_ADDR pAddr
  348. )
  349. /*++
  350. Routine Description:
  351. Write IP4 address.
  352. Arguments:
  353. pAddr -- DNS addr
  354. Return Value:
  355. IP4 address if successful.
  356. INADDR_NONE if not valid IP4
  357. --*/
  358. {
  359. //
  360. // check family
  361. //
  362. if ( DnsAddr_IsIp4(pAddr) )
  363. {
  364. return (IP4_ADDRESS) pAddr->SockaddrIn.sin_addr.s_addr;
  365. }
  366. return INADDR_NONE;
  367. }
  368. //
  369. // Build DNS_ADDRs
  370. //
  371. BOOL
  372. DnsAddr_Build(
  373. OUT PDNS_ADDR pAddr,
  374. IN PSOCKADDR pSockaddr,
  375. IN DWORD Family, OPTIONAL
  376. IN DWORD SubnetLength,
  377. IN DWORD Flags
  378. )
  379. /*++
  380. Routine Description:
  381. Build from sockaddr
  382. Arguments:
  383. pAddr -- addr to set with IP6 address
  384. pSockaddr -- ptr to sockaddr
  385. Family --
  386. AF_INET6 to only extract if 6
  387. AF_INET4 to only extract if 4
  388. 0 to extract always
  389. SubnetLength -- length to set subnet
  390. Return Value:
  391. TRUE if successful.
  392. FALSE on bad sockaddr.
  393. --*/
  394. {
  395. WORD family;
  396. DWORD len;
  397. IP4_ADDRESS ip4;
  398. DNSDBG( TRACE, (
  399. "DnsAddr_Build( %p, %p, %u, %u, 08x )\n",
  400. pAddr,
  401. pSockaddr,
  402. Family,
  403. SubnetLength,
  404. Flags ));
  405. // zero
  406. RtlZeroMemory(
  407. pAddr,
  408. sizeof(*pAddr) );
  409. //
  410. // verify adequate length
  411. // verify family match (if desired)
  412. //
  413. len = Sockaddr_Length( pSockaddr );
  414. if ( len > DNS_ADDR_MAX_SOCKADDR_LENGTH )
  415. {
  416. return FALSE;
  417. }
  418. if ( Family && Family != pSockaddr->sa_family )
  419. {
  420. return FALSE;
  421. }
  422. //
  423. // write sockaddr
  424. // write length fields
  425. //
  426. RtlCopyMemory(
  427. & pAddr->Sockaddr,
  428. pSockaddr,
  429. len );
  430. pAddr->SockaddrLength = len;
  431. //
  432. // extra fields
  433. //
  434. pAddr->SubnetLength = SubnetLength;
  435. pAddr->Flags = Flags;
  436. return TRUE;
  437. }
  438. VOID
  439. DnsAddr_BuildFromIp4(
  440. OUT PDNS_ADDR pAddr,
  441. IN IP4_ADDRESS Ip4,
  442. IN WORD Port
  443. )
  444. /*++
  445. Routine Description:
  446. Build from IP4
  447. Arguments:
  448. pAddr -- addr to set with IP6 address
  449. Ip4 -- IP4 to build
  450. Return Value:
  451. None
  452. --*/
  453. {
  454. SOCKADDR_IN sockaddr;
  455. DNSDBG( TRACE, (
  456. "DnsAddr_BuildFromIp4( %p, %s, %u )\n",
  457. pAddr,
  458. IP4_STRING( Ip4 ),
  459. Port ));
  460. // zero
  461. RtlZeroMemory(
  462. pAddr,
  463. sizeof(*pAddr) );
  464. //
  465. // fill in for IP4
  466. //
  467. pAddr->SockaddrIn.sin_family = AF_INET;
  468. pAddr->SockaddrIn.sin_port = Port;
  469. pAddr->SockaddrIn.sin_addr.s_addr = Ip4;
  470. pAddr->SockaddrLength = sizeof(SOCKADDR_IN);
  471. }
  472. VOID
  473. DnsAddr_BuildFromIp6(
  474. OUT PDNS_ADDR pAddr,
  475. IN PIP6_ADDRESS pIp6,
  476. IN DWORD ScopeId,
  477. IN WORD Port
  478. )
  479. /*++
  480. Routine Description:
  481. Build from IP6
  482. Arguments:
  483. pAddr -- addr to set with IP6 address
  484. pIp6 -- IP6
  485. ScopeId -- scope id
  486. Port -- port
  487. Return Value:
  488. None
  489. --*/
  490. {
  491. DNSDBG( TRACE, (
  492. "DnsAddr_BuildFromIp6( %p, %s, %u, %u )\n",
  493. pAddr,
  494. IPADDR_STRING( pIp6 ),
  495. ScopeId,
  496. Port ));
  497. //
  498. // DCR: IP6 with V4 mapped
  499. // could use build sockaddr from IP6, then
  500. // call generic build
  501. //
  502. // zero
  503. RtlZeroMemory(
  504. pAddr,
  505. sizeof(*pAddr) );
  506. //
  507. // fill in for IP4
  508. //
  509. pAddr->SockaddrIn6.sin6_family = AF_INET6;
  510. pAddr->SockaddrIn6.sin6_port = Port;
  511. pAddr->SockaddrIn6.sin6_scope_id = ScopeId;
  512. IP6_ADDR_COPY(
  513. (PIP6_ADDRESS) &pAddr->SockaddrIn6.sin6_addr,
  514. pIp6 );
  515. pAddr->SockaddrLength = sizeof(SOCKADDR_IN6);
  516. }
  517. VOID
  518. DnsAddr_BuildFromAtm(
  519. OUT PDNS_ADDR pAddr,
  520. IN DWORD AtmType,
  521. IN PCHAR pAtmAddr
  522. )
  523. /*++
  524. Routine Description:
  525. Build from ATM address.
  526. Note, this is not a full SOCKADDR_ATM, see note below.
  527. This is a useful hack for bringing ATMA record info into
  528. DNS_ADDR format for transfer from DNS to RnR.
  529. Arguments:
  530. pAddr -- addr to set with IP6 address
  531. AtmType -- ATM address type
  532. pAtmAddr -- ATM address; ATM_ADDR_SIZE (20) bytes in length
  533. Return Value:
  534. None
  535. --*/
  536. {
  537. ATM_ADDRESS atmAddr;
  538. DNSDBG( TRACE, (
  539. "DnsAddr_BuildFromAtm( %p, %d, %p )\n",
  540. pAddr,
  541. AtmType,
  542. pAtmAddr ));
  543. //
  544. // clear
  545. //
  546. RtlZeroMemory(
  547. pAddr,
  548. sizeof(*pAddr) );
  549. //
  550. // fill in address
  551. //
  552. // note: we are simply using DNS_ADDR sockaddr portion as a
  553. // blob to hold ATM_ADDRESS; this is NOT a full
  554. // SOCKADDR_ATM structure which contains additional fields
  555. // and is larger than what we support in DNS_ADDR
  556. //
  557. // DCR: functionalize ATMA to ATM conversion
  558. // not sure this num of digits is correct
  559. // may have to actually parse address
  560. //
  561. // DCR: not filling satm_blli and satm_bhil fields
  562. // see RnR CSADDR builder for possible default values
  563. //
  564. pAddr->Sockaddr.sa_family = AF_ATM;
  565. pAddr->SockaddrLength = sizeof(ATM_ADDRESS);
  566. atmAddr.AddressType = AtmType;
  567. atmAddr.NumofDigits = ATM_ADDR_SIZE;
  568. RtlCopyMemory(
  569. & atmAddr.Addr,
  570. pAtmAddr,
  571. ATM_ADDR_SIZE );
  572. RtlCopyMemory(
  573. & ((PSOCKADDR_ATM)pAddr)->satm_number,
  574. & atmAddr,
  575. sizeof(ATM_ADDRESS) );
  576. }
  577. BOOL
  578. DnsAddr_BuildFromDnsRecord(
  579. OUT PDNS_ADDR pAddr,
  580. IN PDNS_RECORD pRR
  581. )
  582. /*++
  583. Routine Description:
  584. Build from DNS_RECORD
  585. Arguments:
  586. pAddr -- addr to set with IP6 address
  587. pRR -- DNS record to use
  588. Return Value:
  589. TRUE if successful.
  590. FALSE if unknown family.
  591. --*/
  592. {
  593. BOOL retval = TRUE;
  594. switch ( pRR->wType )
  595. {
  596. case DNS_TYPE_A:
  597. DnsAddr_BuildFromIp4(
  598. pAddr,
  599. pRR->Data.A.IpAddress,
  600. 0 );
  601. break;
  602. case DNS_TYPE_AAAA:
  603. DnsAddr_BuildFromIp6(
  604. pAddr,
  605. &pRR->Data.AAAA.Ip6Address,
  606. pRR->dwReserved,
  607. 0 );
  608. break;
  609. case DNS_TYPE_ATMA:
  610. DnsAddr_BuildFromAtm(
  611. pAddr,
  612. pRR->Data.ATMA.AddressType,
  613. pRR->Data.ATMA.Address );
  614. break;
  615. default:
  616. retval = FALSE;
  617. break;
  618. }
  619. return retval;
  620. }
  621. BOOL
  622. DnsAddr_BuildFromFlatAddr(
  623. OUT PDNS_ADDR pAddr,
  624. IN DWORD Family,
  625. IN PCHAR pFlatAddr,
  626. IN WORD Port
  627. )
  628. /*++
  629. Routine Description:
  630. Build from IP4
  631. Arguments:
  632. pAddr -- addr to set with IP6 address
  633. Family -- address family
  634. pFlatAddr -- ptr to flat IP4 or IP6 address
  635. Port -- port
  636. Return Value:
  637. TRUE if successful.
  638. FALSE if unknown family.
  639. --*/
  640. {
  641. //
  642. // check IP4
  643. //
  644. if ( Family == AF_INET )
  645. {
  646. DnsAddr_BuildFromIp4(
  647. pAddr,
  648. * (PIP4_ADDRESS) pFlatAddr,
  649. Port );
  650. }
  651. else if ( Family == AF_INET6 )
  652. {
  653. DnsAddr_BuildFromIp6(
  654. pAddr,
  655. (PIP6_ADDRESS) pFlatAddr,
  656. 0, // scope less
  657. Port );
  658. }
  659. else
  660. {
  661. return FALSE;
  662. }
  663. return TRUE;
  664. }
  665. BOOL
  666. DnsAddr_BuildMcast(
  667. OUT PDNS_ADDR pAddr,
  668. IN DWORD Family,
  669. IN PWSTR pName
  670. )
  671. /*++
  672. Routine Description:
  673. Build from sockaddr
  674. Arguments:
  675. pAddr -- addr to set with IP6 address
  676. Family --
  677. AF_INET6 for IP6 mcast
  678. AF_INET for IP4 mcast
  679. pName -- published record name; required for IP6 only
  680. Return Value:
  681. TRUE if successful.
  682. FALSE on bad sockaddr.
  683. --*/
  684. {
  685. WORD family;
  686. DWORD len;
  687. IP4_ADDRESS ip4;
  688. DNSDBG( TRACE, (
  689. "DnsAddr_BuildMcast( %p, %d, %s )\n",
  690. pAddr,
  691. Family,
  692. pName ));
  693. //
  694. // zero
  695. RtlZeroMemory(
  696. pAddr,
  697. sizeof(*pAddr) );
  698. //
  699. // IP4 has single mcast address
  700. //
  701. if ( Family == AF_INET )
  702. {
  703. DnsAddr_BuildFromIp4(
  704. pAddr,
  705. MCAST_IP4_ADDRESS,
  706. MCAST_PORT_NET_ORDER );
  707. }
  708. //
  709. // IP6 address includes name hash
  710. //
  711. else if ( Family == AF_INET6 )
  712. {
  713. IP6_ADDRESS mcastAddr;
  714. Ip6_McastCreate(
  715. & mcastAddr,
  716. pName );
  717. DnsAddr_BuildFromIp6(
  718. pAddr,
  719. & mcastAddr,
  720. 0, // no scope
  721. MCAST_PORT_NET_ORDER );
  722. #if 0
  723. CHAR label[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  724. CHAR downLabel[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  725. CHAR md5Hash[ 16 ]; // 128bit hash
  726. // hash of downcased label
  727. Dns_CopyNameLabel(
  728. label,
  729. pName );
  730. Dns_DowncaseNameLabel(
  731. downLabel,
  732. label,
  733. 0, // null terminated
  734. 0 // no flags
  735. );
  736. Dns_Md5Hash(
  737. md5Hash,
  738. downLabel );
  739. // mcast addr
  740. // - first 12 bytes are fixed
  741. // - last 4 bytes are first 32bits of hash
  742. IP6_ADDR_COPY(
  743. & mcastAddr,
  744. & g_Ip6McastBaseAddr );
  745. RtlCopyMemory(
  746. & mcastAddr[12],
  747. & md5Hash,
  748. sizeof(DWORD) );
  749. #endif
  750. }
  751. return TRUE;
  752. }
  753. //
  754. // Printing\string conversion
  755. //
  756. PCHAR
  757. DnsAddr_WriteIpString_A(
  758. OUT PCHAR pBuffer,
  759. IN PDNS_ADDR pAddr
  760. )
  761. /*++
  762. Routine Description:
  763. Write DNS_ADDR IP address to string.
  764. Note: Does NOT write entire DNS_ADDR or sockaddr.
  765. Arguments:
  766. pBuffer -- buffer to write to
  767. pAddr -- addr to write
  768. Return Value:
  769. Ptr to next char in buffer (ie the terminating NULL)
  770. NULL on invalid address. However, invalid address message is
  771. written to the buffer and it's length can be determined.
  772. --*/
  773. {
  774. if ( DnsAddr_IsIp4(pAddr) )
  775. {
  776. pBuffer += sprintf(
  777. pBuffer,
  778. "%s",
  779. inet_ntoa( pAddr->SockaddrIn.sin_addr ) );
  780. }
  781. else if ( DnsAddr_IsIp6(pAddr) )
  782. {
  783. pBuffer = Dns_Ip6AddressToString_A(
  784. pBuffer,
  785. (PIP6_ADDRESS) &pAddr->SockaddrIn6.sin6_addr );
  786. }
  787. else
  788. {
  789. sprintf(
  790. pBuffer,
  791. "Invalid DNS_ADDR at %p",
  792. pAddr );
  793. pBuffer = NULL;
  794. }
  795. return pBuffer;
  796. }
  797. PCHAR
  798. DnsAddr_Ntoa(
  799. IN PDNS_ADDR pAddr
  800. )
  801. /*++
  802. Routine Description:
  803. Get IP address string for DNS_ADDR.
  804. Note: Does NOT write entire DNS_ADDR or sockaddr.
  805. Arguments:
  806. pAddr -- addr to convert
  807. Return Value:
  808. Ptr to TLS blob with address string.
  809. --*/
  810. {
  811. if ( !pAddr )
  812. {
  813. return "Null Address";
  814. }
  815. else if ( DnsAddr_IsIp4(pAddr) )
  816. {
  817. return inet_ntoa( pAddr->SockaddrIn.sin_addr );
  818. }
  819. else if ( DnsAddr_IsIp6(pAddr) )
  820. {
  821. return Ip6_TempNtoa( (PIP6_ADDRESS)&pAddr->SockaddrIn6.sin6_addr );
  822. }
  823. else
  824. {
  825. return NULL;
  826. }
  827. }
  828. PSTR
  829. DnsAddr_WriteStructString_A(
  830. OUT PCHAR pBuffer,
  831. IN PDNS_ADDR pAddr
  832. )
  833. /*++
  834. Routine Description:
  835. Write DNS_ADDR as string.
  836. Arguments:
  837. pAddr -- ptr to IP to get string for
  838. Return Value:
  839. Ptr to next char in buffer (terminating NULL).
  840. --*/
  841. {
  842. CHAR ipBuffer[ DNS_ADDR_STRING_BUFFER_LENGTH ];
  843. //BOOL finValid;
  844. // write address portion
  845. //finValid = !DnsAddr_WriteIpString_A(
  846. DnsAddr_WriteIpString_A(
  847. ipBuffer,
  848. pAddr );
  849. //
  850. // write struct including address
  851. //
  852. pBuffer += sprintf(
  853. pBuffer,
  854. "af=%d, salen=%d, [sub=%d, flag=%08x] p=%u, addr=%s",
  855. pAddr->Sockaddr.sa_family,
  856. pAddr->SockaddrLength,
  857. pAddr->SubnetLength,
  858. pAddr->Flags,
  859. pAddr->SockaddrIn.sin_port,
  860. ipBuffer );
  861. return pBuffer;
  862. }
  863. //
  864. // DNS_ADDR_ARRAY routines
  865. //
  866. DWORD
  867. DnsAddrArray_Sizeof(
  868. IN PDNS_ADDR_ARRAY pArray
  869. )
  870. /*++
  871. Routine Description:
  872. Get size in bytes of address array.
  873. Arguments:
  874. pArray -- address array to find size of
  875. Return Value:
  876. Size in bytes of IP array.
  877. --*/
  878. {
  879. if ( ! pArray )
  880. {
  881. return 0;
  882. }
  883. return (pArray->AddrCount * sizeof(DNS_ADDR)) + sizeof(DNS_ADDR_ARRAY) - sizeof(DNS_ADDR);
  884. }
  885. #if 0
  886. BOOL
  887. DnsAddrArray_Probe(
  888. IN PDNS_ADDR_ARRAY pArray
  889. )
  890. /*++
  891. Routine Description:
  892. Touch all entries in IP array to insure valid memory.
  893. Arguments:
  894. pArray -- ptr to address array
  895. Return Value:
  896. TRUE if successful.
  897. FALSE otherwise
  898. --*/
  899. {
  900. DWORD i;
  901. BOOL result;
  902. if ( ! pArray )
  903. {
  904. return( TRUE );
  905. }
  906. for ( i=0; i<pArray->AddrCount; i++ )
  907. {
  908. result = IP6_IS_ADDR_LOOPBACK( &pArray->AddrArray[i] );
  909. }
  910. return( TRUE );
  911. }
  912. #endif
  913. #if 0
  914. BOOL
  915. DnsAddrArray_ValidateSizeOf(
  916. IN PDNS_ADDR_ARRAY pArray,
  917. IN DWORD dwMemoryLength
  918. )
  919. /*++
  920. Routine Description:
  921. Check that size of IP array, corresponds to length of memory.
  922. Arguments:
  923. pArray -- ptr to address array
  924. dwMemoryLength -- length of IP array memory
  925. Return Value:
  926. TRUE if IP array size matches memory length
  927. FALSE otherwise
  928. --*/
  929. {
  930. return( DnsAddrArray_SizeOf(pArray) == dwMemoryLength );
  931. }
  932. #endif
  933. VOID
  934. DnsAddrArray_Init(
  935. IN OUT PDNS_ADDR_ARRAY pArray,
  936. IN DWORD MaxCount
  937. )
  938. /*++
  939. Routine Description:
  940. Init memory as DNS_ADDR_ARRAY array.
  941. Arguments:
  942. pArray -- array to init
  943. MaxCount -- count of addresses
  944. Return Value:
  945. None
  946. --*/
  947. {
  948. pArray->MaxCount = MaxCount;
  949. pArray->AddrCount = 0;
  950. }
  951. VOID
  952. DnsAddrArray_Free(
  953. IN PDNS_ADDR_ARRAY pArray
  954. )
  955. /*++
  956. Routine Description:
  957. Free IP array.
  958. Only for arrays created through create routines below.
  959. Arguments:
  960. pArray -- IP array to free.
  961. Return Value:
  962. None
  963. --*/
  964. {
  965. FREE_HEAP( pArray );
  966. }
  967. PDNS_ADDR_ARRAY
  968. DnsAddrArray_Create(
  969. IN DWORD MaxCount
  970. )
  971. /*++
  972. Routine Description:
  973. Create uninitialized address array.
  974. Arguments:
  975. AddrCount -- count of addresses array will hold
  976. Return Value:
  977. Ptr to uninitialized address array, if successful
  978. NULL on failure.
  979. --*/
  980. {
  981. PDNS_ADDR_ARRAY parray;
  982. DNSDBG( IPARRAY, ( "DnsAddrArray_Create() of count %d\n", MaxCount ));
  983. parray = (PDNS_ADDR_ARRAY) ALLOCATE_HEAP_ZERO(
  984. (MaxCount * sizeof(DNS_ADDR)) +
  985. sizeof(DNS_ADDR_ARRAY) - sizeof(DNS_ADDR) );
  986. if ( ! parray )
  987. {
  988. return( NULL );
  989. }
  990. //
  991. // initialize IP count
  992. //
  993. parray->MaxCount = MaxCount;
  994. DNSDBG( IPARRAY, (
  995. "DnsAddrArray_Create() new array (count %d) at %p\n",
  996. MaxCount,
  997. parray ));
  998. return( parray );
  999. }
  1000. PDNS_ADDR_ARRAY
  1001. DnsAddrArray_CreateFromIp4Array(
  1002. IN PIP4_ARRAY pArray4
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Create DNS_ADDR_ARRAY from IP4 array.
  1007. Arguments:
  1008. pAddr4Array -- IP4 array
  1009. Return Value:
  1010. Ptr to uninitialized address array, if successful
  1011. NULL on failure.
  1012. --*/
  1013. {
  1014. PDNS_ADDR_ARRAY parray;
  1015. DWORD i;
  1016. DNSDBG( IPARRAY, (
  1017. "DnsAddrArray_CreateFromIp4Array( %p )\n",
  1018. pArray4 ));
  1019. if ( ! pArray4 )
  1020. {
  1021. return( NULL );
  1022. }
  1023. //
  1024. // allocate the array
  1025. //
  1026. parray = DnsAddrArray_Create( pArray4->AddrCount );
  1027. if ( !parray )
  1028. {
  1029. return NULL;
  1030. }
  1031. //
  1032. // fill the array
  1033. //
  1034. for ( i=0; i<pArray4->AddrCount; i++ )
  1035. {
  1036. DnsAddrArray_AddIp4(
  1037. parray,
  1038. pArray4->AddrArray[i],
  1039. 0 // no duplicate screen
  1040. );
  1041. }
  1042. DNSDBG( IPARRAY, (
  1043. "Leave DnsAddrArray_CreateFromIp4Array() new array (count %d) at %p\n",
  1044. parray->AddrCount,
  1045. parray ));
  1046. return( parray );
  1047. }
  1048. PDNS_ADDR_ARRAY
  1049. DnsAddrArray_CopyAndExpand(
  1050. IN PDNS_ADDR_ARRAY pArray,
  1051. IN DWORD ExpandCount,
  1052. IN BOOL fDeleteExisting
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. Create expanded copy of address array.
  1057. Arguments:
  1058. pArray -- address array to copy
  1059. ExpandCount -- number of IP to expand array size by
  1060. fDeleteExisting -- TRUE to delete existing array;
  1061. this is useful when function is used to grow existing
  1062. IP array in place; note that locking must be done
  1063. by caller
  1064. note, that if new array creation FAILS -- then old array
  1065. is NOT deleted
  1066. Return Value:
  1067. Ptr to IP array copy, if successful
  1068. NULL on failure.
  1069. --*/
  1070. {
  1071. PDNS_ADDR_ARRAY pnewArray;
  1072. DWORD newCount;
  1073. //
  1074. // no existing array -- just create desired size
  1075. //
  1076. if ( ! pArray )
  1077. {
  1078. if ( ExpandCount )
  1079. {
  1080. return DnsAddrArray_Create( ExpandCount );
  1081. }
  1082. return( NULL );
  1083. }
  1084. //
  1085. // create IP array of desired size
  1086. // then copy any existing addresses
  1087. //
  1088. pnewArray = DnsAddrArray_Create( pArray->AddrCount + ExpandCount );
  1089. if ( ! pnewArray )
  1090. {
  1091. return( NULL );
  1092. }
  1093. newCount = pnewArray->MaxCount;
  1094. RtlCopyMemory(
  1095. (PBYTE) pnewArray,
  1096. (PBYTE) pArray,
  1097. DnsAddrArray_Sizeof(pArray) );
  1098. pnewArray->MaxCount = newCount;
  1099. //
  1100. // delete existing -- for "grow mode"
  1101. //
  1102. if ( fDeleteExisting )
  1103. {
  1104. FREE_HEAP( pArray );
  1105. }
  1106. return( pnewArray );
  1107. }
  1108. PDNS_ADDR_ARRAY
  1109. DnsAddrArray_CreateCopy(
  1110. IN PDNS_ADDR_ARRAY pArray
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. Create copy of address array.
  1115. Arguments:
  1116. pArray -- address array to copy
  1117. Return Value:
  1118. Ptr to address array copy, if successful
  1119. NULL on failure.
  1120. --*/
  1121. {
  1122. //
  1123. // call essentially "CopyEx" function
  1124. //
  1125. // note, not macroing this because this may well become
  1126. // a DLL entry point
  1127. //
  1128. return DnsAddrArray_CopyAndExpand(
  1129. pArray,
  1130. 0, // no expansion
  1131. 0 // don't delete existing array
  1132. );
  1133. }
  1134. //
  1135. // Tests
  1136. //
  1137. DWORD
  1138. DnsAddrArray_GetFamilyCount(
  1139. IN PDNS_ADDR_ARRAY pArray,
  1140. IN DWORD Family
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. Get count of addrs of a particular family.
  1145. Arguments:
  1146. pArray -- address array
  1147. Family -- family to count
  1148. Return Value:
  1149. Count of addrs of a particular family.
  1150. --*/
  1151. {
  1152. DWORD i;
  1153. DWORD count;
  1154. WORD arrayFamily;
  1155. if ( !pArray )
  1156. {
  1157. return 0;
  1158. }
  1159. // no family specified -- all addrs count
  1160. if ( Family == 0 )
  1161. {
  1162. return pArray->AddrCount;
  1163. }
  1164. //
  1165. // array family is specified -- so either all or none
  1166. //
  1167. if ( arrayFamily = pArray->Family )
  1168. {
  1169. if ( arrayFamily == Family )
  1170. {
  1171. return pArray->AddrCount;
  1172. }
  1173. else
  1174. {
  1175. return 0;
  1176. }
  1177. }
  1178. //
  1179. // family specified and array family unspecified -- must count
  1180. //
  1181. count = 0;
  1182. for (i=0; i<pArray->AddrCount; i++)
  1183. {
  1184. if ( DnsAddr_Family( &pArray->AddrArray[i] ) == Family )
  1185. {
  1186. count++;
  1187. }
  1188. }
  1189. return( count );
  1190. }
  1191. BOOL
  1192. DnsAddrArray_ContainsAddr(
  1193. IN PDNS_ADDR_ARRAY pArray,
  1194. IN PDNS_ADDR pAddr,
  1195. IN DWORD MatchFlag
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. Check if IP array contains desired address.
  1200. Arguments:
  1201. pArray -- address array to copy
  1202. pAddr -- IP to check for
  1203. MatchFlag -- level of match required
  1204. Return Value:
  1205. TRUE if address in array.
  1206. Ptr to address array copy, if successful
  1207. NULL on failure.
  1208. --*/
  1209. {
  1210. DWORD i;
  1211. if ( ! pArray )
  1212. {
  1213. return( FALSE );
  1214. }
  1215. for (i=0; i<pArray->AddrCount; i++)
  1216. {
  1217. if ( DnsAddr_IsEqual(
  1218. pAddr,
  1219. &pArray->AddrArray[i],
  1220. MatchFlag ) )
  1221. {
  1222. return( TRUE );
  1223. }
  1224. }
  1225. return( FALSE );
  1226. }
  1227. BOOL
  1228. DnsAddrArray_ContainsAddrEx(
  1229. IN PDNS_ADDR_ARRAY pArray,
  1230. IN PDNS_ADDR pAddr,
  1231. IN DWORD MatchFlag, OPTIONAL
  1232. IN DNSADDR_SCREEN_FUNC pScreenFunc, OPTIONAL
  1233. IN PDNS_ADDR pScreenAddr OPTIONAL
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. Check if IP array contains desired address.
  1238. Arguments:
  1239. pArray -- address array to copy
  1240. pAddr -- IP to check for
  1241. MatchFlag -- match level for screening dups; zero for no dup screening
  1242. pScreenFunc -- screen function (see header def for explanation)
  1243. pScreenAddr -- screening addr param to screen function
  1244. Return Value:
  1245. TRUE if address in array.
  1246. Ptr to address array copy, if successful
  1247. NULL on failure.
  1248. --*/
  1249. {
  1250. DWORD i;
  1251. DNSDBG( IPARRAY, (
  1252. "DnsAddrArray_ContainsAddrEx( %p, %p, %08x, %p, %p )\n",
  1253. pArray,
  1254. pAddr,
  1255. MatchFlag,
  1256. pScreenFunc,
  1257. pScreenAddr ));
  1258. if ( ! pArray )
  1259. {
  1260. return( FALSE );
  1261. }
  1262. for (i=0; i<pArray->AddrCount; i++)
  1263. {
  1264. if ( DnsAddr_IsEqual(
  1265. pAddr,
  1266. &pArray->AddrArray[i],
  1267. MatchFlag ) )
  1268. {
  1269. //
  1270. // do advanced screening here -- if any
  1271. //
  1272. if ( !pScreenFunc ||
  1273. pScreenFunc(
  1274. &pArray->AddrArray[i],
  1275. pScreenAddr ) )
  1276. {
  1277. return TRUE;
  1278. }
  1279. }
  1280. }
  1281. return( FALSE );
  1282. }
  1283. BOOL
  1284. DnsAddrArray_ContainsIp4(
  1285. IN PDNS_ADDR_ARRAY pArray,
  1286. IN IP4_ADDRESS Ip4
  1287. )
  1288. {
  1289. DNS_ADDR addr;
  1290. // read IP into addr
  1291. DnsAddr_BuildFromIp4(
  1292. & addr,
  1293. Ip4,
  1294. 0 );
  1295. // with only IP, only match IP
  1296. return DnsAddrArray_ContainsAddr(
  1297. pArray,
  1298. & addr,
  1299. DNSADDR_MATCH_IP );
  1300. }
  1301. BOOL
  1302. DnsAddrArray_ContainsIp6(
  1303. IN PDNS_ADDR_ARRAY pArray,
  1304. IN PIP6_ADDRESS pIp6
  1305. )
  1306. {
  1307. DNS_ADDR addr;
  1308. // read IP into addr
  1309. DnsAddr_BuildFromIp6(
  1310. & addr,
  1311. pIp6,
  1312. 0, // no scope
  1313. 0 );
  1314. // with only IP, only match IP
  1315. return DnsAddrArray_ContainsAddr(
  1316. pArray,
  1317. & addr,
  1318. DNSADDR_MATCH_IP );
  1319. }
  1320. //
  1321. // Add \ Delete operations
  1322. //
  1323. BOOL
  1324. DnsAddrArray_AddAddr(
  1325. IN OUT PDNS_ADDR_ARRAY pArray,
  1326. IN PDNS_ADDR pAddr,
  1327. IN DWORD Family,
  1328. IN DWORD MatchFlag OPTIONAL
  1329. )
  1330. /*++
  1331. Routine Description:
  1332. Add IP address to IP array.
  1333. Allowable "slot" in array, is any zero IP address.
  1334. Arguments:
  1335. pArray -- address array to add to
  1336. pAddr -- IP address to add to array
  1337. Family -- optional, only add if match this family
  1338. MatchFlag -- flags for matching if screening dups
  1339. Return Value:
  1340. TRUE if successful.
  1341. FALSE if array full.
  1342. --*/
  1343. {
  1344. DWORD count;
  1345. //
  1346. // screen for existence
  1347. //
  1348. // this check makes it easy to write code that does
  1349. // Add\Full?=>Expand loop without having to write
  1350. // startup existence\create code
  1351. //
  1352. if ( !pArray )
  1353. {
  1354. return FALSE;
  1355. }
  1356. //
  1357. // check family match
  1358. //
  1359. // DCR: error codes on DnsAddrArray_AddAddrEx()?
  1360. // - then can have found dup and bad family
  1361. // errors
  1362. //
  1363. if ( Family &&
  1364. DnsAddr_Family(pAddr) != Family )
  1365. {
  1366. return TRUE;
  1367. }
  1368. //
  1369. // check for duplicates
  1370. //
  1371. if ( MatchFlag )
  1372. {
  1373. if ( DnsAddrArray_ContainsAddr( pArray, pAddr, MatchFlag ) )
  1374. {
  1375. return TRUE;
  1376. }
  1377. }
  1378. count = pArray->AddrCount;
  1379. if ( count >= pArray->MaxCount )
  1380. {
  1381. return FALSE;
  1382. }
  1383. DnsAddr_Copy(
  1384. &pArray->AddrArray[ count ],
  1385. pAddr );
  1386. pArray->AddrCount = ++count;
  1387. return TRUE;
  1388. }
  1389. BOOL
  1390. DnsAddrArray_AddSockaddr(
  1391. IN OUT PDNS_ADDR_ARRAY pArray,
  1392. IN PSOCKADDR pSockaddr,
  1393. IN DWORD Family,
  1394. IN DWORD MatchFlag
  1395. )
  1396. /*++
  1397. Routine Description:
  1398. Add IP address to IP array.
  1399. Allowable "slot" in array, is any zero IP address.
  1400. Arguments:
  1401. pArray -- address array to add to
  1402. pAddIp -- IP address to add to array
  1403. Family -- required family to do add; 0 for add always
  1404. MatchFlag -- match flags if screening duplicates
  1405. Return Value:
  1406. TRUE if successful.
  1407. FALSE if array full.
  1408. --*/
  1409. {
  1410. DNS_ADDR addr;
  1411. if ( !DnsAddr_Build(
  1412. & addr,
  1413. pSockaddr,
  1414. Family,
  1415. 0, // no subnet length info
  1416. 0 // no flags
  1417. ) )
  1418. {
  1419. return FALSE;
  1420. }
  1421. return DnsAddrArray_AddAddr(
  1422. pArray,
  1423. &addr,
  1424. 0, // family screen done in build routine
  1425. MatchFlag );
  1426. }
  1427. BOOL
  1428. DnsAddrArray_AddIp4(
  1429. IN OUT PDNS_ADDR_ARRAY pArray,
  1430. IN IP4_ADDRESS Ip4,
  1431. IN DWORD MatchFlag
  1432. )
  1433. /*++
  1434. Routine Description:
  1435. Add IP4 address to IP array.
  1436. Arguments:
  1437. pArray -- address array to add to
  1438. Ip4 -- IP4 address to add to array
  1439. MatchFlag -- match flags if screening duplicates
  1440. Return Value:
  1441. TRUE if successful.
  1442. FALSE if array full.
  1443. --*/
  1444. {
  1445. DNS_ADDR addr;
  1446. DnsAddr_BuildFromIp4(
  1447. &addr,
  1448. Ip4,
  1449. 0 );
  1450. return DnsAddrArray_AddAddr(
  1451. pArray,
  1452. &addr,
  1453. 0, // no family screen
  1454. MatchFlag );
  1455. }
  1456. BOOL
  1457. DnsAddrArray_AddIp6(
  1458. IN OUT PDNS_ADDR_ARRAY pArray,
  1459. IN PIP6_ADDRESS pIp6,
  1460. IN DWORD ScopeId,
  1461. IN DWORD MatchFlag
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. Add IP4 address to IP array.
  1466. Arguments:
  1467. pArray -- address array to add to
  1468. pIp6 -- IP6 address to add to array
  1469. MatchFlag -- match flags if screening duplicates
  1470. Return Value:
  1471. TRUE if successful.
  1472. FALSE if array full.
  1473. --*/
  1474. {
  1475. DNS_ADDR addr;
  1476. DnsAddr_BuildFromIp6(
  1477. &addr,
  1478. pIp6,
  1479. ScopeId, // no scope
  1480. 0 );
  1481. return DnsAddrArray_AddAddr(
  1482. pArray,
  1483. &addr,
  1484. 0, // no family screen
  1485. MatchFlag );
  1486. }
  1487. DWORD
  1488. DnsAddrArray_DeleteAddr(
  1489. IN OUT PDNS_ADDR_ARRAY pArray,
  1490. IN PDNS_ADDR pAddrDelete,
  1491. IN DWORD MatchFlag
  1492. )
  1493. /*++
  1494. Routine Description:
  1495. Delete IP address from IP array.
  1496. Arguments:
  1497. pArray -- address array to add to
  1498. pAddrDelete -- IP address to delete from array
  1499. Return Value:
  1500. Count of instances of IpDelete found in array.
  1501. --*/
  1502. {
  1503. DWORD found = 0;
  1504. INT i;
  1505. INT currentLast;
  1506. i = currentLast = pArray->AddrCount-1;
  1507. //
  1508. // check each IP for match to delete IP
  1509. // - go backwards through array
  1510. // - swap in last IP in array
  1511. //
  1512. while ( i >= 0 )
  1513. {
  1514. if ( DnsAddr_IsEqual(
  1515. &pArray->AddrArray[i],
  1516. pAddrDelete,
  1517. MatchFlag ) )
  1518. {
  1519. DnsAddr_Copy(
  1520. & pArray->AddrArray[i],
  1521. & pArray->AddrArray[ currentLast ] );
  1522. DnsAddr_Clear( &pArray->AddrArray[ currentLast ] );
  1523. currentLast--;
  1524. found++;
  1525. }
  1526. i--;
  1527. }
  1528. pArray->AddrCount = currentLast + 1;
  1529. return( found );
  1530. }
  1531. DWORD
  1532. DnsAddrArray_DeleteIp4(
  1533. IN OUT PDNS_ADDR_ARRAY pArray,
  1534. IN IP4_ADDRESS Ip4
  1535. )
  1536. {
  1537. DNS_ADDR addr;
  1538. // read IP into addr
  1539. DnsAddr_BuildFromIp4(
  1540. & addr,
  1541. Ip4,
  1542. 0 );
  1543. // with only IP, only match IP
  1544. return DnsAddrArray_DeleteAddr(
  1545. pArray,
  1546. & addr,
  1547. DNSADDR_MATCH_IP );
  1548. }
  1549. DWORD
  1550. DnsAddrArray_DeleteIp6(
  1551. IN OUT PDNS_ADDR_ARRAY pArray,
  1552. IN PIP6_ADDRESS Ip6
  1553. )
  1554. {
  1555. DNS_ADDR addr;
  1556. // read IP into addr
  1557. DnsAddr_BuildFromIp6(
  1558. & addr,
  1559. Ip6,
  1560. 0, // no scope
  1561. 0 );
  1562. // with only IP, only match IP
  1563. return DnsAddrArray_DeleteAddr(
  1564. pArray,
  1565. & addr,
  1566. DNSADDR_MATCH_IP );
  1567. }
  1568. //
  1569. // Array operations
  1570. //
  1571. VOID
  1572. DnsAddrArray_Clear(
  1573. IN OUT PDNS_ADDR_ARRAY pArray
  1574. )
  1575. /*++
  1576. Routine Description:
  1577. Clear memory in IP array.
  1578. Arguments:
  1579. pArray -- address array to clear
  1580. Return Value:
  1581. None.
  1582. --*/
  1583. {
  1584. // clear just the address list, leaving count intact
  1585. RtlZeroMemory(
  1586. pArray->AddrArray,
  1587. pArray->AddrCount * sizeof(DNS_ADDR) );
  1588. }
  1589. VOID
  1590. DnsAddrArray_Reverse(
  1591. IN OUT PDNS_ADDR_ARRAY pArray
  1592. )
  1593. /*++
  1594. Routine Description:
  1595. Reorder the list of IPs in reverse.
  1596. Arguments:
  1597. pArray -- address array to reorder
  1598. Return Value:
  1599. None.
  1600. --*/
  1601. {
  1602. DNS_ADDR tempAddr;
  1603. DWORD i;
  1604. DWORD j;
  1605. //
  1606. // swap IPs working from ends to the middle
  1607. //
  1608. if ( pArray &&
  1609. pArray->AddrCount )
  1610. {
  1611. for ( i = 0, j = pArray->AddrCount - 1;
  1612. i < j;
  1613. i++, j-- )
  1614. {
  1615. DnsAddr_Copy(
  1616. & tempAddr,
  1617. & pArray->AddrArray[i] );
  1618. DnsAddr_Copy(
  1619. & pArray->AddrArray[i],
  1620. & pArray->AddrArray[j] );
  1621. DnsAddr_Copy(
  1622. & pArray->AddrArray[j],
  1623. & tempAddr );
  1624. }
  1625. }
  1626. }
  1627. DNS_STATUS
  1628. DnsAddrArray_AppendArrayEx(
  1629. IN OUT PDNS_ADDR_ARRAY pArray,
  1630. IN PDNS_ADDR_ARRAY pAppendArray,
  1631. IN DWORD AppendCount,
  1632. IN DWORD Family, OPTIONAL
  1633. IN DWORD MatchFlag, OPTIONAL
  1634. IN DNSADDR_SCREEN_FUNC pScreenFunc, OPTIONAL
  1635. IN PDNS_ADDR pScreenAddr OPTIONAL
  1636. )
  1637. /*++
  1638. Routine Description:
  1639. Append entries from another array.
  1640. Arguments:
  1641. pArray -- existing array
  1642. pAppendArray -- array to append
  1643. AppendCount -- number of addrs to append; MAXDWORD for entire array
  1644. Family -- family, if screening family; zero for no screening
  1645. MatchFlag -- match level for screening dups; zero for no dup screening
  1646. pScreenFunc -- screen function (see header def for explanation)
  1647. pScreenAddr -- screening addr param to screen function
  1648. Return Value:
  1649. NO_ERROR if successful.
  1650. ERROR_MORE_DATA -- inadequate space in target array
  1651. --*/
  1652. {
  1653. DWORD i;
  1654. DNS_STATUS status = NO_ERROR;
  1655. DNSDBG( IPARRAY, (
  1656. "DnsAddrArray_AppendArrayEx( %p, %p, %d, %d, %08x, %p, %p )\n",
  1657. pArray,
  1658. pAppendArray,
  1659. AppendCount,
  1660. Family,
  1661. MatchFlag,
  1662. pScreenFunc,
  1663. pScreenAddr ));
  1664. if ( ! pAppendArray )
  1665. {
  1666. return( NO_ERROR );
  1667. }
  1668. //
  1669. // read from append array
  1670. //
  1671. for ( i=0; i<pAppendArray->AddrCount; i++ )
  1672. {
  1673. PDNS_ADDR paddr = &pAppendArray->AddrArray[i];
  1674. //
  1675. // do advanced screening here -- if any
  1676. //
  1677. if ( pScreenAddr )
  1678. {
  1679. if ( !pScreenFunc(
  1680. paddr,
  1681. pScreenAddr ) )
  1682. {
  1683. continue;
  1684. }
  1685. }
  1686. //
  1687. // attempt the add
  1688. //
  1689. if ( DnsAddrArray_AddAddr(
  1690. pArray,
  1691. paddr,
  1692. Family,
  1693. MatchFlag
  1694. ) )
  1695. {
  1696. if ( --AppendCount > 0 )
  1697. {
  1698. continue;
  1699. }
  1700. break;
  1701. }
  1702. else
  1703. {
  1704. //
  1705. // add failed
  1706. // - break if array is full
  1707. //
  1708. // DCR: should really only ERROR_MORE_DATA if there is more data
  1709. // separate error codes on _AddAddr would fix this
  1710. //
  1711. if ( pArray->AddrCount == pArray->MaxCount )
  1712. {
  1713. status = ERROR_MORE_DATA;
  1714. break;
  1715. }
  1716. }
  1717. }
  1718. return( status );
  1719. }
  1720. DNS_STATUS
  1721. DnsAddrArray_AppendArray(
  1722. IN OUT PDNS_ADDR_ARRAY pArray,
  1723. IN PDNS_ADDR_ARRAY pAppendArray
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. Create DNS_ADDR_ARRAY from IP4 array.
  1728. Arguments:
  1729. pArray -- existing array
  1730. pAppendArray -- array to append
  1731. Return Value:
  1732. NO_ERROR if successful.
  1733. ERROR_MORE_DATA -- inadequate space in target array
  1734. --*/
  1735. {
  1736. //
  1737. // append with Ex version
  1738. //
  1739. // note, if EX is expensive, could do simple
  1740. // check\RtlCopyMemory type append
  1741. //
  1742. return DnsAddrArray_AppendArrayEx(
  1743. pArray,
  1744. pAppendArray,
  1745. MAXDWORD, // append entire array
  1746. 0, // no family screen
  1747. 0, // no dup detection
  1748. NULL, // no screen func
  1749. NULL // no screen addr
  1750. );
  1751. }
  1752. //
  1753. // Set operations
  1754. //
  1755. DNS_STATUS
  1756. DnsAddrArray_Diff(
  1757. IN PDNS_ADDR_ARRAY pArray1,
  1758. IN PDNS_ADDR_ARRAY pArray2,
  1759. IN DWORD MatchFlag, OPTIONAL
  1760. OUT PDNS_ADDR_ARRAY* ppOnlyIn1,
  1761. OUT PDNS_ADDR_ARRAY* ppOnlyIn2,
  1762. OUT PDNS_ADDR_ARRAY* ppIntersect
  1763. )
  1764. /*++
  1765. Routine Description:
  1766. Computes differences and intersection of two IP arrays.
  1767. Out arrays are allocated with DnsAddrArray_Alloc(), caller must free with DnsAddrArray_Free()
  1768. Arguments:
  1769. pArray1 -- IP array
  1770. pArray2 -- IP array
  1771. MatchFlag -- flags for determining match
  1772. ppOnlyIn1 -- addr to recv IP array of addresses only in array 1 (not in array2)
  1773. ppOnlyIn2 -- addr to recv IP array of addresses only in array 2 (not in array1)
  1774. ppIntersect -- addr to recv IP array of intersection addresses
  1775. Return Value:
  1776. ERROR_SUCCESS if successful.
  1777. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP arrays.
  1778. --*/
  1779. {
  1780. DWORD j;
  1781. PDNS_ADDR paddr;
  1782. PDNS_ADDR_ARRAY intersectArray = NULL;
  1783. PDNS_ADDR_ARRAY only1Array = NULL;
  1784. PDNS_ADDR_ARRAY only2Array = NULL;
  1785. //
  1786. // create result IP arrays
  1787. //
  1788. if ( ppIntersect )
  1789. {
  1790. intersectArray = DnsAddrArray_CreateCopy( pArray1 );
  1791. if ( !intersectArray )
  1792. {
  1793. goto NoMem;
  1794. }
  1795. *ppIntersect = intersectArray;
  1796. }
  1797. if ( ppOnlyIn1 )
  1798. {
  1799. only1Array = DnsAddrArray_CreateCopy( pArray1 );
  1800. if ( !only1Array )
  1801. {
  1802. goto NoMem;
  1803. }
  1804. *ppOnlyIn1 = only1Array;
  1805. }
  1806. if ( ppOnlyIn2 )
  1807. {
  1808. only2Array = DnsAddrArray_CreateCopy( pArray2 );
  1809. if ( !only2Array )
  1810. {
  1811. goto NoMem;
  1812. }
  1813. *ppOnlyIn2 = only2Array;
  1814. }
  1815. //
  1816. // clean the arrays
  1817. //
  1818. for ( j=0; j< pArray1->AddrCount; j++ )
  1819. {
  1820. paddr = &pArray1->AddrArray[j];
  1821. // if IP in both arrays, delete from "only" arrays
  1822. if ( DnsAddrArray_ContainsAddr( pArray2, paddr, MatchFlag ) )
  1823. {
  1824. if ( only1Array )
  1825. {
  1826. DnsAddrArray_DeleteAddr( only1Array, paddr, MatchFlag );
  1827. }
  1828. if ( only2Array )
  1829. {
  1830. DnsAddrArray_DeleteAddr( only2Array, paddr, MatchFlag );
  1831. }
  1832. }
  1833. // if IP not in both arrays, delete from intersection
  1834. // note intersection started as IpArray1
  1835. else if ( intersectArray )
  1836. {
  1837. DnsAddrArray_DeleteAddr(
  1838. intersectArray,
  1839. paddr,
  1840. MatchFlag );
  1841. }
  1842. }
  1843. return( ERROR_SUCCESS );
  1844. NoMem:
  1845. if ( intersectArray )
  1846. {
  1847. FREE_HEAP( intersectArray );
  1848. }
  1849. if ( only1Array )
  1850. {
  1851. FREE_HEAP( only1Array );
  1852. }
  1853. if ( only2Array )
  1854. {
  1855. FREE_HEAP( only2Array );
  1856. }
  1857. if ( ppIntersect )
  1858. {
  1859. *ppIntersect = NULL;
  1860. }
  1861. if ( ppOnlyIn1 )
  1862. {
  1863. *ppOnlyIn1 = NULL;
  1864. }
  1865. if ( ppOnlyIn2 )
  1866. {
  1867. *ppOnlyIn2 = NULL;
  1868. }
  1869. return( DNS_ERROR_NO_MEMORY );
  1870. }
  1871. BOOL
  1872. DnsAddrArray_IsIntersection(
  1873. IN PDNS_ADDR_ARRAY pArray1,
  1874. IN PDNS_ADDR_ARRAY pArray2,
  1875. IN DWORD MatchFlag OPTIONAL
  1876. )
  1877. /*++
  1878. Routine Description:
  1879. Determine if there's intersection of two IP arrays.
  1880. Arguments:
  1881. pArray1 -- IP array
  1882. pArray2 -- IP array
  1883. MatchFlag -- flags for determining match
  1884. Return Value:
  1885. TRUE if intersection.
  1886. FALSE if no intersection or empty or NULL array.
  1887. --*/
  1888. {
  1889. DWORD count;
  1890. DWORD j;
  1891. //
  1892. // protect against NULL
  1893. // this is called from the server on potentially changing (reconfigurable)
  1894. // IP array pointers; this provides cheaper protection than
  1895. // worrying about locking
  1896. //
  1897. if ( !pArray1 || !pArray2 )
  1898. {
  1899. return( FALSE );
  1900. }
  1901. //
  1902. // same array
  1903. //
  1904. if ( pArray1 == pArray2 )
  1905. {
  1906. return( TRUE );
  1907. }
  1908. //
  1909. // test that at least one IP in array 1 is in array 2
  1910. //
  1911. count = pArray1->AddrCount;
  1912. for ( j=0; j < count; j++ )
  1913. {
  1914. if ( DnsAddrArray_ContainsAddr(
  1915. pArray2,
  1916. &pArray1->AddrArray[j],
  1917. MatchFlag ) )
  1918. {
  1919. return( TRUE );
  1920. }
  1921. }
  1922. // no intersection
  1923. return( FALSE );
  1924. }
  1925. BOOL
  1926. DnsAddrArray_IsEqual(
  1927. IN PDNS_ADDR_ARRAY pArray1,
  1928. IN PDNS_ADDR_ARRAY pArray2,
  1929. IN DWORD MatchFlag
  1930. )
  1931. /*++
  1932. Routine Description:
  1933. Determines if IP arrays are equal.
  1934. Arguments:
  1935. pArray1 -- IP array
  1936. pArray2 -- IP array
  1937. MatchFlag -- level of match
  1938. Return Value:
  1939. TRUE if arrays equal.
  1940. FALSE otherwise.
  1941. --*/
  1942. {
  1943. DWORD j;
  1944. DWORD count;
  1945. //
  1946. // same array? or missing array?
  1947. //
  1948. if ( pArray1 == pArray2 )
  1949. {
  1950. return( TRUE );
  1951. }
  1952. if ( !pArray1 || !pArray2 )
  1953. {
  1954. return( FALSE );
  1955. }
  1956. //
  1957. // arrays the same length?
  1958. //
  1959. count = pArray1->AddrCount;
  1960. if ( count != pArray2->AddrCount )
  1961. {
  1962. return( FALSE );
  1963. }
  1964. //
  1965. // test that each IP in array 1 is in array 2
  1966. //
  1967. // test that each IP in array 2 is in array 1
  1968. // - do second test in case of duplicates
  1969. // that fool equal-lengths check
  1970. //
  1971. for ( j=0; j < count; j++ )
  1972. {
  1973. if ( !DnsAddrArray_ContainsAddr(
  1974. pArray2,
  1975. &pArray1->AddrArray[j],
  1976. MatchFlag ) )
  1977. {
  1978. return( FALSE );
  1979. }
  1980. }
  1981. for ( j=0; j < count; j++ )
  1982. {
  1983. if ( !DnsAddrArray_ContainsAddr(
  1984. pArray1,
  1985. &pArray2->AddrArray[j],
  1986. MatchFlag ) )
  1987. {
  1988. return( FALSE );
  1989. }
  1990. }
  1991. // equal arrays
  1992. return( TRUE );
  1993. }
  1994. DNS_STATUS
  1995. DnsAddrArray_Union(
  1996. IN PDNS_ADDR_ARRAY pArray1,
  1997. IN PDNS_ADDR_ARRAY pArray2,
  1998. OUT PDNS_ADDR_ARRAY* ppUnion
  1999. )
  2000. /*++
  2001. Routine Description:
  2002. Computes the union of two IP arrays.
  2003. Out array is allocated with DnsAddrArray_Alloc(), caller must free with DnsAddrArray_Free()
  2004. Arguments:
  2005. pArray1 -- IP array
  2006. pArray2 -- IP array
  2007. ppUnion -- addr to recv IP array of addresses in array 1 and in array2
  2008. Return Value:
  2009. ERROR_SUCCESS if successful.
  2010. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP array.
  2011. --*/
  2012. {
  2013. PDNS_ADDR_ARRAY punionArray = NULL;
  2014. DWORD j;
  2015. //
  2016. // create result IP arrays
  2017. //
  2018. if ( !ppUnion )
  2019. {
  2020. return( ERROR_INVALID_PARAMETER );
  2021. }
  2022. punionArray = DnsAddrArray_Create(
  2023. pArray1->AddrCount +
  2024. pArray2->AddrCount );
  2025. if ( !punionArray )
  2026. {
  2027. goto NoMem;
  2028. }
  2029. *ppUnion = punionArray;
  2030. //
  2031. // create union from arrays
  2032. //
  2033. for ( j = 0; j < pArray1->AddrCount; j++ )
  2034. {
  2035. DnsAddrArray_AddAddr(
  2036. punionArray,
  2037. & pArray1->AddrArray[j],
  2038. 0, // no family screen
  2039. DNSADDR_MATCH_ALL // screen out dups
  2040. );
  2041. }
  2042. for ( j = 0; j < pArray2->AddrCount; j++ )
  2043. {
  2044. DnsAddrArray_AddAddr(
  2045. punionArray,
  2046. & pArray2->AddrArray[j],
  2047. 0, // no family screen
  2048. DNSADDR_MATCH_ALL // screen out dups
  2049. );
  2050. }
  2051. return( ERROR_SUCCESS );
  2052. NoMem:
  2053. if ( punionArray )
  2054. {
  2055. FREE_HEAP( punionArray );
  2056. *ppUnion = NULL;
  2057. }
  2058. return( DNS_ERROR_NO_MEMORY );
  2059. }
  2060. BOOL
  2061. DnsAddrArray_CheckAndMakeSubset(
  2062. IN OUT PDNS_ADDR_ARRAY pArraySub,
  2063. IN PDNS_ADDR_ARRAY pArraySuper
  2064. )
  2065. /*++
  2066. Routine Description:
  2067. Clear entries from IP array until it is subset of another IP array.
  2068. Arguments:
  2069. pArraySub -- addr array to make into subset
  2070. pArraySuper -- addr array superset
  2071. Return Value:
  2072. TRUE if pArraySub is already subset.
  2073. FALSE if needed to nix entries to make IP array a subset.
  2074. --*/
  2075. {
  2076. DWORD i;
  2077. DWORD newCount;
  2078. //
  2079. // check each entry in subset IP array,
  2080. // if not in superset IP array, eliminate it
  2081. //
  2082. newCount = pArraySub->AddrCount;
  2083. for (i=0; i < newCount; i++)
  2084. {
  2085. if ( ! DnsAddrArray_ContainsAddr(
  2086. pArraySuper,
  2087. & pArraySub->AddrArray[i],
  2088. DNSADDR_MATCH_ALL ) )
  2089. {
  2090. // remove this IP entry and replace with
  2091. // last IP entry in array
  2092. newCount--;
  2093. if ( i >= newCount )
  2094. {
  2095. break;
  2096. }
  2097. DnsAddr_Copy(
  2098. & pArraySub->AddrArray[i],
  2099. & pArraySub->AddrArray[newCount] );
  2100. }
  2101. }
  2102. // if eliminated entries, reset array count
  2103. if ( newCount < pArraySub->AddrCount )
  2104. {
  2105. pArraySub->AddrCount = newCount;
  2106. return( FALSE );
  2107. }
  2108. return( TRUE );
  2109. }
  2110. //
  2111. // Special case initializations
  2112. //
  2113. VOID
  2114. DnsAddrArray_InitSingleWithAddr(
  2115. IN OUT PDNS_ADDR_ARRAY pArray,
  2116. IN PDNS_ADDR pAddr
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. Init array to contain single address.
  2121. This is for single address passing in array -- usually stack array.
  2122. Note, that this assumes uninitialized array unlike DnsAddrArray_AddIp()
  2123. and creates single IP array.
  2124. Arguments:
  2125. pArray -- array, at least of length 1
  2126. pAddr -- ptr to DNS address
  2127. Return Value:
  2128. None
  2129. --*/
  2130. {
  2131. pArray->AddrCount = 1;
  2132. pArray->MaxCount = 1;
  2133. DnsAddr_Copy(
  2134. &pArray->AddrArray[0],
  2135. pAddr );
  2136. }
  2137. VOID
  2138. DnsAddrArray_InitSingleWithIp6(
  2139. IN OUT PDNS_ADDR_ARRAY pArray,
  2140. IN PIP6_ADDRESS pIp6
  2141. )
  2142. /*++
  2143. Routine Description:
  2144. Init array to contain single IP6 address.
  2145. This is for single address passing in array -- usually stack array.
  2146. Note, that this assumes uninitialized array unlike DnsAddrArray_AddIp()
  2147. and creates single IP array.
  2148. Arguments:
  2149. pArray -- array, at least of length 1
  2150. pIp6 -- IP6 address
  2151. Return Value:
  2152. None
  2153. --*/
  2154. {
  2155. pArray->AddrCount = 1;
  2156. pArray->MaxCount = 1;
  2157. DnsAddr_BuildFromIp6(
  2158. &pArray->AddrArray[0],
  2159. pIp6,
  2160. 0, // no scope
  2161. 0 // no port info
  2162. );
  2163. }
  2164. VOID
  2165. DnsAddrArray_InitSingleWithIp4(
  2166. IN OUT PDNS_ADDR_ARRAY pArray,
  2167. IN IP4_ADDRESS Ip4Addr
  2168. )
  2169. /*++
  2170. Routine Description:
  2171. Init IP array to contain single IP4 address.
  2172. This is for single address passing in array -- usually stack array.
  2173. Note, that this assumes uninitialized array unlike DnsAddrArray_AddIp()
  2174. and creates single IP array.
  2175. Arguments:
  2176. pArray -- DNS_ADDR_ARRAY, at least of length 1
  2177. Ip4Addr -- IP4 address
  2178. Return Value:
  2179. None
  2180. --*/
  2181. {
  2182. pArray->AddrCount = 1;
  2183. pArray->MaxCount = 1;
  2184. DnsAddr_BuildFromIp4(
  2185. &pArray->AddrArray[0],
  2186. Ip4Addr,
  2187. 0 // no port info
  2188. );
  2189. }
  2190. DWORD
  2191. DnsAddrArray_InitSingleWithSockaddr(
  2192. IN OUT PDNS_ADDR_ARRAY pArray,
  2193. IN PSOCKADDR pSockAddr
  2194. )
  2195. /*++
  2196. Routine Description:
  2197. Init IP array to contain single address.
  2198. This is for single address passing in array -- usually stack array.
  2199. Note, that this assumes uninitialized array unlike DnsAddrArray_AddIp()
  2200. and creates single IP array.
  2201. Arguments:
  2202. pArray -- DNS_ADDR_ARRAY, at least of length 1
  2203. pSockaddr -- ptr to sockaddr
  2204. Return Value:
  2205. Family of sockaddr (AF_INET or AF_INET6) if successful.
  2206. Zero on error.
  2207. --*/
  2208. {
  2209. pArray->AddrCount = 1;
  2210. pArray->MaxCount = 1;
  2211. return DnsAddr_Build(
  2212. &pArray->AddrArray[0],
  2213. pSockAddr,
  2214. 0, // any family
  2215. 0, // no subnet length info
  2216. 0 // no flags
  2217. );
  2218. }
  2219. //
  2220. // Write other types
  2221. //
  2222. PIP4_ARRAY
  2223. DnsAddrArray_CreateIp4Array(
  2224. IN PDNS_ADDR_ARRAY pArray
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. Create IP4 array from address array.
  2229. Arguments:
  2230. pArray -- array to make into IP4 array.
  2231. Return Value:
  2232. Ptr to IP4_ARRAY with all IP4 addrs in input array.
  2233. NULL if no IP4 in array.
  2234. NULL on failure.
  2235. --*/
  2236. {
  2237. PIP4_ARRAY parray4 = NULL;
  2238. DWORD i;
  2239. DWORD count4 = 0;
  2240. DNSDBG( IPARRAY, (
  2241. "DnsAddrArray_CreateIp4Array( %p )\n",
  2242. pArray ));
  2243. if ( ! pArray )
  2244. {
  2245. goto Done;
  2246. }
  2247. //
  2248. // count IP4
  2249. //
  2250. count4 = DnsAddrArray_GetFamilyCount( pArray, AF_INET );
  2251. //
  2252. // allocate the array
  2253. //
  2254. parray4 = Dns_CreateIpArray( count4 );
  2255. if ( !parray4 )
  2256. {
  2257. goto Done;
  2258. }
  2259. //
  2260. // fill the array
  2261. //
  2262. for ( i=0; i<pArray->AddrCount; i++ )
  2263. {
  2264. IP4_ADDRESS ip4;
  2265. ip4 = DnsAddr_GetIp4( &pArray->AddrArray[i] );
  2266. if ( ip4 != BAD_IP4_ADDR )
  2267. {
  2268. Dns_AddIpToIpArray(
  2269. parray4,
  2270. ip4 );
  2271. }
  2272. }
  2273. //
  2274. // reset to eliminate zero's which may be left by duplicate entries
  2275. //
  2276. // note, this does whack zeros, but that happens in Dns_AddIpToIpArray()
  2277. // above also, as zero's are taken to be "empty slots" in array;
  2278. // this is an artifact of the IP4_ARRAY being used both as a fixed
  2279. // object (where any value would be ok) and dynamically (where the
  2280. // zeros are treated as empty, because we don't have independent size
  2281. // and length fields)
  2282. //
  2283. Dns_CleanIpArray( parray4, DNS_IPARRAY_CLEAN_ZERO );
  2284. Done:
  2285. DNSDBG( IPARRAY, (
  2286. "Leave DnsAddrArray_CreateIp4Array() => %p\n"
  2287. "\tIP4 count %d\n"
  2288. "\tnew array count %d\n",
  2289. parray4,
  2290. parray4 ? parray4->AddrCount : 0,
  2291. count4 ));
  2292. return( parray4 );
  2293. }
  2294. DWORD
  2295. DnsAddrArray_NetworkMatchIp4(
  2296. IN PDNS_ADDR_ARRAY pArray,
  2297. IN IP4_ADDRESS IpAddr,
  2298. OUT PDNS_ADDR * ppAddr
  2299. )
  2300. /*++
  2301. Routine Description:
  2302. Check through array for best network match.
  2303. Arguments:
  2304. pArray -- existing array
  2305. IpAddr -- IP4 addr to check
  2306. ppAddr -- addr to receive ptr to best match element
  2307. Return Value:
  2308. DNSADDR_NETMATCH_NONE
  2309. DNSADDR_NETMATCH_CLASSA
  2310. DNSADDR_NETMATCH_CLASSB
  2311. DNSADDR_NETMATCH_CLASSC
  2312. DNSADDR_NETMATCH_SUBNET
  2313. --*/
  2314. {
  2315. DWORD i;
  2316. IP4_ADDRESS classMask;
  2317. DWORD fmatch = DNSADDR_NETMATCH_NONE;
  2318. PDNS_ADDR paddrMatch = NULL;
  2319. DNSDBG( IPARRAY, (
  2320. "DnsAddrArray_NetworkMatchIp( %p, %s, %p )\n",
  2321. pArray,
  2322. IP4_STRING( IpAddr ),
  2323. ppAddr ));
  2324. if ( ! pArray )
  2325. {
  2326. goto Done;
  2327. }
  2328. //
  2329. // DCR: subnet matching improvements
  2330. // - use length throughout
  2331. // - return bits matched
  2332. // - 32 for identical addrs
  2333. // - 31 for subnet match
  2334. // - 0 no match in class
  2335. //
  2336. // separate matching function with optional
  2337. // IN param of class subnet length of IP
  2338. //
  2339. //
  2340. // get class subnet mask
  2341. //
  2342. classMask = Dns_GetNetworkMask( IpAddr );
  2343. //
  2344. // check each element in array
  2345. //
  2346. for ( i=0; i<pArray->AddrCount; i++ )
  2347. {
  2348. DWORD classMatchLevel;
  2349. IP4_ADDRESS subnet;
  2350. IP4_ADDRESS ip;
  2351. PDNS_ADDR paddr = &pArray->AddrArray[i];
  2352. ip = DnsAddr_GetIp4( paddr );
  2353. if ( ip == BAD_IP4_ADDR )
  2354. {
  2355. continue;
  2356. }
  2357. // xor to nix any common network bits
  2358. ip = ip ^ IpAddr;
  2359. // check subnet match (if subnet given)
  2360. // note shift bits up, as in network order
  2361. subnet = (IP4_ADDRESS)(-1);
  2362. if ( paddr->SubnetLength )
  2363. {
  2364. subnet >>= (32 - paddr->SubnetLength);
  2365. if ( (ip & subnet) == 0 )
  2366. {
  2367. fmatch = DNSADDR_NETMATCH_SUBNET;
  2368. paddrMatch = paddr;
  2369. break;
  2370. }
  2371. }
  2372. //
  2373. // try class match
  2374. // - stop if have previous match at this level
  2375. // - otherwise always do class C
  2376. // - stop if reach class subnet for IpAddr
  2377. // example, we do NOT return NETMATCH_CLASSB for
  2378. // a class C address -- it's meaningless
  2379. //
  2380. classMatchLevel = DNSADDR_NETMATCH_CLASSC;
  2381. subnet = SUBNET_MASK_CLASSC;
  2382. while ( fmatch < classMatchLevel )
  2383. {
  2384. if ( (ip & subnet) == 0 )
  2385. {
  2386. fmatch = classMatchLevel;
  2387. paddrMatch = paddr;
  2388. break;
  2389. }
  2390. classMatchLevel--;
  2391. subnet >>= 8;
  2392. if ( classMask > subnet )
  2393. {
  2394. break;
  2395. }
  2396. }
  2397. }
  2398. Done:
  2399. //
  2400. // set return addr
  2401. //
  2402. if ( ppAddr )
  2403. {
  2404. *ppAddr = paddrMatch;
  2405. }
  2406. DNSDBG( IPARRAY, (
  2407. "Leave DnsAddrArray_NetworkMatchIp( %p, %s, %p )\n"
  2408. "\tMatch Level = %d\n"
  2409. "\tMatch Addr = %s (subnet len %d)\n",
  2410. pArray,
  2411. IP4_STRING( IpAddr ),
  2412. ppAddr,
  2413. paddrMatch ? DNSADDR_STRING(paddrMatch) : NULL,
  2414. paddrMatch ? paddrMatch->SubnetLength : 0 ));
  2415. return( fmatch );
  2416. }
  2417. //
  2418. // End dnsaddr.c
  2419. //