1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// $Id: agent_impl.cpp 91670 2010-09-08 18:02:26Z johnnyw $
// implement a prototype SNMP Agent using ASNMP and ACE
#include <ace/Reactor.h>
#include <ace/SOCK_Dgram.h>
#include <ace/INET_Addr.h>
#include <ace/Signal.h>
#include "agent_impl.h"
agent_impl::agent_impl(unsigned short port, const char *rd, const char *wr) :
sagent(port)
{
ACE_TRACE("agent_impl::agent_impl");
tgt_.set_read_community(rd);
tgt_.set_write_community(wr);
agent_clock_.start();
}
agent_impl::~agent_impl()
{
ACE_TRACE("agent_impl::~agent_impl");
}
// callback : have received a Pdu from the target host with given read comm str
// this is really simplistic, but gives the general idea
int agent_impl::handle_get( Pdu &pdu, UdpTarget &target)
{
ACE_TRACE("agent_impl::handle_get");
OctetStr mgr_rd_str, agent_rd_str;
target.get_read_community(mgr_rd_str); // requster's read community string
tgt_.get_read_community(agent_rd_str); // this agent's read community string
// 1. verify we have a valid read string else drop pdu (no response to caller)
if (mgr_rd_str != agent_rd_str) {
ACE_DEBUG((LM_DEBUG, "agent_impl::handle_get: invalid read community recvd\n"));
return 0;
}
// 2. iterate over each varbind in the pdu, filling providing responses
int fdone = 0;
for (int i = 0; (i < pdu.get_vb_count()) && !fdone; i++) {
Vb vb;
pdu.get_vb(vb, i);
if (get_response(vb)) { // set a value for the oid if we can else
set_error_status(&pdu, SNMP_ERROR_NO_SUCH_NAME); // these ought to be member
set_error_index(&pdu, i); // functions but are not yet...
fdone++; // trigger flag to exit loop early
}
else // failed, return noSuch error
pdu.set_vb(vb, i);
}
// 3. lastly, return the pkt to the caller
return respond(pdu, target);
}
// this routine makes up the brains of the agent
// it knows only the MIB II system group set of variables for a get operation
int agent_impl::get_response(Vb& vb)
{
// these objects represent the MIB II system group per RFC 1213
static Oid sysDescr("1.3.6.1.2.1.1.1.0"),
sysObjectID("1.3.6.1.2.1.1.2.0"), sysUpTime("1.3.6.1.2.1.1.3.0"),
sysContact("1.3.6.1.2.1.1.4.0"), sysName("1.3.6.1.2.1.1.5.0"),
sysLocation("1.3.6.1.2.1.1.6.0"), sysServices("1.3.6.1.2.1.1.7.0");
Oid oid;
vb.get_oid(oid);
if (oid == sysDescr) {
OctetStr desc("ASNMP Prototype Agent 1.0");
vb.set_value(desc);
}
else if (oid == sysObjectID) { // the IANA gives assigns Enterprise Numbers
// see ftp://ftp.isi.edu/in-notes/iana/assignments/enterprise-numbers
// for the official list of enterprise numbers. Then under this tree
// assign a unique subtree to identify this agent
Oid id("1.3.6.1.4.1.2533.9.1");
vb.set_value(id);
}
else if (oid == sysUpTime) {
ACE_Time_Value tv;
agent_clock_.elapsed_time (tv);
TimeTicks tt(tv.msec());
vb.set_value(tt);
}
else if (oid == sysContact) {
OctetStr contact("mrm@acm.org");
vb.set_value(contact);
}
else if (oid == sysName) {
OctetStr fqdn("foo.org"); // extract this from the gethostbyname() TODO
vb.set_value(fqdn);
}
else if (oid == sysLocation) {
OctetStr loc("");
vb.set_value(loc);
}
else if (oid == sysServices) {
SnmpInt32 svcs(72);
vb.set_value(svcs);
}
else
return 1; // noSuchName
return 0;
}
int agent_impl::handle_get_next( Pdu &, UdpTarget &)
{
ACE_TRACE("agent_impl::handle_get_next -NI");
return 0;
}
int agent_impl::handle_set( Pdu &, UdpTarget &)
{
ACE_TRACE("agent_impl::handle_set -NI");
return 0;
}
// stuff used by process_requests
// called when SIGINT
static sig_atomic_t finished = 0;
extern "C" void
sig_handler (int)
{
ACE_TRACE("::sig_handler");
finished = 1;
}
int agent_impl::process_requests()
{
ACE_TRACE("agent_impl::process_requests");
ACE_Reactor reactor;
ACE_Sig_Action sa ((ACE_SignalHandler) sig_handler, SIGINT);
ACE_UNUSED_ARG (sa);
// Read data from other side.
if (reactor.register_handler (this, ACE_Event_Handler::READ_MASK) == -1)
ACE_ERROR_RETURN ((LM_ERROR, "ACE_Reactor::register_handler"), -1);
// TODO: register signal handler to shut down gracefully here
while (!finished)
{
reactor.handle_events ();
ACE_DEBUG ((LM_DEBUG, "return from handle events\n"));
}
ACE_DEBUG ((LM_DEBUG, "return from handle events - normal shut down\n"));
return 0;
}
|