1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
29 /*===================================================================
32 Hewlett-Packard Company
34 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
35 Permission to use, copy, modify, distribute and/or sell this software
36 and/or its documentation is hereby granted without fee. User agrees
37 to display the above copyright notice and this license notice in all
38 copies of the software and any documentation of the software. User
39 agrees to assume all liability for the use of the software; Hewlett-Packard
40 makes no representations about the suitability of this software for any
41 purpose. It is provided "AS-IS" without warranty of any kind,either express
42 or implied. User hereby grants a royalty-free license to any and all
43 derivatives based upon this software code base.
47 ADDRESS CLASS IMPLEMENTATION
49 DESIGN + AUTHOR: Peter E. Mellquist
51 DESCRIPTION: Implementation file for Address classes.
52 =====================================================================*/
53 char address_cpp_version[]="@(#) SNMP++ $Id: address.cpp 1711 2010-02-10 21:25:47Z katz $";
59 #if defined(__APPLE__)
60 #include <arpa/inet.h>
64 #include "snmp_pp/address.h"
65 #include "snmp_pp/v3.h"
66 #include "snmp_pp/IPv6Utility.h"
68 #ifdef SNMP_PP_NAMESPACE
72 /* Borlands isdigit has a bug */
74 #define my_isdigit(c) ((c) >= '0' && (c) <= '9')
76 #define my_isdigit isdigit
80 #define ADDRESS_TRACE debugprintf(0, "ADDRESS %p Enter %s", this, __PRETTY_FUNCTION__)
81 #define ADDRESS_TRACE2 debugprintf(0, "ADDRESS op Enter %s", __PRETTY_FUNCTION__)
84 #define ADDRESS_TRACE2
87 #if !defined HAVE_GETHOSTBYNAME_R || !defined HAVE_GETHOSTBYADDR_R || !defined HAVE_REENTRANT_GETHOSTBYNAME || !defined HAVE_REENTRANT_GETHOSTBYADDR
89 SnmpSynchronized Address::syscall_mutex;
93 //=================================================================
94 //======== Abstract Address Class Implementation ==================
95 //=================================================================
98 : addr_changed(true), valid_flag(false)
102 memset(address_buffer, 0, sizeof(unsigned char)*ADDRBUF);
105 //------------[ Address::trim_white_space( char * ptr) ]------------
106 // destructive trim white space
107 void Address::trim_white_space(char *ptr)
111 char *tmp = ptr; // init
112 while (*tmp==' ') tmp++; // skip leading white space
113 while (*tmp && (*tmp != ' ')) *ptr++ = *tmp++; // move string to beginning
114 *ptr = 0; // set end of string
118 void Address::clear()
122 memset(address_buffer, 0, sizeof(unsigned char)*ADDRBUF);
125 //-----------------------------------------------------------------------
126 // overloaded equivlence operator, are two addresses equal?
127 int operator==(const Address &lhs, const Address &rhs)
131 return (strcmp((const char*)lhs, (const char*)rhs) == 0);
134 //------------------------------------------------------------------
135 // overloaded > operator, is a1 > a2
136 int operator>(const Address &lhs, const Address &rhs)
140 return (strcmp((const char*)lhs, (const char*)rhs) > 0);
143 //-----------------------------------------------------------------
144 // overloaded < operator, is a1 < a2
145 int operator<(const Address &lhs, const Address &rhs)
149 return (strcmp((const char*)lhs, (const char*)rhs) < 0);
152 //------------------------------------------------------------------
153 // equivlence operator overloaded, are an address and a string equal?
154 int operator==(const Address &lhs, const char *rhs)
158 if (!rhs && !lhs.valid())
160 if (strcmp((const char *)lhs, rhs) == 0)
165 //------------------------------------------------------------------
166 // overloaded > , is a > inaddr
167 int operator>(const Address &lhs, const char *rhs)
172 return lhs.valid(); // if lhs valid then > NULL, else invalid !> NULL
173 if (strcmp((const char *)lhs, rhs) > 0)
178 //------------------------------------------------------------------
179 // overloaded >= , is a >= inaddr
180 int operator>=(const Address &lhs, const char *rhs)
185 return TRUE; // always >= NULL
186 if (strcmp((const char *)lhs, rhs) >= 0)
191 //-----------------------------------------------------------------
192 // overloaded < , are an address and a string equal?
193 int operator<(const Address &lhs, const char *rhs)
198 return FALSE; // always >= NULL
199 if (strcmp((const char *)lhs, rhs) < 0)
204 //-----------------------------------------------------------------
205 // overloaded <= , is a <= inaddr
206 int operator<=(const Address &lhs, const char *rhs)
211 return !lhs.valid(); // invalid == NULL, else valid > NULL
212 if (strcmp((const char *)lhs, rhs) <= 0)
217 //=====================================================================
218 //============ IPAddress Implementation ===============================
219 //=====================================================================
221 //-------[ construct an IP address with no agrs ]----------------------
222 IpAddress::IpAddress()
223 : Address(), iv_friendly_name_status(0), ip_version(version_ipv4)
227 // always initialize what type this object is
228 smival.syntax = sNMP_SYNTAX_IPADDR;
229 smival.value.string.len = IPLEN;
230 smival.value.string.ptr = address_buffer;
232 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
235 //-------[ construct an IP address with a string ]---------------------
236 IpAddress::IpAddress(const char *inaddr)
241 // always initialize what type this object is
242 smival.syntax = sNMP_SYNTAX_IPADDR;
243 smival.value.string.len = IPLEN;
244 smival.value.string.ptr = address_buffer;
246 // parse_address initializes valid, address_buffer & iv_friendly_name
247 valid_flag = parse_address(inaddr);
250 //-----[ IP Address copy constructor ]---------------------------------
251 IpAddress::IpAddress(const IpAddress &ipaddr)
252 : iv_friendly_name_status(0), ip_version(ipaddr.ip_version),
253 have_ipv6_scope(ipaddr.have_ipv6_scope)
257 // always initialize what type this object is
258 smival.syntax = sNMP_SYNTAX_IPADDR;
259 smival.value.string.len = ipaddr.smival.value.string.len;
260 smival.value.string.ptr = address_buffer;
262 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
263 valid_flag = ipaddr.valid_flag;
266 // copy the address data
267 MEMCPY(address_buffer, ipaddr.address_buffer, smival.value.string.len);
268 // and the friendly name
269 strcpy(iv_friendly_name, ipaddr.iv_friendly_name);
271 if (!ipaddr.addr_changed)
273 memcpy(output_buffer, ipaddr.output_buffer,
274 sizeof(unsigned char) * OUTBUFF);
275 addr_changed = false;
280 //-----[ construct an IP address with a GenAddress ]---------------------
281 IpAddress::IpAddress(const GenAddress &genaddr)
282 : iv_friendly_name_status(0)
286 // always initialize what type this object is
287 smival.syntax = sNMP_SYNTAX_IPADDR;
288 smival.value.string.len = IPLEN;
289 smival.value.string.ptr = address_buffer;
291 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
294 // allow use of an ip or udp genaddress
295 valid_flag = genaddr.valid();
298 if (genaddr.get_type() == type_ip)
300 // copy in the IP address data
301 *this = genaddr.cast_ipaddress();
304 else if (genaddr.get_type() == type_udp)
306 // copy in the IP address data
307 *this = genaddr.cast_udpaddress();
315 //-----[ IP Address general = operator ]-------------------------------
316 SnmpSyntax& IpAddress::operator=(const SnmpSyntax &val)
320 if (this == &val) return *this; // protect against assignment from itself
323 valid_flag = false; // will get set TRUE if really valid
324 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
328 switch (val.get_syntax())
330 case sNMP_SYNTAX_IPADDR:
331 case sNMP_SYNTAX_OCTETS:
332 if ((((IpAddress &)val).smival.value.string.len == IPLEN) ||
333 (((IpAddress &)val).smival.value.string.len == UDPIPLEN))
335 MEMCPY(address_buffer,
336 ((IpAddress &)val).smival.value.string.ptr, IPLEN);
338 ip_version = version_ipv4;
339 smival.value.string.len = IPLEN;
341 else if ((((IpAddress &)val).smival.value.string.len == IP6LEN_NO_SCOPE) ||
342 (((IpAddress &)val).smival.value.string.len == UDPIP6LEN_NO_SCOPE))
344 MEMCPY(address_buffer,
345 ((IpAddress &)val).smival.value.string.ptr, IP6LEN_NO_SCOPE);
347 ip_version = version_ipv6;
348 smival.value.string.len = IP6LEN_NO_SCOPE;
349 have_ipv6_scope = false;
351 else if ((((IpAddress &)val).smival.value.string.len == IP6LEN_WITH_SCOPE) ||
352 (((IpAddress &)val).smival.value.string.len == UDPIP6LEN_WITH_SCOPE))
354 MEMCPY(address_buffer,
355 ((IpAddress &)val).smival.value.string.ptr, IP6LEN_WITH_SCOPE);
357 ip_version = version_ipv6;
358 smival.value.string.len = IP6LEN_WITH_SCOPE;
359 have_ipv6_scope = true;
363 // NOTE: as a value add, other types could have "logical"
364 // mappings, i.e. integer32 and unsigned32
370 //------[ assignment to another ipaddress object overloaded ]-----------------
371 IpAddress& IpAddress::operator=(const IpAddress &ipaddr)
375 if (this == &ipaddr) return *this; // protect against assignment from itself
377 valid_flag = ipaddr.valid_flag;
378 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
382 if (ipaddr.ip_version == version_ipv4)
384 MEMCPY(address_buffer, ipaddr.address_buffer, IPLEN);
385 ip_version = version_ipv4;
386 smival.value.string.len = IPLEN;
390 if (ipaddr.have_ipv6_scope)
392 MEMCPY(address_buffer, ipaddr.address_buffer, IP6LEN_WITH_SCOPE);
393 ip_version = version_ipv6;
394 smival.value.string.len = IP6LEN_WITH_SCOPE;
395 have_ipv6_scope = true;
399 MEMCPY(address_buffer, ipaddr.address_buffer, IP6LEN_NO_SCOPE);
400 ip_version = version_ipv6;
401 smival.value.string.len = IP6LEN_NO_SCOPE;
402 have_ipv6_scope = false;
405 strcpy(iv_friendly_name, ipaddr.iv_friendly_name);
407 if (ipaddr.addr_changed)
411 memcpy(output_buffer, ipaddr.output_buffer,
412 sizeof(unsigned char) * OUTBUFF);
413 addr_changed = false;
421 IpAddress& IpAddress::operator=(const char *inaddr)
425 valid_flag = parse_address(inaddr);
430 //-------[ return the friendly name ]----------------------------------
431 char *IpAddress::friendly_name(int &status)
435 if ((iv_friendly_name[0]==0) && (valid_flag))
436 this->addr_to_friendly();
437 status = iv_friendly_name_status;
438 return iv_friendly_name;
441 // parse a dotted string
442 int IpAddress::parse_dotted_ipstring(const char *inaddr)
447 char temp[30]; // temp buffer for destruction
449 // check len, an ip can never be bigger than 15
452 if (!inaddr || (strlen(inaddr) >= sizeof(temp))) return FALSE;
454 strcpy(temp, inaddr);
455 trim_white_space(temp);
456 if (strlen(temp) > 15) return FALSE;
458 /* Check for the following:
459 * - exactly three dots
460 * - no dot at begin or end
461 * - at least a digit between two dots
462 * - only dots and digits allowed
466 bool last_char_was_dot = true;
472 if (last_char_was_dot) return FALSE;
474 last_char_was_dot = true;
476 else if (my_isdigit(*ptr))
478 last_char_was_dot = false;
484 if ((dot_count != 3) || (last_char_was_dot))
490 unsigned long number = 0;
492 if (*ptr == '.') ++ptr; // skip over the dot
494 // grab a digit token and convert it to a long int
496 while ((*ptr) && (*ptr != '.'))
498 number = (number * 10) + *(ptr++) - '0';
501 if (digits > 3) return FALSE;
502 if (number > 255) return FALSE;
504 // stuff the value into the array and bump the counter
505 address_buffer[token_count++]= (unsigned char) number;
508 ip_version = version_ipv4;
509 smival.value.string.len = IPLEN;
513 #define ATOI(x) if ((x >= 48) && (x <= 57)) x = x-48; /* 0-9 */ \
514 else if ((x >= 97) && (x <=102)) x = x-87; /* a-f */ \
515 else if ((x >= 65) && (x <= 70)) x = x-55; /* A-F */ \
518 // parse a coloned string
519 int IpAddress::parse_coloned_ipstring(const char *inaddr)
523 unsigned char tmp_address_buffer[ADDRBUF];
524 char temp[60]; // temp buffer for destruction
526 // check len, an ipv6 can never be bigger than 39 + 11
527 // 123456789012345678901234567890123456789
528 // 1BCD:2BCD:3BCD:4BCD:5BCD:6BCD:7BCD:8BCD%4123456789
529 if (!inaddr || (strlen(inaddr) >= sizeof(temp))) return FALSE;
530 strcpy(temp, inaddr);
531 trim_white_space(temp);
533 // first check for ipv6 scope
534 unsigned int scope = 0;
535 bool have_scope = false;
539 for (int i=strlen(temp)-1; i >=0 ; i--)
547 if (!isdigit(temp[i]))
553 scope = atol(temp + scope_pos + 1);
557 if (strlen(temp) > 39) return FALSE;
560 char *out_ptr = (char*)tmp_address_buffer;
561 char *end_first_part = NULL;
563 int second_used = FALSE;
565 int had_double_colon = FALSE;
566 int last_was_colon = FALSE;
571 char last_deliminiter = 0;
577 last_deliminiter = *in_ptr;
582 if ((digit_count > 3) || (digit_count < 1))
584 for (int i=0; i<digit_count; i++)
585 if (!my_isdigit(digits[i]))
587 digits[digit_count] = 0;
588 int value = atoi(digits);
589 if ((value > 0) && (value <= 255))
590 *out_ptr++ = (unsigned char) value;
593 if (strcmp(digits, "0") == 0)
594 *out_ptr++ = (unsigned char) 0;
600 else if (*in_ptr == ':')
602 last_deliminiter = *in_ptr;
605 return FALSE; // don't allow : after a dot
609 // move digits to right
611 for (int i=0; i<digit_count; i++)
613 ATOI(digits[digit_count - 1 - i]);
614 digits[3-i] = digits[digit_count - 1 - i];
618 for (int i=0; i<4-digit_count; i++)
622 // pack two digits into one byte
623 for (int i=0; i < 4; i += 2)
625 unsigned char c = digits[i];
626 unsigned char d = digits[i+1];
627 *out_ptr++ = (c*16 + d);
635 if (had_double_colon)
637 end_first_part = out_ptr;
640 had_double_colon = TRUE;
644 last_was_colon = TRUE;
649 if (digit_count >= 4)
651 if (!isxdigit(*in_ptr))
653 digits[digit_count] = tolower(*in_ptr);
663 // put last bytes from digits into buffer
666 if (last_deliminiter == ':')
669 // move digits to right
670 for (int i=0; i<digit_count; i++)
672 ATOI(digits[digit_count - 1 - i]);
673 digits[3-i] = digits[digit_count - 1 - i];
677 for (int i=0; i<4-digit_count; i++)
681 // pack two digits into one byte
682 for (int i=0; i < 4; i += 2)
684 unsigned char c = digits[i];
685 unsigned char d = digits[i+1];
686 *out_ptr++ = (c*16 + d);
691 else if (last_deliminiter == '.')
693 if ((digit_count > 3) || (digit_count < 1))
695 for (int i=0; i<digit_count; i++)
696 if (!my_isdigit(digits[i]))
698 digits[digit_count] = 0;
699 int value = atoi(digits);
700 if ((value > 0) && (value <= 255))
701 *out_ptr++ = (unsigned char) value;
704 if (strcmp(digits, "0") == 0)
705 *out_ptr++ = (unsigned char) 0;
715 // must have between two and seven colons
716 if ((colon_count > 7) || (colon_count < 2))
719 // if there was a dot there must be three of them
720 if ((dot_count > 0) && (dot_count != 3))
725 int len_first = SAFE_INT_CAST(end_first_part - (char*)tmp_address_buffer);
726 int len_second = SAFE_INT_CAST(out_ptr - second);
729 for (i=0; i<IP6LEN_NO_SCOPE-(len_first + len_second); i++)
730 *end_first_part++ = 0;
731 for (i=0; i<len_second; i++)
732 *end_first_part++ = second[i];
736 end_first_part = out_ptr;
738 // check for short address
739 if (end_first_part - (char*)tmp_address_buffer != IP6LEN_NO_SCOPE)
742 ip_version = version_ipv6;
744 smival.value.string.len = IP6LEN_WITH_SCOPE;
746 smival.value.string.len = IP6LEN_NO_SCOPE;
748 memcpy(address_buffer, tmp_address_buffer, ADDRBUF);
752 unsigned int *scope_p = (unsigned int*)(address_buffer + IP6LEN_NO_SCOPE);
753 *scope_p = htonl(scope);
754 have_ipv6_scope = true;
757 have_ipv6_scope = false;
764 //-----[ IP Address parse Address ]---------------------------------
765 bool IpAddress::parse_address(const char *inaddr)
769 #if !defined HAVE_GETHOSTBYNAME_R && !defined HAVE_REENTRANT_GETHOSTBYNAME
771 SnmpSynchronize s(syscall_mutex);
777 // parse the input char array fill up internal buffer with four ip
778 // bytes set and return validity flag
782 // intialize the friendly_name member variable
783 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
784 iv_friendly_name_status = 0;
786 // is this a dotted IP notation string or a friendly name
787 if (parse_dotted_ipstring(inaddr))
789 // since this is a valid dotted string don't do any DNS
792 else if (parse_coloned_ipstring(inaddr))
794 // since this is a valid ipv6 string don't do any DNS
797 else // not a dotted string, try to resolve it via DNS
799 #if defined (CPU) && CPU == PPC603
800 int lookupResult = hostGetByName(inaddr);
802 if (lookupResult == ERROR)
804 iv_friendly_name_status = lookupResult;
807 // now lets check out the dotted string
808 strcpy(ds,inet_ntoa(lookupResult));
810 if (!parse_dotted_ipstring(ds))
813 // save the friendly name
814 strcpy(iv_friendly_name, inaddr);
819 hostent *lookupResult = 0;
821 #ifdef HAVE_GETHOSTBYNAME_R
822 char buf[2048]; // TODO: Too big buffer?
825 #if defined(__sun) || defined (__QNX_NEUTRINO)
826 lookupResult = gethostbyname_r(inaddr, &lookup_buf, buf, 2048, &herrno);
828 gethostbyname_r(inaddr, &lookup_buf, buf, 2048, &lookupResult, &herrno);
834 lookupResult = gethostbyname_r(inaddr, AF_INET6, &lookup_buf, buf, 2048,
835 &lookupResult, &herrno);
837 gethostbyname2_r(inaddr, AF_INET6, &lookup_buf, buf, 2048,
838 &lookupResult, &herrno);
841 #endif // SNMP_PP_IPv6
842 #else // not HAVE_GETHOSTBYNAME_R
843 lookupResult = gethostbyname(inaddr);
847 #ifdef HAVE_GETHOSTBYNAME2
848 lookupResult = gethostbyname2(inaddr, AF_INET6);
850 lookupResult = gethostbyname(inaddr);
851 #endif // HAVE_GETHOSTBYNAME2
853 #endif // SNMP_PP_IPv6
854 #endif // HAVE_GETHOSTBYNAME_R
858 if (lookupResult->h_length == sizeof(in6_addr))
861 memcpy((void *) &ipAddr, (void *) lookupResult->h_addr,
864 // now lets check out the coloned string
865 if (!inet_ntop(AF_INET6, &ipAddr, ds, 60))
867 debugprintf(4, "from inet_ntop: %s", ds);
868 if (!parse_coloned_ipstring(ds))
871 // save the friendly name
872 strcpy(iv_friendly_name, inaddr);
876 #endif // SNMP_PP_IPv6
877 if (lookupResult->h_length == sizeof(in_addr))
881 memcpy((void *) &ipAddr, (void *) lookupResult->h_addr,
884 // now lets check out the dotted string
885 strcpy(ds,inet_ntoa(ipAddr));
887 if (!parse_dotted_ipstring(ds))
890 // save the friendly name
891 strcpy(iv_friendly_name, inaddr);
895 } // end if lookup result
898 #ifdef HAVE_GETHOSTBYNAME_R
899 iv_friendly_name_status = herrno;
901 iv_friendly_name_status = h_errno;
906 } // end else not a dotted string
910 // using the currently defined address, do a DNS
911 // and try to fill up the name
912 int IpAddress::addr_to_friendly()
916 #if !defined HAVE_GETHOSTBYADDR_R && !defined HAVE_REENTRANT_GETHOSTBYADDR
918 SnmpSynchronize s(syscall_mutex);
922 #if defined (CPU) && CPU == PPC603
924 char hName[MAXHOSTNAMELEN+1];
926 hostent *lookupResult;
930 // can't look up an invalid address
931 if (!valid_flag) return -1;
933 // lets try and get the friendly name from the DNS
934 strcpy(ds, this->IpAddress::get_printable());
936 #if !(defined (CPU) && CPU == PPC603) && defined HAVE_GETHOSTBYADDR_R
939 char buf[2048]; // TODO: Buf size too big?
941 if (ip_version == version_ipv4)
945 #if defined HAVE_INET_ATON
946 if (inet_aton((char*)ds, &ipAddr) == 0)
947 return -1; // bad address
948 #elif defined HAVE_INET_PTON
949 if (inet_pton(AF_INET, (char*)ds, &ipAddr) <= 0)
950 return -1; // bad address
952 ipAddr.s_addr = inet_addr((char*)ds);
953 if (ipAddr.s_addr == INADDR_NONE)
954 return -1; // bad address
957 #if defined (CPU) && CPU == PPC603
958 lookupResult = hostGetByAddr(ipAddr.s_addr, hName);
959 #elif defined HAVE_GETHOSTBYADDR_R
960 #if defined(__sun) || defined(__QNX_NEUTRINO)
961 lookupResult = gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
962 AF_INET, &lookup, buf, 2048, &herrno);
964 gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
965 AF_INET, &lookup, buf, 2048, &lookupResult, &herrno);
968 lookupResult = gethostbyaddr((char *) &ipAddr, sizeof(in_addr),
977 // remove scope from ds
978 for (int i=strlen(ds); i >=0; i--)
988 if (inet_pton(AF_INET6, (char*)ds, &ipAddr) <= 0)
989 return -1; // bad address
991 #if defined (CPU) && CPU == PPC603
992 lookupResult = hostGetByAddr(ipAddr.s_addr, hName);
993 #elif defined HAVE_GETHOSTBYADDR_R
994 #if defined(__sun) || defined(__QNX_NEUTRINO)
995 lookupResult = gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
996 AF_INET6, &lookup, buf, 2048, &herrno);
998 gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
999 AF_INET6, &lookup, buf, 2048, &lookupResult, &herrno);
1002 lookupResult = gethostbyaddr((char *) &ipAddr, sizeof(in6_addr),
1004 #endif // HAVE_GETHOSTBYADDR_R
1007 #endif // SNMP_PP_IPv6
1009 // if we found the name, then update the iv friendly name
1010 #if defined (CPU) && CPU == PPC603
1011 if (lookupResult != ERROR)
1013 strncpy(iv_friendly_name, hName, MAX_FRIENDLY_NAME);
1018 iv_friendly_name_status = lookupResult;
1019 return lookupResult;
1022 return -1; //should not get here
1027 strcpy(iv_friendly_name, lookupResult->h_name);
1032 #ifdef HAVE_GETHOSTBYADDR_R
1033 iv_friendly_name_status = herrno;
1035 iv_friendly_name_status = h_errno;
1037 return iv_friendly_name_status;
1042 unsigned int IpAddress::get_scope() const
1048 const unsigned int *scope;
1049 if ((ip_version == version_ipv6) && (have_ipv6_scope))
1050 scope = (const unsigned int*)(address_buffer + IP6LEN_NO_SCOPE);
1052 return (unsigned int)-1;
1054 return ntohl(*scope);
1056 return (unsigned int)-1; // don't use uninitialized memory
1059 bool IpAddress::set_scope(const unsigned int scope)
1063 if (!valid_flag || (ip_version != version_ipv6))
1066 unsigned int *scope_ptr = (unsigned int*)(address_buffer + IP6LEN_NO_SCOPE);
1068 *scope_ptr = htonl(scope);
1069 addr_changed = true;
1070 smival.value.string.len = IP6LEN_WITH_SCOPE;
1071 have_ipv6_scope = true;
1075 //----[ IP address format output ]------------------------------------
1076 void IpAddress::format_output() const
1080 // if valid format else null it
1083 if (ip_version == version_ipv4)
1084 sprintf((char *) output_buffer,"%d.%d.%d.%d",address_buffer[0],
1085 address_buffer[1], address_buffer[2], address_buffer[3]);
1087 if (have_ipv6_scope)
1088 sprintf((char *) output_buffer,
1089 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
1090 "%02x%02x:%02x%02x:%02x%02x:%02x%02x%%%d",
1091 address_buffer[ 0], address_buffer[ 1], address_buffer[ 2],
1092 address_buffer[ 3], address_buffer[ 4], address_buffer[ 5],
1093 address_buffer[ 6], address_buffer[ 7], address_buffer[ 8],
1094 address_buffer[ 9], address_buffer[10], address_buffer[11],
1095 address_buffer[12], address_buffer[13], address_buffer[14],
1096 address_buffer[15], get_scope());
1098 sprintf((char *) output_buffer,
1099 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
1100 "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
1101 address_buffer[ 0], address_buffer[ 1], address_buffer[ 2],
1102 address_buffer[ 3], address_buffer[ 4], address_buffer[ 5],
1103 address_buffer[ 6], address_buffer[ 7], address_buffer[ 8],
1104 address_buffer[ 9], address_buffer[10], address_buffer[11],
1105 address_buffer[12], address_buffer[13], address_buffer[14],
1106 address_buffer[15]);
1109 *(char *)output_buffer = 0;
1110 IpAddress *nc_this = PP_CONST_CAST(IpAddress*, this);
1111 nc_this->addr_changed = false;
1114 //-----------------------------------------------------------------
1115 // logically and two IPaddresses and
1116 // return the new one
1117 void IpAddress::mask(const IpAddress& ipaddr)
1121 if (valid() && ipaddr.valid())
1123 int count = (ip_version == version_ipv4) ? IPLEN : IP6LEN_NO_SCOPE;
1125 for (int i = 0; i < count; i++)
1126 address_buffer[i] = address_buffer[i] & ipaddr.address_buffer[i];
1127 addr_changed = true;
1132 // Get the count of matching bits from the left.
1133 int IpAddress::get_match_bits(const IpAddress match_ip) const
1139 if (valid() && match_ip.valid() &&
1140 (ip_version == match_ip.ip_version))
1142 int count = (ip_version == version_ipv4) ? IPLEN : IP6LEN_NO_SCOPE;
1144 for (int i = 0; i < count; i++)
1146 if (address_buffer[i] == match_ip.address_buffer[i])
1151 unsigned char c1 = address_buffer[i] >> 1;
1152 unsigned char c2 = match_ip.address_buffer[i] >> 1;
1167 // Map a IPv4 Address to a IPv6 address.
1168 int IpAddress::map_to_ipv6()
1175 if (ip_version != version_ipv4)
1178 /* just copy IPv4 address to the end of the buffer
1179 zero the first 10 bytes and fill 2 Bytes with 0xff */
1180 memcpy(&address_buffer[12], address_buffer, 4);
1181 memset(address_buffer, 0, 10);
1182 address_buffer[10] = 0xff;
1183 address_buffer[11] = 0xff;
1185 smival.value.string.len = IP6LEN_NO_SCOPE;
1186 ip_version = version_ipv6;
1187 have_ipv6_scope = false;
1189 addr_changed = true;
1194 void IpAddress::clear()
1197 memset(output_buffer, 0, sizeof(output_buffer));
1198 iv_friendly_name_status = 0;
1199 ip_version = version_ipv4;
1200 have_ipv6_scope = false;
1201 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
1202 smival.value.string.len = IPLEN;
1205 //=======================================================================
1206 //========== Udp Address Implementation =================================
1207 //=======================================================================
1209 //-------[ construct an IP address with no agrs ]----------------------
1210 UdpAddress::UdpAddress()
1215 // Inherits IP Address attributes
1216 // Always initialize (override) what type this object is
1217 smival.syntax = sNMP_SYNTAX_OCTETS;
1218 smival.value.string.len = UDPIPLEN;
1219 smival.value.string.ptr = address_buffer;
1225 //-----------------[ construct an Udp address with another Udp address ]---
1226 UdpAddress::UdpAddress(const UdpAddress &udpaddr)
1227 : IpAddress(udpaddr)
1231 // always initialize SMI info
1232 smival.syntax = sNMP_SYNTAX_OCTETS;
1233 smival.value.string.len = udpaddr.smival.value.string.len;
1234 smival.value.string.ptr = address_buffer;
1236 // Copy the port value
1238 set_port(udpaddr.get_port());
1240 if (!udpaddr.addr_changed)
1242 memcpy(output_buffer, udpaddr.output_buffer,
1243 sizeof(unsigned char) * OUTBUFF);
1244 addr_changed = false;
1248 // constructor with a dotted string
1249 UdpAddress::UdpAddress(const char *inaddr) : IpAddress()
1253 // always initialize SMI info
1254 smival.syntax = sNMP_SYNTAX_OCTETS;
1255 smival.value.string.len = UDPIPLEN;
1256 smival.value.string.ptr = address_buffer;
1258 valid_flag = parse_address(inaddr);
1259 addr_changed = true;
1262 //-----------------[ construct a UdpAddress from a GenAddress ]--------------
1263 UdpAddress::UdpAddress(const GenAddress &genaddr) : IpAddress()
1267 // always initialize SMI info
1268 smival.syntax = sNMP_SYNTAX_OCTETS;
1269 smival.value.string.len = UDPIPLEN;
1270 smival.value.string.ptr = address_buffer;
1272 valid_flag = genaddr.valid();
1274 // allow use of an ip or udp genaddress
1277 if (genaddr.get_type() == type_udp)
1279 *this = genaddr.cast_udpaddress(); // copy in the IP address data
1281 else if (genaddr.get_type() == type_ip)
1283 *this = genaddr.cast_ipaddress(); // copy in the IP address data
1293 //--------[ construct a udp from an IpAddress ]--------------------------
1294 UdpAddress::UdpAddress(const IpAddress &ipaddr)
1299 // always initialize SMI info
1300 smival.syntax = sNMP_SYNTAX_OCTETS;
1301 if (ip_version == version_ipv4)
1302 smival.value.string.len = UDPIPLEN;
1304 if (have_ipv6_scope)
1305 smival.value.string.len = UDPIP6LEN_WITH_SCOPE;
1307 smival.value.string.len = UDPIP6LEN_NO_SCOPE;
1308 smival.value.string.ptr = address_buffer;
1311 addr_changed = true;
1315 // copy an instance of this Value
1316 SnmpSyntax& UdpAddress::operator=(const SnmpSyntax &val)
1320 if (this == &val) return *this; // protect against assignment from itself
1322 valid_flag = false; // will get set TRUE if really valid
1323 addr_changed = true;
1326 switch (val.get_syntax())
1328 case sNMP_SYNTAX_IPADDR:
1330 UdpAddress temp_udp(val.get_printable());
1331 *this = temp_udp; // valid_flag is set by the udp assignment
1334 case sNMP_SYNTAX_OCTETS:
1335 if (((UdpAddress &)val).smival.value.string.len == UDPIPLEN)
1337 MEMCPY(address_buffer,((UdpAddress &)val).smival.value.string.ptr,
1339 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
1341 ip_version = version_ipv4;
1342 smival.value.string.len = UDPIPLEN;
1344 else if (((UdpAddress &)val).smival.value.string.len == UDPIP6LEN_NO_SCOPE)
1346 MEMCPY(address_buffer,((UdpAddress &)val).smival.value.string.ptr,
1347 UDPIP6LEN_NO_SCOPE);
1348 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
1350 ip_version = version_ipv6;
1351 smival.value.string.len = UDPIP6LEN_NO_SCOPE;
1352 have_ipv6_scope = false;
1354 else if (((UdpAddress &)val).smival.value.string.len == UDPIP6LEN_WITH_SCOPE)
1356 MEMCPY(address_buffer,((UdpAddress &)val).smival.value.string.ptr,
1357 UDPIP6LEN_WITH_SCOPE);
1358 memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
1360 ip_version = version_ipv6;
1361 smival.value.string.len = UDPIP6LEN_WITH_SCOPE;
1362 have_ipv6_scope = true;
1365 // NOTE: as a value add, other types could have "logical"
1366 // mappings, i.e. integer32 and unsigned32
1372 // assignment to another UdpAddress object overloaded
1373 UdpAddress& UdpAddress::operator=(const UdpAddress &udpaddr)
1377 if (this == &udpaddr) return *this; // protect against assignment from itself
1379 (IpAddress &)*this = udpaddr; // use ancestor assignment for ipaddr value
1380 if (ip_version == version_ipv4)
1381 smival.value.string.len = UDPIPLEN;
1383 if (have_ipv6_scope)
1384 smival.value.string.len = UDPIP6LEN_WITH_SCOPE;
1386 smival.value.string.len = UDPIP6LEN_NO_SCOPE;
1388 set_port(udpaddr.get_port()); // copy to port value
1389 if (udpaddr.addr_changed)
1391 addr_changed = true;
1395 memcpy(output_buffer, udpaddr.output_buffer,
1396 sizeof(unsigned char) * OUTBUFF);
1397 addr_changed = false;
1403 // assignment to another UdpAddress object overloaded
1404 UdpAddress& UdpAddress::operator=(const IpAddress &ipaddr)
1408 if (this == &ipaddr) return *this; // protect against assignment from itself
1410 (IpAddress &)*this = ipaddr; // use ancestor assignment for ipaddr value
1412 if (ip_version == version_ipv4)
1413 smival.value.string.len = UDPIPLEN;
1415 if (have_ipv6_scope)
1416 smival.value.string.len = UDPIP6LEN_WITH_SCOPE;
1418 smival.value.string.len = UDPIP6LEN_NO_SCOPE;
1420 set_port(0); // copy to port value
1421 addr_changed = true;
1425 UdpAddress& UdpAddress::operator=(const char *inaddr)
1429 valid_flag = parse_address(inaddr);
1430 addr_changed = true;
1434 //-----[ IP Address parse Address ]---------------------------------
1435 bool UdpAddress::parse_address(const char *inaddr)
1439 addr_changed = true;
1441 char buffer[MAX_FRIENDLY_NAME];
1443 if (inaddr && (strlen(inaddr)< MAX_FRIENDLY_NAME))
1445 strcpy(buffer, inaddr);
1446 trim_white_space(buffer);
1453 // look for port info @ the end of the string
1454 // port can be delineated by a ':' or a '/'
1455 // if neither are present then just treat it
1456 // like a normal IpAddress
1458 int remove_brackets = FALSE;
1460 int pos = (int)strlen(buffer) - 1; // safe to cast as max is MAX_FRIENDLY_NAME
1462 int another_colon_found = FALSE;
1463 bool scope_found = false;
1471 // search from the end, to find the start of the port
1472 // [ipv4]:port [ipv4]/port ipv4/port ipv4:port [ipv4] ipv4
1473 // [ipv6]:port [ipv6]/port ipv6/port [ipv6] ipv6
1476 if (buffer[pos] == '/')
1480 if (buffer[pos -1] == ']')
1481 remove_brackets = TRUE;
1484 if (buffer[pos] == ':')
1486 if ((pos > 1) && (buffer[pos -1] == ']'))
1489 remove_brackets = TRUE;
1494 for (int i=pos - 1; i >= 0 ; i--)
1496 if (buffer[i] == ':')
1497 another_colon_found = TRUE;
1498 if (buffer[i] == '%')
1501 if (scope_found) // must be ipv6, so reset colon_found
1502 another_colon_found = false;
1504 if (!another_colon_found)
1511 if (buffer[pos] == ']')
1513 // we found a ] without following a port, so increase pos
1515 remove_brackets = TRUE;
1519 do_loop = ((found == FALSE) && (pos >= 0) &&
1520 (another_colon_found == FALSE));
1523 if (remove_brackets)
1530 unsigned short port;
1535 port = atoi(&buffer[pos+1]);
1536 result = IpAddress::parse_address(buffer);
1541 result = IpAddress::parse_address(buffer);
1544 if (ip_version == version_ipv4)
1545 smival.value.string.len = UDPIPLEN;
1547 if (have_ipv6_scope)
1548 smival.value.string.len = UDPIP6LEN_WITH_SCOPE;
1550 smival.value.string.len = UDPIP6LEN_NO_SCOPE;
1557 //--------[ set the port number ]---------------------------------------
1558 void UdpAddress::set_port(const unsigned short p)
1562 unsigned short *port_nbo;
1563 if (ip_version == version_ipv4)
1564 port_nbo = (unsigned short*)(address_buffer + IPLEN);
1566 if (have_ipv6_scope)
1567 port_nbo = (unsigned short*)(address_buffer + IP6LEN_WITH_SCOPE);
1569 port_nbo = (unsigned short*)(address_buffer + IP6LEN_NO_SCOPE);
1570 *port_nbo = htons(p);
1571 addr_changed = true;
1574 //---------[ get the port number ]--------------------------------------
1575 unsigned short UdpAddress::get_port() const
1581 const unsigned short *port_nbo;
1582 if (ip_version == version_ipv4)
1583 port_nbo = (const unsigned short*)(address_buffer + IPLEN);
1585 if (have_ipv6_scope)
1586 port_nbo = (const unsigned short*)(address_buffer + IP6LEN_WITH_SCOPE);
1588 port_nbo = (const unsigned short*)(address_buffer + IP6LEN_NO_SCOPE);
1590 return ntohs(*port_nbo);
1592 return 0;// don't use uninitialized memory
1595 //----[ UDP address format output ]------------------------------------
1596 void UdpAddress::format_output() const
1600 IpAddress::format_output(); // allow ancestors to format their buffers
1602 // if valid format else null it
1605 if (ip_version == version_ipv4)
1606 sprintf((char *) output_buffer,"%s%c%d",
1607 IpAddress::get_printable(),
1608 '/',//TODO:look for problems in old code and change to "sep"
1611 sprintf((char *) output_buffer,"[%s]%c%d",
1612 IpAddress::get_printable(),
1613 '/',//TODO:look for problems in old code and change to "sep"
1617 *(char*)output_buffer = 0;
1618 UdpAddress *nc_this = PP_CONST_CAST(UdpAddress*, this);
1619 nc_this->addr_changed = false;
1622 bool UdpAddress::set_scope(const unsigned int scope)
1626 /* Save the port, as IpAddress::set_scope destroys it */
1627 unsigned short old_port = get_port();
1629 if (!IpAddress::set_scope(scope))
1632 smival.value.string.len = UDPIP6LEN_WITH_SCOPE;
1640 * Map a IPv4 UDP address to a IPv6 UDP address.
1642 * @return - TRUE if no error occured.
1644 int UdpAddress::map_to_ipv6()
1648 /* Save the port, as IpAddress::map_to_ipv6 destroys it */
1649 unsigned short old_port = get_port();
1652 if (!IpAddress::map_to_ipv6())
1656 smival.value.string.len = UDPIP6LEN_NO_SCOPE;
1657 ip_version = version_ipv6;
1659 addr_changed = true;
1665 //=======================================================================
1666 //=========== IPX Address Implementation ================================
1667 //=======================================================================
1669 //----------[ constructor no args ]--------------------------------------
1670 IpxAddress::IpxAddress() : Address()
1672 // always initialize SMI info
1673 smival.syntax = sNMP_SYNTAX_OCTETS;
1674 smival.value.string.len = IPXLEN;
1675 smival.value.string.ptr = address_buffer;
1679 addr_changed = true;
1683 //----------[ constructor with a string arg ]---------------------------
1684 IpxAddress::IpxAddress(const char *inaddr):Address()
1686 // always initialize SMI info
1687 smival.syntax = sNMP_SYNTAX_OCTETS;
1688 smival.value.string.len = IPXLEN;
1689 smival.value.string.ptr = address_buffer;
1692 valid_flag = parse_address(inaddr);
1693 addr_changed = true;
1697 //-----[ IPX Address copy constructor ]----------------------------------
1698 IpxAddress::IpxAddress(const IpxAddress &ipxaddr)
1700 // always initialize SMI info
1701 smival.syntax = sNMP_SYNTAX_OCTETS;
1702 smival.value.string.len = IPXLEN;
1703 smival.value.string.ptr = address_buffer;
1706 valid_flag = ipxaddr.valid_flag;
1708 MEMCPY(address_buffer, ipxaddr.address_buffer, IPXLEN);
1709 addr_changed = true;
1713 //----[ construct an IpxAddress from a GenAddress ]---------------------------
1714 IpxAddress::IpxAddress(const GenAddress &genaddr)
1716 // always initialize SMI info
1717 smival.syntax = sNMP_SYNTAX_OCTETS;
1718 smival.value.string.len = IPXLEN;
1719 smival.value.string.ptr = address_buffer;
1721 valid_flag = genaddr.valid();
1722 // allow use of an ipx or ipxsock address
1725 if ((genaddr.get_type() == type_ipx) )
1727 *this = genaddr.cast_ipxaddress(); // copy in the Ipx address data
1729 else if ((genaddr.get_type() == type_ipxsock) )
1731 *this = genaddr.cast_ipxsockaddress(); // copy in the Ipx address data
1738 //-----[ IPX Address general = operator ]-------------------------------
1739 SnmpSyntax& IpxAddress::operator=(const SnmpSyntax &val)
1741 // protect against assignment from itself
1742 if (this == &val) return *this;
1744 valid_flag = false; // will set to TRUE if really valid
1746 switch (val.get_syntax()){
1747 case sNMP_SYNTAX_OCTETS:
1748 if (((IpxAddress &)val).smival.value.string.len == IPXLEN){
1749 MEMCPY(address_buffer, ((IpxAddress &)val).smival.value.string.ptr, IPXLEN);
1755 addr_changed = true;
1759 //--------[ assignment to another IpAddress object overloaded ]----------
1760 IpxAddress& IpxAddress::operator=(const IpxAddress &ipxaddress)
1762 if (this == &ipxaddress) return *this;// protect against assignment from self
1764 valid_flag = ipxaddress.valid_flag;
1766 MEMCPY(address_buffer, ipxaddress.address_buffer, IPXLEN);
1767 addr_changed = true;
1772 //-----[ IPX Address parse Address ]-----------------------------------
1773 // Convert a string to a ten byte ipx address
1774 // On success sets validity TRUE or FALSE
1776 // IPX address format
1778 // NETWORK ID| MAC ADDRESS
1779 // 01 02 03 04|05 06 07 08 09 10
1780 // XX XX XX XX|XX XX XX XX XX XX
1782 // Valid input format
1784 // XXXXXXXX.XXXXXXXXXXXX
1785 // Total length must be 21
1786 // Must have a separator in it
1787 // First string length must be 8
1788 // Second string length must be 12
1789 // Each char must take on value 0-F
1792 // Input formats recognized
1794 // XXXXXXXX.XXXXXXXXXXXX
1795 // XXXXXXXX:XXXXXXXXXXXX
1796 // XXXXXXXX-XXXXXXXXXXXX
1797 // XXXXXXXX.XXXXXX-XXXXXX
1798 // XXXXXXXX:XXXXXX-XXXXXX
1799 // XXXXXXXX-XXXXXX-XXXXXX
1800 bool IpxAddress::parse_address(const char *inaddr)
1802 char unsigned *str1,*str2;
1803 char temp[30]; // don't destroy original
1807 // save the orginal source
1808 if (!inaddr || (strlen(inaddr) >= sizeof(temp))) return FALSE;
1809 strcpy(temp, inaddr);
1810 trim_white_space(temp);
1811 tmplen = strlen(temp);
1813 // bad total length check
1814 // 123456789012345678901
1815 // XXXXXXXX-XXXXXXXXXXXX 21 len
1817 // XXXXXXXX-XXXXXX-XXXXXX 22 len
1818 // need at least 21 chars and no more than 22
1819 if ((tmplen <21) || (tmplen >22))
1822 // convert the string to all lower case
1823 // this allows hex values to be in upper or lower
1824 for (z=0;z< tmplen;z++)
1825 temp[z] = tolower(temp[z]);
1827 // check for separated nodeid
1828 // if found remove it
1829 if (temp[15] == '-')
1831 for(z=16;z<tmplen;z++)
1832 temp[z-1] = temp[z];
1836 // no dot or colon separator check
1837 separator = temp[8];
1838 if ((separator != ':') &&
1839 (separator != '.') &&
1840 (separator != '-') &&
1844 // separate the strings
1845 str1 = (unsigned char *) temp;
1846 while(*str1 != separator) str1++;
1849 str1= (unsigned char *) temp;
1851 // check len of the network portion
1852 if (strlen((char *) str1) != 8) return FALSE;
1854 // check len of mac portion
1855 if (strlen((char *) str2) != 12) return FALSE;
1857 // ok we like then lens, make sure that all chars are 0-f
1858 // check out the net id
1861 if (((*tmp >= '0') && (*tmp <= '9'))|| // good 0-9
1862 ((*tmp >= 'a') && (*tmp <= 'f'))) // or a-f
1867 // check out the MAC address
1870 if (((*tmp >= '0') && (*tmp <= '9'))|| // good 0-9
1871 ((*tmp >= 'a') && (*tmp <= 'f'))) // or a-f
1876 // convert to target string
1880 if ((*tmp >= '0') && (*tmp <= '9'))
1881 *tmp = *tmp - (char unsigned )'0';
1883 *tmp = *tmp - (char unsigned) 'a' + (char unsigned) 10;
1887 // network id portion
1888 address_buffer[0] = (str1[0]*16) + str1[1];
1889 address_buffer[1] = (str1[2]*16) + str1[3];
1890 address_buffer[2] = (str1[4]*16) + str1[5];
1891 address_buffer[3] = (str1[6]*16) + str1[7];
1896 if ((*tmp >= '0') && (*tmp <= '9'))
1897 *tmp = *tmp - (char unsigned) '0';
1899 *tmp = *tmp - (char unsigned) 'a'+ (char unsigned) 10;
1903 address_buffer[4] = (str2[0]*16) + str2[1];
1904 address_buffer[5] = (str2[2]*16) + str2[3];
1905 address_buffer[6] = (str2[4]*16) + str2[5];
1906 address_buffer[7] = (str2[6]*16) + str2[7];
1907 address_buffer[8] = (str2[8]*16) + str2[9];
1908 address_buffer[9] = (str2[10]*16) + str2[11];
1913 //----[ IPX address format output ]-------------------------------------
1914 void IpxAddress::format_output() const
1917 sprintf((char *) output_buffer,
1918 "%02x%02x%02x%02x%c%02x%02x%02x%02x%02x%02x",
1919 address_buffer[0],address_buffer[1],
1920 address_buffer[2],address_buffer[3],'-',
1921 address_buffer[4],address_buffer[5],
1922 address_buffer[6],address_buffer[7],
1923 address_buffer[8],address_buffer[9]);
1925 *(char*)output_buffer = 0;
1926 IpxAddress *nc_this = PP_CONST_CAST(IpxAddress*, this);
1927 nc_this->addr_changed = false;
1932 // get the host id portion of an ipx address
1933 int IpxAddress::get_hostid(MacAddress& mac) const
1938 sprintf(buffer,"%02x:%02x:%02x:%02x:%02x:%02x", address_buffer[4],
1939 address_buffer[5], address_buffer[6], address_buffer[7],
1940 address_buffer[8], address_buffer[9]);
1941 MacAddress temp(buffer);
1948 #endif // function that needs _MAC_ADDRESS
1950 //========================================================================
1951 //======== IpxSockAddress Implementation =================================
1952 //========================================================================
1954 //----------[ constructor no args ]--------------------------------------
1955 IpxSockAddress::IpxSockAddress() : IpxAddress()
1957 // always initialize SMI info
1958 smival.syntax = sNMP_SYNTAX_OCTETS;
1959 smival.value.string.len = IPXSOCKLEN;
1960 smival.value.string.ptr = address_buffer;
1963 addr_changed = true;
1966 //-----------[ construct an IpxSockAddress with another IpxSockAddress]----
1967 IpxSockAddress::IpxSockAddress(const IpxSockAddress &ipxaddr)
1968 : IpxAddress(ipxaddr)
1970 // always initialize SMI info
1971 smival.syntax = sNMP_SYNTAX_OCTETS;
1972 smival.value.string.len = IPXSOCKLEN;
1973 smival.value.string.ptr = address_buffer;
1975 // copy the socket value
1976 set_socket(ipxaddr.get_socket());
1977 addr_changed = true;
1981 //---------------[ construct a IpxSockAddress from a string ]--------------
1982 IpxSockAddress::IpxSockAddress(const char *inaddr):IpxAddress()
1984 // always initialize SMI info
1985 smival.syntax = sNMP_SYNTAX_OCTETS;
1986 smival.value.string.len = IPXSOCKLEN;
1987 smival.value.string.ptr = address_buffer;
1989 valid_flag = parse_address(inaddr);
1990 addr_changed = true;
1994 //---------------[ construct a IpxSockAddress from a GenAddress ]----------
1995 IpxSockAddress::IpxSockAddress(const GenAddress &genaddr):IpxAddress()
1997 // always initialize SMI info
1998 smival.syntax = sNMP_SYNTAX_OCTETS;
1999 smival.value.string.len = IPXSOCKLEN;
2000 smival.value.string.ptr = address_buffer;
2003 unsigned short socketid = 0;
2004 // allow use of an ipx or ipxsock address
2005 if ((genaddr.get_type() == type_ipx) )
2007 valid_flag = genaddr.valid();
2010 // copy in the Ipx address data
2011 IpxAddress temp_ipx((const char *) genaddr);
2015 else if ((genaddr.get_type() == type_ipxsock) )
2017 valid_flag = genaddr.valid();
2020 // copy in the Ipx address data
2021 IpxSockAddress temp_ipxsock((const char *) genaddr);
2022 *this = temp_ipxsock;
2023 // socketid info since are making an IpxSockAddress
2024 socketid = temp_ipxsock.get_socket();
2027 set_socket(socketid);
2028 addr_changed = true;
2031 //------------[ construct an IpxSockAddress from a IpxAddress ]--------------
2032 IpxSockAddress::IpxSockAddress(const IpxAddress &ipxaddr):IpxAddress(ipxaddr)
2034 // always initialize SMI info
2035 smival.syntax = sNMP_SYNTAX_OCTETS;
2036 smival.value.string.len = IPXSOCKLEN;
2037 smival.value.string.ptr = address_buffer;
2040 addr_changed = true;
2043 // copy an instance of this Value
2044 SnmpSyntax& IpxSockAddress::operator=(const SnmpSyntax &val)
2046 if (this == &val) return *this; // protect against assignment from itself
2048 valid_flag = false; // will set to TRUE if really valid
2050 switch (val.get_syntax()){
2051 case sNMP_SYNTAX_OCTETS:
2053 // See if it is of the Ipx address family
2054 // This handles IpxSockAddress == IpxAddress
2055 IpxSockAddress temp_ipx(val.get_printable());
2056 if (temp_ipx.valid()){
2057 *this = temp_ipx; // ipxsock = ipxsock
2059 // See if it is an OctetStr of appropriate length
2060 else if (((IpxSockAddress &)val).smival.value.string.len == IPXSOCKLEN){
2061 MEMCPY(address_buffer,
2062 ((IpxSockAddress &)val).smival.value.string.ptr,
2070 addr_changed = true;
2074 // assignment to another IpAddress object overloaded
2075 IpxSockAddress& IpxSockAddress::operator=(const IpxSockAddress &ipxaddr)
2077 if (this == &ipxaddr) return *this; // protect against assignment from itself
2079 (IpxAddress&)*this = ipxaddr; // use ancestor assignment for ipx addr
2080 set_socket(ipxaddr.get_socket()); // copy socket value
2081 addr_changed = true;
2085 //----[ IPX address format output ]-------------------------------------
2086 void IpxSockAddress::format_output() const
2088 IpxAddress::format_output(); // allow ancestors to format their buffers
2091 sprintf((char *) output_buffer,"%s/%d",
2092 IpxAddress::get_printable(), get_socket());
2094 *(char*)output_buffer = 0;
2095 IpxSockAddress *nc_this = PP_CONST_CAST(IpxSockAddress*, this);
2096 nc_this->addr_changed = false;
2099 //-----[ IP Address parse Address ]---------------------------------
2100 bool IpxSockAddress::parse_address(const char *inaddr)
2102 char buffer[MAX_FRIENDLY_NAME];
2103 unsigned short socketid=0;
2105 if (inaddr && (strlen(inaddr)< MAX_FRIENDLY_NAME))
2106 strcpy(buffer, inaddr);
2112 // look for port info @ the end of the string
2113 // port can be delineated by a ':' or a '/'
2114 // if neither are present then just treat it
2115 // like a normal IpAddress
2117 tmp = strstr(buffer,"/");
2121 *tmp=0; // new null terminator
2123 socketid = atoi(tmp);
2125 set_socket(socketid);
2126 return IpxAddress::parse_address(buffer);
2131 //-------------[ set the socket number ]----------------------------------
2132 void IpxSockAddress::set_socket(const unsigned short s)
2134 unsigned short sock_nbo = htons(s);
2135 MEMCPY(&address_buffer[IPXLEN], &sock_nbo, 2);
2136 addr_changed = true;
2139 //--------------[ get the socket number ]---------------------------------
2140 unsigned short IpxSockAddress::get_socket() const
2144 unsigned short sock_nbo;
2145 MEMCPY(&sock_nbo, &address_buffer[IPXLEN], 2);
2146 return ntohs(sock_nbo);
2148 return 0; // don't use uninitialized memory
2150 #endif // _IPX_ADDRESS
2153 //========================================================================
2154 //======== MACAddress Implementation =====================================
2155 //========================================================================
2157 //--------[ constructor, no arguments ]-----------------------------------
2158 MacAddress::MacAddress() : Address()
2160 // always initialize SMI info
2161 smival.syntax = sNMP_SYNTAX_OCTETS;
2162 smival.value.string.len = MACLEN;
2163 smival.value.string.ptr = address_buffer;
2166 addr_changed = true;
2169 //-----[ MAC Address copy constructor ]---------------------------------
2170 MacAddress::MacAddress(const MacAddress &macaddr)
2172 // always initialize SMI info
2173 smival.syntax = sNMP_SYNTAX_OCTETS;
2174 smival.value.string.len = MACLEN;
2175 smival.value.string.ptr = address_buffer;
2177 valid_flag = macaddr.valid_flag;
2179 MEMCPY(address_buffer, macaddr.address_buffer, MACLEN);
2180 addr_changed = true;
2183 //---------[ constructor with a string argument ]-------------------------
2184 MacAddress::MacAddress(const char *inaddr):Address()
2186 // always initialize SMI info
2187 smival.syntax = sNMP_SYNTAX_OCTETS;
2188 smival.value.string.len = MACLEN;
2189 smival.value.string.ptr = address_buffer;
2191 valid_flag = parse_address(inaddr);
2192 addr_changed = true;
2195 //-----[ construct a MacAddress from a GenAddress ]------------------------
2196 MacAddress::MacAddress(const GenAddress &genaddr)
2198 // always initialize SMI info
2199 smival.syntax = sNMP_SYNTAX_OCTETS;
2200 smival.value.string.len = MACLEN;
2201 smival.value.string.ptr = address_buffer;
2204 // allow use of mac address
2205 if (genaddr.get_type() == type_mac)
2207 valid_flag = genaddr.valid();
2210 // copy in the Mac address data
2211 *this = genaddr.cast_macaddress();
2214 addr_changed = true;
2217 //------[ assignment to another ipaddress object overloaded ]--------------
2218 MacAddress& MacAddress::operator=(const MacAddress &macaddress)
2220 if (this == &macaddress) return *this;// protect against assignment from self
2222 valid_flag = macaddress.valid_flag;
2224 MEMCPY(address_buffer, macaddress.address_buffer, MACLEN);
2225 addr_changed = true;
2231 //-----[ MAC Address general = operator ]---------------------------------
2232 SnmpSyntax& MacAddress::operator=(const SnmpSyntax &val)
2234 if (this == &val) return *this; // protect against assignment from itself
2236 valid_flag = false; // will set to TRUE if really valid
2239 switch (val.get_syntax())
2241 case sNMP_SYNTAX_OCTETS:
2242 if (((MacAddress &)val).smival.value.string.len == MACLEN)
2244 MEMCPY(address_buffer, ((MacAddress &)val).smival.value.string.ptr,
2251 addr_changed = true;
2255 //-----[ MAC Address parse Address ]--------------------------------------
2256 // Convert a string to a six byte MAC address
2257 // On success sets validity TRUE or FALSE
2259 // MAC address format
2262 // 01 02 03 04 05 06
2263 // XX:XX:XX:XX:XX:XX
2264 // Valid input format
2267 // Total length must be 17
2268 // Each char must take on value 0-F
2271 bool MacAddress::parse_address(const char *inaddr)
2273 char temp[30]; // don't destroy original
2277 // save the orginal source
2278 if (!inaddr || (strlen(inaddr) >= sizeof(temp))) return FALSE;
2279 strcpy(temp, inaddr);
2280 trim_white_space(temp);
2282 // bad total length check
2283 if (strlen(temp) != 17)
2287 if ((temp[2] != ':')||(temp[5] != ':')||(temp[8]!=':')||(temp[11]!=':')||(temp[14] !=':'))
2290 // strip off the colons
2291 tmp = (unsigned char *) temp;
2305 for(z=0;z<strlen(temp);z++)
2306 temp[z] = tolower(temp[z]);
2309 // check out the MAC address
2310 tmp = (unsigned char *) temp;
2312 if (((*tmp >= '0') && (*tmp <= '9'))|| // good 0-9
2313 ((*tmp >= 'a') && (*tmp <= 'f'))) // or a-f
2318 // convert to target string
2319 tmp = (unsigned char *) temp;
2322 if ((*tmp >= '0') && (*tmp <= '9'))
2323 *tmp = *tmp - (char unsigned )'0';
2325 *tmp = *tmp - (char unsigned) 'a' + (char unsigned) 10;
2329 address_buffer[0] = (temp[0]*16) + temp[1];
2330 address_buffer[1] = (temp[2]*16) + temp[3];
2331 address_buffer[2] = (temp[4]*16) + temp[5];
2332 address_buffer[3] = (temp[6]*16) + temp[7];
2333 address_buffer[4] = (temp[8]*16) + temp[9];
2334 address_buffer[5] = (temp[10]*16) + temp[11];
2339 //----[ MAC address format output ]---------------------------------
2340 void MacAddress::format_output() const
2343 sprintf((char*)output_buffer,"%02x:%02x:%02x:%02x:%02x:%02x",
2344 address_buffer[0], address_buffer[1], address_buffer[2],
2345 address_buffer[3], address_buffer[4], address_buffer[5]);
2347 *(char*)output_buffer = 0;
2348 MacAddress *nc_this = PP_CONST_CAST(MacAddress*, this);
2349 nc_this->addr_changed = false;
2352 unsigned int MacAddress::hashFunction() const
2354 return ((((address_buffer[0] << 8) + address_buffer[1]) * HASH0)
2355 + (((address_buffer[2] << 8) + address_buffer[3]) * HASH1)
2356 + (((address_buffer[4] << 8) + address_buffer[5]) * HASH2));
2358 #endif // _MAC_ADDRESS
2360 //========================================================================
2361 //========== Generic Address Implementation ==============================
2362 //========================================================================
2364 //-----------[ constructor, no arguments ]--------------------------------
2365 GenAddress::GenAddress() : Address()
2369 // initialize SMI info
2370 // BOK: this is generally not used for GenAddress,
2371 // but we need this to be a replica of the real address'
2372 // smival info so that operator=SnmpSyntax will work.
2373 smival.syntax = sNMP_SYNTAX_NULL; // to be overridden
2374 smival.value.string.len = 0; // to be overridden
2375 smival.value.string.ptr = address_buffer; // constant
2379 output_buffer[0] = 0;
2382 //-----------[ constructor with a string argument ]----------------------
2383 GenAddress::GenAddress(const char *addr,
2384 const Address::addr_type use_type)
2388 // initialize SMI info
2389 // BOK: smival is generally not used for GenAddress, but
2390 // we need this to be a replica of the real address'
2391 // smival info so that <class>::operator=SnmpSyntax
2393 smival.syntax = sNMP_SYNTAX_NULL; // to be overridden
2394 smival.value.string.len = 0; // to be overridden
2395 smival.value.string.ptr = address_buffer; // constant
2398 parse_address(addr, use_type);
2400 // Copy real address smival info into GenAddr smival
2401 // BOK: smival is generally not used for GenAddress, but
2402 // we need this to be a replica of the real address'
2403 // smival info so that <class>::operator=SnmpSyntax
2406 smival.syntax = ((GenAddress *)address)->smival.syntax;
2407 smival.value.string.len =
2408 ((GenAddress *)address)->smival.value.string.len;
2409 memcpy(smival.value.string.ptr,
2410 ((GenAddress *)address)->smival.value.string.ptr,
2411 (size_t)smival.value.string.len);
2413 output_buffer[0] = 0;
2416 //-----------[ constructor with an Address argument ]--------------------
2417 GenAddress::GenAddress(const Address &addr)
2421 output_buffer[0] = 0;
2422 // initialize SMI info
2423 // BOK: this is generally not used for GenAddress,
2424 // but we need this to be a replica of the real address'
2425 // smival info so that operator=SnmpSyntax will work.
2426 smival.syntax = sNMP_SYNTAX_NULL; // to be overridden
2427 smival.value.string.len = 0; // to be overridden
2428 smival.value.string.ptr = address_buffer; // constant
2431 // make sure that the object is valid
2432 if (!addr.valid()) {
2437 // addr can be a GenAddress object and calling clone() on that is bad...
2438 if (addr.is_gen_address())
2439 address = (Address *)(((const GenAddress&)addr).address->clone());
2441 address = (Address*)addr.clone();
2444 valid_flag = address->valid();
2446 // Copy real address smival info into GenAddr smival
2447 // BOK: smival is generally not used for GenAddress, but
2448 // we need this to be a replica of the real address'
2449 // smival info so that <class>::operator=SnmpSyntax
2453 smival.syntax = address->get_syntax();
2454 smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
2455 memcpy(smival.value.string.ptr,
2456 ((GenAddress *)address)->smival.value.string.ptr,
2457 (size_t)smival.value.string.len);
2461 //-----------------[ constructor with another GenAddress object ]-------------
2462 GenAddress::GenAddress(const GenAddress &addr)
2466 output_buffer[0] = 0;
2467 // initialize SMI info
2468 // BOK: this is generally not used for GenAddress,
2469 // but we need this to be a replica of the real address'
2470 // smival info so that operator=SnmpSyntax will work.
2471 smival.syntax = sNMP_SYNTAX_OCTETS;
2472 smival.value.string.len = 0;
2473 smival.value.string.ptr = address_buffer;
2476 // make sure that the object is valid
2477 if (!addr.valid_flag)
2483 address = (Address *)addr.address->clone();
2485 valid_flag = address->valid();
2487 // Copy real address smival info into GenAddr smival
2488 // BOK: smival is generally not used for GenAddress, but
2489 // we need this to be a replica of the real address'
2490 // smival info so that <class>::operator=SnmpSyntax
2494 smival.syntax = ((GenAddress *)address)->smival.syntax;
2495 smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
2496 memcpy(smival.value.string.ptr,
2497 ((GenAddress *)address)->smival.value.string.ptr,
2498 (size_t)smival.value.string.len);
2502 //------[ assignment GenAddress = GenAddress ]-----------------------------
2503 GenAddress& GenAddress::operator=(const GenAddress &addr)
2507 if (this == &addr) return *this; // protect against assignment from itself
2516 address = (Address *)(addr.address->clone());
2518 valid_flag = address->valid();
2520 // Copy real address smival info into GenAddr smival
2521 // BOK: smival is generally not used for GenAddress, but
2522 // we need this to be a replica of the real address'
2523 // smival info so that <class>::operator=SnmpSyntax
2527 smival.syntax = ((GenAddress *)address)->smival.syntax;
2528 smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
2529 memcpy(smival.value.string.ptr,
2530 ((GenAddress *)address)->smival.value.string.ptr,
2531 (size_t)smival.value.string.len);
2537 //------[ assignment GenAddress = Address ]--------------------------------
2538 GenAddress& GenAddress::operator=(const Address &addr)
2542 if (this == &addr) return *this; // protect against assignment from itself
2551 // addr can be a GenAddress object and calling clone() on that is bad...
2552 if (addr.is_gen_address())
2553 address = (Address *)(((const GenAddress&)addr).address->clone());
2555 address = (Address*)addr.clone();
2558 valid_flag = address->valid();
2560 // Copy real address smival info into GenAddr smival
2561 // BOK: smival is generally not used for GenAddress, but
2562 // we need this to be a replica of the real address'
2563 // smival info so that <class>::operator=SnmpSyntax
2567 smival.syntax = ((GenAddress *)address)->smival.syntax;
2568 smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
2569 memcpy(smival.value.string.ptr,
2570 ((GenAddress *)address)->smival.value.string.ptr,
2571 (size_t)smival.value.string.len);
2578 //------[ assignment GenAddress = any SnmpSyntax ]-----------------------
2579 SnmpSyntax& GenAddress::operator=(const SnmpSyntax &val)
2583 if (this == &val) return *this; // protect against assignment from itself
2585 valid_flag = false; // will get set to TRUE if really valid
2594 switch (val.get_syntax() )
2596 //-----[ ip address case ]-------------
2597 // BOK: this case shouldn't be needed since there is an explicit
2598 // GenAddr=Address assignment that will override this assignment.
2599 // Left here for posterity.
2600 case sNMP_SYNTAX_IPADDR:
2602 address = new IpAddress(val.get_printable());
2604 valid_flag = address->valid();
2608 //-----[ udp address case ]------------
2609 //-----[ ipx address case ]------------
2610 //-----[ mac address case ]------------
2611 // BOK: This is here only to support GenAddr = primitive OctetStr.
2612 // The explicit GenAddr=Address assignment will handle the cases
2613 // GenAddr = [UdpAdd|IpxAddr|IpxSock|MacAddr].
2614 // Note, using the heuristic of octet str len to determine type of
2615 // address to create is not accurate when address lengths are equal
2616 // (e.g., UDPIPLEN == MACLEN). It gets worse if we add AppleTalk or
2617 // OSI which use variable length addresses!
2618 case sNMP_SYNTAX_OCTETS:
2620 unsigned long val_len;
2621 val_len = ((GenAddress &)val).smival.value.string.len;
2623 if ((val_len == UDPIPLEN) || IS_UDPIP6LEN(val_len))
2624 address = new UdpAddress;
2625 else if ((val_len == IPLEN) || IS_IP6LEN(val_len))
2626 address = new IpAddress;
2628 else if (val_len == IPXLEN)
2629 address = new IpxAddress;
2630 else if (val_len == IPXSOCKLEN)
2631 address = new IpxSockAddress;
2634 else if (val_len == MACLEN)
2635 address = new MacAddress;
2641 valid_flag = address->valid();
2648 // Copy real address smival info into GenAddr smival
2649 // BOK: smival is generally not used for GenAddress, but
2650 // we need this to be a replica of the real address'
2651 // smival info so that <class>::operator=SnmpSyntax
2655 smival.syntax = ((GenAddress *)address)->smival.syntax;
2656 smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
2657 memcpy(smival.value.string.ptr,
2658 ((GenAddress *)address)->smival.value.string.ptr,
2659 (size_t)smival.value.string.len);
2666 // redefined parse address for macs
2667 bool GenAddress::parse_address(const char *addr,
2668 const Address::addr_type use_type)
2672 if (address) delete address;
2674 // try to create each of the addresses until the correct one
2677 //BOK: Need to try IPX Sock and IPX before UDP since on Win32,
2678 // gethostbyname() seems to think the ipx network number
2679 // portion is a valid ipaddress string... stupid WinSOCK!
2682 if ((use_type == Address::type_invalid) ||
2683 (use_type == Address::type_ipxsock))
2686 address = new IpxSockAddress(addr);
2687 valid_flag = address->valid();
2688 if (valid_flag && ((IpxSockAddress*)address)->get_socket())
2689 return TRUE; // ok its an ipxsock address
2691 delete address; // otherwise delete it and try another
2694 if ((use_type == Address::type_invalid) ||
2695 (use_type == Address::type_ipx))
2698 address = new IpxAddress(addr);
2699 valid_flag = address->valid();
2701 return TRUE; // ok its an ipx address
2703 delete address; // otherwise delete it and try another
2705 #endif // _IPX_ADDRESS
2707 //TM: Must try the derived classes first...one pitfall of the
2708 //following solution is if someone creates with a port/socket of 0 the
2709 //class will get demoted to ip/ipx. The only proper way to do this is
2710 //to parse the strings ourselves.
2712 if ((use_type == Address::type_invalid) ||
2713 (use_type == Address::type_udp))
2716 address = new UdpAddress(addr);
2717 valid_flag = address->valid();
2718 if (valid_flag && ((UdpAddress*)address)->get_port())
2719 return TRUE; // ok its a udp address
2721 delete address; // otherwise delete it and try another
2724 if ((use_type == Address::type_invalid) ||
2725 (use_type == Address::type_ip))
2728 address = new IpAddress(addr);
2729 valid_flag = address->valid();
2731 return TRUE; // ok its an ip address
2733 delete address; // otherwise delete it and try another
2737 if ((use_type == Address::type_invalid) ||
2738 (use_type == Address::type_mac))
2741 address = new MacAddress(addr);
2742 valid_flag = address->valid();
2744 return TRUE; // ok, its a mac
2746 delete address; // otherwise its invalid
2748 #endif // _MAC_ADDRESS
2754 #ifdef SNMP_PP_NAMESPACE
2755 }; // end of namespace Snmp_pp