SNMP: Started register table entries dynamically

Compile-time constant: SNMP_TABLE_DYNAMIC
Added MIB SNMP erroir handling
This commit is contained in:
Olof hagsand 2022-06-08 19:57:00 +02:00
parent eaab900698
commit d9d377de6d
7 changed files with 88 additions and 62 deletions

View file

@ -58,6 +58,7 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
#include "snmp_lib.h" #include "snmp_lib.h"
#include "snmp_register.h"
#include "snmp_handler.h" #include "snmp_handler.h"
static int static int
@ -127,7 +128,6 @@ snmp_common_handler(netsnmp_mib_handler *handler,
* table_container.[ch] * table_container.[ch]
* *
* build_new_oid * build_new_oid
* XXX Check expected return values for these netsnmp handler functions
*/ */
int int
clixon_snmp_table_handler(netsnmp_mib_handler *handler, clixon_snmp_table_handler(netsnmp_mib_handler *handler,
@ -142,27 +142,16 @@ clixon_snmp_table_handler(netsnmp_mib_handler *handler,
cbuf *cb = NULL; cbuf *cb = NULL;
int ret; int ret;
clicon_debug(2, "%s", __FUNCTION__); clicon_debug(1, "%s", __FUNCTION__);
if ((ret = snmp_common_handler(handler, nhreg, reqinfo, requests, &sh, 1)) < 0) if ((ret = snmp_common_handler(handler, nhreg, reqinfo, requests, &sh, 1)) < 0)
goto done; goto done;
switch(reqinfo->mode){ switch(reqinfo->mode){
case MODE_GETNEXT:{ // 160 case MODE_GETNEXT: // 160
#ifdef NOTYET #ifdef SNMP_TABLE_DYNAMIC
char *oidstr = NULL; /* Register table sub-oid:s of existing entries in clixon */
oid oid1[MAX_OID_LEN] = {0,}; if (mibyang_table_poll(sh->sh_h, sh->sh_ys) < 0)
size_t sz1 = MAX_OID_LEN;
oidstr = ".1.3.6.1.2.1.2.2.1.1.1";
if (snmp_parse_oid(oidstr, oid1, &sz1) == NULL){
clicon_err(OE_XML, errno, "snmp_parse_oid");
goto done; goto done;
}
if (snmp_set_var_objid(requests->requestvb, oid1, sz1) != 0){
clicon_err(OE_XML, 0, "snmp_set_var_objid");
goto done;
}
#endif #endif
}
break; break;
case MODE_GET: // 160 case MODE_GET: // 160
case MODE_SET_RESERVE1: case MODE_SET_RESERVE1:
@ -216,6 +205,7 @@ snmp_scalar_get(clicon_handle h,
int asn1type; int asn1type;
char *reason = NULL; char *reason = NULL;
clicon_debug(1, "%s", __FUNCTION__);
/* Prepare backend call by constructing namespace context */ /* Prepare backend call by constructing namespace context */
if (xml_nsctx_yang(ys, &nsc) < 0) if (xml_nsctx_yang(ys, &nsc) < 0)
goto done; goto done;

View file

@ -781,3 +781,47 @@ snmp_agent_cleanup(void)
free(tclist); free(tclist);
return 0; return 0;
} }
/* Specialized SNMP error category log/err callback
*
* This function displays all negative SNMP errors on the form SNMPERR_* that are not SNMPERR_SUCCESS(=0)
* There are also positive SNMP errors on the form SNMP_ERR_* which are not properly handled below
* @param[in] handle Application-specific handle
* @param[in] suberr Application-specific handle, points to SNMP_ERR_* unless < -0x1000 in which
case they are MIB_* errors defined in agent_registry.h
* @param[out] cb Read log/error string into this buffer
* @note Some SNMP API functions sometimes returns NULL/ptr or other return values that do not fall into
* this category, then OE_SNMP should NOT be used.
*/
int
clixon_snmp_err_cb(void *handle,
int suberr,
cbuf *cb)
{
const char *errstr;
clicon_debug(1, "%s", __FUNCTION__);
if (suberr < 0){
if (suberr < -CLIXON_ERR_SNMP_MIB){
switch (suberr+CLIXON_ERR_SNMP_MIB){
case MIB_DUPLICATE_REGISTRATION:
cprintf(cb, "Duplicate MIB registration");
break;
case MIB_REGISTRATION_FAILED:
cprintf(cb, "MIB registration failed");
break;
default:
cprintf(cb, "unknown MIB error %d", suberr+CLIXON_ERR_SNMP_MIB);
break;
}
}
else if ((errstr = snmp_api_errstring(suberr)) == NULL)
cprintf(cb, "unknown SNMP error %d", suberr);
else
cprintf(cb, "%s", errstr);
}
else{ /* See eg SNMP_ERR_* in snmp.h for positive error numbers, are they applicable here? */
cprintf(cb, "unknown error %d", suberr);
}
return 0;
}

View file

@ -41,6 +41,12 @@ extern "C" {
#ifndef _SNMP_LIB_H_ #ifndef _SNMP_LIB_H_
#define _SNMP_LIB_H_ #define _SNMP_LIB_H_
/*
* Constants
*/
/* Need some way to multiplex SNMP_ and MIB errors on OE_SNMP error handler */
#define CLIXON_ERR_SNMP_MIB 0x1000
/* /*
* Types * Types
*/ */
@ -48,7 +54,7 @@ extern "C" {
*/ */
struct clixon_snmp_handle { struct clixon_snmp_handle {
clicon_handle sh_h; clicon_handle sh_h;
yang_stmt *sh_ys; yang_stmt *sh_ys; /* Leaf for scalar, list for table */
oid sh_oid[MAX_OID_LEN]; /* OID for debug, may be removed? */ oid sh_oid[MAX_OID_LEN]; /* OID for debug, may be removed? */
size_t sh_oidlen; size_t sh_oidlen;
char *sh_default; /* MIB default value leaf only */ char *sh_default; /* MIB default value leaf only */
@ -77,6 +83,7 @@ int yang2xpath(yang_stmt *ys, cvec *keyvec, char **xpath);
int snmp_body2oid(cxobj *xi, cg_var *cv); int snmp_body2oid(cxobj *xi, cg_var *cv);
int snmp_agent_check(void); int snmp_agent_check(void);
int snmp_agent_cleanup(void); int snmp_agent_cleanup(void);
int clixon_snmp_err_cb(void *handle, int suberr, cbuf *cb);
#endif /* _SNMP_LIB_H_ */ #endif /* _SNMP_LIB_H_ */

View file

@ -225,7 +225,6 @@ clixon_snmp_input_cb(int s,
return retval; return retval;
} }
/*! Init netsnmp agent connection /*! Init netsnmp agent connection
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] logdst Log destination, see clixon_log.h * @param[in] logdst Log destination, see clixon_log.h
@ -293,37 +292,6 @@ clixon_snmp_init_subagent(clicon_handle h,
return retval; return retval;
} }
/* Specialized SNMP error category log/err callback
*
* This function displays all negative SNMP errors on the form SNMPERR_* that are not SNMPERR_SUCCESS(=0)
* There are also positive SNMP errors on the form SNMP_ERR_* which are not properly handled below
* @param[in] handle Application-specific handle
* @param[in] suberr Application-specific handle
* @param[out] cb Read log/error string into this buffer
* @note Some SNMP API functions sometimes returns NULL/ptr or other return values that do not fall into
* this category, then OE_SNMP should NOT be used.
*/
static int
clixon_snmp_err_cb(void *handle,
int suberr,
cbuf *cb)
{
const char *errstr;
clicon_debug(1, "%s", __FUNCTION__);
if (suberr < 0){
if ((errstr = snmp_api_errstring(suberr)) == NULL)
cprintf(cb, "unknown error %d", suberr);
else
cprintf(cb, "%s", errstr);
}
else{ /* See eg SNMP_ERR_* in snmp.h for positive error numbers, are they applicable here? */
cprintf(cb, "unknown error %d", suberr);
}
return 0;
}
/*! Usage help routine /*! Usage help routine
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] argv0 command line * @param[in] argv0 command line

View file

@ -200,8 +200,8 @@ mibyang_leaf_register(clicon_handle h,
* XXX: nhreg->agent_data * XXX: nhreg->agent_data
*/ */
if ((ret = netsnmp_register_instance(nhreg)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_register_instance(nhreg)) != SNMPERR_SUCCESS){
/* XXX Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION. */ /* Note MIB_ errors, not regular SNMPERR_ */
clicon_err(OE_SNMP, ret, "netsnmp_register_instance"); clicon_err(OE_SNMP, ret-CLIXON_ERR_SNMP_MIB, "netsnmp_register_instance");
goto done; goto done;
} }
clicon_debug(1, "%s %s registered", __FUNCTION__, cbuf_get(cboid)); clicon_debug(1, "%s %s registered", __FUNCTION__, cbuf_get(cboid));
@ -232,7 +232,6 @@ mibyang_leaf_register(clicon_handle h,
*/ */
static int static int
mibyang_table_register(clicon_handle h, mibyang_table_register(clicon_handle h,
yang_stmt *ys,
yang_stmt *ylist) yang_stmt *ylist)
{ {
int retval = -1; int retval = -1;
@ -250,7 +249,13 @@ mibyang_table_register(clicon_handle h,
char *keyname; char *keyname;
yang_stmt *yleaf; yang_stmt *yleaf;
int asn1type; int asn1type;
yang_stmt *ys;
if ((ys = yang_parent_get(ylist)) == NULL ||
yang_keyword_get(ys) != Y_CONTAINER){
clicon_err(OE_YANG, EINVAL, "ylist parent is not list");
goto done;
}
/* Get OID from parent container */ /* Get OID from parent container */
if (yang_extension_value(ys, "oid", IETF_YANG_SMIV2_NS, NULL, &oidstr) < 0) if (yang_extension_value(ys, "oid", IETF_YANG_SMIV2_NS, NULL, &oidstr) < 0)
goto done; goto done;
@ -271,7 +276,7 @@ mibyang_table_register(clicon_handle h,
} }
memset(sh, 0, sizeof(*sh)); memset(sh, 0, sizeof(*sh));
sh->sh_h = h; sh->sh_h = h;
sh->sh_ys = ys; sh->sh_ys = ylist;
memcpy(sh->sh_oid, oid1, sizeof(oid1)); memcpy(sh->sh_oid, oid1, sizeof(oid1));
sh->sh_oidlen = sz1; sh->sh_oidlen = sz1;
@ -357,9 +362,8 @@ mibyang_table_register(clicon_handle h,
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
static int int
mibyang_table_traverse_static(clicon_handle h, mibyang_table_poll(clicon_handle h,
yang_stmt *ys,
yang_stmt *ylist) yang_stmt *ylist)
{ {
int retval = -1; int retval = -1;
@ -378,8 +382,14 @@ mibyang_table_traverse_static(clicon_handle h,
cg_var *cv; cg_var *cv;
int i; int i;
cxobj *xi; cxobj *xi;
yang_stmt *ys;
clicon_debug(1, "%s %s", __FUNCTION__, yang_argument_get(ys)); clicon_debug(1, "%s", __FUNCTION__);
if ((ys = yang_parent_get(ylist)) == NULL ||
yang_keyword_get(ys) != Y_CONTAINER){
clicon_err(OE_YANG, EINVAL, "ylist parent is not list");
goto done;
}
if (xml_nsctx_yang(ys, &nsc) < 0) if (xml_nsctx_yang(ys, &nsc) < 0)
goto done; goto done;
if (yang2xpath(ys, NULL, &xpath) < 0) if (yang2xpath(ys, NULL, &xpath) < 0)
@ -496,11 +506,13 @@ mibyang_traverse(clicon_handle h,
yp = yang_parent_get(yn); yp = yang_parent_get(yn);
if (yang_keyword_get(yp) == Y_CONTAINER){ if (yang_keyword_get(yp) == Y_CONTAINER){
/* Register table entry handler itself (not column/row leafs) */ /* Register table entry handler itself (not column/row leafs) */
if (mibyang_table_register(h, yp, yn) < 0) if (mibyang_table_register(h, yn) < 0)
goto done; goto done;
#ifndef SNMP_TABLE_DYNAMIC
/* Register table sub-oid:s of existing entries in clixon */ /* Register table sub-oid:s of existing entries in clixon */
if (mibyang_table_traverse_static(h, yp, yn) < 0) if (mibyang_table_poll(h, yn) < 0)
goto done; goto done;
#endif
goto ok; goto ok;
} }
break; break;

View file

@ -44,6 +44,7 @@ extern "C" {
/* /*
* Prototypes * Prototypes
*/ */
int mibyang_table_poll(clicon_handle h, yang_stmt *ylist);
int clixon_snmp_traverse_mibyangs(clicon_handle h); int clixon_snmp_traverse_mibyangs(clicon_handle h);
#endif /* _SNMP_REGISTER_H_ */ #endif /* _SNMP_REGISTER_H_ */

View file

@ -163,3 +163,7 @@
* If not set, client will exit * If not set, client will exit
*/ */
#define PROTO_RESTART_RECONNECT #define PROTO_RESTART_RECONNECT
/*! Re-register table entries when quering
*/
#undef SNMP_TABLE_DYNAMIC