netconf: Generalize the error reporting interface

Add some functions to report general XML errors and switch over the
internal functions in netconf to use the new interface.  This prepares
the way for reporting RPC errors from plugins.

Signed-off-by: Corey Minyard <minyard@acm.org>
This commit is contained in:
Corey Minyard 2025-01-29 08:25:24 -08:00 committed by Olof Hagsand
parent 79440c5dfd
commit 3a1aa4052f
2 changed files with 132 additions and 33 deletions

View file

@ -161,6 +161,11 @@ int netconf_missing_attribute_xml(cxobj **xret, char *type, char *info, char *me
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_common_rpc_err(cbuf *cb, char *ns, char *type, char *tag, char *info,
char *severity, char *message);
int netconf_common_rpc_err_xml(cxobj **xret, char *ns, char *type, char *tag,
char *severity, char *infotag, 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);

View file

@ -487,23 +487,85 @@ netconf_unknown_attribute(cbuf *cb,
goto done;
}
/*! Common Netconf element XML tree according to RFC 6241 App A
/*! Create Netconf rpc-error XML tree with all parameters available.
*
* An unexpected attribute is present.
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] ns Namespace. If NULL the netconf base ns will be used
* @param[in] type Error type: "rpc", "application" or "protocol"
* @param[in] severity Severity: "error" or "warning"
* @param[in] tag Error tag, like "invalid-value" or "unknown-attribute"
* @param[in] info bad-attribute or bad-element xml. If NULL not included.
* @param[in] message Error message. May be NULL.
* @retval 0 OK
* @retval -1 Error
*/
int
netconf_common_rpc_err(cbuf *cb,
char *ns,
char *type,
char *tag,
char *severity,
char *info,
char *message)
{
int retval = -1;
char *encstr = NULL;
if (!ns)
ns = NETCONF_BASE_NAMESPACE;
if (cprintf(cb, "<rpc-reply xmlns=\"%s\"><rpc-error>"
"<error-type>%s</error-type>"
"<error-tag>%s</error-tag>"
"<error-severity>%s</error-severity>",
ns, type, tag, severity) < 0)
goto err;
if (info){
if (cprintf(cb, "<error-info>%s</error-info>", info) < 0)
goto err;
}
if (message){
if (xml_chardata_encode(&encstr, 0, "%s", message) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") < 0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
return retval;
err:
clixon_err(OE_XML, errno, "cprintf");
goto done;
}
/*! Common Netconf element XML tree according to RFC 6241 App A, allow a
* passed in namespace.
*
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] ns Namespace to use, if NULL it will use the default
* @param[in] type Error type: "application" or "protocol"
* @param[in] tag Error tag
* @param[in] element bad-element xml
* @param[in] message Error message (will be XML encoded)
* @param[in] severity Message severity
* @param[in] infotag Tag for the info, may be NULL if not tag required
* @param[in] info info, may be NULL if no info
* @param[in] message Error message (will be XML encoded), may be NULL
* @retval 0 OK
* @retval -1 Error
*/
static int
netconf_common_xml(cxobj **xret,
char *type,
char *tag,
char *infotag,
char *element,
char *message)
int
netconf_common_rpc_err_xml(cxobj **xret,
char *ns,
char *type,
char *tag,
char *severity,
char *infotag,
char *info,
char *message)
{
int retval =-1;
cxobj *xerr;
@ -513,22 +575,45 @@ netconf_common_xml(cxobj **xret,
clixon_err(OE_NETCONF, EINVAL, "xret is NULL");
goto done;
}
if (!ns)
ns = NETCONF_BASE_NAMESPACE;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, CX_ELMNT)) == NULL)
goto done;
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
if (xml_add_attr(*xret, "xmlns", ns, NULL, NULL) == NULL)
goto done;
}
else if (xml_name_set(*xret, "rpc-reply") < 0)
goto done;
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
goto done;
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>%s</error-type>"
"<error-tag>%s</error-tag>"
"<error-info><%s>%s</%s></error-info>"
"<error-severity>error</error-severity>",
type, tag, infotag, element, infotag) < 0)
goto done;
if (infotag) {
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
"<error-type>%s</error-type>"
"<error-tag>%s</error-tag>"
"<error-info><%s>%s</%s></error-info>"
"<error-severity>%s</error-severity>",
type, tag, infotag, info, infotag,
severity) < 0)
goto done;
} else if (info) {
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
"<error-type>%s</error-type>"
"<error-tag>%s</error-tag>"
"<error-info>%s</error-info>"
"<error-severity>%s</error-severity>",
type, tag, info, severity) < 0)
goto done;
} else {
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
"<error-type>%s</error-type>"
"<error-tag>%s</error-tag>"
"<error-severity>%s</error-severity>",
type, tag, severity) < 0)
goto done;
}
if (message){
if (xml_chardata_encode(&encstr, 0, "%s", message) < 0)
goto done;
@ -562,8 +647,9 @@ netconf_missing_element(cbuf *cb,
int retval = -1;
cxobj *xret = NULL;
if (netconf_common_xml(&xret, type, "missing-element",
"bad-element", element, message) < 0)
if (netconf_common_rpc_err_xml(&xret, NETCONF_BASE_NAMESPACE, type,
"missing-element", "error",
"bad-element", element, message) < 0)
goto done;
if (clixon_xml2cbuf(cb, xret, 0, 0, NULL, -1, 0) < 0)
goto done;
@ -588,8 +674,9 @@ netconf_missing_element_xml(cxobj **xret,
char *element,
char *message)
{
return netconf_common_xml(xret, type, "missing-element",
"bad-element", element, message);
return netconf_common_rpc_err_xml(xret, NETCONF_BASE_NAMESPACE, type,
"missing-element", "error",
"bad-element", element, message);
}
/*! Create Netconf bad-element error XML tree according to RFC 6241 App A
@ -612,8 +699,9 @@ netconf_bad_element(cbuf *cb,
int retval = -1;
cxobj *xret = NULL;
if (netconf_common_xml(&xret, type, "bad-element",
"bad-element",element, message) < 0)
if (netconf_common_rpc_err_xml(&xret, NETCONF_BASE_NAMESPACE, type,
"bad-element", "error",
"bad-element",element, message) < 0)
goto done;
if (clixon_xml2cbuf(cb, xret, 0, 0, NULL, -1, 0) < 0)
goto done;
@ -630,7 +718,9 @@ netconf_bad_element_xml(cxobj **xret,
char *element,
char *message)
{
return netconf_common_xml(xret, type, "bad-element", "bad-element", element, message);
return netconf_common_rpc_err_xml(xret, NETCONF_BASE_NAMESPACE, type,
"bad-element", "error",
"bad-element", element, message);
}
/*! Create Netconf unknown-element error XML tree according to RFC 6241 App A
@ -652,8 +742,9 @@ netconf_unknown_element(cbuf *cb,
int retval = -1;
cxobj *xret = NULL;
if (netconf_common_xml(&xret, type, "unknown-element",
"bad-element", element, message) < 0)
if (netconf_common_rpc_err_xml(&xret, NETCONF_BASE_NAMESPACE, type,
"unknown-element", "error",
"bad-element", element, message) < 0)
goto done;
if (clixon_xml2cbuf(cb, xret, 0, 0, NULL, -1, 0) < 0)
goto done;
@ -680,8 +771,9 @@ netconf_unknown_element_xml(cxobj **xret,
char *element,
char *message)
{
return netconf_common_xml(xret, type, "unknown-element",
"bad-element", element, message);
return netconf_common_rpc_err_xml(xret, NETCONF_BASE_NAMESPACE, type,
"unknown-element", "error",
"bad-element", element, message);
}
/*! Create Netconf unknown-namespace error XML tree according to RFC 6241 App A
@ -703,8 +795,9 @@ netconf_unknown_namespace(cbuf *cb,
int retval = -1;
cxobj *xret = NULL;
if (netconf_common_xml(&xret, type, "unknown-namespace",
"bad-namespace", ns, message) < 0)
if (netconf_common_rpc_err_xml(&xret, NETCONF_BASE_NAMESPACE, type,
"unknown-namespace", "error",
"bad-namespace", ns, message) < 0)
goto done;
if (clixon_xml2cbuf(cb, xret, 0, 0, NULL, -1, 0) < 0)
goto done;
@ -721,8 +814,9 @@ netconf_unknown_namespace_xml(cxobj **xret,
char *ns,
char *message)
{
return netconf_common_xml(xret, type, "unknown-namespace",
"bad-namespace", ns, message);
return netconf_common_rpc_err_xml(xret, NETCONF_BASE_NAMESPACE, type,
"unknown-namespace", "error",
"bad-namespace", ns, message);
}
/*! Create Netconf access-denied error cbuf according to RFC 6241 App A