From cadd830e5aca1f208541ea6d38da5b4a863db5cc Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 27 Jan 2006 21:36:35 +0000 Subject: Added textual MIB parsing support. See #45 --- daemon/Makefile.am | 3 +- daemon/config.c | 10 ++++-- daemon/rrdbotd.c | 67 +++++++++++++++++++++++++++++------- daemon/rrdbotd.h | 19 +++++++++-- daemon/snmp-help.c | 99 ++++++++++++++++++++++++++++++++++++++++++------------ 5 files changed, 160 insertions(+), 38 deletions(-) (limited to 'daemon') diff --git a/daemon/Makefile.am b/daemon/Makefile.am index c83aabe..969bafb 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -6,6 +6,7 @@ rrdbotd_SOURCES = rrdbotd.c rrdbotd.h config.c usuals.h \ ../common/server-mainloop.c ../common/server-mainloop.h \ ../common/sock-any.h ../common/sock-any.c \ ../common/stringx.h ../common/stringx.c \ - ../common/hash.h ../common/hash.c + ../common/hash.h ../common/hash.c \ + ../mib/parse.c rrdbotd_CFLAGS = -I${top_srcdir}/common/ -I${top_srcdir}/bsnmp/ -I${top_srcdir} rrdbotd_LDADD = $(top_builddir)/bsnmp/libbsnmp-custom.a diff --git a/daemon/config.c b/daemon/config.c index 78ad04b..d33ab69 100644 --- a/daemon/config.c +++ b/daemon/config.c @@ -233,6 +233,9 @@ parse_uri(char *uri, char** scheme, char** host, *path = uri; + while((*path)[0] == '/') + (*path)++; + /* This copy only for error messages */ free(copy); } @@ -303,8 +306,11 @@ parse_item(const char* field, char* uri, config_ctx *ctx) ritem->value = RB_UNKNOWN; /* And parse the OID */ - if(rb_parse_mib(path, &(ritem->snmpfield)) == -1) - errx(2, "%s: invalid OID: %s", ctx->confname, path + 1); + if(rb_snmp_parse_mib(path, &(ritem->snmpfield)) == -1) + errx(2, "%s: invalid MIB: %s", ctx->confname, path); + + rb_messagex(LOG_DEBUG, "parsed MIB into oid: %s -> %s", path, + asn_oid2str(&(ritem->snmpfield.var))); /* And add it to the list */ ritem->next = ctx->items; diff --git a/daemon/rrdbotd.c b/daemon/rrdbotd.c index 39094cd..8434e35 100644 --- a/daemon/rrdbotd.c +++ b/daemon/rrdbotd.c @@ -62,10 +62,41 @@ /* The one main state object */ rb_state g_state; +/* Whether we print warnings when loading MIBs or not */ +int g_mib_warnings = 0; + /* Some logging flags */ static int daemonized = 0; static int debug_level = LOG_ERR; +#include "mib/parse.h" + +static void +test(int argc, char* argv[]) +{ + struct snmp_value val; + mib_node n, n2; + + debug_level = 4; + + if(argc < 2) + errx(2, "specify arguments"); + + while(argc > 1) + { + if(rb_snmp_parse_mib(argv[1], &val) == -1) + warnx("couldn't parse mib value: %s", argv[1]); + else + fprintf(stderr, "the oid is: %s\n", asn_oid2str(&(val.var))); + + argc--; + argv++; + } + + rb_mib_uninit(); + exit(1); +} + /* ----------------------------------------------------------------------------- * CLEANUP */ @@ -120,8 +151,8 @@ rb_atexit(voidfunc func, void* data) * LOGGING */ -static void -vmessage (int level, int err, const char* msg, va_list ap) +void +rb_vmessage(int level, int err, const char* msg, va_list ap) { #define MAX_MSGLEN 1024 char buf[MAX_MSGLEN]; @@ -156,7 +187,7 @@ rb_messagex (int level, const char* msg, ...) { va_list ap; va_start(ap, msg); - vmessage(level, 0, msg, ap); + rb_vmessage(level, 0, msg, ap); va_end(ap); } @@ -165,7 +196,7 @@ rb_message (int level, const char* msg, ...) { va_list ap; va_start(ap, msg); - vmessage(level, 1, msg, ap); + rb_vmessage(level, 1, msg, ap); va_end(ap); } @@ -176,7 +207,7 @@ rb_message (int level, const char* msg, ...) static void usage() { - fprintf(stderr, "usage: rrdbotd [-c confdir] [-w workdir] [-d level] [-p pidfile] [-r retries] [-t timeout]\n"); + fprintf(stderr, "usage: rrdbotd [-M] [-c confdir] [-w workdir] [-d level] [-p pidfile] [-r retries] [-t timeout]\n"); fprintf(stderr, " rrdbotd -v\n"); exit(2); } @@ -212,6 +243,8 @@ main(int argc, char* argv[]) char ch; char* t; + /* test(argc, argv); */ + /* Initialize the state stuff */ memset(&g_state, 0, sizeof(g_state)); @@ -221,7 +254,7 @@ main(int argc, char* argv[]) g_state.timeout = DEFAULT_TIMEOUT; /* Parse the arguments nicely */ - while((ch = getopt(argc, argv, "c:d:p:r:t:w:v")) != -1) + while((ch = getopt(argc, argv, "c:d:Mp:r:t:w:v")) != -1) { switch(ch) { @@ -240,6 +273,11 @@ main(int argc, char* argv[]) debug_level += LOG_ERR; break; + /* MIB load warnings */ + case 'M': + g_mib_warnings = 1; + break; + /* Write out a pid file */ case 'p': pidfile = optarg; @@ -289,6 +327,11 @@ main(int argc, char* argv[]) /* Parse config and setup SNMP system */ rb_config_parse(); + + /* As an optimization we unload the MIB processing data here */ + rb_mib_uninit(); + + /* Rev up the main engine */ rb_snmp_engine_init(); if(daemonize) @@ -302,12 +345,12 @@ main(int argc, char* argv[]) } /* Handle signals */ - signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, SIG_IGN); - signal(SIGINT, on_quit); - signal(SIGTERM, on_quit); - siginterrupt(SIGINT, 1); - siginterrupt(SIGTERM, 1); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, on_quit); + signal(SIGTERM, on_quit); + siginterrupt(SIGINT, 1); + siginterrupt(SIGTERM, 1); /* Open the system log */ openlog("rrdbotd", 0, LOG_DAEMON); diff --git a/daemon/rrdbotd.h b/daemon/rrdbotd.h index 74f8fd5..ce16ebd 100644 --- a/daemon/rrdbotd.h +++ b/daemon/rrdbotd.h @@ -41,6 +41,7 @@ #include #include +#include #include "asn1.h" #include "snmp.h" @@ -147,8 +148,9 @@ extern rb_state g_state; * UTILITIES (rrdbotd.c) */ -void rb_messagex (int level, const char* msg, ...); -void rb_message (int level, const char* msg, ...); +void rb_messagex(int level, const char* msg, ...); +void rb_message(int level, const char* msg, ...); +void rb_vmessage(int level, int err, const char* msg, va_list ap); typedef void (*voidfunc)(void*); void rb_atexit (voidfunc func, void* data); @@ -179,4 +181,17 @@ void rb_snmp_engine_uninit(); void rb_rrd_update(rb_poller *poll); +/* ----------------------------------------------------------------------------- + * MIB PARSING + */ + +typedef void* mib_node; + +void rb_mib_init(int warnings); +mib_node rb_mib_lookup(const char* match); +int rb_mib_subid(mib_node n, const char* name); +void rb_mib_oid(mib_node n, struct asn_oid* oid); +mib_node rb_mib_node(struct asn_oid* oid); +void rb_mib_uninit(); + #endif /* __RRDBOTD_H__ */ diff --git a/daemon/snmp-help.c b/daemon/snmp-help.c index cf13d40..8a54bb1 100644 --- a/daemon/snmp-help.c +++ b/daemon/snmp-help.c @@ -46,9 +46,13 @@ #include "stringx.h" #include "rrdbotd.h" +/* Whether we print warnings when loading MIBs or not */ +extern int g_mib_warnings; + static int -parse_numeric_mib(const char* mib, struct asn_oid* oid) +parse_mixed_mib(const char* mib, struct asn_oid* oid) { + mib_node n; int ret = 0; unsigned int sub; char* next; @@ -58,37 +62,67 @@ parse_numeric_mib(const char* mib, struct asn_oid* oid) memset(oid, 0, sizeof(*oid)); - copy = src = strdup(mib); - if(!src) + copy = strdup(mib); + if(!copy) + { + errno = ENOMEM; return -1; + } - while(src && *src) + for(src = copy; src && *src; src = next) { next = strchr(src, '.'); if(next) + { *next = 0; + next++; + } sub = strtoul(src, &t, 10); - /* Too many parts */ - if(oid->len > ASN_MAXOIDLEN) - ret = -1; + /* An invalid number, try getting a named MIB */ + if(*t || sub < 0) + { + /* Only initializes first time around */ + rb_mib_init(g_mib_warnings); + + /* + * If we haven't parsed anything yet, try a symbolic + * search for root + */ + + if(oid->len == 0) + { + n = rb_mib_lookup(src); + if(n) + { + /* That took care of it */ + rb_mib_oid(n, oid); + continue; + } + } + + /* Try a by name search for sub item */ + n = rb_mib_node(oid); + if(n == NULL) + sub = -1; + else + sub = rb_mib_subid(n, src); + } - /* An invalid number */ - if(*t) + /* Make sure this is a valid part */ + if(sub < 0 || (oid->len == 0 && sub < 1) || sub >= ASN_MAXID) ret = -1; - /* Make sure this is a valid part */ - if((oid->len == 0 && sub < 1) || sub < 0 || sub >= ASN_MAXID) - ret -1; + /* Too many parts */ + if(oid->len > ASN_MAXOIDLEN) + ret = -1; if(ret < 0) break; oid->subs[oid->len] = sub; oid->len++; - - src = next ? next + 1 : NULL; } free(copy); @@ -96,16 +130,39 @@ parse_numeric_mib(const char* mib, struct asn_oid* oid) } int -rb_parse_mib(const char* mib, struct snmp_value* value) +rb_snmp_parse_mib(const char* mib, struct snmp_value* value) { - /* - * TODO: Eventually we'll have code here to parse symbolic - * names, and initialize snmp_value to the right type and - * all that jazz. For now we just have numeric OID support. - */ + int ret; + mib_node n; value->syntax = SNMP_SYNTAX_NULL; memset(&(value->v), 0, sizeof(value->v)); - return parse_numeric_mib(mib, &(value->var)); + /* An initial dot */ + if(*mib == '.') + mib++; + + /* + * First try parsing a numeric OID. This will fall + * back to mixed mode MIB's if necassary. Allows us + * to avoid loading all the MIB files when not + * necessary + */ + + ret = parse_mixed_mib(mib, &(value->var)); + + /* Next try a symolic search */ + if(ret == -1) + { + rb_mib_init(g_mib_warnings); + + n = rb_mib_lookup(mib); + if(n == NULL) + return -1; + + rb_mib_oid(n, &(value->var)); + return 0; + } + + return ret; } -- cgit v1.2.3