Corrected error message for list min/max-value to comply to RFC 7950: a proper path is now returned, peviously only the list symbol. it is also exposed in the CLI correctly.

* Example: `<error-path>/c/a1</error-path>`
This commit is contained in:
Olof hagsand 2020-08-27 15:52:31 +02:00
parent a3e80080e2
commit 558abb1f9b
5 changed files with 49 additions and 28 deletions

View file

@ -35,6 +35,8 @@ Users may have to change how they access the system
### Corrected Bugs ### Corrected Bugs
* Corrected error message for list min/max-value to comply to RFC 7950: a proper path is now returned, peviously only the list symbol. it is also exposed in the CLI correctly.
* Example: `<error-path>/c/a1</error-path>`
* Fixed: [Yang modules skipped if the name is a proper prefix of other module name](https://github.com/clicon/clixon/issues/130) * Fixed: [Yang modules skipped if the name is a proper prefix of other module name](https://github.com/clicon/clixon/issues/130)
* Fixed an error in global default values. Global default values were not written to datastore after startup, but AFTER an edit/commit. * Fixed an error in global default values. Global default values were not written to datastore after startup, but AFTER an edit/commit.
* Fixed: [Type / Endianism problem in yang_parse_file #128](https://github.com/clicon/clixon/issues/128) * Fixed: [Type / Endianism problem in yang_parse_file #128](https://github.com/clicon/clixon/issues/128)

View file

@ -97,7 +97,7 @@ int netconf_operation_failed_xml(cxobj **xret, char *type, char *message);
int netconf_malformed_message(cbuf *cb, char *message); int netconf_malformed_message(cbuf *cb, char *message);
int netconf_malformed_message_xml(cxobj **xret, char *message); int netconf_malformed_message_xml(cxobj **xret, char *message);
int netconf_data_not_unique_xml(cxobj **xret, cxobj *x, cvec *cvk); int netconf_data_not_unique_xml(cxobj **xret, cxobj *x, cvec *cvk);
int netconf_minmax_elements_xml(cxobj **xret, cxobj *x, int max); int netconf_minmax_elements_xml(cxobj **xret, cxobj *xp, char *name, int max);
int netconf_trymerge(cxobj *x, yang_stmt *yspec, cxobj **xret); int netconf_trymerge(cxobj *x, yang_stmt *yspec, cxobj **xret);
int netconf_module_features(clicon_handle h); int netconf_module_features(clicon_handle h);
int netconf_module_load(clicon_handle h); int netconf_module_load(clicon_handle h);

View file

@ -1173,19 +1173,23 @@ netconf_data_not_unique_xml(cxobj **xret,
/*! Create Netconf too-many/few-elements err msg according to RFC 7950 15.2/15.3 /*! Create Netconf too-many/few-elements err msg according to RFC 7950 15.2/15.3
* *
* A NETCONF operation would result in configuration data where a * A NETCONF operation would result in configuration data where a
list or a leaf-list would have too many entries, the following error * list or a leaf-list would have too many entries, the following error
* @param[out] xret Error XML tree. Free with xml_free after use * @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] x List element containing duplicate * @param[in] xp XML parent node (for error)
* @param[in] name Name of list (for error)
* @param[in] max If set, return too-many, otherwise too-few * @param[in] max If set, return too-many, otherwise too-few
* @see RFC7950 Sec 15.1 * @see RFC7950 Sec 15.1
*/ */
int int
netconf_minmax_elements_xml(cxobj **xret, netconf_minmax_elements_xml(cxobj **xret,
cxobj *x, cxobj *xp,
char *name,
int max) int max)
{ {
int retval = -1; int retval = -1;
cxobj *xerr; cxobj *xerr;
char *path = NULL;
cbuf *cb = NULL;
if (*xret == NULL){ if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, CX_ELMNT)) == NULL) if ((*xret = xml_new("rpc-reply", NULL, CX_ELMNT)) == NULL)
@ -1195,16 +1199,31 @@ netconf_minmax_elements_xml(cxobj **xret,
goto done; goto done;
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL) if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
goto done; goto done;
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
if (xml_parent(xp)){ /* Dont include root, eg <config> */
if (xml2xpath(xp, &path) < 0)
goto done;
if (path)
cprintf(cb, "%s", path);
}
cprintf(cb, "/%s", name);
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>protocol</error-type>" if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>protocol</error-type>"
"<error-tag>operation-failed</error-tag>" "<error-tag>operation-failed</error-tag>"
"<error-app-tag>too-%s-elements</error-app-tag>" "<error-app-tag>too-%s-elements</error-app-tag>"
"<error-severity>error</error-severity>" "<error-severity>error</error-severity>"
"<error-path>%s</error-path>", "<error-path>%s</error-path>",
max?"many":"few", max?"many":"few",
xml_name(x)) < 0) /* XXX should be xml2xpath */ cbuf_get(cb)) < 0)
goto done; goto done;
retval = 0; retval = 0;
done: done:
if (path)
free(path);
if (cb)
cbuf_free(cb);
return retval; return retval;
} }
@ -1381,6 +1400,8 @@ netconf_err2cb(cxobj *xerr,
clicon_xml2cbuf(cberr, xml_child_i(x,0), 0, 0, -1); clicon_xml2cbuf(cberr, xml_child_i(x,0), 0, 0, -1);
if ((x=xpath_first(xerr, NULL, "//error-app-tag"))!=NULL) if ((x=xpath_first(xerr, NULL, "//error-app-tag"))!=NULL)
cprintf(cberr, ": %s ", xml_body(x)); cprintf(cberr, ": %s ", xml_body(x));
if ((x=xpath_first(xerr, NULL, "//error-path"))!=NULL)
cprintf(cberr, ": %s ", xml_body(x));
retval = 0; retval = 0;
return retval; return retval;
} }

