diff options
Diffstat (limited to 'perl/OID/OID.xs')
-rw-r--r-- | perl/OID/OID.xs | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/perl/OID/OID.xs b/perl/OID/OID.xs new file mode 100644 index 0000000..10485f9 --- /dev/null +++ b/perl/OID/OID.xs @@ -0,0 +1,442 @@ +/* -*- C -*- */ +#if defined(_WIN32) && !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x501 +#endif + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> + +/* pulled from Dave's, yet-to-be-used, net-snmp library rewrite. + autocompatibility for the future? */ + +typedef struct netsnmp_oid_s { + oid *name; + size_t len; + oid namebuf[ MAX_OID_LEN ]; +} netsnmp_oid; + +static int constant(double *value, const char *name, const int len) +{ + return EINVAL; +} + +netsnmp_oid * +nso_newarrayptr(oid *name, size_t name_len) +{ + netsnmp_oid *RETVAL; + RETVAL = malloc(sizeof(netsnmp_oid)); + RETVAL->name = RETVAL->namebuf; + RETVAL->len = name_len; + memcpy(RETVAL->name, name, name_len * sizeof(oid)); + return RETVAL; +} + +static int __sprint_num_objid _((char *, oid *, int)); + +/* stolen from SNMP.xs. Ug, this needs merging to snmplib */ +/* XXX: this is only here because snmplib forces quotes around the + data and won't return real binary data or a numeric string. Every + app must do its own switch() to get around it. Ug. */ +#define USE_BASIC 0 +#define USE_ENUMS 1 +#define USE_SPRINT_VALUE 2 +static int +__snprint_value (buf, buf_len, var, tp, type, flag) +char * buf; +size_t buf_len; +netsnmp_variable_list * var; +struct tree * tp; +int type; +int flag; +{ + int len = 0; + u_char* ip; + struct enum_list *ep; + + + buf[0] = '\0'; + if (flag == USE_SPRINT_VALUE) { + snprint_value(buf, buf_len, var->name, var->name_length, var); + len = strlen(buf); + } else { + switch (var->type) { + case ASN_INTEGER: + if (flag == USE_ENUMS) { + for(ep = tp->enums; ep; ep = ep->next) { + if (ep->value == *var->val.integer) { + strcpy(buf, ep->label); + len = strlen(buf); + break; + } + } + } + if (!len) { + sprintf(buf,"%ld", *var->val.integer); + len = strlen(buf); + } + break; + + case ASN_GAUGE: + case ASN_COUNTER: + case ASN_TIMETICKS: + case ASN_UINTEGER: + sprintf(buf,"%lu", (unsigned long) *var->val.integer); + len = strlen(buf); + break; + + case ASN_OCTET_STR: + case ASN_OPAQUE: + memcpy(buf, (char*)var->val.string, var->val_len); + len = var->val_len; + break; + + case ASN_IPADDRESS: + ip = (u_char*)var->val.string; + sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + len = strlen(buf); + break; + + case ASN_NULL: + break; + + case ASN_OBJECT_ID: + __sprint_num_objid(buf, (oid *)(var->val.objid), + var->val_len/sizeof(oid)); + len = strlen(buf); + break; + + case SNMP_ENDOFMIBVIEW: + sprintf(buf,"%s", "ENDOFMIBVIEW"); + break; + case SNMP_NOSUCHOBJECT: + sprintf(buf,"%s", "NOSUCHOBJECT"); + break; + case SNMP_NOSUCHINSTANCE: + sprintf(buf,"%s", "NOSUCHINSTANCE"); + break; + + case ASN_COUNTER64: + printU64(buf,(struct counter64 *)var->val.counter64); + len = strlen(buf); + break; + + case ASN_BIT_STR: + snprint_bitstring(buf, buf_len, var, NULL, NULL, NULL); + len = strlen(buf); + break; + + case ASN_NSAP: + default: + warn("snprint_value: asn type not handled %d\n",var->type); + } + } + return(len); +} + +static int +__sprint_num_objid (buf, objid, len) +char *buf; +oid *objid; +int len; +{ + int i; + buf[0] = '\0'; + for (i=0; i < len; i++) { + sprintf(buf,".%" NETSNMP_PRIo "u",*objid++); + buf += strlen(buf); + } + return SNMPERR_SUCCESS; +} + +MODULE = NetSNMP::OID PACKAGE = NetSNMP::OID PREFIX=nso_ + +netsnmp_oid * +nso_newptr(initstring) + char *initstring + CODE: + if (get_tree_head() == NULL) + netsnmp_init_mib(); + RETVAL = malloc(sizeof(netsnmp_oid)); + RETVAL->name = RETVAL->namebuf; + RETVAL->len = sizeof(RETVAL->namebuf)/sizeof(RETVAL->namebuf[0]); + if (!snmp_parse_oid(initstring, (oid *) RETVAL->name, &RETVAL->len)) { + snmp_log(LOG_ERR, "Can't parse: %s\n", initstring); + RETVAL->len = 0; + free(RETVAL); + RETVAL = NULL; + } + OUTPUT: + RETVAL + +void +constant(sv) + PREINIT: + STRLEN len; + INPUT: + SV * sv + char * s = SvPV(sv, len); + INIT: + int status; + double value; + PPCODE: + value = 0; + status = constant(&value, s, len); + XPUSHs(sv_2mortal(newSVuv(status))); + XPUSHs(sv_2mortal(newSVnv(value))); + +int +_snmp_oid_compare(oid1, oid2) + netsnmp_oid *oid1; + netsnmp_oid *oid2; + CODE: + RETVAL = snmp_oid_compare((oid *) oid1->name, oid1->len, + (oid *) oid2->name, oid2->len); + OUTPUT: + RETVAL + +MODULE = NetSNMP::OID PACKAGE = netsnmp_oidPtr PREFIX = nsop_ + +void +nsop_DESTROY(oid1) + netsnmp_oid *oid1 + CODE: +{ + if (oid1->name != oid1->namebuf) { + free(oid1->name); + } + free(oid1); +} + +char * +nsop_to_string(oid1) + netsnmp_oid *oid1 + PREINIT: + static char mystr[SNMP_MAXBUF]; + CODE: + { + if (oid1->len == 0) + snprintf(mystr, sizeof(mystr), "Illegal OID"); + else + snprint_objid(mystr, sizeof(mystr), + (oid *) oid1->name, oid1->len); + RETVAL = mystr; + } + + OUTPUT: + RETVAL + +void +nsop_to_array(oid1) + netsnmp_oid *oid1; + PREINIT: + int i; + + PPCODE: + EXTEND(SP, oid1->len); + for(i=0; i < (int)oid1->len; i++) { + PUSHs(sv_2mortal(newSVnv(oid1->name[i]))); + } + +SV * +nsop_get_indexes(oid1) + netsnmp_oid *oid1; + PREINIT: + int i, nodecount; + struct tree *tp, *tpe, *tpnode, *indexnode; + struct index_list *index; + netsnmp_variable_list vbdata; + u_char *buf = NULL; + size_t buf_len = 256, out_len = 0; + oid name[MAX_OID_LEN]; + size_t name_len = MAX_OID_LEN; + oid *oidp; + size_t oidp_len; + AV *myret; + int is_private; + + CODE: + { + memset(&vbdata, 0, sizeof(vbdata)); + if (NULL == (tp = get_tree(oid1->name, oid1->len, + get_tree_head()))) { + RETVAL = NULL; + return; + } + + if ((buf = netsnmp_malloc(buf_len)) == NULL) { + RETVAL = NULL; + return; + } + + tpe = NULL; + nodecount = 0; + for(tpnode = tp; tpnode; tpnode = tpnode->parent) { + nodecount++; + if (nodecount == 2) + tpe = tpnode; + if (nodecount == 3 && + (strlen(tpnode->label) < 6 || + strcmp(tpnode->label + strlen(tpnode->label) - 5, + "Table"))) { + /* we're not within a table. bad logic, little choice */ + netsnmp_free(buf); + RETVAL = NULL; + return; + } + } + + if (!tpe) { + netsnmp_free(buf); + RETVAL = NULL; + return; + } + + if (tpe->augments && strlen(tpe->augments) > 0) { + /* we're augmenting another table, so use that entry instead */ + if (!snmp_parse_oid(tpe->augments, name, &name_len) || + (NULL == + (tpe = get_tree(name, name_len, + get_tree_head())))) { + netsnmp_free(buf); + RETVAL = NULL; + return; /* XXX: better error recovery needed? */ + } + } + + i = 0; + for(index = tpe->indexes; index; index = index->next) { + i++; + } + + myret = (AV *) sv_2mortal((SV *) newAV()); + + oidp = oid1->name + nodecount; + oidp_len = oid1->len - nodecount; + + for(index = tpe->indexes; index; index = index->next) { + /* XXX: NOT efficient! */ + name_len = MAX_OID_LEN; + if (!snmp_parse_oid(index->ilabel, name, &name_len) || + (NULL == + (indexnode = get_tree(name, name_len, + get_tree_head())))) { + netsnmp_free(buf); + RETVAL = NULL; + return; /* xxx mem leak */ + } + vbdata.type = mib_to_asn_type(indexnode->type); + + if (vbdata.type == (u_char) -1) { + netsnmp_free(buf); + RETVAL = NULL; + return; /* XXX: not good. half populated stack? */ + } + + /* check for fixed length strings */ + if (vbdata.type == ASN_OCTET_STR && + indexnode->ranges && !indexnode->ranges->next + && indexnode->ranges->low == indexnode->ranges->high) { + vbdata.val_len = indexnode->ranges->high; + vbdata.type |= ASN_PRIVATE; + is_private = 1; + } else { + vbdata.val_len = 0; + if (index->isimplied) { + vbdata.type |= ASN_PRIVATE; + is_private = 1; + } else { + is_private = 0; + } + } + + if (parse_one_oid_index(&oidp, &oidp_len, &vbdata, 0) + != SNMPERR_SUCCESS) { + netsnmp_free(buf); + RETVAL = NULL; + return; + } + out_len = 0; + if (is_private) + vbdata.type ^= ASN_PRIVATE; + out_len = + __snprint_value (buf, buf_len, &vbdata, indexnode, + vbdata.type, 0); +/* + sprint_realloc_value(&buf, &buf_len, &out_len, + 1, name, name_len, &vbdata); +*/ + snmp_free_var_internals(&vbdata); + av_push(myret, newSVpv((char *)buf, out_len)); + } + netsnmp_free(buf); + RETVAL = newRV((SV *)myret); + } + OUTPUT: + RETVAL + +void +nsop_append(oid1, string) + netsnmp_oid *oid1; + char *string; + PREINIT: + oid name[MAX_OID_LEN]; + size_t name_len = MAX_OID_LEN; + int i; + CODE: + { + if (!snmp_parse_oid(string, (oid *) name, &name_len)) { + /* XXX */ + } + if (oid1->len + name_len > MAX_OID_LEN) { + /* XXX: illegal */ + } + for(i = 0; i < (int)name_len; i++) { + oid1->name[i+oid1->len] = name[i]; + } + oid1->len += name_len; + } + +void +nsop_append_oid(oid1, oid2) + netsnmp_oid *oid1; + netsnmp_oid *oid2; + PREINIT: + int i; + CODE: + { + if (oid1->len + oid2->len > MAX_OID_LEN) { + /* XXX: illegal */ + } + for(i = 0; i < (int)oid2->len; i++) { + oid1->name[i+oid1->len] = oid2->name[i]; + } + oid1->len += oid2->len; + } + +int +nsop_length(oid1) + netsnmp_oid *oid1; + CODE: + { + RETVAL = oid1->len; + } + OUTPUT: + RETVAL + +netsnmp_oid * +nsop_clone(oid1) + netsnmp_oid *oid1; + PREINIT: + netsnmp_oid *oid2; + CODE: + { + oid2 = nso_newarrayptr(oid1->name, oid1->len); + RETVAL = oid2; + } +OUTPUT: + RETVAL + |