From fc78824110b5609fc856e9084492a314953e4ce0 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Mon, 10 Jun 2019 12:49:40 +0200 Subject: [PATCH] Many validation functions have changed error parameter from cbuf to xml tree. --- CHANGELOG.md | 3 + apps/backend/backend_client.c | 20 ++- apps/backend/backend_commit.c | 55 +++++--- apps/netconf/netconf_main.c | 7 +- apps/netconf/netconf_rpc.c | 27 ++-- apps/restconf/restconf_methods.c | 21 +-- lib/clixon/clixon_netconf_lib.h | 11 +- lib/clixon/clixon_xml_map.h | 10 +- lib/src/clixon_datastore_write.c | 6 +- lib/src/clixon_netconf_lib.c | 217 +++++++++++++++++++++++-------- lib/src/clixon_options.c | 12 +- lib/src/clixon_proto_client.c | 22 ++-- lib/src/clixon_xml_changelog.c | 20 +-- lib/src/clixon_xml_map.c | 180 ++++++++++++------------- test/all.sh | 2 +- test/test_identity.sh | 53 ++++---- test/test_order.sh | 67 +++++----- test/test_stream.sh | 27 ++-- test/test_union.sh | 13 +- test/test_when_must.sh | 33 ++--- test/test_yang.sh | 85 ++++++------ util/clixon_util_xml.c | 20 +-- 22 files changed, 527 insertions(+), 384 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e4fda7e..20d401f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,9 @@ ### API changes on existing features (you may need to change your code) +* Many validation functions have changed error parameter from cbuf to xml tree. + * XML trees are more flexible for utility tools + * If you use these(mostly internal), you need to change the error function: `generic_validate, from_validate_common, xml_yang_validate_all_top, xml_yang_validate_all, xml_yang_validate_add, xml_yang_validate_rpc, xml_yang_validate_list_key_only` * Replaced `CLIXON_DATADIR` with two configurable options defining where Clixon installs Yang files. * use `--with-yang-installdir=DIR` to install Clixon yang files in DIR * use `--with-std-yang-installdir=DIR` to install standard yang files that Clixon may use in DIR diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index 6805dc70..b35975d5 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -411,6 +411,7 @@ from_client_edit_config(clicon_handle h, cbuf *cbx = NULL; /* Assist cbuf */ int ret; char *username; + cxobj *xret = NULL; username = clicon_username_get(h); if ((yspec = clicon_dbspec_yang(h)) == NULL){ @@ -470,10 +471,13 @@ from_client_edit_config(clicon_handle h, goto ok; } /* xmldb_put (difflist handling) requires list keys */ - if ((ret = xml_yang_validate_list_key_only(h, xc, cbret)) < 0) + if ((ret = xml_yang_validate_list_key_only(h, xc, &xret)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0) + goto done; goto ok; + } /* Cant do this earlier since we dont have a yang spec to * the upper part of the tree, until we get the "config" tree. */ @@ -493,6 +497,8 @@ from_client_edit_config(clicon_handle h, ok: retval = 0; done: + if (xret) + xml_free(xret); if (cbx) cbuf_free(cbx); clicon_debug(1, "%s done cbret:%s", __FUNCTION__, cbuf_get(cbret)); @@ -1121,6 +1127,7 @@ from_client_msg(clicon_handle h, yang_stmt *ye; yang_stmt *ymod; cxobj *xnacm = NULL; + cxobj *xret = NULL; clicon_debug(1, "%s", __FUNCTION__); yspec = clicon_dbspec_yang(h); @@ -1147,10 +1154,13 @@ from_client_msg(clicon_handle h, * maybe not necessary since it should be */ if (xml_spec_populate_rpc(h, x, yspec) < 0) goto done; - if ((ret = xml_yang_validate_rpc(h, x, cbret)) < 0) + if ((ret = xml_yang_validate_rpc(h, x, &xret)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0) + goto done; goto reply; + } xe = NULL; username = xml_find_value(x, "username"); /* May be used by callbacks, etc */ @@ -1222,6 +1232,8 @@ from_client_msg(clicon_handle h, retval = 0; done: clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); + if (xret) + xml_free(xret); if (xt) xml_free(xt); if (cbret) diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 07de3da7..61e7193f 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -81,7 +81,7 @@ * are if code comes via XML/NETCONF. * @param[in] yspec Yang spec * @param[in] td Transaction data - * @param[out] cbret Cligen buffer containing netconf error (if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval -1 Error * @retval 0 Validation failed (with cbret set) * @retval 1 Validation OK @@ -90,7 +90,7 @@ static int generic_validate(clicon_handle h, yang_stmt *yspec, transaction_data_t *td, - cbuf *cbret) + cxobj **xret) { int retval = -1; cxobj *x1; @@ -100,7 +100,7 @@ generic_validate(clicon_handle h, int ret; /* All entries */ - if ((ret = xml_yang_validate_all_top(h, td->td_target, cbret)) < 0) + if ((ret = xml_yang_validate_all_top(h, td->td_target, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -109,7 +109,7 @@ generic_validate(clicon_handle h, x1 = td->td_scvec[i]; /* source changed */ x2 = td->td_tcvec[i]; /* target changed */ /* Should this be recursive? */ - if ((ret = xml_yang_validate_add(h, x2, cbret)) < 0) + if ((ret = xml_yang_validate_add(h, x2, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -119,7 +119,7 @@ generic_validate(clicon_handle h, x1 = td->td_dvec[i]; ys = xml_spec(x1); if (ys && yang_mandatory(ys) && yang_config(ys)==0){ - if (netconf_missing_element(cbret, "protocol", xml_name(x1), "Missing mandatory variable") < 0) + if (netconf_missing_element_xml(xret, "protocol", xml_name(x1), "Missing mandatory variable") < 0) goto done; goto fail; } @@ -127,7 +127,7 @@ generic_validate(clicon_handle h, /* added entries */ for (i=0; itd_alen; i++){ x2 = td->td_avec[i]; - if ((ret = xml_yang_validate_add(h, x2, cbret)) < 0) + if ((ret = xml_yang_validate_add(h, x2, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -175,6 +175,7 @@ startup_common(clicon_handle h, modstate_diff_t *msd = NULL; cxobj *xt = NULL; cxobj *x; + cxobj *xret = NULL; /* If CLICON_XMLDB_MODSTATE is enabled, then get the db XML with * potentially non-matching module-state in msd @@ -225,11 +226,13 @@ startup_common(clicon_handle h, /* 5. Make generic validation on all new or changed data. Note this is only call that uses 3-values */ clicon_debug(1, "Validating startup %s", db); - if ((ret = generic_validate(h, yspec, td, cbret)) < 0) + if ((ret = generic_validate(h, yspec, td, &xret)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0) + goto done; goto fail; /* STARTUP_INVALID */ - + } /* 6. Call plugin transaction validate callbacks */ if (plugin_transaction_validate(h, td) < 0) goto done; @@ -240,6 +243,8 @@ startup_common(clicon_handle h, ok: retval = 1; done: + if (xret) + xml_free(xret); if (xt) xml_free(xt); if (msd) @@ -374,6 +379,7 @@ startup_commit(clicon_handle h, * and call application callback validations. * @param[in] h Clicon handle * @param[in] candidate The candidate database. The wanted backend state + * @param[out] xret Error XML tree. Free with xml_free after use * @retval -1 Error - or validation failed (but cbret not set) * @retval 0 Validation failed (with cbret set) * @retval 1 Validation OK @@ -385,7 +391,7 @@ static int from_validate_common(clicon_handle h, char *candidate, transaction_data_t *td, - cbuf *cbret) + cxobj **xret) { int retval = -1; yang_stmt *yspec; @@ -409,7 +415,7 @@ from_validate_common(clicon_handle h, * But xml_diff requires some basic validation, at least check that yang-specs * have been assigned */ - if ((ret = xml_yang_validate_all_top(h, td->td_target, cbret)) < 0) + if ((ret = xml_yang_validate_all_top(h, td->td_target, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -462,7 +468,7 @@ from_validate_common(clicon_handle h, /* 5. Make generic validation on all new or changed data. Note this is only call that uses 3-values */ - if ((ret = generic_validate(h, yspec, td, cbret)) < 0) + if ((ret = generic_validate(h, yspec, td, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -503,6 +509,7 @@ candidate_commit(clicon_handle h, int retval = -1; transaction_data_t *td = NULL; int ret; + cxobj *xret = NULL; /* 1. Start transaction */ if ((td = transaction_new()) == NULL) @@ -511,10 +518,13 @@ candidate_commit(clicon_handle h, /* Common steps (with validate). Load candidate and running and compute diffs * Note this is only call that uses 3-values */ - if ((ret = from_validate_common(h, candidate, td, cbret)) < 0) + if ((ret = from_validate_common(h, candidate, td, &xret)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0) + goto done; goto fail; + } /* 7. Call plugin transaction commit callbacks */ if (plugin_transaction_commit(h, td) < 0) @@ -563,7 +573,9 @@ candidate_commit(clicon_handle h, xmldb_get0_free(h, &td->td_src); transaction_free(td); } - return retval; + if (xret) + xml_free(xret); + return retval; fail: retval = 0; goto done; @@ -725,6 +737,7 @@ from_client_validate(clicon_handle h, transaction_data_t *td = NULL; int ret; char *db; + cxobj *xret = NULL; if ((db = netconf_db_find(xe, "source")) == NULL){ if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0) @@ -737,9 +750,15 @@ from_client_validate(clicon_handle h, if ((td = transaction_new()) == NULL) goto done; /* Common steps (with commit) */ - if ((ret = from_validate_common(h, db, td, cbret)) < 1){ + if ((ret = from_validate_common(h, db, td, &xret)) < 1){ + /* A little complex due to several sources of validation fails or errors. + * (1) xerr is set -> translate to cbret; (2) cbret set use that; otherwise + * use clicon_err. */ + if (xret && clicon_xml2cbuf(cbret, xret, 0, 0) < 0) + goto done; plugin_transaction_abort(h, td); - if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0) + if (!cbuf_len(cbret) && + netconf_operation_failed(cbret, "application", clicon_err_reason)< 0) goto done; goto ok; } @@ -773,6 +792,8 @@ from_client_validate(clicon_handle h, xmldb_get0_free(h, &td->td_src); transaction_free(td); } + if (xret) + xml_free(xret); return retval; } /* from_client_validate */ diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index f1432ec0..a2c90486 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -84,7 +84,7 @@ static int ignore_packet_errors = 1; */ static int netconf_input_packet(clicon_handle h, - cbuf *cb) + cbuf *cb) { int retval = -1; char *str; @@ -125,9 +125,10 @@ netconf_input_packet(clicon_handle h, isrpc++; if (xml_spec_populate_rpc(h, xrpc, yspec) < 0) goto done; - if ((ret = xml_yang_validate_rpc(h, xrpc, cbret)) < 0) + if ((ret = xml_yang_validate_rpc(h, xrpc, &xret)) < 0) goto done; if (ret == 0){ + clicon_xml2cbuf(cbret, xret, 0, 0); netconf_output_encap(1, cbret, "rpc-error"); goto ok; } @@ -155,7 +156,7 @@ netconf_input_packet(clicon_handle h, netconf_output_encap(1, cbret, "rpc-error"); goto done; } - if ((xc = xml_child_i(xret,0))!=NULL){ + if ((xc = xml_child_i(xret, 0))!=NULL){ xa=NULL; /* Copy message-id attribute from incoming to reply. * RFC 6241: diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c index 3204de9a..6668c018 100644 --- a/apps/netconf/netconf_rpc.c +++ b/apps/netconf/netconf_rpc.c @@ -547,6 +547,7 @@ netconf_application_rpc(clicon_handle h, yang_stmt *yinput; yang_stmt *youtput; cxobj *xoutput; + cxobj *xerr = NULL; cbuf *cb = NULL; cbuf *cbret = NULL; int ret; @@ -587,15 +588,13 @@ netconf_application_rpc(clicon_handle h, xml_spec_set(xn, yinput); /* needed for xml_spec_populate */ if (xml_apply(xn, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; - if ((ret = xml_yang_validate_all_top(h, xn, cbret)) < 0) - goto done; - if (ret == 0){ - netconf_output_encap(1, cbret, "rpc-error"); - goto ok; - } - if ((ret = xml_yang_validate_add(h, xn, cbret)) < 0) + 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) < 0) + goto done; netconf_output_encap(1, cbret, "rpc-error"); goto ok; } @@ -622,15 +621,13 @@ netconf_application_rpc(clicon_handle h, if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; - if ((ret = xml_yang_validate_all_top(h, xoutput, cbret)) < 0) - goto done; - if (ret == 0){ - clicon_log(LOG_WARNING, "Errors in output netconf %s", cbuf_get(cbret)); - goto ok; - } - if ((ret = xml_yang_validate_add(h, xoutput, cbret)) < 0) + if ((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; if (ret == 0){ + if (clicon_xml2cbuf(cbret, xerr, 0, 0) < 0) + goto done; clicon_log(LOG_WARNING, "Errors in output netconf %s", cbuf_get(cbret)); goto ok; } @@ -641,6 +638,8 @@ netconf_application_rpc(clicon_handle h, ok: retval = 0; done: + if (xerr) + xml_free(xerr); if (cb) cbuf_free(cb); if (cbret) diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index a62a33ce..b09da045 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -1476,14 +1476,9 @@ api_operations_post_output(clicon_handle h, cxobj *xa; /* xml attribute (xmlns) */ cxobj *x; cxobj *xok; - cbuf *cbret = NULL; int isempty; // clicon_debug(1, "%s", __FUNCTION__); - if ((cbret = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, 0, "cbuf_new"); - goto done; - } /* Validate that exactly only tag */ if ((xoutput = xml_child_i_type(xret, 0, CX_ELMNT)) == NULL || strcmp(xml_name(xoutput),"rpc-reply") != 0 || @@ -1521,14 +1516,12 @@ api_operations_post_output(clicon_handle h, #if 0 if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; - if ((ret = xml_yang_validate_all(xoutput, cbret)) < 0) + if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0) goto done; if (ret == 1 && - (ret = xml_yang_validate_add(h, xoutput, cbret)) < 0) + (ret = xml_yang_validate_add(h, xoutput, &xerr)) < 0) goto done; if (ret == 0){ /* validation failed */ - if (xml_parse_string(cbuf_get(cbret), yspec, &xerr) < 0) - goto done; if ((xe = xpath_first(xerr, "rpc-reply/rpc-error")) == NULL){ clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); goto done; @@ -1573,8 +1566,6 @@ api_operations_post_output(clicon_handle h, retval = 1; done: clicon_debug(1, "%s retval: %d", __FUNCTION__, retval); - if (cbret) - cbuf_free(cbret); if (xerr) xml_free(xerr); return retval; @@ -1760,14 +1751,12 @@ api_operations_post(clicon_handle h, /* 6. Validate incoming RPC and fill in defaults */ if (xml_spec_populate_rpc(h, xtop, yspec) < 0) /* */ goto done; - if ((ret = xml_yang_validate_rpc(h, xtop, cbret)) < 0) + if ((ret = xml_yang_validate_rpc(h, xtop, &xret)) < 0) goto done; if (ret == 0){ - if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0) - goto done; - if ((xe = xpath_first(xret, "rpc-reply/rpc-error")) == NULL){ + if ((xe = xpath_first(xret, "rpc-error")) == NULL){ clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); - goto done; + goto ok; } if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; diff --git a/lib/clixon/clixon_netconf_lib.h b/lib/clixon/clixon_netconf_lib.h index 2953ab5f..f3651da5 100644 --- a/lib/clixon/clixon_netconf_lib.h +++ b/lib/clixon/clixon_netconf_lib.h @@ -32,7 +32,8 @@ ***** END LICENSE BLOCK ***** * Netconf library functions. See RFC6241 - * + * Functions to generate a netconf error message come in two forms: xml-tree and + * cbuf. XML tree is preferred. */ #ifndef _CLIXON_NETCONF_LIB_H #define _CLIXON_NETCONF_LIB_H @@ -60,16 +61,18 @@ int netconf_lock_denied(cbuf *cb, char *info, char *message); int netconf_resource_denied(cbuf *cb, char *type, char *message); int netconf_rollback_failed(cbuf *cb, char *type, char *message); int netconf_data_exists(cbuf *cb, char *message); -int netconf_data_missing(cbuf *cb, char *message); +int netconf_data_missing(cbuf *cb, char *missing_choice, char *message); +int netconf_data_missing_xml(cxobj **xret, char *missing_choice, char *message); int netconf_operation_not_supported(cbuf *cb, char *type, char *message); int netconf_operation_failed(cbuf *cb, char *type, char *message); int netconf_operation_failed_xml(cxobj **xret, char *type, char *message); int netconf_malformed_message(cbuf *cb, char *message); int netconf_malformed_message_xml(cxobj **xret, char *message); -int netconf_data_not_unique(cbuf *cb, cxobj *x, cvec *cvk); -int netconf_minmax_elements(cbuf *cb, cxobj *x, int max); +int netconf_data_not_unique_xml(cxobj **xret, cxobj *x, cvec *cvk); +int netconf_minmax_elements_xml(cxobj **xret, cxobj *x, int max); int netconf_trymerge(cxobj *x, yang_stmt *yspec, cxobj **xret); int netconf_module_load(clicon_handle h); char *netconf_db_find(cxobj *xn, char *name); +int netconf_err2cb(cxobj *xerr, cbuf **cberr); #endif /* _CLIXON_NETCONF_LIB_H */ diff --git a/lib/clixon/clixon_xml_map.h b/lib/clixon/clixon_xml_map.h index a15e68b8..b6a09ccc 100644 --- a/lib/clixon/clixon_xml_map.h +++ b/lib/clixon/clixon_xml_map.h @@ -48,11 +48,11 @@ int xml2txt(FILE *f, cxobj *x, int level); int xml2cli(FILE *f, cxobj *x, char *prepend, enum genmodel_type gt); int xml_yang_root(cxobj *x, cxobj **xr); int xmlns_assign(cxobj *x); -int xml_yang_validate_rpc(clicon_handle h, cxobj *xrpc, cbuf *cbret); -int xml_yang_validate_list_key_only(clicon_handle h, cxobj *xt, cbuf *cbret); -int xml_yang_validate_add(clicon_handle h, cxobj *xt, cbuf *cbret); -int xml_yang_validate_all(clicon_handle h, cxobj *xt, cbuf *cbret); -int xml_yang_validate_all_top(clicon_handle h, cxobj *xt, cbuf *cbret); +int xml_yang_validate_rpc(clicon_handle h, cxobj *xrpc, cxobj **xret); +int xml_yang_validate_list_key_only(clicon_handle h, cxobj *xt, cxobj **xret); +int xml_yang_validate_add(clicon_handle h, cxobj *xt, cxobj **xret); +int xml_yang_validate_all(clicon_handle h, cxobj *xt, cxobj **xret); +int xml_yang_validate_all_top(clicon_handle h, cxobj *xt, cxobj **xret); int xml2cvec(cxobj *xt, yang_stmt *ys, cvec **cvv0); int cvec2xml_1(cvec *cvv, char *toptag, cxobj *xp, cxobj **xt0); diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 3989e816..d36a1239 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -219,7 +219,7 @@ text_modify(clicon_handle h, break; case OP_DELETE: if (x0==NULL){ - if (netconf_data_missing(cbret, "Data does not exist; cannot delete resource") < 0) + if (netconf_data_missing(cbret, NULL, "Data does not exist; cannot delete resource") < 0) goto done; goto fail; } @@ -376,7 +376,7 @@ text_modify(clicon_handle h, break; case OP_DELETE: if (x0==NULL){ - if (netconf_data_missing(cbret, "Data does not exist; cannot delete resource") < 0) + if (netconf_data_missing(cbret, NULL, "Data does not exist; cannot delete resource") < 0) goto done; goto fail; } @@ -488,7 +488,7 @@ text_modify_top(clicon_handle h, I.e., curl -u andy:bar -sS -X DELETE http://localhost/restconf/data */ case OP_DELETE: - if (netconf_data_missing(cbret, "Data does not exist; cannot delete resource") < 0) + if (netconf_data_missing(cbret, NULL, "Data does not exist; cannot delete resource") < 0) goto done; goto fail; break; diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index b02fa04d..6667b436 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -32,6 +32,8 @@ ***** END LICENSE BLOCK ***** * Netconf library functions. See RFC6241 + * Functions to generate a netconf error message come in two forms: xml-tree and + * cbuf. XML tree is preferred. */ #ifdef HAVE_CONFIG_H @@ -63,6 +65,8 @@ #include "clixon_options.h" #include "clixon_data.h" #include "clixon_xml_map.h" +#include "clixon_xpath_ctx.h" +#include "clixon_xpath.h" #include "clixon_netconf_lib.h" /*! Create Netconf in-use error XML tree according to RFC 6241 Appendix A @@ -752,38 +756,81 @@ netconf_data_exists(cbuf *cb, * does not exist. For example, a "delete" operation was attempted on * data that does not exist. * @param[out] cb CLIgen buf. Error XML is written in this buffer + * @param[in] missing_choice If set, see RFC7950: 15.6 violates mandatiry choice * @param[in] message Error message */ int netconf_data_missing(cbuf *cb, + char *missing_choice, char *message) { int retval = -1; - char *encstr = NULL; + cxobj *xret = NULL; - if (cprintf(cb, "" - "application" - "data-missing" - "error") <0) - goto err; + if (netconf_data_missing_xml(&xret, missing_choice, message) < 0) + goto done; + if (clicon_xml2cbuf(cb, xret, 0, 0) < 0) + goto done; + retval = 0; + done: + if (xret) + xml_free(xret); + return retval; +} + +/*! Create Netconf data-missing error XML tree according to RFC 6241 App A + * + * Request could not be completed because the relevant data model content + * does not exist. For example, a "delete" operation was attempted on + * data that does not exist. + * @param[out] xret Error XML tree. Free with xml_free after use + * @param[in] missing_choice If set, see RFC7950: 15.6 violates mandatiry choice + * @param[in] message Error message + */ +int +netconf_data_missing_xml(cxobj **xret, + char *missing_choice, + char *message) +{ + int retval = -1; + char *encstr = NULL; + cxobj *xerr; + + if (*xret == NULL){ + if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) + goto done; + } + else if (xml_name_set(*xret, "rpc-reply") < 0) + goto done; + if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL) + goto done; + if (xml_parse_va(&xerr, NULL, + "application" + "data-missing") < 0) + goto done; + if (missing_choice) /* NYI: RFC7950: 15.6 */ + if (xml_parse_va(&xerr, NULL, + "missing-choice" + "%s", + missing_choice) < 0) + goto done; + if (xml_parse_va(&xerr, NULL, + "error") < 0) + goto done; if (message){ if (xml_chardata_encode(&encstr, "%s", message) < 0) goto done; - if (cprintf(cb, "%s", encstr) < 0) - goto err; + if (xml_parse_va(&xerr, NULL, + "%s", encstr) < 0) + goto done; } - if (cprintf(cb, "") <0) - goto err; retval = 0; done: if (encstr) free(encstr); return retval; - err: - clicon_err(OE_XML, errno, "cprintf"); - goto done; } - + /*! Create Netconf operation-not-supported error XML according to RFC 6241 App A * * Request could not be completed because the requested operation is not @@ -970,79 +1017,97 @@ netconf_malformed_message_xml(cxobj **xret, * * A NETCONF operation would result in configuration data where a * "unique" constraint is invalidated. - * @param[out] cb CLIgen buf. Error XML is written in this buffer - * @param[in] x List element containing duplicate - * @param[in] cvk List of comonents in x that are non-unique + * @param[out] xret Error XML tree. Free with xml_free after use + * @param[in] x List element containing duplicate + * @param[in] cvk List of comonents in x that are non-unique * @see RFC7950 Sec 15.1 */ int -netconf_data_not_unique(cbuf *cb, - cxobj *x, - cvec *cvk) +netconf_data_not_unique_xml(cxobj **xret, + cxobj *x, + cvec *cvk) { int retval = -1; cg_var *cvi = NULL; cxobj *xi; + cxobj *xerr; + cxobj *xinfo; + cbuf *cb = NULL; - if (cprintf(cb, "" - "protocol" - "operation-failed" - "data-not-unique" - "error" - "") < 0) - goto err; - while ((cvi = cvec_each(cvk, cvi)) != NULL){ - if ((xi = xml_find(x, cv_string_get(cvi))) == NULL) - continue; /* ignore, shouldnt happen */ - cprintf(cb, ""); - clicon_xml2cbuf(cb, xi, 0, 0); - cprintf(cb, ""); + if (*xret == NULL){ + if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) + goto done; + } + else if (xml_name_set(*xret, "rpc-reply") < 0) + goto done; + if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL) + goto done; + if (xml_parse_va(&xerr, NULL, "protocol" + "operation-failed" + "data-not-unique" + "error") < 0) + goto done; + if (cvec_len(cvk)){ + if ((xinfo = xml_new("error-info", xerr, NULL)) == NULL) + goto done; + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + while ((cvi = cvec_each(cvk, cvi)) != NULL){ + if ((xi = xml_find(x, cv_string_get(cvi))) == NULL) + continue; /* ignore, shouldnt happen */ + clicon_xml2cbuf(cb, xi, 0, 0); + if (xml_parse_va(&xinfo, NULL, "%s", cbuf_get(cb)) < 0) + goto done; + cbuf_reset(cb); + } } - if (cprintf(cb, "") <0) - goto err; retval = 0; done: + if (cb) + cbuf_free(cb); return retval; - err: - clicon_err(OE_XML, errno, "cprintf"); - goto done; } /*! Create Netconf too-many/few-elements err msg according to RFC 7950 15.2/15.3 * * A NETCONF operation would result in configuration data where a list or a leaf-list would have too many entries, the following error - * @param[out] cb CLIgen buf. Error XML is written in this buffer + * @param[out] xret Error XML tree. Free with xml_free after use * @param[in] x List element containing duplicate * @param[in] max If set, return too-many, otherwise too-few * @see RFC7950 Sec 15.1 */ int -netconf_minmax_elements(cbuf *cb, - cxobj *x, - int max) +netconf_minmax_elements_xml(cxobj **xret, + cxobj *x, + int max) { - int retval = -1; + int retval = -1; + cxobj *xerr; - if (cprintf(cb, "" - "protocol" - "operation-failed" - "too-%s-elements" - "error" - "%s" - "", - max?"many":"few", - xml_name(x)) < 0) /* XXX should be xml2xpath */ - goto err; + if (*xret == NULL){ + if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) + goto done; + } + else if (xml_name_set(*xret, "rpc-reply") < 0) + goto done; + if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL) + goto done; + if (xml_parse_va(&xerr, NULL, "protocol" + "operation-failed" + "too-%s-elements" + "error" + "%s", + max?"many":"few", + xml_name(x)) < 0) /* XXX should be xml2xpath */ + goto done; retval = 0; done: return retval; - err: - clicon_err(OE_XML, errno, "cprintf"); - goto done; } - /*! Help function: merge - check yang - if error make netconf errmsg * @param[in] x XML tree * @param[in] yspec Yang spec @@ -1156,3 +1221,41 @@ netconf_db_find(cxobj *xn, return db; } +/*! Generate netconf error msg to cbuf to use in string printout or logs + * @param[in] xerr Netconf error message on the level: + * @param[out] cberr Translation from netconf err to cbuf. Free with cbuf_free. + * @retval 0 OK, with cberr set + * @retval -1 Error + * @code + * cbuf *cb = NULL; + * if (netconf_err2cb(xerr, &cb) < 0) + * err; + * printf("%s", cbuf_get(cb)); + * @endcode + * @see clicon_rpc_generate_error + */ +int +netconf_err2cb(cxobj *xerr, + cbuf **cberr) +{ + int retval = -1; + cbuf *cb = NULL; + cxobj *x; + + if ((cb = cbuf_new()) ==NULL){ + clicon_err(OE_XML, errno, "cbuf_new"); + goto done; + } + if ((x=xpath_first(xerr, "error-type"))!=NULL) + cprintf(cb, "%s ", xml_body(x)); + if ((x=xpath_first(xerr, "error-tag"))!=NULL) + cprintf(cb, "%s ", xml_body(x)); + if ((x=xpath_first(xerr, "error-message"))!=NULL) + cprintf(cb, "%s ", xml_body(x)); + if ((x=xpath_first(xerr, "error-info"))!=NULL) + clicon_xml2cbuf(cb, xml_child_i(x,0), 0, 0); + *cberr = cb; + retval = 0; + done: + return retval; +} diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index c37416cc..ac04ffb3 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -72,6 +72,7 @@ #include "clixon_data.h" #include "clixon_xpath_ctx.h" #include "clixon_xpath.h" +#include "clixon_netconf_lib.h" #include "clixon_xml_map.h" /* Mapping between Clicon startup modes string <--> constants, @@ -145,6 +146,7 @@ parse_configfile(clicon_handle h, char *body; clicon_hash_t *copt = clicon_options(h); cbuf *cbret = NULL; + cxobj *xret = NULL; int ret; if (filename == NULL || !strlen(filename)){ @@ -194,13 +196,11 @@ parse_configfile(clicon_handle h, } if (xml_apply0(xc, CX_ELMNT, xml_default, h) < 0) goto done; - if ((cbret = cbuf_new()) == NULL){ - clicon_err(OE_XML, errno, "cbuf_new"); - goto done; - } - if ((ret = xml_yang_validate_add(h, xc, cbret)) < 0) + if ((ret = xml_yang_validate_add(h, xc, &xret)) < 0) goto done; if (ret == 0){ + if (netconf_err2cb(xret, &cbret) < 0) + goto done; clicon_err(OE_CFG, 0, "Config file validation: %s", cbuf_get(cbret)); goto done; } @@ -234,6 +234,8 @@ parse_configfile(clicon_handle h, done: if (cbret) cbuf_free(cbret); + if (xret) + xml_free(xret); if (xt) xml_free(xt); if (f) diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index 9502dd64..03a1bf7d 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -71,6 +71,7 @@ #include "clixon_proto.h" #include "clixon_err.h" #include "clixon_err_string.h" +#include "clixon_netconf_lib.h" #include "clixon_proto_client.h" /*! Send internal netconf rpc from client to backend @@ -224,29 +225,22 @@ clicon_rpc_netconf_xml(clicon_handle h, } /*! Generate and log clicon error function call from Netconf error message + * @param[in] prefix Print this string (if given) before: ": " * @param[in] xerr Netconf error message on the level: */ int -clicon_rpc_generate_error(char *format, +clicon_rpc_generate_error(char *prefix, cxobj *xerr) { int retval = -1; cbuf *cb = NULL; - cxobj *x; - if ((cb = cbuf_new()) ==NULL){ - clicon_err(OE_XML, errno, "cbuf_new"); + if (netconf_err2cb(xerr, &cb) < 0) goto done; - } - if ((x=xpath_first(xerr, "error-type"))!=NULL) - cprintf(cb, "%s ", xml_body(x)); - if ((x=xpath_first(xerr, "error-tag"))!=NULL) - cprintf(cb, "%s ", xml_body(x)); - if ((x=xpath_first(xerr, "error-message"))!=NULL) - cprintf(cb, "%s ", xml_body(x)); - if ((x=xpath_first(xerr, "error-info"))!=NULL) - clicon_xml2cbuf(cb, xml_child_i(x,0), 0, 0); - clicon_log(LOG_ERR, "%s: %s", format, cbuf_get(cb)); + if (prefix) + clicon_log(LOG_ERR, "%s: %s", prefix, cbuf_get(cb)); + else + clicon_log(LOG_ERR, "%s", cbuf_get(cb)); retval = 0; done: if (cb) diff --git a/lib/src/clixon_xml_changelog.c b/lib/src/clixon_xml_changelog.c index 024c02c6..850a383c 100644 --- a/lib/src/clixon_xml_changelog.c +++ b/lib/src/clixon_xml_changelog.c @@ -67,6 +67,7 @@ #include "clixon_options.h" #include "clixon_data.h" #include "clixon_yang_module.h" +#include "clixon_netconf_lib.h" #include "clixon_xml_map.h" #include "clixon_xml_changelog.h" #include "clixon_xpath_ctx.h" @@ -424,8 +425,9 @@ clixon_xml_changelog_init(clicon_handle h) int fd = -1; cxobj *xt = NULL; yang_stmt *yspec; - cbuf *cbret = NULL; int ret; + cxobj *xret = NULL; + cbuf *cbret = NULL; yspec = clicon_dbspec_yang(h); if ((filename = clicon_option_str(h, "CLICON_XML_CHANGELOG_FILE")) != NULL){ @@ -437,15 +439,13 @@ clixon_xml_changelog_init(clicon_handle h) goto done; if (xml_rootchild(xt, 0, &xt) < 0) goto done; - if ((cbret = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, errno, "cbuf_new"); + if ((ret = xml_yang_validate_all(h, xt, &xret)) < 0) goto done; - } - if ((ret = xml_yang_validate_all(h, xt, cbret)) < 0) - goto done; - if (ret==1 && (ret = xml_yang_validate_add(h, xt, cbret)) < 0) + if (ret==1 && (ret = xml_yang_validate_add(h, xt, &xret)) < 0) goto done; if (ret == 0){ /* validation failed */ + if (netconf_err2cb(xret, &cbret) < 0) + goto done; clicon_err(OE_YANG, 0, "validation failed: %s", cbuf_get(cbret)); goto done; } @@ -455,12 +455,14 @@ clixon_xml_changelog_init(clicon_handle h) } retval = 0; done: + if (cbret) + cbuf_free(cbret); + if (xret) + xml_free(xret); if (fd != -1) close(fd); if (xt) xml_free(xt); - if (cbret) - cbuf_free(cbret); return retval; } diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 27d099ad..72cceb71 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -248,7 +248,7 @@ xml2cli(FILE *f, /*! Validate xml node of type leafref, ensure the value is one of that path's reference * @param[in] xt XML leaf node of type leafref * @param[in] ytype Yang type statement belonging to the XML node - * @param[out] cbret Error buffer + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed * @retval -1 Error @@ -256,7 +256,7 @@ xml2cli(FILE *f, static int validate_leafref(cxobj *xt, yang_stmt *ytype, - cbuf *cbret) + cxobj **xret) { int retval = -1; yang_stmt *ypath; @@ -270,7 +270,7 @@ validate_leafref(cxobj *xt, if ((leafrefbody = xml_body(xt)) == NULL) goto ok; if ((ypath = yang_find(ytype, Y_PATH, NULL)) == NULL){ - if (netconf_missing_element(cbret, "application", yang_argument_get(ytype), "Leafref requires path statement") < 0) + if (netconf_missing_element_xml(xret, "application", yang_argument_get(ytype), "Leafref requires path statement") < 0) goto done; goto fail; } @@ -284,12 +284,12 @@ validate_leafref(cxobj *xt, break; } if (i==xlen){ - if (netconf_bad_element(cbret, "application", leafrefbody, "Leafref validation failed: No such leaf") < 0) + if (netconf_bad_element_xml(xret, "application", leafrefbody, "Leafref validation failed: No such leaf") < 0) goto done; goto fail; } ok: - retval = 0; + retval = 1; done: if (xvec) free(xvec); @@ -312,7 +312,7 @@ validate_leafref(cxobj *xt, * @param[in] xt XML leaf node of type identityref * @param[in] ys Yang spec of leaf * @param[in] ytype Yang type field of type identityref - * @param[out] cbret Error buffer + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed * @retval -1 Error @@ -324,7 +324,8 @@ static int validate_identityref(cxobj *xt, yang_stmt *ys, yang_stmt *ytype, - cbuf *cbret) + cxobj **xret) + { int retval = -1; char *node; @@ -350,13 +351,13 @@ validate_identityref(cxobj *xt, } /* This is the type's base reference */ if ((ybaseref = yang_find(ytype, Y_BASE, NULL)) == NULL){ - if (netconf_missing_element(cbret, "application", yang_argument_get(ytype), "Identityref validation failed, no base") < 0) + if (netconf_missing_element_xml(xret, "application", yang_argument_get(ytype), "Identityref validation failed, no base") < 0) goto done; goto fail; } /* This is the actual base identity */ if ((ybaseid = yang_find_identity(ybaseref, yang_argument_get(ybaseref))) == NULL){ - if (netconf_missing_element(cbret, "application", yang_argument_get(ybaseref), "Identityref validation failed, no base identity") < 0) + if (netconf_missing_element_xml(xret, "application", yang_argument_get(ybaseref), "Identityref validation failed, no base identity") < 0) goto done; goto fail; } @@ -367,7 +368,7 @@ validate_identityref(cxobj *xt, cbuf_reset(cb); cprintf(cb, "Identityref validation failed, %s not derived from %s", node, yang_argument_get(ybaseid)); - if (netconf_operation_failed(cbret, "application", cbuf_get(cb)) < 0) + if (netconf_operation_failed_xml(xret, "application", cbuf_get(cb)) < 0) goto done; goto fail; } @@ -413,10 +414,12 @@ xml_yang_root(cxobj *x, } /*! Validate an RPC node - * @param[in] xt XML node to be validated - * @retval 1 Validation OK - * @retval 0 Validation failed - * @retval -1 Error + * @param[in] h Clicon handle + * @param[in] xrpc XML node to be validated + * @param[out] xret Error XML tree. Free with xml_free after use + * @retval 1 Validation OK + * @retval 0 Validation failed + * @retval -1 Error * rfc7950 * 7.14.2 * If a leaf in the input tree has a "mandatory" statement with the @@ -454,8 +457,8 @@ xml_yang_root(cxobj *x, */ int xml_yang_validate_rpc(clicon_handle h, - cxobj *xrpc, - cbuf *cbret) + cxobj *xrpc, + cxobj **xret) { int retval = -1; yang_stmt *yn=NULL; /* rpc name */ @@ -469,15 +472,15 @@ xml_yang_validate_rpc(clicon_handle h, /* xn is name of rpc, ie */ while ((xn = xml_child_each(xrpc, xn, CX_ELMNT)) != NULL) { if ((yn = xml_spec(xn)) == NULL){ - if (netconf_unknown_element(cbret, "application", xml_name(xn), NULL) < 0) + if (netconf_unknown_element_xml(xret, "application", xml_name(xn), NULL) < 0) goto done; goto fail; } - if ((retval = xml_yang_validate_all(h, xn, cbret)) < 1) + if ((retval = xml_yang_validate_all(h, xn, xret)) < 1) goto done; /* error or validation fail */ - if ((retval = xml_yang_validate_add(h, xn, cbret)) < 1) + if ((retval = xml_yang_validate_add(h, xn, xret)) < 1) goto done; /* error or validation fail */ - if (xml_apply0(xn, CX_ELMNT, xml_default, NULL) < 0) + if (xml_apply0(xn, CX_ELMNT, xml_default, h) < 0) goto done; } // ok: /* pass validation */ @@ -492,7 +495,7 @@ xml_yang_validate_rpc(clicon_handle h, /*! Check if an xml node is a part of a choice and have >1 siblings * @param[in] xt XML node to be validated * @param[in] yt xt:s yang statement - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed (cbret set) * @retval -1 Error @@ -501,7 +504,7 @@ xml_yang_validate_rpc(clicon_handle h, static int check_choice(cxobj *xt, yang_stmt *yt, - cbuf *cbret) + cxobj **xret) { int retval = -1; yang_stmt *y; @@ -552,7 +555,7 @@ check_choice(cxobj *xt, continue; /* not choice */ break; } - if (netconf_bad_element(cbret, "application", xml_name(x), "Element in choice statement already exists") < 0) + if (netconf_bad_element_xml(xret, "application", xml_name(x), "Element in choice statement already exists") < 0) goto done; goto fail; } /* while */ @@ -569,7 +572,7 @@ check_choice(cxobj *xt, /*! Check if an xml node lacks mandatory children * @param[in] xt XML node to be validated * @param[in] yt xt:s yang statement - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed (cbret set) * @retval -1 Error @@ -577,7 +580,8 @@ check_choice(cxobj *xt, static int check_mandatory(cxobj *xt, yang_stmt *yt, - cbuf *cbret) + cxobj **xret) + { int retval = -1; int i; @@ -600,7 +604,7 @@ check_mandatory(cxobj *xt, while ((cvi = cvec_each(cvk, cvi)) != NULL) { keyname = cv_string_get(cvi); if (xml_find_type(xt, NULL, keyname, CX_ELMNT) == NULL){ - if (netconf_missing_element(cbret, "application", keyname, "Mandatory key") < 0) + if (netconf_missing_element_xml(xret, "application", keyname, "Mandatory key") < 0) goto done; goto fail; } @@ -623,7 +627,7 @@ check_mandatory(cxobj *xt, break; /* got it */ } if (x == NULL){ - if (netconf_missing_element(cbret, "application", yc->ys_argument, "Mandatory variable") < 0) + if (netconf_missing_element_xml(xret, "application", yc->ys_argument, "Mandatory variable") < 0) goto done; goto fail; } @@ -640,17 +644,7 @@ check_mandatory(cxobj *xt, if (x == NULL){ /* @see RFC7950: 15.6 Error Message for Data That Violates * a Mandatory "choice" Statement */ - if (cprintf(cbret, "" - "application" - "data-missing" - "missing-choice" -#ifdef NYI - // "" -#endif - "%s" - "error" - "", - yc->ys_argument) <0) + if (netconf_data_missing_xml(xret, yc->ys_argument, NULL) < 0) goto done; goto fail; } @@ -667,10 +661,14 @@ check_mandatory(cxobj *xt, goto done; } +/*! + * @param[out] xret Error XML tree. Free with xml_free after use + */ static int check_list_key(cxobj *xt, yang_stmt *yt, - cbuf *cbret) + cxobj **xret) + { int retval = -1; int i; @@ -690,7 +688,7 @@ check_list_key(cxobj *xt, while ((cvi = cvec_each(cvk, cvi)) != NULL) { keyname = cv_string_get(cvi); if (xml_find_type(xt, NULL, keyname, CX_ELMNT) == NULL){ - if (netconf_missing_element(cbret, "application", keyname, "Mandatory key") < 0) + if (netconf_missing_element_xml(xret, "application", keyname, "Mandatory key") < 0) goto done; goto fail; } @@ -739,7 +737,7 @@ check_insert_duplicate(char **vec, * @param[in] xt The parent of x * @param[in] y Its yang spec (Y_LIST) * @param[in] yu A yang unique spec (Y_UNIQUE) - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed (cbret set) * @retval -1 Error @@ -750,7 +748,8 @@ check_unique_list(cxobj *x, cxobj *xt, yang_stmt *y, yang_stmt *yu, - cbuf *cbret) + cxobj **xret) + { int retval = -1; cvec *cvk; /* unique vector */ @@ -784,7 +783,7 @@ check_unique_list(cxobj *x, if (cvi==NULL){ /* Last element (i) is newly inserted, see if it is already there */ if (check_insert_duplicate(vec, i, vlen) < 0){ - if (netconf_data_not_unique(cbret, x, cvk) < 0) + if (netconf_data_not_unique_xml(xret, x, cvk) < 0) goto done; goto fail; } @@ -807,7 +806,7 @@ check_unique_list(cxobj *x, * @param[in] x One x (the last) of a specific lis * @param[in] y Yang spec of x * @param[in] nr Number of elements (like x) in thlist - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed (cbret set) * @retval -1 Error @@ -817,7 +816,7 @@ static int check_min_max(cxobj *x, yang_stmt *y, int nr, - cbuf *cbret) + cxobj **xret) { int retval = -1; yang_stmt *ymin; /* yang min */ @@ -827,7 +826,7 @@ check_min_max(cxobj *x, if ((ymin = yang_find(y, Y_MIN_ELEMENTS, NULL)) != NULL){ cv = yang_cv_get(ymin); if (nr < cv_uint32_get(cv)){ - if (netconf_minmax_elements(cbret, x, 0) < 0) + if (netconf_minmax_elements_xml(xret, x, 0) < 0) goto done; goto fail; } @@ -836,7 +835,7 @@ check_min_max(cxobj *x, cv = yang_cv_get(ymax); if (cv_uint32_get(cv) > 0 && /* 0 means unbounded */ nr > cv_uint32_get(cv)){ - if (netconf_minmax_elements(cbret, x, 1) < 0) + if (netconf_minmax_elements_xml(xret, x, 1) < 0) goto done; goto fail; } @@ -851,9 +850,9 @@ check_min_max(cxobj *x, /*! Detect unique constraint for duplicates from parent node and minmax * @param[in] xt XML parent (may have lists w unique constraints as child) - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK - * @retval 0 Validation failed (cbret set) + * @retval 0 Validation failed (xret set) * @retval -1 Error * Assume xt:s children are sorted and yang populated. * The function does two different things of the children of an XML node: @@ -889,8 +888,8 @@ check_min_max(cxobj *x, * are not allowed. */ static int -check_list_unique_minmax(cxobj *xt, - cbuf *cbret) +check_list_unique_minmax(cxobj *xt, + cxobj **xret) { int retval = -1; cxobj *x = NULL; @@ -932,7 +931,7 @@ check_list_unique_minmax(cxobj *xt, } else { /* Check if the list length violates min/max */ - if ((ret = check_min_max(xp, yp, nr, cbret)) < 0) + if ((ret = check_min_max(xp, yp, nr, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -953,7 +952,7 @@ check_list_unique_minmax(cxobj *xt, do { if (yang_keyword_get(ye) == Y_LIST || yang_keyword_get(ye) == Y_LEAF_LIST){ /* Check if the list length violates min/max */ - if ((ret = check_min_max(xt, ye, 0, cbret)) < 0) + if ((ret = check_min_max(xt, ye, 0, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -973,7 +972,7 @@ check_list_unique_minmax(cxobj *xt, * its first element x, its yang spec y, its parent xt, and * a unique yang spec yu, */ - if ((ret = check_unique_list(x, xt, y, yu, cbret)) < 0) + if ((ret = check_unique_list(x, xt, y, yu, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -984,7 +983,7 @@ check_list_unique_minmax(cxobj *xt, */ if (yp){ /* Check if the list length violates min/max */ - if ((ret = check_min_max(xp, yp, nr, cbret)) < 0) + if ((ret = check_min_max(xp, yp, nr, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -996,7 +995,7 @@ check_list_unique_minmax(cxobj *xt, do { if (yang_keyword_get(ye) == Y_LIST || yang_keyword_get(ye) == Y_LEAF_LIST){ /* Check if the list length violates min/max */ - if ((ret = check_min_max(xt, ye, 0, cbret)) < 0) + if ((ret = check_min_max(xt, ye, 0, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -1014,14 +1013,14 @@ check_list_unique_minmax(cxobj *xt, * 1. Check if mandatory leafs present as subs. * 2. Check leaf values, eg int ranges and string regexps. * @param[in] xt XML node to be validated - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree. Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed (cbret set) * @retval -1 Error * @code * cxobj *x; - * cbuf *cbret = cbuf_new(); - * if ((ret = xml_yang_validate_add(h, x, cbret)) < 0) + * cbuf *xret = NULL; + * if ((ret = xml_yang_validate_add(h, x, &xret)) < 0) * err; * if (ret == 0) * fail; @@ -1032,8 +1031,8 @@ check_list_unique_minmax(cxobj *xt, */ int xml_yang_validate_add(clicon_handle h, - cxobj *xt, - cbuf *cbret) + cxobj *xt, + cxobj **xret) { int retval = -1; cg_var *cv = NULL; @@ -1047,11 +1046,11 @@ xml_yang_validate_add(clicon_handle h, /* if not given by argument (overide) use default link and !Node has a config sub-statement and it is false */ if ((yt = xml_spec(xt)) != NULL && yang_config(yt) != 0){ - if ((ret = check_choice(xt, yt, cbret)) < 0) + if ((ret = check_choice(xt, yt, xret)) < 0) goto done; if (ret == 0) goto fail; - if ((ret = check_mandatory(xt, yt, cbret)) < 0) + if ((ret = check_mandatory(xt, yt, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -1073,21 +1072,21 @@ xml_yang_validate_add(clicon_handle h, * are considered as "" */ cvtype = cv_type_get(cv); if (cv_isint(cvtype) || cvtype == CGV_BOOL || cvtype == CGV_DEC64){ - if (netconf_bad_element(cbret, "application", yt->ys_argument, "Invalid NULL value") < 0) + if (netconf_bad_element_xml(xret, "application", yt->ys_argument, "Invalid NULL value") < 0) goto done; goto fail; } } else{ if (cv_parse1(body, cv, &reason) != 1){ - if (netconf_bad_element(cbret, "application", yt->ys_argument, reason) < 0) + if (netconf_bad_element_xml(xret, "application", yt->ys_argument, reason) < 0) goto done; goto fail; } } if ((ys_cv_validate(h, cv, yt, &reason)) != 1){ - if (netconf_bad_element(cbret, "application", yt->ys_argument, reason) < 0) + if (netconf_bad_element_xml(xret, "application", yt->ys_argument, reason) < 0) goto done; goto fail; } @@ -1098,7 +1097,7 @@ xml_yang_validate_add(clicon_handle h, } x = NULL; while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) { - if ((ret = xml_yang_validate_add(h, x, cbret)) < 0) + if ((ret = xml_yang_validate_add(h, x, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -1116,11 +1115,12 @@ xml_yang_validate_add(clicon_handle h, } /*! Some checks done only at edit_config, eg keys in lists + * @param[out] xret Error XML tree. Free with xml_free after use */ int xml_yang_validate_list_key_only(clicon_handle h, - cxobj *xt, - cbuf *cbret) + cxobj *xt, + cxobj **xret) { int retval = -1; yang_stmt *yt; /* yang spec of xt going in */ @@ -1130,14 +1130,14 @@ xml_yang_validate_list_key_only(clicon_handle h, /* if not given by argument (overide) use default link and !Node has a config sub-statement and it is false */ if ((yt = xml_spec(xt)) != NULL && yang_config(yt) != 0){ - if ((ret = check_list_key(xt, yt, cbret)) < 0) + if ((ret = check_list_key(xt, yt, xret)) < 0) goto done; if (ret == 0) goto fail; } x = NULL; while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) { - if ((ret = xml_yang_validate_list_key_only(h, x, cbret)) < 0) + if ((ret = xml_yang_validate_list_key_only(h, x, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -1154,17 +1154,18 @@ xml_yang_validate_list_key_only(clicon_handle h, /*! Validate a single XML node with yang specification for all (not only added) entries * 1. Check leafrefs. Eg you delete a leaf and a leafref references it. * @param[in] xt XML node to be validated - * @param[out] cbret Error buffer (set w netconf error if retval == 0) + * @param[out] xret Error XML tree (if retval=0). Free with xml_free after use * @retval 1 Validation OK * @retval 0 Validation failed (cbret set) * @retval -1 Error * @code * cxobj *x; - * cbuf *cbret = cbuf_new(); - * if ((ret = xml_yang_validate_all(x, cbret)) < 0) + * cbuf *xret = NULL; + * if ((ret = xml_yang_validate_all(h, x, &xret)) < 0) * err; * if (ret == 0) * fail; + * xml_free(xret); * @endcode * @see xml_yang_validate_add * @see xml_yang_validate_rpc @@ -1172,8 +1173,8 @@ xml_yang_validate_list_key_only(clicon_handle h, */ int xml_yang_validate_all(clicon_handle h, - cxobj *xt, - cbuf *cbret) + cxobj *xt, + cxobj **xret) { int retval = -1; yang_stmt *ys; /* yang node */ @@ -1188,7 +1189,7 @@ xml_yang_validate_all(clicon_handle h, and !Node has a config sub-statement and it is false */ ys=xml_spec(xt); if (ys==NULL){ - if (netconf_unknown_element(cbret, "application", xml_name(xt), NULL) < 0) + if (netconf_unknown_element_xml(xret, "application", xml_name(xt), NULL) < 0) goto done; goto fail; } @@ -1207,12 +1208,16 @@ xml_yang_validate_all(clicon_handle h, */ if ((yc = yang_find(ys, Y_TYPE, NULL)) != NULL){ if (strcmp(yc->ys_argument, "leafref") == 0){ - if (validate_leafref(xt, yc, cbret) < 0) + if ((ret = validate_leafref(xt, yc, xret)) < 0) goto done; + if (ret == 0) + goto fail; } else if (strcmp(yc->ys_argument, "identityref") == 0){ - if (validate_identityref(xt, ys, yc, cbret) < 0) + if ((ret = validate_identityref(xt, ys, yc, xret)) < 0) goto done; + if (ret == 0) + goto fail; } } break; @@ -1230,7 +1235,7 @@ xml_yang_validate_all(clicon_handle h, goto done; if (!nr){ ye = yang_find(yc, Y_ERROR_MESSAGE, NULL); - if (netconf_operation_failed(cbret, "application", + if (netconf_operation_failed_xml(xret, "application", ye?ye->ys_argument:"must xpath validation failed") < 0) goto done; goto fail; @@ -1242,7 +1247,7 @@ xml_yang_validate_all(clicon_handle h, if ((nr = xpath_vec_bool(xt, "%s", xpath)) < 0) goto done; if (!nr){ - if (netconf_operation_failed(cbret, "application", + if (netconf_operation_failed_xml(xret, "application", "when xpath validation failed") < 0) goto done; goto fail; @@ -1251,7 +1256,7 @@ xml_yang_validate_all(clicon_handle h, } x = NULL; while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) { - if ((ret = xml_yang_validate_all(h, x, cbret)) < 0) + if ((ret = xml_yang_validate_all(h, x, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -1259,7 +1264,7 @@ xml_yang_validate_all(clicon_handle h, /* Check unique and min-max after choice test for example*/ if (yang_config(ys) != 0){ /* Checks if next level contains any unique list constraints */ - if ((ret = check_list_unique_minmax(xt, cbret)) < 0) + if ((ret = check_list_unique_minmax(xt, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -1274,24 +1279,25 @@ xml_yang_validate_all(clicon_handle h, } /*! Translate a single xml node to a cligen variable vector. Note not recursive + * @param[out] xret Error XML tree (if ret == 0). Free with xml_free after use * @retval 1 Validation OK - * @retval 0 Validation failed (cbret set) + * @retval 0 Validation failed (xret set) * @retval -1 Error */ int xml_yang_validate_all_top(clicon_handle h, cxobj *xt, - cbuf *cbret) + cxobj **xret) { int ret; cxobj *x; x = NULL; while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) { - if ((ret = xml_yang_validate_all(h, x, cbret)) < 1) + if ((ret = xml_yang_validate_all(h, x, xret)) < 1) return ret; } - if ((ret = check_list_unique_minmax(xt, cbret)) < 1) + if ((ret = check_list_unique_minmax(xt, xret)) < 1) return ret; return 1; } diff --git a/test/all.sh b/test/all.sh index 44500b2d..6711558f 100755 --- a/test/all.sh +++ b/test/all.sh @@ -15,7 +15,7 @@ testnr=0 for test in $pattern; do if [ $testnr != 0 ]; then echo; fi testfile=$test - ret=$(./$test) # . ./$test + . ./$test errcode=$? if [ $errcode -ne 0 ]; then err=1 diff --git a/test/test_identity.sh b/test/test_identity.sh index d2ae40cf..a31b1bbb 100755 --- a/test/test_identity.sh +++ b/test/test_identity.sh @@ -15,6 +15,7 @@ cat < $cfg $dir /usr/local/share/clixon $IETFRFC + $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ @@ -108,80 +109,82 @@ cat < $fyang } EOF -new "test params: -f $cfg -y $fyang" +new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg new "waiting" sleep $RCWAIT fi new "Set crypto to aes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'aes]]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 'aes]]>]]>' '^]]>]]>$' new "netconf validate " -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to mc:aes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'mc:aes]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'mc:aes]]>]]>' "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to des:des3" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'des:des3]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'des:des3]]>]]>' "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to mc:foo" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'mc:foo]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'mc:foo]]>]]>' "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to des:des3 using xmlns" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'des:des3]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'des:des3]]>]]>' "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" +if false; then # XXX this is not supported -#new "Set crypto to x:des3 using xmlns" -#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'x:des3]]>]]>' "^]]>]]>$" +new "Set crypto to x:des3 using xmlns" +expecteof "$clixon_netconf -qf $cfg" 0 'x:des3]]>]]>' "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" +fi # not supported new "Set crypto to foo:bar" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'foo:bar]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'foo:bar]]>]]>' "^]]>]]>$" -new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^applicationoperation-failederrorIdentityref validation failed, foo:bar not derived from crypto-alg]]>]]>$" +new "netconf validate (expect fail)" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationoperation-failederrorIdentityref validation failed, foo:bar not derived from crypto-alg]]>]]>$" new "cli set crypto to mc:aes" -expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o set crypto mc:aes" 0 "^$" +expectfn "$clixon_cli -1 -f $cfg -l o set crypto mc:aes" 0 "^$" new "cli validate" -expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o validate" 0 "^$" +expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$" new "cli set crypto to aes" -expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o set crypto aes" 0 "^$" +expectfn "$clixon_cli -1 -f $cfg -l o set crypto aes" 0 "^$" new "cli validate" -expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o validate" 0 "^$" +expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$" new "cli set crypto to des:des3" -expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o set crypto des:des3" 0 "^$" +expectfn "$clixon_cli -1 -f $cfg -l o set crypto des:des3" 0 "^$" new "cli validate" -expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o validate" 0 "^$" +expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$" if [ $BE -eq 0 ]; then exit # BE diff --git a/test/test_order.sh b/test/test_order.sh index 375c537c..20393f18 100755 --- a/test/test_order.sh +++ b/test/test_order.sh @@ -33,6 +33,7 @@ cat < $cfg /tmp/conf_yang.xml /usr/local/share/clixon $IETFRFC + $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -149,16 +150,16 @@ cat < $dbdir/running_db EOF -new "test params: -s running -f $cfg -y $fyang -- -s" +new "test params: -s running -f $cfg -- -s" if [ $BE -ne 0 ]; then new "kill old backend" - sudo clixon_backend -zf $cfg -y $fyang + sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend" - start_backend -s running -f $cfg -y $fyang -- -s + start_backend -s running -f $cfg -- -s new "waiting" sleep $RCWAIT @@ -169,75 +170,75 @@ new "state data (should be unordered: 42,41,43)" cat < $tmp ]]>]]> EOF -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "$(cat $tmp)" '424143]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 "$(cat $tmp)" '424143]]>]]>' # Check as file new "verify running from start, should be: c,l,y0,y1,y2,y3; y1 and y3 sorted." -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^hejhoppdbcaabcddbarabarcbarbbarabarbbarcbardbar]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^hejhoppdbcaabcddbarabarcbarbbarabarbbarcbardbar]]>]]>$' new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^abar]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^abar]]>]]>$' new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^abar]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^abar]]>]]>$' new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^bbar]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^bbar]]>]]>$' new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^bbar]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^bbar]]>]]>$' new "delete candidate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'none]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'none]]>]]>' "^]]>]]>$" # LEAF_LISTS new "add two entries (c,b) to leaf-list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'cb]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'cb]]>]]>' "^]]>]]>$" new "add one entry (a) to leaf-list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'a]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'a]]>]]>' "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "add one entry (0) to leaf-list user order after commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '0]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 '0]]>]]>' "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "verify leaf-list user order in running (as entered: c,b,a,0)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^cba0]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^cba0]]>]]>$' # LISTS new "add two entries to list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'cbarbfoo]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'cbarbfoo]]>]]>' "^]]>]]>$" new "add one entry to list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'afie]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'afie]]>]]>' "^]]>]]>$" new "verify list user order (as entered)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^cbarbfooafie]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^cbarbfooafie]]>]]>$' new "Overwrite existing ordered-by user y2->c" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' cnewc ]]>]]>' new "Overwrite existing ordered-by user y2->b" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' bnewb ]]>]]>' new "Overwrite existing ordered-by user y2->a" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' anewa ]]>]]>' new "Tests for no duplicates." -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^cnewcbnewbanewa]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^cnewcbnewbanewa]]>]]>$' #-- order by type rather than strings. # there are three leaf-lists:strings, ints, and decimal64, and two lists: @@ -246,44 +247,44 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' 1021 ]]>]]>' "^]]>]]>$" new "check string order (1,10,2)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^1102]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^1102]]>]]>$' new "put leaf-list int (10,2,1)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' 1021 ]]>]]>' "^]]>]]>$" new "check leaf-list int order (1,2,10)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^1210]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^1210]]>]]>$' new "put list int (10,2,1)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' 1021 ]]>]]>' "^]]>]]>$" new "check list int order (1,2,10)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^1210]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^1210]]>]]>$' new "put leaf-list decimal64 (10,2,1)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' 10.02.01.0 ]]>]]>' "^]]>]]>$" new "check leaf-list decimal64 order (1,2,10)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^1.02.010.0]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^1.02.010.0]]>]]>$' new "put list decimal64 (10,2,1)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ' +expecteof "$clixon_netconf -qf $cfg" 0 ' 10.02.01.0 ]]>]]>' "^]]>]]>$" new "check list decimal64 order (1,2,10)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^1.02.010.0]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^1.02.010.0]]>]]>$' if [ $BE -eq 0 ]; then exit # BE diff --git a/test/test_stream.sh b/test/test_stream.sh index 01a5697c..806aa9b8 100755 --- a/test/test_stream.sh +++ b/test/test_stream.sh @@ -39,6 +39,7 @@ cat < $cfg $cfg /usr/local/share/clixon $IETFRFC + $fyang false /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/lib/$APPNAME/backend @@ -101,7 +102,7 @@ cat < $fyang } EOF -new "test params: -f $cfg -y $fyang" +new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" @@ -109,15 +110,15 @@ if [ $BE -ne 0 ]; then if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg fi new "kill old restconf daemon" sudo pkill -u www-data -f "/www-data/clixon_restconf" new "start restconf daemon" -start_restconf -f $cfg -y $fyang +start_restconf -f $cfg new "waiting" wait_backend @@ -128,35 +129,35 @@ wait_restconf new "1. Netconf RFC5277 stream testing" # 1.1 Stream discovery new "netconf event stream discovery RFC5277 Sec 3.2.5" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' 'EXAMPLEExample event streamtrue]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' 'EXAMPLEExample event streamtrue]]>]]>' new "netconf event stream discovery RFC8040 Sec 6.2" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' 'EXAMPLEExample event streamtruexmlhttps://localhost/streams/EXAMPLE]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' 'EXAMPLEExample event streamtruexmlhttps://localhost/streams/EXAMPLE]]>]]>' # # 1.2 Netconf stream subscription new "netconf EXAMPLE subscription" -expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLE]]>]]>' '^]]>]]>20' $NCWAIT +expectwait "$clixon_netconf -qf $cfg" 'EXAMPLE]]>]]>' '^]]>]]>20' $NCWAIT new "netconf subscription with empty startTime" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'EXAMPLE]]>]]>' '^applicationbad-elementstartTimeerrorregexp match fail:' +expecteof "$clixon_netconf -qf $cfg" 0 'EXAMPLE]]>]]>' '^applicationbad-elementstartTimeerrorregexp match fail:' new "netconf EXAMPLE subscription with simple filter" -expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLE]]>]]>' '^]]>]]>20' $NCWAIT +expectwait "$clixon_netconf -qf $cfg" 'EXAMPLE]]>]]>' '^]]>]]>20' $NCWAIT new "netconf EXAMPLE subscription with filter classifier" -expectwait "$clixon_netconf -qf $cfg -y $fyang" "EXAMPLE]]>]]>" '^]]>]]>20' $NCWAIT +expectwait "$clixon_netconf -qf $cfg" "EXAMPLE]]>]]>" '^]]>]]>20' $NCWAIT new "netconf NONEXIST subscription" -expectwait "$clixon_netconf -qf $cfg -y $fyang" 'NONEXIST]]>]]>' '^applicationinvalid-valueerrorNo such stream]]>]]>$' $NCWAIT +expectwait "$clixon_netconf -qf $cfg" 'NONEXIST]]>]]>' '^applicationinvalid-valueerrorNo such stream]]>]]>$' $NCWAIT new "netconf EXAMPLE subscription with wrong date" -expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLEkallekaka]]>]]>' '^applicationbad-elementstartTimeerrorregexp match fail:' 0 +expectwait "$clixon_netconf -qf $cfg" 'EXAMPLEkallekaka]]>]]>' '^applicationbad-elementstartTimeerrorregexp match fail:' 0 #new "netconf EXAMPLE subscription with replay" #NOW=$(date +"%Y-%m-%dT%H:%M:%S") #sleep 10 -#expectwait "$clixon_netconf -qf $cfg -y $fyang" "EXAMPLE$NOW]]>]]>" '^]]>]]>20' 10 +#expectwait "$clixon_netconf -qf $cfg" "EXAMPLE$NOW]]>]]>" '^]]>]]>20' 10 sleep 2 # diff --git a/test/test_union.sh b/test/test_union.sh index 6326c5ab..8fa52a7b 100755 --- a/test/test_union.sh +++ b/test/test_union.sh @@ -18,6 +18,7 @@ cat < $cfg $dir /usr/local/share/clixon $IETFRFC + $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -76,7 +77,7 @@ module example{ } EOF -new "test params: -f $cfg -y $fyang" +new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" @@ -84,21 +85,21 @@ if [ $BE -ne 0 ]; then if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg new "waiting" sleep $RCWAIT fi new "cli set transitive string" -expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c talle x" 0 "^$" +expectfn "$clixon_cli -1f $cfg -l o set c talle x" 0 "^$" new "cli set transitive union" -expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle 33" 0 "^$" +expectfn "$clixon_cli -1f $cfg -l o set c ulle 33" 0 "^$" new "cli set transitive union error" -expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle kalle" 255 '^CLI syntax error: "set c ulle kalle": Unknown command$' +expectfn "$clixon_cli -1f $cfg -l o set c ulle kalle" 255 '^CLI syntax error: "set c ulle kalle": Unknown command$' if [ $BE -eq 0 ]; then exit # BE diff --git a/test/test_when_must.sh b/test/test_when_must.sh index d4cbc0ea..a57c4fe4 100755 --- a/test/test_when_must.sh +++ b/test/test_when_must.sh @@ -15,6 +15,7 @@ cat < $cfg $cfg /usr/local/share/clixon $IETFRFC + $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -89,56 +90,56 @@ module $APPNAME{ } EOF -new "test params: -f $cfg -y $fyang" +new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" - sudo clixon_backend -zf $cfg -y $fyang + sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg new "waiting" sleep $RCWAIT fi new "when: add static route" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'staticr1]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'staticr1]]>]]>' "^]]>]]>$" new "when: validate ok" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "when: add direct route" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'directr2]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'directr2]]>]]>' "^]]>]]>$" new "when get config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^directr2staticr1]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^directr2staticr1]]>]]>$' new "when: validate fail" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^applicationoperation-failederrorwhen xpath validation failed]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationoperation-failederrorwhen xpath validation failed]]>]]>$" new "when: discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "must: add interface" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'ethernet1500]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'ethernet1500]]>]]>' "^]]>]]>$" new "must: validate ok" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "must: add atm interface" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'atm32]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'atm32]]>]]>' "^]]>]]>$" new "must: atm validate fail" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^applicationoperation-failederrorAn ATM MTU must be 64 .. 17966]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationoperation-failederrorAn ATM MTU must be 64 .. 17966]]>]]>$" new "must: add eth interface" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'ethernet989]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'ethernet989]]>]]>' "^]]>]]>$" new "must: eth validate fail" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^applicationoperation-failederrorAn Ethernet MTU must be 1500]]>]]>" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationoperation-failederrorAn Ethernet MTU must be 1500]]>]]>" if [ $BE -eq 0 ]; then exit # BE diff --git a/test/test_yang.sh b/test/test_yang.sh index 6ce8ed3d..06161c00 100755 --- a/test/test_yang.sh +++ b/test/test_yang.sh @@ -17,6 +17,7 @@ cat < $cfg /usr/local/share/clixon $dir $IETFRFC + $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -141,35 +142,35 @@ module $APPNAME{ } EOF -new "test params: -f $cfg -y $fyang" +new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" - sudo clixon_backend -zf $cfg -y $fyang + sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg new "waiting" wait_backend fi new "cli defined extension" -expectfn "$clixon_cli -1f $cfg -y $fyang show version" 0 "3." +expectfn "$clixon_cli -1f $cfg show version" 0 "3." new "empty values in leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'a]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'a]]>]]>' "^]]>]]>$" new "empty values in leaf-list2" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf get config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^a]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^a]]>]]>$' new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #new "cli not defined extension" @@ -179,106 +180,106 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "] #expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" 0 "Yang error: Extension ex:not-defined not found" new "netconf schema resource, RFC 7895" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' 'ietf-yang-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-yang-typesimplement' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' 'ietf-yang-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-yang-typesimplement' new "netconf edit config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '125one]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 '125one]]>]]>' "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" # text empty type in running new "netconf commit 2nd" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf get config xpath" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^125one]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^125one]]>]]>$' new "netconf edit leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'hejhopp]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'hejhopp]]>]]>' "^]]>]]>$" new "netconf get leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^hejhopp]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^hejhopp]]>]]>$' new "netconf get leaf-list path" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^hejhopp]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^hejhopp]]>]]>$" new "netconf get (should be some)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^125one' +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^125one' new "cli set leaf-list" -expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" 0 "" +expectfn "$clixon_cli -1f $cfg set x f e foo" 0 "" new "cli show leaf-list" -expectfn "$clixon_cli -1f $cfg -y $fyang show xpath /x/f/e" 0 "foo" +expectfn "$clixon_cli -1f $cfg show xpath /x/f/e" 0 "foo" new "netconf set state data (not allowed)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' '^protocolinvalid-valueerrorState data not allowed]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 '42]]>]]>' '^protocolinvalid-valueerrorState data not allowed]]>]]>$' new "netconf set presence and not present" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf get presence only" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^]]>]]>$' new "netconf get presence only" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf anyxml" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf validate anyxml" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf delete candidate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'none]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'none]]>]]>' "^]]>]]>$" # Check 3-keys new "netconf add one 3-key entry" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '111one]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 '111one]]>]]>' "^]]>]]>$" new "netconf check add one 3-key" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '111one]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '111one]]>]]>' new "netconf add another (with same 1st key)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '121two]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 '121two]]>]]>' "^]]>]]>$" new "netconf check add another" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '111one121two]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '111one121two]]>]]>' new "netconf replace first" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '111replace]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 '111replace]]>]]>' "^]]>]]>$" new "netconf check replace" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '111replace121two]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '111replace121two]]>]]>' new "netconf delete first" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '111]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 '111]]>]]>' "^]]>]]>$" new "netconf check delete" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '121two]]>]]>' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '121two]]>]]>' # clear db for next test new "netconf delete candidate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'none]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'none]]>]]>' "^]]>]]>$" new "netconf commit empty candidate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconfig config submodule" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'afoo]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 'afoo]]>]]>' "^]]>]]>$" new "netconf submodule get config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^afoo]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^afoo]]>]]>$' new "netconf submodule validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf submodule discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" if [ $BE -eq 0 ]; then exit # BE diff --git a/util/clixon_util_xml.c b/util/clixon_util_xml.c index f84bc00c..06504753 100644 --- a/util/clixon_util_xml.c +++ b/util/clixon_util_xml.c @@ -118,7 +118,7 @@ main(int argc, struct stat st; int fd = 0; /* stdin */ cxobj *xcfg = NULL; - cbuf *cberr; + cbuf *cbret = NULL; /* In the startup, logs to stderr & debug flag set later */ clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR); @@ -205,13 +205,13 @@ main(int argc, if ((ret = json_parse_file(fd, yspec, &xt, &xerr)) < 0) goto done; if (ret == 0){ - xml_print(stderr, xerr); + clicon_rpc_generate_error("util_xml", xerr); goto done; } } else{ if (xml_parse_file(fd, "", NULL, &xt) < 0){ - fprintf(stderr, "xml parse error %s\n", clicon_err_reason); + fprintf(stderr, "xml parse error: %s\n", clicon_err_reason); goto done; } } @@ -227,10 +227,6 @@ main(int argc, /* 3. Validate data (if yspec) */ if (validate){ xc = xml_child_i(xt, 0); - if ((cberr = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, errno, "cbuf_new"); - goto done; - } /* Populate */ if (xml_apply0(xc, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; @@ -242,12 +238,14 @@ main(int argc, goto done; if (xml_apply0(xc, -1, xml_sort_verify, h) < 0) clicon_log(LOG_NOTICE, "%s: sort verify failed", __FUNCTION__); - if ((ret = xml_yang_validate_all_top(h, xc, cberr)) < 0) + if ((ret = xml_yang_validate_all_top(h, xc, &xerr)) < 0) goto done; - if (ret > 0 && (ret = xml_yang_validate_add(h, xc, cberr)) < 0) + if (ret > 0 && (ret = xml_yang_validate_add(h, xc, &xerr)) < 0) goto done; if (ret == 0){ - fprintf(stderr, "%s", cbuf_get(cberr)); + if (netconf_err2cb(xerr, &cbret) < 0) + goto done; + fprintf(stderr, "xml validation error: %s\n", cbuf_get(cbret)); goto done; } } @@ -264,6 +262,8 @@ main(int argc, } retval = 0; done: + if (cbret) + cbuf_free(cbret); if (xt) xml_free(xt); if (cb)