View file

@ -694,8 +694,8 @@ check_unique_list(cxobj *x,
} }
/*! Given a list, check if any min/max-elemants constraints apply /*! Given a list, check if any min/max-elemants constraints apply
* @param[in] x One x (the last) of a specific lis * @param[in] xp Parent of the xml list there are too few/many
* @param[in] y Yang spec of x * @param[in] y Yang spec of the failing list
* @param[in] nr Number of elements (like x) in thlist * @param[in] nr Number of elements (like x) in thlist
* @param[out] xret Error XML tree. Free with xml_free after use * @param[out] xret Error XML tree. Free with xml_free after use
* @retval 1 Validation OK * @retval 1 Validation OK
@ -704,7 +704,7 @@ check_unique_list(cxobj *x,
* @see RFC7950 7.7.5 * @see RFC7950 7.7.5
*/ */
static int static int
check_min_max(cxobj *x, check_min_max(cxobj *xp,
yang_stmt *y, yang_stmt *y,
int nr, int nr,
cxobj **xret) cxobj **xret)
@ -717,7 +717,7 @@ check_min_max(cxobj *x,
if ((ymin = yang_find(y, Y_MIN_ELEMENTS, NULL)) != NULL){ if ((ymin = yang_find(y, Y_MIN_ELEMENTS, NULL)) != NULL){
cv = yang_cv_get(ymin); cv = yang_cv_get(ymin);
if (nr < cv_uint32_get(cv)){ if (nr < cv_uint32_get(cv)){
if (netconf_minmax_elements_xml(xret, x, 0) < 0) if (netconf_minmax_elements_xml(xret, xp, yang_argument_get(y), 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -726,7 +726,7 @@ check_min_max(cxobj *x,
cv = yang_cv_get(ymax); cv = yang_cv_get(ymax);
if (cv_uint32_get(cv) > 0 && /* 0 means unbounded */ if (cv_uint32_get(cv) > 0 && /* 0 means unbounded */
nr > cv_uint32_get(cv)){ nr > cv_uint32_get(cv)){
if (netconf_minmax_elements_xml(xret, x, 1) < 0) if (netconf_minmax_elements_xml(xret, xp, yang_argument_get(y), 1) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -789,7 +789,6 @@ check_list_unique_minmax(cxobj *xt,
yang_stmt *yprev = NULL; /* previous in list */ yang_stmt *yprev = NULL; /* previous in list */
yang_stmt *ye = NULL; /* yang each list to catch emtpy */ yang_stmt *ye = NULL; /* yang each list to catch emtpy */
yang_stmt *ych; /* y:s parent node (if choice that ye can compare to) */ yang_stmt *ych; /* y:s parent node (if choice that ye can compare to) */
cxobj *xp = NULL; /* previous in list */
yang_stmt *yu; /* yang unique */ yang_stmt *yu; /* yang unique */
int ret; int ret;
int nr=0; /* Nr of list elements for min/max check */ int nr=0; /* Nr of list elements for min/max check */
@ -818,7 +817,7 @@ check_list_unique_minmax(cxobj *xt,
/* Only lists and leaf-lists are allowed to be many /* Only lists and leaf-lists are allowed to be many
* This checks duplicate container and leafs * This checks duplicate container and leafs
*/ */
if (netconf_minmax_elements_xml(xret, x, 1) < 0) if (netconf_minmax_elements_xml(xret, xt, xml_name(x), 1) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -832,14 +831,13 @@ check_list_unique_minmax(cxobj *xt,
} }
else { else {
/* Check if the list length violates min/max */ /* Check if the list length violates min/max */
if ((ret = check_min_max(xp, yprev, nr, xret)) < 0) if ((ret = check_min_max(xt, yprev, nr, xret)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;
} }
} }
yprev = y; /* Restart min/max count */ yprev = y; /* Restart min/max count */
xp = x; /* Need a reference to the XML as well */
nr = 1; nr = 1;
/* Gap analysis: Check if there is any empty list between y and yprev /* Gap analysis: Check if there is any empty list between y and yprev
* Note, does not detect empty choice list (too complicated) * Note, does not detect empty choice list (too complicated)
@ -884,7 +882,7 @@ check_list_unique_minmax(cxobj *xt,
*/ */
if (yprev){ if (yprev){
/* Check if the list length violates min/max */ /* Check if the list length violates min/max */
if ((ret = check_min_max(xp, yprev, nr, xret)) < 0) if ((ret = check_min_max(xt, yprev, nr, xret)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;

View file

@ -137,31 +137,31 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
#XXX echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' |$clixon_netconf -qf $cfg #XXX echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' |$clixon_netconf -qf $cfg
new "minmax: validate should fail" new "minmax: validate should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>c</error-path></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>/c/a1</error-path></rpc-error></rpc-reply>]]>]]>$'
new "minmax: no list" new "minmax: no list"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><b1>0</b1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><b1>0</b1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "minmax: validate should fail" new "minmax: validate should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>c</error-path></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>/c/a1</error-path></rpc-error></rpc-reply>]]>]]>$'
new "minmax: no leaf-list" new "minmax: no leaf-list"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><a1><k>0</k></a1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><a1><k>0</k></a1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "minmax: validate should fail" new "minmax: validate should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>c</error-path></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>/c/b1</error-path></rpc-error></rpc-reply>]]>]]>$'
new "minmax: Too large list" new "minmax: Too large list"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><a1><k>0</k></a1><a1><k>1</k></a1><a1><k>2</k></a1><b1>0</b1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><a1><k>0</k></a1><a1><k>1</k></a1><a1><k>2</k></a1><b1>0</b1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "minmax: validate should fail" new "minmax: validate should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>a1</error-path></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>/c/a1</error-path></rpc-error></rpc-reply>]]>]]>$'
new "minmax: Too large leaf-list" new "minmax: Too large leaf-list"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><a1><k>0</k></a1><b1>0</b1><b1>1</b1><b1>2</b1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c xmlns="urn:example:clixon"><a1><k>0</k></a1><b1>0</b1><b1>1</b1><b1>2</b1></c></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "minmax: validate should fail" new "minmax: validate should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>b1</error-path></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>/c/b1</error-path></rpc-error></rpc-reply>]]>]]>$'
new "netconf discard-changes" new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -196,7 +196,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
</c2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" </c2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "minmax choice: too many validate should fail" new "minmax choice: too many validate should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>a1</error-path></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>/c2/a1</error-path></rpc-error></rpc-reply>]]>]]>$'
new "netconf discard-changes" new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -219,7 +219,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
</config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" </config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "minmax top level too many should fail" new "minmax top level too many should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>b3</error-path></rpc-error></rpc-reply>]]>]]>' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>/b3</error-path></rpc-error></rpc-reply>]]>]]>'
new "netconf discard-changes" new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"