Fixed: [NETCONF error reply from failed leafref rquire-instance does not comply to RFC 7950](https://github.com/clicon/clixon/issues/53

This commit is contained in:
Olof hagsand 2024-07-22 09:17:13 +02:00
parent 07a1fa164f
commit 816238029d
10 changed files with 96 additions and 47 deletions

View file

@ -162,6 +162,7 @@ int netconf_bad_attribute(cbuf *cb, char *type, char *info, char *message);
int netconf_bad_attribute_xml(cxobj **xret, char *type, char *info, char *message);
int netconf_unknown_attribute(cbuf *cb, char *type, char *info, char *message);
int netconf_missing_element(cbuf *cb, char *type, char *element, char *message);
int netconf_missing_yang_xml(cxobj **xret, char *path, char *app_tag, char *info, char *message);
int netconf_missing_element_xml(cxobj **xret, char *type, char *element, char *message);
int netconf_bad_element(cbuf *cb, char *type, char *info, char *element);
int netconf_bad_element_xml(cxobj **xret, char *type, char *info, char *element);

View file

@ -1060,32 +1060,30 @@ netconf_data_missing_xml(cxobj **xret,
return retval;
}
/*! Create Netconf data-missing / missing-choice as defeind in RFC 7950 15.6
/*! Create Netconf data-missing / missing-choice as defined in RFC 7950 15.5/15.6
*
* If a NETCONF operation would result in configuration data where no
* nodes exists in a mandatory choice, the following error MUST be
* returned:
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] x Element with missing choice
* @param[in] name Name of missing mandatory choice
* @param[in] message Error message
* @retval 0 OK
* @retval -1 Error
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] path Path
* @param[in] app-tag Error app-tag
* @param[in] info Error info
* @param[in] message Error message
* @retval 0 OK
* @retval -1 Error
*/
int
netconf_missing_choice_xml(cxobj **xret,
cxobj *x,
char *name,
char *message)
netconf_missing_yang_xml(cxobj **xret,
char *path,
char *app_tag,
char *info,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xerr;
char *path = NULL;
char *encpath = NULL;
if (xret == NULL || name == NULL){
clixon_err(OE_NETCONF, EINVAL, "xret or name is NULL");
if (xret == NULL || path == NULL){
clixon_err(OE_NETCONF, EINVAL, "xret or path is NULL");
goto done;
}
if (*xret == NULL){
@ -1098,21 +1096,23 @@ netconf_missing_choice_xml(cxobj **xret,
goto done;
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
goto done;
/* error-path: Path to the element with the missing choice. */
if (xml2xpath(x, NULL, 0, 0, &path) < 0)
goto done;
if (xml_chardata_encode(&encpath, 0, "%s", path) < 0)
goto done;
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
"<error-type>application</error-type>"
"<error-tag>data-missing</error-tag>"
"<error-app-tag>missing-choice</error-app-tag>"
"<error-path>%s</error-path>"
"<error-info><missing-choice xmlns=\"%s\">%s</missing-choice></error-info>"
"<error-severity>error</error-severity>",
encpath,
YANG_XML_NAMESPACE,
name) < 0)
"<error-app-tag>%s</error-app-tag>"
"<error-path>%s</error-path>",
app_tag,
encpath) < 0)
goto done;
if (info) {
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
"<error-info>%s</error-info>", info) < 0)
goto done;
}
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
"<error-severity>error</error-severity>") < 0)
goto done;
if (message){
if (xml_chardata_encode(&encstr, 0, "%s", message) < 0)
@ -1123,8 +1123,6 @@ netconf_missing_choice_xml(cxobj **xret,
}
retval = 0;
done:
if (path)
free(path);
if (encstr)
free(encstr);
if (encpath)
@ -1132,6 +1130,52 @@ netconf_missing_choice_xml(cxobj **xret,
return retval;
}
/*! Create Netconf data-missing / missing-choice as defined in RFC 7950 15.6
*
* If a NETCONF operation would result in configuration data where no
* nodes exists in a mandatory choice, the following error MUST be
* returned:
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] x Element with missing choice
* @param[in] name Name of missing mandatory choice
* @param[in] message Error message
* @retval 0 OK
* @retval -1 Error
*/
int
netconf_missing_choice_xml(cxobj **xret,
cxobj *x,
char *name,
char *message)
{
int retval = -1;
cbuf *cbinfo = NULL;
char *path = NULL;
if (name == NULL){
clixon_err(OE_NETCONF, EINVAL, "xret or name is NULL");
goto done;
}
/* error-path: Path to the element. */
if (xml2xpath(x, NULL, 0, 0, &path) < 0)
goto done;
if ((cbinfo = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cbinfo, "<missing-choice xmlns=\"%s\">%s</missing-choice>", YANG_XML_NAMESPACE, name);
if (netconf_missing_yang_xml(xret, path, "missing-choice", cbuf_get(cbinfo), message) < 0)
goto done;
retval = 0;
done:
if (path)
free(path);
if (cbinfo)
cbuf_free(cbinfo);
return retval;
}
/*! Create Netconf operation-not-supported error XML according to RFC 6241 App A
*
* Request could not be completed because the requested operation is not

View file

@ -133,7 +133,6 @@ validate_leafref(cxobj *xt,
cvec *nsc = NULL;
cbuf *cberr = NULL;
char *path_arg;
yang_stmt *ymod;
cg_var *cv;
int require_instance = 1;
@ -179,13 +178,12 @@ validate_leafref(cxobj *xt,
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
ymod = ys_module(ys);
cprintf(cberr, "Leafref validation failed: No leaf %s matching path %s in %s.yang:%d",
leafrefbody,
path_arg,
yang_argument_get(ymod),
yang_linenum_get(ys));
if (xret && netconf_bad_element_xml(xret, "application", leafrefbody, cbuf_get(cberr)) < 0)
/* RFC 7950 15.5 requires:
error-tag: data-missing
error-app-tag: instance-required
error-path: Path to the instance-identifier or leafref leaf.
*/
if (xret && netconf_missing_yang_xml(xret, path_arg, "instance-required", leafrefbody, NULL) < 0)
goto done;
goto fail;
}