address.cpp
上传用户:ets1996
上传日期:2014-09-30
资源大小:353k
文件大小:68k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  address.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8.   _##
  9.   _##  This software is based on SNMP++2.6 from Hewlett Packard:
  10.   _##  
  11.   _##    Copyright (c) 1996
  12.   _##    Hewlett-Packard Company
  13.   _##  
  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. 
  25.   _##  
  26.   _##  Stuttgart, Germany, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. /*===================================================================
  30.   Copyright (c) 1999
  31.   Hewlett-Packard Company
  32.   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  33.   Permission to use, copy, modify, distribute and/or sell this software
  34.   and/or its documentation is hereby granted without fee. User agrees
  35.   to display the above copyright notice and this license notice in all
  36.   copies of the software and any documentation of the software. User
  37.   agrees to assume all liability for the use of the software; Hewlett-Packard
  38.   makes no representations about the suitability of this software for any
  39.   purpose. It is provided "AS-IS" without warranty of any kind,either express
  40.   or implied. User hereby grants a royalty-free license to any and all
  41.   derivatives based upon this software code base.
  42.   A D D R E S S. C P P
  43.   ADDRESS CLASS IMPLEMENTATION
  44.   DESIGN + AUTHOR:  Peter E. Mellquist
  45.   DESCRIPTION:      Implementation file for Address classes.
  46.   LANGUAGE:         ANSI C++
  47. =====================================================================*/
  48. char address_cpp_version[]="@(#) SNMP++ $Id: address.cpp 277 2007-03-22 21:17:36Z katz $";
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <ctype.h>
  52. #include "snmp_pp/address.h"
  53. #include "snmp_pp/v3.h"
  54. #ifdef SNMP_PP_NAMESPACE
  55. namespace Snmp_pp {
  56. #endif
  57. /* Borlands isdigit has a bug */
  58. #ifdef __BCPLUSPLUS__
  59. #define my_isdigit(c) ((c) >= '0' && (c) <= '9')
  60. #else
  61. #define my_isdigit isdigit
  62. #endif
  63. #ifdef ADDRESS_DEBUG
  64. #define ADDRESS_TRACE debugprintf(0, "ADDRESS %p Enter %s", this, __PRETTY_FUNCTION__)
  65. #define ADDRESS_TRACE2 debugprintf(0, "ADDRESS op Enter %s", __PRETTY_FUNCTION__)
  66. #else
  67. #define ADDRESS_TRACE
  68. #define ADDRESS_TRACE2
  69. #endif
  70. #if !defined HAVE_GETHOSTBYNAME_R || !defined HAVE_GETHOSTBYADDR_R || !defined HAVE_REENTRANT_GETHOSTBYNAME || !defined HAVE_REENTRANT_GETHOSTBYADDR
  71. #ifdef _THREADS
  72. SnmpSynchronized Address::syscall_mutex;
  73. #endif
  74. #endif
  75. //=================================================================
  76. //======== Abstract Address Class Implementation ==================
  77. //=================================================================
  78. Address::Address()
  79.   : addr_changed(true), valid_flag(false)
  80. {
  81.   ADDRESS_TRACE;
  82.   memset(address_buffer, 0, sizeof(unsigned char)*ADDRBUF);
  83. }
  84. //------------[ Address::trim_white_space( char * ptr) ]------------
  85. // destructive trim white space
  86. void Address::trim_white_space(char *ptr)
  87. {
  88.   ADDRESS_TRACE;
  89.   char *tmp = ptr;                               // init
  90.   while (*tmp==' ') tmp++;                       // skip leading white space
  91.   while (*tmp && (*tmp != ' ')) *ptr++ = *tmp++; // move string to beginning
  92.   *ptr = 0;                                      // set end of string
  93. }
  94. // Reset the object
  95. void Address::clear()
  96. {
  97.   addr_changed = true;
  98.   valid_flag = false;
  99.   memset(address_buffer, 0, sizeof(unsigned char)*ADDRBUF);
  100. }
  101. //-----------------------------------------------------------------------
  102. // overloaded equivlence operator, are two addresses equal?
  103. int operator==(const Address &lhs, const Address &rhs)
  104. {
  105.   ADDRESS_TRACE2;
  106.   return (strcmp((const char*)lhs, (const char*)rhs) == 0);
  107. }
  108. //------------------------------------------------------------------
  109. // overloaded > operator, is a1 > a2
  110. int operator>(const Address &lhs, const Address &rhs)
  111. {
  112.   ADDRESS_TRACE2;
  113.   return (strcmp((const char*)lhs, (const char*)rhs) > 0);
  114. }
  115. //-----------------------------------------------------------------
  116. // overloaded < operator, is a1 < a2
  117. int operator<(const Address &lhs, const Address &rhs)
  118. {
  119.   ADDRESS_TRACE2;
  120.   return (strcmp((const char*)lhs, (const char*)rhs) < 0);
  121. }
  122. //------------------------------------------------------------------
  123. // equivlence operator overloaded, are an address and a string equal?
  124. int operator==(const Address &lhs, const char *rhs)
  125. {
  126.   ADDRESS_TRACE2;
  127.   if (!rhs && !lhs.valid())
  128.     return TRUE;
  129.   if (strcmp((const char *)lhs, rhs) == 0)
  130.     return TRUE;
  131.   return FALSE;
  132. }
  133. //------------------------------------------------------------------
  134. // overloaded > , is a > inaddr
  135. int operator>(const Address &lhs, const char *rhs)
  136. {
  137.   ADDRESS_TRACE2;
  138.   if (!rhs)
  139.     return lhs.valid();  // if lhs valid then > NULL, else invalid !> NULL
  140.   if (strcmp((const char *)lhs, rhs) > 0)
  141.     return TRUE;
  142.   return FALSE;
  143. }
  144. //------------------------------------------------------------------
  145. // overloaded >= , is a >= inaddr
  146. int operator>=(const Address &lhs, const char *rhs)
  147. {
  148.   ADDRESS_TRACE2;
  149.   if (!rhs)
  150.     return TRUE; // always >= NULL
  151.   if (strcmp((const char *)lhs, rhs) >= 0)
  152.     return TRUE;
  153.   return FALSE;
  154. }
  155. //-----------------------------------------------------------------
  156. // overloaded < , are an address and a string equal?
  157. int operator<(const Address &lhs, const char *rhs)
  158. {
  159.   ADDRESS_TRACE2;
  160.   if (!rhs)
  161.     return FALSE; // always >= NULL
  162.   if (strcmp((const char *)lhs, rhs) < 0)
  163.     return TRUE;
  164.   return FALSE;
  165. }
  166. //-----------------------------------------------------------------
  167. // overloaded <= , is a <= inaddr
  168. int operator<=(const Address &lhs, const char *rhs)
  169. {
  170.   ADDRESS_TRACE2;
  171.   if (!rhs)
  172.     return !lhs.valid(); // invalid == NULL, else valid > NULL
  173.   if (strcmp((const char *)lhs, rhs) <= 0)
  174.     return TRUE;
  175.   return FALSE;
  176. }
  177. //=====================================================================
  178. //============ IPAddress Implementation ===============================
  179. //=====================================================================
  180. //-------[ construct an IP address with no agrs ]----------------------
  181. IpAddress::IpAddress()
  182.   : Address(), iv_friendly_name_status(0), ip_version(version_ipv4)
  183. {
  184.   ADDRESS_TRACE;
  185.   // always initialize what type this object is
  186.   smival.syntax = sNMP_SYNTAX_IPADDR;
  187.   smival.value.string.len = IPLEN;
  188.   smival.value.string.ptr = address_buffer;
  189.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  190. }
  191. //-------[ construct an IP address with a string ]---------------------
  192. IpAddress::IpAddress(const char *inaddr)
  193.   : Address()
  194. {
  195.   ADDRESS_TRACE;
  196.   // always initialize what type this object is
  197.   smival.syntax = sNMP_SYNTAX_IPADDR;
  198.   smival.value.string.len = IPLEN;
  199.   smival.value.string.ptr = address_buffer;
  200.   // parse_address initializes valid, address_buffer & iv_friendly_name
  201.   valid_flag = parse_address(inaddr);
  202. }
  203. //-----[ IP Address copy constructor ]---------------------------------
  204. IpAddress::IpAddress(const IpAddress &ipaddr)
  205.   : iv_friendly_name_status(0), ip_version(ipaddr.ip_version)
  206. {
  207.   ADDRESS_TRACE;
  208.   // always initialize what type this object is
  209.   smival.syntax = sNMP_SYNTAX_IPADDR;
  210.   smival.value.string.len = ipaddr.smival.value.string.len;
  211.   smival.value.string.ptr = address_buffer;
  212.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  213.   valid_flag = ipaddr.valid_flag;
  214.   if (valid_flag)
  215.   {
  216.     // copy the address data
  217.     MEMCPY(address_buffer, ipaddr.address_buffer, smival.value.string.len);
  218.     // and the friendly name
  219.     strcpy(iv_friendly_name, ipaddr.iv_friendly_name);
  220.     if (!ipaddr.addr_changed)
  221.     {
  222.       memcpy(output_buffer, ipaddr.output_buffer,
  223.      sizeof(unsigned char) * OUTBUFF);
  224.       addr_changed = false;
  225.     }
  226.   }
  227. }
  228. //-----[ construct an IP address with a GenAddress ]---------------------
  229. IpAddress::IpAddress(const GenAddress &genaddr)
  230.   : iv_friendly_name_status(0)
  231. {
  232.   ADDRESS_TRACE;
  233.   // always initialize what type this object is
  234.   smival.syntax = sNMP_SYNTAX_IPADDR;
  235.   smival.value.string.len = IPLEN;
  236.   smival.value.string.ptr = address_buffer;
  237.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  238.   output_buffer[0]=0;
  239.   // allow use of an ip or udp genaddress
  240.   valid_flag = genaddr.valid();
  241.   if (valid_flag)
  242.   {
  243.     if (genaddr.get_type() == type_ip)
  244.     {
  245.       // copy in the IP address data
  246.       *this = genaddr.cast_ipaddress();
  247.       return;
  248.     }
  249.     else if (genaddr.get_type() == type_udp)
  250.     {
  251.       // copy in the IP address data
  252.       *this = genaddr.cast_udpaddress();
  253.       return;
  254.     }
  255.   }
  256.   valid_flag = false;
  257.   addr_changed = true;
  258. }
  259. //-----[ IP Address general = operator ]-------------------------------
  260. SnmpSyntax& IpAddress::operator=(const SnmpSyntax &val)
  261. {
  262.   ADDRESS_TRACE;
  263.   if (this == &val) return *this; // protect against assignment from itself
  264.   addr_changed = true;
  265.   valid_flag = false;        // will get set TRUE if really valid
  266.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  267.   if (val.valid())
  268.   {
  269.     switch (val.get_syntax())
  270.     {
  271.       case sNMP_SYNTAX_IPADDR:
  272.       case sNMP_SYNTAX_OCTETS:
  273.         if ((((IpAddress &)val).smival.value.string.len == IPLEN) ||
  274.     (((IpAddress &)val).smival.value.string.len == UDPIPLEN))
  275.         {
  276.           MEMCPY(address_buffer,
  277.                  ((IpAddress &)val).smival.value.string.ptr, IPLEN);
  278.   valid_flag = true;
  279.   ip_version = version_ipv4;
  280.   smival.value.string.len = IPLEN;
  281.         }
  282.         else if ((((IpAddress &)val).smival.value.string.len == IP6LEN) ||
  283.  (((IpAddress &)val).smival.value.string.len == UDPIP6LEN))
  284.         {
  285.   MEMCPY(address_buffer,
  286.  ((IpAddress &)val).smival.value.string.ptr, IP6LEN);
  287.   valid_flag = true;
  288.   ip_version = version_ipv6;
  289.   smival.value.string.len = IP6LEN;
  290.         }
  291.         break;
  292.         // NOTE: as a value add, other types could have "logical"
  293.         // mappings, i.e. integer32 and unsigned32
  294.     }
  295.   }
  296.   return *this;
  297. }
  298. //------[ assignment to another ipaddress object overloaded ]-----------------
  299. IpAddress& IpAddress::operator=(const IpAddress &ipaddr)
  300. {
  301.   ADDRESS_TRACE;
  302.   if (this == &ipaddr) return *this; // protect against assignment from itself
  303.   valid_flag = ipaddr.valid_flag;
  304.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  305.   if (valid_flag)
  306.   {
  307.     if (ipaddr.ip_version == version_ipv4)
  308.     {
  309.       MEMCPY(address_buffer, ipaddr.address_buffer, IPLEN);
  310.       ip_version = version_ipv4;
  311.       smival.value.string.len = IPLEN;
  312.     }
  313.     else
  314.     {
  315.       MEMCPY(address_buffer, ipaddr.address_buffer, IP6LEN);
  316.       ip_version = version_ipv6;
  317.       smival.value.string.len = IP6LEN;
  318.     }
  319.     strcpy(iv_friendly_name, ipaddr.iv_friendly_name);
  320.     if (ipaddr.addr_changed)
  321.       addr_changed = true;
  322.     else
  323.     {
  324.       memcpy(output_buffer, ipaddr.output_buffer,
  325.      sizeof(unsigned char) * OUTBUFF);
  326.       addr_changed = false;
  327.     }
  328.   }
  329.   else
  330.     addr_changed = true;
  331.   return *this;
  332. }
  333. IpAddress& IpAddress::operator=(const char *inaddr)
  334. {
  335.   ADDRESS_TRACE;
  336.   valid_flag = parse_address(inaddr);
  337.   addr_changed = true;
  338.   return *this;
  339. }
  340. //-------[ return the friendly name ]----------------------------------
  341. char *IpAddress::friendly_name(int &status)
  342. {
  343.   ADDRESS_TRACE;
  344.   if ((iv_friendly_name[0]==0) && (valid_flag))
  345.     this->addr_to_friendly();
  346.   status = iv_friendly_name_status;
  347.   return iv_friendly_name;
  348. }
  349. // parse a dotted string
  350. int IpAddress::parse_dotted_ipstring(const char *inaddr)
  351. {
  352.   ADDRESS_TRACE;
  353.   int token_count=0;
  354.   char temp[30];  // temp buffer for destruction
  355.   // check len, an ip can never be bigger than 15
  356.   // 123456789012345
  357.   // XXX.XXX.XXX.XXX
  358.   if (!inaddr || (strlen(inaddr) > 30)) return FALSE;
  359.   strcpy(temp, inaddr);
  360.   trim_white_space(temp);
  361.   if (strlen(temp) > 15) return FALSE;
  362.   /* Check for the following:
  363.    * - exactly three dots
  364.    * - no dot at begin or end
  365.    * - at least a digit between two dots
  366.    * - only dots and digits allowed
  367.    */
  368.   char *ptr = temp;
  369.   int dot_count = 0;
  370.   bool last_char_was_dot = true;
  371.   while (*ptr)
  372.   {
  373.     if (*ptr == '.')
  374.     {
  375.       if (last_char_was_dot) return FALSE;
  376.       ++dot_count;
  377.       last_char_was_dot = true;
  378.     }
  379.     else if (my_isdigit(*ptr))
  380.     {
  381.       last_char_was_dot = false;
  382.     }
  383.     else
  384.       return FALSE;
  385.     ++ptr;
  386.   }
  387.   if ((dot_count != 3) || (last_char_was_dot))
  388.     return FALSE;
  389.   ptr = temp;
  390.   while (*ptr)
  391.   {
  392.     unsigned long number = 0;
  393.     if (*ptr == '.') ++ptr;    // skip over the dot
  394.     // grab a digit token and convert it to a long int
  395.     int digits = 0;
  396.     while ((*ptr) && (*ptr != '.'))
  397.     {
  398.       number = (number * 10) + *(ptr++) - '0';
  399.       ++digits;
  400.     }
  401.     if (digits > 3) return FALSE;
  402.     if (number > 255) return FALSE;
  403.     // stuff the value into the array and bump the counter
  404.     address_buffer[token_count++]= (unsigned char) number;
  405.   }
  406.   ip_version = version_ipv4;
  407.   smival.value.string.len = IPLEN;
  408.   return TRUE;
  409. }
  410. #define ATOI(x)    if      ((x >= 48) && (x <= 57)) x = x-48; /* 0-9 */ 
  411.                    else if ((x >= 97) && (x <=102)) x = x-87; /* a-f */ 
  412.                    else if ((x >= 65) && (x <= 70)) x = x-55; /* A-F */ 
  413.                    else x=0
  414. // parse a coloned string
  415. int IpAddress::parse_coloned_ipstring(const char *inaddr)
  416. {
  417.   ADDRESS_TRACE;
  418.   unsigned char tmp_address_buffer[ADDRBUF];
  419.   char temp[60];  // temp buffer for destruction
  420.   // check len, an ipv6 can never be bigger than 39
  421.   // 123456789012345678901234567890123456789
  422.   // 1BCD:2BCD:3BCD:4BCD:5BCD:6BCD:7BCD:8BCD
  423.   if (!inaddr || (strlen(inaddr) > 60)) return FALSE;
  424.   strcpy(temp, inaddr);
  425.   trim_white_space(temp);
  426.   if (strlen(temp) > 39) return FALSE;
  427.   char *in_ptr = temp;
  428.   char *out_ptr = (char*)tmp_address_buffer;
  429.   char *end_first_part = NULL;
  430.   char second[39];
  431.   int second_used = FALSE;
  432.   int colon_count = 0;
  433.   int had_double_colon = FALSE;
  434.   int last_was_colon = FALSE;
  435.   int had_dot = FALSE;
  436.   int dot_count = 0;
  437.   int digit_count = 0;
  438.   char digits[4];
  439.   char last_deliminiter = 0;
  440.   while (*in_ptr != 0)
  441.   {
  442.     if (*in_ptr == '.')
  443.     {
  444.       last_deliminiter = *in_ptr;
  445.       had_dot = TRUE;
  446.       dot_count++;
  447.       if (dot_count > 3)
  448.         return FALSE;
  449.       if ((digit_count > 3) || (digit_count < 1))
  450.         return FALSE;
  451.       for (int i=0; i<digit_count; i++)
  452.         if (!my_isdigit(digits[i]))
  453.           return FALSE;
  454.       digits[digit_count] = 0;
  455.       int value = atoi(digits);
  456.       if ((value > 0) && (value <= 255))
  457.         *out_ptr++ = (unsigned char) value;
  458.       else
  459.       {
  460.         if (strcmp(digits, "0") == 0)
  461.           *out_ptr++ = (unsigned char) 0;
  462.         else
  463.           return FALSE;
  464.       }
  465.       digit_count = 0;
  466.     }
  467.     else if (*in_ptr == ':')
  468.     {
  469.       last_deliminiter = *in_ptr;
  470.       if (had_dot)
  471.         return FALSE; // don't allow : after a dot
  472.       if (digit_count)
  473.       {
  474.         // move digits to right
  475. {
  476.           for (int i=0; i<digit_count; i++)
  477.           {
  478.             ATOI(digits[digit_count - 1 - i]);
  479.             digits[3-i] = digits[digit_count - 1 - i];
  480.           }
  481. }
  482. {
  483.           for (int i=0; i<4-digit_count; i++)
  484.           digits[i] = 0;
  485. }
  486. {
  487.   // pack two digits into one byte
  488.   for (int i=0; i < 4; i += 2)
  489.           {
  490.     unsigned char c = digits[i];
  491.     unsigned char d = digits[i+1];
  492.     *out_ptr++ = (c*16 + d);
  493.   }
  494. }
  495.         digit_count = 0;
  496.       }
  497.       colon_count++;
  498.       if (last_was_colon)
  499.       {
  500.         if (had_double_colon)
  501.           return FALSE;
  502.         end_first_part = out_ptr;
  503.         out_ptr = second;
  504.         second_used = TRUE;
  505.         had_double_colon = TRUE;
  506.       }
  507.       else
  508.       {
  509.         last_was_colon = TRUE;
  510.       }
  511.     }
  512.     else
  513.     {
  514.       if (digit_count >= 4)
  515.         return FALSE;
  516.       if (!isxdigit(*in_ptr))
  517.         return FALSE;
  518.       digits[digit_count] = tolower(*in_ptr);
  519.       digit_count++;
  520.       if (digit_count > 4)
  521.         return FALSE;
  522.       last_was_colon = 0;
  523.     }
  524.     in_ptr++;
  525.   }
  526.   // put last bytes from digits into buffer
  527.   if (digit_count)
  528.   {
  529.     if (last_deliminiter == ':')
  530.     {
  531.       {
  532. // move digits to right
  533. for (int i=0; i<digit_count; i++)
  534. {
  535.           ATOI(digits[digit_count - 1 - i]);
  536.           digits[3-i] = digits[digit_count - 1 - i];
  537.         }
  538.       }
  539.       {
  540.         for (int i=0; i<4-digit_count; i++)
  541.           digits[i] = 0;
  542.       }
  543.       {
  544.         // pack two digits into one byte
  545.         for (int i=0; i < 4; i += 2)
  546.         {
  547.           unsigned char c = digits[i];
  548.           unsigned char d = digits[i+1];
  549.           *out_ptr++ = (c*16 + d);
  550.         }
  551.       }
  552.       digit_count = 0;
  553.     }
  554.     else if (last_deliminiter == '.')
  555.     {
  556.       if ((digit_count > 3) || (digit_count < 1))
  557.         return FALSE;
  558.       for (int i=0; i<digit_count; i++)
  559.         if (!my_isdigit(digits[i]))
  560.           return FALSE;
  561.       digits[digit_count] = 0;
  562.       int value = atoi(digits);
  563.       if ((value > 0) && (value <= 255))
  564.         *out_ptr++ = (unsigned char) value;
  565.       else
  566.       {
  567.         if (strcmp(digits, "0") == 0)
  568.           *out_ptr++ = (unsigned char) 0;
  569.         else
  570.           return FALSE;
  571.       }
  572.       digit_count = 0;
  573.     }
  574.     else
  575.       return FALSE;
  576.   }
  577.   // must have between two and seven colons
  578.   if ((colon_count > 7) || (colon_count < 2))
  579.     return FALSE;
  580.   // if there was a dot there must be three of them
  581.   if ((dot_count > 0) && (dot_count != 3))
  582.     return FALSE;
  583.   if (second_used)
  584.   {
  585.     int len_first  = SAFE_INT_CAST(end_first_part - (char*)tmp_address_buffer);
  586.     int len_second = SAFE_INT_CAST(out_ptr - second);
  587.     int i=0;
  588.     for (i=0; i<IP6LEN-(len_first + len_second); i++)
  589.       *end_first_part++ = 0;
  590.     for (i=0; i<len_second; i++)
  591.       *end_first_part++ = second[i];
  592.   }
  593.   if (!end_first_part)
  594.     end_first_part = out_ptr;
  595.   // check for short address
  596.   if (end_first_part - (char*)tmp_address_buffer != IP6LEN)
  597.     return FALSE;
  598.   ip_version = version_ipv6;
  599.   smival.value.string.len = IP6LEN;
  600.   memcpy(address_buffer, tmp_address_buffer, ADDRBUF);
  601.   return TRUE;
  602. }
  603. #undef ATOI
  604. //-----[ IP Address parse Address ]---------------------------------
  605. bool IpAddress::parse_address(const char *inaddr)
  606. {
  607.   ADDRESS_TRACE;
  608. #if !defined HAVE_GETHOSTBYNAME_R && !defined HAVE_REENTRANT_GETHOSTBYNAME
  609. #ifdef _THREADS
  610.   SnmpSynchronize s(syscall_mutex);
  611. #endif
  612. #endif
  613.   addr_changed = true;
  614.   // parse the input char array fill up internal buffer with four ip
  615.   // bytes set and return validity flag
  616.   char ds[48];
  617.   // intialize the friendly_name member variable
  618.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  619.   iv_friendly_name_status = 0;
  620.   // is this a dotted IP notation string or a friendly name
  621.   if (parse_dotted_ipstring(inaddr))
  622.   {
  623.     // since this is a valid dotted string don't do any DNS
  624.     return TRUE;
  625.   }
  626.   else if (parse_coloned_ipstring(inaddr))
  627.   {
  628.     // since this is a valid ipv6 string don't do any DNS
  629.     return TRUE;
  630.   }
  631.   else // not a dotted string, try to resolve it via DNS
  632.   {
  633. #if defined (CPU) && CPU == PPC603
  634.   int lookupResult = hostGetByName(inaddr);
  635.   if (lookupResult == ERROR)
  636.   {
  637.       iv_friendly_name_status = lookupResult;
  638.       return FALSE;
  639.   }
  640. // now lets check out the dotted string
  641.   strcpy(ds,inet_ntoa(lookupResult));
  642.   if (!parse_dotted_ipstring(ds))
  643.      return FALSE;
  644. // save the friendly name
  645.   strcpy(iv_friendly_name, inaddr);
  646.   return TRUE;
  647. #else
  648.   hostent *lookupResult = 0;
  649. #ifdef HAVE_GETHOSTBYNAME_R
  650.     char buf[2048]; // TODO: Too big buffer?
  651.     int herrno = 0;
  652.     hostent lookup_buf;
  653. #if defined(__sun) || defined (__QNX_NEUTRINO)
  654.     lookupResult = gethostbyname_r(inaddr, &lookup_buf, buf, 2048, &herrno);
  655. #else    
  656.     gethostbyname_r(inaddr, &lookup_buf, buf, 2048, &lookupResult, &herrno);
  657. #endif
  658. #ifdef SNMP_PP_IPv6
  659.     if (!lookupResult)
  660.     {
  661. #ifdef __sun
  662.       lookupResult = gethostbyname_r(inaddr, AF_INET6, &lookup_buf, buf, 2048,
  663.                                      &lookupResult, &herrno);
  664. #else        
  665.       gethostbyname2_r(inaddr, AF_INET6, &lookup_buf, buf, 2048,
  666.                         &lookupResult, &herrno);
  667. #endif
  668.     }
  669. #endif // SNMP_PP_IPv6
  670. #else // not HAVE_GETHOSTBYNAME_R
  671.     lookupResult = gethostbyname(inaddr);
  672. #ifdef SNMP_PP_IPv6
  673.     if (!lookupResult)
  674.     {
  675. #ifdef HAVE_GETHOSTBYNAME2
  676.       lookupResult = gethostbyname2(inaddr, AF_INET6);
  677. #else
  678.       lookupResult = gethostbyname(inaddr);
  679. #endif // HAVE_GETHOSTBYNAME2
  680.     }
  681. #endif // SNMP_PP_IPv6
  682. #endif // HAVE_GETHOSTBYNAME_R
  683.     if (lookupResult)
  684.     {
  685. #ifdef SNMP_PP_IPv6
  686.       if (lookupResult->h_length == sizeof(in6_addr))
  687.       {
  688.         in6_addr ipAddr;
  689.         memcpy((void *) &ipAddr, (void *) lookupResult->h_addr,
  690.                sizeof(in6_addr));
  691.         // now lets check out the coloned string
  692.         if (!inet_ntop(AF_INET6, &ipAddr, ds, 48))
  693.           return FALSE;
  694.         debugprintf(4, "from inet_ntop: %s", ds);
  695.         if (!parse_coloned_ipstring(ds))
  696.           return FALSE;
  697.         // save the friendly name
  698.         strcpy(iv_friendly_name, inaddr);
  699.         
  700.         return TRUE;
  701.       }
  702. #endif // SNMP_PP_IPv6
  703.       if (lookupResult->h_length == sizeof(in_addr))
  704.       {
  705.         in_addr ipAddr;
  706.         memcpy((void *) &ipAddr, (void *) lookupResult->h_addr,
  707.                sizeof(in_addr));
  708.         // now lets check out the dotted string
  709.         strcpy(ds,inet_ntoa(ipAddr));
  710.         if (!parse_dotted_ipstring(ds))
  711.           return FALSE;
  712.         // save the friendly name
  713.         strcpy(iv_friendly_name, inaddr);
  714.         return TRUE;
  715.       }
  716.     }         // end if lookup result
  717.     else
  718.     {
  719. #ifdef HAVE_GETHOSTBYNAME_R
  720.       iv_friendly_name_status = herrno;
  721. #else
  722.       iv_friendly_name_status = h_errno;
  723. #endif
  724.       return FALSE;
  725.     }
  726. #endif //PPC603
  727.   }  // end else not a dotted string
  728.   return TRUE;
  729. }
  730. // using the currently defined address, do a DNS
  731. // and try to fill up the name
  732. int IpAddress::addr_to_friendly()
  733. {
  734.   ADDRESS_TRACE;
  735. #if !defined HAVE_GETHOSTBYADDR_R && !defined HAVE_REENTRANT_GETHOSTBYADDR
  736. #ifdef _THREADS
  737.   SnmpSynchronize s(syscall_mutex);
  738. #endif
  739. #endif
  740. #if defined (CPU) && CPU == PPC603
  741.   int lookupResult;
  742. char hName[MAXHOSTNAMELEN+1];
  743. #else
  744.   hostent *lookupResult;
  745. #endif
  746.   char    ds[48];
  747.   // can't look up an invalid address
  748.   if (!valid_flag) return -1;
  749.   // lets try and get the friendly name from the DNS
  750.   strcpy(ds, this->IpAddress::get_printable());
  751. #if !(defined (CPU) && CPU == PPC603) && defined HAVE_GETHOSTBYADDR_R
  752.   int herrno = 0;
  753.   hostent lookup;
  754.   char buf[2048]; // TODO: Buf size too big?
  755. #endif
  756.   if (ip_version == version_ipv4)
  757.   {
  758.     in_addr ipAddr;
  759. #if defined HAVE_INET_ATON
  760.     if (inet_aton((char*)ds, &ipAddr) == 0)
  761.       return -1;    // bad address
  762. #elif defined HAVE_INET_PTON
  763.     if (inet_pton(AF_INET, (char*)ds, &ipAddr) <= 0)
  764.       return -1; // bad address
  765. #else
  766.     ipAddr.s_addr = inet_addr((char*)ds);
  767.     if (ipAddr.s_addr == INADDR_NONE)
  768.       return -1; // bad address
  769. #endif
  770. #if defined (CPU) && CPU == PPC603
  771. lookupResult = hostGetByAddr(ipAddr.s_addr, hName);
  772. #elif defined HAVE_GETHOSTBYADDR_R
  773. #if defined(__sun) || defined(__QNX_NEUTRINO)
  774.     lookupResult = gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
  775.                                    AF_INET, &lookup, buf, 2048, &herrno);
  776. #else
  777.     gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
  778.                     AF_INET, &lookup, buf, 2048, &lookupResult, &herrno);
  779. #endif
  780. #else
  781.     lookupResult = gethostbyaddr((char *) &ipAddr, sizeof(in_addr),
  782.                                  AF_INET);
  783. #endif
  784.   }
  785.   else
  786.   {
  787. #ifdef SNMP_PP_IPv6
  788.     in6_addr ipAddr;
  789.     if (inet_pton(AF_INET6, (char*)ds, &ipAddr) <= 0)
  790.       return -1; // bad address
  791. #if defined (CPU) && CPU == PPC603
  792. lookupResult = hostGetByAddr(ipAddr.s_addr, hName);
  793. #elif defined HAVE_GETHOSTBYADDR_R
  794. #if defined(__sun) || defined(__QNX_NEUTRINO)
  795.     lookupResult = gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
  796.                                    AF_INET6, &lookup, buf, 2048, &herrno);
  797. #else
  798.     gethostbyaddr_r((char *) &ipAddr, sizeof(in_addr),
  799.                     AF_INET6, &lookup, buf, 2048, &lookupResult, &herrno);
  800. #endif
  801. #else
  802.     lookupResult = gethostbyaddr((char *) &ipAddr, sizeof(in6_addr),
  803.                                  AF_INET6);
  804. #endif // HAVE_GETHOSTBYADDR_R
  805. #else
  806.     return -1;
  807. #endif // SNMP_PP_IPv6
  808.   }
  809.   // if we found the name, then update the iv friendly name
  810. #if defined (CPU) && CPU == PPC603
  811.   if (lookupResult != ERROR)
  812.   {
  813.     strncpy(iv_friendly_name, hName, MAX_FRIENDLY_NAME);
  814.     return 0;
  815.   }
  816.   else
  817.   {
  818.     iv_friendly_name_status = lookupResult;
  819. return lookupResult;
  820.   }
  821.   return -1; //should not get here
  822. #else
  823.   if (lookupResult)
  824.   {
  825.     strcpy(iv_friendly_name, lookupResult->h_name);
  826.     return 0;
  827.   }
  828.   else
  829.   {
  830. #ifdef HAVE_GETHOSTBYADDR_R
  831.     iv_friendly_name_status = herrno;
  832. #else
  833.     iv_friendly_name_status = h_errno;
  834. #endif
  835.     return iv_friendly_name_status;
  836.   }
  837. #endif //PPC603
  838. }
  839. //----[ IP address format output ]------------------------------------
  840. void IpAddress::format_output() const
  841. {
  842.   ADDRESS_TRACE;
  843.   // if valid format else null it
  844.   if (valid_flag)
  845.   {
  846.     if (ip_version == version_ipv4)
  847.       sprintf((char *) output_buffer,"%d.%d.%d.%d",address_buffer[0],
  848.                address_buffer[1], address_buffer[2], address_buffer[3]);
  849.     else
  850.       sprintf((char *) output_buffer,
  851.                "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
  852.                "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
  853.                address_buffer[ 0], address_buffer[ 1], address_buffer[ 2],
  854.                address_buffer[ 3], address_buffer[ 4], address_buffer[ 5],
  855.                address_buffer[ 6], address_buffer[ 7], address_buffer[ 8],
  856.                address_buffer[ 9], address_buffer[10], address_buffer[11],
  857.                address_buffer[12], address_buffer[13], address_buffer[14],
  858.                address_buffer[15]);
  859.   }
  860.   else
  861.     *(char *)output_buffer = 0;
  862.   IpAddress *nc_this = PP_CONST_CAST(IpAddress*, this);
  863.   nc_this->addr_changed = false;
  864. }
  865. //-----------------------------------------------------------------
  866. // logically and two IPaddresses and
  867. // return the new one
  868. void IpAddress::mask(const IpAddress& ipaddr)
  869. {
  870.   ADDRESS_TRACE;
  871.   if (valid() && ipaddr.valid())
  872.   {
  873.     int count = (ip_version == version_ipv4) ? IPLEN : IP6LEN;
  874.     for (int i = 0; i < count; i++)
  875.       address_buffer[i] = address_buffer[i] & ipaddr.address_buffer[i];
  876.     addr_changed = true;
  877.   }
  878. }
  879. // Get the count of matching bits from the left.
  880. int IpAddress::get_match_bits(const IpAddress match_ip) const
  881. {
  882.   ADDRESS_TRACE;
  883.   int bits = 0;
  884.   if (valid() && match_ip.valid() &&
  885.       (ip_version == match_ip.ip_version))
  886.   {
  887.     int count = (ip_version == version_ipv4) ? IPLEN : IP6LEN;
  888.     for (int i = 0; i < count; i++)
  889.     {
  890. if (address_buffer[i] == match_ip.address_buffer[i])
  891.     bits += 8;
  892. else
  893. {
  894.     bits += 7;
  895.     unsigned char c1 = address_buffer[i] >> 1;
  896.     unsigned char c2 = match_ip.address_buffer[i] >> 1;
  897.     while (c1 != c2)
  898.     {
  899. c1 = c1 >> 1;
  900. c2 = c2 >> 1;
  901. bits--;
  902.     }
  903.     break;
  904. }
  905.     }
  906.   }
  907.   return bits;
  908. }
  909. // Map a IPv4 Address to a IPv6 address.
  910. int IpAddress::map_to_ipv6()
  911. {
  912.   ADDRESS_TRACE;
  913.   if (!valid())
  914.     return FALSE;
  915.   if (ip_version != version_ipv4)
  916.     return FALSE;
  917.   /* just copy IPv4 address to the end of  the buffer
  918.      zero the first 10 bytes and fill 2 Bytes with 0xff */
  919.   memcpy(&address_buffer[12], address_buffer, 4);
  920.   memset(address_buffer, 0, 10);
  921.   address_buffer[10] = 0xff;
  922.   address_buffer[11] = 0xff;
  923.   smival.value.string.len = IP6LEN;
  924.   ip_version = version_ipv6;
  925.   addr_changed = true;
  926.   return TRUE;
  927. }
  928. // Reset the object
  929. void IpAddress::clear()
  930. {
  931.   Address::clear();
  932.   memset(output_buffer, 0, sizeof(output_buffer));
  933.   iv_friendly_name_status = 0;
  934.   ip_version = version_ipv4;
  935.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  936.   smival.value.string.len = IPLEN;
  937. }
  938. //=======================================================================
  939. //========== Udp Address Implementation =================================
  940. //=======================================================================
  941. //-------[ construct an IP address with no agrs ]----------------------
  942. UdpAddress::UdpAddress()
  943.   : IpAddress()
  944. {
  945.   ADDRESS_TRACE;
  946.   // Inherits IP Address attributes
  947.   // Always initialize (override) what type this object is
  948.   smival.syntax = sNMP_SYNTAX_OCTETS;
  949.   smival.value.string.len = UDPIPLEN;
  950.   smival.value.string.ptr = address_buffer;
  951.   sep = ':';
  952.   set_port(0);
  953. }
  954. //-----------------[ construct an Udp address with another Udp address ]---
  955. UdpAddress::UdpAddress(const UdpAddress &udpaddr)
  956.   : IpAddress(udpaddr)
  957. {
  958.   ADDRESS_TRACE;
  959.   // always initialize SMI info
  960.   smival.syntax = sNMP_SYNTAX_OCTETS;
  961.   smival.value.string.len = udpaddr.smival.value.string.len;
  962.   smival.value.string.ptr = address_buffer;
  963.   // Copy the port value
  964.   sep = ':';
  965.   set_port(udpaddr.get_port());
  966.   if (!udpaddr.addr_changed)
  967.   {
  968.     memcpy(output_buffer, udpaddr.output_buffer,
  969.    sizeof(unsigned char) * OUTBUFF);
  970.     addr_changed = false;
  971.   }
  972. }
  973. // constructor with a dotted string
  974. UdpAddress::UdpAddress(const char *inaddr) : IpAddress()
  975. {
  976.   ADDRESS_TRACE;
  977.   // always initialize SMI info
  978.   smival.syntax = sNMP_SYNTAX_OCTETS;
  979.   smival.value.string.len = UDPIPLEN;
  980.   smival.value.string.ptr = address_buffer;
  981.   valid_flag = parse_address(inaddr);
  982.   addr_changed = true;
  983. }
  984. //-----------------[ construct a UdpAddress from a GenAddress ]--------------
  985. UdpAddress::UdpAddress(const GenAddress &genaddr) : IpAddress()
  986. {
  987.   ADDRESS_TRACE;
  988.   // always initialize SMI info
  989.   smival.syntax = sNMP_SYNTAX_OCTETS;
  990.   smival.value.string.len = UDPIPLEN;
  991.   smival.value.string.ptr = address_buffer;
  992.   valid_flag = genaddr.valid();
  993.   // allow use of an ip or udp genaddress
  994.   if (valid_flag)
  995.   {
  996.     if (genaddr.get_type() == type_udp)
  997.     {
  998.       *this = genaddr.cast_udpaddress();      // copy in the IP address data
  999.     }
  1000.     else if (genaddr.get_type() == type_ip)
  1001.     {
  1002.       *this = genaddr.cast_ipaddress();      // copy in the IP address data
  1003.     }
  1004.     else
  1005.     {
  1006.       valid_flag = false;
  1007.     }
  1008.   }
  1009.   sep = ':';
  1010. }
  1011. //--------[ construct a udp from an IpAddress ]--------------------------
  1012. UdpAddress::UdpAddress(const IpAddress &ipaddr):IpAddress(ipaddr)
  1013. {
  1014.   ADDRESS_TRACE;
  1015.   // always initialize SMI info
  1016.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1017.   if (ip_version == version_ipv4)
  1018.       smival.value.string.len = UDPIPLEN;
  1019.   else
  1020.       smival.value.string.len = UDPIP6LEN;
  1021.   smival.value.string.ptr = address_buffer;
  1022.   sep = ':';
  1023.   addr_changed = true;
  1024.   set_port(0);
  1025. }
  1026. // copy an instance of this Value
  1027. SnmpSyntax& UdpAddress::operator=(const SnmpSyntax &val)
  1028. {
  1029.   ADDRESS_TRACE;
  1030.   if (this == &val) return *this;   // protect against assignment from itself
  1031.   valid_flag = false;                // will get set TRUE if really valid
  1032.   addr_changed = true;
  1033.   if (val.valid())
  1034.   {
  1035.     switch (val.get_syntax())
  1036.     {
  1037.       case sNMP_SYNTAX_IPADDR:
  1038.       {
  1039.         UdpAddress temp_udp(val.get_printable());
  1040.         *this = temp_udp;        // valid_flag is set by the udp assignment
  1041.         break;
  1042.       }
  1043.       case sNMP_SYNTAX_OCTETS:
  1044.         if (((UdpAddress &)val).smival.value.string.len == UDPIPLEN)
  1045.         {
  1046.           MEMCPY(address_buffer,((UdpAddress &)val).smival.value.string.ptr,
  1047.                  UDPIPLEN);
  1048.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  1049.           valid_flag = true;
  1050.           ip_version = version_ipv4;
  1051.           smival.value.string.len = UDPIPLEN;
  1052.         }
  1053.         else if (((UdpAddress &)val).smival.value.string.len == UDPIP6LEN)
  1054.         {
  1055.           MEMCPY(address_buffer,((UdpAddress &)val).smival.value.string.ptr,
  1056.                  UDPIP6LEN);
  1057.   memset(iv_friendly_name, 0, sizeof(char) * MAX_FRIENDLY_NAME);
  1058.           valid_flag = true;
  1059.           ip_version = version_ipv6;
  1060.           smival.value.string.len = UDPIP6LEN;
  1061.         }
  1062.         break;
  1063.         // NOTE: as a value add, other types could have "logical"
  1064.         // mappings, i.e. integer32 and unsigned32
  1065.     }
  1066.   }
  1067.   return *this;
  1068. }
  1069. // assignment to another UdpAddress object overloaded
  1070. UdpAddress& UdpAddress::operator=(const UdpAddress &udpaddr)
  1071. {
  1072.   ADDRESS_TRACE;
  1073.   if (this == &udpaddr) return *this; // protect against assignment from itself
  1074.   (IpAddress &)*this = udpaddr; // use ancestor assignment for ipaddr value
  1075.   if (ip_version == version_ipv4)
  1076.     smival.value.string.len = UDPIPLEN;
  1077.   else
  1078.     smival.value.string.len = UDPIP6LEN;
  1079.   set_port(udpaddr.get_port());        // copy to port value
  1080.   if (udpaddr.addr_changed)
  1081.   {
  1082.     addr_changed = true;
  1083.   }
  1084.   else
  1085.   {
  1086.     memcpy(output_buffer, udpaddr.output_buffer,
  1087.    sizeof(unsigned char) * OUTBUFF);
  1088.     addr_changed = false;
  1089.   }
  1090.   return *this;
  1091. }
  1092. // assignment to another UdpAddress object overloaded
  1093. UdpAddress& UdpAddress::operator=(const IpAddress &ipaddr)
  1094. {
  1095.   ADDRESS_TRACE;
  1096.   if (this == &ipaddr) return *this; // protect against assignment from itself
  1097.   (IpAddress &)*this = ipaddr; // use ancestor assignment for ipaddr value
  1098.   if (ip_version == version_ipv4)
  1099.     smival.value.string.len = UDPIPLEN;
  1100.   else
  1101.     smival.value.string.len = UDPIP6LEN;
  1102.   set_port(0);        // copy to port value
  1103.   addr_changed = true;
  1104.   return *this;
  1105. }
  1106. UdpAddress& UdpAddress::operator=(const char *inaddr)
  1107. {
  1108.   ADDRESS_TRACE;
  1109.   valid_flag = parse_address(inaddr);
  1110.   addr_changed = true;
  1111.   return *this;
  1112. }
  1113. //-----[ IP Address parse Address ]---------------------------------
  1114. bool UdpAddress::parse_address(const char *inaddr)
  1115. {
  1116.   ADDRESS_TRACE;
  1117.   addr_changed = true;
  1118.   char buffer[MAX_FRIENDLY_NAME];
  1119.   unsigned short port = 0;
  1120.   if (inaddr && (strlen(inaddr)< MAX_FRIENDLY_NAME))
  1121.   {
  1122.     strcpy(buffer, inaddr);
  1123.     trim_white_space(buffer);
  1124.   }
  1125.   else
  1126.   {
  1127.     valid_flag = false;
  1128.     return FALSE;
  1129.   }
  1130.   // look for port info @ the end of the string
  1131.   // port can be delineated by a ':' or a '/'
  1132.   // if neither are present then just treat it
  1133.   // like a normal IpAddress
  1134.   int remove_brackets = FALSE;
  1135.   int found = FALSE;
  1136.   int pos = (int)strlen(buffer) - 1; // safe to cast as max is MAX_FRIENDLY_NAME
  1137.   int do_loop = TRUE;
  1138.   int another_colon_found = FALSE;
  1139.   if (pos < 0)
  1140.   {
  1141.     valid_flag = false;
  1142.     return FALSE;
  1143.   }
  1144.   // search from the end, to find the start of the port 
  1145.   // [ipv4]:port [ipv4]/port ipv4/port ipv4:port [ipv4] ipv4
  1146.   // [ipv6]:port [ipv6]/port ipv6/port           [ipv6] ipv6
  1147.   while (do_loop)
  1148.   {
  1149.     if (buffer[pos] == '/')
  1150.     {
  1151.       found = TRUE;
  1152.       sep='/';
  1153.       if (buffer[pos -1] == ']')
  1154.         remove_brackets = TRUE;
  1155.       break;
  1156.     }
  1157.     if (buffer[pos] == ':')
  1158.     {
  1159.       if ((pos > 1) && (buffer[pos -1] == ']'))
  1160.       {
  1161.         found = TRUE;
  1162.         remove_brackets = TRUE;
  1163.         sep=':';
  1164.         break;
  1165.       }
  1166.       for (int i=pos - 1; i >= 0 ; i--)
  1167.         if (buffer[i] == ':')
  1168.         {
  1169.           another_colon_found = TRUE;
  1170.         }
  1171.       if (!another_colon_found)
  1172.       {
  1173.         sep=':';
  1174.         found = TRUE;
  1175.         break;
  1176.       }
  1177.     }
  1178.     if (buffer[pos] == ']')
  1179.     {
  1180.       // we found a ] without following a port, so increase pos
  1181.       ++pos;
  1182.       remove_brackets = TRUE;
  1183.       break;
  1184.     }
  1185.     pos--;
  1186.     do_loop = ((found == FALSE) && (pos >= 0) &&
  1187.                (another_colon_found == FALSE));
  1188.   }
  1189.   if (remove_brackets)
  1190.   {
  1191.     buffer[pos-1] = 0;
  1192.     buffer[0] = ' ';
  1193.   }
  1194.   bool result;
  1195.   if (found)
  1196.   {
  1197.     buffer[pos] = 0;
  1198.     port = atoi(&buffer[pos+1]);
  1199.     result = IpAddress::parse_address(buffer);
  1200.   }
  1201.   else
  1202.   {
  1203.     port = 0;
  1204.     result = IpAddress::parse_address(buffer);
  1205.   }
  1206.   if (ip_version == version_ipv4)
  1207.     smival.value.string.len = UDPIPLEN;
  1208.   else
  1209.     smival.value.string.len = UDPIP6LEN;
  1210.   set_port(port);
  1211.   return result;
  1212. }
  1213. //--------[ set the port number ]---------------------------------------
  1214. void UdpAddress::set_port(const unsigned short p)
  1215. {
  1216.   ADDRESS_TRACE;
  1217.   unsigned short *port_nbo;
  1218.   if (ip_version == version_ipv4)
  1219.     port_nbo = (unsigned short*)(address_buffer + IPLEN);
  1220.   else
  1221.     port_nbo = (unsigned short*)(address_buffer + IP6LEN);
  1222.   *port_nbo = htons(p);
  1223.   addr_changed = true;
  1224. }
  1225. //---------[ get the port number ]--------------------------------------
  1226. unsigned short UdpAddress::get_port() const
  1227. {
  1228.   ADDRESS_TRACE;
  1229.   if (valid_flag)
  1230.   {
  1231.     const unsigned short *port_nbo;
  1232.     if (ip_version == version_ipv4)
  1233.       port_nbo = (const unsigned short*)(address_buffer + IPLEN);
  1234.     else
  1235.       port_nbo = (const unsigned short*)(address_buffer + IP6LEN);
  1236.     return ntohs(*port_nbo);
  1237.   }
  1238.   return 0;// don't use uninitialized memory
  1239. }
  1240. //----[ UDP address format output ]------------------------------------
  1241. void UdpAddress::format_output() const
  1242. {
  1243.   ADDRESS_TRACE;
  1244.   IpAddress::format_output(); // allow ancestors to format their buffers
  1245.   // if valid format else null it
  1246.   if (valid_flag)
  1247.   {
  1248.     if (ip_version == version_ipv4)
  1249.       sprintf((char *) output_buffer,"%s%c%d",
  1250.                IpAddress::get_printable(),
  1251.                '/',//TODO:look for problems in old code and change to "sep"
  1252.                get_port() );
  1253.       else
  1254.         sprintf((char *) output_buffer,"[%s]%c%d",
  1255.                  IpAddress::get_printable(),
  1256.                  '/',//TODO:look for problems in old code and change to "sep"
  1257.                  get_port() );
  1258.   }
  1259.   else
  1260.     *(char*)output_buffer = 0;
  1261.   UdpAddress *nc_this = PP_CONST_CAST(UdpAddress*, this);
  1262.   nc_this->addr_changed = false;
  1263. }
  1264. /**
  1265.  * Map a IPv4 UDP address to a IPv6 UDP address.
  1266.  *
  1267.  * @return - TRUE if no error occured.
  1268.  */
  1269. int UdpAddress::map_to_ipv6()
  1270. {
  1271.   ADDRESS_TRACE;
  1272.   /* Save the port, as IpAddress::map_to_ipv6 destroys it */
  1273.   unsigned short old_port = get_port();
  1274.   /* Map IpAddress */
  1275.   if (!IpAddress::map_to_ipv6())
  1276.     return FALSE;
  1277.   set_port(old_port);
  1278.   smival.value.string.len = UDPIP6LEN;
  1279.   ip_version = version_ipv6;
  1280.   addr_changed = true;
  1281.   return TRUE;
  1282. }
  1283. #ifdef _IPX_ADDRESS
  1284. //=======================================================================
  1285. //=========== IPX Address Implementation ================================
  1286. //=======================================================================
  1287. //----------[ constructor no args ]--------------------------------------
  1288. IpxAddress::IpxAddress() : Address()
  1289. {
  1290.   // always initialize SMI info
  1291.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1292.   smival.value.string.len = IPXLEN;
  1293.   smival.value.string.ptr = address_buffer;
  1294.   separator = 0;
  1295.   valid_flag = false;
  1296.   addr_changed = true;
  1297. }
  1298. //----------[ constructor with a string arg ]---------------------------
  1299. IpxAddress::IpxAddress(const char  *inaddr):Address()
  1300. {
  1301.   // always initialize SMI info
  1302.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1303.   smival.value.string.len = IPXLEN;
  1304.   smival.value.string.ptr = address_buffer;
  1305.   separator = 0;
  1306.   valid_flag = parse_address(inaddr);
  1307.   addr_changed = true;
  1308. }
  1309. //-----[ IPX Address copy constructor ]----------------------------------
  1310. IpxAddress::IpxAddress(const IpxAddress &ipxaddr)
  1311. {
  1312.   // always initialize SMI info
  1313.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1314.   smival.value.string.len = IPXLEN;
  1315.   smival.value.string.ptr = address_buffer;
  1316.   separator = 0;
  1317.   valid_flag = ipxaddr.valid_flag;
  1318.   if (valid_flag)
  1319.      MEMCPY(address_buffer, ipxaddr.address_buffer, IPXLEN);
  1320.   addr_changed = true;
  1321. }
  1322. //----[ construct an IpxAddress from a GenAddress ]---------------------------
  1323. IpxAddress::IpxAddress(const GenAddress &genaddr)
  1324. {
  1325.   // always initialize SMI info
  1326.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1327.   smival.value.string.len = IPXLEN;
  1328.   smival.value.string.ptr = address_buffer;
  1329.   valid_flag = genaddr.valid();
  1330.   // allow use of an ipx or ipxsock address
  1331.   if (valid_flag)
  1332.   {
  1333.     if ((genaddr.get_type() == type_ipx) )
  1334.     {
  1335.       *this = genaddr.cast_ipxaddress();     // copy in the Ipx address data
  1336.     }
  1337.     else if ((genaddr.get_type() == type_ipxsock) )
  1338.     {
  1339.       *this = genaddr.cast_ipxsockaddress();  // copy in the Ipx address data
  1340.     }
  1341.     else
  1342.       valid_flag = false;
  1343.   }
  1344. }
  1345. //-----[ IPX Address general = operator ]-------------------------------
  1346. SnmpSyntax& IpxAddress::operator=(const SnmpSyntax &val)
  1347. {
  1348.   // protect against assignment from itself
  1349.   if (this == &val) return *this;
  1350.   valid_flag = false;              // will set to TRUE if really valid
  1351.   if (val.valid()){
  1352.     switch (val.get_syntax()){
  1353.     case sNMP_SYNTAX_OCTETS:
  1354.       if (((IpxAddress &)val).smival.value.string.len == IPXLEN){
  1355.         MEMCPY(address_buffer, ((IpxAddress &)val).smival.value.string.ptr, IPXLEN);
  1356.         valid_flag = true;
  1357.       }
  1358.     break;
  1359.     }
  1360.   }
  1361.   addr_changed = true;
  1362.   return *this;
  1363. }
  1364. //--------[ assignment to another IpAddress object overloaded ]----------
  1365. IpxAddress& IpxAddress::operator=(const IpxAddress &ipxaddress)
  1366. {
  1367.   if (this == &ipxaddress) return *this;// protect against assignment from self
  1368.   valid_flag = ipxaddress.valid_flag;
  1369.   if (valid_flag)
  1370.     MEMCPY(address_buffer, ipxaddress.address_buffer, IPXLEN);
  1371.   addr_changed = true;
  1372.   return *this;
  1373. }
  1374. //-----[ IPX Address parse Address ]-----------------------------------
  1375. // Convert a string to a ten byte ipx address
  1376. // On success sets validity  TRUE or FALSE
  1377. //
  1378. //     IPX address format
  1379. //
  1380. //  NETWORK ID| MAC ADDRESS
  1381. // 01 02 03 04|05 06 07 08 09 10
  1382. // XX XX XX XX|XX XX XX XX XX XX
  1383. //
  1384. //   Valid input format
  1385. //
  1386. //   XXXXXXXX.XXXXXXXXXXXX
  1387. //   Total length must be 21
  1388. //   Must have a separator in it
  1389. //   First string length must be 8
  1390. //   Second string length must be 12
  1391. //   Each char must take on value 0-F
  1392. //
  1393. //
  1394. // Input formats recognized
  1395. //
  1396. //  XXXXXXXX.XXXXXXXXXXXX
  1397. //  XXXXXXXX:XXXXXXXXXXXX
  1398. //  XXXXXXXX-XXXXXXXXXXXX
  1399. //  XXXXXXXX.XXXXXX-XXXXXX
  1400. //  XXXXXXXX:XXXXXX-XXXXXX
  1401. //  XXXXXXXX-XXXXXX-XXXXXX
  1402. bool IpxAddress::parse_address(const char *inaddr)
  1403. {
  1404.   char unsigned *str1,*str2;
  1405.   char temp[30];    // don't destroy original
  1406.   char unsigned *tmp;
  1407.   size_t z, tmplen;
  1408.   // save the orginal source
  1409.   if (!inaddr || (strlen(inaddr) >(sizeof(temp)-1))) return FALSE;
  1410.   strcpy(temp, inaddr);
  1411.   trim_white_space(temp);
  1412.   tmplen = strlen(temp);
  1413.   // bad total length check
  1414.   // 123456789012345678901
  1415.   // XXXXXXXX-XXXXXXXXXXXX  21 len
  1416.   //
  1417.   // XXXXXXXX-XXXXXX-XXXXXX 22 len
  1418.   // need at least 21 chars and no more than 22
  1419.   if ((tmplen <21) || (tmplen >22))
  1420.     return FALSE;
  1421.   // convert the string to all lower case
  1422.   // this allows hex values to be in upper or lower
  1423.   for (z=0;z< tmplen;z++)
  1424.     temp[z] = tolower(temp[z]);
  1425.   // check for separated nodeid
  1426.   // if found remove it
  1427.   if (temp[15] == '-')
  1428.   {
  1429.      for(z=16;z<tmplen;z++)
  1430.         temp[z-1] = temp[z];
  1431.      temp[tmplen-1] = 0;
  1432.   }
  1433.   // no dot or colon separator check
  1434.   separator = temp[8];
  1435.   if ((separator != ':') &&
  1436.       (separator != '.') &&
  1437.       (separator != '-') &&
  1438.       (separator != ' '))
  1439.     return FALSE;
  1440.   // separate the strings
  1441.   str1 = (unsigned char *) temp;
  1442.   while(*str1 != separator) str1++;
  1443.   str2 = str1 + 1;
  1444.   *str1 = 0;
  1445.   str1= (unsigned char *) temp;
  1446.   // check len of the network portion
  1447.   if (strlen((char *) str1) != 8) return FALSE;
  1448.   // check len of mac portion
  1449.   if (strlen((char *) str2) != 12) return FALSE;
  1450.   // ok we like then lens, make sure that all chars are 0-f
  1451.   // check out the net id
  1452.   tmp = str1;
  1453.   while(*tmp != 0)
  1454.     if (((*tmp >= '0') && (*tmp <= '9'))||   // good 0-9
  1455.         ((*tmp >= 'a') && (*tmp <= 'f')))    // or a-f
  1456.       tmp++;
  1457.     else
  1458.       return FALSE;
  1459.   // check out the MAC address
  1460.   tmp = str2;
  1461.   while(*tmp != 0)
  1462.     if (((*tmp >= '0') && (*tmp <= '9'))||   // good 0-9
  1463.         ((*tmp >= 'a') && (*tmp <= 'f')))    // or a-f
  1464.       tmp++;
  1465.     else
  1466.       return FALSE;
  1467.   // convert to target string
  1468.   tmp = str1;
  1469.   while (*tmp != 0)
  1470.   {
  1471.   if ((*tmp >= '0') && (*tmp <= '9'))
  1472.     *tmp = *tmp - (char unsigned )'0';
  1473.   else
  1474.     *tmp = *tmp - (char unsigned) 'a' + (char unsigned) 10;
  1475.   tmp++;
  1476.   }
  1477.   // network id portion
  1478.   address_buffer[0] = (str1[0]*16) + str1[1];
  1479.   address_buffer[1] = (str1[2]*16) + str1[3];
  1480.   address_buffer[2] = (str1[4]*16) + str1[5];
  1481.   address_buffer[3] = (str1[6]*16) + str1[7];
  1482.   tmp = str2;
  1483.   while (*tmp != 0)
  1484.   {
  1485.   if ((*tmp >= '0') && (*tmp <= '9'))
  1486.     *tmp = *tmp - (char unsigned) '0';
  1487.   else
  1488.     *tmp = *tmp - (char unsigned) 'a'+ (char unsigned) 10;
  1489.   tmp++;
  1490.   }
  1491.   address_buffer[4] = (str2[0]*16)  + str2[1];
  1492.   address_buffer[5] = (str2[2]*16)  + str2[3];
  1493.   address_buffer[6] = (str2[4]*16)  + str2[5];
  1494.   address_buffer[7] = (str2[6]*16)  + str2[7];
  1495.   address_buffer[8] = (str2[8]*16)  + str2[9];
  1496.   address_buffer[9] = (str2[10]*16) + str2[11];
  1497.   return TRUE;
  1498. }
  1499. //----[ IPX address format output ]-------------------------------------
  1500. void IpxAddress::format_output() const
  1501. {
  1502.   if (valid_flag)
  1503.     sprintf((char *) output_buffer,
  1504.             "%02x%02x%02x%02x%c%02x%02x%02x%02x%02x%02x",
  1505.             address_buffer[0],address_buffer[1],
  1506.             address_buffer[2],address_buffer[3],'-',
  1507.             address_buffer[4],address_buffer[5],
  1508.             address_buffer[6],address_buffer[7],
  1509.             address_buffer[8],address_buffer[9]);
  1510.   else
  1511.     *(char*)output_buffer = 0;
  1512.   IpxAddress *nc_this = PP_CONST_CAST(IpxAddress*, this);
  1513.   nc_this->addr_changed = false;
  1514. }
  1515. #ifdef _MAC_ADDRESS
  1516. // get the host id portion of an ipx address
  1517. int IpxAddress::get_hostid(MacAddress& mac) const
  1518. {
  1519.    if (valid_flag)
  1520.    {
  1521.        char buffer[18];
  1522.        sprintf(buffer,"%02x:%02x:%02x:%02x:%02x:%02x", address_buffer[4],
  1523.                 address_buffer[5], address_buffer[6], address_buffer[7],
  1524.                 address_buffer[8], address_buffer[9]);
  1525.        MacAddress temp(buffer);
  1526.        mac = temp;
  1527.        if (mac.valid())
  1528.  return TRUE;
  1529.    }
  1530.    return FALSE;
  1531. }
  1532. #endif // function that needs _MAC_ADDRESS
  1533. //========================================================================
  1534. //======== IpxSockAddress Implementation =================================
  1535. //========================================================================
  1536. //----------[ constructor no args ]--------------------------------------
  1537. IpxSockAddress::IpxSockAddress() : IpxAddress()
  1538. {
  1539.   // always initialize SMI info
  1540.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1541.   smival.value.string.len = IPXSOCKLEN;
  1542.   smival.value.string.ptr = address_buffer;
  1543.   set_socket(0);
  1544.   addr_changed = true;
  1545. }
  1546. //-----------[ construct an IpxSockAddress with another IpxSockAddress]----
  1547. IpxSockAddress::IpxSockAddress(const IpxSockAddress &ipxaddr)
  1548.   : IpxAddress(ipxaddr)
  1549. {
  1550.   // always initialize SMI info
  1551.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1552.   smival.value.string.len = IPXSOCKLEN;
  1553.   smival.value.string.ptr = address_buffer;
  1554.   // copy the socket value
  1555.   set_socket(ipxaddr.get_socket());
  1556.   addr_changed = true;
  1557. }
  1558. //---------------[ construct a IpxSockAddress from a string ]--------------
  1559. IpxSockAddress::IpxSockAddress(const char *inaddr):IpxAddress()
  1560. {
  1561.   // always initialize SMI info
  1562.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1563.   smival.value.string.len = IPXSOCKLEN;
  1564.   smival.value.string.ptr = address_buffer;
  1565.   valid_flag = parse_address(inaddr);
  1566.   addr_changed = true;
  1567. }
  1568. //---------------[ construct a IpxSockAddress from a GenAddress ]----------
  1569. IpxSockAddress::IpxSockAddress(const GenAddress &genaddr):IpxAddress()
  1570. {
  1571.   // always initialize SMI info
  1572.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1573.   smival.value.string.len = IPXSOCKLEN;
  1574.   smival.value.string.ptr = address_buffer;
  1575.   valid_flag = false;
  1576.   unsigned short socketid = 0;
  1577.   // allow use of an ipx or ipxsock address
  1578.   if ((genaddr.get_type() == type_ipx) )
  1579.   {
  1580.     valid_flag = genaddr.valid();
  1581.     if (valid_flag)
  1582.     {
  1583.       // copy in the Ipx address data
  1584.       IpxAddress temp_ipx((const char *) genaddr);
  1585.       *this = temp_ipx;
  1586.     }
  1587.   }
  1588.   else if ((genaddr.get_type() == type_ipxsock) )
  1589.   {
  1590.     valid_flag = genaddr.valid();
  1591.     if (valid_flag)
  1592.     {
  1593.       // copy in the Ipx address data
  1594.       IpxSockAddress temp_ipxsock((const char *) genaddr);
  1595.       *this = temp_ipxsock;
  1596.       //  socketid info since are making an IpxSockAddress
  1597.       socketid = temp_ipxsock.get_socket();
  1598.     }
  1599.   }
  1600.   set_socket(socketid);
  1601.   addr_changed = true;
  1602. }
  1603. //------------[ construct an IpxSockAddress from a IpxAddress ]--------------
  1604. IpxSockAddress::IpxSockAddress(const IpxAddress &ipxaddr):IpxAddress(ipxaddr)
  1605. {
  1606.   // always initialize SMI info
  1607.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1608.   smival.value.string.len = IPXSOCKLEN;
  1609.   smival.value.string.ptr = address_buffer;
  1610.   set_socket(0);
  1611.   addr_changed = true;
  1612. }
  1613. // copy an instance of this Value
  1614. SnmpSyntax& IpxSockAddress::operator=(const SnmpSyntax &val)
  1615. {
  1616.   if (this == &val) return *this; // protect against assignment from itself
  1617.   valid_flag = false;              // will set to TRUE if really valid
  1618.   if (val.valid()){
  1619.     switch (val.get_syntax()){
  1620.     case sNMP_SYNTAX_OCTETS:
  1621.       {
  1622.         // See if it is of the Ipx address family
  1623.         // This handles IpxSockAddress == IpxAddress
  1624.         IpxSockAddress temp_ipx(val.get_printable());
  1625.         if (temp_ipx.valid()){
  1626.           *this = temp_ipx;                // ipxsock = ipxsock
  1627.         }
  1628.         // See if it is an OctetStr of appropriate length
  1629.         else if (((IpxSockAddress &)val).smival.value.string.len == IPXSOCKLEN){
  1630.           MEMCPY(address_buffer,
  1631.                  ((IpxSockAddress &)val).smival.value.string.ptr,
  1632.                  IPXSOCKLEN);
  1633.           valid_flag = true;
  1634.         }
  1635.       }
  1636.       break;
  1637.     }
  1638.   }
  1639.   addr_changed = true;
  1640.   return *this;
  1641. }
  1642. // assignment to another IpAddress object overloaded
  1643. IpxSockAddress& IpxSockAddress::operator=(const IpxSockAddress &ipxaddr)
  1644. {
  1645.   if (this == &ipxaddr) return *this; // protect against assignment from itself
  1646.   (IpxAddress&)*this = ipxaddr;         // use ancestor assignment for ipx addr
  1647.   set_socket(ipxaddr.get_socket());        // copy socket value
  1648.   addr_changed = true;
  1649.   return *this;
  1650. }
  1651. //----[ IPX address format output ]-------------------------------------
  1652. void IpxSockAddress::format_output() const
  1653. {
  1654.   IpxAddress::format_output(); // allow ancestors to format their buffers
  1655.   if (valid_flag)
  1656.     sprintf((char *) output_buffer,"%s/%d",
  1657.             IpxAddress::get_printable(), get_socket());
  1658.   else
  1659.     *(char*)output_buffer = 0;
  1660.   IpxSockAddress *nc_this = PP_CONST_CAST(IpxSockAddress*, this);
  1661.   nc_this->addr_changed = false;
  1662. }
  1663. //-----[ IP Address parse Address ]---------------------------------
  1664. bool IpxSockAddress::parse_address(const char *inaddr)
  1665. {
  1666.    char buffer[MAX_FRIENDLY_NAME];
  1667.    unsigned short socketid=0;
  1668.    if (inaddr && (strlen(inaddr)< MAX_FRIENDLY_NAME))
  1669.      strcpy(buffer, inaddr);
  1670.    else
  1671.    {
  1672.      valid_flag = false;
  1673.      return FALSE;
  1674.    }
  1675.    // look for port info @ the end of the string
  1676.    // port can be delineated by a ':' or a '/'
  1677.    // if neither are present then just treat it
  1678.    // like a normal IpAddress
  1679.    char *tmp;
  1680.    tmp = strstr(buffer,"/");
  1681.    if (tmp != NULL)
  1682.    {
  1683.      *tmp=0;   // new null terminator
  1684.      tmp++;
  1685.      socketid = atoi(tmp);
  1686.    }
  1687.    set_socket(socketid);
  1688.    return IpxAddress::parse_address(buffer);
  1689. }
  1690. //-------------[ set the socket number ]----------------------------------
  1691. void IpxSockAddress::set_socket(const unsigned short s)
  1692. {
  1693.   unsigned short sock_nbo = htons(s);
  1694.   MEMCPY(&address_buffer[IPXLEN], &sock_nbo, 2);
  1695.   addr_changed = true;
  1696. }
  1697. //--------------[ get the socket number ]---------------------------------
  1698. unsigned short IpxSockAddress::get_socket() const
  1699. {
  1700.   if (valid_flag)
  1701.   {
  1702.     unsigned short sock_nbo;
  1703.     MEMCPY(&sock_nbo, &address_buffer[IPXLEN], 2);
  1704.     return ntohs(sock_nbo);
  1705.   }
  1706.   return 0; // don't use uninitialized memory
  1707. }
  1708. #endif // _IPX_ADDRESS
  1709. #ifdef _MAC_ADDRESS
  1710. //========================================================================
  1711. //======== MACAddress Implementation =====================================
  1712. //========================================================================
  1713. //--------[ constructor, no arguments ]-----------------------------------
  1714. MacAddress::MacAddress() : Address()
  1715. {
  1716.   // always initialize SMI info
  1717.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1718.   smival.value.string.len = MACLEN;
  1719.   smival.value.string.ptr = address_buffer;
  1720.   valid_flag = false;
  1721.   addr_changed = true;
  1722. }
  1723. //-----[ MAC Address copy constructor ]---------------------------------
  1724. MacAddress::MacAddress(const MacAddress &macaddr)
  1725. {
  1726.   // always initialize SMI info
  1727.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1728.   smival.value.string.len = MACLEN;
  1729.   smival.value.string.ptr = address_buffer;
  1730.   valid_flag = macaddr.valid_flag;
  1731.   if (valid_flag)
  1732.     MEMCPY(address_buffer, macaddr.address_buffer, MACLEN);
  1733.   addr_changed = true;
  1734. }
  1735. //---------[ constructor with a string argument ]-------------------------
  1736. MacAddress::MacAddress(const char  *inaddr):Address()
  1737. {
  1738.   // always initialize SMI info
  1739.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1740.   smival.value.string.len = MACLEN;
  1741.   smival.value.string.ptr = address_buffer;
  1742.   valid_flag = parse_address(inaddr);
  1743.   addr_changed = true;
  1744. }
  1745. //-----[ construct a MacAddress from a GenAddress ]------------------------
  1746. MacAddress::MacAddress(const GenAddress &genaddr)
  1747. {
  1748.   // always initialize SMI info
  1749.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1750.   smival.value.string.len = MACLEN;
  1751.   smival.value.string.ptr = address_buffer;
  1752.   valid_flag = false;
  1753.   // allow use of mac address
  1754.   if (genaddr.get_type() == type_mac)
  1755.   {
  1756.     valid_flag = genaddr.valid();
  1757.     if (valid_flag)
  1758.     {
  1759.       // copy in the Mac address data
  1760.       *this = genaddr.cast_macaddress();
  1761.     }
  1762.   }
  1763.   addr_changed = true;
  1764. }
  1765. //------[ assignment to another ipaddress object overloaded ]--------------
  1766. MacAddress& MacAddress::operator=(const MacAddress &macaddress)
  1767. {
  1768.   if (this == &macaddress) return *this;// protect against assignment from self
  1769.   valid_flag = macaddress.valid_flag;
  1770.   if (valid_flag)
  1771.     MEMCPY(address_buffer, macaddress.address_buffer, MACLEN);
  1772.   addr_changed = true;
  1773.   return *this;
  1774. }
  1775. //-----[ MAC Address general = operator ]---------------------------------
  1776. SnmpSyntax& MacAddress::operator=(const SnmpSyntax &val)
  1777. {
  1778.   if (this == &val) return *this;  // protect against assignment from itself
  1779.   valid_flag = false;              // will set to TRUE if really valid
  1780.   if (val.valid())
  1781.   {
  1782.     switch (val.get_syntax())
  1783.     {
  1784.       case sNMP_SYNTAX_OCTETS:
  1785. if (((MacAddress &)val).smival.value.string.len == MACLEN)
  1786. {
  1787.   MEMCPY(address_buffer, ((MacAddress &)val).smival.value.string.ptr,
  1788.  MACLEN);
  1789.   valid_flag = true;
  1790. }
  1791. break;
  1792.     }
  1793.   }
  1794.   addr_changed = true;
  1795.   return *this;
  1796. }
  1797. //-----[ MAC Address parse Address ]--------------------------------------
  1798. // Convert a string to a six byte MAC address
  1799. // On success sets validity TRUE or FALSE
  1800. //
  1801. //     MAC address format
  1802. //
  1803. //   MAC ADDRESS
  1804. //   01 02 03 04 05 06
  1805. //   XX:XX:XX:XX:XX:XX
  1806. //   Valid input format
  1807. //
  1808. //   XXXXXXXXXXXX
  1809. //   Total length must be 17
  1810. //   Each char must take on value 0-F
  1811. //
  1812. //
  1813. bool MacAddress::parse_address(const char *inaddr)
  1814. {
  1815.   char temp[30];    // don't destroy original
  1816.   char unsigned *tmp;
  1817.   size_t z;
  1818.   // save the orginal source
  1819.   if (!inaddr || (strlen(inaddr) > 30)) return FALSE;
  1820.   strcpy(temp, inaddr);
  1821.   trim_white_space(temp);
  1822.   // bad total length check
  1823.   if (strlen(temp) != 17)
  1824.      return FALSE;
  1825.   // check for colons
  1826.   if ((temp[2] != ':')||(temp[5] != ':')||(temp[8]!=':')||(temp[11]!=':')||(temp[14] !=':'))
  1827.      return FALSE;
  1828.   // strip off the colons
  1829.   tmp = (unsigned char *) temp;
  1830.   int i = 0;
  1831.   while (*tmp != 0)
  1832.   {
  1833.      if (*tmp != ':')
  1834.      {
  1835.         temp[i] = *tmp;
  1836.         i++;
  1837.      }
  1838.      tmp++;
  1839.   }
  1840.   temp[i] = 0;
  1841.   // convert to lower
  1842.   for(z=0;z<strlen(temp);z++)
  1843.      temp[z] = tolower(temp[z]);
  1844.   // check out the MAC address
  1845.   tmp = (unsigned char *) temp;
  1846.   while(*tmp != 0)
  1847.     if (((*tmp >= '0') && (*tmp <= '9'))||   // good 0-9
  1848.         ((*tmp >= 'a') && (*tmp <= 'f')))    // or a-f
  1849.       tmp++;
  1850.     else
  1851.       return FALSE;
  1852.   // convert to target string
  1853.   tmp = (unsigned char *) temp;
  1854.   while (*tmp != 0)
  1855.   {
  1856.   if ((*tmp >= '0') && (*tmp <= '9'))
  1857.     *tmp = *tmp - (char unsigned )'0';
  1858.   else
  1859.     *tmp = *tmp - (char unsigned) 'a' + (char unsigned) 10;
  1860.   tmp++;
  1861.   }
  1862.   address_buffer[0] =  (temp[0]*16) + temp[1];
  1863.   address_buffer[1] =  (temp[2]*16) + temp[3];
  1864.   address_buffer[2] =  (temp[4]*16) + temp[5];
  1865.   address_buffer[3] =  (temp[6]*16) + temp[7];
  1866.   address_buffer[4] =  (temp[8]*16) + temp[9];
  1867.   address_buffer[5] =  (temp[10]*16) + temp[11];
  1868.   return TRUE;
  1869. }
  1870. //----[ MAC address format output ]---------------------------------
  1871. void MacAddress::format_output() const
  1872. {
  1873.   if (valid_flag)
  1874.     sprintf((char*)output_buffer,"%02x:%02x:%02x:%02x:%02x:%02x",
  1875.     address_buffer[0], address_buffer[1], address_buffer[2],
  1876.     address_buffer[3], address_buffer[4], address_buffer[5]);
  1877.   else
  1878.     *(char*)output_buffer = 0;
  1879.   MacAddress *nc_this = PP_CONST_CAST(MacAddress*, this);
  1880.   nc_this->addr_changed = false;
  1881. }
  1882. unsigned int MacAddress::hashFunction() const
  1883. {
  1884.   return ((((address_buffer[0] << 8) + address_buffer[1]) * HASH0)
  1885. + (((address_buffer[2] << 8) + address_buffer[3]) * HASH1)
  1886.         + (((address_buffer[4] << 8) + address_buffer[5]) * HASH2));
  1887. }
  1888. #endif // _MAC_ADDRESS
  1889. //========================================================================
  1890. //========== Generic Address Implementation ==============================
  1891. //========================================================================
  1892. //-----------[ constructor, no arguments ]--------------------------------
  1893. GenAddress::GenAddress() : Address()
  1894. {
  1895.   ADDRESS_TRACE;
  1896.   // initialize SMI info
  1897.   // BOK: this is generally not used for GenAddress,
  1898.   // but we need this to be a replica of the real address'
  1899.   // smival info so that operator=SnmpSyntax will work.
  1900.   smival.syntax = sNMP_SYNTAX_NULL;                // to be overridden
  1901.   smival.value.string.len = 0;                        // to be overridden
  1902.   smival.value.string.ptr = address_buffer;        // constant
  1903.   valid_flag = false;
  1904.   address = 0;
  1905.   output_buffer[0] = 0;
  1906. }
  1907. //-----------[ constructor with a string argument ]----------------------
  1908. GenAddress::GenAddress(const char  *addr,
  1909.        const Address::addr_type use_type)
  1910. {
  1911.   ADDRESS_TRACE;
  1912.   // initialize SMI info
  1913.   // BOK: smival is generally not used for GenAddress, but
  1914.   //      we need this to be a replica of the real address'
  1915.   //      smival info so that <class>::operator=SnmpSyntax
  1916.   //      will work.
  1917.   smival.syntax = sNMP_SYNTAX_NULL;                // to be overridden
  1918.   smival.value.string.len = 0;                        // to be overridden
  1919.   smival.value.string.ptr = address_buffer;        // constant
  1920.   address = 0;
  1921.   parse_address(addr, use_type);
  1922.   // Copy real address smival info into GenAddr smival
  1923.   // BOK: smival is generally not used for GenAddress, but
  1924.   //      we need this to be a replica of the real address'
  1925.   //      smival info so that <class>::operator=SnmpSyntax
  1926.   //      will work.
  1927.   if (valid_flag ) {
  1928.       smival.syntax = ((GenAddress *)address)->smival.syntax;
  1929.       smival.value.string.len =
  1930.           ((GenAddress *)address)->smival.value.string.len;
  1931.       memcpy(smival.value.string.ptr,
  1932.           ((GenAddress *)address)->smival.value.string.ptr,
  1933.           (size_t)smival.value.string.len);
  1934.   }
  1935.   output_buffer[0] = 0;
  1936. }
  1937. //-----------[ constructor with an Address argument ]--------------------
  1938. GenAddress::GenAddress(const Address &addr)
  1939. {
  1940.   ADDRESS_TRACE;
  1941.   output_buffer[0] = 0;
  1942.   // initialize SMI info
  1943.   // BOK: this is generally not used for GenAddress,
  1944.   // but we need this to be a replica of the real address'
  1945.   // smival info so that operator=SnmpSyntax will work.
  1946.   smival.syntax = sNMP_SYNTAX_NULL;                // to be overridden
  1947.   smival.value.string.len = 0;                        // to be overridden
  1948.   smival.value.string.ptr = address_buffer;        // constant
  1949.   valid_flag = false;
  1950.   // make sure that the object is valid
  1951.   if (!addr.valid()) {
  1952.     address = 0;
  1953.     return;
  1954.   }
  1955.   // addr can be a GenAddress object and calling clone() on that is bad...
  1956.   if (addr.is_gen_address())
  1957.     address = (Address *)(((const GenAddress&)addr).address->clone());
  1958.   else
  1959.     address = (Address*)addr.clone();
  1960.   if (address)
  1961.     valid_flag = address->valid();
  1962.   // Copy real address smival info into GenAddr smival
  1963.   // BOK: smival is generally not used for GenAddress, but
  1964.   //      we need this to be a replica of the real address'
  1965.   //      smival info so that <class>::operator=SnmpSyntax
  1966.   //      will work.
  1967.   if (valid_flag )
  1968.   {
  1969.     smival.syntax = address->get_syntax();
  1970.     smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
  1971.     memcpy(smival.value.string.ptr,
  1972.            ((GenAddress *)address)->smival.value.string.ptr,
  1973.            (size_t)smival.value.string.len);
  1974.   }
  1975. }
  1976. //-----------------[ constructor with another GenAddress object ]-------------
  1977. GenAddress::GenAddress(const GenAddress &addr)
  1978. {
  1979.   ADDRESS_TRACE;
  1980.   output_buffer[0] = 0;
  1981.   // initialize SMI info
  1982.   // BOK: this is generally not used for GenAddress,
  1983.   // but we need this to be a replica of the real address'
  1984.   // smival info so that operator=SnmpSyntax will work.
  1985.   smival.syntax = sNMP_SYNTAX_OCTETS;
  1986.   smival.value.string.len = 0;
  1987.   smival.value.string.ptr = address_buffer;
  1988.   valid_flag = false;
  1989.   // make sure that the object is valid
  1990.   if (!addr.valid_flag)
  1991.   {
  1992.     address = 0;
  1993.     return;
  1994.   }
  1995.   address = (Address *)addr.address->clone();
  1996.   if (address)
  1997.     valid_flag = address->valid();
  1998.   // Copy real address smival info into GenAddr smival
  1999.   // BOK: smival is generally not used for GenAddress, but
  2000.   //      we need this to be a replica of the real address'
  2001.   //      smival info so that <class>::operator=SnmpSyntax
  2002.   //      will work.
  2003.   if (valid_flag )
  2004.   {
  2005.     smival.syntax = ((GenAddress *)address)->smival.syntax;
  2006.     smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
  2007.     memcpy(smival.value.string.ptr,
  2008.            ((GenAddress *)address)->smival.value.string.ptr,
  2009.            (size_t)smival.value.string.len);
  2010.   }
  2011. }
  2012. //------[ assignment GenAddress = GenAddress ]-----------------------------
  2013. GenAddress& GenAddress::operator=(const GenAddress &addr)
  2014. {
  2015.   ADDRESS_TRACE;
  2016.   if (this == &addr) return *this;  // protect against assignment from itself
  2017.   valid_flag = false;
  2018.   if (address)
  2019.   {
  2020.     delete address;
  2021.     address = 0;
  2022.   }
  2023.   if (addr.address)
  2024.     address = (Address *)(addr.address->clone());
  2025.   if (address)
  2026.     valid_flag = address->valid();
  2027.   // Copy real address smival info into GenAddr smival
  2028.   // BOK: smival is generally not used for GenAddress, but
  2029.   //      we need this to be a replica of the real address'
  2030.   //      smival info so that <class>::operator=SnmpSyntax
  2031.   //      will work.
  2032.   if (valid_flag )
  2033.   {
  2034.     smival.syntax = ((GenAddress *)address)->smival.syntax;
  2035.     smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
  2036.     memcpy(smival.value.string.ptr,
  2037.            ((GenAddress *)address)->smival.value.string.ptr,
  2038.            (size_t)smival.value.string.len);
  2039.   }
  2040.   return *this;
  2041. }
  2042. //------[ assignment GenAddress = Address ]--------------------------------
  2043. GenAddress& GenAddress::operator=(const Address &addr)
  2044. {
  2045.   ADDRESS_TRACE;
  2046.   if (this == &addr) return *this;  // protect against assignment from itself
  2047.   valid_flag = false;
  2048.   if (address)
  2049.   {
  2050.     delete address;
  2051.     address = 0;
  2052.   }
  2053.   // addr can be a GenAddress object and calling clone() on that is bad...
  2054.   if (addr.is_gen_address())
  2055.     address = (Address *)(((const GenAddress&)addr).address->clone());
  2056.   else
  2057.     address = (Address*)addr.clone();
  2058.   if (address)
  2059.     valid_flag = address->valid();
  2060.   // Copy real address smival info into GenAddr smival
  2061.   // BOK: smival is generally not used for GenAddress, but
  2062.   //      we need this to be a replica of the real address'
  2063.   //      smival info so that <class>::operator=SnmpSyntax
  2064.   //      will work.
  2065.   if (valid_flag )
  2066.   {
  2067.     smival.syntax = ((GenAddress *)address)->smival.syntax;
  2068.     smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
  2069.     memcpy(smival.value.string.ptr,
  2070.            ((GenAddress *)address)->smival.value.string.ptr,
  2071.            (size_t)smival.value.string.len);
  2072.   }
  2073.   return *this;
  2074. }
  2075. //------[ assignment GenAddress = any SnmpSyntax ]-----------------------
  2076. SnmpSyntax& GenAddress::operator=(const SnmpSyntax &val)
  2077. {
  2078.   ADDRESS_TRACE;
  2079.   if (this == &val) return *this; // protect against assignment from itself
  2080.   valid_flag = false;             // will get set to TRUE if really valid
  2081.   if (address)
  2082.   {
  2083.     delete address;
  2084.     address = 0;
  2085.   }
  2086.   if (val.valid())
  2087.   {
  2088.     switch (val.get_syntax() )
  2089.     {
  2090.       //-----[ ip address case ]-------------
  2091.       // BOK: this case shouldn't be needed since there is an explicit
  2092.       // GenAddr=Address assignment that will override this assignment.
  2093.       // Left here for posterity.
  2094.       case sNMP_SYNTAX_IPADDR:
  2095.       {
  2096.         address = new IpAddress(val.get_printable());
  2097.         if (address)
  2098.           valid_flag = address->valid();
  2099.       }
  2100.       break;
  2101.       //-----[ udp address case ]------------
  2102.       //-----[ ipx address case ]------------
  2103.       //-----[ mac address case ]------------
  2104.       // BOK:  This is here only to support GenAddr = primitive OctetStr.
  2105.       // The explicit GenAddr=Address assignment will handle the cases
  2106.       // GenAddr = [UdpAdd|IpxAddr|IpxSock|MacAddr].
  2107.       // Note, using the heuristic of octet str len to determine type of
  2108.       // address to create is not accurate when address lengths are equal
  2109.       // (e.g., UDPIPLEN == MACLEN).  It gets worse if we add AppleTalk or
  2110.       // OSI which use variable length addresses!
  2111.       case sNMP_SYNTAX_OCTETS:
  2112.       {
  2113.         unsigned long val_len;
  2114.         val_len = ((GenAddress &)val).smival.value.string.len;
  2115.         if ((val_len == UDPIPLEN) || (val_len == UDPIP6LEN))
  2116.           address = new UdpAddress;
  2117.         else if ((val_len == IPLEN) || (val_len == IPLEN))
  2118.           address = new IpAddress;
  2119. #ifdef _IPX_ADDRESS
  2120.         else if (val_len == IPXLEN)
  2121.           address = new IpxAddress;
  2122.         else if (val_len == IPXSOCKLEN)
  2123.           address = new IpxSockAddress;
  2124. #endif
  2125. #ifdef _MAC_ADDRESS
  2126.         else  if (val_len == MACLEN)
  2127.           address = new MacAddress;
  2128. #endif
  2129.         if (address)
  2130.         {
  2131.           *address = val;
  2132.           valid_flag = address->valid();
  2133.         }
  2134.       }
  2135.       break;
  2136.     }   // end switch
  2137.   }
  2138.   // Copy real address smival info into GenAddr smival
  2139.   // BOK: smival is generally not used for GenAddress, but
  2140.   //      we need this to be a replica of the real address'
  2141.   //      smival info so that <class>::operator=SnmpSyntax
  2142.   //      will work.
  2143.   if (valid_flag )
  2144.   {
  2145.     smival.syntax = ((GenAddress *)address)->smival.syntax;
  2146.     smival.value.string.len = ((GenAddress *)address)->smival.value.string.len;
  2147.     memcpy(smival.value.string.ptr,
  2148.            ((GenAddress *)address)->smival.value.string.ptr,
  2149.            (size_t)smival.value.string.len);
  2150.   }
  2151.   return *this;
  2152. }
  2153. // redefined parse address for macs
  2154. bool GenAddress::parse_address(const char *addr,
  2155.        const Address::addr_type use_type)
  2156. {
  2157.   ADDRESS_TRACE;
  2158.   if (address) delete address;
  2159.   // try to create each of the addresses until the correct one
  2160.   // is found
  2161.   //BOK: Need to try IPX Sock and IPX before UDP since on Win32,
  2162.   //     gethostbyname() seems to think the ipx network number
  2163.   //     portion is a valid ipaddress string... stupid WinSOCK!
  2164. #ifdef _IPX_ADDRESS
  2165.   if ((use_type == Address::type_invalid) ||
  2166.       (use_type == Address::type_ipxsock))
  2167.   {
  2168.     // ipxsock address
  2169.     address = new IpxSockAddress(addr);
  2170.     valid_flag = address->valid();
  2171.     if (valid_flag && ((IpxSockAddress*)address)->get_socket())
  2172.       return TRUE;   // ok its an ipxsock address
  2173.     delete address;  // otherwise delete it and try another
  2174.   }
  2175.   if ((use_type == Address::type_invalid) ||
  2176.       (use_type == Address::type_ipx))
  2177.   {
  2178.     // ipx address
  2179.     address = new IpxAddress(addr);
  2180.     valid_flag = address->valid();
  2181.     if (valid_flag)
  2182.       return TRUE;   // ok its an ipx address
  2183.     delete address;  // otherwise delete it and try another
  2184.   }
  2185. #endif // _IPX_ADDRESS
  2186.   //TM: Must try the derived classes first...one pitfall of the
  2187.   //following solution is if someone creates with a port/socket of 0 the
  2188.   //class will get demoted to ip/ipx.  The only proper way to do this is
  2189.   //to parse the strings ourselves.
  2190.   if ((use_type == Address::type_invalid) ||
  2191.       (use_type == Address::type_udp))
  2192.   {
  2193.     // udp address
  2194.     address = new UdpAddress(addr);
  2195.     valid_flag = address->valid();
  2196.     if (valid_flag && ((UdpAddress*)address)->get_port())
  2197.       return TRUE;       // ok its a udp address
  2198.     delete address;  // otherwise delete it and try another
  2199.   }
  2200.   if ((use_type == Address::type_invalid) ||
  2201.       (use_type == Address::type_ip))
  2202.   {
  2203.     // ip address
  2204.     address = new IpAddress(addr);
  2205.     valid_flag = address->valid();
  2206.     if (valid_flag)
  2207.       return TRUE;       // ok its an ip address
  2208.     delete address;   // otherwise delete it and try another
  2209.   }
  2210. #ifdef _MAC_ADDRESS
  2211.   if ((use_type == Address::type_invalid) ||
  2212.       (use_type == Address::type_mac))
  2213.   {
  2214.     // mac address
  2215.     address = new MacAddress(addr);
  2216.     valid_flag = address->valid();
  2217.     if (valid_flag)
  2218.       return TRUE;    // ok, its a mac
  2219.     delete address;  // otherwise its invalid
  2220.   }
  2221. #endif // _MAC_ADDRESS
  2222.   address = 0;
  2223.   return FALSE;
  2224. }
  2225. #ifdef SNMP_PP_NAMESPACE
  2226. }; // end of namespace Snmp_pp
  2227. #endif