diff options
Diffstat (limited to 'ACE/ASNMP/asnmp')
43 files changed, 13172 insertions, 0 deletions
diff --git a/ACE/ASNMP/asnmp/ASNMP_Export.h b/ACE/ASNMP/asnmp/ASNMP_Export.h new file mode 100644 index 00000000000..e4c9898f3f5 --- /dev/null +++ b/ACE/ASNMP/asnmp/ASNMP_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl ASNMP +// ------------------------------ +#ifndef ASNMP_EXPORT_H +#define ASNMP_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (ASNMP_HAS_DLL) +# define ASNMP_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && ! ASNMP_HAS_DLL */ + +#if !defined (ASNMP_HAS_DLL) +# define ASNMP_HAS_DLL 1 +#endif /* ! ASNMP_HAS_DLL */ + +#if defined (ASNMP_HAS_DLL) && (ASNMP_HAS_DLL == 1) +# if defined (ASNMP_BUILD_DLL) +# define ASNMP_Export ACE_Proper_Export_Flag +# define ASNMP_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ASNMP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* ASNMP_BUILD_DLL */ +# define ASNMP_Export ACE_Proper_Import_Flag +# define ASNMP_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ASNMP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ASNMP_BUILD_DLL */ +#else /* ASNMP_HAS_DLL == 1 */ +# define ASNMP_Export +# define ASNMP_SINGLETON_DECLARATION(T) +# define ASNMP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ASNMP_HAS_DLL == 1 */ + +// Set ASNMP_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (ASNMP_NTRACE) +# if (ACE_NTRACE == 1) +# define ASNMP_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define ASNMP_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !ASNMP_NTRACE */ + +#if (ASNMP_NTRACE == 1) +# define ASNMP_TRACE(X) +#else /* (ASNMP_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define ASNMP_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (ASNMP_NTRACE == 1) */ + +#endif /* ASNMP_EXPORT_H */ + +// End of auto generated file. diff --git a/ACE/ASNMP/asnmp/ChangeLog b/ACE/ASNMP/asnmp/ChangeLog new file mode 100644 index 00000000000..8d82c1aa36c --- /dev/null +++ b/ACE/ASNMP/asnmp/ChangeLog @@ -0,0 +1,227 @@ +Wed Jan 4 22:50:09 UTC 2006 J.T. Conklin <jtc@acorntoolworks.com> + + * ChangeLog: + + Untabify. + Delete-trailing-whitespace. + + Added "Local Variables" section defining "add-log-time-format" + to a really ugly lambda expression that formats changelog + timestamps in UTC and works with both GNU Emacs and XEmacs. + +Fri May 7 11:40:25 2004 Ossama Othman <ossama@dre.vanderbilt.edu> + + * pdu.cpp (agent_error_reason): + + Really fixed mismatched sprintf() format specifiers this time + around. + +Thu May 6 11:13:25 2004 Ossama Othman <ossama@dre.vanderbilt.edu> + + * oid.cpp (operator+=, OidToStr): + * pdu.cpp (agent_error_reason): + + Fixed warnings regarding mismatch format specifiers and + arguments to sprintf(). + +Thu May 6 11:05:01 2004 Ossama Othman <ossama@dre.vanderbilt.edu> + + * gauge.h: + + Nuked trailing white space. + +Fri Apr 23 11:23:21 2004 Ossama Othman <ossama@dre.vanderbilt.edu> + + * oid.cpp: + + Missed some bool return types for equality operators. + +Thu Apr 22 23:03:48 2004 Ossama Othman <ossama@dre.vanderbilt.edu> + + * address.cpp: + * address.h: + * octet.cpp: + * octet.h: + * oid.cpp: + * oid.h: + * target.cpp: + * target.h: + * vb.cpp: + * vb.h: + + Changed all return types for equality, relational and logical + operators to "bool", as is the norm for modern C++. + +Fri Aug 29 07:57:05 2003 Ossama Othman <ossama@dre.vanderbilt.edu> + + * octet.cpp (to_string_hex): + + Fixed "string literal converted to char *" warning. String + literals are now considered "const" by standard C++. + +Tue Mar 16 16:28:14 1999 David L. Levine <levine@cs.wustl.edu> + + * address.cpp, address.h, asn1.cpp, asn1.h, counter.cpp, ctr64.cpp, + gauge.cpp, integer.cpp, octet.cpp, oid.cpp, pdu.cpp, sagent.cpp, + snmp.cpp, target.cpp, timetick.cpp, transaction.cpp, vb.cpp, + wpdu.cpp: + replaced TRUE with 1, and FALSE and NULL with 0. Thanks to + Achint Sandhu <sandhu@nortelnetworks.com> for reporting that + TRUE and FALSE weren't define on his Linux platform. + + * wpdu.cpp (set_trap_info): wrapped condition with () to + avoid g++ warning about using result of an assignment as + the condition. + + * ctr64.cpp: made MAX64 unsigned, to avoid warning about it + being to big to be signed. + +Wed Jul 15 20:27:23 1998 Mike MacFaden <mrm@tango.cs.wustl.edu> + * asn1.cpp - Hien Nguyen <hnguyen@apexgrp.com> fixed these bugs: + + Problem: The V1 trap agent-addr field tag value is OCTET STRING + instead of IPADDRESS, and the time stamp field tag value is INTEGER + instead of TIME TICKS. + + Fix: Change cmu_snmp::build() to pass in the correct type for agent-addr + and time stamp. + + 2. Problem: The V1 trap enterprise OID is corrupted after is was set in + wpdu constructor. + + Fix: In wpdu::set_trap_info(), the raw_pdu enterprise OID pointer was + assigned to the raw data of an enterprise Oid object on the stack. + Changed to perform an ACE_NEW_RETURN on the raw_pdu->enterprise and + perform a memcpy to copy the OID. The allocated memory is freed in + cmu_snmp::free_pdu() as currently implemented. + + 3. The V1 trap agent-addr field is currently initialized to "0.0.0.0". + I changed wpdu::set_trap_info to initialize it to the local host IP + Address. + + 4. I noticed that the memory allocation for OID in asn1.cpp using + ACE_NEW consistently use (OID length * size(oid)) as the size. + Shouldn't it be simply OID length ? Since there are numerous instances + of this usage in asn1.cpp, I have not fixed those. If you can double + check and fix these, I appreciate it. + + +Wed Aug 20 15:11:23 1997 Mike MacFaden <mrm@tango.cs.wustl.edu> + + * rebuilt Makefile using g++dep + + * pdu.h pdu.cpp initialization errors fixed + + * address.h address.cpp IpAddress::to_octet() added + +Fri Aug 1 19:23:52 1997 Mike MacFaden (mrm@mrm-ss20) + + * NOTES: This first version only tested on Solaris 2.5 + + * review classes for thread safety. Current thread design only + allows for one thread to safely access any ASNMP object created. + + * run purify test of get routine no -memory leaks. + + * verify both shared archive/static archive types work with + example programs + + * << Globals Changes >> + + * tested only archiver library version + + * reformat code to use one brace style. + + * changed all manifest constants defined as _XX to XX_ to stay out + of compiler namespace + + * change all OS calls to use ACE_OS:: portability layer, #include + <ace/OS.h> + + * reformat code to use one consistent brace layout and redo + header using ACE + + * remove semicolons on member functions foo{}; - not necessary + + * make get() methods const member functions + + * removed unnecessary casts that looked like this: and revamped + all memory allocations via ACE_NEW macro + + new_oid = (SmiLPUINT32) new unsigned long [ smival.value.oid.len + + To + + ACE_NEW(new_oid, SmiUINT32[ smival.value.oid.len]) + + * Collapsed default constructors with constructors to constructors + with default arguments. + + * removed unused #include <iostream.h> + + * Added ACE_TRACE() to classes + + * change get_printable() to to_string() - there will be more java + programmers in the future so this should be the first step... + + * removed ASYNC interface till it can be rebuilt using ACE patterns + + * Attempt to make interface more type strict but leaving generic + interfaces as escape hatch. Example: CTarget becomes UdpTarget + for UDP/IP based agents. + + * << Class Specific Changes >> + + * Oid class: + - remove char * routines, simplify class + - added suboid method and removed get_printable() overloads + + * CTarget class: + - renamed to UdpTarget. Stay out of Microsoft Namespace per MSJ + Article by Allen Hollub. + + * Varbind class: + - remove generic set_value for char,int, etc. Too easy to get + this wrong. Allow just types defined. + - added overload for equality operator (==) + - added new constructor to allow setting full vb state oid,value, exception + - add to_string() + + * Address class: + - change manifest constants to enums for address lengths, add IP V6 lens + + - add a netbios name class, still pretty worthless since I don't have spec + in front of me yet... + + - rewrite resolver calls to be thread safe and cleaner by moving to two + class (static) member functions: + + // thread safe routine to lookup ip address given hostname + // return <> 0 on error + static int resolve_to_addr(const char *hostname, in_addr& quad_addr); + + // thread safe routine to lookup name given ip address + // return <> 0 on error + static int resolve_to_hostname(const in_addr& quad_addr, char *hostname) + + * added some interrogation routines to class IpAddress: + is_loopback() const; + + * Ctr64 class: + - added constructor using long long datatype (needs to be made + portable to NT + + * Pdu class: add to_string() + + * Classes added wpdu class: + - a new adpater class between CMU and HP pdu, varbind data structures + + * transaction class: + - implement get/getnext timeout and retry logic using ACE + Reactor class, ACE_Time_Value + +Local Variables: +mode: change-log +add-log-time-format: (lambda () (progn (setq tz (getenv "TZ")) (set-time-zone-rule "UTC") (setq time (format-time-string "%a %b %e %H:%M:%S %Z %Y" (current-time))) (set-time-zone-rule tz) time)) +indent-tabs-mode: nil +End: diff --git a/ACE/ASNMP/asnmp/Makefile.am b/ACE/ASNMP/asnmp/Makefile.am new file mode 100644 index 00000000000..71347a6d858 --- /dev/null +++ b/ACE/ASNMP/asnmp/Makefile.am @@ -0,0 +1,66 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu + +ACE_BUILDDIR = $(top_builddir) +ACE_ROOT = $(top_srcdir) + +## Makefile.asnmp_lib.am + +noinst_LTLIBRARIES = libasnmp.la + +libasnmp_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(ACE_ROOT)/ASNMP \ + -DASNMP_BUILD_DLL + +libasnmp_la_SOURCES = \ + address.cpp \ + asn1.cpp \ + counter.cpp \ + ctr64.cpp \ + gauge.cpp \ + integer.cpp \ + octet.cpp \ + oid.cpp \ + pdu.cpp \ + sagent.cpp \ + snmp.cpp \ + target.cpp \ + timetick.cpp \ + transaction.cpp \ + vb.cpp \ + wpdu.cpp + +noinst_HEADERS = \ + address.h \ + asn1.h \ + counter.h \ + ctr64.h \ + gauge.h \ + integer.h \ + octet.h \ + oid.h \ + pdu.h \ + sagent.h \ + snmp.h \ + target.h \ + timetick.h \ + transaction.h \ + vb.h \ + wpdu.h + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/ACE/ASNMP/asnmp/TODO b/ACE/ASNMP/asnmp/TODO new file mode 100644 index 00000000000..12beb91406b --- /dev/null +++ b/ACE/ASNMP/asnmp/TODO @@ -0,0 +1,25 @@ +This is the todo list aka wish list: feel free to add/implmement +Fri Aug 1 19:40:55 PDT 1997 + +0) collapse CMU and HP code - make this thing faster since it is really + slow and bulky... + +1) implement response time statistics collection so that timeout can vary based + on empirical response times + +2) Implement pdu fragmentation based on tooBig errors or app directed + Snmp::set_pdu_max_size() command + +3) implement async interface + +4) make templatized version to implement sync/nonsync (thread safe version) + +5) add V2c when a real agent is in the field that supports it + +6) Add DISMAN support when IETF approves the Expression Mib + +7) way too many procedural case stmts in the code... + +8) add compare_right() method to be orthogonal to oid class. + + diff --git a/ACE/ASNMP/asnmp/address.cpp b/ACE/ASNMP/asnmp/address.cpp new file mode 100644 index 00000000000..8231868bd89 --- /dev/null +++ b/ACE/ASNMP/asnmp/address.cpp @@ -0,0 +1,2705 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// address.cpp +// +// = DESCRIPTION +// The Vb class is an encapsulation of the snmp variable binding. +// This module contains the class definition for the variable binding (VB) +// class. The VB class is an encapsulation of a SNMP VB. A VB object is +// composed of one SNMP++ Oid and one SMI value. The Vb class utilizes Oid +// objects and thus requires the Oid class. To use this class, +// set oid, value then call valid() to be sure object was constructed correctly. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. + =====================================================================*/ + +#include "asnmp/address.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_arpa_inet.h" +#include "ace/OS_NS_netdb.h" +#include "ace/OS_NS_stdlib.h" +#include "ace/OS_NS_stdio.h" +#include "ace/os_include/os_ctype.h" +#include "ace/OS_Memory.h" + +ACE_RCSID(asnmp, address, "$Id$") + +//================================================================= +//======== Abstract Address Class Implementation ================== +//================================================================= + +// allow destruction of derived classes +Address::~Address() +{ +} + + +//----------------------------------------------------------------- +// is the address object valid? +int Address::valid() const +{ + return valid_flag; +} + +//------------[ Address::trim_white_space( char * ptr) ]------------ +// destructive trim white space +void Address::trim_white_space( char * ptr) +{ + char *tmp; + + tmp = ptr; + // skip leading white space + while (*tmp==' ')tmp++; + ACE_OS::strcpy(ptr,tmp); + + // find end of string + while ((*tmp!=' ') && (*tmp !=0)) tmp++; + if (*tmp!=0) *tmp=0; +} + +//TM: this is not used nor needed, remove? +//-----[ element access ]---------------------------------------------- +unsigned char& Address::operator[]( const int position) +{ + if ( position < MAX_ADDR_SZ) + return address_buffer[ position]; + else + return address_buffer[0]; +} + + +//----------------------------------------------------------------------- +// overloaded equivlence operator, are two addresses equal? +bool operator==( const Address &lhs, const Address &rhs) +{ + if ( ACE_OS::strcmp( (const char*) lhs, (const char*)rhs)==0) + return true; + else + return false; +} + +//----------------------------------------------------------------------- +// overloaded equivlence operator, are two addresses equal? +bool operator!=( const Address &lhs, const Address &rhs) +{ + return (!( lhs == rhs)); +} + + +//------------------------------------------------------------------ +// overloaded > operator, is a1 > a2 +bool operator>( const Address &lhs, const Address &rhs) +{ + if (ACE_OS::strcmp( (const char*) lhs, (const char*)rhs)>0) + return true; + else + return false; +} + +// overloaded >= operator, is a1 > a2 +bool operator>=( const Address &lhs,const Address &rhs) +{ + if (( lhs > rhs) || ( lhs == rhs)) + return true; + else + return false; +} + +// overloaded < operator, is a1 <= a2 +bool operator<=( const Address &lhs,const Address &rhs) +{ + if (( lhs < rhs) || ( lhs == rhs)) + return true; + else + return false; + +} + + +//----------------------------------------------------------------- +// overloaded < operator, is a1 < a2 +bool operator<( const Address &lhs, const Address &rhs) +{ + if (ACE_OS::strcmp( (const char*) lhs, (const char*)rhs)<0) + return true; + else + return false; +} + +//------------------------------------------------------------------ +// equivlence operator overloaded, are an address and a string equal? +bool operator==( const Address &lhs,const char *rhs) +{ + if (!rhs && !lhs.valid()) + return true; + if (ACE_OS::strcmp( (const char *) lhs, rhs)== 0) + return true; + else + return false; +} + +//------------------------------------------------------------------ +// not equal operator overloaded, are an address and a string not equal? +bool operator!=( const Address &lhs,const char *rhs) +{ + return (!( lhs == rhs)); +} + +//------------------------------------------------------------------ +// overloaded > , is a > inaddr +bool operator>( const Address &lhs,const char *rhs) +{ + if (!rhs) + return lhs.valid(); // if lhs valid then > 0, else invalid !> 0 + if (ACE_OS::strcmp( (const char *) lhs, rhs)> 0) + return true; + else + return false; +} + +//------------------------------------------------------------------ +// overloaded >= , is a >= inaddr +bool operator>=( const Address &lhs,const char *rhs) +{ + if (!rhs) + return true; // always >= 0 + if (ACE_OS::strcmp( (const char *) lhs, rhs)>= 0) + return true; + else + return false; +} + +//----------------------------------------------------------------- +// overloaded < , are an address and a string equal? +bool operator<( const Address &lhs,const char *rhs) +{ + if (!rhs) + return false; // always >= 0 + if (ACE_OS::strcmp( (const char *) lhs, rhs)< 0) + return true; + else + return false; +} + +//----------------------------------------------------------------- +// overloaded <= , is a <= inaddr +bool operator<=( const Address &lhs,const char *rhs) +{ + if (!rhs) + return !lhs.valid(); // invalid == 0, else valid > 0 + if (ACE_OS::strcmp( (const char *) lhs, rhs) <= 0) + return true; + else + return false; +} + + +//===================================================================== +//============ IPAddress Implementation =============================== +//===================================================================== + +//-----------[ syntax type ]---------------------------------------------- +SmiUINT32 IpAddress::get_syntax() +{ + return sNMP_SYNTAX_IPADDR; +} + +//-----[ IP Address copy constructor ]--------------------------------- +IpAddress::IpAddress(const IpAddress &ipaddr) + : Address (ipaddr) +{ + // always initialize what type this object is + smival.syntax = sNMP_SYNTAX_IPADDR; + smival.value.string.len =IPV4LEN; + smival.value.string.ptr = address_buffer; + + iv_friendly_name_[0] = 0; + iv_friendly_name_status_ = 0; + valid_flag = ipaddr.valid_flag; + if (valid_flag) { + ACE_OS::memcpy(address_buffer, ipaddr.address_buffer,IPV4LEN); + ACE_OS::strcpy( iv_friendly_name_, ipaddr.iv_friendly_name_); + } + + IpAddress::format_output(); +} + + +//-------[ default construct, an IP address with a string ]--------------------- +IpAddress::IpAddress( const char *inaddr): Address() +{ + // always initialize what type this object is + smival.syntax = sNMP_SYNTAX_IPADDR; + smival.value.string.len = IPV4LEN; + smival.value.string.ptr = address_buffer; + + if (ACE_OS::strlen(inaddr) == 0) { + + valid_flag = 0; + iv_friendly_name_[0] = 0; + iv_friendly_name_status_ = 0; + IpAddress::format_output(); + return; + } + + // parse_address initializes valid, address_buffer & iv_friendly_name_ + valid_flag = parse_address(inaddr); + IpAddress::format_output(); +} + + +//-----[ construct an IP address with a GenAddress ]--------------------- +IpAddress::IpAddress( const GenAddress &genaddr) +{ + // always initialize what type this object is + smival.syntax = sNMP_SYNTAX_IPADDR; + smival.value.string.len = IPV4LEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + iv_friendly_name_[0] = 0; + iv_friendly_name_status_ = 0; + // allow use of an ip or udp genaddress + if (genaddr.get_type() == type_ip) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the IP address data + IpAddress temp_ip( (const char *) genaddr); + *this = temp_ip; + } + } + else + if (genaddr.get_type() == type_udp) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the IP address data + UdpAddress temp_udp( (const char *) genaddr); + *this = temp_udp; + } + } + IpAddress::format_output(); +} + +//-----[ destructor ]-------------------------------------------------- +IpAddress::~IpAddress() +{ +} + +// assumes member data is word aligned to avoid sigbus +int IpAddress::is_loopback() const +{ + if (valid()) { + return (*(u_long *)&address_buffer == INADDR_LOOPBACK); + } + return 0; +} + +int IpAddress::is_multicast() const +{ + if (valid()) { + return (IN_MULTICAST(*(u_long *)&address_buffer)); + } + return 0; +} + +// Private addressess not are not assignable in the Internet, they are +// defined in RFC 1597 as: 10, 172.16, and 192.168.0 +// Some companies use them internally and apply NAT to allow translation +// instead of paying for ip networks. +// Cisco IOS devices can provide NAT aka Network Address Translation +// but don't expect SNMP based networks to handle cross-NAT address spaces. +// assumes storage in network byte order mrm@cisco.com 7/28/97 + +int IpAddress::is_private() const +{ + if (valid()) { + if (address_buffer[0] == 10) + return 1; + if (address_buffer[0] == 172 && address_buffer[1] == 16) + return 1; + if (address_buffer[0] == 192 && address_buffer[1] == 168 && + address_buffer[2] == 0) + return 1; + } + return 0; +} + + +// convert address into octet string format in network byte order +void IpAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + + +int IpAddress::is_broadcast() const +{ + if (valid()) { + return ( (*(u_long *)&address_buffer) & INADDR_BROADCAST); + } + return 0; +} + +//-----[ IP Address general = operator ]------------------------------- +SnmpSyntax& IpAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will get set 1 if really valid + iv_friendly_name_[0]=0; + + if (val.valid()) { + switch (val.get_syntax()) { + case sNMP_SYNTAX_IPADDR: + case sNMP_SYNTAX_OCTETS: + if (((IpAddress &)val).smival.value.string.len ==IPV4LEN) { + ACE_OS::memcpy(address_buffer, + ((IpAddress &)val).smival.value.string.ptr,IPV4LEN); + valid_flag = 1; + } + break; + + // NOTE: as a value add, other types could have "logical" + // mappings, i.e. integer32 and unsigned32 + } + } + IpAddress::format_output(); + return *this; +} + +//------[ assignment to another ipaddress object overloaded ]----------------- +IpAddress& IpAddress::operator=( const IpAddress &ipaddress) +{ + // protect against assignment from itself + if ( this == &ipaddress ) + return *this; + + valid_flag = ipaddress.valid_flag; + iv_friendly_name_[0]=0; + + if (valid_flag) { + ACE_OS::memcpy(address_buffer, ipaddress.address_buffer, IPV4LEN); + ACE_OS::strcpy(iv_friendly_name_, ipaddress.iv_friendly_name_); + } + IpAddress::format_output(); + return *this; +} + + +//--------[ create a new instance of this Value ]----------------------- +SnmpSyntax *IpAddress::clone() const +{ + return (SnmpSyntax *) new IpAddress(*this); +} + +//-------[ return the Fully Qualified Domain Name ]---------------------- +const char *IpAddress::resolve_hostname(int &status) +{ + if ((iv_friendly_name_[0] == 0) && valid_flag) + addr_to_friendly(); + status = iv_friendly_name_status_; + return iv_friendly_name_; +} + +// parse a dotted string +int IpAddress::parse_dotted_ipstring( const char *inaddr) +{ + char *ip_token; + int token_count=0; + unsigned int value; + int error_status = 0; + char temp[MAXHOSTNAMELEN +1]; // temp buffer for destruction + int z,w; + + // check len, an ip can never be bigger than 15 + // 123456789012345 + // XXX.XXX.XXX.XXX + if ( !inaddr || (ACE_OS::strlen( inaddr) > 30)) + return 0; + ACE_OS::strcpy( temp, inaddr); + trim_white_space( temp); + if ( ACE_OS::strlen( temp) > 15) + return 0; + + // must only have three dots + // strtok will not catch this ! + char *ptr = temp; + int dot_count = 0; + while ( *ptr != 0) { + if ( *ptr == '.') dot_count++; + ptr++; + } + if ( dot_count != 3) + return 0; + + // look for dot token separator + ip_token = ACE_OS::strtok( (char *) temp,"."); + + // while more tokens.. + while ( ip_token != 0) { + // verify that the token is all numerics + w = ACE_OS::strlen( ip_token); + if (w>3) + return 0; + for (z=0;z<w;z++) + if (( ip_token[z] < '0') || ( ip_token[z] > '9')) + return 0; + + value = ( unsigned int) strtod(ip_token,0); + if (( value > 0)&& ( value <=255)) + address_buffer[token_count] = (unsigned char) value; + else + if (ACE_OS::strcmp(ip_token,"0")==0) + address_buffer[token_count]= (unsigned char) 0; + else + error_status = 1; + token_count++; + ip_token = ACE_OS::strtok( 0, "."); + } + + // gota be four in len + if ( token_count != 4) + return 0; + + // any parsing errors? + if ( error_status) + return 0; + + return 1; +} + +//-----[ IP Address parse Address ]--------------------------------- +int IpAddress::parse_address( const char *inaddr) +{ + // parse the input char array + // fill up internal buffer with four ip bytes + // set and return validity flag + + in_addr ipAddr; + char ds[MAXHOSTNAMELEN +1]; + + // intialize the friendly_name member variable + iv_friendly_name_[0] = 0; + iv_friendly_name_status_ = 0; + + // is this a dotted IP notation string or + // a friendly name + if ( parse_dotted_ipstring( inaddr)) { + + // since this is a valid dotted string + // don't do any DNS (Performance!) + return 1; + } + else { + int rc; + if ((rc = resolve_to_address(inaddr, ipAddr)) == 0) { + + // now lets check out the dotted string + ACE_OS::strncpy( ds, ACE_OS::inet_ntoa(ipAddr), MAXHOSTNAMELEN); + + if ( !parse_dotted_ipstring( ds)) + return 0; + + // save the friendly name + ACE_OS::strcpy( iv_friendly_name_, inaddr); + + } // end if lookup result + else { + iv_friendly_name_status_ = rc; + return 0; + } + } // end else not a dotted string + return 1; +} + +// using the currently defined address, do a DNS +// and try to fill up the name +int IpAddress::addr_to_friendly() +{ + in_addr ipAddr; + long result = ACE_OS::inet_addr(to_string()); + if (result == -1) + return -1; // expected a dotted quad! + + ipAddr.s_addr = result; + + // set iv_friendly_name_ from ipAddr + if (resolve_to_hostname(ipAddr, iv_friendly_name_) == 0) { + return 0; + } + else { +#if defined (VXWORKS) + // VxWorks doesn't have h_errno + iv_friendly_name_status_ = errno; +#else + iv_friendly_name_status_ = h_errno; +#endif /* VXWORKS */ + return iv_friendly_name_status_; + } +} + +// static aka class member function (1.2.3.4 -> foo.com) +int IpAddress::resolve_to_hostname(const in_addr& quad_addr, char *hostname) +{ + struct hostent lookupResult; + int loc_errno = 0; + ACE_HOSTENT_DATA buffer; + ACE_OS::memset(&lookupResult, 0, sizeof(struct hostent)); + ACE_OS::memset(&buffer, 0, sizeof(ACE_HOSTENT_DATA)); + + // reverse lookup (requires in-addr.arpa to be setup in DNS + if (ACE_OS::gethostbyaddr_r((const char *)&quad_addr.s_addr, IPV4LEN, + AF_INET, &lookupResult, buffer, &loc_errno)) { + + // verify right type of record + if (lookupResult.h_addrtype == AF_INET && + lookupResult.h_length == IPV4LEN) { + ACE_OS::strcpy( hostname, lookupResult.h_name); + // setup multiple entries + return 0; + } + else { + ACE_ASSERT(0); // todo add trace and debug and dump + return -1; // wrong resource record type + } + } + + return loc_errno; +} + +// static aka class member function (foo.com -> 1.2.3.4) +int IpAddress::resolve_to_address(const char *hostname, in_addr& quad_addr) +{ + struct hostent lookupResult; + ACE_HOSTENT_DATA buffer; + ACE_OS::memset(&buffer, 0, sizeof(ACE_HOSTENT_DATA)); + ACE_OS::memset(&lookupResult, 0, sizeof(struct hostent)); + int loc_errno = 0; + if (ACE_OS::gethostbyname_r( hostname, &lookupResult, buffer, &loc_errno)) { + if (lookupResult.h_length == sizeof(in_addr) && + lookupResult.h_addrtype == AF_INET) { + ACE_OS::memcpy((void *) &quad_addr, + (void *) lookupResult.h_addr_list[0], sizeof(in_addr)); + return 0; + } + else + return -1; // wrong address size + } + return loc_errno; +} + +//----[ IP address char * cast ]-------------------------------------- +IpAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +//----[ IP address get char representation ]-------------------------- +const char * IpAddress::to_string() +{ + return (char *)output_buffer; +} + +//----[ IP address format output ]------------------------------------ +void IpAddress::format_output() +{ + // if valid format else null it + if ( valid_flag) + ACE_OS::sprintf( (char *) output_buffer,"%d.%d.%d.%d",address_buffer[0], + address_buffer[1], address_buffer[2], address_buffer[3]); + else + output_buffer[0] = 0; +} + +//------[ return the type ]---------------------------------- +addr_type IpAddress::get_type() const +{ + return type_ip; +} + +//----------------------------------------------------------------- +// logically and two IPaddresses and +// return the new one +void IpAddress::mask( const IpAddress& ipaddr) +{ + if ( this->valid() && ipaddr.valid()) { + this->address_buffer[0] = this->address_buffer[0] & ipaddr.address_buffer[0]; + this->address_buffer[1] = this->address_buffer[1] & ipaddr.address_buffer[1]; + this->address_buffer[2] = this->address_buffer[2] & ipaddr.address_buffer[2]; + this->address_buffer[3] = this->address_buffer[3] & ipaddr.address_buffer[3]; + format_output(); + } + +} + +//======================================================================= +//========== DNS Iterator Implementation ================================ +//======================================================================= + + +Address_Iter::Address_Iter(const char *hostname): valid_(0), count_(0), + entry_(0) +{ + ACE_OS::memset(&buffer_, 0, sizeof(ACE_HOSTENT_DATA)); + ACE_OS::memset(&lookupResult_, 0, sizeof(struct hostent)); + if (ACE_OS::inet_addr(hostname) == (unsigned long) -1) + valid_ = query_dns(hostname); + else { + ACE_ASSERT(0); // don't support dot-quad lookup yet + } + + // count number of hostnames + int n; + char **pc; + for (n = 0, pc = lookupResult_.h_addr_list; *pc != 0; ++n, ++pc); + count_ = n; // plus first one + entry_ = lookupResult_.h_addr_list; +} + +int Address_Iter::valid() const +{ + return (valid_ == 1); +} + +int Address_Iter::how_many_addresses() +{ + return count_; +} + +// return next entry, rc = 0, if entry is null return 0 +int Address_Iter::next(IpAddress& addr) +{ + if (!entry_ || *entry_ == 0) + return 1; + + IpAddress tmp(*entry_++); // return data + addr = tmp; + if (*entry_ == 0) + return 1; + return 0; +} + +// query DNS here +int Address_Iter::query_dns(const char *hostname) +{ + int loc_errno = 0; + if (ACE_OS::gethostbyname_r( hostname, &lookupResult_, buffer_, + &loc_errno)) { + if (lookupResult_.h_length == sizeof(IPV4LEN) && + lookupResult_.h_addrtype == AF_INET) { + return 0; + } + else + return -1; // wrong address size + } + return loc_errno; +} + +//======================================================================= +//========== Udp Address Implementation ================================= +//======================================================================= + +//-----------[ syntax type ]---------------------------------------------- +SmiUINT32 UdpAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +//-----------------[ construct an Udp address with another Udp address ]--- +UdpAddress::UdpAddress( const UdpAddress &udpaddr):IpAddress(udpaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = UDPIPV4LEN; + smival.value.string.ptr = address_buffer; + + // Copy the port value + set_port(udpaddr.get_port()); + format_output(); +} + +// default constructor with a dotted string +UdpAddress::UdpAddress( const char *inaddr):IpAddress() +{ + if (ACE_OS::strlen(inaddr) == 0) { + // Inherits IP Address attributes + // Always initialize (override) what type this object is + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = UDPIPV4LEN; + smival.value.string.ptr = address_buffer; + set_port(0); + format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = UDPIPV4LEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *)inaddr); + format_output(); +} + +//-----------------[ construct a UdpAddress from a GenAddress ]-------------- +UdpAddress::UdpAddress( const GenAddress &genaddr):IpAddress() +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = UDPIPV4LEN; + smival.value.string.ptr = address_buffer; + + unsigned int port = 0; + valid_flag = 0; + + // allow use of an ip or udp genaddress + if (genaddr.get_type() == type_udp) + { + valid_flag = genaddr.valid(); + if ( valid_flag) + { + // copy in the IP address data + UdpAddress temp_udp( (const char *) genaddr); + *this = temp_udp; + + // port info since are making an UpAddress + port = temp_udp.get_port(); + } + } + else + if (genaddr.get_type() == type_ip) + { + valid_flag = genaddr.valid(); + if ( valid_flag) + { + // copy in the IP address data + IpAddress temp_ip( (const char *) genaddr); + *this = temp_ip; + } + } + set_port(port); + format_output(); +} + + +//--------[ construct a udp from an IpAddress ]-------------------------- +UdpAddress::UdpAddress( const IpAddress &ipaddr):IpAddress(ipaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = UDPIPV4LEN; + smival.value.string.ptr = address_buffer; + + set_port(0); + format_output(); +} + + +//-----[ destructor ]-------------------------------------------------- +UdpAddress::~UdpAddress() +{ +} + + + // copy an instance of this Value +SnmpSyntax& UdpAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag=0; // will get set 1 if really valid + if (val.valid()){ + switch (val.get_syntax()){ + case sNMP_SYNTAX_IPADDR: + { + UdpAddress temp_udp(val.to_string()); + *this = temp_udp; // valid_flag is set by the udp assignment + } + break; + + case sNMP_SYNTAX_OCTETS: + if (((UdpAddress &)val).smival.value.string.len == UDPIPV4LEN){ + ACE_OS::memcpy(address_buffer, + ((UdpAddress &)val).smival.value.string.ptr, UDPIPV4LEN); + iv_friendly_name_[0] = 0; + valid_flag = 1; + } + break; + + // NOTE: as a value add, other types could have "logical" + // mappings, i.e. integer32 and unsigned32 + } + } + format_output(); + return *this; +} + + // assignment to another UdpAddress object overloaded +UdpAddress& UdpAddress::operator=( const UdpAddress &udpaddr) +{ + // protect against assignment from itself + if ( this == &udpaddr ) + return *this; + + (IpAddress &)*this = udpaddr; // use ancestor assignment for ipaddr value + set_port(udpaddr.get_port()); // copy to port value + format_output(); + return *this; +} + + +//-----[ IP Address parse Address ]--------------------------------- +int UdpAddress::parse_address( const char *inaddr) +{ + char buffer[MAXHOSTNAMELEN +1]; + + unsigned short port = 0; + if (inaddr && (ACE_OS::strlen( inaddr)< MAXHOSTNAMELEN +1)) + ACE_OS::strcpy( buffer, inaddr); + else { + valid_flag = 0; + return 0; + } + // look for port info @ the end of the string + // port can be delineated by a ':' or a '/' + // if neither are present then just treat it + // like a normal IpAddress + char *tmp; + tmp = ACE_OS::strstr( buffer,":"); + if (tmp==0) + tmp = ACE_OS::strstr(buffer,"/"); + + if ( tmp != 0) { + *tmp=0; // null terminator + tmp++; + port = ACE_OS::atoi( tmp); + } + + set_port(port); + return IpAddress::parse_address( buffer); +} + + +//----------[ create a new instance of this Value ]------------------------ +SnmpSyntax *UdpAddress::clone() const +{ + return (SnmpSyntax *) new UdpAddress(*this); +} + +//--------[ set the port number ]--------------------------------------- +void UdpAddress::set_port( const unsigned short p) +{ + unsigned short port_nbo = htons(p); + ACE_OS::memcpy(&address_buffer[IPV4LEN], &port_nbo, 2); + format_output(); +} + +//---------[ get the port number ]-------------------------------------- +unsigned short UdpAddress::get_port() const +{ + if (valid_flag) { + unsigned short port_nbo; + ACE_OS::memcpy(&port_nbo, &address_buffer[IPV4LEN], 2); + return ntohs(port_nbo); + } + else + return 0; // don't use uninitialized memory +} + +//------[ return the type ]-------------------------------------------- +addr_type UdpAddress::get_type() const +{ + return type_udp; +} + +//----[ UDP address char * cast ]-------------------------------------- +UdpAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +//----[ UDP address get char representation ]-------------------------- +const char * UdpAddress::to_string() +{ + return (char *)output_buffer; +} + +// make format same as ACE_INET_Addr class (addr:port) +void UdpAddress::format_output() +{ + IpAddress::format_output(); // allow ancestors to format their buffers + + // if valid format else null it + if ( valid_flag) + ACE_OS::sprintf( (char *) output_buffer,"%s:%d", + IpAddress::to_string(), + get_port() ); + else + output_buffer[0] = 0; +} + + +//======================================================================= +//=========== Netbios Address Implementation ============================ +//======================================================================= + +void NetbiosAddress::format_output() +{ + if ( valid_flag) + ACE_OS::memcpy(output_buffer, address_buffer, NETBIOSLEN); + else + output_buffer[0] = 0; +} + +void NetbiosAddress::InitNBAddr(const char *inaddr) +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = NETBIOSLEN; + smival.value.string.ptr = address_buffer; + + valid_flag=0; + NetbiosAddress::format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + NetbiosAddress::format_output(); +} + +// TODO: how to handle addresses < 15 chars (zero out or pad with ' ') +NetbiosAddress::NetbiosAddress( const char *inaddr) +{ + InitNBAddr(inaddr); + +} + +NetbiosAddress::NetbiosAddress( const char *inaddr, nb_service svc) +{ + InitNBAddr(inaddr); + address_buffer[15] = svc; +} + +// TODO: go back over ms/ibm specs and verify this +// 16 chars, 15 can be any character, 16th is service number between 0 and 20 +// names beginning with IBM are reserved, and hence invalid +// and doubt IBM would use this class anyway +int NetbiosAddress::parse_address(const char *address) +{ + if (ACE_OS::strlen(address) > NETBIOSLEN) + return 0; // invalid + + if (ACE_OS::strncmp(address, "IBM", 3) == 0) + return 0; // invalid + + // addresses are free form but this check may need to be expose to user + // + //if (address[15] < nb_workstation || address[15] > nb_server) + // return 0; //invalid service type + + ACE_OS::memset(address_buffer, 0, NETBIOSLEN); + ACE_OS::memcpy(address_buffer, address, NETBIOSLEN); + + return 1; // valid +} + +NetbiosAddress::NetbiosAddress( const NetbiosAddress& nbaddr) + : Address (nbaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = NETBIOSLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = nbaddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, nbaddr.address_buffer, NETBIOSLEN); + NetbiosAddress::format_output(); +} + +NetbiosAddress::NetbiosAddress( const GenAddress& genaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = NETBIOSLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_nb) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + NetbiosAddress temp_nb( (const char *) genaddr); + *this = temp_nb; + } + } + NetbiosAddress::format_output(); +} + +NetbiosAddress::~NetbiosAddress() +{ +} + +const char *NetbiosAddress::to_string() +{ + return (char *)output_buffer; +} + +void NetbiosAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + +NetbiosAddress& NetbiosAddress::operator=( const NetbiosAddress &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will set to 1 if really valid + if (val.valid()) { + switch (((NetbiosAddress *) &val)->get_syntax()) { + case sNMP_SYNTAX_OCTETS: + ACE_OS::memcpy(address_buffer, + ((NetbiosAddress &)val).smival.value.string.ptr, NETBIOSLEN); + valid_flag = 1; + break; + } + } + NetbiosAddress::format_output(); + return *this; +} + +nb_service NetbiosAddress::get_service_type() const +{ + return (nb_service) address_buffer[15]; +} + +void NetbiosAddress::set_service_type(nb_service nbservice) +{ + address_buffer[15] = nbservice; + NetbiosAddress::format_output(); +} + +NetbiosAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +SnmpSyntax& NetbiosAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will set to 1 if really valid + if (val.valid()) { + switch (val.get_syntax()) { + case sNMP_SYNTAX_OCTETS: + if (((NetbiosAddress &)val).smival.value.string.len == NETBIOSLEN) { + ACE_OS::memcpy(address_buffer, + ((NetbiosAddress &)val).smival.value.string.ptr, NETBIOSLEN); + valid_flag=1; + } + break; + } + } + NetbiosAddress::format_output(); + return *this; +} + +SnmpSyntax *NetbiosAddress::clone() const +{ + return (SnmpSyntax *) new NetbiosAddress(*this); +} + +SmiUINT32 NetbiosAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +addr_type NetbiosAddress::get_type() const +{ + return type_nb; +} + +//======================================================================= +//=========== IPX Address Implementation ================================ +//======================================================================= + +//-----------[ syntax type ]---------------------------------------------- +SmiUINT32 IpxAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + + +//----------[ default constructor with a string arg ]--------------------------- +IpxAddress::IpxAddress( const char *inaddr):Address( ) +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXLEN; + smival.value.string.ptr = address_buffer; + + separator = '\0'; + valid_flag=0; + IpxAddress::format_output(); + return; + } + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXLEN; + smival.value.string.ptr = address_buffer; + + separator = '\0'; + valid_flag = parse_address( (char *) inaddr); + IpxAddress::format_output(); +} + + +//-----[ IPX Address copy constructor ]---------------------------------- +IpxAddress::IpxAddress(const IpxAddress &ipxaddr) + : Address (ipxaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXLEN; + smival.value.string.ptr = address_buffer; + + separator = '\0'; + valid_flag = ipxaddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, ipxaddr.address_buffer, IPXLEN); + IpxAddress::format_output(); +} + + +//----[ construct an IpxAddress from a GenAddress ]--------------------------- +IpxAddress::IpxAddress( const GenAddress &genaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_ipx) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + IpxAddress temp_ipx( (const char *) genaddr); + *this = temp_ipx; + } + } + else + if ( (genaddr.get_type() == type_ipxsock) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + IpxSockAddress temp_ipxsock( (const char *) genaddr); + *this = temp_ipxsock; + } + } + IpxAddress::format_output(); +} + + +//-----[ destructor ]-------------------------------------------------- +IpxAddress::~IpxAddress() +{ +} + + +//-----[ IPX Address general = operator ]------------------------------- +SnmpSyntax& IpxAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag=0; // will set to 1 if really valid + if (val.valid()){ + switch (val.get_syntax()){ + case sNMP_SYNTAX_OCTETS: + if (((IpxAddress &)val).smival.value.string.len == IPXLEN){ + ACE_OS::memcpy(address_buffer, ((IpxAddress &)val).smival.value.string.ptr, IPXLEN); + valid_flag=1; + } + break; + } + } + IpxAddress::format_output(); + return *this; +} + +//--------[ assignment to another IpAddress object overloaded ]---------- +IpxAddress& IpxAddress::operator=( const IpxAddress &ipxaddress) +{ + // protect against assignment from itself + if ( this == &ipxaddress ) + return *this; + + valid_flag = ipxaddress.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, ipxaddress.address_buffer, IPXLEN); + IpxAddress::format_output(); + return *this; +} + + +// create a new instance of this Value +SnmpSyntax *IpxAddress::clone() const +{ + return (SnmpSyntax *) new IpxAddress(*this); +} + +//-----[ IPX Address parse Address ]----------------------------------- +// Convert a string to a ten byte ipx address +// On success sets validity 1 or 0 +// +// IPX address format +// +// NETWORK ID| MAC ADDRESS +// 01 02 03 04|05 06 07 08 09 10 +// XX XX XX XX|XX XX XX XX XX XX +// +// Valid input format +// +// XXXXXXXX.XXXXXXXXXXXX +// Total length must be 21 +// Must have a separator in it +// First string length must be 8 +// Second string length must be 12 +// Each char must take on value 0-F +// +// +// Input formats recognized +// +// XXXXXXXX.XXXXXXXXXXXX +// XXXXXXXX:XXXXXXXXXXXX +// XXXXXXXX-XXXXXXXXXXXX +// XXXXXXXX.XXXXXX-XXXXXX +// XXXXXXXX:XXXXXX-XXXXXX +// XXXXXXXX-XXXXXX-XXXXXX +int IpxAddress::parse_address( const char *inaddr) +{ + char unsigned *str1,*str2; + char temp[30]; // don't destroy original + char unsigned *tmp; + size_t z, tmplen; + + + // save the orginal source + if (!inaddr || (ACE_OS::strlen( inaddr) >(sizeof(temp)-1))) return 0; + ACE_OS::strcpy( temp, inaddr); + trim_white_space( temp); + tmplen = ACE_OS::strlen(temp); + + // bad total length check + // 123456789012345678901 + // XXXXXXXX-XXXXXXXXXXXX 21 len + // + // XXXXXXXX-XXXXXX-XXXXXX 22 len + // need at least 21 chars and no more than 22 + if ( (tmplen <21) || (tmplen >22)) + return 0; + + // convert the string to all lower case + // this allows hex values to be in upper or lower + for (z=0;z< tmplen;z++) + temp[z] = tolower(temp[z]); + + // check for separated nodeid + // if found remove it + if (temp[15] == '-') + { + for(z=16;z<tmplen;z++) + temp[z-1] = temp[z]; + temp[tmplen-1] = 0; + } + + // no dot or colon separator check + separator = temp[8]; + if (( separator != ':') && + ( separator != '.') && + ( separator != '-') && + ( separator != ' ')) + return 0; + + // separate the strings + str1 = ( unsigned char *) temp; + while( *str1 != separator) str1++; + str2 = str1 + 1; + *str1 = 0; + str1= ( unsigned char *) temp; + + // check len of the network portion + if ( ACE_OS::strlen((char *) str1) != 8) + return 0; + + // check len of mac portion + if ( ACE_OS::strlen( (char *) str2) != 12) + return 0; + + // ok we like then lens, make sure that all chars are 0-f + // check out the net id + tmp = str1; + while( *tmp != 0) + if (((*tmp >= '0') && (*tmp <= '9'))|| // good 0-9 + ((*tmp >= 'a') && (*tmp <= 'f'))) // or a-f + tmp++; + else + return 0; + + // check out the MAC address + tmp = str2; + while( *tmp != 0) + if (((*tmp >= '0') && (*tmp <= '9'))|| // good 0-9 + ((*tmp >= 'a') && (*tmp <= 'f'))) // or a-f + tmp++; + else + return 0; + + // convert to target string + tmp = str1; + while ( *tmp != 0) + { + if (( *tmp >= '0') && ( *tmp <= '9')) + *tmp = *tmp - (char unsigned )'0'; + else + *tmp = *tmp - (char unsigned) 'a' + (char unsigned) 10; + tmp++; + } + + // network id portion + address_buffer[0] = (str1[0]*16) + str1[1]; + address_buffer[1] = (str1[2]*16) + str1[3]; + address_buffer[2] = (str1[4]*16) + str1[5]; + address_buffer[3] = (str1[6]*16) + str1[7]; + + tmp = str2; + while ( *tmp != 0) + { + if (( *tmp >= '0') && ( *tmp <= '9')) + *tmp = *tmp - (char unsigned) '0'; + else + *tmp = *tmp - (char unsigned) 'a'+ (char unsigned) 10; + tmp++; + } + + address_buffer[4] = (str2[0]*16) + str2[1]; + address_buffer[5] = (str2[2]*16) + str2[3]; + address_buffer[6] = (str2[4]*16) + str2[5]; + address_buffer[7] = (str2[6]*16) + str2[7]; + address_buffer[8] = (str2[8]*16) + str2[9]; + address_buffer[9] = (str2[10]*16) + str2[11]; + + return 1; +} + +//----[ IPX address char * cast ]-------------------------------------- +IpxAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +//----[ IPX address get char representation ]-------------------------- +const char * IpxAddress::to_string() +{ + return (char *)output_buffer; +} + + +//----[ IPX address format output ]------------------------------------- +void IpxAddress::format_output() +{ + if ( valid_flag) + ACE_OS::sprintf((char *) output_buffer, + "%02x%02x%02x%02x%c%02x%02x%02x%02x%02x%02x", + address_buffer[0],address_buffer[1], + address_buffer[2],address_buffer[3],'-', + address_buffer[4],address_buffer[5], + address_buffer[6],address_buffer[7], + address_buffer[8],address_buffer[9]); + else + output_buffer[0] = 0; +} + + +// get the host id portion of an ipx address +int IpxAddress::get_hostid( MacAddress& mac) +{ + if ( valid_flag) + { + char buffer[18]; + ACE_OS::sprintf( buffer,"%02x:%02x:%02x:%02x:%02x:%02x", + address_buffer[4], + address_buffer[5], address_buffer[6], address_buffer[7], + address_buffer[8], address_buffer[9]); + MacAddress temp( buffer); + // mac = (SnmpSyntax&) temp; + mac = temp; + if ( mac.valid()) + return 1; + else + return 0; + } + else + return 0; +} + + +//------[ return the type ]---------------------------------- +addr_type IpxAddress::get_type() const +{ + return type_ipx; +} + +void IpxAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + + +//======================================================================== +//======== IpxSockAddress Implementation ================================= +//======================================================================== + +//-----------[ syntax type ]---------------------------------------------- +SmiUINT32 IpxSockAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +//-----------[ construct an IpxSockAddress with another IpxSockAddress]---- +IpxSockAddress::IpxSockAddress( const IpxSockAddress &ipxaddr):IpxAddress(ipxaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXSOCKLEN; + smival.value.string.ptr = address_buffer; + + // copy the socket value + set_socket(ipxaddr.get_socket()); + format_output(); +} + + +//---------------[ default construct a IpxSockAddress ]-------------- +IpxSockAddress::IpxSockAddress( const char *inaddr):IpxAddress() +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXSOCKLEN; + smival.value.string.ptr = address_buffer; + + set_socket(0); + format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXSOCKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + format_output(); +} + + +//---------------[ construct a IpxSockAddress from a GenAddress ]---------- +IpxSockAddress::IpxSockAddress( const GenAddress &genaddr):IpxAddress() +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXSOCKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + unsigned short socketid = 0; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_ipx) ) + { + valid_flag = genaddr.valid(); + if ( valid_flag) + { + // copy in the Ipx address data + IpxAddress temp_ipx( (const char *) genaddr); + *this = temp_ipx; + } + } + else + if ( (genaddr.get_type() == type_ipxsock) ) + { + valid_flag = genaddr.valid(); + if ( valid_flag) + { + // copy in the Ipx address data + IpxSockAddress temp_ipxsock( (const char *) genaddr); + *this = temp_ipxsock; + // socketid info since are making an IpxSockAddress + socketid = temp_ipxsock.get_socket(); + } + } + set_socket(socketid); + format_output(); +} + + +//------------[ construct an IpxSockAddress from a IpxAddress ]-------------- +IpxSockAddress::IpxSockAddress( const IpxAddress &ipxaddr):IpxAddress(ipxaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = IPXSOCKLEN; + smival.value.string.ptr = address_buffer; + + set_socket(0); + format_output(); +} + +//-----[ destructor ]-------------------------------------------------- +IpxSockAddress::~IpxSockAddress() +{ +} + +// copy an instance of this Value +SnmpSyntax& IpxSockAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag=0; // will set to 1 if really valid + if (val.valid()){ + switch (val.get_syntax()){ + case sNMP_SYNTAX_OCTETS: + { + // See if it is of the Ipx address family + // This handles IpxSockAddress == IpxAddress + IpxSockAddress temp_ipx(val.to_string()); + if (temp_ipx.valid()){ + *this = temp_ipx; // ipxsock = ipxsock + } + // See if it is an OctetStr of appropriate length + else if (((IpxSockAddress &)val).smival.value.string.len == IPXSOCKLEN){ + ACE_OS::memcpy(address_buffer, + ((IpxSockAddress &)val).smival.value.string.ptr, + IPXSOCKLEN); + valid_flag=1; + } + } + break; + } + } + format_output(); + return *this; +} + +// assignment to another IpAddress object overloaded +IpxSockAddress& IpxSockAddress::operator=( const IpxSockAddress &ipxaddr) +{ + // protect against assignment from itself + if ( this == &ipxaddr ) + return *this; + + (IpxAddress&)*this = ipxaddr; // use ancestor assignment for ipx addr + set_socket(ipxaddr.get_socket()); // copy socket value + format_output(); + return *this; +} + + +//----------[ create a new instance of this Value ]------------------------ +SnmpSyntax *IpxSockAddress::clone() const +{ + return (SnmpSyntax *) new IpxSockAddress(*this); +} + +//----[ IPXSock address char * cast ]-------------------------------------- +IpxSockAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +//----[ IPXSock address get char representation ]-------------------------- +const char * IpxSockAddress::to_string() +{ + return (char *)output_buffer; +} + +//----[ IPX address format output ]------------------------------------- +void IpxSockAddress::format_output() +{ + IpxAddress::format_output(); // allow ancestors to format their buffers + + if ( valid_flag) + ACE_OS::sprintf((char *) output_buffer,"%s/%d", + IpxAddress::to_string(), get_socket()); + else + output_buffer[0] = 0; +} + +//-----[ IP Address parse Address ]--------------------------------- +int IpxSockAddress::parse_address( const char *inaddr) +{ + char buffer[MAXHOSTNAMELEN +1]; + unsigned short socketid=0; + + if (inaddr && (ACE_OS::strlen( inaddr)< MAXHOSTNAMELEN)) + ACE_OS::strcpy( buffer, inaddr); + else + { + valid_flag = 0; + return 0; + } + // look for port info @ the end of the string + // port can be delineated by a ':' or a '/' + // if neither are present then just treat it + // like a normal IpAddress + char *tmp; + tmp = ACE_OS::strstr( buffer,"/"); + + if (tmp != 0) + { + *tmp=0; // null terminator + tmp++; + socketid = ACE_OS::atoi( tmp); + } + set_socket(socketid); + return IpxAddress::parse_address( buffer); +} + + + +//-------------[ set the socket number ]---------------------------------- +void IpxSockAddress::set_socket( const unsigned short s) +{ + unsigned short sock_nbo = htons(s); + ACE_OS::memcpy(&address_buffer[IPXLEN], &sock_nbo, 2); +} + +//--------------[ get the socket number ]--------------------------------- +unsigned short IpxSockAddress::get_socket() const +{ + if (valid_flag) + { + unsigned short sock_nbo; + ACE_OS::memcpy(&sock_nbo, &address_buffer[IPXLEN], 2); + return ntohs(sock_nbo); + } + else + return 0; // don't use uninitialized memory +} + +//------[ return the type ]---------------------------------------------- +addr_type IpxSockAddress::get_type() const +{ + return type_ipxsock; +} + + +//======================================================================== +//======== MACAddress Implementation ===================================== +//======================================================================== + +//-----------[ syntax type ]---------------------------------------------- +SmiUINT32 MacAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +//-----[ MAC Address copy constructor ]--------------------------------- +MacAddress::MacAddress(const MacAddress &macaddr) + : Address (macaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = MACLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = macaddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, macaddr.address_buffer, MACLEN); + format_output(); +} + +//---------[ constructor with a string argument ]------------------------- +MacAddress::MacAddress( const char *inaddr):Address( ) +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = MACLEN; + smival.value.string.ptr = address_buffer; + + valid_flag=0; + format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = MACLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + format_output(); +} + +//-----[ construct a MacAddress from a GenAddress ]------------------------ +MacAddress::MacAddress( const GenAddress &genaddr) +{ + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = MACLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + // allow use of mac address + if (genaddr.get_type() == type_mac) + { + valid_flag = genaddr.valid(); + if ( valid_flag) + { + // copy in the Mac address data + MacAddress temp_mac( (const char *) genaddr); + *this = temp_mac; + } + } + format_output(); +} + +//-----[ destructor ]-------------------------------------------------- +MacAddress::~MacAddress() +{ +} + +//---------[ MacAddress clone ]------------------------------------------- +SnmpSyntax *MacAddress::clone() const +{ + return (SnmpSyntax *) new MacAddress(*this); +} + +//------[ assignment to another ipaddress object overloaded ]-------------- +MacAddress& MacAddress::operator=( const MacAddress &macaddress) +{ + // protect against assignment from itself + if ( this == &macaddress ) + return *this; + + valid_flag = macaddress.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, macaddress.address_buffer, MACLEN); + format_output(); + return *this; +} + + + +//-----[ MAC Address general = operator ]--------------------------------- +SnmpSyntax& MacAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag=0; // will set to 1 if really valid + if (val.valid()){ + switch (val.get_syntax()){ + case sNMP_SYNTAX_OCTETS: + if (((MacAddress &)val).smival.value.string.len == MACLEN){ + ACE_OS::memcpy(address_buffer, + ((MacAddress &)val).smival.value.string.ptr, MACLEN); + valid_flag=1; + } + break; + } + } + format_output(); + return *this; +} + +//-----[ MAC Address parse Address ]-------------------------------------- +// Convert a string to a six byte MAC address +// On success sets validity 1 or 0 +// +// MAC address format +// +// MAC ADDRESS +// 01 02 03 04 05 06 +// XX:XX:XX:XX:XX:XX +// Valid input format +// +// XXXXXXXXXXXX +// Total length must be 17 +// Each char must take on value 0-F +// +// +int MacAddress::parse_address( const char *inaddr) +{ + char temp[MAXHOSTNAMELEN +1]; // don't destroy original + char unsigned *tmp; + size_t z; + + + // save the orginal source + if ( !inaddr || (ACE_OS::strlen( inaddr) > 30)) return 0; + ACE_OS::strcpy( temp, inaddr); + trim_white_space( temp); + + // bad total length check + if ( ACE_OS::strlen(temp) != 17) + return 0; + + // check for colons + if ((temp[2] != ':')||(temp[5] != ':')||(temp[8]!=':')||(temp[11]!=':') + ||(temp[14] !=':')) + return 0; + + // strip off the colons + tmp = ( unsigned char *) temp; + int i = 0; + while ( *tmp != 0) + { + if (*tmp != ':') + { + temp[i] = *tmp; + i++; + } + tmp++; + } + temp[i] = 0; + + // convert to lower + for(z=0;z<ACE_OS::strlen(temp);z++) + temp[z] = tolower( temp[z]); + + + // check out the MAC address + tmp = ( unsigned char *) temp; + while( *tmp != 0) + if (((*tmp >= '0') && (*tmp <= '9'))|| // good 0-9 + ((*tmp >= 'a') && (*tmp <= 'f'))) // or a-f + tmp++; + else + return 0; + + // convert to target string + tmp = (unsigned char *) temp; + while ( *tmp != 0) + { + if (( *tmp >= '0') && ( *tmp <= '9')) + *tmp = *tmp - (char unsigned )'0'; + else + *tmp = *tmp - (char unsigned) 'a' + (char unsigned) 10; + tmp++; + } + + address_buffer[0] = (temp[0]*16) + temp[1]; + address_buffer[1] = (temp[2]*16) + temp[3]; + address_buffer[2] = (temp[4]*16) + temp[5]; + address_buffer[3] = (temp[6]*16) + temp[7]; + address_buffer[4] = (temp[8]*16) + temp[9]; + address_buffer[5] = (temp[10]*16) + temp[11]; + + return 1; +} + +//----[ MAC address char * cast ]-------------------------------------- +MacAddress::operator const char *() const +{ + return (char *)output_buffer; +} +//----[ MAC address get char representation ]-------------------------- +const char * MacAddress::to_string() +{ + return (char *)output_buffer; +} + +//----[ MAC address format output ]--------------------------------- +void MacAddress::format_output() +{ + if ( valid_flag) + sprintf(output_buffer,"%02x:%02x:%02x:%02x:%02x:%02x",address_buffer[0], + address_buffer[1],address_buffer[2],address_buffer[3], + address_buffer[4],address_buffer[5]); + else + output_buffer[0] = 0; +} + +//------[ return the type ]---------------------------------- +addr_type MacAddress::get_type() const +{ + return type_mac; +} + + +unsigned int MacAddress::hashFunction() const +{ + return ((((address_buffer[0] << 8) + address_buffer[1]) * HASH0LEN) + + (((address_buffer[2] << 8) + address_buffer[3]) * HASH1LEN) + + (((address_buffer[4] << 8) + address_buffer[5]) * HASH2LEN)); +} + +void MacAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + +//======================================================================== +//========== Generic Address Implementation ============================== +//======================================================================== + +//-----------[ get the syntax]---------------------------------------------- +SmiUINT32 GenAddress::get_syntax() +{ + if (address != 0) + return address->get_syntax(); + + return sNMP_SYNTAX_NULL; +} + +void GenAddress::init_smi() +{ + smival.syntax = sNMP_SYNTAX_NULL; // to be overridden + smival.value.string.len = 0; // to be overridden + smival.value.string.ptr = address_buffer; // constant +} + +//-----------[ constructor with a string argument ]---------------------- +GenAddress::GenAddress( const char *addr): address(0) +{ + valid_flag = 0; + // initialize SMI info + // BOK: smival is generally not used for GenAddress, but + // we need this to be a replica of the real address' + // smival info so that <class>::operator=SnmpSyntax + // will work. + init_smi(); + + if (addr && ACE_OS::strlen(addr) == 0) { + format_output(); + return; + } + + parse_address(addr); + + // Copy real address smival info into GenAddr smival + // BOK: smival is generally not used for GenAddress, but + // we need this to be a replica of the real address' + // smival info so that <class>::operator=SnmpSyntax + // will work. + if ( valid_flag ) { + smival.syntax = ((GenAddress *)address)->smival.syntax; + smival.value.string.len = + ((GenAddress *)address)->smival.value.string.len; + ACE_OS::memcpy(smival.value.string.ptr, + ((GenAddress *)address)->smival.value.string.ptr, + (size_t)smival.value.string.len); + } +} + +//-----------[ constructor with an Address argument ]-------------------- +GenAddress::GenAddress( const Address &addr): address(0) +{ + valid_flag = 0; + + // initialize SMI info + // BOK: this is generally not used for GenAddress, + // but we need this to be a replica of the real address' + // smival info so that operator=SnmpSyntax will work. + init_smi(); + // make sure that the object is valid + if (!addr.valid()) { + format_output(); + return; + } + + address = (Address*)addr.clone(); + if (address) + valid_flag = address->valid(); + + // Copy real address smival info into GenAddr smival + // BOK: smival is generally not used for GenAddress, but + // we need this to be a replica of the real address' + // smival info so that <class>::operator=SnmpSyntax + // will work. + if ( valid_flag ) { + smival.syntax = address->get_syntax(); + smival.value.string.len = + ((GenAddress *)address)->smival.value.string.len; + ACE_OS::memcpy(smival.value.string.ptr, + ((GenAddress *)address)->smival.value.string.ptr, + (size_t)smival.value.string.len); + } + + format_output(); +} + +//-----------------[ constructor with another GenAddress object ]------------- +GenAddress::GenAddress( const GenAddress &addr) + : Address (addr), + address(0) +{ + valid_flag = 0; + + // initialize SMI info + // BOK: this is generally not used for GenAddress, + // but we need this to be a replica of the real address' + // smival info so that operator=SnmpSyntax will work. + init_smi(); + + // make sure that the object is valid + if (!addr.valid_flag) { + format_output(); + return; + } + + address = (Address *)addr.address->clone(); + if (address) + valid_flag = address->valid(); + + // Copy real address smival info into GenAddr smival + // BOK: smival is generally not used for GenAddress, but + // we need this to be a replica of the real address' + // smival info so that <class>::operator=SnmpSyntax + // will work. + if ( valid_flag ) { + smival.syntax = ((GenAddress *)address)->smival.syntax; + smival.value.string.len = + ((GenAddress *)address)->smival.value.string.len; + ACE_OS::memcpy(smival.value.string.ptr, + ((GenAddress *)address)->smival.value.string.ptr, + (size_t)smival.value.string.len); + } + + format_output(); +} + +//----------[ destructor ] ------------------------------------------------ +GenAddress::~GenAddress() +{ + if ( address != 0) + delete address; +} + +//----------[ create a new instance of this Value ]------------------------ +SnmpSyntax *GenAddress::clone() const +{ + return (SnmpSyntax *) new GenAddress(*this); +} + +//------[ assignment GenAddress = GenAddress ]----------------------------- +GenAddress& GenAddress::operator=( const GenAddress &addr) +{ + // protect against assignment from itself + if ( this == &addr ) + return *this; + + valid_flag = 0; + if (address) { + delete address; + address = 0; + } + + if (addr.address) + address = (Address *)(addr.address)->clone(); + + if (address) + valid_flag = address->valid(); + + // Copy real address smival info into GenAddr smival + // BOK: smival is generally not used for GenAddress, but + // we need this to be a replica of the real address' + // smival info so that <class>::operator=SnmpSyntax + // will work. + if ( valid_flag ) { + smival.syntax = ((GenAddress *)address)->smival.syntax; + smival.value.string.len = + ((GenAddress *)address)->smival.value.string.len; + ACE_OS::memcpy(smival.value.string.ptr, + ((GenAddress *)address)->smival.value.string.ptr, + (size_t)smival.value.string.len); + } + + format_output(); + return *this; +} + + +//------[ assignment GenAddress = any SnmpSyntax ]----------------------- +SnmpSyntax& GenAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will get set to 1 if really valid + if ( address != 0) { + delete address; + address = 0; + } + + if (val.valid()) { + switch ( val.get_syntax() ) { + //-----[ ip address case ]------------- + // BOK: this case shouldn't be needed since there is an explicit + // GenAddr=Address assignment that will override this assignment. + // Left here for posterity. + case sNMP_SYNTAX_IPADDR: + { + address = (Address *)val.clone(); + if (address) + valid_flag = address->valid(); + } + break; + + //-----[ udp address case ]------------ + //-----[ ipx address case ]------------ + //-----[ mac address case ]------------ + // BOK: This is here only to support GenAddr = primitive OctetStr. + // The explicit GenAddr=Address assignment will handle the cases + // GenAddr = [UdpAdd|IpxAddr|IpxSock|MacAddr|DecNetAddr|NetbiosAddr|AppleTlk]. + // Note, using the heuristic of octet str len to determine type of + // address to create is not accurate when address lengths are equal + // (e.g., UDPIPV4LEN == MACLEN). It gets worse if we add AppleTalk or + // OSI which use variable length addresses! assume AppleTalk as used in IOS Mibs + // is defined in CISCO-TC.my as fixed length of 3 octets + + case sNMP_SYNTAX_OCTETS: + { + unsigned long val_len; + val_len = ((GenAddress &)val).smival.value.string.len; + + if (val_len == UDPIPV4LEN) { + ACE_NEW_RETURN(address, UdpAddress, *this); + } + else if (val_len ==IPV4LEN) { + ACE_NEW_RETURN(address, IpAddress, *this); + } + else if (val_len == IPXLEN) { + ACE_NEW_RETURN(address, IpxAddress, *this); + } + else if (val_len == IPXSOCKLEN) { + ACE_NEW_RETURN(address, IpxSockAddress, *this); + } + else if (val_len == MACLEN) { + ACE_NEW_RETURN(address, MacAddress, *this); + } + else if (val_len == APPLETKLEN) { + ACE_NEW_RETURN(address, AppleTalkAddress, *this); + } + else if (val_len == DECNETLEN) { + ACE_NEW_RETURN(address, DecNetAddress, *this); + } + else if (val_len == NETBIOSLEN) { + ACE_NEW_RETURN(address, DecNetAddress, *this); + } + + if (address) { + *address = val; + valid_flag = address->valid(); + } + } + break; + } // end switch + } + + // Copy real address smival info into GenAddr smival + // BOK: smival is generally not used for GenAddress, but + // we need this to be a replica of the real address' + // smival info so that <class>::operator=SnmpSyntax + // will work. + if ( valid_flag ) { + smival.syntax = ((GenAddress *)address)->smival.syntax; + smival.value.string.len = + ((GenAddress *)address)->smival.value.string.len; + ACE_OS::memcpy(smival.value.string.ptr, + ((GenAddress *)address)->smival.value.string.ptr, + (size_t)smival.value.string.len); + } + + format_output(); + return *this; +} + + +// redefined parse address for macs +// TODO: Add netbios, appletalk, and decnet addresses here +int GenAddress::parse_address( const char *addr) +{ + if ( address != 0) + delete address; + + // try to create each of the addresses until the correct one + // is found + +//BOK: Need to try IPX Sock and IPX before UDP since on Win32, +// gethostbyname() seems to think the ipx network number +// portion is a valid ipaddress string... stupid WinSOCK! + + // ipxsock address + ACE_NEW_RETURN(address, IpxSockAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag && ((IpxSockAddress*)address)->get_socket()) { + format_output(); + return 1; // ok its an ipxsock address + } + // otherwise delete it and try another + delete address; + + // ipx address + ACE_NEW_RETURN(address, IpxAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return 1; // ok its an ipx address + } + // otherwise delete it and try another + delete address; + +//TM: Must try the derived classes first...one pitfall of the +//following solution is if someone creates with a port/socket of 0 the +//class will get demoted to ip/ipx. The only proper way to do this is +//to parse the strings ourselves. + + // udp address + ACE_NEW_RETURN(address, UdpAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag && ((UdpAddress*)address)->get_port()) { + format_output(); + return 1; // ok its a udp address + } + + // otherwise delete it and try another + delete address; + + // ip address + ACE_NEW_RETURN(address, IpAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) + { + format_output(); + return 1; // ok its an ip address + } + // otherwise delete it and try another + delete address; + + // mac address + ACE_NEW_RETURN(address, MacAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return 1; // ok, its a mac + } + + // guess by length of argument the type of address + switch (ACE_OS::strlen(addr)) { + case NETBIOSLEN: + ACE_NEW_RETURN(address, NetbiosAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return 1; // ok, its a mac + } + break; + + case APPLETKLEN: + ACE_NEW_RETURN(address, AppleTalkAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return 1; // ok, its a mac + } + break; + + case DECNETLEN: + ACE_NEW_RETURN(address, DecNetAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return 1; // ok, its a mac + } + break; + + } + // otherwise its invalid + delete address; + address = 0; + format_output(); + return 0; +} + +GenAddress::operator const char *() const +{ + if ( address != 0) + return (const char *)*address; // pass thru + else + return (char *)output_buffer; +} + +// to_string form of the contained address +const char * GenAddress::to_string() +{ + if ( address != 0) + return address->to_string(); // pass thru + else + return (char *)output_buffer; +} + +// format output +void GenAddress::format_output() +{ + output_buffer[0] = '\0'; +} + +//------[ return the type ]---------------------------------- +addr_type GenAddress::get_type() const +{ + if (!valid()) + return type_invalid; + else + return address->get_type(); +} + +// call the particular type class here +void GenAddress::to_octet(OctetStr& octet) const +{ + if (!valid()) + return; + + address->to_octet(octet); +} + +//------------------------------------------------------------------------ +//---------[ DecNet Address Class ]--------------------------------------- +//------------------------------------------------------------------------ + +DecNetAddress::DecNetAddress( const char *inaddr): Address() +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = DECNETLEN; + smival.value.string.ptr = address_buffer; + + valid_flag=0; + DecNetAddress::format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = DECNETLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + DecNetAddress::format_output(); +} + +DecNetAddress::DecNetAddress( const DecNetAddress& addr) + : Address (addr) +{ +} + +DecNetAddress::DecNetAddress( const GenAddress& genaddr) +{ + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = DECNETLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_decnet) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + DecNetAddress temp_ipx( (const char *) genaddr); + *this = temp_ipx; + } + } + DecNetAddress::format_output(); +} + +DecNetAddress::~DecNetAddress() +{ +} + +const char *DecNetAddress::to_string() +{ + return (char *)output_buffer; +} + +DecNetAddress& DecNetAddress::operator=( const DecNetAddress &decaddr) +{ + // protect against assignment from itself + if ( this == &decaddr ) + return *this; + valid_flag = decaddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, decaddr.address_buffer, DECNETLEN); + format_output(); + return *this; +} + +void DecNetAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + +DecNetAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +SmiUINT32 DecNetAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +SnmpSyntax& DecNetAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will get set 1 if really valid + + if (val.valid()) { + if (((DecNetAddress &)val).smival.value.string.len ==DECNETLEN) { + ACE_OS::memcpy(address_buffer, + ((DecNetAddress &)val).smival.value.string.ptr, DECNETLEN); + valid_flag = 1; + } + } + DecNetAddress::format_output(); + return *this; +} + +SnmpSyntax *DecNetAddress::clone() const +{ + return (SnmpSyntax *) new DecNetAddress(*this); +} + +addr_type DecNetAddress::get_type() const +{ + return type_decnet; +} + +void DecNetAddress::format_output() +{ + // if valid format else null it + if ( valid_flag) + ACE_OS::sprintf( (char *) output_buffer,"%d.%d",address_buffer[0], + address_buffer[1]); + else + output_buffer[0] = 0; +} + +int DecNetAddress::parse_address( const char *address) +{ + if (ACE_OS::strlen(address) > DECNETLEN) + return 0; // invalid + + ACE_OS::memset(address_buffer, 0, DECNETLEN); + ACE_OS::memcpy(address_buffer, address, DECNETLEN); + + return 1; // valid +} + + +//------------------------------------------------------------------------ +//---------[ AppleTalk Address Class ]------------------------------------ +//------------------------------------------------------------------------ + +AppleTalkAddress::AppleTalkAddress( const char *inaddr): Address() +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = APPLETKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag=0; + AppleTalkAddress::format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = APPLETKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + AppleTalkAddress::format_output(); +} +AppleTalkAddress::AppleTalkAddress( const AppleTalkAddress& addr) + : Address (addr) +{ +} + +AppleTalkAddress::AppleTalkAddress( const GenAddress& genaddr) +{ + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = APPLETKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = 0; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_atk) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + AppleTalkAddress temp_ipx( (const char *) genaddr); + *this = temp_ipx; + } + } + AppleTalkAddress::format_output(); +} + +AppleTalkAddress::~AppleTalkAddress() +{ +} + +const char *AppleTalkAddress::to_string() +{ + return (char *)output_buffer; +} + +AppleTalkAddress& AppleTalkAddress::operator=( const AppleTalkAddress &ataddr) +{ + // protect against assignment from itself + if ( this == &ataddr ) + return *this; + valid_flag = ataddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, ataddr.address_buffer, APPLETKLEN); + format_output(); + return *this; +} + +void AppleTalkAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + +AppleTalkAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +SmiUINT32 AppleTalkAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +SnmpSyntax& AppleTalkAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will get set 1 if really valid + + if (val.valid()) { + if (((AppleTalkAddress &)val).smival.value.string.len ==APPLETKLEN) { + ACE_OS::memcpy(address_buffer, + ((AppleTalkAddress &)val).smival.value.string.ptr,APPLETKLEN); + valid_flag = 1; + } + } + AppleTalkAddress::format_output(); + return *this; +} + +SnmpSyntax *AppleTalkAddress::clone() const +{ + return (SnmpSyntax *) new AppleTalkAddress(*this); +} + +addr_type AppleTalkAddress::get_type() const +{ + return type_atk; +} + +void AppleTalkAddress::format_output() +{ + // if valid format else null it + if ( valid_flag) + ACE_OS::sprintf( (char *) output_buffer,"%d.%d.%d", address_buffer[0], + address_buffer[1], address_buffer[3]); + else + output_buffer[0] = 0; +} + +int AppleTalkAddress::parse_address( const char *address) +{ + if (ACE_OS::strlen(address) > APPLETKLEN) + return 0; // invalid + + ACE_OS::memset(address_buffer, 0, APPLETKLEN); + ACE_OS::memcpy(address_buffer, address, APPLETKLEN); + + return 1; // valid +} + +char AppleTalkAddress::get_host_address() const +{ + return address_buffer[2]; +} + +void AppleTalkAddress::set_host_address(const char host) +{ + address_buffer[2] = host; +} + +short AppleTalkAddress::get_net_address() const +{ + short net; + ACE_OS::memcpy(&net, address_buffer, APPLETKLEN - 1); + return net; +} + +void AppleTalkAddress::set_net_address(const short atknet) +{ + ACE_OS::memcpy(address_buffer, &atknet, APPLETKLEN -1); +} diff --git a/ACE/ASNMP/asnmp/address.h b/ACE/ASNMP/asnmp/address.h new file mode 100644 index 00000000000..f8131c19485 --- /dev/null +++ b/ACE/ASNMP/asnmp/address.h @@ -0,0 +1,845 @@ + + +#ifndef ADDRESS_ +#define ADDRESS_ +//============================================================================= +/** + * @file address.h + * + * $Id$ + * + * Address class definition. Encapsulates various network + * addresses into easy to use, safe and portable classes. + * + * + * @author Peter E Mellquist + */ +//============================================================================= + + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//----[ includes ]----------------------------------------------------- +// ACE OS Adaption layer +#include "ace/os_include/netinet/os_in.h" +#include "ace/os_include/os_netdb.h" +#include "ace/Log_Msg.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/smival.h" +#include "asnmp/octet.h" + +//----[ enumerated types ] -------------------------------- +enum address_lengths { + IPV4LEN=4, + UDPIPV4LEN=6, + IPV6LEN=16, + UDPIPV6LEN=18, + IPXLEN=10, + IPXSOCKLEN=12, + NETBIOSLEN=16, + APPLETKLEN=3, + DECNETLEN=2, + MACLEN=6, + HASH0LEN=19, + HASH1LEN=13, + HASH2LEN=7, + MAX_ADDR_SZ=20, + MAX_DISPLAY_SZ=MAXHOSTNAMELEN+1 +}; + +enum addr_type { + type_ip, + type_ipx, + type_udp, + type_ipxsock, + type_mac, + type_nb, + type_atk, + type_decnet, + type_e164, + type_sip, // IPv6 + type_invalid +}; + +// TODO: get rest of nb service types added here +enum nb_service { + nb_workstation = 0x0, nb_server = 0x20 +}; + +//---[ forward declarations ]----------------------------------------- +class GenAddress; +class UdpAddress; +class IpxSockAddress; +class NetbiosAddress; +class SIPAddress; // aka ipv6 + +// TODO: +// class AtmE164Address; + + +//-------------------------------------------------------------------- +//----[ Address class ]----------------------------------------------- +//-------------------------------------------------------------------- +/** + * @class + * + * @brief Defines the member functions for the abstract base class + * Address. An Address is a unique network endpoint. + */ +class ASNMP_Export Address: public SnmpSyntax +{ + +public: + /// allow destruction of derived classes + virtual ~Address(); + + /// overloaded equivlence operator, are two addresses equal? + friend ASNMP_Export bool operator==( const Address &lhs,const Address &rhs); + + /// overloaded not equivlence operator, are two addresses not equal? + friend ASNMP_Export bool operator!=( const Address &lhs,const Address &rhs); + + /// overloaded > operator, is a1 > a2 + friend ASNMP_Export bool operator>( const Address &lhs,const Address &rhs); + + /// overloaded >= operator, is a1 >= a2 + friend ASNMP_Export bool operator>=( const Address &lhs,const Address &rhs); + + /// overloaded < operator, is a1 < a2 + friend ASNMP_Export bool operator<( const Address &lhs,const Address &rhs); + + /// overloaded <= operator, is a1 <= a2 + friend ASNMP_Export bool operator<=( const Address &lhs,const Address &rhs); + + /// equivlence operator overloaded, are an address and a string equal? + friend ASNMP_Export bool operator==( const Address &lhs,const char *rhs); + + /// overloaded not equivlence operator, are an address and string not equal? + friend ASNMP_Export bool operator!=( const Address &lhs,const char *rhs); + + /// overloaded < , is an address greater than a string? + friend ASNMP_Export bool operator>( const Address &lhs,const char *rhs); + + /// overloaded >=, is an address greater than or equal to a string? + friend ASNMP_Export bool operator>=( const Address &lhs,const char *rhs); + + /// overloaded < , is an address less than a string? + friend ASNMP_Export bool operator<( const Address &lhs,const char *rhs); + + /// overloaded <=, is an address less than or equal to a string? + friend ASNMP_Export bool operator<=( const Address &lhs,const char *rhs); + + /// overloaded const char * cast + virtual operator const char *() const = 0; + + /// verify the is the address object constructed ok + virtual int valid() const; + + /// return a suitable buffer to contain the address + virtual void to_octet(OctetStr& octet) const = 0; + + /// (pure virtual) syntax type + virtual SmiUINT32 get_syntax() = 0; + + /// for non const [], allows reading and writing + unsigned char& operator[]( const int position); + + /// get a printable ASCII value + virtual const char *to_string() = 0; + + /// create a new instance of this Value + virtual SnmpSyntax *clone() const = 0; + + /// return the type of address + virtual addr_type get_type() const = 0; + + /// overloaded assignment operator + virtual SnmpSyntax& operator=( SnmpSyntax &val) = 0; + + /// return a hash key + virtual unsigned int hashFunction() const { return 0;}; + + +protected: + /// state of constructed object (1/0) + /// addr internal representation + int valid_flag; + unsigned char address_buffer[MAX_ADDR_SZ]; + + /// parse the address string + /// redefined for each specific address subclass + virtual int parse_address( const char * inaddr) =0; + + /// format the output + /// redefined for each specific address subclass + virtual void format_output() =0; + + /// a reused trimm white space method + void trim_white_space( char * ptr); +}; + + +//----------------------------------------------------------------------- +//---------[ IPv4 Address Class ]---------------------------------------- +//----------------------------------------------------------------------- +/** + * @class IpAddress + * + * @brief Defines the member functions for the concrete class IpAddress + * An IP Version 4 Address is 4 bytes long and consists of a + * Network, Sub Network, and host component. + */ +class ASNMP_Export IpAddress : public Address +{ +public: + /// default construct an IP address with a string + IpAddress( const char *inaddr = ""); + + /// construct an IP address with another IP address + IpAddress( const IpAddress &ipaddr); + + /// construct an IP address with a GenAddress + IpAddress( const GenAddress &genaddr); + + /// destructor (ensure that SnmpSyntax::~SnmpSyntax() is overridden) + ~IpAddress(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// assignment to another IpAddress object overloaded + IpAddress& operator=( const IpAddress &ipaddress); + + // TODO: add ability to set addr given long + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// return the DNS Fully Qualified Domain Name (host.domain) + /// on failure returns dotted_quad string + const char *resolve_hostname(int& was_found); + + /// return string representation of object (dotted quad returned) + virtual const char *to_string() ; + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// logically AND two IPaddresses and + /// return the new one + void mask( const IpAddress& ipaddr); + + /// return the type + virtual addr_type get_type() const; + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// is this the loopback address? 127.0.0.1/loopback/1.0.0.127.in-addr.arpa + int is_loopback() const; + + /// determine if this is a multicast address + int is_multicast() const; + + /// determine if this a broadcast address + int is_broadcast() const; + + /// per RFC 1597, private addresses are:: 10, 172.16, and 192.168.0 + int is_private() const; + + /// convert address into octet string format in network byte order + virtual void to_octet(OctetStr& octet) const; + +protected: + char output_buffer[MAX_DISPLAY_SZ]; // output buffer + + /// friendly name storage + char iv_friendly_name_[MAX_DISPLAY_SZ]; + + /// did resolver call work? some addrs won't resolve + int iv_friendly_name_status_; + + /// redefined parse address + /// specific to IP addresses + virtual int parse_address( const char *inaddr); + + /// redefined format output + /// specific to IP addresses + virtual void format_output(); + + /// parse a dotted string + int parse_dotted_ipstring( const char *inaddr); + + /// using the currently defined address, do a gethostbyname() + /// and try to fill up the name + int addr_to_friendly(); + + /// thread safe routine to lookup ip address given hostname + /// return <> 0 on error + static int resolve_to_address(const char *hostname, in_addr& quad_addr); + + /// thread safe routine to lookup name given ip address + /// return <> 0 on error + static int resolve_to_hostname(const in_addr& quad_addr, char *hostname); + +}; + +//------------------------------------------------------------------------ +//--------------[ DNS Iterator Class ]------------------------------------ +//------------------------------------------------------------------------ + +/** + * @class Address_Iter + * + * @brief Defines routines to obtain information on a hostname/FQDN + * such as multiple addresses + */ +class ASNMP_Export Address_Iter +{ +public: + Address_Iter(const char *hostname); // fully qualified domain name, hostname + + /// did hostname resolve via DNS? + int valid() const; + + /// how many addresses associated with this hostname + int how_many_addresses(); + + /// return next address + int next(IpAddress& addr); + +private: + Address_Iter(const Address_Iter&); + int valid_; // ctor status + int count_; // number of addresses + char **entry_; // ptr to current address + struct hostent lookupResult_; + ACE_HOSTENT_DATA buffer_; + int query_dns(const char *hostname); +}; + +//------------------------------------------------------------------------ +//---------[ UDP/IPv4 Address Class ]------------------------------------- +//------------------------------------------------------------------------ +/** + * @class + * + * @brief Defines the member functions for the concrete class UdpAddress + * A Udp Address consists of an IP Version 4 Address (IpAddress) + * and a 2 byte unsigned port number. (see /etc/services file) + * User Datagram Protocol (UDP) is a best effort transport + */ +class ASNMP_Export UdpAddress : public IpAddress +{ +public: + /// default constructor with a dotted string in the form of addr:port + UdpAddress( const char *inaddr = ""); + + /// construct an Udp address with another Udp address + UdpAddress( const UdpAddress &udpaddr); + + /// construct a Udp address with a GenAddress + UdpAddress( const GenAddress &genaddr); + + /// construct a Udp address with an IpAddress + /// default port # to zero + UdpAddress( const IpAddress &ipaddr); + + /// destructor + ~UdpAddress(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// assignment to another IpAddress object overloaded + UdpAddress& operator=( const UdpAddress &udpaddr); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// output in the form of address:port + virtual const char *to_string() ; + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// set the port number + void set_port( const unsigned short p); + + /// get the port number + unsigned short get_port() const; + + /// return the type + virtual addr_type get_type() const; + +protected: + /// output buffer + char output_buffer[MAX_DISPLAY_SZ]; + + /// redefined parse address + /// specific to IP addresses + virtual int parse_address( const char *inaddr); + + /// redefined format output + /// specific to IP addresses + virtual void format_output(); +}; + + +//------------------------------------------------------------------------- +//---------[ 802.3 MAC Address Class ]------------------------------------- +//------------------------------------------------------------------------- +/** + * @class + * + * @brief Defines the member functions for the concrete class MacAddress. + * A Media Access Control Address consists of 48 bits as defined + * in IEEE 802.3 specifications. + */ +class ASNMP_Export MacAddress : public Address +{ +public: + /// constructor with a string argument + MacAddress( const char *inaddr = ""); + + /// constructor with another MAC object + MacAddress( const MacAddress &macaddr); + + /// construct a MacAddress with a GenAddress + MacAddress( const GenAddress &genaddr); + + /// destructor + ~MacAddress(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// assignment to another IpAddress object overloaded + MacAddress& operator=( const MacAddress &macaddress); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// create a string to internal class storage representing object + virtual const char *to_string(); + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// return the type + virtual addr_type get_type() const; + + /// return a hash key + unsigned int hashFunction() const; + + /// return byte array of the mac address + virtual void to_octet(OctetStr& octet) const; + +protected: + /// output buffer containing string representation of object + char output_buffer[MAX_DISPLAY_SZ]; + + /// redefined parse address for macs + virtual int parse_address( const char *inaddr); + + /// redefined format output for MACs + virtual void format_output(); +}; + +//------------------------------------------------------------------------ +//---------[ Netbios Address Class ]-------------------------------------- +//------------------------------------------------------------------------ +/** + * @class + * + * @brief Defines the member functions for the concrete class NetbiosAddress. + * The IBM/Microsoft address for NETBIOS, NETBEUI protocol transport. + */ +class ASNMP_Export NetbiosAddress : public Address +{ +public: + + /// default constructor with string arg + NetbiosAddress( const char *inaddr = ""); + + /// set name and service type + NetbiosAddress( const char *inaddr, nb_service svc); + + /// copy constructor + NetbiosAddress( const NetbiosAddress& nbaddr); + + /// construct with a GenAddress + NetbiosAddress( const GenAddress& genaddr); + + ~NetbiosAddress(); + + virtual const char *to_string(); + + NetbiosAddress& operator=( const NetbiosAddress &nbaddr); + + /// retrieve the network service type + nb_service get_service_type() const; + + /// set the service type (workstation, server, etc) + void set_service_type(nb_service nbservice); + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// output byte buffer containing netbios name + virtual void to_octet(OctetStr& octet) const; + +protected: + void InitNBAddr(const char *inaddr); + char output_buffer[MAX_DISPLAY_SZ]; + + /// output buffer to hold string representation + virtual void format_output(); + virtual int parse_address( const char *inaddr); + virtual addr_type get_type() const; +}; + +//------------------------------------------------------------------------ +//---------[ DecNet Address Class ]--------------------------------------- +//------------------------------------------------------------------------ +/** + * @class + * + * @brief Defines the member functions for the concrete class DecNetAddress. + * DecNet Phase ? address consists of two octets (CISCO-TC.my) + */ +class ASNMP_Export DecNetAddress : public Address +{ + public: + /// default constructor with string arg + DecNetAddress( const char *inaddr = ""); + + /// copy constructor + DecNetAddress( const DecNetAddress& decaddr); + + /// construct with a GenAddress + DecNetAddress( const GenAddress& genaddr); + + ~DecNetAddress(); + + virtual const char *to_string(); + + DecNetAddress& operator=( const DecNetAddress &decaddr); + + /// convert address into octet string format 2 bytes of decnet address + virtual void to_octet(OctetStr& octet) const; + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + protected: + virtual int parse_address( const char *inaddr); + virtual addr_type get_type() const; + virtual void format_output(); + char output_buffer[MAX_DISPLAY_SZ]; +}; + +//------------------------------------------------------------------------ +//---------[ AppleTalk Address Class ]------------------------------------ +//------------------------------------------------------------------------ +/** + * @class + * + * @brief Defines the member functions for the concrete class DecNetAddress. + * DecNet Phase ? address consists of two octets (CISCO-TC.my) + */ +class ASNMP_Export AppleTalkAddress : public Address +{ + public: + /// default constructor with string arg + AppleTalkAddress( const char *inaddr = ""); + + /// copy constructor + AppleTalkAddress( const AppleTalkAddress& atkaddr); + + /// construct with a GenAddress + AppleTalkAddress( const GenAddress& genaddr); + + ~AppleTalkAddress(); + + virtual const char *to_string(); + + AppleTalkAddress& operator=( const AppleTalkAddress &atkaddr); + + /// convert address into octet string format 3 bytes of atk address + virtual void to_octet(OctetStr& octet) const; + + /// get the host part of the address + char get_host_address() const; + + /// set the host part of the address + void set_host_address(const char); + + /// get the 2 byte atk network address + short get_net_address() const; + + /// set the host 2 byte atk network address + void set_net_address(const short atknet); + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + private: + virtual int parse_address( const char *inaddr); + virtual addr_type get_type() const; + virtual void format_output(); + char output_buffer[MAX_DISPLAY_SZ]; +}; + +//------------------------------------------------------------------------ +//---------[ IPX Address Class ]------------------------------------------ +//------------------------------------------------------------------------ +/** + * @class IpxAddress + * + * @brief Defines the member functions for the concrete class IpxAddress. + * Novell's IPX (version ?) network protocol endpoint + */ +class ASNMP_Export IpxAddress : public Address +{ +public: + /// default constructor with a string arg + IpxAddress( const char *inaddr = ""); + + /// constructor with another ipx object + IpxAddress( const IpxAddress &ipxaddr); + + /// construct with a GenAddress + IpxAddress( const GenAddress &genaddr); + + /// destructor + ~IpxAddress(); + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// assignment to another IpxAddress object overloaded + IpxAddress& operator=( const IpxAddress &ipxaddress); + + /// get the host id portion of an ipx address + int get_hostid( MacAddress& mac); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// create string represtation of object value + virtual const char *to_string(); + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// return the type + virtual addr_type get_type() const; + + /// return byte sequence containing ipx address + virtual void to_octet(OctetStr& octet) const; + +protected: + /// ipx format separator {:,/} + char separator; + + /// output buffer to hold string representation + char output_buffer[MAX_DISPLAY_SZ]; + + /// redefined parse address for ipx strings + virtual int parse_address( const char *inaddr); + + /// redefined format output for ipx strings + /// uses same separator as when constructed + virtual void format_output(); +}; + + + +//------------------------------------------------------------------------ +//---------[ IpxSock Address Class ]-------------------------------------- +//------------------------------------------------------------------------ +/** + * @class IpxSockAddress + * + * @brief Defines the member functions for the concrete class IpxAddress. + * Novell's IPX (version ?) network protocol endpoint + */ +class ASNMP_Export IpxSockAddress : public IpxAddress +{ +public: + /// constructor with a dotted string + IpxSockAddress( const char *inaddr = ""); + + /// construct an Udp address with another Udp address + IpxSockAddress( const IpxSockAddress &ipxaddr); + + ///constructor with a GenAddress + IpxSockAddress( const GenAddress &genaddr); + + ///constructor with a IpxAddress + /// default socket # is 0 + IpxSockAddress( const IpxAddress &ipxaddr); + + /// destructor + ~IpxSockAddress(); + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// assignment to another IpxAddress object overloaded + IpxSockAddress& operator=( const IpxSockAddress &ipxaddr); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// set the socket number + void set_socket( const unsigned short s); + + /// get the socket number + unsigned short get_socket() const; + + /// create string representation of object value + virtual const char *to_string(); + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// return the type + virtual addr_type get_type() const; + +protected: + /// output buffer to hold string representation of object + char output_buffer[MAX_DISPLAY_SZ]; + + /// redefined parse address for ipx strings + virtual int parse_address( const char *inaddr); + + /// redefined format output + /// specific to IP addresses + virtual void format_output(); +}; + +//------------------------------------------------------------------------- +//--------[ Generic Address ]---------------------------------------------- +//------------------------------------------------------------------------- +/** + * @class GenAddress + * + * @brief Defines the member functions for the concrete class GenAddress. + * This class attempts to determine an address type given a char string. + */ +class ASNMP_Export GenAddress : public Address +{ +public: + /// constructor with a string argument + GenAddress( const char *addr = ""); + + /// constructor with an Address + GenAddress( const Address &addr); + + /// constructor with another GenAddress + GenAddress( const GenAddress &addr); + + /// destructor + ~GenAddress(); + + /// get the snmp syntax of the contained address + SmiUINT32 get_syntax(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// assignment of a GenAddress + GenAddress& operator=( const GenAddress &addr); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// string representation of object value + virtual const char *to_string(); + + /// const char * operator overloaded for streaming output + virtual operator const char *() const; + + /// return the type + virtual addr_type get_type() const; + + /// return the address as a octet sequence + virtual void to_octet(OctetStr& octet) const; + +protected: + /// pointer to a a concrete address + Address *address; + + /// output buffer of objects value + char output_buffer[MAX_DISPLAY_SZ]; + + /// redefined parse address for macs + virtual int parse_address( const char *addr); + + /// format output for a generic address + virtual void format_output(); + + /// initialize smi data structure + void init_smi(); +}; + +#endif //_ADDRESS diff --git a/ACE/ASNMP/asnmp/asn1.cpp b/ACE/ASNMP/asnmp/asn1.cpp new file mode 100644 index 00000000000..8a3b6f9c088 --- /dev/null +++ b/ACE/ASNMP/asnmp/asn1.cpp @@ -0,0 +1,1729 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// asn1.cpp +// +// = DESCRIPTION +// The Vb class is an encapsulation of the snmp variable binding. +// This module contains the class definition for the variable binding (VB) +// class. The VB class is an encapsulation of a SNMP VB. A VB object is +// composed of one SNMP++ Oid and one SMI value. The Vb class utilizes Oid +// objects and thus requires the Oid class. To use this class, +// set oid, value then call valid() to be sure object was constructed correctly. +// +// = AUTHOR +// S. Waldbusser (assumed) +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/********************************************************************** +// * + * Abstract Syntax Notation One, ASN.1 + * As defined in ISO/IS 8824 and ISO/IS 8825 + * This implements a subset of the above International Standards that + * is sufficient to implement SNMP. + * + * Encodes abstract data types into a machine independent stream of bytes. + * + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation, and that the name of CMU not be + used in advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + ******************************************************************/ + +#include "asnmp/asn1.h" +#include "asnmp/snmp.h" +#include "ace/OS_NS_string.h" + +ACE_RCSID(asnmp, asn1, "$Id$") + +/* + * parse_int - pulls a long out of an ASN int type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::parse_int( u_char *data, + int *datalength, + u_char *type, + long int *intp, + int intsize) +{ + ACE_TRACE("asn1::parse_int"); + /* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + u_char *bufp = data; + u_long asn_length; + long value = 0; + + if (intsize != sizeof (long)){ + ASNERROR("not long"); + return 0; + } + *type = *bufp++; + bufp =asn1::parse_length(bufp, &asn_length); + if (bufp == 0){ + ASNERROR("bad length"); + return 0; + } + if ((int)(asn_length + (bufp - data)) > *datalength){ + ASNERROR("overflow of message"); + return 0; + } + if ((int)asn_length > intsize){ + ASNERROR("I don't support such large integers"); + return 0; + } + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80) + value = -1; /* integer is negative */ + while(asn_length--) + value = (value << 8) | *bufp++; + *intp = value; + return bufp; +} + + +/* + * parse_unsigned_int - pulls an u_long out of an ASN int type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::parse_unsigned_int( u_char *data, + int *datalength, + u_char *type, + u_long *intp, + int intsize) +{ + ACE_TRACE("asn1::parse_unsigned_int"); + /* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + u_char *bufp = data; + u_long asn_length; + u_long value = 0; + + if (intsize != sizeof (long)){ + ASNERROR("not long"); + return 0; + } + *type = *bufp++; + bufp = asn1::parse_length(bufp, &asn_length); + if (bufp == 0){ + ASNERROR("bad length"); + return 0; + } + if ((int)(asn_length + (bufp - data)) > *datalength){ + ASNERROR("overflow of message"); + return 0; + } + if (((int)asn_length > (intsize + 1)) || + (((int)asn_length == intsize + 1) && *bufp != 0x00)){ + ASNERROR("I don't support such large integers"); + return 0; + } + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80) + value = (u_long) -1; + while(asn_length--) + value = (value << 8) | *bufp++; + *intp = value; + return bufp; +} + + +/* + * build_int - builds an ASN object containing an integer. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::build_int( u_char *data, + int *datalength, + u_char type, + long *intp, + int intsize) +{ + ACE_TRACE("asn1::build_int"); + /* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + + long integer; + u_long mask; + + if (intsize != sizeof (long)) + return 0; + integer = *intp; + /* + * Truncate "unnecessary" bytes off of the most significant end of this + * 2's complement integer. There should be no sequence of 9 + * consecutive 1's or 0's at the most significant end of the + * integer. + */ + mask = u_long (0x1FF) << ((8 * (sizeof(u_long) - 1)) - 1); + /* mask is 0xFF800000 on a big-endian machine */ + while((((integer & mask) == 0) || ((integer & mask) == mask)) + && intsize > 1){ + intsize--; + integer <<= 8; + } + data = asn1::build_header(data, datalength, type, intsize); + if (data == 0) + return 0; + if (*datalength < intsize) + return 0; + *datalength -= intsize; + mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + while(intsize--){ + *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1))); + integer <<= 8; + } + return data; +} + + +/* + * build_unsigned_int - builds an ASN object containing an integer. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::build_unsigned_int( u_char *data, + int *datalength, + u_char type, + u_long *intp, + int intsize) +{ + ACE_TRACE("asn1::build_unsigned_int"); + /* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + + u_long integer; + u_long mask; + int add_null_byte = 0; + + if (intsize != sizeof (long)) + return 0; + integer = *intp; + mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + if ((u_char)((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80){ + /* if MSB is set */ + add_null_byte = 1; + intsize++; + } + /* + * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer. + * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the + * integer. + */ + mask = u_long (0x1FF) << ((8 * (sizeof(u_long) - 1)) - 1); + /* mask is 0xFF800000 on a big-endian machine */ + while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){ + intsize--; + integer <<= 8; + } + data = asn1::build_header(data, datalength, type, intsize); + if (data == 0) + return 0; + if (*datalength < intsize) + return 0; + *datalength -= intsize; + if (add_null_byte == 1){ + *data++ = '\0'; + intsize--; + } + mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + while(intsize--){ + *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1))); + integer <<= 8; + } + return data; +} + + +/* + * parse_string - pulls an octet string out of an ASN octet string type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * "string" is filled with the octet string. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::parse_string( u_char *data, + int *datalength, + u_char *type, + u_char *string, + int *strlength) +{ + ACE_TRACE("asn1::parse_string"); + /* + * ASN.1 octet string ::= primstring | cmpdstring + * primstring ::= 0x04 asnlength byte {byte}* + * cmpdstring ::= 0x24 asnlength string {string}* + */ + u_char *bufp = data; + u_long asn_length; + + *type = *bufp++; + bufp = asn1::parse_length(bufp, &asn_length); + if (bufp == 0) + return 0; + if ((int)(asn_length + (bufp - data)) > *datalength){ + ASNERROR("overflow of message"); + return 0; + } + if ((int)asn_length > *strlength){ + ASNERROR("I don't support such long strings"); + return 0; + } + // fixed + ACE_OS::memcpy((char *)string, (char *)bufp, (int)asn_length); + *strlength = (int)asn_length; + *datalength -= (int)asn_length + (bufp - data); + return bufp + asn_length; +} + + +/* + * build_string - Builds an ASN octet string object containing the input string. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::build_string( u_char *data, + int *datalength, + u_char type, + u_char *string, + int strlength) +{ + ACE_TRACE("asn1::build_string"); + /* + * ASN.1 octet string ::= primstring | cmpdstring + * primstring ::= 0x04 asnlength byte {byte}* + * cmpdstring ::= 0x24 asnlength string {string}* + * This code will never send a compound string. + */ + data = asn1::build_header(data, datalength, type, strlength); + if (data == 0) + return 0; + if (*datalength < strlength) + return 0; + // fixed + ACE_OS::memcpy((u_char *)data,(u_char *)string, strlength); + *datalength -= strlength; + return data + strlength; +} + + +/* + * parse_header - interprets the ID and length of the current object. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * in this object following the id and length. + * + * Returns a pointer to the first byte of the contents of this object. + * Returns 0 on any error. + */ +u_char *asn1::parse_header( u_char *data, + int *datalength, + u_char *type) +{ + ACE_TRACE("asn1::parse_header"); + u_char *bufp = data; + register int header_len; + u_long asn_length; + + /* this only works on data types < 30, i.e. no extension octets */ + if (IS_EXTENSION_ID(*bufp)){ + ASNERROR("can't process ID >= 30"); + return 0; + } + *type = *bufp; + bufp = asn1::parse_length(bufp + 1, &asn_length); + if (bufp == 0) + return 0; + header_len = bufp - data; + if ((int)(header_len + asn_length) > *datalength){ + ASNERROR("asn length too long"); + return 0; + } + *datalength = (int)asn_length; + return bufp; +} + +/* + * asn1::build_header - builds an ASN header for an object with the ID and + * length specified. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * in this object following the id and length. + * + * This only works on data types < 30, i.e. no extension octets. + * The maximum length is 0xFFFF; + * + * Returns a pointer to the first byte of the contents of this object. + * Returns 0 on any error. + */ +u_char * asn1::build_header( u_char *data, + int *datalength, + u_char type, + int length) +{ + ACE_TRACE("asn1::build_header"); + if (*datalength < 1) + return 0; + *data++ = type; + (*datalength)--; + return asn1::build_length(data, datalength, length); + +} + +/* + * asn_build_sequence - builds an ASN header for a sequence with the ID and + * length specified. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * in this object following the id and length. + * + * This only works on data types < 30, i.e. no extension octets. + * The maximum length is 0xFFFF; + * + * Returns a pointer to the first byte of the contents of this object. + * Returns 0 on any error. + */ +u_char * asn1::build_sequence( u_char *data, + int *datalength, + u_char type, + int length) +{ + ACE_TRACE("asn1::build_sequence"); + *datalength -= 4; + if (*datalength < 0){ + *datalength += 4; /* fix up before punting */ + return 0; + } + *data++ = type; + *data++ = (u_char)(0x02 | ASN_LONG_LEN); + *data++ = (u_char)((length >> 8) & 0xFF); + *data++ = (u_char)(length & 0xFF); + return data; +} + +/* + * parse_length - interprets the length of the current object. + * On exit, length contains the value of this length field. + * + * Returns a pointer to the first byte after this length + * field (aka: the start of the data field). + * Returns 0 on any error. + */ +u_char * asn1::parse_length( u_char *data, + u_long *length) +{ + ACE_TRACE("asn1::parse_length"); + u_char lengthbyte = *data; + + if (lengthbyte & ASN_LONG_LEN){ + lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */ + if (lengthbyte == 0){ + ASNERROR("We don't support indefinite lengths"); + return 0; + } + if (lengthbyte > sizeof(long)){ + ASNERROR("we can't support data lengths that long"); + return 0; + } + // fixed + ACE_OS::memcpy((char *)length, (char *)data + 1, (int)lengthbyte); + *length = ntohl(*length); + *length >>= (8 * ((sizeof *length) - lengthbyte)); + return data + lengthbyte + 1; + } else { /* short asnlength */ + *length = (long)lengthbyte; + return data + 1; + } +} + +u_char *asn1::build_length( u_char *data, + int *datalength, + int length) +{ + ACE_TRACE("asn1::build_length"); + u_char *start_data = data; + + /* no indefinite lengths sent */ + if (length < 0x80){ + if (*datalength < 1){ + ASNERROR("build_length"); + return 0; + } + *data++ = (u_char)length; + } else if (length <= 0xFF){ + if (*datalength < 2){ + ASNERROR("build_length"); + return 0; + } + *data++ = (u_char)(0x01 | ASN_LONG_LEN); + *data++ = (u_char)length; + } else { /* 0xFF < length <= 0xFFFF */ + if (*datalength < 3){ + ASNERROR("build_length"); + return 0; + } + *data++ = (u_char)(0x02 | ASN_LONG_LEN); + *data++ = (u_char)((length >> 8) & 0xFF); + *data++ = (u_char)(length & 0xFF); + } + *datalength -= (data - start_data); + return data; + +} + +/* + * parse_objid - pulls an object indentifier out of an ASN object identifier type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * "objid" is filled with the object identifier. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char *asn1::parse_objid( u_char *data, + int *datalength, + u_char *type, + oid *objid, + int *objidlength) +{ + ACE_TRACE("asn1::parse_objid"); + /* + * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* + * subidentifier ::= {leadingbyte}* lastbyte + * leadingbyte ::= 1 7bitvalue + * lastbyte ::= 0 7bitvalue + */ + u_char *bufp = data; + oid *oidp = objid + 1; + u_long subidentifier; + long length; + u_long asn_length; + + *type = *bufp++; + bufp = asn1::parse_length(bufp, &asn_length); + if (bufp == 0) + return 0; + if ((int)asn_length + (bufp - data) > *datalength){ + ASNERROR("overflow of message"); + return 0; + } + *datalength -= (int)asn_length + (bufp - data); + + /* Handle invalid object identifier encodings of the form 06 00 robustly */ + if (asn_length == 0) + objid[0] = objid[1] = 0; + + length = asn_length; + (*objidlength)--; /* account for expansion of first byte */ + while (length > 0 && (*objidlength)-- > 0){ + subidentifier = 0; + do { /* shift and add in low order 7 bits */ + subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8); + length--; + } while (*(u_char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */ + if (subidentifier > (u_long)MAX_SUBID){ + ASNERROR("subidentifier too long"); + return 0; + } + *oidp++ = (oid)subidentifier; + } + + /* + * The first two subidentifiers are encoded into the first component + * with the value (X * 40) + Y, where: + * X is the value of the first subidentifier. + * Y is the value of the second subidentifier. + */ + subidentifier = (u_long)objid[1]; + if (subidentifier == 0x2B){ + objid[0] = 1; + objid[1] = 3; + } else { + objid[1] = (u_char)(subidentifier % 40); + objid[0] = (u_char)((subidentifier - objid[1]) / 40); + } + + *objidlength = (int)(oidp - objid); + return bufp; +} + +/* + * build_objid - Builds an ASN object identifier object containing the + * input string. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char *asn1::build_objid( u_char *data, + int *datalength, + u_char type, + oid *objid, + int objidlength) +{ + ACE_TRACE("asn1::build_objid"); + /* + * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* + * subidentifier ::= {leadingbyte}* lastbyte + * leadingbyte ::= 1 7bitvalue + * lastbyte ::= 0 7bitvalue + */ + u_char buf[MAX_OID_LEN]; + u_char *bp = buf; + oid *op = objid; + int asnlength; + u_long subid, mask, testmask; + int bits, testbits; + + if (objidlength < 2){ + *bp++ = 0; + objidlength = 0; + } else { + *bp++ = (u_char) (op[1] + (op[0] * 40)); + objidlength -= 2; + op += 2; + } + + while(objidlength-- > 0){ + subid = *op++; + if (subid < 127){ /* off by one? */ + *bp++ = (u_char )subid; + } else { + mask = 0x7F; /* handle subid == 0 case */ + bits = 0; + /* testmask *MUST* !!!! be of an u_type */ + for(testmask = 0x7F, testbits = 0; testmask != 0; + testmask <<= 7, testbits += 7){ + if (subid & testmask){ /* if any bits set */ + mask = testmask; + bits = testbits; + } + } + /* mask can't be zero here */ + for(;mask != 0x7F; mask >>= 7, bits -= 7){ + /* fix a mask that got truncated above */ + if (mask == 0x1E00000) + mask = 0xFE00000; + *bp++ = (u_char)(((subid & mask) >> bits) | ASN_BIT8); + } + *bp++ = (u_char)(subid & mask); + } + } + asnlength = bp - buf; + data = asn1::build_header(data, datalength, type, asnlength); + if (data == 0) + return 0; + if (*datalength < asnlength) + return 0; + // fixed + ACE_OS::memcpy((char *)data, (char *)buf, asnlength); + *datalength -= asnlength; + return data + asnlength; +} + +/* + * parse_null - Interprets an ASN null type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char *asn1::parse_null(u_char *data, + int *datalength, + u_char *type) +{ + ACE_TRACE("asn1::parse_null"); + /* + * ASN.1 null ::= 0x05 0x00 + */ + u_char *bufp = data; + u_long asn_length; + + *type = *bufp++; + bufp = asn1::parse_length(bufp, &asn_length); + if (bufp == 0) + return 0; + if (asn_length != 0){ + ASNERROR("Malformed 0"); + return 0; + } + *datalength -= (bufp - data); + return bufp + asn_length; +} + + +/* + * build_null - Builds an ASN null object. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char *asn1::build_null( u_char *data, + int *datalength, + u_char type) +{ + ACE_TRACE("asn1::build_null"); + /* + * ASN.1 null ::= 0x05 0x00 + */ + return asn1::build_header(data, datalength, type, 0); +} + +/* + * parse_bitstring - pulls a bitstring out of an ASN bitstring type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * "string" is filled with the bit string. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char *asn1::parse_bitstring( u_char *data, + int *datalength, + u_char *type, + u_char *string, + int *strlength) +{ + ACE_TRACE("asn1::parse_bitstring"); + /* + * bitstring ::= 0x03 asnlength unused {byte}* + */ + u_char *bufp = data; + u_long asn_length; + + *type = *bufp++; + bufp = asn1::parse_length(bufp, &asn_length); + if (bufp == 0) + return 0; + if ((int)(asn_length + (bufp - data)) > *datalength){ + ASNERROR("overflow of message"); + return 0; + } + if ((int) asn_length > *strlength){ + ASNERROR("I don't support such long bitstrings"); + return 0; + } + if (asn_length < 1){ + ASNERROR("Invalid bitstring"); + return 0; + } + if (*bufp > 7){ + ASNERROR("Invalid bitstring"); + return 0; + } + // fixed + ACE_OS::memcpy((char *)string,(char *)bufp, (int)asn_length); + *strlength = (int)asn_length; + *datalength -= (int)asn_length + (bufp - data); + return bufp + asn_length; +} + + +/* + * build_bitstring - Builds an ASN bit string object containing the + * input string. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the beginning of the next object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char *asn1::build_bitstring( u_char *data, + int *datalength, + u_char type, + u_char *string, + int strlength) +{ + ACE_TRACE("asn1::build_bitstring"); + /* + * ASN.1 bit string ::= 0x03 asnlength unused {byte}* + */ + if (strlength < 1 || *string || *string > 7){ + ASNERROR("Building invalid bitstring"); + return 0; + } + data = asn1::build_header(data, datalength, type, strlength); + if (data == 0) + return 0; + if (*datalength < strlength) + return 0; + // fixed + ACE_OS::memcpy((char *)data,(char *)string, strlength); + *datalength -= strlength; + return data + strlength; +} + + +/* + * parse_unsigned_int64 - pulls a 64 bit u_long out of an ASN int + * type. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::parse_unsigned_int64(u_char *data, + int *datalength, + u_char *type, + struct counter64 *cp, + int countersize) +{ + ACE_TRACE("asn1::parse_unsigned_int64"); + /* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + u_char *bufp = data; + u_long asn_length; + u_long low = 0, high = 0; + int intsize = 4; + + if (countersize != sizeof(struct counter64)){ + ASNERROR("not right size"); + return 0; + } + *type = *bufp++; + bufp = asn1::parse_length(bufp, &asn_length); + if (bufp == 0){ + ASNERROR("bad length"); + return 0; + } + if ((int)(asn_length + (bufp - data)) > *datalength){ + ASNERROR("overflow of message"); + return 0; + } + if (((int)asn_length > (intsize * 2 + 1)) || + (((int)asn_length == (intsize * 2) + 1) && *bufp != 0x00)){ + ASNERROR("I don't support such large integers"); + return 0; + } + *datalength -= (int)asn_length + (bufp - data); + if (*bufp & 0x80){ + low = (u_long) -1; // integer is negative + high = (u_long) -1; + } + while(asn_length--){ + high = (high << 8) | ((low & 0xFF000000) >> 24); + low = (low << 8) | *bufp++; + } + cp->low = low; + cp->high = high; + return bufp; +} + + +/* + * build_unsigned_int64 - builds an ASN object containing a 64 bit integer. + * On entry, datalength is input as the number of valid bytes following + * "data". On exit, it is returned as the number of valid bytes + * following the end of this object. + * + * Returns a pointer to the first byte past the end + * of this object (i.e. the start of the next object). + * Returns 0 on any error. + */ +u_char * asn1::build_unsigned_int64( u_char *data, + int *datalength, + u_char type, + struct counter64 *cp, + int countersize) +{ + ACE_TRACE("asn1::build_unsigned_int64"); + /* + * ASN.1 integer ::= 0x02 asnlength byte {byte}* + */ + + u_long low, high; + u_long mask, mask2; + int add_null_byte = 0; + int intsize; + + if (countersize != sizeof (struct counter64)) + return 0; + intsize = 8; + low = cp->low; + high = cp->high; + mask = u_long (0xFF) << (8 * (sizeof(u_long) - 1)); + /* mask is 0xFF000000 on a big-endian machine */ + if ((u_char)((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80){ + /* if MSB is set */ + add_null_byte = 1; + intsize++; + } + /* + * Truncate "unnecessary" bytes off of the most significant end of this 2's + * complement integer. + * There should be no sequence of 9 consecutive 1's or 0's at the most + * significant end of the integer. + */ + mask2 = u_long (0x1FF) << ((8 * (sizeof(u_long) - 1)) - 1); + /* mask2 is 0xFF800000 on a big-endian machine */ + while((((high & mask2) == 0) || ((high & mask2) == mask2)) + && intsize > 1){ + intsize--; + high = (high << 8) + | ((low & mask) >> (8 * (sizeof(long) - 1))); + low <<= 8; + } + data = asn1::build_header(data, datalength, type, intsize); + if (data == 0) + return 0; + if (*datalength < intsize) + return 0; + *datalength -= intsize; + if (add_null_byte == 1){ + *data++ = '\0'; + intsize--; + } + while(intsize--){ + *data++ = (u_char)((high & mask) >> (8 * (sizeof(long) - 1))); + high = (high << 8) + | ((low & mask) >> (8 * (sizeof(long) - 1))); + low <<= 8; + + } + return data; +} + + +// create a pdu +struct snmp_pdu * cmu_snmp::pdu_create( int command) +{ + ACE_TRACE("cmu_snmp::snmp_pdu_create"); + struct snmp_pdu *pdu; + + ACE_NEW_RETURN(pdu, snmp_pdu, 0); + ACE_OS::memset((char *)pdu, 0,sizeof(struct snmp_pdu)); + pdu->command = command; + pdu->errstat = 0; + pdu->errindex = 0; + pdu->enterprise = 0; + pdu->enterprise_length = 0; + pdu->variables = 0; + return pdu; +} + +// release a pdu from memory +void cmu_snmp::free_pdu( struct snmp_pdu *pdu) +{ + ACE_TRACE("cmu_snmp::free_pdu"); + struct variable_list *vp, *ovp; + + vp = pdu->variables; + while(vp){ + // release the oid part + if (vp->name) + delete [] vp->name; + // if deep data, then release as well + if (vp->val.string) + delete [] vp->val.string; + ovp = vp; + // go to the next one + vp = vp->next_variable; + // release up vb itself + delete ovp; + } + // if enterprise release it up + if (pdu->enterprise) + delete [] pdu->enterprise; + // release up pdu itself + delete pdu; +} + + +// add a null var to a pdu +void cmu_snmp::add_var(struct snmp_pdu *pdu, + oid *name, + int name_length, + SmiVALUE *smival) +{ + ACE_TRACE("cmu_snmp::add_var"); + + struct variable_list *vars = 0; + + // if we don't have a vb list ,create one + if (pdu->variables == 0) { + ACE_NEW(pdu->variables, variable_list); + vars = pdu->variables; + } + else + { // we have one, find the end + for(vars = pdu->variables; vars->next_variable; vars = vars->next_variable); + // create one + ACE_NEW(vars->next_variable, variable_list); + // bump ptr + vars = vars->next_variable; + } + + // add the oid with no data + vars->next_variable = 0; + + // hook in the Oid portion + ACE_NEW(vars->name, oid[(name_length)]); + + // fixed + ACE_OS::memcpy((char *)vars->name,(char *)name, name_length * sizeof(oid)); + vars->name_length = name_length; + + // hook in the SMI value + switch( smival->syntax) + { + // null , do nothing + case sNMP_SYNTAX_NULL: + case sNMP_SYNTAX_NOSUCHOBJECT: + case sNMP_SYNTAX_NOSUCHINSTANCE: + case sNMP_SYNTAX_ENDOFMIBVIEW: + { + vars->type = (u_char) smival->syntax; + vars->val.string = 0; + vars->val_len = 0; + } + break; + + // octects + case sNMP_SYNTAX_OCTETS: + case sNMP_SYNTAX_OPAQUE: + case sNMP_SYNTAX_IPADDR: + { + vars->type = (u_char) smival->syntax; + ACE_NEW(vars->val.string, + u_char[(unsigned)smival->value.string.len]); + vars->val_len = (int) smival->value.string.len; + ACE_OS::memcpy( (u_char *) vars->val.string, + (u_char *) smival->value.string.ptr, + (unsigned) smival->value.string.len); + } + break; + + // oid + case sNMP_SYNTAX_OID: + { + vars->type = (u_char) smival->syntax; + vars->val_len = (int) smival->value.oid.len * sizeof(oid); + ACE_NEW(vars->val.objid, oid[(unsigned)vars->val_len]); + ACE_OS::memcpy((u_long *)vars->val.objid, + (u_long *)smival->value.oid.ptr, + (unsigned) vars->val_len); + } + break; + + + + case sNMP_SYNTAX_TIMETICKS: + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_GAUGE32: + case sNMP_SYNTAX_UINT32: + { + long templong; + vars->type = (u_char) smival->syntax; + ACE_NEW(vars->val.integer, long); + vars->val_len = sizeof(long); + templong = (long) smival->value.uNumber; + ACE_OS::memcpy( (long*) vars->val.integer, + (long*) &templong, + sizeof(long)); + } + break; + + case sNMP_SYNTAX_INT32: + { + long templong; + vars->type = (u_char) smival->syntax; + ACE_NEW(vars->val.integer, long); + vars->val_len = sizeof(long); + templong = (long) smival->value.sNumber; + ACE_OS::memcpy( (long*) vars->val.integer, + (long*) &templong, + sizeof(long)); + } + break; + + // 64 bit counter + case sNMP_SYNTAX_CNTR64: + { + vars->type = ( u_char) smival->syntax; + ACE_NEW(vars->val.counter64, counter64); + vars->val_len = sizeof(struct counter64); + ACE_OS::memcpy( (struct counter64*) vars->val.counter64, + (SmiLPCNTR64) &(smival->value.hNumber), + sizeof( SmiCNTR64)); + } + break; + + } // end switch + +} + +// build the authentication +// works for v1 or v2c +u_char *cmu_snmp::auth_build( u_char *data, + int *length, + long int version, + u_char *community, + int community_len, + int messagelen) +{ + ACE_TRACE("cmu_snmp::auth_build"); + u_char *params; + int plen; + + params = community; + plen = community_len; + + data = asn1::build_sequence(data, + length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + messagelen + plen + 5); + if (data == 0){ + ASNERROR("buildheader"); + return 0; + } + data = asn1::build_int(data, + length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&version, + sizeof(version)); + if (data == 0){ + ASNERROR("buildint"); + return 0; + } + + data = asn1::build_string(data, + length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), + params, + plen ); + if (data == 0){ + ASNERROR("buildstring"); + return 0; + } + + return (u_char *)data; +} + + +// build a variable binding +u_char * cmu_snmp::build_var_op(u_char *data, oid * var_name, + int *var_name_len, + u_char var_val_type, + int var_val_len, u_char *var_val, + int *listlength) + +{ + ACE_TRACE("cmu_snmp::build_var_op"); + int dummyLen, headerLen; + u_char *dataPtr; + + dummyLen = *listlength; + dataPtr = data; + + data += 4; + dummyLen -=4; + if (dummyLen < 0) + return 0; + + headerLen = data - dataPtr; + *listlength -= headerLen; + data = asn1::build_objid( data, listlength, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + var_name, *var_name_len); + if (data == 0) { + ASNERROR(""); + return 0; + } + + // based on the type... + switch(var_val_type) { + case ASN_INTEGER: + data = asn1::build_int( data, listlength, var_val_type, (long *)var_val, + var_val_len); + break; + + case SMI_GAUGE: + case SMI_COUNTER: + case SMI_TIMETICKS: + case SMI_UINTEGER: + data = asn1::build_unsigned_int( data, + listlength, + var_val_type, + (u_long *)var_val, + var_val_len); + break; + + case SMI_COUNTER64: + data = asn1::build_unsigned_int64(data, + listlength, + var_val_type, + (struct counter64 *)var_val, + var_val_len); + break; + + case ASN_OCTET_STR: + case SMI_IPADDRESS: + case SMI_OPAQUE: + case SMI_NSAP: + data = asn1::build_string(data, listlength, var_val_type, + var_val, var_val_len); + break; + + case ASN_OBJECT_ID: + data = asn1::build_objid(data, listlength, var_val_type, + (oid *)var_val, var_val_len / sizeof(oid)); + break; + + case ASN_NULL: + data = asn1::build_null(data, listlength, var_val_type); + break; + + case ASN_BIT_STR: + data = asn1::build_bitstring(data, listlength, var_val_type, + var_val, var_val_len); + break; + + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + data = asn1::build_null(data, listlength, var_val_type); + break; + + default: + ASNERROR("wrong type"); + return 0; + } + if (data == 0) { + ASNERROR(""); + return 0; + } + dummyLen = (data - dataPtr) - headerLen; + + asn1::build_sequence(dataPtr, &dummyLen, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + dummyLen); + return data; +} + + +// serialize the pdu +int cmu_snmp::build( struct snmp_pdu *pdu, u_char *packet, + int *out_length, long version, + u_char* community, int community_len) +{ + ACE_TRACE("cmu_snmp::build"); + u_char buf[SNMP_MSG_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable) { + cp = cmu_snmp::build_var_op( cp, vp->name, + &vp->name_length, vp->type, + vp->val_len, (u_char *)vp->val.string, + &length); + if (cp == 0) + return -1; + } + totallength = cp - packet; + + length = SNMP_MSG_LENGTH; + + // encode the total len + cp = asn1::build_header( buf, &length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), + totallength); + if (cp == 0) + return -1; + ACE_OS::memcpy( (char *)cp, (char *)packet,totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG) { + + // request id + cp = asn1::build_int( packet, + &length, + (u_char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, + sizeof(pdu->reqid)); + if (cp == 0) + return -1; + + // error status + cp = asn1::build_int(cp, + &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == 0) + return -1; + + // error index + cp = asn1::build_int(cp, + &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == 0) + return -1; + } + else { // this is a trap message + + // enterprise + cp = asn1::build_objid( packet, + &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, + pdu->enterprise_length); + if (cp == 0) + return -1; + + // agent-addr + cp = asn1::build_string(cp, + &length, + // HDN Fixed to use correct tag + (u_char)SMI_IPADDRESS, + //(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), + (u_char *)&pdu->agent_addr.sin_addr.s_addr, + sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == 0) + return -1; + + // generic trap + cp = asn1::build_int(cp, + &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, + sizeof(pdu->trap_type)); + if (cp == 0) + return -1; + + // specific trap + cp = asn1::build_int( cp, + &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, + sizeof(pdu->specific_type)); + if (cp == 0) + return -1; + + // timestamp + cp = asn1::build_int(cp, + &length, + // HDN Fixed to use correct tag + (u_char)SMI_TIMETICKS, + //(u_char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->time, + sizeof(pdu->time)); + if (cp == 0) + return -1; + } + + if (length < totallength) + return -1; + // fixed + ACE_OS::memcpy((char *)cp, (char *)buf, totallength); + totallength += cp - packet; + + length = SNMP_MSG_LENGTH; + cp = asn1::build_header(buf, + &length, + (u_char)pdu->command, + totallength); + if (cp == 0) + return -1; + if (length < totallength) + return -1; + // fixed + ACE_OS::memcpy((char *)cp, (char *)packet, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = cmu_snmp::auth_build( packet, + &length, + version, + community, + community_len, + totallength ); + if (cp == 0) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + // fixed + ACE_OS::memcpy((char *)cp, (char *)buf, totallength); + totallength += cp - packet; + *out_length = totallength; + + return 0; +} + +// parse the authentication header +u_char *cmu_snmp::auth_parse(u_char *data, + int *length, u_char *sid, + int *slen, long *version) +{ + ACE_TRACE("cmu_snmp::auth_parse"); + u_char type; + + // get the type + data = asn1::parse_header( data, length, &type); + if (data == 0){ + ASNERROR("bad header"); + return 0; + } + + if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { + ASNERROR("wrong auth header type"); + return 0; + } + + // get the version + data = asn1::parse_int(data, length, &type, version, sizeof(*version)); + if (data == 0) { + ASNERROR("bad parse of version"); + return 0; + } + + // get the community name + data = asn1::parse_string(data, length, &type, sid, slen); + if (data == 0) { + ASNERROR("bad parse of community"); + return 0; + } + + return (u_char *)data; +} + +/* u_char *data, // IN - pointer to the start of object + oid *var_name, // OUT - object id of variable + int *var_name_len, // IN/OUT - length of variable name + u_char *var_val_type, // OUT - type of variable + (int or octet string) (one byte) + int *var_val_len, // OUT - length of variable + u_char **var_val, // OUT - pointer to ASN1 encoded value of variable +*/ + +u_char * +cmu_snmp::parse_var_op( u_char *data, oid *var_name, + int *var_name_len, u_char *var_val_type, + int *var_val_len, u_char **var_val, + int *listlength) +{ + ACE_TRACE("cmu_snmp::parse_var_op"); + u_char var_op_type; + int var_op_len = *listlength; + u_char *var_op_start = data; + + data = asn1::parse_header(data, &var_op_len, &var_op_type); + if (data == 0){ + ASNERROR(""); + return 0; + } + if (var_op_type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return 0; + data = asn1::parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len); + if (data == 0) { + ASNERROR(""); + return 0; + } + if (var_op_type != (u_char) + (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID)) + return 0; + *var_val = data; /* save pointer to this object */ + /* find out what type of object this is */ + data = asn1::parse_header(data, &var_op_len, var_val_type); + if (data == 0) { + ASNERROR(""); + return 0; + } + *var_val_len = var_op_len; + data += var_op_len; + *listlength -= (int)(data - var_op_start); + return data; +} + + + +// build a pdu from a data and length +int cmu_snmp::parse( struct snmp_pdu *pdu, + u_char *data, + u_char *community_name, + u_long &community_len, + snmp_version &spp_version, + int length) +{ + ACE_TRACE("cmu_snmp::parse"); + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + + // authenticates message and returns length if valid + data = cmu_snmp::auth_parse(data, + &length, + community, + &community_length, + &version); + if (data == 0) + return -1; + + // copy the returned community name + ACE_OS::memcpy( (u_char *) community_name, + (u_char *) community, + community_length); + community_len = (long) community_length; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C ) { + ASNERROR("Wrong version"); + return -1; + } + + spp_version = (snmp_version) version; + + data = asn1::parse_header(data, + &length, + &msg_type); + if (data == 0) + return -1; + pdu->command = msg_type; + + if (pdu->command != TRP_REQ_MSG){ + // get the rid + data = asn1::parse_int(data, + &length, &type, + (long *)&pdu->reqid, + sizeof(pdu->reqid)); + if (data == 0) + return -1; + // get the error status + data = asn1::parse_int(data, + &length, + &type, + (long *)&pdu->errstat, + sizeof(pdu->errstat)); + if (data == 0) + return -1; + // get the error index + data = asn1::parse_int(data, + &length, + &type, + (long *)&pdu->errindex, + sizeof(pdu->errindex)); + if (data == 0) + return -1; + } + else { // is a trap + + // get the enterprise + pdu->enterprise_length = MAX_NAME_LEN; + data = asn1::parse_objid(data, + &length, + &type, + objid, + &pdu->enterprise_length); + if (data == 0) + return -1; + + ACE_NEW_RETURN(pdu->enterprise, + oid[pdu->enterprise_length*sizeof(oid)],-1); + + // fixed + ACE_OS::memcpy((char *)pdu->enterprise,(char *)objid, + pdu->enterprise_length * sizeof(oid)); + + // get source address + four = 4; + data = asn1::parse_string(data, &length, &type, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, + &four); + if (data == 0) + return -1; + + // get trap type + data = asn1::parse_int(data, &length, &type, (long *)&pdu->trap_type, + sizeof(pdu->trap_type)); + if (data == 0) + return -1; + + // trap type + data = asn1::parse_int(data, &length, &type, (long *)&pdu->specific_type, + sizeof(pdu->specific_type)); + if (data == 0) + return -1; + + // timestamp + data = asn1::parse_int(data, &length, &type, (long *)&pdu->time, + sizeof(pdu->time)); + if (data == 0) + return -1; + } + + // get the vb list + data = asn1::parse_header(data, &length, &type); + if (data == 0) + return -1; + + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + + while((int)length > 0) { + if (pdu->variables == 0) { + ACE_NEW_RETURN(pdu->variables, variable_list, -1); + vp = pdu->variables; + } else { + ACE_NEW_RETURN(vp->next_variable, variable_list, -1); + vp = vp->next_variable; + } + vp->next_variable = 0; + vp->val.string = 0; + vp->name = 0; + vp->name_length = MAX_NAME_LEN; + data = cmu_snmp::parse_var_op( data, objid, + &vp->name_length, &vp->type, + &vp->val_len, &var_val, + (int *)&length); + if (data == 0) + return -1; + + ACE_NEW_RETURN(op, oid[(unsigned)vp->name_length * sizeof(oid)], -1); + + // fixed + ACE_OS::memcpy((char *)op, (char *)objid, vp->name_length * sizeof(oid)); + vp->name = op; + + len = SNMP_MSG_LENGTH; + switch((short)vp->type) { + case ASN_INTEGER: + case SMI_COUNTER: + case SMI_GAUGE: + case SMI_TIMETICKS: + case SMI_UINTEGER: + ACE_NEW_RETURN(vp->val.integer,long, -1); + vp->val_len = sizeof(long); + asn1::parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case SMI_COUNTER64: + ACE_NEW_RETURN(vp->val.counter64, counter64, -1); + vp->val_len = sizeof(struct counter64); + asn1::parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + + case ASN_OCTET_STR: + case SMI_IPADDRESS: + case SMI_OPAQUE: + case SMI_NSAP: + ACE_NEW_RETURN(vp->val.string, u_char[(unsigned)vp->val_len + 1], -1); + asn1::parse_string(var_val, &len, &vp->type, vp->val.string, + &vp->val_len); + break; + + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn1::parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + //vp->val_len *= sizeof(oid); + + ACE_NEW_RETURN(vp->val.objid, oid[(unsigned)vp->val_len*sizeof(oid)], -1); + + // fixed + ACE_OS::memcpy((char *)vp->val.objid, + (char *)objid, + vp->val_len * sizeof(oid)); + break; + + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + ASNERROR("bad type returned "); + break; + } + } + return 0; +} diff --git a/ACE/ASNMP/asnmp/asn1.h b/ACE/ASNMP/asnmp/asn1.h new file mode 100644 index 00000000000..3be7e3925ef --- /dev/null +++ b/ACE/ASNMP/asnmp/asn1.h @@ -0,0 +1,345 @@ +/* -*-C++-*- */ +#ifndef ASN1 +#define ASN1 +//============================================================================= +/** + * @file asn1.h + * + * $Id$ + * + * Abstract Syntax Notation One, ASN.1 + * As defined in ISO/IS 8824 and ISO/IS 8825 + * This implements a subset of the above International Standards that + * is sufficient to implement SNMP. + * + * + * @author Steve Waldbusser/CMU ? + */ +//============================================================================= + + +/********************************************************************** + Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/snmp.h" + +// CMU code to define "oid" typedef (old C style) +#ifndef EIGHTBIT_SUBIDS +typedef unsigned long oid; +#define MAX_SUBID 0xFFFFFFFF +#else +typedef unsigned char oid; +#define MAX_SUBID 0xFF +#endif + +#define MAX_OID_LEN 64 /* max subid's in an oid */ + + +// asn.1 values +#define ASN_BOOLEAN (0x01) +#define ASN_INTEGER (0x02) +#define ASN_BIT_STR (0x03) +#define ASN_OCTET_STR (0x04) +#define ASN_NULL (0x05) +#define ASN_OBJECT_ID (0x06) +#define ASN_SEQUENCE (0x10) +#define ASN_SET (0x11) +#define ASN_UNIVERSAL (0x00) +#define ASN_APPLICATION (0x40) +#define ASN_CONTEXT (0x80) +#define ASN_PRIVATE (0xC0) +#define ASN_PRIMITIVE (0x00) +#define ASN_CONSTRUCTOR (0x20) +#define ASN_LONG_LEN (0x80) +#define ASN_EXTENSION_ID (0x1F) +#define ASN_BIT8 (0x80) + +#define IS_CONSTRUCTOR(byte) ((byte) & ASN_CONSTRUCTOR) +#define IS_EXTENSION_ID(byte) (((byte) & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) + +#define ASNERROR( string) +#define MAX_NAME_LEN 64 +#define SNMP_VERSION_1 0 +#define SNMP_VERSION_2C 1 + + +// defined types (from the SMI, RFC 1065) +#define SMI_IPADDRESS (ASN_APPLICATION | 0) +#define SMI_COUNTER (ASN_APPLICATION | 1) +#define SMI_GAUGE (ASN_APPLICATION | 2) +#define SMI_TIMETICKS (ASN_APPLICATION | 3) +#define SMI_OPAQUE (ASN_APPLICATION | 4) +#define SMI_NSAP (ASN_APPLICATION | 5) +#define SMI_COUNTER64 (ASN_APPLICATION | 6) +#define SMI_UINTEGER (ASN_APPLICATION | 7) + +#define GET_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x0) +#define GETNEXT_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x1) +#define GET_RSP_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x2) +#define SET_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x3) +#define TRP_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x4) + +#define GETBULK_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x5) +#define INFORM_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x6) +#define TRP2_REQ_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x7) +#define REPORT_MSG (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x8) + +#define SNMP_NOSUCHOBJECT (ASN_CONTEXT | ASN_PRIMITIVE | 0x0) +#define SNMP_NOSUCHINSTANCE (ASN_CONTEXT | ASN_PRIMITIVE | 0x1) +#define SNMP_ENDOFMIBVIEW (ASN_CONTEXT | ASN_PRIMITIVE | 0x2) + +#define SNMP_MSG_LENGTH 1500 + +typedef struct sockaddr_in ipaddr; + +// pdu +struct snmp_pdu { + int command; // pdu type + unsigned long reqid; // Request id + unsigned long errstat; // Error status + unsigned long errindex; // Error index + + // Trap information + oid *enterprise; // System OID + int enterprise_length; + ipaddr agent_addr; // address of object generating trap + int trap_type; // trap type + int specific_type; // specific type + unsigned long time; // Uptime + + // vb list + struct variable_list *variables; +}; + +// vb list +struct variable_list { + struct variable_list *next_variable; // 0 for last variable + oid *name; // Object identifier of variable + int name_length; // number of subid's in name + unsigned char type; // ASN type of variable + union { // value of variable + long *integer; + unsigned char *string; + oid *objid; + unsigned char *bitstring; + struct counter64 *counter64; + } val; + int val_len; +}; + +struct counter64 { + unsigned long high; + unsigned long low; +}; + +// CMU Interface class for ASN.1 routines +/** + * @class asn1 + * + * @brief Defines the member functions for the asn1 concrete interface class + * CMU routines for performing ASN.1 data marshalling / representation + */ +class ASNMP_Export asn1 + +{ +public: +static unsigned char *parse_int( unsigned char *data, + int *datalength, + unsigned char *type, + long int *intp, + int intsize); +static unsigned char *parse_unsigned_int( unsigned char *data, + int *datalength, + unsigned char *type, + unsigned long *intp, + int intsize); +static unsigned char *build_int( unsigned char *data, + int *datalength, + unsigned char type, + long *intp, + int intsize); + +static unsigned char *build_unsigned_int( unsigned char *data, + int *datalength, + unsigned char type, + unsigned long *intp, + int intsize); + +static unsigned char *parse_string( unsigned char *data, + int *datalength, + unsigned char *type, + unsigned char *string, + int *strlength); + +static unsigned char *build_string( unsigned char *data, + int *datalength, + unsigned char type, + unsigned char *string, + int strlength); + +static unsigned char *parse_header( unsigned char *data, + int *datalength, + unsigned char *type); + +static unsigned char * build_header( unsigned char *data, + int *datalength, + unsigned char type, + int length); + +static unsigned char * build_sequence( unsigned char *data, + int *datalength, + unsigned char type, + int length); + +static unsigned char * parse_length( unsigned char *data, + unsigned long *length); + +static unsigned char *build_length( unsigned char *data, + int *datalength, + int length); + +static unsigned char *build_objid( unsigned char *data, + int *datalength, + unsigned char type, + oid *objid, + int objidlength); + +static unsigned char *parse_objid( unsigned char *data, + int *datalength, + unsigned char *type, + oid *objid, + int *objidlength); + +static unsigned char *parse_null(unsigned char *data, + int *datalength, unsigned + char *type); + +static unsigned char *build_null( unsigned char *data, + int *datalength, + unsigned char type); + +static unsigned char *parse_bitstring( unsigned char *data, + int *datalength, + unsigned char *type, + unsigned char *string, + int *strlength); + +static unsigned char *build_bitstring( unsigned char *data, + int *datalength, + unsigned char type, + unsigned char *string, + int strlength); + +static unsigned char * parse_unsigned_int64(unsigned char *data, + int *datalength, + unsigned char *type, + struct counter64 *cp, + int countersize); + +static unsigned char * build_unsigned_int64( unsigned char *data, + int *datalength, + unsigned char type, + struct counter64 *cp, + int countersize); + +}; + + +// CMU Interface class for SNMPv1, SNMPv2c routines +/** + * @class cmu_snmp + * + * @brief Defines the static functions for the cmu_snmp concrete class. + * These routine create cmu pdu's that can be sent/received on/from agents + */ +class ASNMP_Export cmu_snmp +{ + public: + static struct snmp_pdu *pdu_create( int command); + static void free_pdu( struct snmp_pdu *pdu); + static int build( struct snmp_pdu *pdu, + unsigned char *packet, + int *out_length, + long version, + unsigned char* community, + int community_len); + + static void add_var(struct snmp_pdu *pdu, + oid *name, + int name_length, + SmiVALUE *smival); + + static int parse( struct snmp_pdu *pdu, + unsigned char *data, + unsigned char *community_name, + unsigned long &community_len, + snmp_version &version, + int length); + static unsigned char *auth_build( unsigned char *data, + int *length, + long int version, + unsigned char *community, + int community_len, + int messagelen); + + static unsigned char *build_var_op(unsigned char *data, + oid * var_name, + int *var_name_len, + unsigned char var_val_type, + int var_val_len, + unsigned char *var_val, + int *listlength); + + +static unsigned char *auth_parse(unsigned char *data, + int *length, + unsigned char *sid, + int *slen, + long *version); + +/* + @params data, IN - pointer to the start of object + var_name OUT - object id of variable + var_name_len IN/OUT - length of variable name + var_val_type OUT - type of variable (int or octet string) (one byte) + var_val_len OUT - length of variable + var_val, OUT - pointer to ASN1 encoded value of variable + listlength IN/OUT - number of valid bytes left in var_op_list +*/ +static unsigned char *parse_var_op( unsigned char *data, + oid *var_name, + int *var_name_len, + unsigned char *var_val_type, + int *var_val_len, + unsigned char **var_val, + int *listlength); + +}; + +#endif // ASN1 + diff --git a/ACE/ASNMP/asnmp/asnmp.mpc b/ACE/ASNMP/asnmp/asnmp.mpc new file mode 100644 index 00000000000..40063285e2b --- /dev/null +++ b/ACE/ASNMP/asnmp/asnmp.mpc @@ -0,0 +1,26 @@ +// $Id$ + +project (asnmp_lib) : acelib { + sharedname = asnmp + dynamicflags = ASNMP_BUILD_DLL + includes += $(ACE_ROOT)/ASNMP + + source_files { + address.cpp + asn1.cpp + counter.cpp + ctr64.cpp + gauge.cpp + integer.cpp + octet.cpp + oid.cpp + pdu.cpp + snmp.cpp + target.cpp + timetick.cpp + transaction.cpp + vb.cpp + wpdu.cpp + sagent.cpp + } +} diff --git a/ACE/ASNMP/asnmp/counter.cpp b/ACE/ASNMP/asnmp/counter.cpp new file mode 100644 index 00000000000..c62b1d0a20a --- /dev/null +++ b/ACE/ASNMP/asnmp/counter.cpp @@ -0,0 +1,107 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// counter.cpp +// +// = DESCRIPTION +// Class implementation for SMI Counter32 class. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/counter.h" + +ACE_RCSID(asnmp, counter, "$Id$") + +// constructor with a value +Counter32::Counter32( const unsigned long i):SnmpUInt32(i) +{ + smival.syntax = sNMP_SYNTAX_CNTR32; +} + +// copy constructor +Counter32::Counter32( const Counter32 &c) + : SnmpUInt32 (c) +{ + this->smival.value.uNumber = c.smival.value.uNumber; + smival.syntax = sNMP_SYNTAX_CNTR32; + valid_flag = 1; +} + +// syntax type +SmiUINT32 Counter32::get_syntax() +{ + return sNMP_SYNTAX_CNTR32; +} + +// general assignment from any Value +SnmpSyntax& Counter32::operator=( SnmpSyntax &in_val){ + if ( this == &in_val ) // handle assignement from itself + return *this; + + valid_flag = 0; // will get set true if really valid + if (in_val.valid()) + { + switch (in_val.get_syntax()) + { + case sNMP_SYNTAX_UINT32: + // case sNMP_SYNTAX_GAUGE32: .. indistinquishable from UINT32 + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_TIMETICKS: + case sNMP_SYNTAX_INT32: // implied cast int -> uint + this->smival.value.uNumber = + ((Counter32 &)in_val).smival.value.uNumber; + valid_flag = 1; + break; + } + } + return *this; +} + +// overloaded assignment +Counter32& Counter32::operator=( const unsigned long int i) +{ + this->smival.value.uNumber=i; + return *this; +} + +// overloaded assignment +Counter32& Counter32::operator=( const Counter32 &uli) +{ + this->smival.value.uNumber = uli.smival.value.uNumber; + return *this; +} + +// otherwise, behave like an unsigned long int +Counter32::operator unsigned long() +{ + return this->smival.value.uNumber; +} + +// clone +SnmpSyntax * Counter32::clone() const +{ + return ( SnmpSyntax *) new Counter32(*this); +} diff --git a/ACE/ASNMP/asnmp/counter.h b/ACE/ASNMP/asnmp/counter.h new file mode 100644 index 00000000000..36fda2f84ce --- /dev/null +++ b/ACE/ASNMP/asnmp/counter.h @@ -0,0 +1,79 @@ +/* -*-C++-*- */ +#ifndef COUNTER_ +#define COUNTER_ +//============================================================================= +/** + * @file counter.h + * + * $Id$ + * + * Class definition for SMI Counter32 class. + * + * + * @author Peter E Mellquist + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/smival.h" +#include "asnmp/integer.h" + +//------------[ Counter32 Class ]------------------------------------------ +// The counter class allows all the functionality of unsigned +// 32 bit integers but is recognized as a distinct SMI type. Counter32 +// class objects may be set or get into Vb objects. +// +// This class does not behave as defined by the abstract model +// in RFC 1155 section 3.2.3.3 + +/** + * @class Counter32 + * + * @brief Defines the member functions for the Counter32 concrete class + * This class implements RFC 1155 Counter Object and is named + * Counter32 after the RFC1902 redefinition of V1 SMI datatypes + */ +class ASNMP_Export Counter32 : public SnmpUInt32 +{ + public: + /// constructor with a value + Counter32( const unsigned long i = 0); + + /// copy constructor + Counter32( const Counter32 &c); + + /// syntax type + SmiUINT32 get_syntax(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// overloaded assignment + Counter32& operator=( const Counter32 &uli); + + /// overloaded assignment + Counter32& operator=( const unsigned long i); + + /// otherwise, behave like an unsigned long int + operator unsigned long(); +}; + +#endif // COUNTER_ diff --git a/ACE/ASNMP/asnmp/ctr64.cpp b/ACE/ASNMP/asnmp/ctr64.cpp new file mode 100644 index 00000000000..df3468a1475 --- /dev/null +++ b/ACE/ASNMP/asnmp/ctr64.cpp @@ -0,0 +1,213 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// ctr64.cpp +// +// = DESCRIPTION +// Implementation for Counter64 ( 64 bit counter class). +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/ctr64.h" +#include "ace/OS_NS_stdio.h" + +ACE_RCSID(asnmp, ctr64, "$Id$") + +#define MAX32 4294967295u + +//-----------[ syntax type ]---------------------------------------------- +SmiUINT32 Counter64::get_syntax() +{ + return sNMP_SYNTAX_CNTR64; +} + +//------------------[ constructor with values ]-------------------------- +Counter64::Counter64( unsigned long hiparm, unsigned long loparm) +{ + smival.syntax = sNMP_SYNTAX_CNTR64; + smival.value.hNumber.hipart = hiparm; + smival.value.hNumber.lopart = loparm; +} + +//------------------[ constructor with low value only ]------------------ +Counter64::Counter64( ACE_UINT64 llw ) +{ + smival.syntax = sNMP_SYNTAX_CNTR64; + smival.value.hNumber.hipart = (unsigned long) (llw >> 32); + smival.value.hNumber.lopart = (unsigned long) llw & 0xffffffff; +} + +//------------------[ copy constructor ]--------------------------------- +Counter64::Counter64( const Counter64 &ctr64 ) + : SnmpSyntax (ctr64) +{ + smival.syntax = sNMP_SYNTAX_CNTR64; + smival.value.hNumber.hipart = ctr64.high(); + smival.value.hNumber.lopart = ctr64.low(); +} + +//------------------[ destructor ]--------------------------------- +Counter64::~Counter64() +{ +} + + +//------------------[ Counter64::high() ]------------------------------ +// return the high part +unsigned long Counter64::high() const +{ + return smival.value.hNumber.hipart; +} + + +//------------------[ Counter64::low() ]------------------------------- +// return the low part +unsigned long Counter64::low() const +{ + return smival.value.hNumber.lopart; +} + +//------------------[ set_high( const unsigned long h) ]----------- +// set the high part +void Counter64::set_high( const unsigned long h) +{ + smival.value.hNumber.hipart = h; +} + +//------------------[ set_low( const unsigned long l) ]------------ +// set the low part +void Counter64::set_low( const unsigned long l) +{ + smival.value.hNumber.lopart = l; +} + + +//-----------[ to_long_double( Counter64 c64) ]----------------------------- +// convert a Counter 64 to a long double +long double Counter64::to_long_double() const +{ + long double ld = this->high(); + ld *= MAX32; + ld += this->low(); + return ld; +} + + +//-----------[ ld_to_c64( long double ld) ]---------------------------- +// convert a long double to a Counter64 +// semantics changed from prior version +Counter64& Counter64::assign( long double ld) +{ + smival.syntax = sNMP_SYNTAX_CNTR64; + unsigned long h = smival.value.hNumber.hipart = (unsigned long)(ld / MAX32); + smival.value.hNumber.lopart = (unsigned long)(ld - h); + return *this; +} + +//----------------[ general Value = operator ]--------------------- +SnmpSyntax& Counter64::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + smival.value.hNumber.lopart = 0; // pessimsitic - assume no mapping + smival.value.hNumber.hipart = 0; + + // try to make assignment valid + if (val.valid()){ + switch (val.get_syntax()){ + case sNMP_SYNTAX_CNTR64: + smival.value.hNumber.hipart = + ((Counter64 &)val).smival.value.hNumber.hipart; + smival.value.hNumber.lopart = + ((Counter64 &)val).smival.value.hNumber.lopart; + break; + + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_TIMETICKS: + case sNMP_SYNTAX_GAUGE32: + // case sNMP_SYNTAX_UINT32: .. indistinguishable from GAUGE32 + case sNMP_SYNTAX_INT32: + // take advantage of union... + smival.value.hNumber.lopart = ((Counter64 &)val).smival.value.uNumber; + smival.value.hNumber.hipart = 0; + break; + } + } + return *this; +} + +// overloaded assignment +Counter64& Counter64::operator=( const ACE_UINT64 rhs) +{ + smival.value.hNumber.hipart = (unsigned long) (rhs >> 32); + smival.value.hNumber.lopart = (unsigned long) rhs; + return *this; +} + +// overloaded assignment +Counter64& Counter64::operator=( const Counter64 &rhs) +{ + smival.value.hNumber.hipart = rhs.high(); + smival.value.hNumber.lopart = rhs.low(); + return *this; +} + +// otherwise, behave like an unsigned long int +Counter64::operator ACE_UINT64() +{ + ACE_UINT64 val = smival.value.hNumber.hipart; + val = val << 32; // shift right 4 bytes + val |= smival.value.hNumber.lopart; + return val; +} + +//----------------[ Counter64::clone() ]----------------------------------- +// create a new instance of this Value +SnmpSyntax* Counter64::clone() const +{ + return ( SnmpSyntax *) new Counter64(*this); +} + +//----------------[ Counter64::valid() ]------------------------------------- +int Counter64::valid() const +{ + return 1; +} + +//----------[ return ASCII format ]------------------------- +// TODO: Fix up to do real 64bit decimal value printing... +// For now, print > 32-bit values in hex +const char * Counter64::to_string() +{ + if ( high() != 0 ) + sprintf(output_buffer, "0x%X%08X", + (unsigned int)high(), (unsigned int)low()); + else + sprintf(output_buffer, "%d", (int) low()); + return output_buffer; +} diff --git a/ACE/ASNMP/asnmp/ctr64.h b/ACE/ASNMP/asnmp/ctr64.h new file mode 100644 index 00000000000..6b97b9966f2 --- /dev/null +++ b/ACE/ASNMP/asnmp/ctr64.h @@ -0,0 +1,111 @@ +/* -*-C++-*- */ +#ifndef CTR64_ +#define CTR64_ +//============================================================================= +/** + * @file ctr64.h + * + * $Id$ + * + * SNMP Counter64 class definition. + * + * + * @author Peter E Mellquist + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/smival.h" +#include "ace/Basic_Types.h" + +#define CTR64OUTBUF 30 // maximum ascii string for a 64-bit ctr + + +//---------[ 64 bit Counter Class ]-------------------------------- +// Counter64 Class encapsulates two unsigned integers into a +// a single entity. This type has is available in SNMPv2 but +// may be used anywhere where needed. +// +/** + * @class Counter64 + * + * @brief Defines the member functions for the Counter64 concrete class + * This class implements RFC 1902 64 bit Counter Object. + */ +class ASNMP_Export Counter64 : public SnmpSyntax +{ +public: + /// default constructor + Counter64( ACE_UINT64 llw = 0); + + /// constructor with values + Counter64( unsigned long hiparm, unsigned long loparm); + + /// copy constructor + Counter64( const Counter64 &ctr64); + + /// destructor (ensure that SnmpSyntax::~SnmpSyntax() is overridden) + ~Counter64(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// return a long double representation + long double to_long_double() const; + + /// assign a long double to a counter64 + Counter64& assign( long double ld); + + /// return the high part + unsigned long high() const; + + /// return the low part + unsigned long low() const; + + /// set the high part + void set_high( const unsigned long h); + + /// set the low part + void set_low( const unsigned long l); + + /// overloaded assignment + Counter64& operator=( const ACE_UINT64 rhs); + + /// overloaded assignment + Counter64& operator=( const Counter64 &rhs); + + /// get a printable ASCII representation + const char *to_string(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// general validity test, always true + int valid() const; + + /// otherwise, behave like an ACE_UINT64 + operator ACE_UINT64(); + +protected: + char output_buffer[CTR64OUTBUF]; +}; + +#endif // CTR64_ diff --git a/ACE/ASNMP/asnmp/enttraps.h b/ACE/ASNMP/asnmp/enttraps.h new file mode 100644 index 00000000000..433538eb258 --- /dev/null +++ b/ACE/ASNMP/asnmp/enttraps.h @@ -0,0 +1,147 @@ +/* -*-C++-*- */ +#ifndef ENTTRAPS_ +#define ENTTRAPS_ +//============================================================================= +/** + * @file enttraps.h + * + * $Id$ + * + * constants for Enterprise Traps + * + * + * @author Peter E MellquistMichael R MacFaden mrm@cisco.com - rework & ACE port + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/asn1.h" // ASN.1 header file + +//--------------[ well known trap ids ]----------------------------------- +/** + * @class snmpTrapsOid + * + * @brief Defines the member functions for the snmpTrapsOid base class + * to implement the traps defined in RFC 1215 + */ +class ASNMP_Export snmpTrapsOid : public Oid +{ + public: + snmpTrapsOid (void):Oid("1.3.6.1.6.3.1.1.5"){} + SnmpSyntax& operator=( SnmpSyntax &val){ return Oid::operator=(val); } +}; + +/** + * @class snmpTrapEnterpriseOid + * + * @brief Defines the default Enterprise Oid for this software package + */ +class ASNMP_Export snmpTrapEnterpriseOid : public Oid +{ + public: + snmpTrapEnterpriseOid(void): Oid("1.3.6.1.6.3.1.1.4.3.0") { } + SnmpSyntax& operator=( SnmpSyntax &val){ return Oid::operator=(val); } +}; + +/** + * @class coldStartOid + * + * @brief Defines the RFC 1215 agent cold start generic trap (system reboot) + */ +class ASNMP_Export coldStartOid : public snmpTrapsOid +{ + public: + coldStartOid( void){*this+=".1";} + SnmpSyntax& operator=( SnmpSyntax &val){ return snmpTrapsOid::operator=(val); } +}; + +/** + * @class warmStartOid + * + * @brief Defines the RFC 1215 agent warm start generic trap (agent reboot) + */ +class ASNMP_Export warmStartOid : public snmpTrapsOid +{ + public: + warmStartOid( void){*this+=".2";} + SnmpSyntax& operator=( SnmpSyntax &val){ return snmpTrapsOid::operator=(val); } +}; + +/** + * @class linkDownOid + * + * @brief Defines the RFC 1215 interface (link) down trap + */ +class ASNMP_Export linkDownOid : public snmpTrapsOid +{ + public: + linkDownOid( void){*this+=".3";} + SnmpSyntax& operator=( SnmpSyntax &val){ return snmpTrapsOid::operator=(val); } +}; + + +// SMI LinkUp Oid +/** + * @class linkUpOid + * + * @brief Defines the RFC 1215 interface (link) up trap + */ +class ASNMP_Export linkUpOid : public snmpTrapsOid +{ + public: + linkUpOid( void){*this+=".4";} + SnmpSyntax& operator=( SnmpSyntax &val){ return snmpTrapsOid::operator=(val); } +}; + +/** + * @class authenticationFailureOid + * + * @brief Defines the RFC 1215 device/agent invalid access trap + */ +class ASNMP_Export authenticationFailureOid : public snmpTrapsOid +{ + public: + authenticationFailureOid( void){*this+=".5";} + SnmpSyntax& operator=( SnmpSyntax &val){ return snmpTrapsOid::operator=(val); } +}; + +/** + * @class egpNeighborLossOid + * + * @brief Defines the RFC 1215 Exterior Gateway Protocol neighbor loss trap + */ +class ASNMP_Export egpNeighborLossOid : public snmpTrapsOid +{ + public: + egpNeighborLossOid( void){*this+=".6";} + SnmpSyntax& operator=( SnmpSyntax &val){ return snmpTrapsOid::operator=(val); } +}; + +#ifdef DEFINE_TRAP_CONSTANTS_ + +const coldStartOid coldStart; +const warmStartOid warmStart; +const linkDownOid linkDown; +const linkUpOid linkUp; +const authenticationFailureOid authenticationFailure; +const egpNeighborLossOid egpNeighborLoss; +const snmpTrapEnterpriseOid snmpTrapEnterprise; + +#endif + +#endif // ENTTRAPS_ diff --git a/ACE/ASNMP/asnmp/gauge.cpp b/ACE/ASNMP/asnmp/gauge.cpp new file mode 100644 index 00000000000..9051e2f83fb --- /dev/null +++ b/ACE/ASNMP/asnmp/gauge.cpp @@ -0,0 +1,114 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// gauge.cpp +// +// = DESCRIPTION +// Class implemtation for SMI Gauge32 class. +// NOTES: This does not behave exactly as a Gauge described in RFC 1155 +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/gauge.h" // header file for gauge class + +ACE_RCSID(asnmp, gauge, "$Id$") + +// constructor with a value +Gauge32::Gauge32( const unsigned long i):SnmpUInt32(i) +{ + smival.syntax = sNMP_SYNTAX_GAUGE32; +} + +// copy constructor +Gauge32::Gauge32 ( const Gauge32 &g) + : SnmpUInt32 (g) +{ this->smival.value.uNumber = g.smival.value.uNumber; + smival.syntax = sNMP_SYNTAX_GAUGE32; + valid_flag = 1; +} + +// destructor +Gauge32::~Gauge32() +{ +} + +// syntax type +SmiUINT32 Gauge32::get_syntax() +{ + return sNMP_SYNTAX_GAUGE32; +} + +// overloaded assignment +Gauge32& Gauge32::operator=( const Gauge32 &uli) +{ + this->smival.value.uNumber = uli.smival.value.uNumber; + return *this; +} + +// overloaded assignment +Gauge32& Gauge32::operator=( const unsigned long int i) +{ + smival.value.uNumber=i; return *this; +} + +// general assignment from any Value +// TODO: this is broken if not inherited from UInt32 (see UInt32 code). +SnmpSyntax& Gauge32::operator=( SnmpSyntax &in_val) +{ + + if ( this == &in_val ) // handle assignement from itself + return *this; + + valid_flag = 0; // will get set true if really valid + if (in_val.valid()) + { + switch (in_val.get_syntax()) + { + case sNMP_SYNTAX_UINT32: + case sNMP_SYNTAX_GAUGE32: + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_TIMETICKS: + case sNMP_SYNTAX_INT32: // implied cast int -> uint + this->smival.value.uNumber = + ((Gauge32 &)in_val).smival.value.uNumber; + valid_flag = 1; + break; + } + } + return *this; +} + +// otherwise, act as unsigned long +Gauge32::operator unsigned long() +{ + return smival.value.uNumber; +} + +// clone - create a new instance of this Value +SnmpSyntax* Gauge32::clone() const +{ + return ( SnmpSyntax *) new Gauge32(*this); +} diff --git a/ACE/ASNMP/asnmp/gauge.h b/ACE/ASNMP/asnmp/gauge.h new file mode 100644 index 00000000000..202edaf98bf --- /dev/null +++ b/ACE/ASNMP/asnmp/gauge.h @@ -0,0 +1,79 @@ +/* -*-C++-*- */ +#ifndef GAUGE_ +#define GAUGE_ +//============================================================================= +/** + * @file gauge.h + * + * $Id$ + * + * Class definition for SMI Gauge32 class. + * This class currently does not behave as defined by the abstract model + * in RFC 1155 section 3.2.3.4 (ie the value doesn't latch on the max value) + * + * + * @author Peter E Mellquist + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/integer.h" + +//------------[ Gauge32 Class ]------------------------------------------ +// The gauge class allows all the functionality of unsigned +// integers but is recognized as a distinct SMI type. Gauge32 +// objects may be set or get into Vb objects. +// + +/** + * @class Gauge32: + * + * @brief Define RFC1902 Gauge datatype from RFC 1155 section 3.2.3.4 + * Note that this datatype does not behave exactly (acts like a long) + */ +class ASNMP_Export Gauge32: public SnmpUInt32 +{ + public: + /// constructor with a value + Gauge32( const unsigned long i = 0); + + /// copy constructor + Gauge32 ( const Gauge32 &g); + + /// destructor for a Gauge32 (ensure that Value::~Value() is overridden) + ~Gauge32(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// overloaded assignment + Gauge32& operator=( const Gauge32 &uli); + + /// overloaded assignment + Gauge32& operator=( const unsigned long i); + + /// otherwise, behave like an unsigned int + operator unsigned long(); + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); +}; +#endif //GAUGE_ diff --git a/ACE/ASNMP/asnmp/integer.cpp b/ACE/ASNMP/asnmp/integer.cpp new file mode 100644 index 00000000000..d732e0f3ff9 --- /dev/null +++ b/ACE/ASNMP/asnmp/integer.cpp @@ -0,0 +1,230 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// integer.cpp +// +// = DESCRIPTION +// Class implemtation for SMI Integer classes. +// +// = AUTHOR +// Jeff Meyer +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/integer.h" // header file for gauge class +#include "ace/OS_NS_stdio.h" + +ACE_RCSID(asnmp, integer, "$Id$") + +// constructor with value +SnmpUInt32::SnmpUInt32 (const unsigned long i) +{ + smival.value.uNumber=i; + smival.syntax = sNMP_SYNTAX_UINT32; + valid_flag = 1; +} + +// copy constructor +SnmpUInt32::SnmpUInt32( const SnmpUInt32 &c) + : SnmpSyntax (c) +{ + smival.value.uNumber=c.smival.value.uNumber; + smival.syntax = sNMP_SYNTAX_UINT32; + valid_flag = 1; +} + +// destructor (ensure that SnmpSyntax::~SnmpSyntax() is overridden) +SnmpUInt32::~SnmpUInt32() +{ +} + +// syntax type +SmiUINT32 SnmpUInt32::get_syntax() +{ + return sNMP_SYNTAX_UINT32; +} + +// object validity +int SnmpUInt32::valid( void) const +{ + return valid_flag; +} + +// overloaded assignment +SnmpUInt32& SnmpUInt32::operator=( const unsigned long int i) +{ + smival.value.uNumber=i; + valid_flag = 1; + return *this; +} + +// general assignment from any Value +SnmpSyntax& SnmpUInt32::operator=( SnmpSyntax &in_val) +{ + if ( this == &in_val ) // handle assignement from itself + return *this; + + valid_flag = 0; // will get set true if really valid + if (in_val.valid()) + { + switch (in_val.get_syntax()) + { + case sNMP_SYNTAX_UINT32: + // case sNMP_SYNTAX_GAUGE32: .. indistinquishable from UINT32 + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_TIMETICKS: + case sNMP_SYNTAX_INT32: // implied cast int -> uint + this->smival.value.uNumber = + ((SnmpUInt32 &)in_val).smival.value.uNumber; + valid_flag = 1; + break; + } + } + return *this; +} + +// overloaded assignment +SnmpUInt32& SnmpUInt32::operator=( const SnmpUInt32 &uli) +{ + this->smival.value.uNumber = uli.smival.value.uNumber; return *this; +} + +// otherwise, behave like an unsigned long int +SnmpUInt32::operator unsigned long() +{ + return smival.value.uNumber; +} + +// create a new instance of this Value +SnmpSyntax* SnmpUInt32::clone() const +{ + return (SnmpSyntax *) new SnmpUInt32(*this); +} + +// ASCII format return +const char * SnmpUInt32::to_string() +{ + sprintf(output_buffer, "%d", (int) (this->smival.value.uNumber)); + return output_buffer; +} + + +//==================================================================== +// INT 32 Implementation +//==================================================================== + +// default constructor +SnmpInt32::SnmpInt32 (const long i) +{ + smival.value.sNumber=i; + smival.syntax = sNMP_SYNTAX_INT32; + valid_flag = 1; +} + +// constructor with value +SnmpInt32::SnmpInt32 (const SnmpInt32 &c) + : SnmpSyntax (c) +{ + smival.value.sNumber=c.smival.value.sNumber; + smival.syntax = sNMP_SYNTAX_INT32; + valid_flag = 1; +} + +// destructor +SnmpInt32::~SnmpInt32() +{ +} + +// syntax type +SmiUINT32 SnmpInt32::get_syntax() +{ + return sNMP_SYNTAX_INT32; +} + +// object validity +int SnmpInt32::valid( void) const +{ + return valid_flag; +} + +// overloaded assignment +SnmpInt32& SnmpInt32::operator=( const long i) +{ + this->smival.value.sNumber = (unsigned long) i; + valid_flag = 1; + return *this; +} + +// overloaded assignment +SnmpInt32& SnmpInt32::operator=( const SnmpInt32 &uli) +{ + this->smival.value.sNumber = uli.smival.value.sNumber; + valid_flag = 1; + return *this; +} + +// general assignment from any Value +SnmpSyntax& SnmpInt32::operator=( SnmpSyntax &in_val) +{ + if ( this == &in_val ) // handle assignement from itself + return *this; + + valid_flag = 0; // will get set true if really valid + if (in_val.valid()) + { + switch (in_val.get_syntax()) + { + case sNMP_SYNTAX_INT32: + case sNMP_SYNTAX_UINT32: // implied cast uint -> int + // case sNMP_SYNTAX_GAUGE32: .. indistinquishable from UINT32 + case sNMP_SYNTAX_CNTR32: // implied cast uint -> int + case sNMP_SYNTAX_TIMETICKS: // implied cast uint -> int + this->smival.value.sNumber = + ((SnmpInt32 &)in_val).smival.value.sNumber; + valid_flag = 1; + break; + } + } + return *this; +} + +// otherwise, behave like a long int +SnmpInt32::operator long() +{ + return (long) smival.value.sNumber; +} + +// clone - create a new instance of this Value +SnmpSyntax* SnmpInt32::clone() const +{ + return ( SnmpSyntax *) new SnmpInt32(*this); +} + +// ASCII format return + +const char *SnmpInt32::to_string() +{ + sprintf(output_buffer, "%d", (int) (long) this->smival.value.sNumber); + return output_buffer; +} diff --git a/ACE/ASNMP/asnmp/integer.h b/ACE/ASNMP/asnmp/integer.h new file mode 100644 index 00000000000..d120684c095 --- /dev/null +++ b/ACE/ASNMP/asnmp/integer.h @@ -0,0 +1,142 @@ +/* -*-C++-*- */ +#ifndef SNMPINTEGER_ +#define SNMPINTEGER_ +//============================================================================= +/** + * @file integer.h + * + * $Id$ + * + * Class definition for Integer classes convertable to SMI. + * + * + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/smival.h" + +// TODO get rid of this constant +#define INTOUTBUF 15 // largest ASCII formatted integer + +//------------[ Integer Classes ]------------------------------------------ +// The integer class allows all the functionality of the various +// integers but is contained in a Value object for consistency +// among the various types. +// class objects may be set or get into Vb objects. +// + +// 32 bit unsigned integer class +/** + * @class SnmpUInt32 + * + * @brief Implement RFC 1920 Unsigned Integer SMI datatype + */ +class ASNMP_Export SnmpUInt32 : public SnmpSyntax +{ + + public: + /// default constructor + SnmpUInt32 (const unsigned long i = 0); + + /// copy constructor + SnmpUInt32( const SnmpUInt32 &c); + + /// destructor (ensure that SnmpSyntax::~SnmpSyntax() is overridden) + virtual ~SnmpUInt32(); + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// overloaded assignment + SnmpUInt32& operator=( const unsigned long i); + + /// overloaded assignment + SnmpUInt32& operator=( const SnmpUInt32 &uli); + + /// otherwise, behave like an unsigned long int + operator unsigned long(); + + /// get a printable ASCII value + virtual const char *to_string(); + + /// create a new instance of this Value + virtual SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// did object construct properly + int valid() const; + + protected: + /// contain string representation of object + int valid_flag; + char output_buffer[INTOUTBUF]; +}; + + +// 32 bit signed integer class + /** + * @class SnmpInt32 + * + * @brief Implement RFC 1902 32 bit Integer SMI data object + */ +class ASNMP_Export SnmpInt32 : public SnmpSyntax +{ + public: + /// constructor with value + SnmpInt32 (const long i = 0); + + /// constructor with value + SnmpInt32 (const SnmpInt32 &c); + + /// destructor (ensure that SnmpSyntax::~SnmpSyntax() is overridden) + virtual ~SnmpInt32(); + + /// syntax type + virtual SmiUINT32 get_syntax(); + + /// overloaded assignment + SnmpInt32& operator=( const long i); + + /// overloaded assignment + SnmpInt32& operator=( const SnmpInt32 &li); + + /// otherwise, behave like a long int + operator long(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + + /// get a printable ASCII value + const char *to_string(); + + /// logical state of object + int valid() const; + + protected: + /// contain string representation of object + int valid_flag; + char output_buffer[INTOUTBUF]; +}; + +#endif diff --git a/ACE/ASNMP/asnmp/octet.cpp b/ACE/ASNMP/asnmp/octet.cpp new file mode 100644 index 00000000000..885197919c4 --- /dev/null +++ b/ACE/ASNMP/asnmp/octet.cpp @@ -0,0 +1,594 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// octet.cpp +// +// = DESCRIPTION +// Implements the SMI Octet datatype (RFC 1155) +// This class is fully contained and does not rely on or any other +// SNMP libraries. Ported to ACE by Michael MacFaden mrm@cisco.com +// +// = AUTHOR +// Peter E Mellquist +// +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/octet.h" // include definition for octet class +#include "ace/OS_Memory.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_ctype.h" +#include "ace/os_include/os_ctype.h" + +ACE_RCSID(asnmp, octet, "$Id$") + +//============[ syntax type ]========================================= +SmiUINT32 OctetStr::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +inline +void init_octet_smi(SmiVALUE& smi) +{ + smi.syntax = sNMP_SYNTAX_OCTETS; + smi.value.string.ptr = 0; + smi.value.string.len = 0; +} + +inline +void reset_octet_smi(SmiVALUE& smi) +{ + delete [] smi.value.string.ptr; + smi.value.string.ptr = 0; + smi.value.string.len = 0; +} + +inline +int copy_octet_smi(SmiVALUE& smi, int size, const char *src, int& valid_flag) +{ + valid_flag = 0; + + if (smi.value.string.ptr) + delete [] smi.value.string.ptr; + + ACE_NEW_RETURN(smi.value.string.ptr, SmiBYTE[size], 1); + ACE_OS::memcpy( smi.value.string.ptr, src, size); + smi.value.string.len = size; + valid_flag = 1; + return 0; +} + +//============[ default constructor ]========================= +OctetStr::OctetStr( const char * string, long size): + output_buffer(0), validity(0) +{ + + init_octet_smi(smival); + + // check for null string + if ( !string) + return; + + if (size == -1) // calc if no length given - assume c style string + size = ACE_OS::strlen( string); + + copy_octet_smi(smival, size, string, validity); +} + + +//============[ set the data on an already constructed Octet ]============ +// TODO: should return status since it can fail in so many places +void OctetStr::set_data( const SmiBYTE* string, long size) +{ + // invalid args, set octetStr to not valid + if ( !string || !size) { + validity = 0; + return; + } + + // assume non-zero terminated string + if (size == -1) // calc if no length given - assume c style string + size = ACE_OS::strlen( (char *)string); + + // free up already used space + if ( smival.value.string.ptr ) { + reset_octet_smi(smival); + } + smival.value.string.len = 0; + + + copy_octet_smi(smival, size, (const char *)string, validity); +} + +//============[ constructor using another octet object ]============== +OctetStr::OctetStr ( const OctetStr &octet): + SnmpSyntax (octet), output_buffer(0), validity(1) +{ + init_octet_smi(smival); + // check for zero len case + if ( octet.smival.value.string.len == 0) { + return; + } + + // must be a valid object + if ( octet.validity == 0) { + validity = 0; + return; + } + + // get the mem needed + copy_octet_smi(smival, octet.smival.value.string.len, + (const char *)octet.smival.value.string.ptr, validity); +} + +//=============[ destructor ]========================================= +OctetStr::~OctetStr() +{ + reset_octet_smi(smival); + delete [] output_buffer; +} + + +//=============[ assignment to a string operator overloaded ]========= +OctetStr& OctetStr::operator=( const char *string) +{ + // get the string size + size_t nz; + + // free up previous memory if needed + if ( smival.value.string.ptr ) { + reset_octet_smi(smival); + } + + // if empty then we are done + if (!string || !(nz = ACE_OS::strlen( string))) { + validity = 1; + return *this; + } + + // get memory needed + copy_octet_smi(smival, nz, string, validity); + return *this; +} + +//=============[ assignment to another oid object overloaded ]======== +OctetStr& OctetStr::operator=( const OctetStr &octet) +{ + // protect against assignment from self + if ( this == &octet ) + return *this; + + // don't assign from invalid objs + if (!octet.validity) { + return *this; + } + + // free up previous memory if needed + if ( smival.value.string.len ) { + reset_octet_smi(smival); + } + + if (!octet.smival.value.string.len) { + validity = 1; + return *this; + } + + // get some memory + copy_octet_smi(smival, octet.smival.value.string.len, + (const char*) octet.smival.value.string.ptr, validity); + return *this; // return self reference +} + +//==============[ equivlence operator overloaded ]==================== +bool operator==( const OctetStr &lhs, const OctetStr &rhs) +{ + if( lhs.left_comparison( rhs.smival.value.string.len, rhs)==0) + return true; + else + return false; +} + +//==============[ not equivlence operator overloaded ]================ +bool operator!=( const OctetStr &lhs, const OctetStr &rhs) +{ + if( lhs.left_comparison( rhs.smival.value.string.len, rhs)!=0) + return true; + else + return false; +} + +//==============[ less than < overloaded ]============================ +bool operator<( const OctetStr &lhs, const OctetStr &rhs) +{ + if( lhs.left_comparison( rhs.smival.value.string.len, rhs)<0) + return true; + else + return false; +} + +//==============[ less than <= overloaded ]=========================== +bool operator<=( const OctetStr &lhs, const OctetStr &rhs) +{ + if(( lhs.left_comparison( rhs.smival.value.string.len, rhs)<0) || + ( lhs.left_comparison( rhs.smival.value.string.len, rhs)==0)) + return true; + else + return false; +} + +//===============[ greater than > overloaded ]======================== +bool operator>( const OctetStr &lhs, const OctetStr &rhs) +{ + if( lhs.left_comparison( rhs.smival.value.string.len, rhs)>0) + return true; + else + return false; +} + +//===============[ greater than >= overloaded ]======================= +bool operator>=( const OctetStr &lhs, const OctetStr &rhs) +{ + if(( lhs.left_comparison( rhs.smival.value.string.len, rhs)>0) || + ( lhs.left_comparison( rhs.smival.value.string.len, rhs)==0)) + return true; + else + return false; +} + +//===============[ equivlence operator overloaded ]=================== +bool operator==( const OctetStr &lhs,const char *rhs) +{ + OctetStr to( rhs); + if( lhs.left_comparison( to.smival.value.string.len,to)==0) + return true; + else + return false; +} + +//===============[ not equivlence operator overloaded ]=============== +bool operator!=( const OctetStr &lhs,const char *rhs) +{ + OctetStr to( rhs); + if ( lhs.left_comparison( to.smival.value.string.len,to)!=0) + return true; + else + return false; +} + +//===============[ less than < operator overloaded ]================== +bool operator<( const OctetStr &lhs,const char *rhs) +{ + OctetStr to( rhs); + if ( lhs.left_comparison( to.smival.value.string.len,to)<0) + return true; + else + return false; +} + +//===============[ less than <= operator overloaded ]================= +bool operator<=( const OctetStr &lhs,char *rhs) +{ + OctetStr to( rhs); + if (( lhs.left_comparison( to.smival.value.string.len,to)<0) || + ( lhs.left_comparison( to.smival.value.string.len,to)==0)) + return true; + else + return false; +} + +//===============[ greater than > operator overloaded ]=============== +bool operator>( const OctetStr &lhs,const char *rhs) +{ + OctetStr to( rhs); + if ( lhs.left_comparison( to.smival.value.string.len,to)>0) + return true; + else + return false; +} + +//===============[ greater than >= operator overloaded ]============== +bool operator>=( const OctetStr &lhs,const char *rhs) +{ + OctetStr to( rhs); + if (( lhs.left_comparison( to.smival.value.string.len,to)>0) || + ( lhs.left_comparison( to.smival.value.string.len,to)==0)) + return true; + else + return false; +} + +//===============[ append operator, appends a string ]================ +OctetStr& OctetStr::operator+=( const char *a) +{ + SmiBYTE *tmp; // temp pointer + size_t slen,nlen; + + // get len of string + if ( !a || ((slen = ACE_OS::strlen( a)) == 0)) + return *this; + + // total len of octet + nlen = slen + (size_t) smival.value.string.len; + ACE_NEW_RETURN(tmp, SmiBYTE [ nlen], *this); + ACE_OS::memcpy ( tmp, smival.value.string.ptr, + (size_t) smival.value.string.len); + ACE_OS::memcpy( tmp + smival.value.string.len, a, (size_t) slen); + // delete the original + if ( smival.value.string.ptr ) + reset_octet_smi(smival); + smival.value.string.ptr = tmp; + smival.value.string.len = nlen; + return *this; +} + +//================[ append one OctetStr to another ]================== +OctetStr& OctetStr::operator+=( const OctetStr& octetstr) +{ + SmiBYTE *tmp; // temp pointer + size_t slen,nlen; + + if (!octetstr.validity || + !(slen = (size_t)octetstr.length())) + return *this; + + // total len of octet + nlen = slen + (size_t) smival.value.string.len; + // get mem needed + ACE_NEW_RETURN(tmp, SmiBYTE[ nlen], *this); + ACE_OS::memcpy ( tmp, smival.value.string.ptr, + (size_t) smival.value.string.len); + ACE_OS::memcpy( tmp + smival.value.string.len, octetstr.data(), + (size_t) slen); + if ( smival.value.string.ptr ) + reset_octet_smi(smival); + smival.value.string.ptr = tmp; + smival.value.string.len = nlen; + return *this; +} + +//================[ appends an int ]================================== +OctetStr& OctetStr::operator+=( const char c) +{ + SmiBYTE *tmp; + // get the memory needed plus one extra byte + ACE_NEW_RETURN(tmp, SmiBYTE[ smival.value.string.len + 1], *this); + ACE_OS::memcpy ( tmp, smival.value.string.ptr, + (size_t) smival.value.string.len); // len of original + tmp[ smival.value.string.len ] = c; // assign in byte + if ( smival.value.string.ptr ) // delete the original + reset_octet_smi(smival); + + smival.value.string.ptr = tmp; // point to one + smival.value.string.len++; // up the len + return *this; +} + + +//================[ compare n elements of an Octet ]================== +int OctetStr::left_comparison( const long n, const OctetStr &o) const +{ + long z, w; + + // both are empty, they are equal + if (( smival.value.string.len == 0) && + ( o.smival.value.string.len == 0)) + return 0; // equal + + // self is empty and param has something + if (( smival.value.string.len == 0) && + ( o.smival.value.string.len >0) && + (n>0)) + return -1; + + // self has something and param has nothing + if (( smival.value.string.len > 0) && + ( o.smival.value.string.len ==0) && + (n>0)) + return 1; + + // special case + if (( smival.value.string.len == 0) && + ( o.smival.value.string.len > 0) && + ( n == 0)) + return 0; + + // pick the Min of n, this and the param len + // this is the maximum # to iterate a search + w = smival.value.string.len < o.smival.value.string.len + ? smival.value.string.len : o.smival.value.string.len; + if (n<w) w=n; + + z = 0; + while( z < w) { + if ( smival.value.string.ptr[z] < o.smival.value.string.ptr[z]) + return -1; // less than + if ( smival.value.string.ptr[z] > o.smival.value.string.ptr[z]) + return 1; // greater than + z++; + } + + if (( z == 0) && + ( smival.value.string.len == 0) && + ( o.smival.value.string.len > 0)) + return -1; + + if (( z == 0) && + ( o.smival.value.string.len == 0) && + ( smival.value.string.len > 0)) + return 1; + + return 0; +} + +//================[ return the length of the oid ]======================= +size_t OctetStr::length() const +{ + return (size_t) smival.value.string.len; +} + +//================[ operator[]: access as if array ]================== +SmiBYTE& OctetStr::operator[]( int position) +{ + return smival.value.string.ptr[position]; +} + +//===============[ reuturns pointer to internal data ]=============== +SmiBYTE * OctetStr::data() const +{ + return smival.value.string.ptr; +} + +//================[ returns validity ]================================ +int OctetStr::valid() const +{ + return validity; +} + +//================[ clone() ]========================================= +SnmpSyntax * OctetStr::clone() const +{ + OctetStr *tmp = new OctetStr(*this); + return ( SnmpSyntax *) tmp; +} + +//================[ ASCII format return ]============================= +const char * OctetStr::to_string() +{ + for ( unsigned long i=0; i < smival.value.string.len; i++) { + if (( smival.value.string.ptr[i] != '\r')&& + ( smival.value.string.ptr[i] != '\n')&& + (ACE_OS::ace_isprint((int) (smival.value.string.ptr[i]))==0)) + return(to_string_hex()); + } + + if ( output_buffer != 0) + delete [] output_buffer; + + ACE_NEW_RETURN(output_buffer, char[smival.value.string.len + 1], ""); + if (smival.value.string.len) + ACE_OS::memcpy(output_buffer, smival.value.string.ptr, + (int) smival.value.string.len); + output_buffer[smival.value.string.len] = '\0'; + return output_buffer; +} + + +//================[ general Value = operator ]======================== +SnmpSyntax& OctetStr::operator=( SnmpSyntax &val) +{ + // protect against assignment from self + if ( this == &val ) + return *this; + + // blow away the old value + validity=0; + if (smival.value.string.ptr) { + reset_octet_smi(smival); + } + smival.value.string.len = 0; + if (val.valid()){ + switch (val.get_syntax()) { + case sNMP_SYNTAX_OCTETS: + case sNMP_SYNTAX_IPADDR: + set_data( ((OctetStr &)val).smival.value.string.ptr, + ((OctetStr &)val).smival.value.string.len); + break; + } + } + return *this; +} + +//================[ format the output into hex ]======================== +const char *OctetStr::to_string_hex() +{ + int cnt; + char char_buf[80]; // holds ASCII representation of data + char *buf_ptr; // pointer into ASCII listing + char *line_ptr; // pointer into Hex listing + int storageNeeded; // how much space do we need ? + int local_len = (int) smival.value.string.len; + SmiBYTE *bytes = smival.value.string.ptr; + + + storageNeeded = (int) ((smival.value.string.len/16)+1) * 72 + 1; + + if ( output_buffer != 0) + delete [] output_buffer; + + ACE_NEW_RETURN(output_buffer, char[storageNeeded], ""); + + line_ptr = output_buffer; + + /*----------------------------------------*/ + /* processing loop for entire data buffer */ + /*----------------------------------------*/ + while (local_len > 0) { + cnt = 16; /* print 16 bytes per line */ + buf_ptr = char_buf; + sprintf(line_ptr, " "); + line_ptr += 2; /* indent */ + + /*-----------------------*/ + /* process a single line */ + /*-----------------------*/ + while (cnt-- > 0 && local_len-- > 0) { + sprintf(line_ptr, "%2.2X ", *bytes); + + line_ptr +=3; /* the display of a byte always 3 chars long */ + if (isprint(*bytes)) + sprintf(buf_ptr, "%c", *bytes); + else + sprintf(buf_ptr, "."); + bytes++; + buf_ptr++; + } + cnt++; + + /*----------------------------------------------------------*/ + /* this is to make sure that the ASCII displays line up for */ + /* incomplete lines of hex */ + /*----------------------------------------------------------*/ + while (cnt-- > 0) { + sprintf(line_ptr," "); + line_ptr += 3; + } + + /*------------------------------------------*/ + /* append the ASCII display to the Hex line */ + /*------------------------------------------*/ + +// TODO: verify ACE_OS:: on NT works like this or not + +#if defined(_WIN32) + const char *fmt = " %s\r\n"; +#else + const char *fmt = " %s\n"; +#endif // _WIN32 + + ACE_OS::sprintf(line_ptr, fmt, char_buf); + line_ptr += 3 + ACE_OS::strlen(char_buf); + } + + return output_buffer; +} diff --git a/ACE/ASNMP/asnmp/octet.h b/ACE/ASNMP/asnmp/octet.h new file mode 100644 index 00000000000..5e8c8d63d98 --- /dev/null +++ b/ACE/ASNMP/asnmp/octet.h @@ -0,0 +1,152 @@ + + +#ifndef OCTET_CLS_ +#define OCTET_CLS_ +//============================================================================= +/** + * @file octet.h + * + * $Id$ + * + * This class is fully contained and does not rely on or any other + * SNMP libraries. This class is portable across any platform + * which supports C++. + * + * + * @author Peter E Mellquist / design/original code Michael R. MacFaden / modified for ACE + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//------------------------------------------------------------------------ +#include "asnmp/smival.h" + +/** + * @class OctetStr + * + * @brief Implement RFC1155 Octet SMI data object + */ +class ASNMP_Export OctetStr : public SnmpSyntax + +{ +public: + /// construct octet from byte buffer, assume c style string if size == -1 + OctetStr( const char *string = "", long size = -1); + + /// constructor using another octet object + OctetStr ( const OctetStr &octet); + + /// destructor + ~OctetStr(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// set octet from byte buffer, assume c style string if size == -1 + void set_data( const SmiBYTE* string, long int size = -1); + + /// assignment to a string operator overloaded + OctetStr& operator=( const char *string); + + /// assignment to another oid object overloaded + OctetStr& operator=( const OctetStr &octet); + + /// equivlence operator overloaded + friend ASNMP_Export bool operator==( const OctetStr &lhs, const OctetStr &rhs); + + /// not equivlence operator overloaded + friend ASNMP_Export bool operator!=( const OctetStr &lhs, const OctetStr &rhs); + + /// less than < overloaded + friend ASNMP_Export bool operator<( const OctetStr &lhs, const OctetStr &rhs); + + /// less than <= overloaded + friend ASNMP_Export bool operator<=( const OctetStr &lhs,const OctetStr &rhs); + + /// greater than > overloaded + friend ASNMP_Export bool operator>( const OctetStr &lhs, const OctetStr &rhs); + + /// greater than >= overloaded + friend ASNMP_Export bool operator>=( const OctetStr &lhs, const OctetStr &rhs); + + /// equivlence operator overloaded + friend ASNMP_Export bool operator==( const OctetStr &lhs,const char *rhs); + + /// not equivlence operator overloaded + friend ASNMP_Export bool operator!=( const OctetStr &lhs,const char *rhs); + + /// less than < operator overloaded + friend ASNMP_Export bool operator<( const OctetStr &lhs,const char *rhs); + + /// less than <= operator overloaded + friend ASNMP_Export bool operator<=( const OctetStr &lhs,char *rhs); + + /// greater than > operator overloaded + friend ASNMP_Export bool operator>( const OctetStr &lhs,const char *rhs); + + /// greater than >= operator overloaded + friend ASNMP_Export bool operator>=( const OctetStr &lhs,const char *rhs); + + /// append operator, appends a string + OctetStr& operator+=( const char *a); + + /// appends an int + OctetStr& operator+=( const char c); + + /// append one octetStr to another + OctetStr& operator+=( const OctetStr& octetstr); + + /// for non const [], allows reading and writing + SmiBYTE& operator[]( int position); + + /** + * compare the n leftmost bytes (left-to-right) + * returns 0, equal + * returns -1, < + * returns 1 , > + */ + int left_comparison( const long n, const OctetStr &o) const; + + /// return the len of the oid + size_t length() const ; + + /// returns validity + int valid() const; + + /// returns pointer to internal data + SmiBYTE *data() const; + + /// get a printable ASCII value + const char *to_string(); + + /// get an ASCII formattted hex dump of the contents + const char *to_string_hex(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + +protected: + //----[ instance variables ] + char *output_buffer; // formatted Octet value + int validity; // validity boolean +}; + +#endif // OCTET_CLS_ diff --git a/ACE/ASNMP/asnmp/oid.cpp b/ACE/ASNMP/asnmp/oid.cpp new file mode 100644 index 00000000000..b5999a1fcbd --- /dev/null +++ b/ACE/ASNMP/asnmp/oid.cpp @@ -0,0 +1,803 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// oid.cpp +// +// = DESCRIPTION +// This module contains the implementation of the oid class. This +// includes all protected and public member functions. The oid class +// may be compiled stand alone without the use of any other library. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS" without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//---------[ external C libaries used ]-------------------------------- + +#include "asnmp/oid.h" // include def for oid class +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_Memory.h" +#include "ace/os_include/os_ctype.h" + +ACE_RCSID(asnmp, oid, "$Id$") + +enum Defs {SNMPBUFFSIZE=300, + SNMPCHARSIZE=15}; // max oid value (4294967295UL) + +#define NO_MEM_STR "ERROR: Oid::to_string: memory allocation failure" + +//=============[Oid::get_syntax(void)]==================================== +SmiUINT32 Oid::get_syntax() +{ + return sNMP_SYNTAX_OID; +} + + +//=============[Oid::Oid( const char *dotted_string ]===================== +// constructor using a dotted string +// +// do a string to oid using the string passed in +Oid::Oid( const char * dotted_oid_string, size_t size) +{ + // can't init enum SmiValue so just memset it clean + set_null(); + + size_t z; + if ((z = ACE_OS::strlen(dotted_oid_string)) == 0) { + set_invalid(); + return; + } + + if (size == (unsigned int)-1) + size = z; + if (size > z) + size = z; + + char *ptr = (char *)dotted_oid_string;; + if (size < z) { + // create new buffer if needed + ACE_NEW(ptr, char [size]); + + // sz should be in StrToOid? + ACE_OS::memcpy( (void *)ptr, dotted_oid_string, size); + } + + size_t byte_counter; + if (StrToOid( (char *) ptr, &smival.value.oid, byte_counter) < 0) + set_invalid(); + if (ptr != dotted_oid_string) + delete [] ptr; +} + + +//=============[Oid::Oid( const Oid &oid) ]================================ +// constructor using another oid object +// +// do an oid copy using the oid object passed in +Oid::Oid ( const Oid &oid) + : SnmpSyntax (oid) +{ + set_null(); + + // allocate some memory for the oid + // in this case the size to allocate is the same + // size as the source oid + if (oid.smival.value.oid.len) { + ACE_NEW(smival.value.oid.ptr, SmiUINT32[ oid.smival.value.oid.len]); + size_t byte_counter; + OidCopy( (SmiLPOID) &(oid.smival.value.oid),(SmiLPOID) + &smival.value.oid, byte_counter); + } +} + + +//=============[Oid::Oid( const unsigned long *raw_oid, int oid_len) ]==== +// constructor using raw numeric form +// +// copy the integer values into the private member +Oid::Oid(const unsigned long *raw_oid, size_t oid_len) +{ + set_null(); + + smival.syntax = sNMP_SYNTAX_OID; + set_invalid(); + + if (raw_oid && oid_len > 0) { + ACE_NEW(smival.value.oid.ptr, SmiUINT32[ oid_len]); + smival.value.oid.len = oid_len; + for (size_t i=0; i < oid_len; i++) + smival.value.oid.ptr[i] = raw_oid[i]; + } +} + +//=============[Oid::~Oid]============================================== +// destructor +// +// free up the descriptor space +Oid::~Oid() +{ + // free up the octet deep memory + if ( smival.value.oid.ptr ) { + set_invalid(); + } + + // free up the output string + if ( iv_str != 0) + delete [] iv_str; +} + + +//=============[Oid::operator = const char * dotted_string ]============== +// assignment to a string operator overloaded +// +// free the existing oid +// create the new oid from the string +// return this object +void Oid::set_data( const char *dotted_oid_string) +{ + // delete the old value + if ( smival.value.oid.ptr ) { + set_invalid(); + } + + // assign the new value + size_t byte_counter; + if (StrToOid( (char *) dotted_oid_string, &smival.value.oid, byte_counter) <0) + set_invalid(); +} + + +//=============[Oid:: operator = const Oid &oid ]========================== +// assignment to another oid object overloaded +// +// free the existing oid +// create a new one from the object passed in +// TODO: measure perf vs memory of no realloc in case where len >= oid.len +Oid& Oid::operator=( const Oid &oid) +{ + // protect against assignment from self + if ( this == &oid) + return *this; + + set_invalid(); + + // check for zero len on source + if ( oid.smival.value.oid.len == 0) + return *this; + + const SmiLPOID srcOid = (SmiLPOID) &(oid.smival.value.oid); + init_value(srcOid, oid.smival.value.oid.len); + return *this; +} + +// assign this object the oid, set to invalid if copy fails +void Oid::init_value(const SmiLPOID srcOid, size_t len) +{ + // allocate some memory for the oid + ACE_NEW(smival.value.oid.ptr, SmiUINT32[ len]); + size_t byte_counter; + OidCopy( srcOid, (SmiLPOID) &smival.value.oid, byte_counter); +} + +void Oid::init_value(const unsigned long *raw_oid, size_t oid_len) +{ + if (smival.value.oid.ptr) + delete [] smival.value.oid.ptr; + + ACE_NEW(smival.value.oid.ptr, SmiUINT32[ oid_len]); + ACE_OS::memcpy((SmiLPBYTE) smival.value.oid.ptr, + (SmiLPBYTE) raw_oid, + (size_t) (oid_len * sizeof(SmiUINT32))); + smival.value.oid.len = oid_len; +} + +//==============[Oid:: operator += const char *a ]========================= +// append operator, appends a string +// +// allocate some space for a max oid string +// extract current string into space +// concat new string +// free up existing oid +// make a new oid from string +// delete allocated space +Oid& Oid::operator+=( const char *a) +{ + unsigned long n; + + if (!a) + return *this; + + if ( *a=='.') + a++; + size_t sz = ACE_OS::strlen(a); + + if (valid()) { + n = (smival.value.oid.len *SNMPCHARSIZE) + smival.value.oid.len + 1 + sz; + char *ptr; + ACE_NEW_RETURN(ptr, char[ n], *this); + size_t byte_counter; + if (OidToStr(&smival.value.oid, n,ptr, byte_counter) > 0) { + delete [] ptr; + set_invalid(); + return *this; + } + + if (ACE_OS::strlen(ptr)) + ACE_OS::strcat(ptr,"."); + ACE_OS::strcat(ptr,a); + if ( smival.value.oid.len !=0) { + set_invalid(); + } + + if (StrToOid( (char *) ptr, &smival.value.oid, byte_counter) < 0) { + set_invalid(); + } + delete [] ptr; + } + else { + size_t byte_counter; + if (StrToOid( (char *) a, &smival.value.oid, byte_counter) < 0) { + set_invalid(); + } + } + + return *this; +} + +//=============[ bool operator == oid,oid ]================================= +// equivlence operator overloaded +bool operator==( const Oid &lhs, const Oid &rhs) +{ + // ensure same len, then use left_comparison + if (rhs.length() != lhs.length()) + return false; + if( lhs.left_comparison( rhs.length(), rhs) == 0) + return true; + else + return false; +} + +//==============[ bool operator!=( Oid &x,Oid &y) ]======================= +//not equivlence operator overloaded +bool operator!=( const Oid &lhs,const Oid &rhs) +{ + return (!(lhs == rhs)); +} + +//==============[ bool operator<( Oid &x,Oid &y) ]======================== +// less than < overloaded +bool operator<( const Oid &lhs,const Oid &rhs) +{ + int result; + + // call left_comparison with the current + // Oidx, Oidy and len of Oidx + if ((result = lhs.left_comparison( rhs.length(), rhs)) < 0) + return true; + else if (result > 0) + return false; + + else{ + // if here, equivalent substrings, call the shorter one < + if (lhs.length() < rhs.length()) + return true; + else + return false; + } +} + +//==============[ bool operator<=( Oid &x,Oid &y) ]======================= +// less than <= overloaded +bool operator<=( const Oid &x,const Oid &y) +{ + if ( (x < y) || (x == y) ) + return true; + else + return false; +} + +//==============[ bool operator>( Oid &x,Oid &y) ]======================== +// greater than > overloaded +bool operator>( const Oid &x,const Oid &y) +{ + // just invert existing <= + if (!(x<=y)) + return true; + else + return false; +} + +//==============[ bool operator>=( Oid &x,Oid &y) ]======================= +// greater than >= overloaded +bool operator>=( const Oid &x,const Oid &y) +{ + // just invert existing < + if (!(x<y)) + return true; + else + return false; +} + +//===============[Oid::oidval ]============================================= +// return the WinSnmp oid part +SmiLPOID Oid::oidval() +{ + return (SmiLPOID) &smival.value.oid; +} + +//===============[Oid::set_data ]==---===================================== +// copy data from raw form... +void Oid::set_data( const unsigned long *raw_oid, const size_t oid_len) +{ + if (smival.value.oid.len < oid_len) { + if ( smival.value.oid.ptr) { + set_invalid(); + } + } + init_value(raw_oid, oid_len); +} + + +//===============[Oid::len ]================================================ +// return the len of the oid +size_t Oid::length() const +{ + return smival.value.oid.len; +} + +//===============[Oid::trim( unsigned int) ]============================ +// trim off the n leftmost values of an oid +// Note!, does not adjust actual space for +// speed +void Oid::trim( const size_t n) +{ + // verify that n is legal + if ((n<=smival.value.oid.len)&&(n>0)) { + smival.value.oid.len -= n; + + if (smival.value.oid.len == 0) { + set_invalid(); + } + } +} + +//===============[Oid::set_invalid() ]==================== +// make this object invalid by resetting all values +void Oid::set_invalid() { + delete [] smival.value.oid.ptr; + smival.value.oid.ptr = 0; + smival.value.oid.len = 0; + delete [] iv_str; + iv_str = 0; +} + +//===============[Oid::set_null() ]==================== +void Oid::set_null() { + smival.syntax = sNMP_SYNTAX_OID; + smival.value.oid.ptr = 0; + smival.value.oid.len = 0; + iv_str = 0; +} + +//===============[Oid::operator += const unsigned int) ]==================== +// append operator, appends an int +// +// allocate some space for a max oid string +// extract current string into space +// concat new string +// free up existing oid +// make a new oid from string +// delete allocated space +Oid& Oid::operator+=( const unsigned long i) +{ + unsigned long n = (smival.value.oid.len * SNMPCHARSIZE) + + ( smival.value.oid.len -1) + 1 + 4; + char buffer[SNMPBUFFSIZE]; + + // two cases: null oid, existing oid + if (valid()) { + // allocate some temporary space + char *ptr; + ACE_NEW_RETURN(ptr, char[ n], *this); + size_t byte_counter; + if (OidToStr(&smival.value.oid, n, ptr, byte_counter) < 0) { + set_invalid(); + delete [] ptr; + return *this; + } + + if (ACE_OS::strlen(ptr)) + ACE_OS::strcat(ptr,"."); + + if (ACE_OS::sprintf( buffer,"%lu",i) != -1) { + ACE_OS::strcat(ptr, buffer); + if ( smival.value.oid.ptr ) { + set_invalid(); + } + if (StrToOid( (char *) ptr, &smival.value.oid, byte_counter) < 0) { + set_invalid(); + } + delete [] ptr; + } + } + else { + init_value((const unsigned long *)&i, (size_t)1); + } + + return *this; +} + +//===============[Oid::operator += const Oid) ]======================== +// append operator, appends an Oid +// +// allocate some space for a max oid string +// extract current string into space +// concat new string +// free up existing oid +// make a new oid from string +// delete allocated space +Oid& Oid::operator+=( const Oid &o) +{ + SmiLPUINT32 new_oid; + + if (o.smival.value.oid.len == 0) + return *this; + + ACE_NEW_RETURN(new_oid, + SmiUINT32[ smival.value.oid.len + o.smival.value.oid.len], *this); + if (smival.value.oid.ptr) { + ACE_OS::memcpy((SmiLPBYTE) new_oid, + (SmiLPBYTE) smival.value.oid.ptr, + (size_t) (smival.value.oid.len*sizeof(SmiUINT32))); + + delete [] smival.value.oid.ptr; + } + + // out with the old, in with the new... + smival.value.oid.ptr = new_oid; + + ACE_OS::memcpy((SmiLPBYTE) &new_oid[smival.value.oid.len], + (SmiLPBYTE) o.smival.value.oid.ptr, + (size_t) (o.smival.value.oid.len*sizeof(SmiUINT32))); + + smival.value.oid.len += o.smival.value.oid.len; + return *this; +} + +// return string portion of the oid +// +const char * Oid::to_string() +{ + unsigned long n; + if (!valid()) + return ""; // be consistent with other classes + + // the worst case char len of an oid can be.. + // oid.len*3 + dots in between if each oid is XXXX + // so.. size = (len*4) + (len-1) + 1 , extra for a null + + n = (smival.value.oid.len *SNMPCHARSIZE) + ( smival.value.oid.len -1) + 1 ; + if (n == 0) + n = 1; // need at least 1 byte for a null string + + // adjust the len of output array in case size was adjusted + if ( iv_str != 0) + delete [] iv_str; + // allocate some space for the output string + ACE_NEW_RETURN(iv_str, char[ n], ""); + + // convert to an output string + size_t how_many; + if ( valid() && iv_str != 0) + if (OidToStr(&smival.value.oid,n,iv_str, how_many) < 0) + return "ERROR: Oid::OidToStr failed"; + return iv_str; +} + +//==============[Oid::suboid( unsigned int start, n) ]============= +int Oid::suboid(Oid& new_oid, size_t start, size_t how_many) +{ + if (how_many == 0) + return 0; + else + if (how_many == (size_t)-1) + how_many = length(); + else + if (how_many > length()) + how_many = length(); + + // reset new_oid + new_oid.set_invalid(); + + size_t new_size = how_many - start; + if (new_size == 0) + new_size++; + new_oid.smival.value.oid.len = new_size; + ACE_NEW_RETURN(new_oid.smival.value.oid.ptr, + SmiUINT32 [ new_oid.smival.value.oid.len], -1); + // copy source to destination + ACE_OS::memcpy( (SmiLPBYTE) new_oid.smival.value.oid.ptr, + (SmiLPBYTE) (smival.value.oid.ptr + start), + new_size * sizeof(SmiLPBYTE)); + return 0; +} + + +//=============[Oid::StrToOid( char *string, SmiLPOID dst) ]============== +// convert a string to an oid +int Oid::StrToOid( const char *string, SmiLPOID dstOid, size_t& how_many) +{ + size_t index = 0; + size_t number = 0; + + // make a temp buffer to copy the data into first + SmiLPUINT32 temp; + unsigned long nz; + + if (string && *string) { + nz = ACE_OS::strlen( string); + } + else { + dstOid->len = 0; + dstOid->ptr = 0; + return -1; + } + + ACE_NEW_RETURN(temp, SmiUINT32[ nz], -1); + while (*string!=0 && index<nz) { + // init the number for each token + number = 0; + // skip over the dot + if (*string=='.') + string++; + + // grab a digit token and convert it to a long int + while (isdigit(*string)) + number=number*10 + *(string++)-'0'; + + // check for invalid chars + if (*string!=0 && *string!='.') { + // Error: Invalid character in string + delete [] temp; + return -1; + } + + // stuff the value into the array + temp[index] = number; + index++; // bump the counter + } + + + // get some space for the real oid + ACE_NEW_RETURN(dstOid->ptr, SmiUINT32[ index], -1); + // TODO: make tmp autoptr type delete [] temp to prevent leak + + // copy in the temp data + ACE_OS::memcpy((SmiLPBYTE) dstOid->ptr, (SmiLPBYTE) temp, + (size_t) (index*sizeof(SmiUINT32))); + + // set the len of the oid + dstOid->len = index; + + // free up temp data + delete [] temp; + + how_many = index; + return 0; +} + + +//===============[Oid::OidCopy( source, destination) ]==================== +// Copy an oid, return bytes copied +int Oid::OidCopy( SmiLPOID srcOid, SmiLPOID dstOid, size_t& how_many_bytes) +{ + // check source len ! zero + if (srcOid->len == 0) + return -1; + + // copy source to destination + ACE_OS::memcpy((SmiLPBYTE) dstOid->ptr, + (SmiLPBYTE) srcOid->ptr, + (size_t) (srcOid->len * sizeof(SmiUINT32))); + + //set the new len + dstOid->len = srcOid->len; + how_many_bytes = srcOid->len; + + return 0; +} + + +//===============[Oid::left_comparison( n, Oid) ]================================= +// compare the n leftmost values of two oids ( left-to_right ) +// +// self == Oid then return 0, they are equal +// self < Oid then return -1, < +// self > Oid then return 1, > +int Oid::left_comparison( const unsigned long n, const Oid &o) const +{ + unsigned long z; + unsigned long len = n; + int reduced_len = 0; + + // 1st case they both are null + if (( len==0)&&( this->smival.value.oid.len==0)) + return 0; // equal + + // verify that n is valid, must be >= 0 + if ( len <=0) + return 1; // ! equal + + // only compare for the minimal length + if (len > this->smival.value.oid.len) { + len = this->smival.value.oid.len; + reduced_len = 1; + } + if (len > o.smival.value.oid.len) { + len = o.smival.value.oid.len; + reduced_len = 1; + } + + z = 0; + while(z < len) { + if ( this->smival.value.oid.ptr[z] < o.smival.value.oid.ptr[z]) + return -1; // less than + if ( this->smival.value.oid.ptr[z] > o.smival.value.oid.ptr[z]) + return 1; // greater than + z++; + } + + // if we truncated the len then these may not be equal + if (reduced_len) { + if (this->smival.value.oid.len < o.smival.value.oid.len) + return -1; + if (this->smival.value.oid.len > o.smival.value.oid.len) + return 1; + } + return 0; // equal + +} + + +//===============[Oid::left_comparison( n, Oid) ]================================= +// compare the n rightmost bytes (right-to-left) +// returns 0, equal +// returns -1, < +// returns 1 , > +int Oid::right_comparison( const unsigned long n, const Oid &o) const +{ + // oid to compare must have at least the same number + // of sub-ids to comparison else the argument Oid is + // less than THIS + if ( o.length() < n) + return -1; + + // also can't compare argument oid for sub-ids which + // THIS does not have + if ( this->length() < n) + return -1; + + int start = (int) this->length(); + int end = (int) start - (int) n; + for ( int z=start;z< end;z--) + { + if ( o.smival.value.oid.ptr[z] < this->smival.value.oid.ptr[z]) + return -1; + if ( o.smival.value.oid.ptr[z] > this->smival.value.oid.ptr[z]) + return 1; + } + + return 0; // they are equal + +} + + +//================[ Oid::valid() ]======================================== +// is the Oid object valid +// returns validity +int Oid::valid() const +{ + return ( smival.value.oid.ptr ? 1 : 0 ); +} + +//================[Oid::OidToStr ]========================================= +// convert an oid to a string +int Oid::OidToStr( SmiLPOID srcOid, unsigned long size, + char *string, size_t& how_many_bytes) +{ + unsigned long index = 0; + unsigned totLen = 0; + char szNumber[SNMPBUFFSIZE]; + + // init the string + string[totLen] = 0; + + // verify there is something to copy + if (srcOid->len == 0) + return -1; + + // loop through and build up a string + for (index=0; index < srcOid->len; index++) { + + // convert data element to a string + if (ACE_OS::sprintf( szNumber,"%lu", srcOid->ptr[index]) == -1) + return -1; + + // verify len is not over + if (totLen + ACE_OS::strlen(szNumber) + 1 >= size) + return -2; + + // if not at end, pad with a dot + if (totLen!=0) + string[totLen++] = '.'; + + // copy the string token into the main string + ACE_OS::strcpy(string + totLen, szNumber); + + // adjust the total len + totLen += ACE_OS::strlen(szNumber); + } + + how_many_bytes = totLen + 1; + return 0; +} + + +//================[ general Value = operator ]======================== +SnmpSyntax& Oid::operator=( SnmpSyntax &val) +{ + // protect against assignment from self + if ( this == &val ) + return *this; + + // blow away old value + smival.value.oid.len = 0; + if (smival.value.oid.ptr) { + set_invalid(); + } + + // assign new value + if (val.valid()) { + switch (val.get_syntax()) { + case sNMP_SYNTAX_OID: + set_data( ((Oid &)val).smival.value.oid.ptr, + (unsigned int)((Oid &)val).smival.value.oid.len); + break; + } + } + return *this; +} + +//================[ [] operator ]===================================== +unsigned long& Oid::operator[](size_t position) +{ + return smival.value.oid.ptr[position]; +} + +//================[ clone ]=========================================== +SnmpSyntax *Oid::clone() const +{ + return (SnmpSyntax *) new Oid(*this); +} diff --git a/ACE/ASNMP/asnmp/oid.h b/ACE/ASNMP/asnmp/oid.h new file mode 100644 index 00000000000..77118b518f0 --- /dev/null +++ b/ACE/ASNMP/asnmp/oid.h @@ -0,0 +1,175 @@ + + +#ifndef OID_CLS_ +#define OID_CLS_ +//============================================================================= +/** + * @file oid.h + * + * $Id$ + * + * This class is fully contained and does not rely on or any other + * SNMP libraries. This class is portable across any platform + * which supports C++. Ported to ACE by Mike MacFaden mrm@cisco.com + * and modified for MT. Some API cleanup: collapse constructors, + * add suboid() method remove unnecessary overload, and update a few + * names and types to improve clarity. + * + * + * @author Peter E Mellquist + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//----------[ extern C libraries Needed ]--------------------------------- +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/smival.h" // derived class for all values + +/** + * @class Oid + * + * @brief Implement RFC 1155 Object Identifier (OID) datatype + */ +class ASNMP_Export Oid : public SnmpSyntax +{ +public: + /// constructor using a dotted string + Oid( const char * dotted_oid_string = "", size_t size = unsigned(-1) ); + + /// constructor using another oid object + Oid ( const Oid &oid); + + /// constructor from raw form + Oid(const unsigned long *raw_oid, size_t oid_len); + + /// destructor + ~Oid(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// assignment to another oid object overloaded + Oid& operator=( const Oid &oid); + + /// equal operator overloaded + friend ASNMP_Export bool operator==( const Oid &lhs,const Oid &rhs); + + /// not equal operator overloaded + friend ASNMP_Export bool operator!=( const Oid &lhs,const Oid &rhs); + + /// less than < overloaded + friend ASNMP_Export bool operator<( const Oid &lhs,const Oid &rhs); + + /// less than <= overloaded + friend ASNMP_Export bool operator<=( const Oid &lhs,const Oid &rhs); + + /// greater than > overloaded + friend ASNMP_Export bool operator>( const Oid &lhs,const Oid &rhs); + + /// greater than >= overloaded + friend ASNMP_Export bool operator>=( const Oid &lhs,const Oid &rhs); + + /// append operator, appends a string + Oid& operator+=( const char *a); + + /// appends an int + Oid& operator+=( const unsigned long i); + + /// appends an Oid + Oid& operator+=( const Oid &o); + + /// allows element access + unsigned long & operator[]( size_t position); + + /// return the WinSnmp oid part + SmiLPOID oidval(); + + /// reset the data from raw 1 byte format + void set_data( const char *dotted_oid_string); + + /// reset the data from raw 4byte integer format + void set_data( const unsigned long *raw_oid, const size_t oid_len); + + /// return the len of the oid + size_t length() const; + + /// trim off the n rightmost values of an oid + void trim( const size_t how_many = 1); + + /// the equivalent of a substr(new_str, 0, 1) + int suboid(Oid& oid, size_t start = 0, size_t how_many = size_t (-1)); + + /** + * compare the n leftmost bytes (left-to-right) + * returns 0, equal + * returns -1, < + * returns 1 , > + */ + int left_comparison( const unsigned long n, const Oid &o) const; + + + /** + * compare the n rightmost bytes (right-to-left) + * returns 0, equal + * returns -1, < + * returns 1 , > + */ + int right_comparison( const unsigned long n, const Oid &o) const; + + /// is the Oid object valid + int valid() const; + + /// return dotted string value from the right + /// where the user specifies how many positions to print + const char *to_string(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=( SnmpSyntax &val); + +protected: + /// used for returning oid string + char *iv_str; + + /// convert a string to an smi oid + int StrToOid( const char *string, SmiLPOID dstOid, size_t& how_many_bytes); + + /// clone an smi oid + int OidCopy( SmiLPOID srcOid, SmiLPOID dstOid, size_t& how_many_bytes); + + /// convert an smi oid to its string representation + int OidToStr(SmiLPOID srcOid, SmiUINT32 size, char *string, size_t& how_many_bytes); + + private: + /// release memory, re-init data members + void set_invalid(); + + /// initialize object data members + void set_null(); + void init_value( const SmiLPOID srcOid, size_t len); + void init_value(const unsigned long *raw_oid, size_t oid_len); +}; + +#endif //OID_CLS_ diff --git a/ACE/ASNMP/asnmp/oid_def.h b/ACE/ASNMP/asnmp/oid_def.h new file mode 100644 index 00000000000..31ccbfa3e4a --- /dev/null +++ b/ACE/ASNMP/asnmp/oid_def.h @@ -0,0 +1,84 @@ +/* -*-C++-*- */ +#ifndef OID_DEF +#define OID_DEF +//============================================================================= +/** + * @file oid_def.h + * + * $Id$ + * + * Well known Oids defined in RFC 1215 + * + * + * @author Peter E Mellquist + */ +//============================================================================= + +/*=================================================================== + + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +// SMI trap oid def +class snmpTrapsOid: public Oid { + public: + snmpTrapsOid (void):Oid("1.3.6.1.6.3.1.1.5"){}; +}; + +// SMI Enterprose Oid +class snmpTrapEnterpriseOid: public Oid { + public: + snmpTrapEnterpriseOid(void):Oid("1.3.6.1.6.3.1.1.4.3.0"){}; +}; + +// SMI Cold Start Oid +class coldStartOid: public snmpTrapsOid { + public: + coldStartOid( void){*this+=".1";}; +}; + +// SMI WarmStart Oid +class warmStartOid: public snmpTrapsOid { + public: + warmStartOid( void){*this+=".2";}; +}; + +// SMI LinkDown Oid +class linkDownOid: public snmpTrapsOid { + public: + linkDownOid( void){*this+=".3";}; +}; + + +// SMI LinkUp Oid +class linkUpOid: public snmpTrapsOid { + public: + linkUpOid( void){*this+=".4";}; +}; + +// SMI Authentication Failure Oid +class authenticationFailureOid: public snmpTrapsOid { + public: + authenticationFailureOid( void){*this+=".5";}; +}; + +// SMI egpneighborloss Oid +class egpNeighborLossOid: public snmpTrapsOid { + public: + egpNeighborLossOid( void){*this+=".6";}; +}; + + +#endif // OID_DEF diff --git a/ACE/ASNMP/asnmp/pdu.cpp b/ACE/ASNMP/asnmp/pdu.cpp new file mode 100644 index 00000000000..cbe67dcbbab --- /dev/null +++ b/ACE/ASNMP/asnmp/pdu.cpp @@ -0,0 +1,499 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// pdu.cpp +// +// = DESCRIPTION +// Pdu class implementation. Encapsulation of an SMI Protocol +// Data Unit (PDU) in C++. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/snmp.h" +#include "asnmp/pdu.h" // include Pdu class definition +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_stdio.h" + +ACE_RCSID(asnmp, pdu, "$Id$") + +//=====================[ constructor no args ]========================= +Pdu::Pdu( void): vb_count_(0), error_status_(0), error_index_(0), +validity_(0), request_id_(0), pdu_type_(0), notify_timestamp_(0), +output_(0) +{ +} + +//=====================[ constructor with vbs_ and count ]============== +Pdu::Pdu( Vb* pvbs, const int pvb_count): vb_count_(0), error_index_(0), +validity_(0), request_id_(0), pdu_type_(0), notify_timestamp_(0), +output_(0) +{ + int z = 0; // looping variable + + // zero is ok + if ( pvb_count == 0) { + validity_ = 1; + return; + } + + // check for over then max + if ( pvb_count > MAX_VBS) { + validity_ = 0; + return; + } + + // loop through and assign internal vbs_ + for (z = 0;z < pvb_count; z++) { + validity_ = 0; + ACE_NEW(vbs_[z], Vb( pvbs[z])); + validity_ = 1; + } + + // assign the vb count + vb_count_ = pvb_count; + + validity_ = 1; +} + +//=====================[ constructor with another Pdu instance ]======== +Pdu::Pdu( const Pdu &pdu): vb_count_(0), +error_index_(0), validity_(0), request_id_(0), pdu_type_(0), +notify_timestamp_(0), output_(0) +{ + *this = pdu; + return; +} + +//=====================[ destructor ]==================================== +Pdu::~Pdu() +{ + delete_all_vbs(); + delete [] output_; +} + + +//=====================[ assignment to another Pdu object overloaded ]=== +Pdu& Pdu::operator=( const Pdu &pdu) +{ + int z; // looping variable + + // Initialize all mv's + error_status_ = pdu.error_status_; + error_index_ = pdu.error_index_; + request_id_ = pdu.request_id_; + pdu_type_ = pdu.pdu_type_; + notify_id_ = pdu.notify_id_; + notify_timestamp_ = pdu.notify_timestamp_; + notify_enterprise_ = pdu.notify_enterprise_; + validity_ = 1; + + // free up old vbs_ + for ( z = 0;z < vb_count_; z++) + delete vbs_[z]; + vb_count_ = 0; + + // check for zero case + if ( pdu.vb_count_ == 0) { + return *this; + } + + // loop through and fill em up + for (z = 0; z < pdu.vb_count_; z++) { + validity_ = 0; + ACE_NEW_RETURN(vbs_[z], Vb ( *(pdu.vbs_[z])), *this); + validity_ = 1; + } + + vb_count_ = pdu.vb_count_; + return *this; +} + +// append operator, appends a string +Pdu& Pdu::operator+=( Vb &vb) +{ + + // do we have room? + if ( vb_count_ + 1 > MAX_VBS) + return *this; + + // add the new one + validity_ = 0; + ACE_NEW_RETURN(vbs_[vb_count_], Vb (vb), *this); + // set up validity_ + validity_ = 1; + + // up the vb count + vb_count_++; + + // return self reference + return *this; + +} + +// return fomatted version of this object +const char * Pdu::to_string() +{ + // determine how big a buffer and allocate it + const int HEADER_STR = 100; + unsigned size = HEADER_STR; // header takes up this much room + int z; + + for ( z = 0; z < vb_count_; z++) + size += ACE_OS::strlen(vbs_[z]->to_string()); + + ACE_NEW_RETURN(output_, char[size], ""); + + // print pdu header info + sprintf(output_, "pdu: valid: %d type:%d, req:%d, cnt: %d, err stat: %d \ + err idx: %d\n", validity_, pdu_type_, (int) request_id_, + vb_count_, error_status_, error_index_ ); + + // now append vb pairs in this object + for ( z = 0; z < vb_count_; z++) { + ACE_OS::strcat(output_, vbs_[z]->to_string()); + ACE_OS::strcat(output_, "\n\t"); + } + + return output_; +} + + +//=====================[ extract Vbs from Pdu ]========================== +// how do you know that the caler has enough memory??? +// should I self allocate this in here and require the +// caller then to free it up at soem later time +int Pdu::get_vblist( Vb* pvbs, const int pvb_count) +{ + if ((!pvbs) || ( pvb_count < 0) || ( pvb_count > vb_count_)) + return 0; + + // loop through all vbs_ and assign to params + int z; + for (z = 0; z < pvb_count; z++) + pvbs[z] = *vbs_[z]; + + return 1; + +} + +//=====================[ deposit Vbs ]=================================== +int Pdu::set_vblist( Vb* pvbs, const int pvb_count) +{ + + // if invalid then don't destroy + if ((!pvbs) || ( pvb_count < 0) || ( pvb_count > MAX_VBS)) + return 0; + + // free up current vbs_ + int z; + for ( z = 0; z < vb_count_; z++) + delete vbs_[z]; + vb_count_ = 0; + + // check for zero case + if ( pvb_count == 0) { + validity_ = 1; + error_status_ = 0; + error_index_ = 0; + request_id_ = 0; + return 0; + } + + + // loop through all vbs_ and reassign them + for ( z = 0; z < pvb_count; z++) { + validity_ = 0; + ACE_NEW_RETURN(vbs_[z], Vb (pvbs[z]), 0); + validity_ = 1; + } + + vb_count_ = pvb_count; + + // clear error status and index since no longer valid + // request id may still apply so don't reassign it + error_status_ = 0; + error_index_ = 0; + validity_ = 1; + + return 1; +} + +//===================[ get a particular vb ]============================= +// here the caller has already instantiated a vb object +// index is zero based +int Pdu::get_vb( Vb &vb, const int index) const +{ + // can't have an index less than 0 + if ( index < 0) + return 0; + + // can't ask for something not there + if ( index > (vb_count_ - 1)) + return 0; + + // asssign it + vb = *vbs_[index]; + + return 1; +} + +//===================[ set a particular vb ]============================= +int Pdu::set_vb( Vb &vb, const int index) +{ + // can't set a vb at index less than 0 + if ( index < 0) + return 0; + + // can't ask for something not there + if ( index > (vb_count_ - 1)) + return 0; + + // delete what is there + delete vbs_[index]; + + // assign it + validity_ = 0; + ACE_NEW_RETURN(vbs_[index], Vb (vb), 0); + validity_ = 1; + + return 1; + +} + +//=====================[ return number of vbs_ ]========================== +int Pdu::get_vb_count() const +{ + return vb_count_; +} + +//=====================[ return the error status ]======================= +int Pdu::get_error_status() const +{ + return error_status_; +} + +const char *Pdu::agent_error_reason() +{ + int pdu_err = get_error_status(); + if (pdu_err == 0) // any real error? + return "not in error state"; + + int n_vbs = get_vb_count(); + Vb bad; + get_vb(bad, get_error_index() -1); // not zero based?? + const char *pmsg = Snmp::error_string(get_error_status()); + const char *id = bad.to_string_oid(); + const char *val = bad.to_string_value(); + const int HDR_SZ = 100; + + if (!output_) { + int size = ACE_OS::strlen(pmsg) + ACE_OS::strlen(id) + + ACE_OS::strlen(val); + ACE_NEW_RETURN(output_, char[size + HDR_SZ], ""); + } + + ACE_OS::sprintf(output_, + "FAIL PDU REPORT: pdu id: %lu vb cnt: %d vb idx: %d\n" + " msg: %s vb oid: %s value: %s\n", + get_request_id(), n_vbs, get_error_index(), + pmsg, id, val); + + return output_; +} + +//=====================[ set the error status ]========================== +// friend +void set_error_status( Pdu *pdu, const int status) +{ + if (pdu) + pdu->error_status_ = status; +} + +//=====================[ return the error index ]======================== +int Pdu::get_error_index() const +{ + return error_index_; +} + +//=====================[ set the error index ]=========================== +// friend +void set_error_index( Pdu *pdu, const int index) +{ + if (pdu) + pdu->error_index_ = index; +} + +//=====================[ clear error status ]============================= +void clear_error_status( Pdu *pdu) +{ + if (pdu) + pdu->error_status_ = 0; +} + +//=====================[ clear error index ]============================== +void clear_error_index( Pdu *pdu) +{ + if (pdu) + pdu->error_index_ = 0; +} + +//=====================[ return the request id ]========================== +unsigned long Pdu::get_request_id() const +{ + return request_id_; +} + +//=====================[ set the request id ]============================= +// friend function +void set_request_id( Pdu *pdu, const unsigned long rid) +{ + if (pdu) + pdu->request_id_ = rid; +} + +//=====================[ returns validity_ of Pdu instance ]=============== +int Pdu::valid() const +{ + return validity_; +} + +//=====================[ get the pdu type ]=============================== +unsigned short Pdu::get_type()const +{ + return pdu_type_; +} + +// set the pdu type +void Pdu::set_type( unsigned short type) +{ + pdu_type_ = type; +} + + +// trim off the last vb +int Pdu::trim(const int p) +{ + int lp = p; + + // verify that lp is legal + if ( lp < 0 || lp > vb_count_) + return 0; + + while ( lp != 0) { + if ( vb_count_ > 0) { + delete vbs_[vb_count_ - 1]; + vb_count_--; + } + lp--; + } + return 1; +} + + + +// delete a Vb anywhere within the Pdu +int Pdu::delete_vb( const int p) +{ + // position has to be in range + if (( p < 0) || ( p > (vb_count_ - 1))) + return 0; + + // safe to remove it + delete vbs_[ p]; + + for ( int z=p;z < (vb_count_-1);z++) { + vbs_[z] = vbs_[z+1]; + } + vb_count_--; + + return 1; +} + +void Pdu::delete_all_vbs() +{ + for ( int z = 0; z < vb_count_; z++) + delete vbs_[z]; + vb_count_ = 0; +} + + +// set notify timestamp +void Pdu::set_notify_timestamp( const TimeTicks & timestamp) +{ + notify_timestamp_ = timestamp; +} + + +// get notify timestamp +void Pdu::get_notify_timestamp( TimeTicks & timestamp) const +{ + timestamp = notify_timestamp_; +} + +// set the notify id +void Pdu::set_notify_id( const Oid id) +{ + notify_id_ = id; +} + +// get the notify id +void Pdu::get_notify_id( Oid &id) const +{ + id = notify_id_; +} + +// set the notify enterprise +void Pdu::set_notify_enterprise( const Oid &enterprise) +{ + notify_enterprise_ = enterprise; +} + +// get the notify enterprise +void Pdu::get_notify_enterprise( Oid & enterprise) const +{ + enterprise = notify_enterprise_; +} + +// ------ class VbIter ------------------- +VbIter::VbIter(Pdu& pdu): idx_(-1), pdu_(&pdu) +{ +} + +// returns 1 if ok, else 0 if none left +int VbIter::next(Vb& vb) +{ + if (idx_ == -1) { + idx_ = 0; + pdu_->get_vb(vb, idx_++); + return 1; + } + else + if (idx_ < pdu_->get_vb_count()) { + pdu_->get_vb(vb, idx_++); + return 1; + } + return 0; // non left +} diff --git a/ACE/ASNMP/asnmp/pdu.h b/ACE/ASNMP/asnmp/pdu.h new file mode 100644 index 00000000000..a2d84388da0 --- /dev/null +++ b/ACE/ASNMP/asnmp/pdu.h @@ -0,0 +1,219 @@ +/* -*-C++-*- */ +#ifndef PDU_CLS_ +#define PDU_CLS_ +//============================================================================= +/** + * @file pdu.h + * + * $Id$ + * + * Pdu class definition. Encapsulation of an SMI Protocol + * Data Unit (PDU) aka Packet in C++. + * + * + * @author Peter E Mellquist original code Michael MacFaden mrm@cisco.com ACE port + * @author add iterator class for pdus + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +// TODO: this needs to be moved into the CLASS and modifyable at runtime +// TODO: define an iterator object to traverse the vbs in a pdu + +#define MAX_VBS 25 +#include "asnmp/vb.h" // include Vb class definition + +/** + * @class Pdu + * + * @brief Protocol Data Unit (PDU) concrete class. An abstraction of the + * data packet used to by two SNMP sessions to communicate. + */ +class ASNMP_Export Pdu +{ +public: + /// constructor no args + Pdu( void); + + /// constructor with vbs and count + Pdu( Vb* pvbs, const int pvb_count); + + /// constructor with another Pdu instance + Pdu( const Pdu &pdu); + + /// destructor + ~Pdu(); + + /// assignment to another Pdu object overloaded + Pdu& operator=( const Pdu &pdu); + + /// append a vb to the pdu + Pdu& operator+=( Vb &vb); + + // TODO: add Pdu& operator-=(const Vb &vb); + + /// extract all Vbs from Pdu + int get_vblist( Vb* pvbs, const int pvb_count); + + /// deposit all Vbs to Pdu + int set_vblist( Vb* pvbs, const int pvb_count); + + /// get a particular vb + /// where 0 is the first vb + int get_vb( Vb &vb, const int index = 0) const; + + /// set a particular vb + /// where 0 is the first vb + int set_vb( Vb &vb, const int index); + + /// return number of vbs + int get_vb_count() const; + + /// return the error status + int get_error_status() const; + + /// return the complete error info from this pdu + const char *agent_error_reason(); + + /// set the error status + friend ASNMP_Export void set_error_status( Pdu *pdu, const int status); + + /// return the error index + int get_error_index() const; + + /// set the error index + friend ASNMP_Export void set_error_index( Pdu *pdu, const int index); + + /// clear error status + friend ASNMP_Export void clear_error_status( Pdu *pdu); + + /// clear error index + friend ASNMP_Export void clear_error_index( Pdu *pdu); + + /// return the request id + unsigned long get_request_id() const; + + /// set the request id + friend void set_request_id( Pdu *pdu, const unsigned long rid); + + /// get the pdu type + unsigned short get_type() const; + + /// set the pdu type + void set_type( unsigned short type); + + /// returns validity of Pdu instance + int valid() const; + + /// trim off count vbs from the end of the vb list + int trim(const int count=1); + + /// delete a Vb anywhere within the Pdu + int delete_vb( const int position); + + /// delete_all vbs in pdu + void delete_all_vbs(); + + /// set notify timestamp + void set_notify_timestamp( const TimeTicks & timestamp); + + /// get notify timestamp + void get_notify_timestamp( TimeTicks & timestamp) const; + + /// set the notify id + void set_notify_id( const Oid id); + + /// get the notify id + void get_notify_id( Oid &id) const; + + /// set the notify enterprise + void set_notify_enterprise( const Oid &enterprise); + + /// get the notify enterprise + void get_notify_enterprise( Oid & enterprise) const; + + /// return fomatted version of this object + const char *to_string(); + + + protected: + /// pointer to array of Vbs + Vb *vbs_[MAX_VBS]; + + /// count of Vbs + int vb_count_; + + /// SMI error status + int error_status_; + + /// SMI error index + int error_index_; + + /// valid boolean status of object construction + /// SMI request id + int validity_; + unsigned long request_id_; + + /// derived at run time based on request type + unsigned short pdu_type_; + + /** + * a timestamp associated with an infor + * for notify Pdu objects only + * traps & notifies + */ + TimeTicks notify_timestamp_; + + /// an id + Oid notify_id_; + + Oid notify_enterprise_; + + private: + /// buffer for to_string() + char *output_; +}; + + +/** + * @class VbIter + * + * @brief Utility class to iterate once through a PDU varbind list + */ +class ASNMP_Export VbIter +{ + public: + /// default constructor + VbIter(Pdu& pdu); + + /// returns 1 if ok, else 0 if none left + int next(Vb& vb); + + private: + /// disallow copy constructor use + VbIter(const VbIter&); + + /// current object in list + int idx_; + + /// ptr to pdu being interated over + Pdu *pdu_; +}; + +#endif //PDU_CLS_ + diff --git a/ACE/ASNMP/asnmp/sagent.cpp b/ACE/ASNMP/asnmp/sagent.cpp new file mode 100644 index 00000000000..8ee2fdb5b8d --- /dev/null +++ b/ACE/ASNMP/asnmp/sagent.cpp @@ -0,0 +1,97 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// sagent.cpp +// +// = DESCRIPTION +// SNMP agent class definition. The sagent class provides an object oriented +// approach for creating SNMP Agents. The sagent class is an encapsulation +// of SNMP sessions, gets, sets, etc. +// +// = AUTHOR +// Michael R. MacFaden +// +// ============================================================================ +#include "ace/Reactor.h" +#include "ace/SOCK_Dgram.h" + +#include "asnmp/oid.h" // snmp++ oid class +#include "asnmp/vb.h" // snbmp++ vb class +#include "asnmp/target.h" // snmp++ target class +#include "asnmp/pdu.h" // snmp++ pdu class +#include "asnmp/snmperrs.h" // error macros and strings +#include "asnmp/address.h" // snmp++ address class defs +#include "asnmp/snmp.h" // manager snmp interface +#include "asnmp/sagent.h" // agent interface +#include "asnmp/transaction.h" // convert from wire to API + +ACE_RCSID(asnmp, sagent, "$Id$") + +sagent::sagent(unsigned short port): Snmp(port) +{ + ACE_TRACE("sagent::sagent(short)"); +} + +sagent::~sagent() +{ + ACE_TRACE("sagent::~sagent"); +} + +int sagent::handle_input(ACE_HANDLE fd) +{ + ACE_TRACE("sagent::handle_input"); + + transaction tr(iv_snmp_session_); // this section needs a better design + tr.handle_input(fd); + char rcv_com_str[MAX_COMM_STR_LEN]; + if (tr.result(pdu_, rcv_com_str) < 0) + return 0; + OctetStr community(rcv_com_str); + const ACE_INET_Addr &ta = tr.get_from_addr(); + ACE_TCHAR buf_tmp[MAXHOSTNAMELEN + 1]; + ta.addr_to_string (buf_tmp, MAXHOSTNAMELEN); + UdpAddress ra (ACE_TEXT_ALWAYS_CHAR (buf_tmp)); + tgt_.set_address(ra); + + + // process msg here by calling subclass's implementation + switch (pdu_.get_type()){ + case sNMP_PDU_GET: + tgt_.set_read_community(community); + this->handle_get(pdu_, tgt_); + break; + + case sNMP_PDU_GETNEXT: + tgt_.set_read_community(community); + this->handle_get_next(pdu_, tgt_); + break; + + case sNMP_PDU_SET: + tgt_.set_write_community(community); + this->handle_set(pdu_, tgt_); + break; + + default: + ACE_ASSERT(0); + } + return 0; +} + +ACE_HANDLE sagent::get_handle() const +{ + ACE_TRACE("sagent::get_handle"); + return iv_snmp_session_.get_handle(); +} + +int sagent::respond(Pdu& pdu,UdpTarget& tgt) +{ + pdu.set_type(sNMP_PDU_RESPONSE); + transaction tr(pdu, tgt, iv_snmp_session_); + tr.send(); + return 0; +} diff --git a/ACE/ASNMP/asnmp/sagent.h b/ACE/ASNMP/asnmp/sagent.h new file mode 100644 index 00000000000..d220c3ed459 --- /dev/null +++ b/ACE/ASNMP/asnmp/sagent.h @@ -0,0 +1,82 @@ +/* -*-C++-*- */ +#ifndef SAGENT_CLS_ +#define SAGENT_CLS_ +//============================================================================= +/** + * @file sagent.h + * + * $Id$ + * + * SNMP agent class defintion. The sagent class provides an object oriented + * approach for creating SNMP Agents. The sagent class is an encapsulation of SNMP + * sessions, gets, sets, etc. + * + * @author Michael R. MacFaden + */ +//============================================================================= + +#include "ace/Reactor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/SOCK_Dgram.h" + +#include "asnmp/oid.h" // snmp++ oid class +#include "asnmp/vb.h" // snbmp++ vb class +#include "asnmp/target.h" // snmp++ target class +#include "asnmp/pdu.h" // snmp++ pdu class +#include "asnmp/snmperrs.h" // error macros and strings +#include "asnmp/address.h" // snmp++ address class defs +#include "asnmp/snmp.h" // snmp interface + +// sagent - supports Version 1 operations in blocking mode + +#define DEF_AGENT_PORT (161) + +/** + * @class sagent + * + * @brief Concrete class sagent defines the session and interface to + * communicate with another SNMP Version 1 manager + */ +class ASNMP_Export sagent : public ACE_Event_Handler, private Snmp +{ + public: + + + // override the next three methods (callbacks) to implment your agent + // + + /// retrieve data from a peer agent for a given list of oid values + virtual int handle_get( Pdu &pdu, UdpTarget &target) = 0; + + /// retrieve data lexically adjacent to the oids specified in the pdu + /// from the peer agent + virtual int handle_get_next( Pdu &pdu, UdpTarget &target) = 0; + + /// set data in the agent from the list of oids in the pdu + virtual int handle_set( Pdu &pdu, UdpTarget &target) = 0; + + /// new pdu received from mgr (reactor calls this) + virtual int handle_input(ACE_HANDLE); + + /// retrieve io descriptor (reactor uses this) + virtual ACE_HANDLE get_handle() const; + + /// send a response pdu to the mgr + int respond(Pdu& pdu, UdpTarget& tgt); + + protected: + sagent(unsigned short port = DEF_AGENT_PORT); + virtual ~sagent(); + +private: + sagent(const sagent&); + Pdu pdu_; // current input pdu + UdpTarget tgt_; // addr & com strs +}; + +#endif //SAGENT_CLS_ + diff --git a/ACE/ASNMP/asnmp/smi.h b/ACE/ASNMP/asnmp/smi.h new file mode 100644 index 00000000000..3e505c64cb8 --- /dev/null +++ b/ACE/ASNMP/asnmp/smi.h @@ -0,0 +1,147 @@ +/* -*-C++-*- */ +#ifndef SMIDEF_ +#define SMIDEF_ +//============================================================================= +/** + * @file smi.h + * + * $Id$ + * + * Address class definition. Encapsulates various network + * addresses into easy to use, safe and portable classes. + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. + +=====================================================================*/ + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +//----------[ ASN/BER Base Types ]----------------------------------------- +// Basic Encoding Rules (BER) +// (used in forming SYNTAXes and certain SNMP types/values) +#define aSN_UNIVERSAL (0x00) +#define aSN_APPLICATION (0x40) +#define aSN_CONTEXT (0x80) +#define aSN_PRIVATE (0xC0) +#define aSN_PRIMITIVE (0x00) +#define aSN_CONSTRUCTOR (0x20) + +//------[ SNMP ObjectSyntax Values ]--------------------------------------- +#define sNMP_SYNTAX_SEQUENCE (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x10) + + +//------------------------------------------------------------------------- +// These values are used in the "syntax" member +// of the smiVALUE structure which follows. +// Note: UInt32 is indistinguishable from Gauge32 per SNMPv2 Draft Standard +// NsapAddr is obsoleted as unique SMI type per SNMPv2 Draft Standard +#define sNMP_SYNTAX_INT (aSN_UNIVERSAL | aSN_PRIMITIVE | 0x02) +#define sNMP_SYNTAX_BITS (aSN_UNIVERSAL | aSN_PRIMITIVE | 0x03) +#define sNMP_SYNTAX_OCTETS (aSN_UNIVERSAL | aSN_PRIMITIVE | 0x04) +#define sNMP_SYNTAX_NULL (aSN_UNIVERSAL | aSN_PRIMITIVE | 0x05) +#define sNMP_SYNTAX_OID (aSN_UNIVERSAL | aSN_PRIMITIVE | 0x06) +#define sNMP_SYNTAX_INT32 sNMP_SYNTAX_INT +#define sNMP_SYNTAX_IPADDR (aSN_APPLICATION | aSN_PRIMITIVE | 0x00) +#define sNMP_SYNTAX_CNTR32 (aSN_APPLICATION | aSN_PRIMITIVE | 0x01) +#define sNMP_SYNTAX_GAUGE32 (aSN_APPLICATION | aSN_PRIMITIVE | 0x02) +#define sNMP_SYNTAX_TIMETICKS (aSN_APPLICATION | aSN_PRIMITIVE | 0x03) +#define sNMP_SYNTAX_OPAQUE (aSN_APPLICATION | aSN_PRIMITIVE | 0x04) +#define sNMP_SYNTAX_CNTR64 (aSN_APPLICATION | aSN_PRIMITIVE | 0x06) +#define sNMP_SYNTAX_UINT32 (aSN_APPLICATION | aSN_PRIMITIVE | 0x07) + +//------------------------------------------------------------------------- + +//---------------[ Exception conditions for SNMPv2 ]----------------------- +// support SNMP v2 +#define sNMP_SYNTAX_NOSUCHOBJECT (aSN_CONTEXT | aSN_PRIMITIVE | 0x00) +#define sNMP_SYNTAX_NOSUCHINSTANCE (aSN_CONTEXT | aSN_PRIMITIVE | 0x01) +#define sNMP_SYNTAX_ENDOFMIBVIEW (aSN_CONTEXT | aSN_PRIMITIVE | 0x02) + + +//--------------[ different types of PDU's ]------------------------------- +#define sNMP_PDU_GET (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x0) +#define sNMP_PDU_GETNEXT (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x1) +#define sNMP_PDU_RESPONSE (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x2) +#define sNMP_PDU_SET (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x3) +#define sNMP_PDU_V1TRAP (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x4) +#define sNMP_PDU_GETBULK (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x5) +#define sNMP_PDU_INFORM (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x6) +#define sNMP_PDU_TRAP (aSN_CONTEXT | aSN_CONSTRUCTOR | 0x7) + + +//------[ smi typedefs ]--------------------------------------------------- +// SNMP-related types from RFC1442 (SMI) + +typedef unsigned char SmiBYTE, *SmiLPBYTE; + +//------------------------------------------------------------------------- +// SNMP-related types from RFC1442 (SMI) + +// int +typedef long SmiINT, *SmiLPINT; + +// int 32 +typedef SmiINT SmiINT32, *SmiLPINT32; + +// unit32 +typedef unsigned long SmiUINT32, *SmiLPUINT32; + +// octet struct +typedef struct { + SmiUINT32 len; + SmiLPBYTE ptr;} SmiOCTETS, *SmiLPOCTETS; + +// bits +typedef SmiOCTETS SmiBITS, *SmiLPBITS; + +// SMI oid struct +typedef struct { + SmiUINT32 len; + SmiLPUINT32 ptr;} SmiOID, *SmiLPOID; + +// ipaddr +typedef SmiOCTETS SmiIPADDR, *SmiLPIPADDR; + +// 32bit counter +typedef SmiUINT32 SmiCNTR32, *SmiLPCNTR32; + +// gauge +typedef SmiUINT32 SmiGAUGE32, *SmiLPGAUGE32; + +// timeticks +typedef SmiUINT32 SmiTIMETICKS, *SmiLPTIMETICKS; + +// opaque +typedef SmiOCTETS SmiOPAQUE, *SmiLPOPAQUE; + +// nsapaddr +typedef SmiOCTETS SmiNSAPADDR, *SmiLPNSAPADDR; + +// 64 bit counter +typedef struct { + SmiUINT32 hipart; + SmiUINT32 lopart; +} SmiCNTR64, *SmiLPCNTR64; + +#endif // SMIDEF_ + + diff --git a/ACE/ASNMP/asnmp/smival.h b/ACE/ASNMP/asnmp/smival.h new file mode 100644 index 00000000000..e754206f506 --- /dev/null +++ b/ACE/ASNMP/asnmp/smival.h @@ -0,0 +1,102 @@ +/* -*-C++-*- */ +#ifndef SMIVALUE_ +#define SMIVALUE_ +//============================================================================= +/** + * @file smival.h + * + * $Id$ + * + * SMIValue class definition. Superclass for the various types + * of SNMP values (Address, Oid, Octet, etc.). Provides + * only a few functions, most info is in subclass. + * + * + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//----[ includes ]----------------------------------------------------- +#include "asnmp/smi.h" +#include "asnmp/ASNMP_Export.h" +#include "ace/os_include/os_stddef.h" + +//----[ macros ]------------------------------------------------------- + +//====================================================================== +// SMI value structure conforming with SMI RFC +// +typedef struct { /* smiVALUE portion of VarBind */ + SmiUINT32 syntax; /* Insert SNMP_SYNTAX_<type> */ + union { + SmiINT sNumber; /* SNMP_SYNTAX_INT + SNMP_SYNTAX_INT32 */ + SmiUINT32 uNumber; /* SNMP_SYNTAX_UINT32 + SNMP_SYNTAX_CNTR32 + SNMP_SYNTAX_GAUGE32 + SNMP_SYNTAX_TIMETICKS */ + SmiCNTR64 hNumber; /* SNMP_SYNTAX_CNTR64 */ + SmiOCTETS string; /* SNMP_SYNTAX_OCTETS + SNMP_SYNTAX_BITS + SNMP_SYNTAX_OPAQUE + SNMP_SYNTAX_IPADDR + SNMP_SYNTAX_NSAPADDR */ + SmiOID oid; /* SNMP_SYNTAX_OID */ + SmiBYTE empty; /* SNMP_SYNTAX_NULL + SNMP_SYNTAX_NOSUCHOBJECT + SNMP_SYNTAX_NOSUCHINSTANCE + SNMP_SYNTAX_ENDOFMIBVIEW */ + } value; +} SmiVALUE, *SmiLPVALUE; + +// An "abstract" (pure virtual) class that serves as the base class +// for all specific SNMP syntax types. +// +class ASNMP_Export SnmpSyntax { + +public: + virtual const char * to_string() = 0; + // virtual function for getting a printable ASCII value for any SNMP Value + + virtual SmiUINT32 get_syntax() = 0; + // return the current syntax + + virtual SnmpSyntax * clone() const = 0; + // virtual clone operation for creating a new Value from an existing + // value. The caller MUST use the delete operation on the return + // value when done. + + virtual ~SnmpSyntax() {}; + // virtual destructor to ensure deletion of derived classes... + + virtual SnmpSyntax& operator=(SnmpSyntax &/*val*/) + { + return *this; + } + // overloaded assignment operator + // This should be pure virtual, but WinNT compiler + // complains about unresolved reference at link time. + + virtual int valid() const = 0; + // return validity of value object. + +protected: + SmiVALUE smival; +}; + +#endif // SMIVALUE_ diff --git a/ACE/ASNMP/asnmp/snmp.cpp b/ACE/ASNMP/asnmp/snmp.cpp new file mode 100644 index 00000000000..cc2e1dd4179 --- /dev/null +++ b/ACE/ASNMP/asnmp/snmp.cpp @@ -0,0 +1,286 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// snmp.cpp +// +// = DESCRIPTION +// The basic SNMPv1 API - blocking version using UDP/IPv4 transport +// and addressing. +// +// = AUTHOR +// Peter E Mellquist class design/orig code +// Michael R MacFaden mrm@cisco.com / rework API, use ACE facilities +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + + +#define INCLUDE_SNMP_ERR_STRINGS_ + +//----[ snmp++ includes ]---------------------------------------------- +#include "asnmp/snmp.h" // class def for this module +#include "asnmp/oid.h" // class def for oids +#include "asnmp/enttraps.h" // class def for well known trap oids +#include "asnmp/vb.h" // class def for vbs +#include "asnmp/address.h" // class def for addresses +#include "asnmp/wpdu.h" // adapter to cmu_library / wire protocol +#include "asnmp/transaction.h" // synchronous transaction processor +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_unistd.h" +#include "ace/OS_NS_time.h" + +ACE_RCSID(asnmp, snmp, "$Id$") + +const coldStartOid coldStart; +const warmStartOid warmStart; +const linkDownOid linkDown; +const linkUpOid linkUp; +const authenticationFailureOid authenticationFailure; +const egpNeighborLossOid egpNeighborLoss; +const snmpTrapEnterpriseOid snmpTrapEnterprise; + +char Snmp::host_name_[MAXHOSTNAMELEN] = ""; + +Snmp::Snmp(unsigned short port): result_(0), construct_status_(SNMP_CLASS_ERROR), last_transaction_status_(0) +{ + ACE_TRACE("Snmp::Snmp"); + + ACE_INET_Addr addr(port); // any port,address is ok + if (iv_snmp_session_.open(addr) < 0) { + last_transaction_status_ = errno; // open udp/ipv4 socket + ACE_DEBUG((LM_DEBUG, "Snmp::snmp::open port %d failed", port)); + return; + } + + // initial request id randomly generated then monotonically incremented + req_id_ = (unsigned) ACE_OS::time(0); + + construct_status_ = SNMP_CLASS_SUCCESS; + return; +} + +Snmp::~Snmp() +{ + ACE_TRACE("Snmp::~Snmp"); + iv_snmp_session_.close(); +} + +int Snmp::valid() const +{ + return construct_status_; +} + +// given error code, return string definition +// class version +// static +const char * Snmp::error_string(int last_transaction_status_) +{ + ACE_TRACE("Snmp::error_string"); + + return ((last_transaction_status_ < 0) ? + ((last_transaction_status_ < MAX_NEG_ERROR)? + nErrs[ abs(MAX_NEG_ERROR) + 1] : nErrs[abs(last_transaction_status_)]): + ((last_transaction_status_ > MAX_POS_ERROR)? + pErrs[MAX_POS_ERROR+1] : pErrs[last_transaction_status_])); +} + +// instance version +const char * Snmp::error_string() +{ + return Snmp::error_string(last_transaction_status_); +} + +void Snmp::check_default_port(UdpTarget& target, unsigned short port) +{ + UdpAddress tmp; + target.get_address(tmp); + if (tmp.get_port() == 0) { + tmp.set_port(port); + target.set_address(tmp); + } +} + +int Snmp::run_transaction(Pdu& pdu, UdpTarget& target) +{ + int rc, done = 0; + + // 1. set unique id to match this packet on return + size_t hold_req_id = req_id_++; + set_request_id(&pdu, hold_req_id); + + // 2. write request to agent + transaction trans(pdu, target, iv_snmp_session_); + + // this call blocks while it attempts to retrieve agent response + while (!done) { + if ((rc = trans.run()) < 0) { + last_transaction_status_ = rc; + return rc; + } + else { + trans.result(pdu); + // verify this is the pdu we are after + if (pdu.get_request_id() == hold_req_id) + done = 1 ; + } + } + return 0; +} + +int Snmp::run_transaction(Pdu& pdu, UdpTarget& target, Snmp_Result * cb) +{ + if (!cb) + return run_transaction(pdu, target); + + // 1. set unique id to match this packet on return + hold_req_id_ = req_id_++; + set_request_id(&pdu, hold_req_id_); + pdu_ = &pdu; + result_ = cb; + + // 2. write request to agent + transaction * trans = new transaction(pdu, target, iv_snmp_session_); + return trans->run(this); +} + +void Snmp::result(transaction *t, int rc) +{ + t->result(*pdu_); + // verify this is the pdu we are after + if (pdu_->get_request_id() == hold_req_id_) + { + last_transaction_status_ = rc; + delete t; + result_->result(this, rc); + } + else + { + rc = t->run(this); + if (rc < 0) + { + delete t; + result_->result(this, rc); + } + } +} + +int Snmp::validate_args(const Pdu& pdu, const UdpTarget& target) const +{ + // 0. check object status + if (construct_status_ != SNMP_CLASS_SUCCESS) + return construct_status_; + + // 1. check args passed + if ( !pdu.valid() || !target.valid() ) + return SNMP_INVALID_ARGS; + return 0; +} + +// SYNC API: write request to wire then wait for reply or timeout +int Snmp::get( Pdu &pdu, UdpTarget &target, Snmp_Result * cb) +{ + ACE_TRACE("Snmp::get"); + int rc; + if ((rc = validate_args(pdu, target)) != 0) + return rc; + + pdu.set_type( sNMP_PDU_GET); + check_default_port(target); + return run_transaction(pdu, target, cb); +} + +int Snmp::get_next( Pdu &pdu, UdpTarget &target, Snmp_Result * cb) +{ + ACE_TRACE("Snmp::get_next"); + int rc; + if ((rc = validate_args(pdu, target)) != 0) + return rc; + + pdu.set_type( sNMP_PDU_GETNEXT); + check_default_port(target); + return run_transaction(pdu, target, cb); +} + +int Snmp::set( Pdu &pdu, UdpTarget &target, Snmp_Result * cb) +{ + ACE_TRACE("Snmp::set"); + int rc; + if ((rc = validate_args(pdu, target)) != 0) + return rc; + + pdu.set_type( sNMP_PDU_SET); + check_default_port(target); + return run_transaction(pdu, target, cb); +} + +// one way, best of luck, non-confirmed alert +int Snmp::trap( Pdu &pdu, UdpTarget &target) +{ + ACE_TRACE("Snmp::trap"); + int rc; + if ((rc = validate_args(pdu, target)) != 0) + return rc; + + pdu.set_type( sNMP_PDU_V1TRAP); + check_default_port(target, DEF_TRAP_PORT); + + // 2. write request to agent + transaction trans(pdu, target, iv_snmp_session_); + if (trans.send() > 0) // expect number of bytes sent on + return 0; + + last_transaction_status_ = SNMP_CLASS_INTERNAL_ERROR; + return -1; +} + +// Allow host name to be overriden. Supplying a null pointer or zero +// length string removes the override. +void Snmp::override_host_name(const char* name) +{ + if (name) + { + ACE_OS::strncpy(host_name_, name, MAXHOSTNAMELEN); + host_name_[MAXHOSTNAMELEN-1] = 0; + } + else { + host_name_[0] = 0; + } +} + +// Returns the current host name in the supplied string. +void Snmp::get_host_name(char* name, int len) +{ + if (name) + { + if (ACE_OS::strlen(host_name_) > 0) + { + ACE_OS::strncpy(name, host_name_, len); + name[len-1] = 0; + } + else + { + if (ACE_OS::hostname(name, len-1) == -1) + name[0] = 0; + } + } +} + +Snmp_Result::~Snmp_Result() {} diff --git a/ACE/ASNMP/asnmp/snmp.h b/ACE/ASNMP/asnmp/snmp.h new file mode 100644 index 00000000000..5bae232baa0 --- /dev/null +++ b/ACE/ASNMP/asnmp/snmp.h @@ -0,0 +1,137 @@ +/* -*-C++-*- */ +#ifndef SNMP_CLS_ +#define SNMP_CLS_ +//============================================================================= +/** + * @file snmp.h + * + * $Id$ + * + * SNMP class defintion. The Snmp class provides an object oriented + * approach to SNMP. The SNMP class is an encapsulation of SNMP + * sessions, gets, sets, etc. The class manages all SNMP + * resources and provides complete retry and timeout capability. + * + * + * @author Peter E Mellquist design + * @author first implementation Michael R. MacFaden port to ACE / use Reactor pattern + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "ace/Reactor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/SOCK_Dgram.h" + +#include "asnmp/oid.h" // snmp++ oid class +#include "asnmp/vb.h" // snbmp++ vb class +#include "asnmp/target.h" // snmp++ target class +#include "asnmp/pdu.h" // snmp++ pdu class +#include "asnmp/snmperrs.h" // error macros and strings +#include "asnmp/address.h" // snmp++ address class defs +#include "asnmp/transaction_result.h" +#include "asnmp/ASNMP_Export.h" + +class Snmp; +class ASNMP_Export Snmp_Result +{ + public: + virtual ~Snmp_Result(); + virtual void result(Snmp *snmp, int result) = 0; +}; + +// Snmp session class - supports Version 1 operations in blocking mode +/** + * @class Snmp + * + * @brief Concrete class Snmp defined the session and interface to + * communicate with another SNMP Version 1 agent + */ +class ASNMP_Export Snmp : public transaction_result +{ + Snmp_Result * result_; + Pdu * pdu_; + unsigned hold_req_id_; +public: + Snmp(unsigned short port = INADDR_ANY); + virtual ~Snmp(); + + /// retrieve data from a peer agent for a given list of oid values + /// default port 161 + int get( Pdu &pdu, UdpTarget &target, Snmp_Result * cb = 0); + + /** + * retrieve data lexically adjacent to the oids specified in the pdu + * from the peer agent + * default port 161 + */ + int get_next( Pdu &pdu, UdpTarget &target, Snmp_Result * cb = 0); + + /// set data in the agent from the list of oids in the pdu + /// default port 161 + int set( Pdu &pdu, UdpTarget &target, Snmp_Result * cb = 0); + + /// send an SNMPv1 trap (unreliable) to a remote system (def port 162) + int trap( Pdu &pdu, UdpTarget &target); + + /// status of object after construction + int valid() const; + + /// given error code, return string reason + static const char * error_string(int code); + + /// retrieve a reason string if any of the above commands fail + const char * error_string(); + + /// for async transaction results + void result(transaction * t, int rc); + + /// allow the host name to be overriden + static void override_host_name(const char* name); + + /// returns the overriden host name + static void get_host_name(char* name, int len); + +protected: + void check_default_port(UdpTarget& target,unsigned short port=DEF_AGENT_PORT); + int run_transaction(Pdu& pdu, UdpTarget& target); + int run_transaction(Pdu& pdu, UdpTarget& target, Snmp_Result * cb); + int validate_args(const Pdu& pdu, const UdpTarget& target) const; + + Snmp(const Snmp&); + + /// io object + ACE_SOCK_Dgram iv_snmp_session_; + + /// status of construction + int construct_status_; + + /// result code from last transaction + int last_transaction_status_; + + /// transaction request id + unsigned req_id_; + + static char host_name_[MAXHOSTNAMELEN]; +}; + +#endif //SNMP_CLS_ diff --git a/ACE/ASNMP/asnmp/snmperrs.h b/ACE/ASNMP/asnmp/snmperrs.h new file mode 100644 index 00000000000..7aafdc0619a --- /dev/null +++ b/ACE/ASNMP/asnmp/snmperrs.h @@ -0,0 +1,210 @@ +/* -*-C++-*- */ +#ifndef SNMPERRS_H_ +#define SNMPERRS_H_ +//============================================================================= +/** + * @file snmperrs.h + * + * $Id$ + * + * Definition of error macros and error strings + * + * + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +============================================================================*/ + + +//-------[ Positive ASNMP Error Return Codes ]------------------------------ +// These values are error status values from RFC 1905 +// +// The values can be returned via Pdu::get_error_status() +// +#define SNMP_ERROR_SUCCESS 0 // Success Status +#define SNMP_ERROR_TOO_BIG 1 // Pdu encoding too big +#define SNMP_ERROR_NO_SUCH_NAME 2 // No such VB name, see error index +#define SNMP_ERROR_BAD_VALUE 3 // Bad Vb +#define SNMP_ERROR_READ_ONLY 4 // VB is read only, see error index +#define SNMP_ERROR_GENERAL_VB_ERR 5 // General VB error, see error index +#define SNMP_ERROR_NO_ACCESS 6 // No access to MIBs data +#define SNMP_ERROR_WRONG_TYPE 7 // Requested type was incorrect +#define SNMP_ERROR_WRONG_LENGTH 8 // Request Pdu has inccorect length +#define SNMP_ERROR_WRONG_ENCODING 9 // Request Pdu has wrong encoding +#define SNMP_ERROR_WRONG_VALUE 10 // Request Pdu has wrong value +#define SNMP_ERROR_NO_CREATION 11 // Unable to create object specified +#define SNMP_ERROR_INCONSIST_VAL 12 // Inconsistent value in request +#define SNMP_ERROR_RESOURCE_UNAVAIL 13 // Resources unavailable +#define SNMP_ERROR_COMITFAIL 14 // Unable to comit +#define SNMP_ERROR_UNDO_FAIL 15 // Unable to undo +#define SNMP_ERROR_AUTH_ERR 16 // Authentication failure +#define SNMP_ERROR_NOT_WRITEABLE 17 // Mib Object not writeable +#define SNMP_ERROR_INCONSIS_NAME 18 // Inconsistent naming used + + +//-------[ Negative ASNMP Result/Error Return Codes ]------------------- + +// General +#define SNMP_CLASS_SUCCESS 0 // success +#define SNMP_CLASS_ERROR -1 // general error +#define SNMP_CLASS_RESOURCE_UNAVAIL -2 // e.g., malloc failed +#define SNMP_CLASS_INTERNAL_ERROR -3 // unexpected / internal error +#define SNMP_CLASS_UNSUPPORTED -4 // unsupported function + +// Callback reasons: +#define SNMP_CLASS_TIMEOUT -5 // outstanding request timed out +#define SNMP_CLASS_ASYNC_RESPONSE -6 // received response for outstd request +#define SNMP_CLASS_NOTIFICATION -7 // received notification (trap/inform) +#define SNMP_CLASS_SESSION_DESTROYED -8 // snmp::destroyed with oustanding reqs pending + +// Snmp Class: +#define SNMP_CLASS_INVALID -10 // snmp::mf called on invalid instance +#define SNMP_CLASS_INVALID_PDU -11 // invalid pdu passed to mf +#define SNMP_CLASS_INVALID_TARGET -12 // invalid target passed to mf +#define SNMP_CLASS_INVALID_CALLBACK -13 // invalid callback to mf +#define SNMP_CLASS_INVALID_REQID -14 // invalid request id to cancel +#define SNMP_CLASS_INVALID_NOTIFYID -15 // missing trap/inform oid +#define SNMP_CLASS_INVALID_OPERATION -16 // snmp operation not allowed for specified target +#define SNMP_CLASS_INVALID_OID -17 // invalid oid passed to mf +#define SNMP_CLASS_INVALID_ADDRESS -18 // invalid address passed to mf +#define SNMP_CLASS_ERR_STATUS_SET -19 // agent returned response pdu with error_status set + +// Transport Errors: +#define SNMP_CLASS_TL_UNSUPPORTED -20 // transport unsupported +#define SNMP_CLASS_TL_IN_USE -21 // transport in use +#define SNMP_CLASS_TL_FAILED -22 // transport operation failed + +// extras +#define SNMP_CLASS_SHUTDOWN -23 // used for back door shutdown +#define SNMP_INVALID_ARGS -24 // invalid args passed + +#ifdef INCLUDE_SNMP_ERR_STRINGS_ + +// ASCII strings returned through Snmp::error() function. NOTE: altering +// the strings in this header file will not affect the return values of +// Snmp::error(), unless you rebuild the ASNMP library from source. + +#define MAX_POS_ERROR SNMP_ERROR_INCONSIS_NAME +#define MAX_NEG_ERROR SNMP_CLASS_SHUTDOWN + +static const char * pErrs[] = { + "Success", // 0 + "SNMP: Response PDU Too Big", // 1 + "SNMP: Variable does not exist", // 2 + "SNMP: Cannot modify variable: Bad Value", // 3 + "SNMP: Cannot modify object, Read Only", // 4 + "SNMP: Cannot perform operation, General Error", // 5 + "SNMP: Cannot access variable, No Access", // 6 + "SNMP: Cannot create/modify variable, Wrong Type", // 7 + "SNMP: Cannot create/set variable, Wrong Length", // 8 + "SNMP: Cannot create/set variable, Wrong Encoding", // 9 + "SNMP: Cannot create/set variable, Wrong Value", // 10 + "SNMP: Cannot create variable, Creation Not Allowed", // 11 + "SNMP: Cannot create/set variable, Inconsistent Value", // 12 + "SNMP: Cannot create/set variable, Resource Unavailable", // 13 + "SNMP: Cannot create/set variable, Commit Failed", // 14 + "SNMP: Cannot create/set variable, Undo Failed", // 15 + "SNMP: Cannot perform operation, Authorization Error", // 16 + "SNMP: Cannot create/set variable, Not Writable", // 17 + "SNMP: Cannot create variable, Inconsistent Name", // 18 +}; + + +static const char * nErrs[] = { + // General: + // 0 SNMP_CLASS_SUCCESS + "ASNMP: Success", + + // 1 SNMP_CLASS_ERROR + "ASNMP: Operation failed", + + // 2 SNMP_CLASS_RESOURCE_UNAVAIL + "ASNMP: Resource unavailable", + + // 3 SNMP_CLASS_INTERNAL_ERROR + "ASNMP: Internal error", + + // 4 SNMP_CLASS_UNSUPPORTED + "ASNMP: Unsupported function", + + // Callback reasons: + // 5 SNMP_CLASS_TIMEOUT + "ASNMP: SNMP request timed out", + + // 6 SNMP_CLASS_ASYNC_RESPONSE + "ASNMP: Received SNMP Response", + + // 7 SNMP_CLASS_NOTIFICATION + "ASNMP: Received SNMP Notification (trap or inform)", + + // 8 SNMP_CLASS_SESSION_DESTROYED + "ASNMP: Closing session with outstanding requests", + + // 9 reserved for future + "Unknown error code", + + // Snmp Class errors: + // 10 SNMP_CLASS_INVALID + "ASNMP: Class not valid", + + // 11 SNMP_CLASS_INVALID_PDU + "ASNMP: Invalid Pdu", + + // 12 SNMP_CLASS_INVALID_TARGET + "ASNMP: Invalid Target", + + // 13 SNMP_CLASS_INVALID_CALLBACK + "ASNMP: Invalid (null) Callback Function", + + // 14 SNMP_CLASS_INVALID_REQID + "ASNMP: Invalid Request Id", + + // 15 SNMP_CLASS_INVALID_NOTIFYID + "ASNMP: Invalid Notification Id", + + // 16 SNMP_CLASS_INVALID_OPERATION + "ASNMP: SNMP Operation not supported on specified Target", + + // 17 SNMP_CLASS_INVALID_OID + "ASNMP: Invalid Object Identifier", + + // 18 SNMP_CLASS_INVALID_ADDRESS + "ASNMP: Invalid Address", + + // 19 SNMP_CLASS_ERR_STATUS_SET + "ASNMP: Agent indicates error in SNMP request", + + // Transport Errors: + // 20 SNMP_CLASS_TL_UNSUPPORTED + "ASNMP: Transport is not supported", + + // 21 SNMP_CLASS_TL_IN_USE + "ASNMP: Transport is in use", + + // 22 SNMP_CLASS_TL_FAILED + "ASNMP: Transport operation failed", + + // 23 SNMP_CLASS_SHUTDOWN + "ASNMP: Blocked Mode Shutdown", + + // unknown error code + "Unknown error code", +}; + +#endif //INCLUDE_SNMP_ERR_STRINGS_ + +#endif //SNMPERRS_H_ diff --git a/ACE/ASNMP/asnmp/target.cpp b/ACE/ASNMP/asnmp/target.cpp new file mode 100644 index 00000000000..7c93a9275f9 --- /dev/null +++ b/ACE/ASNMP/asnmp/target.cpp @@ -0,0 +1,321 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// target.cpp +// +// = DESCRIPTION +// Target class defines target SNMP agents. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. + =====================================================================*/ + +#include "asnmp/target.h" + +ACE_RCSID(asnmp, target, "$Id$") + +//---------------------------------------------------------------------- +//--------[ Class default values ]---------------------- +//---------------------------------------------------------------------- +u_long SnmpTarget::default_timeout_ = DEF_TIMEOUT; +int SnmpTarget::default_retries_ = DEF_RETRIES; +u_long SnmpTarget::default_max_pdu_size_ = DEF_MAX_SNMP_PACKET; +snmp_version SnmpTarget::default_version_ = version1; + +OctetStr UdpTarget::default_rd_community_(READ_COMM_STR); +OctetStr UdpTarget::default_wr_community_(WRITE_COMM_STR); + +//---------------------------------------------------------------------- +//--------[ Abstract SnmpTarget Member Functions ]---------------------- +//---------------------------------------------------------------------- +SnmpTarget::SnmpTarget(): + validity_(0), timeout_(default_timeout_), retries_(default_retries_), + max_pdu_size_(default_max_pdu_size_), version_(default_version_) +{ +} + +// return validity of target +int SnmpTarget::valid() const +{ + return validity_; +} + +// allow destruction of derived classes +SnmpTarget::~SnmpTarget() +{ +} + +// set the timeout +void SnmpTarget::set_timeout( const u_long t) +{ + timeout_ = t; +} + +// change the default timeout +void SnmpTarget::set_default_timeout( const u_long t) +{ + default_timeout_ = t; +} + +// set the retry value +void SnmpTarget::set_retry( const int r) +{ + retries_ = r; +} + +// change the default retries +void SnmpTarget::set_default_retry( const int r) +{ + default_retries_ = r; +} + +void SnmpTarget:: set_max_pdu_size(const u_long max_pdu_sz) +{ + max_pdu_size_ = max_pdu_sz; +} + + +void SnmpTarget::set_default_max_pdu_size(const u_long max_pdu_sz) +{ + default_max_pdu_size_ = max_pdu_sz; +} + +void SnmpTarget::set_version( const snmp_version v) +{ + version_ = v; +} + +void SnmpTarget::set_default_version( const snmp_version v) +{ + default_version_ = v; +} + +snmp_version SnmpTarget::get_version() const +{ + return version_; +} + +snmp_version SnmpTarget::get_default_version() const +{ + return default_version_; +} + +u_long SnmpTarget::get_max_pdu_size() const +{ + return max_pdu_size_; +} + +// get the retry value +int SnmpTarget::get_retry() const +{ + return retries_; +} + +// get the retry value +int SnmpTarget::get_default_retry() const +{ + return default_retries_; +} + +// get the timeout +u_long SnmpTarget::get_timeout() const +{ + return timeout_; +} + +SnmpTarget& SnmpTarget::operator=(const SnmpTarget& lhs) +{ + if (this == &lhs) + return *this; + + validity_ = lhs.validity_; + timeout_ = lhs.timeout_; + retries_ = lhs.retries_; + max_pdu_size_ =lhs.max_pdu_size_; + version_ = lhs.version_; + return *this; +} + +bool operator==(const SnmpTarget& lhs, const SnmpTarget& rhs) +{ + if (lhs.timeout_ != rhs.timeout_) + return false; + + if (lhs.retries_ != rhs.retries_) + return false; + + if (lhs.max_pdu_size_ != rhs.max_pdu_size_) + return false; + + if (lhs.version_ != rhs.version_) + return false; + + return true; +} + + +//---------------------------------------------------------------------- +//--------[ IpTarget Member Functions ]---------------------------------- +//---------------------------------------------------------------------- + + +//---------[ UdpTarget::UdpTarget( void) ]---------------------------------- + +UdpTarget::UdpTarget() +{ + validity_ = 0; + read_community_ = default_rd_community_; // assign by init fails + write_community_ = default_wr_community_; +} + +UdpTarget::UdpTarget(const UdpAddress& udp) : udp_address_(udp) +{ + if (udp_address_.valid()) + validity_ = 1; + read_community_ = default_rd_community_; + write_community_ = default_wr_community_; +} + +// - copy constructor can be synthesised by compiler + +//-----------[ UdpTarget::~UdpTarget() ]-------------------------------- +UdpTarget::~UdpTarget() +{ +} + +//-----------[ UdpTarget::clone() ]-------------------------------- +SnmpTarget * UdpTarget::clone() const +{ + return (SnmpTarget *) new UdpTarget(*this); +} + + +void UdpTarget::set_default_read_community(const OctetStr& rd_community) +{ + default_rd_community_ = rd_community; +} + +void UdpTarget::set_default_write_community(const OctetStr& wr_community) +{ + default_wr_community_ = wr_community; +} + + +// get the read community name as an u_char and len +void UdpTarget::get_read_community( OctetStr& read_community_oct) const +{ + read_community_oct = read_community_; +} + +//---------[ UdpTarget::set_getcommunity ]--------------------------------- +// set the read community name +void UdpTarget::set_read_community( const OctetStr& new_read_community) +{ + read_community_ = new_read_community; +} + +//---------[ UdpTarget::get_writecommunity ]---------------------------- +// get the write community +void UdpTarget::get_write_community( OctetStr &write_community_oct) const +{ + write_community_oct = write_community_; +} + +//-----------[ UdpTarget::set_writecommunity ]--------------------------- +// set the write community +void UdpTarget::set_write_community( const OctetStr& write_community_oct) +{ + write_community_ = write_community_oct; +} + +//------------[ Address& UdpTarget::get_address() ]--------------------- +// get the address +void UdpTarget::get_address( UdpAddress &address) const +{ + address = udp_address_; + return; +} + +//-------------[ UdpTarget::set_address ]-------------------------------- +// set the address +int UdpTarget::set_address( UdpAddress &udp_address) +{ + udp_address_ = udp_address; + if ( udp_address_.valid()) + validity_ = 1; + else + validity_ = 0; + + return validity_; +} + +// overloaded assignment +UdpTarget& UdpTarget::operator=( const UdpTarget& lhs) +{ + if (this == &lhs) + return *this; + + // assign base part + *((SnmpTarget *) this) = *((SnmpTarget *)&lhs); + + udp_address_ = lhs.udp_address_; + read_community_ = lhs.read_community_; + write_community_ = lhs.write_community_; + validity_ = lhs.validity_; + + return *this; +} + +const char *UdpTarget::to_string() +{ + sprintf(output_buffer_,"UdpTarget: [ valid: %d addr: %s rd: %s wr: %s \ +ver: %d, timeout: %d, retries: %d max_pdu_size: %d]", + valid(), udp_address_.to_string(), read_community_.to_string(), + write_community_.to_string(), version_, (int) timeout_, + retries_, max_pdu_size_); + return output_buffer_; +} + +//=============[ int operator == UdpTarget, UdpTarget ]=============== +// equivlence operator overloaded +bool operator==( const UdpTarget &lhs,const UdpTarget &rhs) +{ + // need to compare all the members of a UdpTarget + if ( lhs.read_community_ != rhs.read_community_) + return false; // != + + if ( lhs.write_community_ != rhs.write_community_) + return false; // != + + if ( lhs.udp_address_ != rhs.udp_address_) + return false; + + if ( lhs.timeout_ != rhs.timeout_) + return false; + + if ( lhs.retries_ != rhs.retries_) + return false; + + return true; // they are equal +} diff --git a/ACE/ASNMP/asnmp/target.h b/ACE/ASNMP/asnmp/target.h new file mode 100644 index 00000000000..084088e5f4f --- /dev/null +++ b/ACE/ASNMP/asnmp/target.h @@ -0,0 +1,260 @@ + + +#ifndef TARGET_ +#define TARGET_ +//============================================================================= +/** + * @file target.h + * + * $Id$ + * + * @brief + * + * @author Peter E Mellquist Michael R. MacFaden (ported to ACE) + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS" without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//----[ includes ]------------------------------------------------ +#include "ace/INET_Addr.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/address.h" +#include "asnmp/oid.h" +#include "asnmp/octet.h" + +//----[ enumerated types for SNMP versions ]------------------------- +enum snmp_version { + version1, // 0 + version2c, // 1 (Cisco IOS does not have IOS v2c agent available yet) + version3 // 2 (IETF working on this version) +}; + +// targets contain the following default properties +enum ASNMP_Defs { + DEF_TIMEOUT = 1, // unit: seconds + DEF_RETRIES = 1, // no retry default + DEF_MAX_SNMP_PACKET = 1430, // maximum pdu len on the wire (eth mtu-ip hdr) + // split bigger pdus (not implemented yet) + DEF_AGENT_PORT = 161, // port # for SNMP agent + DEF_TRAP_PORT = 162, // port # for SNMP trap receiver + DEF_VERSION = version1, // default SNMP version + MAX_COMM_STR_LEN = 255, // max value this impl will accept from client + MAX_TARGET_STRING_REP = 2048 // max value this impl will accept from client +}; + +#define READ_COMM_STR "public" +#define WRITE_COMM_STR "private" + +// Abstract class used to provide a virtual interface into Targets +// +/** + * @class SnmpTarget + * + * @brief Abstract Base class SnmpTarget is used to Collect all transmission + * details to communicate with an SNMP + */ +class ASNMP_Export SnmpTarget +{ + public: + + /// allow destruction of derived classes + virtual ~SnmpTarget(); + + /// return validity of target + int valid() const; + + /// set the retry value + void set_retry( const int r); + + /// set the object's timeout (in seconds) + void set_timeout( const unsigned long t); + + /// set the instance version + void set_version( const snmp_version v); + + /// all classes constructed will have this write community string + void set_max_pdu_size(const unsigned long max_pdu_sz); + + /// change the "class" default default timeout (in seconds) + void set_default_timeout( const unsigned long t); + + /// change the default send retries + void set_default_retry( const int r); + + /// all classes constructed will have this write community string + void set_default_max_pdu_size(const unsigned long max_pdu_sz); + + /// change class default + void set_default_version( const snmp_version v); + + // *** get methods *** + + /// get the retry value + int get_default_retry() const; + + /// get the timeout (seconds) + unsigned long get_timeout() const; + + /// get instance max buffer size + unsigned long get_max_pdu_size() const; + + /// all classes constructed will have this write community string + void get_default_max_pdu_size(const unsigned long max_pdu_sz); + + /// get the version + snmp_version get_version() const; + + snmp_version get_default_version() const; + + /// return send retry number for this instancd + int get_retry() const; + + /** + * virtual clone operation for creating a new SnmpTarget from an existing + * SnmpTarget. The caller MUST use the delete operation on the return + * value when done. + */ + virtual SnmpTarget *clone() const = 0; + + /// manipulate the base part + friend bool operator==(const SnmpTarget& lhs, const SnmpTarget& rhs); + + SnmpTarget& operator=(const SnmpTarget& lhs); + + protected: + /// SnmpTarget(const SnmpTarget &); + SnmpTarget(); + + /// used by derived class instances + int validity_; + + /// instance value xmit timeout in milli secs + unsigned long timeout_; + + /// instance value number of retries + int retries_; + + /// size of pdu + unsigned max_pdu_size_; + + /// instance value the snmp version + snmp_version version_; + + // class wide default values + /// xmit timeout in secs + static unsigned long default_timeout_; + + /// number of retries + static int default_retries_; + + /// snmp protocol version + static unsigned long default_max_pdu_size_; + static snmp_version default_version_; +}; + +//----[ UdpTarget class ]---------------------------------------------- +// UDP/IP transport using "community string" based agents (targets) +// +/** + * @class UdpTarget + * + * @brief Concrete class UdpTarget contains all Details for communicating + * with a SNMPv1 agent over UDP/IPv4 transport + */ +class ASNMP_Export UdpTarget : public SnmpTarget +{ + public: + UdpTarget(); + + /** + * constructor with only address + * assumes default as public, public + * can be constructed with IP address object + */ + UdpTarget( const UdpAddress& udp); + + /// can be constructed with Udp address object TODO: merge addresses + UdpTarget( ACE_INET_Addr& ace_inet_addr); + + /// destructor + ~UdpTarget(); + + // ** set *** + + /// set the read community using an OctetStr + void set_read_community( const OctetStr& new_read_community); + + /// set the write community using an OctetStr + void set_write_community( const OctetStr& write_community); + + /// set the address + int set_address( UdpAddress &udp_address); + + // ** get *** + + /// get the read community as an Octet Str object + void get_read_community( OctetStr& read_community_oct) const; + + /// get the write community as an OctetStr + void get_write_community( OctetStr &write_community_oct) const; + + /// get the address + void get_address( UdpAddress& address) const; + + /// all classes constructed will have this read community string + void set_default_read_community(const OctetStr& rd_community); + + /// all classes constructed will have this write community string + void set_default_write_community(const OctetStr& wr_community); + + /// all classes constructed will have this read community string + void get_default_read_community(OctetStr& rd_community) const; + + /// all classes constructed will have this write community string + void get_default_write_community(OctetStr& wr_community) const; + + /// overloaded assignment + UdpTarget& operator=( const UdpTarget& target); + + /// compare two C targets + friend bool operator==( const UdpTarget &lhs, const UdpTarget &rhs); + + /// string representation of object + const char *to_string(); + + /// clone from existing UdpTarget + SnmpTarget *clone() const; + + protected: + static OctetStr default_rd_community_; + static OctetStr default_wr_community_; + OctetStr read_community_; + OctetStr write_community_; + UdpAddress udp_address_; + snmp_version version_; + + /// to_string() rep of data + char output_buffer_[MAX_TARGET_STRING_REP]; +}; + + +#endif //TARGET_ diff --git a/ACE/ASNMP/asnmp/timetick.cpp b/ACE/ASNMP/asnmp/timetick.cpp new file mode 100644 index 00000000000..e6b2d0d2231 --- /dev/null +++ b/ACE/ASNMP/asnmp/timetick.cpp @@ -0,0 +1,144 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// timetick.cpp +// +// = DESCRIPTION +// Class implentation for SMI Timeticks class. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/timetick.h" // include header file for timetick class +#include "ace/OS_NS_stdio.h" + +ACE_RCSID(asnmp, timetick, "$Id$") + +// constructor with a value +TimeTicks::TimeTicks( const unsigned long i):SnmpUInt32(i) +{ + smival.syntax = sNMP_SYNTAX_TIMETICKS; +} + +// copy constructor +TimeTicks::TimeTicks( const TimeTicks &t) + : SnmpUInt32 (t) +{ + smival.value.uNumber = t.smival.value.uNumber; + smival.syntax = sNMP_SYNTAX_TIMETICKS; +} + +// destructor +TimeTicks::~TimeTicks() +{ +} + +// syntax type +SmiUINT32 TimeTicks::get_syntax() +{ + return sNMP_SYNTAX_TIMETICKS; +} + +// create a new instance of this Value +SnmpSyntax *TimeTicks::clone() const +{ + return (SnmpSyntax *) new TimeTicks(*this); +} + +// overloaded assignement from ulong +TimeTicks& TimeTicks::operator=( const unsigned long int i) +{ + smival.value.uNumber =i; return *this; +} + +// overloaded assignment from TimeTicks +TimeTicks& TimeTicks::operator=( const TimeTicks &uli) +{ + this->smival.value.uNumber = uli.smival.value.uNumber; return *this; +} + +// general assignment from any Value +SnmpSyntax& TimeTicks::operator=( SnmpSyntax &in_val) +{ + if ( this == &in_val ) // handle assignement from itself + return *this; + + valid_flag = 0; // will get set true if really valid + if (in_val.valid()) { + switch (in_val.get_syntax()) { + case sNMP_SYNTAX_UINT32: + // case sNMP_SYNTAX_GAUGE32: .. indistinquishable from UINT32 + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_TIMETICKS: + case sNMP_SYNTAX_INT32: // implied cast int -> uint + this->smival.value.uNumber = + ((TimeTicks &)in_val).smival.value.uNumber; + valid_flag = 1; + break; + } + } + return *this; +} + +// otherwise, behave like an unsigned long +TimeTicks::operator unsigned long() +{ + return smival.value.uNumber; +} + + +// ASCII format return +const char * TimeTicks::to_string() + /* Should do something nicer like days:hours:minutes... */ +{ + unsigned long tt, hseconds, seconds, minutes, hours, days; + tt = this->smival.value.uNumber; + + // days + days = tt / 8640000; + tt %= 8640000; + + // hours + hours = tt / 360000; + tt %= 360000; + + // minutes + minutes = tt / 6000; + tt %= 6000; + + seconds = tt / 100; + tt %= 100; + + hseconds = tt; + + if ( days ==0) + sprintf( output_buffer,"%ld:%02ld:%02ld.%02ld", hours, minutes,seconds,hseconds); + else if ( days==1) + sprintf( output_buffer,"1 day %ld:%02ld:%02ld.%02ld", hours, minutes,seconds,hseconds); + else + sprintf( output_buffer,"%ld days, %ld:%02ld:%02ld.%02ld", days,hours, minutes,seconds,hseconds); + + return output_buffer; +} diff --git a/ACE/ASNMP/asnmp/timetick.h b/ACE/ASNMP/asnmp/timetick.h new file mode 100644 index 00000000000..ca52a3e1d9d --- /dev/null +++ b/ACE/ASNMP/asnmp/timetick.h @@ -0,0 +1,85 @@ +/* -*-C++-*- */ +#ifndef TIMETICKS_ +#define TIMETICKS_ +//============================================================================= +/** + * @file timetick.h + * + * $Id$ + * + * Class definition for SMI Timeticks class. + * + * + * @author Michael R. MacFaden <mrm@cisco.com> + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/integer.h" + +#define TICKOUTBUF 30 // max formatted time string + +//------------[ TimeTicks Class ]----------------------------------- +// The timeticks class allows all the functionality of unsigned +// integers but is recognized as a distinct SMI type. TimeTicks +// objects may be get or set into Vb objects. +// +/** + * @class TimeTicks + * + * @brief Define RFC1155 TimeTicks Data object + */ +class ASNMP_Export TimeTicks : public SnmpUInt32 + +{ + + public: + TimeTicks( const unsigned long i = 0); + + /// copy constructor + TimeTicks( const TimeTicks &t); + + /// destructor + ~TimeTicks(); + + /// syntax type + SmiUINT32 get_syntax(); + + /// get a printable ASCII value + const char *to_string(); + + /// create a new instance of this Value + SnmpSyntax *clone() const; + + /// copy an instance of this Value + SnmpSyntax& operator=(SnmpSyntax &val); + + /// overloaded assignment + TimeTicks& operator=( const TimeTicks &uli); + + /// overloaded assignment + TimeTicks& operator=( const unsigned long int i); + + /// otherwise, behave like an unsigned long + operator unsigned long(); + + protected: + /// for storing printed form + char output_buffer[TICKOUTBUF]; +}; +#endif // TIMETICKS_ diff --git a/ACE/ASNMP/asnmp/transaction.cpp b/ACE/ASNMP/asnmp/transaction.cpp new file mode 100644 index 00000000000..2f29cf79544 --- /dev/null +++ b/ACE/ASNMP/asnmp/transaction.cpp @@ -0,0 +1,207 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// transaction.cpp +// +// = DESCRIPTION +// implements blocking SNMPv1 API using a simple state machine +// transactions over UDP/IP networks +// +// = AUTHOR +// Michael R MacFaden mrm@cisco.com - remove v2c, async, rework for ACE +// ============================================================================ + +#include "ace/Reactor.h" +#include "asnmp/transaction.h" +#include "ace/OS_NS_string.h" + +ACE_RCSID(asnmp, transaction, "$Id$") + +// pre: pdu, target report valid() == 1 +// post: pdu sent out over the wire +inline void reset_receive_buffer(iovec& io) +{ + io.iov_base = 0; + io.iov_len = 0; +} + +transaction::transaction(const Pdu& pdu, const UdpTarget& target, + ACE_SOCK_Dgram& io): + result_(0), + wp_(pdu,target), params_(target), session_(io) +{ + // last step, convert address (get ride of this once we have merged address + UdpAddress udp; + target.get_address(udp); + // via string conversion "dotted-quad:port" + ACE_INET_Addr tmp(udp); + addr_ = tmp; + reset_receive_buffer(receive_iovec_); +} + +transaction::~transaction() +{ + ACE_Reactor::instance()->remove_handler(this, READ_MASK | DONT_CALL); + ACE_Reactor::instance()->cancel_timer(this); + + delete [] (char *) receive_iovec_.iov_base; +} + +// implement state machine, send, wait (timeout/results) return +int transaction::run() +{ + int rc, done = 0; + int retry_counter = 0; + ACE_Time_Value to(params_.get_timeout(), 0); // seconds + ACE_Reactor *reactor = ACE_Reactor::instance (); + + // 1. register io port for read access + if (reactor->register_handler(session_.get_handle(), this, + ACE_Event_Handler::READ_MASK) == -1) + return SNMP_CLASS_INTERNAL_ERROR; + + // register a time handler and a socket with this + + while (!done) { + + if ((rc = send()) < 0) // send pkt to agent + return rc; + else { + if (retry_counter++ > params_.get_retry()) + return SNMP_CLASS_TIMEOUT; + } + + // 2. wait for events (timeout, returned msg) + if (( rc = reactor->handle_events (to)) == 1) // one handler registered + return 0; + else { + if (rc == 0) { + to.set(params_.get_timeout(), 0); + } + else + return SNMP_CLASS_INTERNAL_ERROR; + } + } + return SNMP_CLASS_INTERNAL_ERROR; +} + +// implement state machine, send, wait (timeout/results) return +int transaction::run(transaction_result * r) +{ + result_ = r; + int rc; + + // 1. register io port for read access + ACE_Reactor * reactor = ACE_Reactor::instance(); + if (reactor->register_handler(session_.get_handle(), + this, + READ_MASK) == -1) + return SNMP_CLASS_INTERNAL_ERROR; + + retry_counter_ = 0; + + // register a time handler and a socket with this + ACE_Time_Value to (params_.get_timeout()); + if (reactor->schedule_timer(this, 0, to, to) < 0) + return SNMP_CLASS_INTERNAL_ERROR; + + if ((rc = send()) < 0) // send pkt to agent + return rc; + return 0; +} + +// got back response from SNMPv1 agent - process it +int transaction::handle_input (ACE_HANDLE) +{ + // OS allocates iovec_.iov_base ptr and len + delete [] (char*) receive_iovec_.iov_base; + reset_receive_buffer(receive_iovec_); + int rc = session_.recv(&receive_iovec_, receive_addr_, 0); + if (rc == -1) + { + delete [] (char*) receive_iovec_.iov_base; + reset_receive_buffer(receive_iovec_); + if (result_) + result_->result(this, SNMP_CLASS_RESOURCE_UNAVAIL); + return SNMP_CLASS_RESOURCE_UNAVAIL; + } + if (result_) + result_->result(this, rc); + + return 0; +} + +int transaction::handle_timeout(const ACE_Time_Value &, + const void *) +{ + if (send() < 0) // send pkt to agent + result_->result(this, 0); + else + if (retry_counter_++ > params_.get_retry()) + result_->result(this, SNMP_CLASS_TIMEOUT); + + return 0; +} + + +const ACE_INET_Addr& transaction::get_from_addr() const +{ + return receive_addr_; +} + + +// return pdu to caller +int transaction::result(Pdu& pdu, char *comm_str, ACE_INET_Addr *from) +{ + // TODO: check to see the sender matches the receiver address.. + + // remove any vbs existing in this pdu + pdu.delete_all_vbs(); + + // any data to return? + if (receive_iovec_.iov_len == 0) + return -1; + + wpdu tmp(receive_iovec_); + + snmp_version ver; + + // return comm str and from address of incomming pdu if requested + int rc = tmp.get_pdu(pdu, ver); + if (comm_str) + ACE_OS::strcpy(comm_str, (char *)tmp.get_community()); + if (from) + *from = receive_addr_; + return rc; +} + +transaction::transaction(ACE_SOCK_Dgram& io) +: result_(0), session_(io) +{ + reset_receive_buffer(receive_iovec_); +} + + +int transaction::send() +{ + iovec io = wp_.get_buffer(); + if (io.iov_len == 0) { + // NO DATA ? + return -1; + } + ssize_t rc = session_.send (io.iov_base, io.iov_len, addr_ , 0); + return rc; +} + +transaction_result::~transaction_result() {} + +ACE_HANDLE +transaction::get_handle () const +{ + return session_.get_handle (); +} diff --git a/ACE/ASNMP/asnmp/transaction.h b/ACE/ASNMP/asnmp/transaction.h new file mode 100644 index 00000000000..d114bd40d1f --- /dev/null +++ b/ACE/ASNMP/asnmp/transaction.h @@ -0,0 +1,83 @@ +/* -*-C++-*- */ +#ifndef TRANSACTION_ +#define TRANSACTION_ +//============================================================================= +/** + * @file transaction.h + * + * $Id$ + * + * @brief + * + * @author Michael R. MacFaden port to ACE / use Reactor pattern + */ +//============================================================================= + + +#include "ace/Event_Handler.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/target.h" +#include "asnmp/pdu.h" +#include "asnmp/transaction_result.h" +#include "asnmp/wpdu.h" // cmu adapter class +#include "ace/SOCK_Dgram.h" + +/** + * @class transaction + * + * @brief Used to manage the details of a particular transaction betwen + * two SNMP agents. Uses SnmpTarget class to implement retry/timeout + */ +class ASNMP_Export transaction : public ACE_Event_Handler + +{ + int retry_counter_; + transaction_result * result_; + +public: + /// constructor + /// destructor + transaction(const Pdu& pdu, const UdpTarget& target, ACE_SOCK_Dgram& io); + transaction(ACE_SOCK_Dgram& io); + ~transaction(); + + /// begin polling for values + int run(); + int run(transaction_result *r); // Async interface, with callback object + + /// return pdu with result from agent after run() is completed rc = 0 + /// optionally get community str + int result(Pdu& pdu, char *comm_str = 0, ACE_INET_Addr *from_addr = 0); + + /// called by reactor when data is ready to be read in from OS memory + /// used for resend in asynchronous run() + virtual int handle_input (ACE_HANDLE fd); + virtual int handle_timeout (const ACE_Time_Value &, const void *); + + /// transmit buffer command to network... + int send(); + + /// pre: handle_input called + /// retrieve the sender's from address from the last pkt + const ACE_INET_Addr& get_from_addr() const; + + /// Return session_ handle. + ACE_HANDLE get_handle () const; + +private: + /// disallow copy construction + transaction(const transaction&); + + wpdu wp_; // wire pdu + UdpTarget params_; // params + ACE_INET_Addr addr_; // to address + ACE_SOCK_Dgram session_; // io object + iovec receive_iovec_; // receive buffer + ACE_INET_Addr receive_addr_; // from address +}; + +#endif // TRANSACTION_ diff --git a/ACE/ASNMP/asnmp/transaction_result.h b/ACE/ASNMP/asnmp/transaction_result.h new file mode 100644 index 00000000000..9ea94c60e8e --- /dev/null +++ b/ACE/ASNMP/asnmp/transaction_result.h @@ -0,0 +1,26 @@ +/* -*-C++-*- */ +#ifndef TRANSACTION_RESULT_H_ +#define TRANSACTION_RESULT_H_ +//============================================================================= +/** + * @file transaction_result.h + * + * $Id$ + * + * An object respresenting a request/reply operation between mgr/agent + * + * + * @author Michael R. MacFaden + */ +//============================================================================= + + +class transaction; +class ASNMP_Export transaction_result +{ + public: + virtual ~transaction_result(); + virtual void result(transaction * trans, int) = 0; +}; + +#endif diff --git a/ACE/ASNMP/asnmp/vb.cpp b/ACE/ASNMP/asnmp/vb.cpp new file mode 100644 index 00000000000..4e94b5e81b9 --- /dev/null +++ b/ACE/ASNMP/asnmp/vb.cpp @@ -0,0 +1,399 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// asnmp +// +// = FILENAME +// vb.h +// +// = DESCRIPTION +// The Vb class is an encapsulation of the snmp variable binding. +// This module contains the class definition for the variable binding (VB) +// class. The VB class is an encapsulation of a SNMP VB. A VB object is +// composed of one SNMP++ Oid and one SMI value. The Vb class utilizes Oid +// objects and thus requires the Oid class. To use this class, +// set oid, value then call valid() to be sure object was constructed correctly. +// +// = AUTHOR +// Peter E Mellquist +// Michael R MacFaden mrm@cisco.com - rework & ACE port +// ============================================================================ +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +#include "asnmp/oid.h" // include oid class defs +#include "asnmp/vb.h" // include vb class defs +#include "asnmp/snmperrs.h" // error codes +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_Memory.h" + +ACE_RCSID(asnmp, vb, "$Id$") + +//---------------[ Vb::Vb( void) ]-------------------------------------- +// constructor with no arguments +// makes an vb, unitialized +Vb::Vb( void): output_(0), iv_vb_value_(0), + exception_status_(SNMP_CLASS_SUCCESS) +{ +} + +//---------------[ Vb::Vb( const Oid &oid) ]----------------------------- +// constructor to initialize the oid +// makes a vb with oid portion initialized +Vb::Vb( const Oid &oid): output_(0), iv_vb_oid_(oid), iv_vb_value_(0), + exception_status_(SNMP_CLASS_SUCCESS) +{ +} + +//---------------[ Vb::Vb( const Oid &oid, const SmiSyntax &val) ]------- +Vb::Vb( const Oid &oid, const SnmpSyntax &val, const SmiUINT32 status): + output_(0), iv_vb_oid_(oid), iv_vb_value_(0), exception_status_(status) +{ + // iv_vb_value_ = recast_smi_object(val); // allocate and construct object + iv_vb_value_ = val.clone(); +} + +//---------------[ Vb::Vb( const Vb &vb) ]----------------------------- +// copy constructor +Vb::Vb( const Vb &vb): output_(0), iv_vb_value_(0) +{ + *this = vb; +} + +//---------------[ Vb::~Vb() ]------------------------------------------ +// destructor +// if the vb has a oid or an octect string then +// the associated memory needs to be freed +Vb::~Vb() +{ + free_vb(); + delete [] output_; // formatting buffer if it exists +} + + +//--------------[ Vb::valid() ]----------------------------------------- +// returns validity of a Vb object +// must have a valid oid and value +int Vb::valid() const +{ + if ( iv_vb_oid_.valid() && (iv_vb_value_ && iv_vb_value_->valid()) ) + return 1; + else + return 0; +} + + +//---------------[ Vb& Vb::operator=( const Vb &vb) ]-------------------- +// overloaded assignment allows assigning one Vb to another +// this involves deep memory thus target vb needs to be freed +// before assigning source +Vb& Vb::operator=( const Vb &vb) +{ + free_vb(); // free up target to begin with + + //-----[ reassign the Oid portion 1st ] + vb.get_oid( iv_vb_oid_); + + //-----[ next set the vb value portion ] + if (vb.iv_vb_value_ == 0) { + iv_vb_value_ = 0; + } + else { + iv_vb_value_ = vb.iv_vb_value_->clone(); + } + exception_status_ = vb.exception_status_; + + return *this; // return self reference +} + + // set a Vb null, if its not already +void Vb::set_null() +{ + free_vb(); +} + +//---------------[ Vb::set_oid( const Oid oid ) ]----------------------- +// set value oid only with another oid +void Vb::set_oid( const Oid& oid) +{ + iv_vb_oid_ = oid; +} + +//---------------[ Vb::get_oid( Oid &oid) ]----------------------------- +// get oid portion +void Vb::get_oid( Oid &oid) const +{ + oid = iv_vb_oid_; +} + +//----------------[ void Vb::free_vb() ]-------------------------------- +// protected method to free memory +// this methos is used to free memory when assigning new vbs +// or destructing +// in the case of oids and octets, we need to do a deep free +void Vb::free_vb() +{ + if (iv_vb_value_) + delete iv_vb_value_; + exception_status_ = SNMP_CLASS_SUCCESS; + iv_vb_value_ = 0; +} + +void Vb::set_value( const SnmpInt32& i) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new SnmpInt32(i); +} + +void Vb::set_value( const SnmpUInt32& u) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new SnmpUInt32(u); +} + +void Vb::set_value( const Gauge32& g) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new Gauge32(g); +} + +void Vb::set_value( const Counter32& c) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new Counter32(c); +} + +void Vb::set_value( const Counter64& c) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new Counter64(c); +} + +void Vb::set_value( const TimeTicks& t) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new TimeTicks(t); +} + +void Vb::set_value( const OctetStr& s) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new OctetStr(s); +} + +void Vb::set_value( const Oid& o) +{ + free_vb(); + iv_vb_value_ = (SnmpSyntax *)new Oid(o); +} + +void Vb::set_value ( const SnmpSyntax &val) +{ + free_vb(); + iv_vb_value_ = val.clone(); +} + +int Vb::get_value( SnmpInt32 &i) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + (iv_vb_value_->get_syntax() == sNMP_SYNTAX_INT32 )) { + i = *((SnmpInt32 *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + +int Vb::get_value( SnmpUInt32 &u) +{ + if (iv_vb_value_ && iv_vb_value_->valid()) + { + SmiUINT32 syntax = iv_vb_value_->get_syntax(); + if (syntax == sNMP_SYNTAX_GAUGE32 || + syntax == sNMP_SYNTAX_CNTR32 || + syntax == sNMP_SYNTAX_TIMETICKS || + syntax == sNMP_SYNTAX_UINT32) + { + u = *((SnmpUInt32 *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + } + return SNMP_CLASS_INVALID; +} + +/* return a uint or a gauge. this is casting, but no semantic difference + * at this level + */ +int Vb::get_value( Gauge32 &g) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + ((iv_vb_value_->get_syntax() == sNMP_SYNTAX_GAUGE32) || + iv_vb_value_->get_syntax() == sNMP_SYNTAX_UINT32) ) { + g = *((Gauge32 *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + +int Vb::get_value( Counter32 &c) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + (iv_vb_value_->get_syntax() == sNMP_SYNTAX_CNTR32 )) { + c = *((Counter32 *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + +int Vb::get_value( Counter64 &c) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + (iv_vb_value_->get_syntax() == sNMP_SYNTAX_CNTR64 )) { + c = *((Counter32 *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + +int Vb::get_value( TimeTicks &t) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + (iv_vb_value_->get_syntax() == sNMP_SYNTAX_TIMETICKS )) { + t = *((TimeTicks *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + +int Vb::get_value( OctetStr &s) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + (iv_vb_value_->get_syntax() == sNMP_SYNTAX_OCTETS )) { + s = *((OctetStr *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + +int Vb::get_value( Oid &s) +{ + if (iv_vb_value_ && + iv_vb_value_->valid() && + (iv_vb_value_->get_syntax() == sNMP_SYNTAX_OID )) { + s = *((Oid *) iv_vb_value_); + return SNMP_CLASS_SUCCESS; + } + else + return SNMP_CLASS_INVALID; +} + + +//---------------[ Vb::get_value( Value &val) ]-------- +int Vb::get_value( SnmpSyntax &val) +{ + if (iv_vb_value_) { + val = *iv_vb_value_; + if (val.valid()) + return SNMP_CLASS_SUCCESS; + else + return SNMP_CLASS_INVALID; + } + else + { +//TM: should set val to be invalid + return SNMP_CLASS_INVALID; + } +} + + + +//-----[ misc]-------------------------------------------------------- + +// return the current syntax +// This method violates Object Orientation but may be useful if +// the caller has a vb object and does not know what it is. +// This would be useful in the implementation of a browser. +SmiUINT32 Vb::get_syntax() +{ + if ( exception_status_ != SNMP_CLASS_SUCCESS) + return exception_status_; + else + return ( iv_vb_value_ ? iv_vb_value_->get_syntax() : sNMP_SYNTAX_NULL); +} + +// return the printabel value +const char *Vb::to_string_value() +{ + if (iv_vb_value_) + return iv_vb_value_->to_string(); + else + return ""; +} + +// return the printable oid +const char *Vb::to_string_oid() +{ + return iv_vb_oid_.to_string(); +} + +// generate string with name/ value format +const char *Vb::to_string() +{ + int len = ACE_OS::strlen(iv_vb_oid_.to_string()); + const char *ptr = iv_vb_value_ ? iv_vb_value_->to_string() : ""; + len += ACE_OS::strlen(ptr) + 3 + 1; // " / " + null + ACE_NEW_RETURN(output_, char[len], ""); + ACE_OS::sprintf(output_, "%s / %s", iv_vb_oid_.to_string(), ptr); + return output_; +} + +// friend function to set exception status +void set_exception_status( Vb *vb, const SmiUINT32 status) +{ + vb->exception_status_ = status; +} + +// equivlence operator overloaded +// hack, by side effect, compare based on string formatting output_ +bool operator==( const Vb &lhs, const Vb &rhs) +{ + if ( lhs.iv_vb_oid_ != rhs.iv_vb_oid_) + return false; + + if (lhs.iv_vb_value_ != 0 && rhs.iv_vb_value_ != 0) + { + const int val = + ACE_OS::strcmp (lhs.iv_vb_value_->to_string(), + rhs.iv_vb_value_->to_string()); + return !val; + } + else + return false; +} diff --git a/ACE/ASNMP/asnmp/vb.h b/ACE/ASNMP/asnmp/vb.h new file mode 100644 index 00000000000..b82adb2bc0e --- /dev/null +++ b/ACE/ASNMP/asnmp/vb.h @@ -0,0 +1,207 @@ + + +#ifndef VB_CLS_ +#define VB_CLS_ +//============================================================================= +/** + * @file vb.h + * + * $Id$ + * + * This module contains the class definition for the variable binding (VB) + * class. The VB class is an encapsulation of a SNMP VB. A VB object is + * composed of one SNMP++ Oid and one SMI value. The Vb class utilizes Oid + * objects and thus requires the Oid class. To use this class, + * set oid, value then call valid() to be sure object was constructed correctly. + * + * + * @author Peter E Mellquist + */ +//============================================================================= + +/*=================================================================== + Copyright (c) 1996 + Hewlett-Packard Company + + ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + Permission to use, copy, modify, distribute and/or sell this software + and/or its documentation is hereby granted without fee. User agrees + to display the above copyright notice and this license notice in all + copies of the software and any documentation of the software. User + agrees to assume all liability for the use of the software; Hewlett-Packard + makes no representations about the suitability of this software for any + purpose. It is provided "AS-IS without warranty of any kind,either express + or implied. User hereby grants a royalty-free license to any and all + derivatives based upon this software code base. +=====================================================================*/ + +//----[ external calls ]---------------------------------------------- +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/smival.h" +#include "asnmp/snmperrs.h" // V2c error def +#include "asnmp/oid.h" // oid class def +#include "asnmp/timetick.h" // time ticks +#include "asnmp/counter.h" // counter +#include "asnmp/gauge.h" // gauge class +#include "asnmp/ctr64.h" // 64 bit counters +#include "asnmp/octet.h" // octet class +#include "asnmp/address.h" // address class def +#include "asnmp/integer.h" // integer class + + +//------------[ VB Class Def ]------------------------------------- +// The Vb class is the encapsulation of the SNMP variable binding. +// Variable binding lists in SNMP++ are represented as arrays of +// Vb objects. Vb objects are passed to and from SNMP objects to +// provide getting or setting MIB values. +// The vb class keeps its own memory for objects and does not +// utilize pointers to external data structures. +// +/** + * @class Vb + * + * @brief Implement the concrete Variable Bindings aka Varbind + * composite type. Varbinds hold 1 Oid and 1 Value (Any SMI value) + */ +class ASNMP_Export Vb +{ +public: + /// constructor with no arguments + /// makes an vb, unitialized (does not make object valid) + Vb( void); + + /// constructor to initialize the oid + /// makes a vb with oid portion initialized (does not make object valid) + Vb( const Oid &oid); + + /// constructor to initialize the oid + /// makes a vb with oid portion and value portion initialized, (valid) + Vb( const Oid& vb, const SnmpSyntax &val, const SmiUINT32=SNMP_CLASS_SUCCESS); + + /// copy constructor + Vb( const Vb &vb); + + /** + * destructor + * if the vb has a oid or an octect string then + * the associated memory needs to be freed + */ + ~Vb(); + + /// return validity of Vb object (both oid and value set return 1 else 0) + int valid() const; + + /// assignment to another Vb object overloaded + Vb& operator=( const Vb &vb); + + /// equivlence operator overloaded + friend ASNMP_Export bool operator==( const Vb &lhs, const Vb &rhs); + + //-----[ set oid / get oid part]------------------------------------------ + + /// set value oid only with another oid + void set_oid( const Oid& oid); + + /// get oid portion + void get_oid( Oid &oid) const; + + //-----[ set value part]-------------------------------------------------- + + /// set a Vb null, if its not already + void set_null(); + + /// returns 0 on success and a value + void set_value( const TimeTicks& ticks); + + /// returns 0 on success and a value + void set_value( const Oid& oid); + + /// returns 0 on success and a value + void set_value( const Counter32& ctr); + + /// returns 0 on success and a value + void set_value( const Counter64& ctr); + + /// returns 0 on success and a value + void set_value( const Gauge32& ctr); + + /// returns 0 on success and a value + void set_value( const SnmpUInt32& ctr); + + /// returns 0 on success and a value + void set_value( const SnmpInt32& ctr); + + /// get an octet string object + void set_value( const OctetStr& oct_str); + + //----[ get value ]------------------------------------------------ + + /// returns 0 on success and a value + int get_value( TimeTicks& ticks); + + /// returns 0 on success and a value + int get_value( Oid& oid); + + /// returns 0 on success and a value + int get_value( Counter32& ctr); + + /// returns 0 on success and a value + int get_value( Counter64& ctr); + + /// returns 0 on success and a value + int get_value( Gauge32& ctr); + + /// returns 0 on success and a value + int get_value( SnmpUInt32& ctr); + + /// returns 0 on success and a value + int get_value( SnmpInt32& ctr); + + /// get an octet string object + int get_value( OctetStr& oct_str); + + // escape hatch + /// for other derived types that can be casted + void set_value( const SnmpSyntax &val); + + /// gets a general value + int get_value( SnmpSyntax &val); + + /// return the current syntax + /// Or.. if a V2 VB exception is present then return the exception value + SmiUINT32 get_syntax(); + + /// set the exception status + friend ASNMP_Export void set_exception_status( Vb *vb, const SmiUINT32 status); + + /// return fomatted version of this object + const char *to_string(); + + /// returns a formatted version of the value + const char *to_string_value(); + + /// returns a formatted version of the value + const char *to_string_oid(); + +protected: + /// display vb as [ oid / value ] + char *output_; + + /// a vb is made up of a oid + Oid iv_vb_oid_; + + /// and a value... + SnmpSyntax *iv_vb_value_; + + /// are there any vb exceptions?? + SmiUINT32 exception_status_; + + void free_vb(); +}; + +#endif // VB_CLS_ diff --git a/ACE/ASNMP/asnmp/wpdu.cpp b/ACE/ASNMP/asnmp/wpdu.cpp new file mode 100644 index 00000000000..d05a750970f --- /dev/null +++ b/ACE/ASNMP/asnmp/wpdu.cpp @@ -0,0 +1,521 @@ +// $Id$ + +// ============================================================================ +// = LIBRARY +// asnmp +// +// = FILENAME +// wpdu.cpp +// +// = DESCRIPTION +// Adapter class. Converts between raw wire format and Pdu objects +// that can be stuffed out a I/O port or reconstructed +// +// = AUTHOR +// Michael R. MacFaden rework the class api and impl using ACE +// Peter E Mellquist implementation/code from snmp++ snmpmsg class +// +// ============================================================================ + +#include "asnmp/wpdu.h" +#include <ace/Log_Msg.h> +#include "ace/OS_NS_string.h" + +#define DEFINE_TRAP_CONSTANTS_ +#include "asnmp/enttraps.h" + +ACE_RCSID(asnmp, wpdu, "$Id$") + +#define MAX_COMM_STR_LEN 255 +#define V1_COLD_START 0 +#define V1_WARM_START 1 +#define V1_LINK_DOWN 2 +#define V1_LINK_UP 3 +#define V1_AUTH_FAILURE 4 +#define V1_EGP_NEIGHBOR_LOSS 5 +#define V1_ENT_SPECIFIC 6 + +inline +void reset_iov(iovec& iov) +{ + iov.iov_base = 0; + iov.iov_len = 0; +} + +wpdu::wpdu(const Pdu& pdu, const UdpTarget& target): + valid_flag_(SNMP_CLASS_INVALID ), comm_len(MAX_COMM_STR_LEN) +{ + reset_iov(iovec_); + version_ = target.get_version(); + int status; + OctetStr comm_str; + + community_name[0] = 0; + + snmp_pdu *raw_pdu; // create a raw pdu + raw_pdu = cmu_snmp::pdu_create( (int) pdu.get_type()); + if (!raw_pdu) { + valid_flag_ = SNMP_CLASS_RESOURCE_UNAVAIL; + return; + } + + raw_pdu->reqid = pdu.get_request_id(); + raw_pdu->errstat= (unsigned long) pdu.get_error_status(); + raw_pdu->errindex= (unsigned long) pdu.get_error_index(); + + switch (raw_pdu->command) { + case sNMP_PDU_GET: + case sNMP_PDU_GETNEXT: + target.get_read_community(comm_str); + break; + + case sNMP_PDU_SET: + target.get_write_community(comm_str); + break; + + case sNMP_PDU_V1TRAP: + target.get_read_community(comm_str); + if (set_trap_info(raw_pdu, pdu)) // will free raw_pdu + return; + break; + case sNMP_PDU_RESPONSE: + break; + + default: + ACE_ASSERT(0); + return; + } + + if (load_vbs(raw_pdu, pdu)) { + cmu_snmp::free_pdu( raw_pdu); + valid_flag_ = SNMP_CLASS_RESOURCE_UNAVAIL; + return; + } + + // TODO: determine how big raw_pdu serializes out to + iovec_.iov_len = target.get_max_pdu_size(); + ACE_NEW(iovec_.iov_base, char [iovec_.iov_len]); + + // create raw byte stream + status = cmu_snmp::build( raw_pdu, + (unsigned char *)iovec_.iov_base, + (int *) &iovec_.iov_len, + target.get_version(), + comm_str.data(), comm_str.length()); + if ( status != 0) { + valid_flag_ = SNMP_ERROR_WRONG_ENCODING; + cmu_snmp::free_pdu( raw_pdu); + return; + } + + cmu_snmp::free_pdu( raw_pdu); + valid_flag_ = SNMP_CLASS_SUCCESS; +} + +int wpdu::set_trap_info(snmp_pdu *raw_pdu, const Pdu& pdu) const +{ + Oid enterprise; + Oid trapid; // validate caller has set this correctly + pdu.get_notify_id( trapid); + if ( !trapid.valid() || trapid.length() < 2 ) { + cmu_snmp::free_pdu( raw_pdu); + return SNMP_CLASS_INVALID_NOTIFYID; + } + + + raw_pdu->specific_type=0; + + // TODO: object should emit numeric instead of this kind of mess... + if ( trapid == coldStart) + raw_pdu->trap_type = V1_COLD_START; // cold start + else if ( trapid == warmStart) + raw_pdu->trap_type = V1_WARM_START; // warm start + else if( trapid == linkDown) + raw_pdu->trap_type = V1_LINK_DOWN; // link down + else if ( trapid == linkUp) + raw_pdu->trap_type = V1_LINK_UP; // link up + else if ( trapid == authenticationFailure ) + raw_pdu->trap_type = V1_AUTH_FAILURE; // authentication failure + else if ( trapid == egpNeighborLoss) + raw_pdu->trap_type = V1_EGP_NEIGHBOR_LOSS; // egp neighbor loss + else { + raw_pdu->trap_type = V1_ENT_SPECIFIC; // enterprise specific + // last oid subid is the specific value + // if 2nd to last subid is "0", remove it + // enterprise is always the notify oid prefix + raw_pdu->specific_type = (int) trapid[(int) (trapid.length() - 1)]; + trapid.trim(1); + if ( trapid[(int)(trapid.length() - 1)] == 0 ) + trapid.trim(1); + enterprise = trapid; + } + + if ( raw_pdu->trap_type != V1_ENT_SPECIFIC) + pdu.get_notify_enterprise( enterprise); + if ( enterprise.length() > 0) { + // note!! To the contrary, enterprise OID val is + // copied here and raw_pdu->enterprise is freed in free_pdu + // as it should be (HDN) + // these are hooks into an SNMP++ oid + // and therefor the raw_pdu enterprise + // should not free them. null them out!! + SmiLPOID rawOid; + rawOid = enterprise.oidval(); + // HDN - enterprise is a local object, cannot simply assign pointer + //raw_pdu->enterprise = rawOid->ptr; + raw_pdu->enterprise_length = (int) rawOid->len; + ACE_NEW_RETURN(raw_pdu->enterprise, + oid[raw_pdu->enterprise_length],-1); + ACE_OS::memcpy((char *)raw_pdu->enterprise,(char *)rawOid->ptr, + raw_pdu->enterprise_length * sizeof(oid)); + } + + TimeTicks timestamp; + pdu.get_notify_timestamp( timestamp); + raw_pdu->time = ( unsigned long) timestamp; + + // HDN - set agent addr using the local hostname if possible + char localHostName[MAXHOSTNAMELEN]; + Snmp::get_host_name(localHostName, MAXHOSTNAMELEN); + if (ACE_OS::strlen(localHostName) > 0) { + GenAddress addr(localHostName); + OctetStr octet; + addr.to_octet(octet); + ACE_OS::memcpy(&(raw_pdu->agent_addr.sin_addr), + octet.data(), + octet.length()); + } + + return 0; +} + +wpdu::wpdu(const iovec& iov): valid_flag_(0),comm_len(MAX_COMM_STR_LEN) +{ + community_name[0] = 0; + reset_iov(iovec_); + version_ = version1; // TODO: figure where this should come from + ACE_NEW(iovec_.iov_base, char[iov.iov_len]); + if (!iovec_.iov_base) { + valid_flag_ = SNMP_CLASS_RESOURCE_UNAVAIL; + return; + } + + copy_iovec(iovec_, iov); + valid_flag_ = SNMP_CLASS_SUCCESS; +} + +wpdu::wpdu(): valid_flag_(0), comm_len(MAX_COMM_STR_LEN) +{ + community_name[0] = 0; + reset_iov(iovec_); + version_ = version1; // TODO: figure where this should come from +} + +int wpdu::valid() const +{ + return (valid_flag_ == SNMP_CLASS_SUCCESS); +} + +int wpdu::load_vbs(snmp_pdu *raw_pdu, const Pdu& pdu) +{ + int status = 0; + + // load up the payload + // for all Vbs in list, add them to the pdu + int vb_count; + Vb tempvb; + Oid tempoid; + SmiLPOID smioid; + SmiVALUE smival; + + vb_count = pdu.get_vb_count(); + + for (int z = 0; z < vb_count; z++) { + pdu.get_vb( tempvb, z); + tempvb.get_oid( tempoid); + smioid = tempoid.oidval(); + // what are we trying to convert here (vb oid part or value part) + status = convert_vb_to_smival( tempvb, &smival ); + if ( status != SNMP_CLASS_SUCCESS) + return status; + + // add the var to the raw pdu + cmu_snmp::add_var(raw_pdu, smioid->ptr, (int) smioid->len, &smival); + free_smival_descriptor( &smival); + } + + return status; +} + +// supports overlapped copies +// static +void wpdu::copy_iovec(iovec& dest, const iovec& src) +{ + if (&dest == &src) + return; + + ACE_OS:: memmove( dest.iov_base, src.iov_base, src.iov_len); + dest.iov_len = src.iov_len; +} + +int wpdu::convert_vb_to_smival( Vb &tempvb, SmiVALUE *smival ) +{ + smival->syntax = tempvb.get_syntax(); + + switch ( smival->syntax ) { + + case sNMP_SYNTAX_NULL: + break; + + // case sNMP_SYNTAX_INT32: + case sNMP_SYNTAX_INT: + { + SnmpInt32 tmp; + tempvb.get_value(tmp); + smival->value.sNumber = tmp; + } + break; + + // case sNMP_SYNTAX_UINT32: + case sNMP_SYNTAX_GAUGE32: + case sNMP_SYNTAX_CNTR32: + case sNMP_SYNTAX_TIMETICKS: + { + SnmpUInt32 tmp; + tempvb.get_value(tmp); + smival->value.uNumber = tmp; + } + break; + + // case Counter64 + case sNMP_SYNTAX_CNTR64: + { + Counter64 c64; + tempvb.get_value(c64); + smival->value.hNumber.hipart = c64.high(); + smival->value.hNumber.lopart = c64.low(); + } + break; + + // OID syntax + case sNMP_SYNTAX_OID: + { + Oid tmpoid; + tmpoid.oidval(); + tempvb.get_value(tmpoid); + SmiLPOID smi = tmpoid.oidval(); + smival->value.oid.len = tmpoid.length(); + ACE_NEW_RETURN(smival->value.oid.ptr, + SmiUINT32 [smival->value.oid.len], 1); + ACE_OS::memcpy(smival->value.oid.ptr, smi->ptr, + smival->value.oid.len *sizeof(SmiUINT32)); + } + break; + + case sNMP_SYNTAX_BITS: + case sNMP_SYNTAX_OCTETS: + case sNMP_SYNTAX_IPADDR: + { + OctetStr os; + tempvb.get_value(os); + smival->value.string.ptr = 0; + smival->value.string.len = os.length(); + if ( smival->value.string.len > 0 ) { + ACE_NEW_RETURN(smival->value.string.ptr, + SmiBYTE [smival->value.string.len], 1); + if ( smival->value.string.ptr ) { + for (int i=0; i<(int) smival->value.string.len ; i++) + smival->value.string.ptr[i] = os[i]; + } + else { + smival->syntax = sNMP_SYNTAX_NULL; // invalidate the smival + return SNMP_CLASS_RESOURCE_UNAVAIL; + } + } + } + break; + + default: + ACE_DEBUG((LM_DEBUG, "wpdu::convert_vb_to_smival did not convert vb\n")); + // ACE_ASSERT(0); + } // switch + + return 0; +} + +// free a SMI value +void wpdu::free_smival_descriptor( SmiVALUE *smival ) +{ + switch ( smival->syntax ) { + case sNMP_SYNTAX_OCTETS: + case sNMP_SYNTAX_OPAQUE: + case sNMP_SYNTAX_IPADDR: + case sNMP_SYNTAX_BITS: // obsoleted in SNMPv2 Draft Std + delete [] smival->value.string.ptr; + break; + + case sNMP_SYNTAX_OID: + delete [] smival->value.oid.ptr; + break; + } + smival->syntax = sNMP_SYNTAX_NULL; +} + + +wpdu::~wpdu() +{ + delete [] (char*) iovec_.iov_base; +} + +const iovec& wpdu::get_buffer() const +{ + return iovec_; +} + +// return a pdu from a buffer +int wpdu::get_pdu(Pdu& pdu, snmp_version& version) +{ + if (iovec_.iov_len == 0) + return -1; // NO DATA + + snmp_pdu *raw_pdu; + raw_pdu = cmu_snmp::pdu_create(0); + if (!raw_pdu) { + return SNMP_CLASS_RESOURCE_UNAVAIL; + } + + // max value a client can send us - TODO: replace this with an + // api to get actual string length + int status = cmu_snmp::parse( raw_pdu, (unsigned char *)iovec_.iov_base, + community_name, comm_len, + version, iovec_.iov_len); + if (status != 0) + return SNMP_CLASS_INTERNAL_ERROR; + + community_name[comm_len] = 0; // set null based on returned length + set_request_id( &pdu, raw_pdu->reqid); + set_error_status( &pdu, (int) raw_pdu->errstat); + set_error_index( &pdu, (int) raw_pdu->errindex); + pdu.set_type( raw_pdu->command); + + if (restore_vbs(pdu, raw_pdu)) { + cmu_snmp::free_pdu(raw_pdu); + return SNMP_CLASS_INTERNAL_ERROR; + } + + cmu_snmp::free_pdu(raw_pdu); + return 0; +} + +int wpdu::restore_vbs(Pdu& pdu, const snmp_pdu *raw_pdu) const +{ + Vb tempvb; + Oid tempoid; + struct variable_list *vp; + + for(vp = raw_pdu->variables; vp; vp = vp->next_variable) { + + // extract the oid portion + tempoid.set_data( (unsigned long *)vp->name, + ( unsigned int) vp->name_length); + tempvb.set_oid( tempoid); + + // extract the value portion + switch(vp->type) { + + // octet string + case sNMP_SYNTAX_OCTETS: + case sNMP_SYNTAX_OPAQUE: + { + OctetStr octets( (char *) vp->val.string, + (long) vp->val_len); + tempvb.set_value( octets); + } + break; + + // object id + case sNMP_SYNTAX_OID: + { + Oid oid( (unsigned long*) vp->val.objid, + (int) vp->val_len); + tempvb.set_value( oid); + } + break; + + // timeticks + case sNMP_SYNTAX_TIMETICKS: + { + TimeTicks timeticks( (unsigned long) *(vp->val.integer)); + tempvb.set_value( timeticks); + } + break; + + // 32 bit counter + case sNMP_SYNTAX_CNTR32: + { + Counter32 counter32( (unsigned long) *(vp->val.integer)); + tempvb.set_value( counter32); + } + break; + + // ip address + case sNMP_SYNTAX_IPADDR: + { + char buffer[20]; + sprintf( buffer,"%d.%d.%d.%d", + vp->val.string[0], + vp->val.string[1], + vp->val.string[2], + vp->val.string[3]); + IpAddress ipaddress( buffer); + tempvb.set_value( ipaddress); + } + break; + + // 32 bit integer + case sNMP_SYNTAX_INT: + { + SnmpInt32 int32( (long) *(vp->val.integer)); + tempvb.set_value( int32); + } + break; + + // 32 bit unsigned integer + case sNMP_SYNTAX_UINT32: + { + SnmpUInt32 uint32( (unsigned long) *(vp->val.integer)); + tempvb.set_value( uint32); + } + break; + + // v2 counter 64's + case sNMP_SYNTAX_CNTR64: + break; + + case sNMP_SYNTAX_NULL: + tempvb.set_null(); + break; + + // v2 vb exceptions + case sNMP_SYNTAX_NOSUCHOBJECT: + case sNMP_SYNTAX_NOSUCHINSTANCE: + case sNMP_SYNTAX_ENDOFMIBVIEW: + set_exception_status( &tempvb, vp->type); + break; + + default: + tempvb.set_null(); + + } // end switch + + // append the vb to the pdu + pdu += tempvb; + } + + return 0; +} + +const unsigned char *wpdu::get_community() const +{ + return community_name; +} diff --git a/ACE/ASNMP/asnmp/wpdu.h b/ACE/ASNMP/asnmp/wpdu.h new file mode 100644 index 00000000000..7feec356bc8 --- /dev/null +++ b/ACE/ASNMP/asnmp/wpdu.h @@ -0,0 +1,84 @@ +/* -*-C++-*- */ +#ifndef WPDU_H_ +#define WPDU_H_ +//============================================================================= +/** + * @file wpdu.h + * + * $Id$ + * + * Adapter class. Converts a Pdu and GenTarget into a format + * that can be stuffed out a I/O port + * + * + * @author Michael R. MacFaden re-worked api + * @author use ACE APIPeter E Mellquist wrote original class snmpmsg + */ +//============================================================================= + + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "asnmp/asn1.h" +#include "asnmp/pdu.h" +#include "asnmp/target.h" + +// this is an adapter class, it peforms the following transformations +// PDU / Target -> iovec buffer +// iovec buffer -> PDU / Target +struct snmp_pdu; +/** + * @class wpdu + * + * @brief Implement an Adapter pattern between CMU SNMP and HP SNMP++ + */ +class ASNMP_Export wpdu +{ +public: + + /// construct CMU data from HP SNMP++ objects + /// construct HP SNMP++ objects from raw buffer via CMU SNMP datatypes + wpdu(const Pdu& pdu, const UdpTarget& target); + wpdu(const iovec& buffer); + wpdu(); // same as using iovec? + + ~wpdu(); + + /// constructor completed ok? rc = 1 else 0 + int valid() const; + + /// return raw data stream via CMU code + const iovec& get_buffer() const; + + /// return HP SNMP++ pdu + int get_pdu(Pdu& pdu, snmp_version& version); + + /// return community strptr + const unsigned char *get_community() const; + +private: + int convert_vb_to_smival( Vb &tempvb, SmiVALUE *smival ); + int load_vbs(snmp_pdu *raw_pdu, const Pdu& pdu); + int restore_vbs(Pdu& pdu, const snmp_pdu *raw_pdu) const; + void free_smival_descriptor( SmiVALUE *smival ); + static void copy_iovec(iovec& dest, const iovec& src); + int set_trap_info(snmp_pdu *raw_pdu, const Pdu& pdu) const; + + /// raw format + iovec iovec_; + + /// object construction state + int valid_flag_; + + /// snmp version + snmp_version version_; + + unsigned char community_name[MAX_COMM_STR_LEN]; + unsigned long comm_len; // = MAX_COMM_STR_LEN; +}; + +#endif // WPDU_H_ |