Blob Blame History Raw
/* -*- 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/library/asn1.h>
#include <net-snmp/library/snmp_impl.h>

#define TEST_CONSTANT(value, name, C)           \
    if (strEQ(name, #C)) {                      \
        *value = C;                             \
        return 0;                               \
    }

static int constant_ASN_O(double *value, const char *name, const int len)
{
    switch (len >= 5 ? name[5] : -1) {
    case 'B':
        TEST_CONSTANT(value, name, ASN_OBJECT_ID);
        break;
    case 'C':
        TEST_CONSTANT(value, name, ASN_OCTET_STR);
        break;
    case 'P':
        TEST_CONSTANT(value, name, ASN_OPAQUE);
        break;
    }
    return EINVAL;
}

static int constant_ASN_B(double *value, const char *name, const int len)
{
    switch (len >= 5 ? name[5] : -1) {
    case 'I':
        TEST_CONSTANT(value, name, ASN_BIT_STR);
        break;
    case 'O':
        TEST_CONSTANT(value, name, ASN_BOOLEAN);
        break;
    }
    return EINVAL;
}

static int constant_ASN_S(double *value, const char *name, const int len)
{
    switch (len >= 6 ? name[6] : -1) {
    case 'Q':
        TEST_CONSTANT(value, name, ASN_SEQUENCE);
        break;
    case 'T':
        TEST_CONSTANT(value, name, ASN_SET);
        break;
    }
    return EINVAL;
}

static int constant_ASN_C(double *value, const char *name, const int len)
{
    switch (len >= 11 ? name[11] : -1) {
    case '\0':
        TEST_CONSTANT(value, name, ASN_COUNTER);
        break;
    case '6':
        TEST_CONSTANT(value, name, ASN_COUNTER64);
        break;
    }
    return EINVAL;
}

static int constant_ASN_U(double *value, const char *name, const int len)
{
    switch (len >= 12 ? name[12] : -1) {
    case '\0':
	TEST_CONSTANT(value, name, ASN_UNSIGNED);
        break;
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
    case '6':
	TEST_CONSTANT(value, name, ASN_UNSIGNED64);
        break;
#endif
    }
    return EINVAL;
}

static int constant_ASN_IN(double *value, const char *name, const int len)
{
    switch (len >= 11 ? name[11] : -1) {
    case '\0':
        TEST_CONSTANT(value, name, ASN_INTEGER);
        break;
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
    case '6':
        TEST_CONSTANT(value, name, ASN_INTEGER64);
        break;
#endif
    }
    return EINVAL;
}

static int constant_ASN_I(double* value, const char *name, const int len)
{
    switch (len >= 5 ? name[5] : -1) {
    case 'N':
	return constant_ASN_IN(value, name, len);
    case 'P':
        TEST_CONSTANT(value, name, ASN_IPADDRESS);
        break;
    }
    return EINVAL;
}

static int constant(double *value, const char *const name, const int len)
{
    if (!strnEQ(name, "ASN_", 4))
        return EINVAL;

    switch (name[4]) {
    case 'A':
	TEST_CONSTANT(value, name, ASN_APPLICATION);
        break;
    case 'B':
	return constant_ASN_B(value, name, len);
    case 'C':
	return constant_ASN_C(value, name, len);
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
    case 'D':
        TEST_CONSTANT(value, name, ASN_DOUBLE);
        break;
    case 'F':
        TEST_CONSTANT(value, name, ASN_FLOAT);
        break;
#endif
    case 'G':
        TEST_CONSTANT(value, name, ASN_GAUGE);
        break;
    case 'I':
	return constant_ASN_I(value, name, len);
    case 'N':
        TEST_CONSTANT(value, name, ASN_NULL);
        break;
    case 'O':
	return constant_ASN_O(value, name, len);
    case 'S':
	return constant_ASN_S(value, name, len);
    case 'T':
        TEST_CONSTANT(value, name, ASN_TIMETICKS);
        break;
    case 'U':
	return constant_ASN_U(value, name, len);
    }
    return EINVAL;
}


MODULE = NetSNMP::ASN		PACKAGE = NetSNMP::ASN		


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)));