// 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 #include // 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; }