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