From 3a1aa4052f8c41b0b9d72564aac310f468703eb1 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 29 Jan 2025 08:25:24 -0800 Subject: [PATCH] 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 --- lib/clixon/clixon_netconf_lib.h | 5 + lib/src/clixon_netconf_lib.c | 160 +++++++++++++++++++++++++------- 2 files changed, 132 insertions(+), 33 deletions(-) diff --git a/lib/clixon/clixon_netconf_lib.h b/lib/clixon/clixon_netconf_lib.h index fdcceb50..3f2ba051 100644 --- a/lib/clixon/clixon_netconf_lib.h +++ b/lib/clixon/clixon_netconf_lib.h @@ -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); diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index 5e37013f..71f44a68 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -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, "" + "%s" + "%s" + "%s", + ns, type, tag, severity) < 0) + goto err; + if (info){ + if (cprintf(cb, "%s", info) < 0) + goto err; + } + if (message){ + if (xml_chardata_encode(&encstr, 0, "%s", message) < 0) + goto done; + if (cprintf(cb, "%s", encstr) < 0) + goto err; + } + if (cprintf(cb, "") < 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, "%s" - "%s" - "<%s>%s" - "error", - type, tag, infotag, element, infotag) < 0) - goto done; + if (infotag) { + if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, + "%s" + "%s" + "<%s>%s" + "%s", + type, tag, infotag, info, infotag, + severity) < 0) + goto done; + } else if (info) { + if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, + "%s" + "%s" + "%s" + "%s", + type, tag, info, severity) < 0) + goto done; + } else { + if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, + "%s" + "%s" + "%s", + type, tag, severity) < 0) + goto done; + } if (message){ if (xml_chardata_encode(&encstr, 0, "%s", message) < 0) goto done; @@ -541,7 +626,7 @@ netconf_common_xml(cxobj **xret, if (encstr) free(encstr); return retval; -} +} /*! Create Netconf missing-element error XML tree according to RFC 6241 App A * @@ -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