From 6465022f578961c3c7a8096ca62eadd659a90209 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Thu, 15 Oct 2020 13:55:44 +0200 Subject: [PATCH] Find non-config nodes and mark/return error with better error message --- apps/backend/backend_client.c | 11 +++++-- lib/clixon/clixon_xml_map.h | 3 +- lib/src/clixon_xml_map.c | 57 ++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index 54606f5d..d931730d 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -640,9 +640,14 @@ from_client_edit_config(clicon_handle h, goto done; goto ok; } - /* Mark all nodes that are not configure data and set return */ - if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0) + /* (Mark all nodes that are not configure data and) set return */ + if ((ret = xml_non_config_data(xc, &xret)) < 0) goto done; + if (ret == 0){ + if (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0) + goto done; + goto ok; + } if (non_config){ if (netconf_invalid_value(cbret, "protocol", "State data not allowed")< 0) goto done; @@ -1143,7 +1148,7 @@ from_client_get(clicon_handle h, /* Keep state data only, remove everything that is not config. Note that state data * may be a sub-part in a config tree, we need to traverse to find all */ - if (xml_apply(xret, CX_ELMNT, xml_non_config_data, NULL) < 0) + if (xml_non_config_data(xret, NULL) < 0) goto done; if (xml_tree_prune_flagged_sub(xret, XML_FLAG_MARK, 1, NULL) < 0) goto done; diff --git a/lib/clixon/clixon_xml_map.h b/lib/clixon/clixon_xml_map.h index 75292014..5e045d30 100644 --- a/lib/clixon/clixon_xml_map.h +++ b/lib/clixon/clixon_xml_map.h @@ -69,8 +69,7 @@ int xml_global_defaults(clicon_handle h, cxobj *xn, cvec *nsc, const char *xpath int xml_nopresence_default(cxobj *xt); int xml_nopresence_default_mark(cxobj *x, void *arg); int xml_sanity(cxobj *x, void *arg); -int xml_non_config_data(cxobj *xt, void *arg); - +int xml_non_config_data(cxobj *xt, cxobj **xerr); int xml2xpath(cxobj *x, char **xpath); int assign_namespace_element(cxobj *x0, cxobj *x1, cxobj *x1p); int assign_namespace_body(cxobj *x0, char *x0bstr, cxobj *x1); diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index a599b1db..178ad772 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -1440,28 +1440,55 @@ xml_sanity(cxobj *xt, return retval; } -/*! Mark all nodes that are not configure data and set return +/*! Detect state data: Either mark or break on first occurence and return xerror * @param[in] xt XML tree - * @param[out] arg If set, set to 1 as int* if not config data + * @param[out] xerr If set return netconf error, abort and return if a state variable found + * @retval -1 Error + * @retval 0 Status node found and return xerror + * @retval 1 OK + * Note that the behaviour is quite different if xerr is set or not,... */ int -xml_non_config_data(cxobj *xt, - void *arg) /* Set to 1 if state node */ +xml_non_config_data(cxobj *xt, + cxobj **xerr) { int retval = -1; - yang_stmt *ys; - - if ((ys = (yang_stmt*)xml_spec(xt)) == NULL){ - retval = 0; - goto done; + cxobj *x; + yang_stmt *y; + int ret; + cbuf *cb = NULL; + + x = NULL; + while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) { + if ((y = (yang_stmt*)xml_spec(x)) == NULL) + goto ok; + if (!yang_config(y)){ /* config == false means state data */ + if (xerr){ /* behaviour 1: return on error */ + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + cprintf(cb, "%s in module %s: state data node unexpected", + yang_argument_get(y), yang_argument_get(ys_module(y))); + if (netconf_invalid_value_xml(xerr, "application", cbuf_get(cb)) < 0) + goto done; + retval = 0; + goto done; + } + xml_flag_set(x, XML_FLAG_MARK); /* behaviour 2: mark and continue */ + } + if ((ret = xml_non_config_data(x, xerr)) < 0) + goto done; + if (ret == 0){ + retval = 0; + goto done; + } } - if (!yang_config(ys)){ /* config == false means state data: mark for remove */ - xml_flag_set(xt, XML_FLAG_MARK); - if (arg) - (*(int*)arg) = 1; - } - retval = 0; + ok: + retval = 1; done: + if (cb) + cbuf_free(cb); return retval; }