Skip to content

Commit

Permalink
Add support for custom snmp-keys
Browse files Browse the repository at this point in the history
This commit adds support for defining a
different table/list keys for snmp and
yang lists.

The definition is being done using the
cx-snmp:table-key extension.

Solves #399
  • Loading branch information
shmuelhazan committed Aug 13, 2023
1 parent 4a605ff commit a051c8f
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 23 deletions.
29 changes: 12 additions & 17 deletions apps/snmp/snmp_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,12 +858,12 @@ snmp_table_get(clicon_handle h,
yang_stmt *ys;
yang_stmt *yk;
char *xpath = NULL;
cvec *cvk_orig;
cvec *cvk_val = NULL;
int i;
cg_var *cv;
char *defaultval = NULL;
int ret;
clicon_debug(1, "%s", __FUNCTION__);

/* Get yang of leaf from first part of OID */
ys = NULL;
Expand All @@ -889,18 +889,14 @@ snmp_table_get(clicon_handle h,
*/
if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &defaultval) < 0)
goto done;

/* Create xpath with right keys from later part of OID
* Inverse of snmp_str2oid
*/
if ((cvk_orig = yang_cvec_get(yt)) == NULL){
clicon_err(OE_YANG, 0, "No keys");
goto done;
}
if ((cvk_val = cvec_dup(cvk_orig)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_dup");
if (clixon_snmp_ylist_keys(yt, &cvk_val) < 0) {
clicon_err(OE_XML, errno, "clixon_snmp_ylist_keys");
goto done;
}

/* read through keys and create cvk */
oidilen = oidslen-(oidtlen+1);
oidi = oids+oidtlen+1;
Expand Down Expand Up @@ -974,7 +970,6 @@ snmp_table_set(clicon_handle h,
yang_stmt *yk;
yang_stmt *yrestype = NULL;
char *xpath = NULL;
cvec *cvk_orig;
cvec *cvk_val = NULL;
int i;
cg_var *cv;
Expand All @@ -983,6 +978,7 @@ snmp_table_set(clicon_handle h,
netsnmp_variable_list *requestvb;
int rowstatus = 0;
char *origtype;
clicon_debug(1, "%s", __FUNCTION__);

/* Get OID from table /list */
if ((ret = yangext_oid_get(yt, oidt, &oidtlen, NULL)) < 0)
Expand Down Expand Up @@ -1056,12 +1052,9 @@ snmp_table_set(clicon_handle h,
/* Create xpath with right keys from later part of OID
* Inverse of snmp_str2oid
*/
if ((cvk_orig = yang_cvec_get(yt)) == NULL){
clicon_err(OE_YANG, 0, "No keys");
goto done;
}
if ((cvk_val = cvec_dup(cvk_orig)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_dup");

if (clixon_snmp_ylist_keys(yt, &cvk_val) < 0) {
clicon_err(OE_XML, errno, "clixon_snmp_ylist_keys");
goto done;
}
/* read through keys and create cvk */
Expand Down Expand Up @@ -1182,7 +1175,7 @@ snmp_table_getnext(clicon_handle h,
yang_stmt *ycol;
yang_stmt *ys;
int ret;
cvec *cvk_name;
cvec *cvk_name = NULL;
oid oidc[MAX_OID_LEN] = {0,}; /* Table / list oid */
size_t oidclen = MAX_OID_LEN;
oid oidk[MAX_OID_LEN] = {0,}; /* Key oid */
Expand Down Expand Up @@ -1212,7 +1205,7 @@ snmp_table_getnext(clicon_handle h,
}
if ((xtable = xpath_first(xt, nsc, "%s", xpath)) != NULL) {
/* Make a clone of key-list, but replace names with values */
if ((cvk_name = yang_cvec_get(ylist)) == NULL){
if (clixon_snmp_ylist_keys(ylist, &cvk_name) < 0){
clicon_err(OE_YANG, 0, "No keys");
goto done;
}
Expand Down Expand Up @@ -1260,6 +1253,8 @@ snmp_table_getnext(clicon_handle h,
}
retval = found;
done:
if (cvk_name)
cvec_free(cvk_name);
if (cb)
cbuf_free(cb);
if (xpath)
Expand Down
40 changes: 39 additions & 1 deletion apps/snmp/snmp_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ snmp_yang2xpath_cb(yang_stmt *ys,
}
switch (yang_keyword_get(ys)){
case Y_LIST:
if ((cvk = yang_cvec_get(ys)) == NULL) /* Use Y_LIST cache, see ys_populate_list() */
if (clixon_snmp_ylist_keys(ys, &cvk) < 0)
break;
/* Iterate over individual keys */
assert(keyvec && cvec_len(cvk) == cvec_len(keyvec));
Expand All @@ -1040,6 +1040,7 @@ snmp_yang2xpath_cb(yang_stmt *ys,
cv_string_get(cvec_i(cvk, i)),
cv_string_get(cvec_i(keyvec, i)));
}
cvec_free(cvk);
break;
case Y_LEAF_LIST:
assert(0); // NYI
Expand Down Expand Up @@ -1378,3 +1379,40 @@ clixon_snmp_api_oid_find(oid *oid0,
return retval;
}

/*! Get an SNMP key list from a ylist.
* @param[in] ylist ylist
* @param[out] ylist_keys Vector of key names (strings).
* @retval -1 Error
* @retval 0 OK
* Note: ylist_keys need to be freed.
*/
int clixon_snmp_ylist_keys(yang_stmt *ylist, cvec **ylist_keys) {
int retval = -1;
cvec *cvk = NULL;
char *smi_key_name = NULL;
if (yang_extension_value(ylist, "table-key", CLIXON_SNMP_NS, NULL, &smi_key_name) < 0){
clicon_err(OE_XML, errno, "could not lookup table-key");
goto done;
}

if (!smi_key_name){
/* Keys, go through keys */
if ((cvk = yang_cvec_get(ylist)) == NULL){
clicon_err(OE_YANG, 0, "No keys");
goto done;
}

cvk = cvec_dup(cvk);
} else {
cvk = cvec_new(0);
if (cvec_add_string(cvk, NULL, smi_key_name) < 0){
clicon_err(OE_UNIX, 0, "Could not add key");
goto done;
}
}

*ylist_keys = cvk;
retval = 0;
done:
return retval;
}
2 changes: 2 additions & 0 deletions apps/snmp/snmp_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ extern "C" {
#define CLIXON_ERR_SNMP_MIB 0x1000

#define IETF_YANG_SMIV2_NS "urn:ietf:params:xml:ns:yang:ietf-yang-smiv2"
#define CLIXON_SNMP_NS "http://clicon.org/snmp"

/* Special case/extended Clixon ASN1 types
* Set in type_yang2asn1() if extended is true
Expand Down Expand Up @@ -107,6 +108,7 @@ int snmp_str2oid(char *str, yang_stmt *yi, oid *objid, size_t *objidlen);
int snmp_oid2str(oid **oidi, size_t *oidilen, yang_stmt *yi, cg_var *cv);
int clixon_snmp_err_cb(void *handle, int suberr, cbuf *cb);
int snmp_xmlkey2val_oid(cxobj *xrow, cvec *cvk_name, cvec **cvk_orig, oid *objidk, size_t *objidklen);
int clixon_snmp_ylist_keys(yang_stmt *ylist, cvec **ylist_keys);

/*========== libnetsnmp-specific code =============== */
int clixon_snmp_api_agent_check(void);
Expand Down
15 changes: 11 additions & 4 deletions apps/snmp/snmp_register.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,12 @@ mibyang_table_register(clicon_handle h,
clicon_err(OE_UNIX, errno, "SNMP_MALLOC_TYPEDEF");
goto done;
}
/* Keys, go through keys */
if ((cvk = yang_cvec_get(ylist)) == NULL){
clicon_err(OE_YANG, 0, "No keys");

if (clixon_snmp_ylist_keys(ylist, &cvk) < 0) {
clicon_err(OE_XML, errno, "clixon_snmp_ylist_keys");
goto done;
}

cvi = NULL;
/* Iterate over individual keys */
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
Expand Down Expand Up @@ -331,6 +332,9 @@ mibyang_table_register(clicon_handle h,
ok:
retval = 0;
done:
if (cvk)
cvec_free(cvk);

return retval;
}

Expand Down Expand Up @@ -495,7 +499,8 @@ mibyang_table_poll(clicon_handle h,
}
if ((xtable = xpath_first(xt, nsc, "%s", xpath)) != NULL) {
/* Make a clone of key-list, but replace names with values */
if ((cvk_name = yang_cvec_get(ylist)) == NULL){

if (clixon_snmp_ylist_keys(ylist, &cvk_name) < 0){
clicon_err(OE_YANG, 0, "No keys");
goto done;
}
Expand All @@ -516,6 +521,8 @@ mibyang_table_poll(clicon_handle h,
}
retval = 0;
done:
if (cvk_name)
cvec_free(cvk_name);
if (xpath)
free(xpath);
if (cvk_val)
Expand Down
Loading

0 comments on commit a051c8f

Please sign in to comment.