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.
 
 
 
 
 
 

800 lines
21 KiB

// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
/*---------------------------------------------------------
Filename: address.cpp
Written By: B.Rajeev
----------------------------------------------------------*/
#include "precomp.h"
#include "common.h"
#include "address.h"
#include <winsock.h>
#include <iomanip.h>
// this character separates the field values in a dot-notation representation
#define FIELD_SEPARATOR '.'
#define IPX_FIELD_SEPARATOR ':'
SnmpTransportIpAddress::SnmpTransportIpAddress ( IN const UCHAR *address, IN const USHORT address_length )
{
allocated = FALSE;
is_valid = FALSE;
if ( address_length != SNMP_IP_ADDR_LEN )
return;
is_valid = TRUE;
for ( ULONG index = 0 ; index < SNMP_IP_ADDR_LEN ; index ++ )
{
field [ index ] = address [ index ] ;
}
}
// sets the fields to the contents extracted from the dotted
// decimal address string in parameter
SnmpTransportIpAddress::SnmpTransportIpAddress ( IN const char *address , IN const ULONG addressResolution )
{
allocated = FALSE;
is_valid = FALSE;
if ( addressResolution & SNMP_ADDRESS_RESOLVE_VALUE )
{
is_valid = GetIpAddress ( address ) ;
if ( is_valid == FALSE )
{
// Try GetHostByName
if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
{
hostent FAR *hostEntry = gethostbyname ( address );
if ( hostEntry )
{
is_valid = TRUE ;
field [ 0 ] = ( UCHAR ) hostEntry->h_addr [ 0 ] ;
field [ 1 ] = ( UCHAR ) hostEntry->h_addr [ 1 ] ;
field [ 2 ] = ( UCHAR ) hostEntry->h_addr [ 2 ] ;
field [ 3 ] = ( UCHAR ) hostEntry->h_addr [ 3 ] ;
}
}
}
}
else if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
{
hostent FAR *hostEntry = gethostbyname ( address );
if ( hostEntry )
{
is_valid = TRUE ;
field [ 0 ] = ( UCHAR ) hostEntry->h_addr [ 0 ] ;
field [ 1 ] = ( UCHAR ) hostEntry->h_addr [ 1 ] ;
field [ 2 ] = ( UCHAR ) hostEntry->h_addr [ 2 ] ;
field [ 3 ] = ( UCHAR ) hostEntry->h_addr [ 3 ] ;
}
}
}
BOOL SnmpTransportIpAddress::ValidateAddress ( IN const char *address , IN const ULONG addressResolution )
{
BOOL is_valid = FALSE ;
if ( addressResolution & SNMP_ADDRESS_RESOLVE_VALUE )
{
// create a stream to read the fields from
istrstream address_stream((char *)address);
// contains the maximum value for a USHORT. used
// for comparison with the field values read
const UCHAR max_uchar = -1;
// consecutive fields must be separated by a
// FIELD_SEPARATOR
char separator;
// a field is first read into this for comparison
// with max_uchar
ULONG temp_field;
// read the first three (USHORT,FIELD_SEPARATOR) pairs
// check if the stream is good before each read
for(int i=0; i < (SNMP_IP_ADDR_LEN-1); i++)
{
if ( !address_stream.good() )
break;
address_stream >> temp_field;
if ( temp_field > max_uchar )
{
address_stream.clear ( ios :: badbit ) ;
break;
}
if ( !address_stream.good() )
break;
address_stream >> separator;
if ( separator != FIELD_SEPARATOR )
{
address_stream.clear ( ios :: badbit ) ;
break;
}
}
if ( address_stream.good() )
{
address_stream >> temp_field;
if (temp_field <= max_uchar)
{
// make sure that there are is nothing more left in the
// stream
if ( address_stream.eof() )
{
is_valid = TRUE;
}
}
}
if ( ! is_valid )
{
if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
{
hostent FAR *hostEntry = gethostbyname ( address );
if ( hostEntry )
{
is_valid = TRUE ;
}
}
}
}
else
{
if ( addressResolution & SNMP_ADDRESS_RESOLVE_NAME )
{
hostent FAR *hostEntry = gethostbyname ( address );
if ( hostEntry )
{
is_valid = TRUE ;
}
}
}
return is_valid ;
}
BOOL SnmpTransportIpAddress::GetIpAddress ( IN const char *address )
{
// create a stream to read the fields from
istrstream address_stream((char *)address);
// contains the maximum value for a USHORT. used
// for comparison with the field values read
const UCHAR max_uchar = -1;
// consecutive fields must be separated by a
// FIELD_SEPARATOR
char separator;
// a field is first read into this for comparison
// with max_uchar
ULONG temp_field;
is_valid = FALSE;
// read the first three (USHORT,FIELD_SEPARATOR) pairs
// check if the stream is good before each read
for(int i=0; i < (SNMP_IP_ADDR_LEN-1); i++)
{
if ( !address_stream.good() )
break;
address_stream >> temp_field;
if ( temp_field > max_uchar )
{
address_stream.clear ( ios :: badbit ) ;
break;
}
field[i] = (UCHAR)temp_field;
if ( !address_stream.good() )
break;
address_stream >> separator;
if ( separator != FIELD_SEPARATOR )
{
address_stream.clear ( ios :: badbit ) ;
break;
}
}
if ( address_stream.good() )
{
address_stream >> temp_field;
if (temp_field <= max_uchar)
{
field[SNMP_IP_ADDR_LEN-1] = (UCHAR)temp_field;
// make sure that there are is nothing more left in the
// stream
if ( address_stream.eof() )
{
is_valid = TRUE;
}
}
}
return is_valid ;
}
// set the fields to the lower 32 bits in the ULONG parameter
// in general, sets the SNMP_IP_ADDR_LEN fields, each of size 8 bits
#pragma warning (disable:4244)
SnmpTransportIpAddress::SnmpTransportIpAddress( IN const ULONG address )
{
allocated = FALSE;
// flag starts with the last byte on
ULONG hostOrder = ntohl ( address ) ;
field [ 0 ] = ( hostOrder >> 24 ) & 0xff ;
field [ 1 ] = ( hostOrder >> 16 ) & 0xff ;
field [ 2 ] = ( hostOrder >> 8 ) & 0xff ;
field [ 3 ] = hostOrder & 0xff ;
is_valid = TRUE;
}
#pragma warning (default:4244)
// free the dotted notation string if it was allocated
SnmpTransportIpAddress::~SnmpTransportIpAddress()
{
if ( allocated )
delete[] dotted_notation;
}
// returns the number of fields copied
USHORT SnmpTransportIpAddress::GetAddress ( OUT UCHAR *address , IN const USHORT length ) const
{
// if the stream is valid, copy the fields onto the
// buffer pointed to by address.
if ( is_valid )
{
// only these many fields need be copied
USHORT len = MIN(length,SNMP_IP_ADDR_LEN);
for(int i=0; i < len; i++)
address[i] = field[i];
return len;
}
else
return 0;
}
// prepares a dot-notation representation of the address and points
// the dotted_notation char ptr to the allocated string.
// Note: memory for the decimal notation string is allocated only when
// the char *GetAddress method is called (and the address is valid)
// this memory must be freed if required
char *SnmpTransportIpAddress::GetAddress()
{
// do all this only when the address is valid
if ( is_valid )
{
// if already allocated, return the stored string
if ( allocated )
return dotted_notation;
else
{
// create a temp. output stream to prepare the char string
dotted_notation = new char[ MAX_ADDRESS_LEN ];
allocated = TRUE;
sprintf (
dotted_notation,
"%d.%d.%d.%d" ,
(ULONG)field[0],
(ULONG)field[1],
(ULONG)field[2],
(ULONG)field[3]
);
return dotted_notation;
}
}
else
return NULL;
}
SnmpTransportAddress *SnmpTransportIpAddress::Copy () const
{
SnmpTransportIpAddress *new_address = new SnmpTransportIpAddress();
if ( is_valid )
*new_address = field;
return new_address;
}
// checks if the two instances represent equal addresses
BOOL SnmpTransportIpAddress::operator== ( IN const SnmpTransportIpAddress & address ) const
{
// if both the instances are valid, then a field
// by field comparison, starting with the most
// significant field (index 0) yields the answer
if ( (is_valid) && address.IsValid() )
{
UCHAR temp[SNMP_IP_ADDR_LEN];
address.GetAddress(temp,SNMP_IP_ADDR_LEN);
for(int i=0; i < SNMP_IP_ADDR_LEN; i++)
if ( field[i] != temp[i] )
return FALSE;
return TRUE;
}
else // if either of them is invalid, they
// cannot be equal
return FALSE;
}
// sets the internal address to the specified parameter
// and makes the instance valid
SnmpTransportIpAddress &SnmpTransportIpAddress::operator= ( IN const UCHAR *ipAddr )
{
if ( ipAddr == NULL )
return *this;
const UCHAR max_uchar = -1;
for(int i=0; i < SNMP_IP_ADDR_LEN; i++)
{
if ( ipAddr[i] > max_uchar )
return *this;
field[i] = ipAddr[i];
}
is_valid = TRUE;
// if a dotted-notation char string was prepared for the previous address
// free the allocated memory
if ( allocated )
{
delete[] dotted_notation;
allocated = FALSE;
}
return *this;
}
// copies the specified instance (parameter) onto itself
// if the parameter instance is found valid
SnmpTransportIpAddress &SnmpTransportIpAddress::operator= ( IN const SnmpTransportIpAddress &address )
{
const UCHAR max_uchar = -1;
// if valid, proceed
if (address.IsValid())
{
// get address fields
address.GetAddress(field,SNMP_IP_ADDR_LEN);
// copy the obtained fields onto local fields
for( int i=0; i < SNMP_IP_ADDR_LEN; i++ )
if ( field[i] > max_uchar )
return *this;
is_valid = TRUE;
// since the address changes, free the previously
// allocated dotted-notation char string
if ( allocated )
{
delete[] dotted_notation;
allocated = FALSE;
}
}
return *this;
}
// returns the field requested by the parameter index
// if the index is illegal, an OutOfRange exception is
// raised
UCHAR SnmpTransportIpAddress::operator[] ( IN const USHORT index ) const
{
// if valid and the index is legal, return the field
if ( (is_valid) && (BETWEEN(index,0,SNMP_IP_ADDR_LEN)) )
return field[index];
// should never reach here if the caller checked the index
return 0;
}
SnmpTransportIpxAddress::SnmpTransportIpxAddress ( IN const UCHAR *address, IN const USHORT address_length )
{
allocated = FALSE;
is_valid = FALSE;
if ( address_length != SNMP_IPX_ADDR_LEN )
return;
is_valid = TRUE;
for ( ULONG index = 0 ; index < SNMP_IPX_ADDR_LEN ; index ++ )
{
field [ index ] = address [ index ] ;
}
}
// sets the fields to the contents extracted from the dotted
// decimal address string in parameter
SnmpTransportIpxAddress::SnmpTransportIpxAddress ( IN const char *address )
{
allocated = FALSE;
is_valid = GetIpxAddress ( address ) ;
}
UCHAR HexToDecInteger ( char token )
{
if ( token >= '0' && token <= '9' )
{
return token - '0' ;
}
else if ( token >= 'a' && token <= 'f' )
{
return token - 'a' + 10 ;
}
else if ( token >= 'A' && token <= 'F' )
{
return token - 'A' + 10 ;
}
else
{
return 0 ;
}
}
#pragma warning (disable:4244)
BOOL SnmpTransportIpxAddress::ValidateAddress ( IN const char *address )
{
BOOL is_valid = TRUE ;
// create a stream to read the fields from
istrstream address_stream((char *)address);
address_stream.setf ( ios :: hex ) ;
ULONG t_NetworkAddress ;
address_stream >> t_NetworkAddress ;
if ( address_stream.good() )
{
// consecutive fields must be separated by a
// FIELD_SEPARATOR
char separator;
address_stream >> separator;
if ( separator == IPX_FIELD_SEPARATOR )
{
ULONG t_StationOctets = 0 ;
while ( is_valid && t_StationOctets < 6 )
{
int t_OctetHigh = address_stream.get () ;
int t_OctetLow = address_stream.get () ;
if ( isxdigit ( t_OctetHigh ) && isxdigit ( t_OctetLow ) )
{
t_StationOctets ++ ;
}
else
{
is_valid = FALSE ;
}
}
if ( t_StationOctets != 6 )
{
is_valid = FALSE ;
}
}
if ( address_stream.eof() )
{
is_valid = TRUE;
}
}
else
{
is_valid = FALSE ;
}
return is_valid ;
}
BOOL SnmpTransportIpxAddress::GetIpxAddress ( IN const char *address )
{
// create a stream to read the fields from
istrstream address_stream((char *)address);
address_stream.setf ( ios :: hex ) ;
is_valid = TRUE ;
ULONG t_NetworkAddress ;
address_stream >> t_NetworkAddress ;
if ( address_stream.good() )
{
field [ 0 ] = ( t_NetworkAddress >> 24 ) & 0xff ;
field [ 1 ] = ( t_NetworkAddress >> 16 ) & 0xff ;
field [ 2 ] = ( t_NetworkAddress >> 8 ) & 0xff ;
field [ 3 ] = t_NetworkAddress & 0xff ;
// consecutive fields must be separated by a
// FIELD_SEPARATOR
char separator;
address_stream >> separator;
if ( separator == IPX_FIELD_SEPARATOR )
{
ULONG t_StationOctets = 0 ;
while ( is_valid && t_StationOctets < 6 )
{
int t_OctetHigh = address_stream.get () ;
int t_OctetLow = address_stream.get () ;
if ( isxdigit ( t_OctetHigh ) && isxdigit ( t_OctetLow ) )
{
UCHAR t_Octet = ( HexToDecInteger ( (char)t_OctetHigh ) << 4 ) + HexToDecInteger ( (char)t_OctetLow ) ;
field [ 4 + t_StationOctets ] = t_Octet ;
t_StationOctets ++ ;
}
else
{
is_valid = FALSE ;
}
}
if ( t_StationOctets != 6 )
{
is_valid = FALSE ;
}
}
if ( address_stream.eof() )
{
is_valid = TRUE;
}
}
else
{
is_valid = FALSE ;
}
return is_valid ;
}
#pragma warning (default:4244)
// free the dotted notation string if it was allocated
SnmpTransportIpxAddress::~SnmpTransportIpxAddress()
{
if ( allocated )
delete[] dotted_notation;
}
// returns the number of fields copied
USHORT SnmpTransportIpxAddress::GetAddress ( OUT UCHAR *address , IN const USHORT length ) const
{
// if the stream is valid, copy the fields onto the
// buffer pointed to by address.
if ( is_valid )
{
// only these many fields need be copied
USHORT len = MIN(length,SNMP_IPX_ADDR_LEN);
for(int i=0; i < len; i++)
address[i] = field[i];
return len;
}
else
return 0;
}
// prepares a dot-notation representation of the address and points
// the dotted_notation char ptr to the allocated string.
// Note: memory for the decimal notation string is allocated only when
// the char *GetAddress method is called (and the address is valid)
// this memory must be freed if required
char *SnmpTransportIpxAddress::GetAddress()
{
// do all this only when the address is valid
if ( is_valid )
{
// if already allocated, return the stored string
if ( allocated )
return dotted_notation;
else
{
// create a temp. output stream to prepare the char string
char temp[MAX_ADDRESS_LEN];
ostrstream temp_stream(temp, MAX_ADDRESS_LEN);
// if any problems with the stream return NULL
if ( !temp_stream.good() )
return NULL;
temp_stream.setf ( ios :: hex ) ;
temp_stream.width ( 8 ) ;
temp_stream.fill ( '0' ) ;
ULONG t_NetworkAddress = ( field [ 0 ] << 24 ) +
( field [ 1 ] << 16 ) +
( field [ 2 ] << 8 ) +
( field [ 3 ] ) ;
// output the fields separated by the FIELD_SEPARATOR onto the output stream
temp_stream << t_NetworkAddress << IPX_FIELD_SEPARATOR ;
;
for(int i=SNMP_IPX_NETWORK_LEN; (temp_stream.good()) && (i < SNMP_IPX_ADDR_LEN); i++)
{
temp_stream.width ( 2 ) ;
temp_stream << (ULONG)field[i];
}
// if any problems with the stream return NULL
if ( !temp_stream.good() )
return NULL;
// end of string
temp_stream << (char)EOS;
// allocate the required memory and copy the prepared string onto it
int len = strlen(temp);
dotted_notation = new char[len+1];
allocated = TRUE;
strcpy(dotted_notation, temp);
return dotted_notation;
}
}
else
return NULL;
}
SnmpTransportAddress *SnmpTransportIpxAddress::Copy () const
{
SnmpTransportIpxAddress *new_address = new SnmpTransportIpxAddress();
if ( is_valid )
*new_address = field;
return new_address;
}
// checks if the two instances represent equal addresses
BOOL SnmpTransportIpxAddress::operator== ( IN const SnmpTransportIpxAddress & address ) const
{
// if both the instances are valid, then a field
// by field comparison, starting with the most
// significant field (index 0) yields the answer
if ( (is_valid) && address.IsValid() )
{
UCHAR temp[SNMP_IPX_ADDR_LEN];
address.GetAddress(temp,SNMP_IPX_ADDR_LEN);
for(int i=0; i < SNMP_IPX_ADDR_LEN; i++)
if ( field[i] != temp[i] )
return FALSE;
return TRUE;
}
else // if either of them is invalid, they
// cannot be equal
return FALSE;
}
// sets the internal address to the specified parameter
// and makes the instance valid
SnmpTransportIpxAddress &SnmpTransportIpxAddress::operator= ( IN const UCHAR *ipAddr )
{
if ( ipAddr == NULL )
return *this;
const UCHAR max_uchar = -1;
for(int i=0; i < SNMP_IPX_ADDR_LEN; i++)
{
if ( ipAddr[i] > max_uchar )
return *this;
field[i] = ipAddr[i];
}
is_valid = TRUE;
// if a dotted-notation char string was prepared for the previous address
// free the allocated memory
if ( allocated )
{
delete[] dotted_notation;
allocated = FALSE;
}
return *this;
}
// copies the specified instance (parameter) onto itself
// if the parameter instance is found valid
SnmpTransportIpxAddress &SnmpTransportIpxAddress::operator= ( IN const SnmpTransportIpxAddress &address )
{
const UCHAR max_uchar = -1;
// if valid, proceed
if (address.IsValid())
{
// get address fields
address.GetAddress(field,SNMP_IPX_ADDR_LEN);
// copy the obtained fields onto local fields
for( int i=0; i < SNMP_IPX_ADDR_LEN; i++ )
if ( field[i] > max_uchar )
return *this;
is_valid = TRUE;
// since the address changes, free the previously
// allocated dotted-notation char string
if ( allocated )
{
delete[] dotted_notation;
allocated = FALSE;
}
}
return *this;
}
// returns the field requested by the parameter index
// if the index is illegal, an OutOfRange exception is
// raised
UCHAR SnmpTransportIpxAddress::operator[] ( IN const USHORT index ) const
{
// if valid and the index is legal, return the field
if ( (is_valid) && (BETWEEN(index,0,SNMP_IPX_ADDR_LEN)) )
return field[index];
// should never reach here if the caller checked the index
return 0;
}