Many validation functions have changed error parameter from cbuf to xml tree.

This commit is contained in:
Olof hagsand 2019-06-10 12:49:40 +02:00
parent dfa3970ab2
commit fc78824110
22 changed files with 527 additions and 384 deletions

View file

@ -411,6 +411,7 @@ from_client_edit_config(clicon_handle h,
cbuf *cbx = NULL; /* Assist cbuf */
int ret;
char *username;
cxobj *xret = NULL;
username = clicon_username_get(h);
if ((yspec = clicon_dbspec_yang(h)) == NULL){
@ -470,10 +471,13 @@ from_client_edit_config(clicon_handle h,
goto ok;
}
/* xmldb_put (difflist handling) requires list keys */
if ((ret = xml_yang_validate_list_key_only(h, xc, cbret)) < 0)
if ((ret = xml_yang_validate_list_key_only(h, xc, &xret)) < 0)
goto done;
if (ret == 0)
if (ret == 0){
if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0)
goto done;
goto ok;
}
/* Cant do this earlier since we dont have a yang spec to
* the upper part of the tree, until we get the "config" tree.
*/
@ -493,6 +497,8 @@ from_client_edit_config(clicon_handle h,
ok:
retval = 0;
done:
if (xret)
xml_free(xret);
if (cbx)
cbuf_free(cbx);
clicon_debug(1, "%s done cbret:%s", __FUNCTION__, cbuf_get(cbret));
@ -1121,6 +1127,7 @@ from_client_msg(clicon_handle h,
yang_stmt *ye;
yang_stmt *ymod;
cxobj *xnacm = NULL;
cxobj *xret = NULL;
clicon_debug(1, "%s", __FUNCTION__);
yspec = clicon_dbspec_yang(h);
@ -1147,10 +1154,13 @@ from_client_msg(clicon_handle h,
* maybe not necessary since it should be */
if (xml_spec_populate_rpc(h, x, yspec) < 0)
goto done;
if ((ret = xml_yang_validate_rpc(h, x, cbret)) < 0)
if ((ret = xml_yang_validate_rpc(h, x, &xret)) < 0)
goto done;
if (ret == 0)
if (ret == 0){
if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0)
goto done;
goto reply;
}
xe = NULL;
username = xml_find_value(x, "username");
/* May be used by callbacks, etc */
@ -1222,6 +1232,8 @@ from_client_msg(clicon_handle h,
retval = 0;
done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
if (xret)
xml_free(xret);
if (xt)
xml_free(xt);
if (cbret)

View file

@ -81,7 +81,7 @@
* are if code comes via XML/NETCONF.
* @param[in] yspec Yang spec
* @param[in] td Transaction data
* @param[out] cbret Cligen buffer containing netconf error (if retval == 0)
* @param[out] xret Error XML tree. Free with xml_free after use
* @retval -1 Error
* @retval 0 Validation failed (with cbret set)
* @retval 1 Validation OK
@ -90,7 +90,7 @@ static int
generic_validate(clicon_handle h,
yang_stmt *yspec,
transaction_data_t *td,
cbuf *cbret)
cxobj **xret)
{
int retval = -1;
cxobj *x1;
@ -100,7 +100,7 @@ generic_validate(clicon_handle h,
int ret;
/* All entries */
if ((ret = xml_yang_validate_all_top(h, td->td_target, cbret)) < 0)
if ((ret = xml_yang_validate_all_top(h, td->td_target, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
@ -109,7 +109,7 @@ generic_validate(clicon_handle h,
x1 = td->td_scvec[i]; /* source changed */
x2 = td->td_tcvec[i]; /* target changed */
/* Should this be recursive? */
if ((ret = xml_yang_validate_add(h, x2, cbret)) < 0)
if ((ret = xml_yang_validate_add(h, x2, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
@ -119,7 +119,7 @@ generic_validate(clicon_handle h,
x1 = td->td_dvec[i];
ys = xml_spec(x1);
if (ys && yang_mandatory(ys) && yang_config(ys)==0){
if (netconf_missing_element(cbret, "protocol", xml_name(x1), "Missing mandatory variable") < 0)
if (netconf_missing_element_xml(xret, "protocol", xml_name(x1), "Missing mandatory variable") < 0)
goto done;
goto fail;
}
@ -127,7 +127,7 @@ generic_validate(clicon_handle h,
/* added entries */
for (i=0; i<td->td_alen; i++){
x2 = td->td_avec[i];
if ((ret = xml_yang_validate_add(h, x2, cbret)) < 0)
if ((ret = xml_yang_validate_add(h, x2, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
@ -175,6 +175,7 @@ startup_common(clicon_handle h,
modstate_diff_t *msd = NULL;
cxobj *xt = NULL;
cxobj *x;
cxobj *xret = NULL;
/* If CLICON_XMLDB_MODSTATE is enabled, then get the db XML with
* potentially non-matching module-state in msd
@ -225,11 +226,13 @@ startup_common(clicon_handle h,
/* 5. Make generic validation on all new or changed data.
Note this is only call that uses 3-values */
clicon_debug(1, "Validating startup %s", db);
if ((ret = generic_validate(h, yspec, td, cbret)) < 0)
if ((ret = generic_validate(h, yspec, td, &xret)) < 0)
goto done;
if (ret == 0)
if (ret == 0){
if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0)
goto done;
goto fail; /* STARTUP_INVALID */
}
/* 6. Call plugin transaction validate callbacks */
if (plugin_transaction_validate(h, td) < 0)
goto done;
@ -240,6 +243,8 @@ startup_common(clicon_handle h,
ok:
retval = 1;
done:
if (xret)
xml_free(xret);
if (xt)
xml_free(xt);
if (msd)
@ -374,6 +379,7 @@ startup_commit(clicon_handle h,
* and call application callback validations.
* @param[in] h Clicon handle
* @param[in] candidate The candidate database. The wanted backend state
* @param[out] xret Error XML tree. Free with xml_free after use
* @retval -1 Error - or validation failed (but cbret not set)
* @retval 0 Validation failed (with cbret set)
* @retval 1 Validation OK
@ -385,7 +391,7 @@ static int
from_validate_common(clicon_handle h,
char *candidate,
transaction_data_t *td,
cbuf *cbret)
cxobj **xret)
{
int retval = -1;
yang_stmt *yspec;
@ -409,7 +415,7 @@ from_validate_common(clicon_handle h,
* But xml_diff requires some basic validation, at least check that yang-specs
* have been assigned
*/
if ((ret = xml_yang_validate_all_top(h, td->td_target, cbret)) < 0)
if ((ret = xml_yang_validate_all_top(h, td->td_target, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
@ -462,7 +468,7 @@ from_validate_common(clicon_handle h,
/* 5. Make generic validation on all new or changed data.
Note this is only call that uses 3-values */
if ((ret = generic_validate(h, yspec, td, cbret)) < 0)
if ((ret = generic_validate(h, yspec, td, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
@ -503,6 +509,7 @@ candidate_commit(clicon_handle h,
int retval = -1;
transaction_data_t *td = NULL;
int ret;
cxobj *xret = NULL;
/* 1. Start transaction */
if ((td = transaction_new()) == NULL)
@ -511,10 +518,13 @@ candidate_commit(clicon_handle h,
/* Common steps (with validate). Load candidate and running and compute diffs
* Note this is only call that uses 3-values
*/
if ((ret = from_validate_common(h, candidate, td, cbret)) < 0)
if ((ret = from_validate_common(h, candidate, td, &xret)) < 0)
goto done;
if (ret == 0)
if (ret == 0){
if (clicon_xml2cbuf(cbret, xret, 0, 0) < 0)
goto done;
goto fail;
}
/* 7. Call plugin transaction commit callbacks */
if (plugin_transaction_commit(h, td) < 0)
@ -563,7 +573,9 @@ candidate_commit(clicon_handle h,
xmldb_get0_free(h, &td->td_src);
transaction_free(td);
}
return retval;
if (xret)
xml_free(xret);
return retval;
fail:
retval = 0;
goto done;
@ -725,6 +737,7 @@ from_client_validate(clicon_handle h,
transaction_data_t *td = NULL;
int ret;
char *db;
cxobj *xret = NULL;
if ((db = netconf_db_find(xe, "source")) == NULL){
if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0)
@ -737,9 +750,15 @@ from_client_validate(clicon_handle h,
if ((td = transaction_new()) == NULL)
goto done;
/* Common steps (with commit) */
if ((ret = from_validate_common(h, db, td, cbret)) < 1){
if ((ret = from_validate_common(h, db, td, &xret)) < 1){
/* A little complex due to several sources of validation fails or errors.
* (1) xerr is set -> translate to cbret; (2) cbret set use that; otherwise
* use clicon_err. */
if (xret && clicon_xml2cbuf(cbret, xret, 0, 0) < 0)
goto done;
plugin_transaction_abort(h, td);
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
if (!cbuf_len(cbret) &&
netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
goto done;
goto ok;
}
@ -773,6 +792,8 @@ from_client_validate(clicon_handle h,
xmldb_get0_free(h, &td->td_src);
transaction_free(td);
}
if (xret)
xml_free(xret);
return retval;
} /* from_client_validate */

View file

@ -84,7 +84,7 @@ static int ignore_packet_errors = 1;
*/
static int
netconf_input_packet(clicon_handle h,
cbuf *cb)
cbuf *cb)
{
int retval = -1;
char *str;
@ -125,9 +125,10 @@ netconf_input_packet(clicon_handle h,
isrpc++;
if (xml_spec_populate_rpc(h, xrpc, yspec) < 0)
goto done;
if ((ret = xml_yang_validate_rpc(h, xrpc, cbret)) < 0)
if ((ret = xml_yang_validate_rpc(h, xrpc, &xret)) < 0)
goto done;
if (ret == 0){
clicon_xml2cbuf(cbret, xret, 0, 0);
netconf_output_encap(1, cbret, "rpc-error");
goto ok;
}
@ -155,7 +156,7 @@ netconf_input_packet(clicon_handle h,
netconf_output_encap(1, cbret, "rpc-error");
goto done;
}
if ((xc = xml_child_i(xret,0))!=NULL){
if ((xc = xml_child_i(xret, 0))!=NULL){
xa=NULL;
/* Copy message-id attribute from incoming to reply.
* RFC 6241:

View file

@ -547,6 +547,7 @@ netconf_application_rpc(clicon_handle h,
yang_stmt *yinput;
yang_stmt *youtput;
cxobj *xoutput;
cxobj *xerr = NULL;
cbuf *cb = NULL;
cbuf *cbret = NULL;
int ret;
@ -587,15 +588,13 @@ netconf_application_rpc(clicon_handle h,
xml_spec_set(xn, yinput); /* needed for xml_spec_populate */
if (xml_apply(xn, CX_ELMNT, xml_spec_populate, yspec) < 0)
goto done;
if ((ret = xml_yang_validate_all_top(h, xn, cbret)) < 0)
goto done;
if (ret == 0){
netconf_output_encap(1, cbret, "rpc-error");
goto ok;
}
if ((ret = xml_yang_validate_add(h, xn, cbret)) < 0)
if ((ret = xml_yang_validate_all_top(h, xn, &xerr)) < 0)
goto done;
if (ret > 0 && (ret = xml_yang_validate_add(h, xn, &xerr)) < 0)
goto done;
if (ret == 0){
if (clicon_xml2cbuf(cbret, xerr, 0, 0) < 0)
goto done;
netconf_output_encap(1, cbret, "rpc-error");
goto ok;
}
@ -622,15 +621,13 @@ netconf_application_rpc(clicon_handle h,
if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, yspec) < 0)
goto done;
if ((ret = xml_yang_validate_all_top(h, xoutput, cbret)) < 0)
goto done;
if (ret == 0){
clicon_log(LOG_WARNING, "Errors in output netconf %s", cbuf_get(cbret));
goto ok;
}
if ((ret = xml_yang_validate_add(h, xoutput, cbret)) < 0)
if ((ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0)
goto done;
if (ret > 0 && (ret = xml_yang_validate_add(h, xoutput, &xerr)) < 0)
goto done;
if (ret == 0){
if (clicon_xml2cbuf(cbret, xerr, 0, 0) < 0)
goto done;
clicon_log(LOG_WARNING, "Errors in output netconf %s", cbuf_get(cbret));
goto ok;
}
@ -641,6 +638,8 @@ netconf_application_rpc(clicon_handle h,
ok:
retval = 0;
done:
if (xerr)
xml_free(xerr);
if (cb)
cbuf_free(cb);
if (cbret)

View file

@ -1476,14 +1476,9 @@ api_operations_post_output(clicon_handle h,
cxobj *xa; /* xml attribute (xmlns) */
cxobj *x;
cxobj *xok;
cbuf *cbret = NULL;
int isempty;
// clicon_debug(1, "%s", __FUNCTION__);
if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_UNIX, 0, "cbuf_new");
goto done;
}
/* Validate that exactly only <rpc-reply> tag */
if ((xoutput = xml_child_i_type(xret, 0, CX_ELMNT)) == NULL ||
strcmp(xml_name(xoutput),"rpc-reply") != 0 ||
@ -1521,14 +1516,12 @@ api_operations_post_output(clicon_handle h,
#if 0
if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, yspec) < 0)
goto done;
if ((ret = xml_yang_validate_all(xoutput, cbret)) < 0)
if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0)
goto done;
if (ret == 1 &&
(ret = xml_yang_validate_add(h, xoutput, cbret)) < 0)
(ret = xml_yang_validate_add(h, xoutput, &xerr)) < 0)
goto done;
if (ret == 0){ /* validation failed */
if (xml_parse_string(cbuf_get(cbret), yspec, &xerr) < 0)
goto done;
if ((xe = xpath_first(xerr, "rpc-reply/rpc-error")) == NULL){
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done;
@ -1573,8 +1566,6 @@ api_operations_post_output(clicon_handle h,
retval = 1;
done:
clicon_debug(1, "%s retval: %d", __FUNCTION__, retval);
if (cbret)
cbuf_free(cbret);
if (xerr)
xml_free(xerr);
return retval;
@ -1760,14 +1751,12 @@ api_operations_post(clicon_handle h,
/* 6. Validate incoming RPC and fill in defaults */
if (xml_spec_populate_rpc(h, xtop, yspec) < 0) /* */
goto done;
if ((ret = xml_yang_validate_rpc(h, xtop, cbret)) < 0)
if ((ret = xml_yang_validate_rpc(h, xtop, &xret)) < 0)
goto done;
if (ret == 0){
if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0)
goto done;
if ((xe = xpath_first(xret, "rpc-reply/rpc-error")) == NULL){
if ((xe = xpath_first(xret, "rpc-error")) == NULL){
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done;
goto ok;
}
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
goto done;