summaryrefslogtreecommitdiff
path: root/ACE/ASNMP/asnmp/snmp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ASNMP/asnmp/snmp.cpp')
-rw-r--r--ACE/ASNMP/asnmp/snmp.cpp286
1 files changed, 286 insertions, 0 deletions
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() {}