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 Jan 2, 2024
1 parent 798a9fb commit 1fb33df
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 22 deletions.
29 changes: 12 additions & 17 deletions apps/snmp/snmp_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,12 +864,12 @@ snmp_table_get(clixon_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 @@ -895,18 +895,14 @@ snmp_table_get(clixon_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){
clixon_err(OE_YANG, 0, "No keys");
goto done;
}
if ((cvk_val = cvec_dup(cvk_orig)) == NULL){
clixon_err(OE_UNIX, errno, "cvec_dup");
if (clixon_snmp_ylist_keys(yt, &cvk_val) < 0) {
clixon_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 @@ -981,7 +977,6 @@ snmp_table_set(clixon_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 @@ -990,6 +985,7 @@ snmp_table_set(clixon_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 @@ -1063,12 +1059,9 @@ snmp_table_set(clixon_handle h,
/* Create xpath with right keys from later part of OID
* Inverse of snmp_str2oid
*/
if ((cvk_orig = yang_cvec_get(yt)) == NULL){
clixon_err(OE_YANG, 0, "No keys");
goto done;
}
if ((cvk_val = cvec_dup(cvk_orig)) == NULL){
clixon_err(OE_UNIX, errno, "cvec_dup");

if (clixon_snmp_ylist_keys(yt, &cvk_val) < 0) {
clixon_err(OE_XML, errno, "clixon_snmp_ylist_keys");
goto done;
}
/* read through keys and create cvk */
Expand Down Expand Up @@ -1190,7 +1183,7 @@ snmp_table_getnext(clixon_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 @@ -1220,7 +1213,7 @@ snmp_table_getnext(clixon_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){
clixon_err(OE_YANG, 0, "No keys");
goto done;
}
Expand Down Expand Up @@ -1268,6 +1261,8 @@ snmp_table_getnext(clixon_handle h,
}
retval = found;
done:
if (cvk_name)
cvec_free(cvk_name);
if (cb)
cbuf_free(cb);
if (xpath)
Expand Down
41 changes: 40 additions & 1 deletion apps/snmp/snmp_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,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 @@ -1042,6 +1042,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 @@ -1389,3 +1390,41 @@ clixon_snmp_api_oid_find(oid *oid0,
// done:
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 @@ -285,11 +285,12 @@ mibyang_table_register(clixon_handle h,
clixon_err(OE_UNIX, errno, "SNMP_MALLOC_TYPEDEF");
goto done;
}
/* Keys, go through keys */
if ((cvk = yang_cvec_get(ylist)) == NULL){
clixon_err(OE_YANG, 0, "No keys");

if (clixon_snmp_ylist_keys(ylist, &cvk) < 0) {
clixon_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(clixon_handle h,
ok:
retval = 0;
done:
if (cvk)
cvec_free(cvk);

return retval;
}

Expand Down Expand Up @@ -496,7 +500,8 @@ mibyang_table_poll(clixon_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){
clixon_err(OE_YANG, 0, "No keys");
goto done;
}
Expand All @@ -517,6 +522,8 @@ mibyang_table_poll(clixon_handle h,
}
retval = 0;
done:
if (cvk_name)
cvec_free(cvk_name);
if (xpath)
free(xpath);
if (cvk_val)
Expand Down
1 change: 1 addition & 0 deletions yang/clixon/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ YANGSPECS += clixon-rfc5277@2008-07-01.yang
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9
YANGSPECS += clixon-autocli@2023-09-01.yang # 6.4
YANGSPECS += clixon-snmp@2023-01-17.yang

all:

Expand Down
55 changes: 55 additions & 0 deletions yang/clixon/clixon-snmp@2023-01-17.yang
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module clixon-snmp{
yang-version 1.1;
namespace "http://clicon.org/snmp";
prefix cx-snmp;

organization
"Clicon / Clixon";

contact
"Olof Hagsand <olof@hagsand.se>";

description
"Clixon SNMP-specific extensions.
Design inspired by ietf-netconf-acm.yang
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
This file is part of CLIXON
Licensed under the Apache License, Version 2.0 (the \"License\");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an \"AS IS\" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the \"GPL\"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****";


revision 2023-01-17 {
description
"Initial version";
}
extension table-key {
argument key-name;

description
"Selects an alternative key for an SNMP table represented by the YANG list.";
}
}

0 comments on commit 1fb33df

Please sign in to comment.