|
|
/*++
Copyright (c) 1995-2000 Microsoft Corporation
Module Name:
iparray.c
Abstract:
Domain Name System (DNS) Library
IP Address array routines.
Author:
Jim Gilroy (jamesg) October 1995
Revision History:
--*/
#include "local.h"
//
// Max IP count when doing IP array to\from string conversions
//
#define MAX_PARSE_IP (1000)
//
// Routines to handle actual array of IP addresses.
//
PIP4_ADDRESS Dns_CreateIpAddressArrayCopy( IN PIP4_ADDRESS aipAddress, IN DWORD cipAddress ) /*++
Routine Description:
Create copy of IP address array.
Arguments:
aipAddress -- array of IP addresses cipAddress -- count of IP addresses
Return Value:
Ptr to IP address array copy, if successful NULL on failure.
--*/ { PIP4_ADDRESS pipArray;
// validate
if ( ! aipAddress || cipAddress == 0 ) { return( NULL ); }
// allocate memory and copy
pipArray = (PIP4_ADDRESS) ALLOCATE_HEAP( cipAddress*sizeof(IP4_ADDRESS) ); if ( ! pipArray ) { return( NULL ); }
memcpy( pipArray, aipAddress, cipAddress*sizeof(IP4_ADDRESS) );
return( pipArray ); }
BOOL Dns_ValidateIpAddressArray( IN PIP4_ADDRESS aipAddress, IN DWORD cipAddress, IN DWORD dwFlag ) /*++
Routine Description:
Validate IP address array.
Current checks: - existence - non-broadcast - non-lookback
Arguments:
aipAddress -- array of IP addresses
cipAddress -- count of IP addresses
dwFlag -- validity tests to do; currently unused
Return Value:
TRUE if valid IP addresses. FALSE if invalid address found.
--*/ { DWORD i;
//
// protect against bad parameters
//
if ( cipAddress && ! aipAddress ) { return( FALSE ); }
//
// check each IP address
//
for ( i=0; i < cipAddress; i++) { if( aipAddress[i] == INADDR_ANY || aipAddress[i] == INADDR_BROADCAST || aipAddress[i] == INADDR_LOOPBACK ) { return( FALSE ); } } return( TRUE ); }
//
// IP4_ARRAYroutines
//
DWORD Dns_SizeofIpArray( IN PIP4_ARRAY pIpArray ) /*++
Routine Description:
Get size in bytes of IP address array.
Arguments:
pIpArray -- IP address array to find size of
Return Value:
Size in bytes of IP array.
--*/ { if ( ! pIpArray ) { return 0; } return (pIpArray->AddrCount * sizeof(IP4_ADDRESS)) + sizeof(DWORD); }
BOOL Dns_ProbeIpArray( IN PIP4_ARRAY pIpArray ) /*++
Routine Description:
Touch all entries in IP array to insure valid memory.
Arguments:
pIpArray -- ptr to IP address array
Return Value:
TRUE if successful. FALSE otherwise
--*/ { DWORD i; BOOL result;
if ( ! pIpArray ) { return( TRUE ); } for ( i=0; i<pIpArray->AddrCount; i++ ) { result = ( pIpArray->AddrArray[i] == 0 ); } return( TRUE ); }
#if 0
BOOL Dns_ValidateSizeOfIpArray( IN PIP4_ARRAY pIpArray, IN DWORD dwMemoryLength ) /*++
Routine Description:
Check that size of IP array, corresponds to length of memory.
Arguments:
pIpArray -- ptr to IP address array
dwMemoryLength -- length of IP array memory
Return Value:
TRUE if IP array size matches memory length FALSE otherwise
--*/ { return( Dns_SizeOfIpArray(pIpArray) == dwMemoryLength ); } #endif
PIP4_ARRAY Dns_CreateIpArray( IN DWORD AddrCount ) /*++
Routine Description:
Create uninitialized IP address array.
Arguments:
AddrCount -- count of addresses array will hold
Return Value:
Ptr to uninitialized IP address array, if successful NULL on failure.
--*/ { PIP4_ARRAY pIpArray;
DNSDBG( IPARRAY, ( "Dns_CreateIpArray() of count %d\n", AddrCount ));
pIpArray = (PIP4_ARRAY) ALLOCATE_HEAP_ZERO( (AddrCount * sizeof(IP4_ADDRESS)) + sizeof(DWORD) ); if ( ! pIpArray ) { return( NULL ); }
//
// initialize IP count
//
pIpArray->AddrCount = AddrCount;
DNSDBG( IPARRAY, ( "Dns_CreateIpArray() new array (count %d) at %p\n", AddrCount, pIpArray ));
return( pIpArray ); }
PIP4_ARRAY Dns_BuildIpArray( IN DWORD AddrCount, IN PIP4_ADDRESS pipAddrs ) /*++
Routine Description:
Create IP address array structure from existing array of IP addresses.
Arguments:
AddrCount -- count of addresses in array pipAddrs -- IP address array
Return Value:
Ptr to IP address array. NULL on failure.
--*/ { PIP4_ARRAY pIpArray;
if ( ! pipAddrs || ! AddrCount ) { return( NULL ); }
// create IP array of desired size
// then copy incoming array of addresses
pIpArray = Dns_CreateIpArray( AddrCount ); if ( ! pIpArray ) { return( NULL ); } pIpArray->AddrCount = AddrCount;
memcpy( pIpArray->AddrArray, pipAddrs, AddrCount * sizeof(IP4_ADDRESS) );
return( pIpArray ); }
PIP4_ARRAY Dns_CopyAndExpandIpArray( IN PIP4_ARRAY pIpArray, IN DWORD ExpandCount, IN BOOL fDeleteExisting ) /*++
Routine Description:
Create expanded copy of IP address array.
Arguments:
pIpArray -- IP address array to copy
ExpandCount -- number of IP to expand array size by
fDeleteExisting -- TRUE to delete existing array; this is useful when function is used to grow existing IP array in place; note that locking must be done by caller
note, that if new array creation FAILS -- then old array is NOT deleted
Return Value:
Ptr to IP array copy, if successful NULL on failure.
--*/ { PIP4_ARRAY pnewArray; DWORD newCount;
//
// no existing array -- just create desired size
//
if ( ! pIpArray ) { if ( ExpandCount ) { return Dns_CreateIpArray( ExpandCount ); } return( NULL ); }
//
// create IP array of desired size
// then copy any existing addresses
//
pnewArray = Dns_CreateIpArray( pIpArray->AddrCount + ExpandCount ); if ( ! pnewArray ) { return( NULL ); }
RtlCopyMemory( (PBYTE) pnewArray->AddrArray, (PBYTE) pIpArray->AddrArray, pIpArray->AddrCount * sizeof(IP4_ADDRESS) );
//
// delete existing -- for "grow mode"
//
if ( fDeleteExisting ) { FREE_HEAP( pIpArray ); }
return( pnewArray ); }
PIP4_ARRAY Dns_CreateIpArrayCopy( IN PIP4_ARRAY pIpArray ) /*++
Routine Description:
Create copy of IP address array.
Arguments:
pIpArray -- IP address array to copy
Return Value:
Ptr to IP address array copy, if successful NULL on failure.
--*/ { #if 0
PIP4_ARRAY pIpArrayCopy;
if ( ! pIpArray ) { return( NULL ); }
// create IP array of desired size
// then copy entire structure
pIpArrayCopy = Dns_CreateIpArray( pIpArray->AddrCount ); if ( ! pIpArrayCopy ) { return( NULL ); }
memcpy( pIpArrayCopy, pIpArray, Dns_SizeofIpArray(pIpArray) );
return( pIpArrayCopy ); #endif
//
// call essentially "CopyEx" function
//
// note, not macroing this because this may well become
// a DLL entry point
//
return Dns_CopyAndExpandIpArray( pIpArray, 0, // no expansion
0 // don't delete existing array
); }
BOOL Dns_IsAddressInIpArray( IN PIP4_ARRAY pIpArray, IN IP4_ADDRESS ipAddress ) /*++
Routine Description:
Check if IP array contains desired address.
Arguments:
pIpArray -- IP address array to copy
Return Value:
TRUE if address in array. Ptr to IP address array copy, if successful NULL on failure.
--*/ { DWORD i;
if ( ! pIpArray ) { return( FALSE ); } for (i=0; i<pIpArray->AddrCount; i++) { if ( ipAddress == pIpArray->AddrArray[i] ) { return( TRUE ); } } return( FALSE ); }
BOOL Dns_AddIpToIpArray( IN OUT PIP4_ARRAY pIpArray, IN IP4_ADDRESS NewIp ) /*++
Routine Description:
Add IP address to IP array.
Allowable "slot" in array, is any zero IP address.
Arguments:
pIpArray -- IP address array to add to
NewIp -- IP address to add to array
Return Value:
TRUE if successful. FALSE if array full.
--*/ { DWORD i;
//
// screen for existence
//
// this check makes it easy to write code that does
// Add\Full?=>Expand loop without having to write
// startup existence\create code
//
if ( !pIpArray ) { return( FALSE ); }
for (i=0; i<pIpArray->AddrCount; i++) { if ( pIpArray->AddrArray[i] == 0 ) { pIpArray->AddrArray[i] = NewIp; return( TRUE ); } else if ( pIpArray->AddrArray[i] == NewIp ) { return( TRUE ); } } return( FALSE ); }
VOID Dns_ClearIpArray( IN OUT PIP4_ARRAY pIpArray ) /*++
Routine Description:
Clear memory in IP array.
Arguments:
pIpArray -- IP address array to clear
Return Value:
None.
--*/ { // clear just the address list, leaving count intact
RtlZeroMemory( pIpArray->AddrArray, pIpArray->AddrCount * sizeof(IP4_ADDRESS) ); }
VOID Dns_ReverseOrderOfIpArray( IN OUT PIP4_ARRAY pIpArray ) /*++
Routine Description:
Reorder the list of IPs in reverse.
Arguments:
pIpArray -- IP address array to reorder
Return Value:
None.
--*/ { IP4_ADDRESS tempIp; DWORD i; DWORD j;
//
// swap IPs working from ends to the middle
//
if ( pIpArray && pIpArray->AddrCount ) { for ( i = 0, j = pIpArray->AddrCount - 1; i < j; i++, j-- ) { tempIp = pIpArray->AddrArray[i]; pIpArray->AddrArray[i] = pIpArray->AddrArray[j]; pIpArray->AddrArray[j] = tempIp; } } }
BOOL Dns_CheckAndMakeIpArraySubset( IN OUT PIP4_ARRAY pIpArraySub, IN PIP4_ARRAY pIpArraySuper ) /*++
Routine Description:
Clear entries from IP array until it is subset of another IP array.
Arguments:
pIpArraySub -- IP array to make into subset
pIpArraySuper -- IP array superset
Return Value:
TRUE if pIpArraySub is already subset. FALSE if needed to nix entries to make IP array a subset.
--*/ { DWORD i; DWORD newIpCount;
//
// check each entry in subset IP array,
// if not in superset IP array, eliminate it
//
newIpCount = pIpArraySub->AddrCount;
for (i=0; i < newIpCount; i++) { if ( ! Dns_IsAddressInIpArray( pIpArraySuper, pIpArraySub->AddrArray[i] ) ) { // remove this IP entry and replace with
// last IP entry in array
newIpCount--; if ( i >= newIpCount ) { break; } pIpArraySub->AddrArray[i] = pIpArraySub->AddrArray[ newIpCount ]; } }
// if eliminated entries, reset array count
if ( newIpCount < pIpArraySub->AddrCount ) { pIpArraySub->AddrCount = newIpCount; return( FALSE ); } return( TRUE ); }
INT WINAPI Dns_ClearIpFromIpArray( IN OUT PIP4_ARRAY pIpArray, IN IP4_ADDRESS IpDelete ) /*++
Routine Description:
Clear IP address from IP array.
Note difference between this function and Dns_DeleteIpFromIpArray() below.
This function leaves list size unchanged allowing new adds.
Arguments:
pIpArray -- IP address array to add to
IpDelete -- IP address to delete from array
Return Value:
Count of instances of IpDelete in array.
--*/ { DWORD found = 0; INT i; INT currentLast;
i = currentLast = pIpArray->AddrCount-1;
while ( i >= 0 ) { if ( pIpArray->AddrArray[i] == IpDelete ) { pIpArray->AddrArray[i] = pIpArray->AddrArray[ currentLast ]; pIpArray->AddrArray[ currentLast ] = 0; currentLast--; found++; } i--; }
return( found ); }
INT WINAPI Dns_DeleteIpFromIpArray( IN OUT PIP4_ARRAY pIpArray, IN IP4_ADDRESS IpDelete ) /*++
Routine Description:
Delete IP address from IP array.
Note difference between this function and Dns_ClearIpFromIpArray() above.
This delete leaves a SMALLER array. The IP slot is NON_RECOVERABLE.
Arguments:
pIpArray -- IP address array to add to
IpDelete -- IP address to delete from array
Return Value:
Count of instances of IpDelete in array.
--*/ { DWORD found;
found = Dns_ClearIpFromIpArray( pIpArray, IpDelete );
pIpArray->AddrCount -= found;
return( found ); }
INT WINAPI Dns_CleanIpArray( IN OUT PIP4_ARRAY pIpArray, IN DWORD Flag ) /*++
Routine Description:
Clean IP array.
Remove bogus stuff from IP Array: -- Zeros -- Loopback -- AutoNet
Arguments:
pIpArray -- IP address array to add to
Flag -- which cleanups to make
Return Value:
Count of instances cleaned from array.
--*/ { DWORD found = 0; INT i; INT currentLast; IP4_ADDRESS ip;
i = currentLast = pIpArray->AddrCount-1;
while ( i >= 0 ) { ip = pIpArray->AddrArray[i];
if ( ( (Flag & DNS_IPARRAY_CLEAN_LOOPBACK) && ip == DNS_NET_ORDER_LOOPBACK ) || ( (Flag & DNS_IPARRAY_CLEAN_ZERO) && ip == 0 ) || ( (Flag & DNS_IPARRAY_CLEAN_AUTONET) && DNS_IS_AUTONET_IP(ip) ) ) { // remove IP from array
pIpArray->AddrArray[i] = pIpArray->AddrArray[ currentLast ]; currentLast--; found++; } i--; }
pIpArray->AddrCount -= found; return( found ); }
DNS_STATUS WINAPI Dns_DiffOfIpArrays( IN PIP4_ARRAY pIpArray1, IN PIP4_ARRAY pIpArray2, OUT PIP4_ARRAY* ppOnlyIn1, OUT PIP4_ARRAY* ppOnlyIn2, OUT PIP4_ARRAY* ppIntersect ) /*++
Routine Description:
Computes differences and intersection of two IP arrays.
Out arrays are allocated with Dns_Alloc(), caller must free with Dns_Free()
Arguments:
pIpArray1 -- IP array
pIpArray2 -- IP array
ppOnlyIn1 -- addr to recv IP array of addresses only in array 1 (not in array2)
ppOnlyIn2 -- addr to recv IP array of addresses only in array 2 (not in array1)
ppIntersect -- addr to recv IP array of intersection addresses
Return Value:
ERROR_SUCCESS if successful. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP arrays.
--*/ { DWORD j; DWORD ip; PIP4_ARRAY intersectArray = NULL; PIP4_ARRAY only1Array = NULL; PIP4_ARRAY only2Array = NULL;
//
// create result IP arrays
//
if ( ppIntersect ) { intersectArray = Dns_CreateIpArrayCopy( pIpArray1 ); if ( !intersectArray ) { goto NoMem; } *ppIntersect = intersectArray; } if ( ppOnlyIn1 ) { only1Array = Dns_CreateIpArrayCopy( pIpArray1 ); if ( !only1Array ) { goto NoMem; } *ppOnlyIn1 = only1Array; } if ( ppOnlyIn2 ) { only2Array = Dns_CreateIpArrayCopy( pIpArray2 ); if ( !only2Array ) { goto NoMem; } *ppOnlyIn2 = only2Array; }
//
// clean the arrays
//
for ( j=0; j< pIpArray1->AddrCount; j++ ) { ip = pIpArray1->AddrArray[j];
// if IP in both arrays, delete from "only" arrays
if ( Dns_IsAddressInIpArray( pIpArray2, ip ) ) { if ( only1Array ) { Dns_DeleteIpFromIpArray( only1Array, ip ); } if ( only2Array ) { Dns_DeleteIpFromIpArray( only2Array, ip ); } }
// if IP not in both arrays, delete from intersection
// note intersection started as IpArray1
else if ( intersectArray ) { Dns_DeleteIpFromIpArray( intersectArray, ip ); } }
return( ERROR_SUCCESS );
NoMem:
if ( intersectArray ) { FREE_HEAP( intersectArray ); } if ( only1Array ) { FREE_HEAP( only1Array ); } if ( only2Array ) { FREE_HEAP( only2Array ); } if ( ppIntersect ) { *ppIntersect = NULL; } if ( ppOnlyIn1 ) { *ppOnlyIn1 = NULL; } if ( ppOnlyIn2 ) { *ppOnlyIn2 = NULL; } return( DNS_ERROR_NO_MEMORY ); }
BOOL WINAPI Dns_IsIntersectionOfIpArrays( IN PIP4_ARRAY pIpArray1, IN PIP4_ARRAY pIpArray2 ) /*++
Routine Description:
Determine if there's intersection of two IP arrays.
Arguments:
pIpArray1 -- IP array
pIpArray2 -- IP array
Return Value:
TRUE if intersection. FALSE if no intersection or empty or NULL array.
--*/ { DWORD count; DWORD j;
//
// protect against NULL
// this is called from the server on potentially changing (reconfigurable)
// IP array pointers; this provides cheaper protection than
// worrying about locking
//
if ( !pIpArray1 || !pIpArray2 ) { return( FALSE ); }
//
// same array
//
if ( pIpArray1 == pIpArray2 ) { return( TRUE ); }
//
// test that at least one IP in array 1 is in array 2
//
count = pIpArray1->AddrCount;
for ( j=0; j < count; j++ ) { if ( Dns_IsAddressInIpArray( pIpArray2, pIpArray1->AddrArray[j] ) ) { return( TRUE ); } }
// no intersection
return( FALSE ); }
BOOL Dns_AreIpArraysEqual( IN PIP4_ARRAY pIpArray1, IN PIP4_ARRAY pIpArray2 ) /*++
Routine Description:
Determines if IP arrays are equal.
Arguments:
pIpArray1 -- IP array
pIpArray2 -- IP array
Return Value:
TRUE if arrays equal. FALSE otherwise.
--*/ { DWORD j; DWORD count;
//
// same array? or missing array?
//
if ( pIpArray1 == pIpArray2 ) { return( TRUE ); } if ( !pIpArray1 || !pIpArray2 ) { return( FALSE ); }
//
// arrays the same length?
//
count = pIpArray1->AddrCount;
if ( count != pIpArray2->AddrCount ) { return( FALSE ); }
//
// test that each IP in array 1 is in array 2
//
// test that each IP in array 2 is in array 1
// - do second test in case of duplicates
// that fool equal-lengths check
//
for ( j=0; j < count; j++ ) { if ( !Dns_IsAddressInIpArray( pIpArray2, pIpArray1->AddrArray[j] ) ) { return( FALSE ); } } for ( j=0; j < count; j++ ) { if ( !Dns_IsAddressInIpArray( pIpArray1, pIpArray2->AddrArray[j] ) ) { return( FALSE ); } }
// equal arrays
return( TRUE ); }
DNS_STATUS WINAPI Dns_UnionOfIpArrays( IN PIP4_ARRAY pIpArray1, IN PIP4_ARRAY pIpArray2, OUT PIP4_ARRAY* ppUnion ) /*++
Routine Description:
Computes the union of two IP arrays.
Out array is allocated with Dns_Alloc(), caller must free with Dns_Free()
Arguments:
pIpArray1 -- IP array
pIpArray2 -- IP array
ppUnion -- addr to recv IP array of addresses in array 1 and in array2
Return Value:
ERROR_SUCCESS if successful. DNS_ERROR_NO_MEMORY if unable to allocate memory for IP array.
--*/ { DWORD j; DWORD ip; DWORD Count = 0; PIP4_ARRAY punionArray = NULL;
//
// create result IP arrays
//
if ( !ppUnion ) { return( ERROR_INVALID_PARAMETER ); }
punionArray = Dns_CreateIpArray( pIpArray1->AddrCount + pIpArray2->AddrCount ); if ( !punionArray ) { goto NoMem; } *ppUnion = punionArray;
//
// create union from arrays
//
for ( j = 0; j < pIpArray1->AddrCount; j++ ) { ip = pIpArray1->AddrArray[j];
if ( !Dns_IsAddressInIpArray( punionArray, ip ) ) { Dns_AddIpToIpArray( punionArray, ip ); Count++; } }
for ( j = 0; j < pIpArray2->AddrCount; j++ ) { ip = pIpArray2->AddrArray[j];
if ( !Dns_IsAddressInIpArray( punionArray, ip ) ) { Dns_AddIpToIpArray( punionArray, ip ); Count++; } }
punionArray->AddrCount = Count;
return( ERROR_SUCCESS );
NoMem:
if ( punionArray ) { FREE_HEAP( punionArray ); *ppUnion = NULL; } return( DNS_ERROR_NO_MEMORY ); }
DNS_STATUS Dns_CreateIpArrayFromMultiIpString( IN LPSTR pszMultiIpString, OUT PIP4_ARRAY* ppIpArray ) /*++
Routine Description:
Create IP array out of multi-IP string.
Arguments:
pszMultiIpString -- string containing IP addresses; separator is whitespace or comma
ppIpArray -- addr to receive ptr to allocated IP array
Return Value:
ERROR_SUCCESS if one or more valid IP addresses in string. DNS_ERROR_INVALID_IP_ADDRESS if parsing error. DNS_ERROR_NO_MEMORY if can not create IP array.
--*/ { PCHAR pch; CHAR ch; PCHAR pbuf; PCHAR pbufStop; DNS_STATUS status = ERROR_SUCCESS; DWORD countIp = 0; IP4_ADDRESS ip; CHAR buffer[ IP4_ADDRESS_STRING_LENGTH+2 ]; IP4_ADDRESS arrayIp[ MAX_PARSE_IP ];
// stop byte for IP string buffer
// - note we put extra byte pad in buffer above
// this allows us to write ON stop byte and use
// that to detect invalid-long IP string
//
pbufStop = buffer + IP4_ADDRESS_STRING_LENGTH;
//
// DCR: use IP array builder for local IP address
// then need Dns_CreateIpArrayFromMultiIpString()
// to use count\alloc method when buffer overflows
// to do this we'd need to do parsing in loop
// and skip conversion when count overflow, but set
// flag to go back in again with allocated buffer
//
// safer would be to tokenize-count, alloc, build from tokens
//
//
// loop until reach end of string
//
pch = pszMultiIpString;
while ( countIp < MAX_PARSE_IP ) { // skip whitespace
while ( ch = *pch++ ) { if ( ch == ' ' || ch == '\t' || ch == ',' ) { continue; } break; } if ( !ch ) { break; }
//
// copy next IP string into buffer
// - stop copy at whitespace or NULL
// - on invalid-long IP string, stop copying
// but continue parsing, so can still get any following IPs
// note, we actually write ON the buffer stop byte as our
// "invalid-long" detection mechanism
//
pbuf = buffer; do { if ( pbuf <= pbufStop ) { *pbuf++ = ch; } ch = *pch++; } while ( ch && ch != ' ' && ch != ',' && ch != '\t' );
//
// convert buffer into IP address
// - insure was valid length string
// - null terminate
//
if ( pbuf <= pbufStop ) { *pbuf = 0;
ip = inet_addr( buffer ); if ( ip == INADDR_BROADCAST ) { status = DNS_ERROR_INVALID_IP_ADDRESS; } else { arrayIp[ countIp++ ] = ip; } } else { status = DNS_ERROR_INVALID_IP_ADDRESS; }
// quit if at end of string
if ( !ch ) { break; } }
//
// if successfully parsed IP addresses, create IP array
// note, we'll return what we have even if some addresses are
// bogus, status code will indicate the parsing problem
//
// note, if explicitly passed empty string, then create
// empty IP array, don't error
//
if ( countIp == 0 && *pszMultiIpString != 0 ) { *ppIpArray = NULL; status = DNS_ERROR_INVALID_IP_ADDRESS; } else { *ppIpArray = Dns_BuildIpArray( countIp, arrayIp ); if ( !*ppIpArray ) { status = DNS_ERROR_NO_MEMORY; } IF_DNSDBG( IPARRAY ) { DnsDbg_Ip4Array( "New Parsed IP array", NULL, // no name
*ppIpArray ); } }
return( status ); }
LPSTR Dns_CreateMultiIpStringFromIpArray( IN PIP4_ARRAY pIpArray, IN CHAR chSeparator OPTIONAL ) /*++
Routine Description:
Create IP array out of multi-IP string.
Arguments:
pIpArray -- IP array to generate string for
chSeparator -- separating character between strings; OPTIONAL, if not given, blank is used
Return Value:
Ptr to string representation of IP array. Caller must free.
--*/ { PCHAR pch; DWORD i; PCHAR pszip; DWORD length; PCHAR pchstop; CHAR buffer[ IP4_ADDRESS_STRING_LENGTH*MAX_PARSE_IP + 1 ];
//
// if no IP array, return NULL string
// this allows this function to simply indicate when registry
// delete rather than write is indicated
//
if ( !pIpArray ) { return( NULL ); }
// if no separator, use blank
if ( !chSeparator ) { chSeparator = ' '; }
//
// loop through all IPs in array, appending each
//
pch = buffer; pchstop = pch + ( IP4_ADDRESS_STRING_LENGTH * (MAX_PARSE_IP-1) ); *pch = 0;
for ( i=0; i < pIpArray->AddrCount; i++ ) { if ( pch >= pchstop ) { break; } pszip = IP4_STRING( pIpArray->AddrArray[i] ); if ( pszip ) { length = strlen( pszip );
memcpy( pch, pszip, length );
pch += length; *pch++ = chSeparator; } }
// if wrote any strings, then write terminator over last separator
if ( pch != buffer ) { *--pch = 0; }
// create copy of buffer as return
length = (DWORD)(pch - buffer) + 1; pch = ALLOCATE_HEAP( length ); if ( !pch ) { return( NULL ); }
memcpy( pch, buffer, length );
DNSDBG( IPARRAY, ( "String representation %s of IP array at %p\n", pch, pIpArray ));
return( pch ); }
//
// End iparray.c
//
|