diff --git a/apps/snmp/snmp_handler.c b/apps/snmp/snmp_handler.c index 2d77213c..f067f7d3 100644 --- a/apps/snmp/snmp_handler.c +++ b/apps/snmp/snmp_handler.c @@ -118,6 +118,143 @@ done: return retval; } +/*! Scalar handler, set a value to clixon + * get xpath: see yang2api_path_fmt / api_path2xpath + */ +static int +snmp_scalar_get(clicon_handle h, + yang_stmt *ys, + netsnmp_variable_list *requestvb, + char *defaultval, + enum cv_type cvtype, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int retval = -1; + cvec *nsc = NULL; + char *xpath = NULL; + cxobj *xt = NULL; + cxobj *xerr; + cxobj *x; + char *valstr = NULL; + u_char *snmpval = NULL; + size_t snmplen; + int ret; + + if (xml_nsctx_yang(ys, &nsc) < 0) + goto done; + if (yang2xpath(ys, &xpath) < 0) + goto done; + if (clicon_rpc_get(h, xpath, nsc, CONTENT_ALL, -1, &xt) < 0) + goto done; + if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){ + clixon_netconf_error(xerr, "clicon_rpc_get", NULL); + goto done; + } + /* Get value, either from xml, or smiv2 default */ + if ((x = xpath_first(xt, nsc, "%s", xpath)) != NULL) { + valstr = xml_body(x); + } + else if ((valstr = defaultval) != NULL) + ; + else{ + netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); + goto ok; + } + if ((ret = type_yang2snmp(valstr, cvtype, reqinfo, requests, &snmpval, &snmplen)) < 0) + goto done; + if (ret == 0) + goto ok; + + /* 1. use cligen object and get rwa buf / size from that, OR + * + have parse function from YANG + * - does not have + * 2. use union netsnmp_vardata and pass that here? + * 3. Make cv2asn1 conversion function <-- + */ + + /* see snmplib/snmp_client.c */ + if (snmp_set_var_value(requestvb, + snmpval, + snmplen) != 0){ + clicon_err(OE_SNMP, 0, "snmp_set_var_value"); + goto done; + } + ok: + retval = 0; + done: + if (snmpval) + free(snmpval); + if (xt) + xml_free(xt); + if (xpath) + free(xpath); + if (nsc) + xml_nsctx_free(nsc); + return retval; +} + +/*! Scalar handler, get a value from clixon + */ +static int +snmp_scalar_set(clicon_handle h, + yang_stmt *ys, + netsnmp_variable_list *requestvb, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int retval = -1; + char *api_path = NULL; + cxobj *xtop = NULL; + cxobj *xbot = NULL; + cxobj *xb; + yang_stmt *yspec; + int ret; + char *valstr = NULL; + cbuf *cb = NULL; + + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_FATAL, 0, "No DB_SPEC"); + goto done; + } + if ((xtop = xml_new(NETCONF_INPUT_CONFIG, NULL, CX_ELMNT)) == NULL) + goto done; + if (yang2api_path_fmt(ys, 0, &api_path) < 0) + goto done; + if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 1, &xbot, NULL, NULL)) < 0) + goto done; + + if (ret == 0){ + clicon_err(OE_XML, 0, "api_path2xml %s invalid", api_path); + goto done; + } + if ((xb = xml_new("body", xbot, CX_BODY)) == NULL) + goto done; + if ((ret = type_snmp2yang(requestvb, reqinfo, requests, &valstr)) < 0) + goto done; + if (ret == 0) + goto ok; + if (xml_value_set(xb, valstr) < 0) + goto done; + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + if (clicon_xml2cbuf(cb, xtop, 0, 0, -1) < 0) + goto done; + if (clicon_rpc_edit_config(h, "candidate", OP_MERGE, cbuf_get(cb)) < 0) + goto done; + ok: + retval = 0; + done: + if (cb) + cbuf_free(cb); + if (xtop) + xml_free(xtop); + if (valstr) + free(valstr); + return retval; +} /*! SNMP Scalar operation handler * Calls order: READ:160, @@ -131,25 +268,13 @@ snmp_scalar_handler(netsnmp_mib_handler *handler, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { - int retval = -1; - clixon_snmp_handle *sh; - yang_stmt *ys; - clicon_handle h; - cg_var *cv = NULL; - cxobj *xt = NULL; - cxobj *xerr; - cvec *nsc = NULL; - cxobj *x; - char *xpath = NULL; - int asn1_type; - enum cv_type cvtype; - char *valstr; - u_char *snmpval = NULL; - size_t snmplen; - int ret; + int retval = -1; + clixon_snmp_handle *sh; + yang_stmt *ys; + int asn1_type; netsnmp_variable_list *requestvb; /* sub of requests */ - cbuf *cb = NULL; - + enum cv_type cvtype; + /* * can be used to pass information on a per-pdu basis from a * helper to the later handlers @@ -174,7 +299,6 @@ snmp_scalar_handler(netsnmp_mib_handler *handler, requests->inclusive); sh = (clixon_snmp_handle*)nhreg->my_reg_void; ys = sh->sh_ys; - h = sh->sh_h; // fprint_objid(stderr, nhreg->rootoid, nhreg->rootoid_len); assert(sh->sh_oidlen == requestvb->name_length); assert(requestvb->name_length == nhreg->rootoid_len); @@ -188,123 +312,43 @@ snmp_scalar_handler(netsnmp_mib_handler *handler, SNMP_NOSUCHOBJECT); return SNMP_ERR_NOERROR; #endif - if (yang2snmp_types(ys, &asn1_type, &cvtype) < 0) goto done; /* see net-snmp/agent/snmp_agent.h / net-snmp/library/snmp.h */ switch (reqinfo->mode) { - case MODE_GET: // 160 + case MODE_GET: /* 160 */ requestvb->type = asn1_type; // ASN_NULL on input - - /* get xpath: see yang2api_path_fmt / api_path2xpath - New fn: yang2xpath? - clicon_rpc_get() - " - - */ - - if (xml_nsctx_yang(ys, &nsc) < 0) + if (snmp_scalar_get(sh->sh_h, ys, requestvb, sh->sh_default, cvtype, reqinfo, requests) < 0) goto done; - if (yang2xpath(ys, &xpath) < 0) - goto done; - if (clicon_rpc_get(h, xpath, nsc, CONTENT_ALL, -1, &xt) < 0) - goto done; - if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){ - clixon_netconf_error(xerr, "clicon_rpc_get", NULL); - goto done; - } - /* Get value, either from xml, or smiv2 default */ - if ((x = xpath_first(xt, nsc, "%s", xpath)) != NULL) { - valstr = xml_body(x); - } - else if ((valstr = sh->sh_default) != NULL) - ; - else{ - netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); - goto ok; - } - if ((ret = type_yang2snmp(valstr, cvtype, reqinfo, requests, &snmpval, &snmplen)) < 0) - goto done; - if (ret == 0) - goto ok; - - /* 1. use cligen object and get rwa buf / size from that, OR - * + have parse function from YANG - * - does not have - * 2. use union netsnmp_vardata and pass that here? - * 3. Make cv2asn1 conversion function <-- - */ - - /* see snmplib/snmp_client.c */ - if (snmp_set_var_value(requestvb, - snmpval, - snmplen) != 0){ - clicon_err(OE_SNMP, 0, "snmp_set_var_value"); - goto done; - } break; - case MODE_GETNEXT: // 161 + case MODE_GETNEXT: /* 161 */ assert(0); // Not seen? break; - case MODE_SET_RESERVE1: // 0 + case MODE_SET_RESERVE1: /* 0 */ if (requestvb->type != asn1_type) netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); break; - - case MODE_SET_RESERVE2: // 1 + case MODE_SET_RESERVE2: /* 1 */ break; - - case MODE_SET_ACTION: // 2 - /* - * update current - */ - /* yang2xpath -> xpath2xml - * accesses = *(requestvb->val.integer); - * rpc edit-config - - */ - - if ((cb = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, errno, "cbuf_new"); - goto done; - } - /*! XXX only int */ - cprintf(cb, "%ld", *requestvb->val.integer); - if (clicon_rpc_edit_config(h, "candidate", OP_MERGE, cbuf_get(cb)) < 0) + case MODE_SET_ACTION: /* 2 */ + if (snmp_scalar_set(sh->sh_h, ys, requestvb, reqinfo, requests) < 0) goto done; break; - - case MODE_SET_UNDO: // 5 - if (clicon_rpc_discard_changes(h) < 0) + case MODE_SET_UNDO: /* 5 */ + if (clicon_rpc_discard_changes(sh->sh_h) < 0) goto done; break; - case MODE_SET_COMMIT: // 3 - if (clicon_rpc_commit(h) < 0) + case MODE_SET_COMMIT: /* 3 */ + if (clicon_rpc_commit(sh->sh_h) < 0) goto done; break; - case MODE_SET_FREE: // 4 - /* - * nothing to do - */ + case MODE_SET_FREE: /* 4 */ break; } - ok: retval = SNMP_ERR_NOERROR; done: - if (snmpval) - free(snmpval); - if (cb) - cbuf_free(cb); - if (xpath) - free(xpath); - if (xt) - xml_free(xt); - if (nsc) - xml_nsctx_free(nsc); - if (cv) - cv_free(cv); return retval; } diff --git a/apps/snmp/snmp_lib.c b/apps/snmp/snmp_lib.c index 6c21db6f..16cc38d1 100644 --- a/apps/snmp/snmp_lib.c +++ b/apps/snmp/snmp_lib.c @@ -54,8 +54,9 @@ #include #include #include -#include #include +#include +#include /* net-snmp */ #include @@ -91,16 +92,19 @@ static const map_str2int snmp_access_map[] = { /* Map between clixon and ASN.1 types. * @see net-snmp/library/asn1.h * @see union netsnmp_vardata in net-snmp/types.h + * XXX not complete + * XXX TimeTicks */ static const map_str2int snmp_type_map[] = { - {"bool", ASN_BOOLEAN}, + {"int32", ASN_INTEGER}, - {"bits", ASN_BIT_STR}, {"string", ASN_OCTET_STR}, - {"empty", ASN_NULL}, - //XXX {"", ASN_OBJECT_ID}, - // XXX {"", ASN_SEQUENCE}, - // XXX {"", ASN_SET}, + // {"bool", ASN_BOOLEAN}, + // {"empty", ASN_NULL}, + // {"bits", ASN_BIT_STR}, + // {"", ASN_OBJECT_ID}, + // {"", ASN_SEQUENCE}, + // {"", ASN_SET}, {NULL, -1} }; @@ -130,7 +134,13 @@ snmp_msg_int2str(int msg) { return clicon_int2str(snmp_msg_map, msg); } -/*! +/*! Translate from YANG to SNMP asn1.1 type ids (not value) + * + * @param[in] ys YANG leaf node + * @param[out] asn1_type ASN.1 type id + * @param[out] cvtype Clixon cv type + * @retval 0 OK + * @retval -1 Error */ int yang2snmp_types(yang_stmt *ys, @@ -141,31 +151,38 @@ yang2snmp_types(yang_stmt *ys, yang_stmt *yrestype; /* resolved type */ char *restype; /* resolved type */ char *origtype=NULL; /* original type */ + int at; /* Get yang type of leaf and trasnslate to ASN.1 */ if (yang_type_get(ys, &origtype, &yrestype, NULL, NULL, NULL, NULL, NULL) < 0) goto done; restype = yrestype?yang_argument_get(yrestype):NULL; - if (clicon_type2cv(origtype, restype, ys, cvtype) < 0) - goto done; /* translate to asn.1 */ - *asn1_type = clicon_str2int(snmp_type_map, restype); + if ((at = clicon_str2int(snmp_type_map, restype)) < 0){ + clicon_err(OE_YANG, 0, "No snmp translation for YANG %s type:%s", + yang_argument_get(ys), restype); + // goto done; + } + if (asn1_type) + *asn1_type = at; + if (cvtype && clicon_type2cv(origtype, restype, ys, cvtype) < 0) + goto done; clicon_debug(1, "%s type:%s", __FUNCTION__, restype); retval = 0; done: return retval; } - /*! Translate from yang/xml/clixon to SNMP/ASN.1 -** -* The tran + * * @param[in] valstr Clixon/yang/xml string value * @param[in] cvtype Type of clixon type + * @param[in] reqinfo snmpd API struct for error + * @param[in] requests snmpd API struct for error * @param[out] snmpval Malloc:ed snmp type * @param[out] snmplen Length of snmp type * @retval 1 OK - * @retval 0 Invalid value + * @retval 0 Invalid value or type * @retval -1 Error */ int @@ -216,6 +233,7 @@ type_yang2snmp(char *valstr, break; } default: + assert(0); // XXX clicon_debug(1, "%s %s not supported", __FUNCTION__, cv_type2str(cvtype)); netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); goto fail; @@ -231,6 +249,66 @@ type_yang2snmp(char *valstr, retval = 0; goto done; } +/*! Translate from yang/xml/clixon to SNMP/ASN.1 + * + * @param[in] snmpval Malloc:ed snmp type + * @param[in] snmplen Length of snmp type + * @param[in] reqinfo snmpd API struct for error + * @param[in] requests snmpd API struct for error + * @param[out] valstr Clixon/yang/xml string value, free after use) + * @retval 1 OK, and valstr set + * @retval 0 Invalid value or type + * @retval -1 Error + */ +int +type_snmp2yang(netsnmp_variable_list *requestvb, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests, + char **valstr) +{ + int retval = -1; + char *cvtypestr; + enum cv_type cvtype; + cg_var *cv; + + clicon_debug(1, "%s", __FUNCTION__); + if (valstr == NULL){ + clicon_err(OE_UNIX, EINVAL, "valstr is NULL"); + goto done; + } + cvtypestr = (char*)clicon_int2str(snmp_type_map, requestvb->type); + cvtype = cv_str2type(cvtypestr); + if ((cv = cv_new(cvtype)) == NULL){ + clicon_err(OE_UNIX, errno, "cv_new"); + goto done; + } + switch (requestvb->type){ + case ASN_BOOLEAN: + case ASN_INTEGER: + cv_int32_set(cv, *requestvb->val.integer); + break; + case ASN_OCTET_STR: + cv_string_set(cv, (char*)requestvb->val.string); + break; + default: + assert(0); // XXX + clicon_debug(1, "%s %s not supported", __FUNCTION__, cv_type2str(cvtype)); + netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); + goto fail; + break; + } + if ((*valstr = cv2str_dup(cv)) == NULL){ + clicon_err(OE_UNIX, errno, "cv2str_dup"); + goto done; + } + retval = 1; + done: + clicon_debug(1, "%s %d", __FUNCTION__, retval); + return retval; + fail: + retval = 0; + goto done; +} /*! Construct an xpath from yang statement, internal fn using cb * Recursively construct it to the top. @@ -263,9 +341,10 @@ yang2xpath_cb(yang_stmt *ys, cprintf(cb, "/"); } } - cprintf(cb, "%s:", yang_find_myprefix(ys)); - if (yang_keyword_get(ys) != Y_CHOICE && yang_keyword_get(ys) != Y_CASE) + if (yang_keyword_get(ys) != Y_CHOICE && yang_keyword_get(ys) != Y_CASE){ + cprintf(cb, "%s:", yang_find_myprefix(ys)); cprintf(cb, "%s", yang_argument_get(ys)); + } switch (yang_keyword_get(ys)){ case Y_LIST: // XXX not xpaths cvk = yang_cvec_get(ys); /* Use Y_LIST cache, see ys_populate_list() */ @@ -290,7 +369,6 @@ yang2xpath_cb(yang_stmt *ys, } /*! Construct an xpath from yang statement - * Recursively construct it to the top. * @param[in] ys Yang statement * @param[out] xpath Malloced xpath string, use free() after use diff --git a/apps/snmp/snmp_lib.h b/apps/snmp/snmp_lib.h index ed572180..13a6cbe4 100644 --- a/apps/snmp/snmp_lib.h +++ b/apps/snmp/snmp_lib.h @@ -64,6 +64,10 @@ int yang2snmp_types(yang_stmt *ys, int *asn1_type, enum cv_type *cvtype); int type_yang2snmp(char *valstr, enum cv_type cvtype, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests, u_char **snmpval, size_t *snmplen); +int type_snmp2yang(netsnmp_variable_list *requestvb, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests, + char **valstr); int yang2xpath(yang_stmt *ys, char **xpath); int clixon_table_create(netsnmp_table_data_set *table, yang_stmt *ys, clicon_handle h); diff --git a/apps/snmp/snmp_main.c b/apps/snmp/snmp_main.c index 66ba4cae..0cc25f13 100644 --- a/apps/snmp/snmp_main.c +++ b/apps/snmp/snmp_main.c @@ -448,8 +448,8 @@ main(int argc, /* Init snmp as subagent */ if (clixon_snmp_subagent(h, logdst) < 0) goto done; - /* Init mib-translated yangs and register callbacks */ - if (clixon_snmp_mib_yangs(h) < 0) + /* Init and traverse mib-translated yangs and register callbacks */ + if (clixon_snmp_traverse_mibyangs(h) < 0) goto done; if (dbg) diff --git a/apps/snmp/snmp_register.c b/apps/snmp/snmp_register.c index 4082e2b7..dd67eee7 100644 --- a/apps/snmp/snmp_register.c +++ b/apps/snmp/snmp_register.c @@ -81,258 +81,6 @@ #define IETF_YANG_SMIV2_NS "urn:ietf:params:xml:ns:yang:ietf-yang-smiv2" -#if 0 -/*! SNMP table operation handlre - - * Callorder: 161,160,.... 0, 1,2,3, 160,161,... - * see https://net-snmp.sourceforge.io/dev/agent/data_set_8c-example.html#_a0 - */ -int -snmp_table_handler(netsnmp_mib_handler *handler, - netsnmp_handler_registration *nhreg, - netsnmp_agent_request_info *reqinfo, - netsnmp_request_info *requests) -{ - int retval = SNMP_ERR_GENERR; - clixon_snmp_handle *sh; - netsnmp_table_data_set *table; - yang_stmt *ys; - clicon_handle h; - yang_stmt *ylist; - cvec *nsc = NULL; - cxobj *xt = NULL; - cbuf *cb = NULL; - - clicon_debug(1, "%s %s %s", __FUNCTION__, - handler->handler_name, - snmp_msg_int2str(reqinfo->mode)); - sh = (clixon_snmp_handle*)nhreg->my_reg_void; - ys = sh->sh_ys; - h = sh->sh_h; - table = sh->sh_table; - - if ((ylist = yang_find(ys, Y_LIST, NULL)) == NULL) - goto ok; - - if (clixon_table_create(table, ys, h) < 0) - goto done; - - switch(reqinfo->mode){ - case MODE_GETNEXT: // 160 - break; - case MODE_GET: // 160 - case MODE_SET_RESERVE1: - case MODE_SET_RESERVE2: - case MODE_SET_ACTION: - case MODE_SET_COMMIT: - break; - - } -ok: - retval = SNMP_ERR_NOERROR; - -done: - if (xt) - xml_free(xt); - if (cb) - cbuf_free(cb); - if (nsc) - xml_nsctx_free(nsc); - return retval; -} - - -/*! SNMP Scalar operation handler - * Calls order: READ:160, - * WRITE: 0, 1, 2, 3, - * MODE_SET_RESERVE1, MODE_SET_RESERVE2, MODE_SET_ACTION, MODE_SET_COMMIT - * - */ -int -snmp_scalar_handler(netsnmp_mib_handler *handler, - netsnmp_handler_registration *nhreg, - netsnmp_agent_request_info *reqinfo, - netsnmp_request_info *requests) -{ - int retval = -1; - clixon_snmp_handle *sh; - yang_stmt *ys; - clicon_handle h; - cg_var *cv = NULL; - cxobj *xt = NULL; - cxobj *xerr; - cvec *nsc = NULL; - cxobj *x; - char *xpath = NULL; - int asn1_type; - enum cv_type cvtype; - char *valstr; - u_char *snmpval = NULL; - size_t snmplen; - int ret; - netsnmp_variable_list *requestvb; /* sub of requests */ - cbuf *cb = NULL; - - /* - * can be used to pass information on a per-pdu basis from a - * helper to the later handlers - netsnmp_agent_request_info *reqinfo, - netsnmp_data_list *agent_data; - netsnmp_free_agent_data_set() - */ - requestvb = requests->requestvb; - if (0) - fprintf(stderr, "%s %s %s\n", __FUNCTION__, - handler->handler_name, - snmp_msg_int2str(reqinfo->mode) - ); - - if (0) - fprintf(stderr, "inclusive:%d\n", - requests->inclusive - ); - clicon_debug(1, "%s %s %s %d", __FUNCTION__, - handler->handler_name, - snmp_msg_int2str(reqinfo->mode), - requests->inclusive); - sh = (clixon_snmp_handle*)nhreg->my_reg_void; - ys = sh->sh_ys; - h = sh->sh_h; - // fprint_objid(stderr, nhreg->rootoid, nhreg->rootoid_len); - assert(sh->sh_oidlen == requestvb->name_length); - assert(requestvb->name_length == nhreg->rootoid_len); - assert(snmp_oid_compare(sh->sh_oid, sh->sh_oidlen, - requestvb->name, requestvb->name_length) == 0); - assert(snmp_oid_compare(requestvb->name, requestvb->name_length, - nhreg->rootoid, nhreg->rootoid_len) == 0); - -#if 0 /* If oid match fails */ - netsnmp_set_request_error(reqinfo, requests, - SNMP_NOSUCHOBJECT); - return SNMP_ERR_NOERROR; -#endif - - if (yang2snmp_types(ys, &asn1_type, &cvtype) < 0) - goto done; - - /* see net-snmp/agent/snmp_agent.h / net-snmp/library/snmp.h */ - switch (reqinfo->mode) { - case MODE_GET: // 160 - requestvb->type = asn1_type; // ASN_NULL on input - - /* get xpath: see yang2api_path_fmt / api_path2xpath - New fn: yang2xpath? - clicon_rpc_get() - " - - */ - - if (xml_nsctx_yang(ys, &nsc) < 0) - goto done; - if (yang2xpath(ys, &xpath) < 0) - goto done; - if (clicon_rpc_get(h, xpath, nsc, CONTENT_ALL, -1, &xt) < 0) - goto done; - if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){ - clixon_netconf_error(xerr, "clicon_rpc_get", NULL); - goto done; - } - /* Get value, either from xml, or smiv2 default */ - if ((x = xpath_first(xt, nsc, "%s", xpath)) != NULL) { - valstr = xml_body(x); - } - else if ((valstr = sh->sh_default) != NULL) - ; - else{ - netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); - goto ok; - } - if ((ret = type_yang2snmp(valstr, cvtype, reqinfo, requests, &snmpval, &snmplen)) < 0) - goto done; - if (ret == 0) - goto ok; - - /* 1. use cligen object and get rwa buf / size from that, OR - * + have parse function from YANG - * - does not have - * 2. use union netsnmp_vardata and pass that here? - * 3. Make cv2asn1 conversion function <-- - */ - - /* see snmplib/snmp_client.c */ - if (snmp_set_var_value(requestvb, - snmpval, - snmplen) != 0){ - clicon_err(OE_SNMP, 0, "snmp_set_var_value"); - goto done; - } - break; - case MODE_GETNEXT: // 161 - assert(0); // Not seen? - break; - case MODE_SET_RESERVE1: // 0 - if (requestvb->type != asn1_type) - netsnmp_set_request_error(reqinfo, requests, - SNMP_ERR_WRONGTYPE); - break; - - case MODE_SET_RESERVE2: // 1 - break; - - case MODE_SET_ACTION: // 2 - /* - * update current - */ - /* yang2xpath -> xpath2xml - * accesses = *(requestvb->val.integer); - * rpc edit-config - - */ - - if ((cb = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, errno, "cbuf_new"); - goto done; - } - /*! XXX only int */ - cprintf(cb, "%ld", *requestvb->val.integer); - if (clicon_rpc_edit_config(h, "candidate", OP_MERGE, cbuf_get(cb)) < 0) - goto done; - break; - - case MODE_SET_UNDO: // 5 - if (clicon_rpc_discard_changes(h) < 0) - goto done; - break; - - case MODE_SET_COMMIT: // 3 - if (clicon_rpc_commit(h) < 0) - goto done; - break; - case MODE_SET_FREE: // 4 - /* - * nothing to do - */ - break; - } - ok: - retval = SNMP_ERR_NOERROR; - done: - if (snmpval) - free(snmpval); - if (cb) - cbuf_free(cb); - if (xpath) - free(xpath); - if (xt) - xml_free(xt); - if (nsc) - xml_nsctx_free(nsc); - if (cv) - cv_free(cv); - return retval; -} -#endif - /*! Parse smiv2 extensions for YANG container/list * * Typical table: @@ -457,7 +205,10 @@ mib_yang_leaf(clicon_handle h, } if (yang_extension_value(ys, "max-access", IETF_YANG_SMIV2_NS, NULL, &modes_str) < 0) goto done; - +#if 0 /* Sanity check of types */ + if (yang2snmp_types(ys, NULL, NULL) < 0) + goto done; +#endif /* Get modes (access) read-only, read-write, not-accessible, oaccessible-for-notify */ if (modes_str == NULL) @@ -489,10 +240,8 @@ mib_yang_leaf(clicon_handle h, memcpy(sh->sh_oid, oid1, sizeof(oid1)); sh->sh_oidlen = sz1; sh->sh_default = default_str; - if ((nhreg = netsnmp_handler_registration_create(name, - handler, - oid1, - sz1, + if ((nhreg = netsnmp_handler_registration_create(name, handler, + oid1, sz1, modes)) == NULL){ clicon_err(OE_SNMP, errno, "netsnmp_handler_registration_create"); netsnmp_handler_free(handler); @@ -587,7 +336,7 @@ mib_traverse(clicon_handle h, * @retval -1 Error */ int -clixon_snmp_mib_yangs(clicon_handle h) +clixon_snmp_traverse_mibyangs(clicon_handle h) { int retval = -1; char *modname; diff --git a/apps/snmp/snmp_register.h b/apps/snmp/snmp_register.h index 17a3ac5d..833f2f83 100644 --- a/apps/snmp/snmp_register.h +++ b/apps/snmp/snmp_register.h @@ -43,7 +43,7 @@ extern "C" { /* * Prototypes */ -int clixon_snmp_mib_yangs(clicon_handle h); +int clixon_snmp_traverse_mibyangs(clicon_handle h); #endif /* _SNMP_REGISTER_H_ */ diff --git a/lib/src/clixon_path.c b/lib/src/clixon_path.c index 2dc2bc83..a8c15dcf 100644 --- a/lib/src/clixon_path.c +++ b/lib/src/clixon_path.c @@ -386,6 +386,8 @@ yang2api_path_fmt_1(yang_stmt *ys, * @param[in] ys Yang statement * @param[in] inclkey If set include key leaf (eg last leaf d in ex) * @param[out] api_path_fmt XML api path. Needs to be freed after use. + * @retval 0 OK + * @retval -1 Error * "api-path" is "URI-encoded path expression" definition in RFC8040 3.5.3 */ int @@ -902,7 +904,7 @@ api_path2xpath(char *api_path, * @param[in] nodeclass Set to schema nodes, data nodes, etc * @param[in] strict Break if api-path is not "complete" otherwise ignore and continue * @param[out] xbotp Resulting xml tree - * @param[out] ybotp Yang spec matching xpathp + * @param[out] ybotp Yang spec matching xpathp * @param[out] xerr Netconf error message (if retval=0) * @retval 1 OK * @retval 0 Invalid api_path or associated XML, netconf error @@ -1144,7 +1146,7 @@ api_path2xml_vec(char **vec, * @param[in,out] xtop Incoming XML tree * @param[in] nodeclass Set to schema nodes, data nodes, etc * @param[in] strict Break if api-path is not "complete" otherwise ignore and continue - * @param[out] xbotp Resulting xml tree (end of xpath) + * @param[out] xbotp Resulting xml tree (end of xpath) (optional) * @param[out] ybotp Yang spec matching xbotp * @param[out] xerr Netconf error message (if retval=0) * @retval 1 OK diff --git a/test/test_snmp_set.sh b/test/test_snmp_set.sh index e558bd64..b3afeefe 100755 --- a/test/test_snmp_set.sh +++ b/test/test_snmp_set.sh @@ -104,16 +104,17 @@ testinit # NET-SNMP-EXAMPLES-MIB::netSnmpExamples MIB=".1.3.6.1.4.1.8072.2" -OID="${MIB}.1.1" # netSnmpExampleInteger +OID1="${MIB}.1.1" # netSnmpExampleInteger +OID3="${MIB}.1.3" # netSnmpExampleString new "Test SNMP get for default value" -expectpart "$($snmpget $OID)" 0 "$OID = INTEGER: 42" +expectpart "$($snmpget $OID1)" 0 "$OID1 = INTEGER: 42" -new "Set new value to OID" -expectpart "$($snmpset $OID i 1234)" 0 "$OID = INTEGER: 1234" +new "Set new value to OID1" +expectpart "$($snmpset $OID1 i 1234)" 0 "$OID1 = INTEGER: 1234" new "Get new value" -expectpart "$($snmpget $OID)" 0 "$OID = INTEGER: 1234" +expectpart "$($snmpget $OID1)" 0 "$OID1 = INTEGER: 1234" new "Set new value via NETCONF" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "none999" "" "" @@ -122,7 +123,16 @@ new "netconf commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" new "Get new value" -expectpart "$($snmpget $OID)" 0 "$OID = INTEGER: 999" +expectpart "$($snmpget $OID1)" 0 "$OID1 = INTEGER: 999" + +new "Test SNMP get string for default value" +expectpart "$($snmpget $OID3)" 0 "$OID3 = STRING: So long, and thanks for all the fish!." + +new "Set new string value to OID3" +expectpart "$($snmpset $OID3 s foobar)" 0 "$OID3 = STRING: foobar" + +new "Get new value" +expectpart "$($snmpget $OID3)" 0 "$OID3 = STRING: foobar" new "Cleaning up" testexit