diff options
Diffstat (limited to 'src/snmploop.c')
-rw-r--r-- | src/snmploop.c | 169 |
1 files changed, 120 insertions, 49 deletions
diff --git a/src/snmploop.c b/src/snmploop.c index 5d1e98e..3ce638f 100644 --- a/src/snmploop.c +++ b/src/snmploop.c @@ -66,6 +66,40 @@ slb_format_oid_value(oid *oid, size_t len, struct variable_list *vp, return (char*) cache->cache_buffer; } +static int +assrt_clear_prev(void *sym, void *data) +{ + struct slb_assertion *ap = sym; + if (ap->flags & SLB_ASSERT_PREV) { + free(ap->value); + ap->value = NULL; + } + return 0; +} + +static int +table_clear(void *sym, void *data) +{ + struct slb_table *tab = sym; + grecs_symtab_clear(tab->tab_idx); + return 0; +} + +/* Re-initialize server state */ +static int +slb_server_init(struct slb_server *srv, int clrflag) +{ + slb_node_state_init(srv->state); + srv->expr->ex_eval_count = 0; + grecs_symtab_enumerate(srv->assertions, + assrt_clear_prev, + NULL); + if (clrflag) { + grecs_symtab_enumerate(srv->tables, table_clear, NULL); + srv->flags &= ~clrflag; + } +} + #define E_VARINST_OK 0 #define E_VARINST_UNSUPPORTED 1 #define E_VARINST_OVERFLOW 2 @@ -125,7 +159,8 @@ varinst_assign(struct slb_varinstance *inst, struct variable_list *var, } static int -assertion_test(struct slb_assertion *ap, struct variable_list *vp) +assertion_test(struct slb_server *srv, struct slb_assertion *ap, + struct variable_list *vp) { size_t out_len = 0; int rc; @@ -134,40 +169,55 @@ assertion_test(struct slb_assertion *ap, struct variable_list *vp) buf = slb_format_oid_value(ap->name, ap->length, vp, &ap->cache); if (!buf) return 1; - switch (ap->opcode) { - case SLB_ASSERT_EQ: - rc = ((ap->flags & SLB_ASSERT_ICASE) ? strcasecmp : strcmp) - (ap->value, buf)== 0; - break; - case SLB_ASSERT_PREFIX: - rc = strlen(buf) >= ap->vallen && - ((ap->flags & SLB_ASSERT_ICASE) ? - strncasecmp : strncmp) (buf, ap->value, ap->vallen) - == 0; - break; - case SLB_ASSERT_SUFFIX: - rc = strlen(buf) >= ap->vallen && - ((ap->flags & SLB_ASSERT_ICASE) ? - strncasecmp : strncmp) - (buf + strlen(buf) - ap->vallen, - ap->value, ap->vallen) == 0; - break; - case SLB_ASSERT_GLOB: - rc = wildmatch(ap->value, buf, - ap->flags & SLB_ASSERT_ICASE) == 0; - break; - case SLB_ASSERT_EQUAL: - /* FIXME */ - rc = strtoul(buf, NULL, 10) == strtoul(ap->value, NULL, 10); - break; - case SLB_ASSERT_LT: - rc = strtoul(buf, NULL, 10) < strtoul(ap->value, NULL, 10); - break; - case SLB_ASSERT_LE: - rc = strtoul(buf, NULL, 10) <= strtoul(ap->value, NULL, 10); + + if (!ap->value) { + rc = 1; + } else { + switch (ap->opcode) { + case SLB_ASSERT_EQ: + rc = ((ap->flags & SLB_ASSERT_ICASE) ? + strcasecmp : strcmp) + (ap->value, buf) == 0; + break; + case SLB_ASSERT_PREFIX: + rc = strlen(buf) >= ap->vallen && + ((ap->flags & SLB_ASSERT_ICASE) ? + strncasecmp : strncmp) + (buf, ap->value, ap->vallen) == 0; + break; + case SLB_ASSERT_SUFFIX: + rc = strlen(buf) >= ap->vallen && + ((ap->flags & SLB_ASSERT_ICASE) ? + strncasecmp : strncmp) + (buf + strlen(buf) - ap->vallen, + ap->value, ap->vallen) == 0; + break; + case SLB_ASSERT_GLOB: + rc = wildmatch(ap->value, buf, + ap->flags & SLB_ASSERT_ICASE) == 0; + break; + case SLB_ASSERT_EQUAL: + /* FIXME */ + rc = strtoul(buf, NULL, 10) == + strtoul(ap->value, NULL, 10); + break; + case SLB_ASSERT_LT: + rc = strtoul(buf, NULL, 10) < + strtoul(ap->value, NULL, 10); + break; + case SLB_ASSERT_LE: + rc = strtoul(buf, NULL, 10) <= + strtoul(ap->value, NULL, 10); + } + if (ap->flags & SLB_ASSERT_NEG) + rc = !rc; + } + + if (ap->flags & SLB_ASSERT_PREV) { + free(ap->value); + ap->value = grecs_strdup(buf); + ap->vallen = strlen(ap->value); } - if (ap->flags & SLB_ASSERT_NEG) - rc = !rc; return rc; } @@ -184,14 +234,40 @@ process_result(struct slb_server *srv, struct snmp_pdu *pdu) ap = assertion_lookup(srv->assertions, vp->name, vp->name_length, NULL); - if (ap && !assertion_test(ap, vp)) { - logmsg(LOG_NOTICE, - "%s:%d: %s: assertion \"%s\" failed, got %s", - ap->locus.beg.file, ap->locus.beg.line, - srvid(srv), - ap->text, - ap->cache.cache_buffer); - return; + if (ap && !assertion_test(srv, ap, vp)) { + switch (ap->action) { + case SLB_ASSERT_ABORT: + logmsg(LOG_NOTICE, + "%s:%d: %s: assertion \"%s\" failed, " + "got %s", + ap->locus.beg.file, ap->locus.beg.line, + srvid(srv), + ap->text, + ap->cache.cache_buffer); + return; + + case SLB_ASSERT_WARN: + logmsg(LOG_NOTICE, + "%s:%d: %s: warning: " + "assertion \"%s\" failed, " + "got %s", + ap->locus.beg.file, ap->locus.beg.line, + srvid(srv), + ap->text, + ap->cache.cache_buffer); + break; + + case SLB_ASSERT_REINIT: + logmsg(LOG_NOTICE, + "%s:%d: %s: assertion \"%s\" failed " + "(got %s); re-initializing server", + ap->locus.beg.file, ap->locus.beg.line, + srvid(srv), + ap->text, + ap->cache.cache_buffer); + slb_server_init(srv, SLB_SRV_TAB_RESOLVED); + return; + } } inst = oidtab_lookup(srv->oidtab, vp->name, vp->name_length); @@ -312,7 +388,6 @@ oid_to_table(struct slb_server *srv, oid *oid, size_t oidlen) return clos.result; } - static void process_next(struct slb_server *srv, struct snmp_pdu *pdu) { @@ -358,11 +433,7 @@ _process_pdu(int operation, struct slb_server *srv, 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; + slb_server_init(srv, clrflag); } } @@ -592,7 +663,7 @@ resolve_tabref(struct slb_varinstance *vinst, struct slb_server *srv) grecs_txtacc_grow_char(acc, 0); mib = grecs_txtacc_finish(acc, 0); vinst->vi_oidlen = MAX_OID_LEN; - /* FIXME: oidtab_delete(srv->oidtab, vinst) */ + oidtab_delete(srv->oidtab, vinst); if (!read_objid(mib, vinst->vi_oid, &vinst->vi_oidlen)) { logmsg(LOG_NOTICE, "%s:%d: cannot parse %s (MIB %s); " |