diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ee262ce1..0c8fe6f05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,6 +112,7 @@ Developers may need to change their code ### Corrected Bugs +* Fixed [xml bind yang error in xml_bind_yang_rpc_reply #175](https://github.com/clicon/clixon/issues/175) * Fixed: [Is there an error with plugin's ca_interrupt setting ? #173](https://github.com/clicon/clixon/issues/173) * Fixed: unknown nodes (for extenstions) did not work when placed directly under a grouping clause * Fixed: [Behaviour of Empty LIST Input in RESTCONF JSON #166](https://github.com/clicon/clixon/issues/166) diff --git a/example/main/clixon-example@2020-12-01.yang b/example/main/clixon-example@2020-12-01.yang index cb67328fc..6403dda24 100644 --- a/example/main/clixon-example@2020-12-01.yang +++ b/example/main/clixon-example@2020-12-01.yang @@ -216,6 +216,9 @@ module clixon-example { leaf uk{ type string; } + leaf val{ + type string; + } } } } diff --git a/example/main/example_backend.c b/example/main/example_backend.c index a364d886e..7f402e1e7 100644 --- a/example/main/example_backend.c +++ b/example/main/example_backend.c @@ -309,7 +309,7 @@ example_rpc(clicon_handle h, /* Clicon handle */ cprintf(cbret, "", msgid); + cprintf(cbret, " message-id=\"%s\"", msgid); } cprintf(cbret, ">"); if (!xml_child_nr_type(xe, CX_ELMNT)) diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index 7d97ffa03..6479bcfae 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -323,6 +323,8 @@ clicon_rpc_netconf(clicon_handle h, * @param[in] xml XML netconf tree * @param[out] xret Return XML netconf tree, error or OK * @param[out] sp Socket pointer for notification, otherwise NULL + * @retval 0 OK + * @retval -1 Error * @code * cxobj *xret = NULL; * int s; @@ -345,6 +347,8 @@ clicon_rpc_netconf_xml(clicon_handle h, char *rpcname; cxobj *xreply; yang_stmt *yspec; + cxobj *xerr = NULL; + int ret; if ((cb = cbuf_new()) == NULL){ clicon_err(OE_XML, errno, "cbuf_new"); @@ -363,11 +367,24 @@ clicon_rpc_netconf_xml(clicon_handle h, xml_find_type(xreply, NULL, "rpc-error", CX_ELMNT) == NULL){ yspec = clicon_dbspec_yang(h); /* Here use rpc name to bind to yang */ - if (xml_bind_yang_rpc_reply(xreply, rpcname, yspec, NULL) < 0) + if ((ret = xml_bind_yang_rpc_reply(xreply, rpcname, yspec, &xerr)) < 0) goto done; + if (ret == 0){ + /* Replace reply with error */ + if (*xret) { + cxobj *xc; + if ((xc = xml_child_i(*xret, 0)) != NULL) + xml_purge(xc); + if (xml_addsub(*xret, xerr) < 0) + goto done; + xerr = NULL; + } + } } retval = 0; done: + if (xerr) + xml_free(xerr); if (cb) cbuf_free(cb); return retval; diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c index 4719df479..babfd50ba 100644 --- a/lib/src/clixon_xml_bind.c +++ b/lib/src/clixon_xml_bind.c @@ -613,9 +613,9 @@ xml_bind_yang_rpc(cxobj *xrpc, /*! Find yang spec association of XML node for outgoing RPC starting with * - * Incoming RPC has an "input" structure that is not taken care of by xml_bind_yang - * @param[in] xrpc XML rpc node - * @param[in] name Name of RPC (not seen in output/reply) + * Outgoing RPC has an "output" structure that is not taken care of by xml_bind_yang + * @param[in] xrpc XML rpc node + * @param[in] name Name of RPC (not seen in output/reply) * @param[in] yspec Yang spec * @param[out] xerr Reason for failure, or NULL * @retval 1 OK yang assignment made @@ -640,10 +640,20 @@ xml_bind_yang_rpc_reply(cxobj *xrpc, yang_stmt *yo = NULL; /* output */ cxobj *x; int ret; + cxobj *xerr1 = NULL; + char *opname; + cbuf *cberr = NULL; - if (strcmp(xml_name(xrpc), "rpc-reply")){ - clicon_err(OE_UNIX, EINVAL, "rpc-reply expected"); - goto done; + opname = xml_name(xrpc); + if (strcmp(opname, "rpc-reply")){ + if ((cberr = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + cprintf(cberr, "Internal error, unrecognized netconf operation in backend reply, expected rpc-reply but received: %s", opname); + if (xerr && netconf_operation_failed_xml(xerr, "application", cbuf_get(cberr)) < 0) + goto done; + goto fail; } x = NULL; while ((x = xml_child_each(xrpc, x, CX_ELMNT)) != NULL) { @@ -663,18 +673,31 @@ xml_bind_yang_rpc_reply(cxobj *xrpc, } if (yo != NULL){ xml_spec_set(xrpc, yo); - if ((ret = xml_bind_yang(xrpc, YB_MODULE, yspec, xerr)) < 0) + /* Use a temporary xml error tree since it is stringified in the original error on error */ + if ((ret = xml_bind_yang(xrpc, YB_PARENT, NULL, &xerr1)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + if ((cberr = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + cprintf(cberr, "Internal error in backend reply: "); + if (netconf_err2cb(xerr1, cberr) < 0) + goto done; + if (xerr && netconf_operation_failed_xml(xerr, "application", cbuf_get(cberr)) < 0) + goto done; goto fail; + } } retval = 1; done: + if (cberr) + cbuf_free(cberr); + if (xerr1) + xml_free(xerr1); return retval; fail: retval = 0; goto done; } - -