net-snmp/perl/OID/OID.xs

443 lines
12 KiB
Plaintext
Raw Normal View History

2022-06-27 15:01:12 +08:00
/* -*- 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;
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(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