* New XML parsing API:
* `clixon_xml_parse_string()` * `clixon_xml_parse_file()` * New JSON parsing API, with same signature as XML parsing: * `clixon_json_parse_string()` * `clixon_xml_parse_file()` * XML YANG binding API have been rearranged as follows: * `xml_bind_yang_rpc()` * `xml_bind_yang_rpc_reply()` * `xml_bind_yang()` * `xml_bind_yang0()`
This commit is contained in:
parent
c4b0491754
commit
09a2e09848
54 changed files with 590 additions and 711 deletions
35
CHANGELOG.md
35
CHANGELOG.md
|
|
@ -76,23 +76,28 @@ features include optimized search functions and a repair callback.
|
||||||
* If you have used, `ys`, add `xml_spec_set(x, ys)` after the statement
|
* If you have used, `ys`, add `xml_spec_set(x, ys)` after the statement
|
||||||
* If you have `xml_type_set(x, TYPE)` after the statement, you can remove it and set it directly as: `xml_new(name, xp, TYPE)`
|
* If you have `xml_type_set(x, TYPE)` after the statement, you can remove it and set it directly as: `xml_new(name, xp, TYPE)`
|
||||||
* `xml_type_set()`has been removed in the API. The type must be set at creation timw with `xml_new`
|
* `xml_type_set()`has been removed in the API. The type must be set at creation timw with `xml_new`
|
||||||
|
* `clicon_rpc_generate_error()` renamed to `clixon_netconf_error()` and added a category parameter
|
||||||
* All uses of `api_path2xpath_cvv()` should be replaced by `api_path2xpath()`
|
* All uses of `api_path2xpath_cvv()` should be replaced by `api_path2xpath()`
|
||||||
* `api_path2xpath()` added an `xerr` argument.
|
* `api_path2xpath()` added an `xerr` argument.
|
||||||
* Parse and validation API more capable
|
* XML and JSON parsing functions have been rearranged/cleaned up as follows:
|
||||||
* `xml_spec_populate` has been split into a family of functions
|
* Three value returns: -1: error, 0: parse OK, 1: parse and YANG binding OK.
|
||||||
* `xml_bind_yang_rpc()`
|
* New concept called `yang_bind` that defines how XML symbols are bound to YANG after parsing (see below)
|
||||||
* `xml_bind_yang_rpc_reply()`
|
* New XML parsing API:
|
||||||
* `xml_bind_yang0()`
|
* `clixon_xml_parse_string()`
|
||||||
* `xml_bind_yang0_parent()`
|
* `clixon_xml_parse_file()`
|
||||||
* `xml_bind_yang()`
|
* New JSON parsing API, with same signature as XML parsing:
|
||||||
* `xml_bind_yang_parent()`
|
* `clixon_json_parse_string()`
|
||||||
* All have three-value return values: -1: error, 0: parse OK, 1: parse and YANG binding OK.
|
* `clixon_xml_parse_file()`
|
||||||
* `xml_parse` and `json_parse` API changes
|
* Yang binding type has been introduced as a new concept and used in the API with the following values:
|
||||||
* Three value returns: -1: error, 0: parse OK, 1: parse and YANG binding OK.
|
* `YB_MODULE` : Search for matching yang binding among top-level symbols of Yang modules
|
||||||
* Extended `xml_parse_file2` and `xml_parse_string2` extended API functions with all options available.
|
* `YB_PARENT` : Assume yang binding of existing parent and match its children by name
|
||||||
* New concept called `yang_bind` that defines how XML symbols are bound to YANG after parsing
|
* `YB_NONE` : Don't do YANG binding
|
||||||
* Existing API same except `xml_parse_file` `endtag` argument moved to `xml_parse_file2`
|
* XML YANG binding API have been rearranged as follows:
|
||||||
* Changed `clicon_session_id_get(clicon_handle h, uint32_t *id)`
|
* `xml_bind_yang_rpc()`
|
||||||
|
* `xml_bind_yang_rpc_reply()`
|
||||||
|
* `xml_bind_yang()`
|
||||||
|
* `xml_bind_yang0()`
|
||||||
|
* All have three-value return values: -1: error, 0: YANG binding failed, 1: parse and YANG binding OK.
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ client_get_capabilities(clicon_handle h,
|
||||||
cprintf(cb, "<capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability>");
|
cprintf(cb, "<capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability>");
|
||||||
cprintf(cb, "<capability>urn:ietf:params:restconf:capability:depth:1.0</capability>");
|
cprintf(cb, "<capability>urn:ietf:params:restconf:capability:depth:1.0</capability>");
|
||||||
cprintf(cb, "</capabilities>");
|
cprintf(cb, "</capabilities>");
|
||||||
if (xml_parse_string2(cbuf_get(cb), YB_PARENT, NULL, &xrstate, NULL) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_PARENT, NULL, &xrstate, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -236,7 +236,7 @@ client_get_streams(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb,"</%s>", top);
|
cprintf(cb,"</%s>", top);
|
||||||
|
|
||||||
if (xml_parse_string(cbuf_get(cb), yspec, &x) < 0){
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, &x, NULL) < 0){
|
||||||
if (netconf_operation_failed_xml(xret, "protocol", clicon_err_reason)< 0)
|
if (netconf_operation_failed_xml(xret, "protocol", clicon_err_reason)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -320,7 +320,7 @@ clixon_stats_get(clicon_handle h,
|
||||||
clixon_stats_get_db(h, "candidate", cb);
|
clixon_stats_get_db(h, "candidate", cb);
|
||||||
clixon_stats_get_db(h, "startup", cb);
|
clixon_stats_get_db(h, "startup", cb);
|
||||||
cprintf(cb, "</clixon-stats>");
|
cprintf(cb, "</clixon-stats>");
|
||||||
if ((ret = xml_parse_string2(cbuf_get(cb), YB_TOP, yspec, xret, NULL)) < 0)
|
if ((ret = clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
clicon_err(OE_XML, EINVAL, "Internal error");
|
clicon_err(OE_XML, EINVAL, "Internal error");
|
||||||
|
|
@ -376,7 +376,7 @@ client_statedata(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cb, "<netconf xmlns=\"%s\"/>", namespace);
|
cprintf(cb, "<netconf xmlns=\"%s\"/>", namespace);
|
||||||
if (xml_parse_string2(cbuf_get(cb), YB_TOP, yspec, xret, NULL) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = client_get_streams(h, yspec, xpath, ymod, "netconf", xret)) < 0)
|
if ((ret = client_get_streams(h, yspec, xpath, ymod, "netconf", xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -394,7 +394,7 @@ client_statedata(clicon_handle h,
|
||||||
}
|
}
|
||||||
cbuf_reset(cb);
|
cbuf_reset(cb);
|
||||||
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
||||||
if (xml_parse_string2(cbuf_get(cb), YB_TOP, yspec, xret, NULL) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = client_get_streams(h, yspec, xpath, ymod, "restconf-state", xret)) < 0)
|
if ((ret = client_get_streams(h, yspec, xpath, ymod, "restconf-state", xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -670,7 +670,7 @@ from_client_edit_config(clicon_handle h,
|
||||||
xml_spec_set(xc, NULL);
|
xml_spec_set(xc, NULL);
|
||||||
/* Populate XML with Yang spec (why not do this in parser?)
|
/* Populate XML with Yang spec (why not do this in parser?)
|
||||||
*/
|
*/
|
||||||
if (xml_bind_yang(xc, yspec, NULL) < 0)
|
if (xml_bind_yang(xc, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Maybe validate xml here as in text_modify_top? */
|
/* Maybe validate xml here as in text_modify_top? */
|
||||||
if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0)
|
if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0)
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ startup_common(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* After upgrading, XML tree needs to be sorted and yang spec populated */
|
/* After upgrading, XML tree needs to be sorted and yang spec populated */
|
||||||
if (xml_bind_yang(xt, yspec, NULL) < 0)
|
if (xml_bind_yang(xt, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_apply0(xt, CX_ELMNT, xml_sort, h) < 0)
|
if (xml_apply0(xt, CX_ELMNT, xml_sort, h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ nacm_load_external(clicon_handle h)
|
||||||
goto done;
|
goto done;
|
||||||
fd = fileno(f);
|
fd = fileno(f);
|
||||||
/* Read configfile */
|
/* Read configfile */
|
||||||
if (xml_parse_file(fd, yspec, &xt) < 0)
|
if (clixon_xml_parse_file(fd, YB_MODULE, yspec, NULL, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xt == NULL){
|
if (xt == NULL){
|
||||||
clicon_err(OE_XML, 0, "No xml tree in %s", filename);
|
clicon_err(OE_XML, 0, "No xml tree in %s", filename);
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ clixon_plugin_statedata(clicon_handle h,
|
||||||
if (debug)
|
if (debug)
|
||||||
clicon_log_xml(LOG_DEBUG, x, "%s STATE:", __FUNCTION__);
|
clicon_log_xml(LOG_DEBUG, x, "%s STATE:", __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
if (xml_bind_yang(x, yspec, NULL) < 0)
|
if (xml_bind_yang(x, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ load_extraxml(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
yspec = clicon_dbspec_yang(h);
|
yspec = clicon_dbspec_yang(h);
|
||||||
if (xml_parse_file(fd, yspec, &xt) < 0)
|
if (clixon_xml_parse_file(fd, YB_MODULE, yspec, NULL, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Replace parent w first child */
|
/* Replace parent w first child */
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
|
|
|
||||||
|
|
@ -712,13 +712,13 @@ compare_dbs(clicon_handle h,
|
||||||
if (clicon_rpc_get_config(h, NULL, "running", "/", NULL, &xc1) < 0)
|
if (clicon_rpc_get_config(h, NULL, "running", "/", NULL, &xc1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xc1, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xc1, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_get_config(h, NULL, "candidate", "/", NULL, &xc2) < 0)
|
if (clicon_rpc_get_config(h, NULL, "candidate", "/", NULL, &xc2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xc2, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xc2, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
|
if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
|
||||||
|
|
@ -795,7 +795,7 @@ load_config_file(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", filename);
|
clicon_err(OE_UNIX, errno, "open(%s)", filename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_parse_file(fd, NULL, &xt) < 0)
|
if (clixon_xml_parse_file(fd, YB_NONE, NULL, NULL, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xt == NULL)
|
if (xt == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -882,7 +882,7 @@ save_config_file(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* get-config returns a <data> tree. Save as <config> tree so it can be used
|
/* get-config returns a <data> tree. Save as <config> tree so it can be used
|
||||||
|
|
@ -1222,7 +1222,7 @@ cli_copy_config(clicon_handle h,
|
||||||
if (clicon_rpc_get_config(h, NULL, db, cbuf_get(cb), nsc, &x1) < 0)
|
if (clicon_rpc_get_config(h, NULL, db, cbuf_get(cb), nsc, &x1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(x1, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(x1, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ expand_dbvar(void *h,
|
||||||
if (clicon_rpc_get_config(h, NULL, dbstr, xpath, nsc, &xt) < 0) /* XXX */
|
if (clicon_rpc_get_config(h, NULL, dbstr, xpath, nsc, &xt) < 0) /* XXX */
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xe, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xe, "Get configuration", NULL);
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
xcur = xt; /* default top-of-tree */
|
xcur = xt; /* default top-of-tree */
|
||||||
|
|
@ -176,7 +176,7 @@ expand_dbvar(void *h,
|
||||||
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 0, &xbot, &y, &xerr)) < 0)
|
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 0, &xbot, &y, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
clicon_rpc_generate_error(xerr, "Expand datastore symbol", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Expand datastore symbol", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -492,7 +492,7 @@ cli_show_config1(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Print configuration according to format */
|
/* Print configuration according to format */
|
||||||
|
|
@ -633,7 +633,7 @@ show_conf_xpath(clicon_handle h,
|
||||||
if (clicon_rpc_get_config(h, NULL, str, xpath, nsc, &xt) < 0)
|
if (clicon_rpc_get_config(h, NULL, str, xpath, nsc, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -735,7 +735,7 @@ cli_show_auto1(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xp = xpath_first(xt, nsc, "%s", xpath)) != NULL)
|
if ((xp = xpath_first(xt, nsc, "%s", xpath)) != NULL)
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ netconf_output(int s,
|
||||||
clicon_debug(1, "SEND %s", msg);
|
clicon_debug(1, "SEND %s", msg);
|
||||||
if (debug > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */
|
if (debug > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
if (xml_parse_string(buf, NULL, &xt) == 0){
|
if (clixon_xml_parse_string(buf, YB_NONE, NULL, &xt, NULL) == 0){
|
||||||
clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0);
|
clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ netconf_input_packet(clicon_handle h,
|
||||||
}
|
}
|
||||||
str = str0;
|
str = str0;
|
||||||
/* Parse incoming XML message */
|
/* Parse incoming XML message */
|
||||||
if (xml_parse_string(str, yspec, &xreq) < 0){
|
if (clixon_xml_parse_string(str, YB_MODULE, yspec, &xreq, NULL) < 0){
|
||||||
free(str0);
|
free(str0);
|
||||||
if (netconf_operation_failed(cbret, "rpc", clicon_err_reason)< 0)
|
if (netconf_operation_failed(cbret, "rpc", clicon_err_reason)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -93,12 +93,12 @@ netconf_get_config_subtree(clicon_handle h,
|
||||||
if ((xdata = xpath_first(*xret, NULL, "/rpc-reply/data")) == NULL)
|
if ((xdata = xpath_first(*xret, NULL, "/rpc-reply/data")) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
if (xml_filter(xfilter, xdata) < 0){
|
if (xml_filter(xfilter, xdata) < 0){
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-info>filtering</error-info>"
|
"<error-info>filtering</error-info>"
|
||||||
"</rpc-error></rpc-reply>");
|
"</rpc-error></rpc-reply>");
|
||||||
}
|
}
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -180,13 +180,13 @@ netconf_get_config(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-message>filter type not supported</error-message>"
|
"<error-message>filter type not supported</error-message>"
|
||||||
"<error-info>type</error-info>"
|
"<error-info>type</error-info>"
|
||||||
"</rpc-error></rpc-reply>");
|
"</rpc-error></rpc-reply>");
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -245,11 +245,11 @@ get_edit_opts(cxobj *xn,
|
||||||
retval = 1; /* hunky dory */
|
retval = 1; /* hunky dory */
|
||||||
return retval;
|
return retval;
|
||||||
parerr: /* parameter error, xret set */
|
parerr: /* parameter error, xret set */
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>invalid-value</error-tag>"
|
"<error-tag>invalid-value</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"</rpc-error></rpc-reply>");
|
"</rpc-error></rpc-reply>");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,11 +322,11 @@ netconf_edit_config(clicon_handle h,
|
||||||
* (implement the features before removing these checks)
|
* (implement the features before removing these checks)
|
||||||
*/
|
*/
|
||||||
if (testopt!=TEST_THEN_SET || erropt!=STOP_ON_ERROR){
|
if (testopt!=TEST_THEN_SET || erropt!=STOP_ON_ERROR){
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-not-supported</error-tag>"
|
"<error-tag>operation-not-supported</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"</rpc-error></rpc-reply>");
|
"</rpc-error></rpc-reply>");
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0)
|
if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0)
|
||||||
|
|
@ -377,13 +377,13 @@ netconf_get(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-message>filter type not supported</error-message>"
|
"<error-message>filter type not supported</error-message>"
|
||||||
"<error-info>type</error-info>"
|
"<error-info>type</error-info>"
|
||||||
"</rpc-error></rpc-reply>");
|
"</rpc-error></rpc-reply>");
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -498,13 +498,13 @@ netconf_create_subscription(clicon_handle h,
|
||||||
if ((xfilter = xpath_first(xn, NULL, "//filter")) != NULL){
|
if ((xfilter = xpath_first(xn, NULL, "//filter")) != NULL){
|
||||||
if ((ftype = xml_find_value(xfilter, "type")) != NULL){
|
if ((ftype = xml_find_value(xfilter, "type")) != NULL){
|
||||||
if (strcmp(ftype, "xpath") != 0){
|
if (strcmp(ftype, "xpath") != 0){
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>application</error-type>"
|
"<error-type>application</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-message>only xpath filter type supported</error-message>"
|
"<error-message>only xpath filter type supported</error-message>"
|
||||||
"<error-info>type</error-info>"
|
"<error-info>type</error-info>"
|
||||||
"</rpc-error></rpc-reply>");
|
"</rpc-error></rpc-reply>");
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -572,13 +572,13 @@ netconf_application_rpc(clicon_handle h,
|
||||||
if (ys_module_by_xml(yspec, xn, &ymod) < 0)
|
if (ys_module_by_xml(yspec, xn, &ymod) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ymod == NULL){
|
if (ymod == NULL){
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>rpc</error-type>"
|
"<error-type>rpc</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-message>%s</error-message>"
|
"<error-message>%s</error-message>"
|
||||||
"<error-info>Not recognized module</error-info>"
|
"<error-info>Not recognized module</error-info>"
|
||||||
"</rpc-error></rpc-reply>", xml_name(xn));
|
"</rpc-error></rpc-reply>", xml_name(xn));
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
yrpc = yang_find(ymod, Y_RPC, xml_name(xn));
|
yrpc = yang_find(ymod, Y_RPC, xml_name(xn));
|
||||||
|
|
@ -587,7 +587,7 @@ netconf_application_rpc(clicon_handle h,
|
||||||
/* 1. Check xn arguments with input statement. */
|
/* 1. Check xn arguments with input statement. */
|
||||||
if ((yinput = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
|
if ((yinput = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
|
||||||
xml_spec_set(xn, yinput); /* needed for xml_bind_yang */
|
xml_spec_set(xn, yinput); /* needed for xml_bind_yang */
|
||||||
if (xml_bind_yang(xn, yspec, NULL) < 0)
|
if (xml_bind_yang(xn, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = xml_yang_validate_all_top(h, xn, &xerr)) < 0)
|
if ((ret = xml_yang_validate_all_top(h, xn, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -604,7 +604,7 @@ netconf_application_rpc(clicon_handle h,
|
||||||
if ((ret = rpc_callback_call(h, xn, cbret, NULL)) < 0)
|
if ((ret = rpc_callback_call(h, xn, cbret, NULL)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret > 0){ /* Handled locally */
|
if (ret > 0){ /* Handled locally */
|
||||||
if (xml_parse_string(cbuf_get(cbret), NULL, xret) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cbret), YB_NONE, NULL, xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else /* Send to backend */
|
else /* Send to backend */
|
||||||
|
|
@ -619,7 +619,7 @@ netconf_application_rpc(clicon_handle h,
|
||||||
if ((youtput = yang_find(yrpc, Y_OUTPUT, NULL)) != NULL){
|
if ((youtput = yang_find(yrpc, Y_OUTPUT, NULL)) != NULL){
|
||||||
xoutput=xpath_first(*xret, NULL, "/");
|
xoutput=xpath_first(*xret, NULL, "/");
|
||||||
xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
|
xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
|
||||||
if (xml_bind_yang(xoutput, yspec, NULL) < 0)
|
if (xml_bind_yang(xoutput, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0)
|
if ((ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -724,13 +724,13 @@ netconf_rpc_dispatch(clicon_handle h,
|
||||||
if ((retval = netconf_application_rpc(h, xe, xret)) < 0)
|
if ((retval = netconf_application_rpc(h, xe, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (retval == 0){ /* not handled by callback */
|
if (retval == 0){ /* not handled by callback */
|
||||||
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
clixon_xml_parse_va(YB_NONE, NULL, xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>rpc</error-type>"
|
"<error-type>rpc</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-message>%s</error-message>"
|
"<error-message>%s</error-message>"
|
||||||
"<error-info>Not recognized</error-info>"
|
"<error-info>Not recognized</error-info>"
|
||||||
"</rpc-error></rpc-reply>", xml_name(xe));
|
"</rpc-error></rpc-reply>", xml_name(xe));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,9 @@ api_root(clicon_handle h,
|
||||||
FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
|
FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
|
|
||||||
if (xml_parse_string("<restconf xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"><data/><operations/><yang-library-version>2016-06-21</yang-library-version></restconf>", yspec, &xt) < 0)
|
if (clixon_xml_parse_string("<restconf xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"><data/>"
|
||||||
|
"<operations/><yang-library-version>2016-06-21</yang-library-version></restconf>",
|
||||||
|
YB_MODULE, yspec, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
|
@ -283,7 +285,9 @@ api_yang_library_version(clicon_handle h,
|
||||||
FCGX_FPrintF(r->out, "Cache-Control: no-cache\r\n");
|
FCGX_FPrintF(r->out, "Cache-Control: no-cache\r\n");
|
||||||
FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
|
FCGX_FPrintF(r->out, "Content-Type: %s\r\n", restconf_media_int2str(media_out));
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
if (xml_parse_va(&xt, NULL, "<yang-library-version>%s</yang-library-version>", ietf_yang_library_revision) < 0)
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xt, NULL,
|
||||||
|
"<yang-library-version>%s</yang-library-version>",
|
||||||
|
ietf_yang_library_revision) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ api_data_write(clicon_handle h,
|
||||||
char *namespace = NULL;
|
char *namespace = NULL;
|
||||||
char *dname;
|
char *dname;
|
||||||
cvec *nsc = NULL;
|
cvec *nsc = NULL;
|
||||||
enum yang_bind yb;
|
yang_bind yb;
|
||||||
char *xpath = NULL;
|
char *xpath = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path0);
|
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path0);
|
||||||
|
|
@ -380,7 +380,7 @@ api_data_write(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xml_spec(xdata0)==NULL)
|
if (xml_spec(xdata0)==NULL)
|
||||||
yb = YB_TOP;
|
yb = YB_MODULE;
|
||||||
else
|
else
|
||||||
yb = YB_PARENT;
|
yb = YB_PARENT;
|
||||||
|
|
||||||
|
|
@ -392,7 +392,7 @@ api_data_write(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
switch (media_in){
|
switch (media_in){
|
||||||
case YANG_DATA_XML:
|
case YANG_DATA_XML:
|
||||||
if ((ret = xml_parse_string2(data, yb, yspec, &xdata0, &xerr)) < 0){
|
if ((ret = clixon_xml_parse_string(data, yb, yspec, &xdata0, &xerr)) < 0){
|
||||||
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -414,7 +414,7 @@ api_data_write(clicon_handle h,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case YANG_DATA_JSON:
|
case YANG_DATA_JSON:
|
||||||
if ((ret = json_parse_str2(data, yb, yspec, &xdata0, &xerr)) < 0){
|
if ((ret = clixon_json_parse_string(data, yb, yspec, &xdata0, &xerr)) < 0){
|
||||||
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ api_data_get2(clicon_handle h,
|
||||||
if ((xtop = xml_new("top", NULL, CX_ELMNT)) == NULL)
|
if ((xtop = xml_new("top", NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Translate api-path to xml, but to validate the api-path, note: strict=1
|
/* Translate api-path to xml, but to validate the api-path, note: strict=1
|
||||||
* xtop and xbot unnecessary fir this function but neede by function
|
* xtop and xbot unnecessary for this function but needed by function
|
||||||
*/
|
*/
|
||||||
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 1, &xbot, &y, &xerr)) < 0)
|
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 1, &xbot, &y, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ api_data_post(clicon_handle h,
|
||||||
int ret;
|
int ret;
|
||||||
restconf_media media_in;
|
restconf_media media_in;
|
||||||
int nrchildren0 = 0;
|
int nrchildren0 = 0;
|
||||||
enum yang_bind yb;
|
yang_bind yb;
|
||||||
|
|
||||||
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path);
|
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path);
|
||||||
clicon_debug(1, "%s data:\"%s\"", __FUNCTION__, data);
|
clicon_debug(1, "%s data:\"%s\"", __FUNCTION__, data);
|
||||||
|
|
@ -180,7 +180,7 @@ api_data_post(clicon_handle h,
|
||||||
xml_flag_set(x, XML_FLAG_MARK);
|
xml_flag_set(x, XML_FLAG_MARK);
|
||||||
}
|
}
|
||||||
if (xml_spec(xbot)==NULL)
|
if (xml_spec(xbot)==NULL)
|
||||||
yb = YB_TOP;
|
yb = YB_MODULE;
|
||||||
else
|
else
|
||||||
yb = YB_PARENT;
|
yb = YB_PARENT;
|
||||||
/* Parse input data as json or xml into xml
|
/* Parse input data as json or xml into xml
|
||||||
|
|
@ -190,7 +190,7 @@ api_data_post(clicon_handle h,
|
||||||
media_in = restconf_content_type(r);
|
media_in = restconf_content_type(r);
|
||||||
switch (media_in){
|
switch (media_in){
|
||||||
case YANG_DATA_XML:
|
case YANG_DATA_XML:
|
||||||
if ((ret = xml_parse_string2(data, yb, yspec, &xbot, &xerr)) < 0){
|
if ((ret = clixon_xml_parse_string(data, yb, yspec, &xbot, &xerr)) < 0){
|
||||||
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -212,7 +212,7 @@ api_data_post(clicon_handle h,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case YANG_DATA_JSON:
|
case YANG_DATA_JSON:
|
||||||
if ((ret = json_parse_str2(data, yb, yspec, &xbot, &xerr)) < 0){
|
if ((ret = clixon_json_parse_string(data, yb, yspec, &xbot, &xerr)) < 0){
|
||||||
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -453,7 +453,9 @@ api_operations_post_input(clicon_handle h,
|
||||||
media_in = restconf_content_type(r);
|
media_in = restconf_content_type(r);
|
||||||
switch (media_in){
|
switch (media_in){
|
||||||
case YANG_DATA_XML:
|
case YANG_DATA_XML:
|
||||||
if (xml_parse_string(data, yspec, &xdata) < 0){
|
/* XXX: Here data is on the form: <input xmlns="urn:example:clixon"/> and has no proper yang binding
|
||||||
|
* support */
|
||||||
|
if ((ret = clixon_xml_parse_string(data, YB_NONE, yspec, &xdata, &xerr)) < 0){
|
||||||
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -464,9 +466,21 @@ api_operations_post_input(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
clicon_debug(1, "%s F", __FUNCTION__);
|
||||||
|
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (api_return_err(h, r, xe, pretty, media_out, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case YANG_DATA_JSON:
|
case YANG_DATA_JSON:
|
||||||
if ((ret = json_parse_str(data, yspec, &xdata, &xerr)) < 0){
|
/* XXX: Here data is on the form: {"clixon-example:input":null} and has no proper yang binding
|
||||||
|
* support */
|
||||||
|
if ((ret = clixon_json_parse_string(data, YB_NONE, yspec, &xdata, &xerr)) < 0){
|
||||||
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xe = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -492,6 +506,7 @@ api_operations_post_input(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
} /* switch media_in */
|
} /* switch media_in */
|
||||||
|
clicon_debug(1, "%s F", __FUNCTION__);
|
||||||
xml_name_set(xdata, "data");
|
xml_name_set(xdata, "data");
|
||||||
/* Here xdata is:
|
/* Here xdata is:
|
||||||
* <data><input xmlns="urn:example:clixon">...</input></data>
|
* <data><input xmlns="urn:example:clixon">...</input></data>
|
||||||
|
|
@ -610,8 +625,8 @@ api_operations_post_output(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
if (youtput != NULL){
|
if (youtput != NULL){
|
||||||
xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
|
xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
|
||||||
#if 0
|
#ifdef notyet
|
||||||
if (xml_bind_yang(xoutput, yspec, NULL) < 0)
|
if (xml_bind_yang(xoutput, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0)
|
if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -863,7 +878,7 @@ api_operations_post(clicon_handle h,
|
||||||
if ((ret = rpc_callback_call(h, xbot, cbret, r)) < 0)
|
if ((ret = rpc_callback_call(h, xbot, cbret, r)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret > 0){ /* Handled locally */
|
if (ret > 0){ /* Handled locally */
|
||||||
if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cbret), YB_NONE, NULL, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Local error: return it and quit */
|
/* Local error: return it and quit */
|
||||||
if ((xe = xpath_first(xret, NULL, "rpc-reply/rpc-error")) != NULL){
|
if ((xe = xpath_first(xret, NULL, "rpc-reply/rpc-error")) != NULL){
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ example_statedata(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
clicon_err(OE_UNIX, errno, "open(%s)", _state_file);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_parse_file(fd, yspec, &xstate) < 0)
|
if (clixon_xml_parse_file(fd, YB_MODULE, yspec, NULL, &xstate, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -353,16 +353,18 @@ example_statedata(clicon_handle h,
|
||||||
cprintf(cb, "</interface>");
|
cprintf(cb, "</interface>");
|
||||||
}
|
}
|
||||||
cprintf(cb, "</interfaces>");
|
cprintf(cb, "</interfaces>");
|
||||||
if (xml_parse_string(cbuf_get(cb), NULL, &xstate) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, &xstate, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* State in test_yang.sh , test_restconf.sh and test_order.sh */
|
/* State in test_yang.sh , test_restconf.sh and test_order.sh */
|
||||||
if (yang_find_module_by_namespace(yspec, "urn:example:clixon") != NULL){
|
if (yang_find_module_by_namespace(yspec, "urn:example:clixon") != NULL){
|
||||||
if (xml_parse_string("<state xmlns=\"urn:example:clixon\">"
|
if (clixon_xml_parse_string("<state xmlns=\"urn:example:clixon\">"
|
||||||
"<op>42</op>"
|
"<op>42</op>"
|
||||||
"<op>41</op>"
|
"<op>41</op>"
|
||||||
"<op>43</op>" /* should not be ordered */
|
"<op>43</op>" /* should not be ordered */
|
||||||
"</state>", NULL, &xstate) < 0)
|
"</state>",
|
||||||
|
YB_NONE,
|
||||||
|
NULL, &xstate, NULL) < 0)
|
||||||
goto done; /* For the case when urn:example:clixon is not loaded */
|
goto done; /* For the case when urn:example:clixon is not loaded */
|
||||||
}
|
}
|
||||||
/* Event state from RFC8040 Appendix B.3.1
|
/* Event state from RFC8040 Appendix B.3.1
|
||||||
|
|
@ -375,7 +377,7 @@ example_statedata(clicon_handle h,
|
||||||
cprintf(cb, "<event><name>interface-down</name><event-count>90</event-count></event>");
|
cprintf(cb, "<event><name>interface-down</name><event-count>90</event-count></event>");
|
||||||
cprintf(cb, "<event><name>interface-up</name><event-count>77</event-count></event>");
|
cprintf(cb, "<event><name>interface-up</name><event-count>77</event-count></event>");
|
||||||
cprintf(cb, "</events>");
|
cprintf(cb, "</events>");
|
||||||
if (xml_parse_string(cbuf_get(cb), NULL, &xstate) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, &xstate, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -757,9 +759,9 @@ example_reset(clicon_handle h,
|
||||||
|
|
||||||
if (!_reset)
|
if (!_reset)
|
||||||
goto ok; /* Note not enabled by default */
|
goto ok; /* Note not enabled by default */
|
||||||
if (xml_parse_string("<config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface>"
|
if (clixon_xml_parse_string("<config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\">"
|
||||||
"<name>lo</name><type>ex:loopback</type>"
|
"<interface><name>lo</name><type>ex:loopback</type>"
|
||||||
"</interface></interfaces></config>", NULL, &xt) < 0)
|
"</interface></interfaces></config>", YB_NONE, NULL, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Replace parent w first child */
|
/* Replace parent w first child */
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
|
|
|
||||||
|
|
@ -173,11 +173,11 @@ nacm_statedata(clicon_handle h,
|
||||||
cxobj **xvec = NULL;
|
cxobj **xvec = NULL;
|
||||||
|
|
||||||
/* Example of (static) statedata, real code would poll state */
|
/* Example of (static) statedata, real code would poll state */
|
||||||
if (xml_parse_string("<nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\">"
|
if (clixon_xml_parse_string("<nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\">"
|
||||||
"<denied-data-writes>0</denied-data-writes>"
|
"<denied-data-writes>0</denied-data-writes>"
|
||||||
"<denied-operations>0</denied-operations>"
|
"<denied-operations>0</denied-operations>"
|
||||||
"<denied-notifications>0</denied-notifications>"
|
"<denied-notifications>0</denied-notifications>"
|
||||||
"</nacm>", NULL, &xstate) < 0)
|
"</nacm>", YB_NONE, NULL, &xstate, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
|
|
@ -98,10 +98,12 @@ example_client_rpc(clicon_handle h,
|
||||||
/* User supplied variable in CLI command */
|
/* User supplied variable in CLI command */
|
||||||
cva = cvec_find(cvv, "a"); /* get a cligen variable from vector */
|
cva = cvec_find(cvv, "a"); /* get a cligen variable from vector */
|
||||||
/* Create XML for example netconf RPC */
|
/* Create XML for example netconf RPC */
|
||||||
if (xml_parse_va(&xtop, NULL, "<rpc message-id=\"101\" xmlns=\"%s\" username=\"%s\"><example xmlns=\"urn:example:clixon\"><x>%s</x></example></rpc>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xtop, NULL,
|
||||||
NETCONF_BASE_NAMESPACE,
|
"<rpc message-id=\"101\" xmlns=\"%s\" username=\"%s\">"
|
||||||
clicon_username_get(h),
|
"<example xmlns=\"urn:example:clixon\"><x>%s</x></example></rpc>",
|
||||||
cv_string_get(cva)) < 0)
|
NETCONF_BASE_NAMESPACE,
|
||||||
|
clicon_username_get(h),
|
||||||
|
cv_string_get(cva)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Skip top-level */
|
/* Skip top-level */
|
||||||
xrpc = xml_child_i(xtop, 0);
|
xrpc = xml_child_i(xtop, 0);
|
||||||
|
|
@ -109,7 +111,7 @@ example_client_rpc(clicon_handle h,
|
||||||
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Get configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Get configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Print result */
|
/* Print result */
|
||||||
|
|
|
||||||
|
|
@ -93,9 +93,9 @@ extern char clicon_err_reason[ERR_STRLEN];
|
||||||
*/
|
*/
|
||||||
int clicon_err_reset(void);
|
int clicon_err_reset(void);
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||||
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
int clicon_err_fn(const char *fn, const int line, int category, int err, char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
||||||
#else
|
#else
|
||||||
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...);
|
int clicon_err_fn(const char *fn, const int line, int category, int err, char *format, ...);
|
||||||
#endif
|
#endif
|
||||||
char *clicon_strerror(int err);
|
char *clicon_strerror(int err);
|
||||||
void *clicon_err_save(void);
|
void *clicon_err_save(void);
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,7 @@ int xml2json_cbuf_vec(cbuf *cb, cxobj **vec, size_t veclen, int pretty);
|
||||||
int xml2json(FILE *f, cxobj *x, int pretty);
|
int xml2json(FILE *f, cxobj *x, int pretty);
|
||||||
int json_print(FILE *f, cxobj *x);
|
int json_print(FILE *f, cxobj *x);
|
||||||
int xml2json_vec(FILE *f, cxobj **vec, size_t veclen, int pretty);
|
int xml2json_vec(FILE *f, cxobj **vec, size_t veclen, int pretty);
|
||||||
int json_parse_str(char *str, yang_stmt *yspec, cxobj **xt, cxobj **xret);
|
int clixon_json_parse_string(char *str, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xret);
|
||||||
int json_parse_str2(char *str, enum yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xret);
|
int clixon_json_parse_file(int fd, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xret);
|
||||||
int json_parse_file(int fd, yang_stmt *yspec, cxobj **xt, cxobj **xret);
|
|
||||||
|
|
||||||
#endif /* _CLIXON_JSON_H */
|
#endif /* _CLIXON_JSON_H */
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,11 @@ enum netconf_content{
|
||||||
};
|
};
|
||||||
typedef enum netconf_content netconf_content;
|
typedef enum netconf_content netconf_content;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros
|
||||||
|
*/
|
||||||
|
#define clixon_netconf_error(c, x, f, a) clixon_netconf_error_fn(__FUNCTION__, __LINE__, (c), (x), (f), (a))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
|
@ -96,4 +101,7 @@ const char *netconf_content_int2str(netconf_content nr);
|
||||||
int netconf_hello_server(clicon_handle h, cbuf *cb, uint32_t session_id);
|
int netconf_hello_server(clicon_handle h, cbuf *cb, uint32_t session_id);
|
||||||
int netconf_hello_req(clicon_handle h, cbuf *cb);
|
int netconf_hello_req(clicon_handle h, cbuf *cb);
|
||||||
|
|
||||||
|
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...);
|
||||||
|
int clixon_netconf_error_fn(const char *fn, const int line, int category, cxobj *xerr, const char *fmt, const char *arg);
|
||||||
|
|
||||||
#endif /* _CLIXON_NETCONF_LIB_H */
|
#endif /* _CLIXON_NETCONF_LIB_H */
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ int clicon_rpc_msg(clicon_handle h, struct clicon_msg *msg, cxobj **xret0,
|
||||||
int *sock0);
|
int *sock0);
|
||||||
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
||||||
int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp);
|
int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp);
|
||||||
int clicon_rpc_generate_error(cxobj *xerr, const char *fmt, const char *arg);
|
|
||||||
int clicon_rpc_get_config(clicon_handle h, char *username, char *db, char *xpath, cvec *nsc, cxobj **xret);
|
int clicon_rpc_get_config(clicon_handle h, char *username, char *db, char *xpath, cvec *nsc, cxobj **xret);
|
||||||
int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op,
|
int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op,
|
||||||
char *xml);
|
char *xml);
|
||||||
|
|
|
||||||
|
|
@ -84,14 +84,47 @@ enum cxobj_type {CX_ERROR=-1,
|
||||||
CX_ATTR,
|
CX_ATTR,
|
||||||
CX_BODY};
|
CX_BODY};
|
||||||
|
|
||||||
/* How to bind yang to XML top-level when parsing */
|
/* How to bind yang to XML top-level when parsing
|
||||||
|
* Assume an XML tree x with parent xp (or NULL) and a set of children c1,c2:
|
||||||
|
*
|
||||||
|
* (XML) xp
|
||||||
|
* |
|
||||||
|
* x
|
||||||
|
* / \
|
||||||
|
* c1 c2
|
||||||
|
* (1) If you make a binding using YB_MODULE, you assume there is a loaded module "ym" with a top-level
|
||||||
|
* data resource "y" that the XML node x can match to:
|
||||||
|
*
|
||||||
|
* (XML) xp ym (YANG)
|
||||||
|
* | |
|
||||||
|
* x - - - - - y
|
||||||
|
* / \ / \
|
||||||
|
* x1 x2 - - y1 y2
|
||||||
|
* In that case, "y" is a container, list, leaf or leaf-list with same name as "x".
|
||||||
|
*
|
||||||
|
* (2) If you make a binding using YB_PARENT, you assume xp already have a YANG binding (eg to "yp"):
|
||||||
|
*
|
||||||
|
* (XML) xp - - - - yp (YANG)
|
||||||
|
* |
|
||||||
|
* x
|
||||||
|
* so that the yang binding of "x" is a child of "yp":
|
||||||
|
*
|
||||||
|
* (XML) xp - - - - yp (YANG)
|
||||||
|
* | |
|
||||||
|
* x - - - - y
|
||||||
|
* / \ / \
|
||||||
|
* x1 x2 - - y1 y2
|
||||||
|
* XXX: lacks support for incoming restconf rpc, see api_operations_post_input)
|
||||||
|
*/
|
||||||
enum yang_bind{
|
enum yang_bind{
|
||||||
YB_UNKNOWN=0, /* System derive binding: top if parent not exist or no spec, otherwise parent */
|
YB_MODULE=0, /* Search for matching yang binding among top-level symbols of Yang modules */
|
||||||
YB_NONE, /* Dont try to do Yang binding */
|
YB_PARENT, /* Assume yang binding of existing parent and match its children by name */
|
||||||
YB_PARENT, /* Get yang binding from parents yang */
|
YB_NONE, /* Dont do Yang binding */
|
||||||
YB_TOP, /* Get yang binding from top-level modules */
|
#ifdef NYI
|
||||||
YB_RPC, /* Assume top-level xml is an netconf RPC message */
|
YB_RPC, /* Assume top-level xml is an netconf RPC message (NYI) */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
typedef enum yang_bind yang_bind;
|
||||||
|
|
||||||
#define CX_ANY CX_ERROR /* catch all and error is same */
|
#define CX_ANY CX_ERROR /* catch all and error is same */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,18 +48,15 @@ int xml_print(FILE *f, cxobj *xn);
|
||||||
int clicon_xml2cbuf(cbuf *cb, cxobj *x, int level, int prettyprint, int32_t depth);
|
int clicon_xml2cbuf(cbuf *cb, cxobj *x, int level, int prettyprint, int32_t depth);
|
||||||
int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
|
int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
|
||||||
|
|
||||||
int xml_parse_file(int fd, yang_stmt *yspec, cxobj **xt);
|
int clixon_xml_parse_file(int fd, yang_bind yb, yang_stmt *yspec, char *endtag, cxobj **xt, cxobj **xerr);
|
||||||
int xml_parse_file2(int fd, enum yang_bind yb, yang_stmt *yspec, char *endtag, cxobj **xt, cxobj **xerr);
|
int clixon_xml_parse_string(const char *str, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
|
||||||
int xml_parse_string2(const char *str, enum yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
|
|
||||||
int xml_parse_string(const char *str, yang_stmt *yspec, cxobj **xt);
|
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||||
int xml_parse_va(cxobj **xt, yang_stmt *yspec, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
int clixon_xml_parse_va(yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr,
|
||||||
|
const char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
||||||
#else
|
#else
|
||||||
int xml_parse_va(cxobj **xt, yang_stmt *yspec, const char *format, ...);
|
int clixon_xml_parse_va(yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr,
|
||||||
#endif
|
const char *format, ...);
|
||||||
#ifdef NOTUSED
|
|
||||||
int xml_body_int32(cxobj *xb, int32_t *val);
|
|
||||||
int xml_body_uint32(cxobj *xb, uint32_t *val);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _CLIXON_XML_IO_H_ */
|
#endif /* _CLIXON_XML_IO_H_ */
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,8 @@ int xml_sanity(cxobj *x, void *arg);
|
||||||
int xml_non_config_data(cxobj *xt, void *arg);
|
int xml_non_config_data(cxobj *xt, void *arg);
|
||||||
int xml_bind_yang_rpc(cxobj *xrpc, yang_stmt *yspec, cxobj **xerr);
|
int xml_bind_yang_rpc(cxobj *xrpc, yang_stmt *yspec, cxobj **xerr);
|
||||||
int xml_bind_yang_rpc_reply(cxobj *xrpc, char *name, yang_stmt *yspec, cxobj **xerr);
|
int xml_bind_yang_rpc_reply(cxobj *xrpc, char *name, yang_stmt *yspec, cxobj **xerr);
|
||||||
int xml_bind_yang0(cxobj *xt, yang_stmt *yspec, cxobj **xerr);
|
int xml_bind_yang0(cxobj *xt, yang_bind yb, yang_stmt *yspec, cxobj **xerr);
|
||||||
int xml_bind_yang0_parent(cxobj *xt, cxobj **xerr);
|
int xml_bind_yang(cxobj *xt, yang_bind yb, yang_stmt *yspec, cxobj **xerr);
|
||||||
int xml_bind_yang(cxobj *xt, yang_stmt *yspec, cxobj **xerr);
|
|
||||||
int xml_bind_yang_parent(cxobj *xt, cxobj **xerr);
|
|
||||||
|
|
||||||
int xml2xpath(cxobj *x, char **xpath);
|
int xml2xpath(cxobj *x, char **xpath);
|
||||||
int assign_namespaces(cxobj *x0, cxobj *x1, cxobj *x1p);
|
int assign_namespaces(cxobj *x0, cxobj *x1, cxobj *x1p);
|
||||||
|
|
|
||||||
|
|
@ -250,11 +250,13 @@ text_read_modstate(clicon_handle h,
|
||||||
else if (xmcache && msd){
|
else if (xmcache && msd){
|
||||||
msd->md_status = 1; /* There is module state in the file */
|
msd->md_status = 1; /* There is module state in the file */
|
||||||
/* Create diff trees */
|
/* Create diff trees */
|
||||||
if (xml_parse_string("<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\"/>", yspec, &msd->md_del) < 0)
|
if (clixon_xml_parse_string("<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\"/>",
|
||||||
|
YB_MODULE, yspec, &msd->md_del, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(msd->md_del, 0, &msd->md_del) < 0)
|
if (xml_rootchild(msd->md_del, 0, &msd->md_del) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_string("<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\"/>", yspec, &msd->md_mod) < 0)
|
if (clixon_xml_parse_string("<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\"/>",
|
||||||
|
YB_MODULE, yspec, &msd->md_mod, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(msd->md_mod, 0, &msd->md_mod) < 0)
|
if (xml_rootchild(msd->md_mod, 0, &msd->md_mod) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -349,10 +351,10 @@ xmldb_readfile(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (strcmp(format, "json")==0){
|
if (strcmp(format, "json")==0){
|
||||||
if ((ret = json_parse_file(fd, yspec, &x0, NULL)) < 0) /* XXX: ret == 0*/
|
if ((ret = clixon_json_parse_file(fd, YB_MODULE, yspec, &x0, NULL)) < 0) /* XXX: ret == 0*/
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if ((xml_parse_file2(fd, YB_TOP, yspec, "</config>", &x0, NULL)) < 0)
|
else if ((clixon_xml_parse_file(fd, YB_MODULE, yspec, "</config>", &x0, NULL)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Always assert a top-level called "config".
|
/* Always assert a top-level called "config".
|
||||||
|
|
|
||||||
|
|
@ -808,7 +808,7 @@ xml_container_presence(cxobj *x,
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt;
|
* cxobj *xt;
|
||||||
* cxobj *xret = NULL;
|
* cxobj *xret = NULL;
|
||||||
* if (xml_parse_string("<a>17</a>", yspec, &xt) < 0)
|
* if (clixon_xml_parse_string("<a>17</a>", YB_NONE, NULL, &xt, NULL) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if ((ret = xmldb_put(h, "running", OP_MERGE, xt, username, cbret)) < 0)
|
* if ((ret = xmldb_put(h, "running", OP_MERGE, xt, username, cbret)) < 0)
|
||||||
* err;
|
* err;
|
||||||
|
|
|
||||||
|
|
@ -139,17 +139,16 @@ clicon_err_reset(void)
|
||||||
*
|
*
|
||||||
* @param[in] fn Inline function name (when called from clicon_err() macro)
|
* @param[in] fn Inline function name (when called from clicon_err() macro)
|
||||||
* @param[in] line Inline file line number (when called from clicon_err() macro)
|
* @param[in] line Inline file line number (when called from clicon_err() macro)
|
||||||
* @param[in] err Error number, typically errno
|
* @param[in] category See enum clicon_err
|
||||||
* @param[in] suberr Sub-error number
|
* @param[in] errno Error number, typically errno
|
||||||
* @param[in] reason Error string, format with argv
|
* @param[in] reason Error string, format with argv
|
||||||
* @see clicon_err_reser Resetting the global error variables.
|
* @see clicon_err_reser Resetting the global error variables.
|
||||||
*/
|
*/
|
||||||
int
|
int clicon_err_fn(const char *fn,
|
||||||
clicon_err_fn(const char *fn,
|
const int line,
|
||||||
const int line,
|
int category,
|
||||||
int category,
|
int err,
|
||||||
int suberr,
|
char *format, ...)
|
||||||
char *reason, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
int len;
|
int len;
|
||||||
|
|
@ -158,11 +157,11 @@ clicon_err_fn(const char *fn,
|
||||||
|
|
||||||
/* Set the global variables */
|
/* Set the global variables */
|
||||||
clicon_errno = category;
|
clicon_errno = category;
|
||||||
clicon_suberrno = suberr;
|
clicon_suberrno = errno;
|
||||||
|
|
||||||
/* first round: compute length of error message */
|
/* first round: compute length of error message */
|
||||||
va_start(args, reason);
|
va_start(args, format);
|
||||||
len = vsnprintf(NULL, 0, reason, args);
|
len = vsnprintf(NULL, 0, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
/* allocate a message string exactly fitting the message length */
|
/* allocate a message string exactly fitting the message length */
|
||||||
|
|
@ -171,9 +170,9 @@ clicon_err_fn(const char *fn,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* second round: compute write message from reason and args */
|
/* second round: compute write message from format and args */
|
||||||
va_start(args, reason);
|
va_start(args, format);
|
||||||
if (vsnprintf(msg, len+1, reason, args) < 0){
|
if (vsnprintf(msg, len+1, format, args) < 0){
|
||||||
va_end(args);
|
va_end(args);
|
||||||
fprintf(stderr, "vsnprintf: %s\n", strerror(errno)); /* dont use clicon_err here due to recursion */
|
fprintf(stderr, "vsnprintf: %s\n", strerror(errno)); /* dont use clicon_err here due to recursion */
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -182,14 +181,14 @@ clicon_err_fn(const char *fn,
|
||||||
strncpy(clicon_err_reason, msg, ERR_STRLEN-1);
|
strncpy(clicon_err_reason, msg, ERR_STRLEN-1);
|
||||||
|
|
||||||
/* Actually log it */
|
/* Actually log it */
|
||||||
if (suberr){
|
if (errno){
|
||||||
/* Here we could take care of specific suberr, like application-defined errors */
|
/* Here we could take care of specific errno, like application-defined errors */
|
||||||
clicon_log(LOG_ERR, "%s: %d: %s: %s: %s",
|
clicon_log(LOG_ERR, "%s: %d: %s: %s: %s",
|
||||||
fn,
|
fn,
|
||||||
line,
|
line,
|
||||||
clicon_strerror(category),
|
clicon_strerror(category),
|
||||||
msg,
|
msg,
|
||||||
suberr==XMLPARSE_ERRNO?"XML parse error":strerror(suberr));
|
errno==XMLPARSE_ERRNO?"XML parse error":strerror(errno));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
clicon_log(LOG_ERR, "%s: %d: %s: %s",
|
clicon_log(LOG_ERR, "%s: %d: %s: %s",
|
||||||
|
|
|
||||||
|
|
@ -1169,11 +1169,11 @@ json_xmlns_translate(yang_stmt *yspec,
|
||||||
* @see RFC 7951
|
* @see RFC 7951
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
_json_parse(char *str,
|
_json_parse(char *str,
|
||||||
enum yang_bind yb,
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj *xt,
|
cxobj *xt,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_json_yacc jy = {0,};
|
clixon_json_yacc jy = {0,};
|
||||||
|
|
@ -1223,22 +1223,32 @@ _json_parse(char *str,
|
||||||
* XXX should be xml_bind_yang0_parent() sometimes.
|
* XXX should be xml_bind_yang0_parent() sometimes.
|
||||||
*/
|
*/
|
||||||
switch (yb){
|
switch (yb){
|
||||||
case YB_RPC:
|
|
||||||
case YB_UNKNOWN:
|
|
||||||
case YB_NONE:
|
|
||||||
break;
|
|
||||||
case YB_PARENT:
|
case YB_PARENT:
|
||||||
if ((ret = xml_bind_yang0_parent(x, xerr)) < 0)
|
if ((ret = xml_bind_yang0(x, yb, yspec, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
failed++;
|
failed++;
|
||||||
break;
|
break;
|
||||||
case YB_TOP:
|
case YB_MODULE:
|
||||||
if (xml_bind_yang0(x, yspec, xerr) < 0)
|
#ifdef XMLDB_CONFIG_HACK
|
||||||
goto done;
|
if (strcmp(xml_name(x),"config") == 0 ||
|
||||||
|
strcmp(xml_name(x),"data") == 0){
|
||||||
|
/* xt:<top> nospec
|
||||||
|
* x: <config>
|
||||||
|
* <a> <-- populate from modules
|
||||||
|
*/
|
||||||
|
if ((ret = xml_bind_yang(x, yb, yspec, xerr)) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if ((ret = xml_bind_yang0(x, yb, yspec, xerr)) < 0)
|
||||||
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
failed++;
|
failed++;
|
||||||
break;
|
break;
|
||||||
|
case YB_NONE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* Now find leafs with identityrefs (+transitive) and translate
|
/* Now find leafs with identityrefs (+transitive) and translate
|
||||||
* prefixes in values to XML namespaces */
|
* prefixes in values to XML namespaces */
|
||||||
|
|
@ -1247,9 +1257,12 @@ _json_parse(char *str,
|
||||||
if (ret == 0) /* XXX necessary? */
|
if (ret == 0) /* XXX necessary? */
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (failed)
|
||||||
|
goto fail;
|
||||||
|
/* This fails if xt is not bound to yang */
|
||||||
if (xml_apply0(xt, CX_ELMNT, xml_sort, NULL) < 0)
|
if (xml_apply0(xt, CX_ELMNT, xml_sort, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = (failed==0) ? 1 : 0;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
if (cberr)
|
if (cberr)
|
||||||
|
|
@ -1267,29 +1280,30 @@ _json_parse(char *str,
|
||||||
/*! Parse string containing JSON and return an XML tree
|
/*! Parse string containing JSON and return an XML tree
|
||||||
*
|
*
|
||||||
* @param[in] str String containing JSON
|
* @param[in] str String containing JSON
|
||||||
|
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] yspec Yang specification, mandatory to make module->xmlns translation
|
* @param[in] yspec Yang specification, mandatory to make module->xmlns translation
|
||||||
* @param[in,out] xt Top object, if not exists, on success it is created with name 'top'
|
* @param[in,out] xt Top object, if not exists, on success it is created with name 'top'
|
||||||
* @param[out] xerr Reason for invalid returned as netconf err msg
|
* @param[out] xerr Reason for invalid returned as netconf err msg
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* cxobj *cx = NULL;
|
|
||||||
* if (json_parse_str(str, yspec, &cx, &xerr) < 0)
|
|
||||||
* err;
|
|
||||||
* xml_free(cx);
|
|
||||||
* @endcode
|
|
||||||
* @note you need to free the xml parse tree after use, using xml_free()
|
|
||||||
* @see json_parse_file
|
|
||||||
* @retval 1 OK and valid
|
* @retval 1 OK and valid
|
||||||
* @retval 0 Invalid (only if yang spec) w xerr set
|
* @retval 0 Invalid (only if yang spec) w xerr set
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval -1 Error with clicon_err called
|
||||||
* @see json_parse_file with a file descriptor (and more description)
|
*
|
||||||
|
* @code
|
||||||
|
* cxobj *x = NULL;
|
||||||
|
* if (clixon_json_parse_string(str, YB_MODULE, yspec, &x, &xerr) < 0)
|
||||||
|
* err;
|
||||||
|
* xml_free(x);
|
||||||
|
* @endcode
|
||||||
|
* @note you need to free the xml parse tree after use, using xml_free()
|
||||||
|
* @see clixon_xml_parse_string XML instead of JSON
|
||||||
|
* @see clixon_json_parse_file From a file
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
json_parse_str2(char *str,
|
clixon_json_parse_string(char *str,
|
||||||
enum yang_bind yb,
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj **xt,
|
cxobj **xt,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if (xt==NULL){
|
if (xt==NULL){
|
||||||
|
|
@ -1303,31 +1317,6 @@ json_parse_str2(char *str,
|
||||||
return _json_parse(str, yb, yspec, *xt, xerr);
|
return _json_parse(str, yb, yspec, *xt, xerr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
json_parse_str(char *str,
|
|
||||||
yang_stmt *yspec,
|
|
||||||
cxobj **xt,
|
|
||||||
cxobj **xerr)
|
|
||||||
{
|
|
||||||
enum yang_bind yb = YB_PARENT;
|
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
|
||||||
if (xt==NULL){
|
|
||||||
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*xt == NULL){
|
|
||||||
yb = YB_TOP; /* ad-hoc #1 */
|
|
||||||
if ((*xt = xml_new("top", NULL, CX_ELMNT)) == NULL)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (xml_spec(*xt) == NULL)
|
|
||||||
yb = YB_TOP; /* ad-hoc #2 */
|
|
||||||
}
|
|
||||||
return _json_parse(str, yb, yspec, *xt, xerr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read a JSON definition from file and parse it into a parse-tree.
|
/*! Read a JSON definition from file and parse it into a parse-tree.
|
||||||
*
|
*
|
||||||
* File will be parsed as follows:
|
* File will be parsed as follows:
|
||||||
|
|
@ -1347,7 +1336,7 @@ json_parse_str(char *str,
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
* if (json_parse_file(0, yspec, &xt) < 0)
|
* if (clixon_json_parse_file(0, YB_MODULE, yspec, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* xml_free(xt);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
|
|
@ -1359,31 +1348,29 @@ json_parse_str(char *str,
|
||||||
* @retval 0 Invalid (only if yang spec) w xerr set
|
* @retval 0 Invalid (only if yang spec) w xerr set
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval -1 Error with clicon_err called
|
||||||
*
|
*
|
||||||
* @see json_parse_str
|
* @see clixon_json_parse_string
|
||||||
* @see RFC7951
|
* @see RFC7951
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
json_parse_file(int fd,
|
clixon_json_parse_file(int fd,
|
||||||
yang_stmt *yspec,
|
yang_bind yb,
|
||||||
cxobj **xt,
|
yang_stmt *yspec,
|
||||||
cxobj **xerr)
|
cxobj **xt,
|
||||||
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int ret;
|
int ret;
|
||||||
char *jsonbuf = NULL;
|
char *jsonbuf = NULL;
|
||||||
int jsonbuflen = BUFLEN; /* start size */
|
int jsonbuflen = BUFLEN; /* start size */
|
||||||
int oldjsonbuflen;
|
int oldjsonbuflen;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
char ch;
|
char ch;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
enum yang_bind yb = YB_PARENT;
|
|
||||||
|
|
||||||
if (xt==NULL){
|
if (xt==NULL){
|
||||||
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (*xt==NULL)
|
|
||||||
yb = YB_TOP;
|
|
||||||
if ((jsonbuf = malloc(jsonbuflen)) == NULL){
|
if ((jsonbuf = malloc(jsonbuflen)) == NULL){
|
||||||
clicon_err(OE_XML, errno, "malloc");
|
clicon_err(OE_XML, errno, "malloc");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -134,15 +134,16 @@ netconf_invalid_value_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
"<error-tag>invalid-value</error-tag>"
|
"<error-type>%s</error-type>"
|
||||||
"<error-severity>error</error-severity>", type) < 0)
|
"<error-tag>invalid-value</error-tag>"
|
||||||
|
"<error-severity>error</error-severity>", type) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
encstr) < 0)
|
"<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -314,16 +315,16 @@ netconf_bad_attribute_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>%s</error-type>"
|
||||||
"<error-tag>bad-attribute</error-tag>"
|
"<error-tag>bad-attribute</error-tag>"
|
||||||
"<error-info>%s</error-info>"
|
"<error-info>%s</error-info>"
|
||||||
"<error-severity>error</error-severity>", type, info) < 0)
|
"<error-severity>error</error-severity>", type, info) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-message>%s</error-message>",
|
||||||
encstr) < 0)
|
encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -403,17 +404,17 @@ netconf_common_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>%s</error-type>"
|
||||||
"<error-tag>%s</error-tag>"
|
"<error-tag>%s</error-tag>"
|
||||||
"<error-info><%s>%s</%s></error-info>"
|
"<error-info><%s>%s</%s></error-info>"
|
||||||
"<error-severity>error</error-severity>",
|
"<error-severity>error</error-severity>",
|
||||||
type, tag, infotag, element, infotag) < 0)
|
type, tag, infotag, element, infotag) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-message>%s</error-message>",
|
||||||
encstr) < 0)
|
encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -653,15 +654,15 @@ netconf_access_denied_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>%s</error-type>"
|
||||||
"<error-tag>access-denied</error-tag>"
|
"<error-tag>access-denied</error-tag>"
|
||||||
"<error-severity>error</error-severity>", type) < 0)
|
"<error-severity>error</error-severity>", type) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-message>%s</error-message>",
|
||||||
encstr) < 0)
|
encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -883,24 +884,24 @@ netconf_data_missing_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL,
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
"<error-type>application</error-type>"
|
"<error-type>application</error-type>"
|
||||||
"<error-tag>data-missing</error-tag>") < 0)
|
"<error-tag>data-missing</error-tag>") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (missing_choice) /* NYI: RFC7950: 15.6 <error-path> */
|
if (missing_choice) /* NYI: RFC7950: 15.6 <error-path> */
|
||||||
if (xml_parse_va(&xerr, NULL,
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
"<error-app-tag>missing-choice</error-app-tag>"
|
"<error-app-tag>missing-choice</error-app-tag>"
|
||||||
"<error-info><missing-choice>%s</missing-choice></error-info>",
|
"<error-info><missing-choice>%s</missing-choice></error-info>",
|
||||||
missing_choice) < 0)
|
missing_choice) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL,
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
"<error-severity>error</error-severity>") < 0)
|
"<error-severity>error</error-severity>") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL,
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
"<error-message>%s</error-message>", encstr) < 0)
|
"<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1011,16 +1012,16 @@ netconf_operation_failed_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>%s</error-type>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-severity>error</error-severity>",
|
"<error-severity>error</error-severity>",
|
||||||
type) < 0)
|
type) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-message>%s</error-message>",
|
||||||
encstr) < 0)
|
encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1090,15 +1091,15 @@ netconf_malformed_message_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>rpc</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>rpc</error-type>"
|
||||||
"<error-tag>malformed-message</error-tag>"
|
"<error-tag>malformed-message</error-tag>"
|
||||||
"<error-severity>error</error-severity>") < 0)
|
"<error-severity>error</error-severity>") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-message>%s</error-message>",
|
||||||
encstr) < 0)
|
encstr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1137,10 +1138,11 @@ netconf_data_not_unique_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>protocol</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL,
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-app-tag>data-not-unique</error-app-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-severity>error</error-severity>") < 0)
|
"<error-app-tag>data-not-unique</error-app-tag>"
|
||||||
|
"<error-severity>error</error-severity>") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cvec_len(cvk)){
|
if (cvec_len(cvk)){
|
||||||
if ((xinfo = xml_new("error-info", xerr, CX_ELMNT)) == NULL)
|
if ((xinfo = xml_new("error-info", xerr, CX_ELMNT)) == NULL)
|
||||||
|
|
@ -1153,7 +1155,8 @@ netconf_data_not_unique_xml(cxobj **xret,
|
||||||
if ((xi = xml_find(x, cv_string_get(cvi))) == NULL)
|
if ((xi = xml_find(x, cv_string_get(cvi))) == NULL)
|
||||||
continue; /* ignore, shouldnt happen */
|
continue; /* ignore, shouldnt happen */
|
||||||
clicon_xml2cbuf(cb, xi, 0, 0, -1);
|
clicon_xml2cbuf(cb, xi, 0, 0, -1);
|
||||||
if (xml_parse_va(&xinfo, NULL, "<non-unique>%s</non-unique>", cbuf_get(cb)) < 0)
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xinfo, NULL,
|
||||||
|
"<non-unique>%s</non-unique>", cbuf_get(cb)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cbuf_reset(cb);
|
cbuf_reset(cb);
|
||||||
}
|
}
|
||||||
|
|
@ -1190,13 +1193,13 @@ netconf_minmax_elements_xml(cxobj **xret,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_va(&xerr, NULL, "<error-type>protocol</error-type>"
|
if (clixon_xml_parse_va(YB_NONE, NULL, &xerr, NULL, "<error-type>protocol</error-type>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-app-tag>too-%s-elements</error-app-tag>"
|
"<error-app-tag>too-%s-elements</error-app-tag>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
"<error-path>%s</error-path>",
|
"<error-path>%s</error-path>",
|
||||||
max?"many":"few",
|
max?"many":"few",
|
||||||
xml_name(x)) < 0) /* XXX should be xml2xpath */
|
xml_name(x)) < 0) /* XXX should be xml2xpath */
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -1264,19 +1267,20 @@ netconf_module_features(clicon_handle h)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
yang_stmt *yspec;
|
|
||||||
|
|
||||||
yspec = clicon_dbspec_yang(h);
|
|
||||||
if ((xc = clicon_conf_xml(h)) == NULL){
|
if ((xc = clicon_conf_xml(h)) == NULL){
|
||||||
clicon_err(OE_CFG, ENOENT, "Clicon configuration not loaded");
|
clicon_err(OE_CFG, ENOENT, "Clicon configuration not loaded");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Enable features (hardcoded here) */
|
/* Enable features (hardcoded here) */
|
||||||
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:candidate</CLICON_FEATURE>", yspec, &xc) < 0)
|
if (clixon_xml_parse_string("<CLICON_FEATURE>ietf-netconf:candidate</CLICON_FEATURE>",
|
||||||
|
YB_PARENT, NULL, &xc, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:validate</CLICON_FEATURE>", yspec, &xc) < 0)
|
if (clixon_xml_parse_string("<CLICON_FEATURE>ietf-netconf:validate</CLICON_FEATURE>",
|
||||||
|
YB_PARENT, NULL, &xc, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:xpath</CLICON_FEATURE>", yspec, &xc) < 0)
|
if (clixon_xml_parse_string("<CLICON_FEATURE>ietf-netconf:xpath</CLICON_FEATURE>",
|
||||||
|
YB_PARENT, NULL, &xc, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -1320,7 +1324,7 @@ netconf_module_load(clicon_handle h)
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
* char *db;
|
* char *db;
|
||||||
* xml_parse_string("<x><target>source</target></x>", NULL, &xt);
|
* clixon_xml_parse_string("<x><target>source</target></x>", YB_NONE, NULL, &xt, NULL);
|
||||||
* db = netconf_db_find(xt, "target");
|
* db = netconf_db_find(xt, "target");
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
|
|
@ -1355,7 +1359,7 @@ netconf_db_find(cxobj *xn,
|
||||||
* printf("%s", cbuf_get(cb));
|
* printf("%s", cbuf_get(cb));
|
||||||
* cbuf_free(cb);
|
* cbuf_free(cb);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see clicon_rpc_generate_error
|
* @see clixon_netconf_error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_err2cb(cxobj *xerr,
|
netconf_err2cb(cxobj *xerr,
|
||||||
|
|
@ -1496,3 +1500,46 @@ netconf_hello_req(clicon_handle h,
|
||||||
retval = 0;
|
retval = 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Generate clicon error from Netconf error message
|
||||||
|
*
|
||||||
|
* Get a text error message from netconf error message and generate error on the form:
|
||||||
|
* <msg>: "<arg>": <netconf-error> or <msg>: <netconf-error>
|
||||||
|
* @param[in] fn Inline function name (when called from clicon_err() macro)
|
||||||
|
* @param[in] line Inline file line number (when called from clicon_err() macro)
|
||||||
|
* @param[in] err Error number, typically errno
|
||||||
|
* @param[in] xerr Netconf error xml tree on the form: <rpc-error>
|
||||||
|
* @param[in] format Format string
|
||||||
|
* @param[in] arg String argument to format (optional)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_netconf_error_fn(const char *fn,
|
||||||
|
const int line,
|
||||||
|
int category,
|
||||||
|
cxobj *xerr,
|
||||||
|
const char *msg,
|
||||||
|
const char *arg)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) ==NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (msg){
|
||||||
|
cprintf(cb, "%s", msg);
|
||||||
|
if (arg)
|
||||||
|
cprintf(cb, " \"%s\" ", arg);
|
||||||
|
cprintf(cb, ": ");
|
||||||
|
}
|
||||||
|
if (netconf_err2cb(xerr, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
clicon_err_fn(fn, line, category, 0, "%s", cbuf_get(cb));
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ parse_configfile(clicon_handle h,
|
||||||
char *body;
|
char *body;
|
||||||
clicon_hash_t *copt = clicon_options(h);
|
clicon_hash_t *copt = clicon_options(h);
|
||||||
cbuf *cbret = NULL;
|
cbuf *cbret = NULL;
|
||||||
cxobj *xret = NULL;
|
cxobj *xerr = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
cvec *nsc = NULL;
|
cvec *nsc = NULL;
|
||||||
|
|
||||||
|
|
@ -236,8 +236,18 @@ parse_configfile(clicon_handle h,
|
||||||
}
|
}
|
||||||
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
|
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
|
||||||
fd = fileno(f);
|
fd = fileno(f);
|
||||||
if (xml_parse_file(fd, yspec, &xt) < 0)
|
if ((ret = clixon_xml_parse_file(fd, yspec?YB_MODULE:YB_NONE, yspec, NULL, &xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
if ((cbret = cbuf_new()) ==NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (netconf_err2cb(xerr, cbret) < 0)
|
||||||
|
goto done;
|
||||||
|
clixon_netconf_error(OE_CFG, xerr, NULL, NULL);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (xml_child_nr(xt)==1 && xml_child_nr_type(xt, CX_BODY)==1){
|
if (xml_child_nr(xt)==1 && xml_child_nr_type(xt, CX_BODY)==1){
|
||||||
clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename);
|
clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -252,14 +262,14 @@ parse_configfile(clicon_handle h,
|
||||||
}
|
}
|
||||||
if (xml_apply0(xc, CX_ELMNT, xml_default, h) < 0)
|
if (xml_apply0(xc, CX_ELMNT, xml_default, h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = xml_yang_validate_add(h, xc, &xret)) < 0)
|
if ((ret = xml_yang_validate_add(h, xc, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if ((cbret = cbuf_new()) ==NULL){
|
if ((cbret = cbuf_new()) ==NULL){
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (netconf_err2cb(xret, cbret) < 0)
|
if (netconf_err2cb(xerr, cbret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_err(OE_CFG, 0, "Config file validation: %s", cbuf_get(cbret));
|
clicon_err(OE_CFG, 0, "Config file validation: %s", cbuf_get(cbret));
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -296,8 +306,8 @@ parse_configfile(clicon_handle h,
|
||||||
xml_nsctx_free(nsc);
|
xml_nsctx_free(nsc);
|
||||||
if (cbret)
|
if (cbret)
|
||||||
cbuf_free(cbret);
|
cbuf_free(cbret);
|
||||||
if (xret)
|
if (xerr)
|
||||||
xml_free(xret);
|
xml_free(xerr);
|
||||||
if (xt)
|
if (xt)
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
if (f)
|
if (f)
|
||||||
|
|
@ -330,8 +340,8 @@ clicon_option_add(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, ENOENT, "option %s not found (clicon_conf_xml_set has not been called?)", name);
|
clicon_err(OE_UNIX, ENOENT, "option %s not found (clicon_conf_xml_set has not been called?)", name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_parse_va(&x, NULL, "<%s>%s</%s>",
|
if (clixon_xml_parse_va(YB_NONE, NULL, &x, NULL, "<%s>%s</%s>",
|
||||||
name, value, name) < 0)
|
name, value, name) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_hash_add(copt,
|
if (clicon_hash_add(copt,
|
||||||
|
|
@ -394,7 +404,7 @@ clicon_options_main(clicon_handle h)
|
||||||
* - no default values
|
* - no default values
|
||||||
* - no sanity checks
|
* - no sanity checks
|
||||||
*/
|
*/
|
||||||
if (parse_configfile(h, configfile, yspec, &xconfig) < 0)
|
if (parse_configfile(h, configfile, NULL, &xconfig) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ clicon_msg_decode(struct clicon_msg *msg,
|
||||||
/* body */
|
/* body */
|
||||||
xmlstr = msg->op_body;
|
xmlstr = msg->op_body;
|
||||||
clicon_debug(1, "%s %s", __FUNCTION__, xmlstr);
|
clicon_debug(1, "%s %s", __FUNCTION__, xmlstr);
|
||||||
if (xml_parse_string(xmlstr, yspec, xml) < 0)
|
if (clixon_xml_parse_string(xmlstr, yspec?YB_MODULE:YB_NONE, yspec, xml, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
/* Cannot populate xret here because need to know RPC name (eg "lock") in order to associate yang
|
/* Cannot populate xret here because need to know RPC name (eg "lock") in order to associate yang
|
||||||
* to reply.
|
* to reply.
|
||||||
*/
|
*/
|
||||||
if (xml_parse_string2(retdata, YB_NONE, NULL, &xret, NULL) < 0)
|
if (clixon_xml_parse_string(retdata, YB_NONE, NULL, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xret0){
|
if (xret0){
|
||||||
|
|
@ -280,38 +280,6 @@ clicon_rpc_netconf_xml(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Generate clicon error from Netconf error message
|
|
||||||
*
|
|
||||||
* Get a text error message from netconf error message and generate error on the form:
|
|
||||||
* <msg>: "<arg>": <netconf-error> or <msg>: <netconf-error>
|
|
||||||
* @param[in] xerr Netconf error xml tree on the form: <rpc-error>
|
|
||||||
* @param[in] format Format string
|
|
||||||
* @param[in] arg String argument to format (optional)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clicon_rpc_generate_error(cxobj *xerr,
|
|
||||||
const char *msg,
|
|
||||||
const char *arg)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cbuf *cb = NULL;
|
|
||||||
|
|
||||||
if ((cb = cbuf_new()) ==NULL){
|
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (netconf_err2cb(xerr, cb) < 0)
|
|
||||||
goto done;
|
|
||||||
cprintf(cb, ". %s", msg);
|
|
||||||
if (arg)
|
|
||||||
cprintf(cb, " \"%s\" ", arg);
|
|
||||||
clicon_err(OE_NETCONF, 0, "%s", cbuf_get(cb));
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (cb)
|
|
||||||
cbuf_free(cb);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Get database configuration
|
/*! Get database configuration
|
||||||
* Same as clicon_proto_change just with a cvec instead of lvec
|
* Same as clicon_proto_change just with a cvec instead of lvec
|
||||||
|
|
@ -333,7 +301,7 @@ clicon_rpc_generate_error(cxobj *xerr,
|
||||||
* if (clicon_rpc_get_config(h, NULL, "running", "/hello/world", nsc, &xt) < 0)
|
* if (clicon_rpc_get_config(h, NULL, "running", "/hello/world", nsc, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
* clicon_rpc_generate_error(xerr, "msg", "/hello/world");
|
* clixon_netconf_error(OE_NETCONF, xerr, "msg", "/hello/world");
|
||||||
* err;
|
* err;
|
||||||
* }
|
* }
|
||||||
* if (xt)
|
* if (xt)
|
||||||
|
|
@ -342,7 +310,7 @@ clicon_rpc_generate_error(cxobj *xerr,
|
||||||
* xml_nsctx_free(nsc);
|
* xml_nsctx_free(nsc);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see clicon_rpc_get
|
* @see clicon_rpc_get
|
||||||
* @see clicon_rpc_generate_error
|
* @see clixon_netconf_error
|
||||||
* @note the netconf return message is yang populated, as well as the return data
|
* @note the netconf return message is yang populated, as well as the return data
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -403,7 +371,7 @@ clicon_rpc_get_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
yspec = clicon_dbspec_yang(h);
|
yspec = clicon_dbspec_yang(h);
|
||||||
if ((ret = xml_bind_yang(xd, yspec, &xerr)) < 0)
|
if ((ret = xml_bind_yang(xd, YB_MODULE, yspec, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -477,7 +445,7 @@ clicon_rpc_edit_config(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Editing configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Editing configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -527,7 +495,7 @@ clicon_rpc_copy_config(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Copying configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Copying configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -570,7 +538,7 @@ clicon_rpc_delete_config(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Deleting configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Deleting configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -609,7 +577,7 @@ clicon_rpc_lock(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Locking configuration", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Locking configuration", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -647,7 +615,7 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Configuration unlock", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Configuration unlock", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -681,7 +649,7 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
* if (clicon_rpc_get(h, "/hello/world", nsc, CONTENT_ALL, -1, &xt) < 0)
|
* if (clicon_rpc_get(h, "/hello/world", nsc, CONTENT_ALL, -1, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
* if ((xerr = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
* clicon_rpc_generate_error(xerr, "clicon_rpc_get", NULL);
|
* clixon_netconf_error(OE_NETCONF, xerr, "clicon_rpc_get", NULL);
|
||||||
* err;
|
* err;
|
||||||
* }
|
* }
|
||||||
* if (xt)
|
* if (xt)
|
||||||
|
|
@ -690,7 +658,7 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
* xml_nsctx_free(nsc);
|
* xml_nsctx_free(nsc);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see clicon_rpc_get_config which is almost the same as with content=config, but you can also select dbname
|
* @see clicon_rpc_get_config which is almost the same as with content=config, but you can also select dbname
|
||||||
* @see clicon_rpc_generate_error
|
* @see clixon_netconf_error
|
||||||
* @note the netconf return message is yang populated, as well as the return data
|
* @note the netconf return message is yang populated, as well as the return data
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -759,7 +727,7 @@ clicon_rpc_get(clicon_handle h,
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
yspec = clicon_dbspec_yang(h);
|
yspec = clicon_dbspec_yang(h);
|
||||||
if ((ret = xml_bind_yang(xd, yspec, &xerr)) < 0)
|
if ((ret = xml_bind_yang(xd, YB_MODULE, yspec, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){
|
||||||
|
|
@ -811,7 +779,7 @@ clicon_rpc_close_session(clicon_handle h)
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Close session", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Close session", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -850,7 +818,7 @@ clicon_rpc_kill_session(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Kill session", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Kill session", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -888,7 +856,7 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, CLIXON_ERRSTR_VALIDATE_FAILED, NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, CLIXON_ERRSTR_VALIDATE_FAILED, NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -924,7 +892,7 @@ clicon_rpc_commit(clicon_handle h)
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, CLIXON_ERRSTR_COMMIT_FAILED, NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, CLIXON_ERRSTR_COMMIT_FAILED, NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -960,7 +928,7 @@ clicon_rpc_discard_changes(clicon_handle h)
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Discard changes", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Discard changes", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1010,7 +978,7 @@ clicon_rpc_create_subscription(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, s0) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, s0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Create subscription", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Create subscription", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1048,7 +1016,7 @@ clicon_rpc_debug(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Debug", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Debug", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xpath_first(xret, NULL, "//rpc-reply/ok") == NULL){
|
if (xpath_first(xret, NULL, "//rpc-reply/ok") == NULL){
|
||||||
|
|
@ -1091,7 +1059,7 @@ clicon_hello_req(clicon_handle h,
|
||||||
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||||
clicon_rpc_generate_error(xerr, "Hello", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "Hello", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((x = xpath_first(xret, NULL, "hello/session-id")) == NULL){
|
if ((x = xpath_first(xret, NULL, "hello/session-id")) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -584,7 +584,7 @@ stream_notify(clicon_handle h,
|
||||||
/* From RFC5277 */
|
/* From RFC5277 */
|
||||||
cprintf(cb, "<notification xmlns=\"%s\"><eventTime>%s</eventTime>%s</notification>",
|
cprintf(cb, "<notification xmlns=\"%s\"><eventTime>%s</eventTime>%s</notification>",
|
||||||
NOTIFICATION_RFC5277_NAMESPACE, timestr, str);
|
NOTIFICATION_RFC5277_NAMESPACE, timestr, str);
|
||||||
if (xml_parse_string(cbuf_get(cb), yspec, &xev) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, &xev, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xev, 0, &xev) < 0)
|
if (xml_rootchild(xev, 0, &xev) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -649,7 +649,7 @@ stream_notify_xml(clicon_handle h,
|
||||||
cprintf(cb, "<notification xmlns=\"%s\"><eventTime>%s</eventTime>NULL</notification>",
|
cprintf(cb, "<notification xmlns=\"%s\"><eventTime>%s</eventTime>NULL</notification>",
|
||||||
NOTIFICATION_RFC5277_NAMESPACE,
|
NOTIFICATION_RFC5277_NAMESPACE,
|
||||||
timestr); /* XXX str is always NULL */
|
timestr); /* XXX str is always NULL */
|
||||||
if (xml_parse_string(cbuf_get(cb), yspec, &xev) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, yspec, &xev, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xev, 0, &xev) < 0)
|
if (xml_rootchild(xev, 0, &xev) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -1416,7 +1416,7 @@ xml_rm_children(cxobj *xp,
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
* if (xml_parse_string("<a>2</a>", NULL, &xt) < 0)
|
* if (clixon_xml_parse_string("<a>2</a>", YB_NONE, NULL, &xt, NULL) < 0)
|
||||||
* err;
|
* err;
|
||||||
* # Here xt will be: <top><a>2</a></top>
|
* # Here xt will be: <top><a>2</a></top>
|
||||||
* if (xml_rootchild(xt, 0, &xt) < 0)
|
* if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
|
|
|
||||||
|
|
@ -447,7 +447,7 @@ clixon_xml_changelog_init(clicon_handle h)
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", filename);
|
clicon_err(OE_UNIX, errno, "open(%s)", filename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_parse_file(fd, yspec, &xt) < 0)
|
if (clixon_xml_parse_file(fd, YB_MODULE, yspec, NULL, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -372,18 +372,17 @@ xmltree2cbuf(cbuf *cb,
|
||||||
* @retval 1 Parse OK and all yang assignment made
|
* @retval 1 Parse OK and all yang assignment made
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial) and xerr set
|
* @retval 0 Parse OK but yang assigment not made (or only partial) and xerr set
|
||||||
* @retval -1 Error with clicon_err called. Includes parse error
|
* @retval -1 Error with clicon_err called. Includes parse error
|
||||||
* @see xml_parse_file
|
* @see clixon_xml_parse_file
|
||||||
* @see xml_parse_string
|
* @see clixon_xml_parse_string
|
||||||
* @see xml_parse_va
|
|
||||||
* @see _json_parse
|
* @see _json_parse
|
||||||
* @note special case is empty XML where the parser is not invoked.
|
* @note special case is empty XML where the parser is not invoked.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
_xml_parse(const char *str,
|
_xml_parse(const char *str,
|
||||||
enum yang_bind yb,
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj *xt,
|
cxobj *xt,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
clixon_xml_yacc xy = {0,};
|
clixon_xml_yacc xy = {0,};
|
||||||
|
|
@ -423,21 +422,19 @@ _xml_parse(const char *str,
|
||||||
/* Populate, ie associate xml nodes with yang specs
|
/* Populate, ie associate xml nodes with yang specs
|
||||||
*/
|
*/
|
||||||
switch (yb){
|
switch (yb){
|
||||||
case YB_RPC:
|
|
||||||
case YB_UNKNOWN:
|
|
||||||
case YB_NONE:
|
case YB_NONE:
|
||||||
break;
|
break;
|
||||||
case YB_PARENT:
|
case YB_PARENT:
|
||||||
/* xt:n Has spec
|
/* xt:n Has spec
|
||||||
* x: <a> <-- populate from parent
|
* x: <a> <-- populate from parent
|
||||||
*/
|
*/
|
||||||
if ((ret = xml_bind_yang0_parent(x, xerr)) < 0)
|
if ((ret = xml_bind_yang0(x, YB_PARENT, NULL, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
failed++;
|
failed++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YB_TOP:
|
case YB_MODULE:
|
||||||
/* xt:<top> nospec
|
/* xt:<top> nospec
|
||||||
* x: <a> <-- populate from modules
|
* x: <a> <-- populate from modules
|
||||||
*/
|
*/
|
||||||
|
|
@ -448,22 +445,25 @@ _xml_parse(const char *str,
|
||||||
* x: <config>
|
* x: <config>
|
||||||
* <a> <-- populate from modules
|
* <a> <-- populate from modules
|
||||||
*/
|
*/
|
||||||
if ((ret = xml_bind_yang(x, yspec, xerr)) < 0)
|
if ((ret = xml_bind_yang(x, YB_MODULE, yspec, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if ((ret = xml_bind_yang0(x, yspec, xerr)) < 0)
|
if ((ret = xml_bind_yang0(x, YB_MODULE, yspec, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
failed++;
|
failed++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (failed)
|
||||||
|
goto fail;
|
||||||
|
/* This fails if xt is not bound to yang */
|
||||||
/* Sort the complete tree after parsing. Sorting is less meaningful if Yang not bound */
|
/* Sort the complete tree after parsing. Sorting is less meaningful if Yang not bound */
|
||||||
if (xml_apply0(xt, CX_ELMNT, xml_sort, NULL) < 0)
|
if (xml_apply0(xt, CX_ELMNT, xml_sort, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = (failed==0) ? 1 : 0;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
clixon_xml_parsel_exit(&xy);
|
clixon_xml_parsel_exit(&xy);
|
||||||
if (xy.xy_parse_string != NULL)
|
if (xy.xy_parse_string != NULL)
|
||||||
|
|
@ -471,43 +471,9 @@ _xml_parse(const char *str,
|
||||||
if (xy.xy_xvec)
|
if (xy.xy_xvec)
|
||||||
free(xy.xy_xvec);
|
free(xy.xy_xvec);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
fail: /* invalid */
|
||||||
|
retval = 0;
|
||||||
/*! Read an XML definition from file and parse it into a parse-tree.
|
goto done;
|
||||||
*
|
|
||||||
* @param[in] fd A file descriptor containing the XML file (as ASCII characters)
|
|
||||||
* @param[in] yspec Yang specification, or NULL
|
|
||||||
* @param[in,out] xt Pointer to XML parse tree. If empty, create.
|
|
||||||
* @retval 1 Parse OK and all yang assignment made
|
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial)
|
|
||||||
* @retval -1 Error with clicon_err called. Includes parse error *
|
|
||||||
* @code
|
|
||||||
* cxobj *xt = NULL;
|
|
||||||
* int fd;
|
|
||||||
* fd = open(filename, O_RDONLY);
|
|
||||||
* xml_parse_file(fd, yspec, &xt);
|
|
||||||
* xml_free(xt);
|
|
||||||
* @endcode
|
|
||||||
* @see xml_parse_string
|
|
||||||
* @see xml_parse_va
|
|
||||||
* @note, If xt empty, a top-level symbol will be added so that <tree../> will be: <top><tree.../></tree></top>
|
|
||||||
* @note May block on file I/O
|
|
||||||
* @see xml_parse_file2 for a more advanced API
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_parse_file(int fd,
|
|
||||||
yang_stmt *yspec,
|
|
||||||
cxobj **xt)
|
|
||||||
{
|
|
||||||
enum yang_bind yb = YB_PARENT;
|
|
||||||
|
|
||||||
if (xt==NULL){
|
|
||||||
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*xt==NULL)
|
|
||||||
yb = YB_TOP;
|
|
||||||
return xml_parse_file2(fd, yb, yspec, NULL, xt, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! FSM to detect substring
|
/*! FSM to detect substring
|
||||||
|
|
@ -539,22 +505,22 @@ FSM(char *tag,
|
||||||
* cxobj *xerr = NULL;
|
* cxobj *xerr = NULL;
|
||||||
* int fd;
|
* int fd;
|
||||||
* fd = open(filename, O_RDONLY);
|
* fd = open(filename, O_RDONLY);
|
||||||
* if ((ret = xml_parse_file2(fd, YB_TOP, yspec, "</config>", &xt, &xerr)) < 0)
|
* if ((ret = clixon_xml_parse_file(fd, YB_MODULE, yspec, "</config>", &xt, &xerr)) < 0)
|
||||||
* err;
|
* err;
|
||||||
* xml_free(xt);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xml_parse_string
|
* @see clixon_xml_parse_string
|
||||||
* @see xml_parse_file
|
* @see clixon_json_parse_file
|
||||||
* @note, If xt empty, a top-level symbol will be added so that <tree../> will be: <top><tree.../></tree></top>
|
* @note, If xt empty, a top-level symbol will be added so that <tree../> will be: <top><tree.../></tree></top>
|
||||||
* @note May block on file I/O
|
* @note May block on file I/O
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_parse_file2(int fd,
|
clixon_xml_parse_file(int fd,
|
||||||
enum yang_bind yb,
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
char *endtag,
|
char *endtag,
|
||||||
cxobj **xt,
|
cxobj **xt,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -568,6 +534,14 @@ xml_parse_file2(int fd,
|
||||||
int oldxmlbuflen;
|
int oldxmlbuflen;
|
||||||
int failed = 0;
|
int failed = 0;
|
||||||
|
|
||||||
|
if (xt==NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (yb == YB_MODULE && yspec == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "yspec is required if yb == YB_MODULE");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (endtag != NULL)
|
if (endtag != NULL)
|
||||||
endtaglen = strlen(endtag);
|
endtaglen = strlen(endtag);
|
||||||
if ((xmlbuf = malloc(xmlbuflen)) == NULL){
|
if ((xmlbuf = malloc(xmlbuflen)) == NULL){
|
||||||
|
|
@ -635,27 +609,31 @@ xml_parse_file2(int fd,
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
* cxobj *xerr = NULL;
|
* cxobj *xerr = NULL;
|
||||||
* if (xml_parse_string2(str, YB_TOP, yspec, &xt, &xerr) < 0)
|
* if (clixon_xml_parse_string(str, YB_MODULE, yspec, &xt, &xerr) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if (xml_rootchild(xt, 0, &xt) < 0) # If you want to remove TOP
|
* if (xml_rootchild(xt, 0, &xt) < 0) # If you want to remove TOP
|
||||||
* err;
|
* err;
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xml_parse_file
|
* @see clixon_xml_parse_file
|
||||||
* @see xml_parse_va
|
* @see clixon_xml_parse_va
|
||||||
* @note You need to free the xml parse tree after use, using xml_free()
|
* @note You need to free the xml parse tree after use, using xml_free()
|
||||||
* @note If empty on entry, a new TOP xml will be created named "top"
|
* @note If empty on entry, a new TOP xml will be created named "top"
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_parse_string2(const char *str,
|
clixon_xml_parse_string(const char *str,
|
||||||
enum yang_bind yb,
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj **xt,
|
cxobj **xt,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
if (xt==NULL){
|
if (xt==NULL){
|
||||||
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (yb == YB_MODULE && yspec == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "yspec is required if yb == YB_MODULE");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (*xt == NULL){
|
if (*xt == NULL){
|
||||||
if ((*xt = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
if ((*xt = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -663,57 +641,15 @@ xml_parse_string2(const char *str,
|
||||||
return _xml_parse(str, yb, yspec, *xt, xerr);
|
return _xml_parse(str, yb, yspec, *xt, xerr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Read an XML definition from string and parse it into a parse-tree
|
|
||||||
*
|
|
||||||
* @param[in] str String containing XML definition.
|
|
||||||
* @param[in] yspec Yang specification, or NULL
|
|
||||||
* @param[in,out] xt Pointer to XML parse tree. If empty will be created.
|
|
||||||
* @retval 1 Parse OK and all yang assignment made
|
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial)
|
|
||||||
* @retval -1 Error with clicon_err called. Includes parse error
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* cxobj *xt = NULL;
|
|
||||||
* if (xml_parse_string(str, yspec, &xt) < 0)
|
|
||||||
* err;
|
|
||||||
* if (xml_rootchild(xt, 0, &xt) < 0) # If you want to remove TOP
|
|
||||||
* err;
|
|
||||||
* @endcode
|
|
||||||
* @see xml_parse_file
|
|
||||||
* @see xml_parse_va
|
|
||||||
* @note You need to free the xml parse tree after use, using xml_free()
|
|
||||||
* @note If xt is empty on entry, a new TOP xml will be created named "top" and yang binding
|
|
||||||
* assumed to be TOP
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_parse_string(const char *str,
|
|
||||||
yang_stmt *yspec,
|
|
||||||
cxobj **xt)
|
|
||||||
{
|
|
||||||
enum yang_bind yb = YB_PARENT;
|
|
||||||
|
|
||||||
if (xt==NULL){
|
|
||||||
clicon_err(OE_XML, EINVAL, "xt is NULL");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*xt == NULL){
|
|
||||||
yb = YB_TOP; /* ad-hoc #1 */
|
|
||||||
if ((*xt = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (xml_spec(*xt) == NULL)
|
|
||||||
yb = YB_TOP; /* ad-hoc #2 */
|
|
||||||
}
|
|
||||||
return _xml_parse(str, yb, yspec, *xt, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Read XML from var-arg list and parse it into xml tree
|
/*! Read XML from var-arg list and parse it into xml tree
|
||||||
*
|
*
|
||||||
* Utility function using stdarg instead of static string.
|
* Utility function using stdarg instead of static string.
|
||||||
* @param[in,out] xtop Top of XML parse tree. If it is NULL, top element
|
|
||||||
called 'top' will be created. Call xml_free() after use
|
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] yspec Yang specification, or NULL
|
* @param[in] yspec Yang specification, or NULL
|
||||||
|
* @param[in,out] xtop Top of XML parse tree. If it is NULL, top element
|
||||||
|
* called 'top' will be created. Call xml_free() after use
|
||||||
|
* @param[out] xerr Reason for failure (yang assignment not made)
|
||||||
* @param[in] format Format string for stdarg according to printf(3)
|
* @param[in] format Format string for stdarg according to printf(3)
|
||||||
* @retval 1 Parse OK and all yang assignment made
|
* @retval 1 Parse OK and all yang assignment made
|
||||||
* @retval 0 Parse OK but yang assigment not made (or only partial)
|
* @retval 0 Parse OK but yang assigment not made (or only partial)
|
||||||
|
|
@ -721,18 +657,20 @@ xml_parse_string(const char *str,
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
* if (xml_parse_va(&xt, NULL, "<xml>%d</xml>", 22) < 0)
|
* if (clixon_xml_parse_va(YB_NONE, NULL, &xt, NULL, "<xml>%d</xml>", 22) < 0)
|
||||||
* err;
|
* err;
|
||||||
* xml_free(xt);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xml_parse_string
|
* @see clixon_xml_parse_string
|
||||||
* @see xml_parse_file
|
* @see clixon_xml_parse_file
|
||||||
* @note If vararg list is empty, consider using xml_parse_string()
|
* @note If vararg list is empty, consider using clixon_xml_parse_string()
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_parse_va(cxobj **xtop,
|
clixon_xml_parse_va(yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
const char *format, ...)
|
cxobj **xtop,
|
||||||
|
cxobj **xerr,
|
||||||
|
const char *format, ...)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -750,104 +688,10 @@ xml_parse_va(cxobj **xtop,
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
len = vsnprintf(str, len, format, args) + 1;
|
len = vsnprintf(str, len, format, args) + 1;
|
||||||
va_end(args);
|
va_end(args);
|
||||||
retval = xml_parse_string(str, yspec, xtop); /* xml_parse_string2 */
|
retval = clixon_xml_parse_string(str, yb, yspec, xtop, xerr);
|
||||||
done:
|
done:
|
||||||
if (str)
|
if (str)
|
||||||
free(str);
|
free(str);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOTUSED
|
|
||||||
/*! Generic parse function for xml values
|
|
||||||
* @param[in] xb xml tree body node, ie containing a value to be parsed
|
|
||||||
* @param[in] type Type of value to be parsed in value
|
|
||||||
* @param[out] cvp CLIgen variable containing the parsed value
|
|
||||||
* @note free cv with cv_free after use.
|
|
||||||
* @see xml_body_int32 etc, for type-specific parse functions
|
|
||||||
* @note range check failure returns 0
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xml_body_parse(cxobj *xb,
|
|
||||||
enum cv_type type,
|
|
||||||
cg_var **cvp)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cg_var *cv = NULL;
|
|
||||||
int cvret;
|
|
||||||
char *bstr;
|
|
||||||
char *reason = NULL;
|
|
||||||
|
|
||||||
if ((bstr = xml_body(xb)) == NULL){
|
|
||||||
clicon_err(OE_XML, 0, "No body found");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((cv = cv_new(type)) == NULL){
|
|
||||||
clicon_err(OE_XML, errno, "cv_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((cvret = cv_parse1(bstr, cv, &reason)) < 0){
|
|
||||||
clicon_err(OE_XML, errno, "cv_parse");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cvret == 0){ /* parsing failed */
|
|
||||||
clicon_err(OE_XML, errno, "Parsing CV: %s", reason);
|
|
||||||
if (reason)
|
|
||||||
free(reason);
|
|
||||||
}
|
|
||||||
*cvp = cv;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (retval < 0 && cv != NULL)
|
|
||||||
cv_free(cv);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Parse an xml body as int32
|
|
||||||
* The real parsing functions are in the cligen code
|
|
||||||
* @param[in] xb xml tree body node, ie containing a value to be parsed
|
|
||||||
* @param[out] val Value after parsing
|
|
||||||
* @retval 0 OK, parsed value in 'val'
|
|
||||||
* @retval -1 Error, one of: body not found, parse error,
|
|
||||||
* alloc error.
|
|
||||||
* @note extend to all other cligen var types and generalize
|
|
||||||
* @note use yang type info?
|
|
||||||
* @note range check failure returns 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_body_int32(cxobj *xb,
|
|
||||||
int32_t *val)
|
|
||||||
{
|
|
||||||
cg_var *cv = NULL;
|
|
||||||
|
|
||||||
if (xml_body_parse(xb, CGV_INT32, &cv) < 0)
|
|
||||||
return -1;
|
|
||||||
*val = cv_int32_get(cv);
|
|
||||||
cv_free(cv);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Parse an xml body as uint32
|
|
||||||
* The real parsing functions are in the cligen code
|
|
||||||
* @param[in] xb xml tree body node, ie containing a value to be parsed
|
|
||||||
* @param[out] val Value after parsing
|
|
||||||
* @retval 0 OK, parsed value in 'val'
|
|
||||||
* @retval -1 Error, one of: body not found, parse error,
|
|
||||||
* alloc error.
|
|
||||||
* @note extend to all other cligen var types and generalize
|
|
||||||
* @note use yang type info?
|
|
||||||
* @note range check failure returns 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_body_uint32(cxobj *xb,
|
|
||||||
uint32_t *val)
|
|
||||||
{
|
|
||||||
cg_var *cv = NULL;
|
|
||||||
|
|
||||||
if (xml_body_parse(xb, CGV_UINT32, &cv) < 0)
|
|
||||||
return -1;
|
|
||||||
*val = cv_uint32_get(cv);
|
|
||||||
cv_free(cv);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* NOTUSED */
|
|
||||||
|
|
|
||||||
|
|
@ -1201,18 +1201,17 @@ strip_whitespace(cxobj *xt)
|
||||||
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
|
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @code
|
* @code
|
||||||
* if (xml_bind_yang(x, yspec, NULL) < 0)
|
* if (xml_bind_yang(x, YB_MODULE, yspec, NULL) < 0)
|
||||||
* err;
|
* err;
|
||||||
* @endcode
|
* @endcode
|
||||||
* @note For subs to anyxml nodes will not have spec set
|
* @note For subs to anyxml nodes will not have spec set
|
||||||
* There are several functions in the API family
|
* There are several functions in the API family
|
||||||
* @see xml_bind_yang_rpc for incoming rpc
|
* @see xml_bind_yang_rpc for incoming rpc
|
||||||
* @see xml_bind_yang_parent Not top-level and parent is properly yang populated
|
|
||||||
* @see xml_bind_yang0 If the calling xml object should also be populated
|
* @see xml_bind_yang0 If the calling xml object should also be populated
|
||||||
* @see xml_bind_yang0_parent
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_bind_yang(cxobj *xt,
|
xml_bind_yang(cxobj *xt,
|
||||||
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
|
|
@ -1224,33 +1223,7 @@ xml_bind_yang(cxobj *xt,
|
||||||
strip_whitespace(xt);
|
strip_whitespace(xt);
|
||||||
xc = NULL; /* Apply on children */
|
xc = NULL; /* Apply on children */
|
||||||
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
|
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
|
||||||
if ((ret = xml_bind_yang0(xc, yspec, xerr)) < 0)
|
if ((ret = xml_bind_yang0(xc, yb, yspec, xerr)) < 0)
|
||||||
goto done;
|
|
||||||
if (ret == 0)
|
|
||||||
failed++;
|
|
||||||
}
|
|
||||||
retval = (failed==0) ? 1 : 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Find yang spec association of tree of XML nodes
|
|
||||||
*
|
|
||||||
* Populate xt:s children outgoing from that xt is populated
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_bind_yang_parent(cxobj *xt,
|
|
||||||
cxobj **xerr)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cxobj *xc; /* xml child */
|
|
||||||
int ret;
|
|
||||||
int failed = 0; /* we continue loop after failure, should we stop at fail?`*/
|
|
||||||
|
|
||||||
strip_whitespace(xt);
|
|
||||||
xc = NULL; /* Apply on children */
|
|
||||||
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
|
|
||||||
if ((ret = xml_bind_yang0_parent(xc, xerr)) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
failed++;
|
failed++;
|
||||||
|
|
@ -1263,15 +1236,22 @@ xml_bind_yang_parent(cxobj *xt,
|
||||||
fail:
|
fail:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Find yang spec association of tree of XML nodes
|
/*! Find yang spec association of tree of XML nodes
|
||||||
*
|
*
|
||||||
|
* @param[in] xt XML tree node
|
||||||
|
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[out] xerr Reason for failure, or NULL
|
||||||
|
* @retval 1 OK yang assignment made
|
||||||
|
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
|
||||||
|
* @retval -1 Error
|
||||||
* Populate xt as top-level node
|
* Populate xt as top-level node
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_bind_yang0(cxobj *xt,
|
xml_bind_yang0(cxobj *xt,
|
||||||
|
yang_bind yb,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
|
|
@ -1280,49 +1260,26 @@ xml_bind_yang0(cxobj *xt,
|
||||||
int ret;
|
int ret;
|
||||||
int failed = 0; /* we continue loop after failure, should we stop at fail?`*/
|
int failed = 0; /* we continue loop after failure, should we stop at fail?`*/
|
||||||
|
|
||||||
if ((ret = populate_self_top(xt, yspec, xerr)) < 0)
|
switch (yb){
|
||||||
goto done;
|
case YB_MODULE:
|
||||||
if (ret == 0)
|
if ((ret = populate_self_top(xt, yspec, xerr)) < 0)
|
||||||
goto fail;
|
|
||||||
strip_whitespace(xt);
|
|
||||||
xc = NULL; /* Apply on children */
|
|
||||||
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
|
|
||||||
if ((ret = xml_bind_yang0_parent(xc, xerr)) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
break;
|
||||||
failed++;
|
case YB_PARENT:
|
||||||
}
|
if ((ret = populate_self_parent(xt, xerr)) < 0)
|
||||||
if (failed)
|
goto done;
|
||||||
goto fail;
|
break;
|
||||||
retval = 1;
|
default:
|
||||||
done:
|
clicon_err(OE_XML, EINVAL, "Invalid yang binding: %d", yb);
|
||||||
return retval;
|
|
||||||
fail:
|
|
||||||
retval = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Find yang spec association of tree of XML nodes
|
|
||||||
*
|
|
||||||
* Populate xt as if xt:s parent is populated
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_bind_yang0_parent(cxobj *xt,
|
|
||||||
cxobj **xerr)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cxobj *xc; /* xml child */
|
|
||||||
int ret;
|
|
||||||
int failed = 0; /* we continue loop after failure, should we stop at fail?`*/
|
|
||||||
|
|
||||||
if ((ret = populate_self_parent(xt, xerr)) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
strip_whitespace(xt);
|
strip_whitespace(xt);
|
||||||
xc = NULL; /* Apply on children */
|
xc = NULL; /* Apply on children */
|
||||||
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
|
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
|
||||||
if ((ret = xml_bind_yang0_parent(xc, xerr)) < 0)
|
if ((ret = xml_bind_yang0(xc, YB_PARENT, yspec, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
failed++;
|
failed++;
|
||||||
|
|
@ -1356,8 +1313,8 @@ xml_bind_yang0_parent(cxobj *xt,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_bind_yang_rpc(cxobj *xrpc,
|
xml_bind_yang_rpc(cxobj *xrpc,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yrpc = NULL; /* yang node */
|
yang_stmt *yrpc = NULL; /* yang node */
|
||||||
|
|
@ -1385,7 +1342,7 @@ xml_bind_yang_rpc(cxobj *xrpc,
|
||||||
* recursive population to work. Therefore, assign input yang
|
* recursive population to work. Therefore, assign input yang
|
||||||
* to rpc level although not 100% intuitive */
|
* to rpc level although not 100% intuitive */
|
||||||
xml_spec_set(x, yi);
|
xml_spec_set(x, yi);
|
||||||
if ((ret = xml_bind_yang_parent(x, xerr)) < 0)
|
if ((ret = xml_bind_yang(x, YB_PARENT, NULL, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -1452,7 +1409,7 @@ xml_bind_yang_rpc_reply(cxobj *xrpc,
|
||||||
}
|
}
|
||||||
if (yo != NULL){
|
if (yo != NULL){
|
||||||
xml_spec_set(xrpc, yo);
|
xml_spec_set(xrpc, yo);
|
||||||
if ((ret = xml_bind_yang(xrpc, yspec, xerr)) < 0)
|
if ((ret = xml_bind_yang(xrpc, YB_MODULE, yspec, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,10 @@ xml_cv_cache(cxobj *x,
|
||||||
body="";
|
body="";
|
||||||
if ((cv = xml_cv(x)) != NULL)
|
if ((cv = xml_cv(x)) != NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
if ((y = xml_spec(x)) == NULL)
|
if ((y = xml_spec(x)) == NULL){
|
||||||
goto ok;
|
clicon_err(OE_XML, EFAULT, "Yang binding missing for xml symbol %s, body:%s", xml_name(x), body);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (yang_type_get(y, NULL, &yrestype, &options, NULL, NULL, NULL, &fraction) < 0)
|
if (yang_type_get(y, NULL, &yrestype, &options, NULL, NULL, NULL, &fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
yang2cv_type(yang_argument_get(yrestype), &cvtype);
|
yang2cv_type(yang_argument_get(yrestype), &cvtype);
|
||||||
|
|
@ -195,8 +197,8 @@ xml_cmp(cxobj *x1,
|
||||||
char *b1;
|
char *b1;
|
||||||
char *b2;
|
char *b2;
|
||||||
char *keyname;
|
char *keyname;
|
||||||
cg_var *cv1;
|
cg_var *cv1 = NULL;
|
||||||
cg_var *cv2;
|
cg_var *cv2 = NULL;
|
||||||
int nr1 = 0;
|
int nr1 = 0;
|
||||||
int nr2 = 0;
|
int nr2 = 0;
|
||||||
cxobj *x1b;
|
cxobj *x1b;
|
||||||
|
|
@ -1324,7 +1326,7 @@ xml_find_index_yang(cxobj *xp,
|
||||||
if (revert)
|
if (revert)
|
||||||
goto revert;
|
goto revert;
|
||||||
#endif
|
#endif
|
||||||
if (xml_parse_string(cbuf_get(cb), yc, &xc) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, &xc, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xc, 0, &xc) < 0)
|
if (xml_rootchild(xc, 0, &xc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,7 @@ yang_modules_state_get(clicon_handle h,
|
||||||
/* Parse cb, x is on the form: <top><modules-state>...
|
/* Parse cb, x is on the form: <top><modules-state>...
|
||||||
* Note, list is not sorted since it is state (should not be)
|
* Note, list is not sorted since it is state (should not be)
|
||||||
*/
|
*/
|
||||||
if (xml_parse_string(cbuf_get(cb), yspec, &x) < 0){
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, &x, NULL) < 0){
|
||||||
if (netconf_operation_failed_xml(xret, "protocol", clicon_err_reason)< 0)
|
if (netconf_operation_failed_xml(xret, "protocol", clicon_err_reason)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ new "cli configure using encoded chars name <&"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface fddi&< type ianaift:ethernetCsmacd" 0 ""
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface fddi&< type ianaift:ethernetCsmacd" 0 ""
|
||||||
|
|
||||||
new "cli failed validate"
|
new "cli failed validate"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o validate" 255 "Netconf error: application missing-element Mandatory variable <bad-element>type</bad-element>. Validate failed. Edit and try again or discard changes"
|
expectpart "$($clixon_cli -1 -f $cfg -l o validate)" 255 "Netconf error: Validate failed. Edit and try again or discard changes: application missing-element Mandatory variable <bad-element>type</bad-element>"
|
||||||
|
|
||||||
new "cli configure ip addr"
|
new "cli configure ip addr"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 ipv4 address 1.2.3.4 prefix-length 24" 0 "^$"
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 ipv4 address 1.2.3.4 prefix-length 24" 0 "^$"
|
||||||
|
|
|
||||||
|
|
@ -253,14 +253,14 @@ new "CLI set wrong acl-type"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o set acls acl x type undefined" 0 "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o set acls acl x type undefined" 0 "^$"
|
||||||
|
|
||||||
new "cli validate acl-type"
|
new "cli validate acl-type"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o validate" 255 "Netconf error: application operation-failed Identityref validation failed, undefined not derived from acl-base . Validate failed. Edit and try again or discard changes"
|
expectpart "$($clixon_cli -1 -f $cfg -l o validate)" 255 " Netconf error: Validate failed. Edit and try again or discard changes: application operation-failed Identityref validation failed, undefined not derived from acl-base"
|
||||||
|
|
||||||
# test empty identityref list
|
# test empty identityref list
|
||||||
new "cli set empty"
|
new "cli set empty"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o set e undefined" 0 "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o set e undefined" 0 "^$"
|
||||||
|
|
||||||
new "cli validate empty"
|
new "cli validate empty"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o validate" 255 "Netconf error: application operation-failed Identityref validation failed, undefined not derived from acl-base . Validate failed. Edit and try again or discard changes"
|
expectpart "$($clixon_cli -1 -f $cfg -l o validate)" 255 "Netconf error: Validate failed. Edit and try again or discard changes: application operation-failed Identityref validation failed, undefined not derived from acl-base"
|
||||||
|
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ cat <<EOF > $cfg
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
|
||||||
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||||
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
|
||||||
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
<CLICON_NACM_CREDENTIALS>none</CLICON_NACM_CREDENTIALS>
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ new "create list permit"
|
||||||
expectpart "$(curl -u andy:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/clixon-example:translate/translate=key42 -d '{"clixon-example:translate": [{"k":"key42","value":"val42"}]}')" 0 'HTTP/1.1 201 Created'
|
expectpart "$(curl -u andy:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/clixon-example:translate/translate=key42 -d '{"clixon-example:translate": [{"k":"key42","value":"val42"}]}')" 0 'HTTP/1.1 201 Created'
|
||||||
|
|
||||||
new "default update list deny"
|
new "default update list deny"
|
||||||
expectpart "$(curl -u wilma:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/clixon-example:translate=key42 -d '{"clixon-example:translate": [{"k":"key42","value":"val99"}]}')" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}'
|
expectpart "$(curl -u wilma:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/clixon-example:translate/translate=key42 -d '{"clixon-example:translate": [{"k":"key42","value":"val99"}]}')" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}'
|
||||||
|
|
||||||
new "default delete list deny"
|
new "default delete list deny"
|
||||||
expectpart "$(curl -u wilma:bar -siS -X DELETE http://localhost/restconf/data/clixon-example:translate=key42)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}'
|
expectpart "$(curl -u wilma:bar -siS -X DELETE http://localhost/restconf/data/clixon-example:translate=key42)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}'
|
||||||
|
|
|
||||||
|
|
@ -110,9 +110,12 @@ expectpart "$(curl -is -X OPTIONS http://localhost/restconf/data)" 0 "HTTP/1.1 2
|
||||||
new "restconf HEAD. RFC 8040 4.2"
|
new "restconf HEAD. RFC 8040 4.2"
|
||||||
expectpart "$(curl -si -I -H "Accept: application/yang-data+json" http://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+json"
|
expectpart "$(curl -si -I -H "Accept: application/yang-data+json" http://localhost/restconf/data)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+json"
|
||||||
|
|
||||||
new "restconf empty rpc"
|
new "restconf empty rpc JSON"
|
||||||
expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+json" -d {\"clixon-example:input\":null} http://localhost/restconf/operations/clixon-example:empty)" 0 "HTTP/1.1 204 No Content"
|
expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+json" -d {\"clixon-example:input\":null} http://localhost/restconf/operations/clixon-example:empty)" 0 "HTTP/1.1 204 No Content"
|
||||||
|
|
||||||
|
new "restconf empty rpc XML"
|
||||||
|
expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+xml" -d '<input xmlns="urn:example:clixon"></input>' http://localhost/restconf/operations/clixon-example:empty)" 0 "HTTP/1.1 204 No Content"
|
||||||
|
|
||||||
new "restconf empty rpc, default media type should fail"
|
new "restconf empty rpc, default media type should fail"
|
||||||
expectpart "$(curl -si -X POST -d {\"clixon-example:input\":null} http://localhost/restconf/operations/clixon-example:empty)" 0 'HTTP/1.1 415 Unsupported Media Type'
|
expectpart "$(curl -si -X POST -d {\"clixon-example:input\":null} http://localhost/restconf/operations/clixon-example:empty)" 0 'HTTP/1.1 415 Unsupported Media Type'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -332,9 +332,9 @@ runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1><b xmlns="
|
||||||
new "5. Load non-compat invalid startup. Enter failsafe, startup invalid."
|
new "5. Load non-compat invalid startup. Enter failsafe, startup invalid."
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
(cd $dir; cp non-compat-invalid.xml startup_db)
|
(cd $dir; cp non-compat-invalid.xml startup_db)
|
||||||
#runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>' # sorted
|
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>' # sorted
|
||||||
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><c xmlns="urn:example:c">bla bla</c><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b></data>' # unsorted
|
#runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><c xmlns="urn:example:c">bla bla</c><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b></data>' # unsorted
|
||||||
|
exit
|
||||||
new "6. Load non-compat invalid running. Enter failsafe, startup invalid."
|
new "6. Load non-compat invalid running. Enter failsafe, startup invalid."
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
(cd $dir; cp non-compat-invalid.xml running_db)
|
(cd $dir; cp non-compat-invalid.xml running_db)
|
||||||
|
|
@ -346,8 +346,8 @@ runtest true running '<data><a1 xmlns="urn:example:a">always work</a1></data>' '
|
||||||
new "7. Load compatible invalid startup."
|
new "7. Load compatible invalid startup."
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
(cd $dir; cp compat-invalid.xml startup_db)
|
(cd $dir; cp compat-invalid.xml startup_db)
|
||||||
#runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>' # sorted
|
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>' # sorted
|
||||||
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><c xmlns="urn:example:c">bla bla</c><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b></data>' # unsorted
|
#runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><c xmlns="urn:example:c">bla bla</c><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b></data>' # unsorted
|
||||||
|
|
||||||
# This testcase contains an error/exception of the clixon xml parser, and
|
# This testcase contains an error/exception of the clixon xml parser, and
|
||||||
# I cant track down the memory leakage.
|
# I cant track down the memory leakage.
|
||||||
|
|
|
||||||
|
|
@ -254,12 +254,12 @@ main(int argc, char **argv)
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", xmlfilename);
|
clicon_err(OE_UNIX, errno, "open(%s)", xmlfilename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_parse_file(fd, yspec, &xt) < 0)
|
if (clixon_xml_parse_file(fd, YB_MODULE, yspec, NULL, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (xml_parse_string(argv[2], yspec, &xt) < 0)
|
if (clixon_xml_parse_string(argv[2], YB_MODULE, yspec, &xt, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
* On success, nothing is printed and exitcode 0
|
* On success, nothing is printed and exitcode 0
|
||||||
* On failure, an error is printed on stderr and exitcode != 0
|
* On failure, an error is printed on stderr and exitcode != 0
|
||||||
* Failure error prints are different, it would be nice to make them more
|
* Failure error prints are different, it would be nice to make them more
|
||||||
* uniform. (see clicon_rpc_generate_error)
|
* uniform. (see clixon_netconf_error)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
|
|
||||||
|
|
@ -140,19 +140,14 @@ main(int argc, char **argv)
|
||||||
clicon_debug(1, "xpath:%s", xpath);
|
clicon_debug(1, "xpath:%s", xpath);
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
#if 1
|
|
||||||
if (yang_spec_parse_file(h, filename, yspec) < 0)
|
if (yang_spec_parse_file(h, filename, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
#else
|
|
||||||
if (yang_parse_file(fd, "yang test", yspec) == NULL)
|
|
||||||
goto done;
|
|
||||||
#endif
|
|
||||||
/* Parse base XML */
|
/* Parse base XML */
|
||||||
if (xml_parse_string(x0str, yspec, &x0) < 0){
|
if (clixon_xml_parse_string(x0str, YB_MODULE, yspec, &x0, NULL) < 0){
|
||||||
clicon_err(OE_XML, 0, "Parsing base xml: %s", x0str);
|
clicon_err(OE_XML, 0, "Parsing base xml: %s", x0str);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_bind_yang(x0, yspec, NULL) < 0)
|
if (xml_bind_yang(x0, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xb = xpath_first(x0, NULL, "%s", xpath)) == NULL){
|
if ((xb = xpath_first(x0, NULL, "%s", xpath)) == NULL){
|
||||||
clicon_err(OE_XML, 0, "xpath: %s not found in x0", xpath);
|
clicon_err(OE_XML, 0, "xpath: %s not found in x0", xpath);
|
||||||
|
|
@ -163,11 +158,11 @@ main(int argc, char **argv)
|
||||||
xml_print(stderr, xb);
|
xml_print(stderr, xb);
|
||||||
}
|
}
|
||||||
/* Parse insert XML */
|
/* Parse insert XML */
|
||||||
if (xml_parse_string(xistr, yspec, &xi) < 0){
|
if (clixon_xml_parse_string(xistr, YB_MODULE, yspec, &xi, NULL) < 0){
|
||||||
clicon_err(OE_XML, 0, "Parsing insert xml: %s", xistr);
|
clicon_err(OE_XML, 0, "Parsing insert xml: %s", xistr);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_bind_yang(xi, yspec, NULL) < 0)
|
if (xml_bind_yang(xi, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xi = xpath_first(xi, NULL, "%s", xpath)) == NULL){
|
if ((xi = xpath_first(xi, NULL, "%s", xpath)) == NULL){
|
||||||
clicon_err(OE_XML, 0, "xpath: %s not found in xi", xpath);
|
clicon_err(OE_XML, 0, "xpath: %s not found in xi", xpath);
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ main(int argc,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ret = json_parse_file(0, yspec, &xt, &xerr)) < 0)
|
if ((ret = clixon_json_parse_file(0, yspec?YB_MODULE:YB_NONE, yspec, &xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
xml_print(stderr, xerr);
|
xml_print(stderr, xerr);
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ main(int argc,
|
||||||
* If fd=0, then continue reading from stdin (after CR)
|
* If fd=0, then continue reading from stdin (after CR)
|
||||||
* If fd>0, reading from file opened as argv[1]
|
* If fd>0, reading from file opened as argv[1]
|
||||||
*/
|
*/
|
||||||
if (xml_parse_file(fd, NULL, &x) < 0){
|
if (clixon_xml_parse_file(fd, YB_NONE, NULL, NULL, &x, NULL) < 0){
|
||||||
fprintf(stderr, "Error: parsing: %s\n", clicon_err_reason);
|
fprintf(stderr, "Error: parsing: %s\n", clicon_err_reason);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +220,7 @@ main(int argc,
|
||||||
/* Validate XML as well */
|
/* Validate XML as well */
|
||||||
if (yang_file_dir){
|
if (yang_file_dir){
|
||||||
/* Populate */
|
/* Populate */
|
||||||
if (xml_bind_yang(x, yspec, NULL) < 0)
|
if (xml_bind_yang(x, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Add default values */
|
/* Add default values */
|
||||||
if (xml_apply(x, CX_ELMNT, xml_default, h) < 0)
|
if (xml_apply(x, CX_ELMNT, xml_default, h) < 0)
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ main(int argc,
|
||||||
}
|
}
|
||||||
/* 2. Parse data (xml/json) */
|
/* 2. Parse data (xml/json) */
|
||||||
if (jsonin){
|
if (jsonin){
|
||||||
if ((ret = json_parse_file(fd, NULL, &xt, &xerr)) < 0)
|
if ((ret = clixon_json_parse_file(fd, YB_NONE, NULL, &xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
fprintf(stderr, "Invalid JSON\n");
|
fprintf(stderr, "Invalid JSON\n");
|
||||||
|
|
@ -150,7 +150,7 @@ main(int argc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (xml_parse_file(fd, NULL, &xt) < 0){
|
if (clixon_xml_parse_file(fd, YB_NONE, NULL, NULL, &xt, NULL) < 0){
|
||||||
fprintf(stderr, "xml parse error: %s\n", clicon_err_reason);
|
fprintf(stderr, "xml parse error: %s\n", clicon_err_reason);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
* On success, nothing is printed and exitcode 0
|
* On success, nothing is printed and exitcode 0
|
||||||
* On failure, an error is printed on stderr and exitcode != 0
|
* On failure, an error is printed on stderr and exitcode != 0
|
||||||
* Failure error prints are different, it would be nice to make them more
|
* Failure error prints are different, it would be nice to make them more
|
||||||
* uniform. (see clicon_rpc_generate_error)
|
* uniform. (see clixon_netconf_error)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
|
@ -161,7 +161,7 @@ main(int argc,
|
||||||
char *top_path = NULL;
|
char *top_path = NULL;
|
||||||
cxobj *xbot; /* Place in xtop where base cxobj is parsed */
|
cxobj *xbot; /* Place in xtop where base cxobj is parsed */
|
||||||
cvec *nsc = NULL;
|
cvec *nsc = NULL;
|
||||||
enum yang_bind yb;
|
yang_bind yb;
|
||||||
|
|
||||||
/* In the startup, logs to stderr & debug flag set later */
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
|
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
|
||||||
|
|
@ -260,10 +260,14 @@ main(int argc,
|
||||||
clicon_err(OE_YANG, errno, "open(%s)", top_input_filename);
|
clicon_err(OE_YANG, errno, "open(%s)", top_input_filename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_parse_file(tfd, yspec, &xtop) < 0){
|
if ((ret = clixon_xml_parse_file(tfd, YB_MODULE, yspec, NULL, &xtop, &xerr)) < 0){
|
||||||
fprintf(stderr, "xml parse error: %s\n", clicon_err_reason);
|
fprintf(stderr, "xml parse error: %s\n", clicon_err_reason);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clixon_netconf_error(OE_NETCONF, xerr, "Parse top file", NULL);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (validate_tree(h, xtop, yspec) < 0)
|
if (validate_tree(h, xtop, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
|
@ -284,10 +288,10 @@ main(int argc,
|
||||||
}
|
}
|
||||||
/* 2. Parse data (xml/json) */
|
/* 2. Parse data (xml/json) */
|
||||||
if (jsonin){
|
if (jsonin){
|
||||||
if ((ret = json_parse_file(fd, yspec, &xt, &xerr)) < 0)
|
if ((ret = clixon_json_parse_file(fd, top_input_filename?YB_PARENT:YB_MODULE, yspec, &xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
clicon_rpc_generate_error(xerr, "util_xml", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "util_xml", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -295,15 +299,15 @@ main(int argc,
|
||||||
if (!yang_file_dir)
|
if (!yang_file_dir)
|
||||||
yb = YB_NONE;
|
yb = YB_NONE;
|
||||||
else if (xt == NULL)
|
else if (xt == NULL)
|
||||||
yb = YB_TOP;
|
yb = YB_MODULE;
|
||||||
else
|
else
|
||||||
yb = YB_PARENT;
|
yb = YB_PARENT;
|
||||||
if ((ret = xml_parse_file2(fd, yb, yspec, NULL, &xt, &xerr)) < 0){
|
if ((ret = clixon_xml_parse_file(fd, yb, yspec, NULL, &xt, &xerr)) < 0){
|
||||||
fprintf(stderr, "xml parse error: %s\n", clicon_err_reason);
|
fprintf(stderr, "xml parse error: %s\n", clicon_err_reason);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
clicon_rpc_generate_error(xerr, "util_xml", NULL);
|
clixon_netconf_error(OE_NETCONF, xerr, "util_xml", NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ main(int argc,
|
||||||
* If fd=0, then continue reading from stdin (after CR)
|
* If fd=0, then continue reading from stdin (after CR)
|
||||||
* If fd>0, reading from file opened as argv[1]
|
* If fd>0, reading from file opened as argv[1]
|
||||||
*/
|
*/
|
||||||
if (xml_parse_file(fd, NULL, &x0) < 0){
|
if (clixon_xml_parse_file(fd, YB_NONE, NULL, NULL, &x0, NULL) < 0){
|
||||||
fprintf(stderr, "Error: parsing: %s\n", clicon_err_reason);
|
fprintf(stderr, "Error: parsing: %s\n", clicon_err_reason);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -288,7 +288,7 @@ main(int argc,
|
||||||
/* Validate XML as well */
|
/* Validate XML as well */
|
||||||
if (yang_file_dir){
|
if (yang_file_dir){
|
||||||
/* Populate */
|
/* Populate */
|
||||||
if (xml_bind_yang(x0, yspec, NULL) < 0)
|
if (xml_bind_yang(x0, YB_MODULE, yspec, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Sort */
|
/* Sort */
|
||||||
if (xml_apply(x0, CX_ELMNT, xml_sort, h) < 0)
|
if (xml_apply(x0, CX_ELMNT, xml_sort, h) < 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue