diff --git a/CHANGELOG.md b/CHANGELOG.md index 84caa282..0e03a934 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ * If dropped temporary, you can restore privileges with `restore_priv()` ### API changes on existing features (you may need to change your code) +* RESTCONF error reporting + * Invalid api-path syntax error changed from 412 operation-failed to 404 invalid-value. For example, change from + ``` + HTTP/1.1 412 Precondition Failed + {"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"No such yang module: badmodule"}}} + ``` + to: + ``` + HTTP/1.1 404 Not Found + {"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"No such yang module: badmodule"}}} + ``` * Typical installation should now add a `clicon` user (as well as group) * New clixon-config@2019-09-11.yang revision * Added: CLICON_BACKEND_USER: drop of privileges to user, diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c index 2e14cf2d..268974bb 100644 --- a/apps/restconf/restconf_lib.c +++ b/apps/restconf/restconf_lib.c @@ -67,8 +67,8 @@ */ static const map_str2int netconf_restconf_map[] = { {"in-use", 409}, - {"invalid-value", 400}, {"invalid-value", 404}, + {"invalid-value", 400}, {"invalid-value", 406}, {"too-big", 413}, /* request */ {"too-big", 400}, /* response */ diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index bf4c37db..0ae3690b 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -280,12 +280,9 @@ api_data_write(clicon_handle h, if ((cbpath = cbuf_new()) == NULL) goto done; cprintf(cbpath, "/"); - if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace)) < 0) + if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace, &xerr)) < 0) goto done; if (ret == 0){ - if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0) - goto done; - clicon_err_reset(); if ((xe = xpath_first(xerr, "rpc-error")) == NULL){ clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); goto done; diff --git a/apps/restconf/restconf_methods_get.c b/apps/restconf/restconf_methods_get.c index 38757440..8d8a72f6 100644 --- a/apps/restconf/restconf_methods_get.c +++ b/apps/restconf/restconf_methods_get.c @@ -166,8 +166,18 @@ api_data_get2(clicon_handle h, goto done; cprintf(cbpath, "/"); /* We know "data" is element pi-1 */ - if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace)) < 0) + if ((ret = api_path2xpath_cvv(pcvec, pi, yspec, cbpath, &namespace, &xerr)) < 0) goto done; + if (ret == 0){ + clicon_err_reset(); + if ((xe = xpath_first(xerr, "rpc-error")) == NULL){ + clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); + goto done; + } + if (api_return_err(h, r, xe, pretty, media_out, 0) < 0) + goto done; + goto ok; + } if (ret == 0){ if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0) goto done; diff --git a/lib/clixon/clixon_xml_map.h b/lib/clixon/clixon_xml_map.h index e3b98d69..c464ac8f 100644 --- a/lib/clixon/clixon_xml_map.h +++ b/lib/clixon/clixon_xml_map.h @@ -70,7 +70,7 @@ int xml_sanity(cxobj *x, void *arg); int xml_non_config_data(cxobj *xt, void *arg); int xml_spec_populate_rpc(clicon_handle h, cxobj *x, yang_stmt *yspec); int xml_spec_populate(cxobj *x, void *arg); -int api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, char **namespace); +int api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, char **namespace, cxobj **xerr); int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, char **namespace); int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop, yang_class nodeclass, int strict, cxobj **xpathp, yang_stmt **ypathp); diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 6344245e..1982515a 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -2382,11 +2382,12 @@ xml_spec_populate(cxobj *x, * @param[in] yspec Yang spec * @param[in,out] xpath The xpath as cbuf (must be created and may have content) * @param[out] namespace Namespace of xpath (direct pointer don't free) + * @param[out] xerr Netconf error message * @retval 1 OK - * @retval 0 Invalid api_path or associated XML, clicon_err called + * @retval 0 Invalid api_path or associated XML, netconf error xml set * @retval -1 Fatal error, clicon_err called * - * @note both retval 0 and -1 set clicon_err, but the later is fatal + * @note both retval -1 set clicon_err, retval 0 sets netconf xml msg * @note Not proper namespace translation from api-path 2 xpath * It works like this: * Assume origin incoming path is @@ -2413,7 +2414,8 @@ api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, - char **namespace) + char **namespace, + cxobj **xerr) { int retval = -1; int i; @@ -2429,6 +2431,7 @@ api_path2xpath_cvv(cvec *api_path, char **valvec = NULL; int vi; int nvalvec; + cbuf *cberr = NULL; for (i=offset; i