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.

2426 lines
44 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. ip6.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. IP6 address array routines.
  8. Author:
  9. Jim Gilroy (jamesg) October 2001
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. //
  14. // Max IP count when doing IP array to\from string conversions
  15. //
  16. #define MAX_PARSE_IP (1000)
  17. //
  18. // For IP6 debug string writing.
  19. //
  20. CHAR g_Ip6StringBuffer[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
  21. //
  22. // IP6 Mcast address base
  23. // FF02:0:0:0:0:2::/96 base plus 32bits of hash
  24. //
  25. // IP6_ADDRESS g_Ip6McastBaseAddr = {0xFF,2, 0,0, 0,0, 0,0, 0,0, 0,2, 0,0, 0,0};
  26. //
  27. // General IP6 routines.
  28. //
  29. VOID
  30. Dns_Md5Hash(
  31. OUT PBYTE pHash,
  32. IN PSTR pName
  33. )
  34. /*++
  35. Routine Description:
  36. Create MD5 hash of name.
  37. Arguments:
  38. pHash -- 128bit (16 byte) buffer to recv hash
  39. pName -- name to hash
  40. Return Value:
  41. None
  42. --*/
  43. {
  44. DNSDBG( TRACE, (
  45. "Dns_Md5Hash( %p, %s )\n",
  46. pHash,
  47. pName ));
  48. //
  49. // DCR: FIX0: need real MD5 hash -- ask Lars, Scott
  50. //
  51. {
  52. DWORD sum = 0;
  53. RtlZeroMemory(
  54. pHash,
  55. 16 );
  56. while ( *pName )
  57. {
  58. sum += *pName++;
  59. }
  60. * (PDWORD)pHash = sum;
  61. }
  62. }
  63. BOOL
  64. Ip6_McastCreate(
  65. OUT PIP6_ADDRESS pIp,
  66. IN PWSTR pName
  67. )
  68. /*++
  69. Routine Description:
  70. Create mcast IP6 address.
  71. Arguments:
  72. pIp -- address to set with mcast address
  73. pName -- DNS name mcast address is for
  74. Return Value:
  75. TRUE if made mcast address for name.
  76. FALSE on error.
  77. --*/
  78. {
  79. WCHAR label[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  80. WCHAR downLabel[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  81. CHAR utf8Label[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  82. CHAR md5Hash[ 16 ]; // 128bit hash
  83. IP6_ADDRESS mcastAddr;
  84. DWORD bufLength;
  85. DNSDBG( TRACE, (
  86. "Ip6_McastCreate( %p, %S )\n",
  87. pIp,
  88. pName ));
  89. //
  90. // hash of downcased label
  91. //
  92. Dns_CopyNameLabelW(
  93. label,
  94. pName );
  95. Dns_MakeCanonicalNameW(
  96. downLabel,
  97. DNS_MAX_LABEL_BUFFER_LENGTH,
  98. label,
  99. 0 // null terminated
  100. );
  101. bufLength = DNS_MAX_LABEL_BUFFER_LENGTH;
  102. if ( !Dns_StringCopy(
  103. utf8Label,
  104. & bufLength,
  105. (PCHAR) downLabel,
  106. 0, // null terminated
  107. DnsCharSetUnicode,
  108. DnsCharSetUtf8 ) )
  109. {
  110. DNS_ASSERT( FALSE );
  111. return FALSE;
  112. }
  113. //
  114. // hash
  115. //
  116. Dns_Md5Hash(
  117. md5Hash,
  118. utf8Label );
  119. // mcast addr
  120. // - first 12 bytes are fixed
  121. // - last 4 bytes are first 32bits of hash
  122. #if 0
  123. IP6_ADDR_COPY(
  124. pIp,
  125. & g_Ip6McastBaseAddr );
  126. #else
  127. RtlZeroMemory(
  128. pIp,
  129. sizeof(IP6_ADDRESS) );
  130. pIp->IP6Byte[0] = 0xff;
  131. pIp->IP6Byte[1] = 2;
  132. pIp->IP6Byte[11] = 2;
  133. #endif
  134. RtlCopyMemory(
  135. & pIp->IP6Dword[3],
  136. md5Hash,
  137. sizeof(DWORD) );
  138. return TRUE;
  139. }
  140. DWORD
  141. Ip6_CopyFromSockaddr(
  142. OUT PIP6_ADDRESS pIp,
  143. IN PSOCKADDR pSockAddr,
  144. IN INT Family
  145. )
  146. /*++
  147. Routine Description:
  148. Extract IP from sockaddr.
  149. Arguments:
  150. pIp -- addr to set with IP6 address
  151. pSockaddr -- ptr to sockaddr
  152. Family --
  153. AF_INET6 to only extract if 6
  154. AF_INET4 to only extract if 4
  155. 0 to extract always
  156. Return Value:
  157. Family extracted (AF_INET) or (AF_INET6) if successful.
  158. Zero on bad sockaddr family.
  159. --*/
  160. {
  161. DWORD saFamily = pSockAddr->sa_family;
  162. if ( Family &&
  163. saFamily != Family )
  164. {
  165. return 0;
  166. }
  167. if ( saFamily == AF_INET6 )
  168. {
  169. IP6_ADDR_COPY(
  170. pIp,
  171. (PIP6_ADDRESS) &((PSOCKADDR_IN6)pSockAddr)->sin6_addr );
  172. }
  173. else if ( saFamily == AF_INET )
  174. {
  175. IP6_SET_ADDR_V4MAPPED(
  176. pIp,
  177. ((PSOCKADDR_IN)pSockAddr)->sin_addr.s_addr );
  178. }
  179. else
  180. {
  181. saFamily = 0;
  182. }
  183. return saFamily;
  184. }
  185. INT
  186. Ip6_Family(
  187. IN PIP6_ADDRESS pIp
  188. )
  189. /*++
  190. Routine Description:
  191. Get IP6 family
  192. AF_INET if V4MAPPED
  193. AF_INET6 otherwise
  194. Arguments:
  195. pIp -- addr
  196. Return Value:
  197. AF_INET if address is V4MAPPED
  198. AF_INET6 otherwise
  199. --*/
  200. {
  201. return IP6_IS_ADDR_V4MAPPED(pIp) ? AF_INET : AF_INET6;
  202. }
  203. INT
  204. Ip6_WriteSockaddr(
  205. OUT PSOCKADDR pSockaddr,
  206. OUT PDWORD pSockaddrLength, OPTIONAL
  207. IN PIP6_ADDRESS pIp,
  208. IN WORD Port OPTIONAL
  209. )
  210. /*++
  211. Routine Description:
  212. Write sockaddr with IP6 or IP4 address.
  213. Arguments:
  214. pSockaddr -- ptr to sockaddr, must be at least SOCKADDR_IN6 size
  215. pSockaddrLength -- ptr to DWORD to set be with sockaddr length
  216. pIp -- addr to set with IP6 address
  217. Port -- port to write
  218. Return Value:
  219. Family written (AF_INET) or (AF_INET6) if successful.
  220. Zero on bad sockaddr family.
  221. --*/
  222. {
  223. WORD family;
  224. DWORD length;
  225. IP4_ADDRESS ip4;
  226. DNSDBG( SOCKET, (
  227. "Ip6_WriteSockaddr( %p, %p, %p, %d )\n",
  228. pSockaddr,
  229. pSockaddrLength,
  230. pIp,
  231. Port ));
  232. // zero
  233. RtlZeroMemory(
  234. pSockaddr,
  235. sizeof( SOCKADDR_IN6 ) );
  236. //
  237. // fill in sockaddr for IP4 or IP6
  238. //
  239. ip4 = IP6_GET_V4_ADDR_IF_MAPPED( pIp );
  240. if ( ip4 != BAD_IP4_ADDR )
  241. {
  242. family = AF_INET;
  243. length = sizeof(SOCKADDR_IN);
  244. ((PSOCKADDR_IN)pSockaddr)->sin_addr.s_addr = ip4;
  245. }
  246. else
  247. {
  248. family = AF_INET6;
  249. length = sizeof(SOCKADDR_IN6);
  250. RtlCopyMemory(
  251. (PIP6_ADDRESS) &((PSOCKADDR_IN6)pSockaddr)->sin6_addr,
  252. pIp,
  253. sizeof(IP6_ADDRESS) );
  254. }
  255. // fill family and port -- same position for both type
  256. pSockaddr->sa_family = family;
  257. ((PSOCKADDR_IN)pSockaddr)->sin_port = Port;
  258. // return length if requested
  259. if ( pSockaddrLength )
  260. {
  261. *pSockaddrLength = length;
  262. }
  263. return family;
  264. }
  265. INT
  266. Ip6_WriteDnsAddr(
  267. OUT PDNS_ADDR pDnsAddr,
  268. IN PIP6_ADDRESS pIp,
  269. IN WORD Port OPTIONAL
  270. )
  271. /*++
  272. Routine Description:
  273. Write DNS_ADDR with IP6 or IP4 address.
  274. Arguments:
  275. pSockaddr -- ptr to sockaddr blob
  276. pIp -- addr to set with IP6 address
  277. Port -- port to write
  278. Return Value:
  279. Family written (AF_INET) or (AF_INET6) if successful.
  280. Zero on bad sockaddr family.
  281. --*/
  282. {
  283. return Ip6_WriteSockaddr(
  284. & pDnsAddr->Sockaddr,
  285. & pDnsAddr->SockaddrLength,
  286. pIp,
  287. Port );
  288. }
  289. PSTR
  290. Ip6_TempNtoa(
  291. IN PIP6_ADDRESS pIp
  292. )
  293. /*++
  294. Routine Description:
  295. Get string for IP6 address.
  296. This is temp inet6_ntoa() until i get that built.
  297. This will work for all IP4 addresses and will (we presume)
  298. only rarely collide on IP6.
  299. Arguments:
  300. pIp -- ptr to IP to get string for
  301. Return Value:
  302. Address string.
  303. --*/
  304. {
  305. // make life simple
  306. if ( !pIp )
  307. {
  308. return NULL;
  309. }
  310. // if IP4, use existing inet_ntoa()
  311. if ( IP6_IS_ADDR_V4MAPPED( pIp ) )
  312. {
  313. return inet_ntoa( *(IN_ADDR *) &pIp->IP6Dword[3] );
  314. }
  315. // if IP6 write into global buffer
  316. // - until inet6_ntoa() which will use existing TLS block
  317. g_Ip6StringBuffer[0] = 0;
  318. RtlIpv6AddressToStringA(
  319. (PIN6_ADDR) pIp,
  320. g_Ip6StringBuffer );
  321. return g_Ip6StringBuffer;
  322. }
  323. PSTR
  324. Ip6_AddrStringForSockaddr(
  325. IN PSOCKADDR pSockaddr
  326. )
  327. /*++
  328. Routine Description:
  329. Get string for sockaddr.
  330. Arguments:
  331. pSockaddr -- ptr to sockaddr
  332. Return Value:
  333. Address string.
  334. --*/
  335. {
  336. IP6_ADDRESS ip6;
  337. if ( ! pSockaddr ||
  338. ! Ip6_CopyFromSockaddr(
  339. & ip6,
  340. pSockaddr,
  341. 0 ) )
  342. {
  343. return NULL;
  344. }
  345. return Ip6_TempNtoa( &ip6 );
  346. }
  347. //
  348. // Routines to handle actual array of IP addresses.
  349. //
  350. PIP6_ADDRESS
  351. Ip6_FlatArrayCopy(
  352. IN PIP6_ADDRESS AddrArray,
  353. IN DWORD Count
  354. )
  355. /*++
  356. Routine Description:
  357. Create copy of IP address array.
  358. Arguments:
  359. AddrArray -- array of IP addresses
  360. Count -- count of IP addresses
  361. Return Value:
  362. Ptr to IP address array copy, if successful
  363. NULL on failure.
  364. --*/
  365. {
  366. PIP6_ADDRESS parray;
  367. // validate
  368. if ( ! AddrArray || Count == 0 )
  369. {
  370. return( NULL );
  371. }
  372. // allocate memory and copy
  373. parray = (PIP6_ADDRESS) ALLOCATE_HEAP( Count*sizeof(IP6_ADDRESS) );
  374. if ( ! parray )
  375. {
  376. return( NULL );
  377. }
  378. memcpy(
  379. parray,
  380. AddrArray,
  381. Count*sizeof(IP6_ADDRESS) );
  382. return( parray );
  383. }
  384. #if 0
  385. BOOL
  386. Dns_ValidateIp6Array(
  387. IN PIP6_ADDRESS AddrArray,
  388. IN DWORD Count,
  389. IN DWORD dwFlag
  390. )
  391. /*++
  392. Routine Description:
  393. Validate IP address array.
  394. Current checks:
  395. - existence
  396. - non-broadcast
  397. - non-lookback
  398. Arguments:
  399. AddrArray -- array of IP addresses
  400. Count -- count of IP addresses
  401. dwFlag -- validity tests to do; currently unused
  402. Return Value:
  403. TRUE if valid IP addresses.
  404. FALSE if invalid address found.
  405. --*/
  406. {
  407. DWORD i;
  408. //
  409. // protect against bad parameters
  410. //
  411. if ( Count && ! AddrArray )
  412. {
  413. return( FALSE );
  414. }
  415. //
  416. // check each IP address
  417. //
  418. for ( i=0; i < Count; i++)
  419. {
  420. // DCR: need IP6 validations
  421. if( AddrArray[i] == INADDR_ANY
  422. ||
  423. AddrArray[i] == INADDR_BROADCAST
  424. ||
  425. AddrArray[i] == INADDR_LOOPBACK )
  426. {
  427. return( FALSE );
  428. }
  429. }
  430. return( TRUE );
  431. }
  432. #endif
  433. //
  434. // IP6_ARRAY routines
  435. //
  436. DWORD
  437. Ip6Array_Sizeof(
  438. IN PIP6_ARRAY pIpArray
  439. )
  440. /*++
  441. Routine Description:
  442. Get size in bytes of IP address array.
  443. Arguments:
  444. pIpArray -- IP address array to find size of
  445. Return Value:
  446. Size in bytes of IP array.
  447. --*/
  448. {
  449. if ( ! pIpArray )
  450. {
  451. return 0;
  452. }
  453. return (pIpArray->AddrCount * sizeof(IP6_ADDRESS)) + 2*sizeof(DWORD);
  454. }
  455. BOOL
  456. Ip6Array_Probe(
  457. IN PIP6_ARRAY pIpArray
  458. )
  459. /*++
  460. Routine Description:
  461. Touch all entries in IP array to insure valid memory.
  462. Arguments:
  463. pIpArray -- ptr to IP address array
  464. Return Value:
  465. TRUE if successful.
  466. FALSE otherwise
  467. --*/
  468. {
  469. DWORD i;
  470. BOOL result;
  471. if ( ! pIpArray )
  472. {
  473. return( TRUE );
  474. }
  475. for ( i=0; i<pIpArray->AddrCount; i++ )
  476. {
  477. result = IP6_IS_ADDR_LOOPBACK( &pIpArray->AddrArray[i] );
  478. }
  479. return( TRUE );
  480. }
  481. #if 0
  482. BOOL
  483. Ip6Array_ValidateSizeOf(
  484. IN PIP6_ARRAY pIpArray,
  485. IN DWORD dwMemoryLength
  486. )
  487. /*++
  488. Routine Description:
  489. Check that size of IP array, corresponds to length of memory.
  490. Arguments:
  491. pIpArray -- ptr to IP address array
  492. dwMemoryLength -- length of IP array memory
  493. Return Value:
  494. TRUE if IP array size matches memory length
  495. FALSE otherwise
  496. --*/
  497. {
  498. return( Ip6Array_SizeOf(pIpArray) == dwMemoryLength );
  499. }
  500. #endif
  501. VOID
  502. Ip6Array_Init(
  503. IN OUT PIP6_ARRAY pIpArray,
  504. IN DWORD MaxCount
  505. )
  506. /*++
  507. Routine Description:
  508. Init memory as IP6 array.
  509. Arguments:
  510. pArray -- array to init
  511. MaxCount -- count of addresses
  512. Return Value:
  513. None
  514. --*/
  515. {
  516. pIpArray->MaxCount = MaxCount;
  517. pIpArray->AddrCount = 0;
  518. }
  519. VOID
  520. Ip6Array_Free(
  521. IN PIP6_ARRAY pIpArray
  522. )
  523. /*++
  524. Routine Description:
  525. Free IP array.
  526. Only for arrays created through create routines below.
  527. Arguments:
  528. pIpArray -- IP array to free.
  529. Return Value:
  530. None
  531. --*/
  532. {
  533. FREE_HEAP( pIpArray );
  534. }
  535. PIP6_ARRAY
  536. Ip6Array_Create(
  537. IN DWORD MaxCount
  538. )
  539. /*++
  540. Routine Description:
  541. Create uninitialized IP address array.
  542. Arguments:
  543. AddrCount -- count of addresses array will hold
  544. Return Value:
  545. Ptr to uninitialized IP address array, if successful
  546. NULL on failure.
  547. --*/
  548. {
  549. PIP6_ARRAY parray;
  550. DNSDBG( IPARRAY, ( "Ip6Array_Create() of count %d\n", MaxCount ));
  551. parray = (PIP6_ARRAY) ALLOCATE_HEAP_ZERO(
  552. (MaxCount * sizeof(IP6_ADDRESS)) +
  553. sizeof(IP6_ARRAY) - sizeof(IP6_ADDRESS) );
  554. if ( ! parray )
  555. {
  556. return( NULL );
  557. }
  558. //
  559. // initialize IP count
  560. //
  561. parray->MaxCount = MaxCount;
  562. DNSDBG( IPARRAY, (
  563. "Ip6Array_Create() new array (count %d) at %p\n",
  564. MaxCount,
  565. parray ));
  566. return( parray );
  567. }
  568. PIP6_ARRAY
  569. Ip6Array_CreateFromIp4Array(
  570. IN PIP4_ARRAY pIp4Array
  571. )
  572. /*++
  573. Routine Description:
  574. Create IP6 array from IP4 array.
  575. Arguments:
  576. pIp4Array -- IP4 array
  577. Return Value:
  578. Ptr to uninitialized IP address array, if successful
  579. NULL on failure.
  580. --*/
  581. {
  582. PIP6_ARRAY parray;
  583. DWORD i;
  584. DNSDBG( IPARRAY, (
  585. "Ip6Array_CreateFromIp4Array( %p )\n",
  586. pIp4Array ));
  587. if ( ! pIp4Array )
  588. {
  589. return( NULL );
  590. }
  591. //
  592. // allocate the array
  593. //
  594. parray = Ip6Array_Create( pIp4Array->AddrCount );
  595. if ( !parray )
  596. {
  597. return NULL;
  598. }
  599. //
  600. // fill the array
  601. //
  602. for ( i=0; i<pIp4Array->AddrCount; i++ )
  603. {
  604. Ip6Array_AddIp4(
  605. parray,
  606. pIp4Array->AddrArray[i],
  607. FALSE // no duplicate screen
  608. );
  609. }
  610. DNSDBG( IPARRAY, (
  611. "Leave Ip6Array_CreateFromIp4Array() new array (count %d) at %p\n",
  612. parray->AddrCount,
  613. parray ));
  614. return( parray );
  615. }
  616. PIP6_ARRAY
  617. Ip6Array_CreateFromFlatArray(
  618. IN DWORD AddrCount,
  619. IN PIP6_ADDRESS pipAddrs
  620. )
  621. /*++
  622. Routine Description:
  623. Create IP address array structure from existing array of IP addresses.
  624. Arguments:
  625. AddrCount -- count of addresses in array
  626. pipAddrs -- IP address array
  627. Return Value:
  628. Ptr to IP address array.
  629. NULL on failure.
  630. --*/
  631. {
  632. PIP6_ARRAY parray;
  633. if ( ! pipAddrs || ! AddrCount )
  634. {
  635. return( NULL );
  636. }
  637. // create IP array of desired size
  638. // then copy incoming array of addresses
  639. parray = Ip6Array_Create( AddrCount );
  640. if ( ! parray )
  641. {
  642. return( NULL );
  643. }
  644. memcpy(
  645. parray->AddrArray,
  646. pipAddrs,
  647. AddrCount * sizeof(IP6_ADDRESS) );
  648. parray->AddrCount = AddrCount;
  649. return( parray );
  650. }
  651. PIP6_ARRAY
  652. Ip6Array_CopyAndExpand(
  653. IN PIP6_ARRAY pIpArray,
  654. IN DWORD ExpandCount,
  655. IN BOOL fDeleteExisting
  656. )
  657. /*++
  658. Routine Description:
  659. Create expanded copy of IP address array.
  660. Arguments:
  661. pIpArray -- IP address array to copy
  662. ExpandCount -- number of IP to expand array size by
  663. fDeleteExisting -- TRUE to delete existing array;
  664. this is useful when function is used to grow existing
  665. IP array in place; note that locking must be done
  666. by caller
  667. note, that if new array creation FAILS -- then old array
  668. is NOT deleted
  669. Return Value:
  670. Ptr to IP array copy, if successful
  671. NULL on failure.
  672. --*/
  673. {
  674. PIP6_ARRAY pnewArray;
  675. DWORD newCount;
  676. //
  677. // no existing array -- just create desired size
  678. //
  679. if ( ! pIpArray )
  680. {
  681. if ( ExpandCount )
  682. {
  683. return Ip6Array_Create( ExpandCount );
  684. }
  685. return( NULL );
  686. }
  687. //
  688. // create IP array of desired size
  689. // then copy any existing addresses
  690. //
  691. pnewArray = Ip6Array_Create( pIpArray->AddrCount + ExpandCount );
  692. if ( ! pnewArray )
  693. {
  694. return( NULL );
  695. }
  696. RtlCopyMemory(
  697. (PBYTE) pnewArray->AddrArray,
  698. (PBYTE) pIpArray->AddrArray,
  699. pIpArray->AddrCount * sizeof(IP6_ADDRESS) );
  700. //
  701. // delete existing -- for "grow mode"
  702. //
  703. if ( fDeleteExisting )
  704. {
  705. FREE_HEAP( pIpArray );
  706. }
  707. return( pnewArray );
  708. }
  709. PIP6_ARRAY
  710. Ip6Array_CreateCopy(
  711. IN PIP6_ARRAY pIpArray
  712. )
  713. /*++
  714. Routine Description:
  715. Create copy of IP address array.
  716. Arguments:
  717. pIpArray -- IP address array to copy
  718. Return Value:
  719. Ptr to IP address array copy, if successful
  720. NULL on failure.
  721. --*/
  722. {
  723. #if 0
  724. PIP6_ARRAY pIpArrayCopy;
  725. if ( ! pIpArray )
  726. {
  727. return( NULL );
  728. }
  729. // create IP array of desired size
  730. // then copy entire structure
  731. pIpArrayCopy = Ip6Array_Create( pIpArray->AddrCount );
  732. if ( ! pIpArrayCopy )
  733. {
  734. return( NULL );
  735. }
  736. memcpy(
  737. pIpArrayCopy,
  738. pIpArray,
  739. Ip6Array_Sizeof(pIpArray) );
  740. return( pIpArrayCopy );
  741. #endif
  742. //
  743. // call essentially "CopyEx" function
  744. //
  745. // note, not macroing this because this may well become
  746. // a DLL entry point
  747. //
  748. return Ip6Array_CopyAndExpand(
  749. pIpArray,
  750. 0, // no expansion
  751. 0 // don't delete existing array
  752. );
  753. }
  754. BOOL
  755. Ip6Array_ContainsIp(
  756. IN PIP6_ARRAY pIpArray,
  757. IN PIP6_ADDRESS pIp
  758. )
  759. /*++
  760. Routine Description:
  761. Check if IP array contains desired address.
  762. Arguments:
  763. pIpArray -- IP address array to copy
  764. pIp -- IP to check for
  765. Return Value:
  766. TRUE if address in array.
  767. Ptr to IP address array copy, if successful
  768. NULL on failure.
  769. --*/
  770. {
  771. DWORD i;
  772. if ( ! pIpArray )
  773. {
  774. return( FALSE );
  775. }
  776. for (i=0; i<pIpArray->AddrCount; i++)
  777. {
  778. if ( IP6_ADDR_EQUAL( pIp, &pIpArray->AddrArray[i] ) )
  779. {
  780. return( TRUE );
  781. }
  782. }
  783. return( FALSE );
  784. }
  785. BOOL
  786. Ip6Array_AddIp(
  787. IN OUT PIP6_ARRAY pIpArray,
  788. IN PIP6_ADDRESS pAddIp,
  789. IN BOOL fScreenDups
  790. )
  791. /*++
  792. Routine Description:
  793. Add IP address to IP array.
  794. Allowable "slot" in array, is any zero IP address.
  795. Arguments:
  796. pIpArray -- IP address array to add to
  797. pAddIp -- IP address to add to array
  798. fScreenDups -- screen out duplicates
  799. Return Value:
  800. TRUE if successful.
  801. FALSE if array full.
  802. --*/
  803. {
  804. DWORD count;
  805. //
  806. // screen for existence
  807. //
  808. // this check makes it easy to write code that does
  809. // Add\Full?=>Expand loop without having to write
  810. // startup existence\create code
  811. //
  812. if ( !pIpArray )
  813. {
  814. return FALSE;
  815. }
  816. //
  817. // check for duplicates
  818. //
  819. if ( fScreenDups )
  820. {
  821. if ( Ip6Array_ContainsIp( pIpArray, pAddIp ) )
  822. {
  823. return TRUE;
  824. }
  825. }
  826. count = pIpArray->AddrCount;
  827. if ( count >= pIpArray->MaxCount )
  828. {
  829. return FALSE;
  830. }
  831. IP6_ADDR_COPY(
  832. &pIpArray->AddrArray[ count ],
  833. pAddIp );
  834. pIpArray->AddrCount = ++count;
  835. return TRUE;
  836. }
  837. BOOL
  838. Ip6Array_AddSockaddr(
  839. IN OUT PIP6_ARRAY pIpArray,
  840. IN PSOCKADDR pSockaddr,
  841. IN DWORD Family,
  842. IN BOOL fScreenDups
  843. )
  844. /*++
  845. Routine Description:
  846. Add IP address to IP array.
  847. Allowable "slot" in array, is any zero IP address.
  848. Arguments:
  849. pIpArray -- IP address array to add to
  850. pAddIp -- IP address to add to array
  851. Family -- required family to do add; 0 for add always
  852. fScreenDups -- screen out duplicates
  853. Return Value:
  854. TRUE if successful.
  855. FALSE if array full.
  856. --*/
  857. {
  858. IP6_ADDRESS ip6;
  859. if ( !Ip6_CopyFromSockaddr(
  860. & ip6,
  861. pSockaddr,
  862. Family ) )
  863. {
  864. return FALSE;
  865. }
  866. return Ip6Array_AddIp(
  867. pIpArray,
  868. &ip6,
  869. fScreenDups );
  870. }
  871. BOOL
  872. Ip6Array_AddIp4(
  873. IN OUT PIP6_ARRAY pIpArray,
  874. IN IP4_ADDRESS Ip4,
  875. IN BOOL fScreenDups
  876. )
  877. /*++
  878. Routine Description:
  879. Add IP4 address to IP array.
  880. Arguments:
  881. pIpArray -- IP address array to add to
  882. Ip4 -- IP4 address to add to array
  883. fScreenDups -- screen out duplicates
  884. Return Value:
  885. TRUE if successful.
  886. FALSE if array full.
  887. --*/
  888. {
  889. IP6_ADDRESS ip6;
  890. IP6_SET_ADDR_V4MAPPED(
  891. &ip6,
  892. Ip4 );
  893. return Ip6Array_AddIp(
  894. pIpArray,
  895. &ip6,
  896. fScreenDups );
  897. }
  898. VOID
  899. Ip6Array_Clear(
  900. IN OUT PIP6_ARRAY pIpArray
  901. )
  902. /*++
  903. Routine Description:
  904. Clear memory in IP array.
  905. Arguments:
  906. pIpArray -- IP address array to clear
  907. Return Value:
  908. None.
  909. --*/
  910. {
  911. // clear just the address list, leaving count intact
  912. RtlZeroMemory(
  913. pIpArray->AddrArray,
  914. pIpArray->AddrCount * sizeof(IP6_ADDRESS) );
  915. }
  916. VOID
  917. Ip6Array_Reverse(
  918. IN OUT PIP6_ARRAY pIpArray
  919. )
  920. /*++
  921. Routine Description:
  922. Reorder the list of IPs in reverse.
  923. Arguments:
  924. pIpArray -- IP address array to reorder
  925. Return Value:
  926. None.
  927. --*/
  928. {
  929. IP6_ADDRESS tempIp;
  930. DWORD i;
  931. DWORD j;
  932. //
  933. // swap IPs working from ends to the middle
  934. //
  935. if ( pIpArray &&
  936. pIpArray->AddrCount )
  937. {
  938. for ( i = 0, j = pIpArray->AddrCount - 1;
  939. i < j;
  940. i++, j-- )
  941. {
  942. IP6_ADDR_COPY(
  943. & tempIp,
  944. & pIpArray->AddrArray[i] );
  945. IP6_ADDR_COPY(
  946. & pIpArray->AddrArray[i],
  947. & pIpArray->AddrArray[j] );
  948. IP6_ADDR_COPY(
  949. & pIpArray->AddrArray[j],
  950. & tempIp );
  951. }
  952. }
  953. }
  954. BOOL
  955. Ip6Array_CheckAndMakeIpArraySubset(
  956. IN OUT PIP6_ARRAY pIpArraySub,
  957. IN PIP6_ARRAY pIpArraySuper
  958. )
  959. /*++
  960. Routine Description:
  961. Clear entries from IP array until it is subset of another IP array.
  962. Arguments:
  963. pIpArraySub -- IP array to make into subset
  964. pIpArraySuper -- IP array superset
  965. Return Value:
  966. TRUE if pIpArraySub is already subset.
  967. FALSE if needed to nix entries to make IP array a subset.
  968. --*/
  969. {
  970. DWORD i;
  971. DWORD newCount;
  972. //
  973. // check each entry in subset IP array,
  974. // if not in superset IP array, eliminate it
  975. //
  976. newCount = pIpArraySub->AddrCount;
  977. for (i=0; i < newCount; i++)
  978. {
  979. if ( ! Ip6Array_ContainsIp(
  980. pIpArraySuper,
  981. & pIpArraySub->AddrArray[i] ) )
  982. {
  983. // remove this IP entry and replace with
  984. // last IP entry in array
  985. newCount--;
  986. if ( i >= newCount )
  987. {
  988. break;
  989. }
  990. IP6_ADDR_COPY(
  991. & pIpArraySub->AddrArray[i],
  992. & pIpArraySub->AddrArray[ newCount ] );
  993. }
  994. }
  995. // if eliminated entries, reset array count
  996. if ( newCount < pIpArraySub->AddrCount )
  997. {
  998. pIpArraySub->AddrCount = newCount;
  999. return( FALSE );
  1000. }
  1001. return( TRUE );
  1002. }
  1003. DWORD
  1004. WINAPI
  1005. Ip6Array_DeleteIp(
  1006. IN OUT PIP6_ARRAY pIpArray,
  1007. IN PIP6_ADDRESS pIpDelete
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. Delete IP address from IP array.
  1012. Arguments:
  1013. pIpArray -- IP address array to add to
  1014. pIpDelete -- IP address to delete from array
  1015. Return Value:
  1016. Count of instances of IpDelete found in array.
  1017. --*/
  1018. {
  1019. DWORD found = 0;
  1020. INT i;
  1021. INT currentLast;
  1022. i = currentLast = pIpArray->AddrCount-1;
  1023. //
  1024. // check each IP for match to delete IP
  1025. // - go backwards through array
  1026. // - swap in last IP in array
  1027. //
  1028. while ( i >= 0 )
  1029. {
  1030. if ( IP6_ADDR_EQUAL( &pIpArray->AddrArray[i], pIpDelete ) )
  1031. {
  1032. IP6_ADDR_COPY(
  1033. & pIpArray->AddrArray[i],
  1034. & pIpArray->AddrArray[ currentLast ] );
  1035. IP6_SET_ADDR_ANY( &pIpArray->AddrArray[ currentLast ] );
  1036. currentLast--;
  1037. found++;
  1038. }
  1039. i--;
  1040. }
  1041. pIpArray->AddrCount = currentLast + 1;
  1042. return( found );
  1043. }
  1044. #if 0
  1045. INT
  1046. WINAPI
  1047. Ip6Array_Clean(
  1048. IN OUT PIP6_ARRAY pIpArray,
  1049. IN DWORD Flag
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. Clean IP array.
  1054. Remove bogus stuff from IP Array:
  1055. -- Zeros
  1056. -- Loopback
  1057. -- AutoNet
  1058. Arguments:
  1059. pIpArray -- IP address array to add to
  1060. Flag -- which cleanups to make
  1061. Return Value:
  1062. Count of instances cleaned from array.
  1063. --*/
  1064. {
  1065. DWORD found = 0;
  1066. INT i;
  1067. INT currentLast;
  1068. IP6_ADDRESS ip;
  1069. i = currentLast = pIpArray->AddrCount-1;
  1070. while ( i >= 0 )
  1071. {
  1072. ip = pIpArray->AddrArray[i];
  1073. if (
  1074. ( (Flag & DNS_IPARRAY_CLEAN_LOOPBACK) && ip == DNS_NET_ORDER_LOOPBACK )
  1075. ||
  1076. ( (Flag & DNS_IPARRAY_CLEAN_ZERO) && ip == 0 )
  1077. ||
  1078. ( (Flag & DNS_IPARRAY_CLEAN_AUTONET) && DNS_IS_AUTONET_IP(ip) ) )
  1079. {
  1080. // remove IP from array
  1081. pIpArray->AddrArray[i] = pIpArray->AddrArray[ currentLast ];
  1082. currentLast--;
  1083. found++;
  1084. }
  1085. i--;
  1086. }
  1087. pIpArray->AddrCount -= found;
  1088. return( found );
  1089. }
  1090. #endif
  1091. DNS_STATUS
  1092. WINAPI
  1093. Ip6Array_Diff(
  1094. IN PIP6_ARRAY pIpArray1,
  1095. IN PIP6_ARRAY pIpArray2,
  1096. OUT PIP6_ARRAY* ppOnlyIn1,
  1097. OUT PIP6_ARRAY* ppOnlyIn2,
  1098. OUT PIP6_ARRAY* ppIntersect
  1099. )
  1100. /*++
  1101. Routine Description:
  1102. Computes differences and intersection of two IP arrays.
  1103. Out arrays are allocated with Ip6Array_Alloc(), caller must free with Ip6Array_Free()
  1104. Arguments:
  1105. pIpArray1 -- IP array
  1106. pIpArray2 -- IP array
  1107. ppOnlyIn1 -- addr to recv IP array of addresses only in array 1 (not in array2)
  1108. ppOnlyIn2 -- addr to recv IP array of addresses only in array 2 (not in array1)
  1109. ppIntersect -- addr to recv IP array of intersection addresses
  1110. Return Value:
  1111. ERROR_SUCCESS if successful.
  1112. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP arrays.
  1113. --*/
  1114. {
  1115. DWORD j;
  1116. PIP6_ADDRESS pip;
  1117. PIP6_ARRAY intersectArray = NULL;
  1118. PIP6_ARRAY only1Array = NULL;
  1119. PIP6_ARRAY only2Array = NULL;
  1120. //
  1121. // create result IP arrays
  1122. //
  1123. if ( ppIntersect )
  1124. {
  1125. intersectArray = Ip6Array_CreateCopy( pIpArray1 );
  1126. if ( !intersectArray )
  1127. {
  1128. goto NoMem;
  1129. }
  1130. *ppIntersect = intersectArray;
  1131. }
  1132. if ( ppOnlyIn1 )
  1133. {
  1134. only1Array = Ip6Array_CreateCopy( pIpArray1 );
  1135. if ( !only1Array )
  1136. {
  1137. goto NoMem;
  1138. }
  1139. *ppOnlyIn1 = only1Array;
  1140. }
  1141. if ( ppOnlyIn2 )
  1142. {
  1143. only2Array = Ip6Array_CreateCopy( pIpArray2 );
  1144. if ( !only2Array )
  1145. {
  1146. goto NoMem;
  1147. }
  1148. *ppOnlyIn2 = only2Array;
  1149. }
  1150. //
  1151. // clean the arrays
  1152. //
  1153. for ( j=0; j< pIpArray1->AddrCount; j++ )
  1154. {
  1155. pip = &pIpArray1->AddrArray[j];
  1156. // if IP in both arrays, delete from "only" arrays
  1157. if ( Ip6Array_ContainsIp( pIpArray2, pip ) )
  1158. {
  1159. if ( only1Array )
  1160. {
  1161. Ip6Array_DeleteIp( only1Array, pip );
  1162. }
  1163. if ( only2Array )
  1164. {
  1165. Ip6Array_DeleteIp( only2Array, pip );
  1166. }
  1167. }
  1168. // if IP not in both arrays, delete from intersection
  1169. // note intersection started as IpArray1
  1170. else if ( intersectArray )
  1171. {
  1172. Ip6Array_DeleteIp( intersectArray, pip );
  1173. }
  1174. }
  1175. return( ERROR_SUCCESS );
  1176. NoMem:
  1177. if ( intersectArray )
  1178. {
  1179. FREE_HEAP( intersectArray );
  1180. }
  1181. if ( only1Array )
  1182. {
  1183. FREE_HEAP( only1Array );
  1184. }
  1185. if ( only2Array )
  1186. {
  1187. FREE_HEAP( only2Array );
  1188. }
  1189. if ( ppIntersect )
  1190. {
  1191. *ppIntersect = NULL;
  1192. }
  1193. if ( ppOnlyIn1 )
  1194. {
  1195. *ppOnlyIn1 = NULL;
  1196. }
  1197. if ( ppOnlyIn2 )
  1198. {
  1199. *ppOnlyIn2 = NULL;
  1200. }
  1201. return( DNS_ERROR_NO_MEMORY );
  1202. }
  1203. BOOL
  1204. WINAPI
  1205. Ip6Array_IsIntersection(
  1206. IN PIP6_ARRAY pIpArray1,
  1207. IN PIP6_ARRAY pIpArray2
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. Determine if there's intersection of two IP arrays.
  1212. Arguments:
  1213. pIpArray1 -- IP array
  1214. pIpArray2 -- IP array
  1215. Return Value:
  1216. TRUE if intersection.
  1217. FALSE if no intersection or empty or NULL array.
  1218. --*/
  1219. {
  1220. DWORD count;
  1221. DWORD j;
  1222. //
  1223. // protect against NULL
  1224. // this is called from the server on potentially changing (reconfigurable)
  1225. // IP array pointers; this provides cheaper protection than
  1226. // worrying about locking
  1227. //
  1228. if ( !pIpArray1 || !pIpArray2 )
  1229. {
  1230. return( FALSE );
  1231. }
  1232. //
  1233. // same array
  1234. //
  1235. if ( pIpArray1 == pIpArray2 )
  1236. {
  1237. return( TRUE );
  1238. }
  1239. //
  1240. // test that at least one IP in array 1 is in array 2
  1241. //
  1242. count = pIpArray1->AddrCount;
  1243. for ( j=0; j < count; j++ )
  1244. {
  1245. if ( Ip6Array_ContainsIp( pIpArray2, &pIpArray1->AddrArray[j] ) )
  1246. {
  1247. return( TRUE );
  1248. }
  1249. }
  1250. // no intersection
  1251. return( FALSE );
  1252. }
  1253. BOOL
  1254. WINAPI
  1255. Ip6Array_IsEqual(
  1256. IN PIP6_ARRAY pIpArray1,
  1257. IN PIP6_ARRAY pIpArray2
  1258. )
  1259. /*++
  1260. Routine Description:
  1261. Determines if IP arrays are equal.
  1262. Arguments:
  1263. pIpArray1 -- IP array
  1264. pIpArray2 -- IP array
  1265. Return Value:
  1266. TRUE if arrays equal.
  1267. FALSE otherwise.
  1268. --*/
  1269. {
  1270. DWORD j;
  1271. DWORD count;
  1272. //
  1273. // same array? or missing array?
  1274. //
  1275. if ( pIpArray1 == pIpArray2 )
  1276. {
  1277. return( TRUE );
  1278. }
  1279. if ( !pIpArray1 || !pIpArray2 )
  1280. {
  1281. return( FALSE );
  1282. }
  1283. //
  1284. // arrays the same length?
  1285. //
  1286. count = pIpArray1->AddrCount;
  1287. if ( count != pIpArray2->AddrCount )
  1288. {
  1289. return( FALSE );
  1290. }
  1291. //
  1292. // test that each IP in array 1 is in array 2
  1293. //
  1294. // test that each IP in array 2 is in array 1
  1295. // - do second test in case of duplicates
  1296. // that fool equal-lengths check
  1297. //
  1298. for ( j=0; j < count; j++ )
  1299. {
  1300. if ( !Ip6Array_ContainsIp( pIpArray2, &pIpArray1->AddrArray[j] ) )
  1301. {
  1302. return( FALSE );
  1303. }
  1304. }
  1305. for ( j=0; j < count; j++ )
  1306. {
  1307. if ( !Ip6Array_ContainsIp( pIpArray1, &pIpArray2->AddrArray[j] ) )
  1308. {
  1309. return( FALSE );
  1310. }
  1311. }
  1312. // equal arrays
  1313. return( TRUE );
  1314. }
  1315. DNS_STATUS
  1316. WINAPI
  1317. Ip6Array_Union(
  1318. IN PIP6_ARRAY pIpArray1,
  1319. IN PIP6_ARRAY pIpArray2,
  1320. OUT PIP6_ARRAY* ppUnion
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. Computes the union of two IP arrays.
  1325. Out array is allocated with Ip6Array_Alloc(), caller must free with Ip6Array_Free()
  1326. Arguments:
  1327. pIpArray1 -- IP array
  1328. pIpArray2 -- IP array
  1329. ppUnion -- addr to recv IP array of addresses in array 1 and in array2
  1330. Return Value:
  1331. ERROR_SUCCESS if successful.
  1332. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP array.
  1333. --*/
  1334. {
  1335. DWORD j;
  1336. PIP6_ARRAY punionArray = NULL;
  1337. //
  1338. // create result IP arrays
  1339. //
  1340. if ( !ppUnion )
  1341. {
  1342. return( ERROR_INVALID_PARAMETER );
  1343. }
  1344. punionArray = Ip6Array_Create( pIpArray1->AddrCount +
  1345. pIpArray2->AddrCount );
  1346. if ( !punionArray )
  1347. {
  1348. goto NoMem;
  1349. }
  1350. *ppUnion = punionArray;
  1351. //
  1352. // create union from arrays
  1353. //
  1354. for ( j = 0; j < pIpArray1->AddrCount; j++ )
  1355. {
  1356. Ip6Array_AddIp(
  1357. punionArray,
  1358. & pIpArray1->AddrArray[j],
  1359. TRUE // screen out dups
  1360. );
  1361. }
  1362. for ( j = 0; j < pIpArray2->AddrCount; j++ )
  1363. {
  1364. Ip6Array_AddIp(
  1365. punionArray,
  1366. & pIpArray2->AddrArray[j],
  1367. TRUE // screen out dups
  1368. );
  1369. }
  1370. return( ERROR_SUCCESS );
  1371. NoMem:
  1372. if ( punionArray )
  1373. {
  1374. FREE_HEAP( punionArray );
  1375. *ppUnion = NULL;
  1376. }
  1377. return( DNS_ERROR_NO_MEMORY );
  1378. }
  1379. #if 0
  1380. DNS_STATUS
  1381. Ip6Array_CreateIpArrayFromMultiIpString(
  1382. IN PSTR pszMultiIpString,
  1383. OUT PIP6_ARRAY* ppIpArray
  1384. )
  1385. /*++
  1386. Routine Description:
  1387. Create IP array out of multi-IP string.
  1388. Arguments:
  1389. pszMultiIpString -- string containing IP addresses;
  1390. separator is whitespace or comma
  1391. ppIpArray -- addr to receive ptr to allocated IP array
  1392. Return Value:
  1393. ERROR_SUCCESS if one or more valid IP addresses in string.
  1394. DNS_ERROR_INVALID_IP6_ADDRESS if parsing error.
  1395. DNS_ERROR_NO_MEMORY if can not create IP array.
  1396. --*/
  1397. {
  1398. PCHAR pch;
  1399. CHAR ch;
  1400. PCHAR pbuf;
  1401. PCHAR pbufStop;
  1402. DNS_STATUS status = ERROR_SUCCESS;
  1403. DWORD countIp = 0;
  1404. IP6_ADDRESS ip;
  1405. CHAR buffer[ IP6_ADDRESS_STRING_LENGTH+2 ];
  1406. IP6_ADDRESS arrayIp[ MAX_PARSE_IP ];
  1407. // stop byte for IP string buffer
  1408. // - note we put extra byte pad in buffer above
  1409. // this allows us to write ON stop byte and use
  1410. // that to detect invalid-long IP string
  1411. //
  1412. pbufStop = buffer + IP6_ADDRESS_STRING_LENGTH;
  1413. //
  1414. // DCR: use IP array builder for local IP address
  1415. // then need Ip6Array_CreateIpArrayFromMultiIpString()
  1416. // to use count\alloc method when buffer overflows
  1417. // to do this we'd need to do parsing in loop
  1418. // and skip conversion when count overflow, but set
  1419. // flag to go back in again with allocated buffer
  1420. //
  1421. // safer would be to tokenize-count, alloc, build from tokens
  1422. //
  1423. //
  1424. // loop until reach end of string
  1425. //
  1426. pch = pszMultiIpString;
  1427. while ( countIp < MAX_PARSE_IP )
  1428. {
  1429. // skip whitespace
  1430. while ( ch = *pch++ )
  1431. {
  1432. if ( ch == ' ' || ch == '\t' || ch == ',' )
  1433. {
  1434. continue;
  1435. }
  1436. break;
  1437. }
  1438. if ( !ch )
  1439. {
  1440. break;
  1441. }
  1442. //
  1443. // copy next IP string into buffer
  1444. // - stop copy at whitespace or NULL
  1445. // - on invalid-long IP string, stop copying
  1446. // but continue parsing, so can still get any following IPs
  1447. // note, we actually write ON the buffer stop byte as our
  1448. // "invalid-long" detection mechanism
  1449. //
  1450. pbuf = buffer;
  1451. do
  1452. {
  1453. if ( pbuf <= pbufStop )
  1454. {
  1455. *pbuf++ = ch;
  1456. }
  1457. ch = *pch++;
  1458. }
  1459. while ( ch && ch != ' ' && ch != ',' && ch != '\t' );
  1460. //
  1461. // convert buffer into IP address
  1462. // - insure was valid length string
  1463. // - null terminate
  1464. //
  1465. if ( pbuf <= pbufStop )
  1466. {
  1467. *pbuf = 0;
  1468. ip = inet_addr( buffer );
  1469. if ( ip == INADDR_BROADCAST )
  1470. {
  1471. status = DNS_ERROR_INVALID_IP6_ADDRESS ;
  1472. }
  1473. else
  1474. {
  1475. arrayIp[ countIp++ ] = ip;
  1476. }
  1477. }
  1478. else
  1479. {
  1480. status = DNS_ERROR_INVALID_IP6_ADDRESS ;
  1481. }
  1482. // quit if at end of string
  1483. if ( !ch )
  1484. {
  1485. break;
  1486. }
  1487. }
  1488. //
  1489. // if successfully parsed IP addresses, create IP array
  1490. // note, we'll return what we have even if some addresses are
  1491. // bogus, status code will indicate the parsing problem
  1492. //
  1493. // note, if explicitly passed empty string, then create
  1494. // empty IP array, don't error
  1495. //
  1496. if ( countIp == 0 && *pszMultiIpString != 0 )
  1497. {
  1498. *ppIpArray = NULL;
  1499. status = DNS_ERROR_INVALID_IP6_ADDRESS ;
  1500. }
  1501. else
  1502. {
  1503. *ppIpArray = Ip6Array_CreateFromFlatArray(
  1504. countIp,
  1505. arrayIp );
  1506. if ( !*ppIpArray )
  1507. {
  1508. status = DNS_ERROR_NO_MEMORY;
  1509. }
  1510. IF_DNSDBG( IPARRAY )
  1511. {
  1512. DnsDbg_IpArray(
  1513. "New Parsed IP array",
  1514. NULL, // no name
  1515. *ppIpArray );
  1516. }
  1517. }
  1518. return( status );
  1519. }
  1520. LPSTR
  1521. Ip6Array_CreateMultiIpStringFrom(
  1522. IN PIP6_ARRAY pIpArray,
  1523. IN CHAR chSeparator OPTIONAL
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. Create IP array out of multi-IP string.
  1528. Arguments:
  1529. pIpArray -- IP array to generate string for
  1530. chSeparator -- separating character between strings;
  1531. OPTIONAL, if not given, blank is used
  1532. Return Value:
  1533. Ptr to string representation of IP array.
  1534. Caller must free.
  1535. --*/
  1536. {
  1537. PCHAR pch;
  1538. DWORD i;
  1539. PCHAR pszip;
  1540. DWORD length;
  1541. PCHAR pchstop;
  1542. CHAR buffer[ IP6_ADDRESS _STRING_LENGTH*MAX_PARSE_IP + 1 ];
  1543. //
  1544. // if no IP array, return NULL string
  1545. // this allows this function to simply indicate when registry
  1546. // delete rather than write is indicated
  1547. //
  1548. if ( !pIpArray )
  1549. {
  1550. return( NULL );
  1551. }
  1552. // if no separator, use blank
  1553. if ( !chSeparator )
  1554. {
  1555. chSeparator = ' ';
  1556. }
  1557. //
  1558. // loop through all IPs in array, appending each
  1559. //
  1560. pch = buffer;
  1561. pchstop = pch + ( IP6_ADDRESS _STRING_LENGTH * (MAX_PARSE_IP-1) );
  1562. *pch = 0;
  1563. for ( i=0; i < pIpArray->AddrCount; i++ )
  1564. {
  1565. if ( pch >= pchstop )
  1566. {
  1567. break;
  1568. }
  1569. pszip = IP4_STRING( pIpArray->AddrArray[i] );
  1570. if ( pszip )
  1571. {
  1572. length = strlen( pszip );
  1573. memcpy(
  1574. pch,
  1575. pszip,
  1576. length );
  1577. pch += length;
  1578. *pch++ = chSeparator;
  1579. }
  1580. }
  1581. // if wrote any strings, then write terminator over last separator
  1582. if ( pch != buffer )
  1583. {
  1584. *--pch = 0;
  1585. }
  1586. // create copy of buffer as return
  1587. length = (DWORD)(pch - buffer) + 1;
  1588. pch = ALLOCATE_HEAP( length );
  1589. if ( !pch )
  1590. {
  1591. return( NULL );
  1592. }
  1593. memcpy(
  1594. pch,
  1595. buffer,
  1596. length );
  1597. DNSDBG( IPARRAY, (
  1598. "String representation %s of IP array at %p\n",
  1599. pch,
  1600. pIpArray ));
  1601. return( pch );
  1602. }
  1603. #endif
  1604. VOID
  1605. Ip6Array_InitSingleWithIp(
  1606. IN OUT PIP6_ARRAY pArray,
  1607. IN PIP6_ADDRESS pIp
  1608. )
  1609. /*++
  1610. Routine Description:
  1611. Init IP array to contain single address.
  1612. This is for single address passing in array -- usually stack array.
  1613. Note, that this assumes uninitialized array unlike Ip6Array_AddIp()
  1614. and creates single IP array.
  1615. Arguments:
  1616. pArray -- IP6 array, at least of length 1
  1617. pIp -- ptr to IP6 address
  1618. Return Value:
  1619. None
  1620. --*/
  1621. {
  1622. pArray->AddrCount = 1;
  1623. pArray->MaxCount = 1;
  1624. IP6_ADDR_COPY(
  1625. &pArray->AddrArray[0],
  1626. pIp );
  1627. }
  1628. VOID
  1629. Ip6Array_InitSingleWithIp4(
  1630. IN OUT PIP6_ARRAY pArray,
  1631. IN IP4_ADDRESS Ip4Addr
  1632. )
  1633. /*++
  1634. Routine Description:
  1635. Init IP array to contain single address.
  1636. This is for single address passing in array -- usually stack array.
  1637. Note, that this assumes uninitialized array unlike Ip6Array_AddIp()
  1638. and creates single IP array.
  1639. Arguments:
  1640. pArray -- IP6 array, at least of length 1
  1641. Ip4Addr -- IP4 address
  1642. Return Value:
  1643. None
  1644. --*/
  1645. {
  1646. pArray->AddrCount = 1;
  1647. pArray->MaxCount = 1;
  1648. IP6_SET_ADDR_V4MAPPED(
  1649. &pArray->AddrArray[0],
  1650. Ip4Addr );
  1651. }
  1652. DWORD
  1653. Ip6Array_InitSingleWithSockaddr(
  1654. IN OUT PIP6_ARRAY pArray,
  1655. IN PSOCKADDR pSockAddr
  1656. )
  1657. /*++
  1658. Routine Description:
  1659. Init IP array to contain single address.
  1660. This is for single address passing in array -- usually stack array.
  1661. Note, that this assumes uninitialized array unlike Ip6Array_AddIp()
  1662. and creates single IP array.
  1663. Arguments:
  1664. pArray -- IP6 array, at least of length 1
  1665. pSockaddr -- ptr to sockaddr
  1666. Return Value:
  1667. Family of sockaddr (AF_INET or AF_INET6) if successful.
  1668. Zero on error.
  1669. --*/
  1670. {
  1671. pArray->AddrCount = 1;
  1672. pArray->MaxCount = 1;
  1673. return Ip6_CopyFromSockaddr(
  1674. &pArray->AddrArray[0],
  1675. pSockAddr,
  1676. 0 );
  1677. }
  1678. PIP4_ARRAY
  1679. Ip4Array_CreateFromIp6Array(
  1680. IN PIP6_ARRAY pIp6Array,
  1681. OUT PDWORD pCount6
  1682. )
  1683. /*++
  1684. Routine Description:
  1685. Create IP4 array from IP6 array.
  1686. Arguments:
  1687. pIp6Array -- IP6 array
  1688. pCount6 -- addr to receive count of IP6 addresses dropped
  1689. Return Value:
  1690. Ptr to uninitialized IP address array, if successful
  1691. NULL on failure.
  1692. --*/
  1693. {
  1694. PIP4_ARRAY parray = NULL;
  1695. DWORD i;
  1696. DWORD count6 = 0;
  1697. DNSDBG( IPARRAY, (
  1698. "Ip4Array_CreateFromIp6Array( %p, %p )\n",
  1699. pIp6Array,
  1700. pCount6 ));
  1701. if ( ! pIp6Array )
  1702. {
  1703. goto Done;
  1704. }
  1705. //
  1706. // allocate the array
  1707. //
  1708. parray = Dns_CreateIpArray( pIp6Array->AddrCount );
  1709. if ( !parray )
  1710. {
  1711. goto Done;
  1712. }
  1713. //
  1714. // fill the array
  1715. //
  1716. for ( i=0; i<pIp6Array->AddrCount; i++ )
  1717. {
  1718. IP4_ADDRESS ip4;
  1719. ip4 = IP6_GET_V4_ADDR_IF_MAPPED( &pIp6Array->AddrArray[i] );
  1720. if ( ip4 != BAD_IP4_ADDR )
  1721. {
  1722. Dns_AddIpToIpArray(
  1723. parray,
  1724. ip4 );
  1725. }
  1726. else
  1727. {
  1728. count6++;
  1729. }
  1730. }
  1731. Done:
  1732. // set dropped IP6 count
  1733. if ( pCount6 )
  1734. {
  1735. *pCount6 = count6;
  1736. }
  1737. DNSDBG( IPARRAY, (
  1738. "Leave Ip4Array_CreateFromIp6Array()\n"
  1739. "\tnew array (count %d) at %p\n"
  1740. "\tdropped IP6 count %d\n",
  1741. parray ? parray->AddrCount : 0,
  1742. parray,
  1743. count6 ));
  1744. return( parray );
  1745. }
  1746. //
  1747. // End ip6.c
  1748. //