From 62446db752296e4657955357b0f8409faf45297c Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 14 Jul 2020 19:56:42 +0200 Subject: [PATCH] Fixed `CLICON_YANG_UNKNOWN_ANYDATA` for config and state data. This feature introduced in 4.5 didnt really work. --- CHANGELOG.md | 1 + lib/clixon/clixon_yang.h | 2 ++ lib/src/clixon_datastore_write.c | 30 ++++++++++++++++++++++++------ lib/src/clixon_xml_bind.c | 8 ++++++++ lib/src/clixon_yang.c | 26 ++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d53ca60..b475f5b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,7 @@ Expected: July 2020 ### Corrected Bugs +* Fixed `CLICON_YANG_UNKNOWN_ANYDATA` for config and state data. This feature introduced in 4.5 didnt really work. * Fixed: [Double free when using libxml2 as regex engine #117](https://github.com/clicon/clixon/issues/117) * Fixed: Reading in a yang-spec file exactly the same size as the buffer (1024/2048/4096/...) could leave the buffer not terminated with a 0 byte * Fixed: The module `clixon-rfc5277` was always enabled, but should only be enabled when `CLICON_STREAM_DISCOVERY_RFC5277` is enabled. diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 309dcaac..bc7fc3e2 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -254,5 +254,7 @@ int yang_type_cache_get(yang_stmt *ytype, yang_stmt **resolved, int *opti cvec **cvv, cvec *patterns, int *rxmode, cvec *regexps, uint8_t *fraction); int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv, cvec *patterns, uint8_t fraction); +yang_stmt *yang_anydata_add(yang_stmt *yp, char *name); + #endif /* _CLIXON_YANG_H_ */ diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 8c90923a..f0d767e6 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -571,9 +571,19 @@ text_modify(clicon_handle h, while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) { x1cname = xml_name(x1c); /* Get yang spec of the child by child matching */ - if ((yc = yang_find_datanode(y0, x1cname)) == NULL){ - clicon_err(OE_YANG, errno, "No yang node found: %s", x1cname); - goto done; + yc = yang_find_datanode(y0, x1cname); + if (yc == NULL){ + if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1){ + /* Add dummy Y_ANYDATA yang stmt, see ysp_add */ + if ((yc = yang_anydata_add(y0, x1cname)) < 0) + goto done; + xml_spec_set(x1c, yc); + } + else{ + if (netconf_unknown_element(cbret, "application", x1cname, "Unassigned yang spec") < 0) + goto done; + goto fail; + } } /* There is a cornercase (eg augment) of multi-namespace trees where * the yang child has a different namespace. @@ -767,9 +777,17 @@ text_modify_top(clicon_handle h, if (ymod != NULL) yc = yang_find_datanode(ymod, x1cname); if (yc == NULL){ - if (netconf_unknown_element(cbret, "application", x1cname, "Unassigned yang spec") < 0) - goto done; - goto fail; + if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1){ + /* Add dummy Y_ANYDATA yang stmt, see ysp_add */ + if ((yc = yang_anydata_add(ymod, x1cname)) < 0) + goto done; + xml_spec_set(x1c, yc); + } + else{ + if (netconf_unknown_element(cbret, "application", x1cname, "Unassigned yang spec") < 0) + goto done; + goto fail; + } } /* See if there is a corresponding node in the base tree */ if (match_base_child(x0, x1c, yc, &x0c) < 0) diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c index c40f0ed4..67bb067b 100644 --- a/lib/src/clixon_xml_bind.c +++ b/lib/src/clixon_xml_bind.c @@ -168,6 +168,10 @@ populate_self_parent(cxobj *xt, goto done; if ((y = yang_find_datanode(yparent, name)) == NULL){ if (_yang_unknown_anydata){ + /* Add dummy Y_ANYDATA yang stmt, see ysp_add */ + if ((y = yang_anydata_add(yparent, name)) < 0) + goto done; + xml_spec_set(xt, y); retval = 2; /* treat as anydata */ goto done; } @@ -258,6 +262,10 @@ populate_self_top(cxobj *xt, goto done; if ((y = yang_find_schemanode(ymod, name)) == NULL){ /* also rpc */ if (_yang_unknown_anydata){ + /* Add dummy Y_ANYDATA yang stmt, see ysp_add */ + if ((y = yang_anydata_add(ymod, name)) < 0) + goto done; + xml_spec_set(xt, y); retval = 2; /* treat as anydata */ goto done; } diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 595c9420..5e92dc90 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -2850,6 +2850,32 @@ yang_type_cache_free(yang_type_cache *ycache) return 0; } +/*! Add a simple anydata-node + * + * One usecase is CLICON_YANG_UNKNOWN_ANYDATA when unknown data is treated as anydata + * @param[in] yp Yang parent statement + * @param[in] name Node name + * @retval ys OK + * @retval NULL Error + * @see ysp_add + */ +yang_stmt * +yang_anydata_add(yang_stmt *yp, + char *name) +{ + yang_stmt *ys = NULL; + + if ((ys = ys_new(Y_ANYDATA)) == NULL) + goto done; + yang_argument_set(ys, name); + if (yn_insert(yp, ys) < 0){ /* Insert into hierarchy */ + ys = NULL; + goto done; + } + done: + return ys; +} + #ifdef XML_EXPLICIT_INDEX /*! Mark element as search_index in list * @retval 0 OK