Hello!

I have recently seen a project that used NetSNMP::TrapHandler and it stated
that when you use it you should start snmptrapd with -On.

This is a result of the use of global variables to specify how all formatting
is done and the fact that the only way the value is passed on is in the written
out string representation.

Now, to get partway around this I have written a patch that adds a fourth
value to each VB that is passed as the second argument and there I put the
"raw" value with a correct type, at least as far as perl allows.

Attached is my first attept on implementing this and I would like to know if
this is a reasonable approach or if I messed up completley as this is the
first time I have tried to make anything with perl extensions.

/MF
>From dac01de798e46673932c9a68512e0a01599ca680 Mon Sep 17 00:00:00 2001
From: Magnus Fromreide <ma...@lysator.liu.se>
Date: Fri, 25 Sep 2015 18:39:30 +0200
Subject: [PATCH 1/2] Factor out the construction of OID objects to a separate
 function.

---
 perl/TrapReceiver/TrapReceiver.xs | 96 +++++++++++++++++++++------------------
 1 file changed, 51 insertions(+), 45 deletions(-)

diff --git a/perl/TrapReceiver/TrapReceiver.xs 
b/perl/TrapReceiver/TrapReceiver.xs
index a4fc136..1ca4801 100644
--- a/perl/TrapReceiver/TrapReceiver.xs
+++ b/perl/TrapReceiver/TrapReceiver.xs
@@ -27,6 +27,56 @@ typedef struct netsnmp_oid_s {
     oid                  namebuf[ MAX_OID_LEN ];
 } netsnmp_oid;
 
+static SV* newSVoid(oid* sname, size_t slen)
+{
+    /*assert(slen < MAX_OID_LEN);*/
+    netsnmp_oid *o = malloc(sizeof(netsnmp_oid));
+    o->name = o->namebuf;
+    o->len = slen;
+    memcpy(o->name, sname, slen * sizeof(oid));
+
+#undef CALL_EXTERNAL_OID_NEW
+
+#ifdef CALL_EXTERNAL_OID_NEW
+    {
+      SV *arg;
+      SV *rarg;
+
+      PUSHMARK(sp);
+
+      rarg = sv_2mortal(newSViv((IV) 0));
+      arg = sv_2mortal(newSVrv(rarg, "netsnmp_oidPtr"));
+      sv_setiv(arg, (IV) o);
+      XPUSHs(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 */
+      }
+      /* get the value */
+      {
+         SV *rv = POPs;
+         SvREFCNT_inc(rv);
+         PUTBACK;
+         return rv;
+      }
+    }
+#else /* build it and bless ourselves */
+    {
+      HV *hv = newHV();
+      SV *rv = newRV_noinc((SV *) hv);
+      SV *rvsub = newRV_noinc((SV *) newSViv((UV) o));
+      rvsub = sv_bless(rvsub, gv_stashpv("netsnmp_oidPtr", 1));
+      (void)hv_store(hv, "oidptr", 6,  rvsub, 0);
+      return sv_bless(rv, gv_stashpv("NetSNMP::OID", 1));
+    }
+#endif /* build oid ourselves */
+}
+
 int   perl_trapd_handler( netsnmp_pdu           *pdu,
                           netsnmp_transport     *transport,
                           netsnmp_trapd_handler *handler)
@@ -34,7 +84,6 @@ int   perl_trapd_handler( netsnmp_pdu           *pdu,
     trapd_cb_data *cb_data;
     SV *pcallback;
     netsnmp_variable_list *vb;
-    netsnmp_oid *o;
     SV **tmparray;
     int i, c = 0;
     u_char *outbuf;
@@ -113,50 +162,7 @@ int   perl_trapd_handler( netsnmp_pdu           *pdu,
     for(vb = pdu->variables; vb; vb = vb->next_variable) {
 
         /* get the oid */
-        o = malloc(sizeof(netsnmp_oid));
-        o->name = o->namebuf;
-        o->len = vb->name_length;
-        memcpy(o->name, vb->name, vb->name_length * sizeof(oid));
-
-#undef CALL_EXTERNAL_OID_NEW
-
-#ifdef CALL_EXTERNAL_OID_NEW
-        {
-        SV *arg;
-        SV *rarg;
-
-        PUSHMARK(sp);
-
-        rarg = sv_2mortal(newSViv((IV) 0));
-        arg = sv_2mortal(newSVrv(rarg, "netsnmp_oidPtr"));
-        sv_setiv(arg, (IV) o);
-        XPUSHs(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 */
-        }
-        /* get the value */
-        tmparray[c++] = POPs;
-        SvREFCNT_inc(tmparray[c-1]);
-        PUTBACK;
-        }
-#else /* build it and bless ourselves */
-        {
-            HV *hv = newHV();
-            SV *rv = newRV_noinc((SV *) hv);
-            SV *rvsub = newRV_noinc((SV *) newSViv((UV) o));
-            rvsub = sv_bless(rvsub, gv_stashpv("netsnmp_oidPtr", 1));
-            (void)hv_store(hv, "oidptr", 6,  rvsub, 0);
-            rv = sv_bless(rv, gv_stashpv("NetSNMP::OID", 1));
-            tmparray[c++] = rv;
-        }
-        
-#endif /* build oid ourselves */
+       tmparray[c++] = newSVoid(vb->name, vb->name_length);
     }
 
     /*
-- 
2.4.3

>From aedad20c169e4250239eb47f92242013f8677d8d Mon Sep 17 00:00:00 2001
From: Magnus Fromreide <ma...@lysator.liu.se>
Date: Fri, 25 Sep 2015 18:50:54 +0200
Subject: [PATCH 2/2] Add a fourth value to the oid list, the raw data of the
 value.

The point of this is to provide the value directly, avoiding having to force
clients to guess what the value was.
The type of the parameter depends on the type tag in [2], according to the
following:
  INTEGER
    Signed integer
  OCTET STRING, Opaque, BITS, IpAddress, Counter64, I64, U64, C64
    String
  Counter, Gauge, TimeTicks, UInteger
    Unsigned integer
  OBJECT IDENTIFIER
    NetSNMP::OID
  NULL, anything else
    undef
---
 perl/TrapReceiver/TrapReceiver.pm |  9 ++++---
 perl/TrapReceiver/TrapReceiver.xs | 51 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/perl/TrapReceiver/TrapReceiver.pm 
b/perl/TrapReceiver/TrapReceiver.pm
index a9b73ae..8720111 100644
--- a/perl/TrapReceiver/TrapReceiver.pm
+++ b/perl/TrapReceiver/TrapReceiver.pm
@@ -131,9 +131,12 @@ it came from, what SNMP user name or community name it was 
sent under,
 etc).  The second argument is a reference to an array containing the
 variable bindings (OID and value information) that define the
 noification itself.  Each variable is itself a reference to an array
-containing three values: a NetSNMP::OID object, the value that came
-associated with it, and the value's numeric type (see NetSNMP::ASN for
-further details on SNMP typing information).
+containing four values: a NetSNMP::OID object, a string representation
+of the value that came associated with it, the value's numeric type (see
+NetSNMP::ASN for further details on SNMP typing information), and the raw
+value of the trap, encoded according to its type, 64-bit integer types are
+returned as strings, integer types as integers, strings as strings, object
+identifiers as NetSNMP::OID objects, and any other types as undefs.
 
 Registered functions should return one of the following values:
 
diff --git a/perl/TrapReceiver/TrapReceiver.xs 
b/perl/TrapReceiver/TrapReceiver.xs
index 1ca4801..50ef116 100644
--- a/perl/TrapReceiver/TrapReceiver.xs
+++ b/perl/TrapReceiver/TrapReceiver.xs
@@ -186,6 +186,57 @@ int   perl_trapd_handler( netsnmp_pdu           *pdu,
         av_push(vba,newSVpvn((char *) outbuf, oo_len));
         netsnmp_free(outbuf);
         av_push(vba,newSViv(vb->type));
+       switch (vb->type) {
+       case ASN_INTEGER:
+               av_push(vba,newSViv((int32_t)*vb->val.integer));
+               break;
+       case ASN_COUNTER:
+       case ASN_GAUGE:
+       case ASN_TIMETICKS:
+       case ASN_UINTEGER: /* from rfc1442 */
+               av_push(vba,newSVuv((uint32_t)*vb->val.integer));
+               break;
+       case ASN_IPADDRESS:
+       case ASN_OCTET_STR:
+       case ASN_OPAQUE:
+       case ASN_NSAP:
+               av_push(vba,newSVpvn((char*)vb->val.string,vb->val_len));
+               break;
+       case ASN_BIT_STR:
+               av_push(vba,newSVpvn((char*)vb->val.bitstring,vb->val_len));
+               break;
+       case ASN_OBJECT_ID:
+               av_push(vba,newSVoid(vb->val.objid,vb->val_len / sizeof(oid)));
+               break;
+#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
+       case ASN_OPAQUE_FLOAT:
+               av_push(vba,newSVnv(*vb->val.floatVal));
+               break;
+       case ASN_OPAQUE_DOUBLE:
+               av_push(vba,newSVnv(*vb->val.doubleVal));
+               break;
+       case ASN_OPAQUE_I64:
+               {
+                       char buf[I64CHARSZ + 1];
+                       printI64(buf, vb->val.counter64);
+                       av_push(vba,newSVpv(buf,0));
+               }
+               break;
+       case ASN_OPAQUE_COUNTER64:
+       case ASN_OPAQUE_U64:
+#endif
+       case ASN_COUNTER64:
+               {
+                       char buf[I64CHARSZ + 1];
+                       printU64(buf, vb->val.counter64);
+                       av_push(vba,newSVpv(buf,0));
+               }
+               break;
+       case ASN_NULL:
+       default:
+               av_push(vba,newSV(0));
+               break;
+       }
         av_push(varbinds, (SV *) newRV_noinc((SV *) vba));
     }
 
-- 
2.4.3

------------------------------------------------------------------------------
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to