diff --git a/CHANGELOG.md b/CHANGELOG.md
index d148b086..fed34fcc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -51,9 +51,11 @@ Expected: July 2020
* CLICON_SSL_CA_CERT
* Restconf FCGI (eg via nginx) have changed reply message syntax slightly as follows (due to refactoring and common code with evhtp):
- * Bodies in error reyruns including html code have been removed
+ * Bodies in error retuns including html code have been removed
* Some (extra) CRLF:s have been removed
+* Changed and enhanced several `bad-element` error replies to `unknown-element` with more detailed error-message.
+
### C/CLI-API changes on existing features (For developers)
* Changed module-specific upgrade API, not backward compatible. The API has been simplified which means more has to be done by the programmer.
diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c
index 43b7d61a..d6361492 100644
--- a/apps/backend/backend_client.c
+++ b/apps/backend/backend_client.c
@@ -624,8 +624,13 @@ from_client_edit_config(clicon_handle h,
xml_spec_set(xc, NULL);
/* Populate XML with Yang spec (why not do this in parser?)
*/
- if (xml_bind_yang(xc, YB_MODULE, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang(xc, YB_MODULE, yspec, &xret)) < 0)
goto done;
+ if (ret == 0){
+ if (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
+ goto done;
+ goto ok;
+ }
/* Maybe validate xml here as in text_modify_top? */
if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0)
goto done;
diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c
index 1e8ef39c..6879424b 100644
--- a/apps/backend/backend_commit.c
+++ b/apps/backend/backend_commit.c
@@ -217,8 +217,13 @@ startup_common(clicon_handle h,
goto done;
}
/* After upgrading, XML tree needs to be sorted and yang spec populated */
- if (xml_bind_yang(xt, YB_MODULE, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang(xt, YB_MODULE, yspec, &xret)) < 0)
goto done;
+ if (ret == 0){
+ if (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
+ goto done;
+ goto fail;
+ }
if (xml_sort_recurse(xt) < 0)
goto done;
/* Handcraft transition with with only add tree */
diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c
index 5d30ec02..e620b1ff 100644
--- a/apps/netconf/netconf_main.c
+++ b/apps/netconf/netconf_main.c
@@ -149,9 +149,10 @@ netconf_input_packet(clicon_handle h,
free(str0);
if ((xrpc=xpath_first(xreq, NULL, "//rpc")) != NULL){
isrpc++;
- if (xml_bind_yang_rpc(xrpc, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang_rpc(xrpc, yspec, &xret)) < 0)
goto done;
- if ((ret = xml_yang_validate_rpc(h, xrpc, &xret)) < 0)
+ if (ret > 0 &&
+ (ret = xml_yang_validate_rpc(h, xrpc, &xret)) < 0)
goto done;
if (ret == 0){
clicon_xml2cbuf(cbret, xret, 0, 0, -1);
diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c
index ff9ba58a..f0e29cd7 100644
--- a/apps/netconf/netconf_rpc.c
+++ b/apps/netconf/netconf_rpc.c
@@ -535,6 +535,7 @@ netconf_create_subscription(clicon_handle h,
*
* This may either be local client-side or backend. If backend send as netconf
* RPC.
+ * Assume already bound and validated.
* @param[in] h clicon handle
* @param[in] xn Sub-tree (under xorig) at child of rpc: .
* @param[out] xret Return XML, error or OK
@@ -542,6 +543,7 @@ netconf_create_subscription(clicon_handle h,
* @retval -1 Error
* @retval 0 OK, not found handler.
* @retval 1 OK, handler called
+ * @see netconf_input_packet Assume bind and validation made there
*/
static int
netconf_application_rpc(clicon_handle h,
@@ -552,7 +554,6 @@ netconf_application_rpc(clicon_handle h,
yang_stmt *yspec = NULL; /* application yspec */
yang_stmt *yrpc = NULL;
yang_stmt *ymod = NULL;
- yang_stmt *yinput;
yang_stmt *youtput;
cxobj *xoutput;
cxobj *xerr = NULL;
@@ -591,22 +592,7 @@ netconf_application_rpc(clicon_handle h,
yrpc = yang_find(ymod, Y_RPC, xml_name(xn));
/* Check if found */
if (yrpc != NULL){
- /* 1. Check xn arguments with input statement. */
- if ((yinput = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
- xml_spec_set(xn, yinput); /* needed for xml_bind_yang */
- if (xml_bind_yang(xn, YB_MODULE, yspec, NULL) < 0)
- goto done;
- if ((ret = xml_yang_validate_all_top(h, xn, &xerr)) < 0)
- goto done;
- if (ret > 0 && (ret = xml_yang_validate_add(h, xn, &xerr)) < 0)
- goto done;
- if (ret == 0){
- if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
- goto done;
- netconf_output_encap(1, cbret, "rpc-error");
- goto ok;
- }
- }
+ /* No need to check xn arguments with input statement since already bound and validated. */
/* Look for local (client-side) netconf plugins. */
if ((ret = rpc_callback_call(h, xn, cbret, NULL)) < 0)
goto done;
@@ -626,9 +612,9 @@ netconf_application_rpc(clicon_handle h,
if ((youtput = yang_find(yrpc, Y_OUTPUT, NULL)) != NULL){
xoutput=xpath_first(*xret, NULL, "/");
xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
- if (xml_bind_yang(xoutput, YB_MODULE, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang(xoutput, YB_MODULE, yspec, &xerr)) < 0)
goto done;
- if ((ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0)
+ if (ret > 0 && (ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0)
goto done;
if (ret > 0 && (ret = xml_yang_validate_add(h, xoutput, &xerr)) < 0)
goto done;
diff --git a/apps/restconf/restconf_methods_post.c b/apps/restconf/restconf_methods_post.c
index e85dad9f..2f166b3c 100644
--- a/apps/restconf/restconf_methods_post.c
+++ b/apps/restconf/restconf_methods_post.c
@@ -670,9 +670,9 @@ api_operations_post_output(clicon_handle h,
if (youtput != NULL){
xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
#ifdef notyet
- if (xml_bind_yang(xoutput, YB_MODULE, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang(xoutput, YB_MODULE, yspec, &xerr)) < 0)
goto done;
- if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0)
+ if (ret > 0 && (ret = xml_yang_validate_all(xoutput, &xerr)) < 0)
goto done;
if (ret == 1 &&
(ret = xml_yang_validate_add(h, xoutput, &xerr)) < 0)
diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c
index 67bb067b..bbef0f4b 100644
--- a/lib/src/clixon_xml_bind.c
+++ b/lib/src/clixon_xml_bind.c
@@ -184,7 +184,7 @@ populate_self_parent(cxobj *xt,
if (ns)
cprintf(cb, " in namespace: %s", ns);
if (xerr &&
- netconf_bad_element_xml(xerr, "application", name, cbuf_get(cb)) < 0)
+ netconf_unknown_element_xml(xerr, "application", name, cbuf_get(cb)) < 0)
goto done;
goto fail;
}
@@ -251,15 +251,26 @@ populate_self_top(cxobj *xt,
}
if (ys_module_by_xml(yspec, xt, &ymod) < 0)
goto done;
- /* ymod is "real" module, name may belong to included submodule */
- if (ymod == NULL){
- if (xerr &&
- netconf_bad_element_xml(xerr, "application", name, "No such yang module") < 0)
- goto done;
- goto fail;
- }
if (xml2ns(xt, xml_prefix(xt), &ns) < 0)
goto done;
+ /* ymod is "real" module, name may belong to included submodule */
+ if (ymod == NULL){
+ if (xerr){
+ if ((cb = cbuf_new()) == NULL){
+ clicon_err(OE_UNIX, errno, "cbuf_new");
+ goto done;
+ }
+ cprintf(cb, "Failed to find YANG spec of XML node: %s", name);
+ if ((xp = xml_parent(xt)) != NULL)
+ cprintf(cb, " with parent: %s", xml_name(xp));
+ if (ns)
+ cprintf(cb, " in namespace: %s", ns);
+ if (netconf_unknown_element_xml(xerr, "application", name, cbuf_get(cb)) < 0)
+ goto done;
+ }
+ goto fail;
+ }
+
if ((y = yang_find_schemanode(ymod, name)) == NULL){ /* also rpc */
if (_yang_unknown_anydata){
/* Add dummy Y_ANYDATA yang stmt, see ysp_add */
@@ -279,7 +290,7 @@ populate_self_top(cxobj *xt,
if (ns)
cprintf(cb, " in namespace: %s", ns);
if (xerr &&
- netconf_bad_element_xml(xerr, "application", name, cbuf_get(cb)) < 0)
+ netconf_unknown_element_xml(xerr, "application", name, cbuf_get(cb)) < 0)
goto done;
goto fail;
}
@@ -320,7 +331,8 @@ populate_self_top(cxobj *xt,
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
* @retval -1 Error
* @code
- * if (xml_bind_yang(x, YB_MODULE, yspec, NULL) < 0)
+ * cxobj *xerr = NULL;
+ * if (xml_bind_yang(x, YB_MODULE, yspec, &xerr) < 0)
* err;
* @endcode
* @note For subs to anyxml nodes will not have spec set
@@ -493,7 +505,7 @@ xml_bind_yang0(cxobj *xt,
/*! Find yang spec association of XML node for incoming 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] xrpc XML rpc node
* @param[in] yspec Yang spec
* @param[out] xerr Reason for failure, or NULL
* @retval 1 OK yang assignment made
diff --git a/lib/src/clixon_xpath.c b/lib/src/clixon_xpath.c
index 15bf7260..3959a446 100644
--- a/lib/src/clixon_xpath.c
+++ b/lib/src/clixon_xpath.c
@@ -514,7 +514,8 @@ xpath_parse(const char *xpath,
}
xpath_parse_exit(&xpy);
xpath_scan_exit(&xpy);
- *xptree = xpy.xpy_top;
+ if (xptree)
+ *xptree = xpy.xpy_top;
retval = 0;
done:
if (cb)
diff --git a/test/lib.sh b/test/lib.sh
index 288f1200..d74c02d5 100755
--- a/test/lib.sh
+++ b/test/lib.sh
@@ -129,6 +129,7 @@ fi
BUSER=clicon
# If set, unknown XML is treated as ANYDATA
+# This would only happen if you set option YANG_UNKNOWN_ANYDATA to something else than default
: ${YANG_UNKNOWN_ANYDATA:=false}
# Follow the binary programs that can be parametrized (eg with valgrind)
diff --git a/test/test_c++.sh b/test/test_c++.sh
index 41985e40..27ffcc52 100755
--- a/test/test_c++.sh
+++ b/test/test_c++.sh
@@ -1,5 +1,8 @@
#!/usr/bin/env bash
-# Tests cpp compatibility with clixon
+# Tests C++ compatibility with clixon
+# The test compiles a c++ backend plugin, installs it and starts the backend, and then runs
+# an RPC example.
+# The RPC example is the "example" RPC in clixon-example.yang
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
diff --git a/test/test_copy_config.sh b/test/test_copy_config.sh
index 1aad72ab..8cd20863 100755
--- a/test/test_copy_config.sh
+++ b/test/test_copy_config.sh
@@ -149,8 +149,8 @@ expecteof "$clixon_netconf -qf $cfg" 0 'candidate"
expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$"
-new "copy startup->running not allowed"
if ! $YANG_UNKNOWN_ANYDATA ; then
+new "copy startup->running not allowed"
expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationunknown-elementrunningerrorFailed to find YANG spec of XML node: running with parent: target in namespace: urn:ietf:params:xml:ns:netconf:base:1.0]]>]]>$"
fi
diff --git a/test/test_feature.sh b/test/test_feature.sh
index 60440377..de822e30 100755
--- a/test/test_feature.sh
+++ b/test/test_feature.sh
@@ -109,7 +109,7 @@ new "netconf validate enabled feature"
expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$"
new "netconf disabled feature"
-expecteof "$clixon_netconf -qf $cfg" 0 'foo]]>]]>' '^applicationunknown-elementyerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'foo]]>]]>' '^applicationunknown-elementyerrorFailed to find YANG spec of XML node: y with parent: config in namespace: urn:example:clixon]]>]]>$'
# This test has been broken up into all different modules instead of one large
# reply since the modules change so often
diff --git a/test/test_identity.sh b/test/test_identity.sh
index bf1b3bb9..918f0e5e 100755
--- a/test/test_identity.sh
+++ b/test/test_identity.sh
@@ -284,7 +284,7 @@ expectpart "$(curl $CURLOPTS -X DELETE $RCPROTO://localhost/restconf/data/exampl
# 2. set identity in other module with restconf , read it with restconf and netconf
if ! $YANG_UNKNOWN_ANYDATA ; then
new "restconf add POST instead of PUT (should fail)"
-expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example:crypto -d '{"example:crypto":"example-des:des3"}')" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"crypto"},"error-severity":"error","error-message":"Failed to find YANG spec of XML node: crypto with parent: crypto in namespace: urn:example:my-crypto"}}}'
+expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example:crypto -d '{"example:crypto":"example-des:des3"}')" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"crypto"},"error-severity":"error","error-message":"Failed to find YANG spec of XML node: crypto with parent: crypto in namespace: urn:example:my-crypto"}}}'
fi
# Alternative error:
diff --git a/test/test_netconf.sh b/test/test_netconf.sh
index 180a2b4d..94163507 100755
--- a/test/test_netconf.sh
+++ b/test/test_netconf.sh
@@ -202,7 +202,7 @@ new "netconf client-side rpc"
expecteof "$clixon_netconf -qf $cfg" 0 'val42]]>]]>' '^val42]]>]]>$'
new "netconf extra leaf in leaf should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'e0e1]]>]]>' '^applicationunknown-elementnameerrorLeaf contains sub-element]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'e0e1]]>]]>' '^applicationunknown-elementnameerrorFailed to find YANG spec of XML node: name with parent: name in namespace: urn:ietf:params:xml:ns:yang:ietf-interfaces]]>]]>$'
if [ $BE -eq 0 ]; then
exit # BE
diff --git a/test/test_restconf.sh b/test/test_restconf.sh
index 4cee162f..34c043df 100755
--- a/test/test_restconf.sh
+++ b/test/test_restconf.sh
@@ -231,7 +231,7 @@ expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+jso
if ! $YANG_UNKNOWN_ANYDATA ; then
new "restconf rpc using POST json wrong"
-expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"wrongelement":"ipv4"}}' $RCPROTO://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"wrongelement"},"error-severity":"error","error-message":"Failed to find YANG spec of XML node: wrongelement with parent: example in namespace: urn:example:clixon"}}}'
+expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"wrongelement":"ipv4"}}' $RCPROTO://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"wrongelement"},"error-severity":"error","error-message":"Failed to find YANG spec of XML node: wrongelement with parent: example in namespace: urn:example:clixon"}}}'
fi
new "restconf rpc non-existing rpc without namespace"
diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh
index 2530f6fa..270491e3 100755
--- a/test/test_restconf_err.sh
+++ b/test/test_restconf_err.sh
@@ -216,7 +216,7 @@ expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/augment:r
#----------------------------------------------
# Also generate an invalid state XML. This should generate an "Internal" error and the name of the
new "restconf GET failed state"
-expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 '412 Precondition Failed' 'applicationoperation-failedmystateerrorNo such yang module. Internal error, state callback returned invalid XML: example_backend'
+expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 '412 Precondition Failed' 'applicationoperation-failedmystateerrorFailed to find YANG spec of XML node: mystate with parent: top in namespace: urn:example:foobar. Internal error, state callback returned invalid XML: example_backend'
if [ $RC -ne 0 ]; then
new "Kill restconf daemon"
diff --git a/test/test_rpc.sh b/test/test_rpc.sh
index a9efa306..2bd881a7 100755
--- a/test/test_rpc.sh
+++ b/test/test_rpc.sh
@@ -126,7 +126,7 @@ expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+jso
new "restconf add extra w/o yang: should fail"
if ! $YANG_UNKNOWN_ANYDATA ; then
-expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"x":"0","extra":"0"}}' $RCPROTO://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"bad-element","error-info":{"bad-element":"extra"},"error-severity":"error","error-message":"Failed to find YANG spec of XML node: extra with parent: example in namespace: urn:example:clixon"}}}'
+expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"x":"0","extra":"0"}}' $RCPROTO://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 400 Bad Request' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"unknown-element","error-info":{"bad-element":"extra"},"error-severity":"error","error-message":"Failed to find YANG spec of XML node: extra with parent: example in namespace: urn:example:clixon"}}}'
fi
new "restconf wrong method"
@@ -157,7 +157,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^applicationunknown-elementgeterror]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^applicationunknown-elementgeterrorUnrecognized RPC (wrong namespace?)]]>]]>$'
new "restconf wrong rpc: should fail"
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" u $RCPROTO://localhost/restconf/operations/clixon-foo:get)" 0 'HTTP/1.1 412 Precondition Failed' '{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"operation-failed","error-severity":"error","error-message":"yang module not found"}}}'
diff --git a/test/test_yang_anydata.sh b/test/test_yang_anydata.sh
index 48cbdb26..9685a5d1 100755
--- a/test/test_yang_anydata.sh
+++ b/test/test_yang_anydata.sh
@@ -113,12 +113,12 @@ testrun()
XML="$XMLA$XMLU"
else
XML="$XMLA"
- unknownreply="applicationunknown-elementu1errorUnassigned yang spec]]>]]>"
+ unknownreply="applicationunknown-elementu1errorFailed to find YANG spec of XML node: u1 with parent: config in namespace: urn:example:unknown"
fi
else
XML="$XMLA"
- unknownreply="applicationunknown
--elementu1errorUnassigned yang spec]]>]]>"
+ unknownreply="applicationunknown
+-elementu1errorFailed to find YANG spec of XML node: u1 with parent: config in namespace: urn:example:unknown"
fi
if $startup; then # get config from startup
@@ -265,16 +265,16 @@ EOF
new "test params: -f $cfg"
-new "no startup, dont treat unknown as anydata"
+new "no startup, dont treat unknown as anydata----"
testrun false false
-new "startup, dont treat unknown as anydata"
+new "startup, dont treat unknown as anydata----"
testrun true false
-new "no startup, treat unknown as anydata"
+new "no startup, treat unknown as anydata----"
testrun false true
-new "startup, treat unknown as anydata"
+new "startup, treat unknown as anydata----"
testrun true true
rm -rf $dir
diff --git a/test/test_yang_load.sh b/test/test_yang_load.sh
index 17e25ae6..756b08e2 100755
--- a/test/test_yang_load.sh
+++ b/test/test_yang_load.sh
@@ -91,10 +91,10 @@ new "1. Set newex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set oldex should fail (since oldex is in old revision and only the new is loaded)"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementoldexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementoldexerrorFailed to find YANG spec of XML node: oldex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorFailed to find YANG spec of XML node: other with parent: config in namespace: urn:example:clixon2]]>]]>$'
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -139,10 +139,10 @@ new "Set oldex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set newex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorFailed to find YANG spec of XML node: newex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorFailed to find YANG spec of XML node: other with parent: config in namespace: urn:example:clixon2]]>]]>$'
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -183,10 +183,10 @@ new "Set newex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set oldex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementoldexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementoldexerrorFailed to find YANG spec of XML node: oldex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorFailed to find YANG spec of XML node: other with parent: config in namespace: urn:example:clixon2]]>]]>$'
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -227,10 +227,10 @@ new "Set oldex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set newex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorFailed to find YANG spec of XML node: newex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorFailed to find YANG spec of XML node: other with parent: config in namespace: urn:example:clixon2]]>]]>$'
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -271,10 +271,10 @@ new "Set newex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set oldex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementoldexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementoldexerrorFailed to find YANG spec of XML node: oldex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -316,7 +316,7 @@ new "Set oldex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set newex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorUnassigned yang spec]]>]]>'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorFailed to find YANG spec of XML node: newex with parent: config in namespace: urn:example:clixon]]>]]>'
new "Set other"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
@@ -362,7 +362,7 @@ new "Set oldex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set newex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorFailed to find YANG spec of XML node: newex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
@@ -408,10 +408,10 @@ new "Set oldex"
expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^]]>]]>$'
new "Set newex should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementnewexerrorFailed to find YANG spec of XML node: newex with parent: config in namespace: urn:example:clixon]]>]]>$'
new "Set other should fail"
-expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorUnassigned yang spec]]>]]>$'
+expecteof "$clixon_netconf -qf $cfg" 0 'str]]>]]>' '^applicationunknown-elementothererrorFailed to find YANG spec of XML node: other with parent: config in namespace: urn:example:clixon2]]>]]>$'
if [ $BE -ne 0 ]; then
new "Kill backend"
diff --git a/util/clixon_util_path.c b/util/clixon_util_path.c
index 2805b5c8..2250ab79 100644
--- a/util/clixon_util_path.c
+++ b/util/clixon_util_path.c
@@ -223,8 +223,18 @@ main(int argc,
/* Validate XML as well */
if (yang_file_dir){
/* Populate */
- if (xml_bind_yang(x, YB_MODULE, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang(x, YB_MODULE, yspec, &xerr)) < 0)
goto done;
+ if (ret == 0){
+ if ((cb = cbuf_new()) ==NULL){
+ clicon_err(OE_XML, errno, "cbuf_new");
+ goto done;
+ }
+ if (netconf_err2cb(xerr, cb) < 0)
+ goto done;
+ fprintf(stderr, "xml validation error: %s\n", cbuf_get(cb));
+ goto done;
+ }
/* sort */
if (xml_sort_recurse(x) < 0)
goto done;
diff --git a/util/clixon_util_xpath.c b/util/clixon_util_xpath.c
index 1513633d..6d104e70 100644
--- a/util/clixon_util_xpath.c
+++ b/util/clixon_util_xpath.c
@@ -291,8 +291,18 @@ main(int argc,
/* Validate XML as well */
if (yang_file_dir){
/* Populate */
- if (xml_bind_yang(x0, YB_MODULE, yspec, NULL) < 0)
+ if ((ret = xml_bind_yang(x0, YB_MODULE, yspec, &xerr)) < 0)
goto done;
+ if (ret == 0){
+ if ((cb = cbuf_new()) ==NULL){
+ clicon_err(OE_XML, errno, "cbuf_new");
+ goto done;
+ }
+ if (netconf_err2cb(xerr, cbret) < 0)
+ goto done;
+ fprintf(stderr, "xml validation error: %s\n", cbuf_get(cbret));
+ goto done;
+ }
/* Sort */
if (xml_sort_recurse(x0) < 0)
goto done;