summaryrefslogtreecommitdiff
path: root/perl/agent/agent.xs
diff options
context:
space:
mode:
Diffstat (limited to 'perl/agent/agent.xs')
-rw-r--r--perl/agent/agent.xs1083
1 files changed, 1083 insertions, 0 deletions
diff --git a/perl/agent/agent.xs b/perl/agent/agent.xs
new file mode 100644
index 0000000..0fa89f4
--- /dev/null
+++ b/perl/agent/agent.xs
@@ -0,0 +1,1083 @@
+/* -*- C -*- */
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include <netdb.h>
+#include <sys/socket.h>
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#ifndef sv_undef
+#define sv_undef PL_sv_undef
+#endif
+
+typedef netsnmp_handler_registration *NetSNMP__agent__netsnmp_handler_registration;
+
+typedef struct handler_cb_data_s {
+ SV *perl_cb;
+} handler_cb_data;
+
+typedef struct netsnmp_oid_s {
+ oid *name;
+ size_t len;
+ oid namebuf[ MAX_OID_LEN ];
+} netsnmp_oid;
+
+static int have_done_agent = 0;
+static int have_done_lib = 0;
+
+static int
+not_here(char *s)
+{
+ croak("%s not implemented on this architecture", s);
+ return -1;
+}
+
+static double
+constant_MODE_G(char *name, int len, int arg)
+{
+ if (6 + 2 > len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[6 + 2]) {
+ case '\0':
+ if (strEQ(name + 6, "ET")) { /* MODE_G removed */
+#ifdef MODE_GET
+ return MODE_GET;
+#else
+ goto not_there;
+#endif
+ }
+ case 'B':
+ if (strEQ(name + 6, "ETBULK")) { /* MODE_G removed */
+#ifdef MODE_GETBULK
+ return MODE_GETBULK;
+#else
+ goto not_there;
+#endif
+ }
+ case 'N':
+ if (strEQ(name + 6, "ETNEXT")) { /* MODE_G removed */
+#ifdef MODE_GETNEXT
+ return MODE_GETNEXT;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_MODE_SET_R(char *name, int len, int arg)
+{
+ if (10 + 6 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[10 + 6]) {
+ case '1':
+ if (strEQ(name + 10, "ESERVE1")) { /* MODE_SET_R removed */
+#ifdef MODE_SET_RESERVE1
+ return MODE_SET_RESERVE1;
+#else
+ goto not_there;
+#endif
+ }
+ case '2':
+ if (strEQ(name + 10, "ESERVE2")) { /* MODE_SET_R removed */
+#ifdef MODE_SET_RESERVE2
+ return MODE_SET_RESERVE2;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_SNMP_ERR(char *name, int len, int arg)
+{
+ if (9 + 1 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[9]) {
+
+ case 'A':
+ if (strEQ(name + 10, "UTHORIZATIONERROR")) { /* SNMP_ERR_A removed */
+#ifdef SNMP_ERR_AUTHORIZATIONERROR
+ return SNMP_ERR_AUTHORIZATIONERROR;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'B':
+ if (strEQ(name + 10, "ADVALUE")) { /* SNMP_ERR_B removed */
+#ifdef SNMP_ERR_BADVALUE
+ return SNMP_ERR_BADVALUE;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'C':
+ if (strEQ(name + 10, "OMMITFAILED")) { /* SNMP_ERR_C removed */
+#ifdef SNMP_ERR_COMMITFAILED
+ return SNMP_ERR_COMMITFAILED;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'G':
+ if (strEQ(name + 10, "ENERR")) { /* SNMP_ERR_G removed */
+#ifdef SNMP_ERR_GENERR
+ return SNMP_ERR_GENERR;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'I':
+ if (strEQ(name + 10, "NCONSISTENTVALUE")) { /* SNMP_ERR_I removed */
+#ifdef SNMP_ERR_INCONSISTENTVALUE
+ return SNMP_ERR_INCONSISTENTVALUE;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'N':
+ if (strEQ(name + 10, "OACCESS")) { /* SNMP_ERR_N removed */
+#ifdef SNMP_ERR_NOACCESS
+ return SNMP_ERR_NOACCESS;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "OCREATION")) { /* SNMP_ERR_N removed */
+#ifdef SNMP_ERR_NOCREATION
+ return SNMP_ERR_NOCREATION;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "OERROR")) { /* SNMP_ERR_N removed */
+#ifdef SNMP_ERR_NOERROR
+ return SNMP_ERR_NOERROR;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "OSUCHNAME")) { /* SNMP_ERR_N removed */
+#ifdef SNMP_ERR_NOSUCHNAME
+ return SNMP_ERR_NOSUCHNAME;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "OTWRITABLE")) { /* SNMP_ERR_N removed */
+#ifdef SNMP_ERR_NOTWRITABLE
+ return SNMP_ERR_NOTWRITABLE;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'R':
+ if (strEQ(name + 10, "EADONLY")) { /* SNMP_ERR_R removed */
+#ifdef SNMP_ERR_READONLY
+ return SNMP_ERR_READONLY;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "ESOURCEUNAVAILABLE")) { /* SNMP_ERR_R removed */
+#ifdef SNMP_ERR_RESOURCEUNAVAILABLE
+ return SNMP_ERR_RESOURCEUNAVAILABLE;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'T':
+ if (strEQ(name + 10, "OOBIG")) { /* SNMP_ERR_T removed */
+#ifdef SNMP_ERR_TOOBIG
+ return SNMP_ERR_TOOBIG;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'U':
+ if (strEQ(name + 10, "NDOFAILED")) { /* SNMP_ERR_U removed */
+#ifdef SNMP_ERR_UNDOFAILED
+ return SNMP_ERR_UNDOFAILED;
+#else
+ goto not_there;
+#endif
+ }
+ break;
+
+ case 'W':
+ if (strEQ(name + 10, "RONGENCODING")) { /* SNMP_ERR_W removed */
+#ifdef SNMP_ERR_WRONGENCODING
+ return SNMP_ERR_WRONGENCODING;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "RONGLENGTH")) { /* SNMP_ERR_W removed */
+#ifdef SNMP_ERR_WRONGLENGTH
+ return SNMP_ERR_WRONGLENGTH;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "RONGTYPE")) { /* SNMP_ERR_W removed */
+#ifdef SNMP_ERR_WRONGTYPE
+ return SNMP_ERR_WRONGTYPE;
+#else
+ goto not_there;
+#endif
+ }
+
+ if (strEQ(name + 10, "RONGVALUE")) { /* SNMP_ERR_W removed */
+#ifdef SNMP_ERR_WRONGVALUE
+ return SNMP_ERR_WRONGVALUE;
+#else
+ goto not_there;
+#endif
+ }
+ }
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_MODE_S(char *name, int len, int arg)
+{
+ if (6 + 3 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[6 + 3]) {
+ case 'A':
+ if (strEQ(name + 6, "ET_ACTION")) { /* MODE_S removed */
+#ifdef MODE_SET_ACTION
+ return MODE_SET_ACTION;
+#else
+ goto not_there;
+#endif
+ }
+ case 'B':
+ if (strEQ(name + 6, "ET_BEGIN")) { /* MODE_S removed */
+#ifdef MODE_SET_BEGIN
+ return MODE_SET_BEGIN;
+#else
+ goto not_there;
+#endif
+ }
+ case 'C':
+ if (strEQ(name + 6, "ET_COMMIT")) { /* MODE_S removed */
+#ifdef MODE_SET_COMMIT
+ return MODE_SET_COMMIT;
+#else
+ goto not_there;
+#endif
+ }
+ case 'F':
+ if (strEQ(name + 6, "ET_FREE")) { /* MODE_S removed */
+#ifdef MODE_SET_FREE
+ return MODE_SET_FREE;
+#else
+ goto not_there;
+#endif
+ }
+ case 'R':
+ if (!strnEQ(name + 6,"ET_", 3))
+ break;
+ return constant_MODE_SET_R(name, len, arg);
+ case 'U':
+ if (strEQ(name + 6, "ET_UNDO")) { /* MODE_S removed */
+#ifdef MODE_SET_UNDO
+ return MODE_SET_UNDO;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant(char *name, int len, int arg)
+{
+ errno = 0;
+ if (0 + 5 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[0 + 5]) {
+ case 'G':
+ if (!strnEQ(name + 0,"MODE_", 5))
+ break;
+ return constant_MODE_G(name, len, arg);
+ case 'S':
+ if (!strnEQ(name + 0,"MODE_", 5))
+ break;
+ return constant_MODE_S(name, len, arg);
+ case 'E':
+ if (!strnEQ(name + 0,"SNMP_ERR_", 9))
+ break;
+ return constant_SNMP_ERR(name, len, arg);
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+int
+handler_wrapper(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+ u_long intret = 5;
+ handler_cb_data *cb_data = (handler_cb_data *) handler->myvoid;
+ SV *cb;
+
+ if (cb_data && (cb = cb_data->perl_cb)) {
+ SV *arg;
+ SV *rarg;
+ dSP;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(sp);
+ rarg = newSViv(0);
+ arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_mib_handler");
+ sv_setiv(arg, (IV) handler);
+ XPUSHs(sv_2mortal(rarg));
+ rarg = newSViv(0);
+ arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_handler_registrationPtr");
+ sv_setiv(arg, (IV) reginfo);
+ XPUSHs(sv_2mortal(rarg));
+ rarg = newSViv(0);
+ arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_agent_request_info");
+ sv_setiv(arg, (IV) reqinfo);
+ XPUSHs(sv_2mortal(rarg));
+ rarg = newSViv(0);
+ arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_request_infoPtr");
+ sv_setiv(arg, (IV) requests);
+ XPUSHs(sv_2mortal(rarg));
+ PUTBACK;
+ if (SvTYPE(cb) == SVt_PVCV) {
+ perl_call_sv(cb, G_DISCARD);
+
+ } else if (SvROK(cb) && SvTYPE(SvRV(cb)) == SVt_PVCV) {
+ perl_call_sv(SvRV(cb), G_DISCARD);
+ }
+ SPAGAIN;
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent
+
+double
+constant(sv,arg)
+ PREINIT:
+ STRLEN len;
+ INPUT:
+ SV * sv
+ char * s = SvPV(sv, len);
+ int arg
+ CODE:
+ RETVAL = constant(s,len,arg);
+ OUTPUT:
+ RETVAL
+
+int
+__agent_check_and_process(block = 1)
+ int block;
+ CODE:
+ RETVAL = agent_check_and_process(block);
+ OUTPUT:
+ RETVAL
+
+void
+init_mib()
+ CODE:
+ {
+ netsnmp_init_mib();
+ }
+
+int
+init_agent(name)
+ const char *name;
+
+void
+init_snmp(name)
+ const char *name;
+
+int
+init_master_agent()
+
+void
+snmp_enable_stderrlog()
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent PREFIX = na_
+
+void
+na_shutdown(me)
+ SV *me;
+ CODE:
+ {
+ snmp_shutdown("perl");
+ }
+
+void
+na_errlog(me,value)
+ SV *me;
+ SV *value;
+ PREINIT:
+ STRLEN stringlen;
+ char * stringptr;
+ CODE:
+ {
+ stringptr = SvPV(value, stringlen);
+ snmp_log(LOG_ERR, stringptr );
+ }
+
+
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_handler_registration PREFIX = nsahr_
+
+NetSNMP::agent::netsnmp_handler_registration
+nsahr_new(name, regoid, perlcallback)
+ char *name;
+ char *regoid;
+ SV *perlcallback;
+ PREINIT:
+ oid myoid[MAX_OID_LEN];
+ size_t myoid_len = MAX_OID_LEN;
+ handler_cb_data *cb_data;
+ int gotit=1;
+ CODE:
+ if (!snmp_parse_oid(regoid, myoid, &myoid_len)) {
+ if (!read_objid(regoid, myoid, &myoid_len)) {
+ snmp_log(LOG_ERR, "couldn't parse %s (reg name: %s)\n",
+ regoid, name);
+ RETVAL = NULL;
+ gotit = 0;
+ }
+ }
+ if (gotit) {
+ cb_data = (handler_cb_data *) malloc(sizeof(handler_cb_data));
+ RETVAL = netsnmp_create_handler_registration(name, handler_wrapper,
+ myoid, myoid_len,
+ HANDLER_CAN_RWRITE);
+ cb_data->perl_cb = newSVsv(perlcallback);
+ RETVAL->handler->myvoid = cb_data;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+nsahr_DESTROY(reginfo)
+ netsnmp_handler_registration *reginfo
+ CODE:
+ netsnmp_handler_registration_free(reginfo);
+
+int
+nsahr_register(me)
+ SV *me;
+ PREINIT:
+ netsnmp_handler_registration *reginfo;
+ CODE:
+ {
+ reginfo = (netsnmp_handler_registration *) SvIV(SvRV(me));
+ RETVAL = netsnmp_register_handler(reginfo);
+ if (!RETVAL) {
+ /* the agent now has a "reference" to this reg pointer */
+ SvREFCNT_inc(me);
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_handler_registrationPtr PREFIX = nsahr_
+
+void
+nsahr_getRootOID(me)
+ SV *me;
+ PREINIT:
+ int i;
+ netsnmp_oid *o;
+ netsnmp_handler_registration *reginfo;
+ SV *arg, *rarg;
+ PPCODE:
+ {
+ dSP;
+ PUSHMARK(SP);
+ reginfo = (netsnmp_handler_registration *) SvIV(SvRV(me));
+
+ o = SNMP_MALLOC_TYPEDEF(netsnmp_oid);
+ o->name = o->namebuf;
+ o->len = reginfo->rootoid_len;
+ memcpy(o->name, reginfo->rootoid,
+ reginfo->rootoid_len * sizeof(oid));
+
+ rarg = newSViv((int) 0);
+ arg = newSVrv(rarg, "netsnmp_oidPtr");
+ sv_setiv(arg, (IV) o);
+
+ XPUSHs(sv_2mortal(rarg));
+
+ PUTBACK;
+ i = perl_call_pv("NetSNMP::OID::newwithptr", G_SCALAR);
+ SPAGAIN;
+ if (i != 1) {
+ snmp_log(LOG_ERR, "unhandled OID error.\n");
+ /* ack XXX */
+ }
+ ST(0) = POPs;
+ XSRETURN(1);
+ }
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_request_infoPtr PREFIX = nari_
+
+void
+getOID(me)
+ SV *me;
+ PREINIT:
+ int i;
+ netsnmp_oid *o;
+ netsnmp_request_info *request;
+ SV *arg, *rarg;
+ PPCODE:
+ {
+ dSP;
+ PUSHMARK(SP);
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+
+ o = SNMP_MALLOC_TYPEDEF(netsnmp_oid);
+ o->name = o->namebuf;
+ o->len = request->requestvb->name_length;
+ memcpy(o->name, request->requestvb->name,
+ request->requestvb->name_length * sizeof(oid));
+
+ rarg = newSViv((int) 0);
+ arg = newSVrv(rarg, "netsnmp_oidPtr");
+ sv_setiv(arg, (IV) o);
+
+ XPUSHs(sv_2mortal(rarg));
+
+ PUTBACK;
+ i = perl_call_pv("NetSNMP::OID::newwithptr", G_SCALAR);
+ SPAGAIN;
+ if (i != 1) {
+ snmp_log(LOG_ERR, "unhandled OID error.\n");
+ /* ack XXX */
+ }
+ ST(0) = POPs;
+ XSRETURN(1);
+ }
+
+netsnmp_oid *
+nari_getOIDptr(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ RETVAL = SNMP_MALLOC_TYPEDEF(netsnmp_oid);
+ RETVAL->name = RETVAL->namebuf;
+ RETVAL->len = request->requestvb->name_length;
+ memcpy(RETVAL->name, request->requestvb->name,
+ request->requestvb->name_length * sizeof(oid));
+ OUTPUT:
+ RETVAL
+
+int
+nari_getType(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+
+ RETVAL = request->requestvb->type ;
+ OUTPUT:
+ RETVAL
+
+void
+nari_setType(me, newvalue)
+ SV *me;
+ int newvalue;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ request->requestvb->type=newvalue;
+
+char *
+nari_getValue(me)
+ SV *me;
+ PREINIT:
+ u_char buf[1024] ;
+ u_char *oidbuf = buf ;
+ size_t ob_len = 1024, oo_len = 0;
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ sprint_realloc_by_type(&oidbuf, &ob_len, &oo_len, 0,
+ request->requestvb, 0, 0, 0);
+ RETVAL = oidbuf; /* mem leak */
+ OUTPUT:
+ RETVAL
+
+int
+nari_getDelegated(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ RETVAL = request->delegated;
+ OUTPUT:
+ RETVAL
+
+void
+nari_setDelegated(me, newdelegated)
+ SV *me;
+ int newdelegated;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ request->delegated = newdelegated;
+
+int
+nari_getProcessed(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ RETVAL = request->processed;
+ OUTPUT:
+ RETVAL
+
+void
+nari_setProcessed(me, newprocessed)
+ SV *me;
+ int newprocessed;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ request->processed = newprocessed;
+
+int
+nari_getStatus(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ RETVAL = request->status;
+ OUTPUT:
+ RETVAL
+
+void
+nari_setStatus(me, newstatus)
+ SV *me;
+ int newstatus;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ request->status = newstatus;
+
+int
+nari_getRepeat(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ RETVAL = request->repeat;
+ OUTPUT:
+ RETVAL
+
+void
+nari_setRepeat(me, newrepeat)
+ SV *me;
+ int newrepeat;
+ PREINIT:
+ netsnmp_request_info *request;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ request->repeat = newrepeat;
+
+int
+nari_setValue(me, type, value)
+ SV *me;
+ int type;
+ SV *value;
+ PREINIT:
+ u_char *oidbuf = NULL;
+ size_t ob_len = 0, oo_len = 0;
+ netsnmp_request_info *request;
+ u_long utmp;
+ long ltmp;
+ uint64_t ulltmp;
+ struct counter64 c64;
+ oid myoid[MAX_OID_LEN];
+ size_t myoid_len;
+ STRLEN stringlen;
+ char * stringptr;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ switch(type) {
+ case SNMP_NOSUCHINSTANCE :
+ snmp_set_var_typed_value(request->requestvb,SNMP_NOSUCHINSTANCE,0,0) ;
+ RETVAL = 1;
+ break ;
+ case SNMP_NOSUCHOBJECT :
+ snmp_set_var_typed_value(request->requestvb,SNMP_NOSUCHOBJECT,0,0) ;
+ RETVAL = 1;
+ break ;
+ case SNMP_ENDOFMIBVIEW :
+ snmp_set_var_typed_value(request->requestvb,SNMP_ENDOFMIBVIEW,0,0) ;
+ RETVAL = 1;
+ break ;
+ case ASN_INTEGER:
+ /* We want an integer here */
+ if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG) ||
+ SvIOK(value)) {
+ /* Good - got a real one (or a blessed object that we hope will turn out OK) */
+ ltmp = SvIV(value);
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) &ltmp, sizeof(ltmp));
+ RETVAL = 1;
+ break;
+ }
+ else if (SvPOKp(value)) {
+ /* Might be OK - got a string, so try to convert it, allowing base 10, octal, and hex forms */
+ stringptr = SvPV(value, stringlen);
+ ltmp = strtol( stringptr, NULL, 0 );
+ if (errno == EINVAL) {
+ snmp_log(LOG_ERR, "Could not convert string to number in setValue: '%s'", stringptr);
+ RETVAL = 0;
+ break;
+ }
+
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) &ltmp, sizeof(ltmp));
+ RETVAL = 1;
+ break;
+ }
+ else {
+ snmp_log(LOG_ERR, "Non-integer value passed to setValue with ASN_INTEGER: type was %d\n",
+ SvTYPE(value));
+ RETVAL = 0;
+ break;
+ }
+
+
+ case ASN_UNSIGNED:
+ case ASN_COUNTER:
+ case ASN_TIMETICKS:
+ /* We want an integer here */
+ if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG) ||
+ SvIOK(value)) {
+ /* Good - got a real one (or a blessed scalar which we have to hope will turn out OK) */
+ utmp = SvIV(value);
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) &utmp, sizeof(utmp));
+ RETVAL = 1;
+ break;
+ }
+ else if (SvPOKp(value)) {
+ /* Might be OK - got a string, so try to convert it, allowing base 10, octal, and hex forms */
+ stringptr = SvPV(value, stringlen);
+ utmp = strtoul( stringptr, NULL, 0 );
+ if (errno == EINVAL) {
+ snmp_log(LOG_ERR, "Could not convert string to number in setValue: '%s'", stringptr);
+ RETVAL = 0;
+ break;
+ }
+
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) &utmp, sizeof(utmp));
+ RETVAL = 1;
+ break;
+ }
+ else {
+ snmp_log(LOG_ERR, "Non-unsigned-integer value passed to setValue with ASN_UNSIGNED/ASN_COUNTER/ASN_TIMETICKS: type was %d\n",
+ SvTYPE(value));
+ RETVAL = 0;
+ break;
+ }
+
+ case ASN_COUNTER64:
+ /* We want an integer here */
+ if ((SvTYPE(value) == SVt_IV) || (SvTYPE(value) == SVt_PVMG)) {
+ /* Good - got a real one (or a blessed scalar which we have to hope will turn out OK) */
+ ulltmp = SvIV(value);
+ c64.high = (uint32_t)(ulltmp >> 32);
+ c64.low = (uint32_t)ulltmp;
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) &c64, sizeof(struct counter64));
+ RETVAL = 1;
+ break;
+ }
+ else if (SvPOKp(value)) {
+ /* Might be OK - got a string, so try to convert it, allowing base 10, octal, and hex forms */
+ stringptr = SvPV(value, stringlen);
+#if defined(WIN32)
+ ulltmp = strtoul( stringptr, NULL, 0 );
+#else
+ ulltmp = strtoull( stringptr, NULL, 0 );
+#endif
+ if (errno == EINVAL) {
+ snmp_log(LOG_ERR, "Could not convert string to number in setValue: '%s'", stringptr);
+ RETVAL = 0;
+ break;
+ }
+
+ c64.high = (uint32_t)(ulltmp >> 32);
+ c64.low = (uint32_t)ulltmp;
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) &c64, sizeof(struct counter64));
+ RETVAL = 1;
+ break;
+ }
+ else {
+ snmp_log(LOG_ERR, "Non-unsigned-integer value passed to setValue with ASN_COUNTER64: type was %d\n",
+ SvTYPE(value));
+ RETVAL = 0;
+ break;
+ }
+
+ case ASN_OCTET_STR:
+ case ASN_BIT_STR:
+ /* Check that we have been passed something with a string value (or a blessed scalar) */
+ if (!SvPOKp(value) && (SvTYPE(value) != SVt_PVMG)) {
+ snmp_log(LOG_ERR, "Non-string value passed to setValue with ASN_OCTET_STR/ASN_BIT_STR: type was %d\n",
+ SvTYPE(value));
+ RETVAL = 0;
+ break;
+ }
+
+ /* Find length of string (strlen will *not* do, as these are binary strings) */
+ stringptr = SvPV(value, stringlen);
+
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) stringptr,
+ stringlen);
+ RETVAL = 1;
+ break;
+
+ case ASN_IPADDRESS:
+ /* IP addresses are passed as *binary* strings.
+ * In the case of IPv4 addresses, these are 4 bytes long.
+ * NOTE: the use of binary strings rather than dotted-quad or FQDNs was
+ * introduced here by Andrew Findlay's patch of March 17th 2003,
+ * and is effectively a change to the previous implied API which assumed
+ * the value was a (valid) hostname.
+ * Responsibility for decoding and resolving has been passed up to the Perl script.
+ */
+
+ /* Check that we have been passed something with a string value (or a blessed scalar) */
+ if (!SvPOKp(value) && (SvTYPE(value) != SVt_PVMG)) {
+ snmp_log(LOG_ERR, "Non-string value passed to setValue with ASN_IPADDRESS: type was %d\n",
+ SvTYPE(value));
+ RETVAL = 0;
+ break;
+ }
+
+ /* Find length of string (strlen will *not* do, as these are binary strings) */
+ stringptr = SvPV(value, stringlen);
+
+ # snmp_log(LOG_ERR, "IP address returned with length %d: %u.%u.%u.%u\n", stringlen, stringptr[0],
+ # stringptr[1], stringptr[2], stringptr[3] );
+
+ # Sanity check on address length
+ if ((stringlen != 4) && (stringlen != 16)) {
+ snmp_log(LOG_ERR, "IP address of %d bytes passed to setValue with ASN_IPADDRESS\n", stringlen);
+ RETVAL = 0;
+ break;
+ }
+
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ stringptr, stringlen);
+ RETVAL = 1;
+ break;
+
+ case ASN_OBJECT_ID:
+ /* Check that we have been passed something with a string value (or a blessed scalar) */
+ if (!SvPOKp(value) && (SvTYPE(value) != SVt_PVMG)) {
+ snmp_log(LOG_ERR, "Non-string value passed to setValue with ASN_OBJECT_ID: type was %d\n",
+ SvTYPE(value));
+ RETVAL = 0;
+ break;
+ }
+
+ /* Extract the string */
+ stringptr = SvPV(value, stringlen);
+
+ /* snmp_log(LOG_ERR, "setValue returning OID '%s'\n", stringptr); */
+
+ myoid_len = MAX_OID_LEN;
+ if (!snmp_parse_oid(stringptr, myoid, &myoid_len)) {
+ snmp_log(LOG_ERR, "couldn't parse %s in setValue\n", stringptr);
+ RETVAL = 0;
+ break;
+ } else {
+ /* snmp_log(LOG_ERR, "setValue returning OID length %d\n", myoid_len); */
+
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ snmp_set_var_typed_value(request->requestvb, (u_char)type,
+ (u_char *) myoid, (myoid_len * sizeof(myoid[0])) );
+ }
+
+ RETVAL = 1;
+ break;
+
+ default:
+ snmp_log(LOG_ERR, "unknown var value type: %d\n",
+ type);
+ RETVAL = 0;
+ break;
+ }
+
+ OUTPUT:
+ RETVAL
+
+void
+nari_setOID(me, value)
+ SV *me;
+ char *value;
+ PREINIT:
+ oid myoid[MAX_OID_LEN];
+ size_t myoid_len = MAX_OID_LEN;
+ netsnmp_request_info *request;
+ CODE:
+ myoid_len = MAX_OID_LEN;
+ if (!snmp_parse_oid(value, myoid, &myoid_len)) {
+ snmp_log(LOG_ERR, "couldn't parse %s in setOID\n", value);
+ } else {
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ snmp_set_var_objid(request->requestvb, myoid, myoid_len);
+ }
+
+void
+nari_setError(me, rinfo, ecode)
+ SV *me;
+ SV *rinfo;
+ int ecode;
+ PREINIT:
+ oid myoid[MAX_OID_LEN];
+ size_t myoid_len = MAX_OID_LEN;
+ netsnmp_request_info *request;
+ netsnmp_agent_request_info *reqinfo;
+ CODE:
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(rinfo));
+ netsnmp_set_request_error(reqinfo, request, ecode);
+
+SV *
+nari_next(me)
+ SV *me;
+ PREINIT:
+ netsnmp_request_info *request;
+ SV *arg, *rarg;
+ CODE:
+ {
+ request = (netsnmp_request_info *) SvIV(SvRV(me));
+ if (request && request->next) {
+ request = request->next;
+ rarg = newSViv(0);
+ arg = newSVrv(rarg, "NetSNMP::agent::netsnmp_request_infoPtr");
+ sv_setiv(arg, (IV) request);
+ RETVAL = rarg;
+ } else {
+ RETVAL = &sv_undef;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent::netsnmp_agent_request_info PREFIX = narqi_
+
+int
+narqi_getMode(me)
+ SV *me;
+ PREINIT:
+ netsnmp_agent_request_info *reqinfo;
+ CODE:
+ reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
+ RETVAL = reqinfo->mode;
+ OUTPUT:
+ RETVAL
+
+void
+narqi_setMode(me, newvalue)
+ SV *me;
+ int newvalue;
+ PREINIT:
+ netsnmp_agent_request_info *reqinfo;
+ CODE:
+ reqinfo = (netsnmp_agent_request_info *) SvIV(SvRV(me));
+ reqinfo->mode = newvalue;
+
+
+MODULE = NetSNMP::agent PACKAGE = NetSNMP::agent
+