summaryrefslogtreecommitdiff
path: root/perl/OID/OID.xs
diff options
context:
space:
mode:
Diffstat (limited to 'perl/OID/OID.xs')
-rw-r--r--perl/OID/OID.xs442
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
+