From ebfd173e0b0d44750627b8d3790412cdbe1acc9c Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Thu, 16 Jun 2022 14:26:43 +0200 Subject: [PATCH] SNMP: Dynamic table fixes --- apps/snmp/snmp_handler.c | 108 +++++++++++++++++++++++++++------------ apps/snmp/snmp_lib.c | 34 +++++++++--- 2 files changed, 102 insertions(+), 40 deletions(-) diff --git a/apps/snmp/snmp_handler.c b/apps/snmp/snmp_handler.c index f3cd9216..952f38a7 100644 --- a/apps/snmp/snmp_handler.c +++ b/apps/snmp/snmp_handler.c @@ -140,7 +140,10 @@ snmp_scalar_return(cxobj *xs, if ((ret = type_xml2snmp_pre(xml_body(xs), ys, &xmlstr)) < 0) goto done; if (ret == 0){ - netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE); + if ((ret = netsnmp_request_set_error(requests, SNMP_ERR_WRONGVALUE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto ok; } } @@ -151,7 +154,10 @@ snmp_scalar_return(cxobj *xs, } } else{ - netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); + if ((ret = netsnmp_request_set_error(requests, SNMP_NOSUCHINSTANCE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto ok; } if (type_yang2asn1(ys, &asn1type, 1) < 0) @@ -160,7 +166,10 @@ snmp_scalar_return(cxobj *xs, goto done; if (ret == 0){ clicon_debug(1, "%s %s", __FUNCTION__, reason); - netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); + if ((ret = netsnmp_request_set_error(requests, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto ok; } /* see snmplib/snmp_client. somewhat indirect @@ -245,7 +254,10 @@ snmp_scalar_get(clicon_handle h, if ((ret = type_xml2snmp_pre(xml_body(x), ys, &xmlstr)) < 0) goto done; if (ret == 0){ - netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE); + if ((ret = netsnmp_request_set_error(requests, SNMP_ERR_WRONGVALUE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto ok; } } @@ -256,7 +268,10 @@ snmp_scalar_get(clicon_handle h, } } else{ - netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); + if ((ret = netsnmp_request_set_error(requests, SNMP_NOSUCHINSTANCE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto ok; } if (type_yang2asn1(ys, &asn1type, 1) < 0) @@ -265,7 +280,10 @@ snmp_scalar_get(clicon_handle h, goto done; if (ret == 0){ clicon_debug(1, "%s %s", __FUNCTION__, reason); - netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); + if ((ret = netsnmp_request_set_error(requests, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto ok; } /* see snmplib/snmp_client. somewhat indirect @@ -371,6 +389,7 @@ clixon_snmp_scalar_handler(netsnmp_mib_handler *handler, clixon_snmp_handle *sh = NULL; int asn1_type; netsnmp_variable_list *requestvb = requests->requestvb; + int ret; clicon_debug(2, "%s", __FUNCTION__); if (snmp_common_handler(handler, nhreg, reqinfo, requests, &sh, 0) < 0) @@ -391,8 +410,10 @@ clixon_snmp_scalar_handler(netsnmp_mib_handler *handler, goto done; if (requestvb->type != asn1_type){ clicon_debug(1, "%s Expected type:%d, got: %d", __FUNCTION__, requestvb->type, asn1_type); - netsnmp_set_request_error(reqinfo, requests, - SNMP_ERR_WRONGTYPE); + if ((ret = netsnmp_request_set_error(requests, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } } break; case MODE_SET_RESERVE2: /* 1 */ @@ -496,6 +517,7 @@ snmp_table_get(clicon_handle h, clicon_err(OE_UNIX, errno, "cvec_dup"); goto done; } + /* read through keys and create cvk */ oidilen = oidslen-(oidtlen+1); oidi = oids+oidtlen+1; /* Add keys */ @@ -536,8 +558,9 @@ snmp_table_get(clicon_handle h, * @param[in] ylist Yang of table (of list type) * @param[in] oids OID of ultimate scalar value * @param[in] oidslen OID length of scalar - * @retval -1 Error - * @retval 0 OK + * @retval 1 OK + * @retval 0 Failed + * @retval -1 Error */ static int snmp_table_getnext(clicon_handle h, @@ -563,9 +586,13 @@ snmp_table_getnext(clicon_handle h, size_t oidclen = MAX_OID_LEN; oid oidk[MAX_OID_LEN] = {0,}; /* Key oid */ size_t oidklen = MAX_OID_LEN; - int getnext = 0; + oid oidnext[MAX_OID_LEN] = {0x7fffffff,}; /* Next oid: start with high value */ + size_t oidnextlen = MAX_OID_LEN; int found = 0; - + cxobj *xnext = NULL; + yang_stmt *ynext = NULL; + cbuf *cb = NULL; + clicon_debug(1, "%s", __FUNCTION__); if ((ys = yang_parent_get(ylist)) == NULL || yang_keyword_get(ys) != Y_CONTAINER){ @@ -606,29 +633,32 @@ snmp_table_getnext(clicon_handle h, /* Append key oid */ if (oid_append(oidc, &oidclen, oidk, oidklen) < 0) goto done; - if (getnext){ - found++; /* return this */ - break; - } - /* Match oidc - key */ - if ((ret = oid_eq(oidc, oidclen, oids, oidslen)) == 0){ - getnext++; /* return next object if any */ - } - else if (ret > 0){ - found++; /* return this */ - break; + /* Get smallest larger */ + if (oid_eq(oidc, oidclen, oids, oidslen) > 0 && + oid_eq(oidc, oidclen, oidnext, oidnextlen) < 0){ + memcpy(oidnext, oidc, oidclen*sizeof(*oidnext)); + oidnextlen = oidclen; + xnext = xcol; + ynext = ycol; + found++; } } /* while xcol */ - if (found) - break; } /* while xrow */ } if (found){ - if (snmp_scalar_return(xcol, ycol, oidc, oidclen, reqinfo, requests) < 0) + if (snmp_scalar_return(xnext, ynext, oidnext, oidnextlen, reqinfo, requests) < 0) goto done; + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + oid_cbuf(cb, oidnext, oidnextlen); + clicon_debug(1, "%s next: %s", __FUNCTION__, cbuf_get(cb)); } - retval = 0; + retval = found; done: + if (cb) + cbuf_free(cb); if (xpath) free(xpath); if (xt) @@ -688,17 +718,31 @@ clixon_snmp_table_handler(netsnmp_mib_handler *handler, requestvb->name, requestvb->name_length, reqinfo, requests)) < 0) goto done; - if (ret == 0) - netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); + if (ret == 0){ + if ((ret = netsnmp_request_set_error(requests, SNMP_NOSUCHINSTANCE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } + clicon_debug(1, "%s Nosuchinstance", __FUNCTION__); + } #endif break; case MODE_GETNEXT: // 161 #ifdef SNMP_TABLE_DYNAMIC /* Register table sub-oid:s of existing entries in clixon */ - if (snmp_table_getnext(sh->sh_h, sh->sh_ys, - requestvb->name, requestvb->name_length, - reqinfo, requests) < 0) + if ((ret = snmp_table_getnext(sh->sh_h, sh->sh_ys, + requestvb->name, requestvb->name_length, + reqinfo, requests)) < 0) goto done; + if (ret == 0){ + // if ((ret = netsnmp_request_set_error(requests, SNMP_NOSUCHOBJECT)) != SNMPERR_SUCCESS){ + if ((ret = netsnmp_request_set_error(requests, SNMP_NOSUCHOBJECT)) != SNMPERR_SUCCESS){ + + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } + clicon_debug(1, "%s No such object", __FUNCTION__); + } #endif break; case MODE_SET_RESERVE1: diff --git a/apps/snmp/snmp_lib.c b/apps/snmp/snmp_lib.c index 360dc01c..d76a95b9 100644 --- a/apps/snmp/snmp_lib.c +++ b/apps/snmp/snmp_lib.c @@ -165,7 +165,7 @@ snmp_msg_int2str(int msg) * @param[in] objid1len Length of second OID vector * @retval 0 Equal * @retval !=0 Not equal, see man memcmp - * (Should be netsnmp lib function, cant find it) + * Should really be netsnmp lib function, but cant find any? */ int oid_eq(const oid *objid0, @@ -173,12 +173,24 @@ oid_eq(const oid *objid0, const oid *objid1, size_t objid1len) { + size_t min; + int ret; + + if (objid0len < objid1len) + min = objid0len; + else + min = objid1len; + /* First compare common prefix */ + ret = memcmp(objid0, objid1, min*sizeof(*objid0)); + if (ret != 0) + return ret; + /* If equal, check lengths */ if (objid0len < objid1len) return -1; else if (objid0len > objid1len) return 1; else - return memcmp(objid0, objid1, objid0len*sizeof(*objid0)); + return 0; } /*! Append a second OID to a first @@ -470,6 +482,7 @@ type_snmp2xml(yang_stmt *ys, cg_var *cv = NULL; char *restype = NULL; /* resolved type */ yang_stmt *yrestype = NULL; + int ret; clicon_debug(1, "%s", __FUNCTION__); if (valstr == NULL){ @@ -540,7 +553,10 @@ type_snmp2xml(yang_stmt *ys, default: assert(0); // XXX clicon_debug(1, "%s %s not supported", __FUNCTION__, cv_type2str(cvtype)); - netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); + if ((ret = netsnmp_request_set_error(requests, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ + clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); + goto done; + } goto fail; break; } @@ -934,20 +950,22 @@ snmp_oid2str(oid **oidi, case ASN_COUNTER: case ASN_IPADDRESS: cprintf(enc, "%lu", (*oidi)[i++]); - if (cv_string_set(cv, cbuf_get(enc)) < 0){ - clicon_err(OE_UNIX, errno, "cv_string_set"); - goto done; - } break; case ASN_OCTET_STR: /* decode from N.c.c.c.c */ len = (*oidi)[i++]; - for (; i