From 57b104bc25aca8d7ce30d0e93c8aada92522c86f Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sat, 25 Jul 2020 16:09:24 +0200 Subject: [PATCH] * Checked yang binding validity which lead to: * Changed and enhanced several `bad-element` error replies to `unknown-element` with more detailed error-message. --- CHANGELOG.md | 4 +++- apps/backend/backend_client.c | 7 +++++- apps/backend/backend_commit.c | 7 +++++- apps/netconf/netconf_main.c | 5 ++-- apps/netconf/netconf_rpc.c | 24 ++++--------------- apps/restconf/restconf_methods_post.c | 4 ++-- lib/src/clixon_xml_bind.c | 34 ++++++++++++++++++--------- lib/src/clixon_xpath.c | 3 ++- test/lib.sh | 1 + test/test_c++.sh | 5 +++- test/test_copy_config.sh | 2 +- test/test_feature.sh | 2 +- test/test_identity.sh | 2 +- test/test_netconf.sh | 2 +- test/test_restconf.sh | 2 +- test/test_restconf_err.sh | 2 +- test/test_rpc.sh | 4 ++-- test/test_yang_anydata.sh | 14 +++++------ test/test_yang_load.sh | 28 +++++++++++----------- util/clixon_util_path.c | 12 +++++++++- util/clixon_util_xpath.c | 12 +++++++++- 21 files changed, 106 insertions(+), 70 deletions(-) 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;