Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1543 lines
27 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. iparray.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. IP Address array routines.
  8. Author:
  9. Jim Gilroy (jamesg) October 1995
  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. // Routines to handle actual array of IP addresses.
  19. //
  20. PIP_ADDRESS
  21. Dns_CreateIpAddressArrayCopy(
  22. IN PIP_ADDRESS aipAddress,
  23. IN DWORD cipAddress
  24. )
  25. /*++
  26. Routine Description:
  27. Create copy of IP address array.
  28. Arguments:
  29. aipAddress -- array of IP addresses
  30. cipAddress -- count of IP addresses
  31. Return Value:
  32. Ptr to IP address array copy, if successful
  33. NULL on failure.
  34. --*/
  35. {
  36. PIP_ADDRESS pipArray;
  37. // validate
  38. if ( ! aipAddress || cipAddress == 0 )
  39. {
  40. return( NULL );
  41. }
  42. // allocate memory and copy
  43. pipArray = (PIP_ADDRESS) ALLOCATE_HEAP( cipAddress*sizeof(IP_ADDRESS) );
  44. if ( ! pipArray )
  45. {
  46. return( NULL );
  47. }
  48. memcpy(
  49. pipArray,
  50. aipAddress,
  51. cipAddress*sizeof(IP_ADDRESS) );
  52. return( pipArray );
  53. }
  54. BOOL
  55. Dns_ValidateIpAddressArray(
  56. IN PIP_ADDRESS aipAddress,
  57. IN DWORD cipAddress,
  58. IN DWORD dwFlag
  59. )
  60. /*++
  61. Routine Description:
  62. Validate IP address array.
  63. Current checks:
  64. - existence
  65. - non-broadcast
  66. - non-lookback
  67. Arguments:
  68. aipAddress -- array of IP addresses
  69. cipAddress -- count of IP addresses
  70. dwFlag -- validity tests to do; currently unused
  71. Return Value:
  72. TRUE if valid IP addresses.
  73. FALSE if invalid address found.
  74. --*/
  75. {
  76. DWORD i;
  77. //
  78. // protect against bad parameters
  79. //
  80. if ( cipAddress && ! aipAddress )
  81. {
  82. return( FALSE );
  83. }
  84. //
  85. // check each IP address
  86. //
  87. for ( i=0; i < cipAddress; i++)
  88. {
  89. if( aipAddress[i] == INADDR_ANY
  90. ||
  91. aipAddress[i] == INADDR_BROADCAST
  92. ||
  93. aipAddress[i] == INADDR_LOOPBACK )
  94. {
  95. return( FALSE );
  96. }
  97. }
  98. return( TRUE );
  99. }
  100. //
  101. // IP_ARRAY routines
  102. //
  103. DWORD
  104. Dns_SizeofIpArray(
  105. IN PIP_ARRAY pIpArray
  106. )
  107. /*++
  108. Routine Description:
  109. Get size in bytes of IP address array.
  110. Arguments:
  111. pIpArray -- IP address array to find size of
  112. Return Value:
  113. Size in bytes of IP array.
  114. --*/
  115. {
  116. if ( ! pIpArray )
  117. {
  118. return 0;
  119. }
  120. return (pIpArray->AddrCount * sizeof(IP4_ADDRESS)) + sizeof(DWORD);
  121. }
  122. BOOL
  123. Dns_ProbeIpArray(
  124. IN PIP_ARRAY pIpArray
  125. )
  126. /*++
  127. Routine Description:
  128. Touch all entries in IP array to insure valid memory.
  129. Arguments:
  130. pIpArray -- ptr to IP address array
  131. Return Value:
  132. TRUE if successful.
  133. FALSE otherwise
  134. --*/
  135. {
  136. DWORD i;
  137. BOOL result;
  138. if ( ! pIpArray )
  139. {
  140. return( TRUE );
  141. }
  142. for ( i=0; i<pIpArray->AddrCount; i++ )
  143. {
  144. result = ( pIpArray->AddrArray[i] == 0 );
  145. }
  146. return( TRUE );
  147. }
  148. #if 0
  149. BOOL
  150. Dns_ValidateSizeOfIpArray(
  151. IN PIP_ARRAY pIpArray,
  152. IN DWORD dwMemoryLength
  153. )
  154. /*++
  155. Routine Description:
  156. Check that size of IP array, corresponds to length of memory.
  157. Arguments:
  158. pIpArray -- ptr to IP address array
  159. dwMemoryLength -- length of IP array memory
  160. Return Value:
  161. TRUE if IP array size matches memory length
  162. FALSE otherwise
  163. --*/
  164. {
  165. return( Dns_SizeOfIpArray(pIpArray) == dwMemoryLength );
  166. }
  167. #endif
  168. PIP_ARRAY
  169. Dns_CreateIpArray(
  170. IN DWORD AddrCount
  171. )
  172. /*++
  173. Routine Description:
  174. Create uninitialized IP address array.
  175. Arguments:
  176. AddrCount -- count of addresses array will hold
  177. Return Value:
  178. Ptr to uninitialized IP address array, if successful
  179. NULL on failure.
  180. --*/
  181. {
  182. PIP_ARRAY pIpArray;
  183. DNSDBG( IPARRAY, ( "Dns_CreateIpArray() of count %d\n", AddrCount ));
  184. pIpArray = (PIP_ARRAY) ALLOCATE_HEAP_ZERO(
  185. (AddrCount * sizeof(IP_ADDRESS)) + sizeof(DWORD) );
  186. if ( ! pIpArray )
  187. {
  188. return( NULL );
  189. }
  190. //
  191. // initialize IP count
  192. //
  193. pIpArray->AddrCount = AddrCount;
  194. DNSDBG( IPARRAY, (
  195. "Dns_CreateIpArray() new array (count %d) at %p\n",
  196. AddrCount,
  197. pIpArray ));
  198. return( pIpArray );
  199. }
  200. PIP_ARRAY
  201. Dns_BuildIpArray(
  202. IN DWORD AddrCount,
  203. IN PIP_ADDRESS pipAddrs
  204. )
  205. /*++
  206. Routine Description:
  207. Create IP address array structure from existing array of IP addresses.
  208. Arguments:
  209. AddrCount -- count of addresses in array
  210. pipAddrs -- IP address array
  211. Return Value:
  212. Ptr to IP address array.
  213. NULL on failure.
  214. --*/
  215. {
  216. PIP_ARRAY pIpArray;
  217. if ( ! pipAddrs || ! AddrCount )
  218. {
  219. return( NULL );
  220. }
  221. // create IP array of desired size
  222. // then copy incoming array of addresses
  223. pIpArray = Dns_CreateIpArray( AddrCount );
  224. if ( ! pIpArray )
  225. {
  226. return( NULL );
  227. }
  228. pIpArray->AddrCount = AddrCount;
  229. memcpy(
  230. pIpArray->AddrArray,
  231. pipAddrs,
  232. AddrCount * sizeof(IP_ADDRESS) );
  233. return( pIpArray );
  234. }
  235. PIP_ARRAY
  236. Dns_CopyAndExpandIpArray(
  237. IN PIP_ARRAY pIpArray,
  238. IN DWORD ExpandCount,
  239. IN BOOL fDeleteExisting
  240. )
  241. /*++
  242. Routine Description:
  243. Create expanded copy of IP address array.
  244. Arguments:
  245. pIpArray -- IP address array to copy
  246. ExpandCount -- number of IP to expand array size by
  247. fDeleteExisting -- TRUE to delete existing array;
  248. this is useful when function is used to grow existing
  249. IP array in place; note that locking must be done
  250. by caller
  251. note, that if new array creation FAILS -- then old array
  252. is NOT deleted
  253. Return Value:
  254. Ptr to IP array copy, if successful
  255. NULL on failure.
  256. --*/
  257. {
  258. PIP_ARRAY pnewArray;
  259. DWORD newCount;
  260. //
  261. // no existing array -- just create desired size
  262. //
  263. if ( ! pIpArray )
  264. {
  265. if ( ExpandCount )
  266. {
  267. return Dns_CreateIpArray( ExpandCount );
  268. }
  269. return( NULL );
  270. }
  271. //
  272. // create IP array of desired size
  273. // then copy any existing addresses
  274. //
  275. pnewArray = Dns_CreateIpArray( pIpArray->AddrCount + ExpandCount );
  276. if ( ! pnewArray )
  277. {
  278. return( NULL );
  279. }
  280. RtlCopyMemory(
  281. (PBYTE) pnewArray->AddrArray,
  282. (PBYTE) pIpArray->AddrArray,
  283. pIpArray->AddrCount * sizeof(IP4_ADDRESS) );
  284. //
  285. // delete existing -- for "grow mode"
  286. //
  287. if ( fDeleteExisting )
  288. {
  289. FREE_HEAP( pIpArray );
  290. }
  291. return( pnewArray );
  292. }
  293. PIP_ARRAY
  294. Dns_CreateIpArrayCopy(
  295. IN PIP_ARRAY pIpArray
  296. )
  297. /*++
  298. Routine Description:
  299. Create copy of IP address array.
  300. Arguments:
  301. pIpArray -- IP address array to copy
  302. Return Value:
  303. Ptr to IP address array copy, if successful
  304. NULL on failure.
  305. --*/
  306. {
  307. #if 0
  308. PIP_ARRAY pIpArrayCopy;
  309. if ( ! pIpArray )
  310. {
  311. return( NULL );
  312. }
  313. // create IP array of desired size
  314. // then copy entire structure
  315. pIpArrayCopy = Dns_CreateIpArray( pIpArray->AddrCount );
  316. if ( ! pIpArrayCopy )
  317. {
  318. return( NULL );
  319. }
  320. memcpy(
  321. pIpArrayCopy,
  322. pIpArray,
  323. Dns_SizeofIpArray(pIpArray) );
  324. return( pIpArrayCopy );
  325. #endif
  326. //
  327. // call essentially "CopyEx" function
  328. //
  329. // note, not macroing this because this may well become
  330. // a DLL entry point
  331. //
  332. return Dns_CopyAndExpandIpArray(
  333. pIpArray,
  334. 0, // no expansion
  335. 0 // don't delete existing array
  336. );
  337. }
  338. BOOL
  339. Dns_IsAddressInIpArray(
  340. IN PIP_ARRAY pIpArray,
  341. IN IP_ADDRESS ipAddress
  342. )
  343. /*++
  344. Routine Description:
  345. Check if IP array contains desired address.
  346. Arguments:
  347. pIpArray -- IP address array to copy
  348. Return Value:
  349. TRUE if address in array.
  350. Ptr to IP address array copy, if successful
  351. NULL on failure.
  352. --*/
  353. {
  354. DWORD i;
  355. if ( ! pIpArray )
  356. {
  357. return( FALSE );
  358. }
  359. for (i=0; i<pIpArray->AddrCount; i++)
  360. {
  361. if ( ipAddress == pIpArray->AddrArray[i] )
  362. {
  363. return( TRUE );
  364. }
  365. }
  366. return( FALSE );
  367. }
  368. BOOL
  369. Dns_AddIpToIpArray(
  370. IN OUT PIP_ARRAY pIpArray,
  371. IN IP_ADDRESS NewIp
  372. )
  373. /*++
  374. Routine Description:
  375. Add IP address to IP array.
  376. Allowable "slot" in array, is any zero IP address.
  377. Arguments:
  378. pIpArray -- IP address array to add to
  379. NewIp -- IP address to add to array
  380. Return Value:
  381. TRUE if successful.
  382. FALSE if array full.
  383. --*/
  384. {
  385. DWORD i;
  386. //
  387. // screen for existence
  388. //
  389. // this check makes it easy to write code that does
  390. // Add\Full?=>Expand loop without having to write
  391. // startup existence\create code
  392. //
  393. if ( !pIpArray )
  394. {
  395. return( FALSE );
  396. }
  397. for (i=0; i<pIpArray->AddrCount; i++)
  398. {
  399. if ( pIpArray->AddrArray[i] == 0 )
  400. {
  401. pIpArray->AddrArray[i] = NewIp;
  402. return( TRUE );
  403. }
  404. else if ( pIpArray->AddrArray[i] == NewIp )
  405. {
  406. return( TRUE );
  407. }
  408. }
  409. return( FALSE );
  410. }
  411. VOID
  412. Dns_ClearIpArray(
  413. IN OUT PIP_ARRAY pIpArray
  414. )
  415. /*++
  416. Routine Description:
  417. Clear memory in IP array.
  418. Arguments:
  419. pIpArray -- IP address array to clear
  420. Return Value:
  421. None.
  422. --*/
  423. {
  424. // clear just the address list, leaving count intact
  425. RtlZeroMemory(
  426. pIpArray->AddrArray,
  427. pIpArray->AddrCount * sizeof(IP_ADDRESS) );
  428. }
  429. VOID
  430. Dns_ReverseOrderOfIpArray(
  431. IN OUT PIP_ARRAY pIpArray
  432. )
  433. /*++
  434. Routine Description:
  435. Reorder the list of IPs in reverse.
  436. Arguments:
  437. pIpArray -- IP address array to reorder
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. IP_ADDRESS tempIp;
  443. DWORD i;
  444. DWORD j;
  445. //
  446. // swap IPs working from ends to the middle
  447. //
  448. if ( pIpArray &&
  449. pIpArray->AddrCount )
  450. {
  451. for ( i = 0, j = pIpArray->AddrCount - 1;
  452. i < j;
  453. i++, j-- )
  454. {
  455. tempIp = pIpArray->AddrArray[i];
  456. pIpArray->AddrArray[i] = pIpArray->AddrArray[j];
  457. pIpArray->AddrArray[j] = tempIp;
  458. }
  459. }
  460. }
  461. BOOL
  462. Dns_CheckAndMakeIpArraySubset(
  463. IN OUT PIP_ARRAY pIpArraySub,
  464. IN PIP_ARRAY pIpArraySuper
  465. )
  466. /*++
  467. Routine Description:
  468. Clear entries from IP array until it is subset of another IP array.
  469. Arguments:
  470. pIpArraySub -- IP array to make into subset
  471. pIpArraySuper -- IP array superset
  472. Return Value:
  473. TRUE if pIpArraySub is already subset.
  474. FALSE if needed to nix entries to make IP array a subset.
  475. --*/
  476. {
  477. DWORD i;
  478. DWORD newIpCount;
  479. //
  480. // check each entry in subset IP array,
  481. // if not in superset IP array, eliminate it
  482. //
  483. newIpCount = pIpArraySub->AddrCount;
  484. for (i=0; i < newIpCount; i++)
  485. {
  486. if ( ! Dns_IsAddressInIpArray(
  487. pIpArraySuper,
  488. pIpArraySub->AddrArray[i] ) )
  489. {
  490. // remove this IP entry and replace with
  491. // last IP entry in array
  492. newIpCount--;
  493. if ( i >= newIpCount )
  494. {
  495. break;
  496. }
  497. pIpArraySub->AddrArray[i] = pIpArraySub->AddrArray[ newIpCount ];
  498. }
  499. }
  500. // if eliminated entries, reset array count
  501. if ( newIpCount < pIpArraySub->AddrCount )
  502. {
  503. pIpArraySub->AddrCount = newIpCount;
  504. return( FALSE );
  505. }
  506. return( TRUE );
  507. }
  508. INT
  509. WINAPI
  510. Dns_ClearIpFromIpArray(
  511. IN OUT PIP_ARRAY pIpArray,
  512. IN IP_ADDRESS IpDelete
  513. )
  514. /*++
  515. Routine Description:
  516. Clear IP address from IP array.
  517. Note difference between this function and Dns_DeleteIpFromIpArray()
  518. below.
  519. This function leaves list size unchanged allowing new adds.
  520. Arguments:
  521. pIpArray -- IP address array to add to
  522. IpDelete -- IP address to delete from array
  523. Return Value:
  524. Count of instances of IpDelete in array.
  525. --*/
  526. {
  527. DWORD found = 0;
  528. INT i;
  529. INT currentLast;
  530. i = currentLast = pIpArray->AddrCount-1;
  531. while ( i >= 0 )
  532. {
  533. if ( pIpArray->AddrArray[i] == IpDelete )
  534. {
  535. pIpArray->AddrArray[i] = pIpArray->AddrArray[ currentLast ];
  536. pIpArray->AddrArray[ currentLast ] = 0;
  537. currentLast--;
  538. found++;
  539. }
  540. i--;
  541. }
  542. return( found );
  543. }
  544. INT
  545. WINAPI
  546. Dns_DeleteIpFromIpArray(
  547. IN OUT PIP_ARRAY pIpArray,
  548. IN IP_ADDRESS IpDelete
  549. )
  550. /*++
  551. Routine Description:
  552. Delete IP address from IP array.
  553. Note difference between this function and Dns_ClearIpFromIpArray()
  554. above.
  555. This delete leaves a SMALLER array. The IP slot is NON_RECOVERABLE.
  556. Arguments:
  557. pIpArray -- IP address array to add to
  558. IpDelete -- IP address to delete from array
  559. Return Value:
  560. Count of instances of IpDelete in array.
  561. --*/
  562. {
  563. DWORD found;
  564. found = Dns_ClearIpFromIpArray( pIpArray, IpDelete );
  565. pIpArray->AddrCount -= found;
  566. return( found );
  567. }
  568. INT
  569. WINAPI
  570. Dns_CleanIpArray(
  571. IN OUT PIP_ARRAY pIpArray,
  572. IN DWORD Flag
  573. )
  574. /*++
  575. Routine Description:
  576. Clean IP array.
  577. Remove bogus stuff from IP Array:
  578. -- Zeros
  579. -- Loopback
  580. -- AutoNet
  581. Arguments:
  582. pIpArray -- IP address array to add to
  583. Flag -- which cleanups to make
  584. Return Value:
  585. Count of instances cleaned from array.
  586. --*/
  587. {
  588. DWORD found = 0;
  589. INT i;
  590. INT currentLast;
  591. IP_ADDRESS ip;
  592. i = currentLast = pIpArray->AddrCount-1;
  593. while ( i >= 0 )
  594. {
  595. ip = pIpArray->AddrArray[i];
  596. if (
  597. ( (Flag & DNS_IPARRAY_CLEAN_LOOPBACK) && ip == DNS_NET_ORDER_LOOPBACK )
  598. ||
  599. ( (Flag & DNS_IPARRAY_CLEAN_ZERO) && ip == 0 )
  600. ||
  601. ( (Flag & DNS_IPARRAY_CLEAN_AUTONET) && DNS_IS_AUTONET_IP(ip) ) )
  602. {
  603. // remove IP from array
  604. pIpArray->AddrArray[i] = pIpArray->AddrArray[ currentLast ];
  605. currentLast--;
  606. found++;
  607. }
  608. i--;
  609. }
  610. pIpArray->AddrCount -= found;
  611. return( found );
  612. }
  613. DNS_STATUS
  614. WINAPI
  615. Dns_DiffOfIpArrays(
  616. IN PIP_ARRAY pIpArray1,
  617. IN PIP_ARRAY pIpArray2,
  618. OUT PIP_ARRAY * ppOnlyIn1,
  619. OUT PIP_ARRAY * ppOnlyIn2,
  620. OUT PIP_ARRAY * ppIntersect
  621. )
  622. /*++
  623. Routine Description:
  624. Computes differences and intersection of two IP arrays.
  625. Out arrays are allocated with Dns_Alloc(), caller must free with Dns_Free()
  626. Arguments:
  627. pIpArray1 -- IP array
  628. pIpArray2 -- IP array
  629. ppOnlyIn1 -- addr to recv IP array of addresses only in array 1 (not in array2)
  630. ppOnlyIn2 -- addr to recv IP array of addresses only in array 2 (not in array1)
  631. ppIntersect -- addr to recv IP array of intersection addresses
  632. Return Value:
  633. ERROR_SUCCESS if successful.
  634. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP arrays.
  635. --*/
  636. {
  637. DWORD j;
  638. DWORD ip;
  639. PIP_ARRAY intersectArray = NULL;
  640. PIP_ARRAY only1Array = NULL;
  641. PIP_ARRAY only2Array = NULL;
  642. //
  643. // create result IP arrays
  644. //
  645. if ( ppIntersect )
  646. {
  647. intersectArray = Dns_CreateIpArrayCopy( pIpArray1 );
  648. if ( !intersectArray )
  649. {
  650. goto NoMem;
  651. }
  652. *ppIntersect = intersectArray;
  653. }
  654. if ( ppOnlyIn1 )
  655. {
  656. only1Array = Dns_CreateIpArrayCopy( pIpArray1 );
  657. if ( !only1Array )
  658. {
  659. goto NoMem;
  660. }
  661. *ppOnlyIn1 = only1Array;
  662. }
  663. if ( ppOnlyIn2 )
  664. {
  665. only2Array = Dns_CreateIpArrayCopy( pIpArray2 );
  666. if ( !only2Array )
  667. {
  668. goto NoMem;
  669. }
  670. *ppOnlyIn2 = only2Array;
  671. }
  672. //
  673. // clean the arrays
  674. //
  675. for ( j=0; j< pIpArray1->AddrCount; j++ )
  676. {
  677. ip = pIpArray1->AddrArray[j];
  678. // if IP in both arrays, delete from "only" arrays
  679. if ( Dns_IsAddressInIpArray( pIpArray2, ip ) )
  680. {
  681. if ( only1Array )
  682. {
  683. Dns_DeleteIpFromIpArray( only1Array, ip );
  684. }
  685. if ( only2Array )
  686. {
  687. Dns_DeleteIpFromIpArray( only2Array, ip );
  688. }
  689. }
  690. // if IP not in both arrays, delete from intersection
  691. // note intersection started as IpArray1
  692. else if ( intersectArray )
  693. {
  694. Dns_DeleteIpFromIpArray( intersectArray, ip );
  695. }
  696. }
  697. return( ERROR_SUCCESS );
  698. NoMem:
  699. if ( intersectArray )
  700. {
  701. FREE_HEAP( intersectArray );
  702. }
  703. if ( only1Array )
  704. {
  705. FREE_HEAP( only1Array );
  706. }
  707. if ( only2Array )
  708. {
  709. FREE_HEAP( only2Array );
  710. }
  711. if ( ppIntersect )
  712. {
  713. *ppIntersect = NULL;
  714. }
  715. if ( ppOnlyIn1 )
  716. {
  717. *ppOnlyIn1 = NULL;
  718. }
  719. if ( ppOnlyIn2 )
  720. {
  721. *ppOnlyIn2 = NULL;
  722. }
  723. return( DNS_ERROR_NO_MEMORY );
  724. }
  725. BOOL
  726. WINAPI
  727. Dns_IsIntersectionOfIpArrays(
  728. IN PIP_ARRAY pIpArray1,
  729. IN PIP_ARRAY pIpArray2
  730. )
  731. /*++
  732. Routine Description:
  733. Determine if there's intersection of two IP arrays.
  734. Arguments:
  735. pIpArray1 -- IP array
  736. pIpArray2 -- IP array
  737. Return Value:
  738. TRUE if intersection.
  739. FALSE if no intersection or empty or NULL array.
  740. --*/
  741. {
  742. DWORD count;
  743. DWORD j;
  744. //
  745. // protect against NULL
  746. // this is called from the server on potentially changing (reconfigurable)
  747. // IP array pointers; this provides cheaper protection than
  748. // worrying about locking
  749. //
  750. if ( !pIpArray1 || !pIpArray2 )
  751. {
  752. return( FALSE );
  753. }
  754. //
  755. // same array
  756. //
  757. if ( pIpArray1 == pIpArray2 )
  758. {
  759. return( TRUE );
  760. }
  761. //
  762. // test that at least one IP in array 1 is in array 2
  763. //
  764. count = pIpArray1->AddrCount;
  765. for ( j=0; j < count; j++ )
  766. {
  767. if ( Dns_IsAddressInIpArray( pIpArray2, pIpArray1->AddrArray[j] ) )
  768. {
  769. return( TRUE );
  770. }
  771. }
  772. // no intersection
  773. return( FALSE );
  774. }
  775. BOOL
  776. Dns_AreIpArraysEqual(
  777. IN PIP_ARRAY pIpArray1,
  778. IN PIP_ARRAY pIpArray2
  779. )
  780. /*++
  781. Routine Description:
  782. Determines if IP arrays are equal.
  783. Arguments:
  784. pIpArray1 -- IP array
  785. pIpArray2 -- IP array
  786. Return Value:
  787. TRUE if arrays equal.
  788. FALSE otherwise.
  789. --*/
  790. {
  791. DWORD j;
  792. DWORD count;
  793. //
  794. // same array? or missing array?
  795. //
  796. if ( pIpArray1 == pIpArray2 )
  797. {
  798. return( TRUE );
  799. }
  800. if ( !pIpArray1 || !pIpArray2 )
  801. {
  802. return( FALSE );
  803. }
  804. //
  805. // arrays the same length?
  806. //
  807. count = pIpArray1->AddrCount;
  808. if ( count != pIpArray2->AddrCount )
  809. {
  810. return( FALSE );
  811. }
  812. //
  813. // test that each IP in array 1 is in array 2
  814. //
  815. // test that each IP in array 2 is in array 1
  816. // - do second test in case of duplicates
  817. // that fool equal-lengths check
  818. //
  819. for ( j=0; j < count; j++ )
  820. {
  821. if ( !Dns_IsAddressInIpArray( pIpArray2, pIpArray1->AddrArray[j] ) )
  822. {
  823. return( FALSE );
  824. }
  825. }
  826. for ( j=0; j < count; j++ )
  827. {
  828. if ( !Dns_IsAddressInIpArray( pIpArray1, pIpArray2->AddrArray[j] ) )
  829. {
  830. return( FALSE );
  831. }
  832. }
  833. // equal arrays
  834. return( TRUE );
  835. }
  836. DNS_STATUS
  837. WINAPI
  838. Dns_UnionOfIpArrays(
  839. IN PIP_ARRAY pIpArray1,
  840. IN PIP_ARRAY pIpArray2,
  841. OUT PIP_ARRAY * ppUnion
  842. )
  843. /*++
  844. Routine Description:
  845. Computes the union of two IP arrays.
  846. Out array is allocated with Dns_Alloc(), caller must free with Dns_Free()
  847. Arguments:
  848. pIpArray1 -- IP array
  849. pIpArray2 -- IP array
  850. ppUnion -- addr to recv IP array of addresses in array 1 and in array2
  851. Return Value:
  852. ERROR_SUCCESS if successful.
  853. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP array.
  854. --*/
  855. {
  856. DWORD j;
  857. DWORD ip;
  858. DWORD Count = 0;
  859. PIP_ARRAY punionArray = NULL;
  860. //
  861. // create result IP arrays
  862. //
  863. if ( !ppUnion )
  864. {
  865. return( ERROR_INVALID_PARAMETER );
  866. }
  867. punionArray = Dns_CreateIpArray( pIpArray1->AddrCount +
  868. pIpArray2->AddrCount );
  869. if ( !punionArray )
  870. {
  871. goto NoMem;
  872. }
  873. *ppUnion = punionArray;
  874. //
  875. // create union from arrays
  876. //
  877. for ( j = 0; j < pIpArray1->AddrCount; j++ )
  878. {
  879. ip = pIpArray1->AddrArray[j];
  880. if ( !Dns_IsAddressInIpArray( punionArray, ip ) )
  881. {
  882. Dns_AddIpToIpArray( punionArray, ip );
  883. Count++;
  884. }
  885. }
  886. for ( j = 0; j < pIpArray2->AddrCount; j++ )
  887. {
  888. ip = pIpArray2->AddrArray[j];
  889. if ( !Dns_IsAddressInIpArray( punionArray, ip ) )
  890. {
  891. Dns_AddIpToIpArray( punionArray, ip );
  892. Count++;
  893. }
  894. }
  895. punionArray->AddrCount = Count;
  896. return( ERROR_SUCCESS );
  897. NoMem:
  898. if ( punionArray )
  899. {
  900. FREE_HEAP( punionArray );
  901. *ppUnion = NULL;
  902. }
  903. return( DNS_ERROR_NO_MEMORY );
  904. }
  905. DNS_STATUS
  906. Dns_CreateIpArrayFromMultiIpString(
  907. IN LPSTR pszMultiIpString,
  908. OUT PIP_ARRAY * ppIpArray
  909. )
  910. /*++
  911. Routine Description:
  912. Create IP array out of multi-IP string.
  913. Arguments:
  914. pszMultiIpString -- string containing IP addresses;
  915. separator is whitespace or comma
  916. ppIpArray -- addr to receive ptr to allocated IP array
  917. Return Value:
  918. ERROR_SUCCESS if one or more valid IP addresses in string.
  919. DNS_ERROR_INVALID_IP_ADDRESS if parsing error.
  920. DNS_ERROR_NO_MEMORY if can not create IP array.
  921. --*/
  922. {
  923. PCHAR pch;
  924. CHAR ch;
  925. PCHAR pbuf;
  926. PCHAR pbufStop;
  927. DNS_STATUS status = ERROR_SUCCESS;
  928. DWORD countIp = 0;
  929. IP_ADDRESS ip;
  930. CHAR buffer[ IP_ADDRESS_STRING_LENGTH+2 ];
  931. IP_ADDRESS arrayIp[ MAX_PARSE_IP ];
  932. // stop byte for IP string buffer
  933. // - note we put extra byte pad in buffer above
  934. // this allows us to write ON stop byte and use
  935. // that to detect invalid-long IP string
  936. //
  937. pbufStop = buffer + IP_ADDRESS_STRING_LENGTH;
  938. //
  939. // DCR: use IP array builder for local IP address
  940. // then need Dns_CreateIpArrayFromMultiIpString()
  941. // to use count\alloc method when buffer overflows
  942. // to do this we'd need to do parsing in loop
  943. // and skip conversion when count overflow, but set
  944. // flag to go back in again with allocated buffer
  945. //
  946. // safer would be to tokenize-count, alloc, build from tokens
  947. //
  948. //
  949. // loop until reach end of string
  950. //
  951. pch = pszMultiIpString;
  952. while ( countIp < MAX_PARSE_IP )
  953. {
  954. // skip whitespace
  955. while ( ch = *pch++ )
  956. {
  957. if ( ch == ' ' || ch == '\t' || ch == ',' )
  958. {
  959. continue;
  960. }
  961. break;
  962. }
  963. if ( !ch )
  964. {
  965. break;
  966. }
  967. //
  968. // copy next IP string into buffer
  969. // - stop copy at whitespace or NULL
  970. // - on invalid-long IP string, stop copying
  971. // but continue parsing, so can still get any following IPs
  972. // note, we actually write ON the buffer stop byte as our
  973. // "invalid-long" detection mechanism
  974. //
  975. pbuf = buffer;
  976. do
  977. {
  978. if ( pbuf <= pbufStop )
  979. {
  980. *pbuf++ = ch;
  981. }
  982. ch = *pch++;
  983. }
  984. while ( ch && ch != ' ' && ch != ',' && ch != '\t' );
  985. //
  986. // convert buffer into IP address
  987. // - insure was valid length string
  988. // - null terminate
  989. //
  990. if ( pbuf <= pbufStop )
  991. {
  992. *pbuf = 0;
  993. ip = inet_addr( buffer );
  994. if ( ip == INADDR_BROADCAST )
  995. {
  996. status = DNS_ERROR_INVALID_IP_ADDRESS;
  997. }
  998. else
  999. {
  1000. arrayIp[ countIp++ ] = ip;
  1001. }
  1002. }
  1003. else
  1004. {
  1005. status = DNS_ERROR_INVALID_IP_ADDRESS;
  1006. }
  1007. // quit if at end of string
  1008. if ( !ch )
  1009. {
  1010. break;
  1011. }
  1012. }
  1013. //
  1014. // if successfully parsed IP addresses, create IP array
  1015. // note, we'll return what we have even if some addresses are
  1016. // bogus, status code will indicate the parsing problem
  1017. //
  1018. // note, if explicitly passed empty string, then create
  1019. // empty IP array, don't error
  1020. //
  1021. if ( countIp == 0 && *pszMultiIpString != 0 )
  1022. {
  1023. *ppIpArray = NULL;
  1024. status = DNS_ERROR_INVALID_IP_ADDRESS;
  1025. }
  1026. else
  1027. {
  1028. *ppIpArray = Dns_BuildIpArray(
  1029. countIp,
  1030. arrayIp );
  1031. if ( !*ppIpArray )
  1032. {
  1033. status = DNS_ERROR_NO_MEMORY;
  1034. }
  1035. IF_DNSDBG( IPARRAY )
  1036. {
  1037. DnsDbg_IpArray(
  1038. "New Parsed IP array",
  1039. NULL, // no name
  1040. *ppIpArray );
  1041. }
  1042. }
  1043. return( status );
  1044. }
  1045. LPSTR
  1046. Dns_CreateMultiIpStringFromIpArray(
  1047. IN PIP_ARRAY pIpArray,
  1048. IN CHAR chSeparator OPTIONAL
  1049. )
  1050. /*++
  1051. Routine Description:
  1052. Create IP array out of multi-IP string.
  1053. Arguments:
  1054. pIpArray -- IP array to generate string for
  1055. chSeparator -- separating character between strings;
  1056. OPTIONAL, if not given, blank is used
  1057. Return Value:
  1058. Ptr to string representation of IP array.
  1059. Caller must free.
  1060. --*/
  1061. {
  1062. PCHAR pch;
  1063. DWORD i;
  1064. PCHAR pszip;
  1065. DWORD length;
  1066. PCHAR pchstop;
  1067. CHAR buffer[ IP_ADDRESS_STRING_LENGTH*MAX_PARSE_IP + 1 ];
  1068. //
  1069. // if no IP array, return NULL string
  1070. // this allows this function to simply indicate when registry
  1071. // delete rather than write is indicated
  1072. //
  1073. if ( !pIpArray )
  1074. {
  1075. return( NULL );
  1076. }
  1077. // if no separator, use blank
  1078. if ( !chSeparator )
  1079. {
  1080. chSeparator = ' ';
  1081. }
  1082. //
  1083. // loop through all IPs in array, appending each
  1084. //
  1085. pch = buffer;
  1086. pchstop = pch + ( IP_ADDRESS_STRING_LENGTH * (MAX_PARSE_IP-1) );
  1087. *pch = 0;
  1088. for ( i=0; i < pIpArray->AddrCount; i++ )
  1089. {
  1090. if ( pch >= pchstop )
  1091. {
  1092. break;
  1093. }
  1094. pszip = IP_STRING( pIpArray->AddrArray[i] );
  1095. if ( pszip )
  1096. {
  1097. length = strlen( pszip );
  1098. memcpy(
  1099. pch,
  1100. pszip,
  1101. length );
  1102. pch += length;
  1103. *pch++ = chSeparator;
  1104. }
  1105. }
  1106. // if wrote any strings, then write terminator over last separator
  1107. if ( pch != buffer )
  1108. {
  1109. *--pch = 0;
  1110. }
  1111. // create copy of buffer as return
  1112. length = (DWORD)(pch - buffer) + 1;
  1113. pch = ALLOCATE_HEAP( length );
  1114. if ( !pch )
  1115. {
  1116. return( NULL );
  1117. }
  1118. memcpy(
  1119. pch,
  1120. buffer,
  1121. length );
  1122. DNSDBG( IPARRAY, (
  1123. "String representation %s of IP array at %p\n",
  1124. pch,
  1125. pIpArray ));
  1126. return( pch );
  1127. }
  1128. //
  1129. // End iparray.c
  1130. //