aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-02-15 15:43:56 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2012-02-15 17:24:43 +0200
commitefecb9a56bb848eb6b0dd45b9a69020e80ac8b0c (patch)
tree763bc75011389bc0eeb8a93a035c978da013295e
parent8af027bd45b4b12917ed8687c4846722b74f3a2c (diff)
downloadslb-efecb9a56bb848eb6b0dd45b9a69020e80ac8b0c.tar.gz
slb-efecb9a56bb848eb6b0dd45b9a69020e80ac8b0c.tar.bz2
Implement simple indexing feature.
* NEWS: Update. * src/config.c (cb_table,cb_index): New callbacks. (cb_server_variable): Implement index replacements in MIBs. (cb_server_assert): Clone locus. (server_kw): New keywords: table, index. (server_kw) <variable>: Change base ptr. (slb_server_new): Allocate srv->tables and srv->indices. * src/oidtab.c (oidtab_install): New function. (_create_ref): Call oidtab_install. * src/slb.h (slb_varinstance) <vi_mib>: Remove const qualifier. <vi_index,vi_idxpos,vi_locus>: New members. (slb_server) <test_pdu>: Rename to pdu. All uses updated. (oidtab_install,table_lookup,table_lookupz) (idxnum_lookup,idxnum_lookupz) (index_lookup,index_lookupz): New protos. (slb_table,slb_idxnum,slb_index): New structs. (slb_server) <tables,indices>: New members. * src/snmploop.c (process_next,_process_pdu) (asynch_response_next): New functions. (server_process_pdu): Rewrite using new functions. (send_requests): Handle unresolved oids. Return number of ones waiting to be resolved. (resolve_tables): New function. (snmploop): Resolve tables as necessary. * src/symimp.c (table_lookup,table_lookupz) (index_lookup,index_lookupz) (idxnum_lookup,idxnum_lookupz): New functions.
-rw-r--r--NEWS22
-rw-r--r--configure.ac4
-rw-r--r--src/config.c169
-rw-r--r--src/oidtab.c14
-rw-r--r--src/slb.h54
-rw-r--r--src/snmploop.c295
-rw-r--r--src/symimp.c45
-rw-r--r--src/test.c16
8 files changed, 566 insertions, 53 deletions
diff --git a/NEWS b/NEWS
index 6633d2a..a7b3dbb 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,11 @@
-SLB NEWS -- history of user-visible changes. 2011-05-11
-Copyright (C) 2011 Sergey Poznyakoff
+SLB NEWS -- history of user-visible changes. 2012-02-15
+Copyright (C) 2011, 2012 Sergey Poznyakoff
See the end of file for copying conditions.
Please send SLB bug reports to <gray+slb@gnu.org.ua>
-Version 1.0.92 (Git)
+Version 1.0.93 (Git)
* Support SNMPv3
* Default SNMP version is 2c
@@ -14,7 +14,21 @@ Version 1.0.92 (Git)
* Variable assignments in expressions
* Detection of SNMP counter overflows
* Comma operator
+* Support for indexed MIBs
+This feature allows you to use symbolic names instead of the fixed MIBs
+for MIBs that are part of SNMP subtrees. For example, to get number of
+packets sent over eth0 into variable "out", you would do the following:
+
+ table iftable IF-MIB::ifDescr;
+ index x eth0 iftable;
+ variable out "IF-MIB::ifOutUcastPkts.$x";
+
+The first statement converts entire subtree into a "table" named "iftable".
+The second one defines "x" as an index into an entry in that table that has
+the value "eth0".
+Finally, in the third statement, this index is used to define a MIB.
+
Version 1.0, 2011-04-26
@@ -24,7 +38,7 @@ First release.
=========================================================================
Copyright information:
-Copyright (C) 2011 Sergey Poznyakoff
+Copyright (C) 2011, 2012 Sergey Poznyakoff
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/configure.ac b/configure.ac
index 893bd81..74082bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
# This file is part of SLB -*- autoconf -*-
-# Copyright (C) 2011 Sergey Poznyakoff
+# Copyright (C) 2011, 2012 Sergey Poznyakoff
#
# SLB is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
# along with SLB. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ(2.63)
-AC_INIT([slb], 1.0.92, [gray+slb@gnu.org.ua])
+AC_INIT([slb], 1.0.93, [gray+slb@gnu.org.ua])
AC_CONFIG_SRCDIR([src/slb.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADER([config.h])
diff --git a/src/config.c b/src/config.c
index b28a22a..3bc4126 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,5 +1,5 @@
/* This file is part of SLB
- Copyright (C) 2011 Sergey Poznyakoff
+ Copyright (C) 2011, 2012 Sergey Poznyakoff
SLB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,6 +15,7 @@
along with SLB. If not, see <http://www.gnu.org/licenses/>. */
#include "slb.h"
+#include "wordsplit.h"
struct grecs_list *mib_file_list;
@@ -165,13 +166,93 @@ cb_server_expression(enum grecs_callback_command cmd,
}
int
+cb_table(enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value,
+ void *cb_data)
+{
+ struct grecs_symtab *tp = *(struct grecs_symtab **)varptr;
+ struct slb_table *tab;
+ size_t oidlen;
+ oid oid[MAX_OID_LEN];
+ int install;
+
+ if (assert_n_strings(locus, cmd, value, 2, 2))
+ return 1;
+
+ oidlen = MAX_OID_LEN;
+ if (!read_objid(value->v.arg.v[1]->v.string, oid, &oidlen)) {
+ grecs_error(locus, 0, _("cannot parse oid"));
+ return 1;
+ }
+
+ install = 1;
+ tab = table_lookupz(tp, value->v.arg.v[0]->v.string, &install);
+ if (!install) {
+ grecs_error(locus, 0,
+ _("redefinition of table %s"), tab->tab_sym.name);
+ grecs_symtab_clear(tab->tab_idx);
+ } else
+ tab->tab_idx = grecs_symtab_create_default(sizeof(size_t));
+
+ tab->tab_oidlen = oidlen;
+ memcpy(tab->tab_oid, oid, sizeof(oid));
+
+ return 0;
+}
+
+int
+cb_index(enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value,
+ void *cb_data)
+{
+ struct slb_server *srv = varptr;
+ struct slb_table *tab;
+ struct slb_index *idx;
+ int install;
+
+ if (assert_n_strings(locus, cmd, value, 3, 3))
+ return 1;
+ tab = table_lookupz(srv->tables, value->v.arg.v[2]->v.string, NULL);
+ if (!tab) {
+ grecs_error(locus, 0,
+ _("no SNMP table of such name known: %s"),
+ value->v.arg.v[2]->v.string);
+ return 1;
+ }
+
+ install = 1;
+ idx = index_lookupz(srv->indices, value->v.arg.v[0]->v.string,
+ &install);
+ if (!install)
+ grecs_error(locus, 0,
+ _("redefinition of table %s"), tab->tab_sym.name);
+ idx->idx_table = tab;
+ idx->idx_tag = grecs_strdup(value->v.arg.v[1]->v.string);
+
+ return 0;
+}
+
+static void
+clone_locus(grecs_locus_t *dst, grecs_locus_t *src)
+{
+ *dst = *src;
+ dst->beg.file = grecs_strdup(dst->beg.file);
+ dst->end.file = grecs_strdup(dst->end.file);
+}
+
+int
cb_server_variable(enum grecs_callback_command cmd,
grecs_locus_t *locus,
void *varptr,
grecs_value_t *value,
void *cb_data)
{
- struct grecs_symtab *vt = *(struct grecs_symtab **)varptr;
+ struct slb_server *srv = varptr;
+ struct grecs_symtab *vt = srv->varinst;
struct slb_varinstance *inst;
int install;
char *name;
@@ -187,15 +268,77 @@ cb_server_variable(enum grecs_callback_command cmd,
if (!install)
grecs_error(locus, 0,
_("redefinition of %s"), inst->vi_sym.name);
+ clone_locus(&inst->vi_locus, locus);
if (value->type == GRECS_TYPE_ARRAY && value->v.arg.c >= 2) {
+ struct wordsplit ws;
+ int err = 0;
+ size_t i;
+
+ ws.ws_delim = ".";
+ if (wordsplit(value->v.arg.v[1]->v.string, &ws,
+ WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM)) {
+ grecs_error(locus, 0,
+ _("can't split oid: %s"),
+ wordsplit_strerror(&ws));
+ return 1;
+ }
+
+ for (i = 0; i < ws.ws_wordc; i++) {
+ if (ws.ws_wordv[i][0] == '$') {
+ char *name = ws.ws_wordv[i] + 1;
+
+ if (inst->vi_index) {
+ grecs_error(locus, 0,
+ _("OID can have at most "
+ "one index"));
+ err = 1;
+ break;
+ }
+
+ inst->vi_index = index_lookupz(srv->indices,
+ name,
+ NULL);
+ if (!inst->vi_index) {
+ grecs_error(locus, 0,
+ _("unknown index: %s"),
+ name);
+ err = 1;
+ break;
+ }
+ inst->vi_idxpos = ws.ws_wordc - i;
+ }
+
+ }
+ wordsplit_free(&ws);
+ if (err)
+ return 1;
+
+ inst->vi_mib = grecs_strdup(value->v.arg.v[1]->v.string);
+ if (inst->vi_index) {
+ char *str = (char*)inst->vi_mib;
+ char *p, *q;
+
+ for (p = str + strlen(str) - 1, i = 0; p > str; p--) {
+ if (*p == '.' && ++i == inst->vi_idxpos)
+ break;
+ }
+ ++p;
+ *p++ = '1';
+ q = strchr(p, '.');
+ if (q == NULL)
+ *p++ = 0;
+ else if (q > p)
+ memmove(p, q, strlen(q) + 1);
+ srv->flags |= SLB_SRV_TAB_REFERENCED;
+ }
+
inst->vi_oidlen = MAX_OID_LEN;
- if (!read_objid(value->v.arg.v[1]->v.string,
- inst->vi_oid, &inst->vi_oidlen)) {
+ if (!read_objid(inst->vi_mib, inst->vi_oid,
+ &inst->vi_oidlen)) {
grecs_error(locus, 0, _("cannot parse oid"));
return 1;
}
- inst->vi_mib = grecs_strdup(value->v.arg.v[1]->v.string);
inst->vi_flags = SLV_VIF_SNMP;
if (value->v.arg.c == 3) {
@@ -299,7 +442,7 @@ cb_server_assert(enum grecs_callback_command cmd,
ap->value = grecs_strdup(value->v.arg.v[2]->v.string);
ap->flags = flags;
- ap->locus = *locus;
+ clone_locus(&ap->locus, locus);
return 0;
}
@@ -616,10 +759,20 @@ static struct grecs_keyword server_kw[] = {
grecs_type_string, GRECS_AGGR,
NULL, offsetof(struct slb_server, expr),
cb_server_expression },
+ { "table", N_("<name: string> <base-oid: string>"),
+ N_("Define SNMP table"),
+ grecs_type_string, GRECS_DFLT,
+ NULL, offsetof(struct slb_server, tables),
+ cb_table },
+ { "index", N_("<name: string> <tag: string> <table: string>"),
+ N_("Define an index into SNMP table"),
+ grecs_type_string, GRECS_DFLT,
+ NULL, 0,
+ cb_index },
{ "variable", N_("<name: string> <oid: string>"),
N_("Define SNMP variable"),
grecs_type_string, GRECS_MULT,
- NULL, offsetof(struct slb_server, varinst),
+ NULL, 0,
cb_server_variable },
{ "constant", N_("<name: string> <value: string>"),
N_("Define a constant"),
@@ -647,6 +800,8 @@ slb_server_new(const char *id)
srv->snmpver = snmp_version;
srv->varinst = grecs_symtab_create_default(sizeof(struct slb_varinstance));
srv->macros = grecs_symtab_create_default(sizeof(struct slb_macro));
+ srv->tables = grecs_symtab_create_default(sizeof(struct slb_table));
+ srv->indices = grecs_symtab_create_default(sizeof(struct slb_index));
srv->assertions = assertion_symtab_create();
return srv;
}
diff --git a/src/oidtab.c b/src/oidtab.c
index c6d4c28..c713a2b 100644
--- a/src/oidtab.c
+++ b/src/oidtab.c
@@ -63,16 +63,22 @@ oidref_free(void *p)
free(p);
}
-static int
-_create_ref(void *sym, void *data)
+int
+oidtab_install(struct grecs_symtab *oidtab, struct slb_varinstance *vinst)
{
- struct slb_varinstance *vinst = sym;
- struct grecs_symtab *oidtab = data;
struct slb_oidref key;
int install = 1;
key.inst = vinst;
return grecs_symtab_lookup_or_install(oidtab, &key, &install) == NULL;
+}
+
+static int
+_create_ref(void *sym, void *data)
+{
+ struct slb_varinstance *vinst = sym;
+ struct grecs_symtab *oidtab = data;
+ return oidtab_install(oidtab, vinst);
}
struct grecs_symtab *
diff --git a/src/slb.h b/src/slb.h
index 31fb0e5..20ab712 100644
--- a/src/slb.h
+++ b/src/slb.h
@@ -1,5 +1,5 @@
/* This file is part of SLB
- Copyright (C) 2011 Sergey Poznyakoff
+ Copyright (C) 2011, 2012 Sergey Poznyakoff
SLB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -176,12 +176,15 @@ struct slb_varref {
struct slb_varinstance {
struct grecs_syment vi_sym;
- const char *vi_mib;
+ char *vi_mib;
oid vi_oid[MAX_OID_LEN];
size_t vi_oidlen;
double vi_value;
int vi_flags;
char *vi_extra;
+ struct slb_index *vi_index;
+ size_t vi_idxpos;
+ grecs_locus_t vi_locus;
};
struct slb_expression {
@@ -224,9 +227,44 @@ void varinst_clear(struct grecs_symtab *vit);
int varinst_allset(struct grecs_symtab *vit);
struct grecs_symtab *create_oidtab(struct grecs_symtab *vit);
+int oidtab_install(struct grecs_symtab *oidtab, struct slb_varinstance *vinst);
struct slb_varinstance *oidtab_lookup(struct grecs_symtab *oidtab,
oid *name, size_t name_length);
+
+struct slb_table {
+ struct grecs_syment tab_sym;
+ oid tab_oid[MAX_OID_LEN];
+ size_t tab_oidlen;
+ struct grecs_symtab *tab_idx;
+};
+
+struct slb_table *table_lookup(struct grecs_symtab *tab, const char *name,
+ size_t len, int *install);
+struct slb_table *table_lookupz(struct grecs_symtab *tab, const char *name,
+ int *install);
+
+struct slb_idxnum {
+ struct grecs_syment idxnum_sym;
+ size_t idxnum_num;
+};
+
+struct slb_idxnum *idxnum_lookup(struct grecs_symtab *tab,
+ const char *name, size_t len,
+ int *install);
+struct slb_idxnum *idxnum_lookupz(struct grecs_symtab *tab, const char *name,
+ int *install);
+
+
+struct slb_index {
+ struct grecs_syment idx_sym;
+ char *idx_tag;
+ struct slb_table *idx_table;
+};
+struct slb_index *index_lookup(struct grecs_symtab *tab, const char *name,
+ size_t len, int *install);
+struct slb_index *index_lookupz(struct grecs_symtab *tab, const char *name,
+ int *install);
int symtab_register_expression(struct grecs_symtab **pexptab,
struct slb_expression *expr);
@@ -291,8 +329,10 @@ struct slb_snmp_v3 {
u_int engine_time; /* initial engine time for remote engine */
};
-#define SLB_SRV_DISABLED 0x01
-#define SLB_SRV_COMPUTED 0x02
+#define SLB_SRV_DISABLED 0x01 /* Server is disabled */
+#define SLB_SRV_COMPUTED 0x02 /* Expression has been computed */
+#define SLB_SRV_TAB_REFERENCED 0x04 /* Variables refer to SNMP tables */
+#define SLB_SRV_TAB_RESOLVED 0x08 /* Table references resolved */
struct slb_server {
char *id; /* Server ID */
@@ -309,14 +349,18 @@ struct slb_server {
struct grecs_symtab *oidtab; /* A reverse index to the entries from
varinst */
struct grecs_symtab *macros; /* Defined macros */
+ struct grecs_symtab *tables; /* SNMP tables */
+ struct grecs_symtab *indices; /* Indices to SNMP tables */
struct slb_node_state *state; /* Preserved node states for expression
evaluator */
struct grecs_symtab *exprtab; /* Table of expressions used by
output driver of this server */
struct slb_expression *expr; /* Expression returning the server
load "weight" */
+
struct snmp_session *sess; /* SNMP session */
- struct snmp_pdu *test_pdu; /* A PDU used only in test mode */
+ struct snmp_pdu *pdu; /* PDU used in test mode and when handling
+ GETNEXT requests. */
double weight; /* Last computed server weight (relative load) */
int flags; /* Server flags */
struct slb_server *next; /* Next server in the list */
diff --git a/src/snmploop.c b/src/snmploop.c
index d54b84f..c39a159 100644
--- a/src/snmploop.c
+++ b/src/snmploop.c
@@ -1,5 +1,5 @@
/* This file is part of SLB
- Copyright (C) 2011 Sergey Poznyakoff
+ Copyright (C) 2011, 2012 Sergey Poznyakoff
SLB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -122,10 +122,11 @@ process_result(struct slb_server *srv, struct snmp_pdu *pdu)
vp->name_length, NULL);
if (ap && assertion_test(ap, vp)) {
logmsg(LOG_NOTICE,
- "%s:%d: %s: assertion \"%s\" failed",
+ "%s:%d: %s: assertion \"%s\" failed, got %s",
ap->locus.beg.file, ap->locus.beg.line,
srvid(srv),
- ap->text);
+ ap->text,
+ ap->buf);
return;
}
@@ -177,27 +178,156 @@ process_result(struct slb_server *srv, struct snmp_pdu *pdu)
}
}
-void
-server_process_pdu(int operation, struct slb_server *srv, struct snmp_pdu *pdu)
+static int
+slb_table_grow(struct slb_table *tab, struct variable_list *vp)
+{
+ size_t out_len = 0;
+ size_t bufsize = 16;
+ unsigned char *buf = grecs_malloc(bufsize);
+ struct slb_idxnum *ent;
+ int install = 1;
+ int rc;
+
+ /* This is needed by sprint_realloc_value.
+ Very unfortunate. */
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_QUICK_PRINT, 1);
+ rc = sprint_realloc_value(&buf, &bufsize, &out_len,
+ 1, vp->name, vp->name_length, vp);
+ /* On the other hand, assertions assume data type prefix */
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_QUICK_PRINT, 0);
+ if (rc == 0) {
+ logmsg(LOG_ERR,
+ "cannot format variable: %s",
+ snmp_api_errstring(snmp_errno));
+ return 1;
+ }
+
+ ent = idxnum_lookupz(tab->tab_idx, buf, &install);
+ ent->idxnum_num = vp->name[tab->tab_oidlen];
+
+ return 0;
+}
+
+struct table_match_closure {
+ struct grecs_symtab *tables;
+ oid *oid;
+ size_t oidlen;
+ struct slb_table *result;
+};
+
+static int
+table_match_var(void *sym, void *data)
+{
+ struct slb_table *tab = sym;
+ struct table_match_closure *clos = data;
+
+ if (clos->oidlen >= tab->tab_oidlen
+ && memcmp(tab->tab_oid, clos->oid,
+ tab->tab_oidlen * sizeof(clos->oid[0])) == 0) {
+ /* Select longest matching prefix */
+ if (!clos->result ||
+ clos->result->tab_oidlen < tab->tab_oidlen)
+ clos->result = tab;
+ }
+ return 0;
+}
+
+static struct slb_table *
+oid_to_table(struct slb_server *srv, oid *oid, size_t oidlen)
+{
+ struct table_match_closure clos;
+
+ clos.tables = srv->tables;
+ clos.oid = oid;
+ clos.oidlen = oidlen;
+ clos.result = NULL;
+ grecs_symtab_enumerate(srv->tables, table_match_var, &clos);
+ return clos.result;
+}
+
+
+static void
+process_next(struct slb_server *srv, struct snmp_pdu *pdu)
+{
+ struct variable_list *vp;
+ struct snmp_pdu *pdu2;
+ size_t varcnt = 0;
+
+ if (debug_level[SLB_DEBCAT_SNMP] >= 2 &&
+ !(srv->flags & SLB_SRV_COMPUTED)) {
+ debug_printf("%s replied", srvid(srv));
+ srv->flags |= SLB_SRV_COMPUTED;
+ }
+ debug(SLB_DEBCAT_SNMP, 10, ("reply from %s", srvid(srv)));
+
+ pdu2 = snmp_clone_pdu(srv->pdu);
+ snmp_free_varbind(pdu2->variables);
+ pdu2->variables = NULL;
+ srv->pdu = pdu2;
+
+ for (vp = pdu->variables; vp; vp = vp->next_variable) {
+ struct slb_table *tab =
+ oid_to_table(srv, vp->name, vp->name_length);
+ if (!tab)
+ continue;
+ slb_table_grow(tab, vp);
+ snmp_add_null_var(pdu2, vp->name, vp->name_length);
+ varcnt++;
+ }
+
+ if (varcnt && snmp_send(srv->sess, pdu2))
+ active_count++;
+ else
+ snmp_free_pdu(pdu2);
+}
+
+static void
+_process_pdu(int operation, struct slb_server *srv,
+ struct snmp_pdu *pdu,
+ void (*proc)(struct slb_server *, struct snmp_pdu *),
+ int clrflag)
{
if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
- process_result(srv, pdu);
+ proc(srv, pdu);
} else {
logmsg(LOG_ERR, "server %s: timeout", srvid(srv));
/* Re-initialize server state */
slb_node_state_init(srv->state);
srv->expr->ex_eval_count = 0;
+ if (clrflag)
+ srv->flags &= ~clrflag;
}
}
+void
+server_process_pdu(int operation, struct slb_server *srv,
+ struct snmp_pdu *pdu)
+{
+ _process_pdu(operation, srv, pdu, process_result, 0);
+}
+
int
asynch_response(int operation, struct snmp_session *sp, int reqid,
struct snmp_pdu *pdu, void *magic)
{
struct slb_server *srv = magic;
- server_process_pdu(operation, srv, pdu);
active_count--;
+ _process_pdu(operation, srv, pdu, process_result, 0);
+ return 1;
+}
+
+int
+asynch_response_next(int operation, struct snmp_session *sp, int reqid,
+ struct snmp_pdu *pdu, void *magic)
+{
+ struct slb_server *srv = magic;
+
+ active_count--;
+ _process_pdu(operation, srv, pdu, process_next,
+ SLB_SRV_TAB_RESOLVED);
return 1;
}
@@ -223,11 +353,21 @@ add_snmp_assertion(void *sym, void *data)
return 0;
}
-static void
+static int
+add_table_var(void *sym, void *data)
+{
+ struct slb_table *tab = sym;
+ struct snmp_pdu *req = data;
+ snmp_add_null_var(req, tab->tab_oid, tab->tab_oidlen);
+ return 0;
+}
+
+static size_t
send_requests()
{
struct slb_server *srv;
-
+ size_t refcnt = 0;
+
debug(SLB_DEBCAT_SNMP, 1, ("sending requests"));
for (srv = srv_head; srv; srv = srv->next) {
struct snmp_session sess;
@@ -296,25 +436,43 @@ send_requests()
sess.engineBoots = srv->snmp_v3.engine_boots;
sess.engineTime = srv->snmp_v3.engine_time;
}
-
- sess.callback = asynch_response;
+
sess.callback_magic = srv;
+
+ if ((srv->flags & SLB_SRV_TAB_REFERENCED) &&
+ !(srv->flags & SLB_SRV_TAB_RESOLVED)) {
+ sess.callback = asynch_response_next;
+ refcnt++;
+
+ req = snmp_pdu_create(SNMP_MSG_GETNEXT);
+ grecs_symtab_enumerate(srv->tables, add_table_var,
+ req);
+ srv->flags |= SLB_SRV_TAB_RESOLVED;
+ } else {
+ sess.callback = asynch_response;
+ varinst_unset(srv->varinst);
+
+ req = snmp_pdu_create(SNMP_MSG_GET);
+ grecs_symtab_enumerate(srv->varinst,
+ add_snmp_var,
+ req);
+ grecs_symtab_enumerate(srv->assertions,
+ add_snmp_assertion,
+ req);
+ }
+ srv->flags &= ~SLB_SRV_COMPUTED;
+
if (!(srv->sess = snmp_open(&sess))) {
- logmsg(LOG_ERR, "server %s: snmp_open failed: %s",
- srvid(srv), snmp_api_errstring(snmp_errno));
+ logmsg(LOG_ERR,
+ "server %s: snmp_open failed: %s",
+ srvid(srv),
+ snmp_api_errstring(snmp_errno));
continue;
}
- varinst_unset(srv->varinst);
- srv->flags &= ~SLB_SRV_COMPUTED;
-
- req = snmp_pdu_create(SNMP_MSG_GET);
- grecs_symtab_enumerate(srv->varinst, add_snmp_var, req);
- grecs_symtab_enumerate(srv->assertions, add_snmp_assertion,
- req);
-
if (snmp_send(srv->sess, req)) {
active_count++;
+ srv->pdu = req;
} else {
logmsg(LOG_ERR, "server %s: snmp_send failed: %s",
srvid(srv), snmp_api_errstring(snmp_errno));
@@ -323,6 +481,92 @@ send_requests()
srv->sess = NULL;
}
}
+ return refcnt;
+}
+
+static int
+resolve_varinst_index(void *sym, void *data)
+{
+ struct slb_varinstance *vinst = sym;
+ struct slb_server *srv = data;
+
+ if (vinst->vi_index) {
+ struct slb_index *idx = vinst->vi_index;
+ struct slb_idxnum *ent =
+ idxnum_lookupz(idx->idx_table->tab_idx,
+ idx->idx_tag, NULL);
+ if (ent) {
+ unsigned char *buf;
+ size_t buf_len = 256;
+ size_t out_len = 0;
+ int ovf = 0;
+
+ vinst->vi_oid[vinst->vi_oidlen - vinst->vi_idxpos] =
+ ent->idxnum_num;
+
+ buf = grecs_malloc(buf_len);
+ netsnmp_sprint_realloc_objid(&buf,
+ &buf_len,
+ &out_len, 1,
+ &ovf,
+ vinst->vi_oid,
+ vinst->vi_oidlen);
+
+ logmsg(LOG_INFO,
+ "%s:%d: (%s) %s resolved to %s",
+ vinst->vi_locus.beg.file,
+ vinst->vi_locus.beg.line,
+ srvid(srv),
+ vinst->vi_mib,
+ buf);
+
+ /* FIXME: This has a side effect of converting
+ the MIB to numeric form. */
+ free(vinst->vi_mib);
+ vinst->vi_mib = buf;
+ oidtab_install(srv->oidtab, vinst);
+ return 0;
+ }
+
+ logmsg(LOG_NOTICE,
+ "%s:%d: cannot resolve %s; disabling server %s",
+ vinst->vi_locus.beg.file,
+ vinst->vi_locus.beg.line,
+ vinst->vi_mib,
+ srvid(srv));
+ srv->flags |= SLB_SRV_DISABLED;
+ return 1;
+ }
+ return 0;
+}
+
+#if 0
+static int
+resolve_assertion_index(void *sym, void *data)
+{
+ struct slb_assertion *ap = sym;
+ struct slb_server *srv = data;
+ return 1;//FIXME
+}
+#endif
+
+static void
+resolve_tables()
+{
+ struct slb_server *srv;
+ for (srv = srv_head; srv; srv = srv->next) {
+ if (srv->flags & SLB_SRV_DISABLED ||
+ !(srv->flags & SLB_SRV_TAB_RESOLVED))
+ continue;
+ grecs_symtab_enumerate(srv->varinst,
+ resolve_varinst_index,
+ srv);
+#if 0
+ grecs_symtab_enumerate(srv->assertions,
+ resolve_assertion_index,
+ srv);
+#endif
+ }
}
static void
@@ -403,7 +647,14 @@ snmploop()
{
active_count = 0;
slb_loop_serial++;
- send_requests();
+ if (send_requests()) {
+ /* Process tables */
+ debug(SLB_DEBCAT_SNMP, 2, ("getting subtrees"));
+ recv_loop();
+ debug(SLB_DEBCAT_SNMP, 2, ("resolving indexed variables"));
+ resolve_tables();
+ send_requests();
+ }
slb_loop_ts = time(NULL);
recv_loop();
sess_cleanup();
diff --git a/src/symimp.c b/src/symimp.c
index 2d54c18..d8d693c 100644
--- a/src/symimp.c
+++ b/src/symimp.c
@@ -1,5 +1,5 @@
/* This file is part of SLB
- Copyright (C) 2011 Sergey Poznyakoff
+ Copyright (C) 2011, 2012 Sergey Poznyakoff
SLB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -163,3 +163,46 @@ macro_lookupz(struct grecs_symtab *mt, const char *name, int *install)
_lookupz(mt, name, install, "macro");
}
+struct slb_table *
+table_lookup(struct grecs_symtab *tab, const char *name, size_t len,
+ int *install)
+{
+ return (struct slb_table *)
+ _lookup(tab, name, len, install, "table");
+}
+
+struct slb_table *
+table_lookupz(struct grecs_symtab *tab, const char *name, int *install)
+{
+ return (struct slb_table *)
+ _lookupz(tab, name, install, "table");
+}
+
+struct slb_index *
+index_lookup(struct grecs_symtab *tab, const char *name, size_t len,
+ int *install)
+{
+ return (struct slb_index *)
+ _lookup(tab, name, len, install, "index");
+}
+
+struct slb_index *
+index_lookupz(struct grecs_symtab *tab, const char *name, int *install)
+{
+ return (struct slb_index *)
+ _lookupz(tab, name, install, "index");
+}
+
+struct slb_idxnum *
+idxnum_lookup(struct grecs_symtab *tab, const char *name, size_t len,
+ int *install)
+{
+ return (struct slb_idxnum *)
+ _lookup(tab, name, len, install, "idxnum");
+}
+
+struct slb_idxnum *
+idxnum_lookupz(struct grecs_symtab *tab, const char *name, int *install)
+{
+ return (struct slb_idxnum *) _lookupz(tab, name, install, "indnum");
+}
diff --git a/src/test.c b/src/test.c
index 765849c..c034341 100644
--- a/src/test.c
+++ b/src/test.c
@@ -85,8 +85,8 @@ input_read_server(struct slb_server *srv)
int wsflags = WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE |
WRDSF_SQUEEZE_DELIMS;
- if (!srv->test_pdu)
- srv->test_pdu = snmp_pdu_create(SNMP_MSG_GET);
+ if (!srv->pdu)
+ srv->pdu = snmp_pdu_create(SNMP_MSG_GET);
while (1) {
oid oid[MAX_OID_LEN];
size_t oidlen;
@@ -127,7 +127,7 @@ input_read_server(struct slb_server *srv)
continue;
}
- if (snmp_add_var(srv->test_pdu, oid, oidlen,
+ if (snmp_add_var(srv->pdu, oid, oidlen,
*ws.ws_wordv[1], ws.ws_wordv[2])) {
logmsg(LOG_CRIT,
"%s:%d: cannot add variable: %s",
@@ -151,14 +151,14 @@ test_server_replies()
varinst_unset(srv->varinst);
srv->flags &= ~SLB_SRV_COMPUTED;
- server_process_pdu(srv->test_pdu ?
+ server_process_pdu(srv->pdu ?
NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE :
NETSNMP_CALLBACK_OP_TIMED_OUT,
srv,
- srv->test_pdu);
- if (srv->test_pdu) {
- snmp_free_pdu(srv->test_pdu);
- srv->test_pdu = NULL;
+ srv->pdu);
+ if (srv->pdu) {
+ snmp_free_pdu(srv->pdu);
+ srv->pdu = NULL;
}
}
sort();

Return to:

Send suggestions and report system problems to the System administrator.