Added new API function `xpath_parse()` to split parsing and xml evaluation.
This commit is contained in:
Olof hagsand 2019-07-08 14:47:18 +02:00
commit 1f8c759f3d
64 changed files with 2282 additions and 1350 deletions

1
.gitignore vendored
View file

@ -49,6 +49,7 @@ build-root/*.rpm
build-root/rpmbuild build-root/rpmbuild
util/clixon_util_datastore util/clixon_util_datastore
util/clixon_util_insert
util/clixon_util_json util/clixon_util_json
util/clixon_util_stream util/clixon_util_stream
util/clixon_util_xml util/clixon_util_xml

View file

@ -86,7 +86,15 @@
* rpc get and get-config api function has an added namespace argument: * rpc get and get-config api function has an added namespace argument:
* `clicon_rpc_get_config(clicon_handle h, char *db, char *xpath, char *namespace, cxobj **xt);` * `clicon_rpc_get_config(clicon_handle h, char *db, char *xpath, char *namespace, cxobj **xt);`
* `int clicon_rpc_get(clicon_handle h, char *xpath, char *namespace, cxobj **xt);` * `int clicon_rpc_get(clicon_handle h, char *xpath, char *namespace, cxobj **xt);`
* Error messages for invalid number ranges and string lengths have been uniformed and changed.
* Error messages for invalid ranges are now on the form:
```
Number 23 out of range: 1 - 10
String length 23 out of range: 1 - 10
```
* On validation callbacks, XML_FLAG_ADD is added to all nodes at startup validation, not just the top-level. This is the same behaviour as for steady-state validation.
* All hash_ functions have been prefixed with `clicon_` to avoid name collision with other packages (frr)
* All calls to the following functions must be changed: `hash_init`, `hash_free`, `hash_lookup`, `hash_value`, `hash_add`, `hash_del`, `hash_dump`, and `hash_keys`.
* RESTCONF strict namespace validation of data in POST and PUT. * RESTCONF strict namespace validation of data in POST and PUT.
* Accepted: * Accepted:
``` ```
@ -209,7 +217,9 @@
### Minor changes ### Minor changes
* Added new API function `xpath_parse()` to split parsing and xml evaluation.
* Rewrote `api_path2xpath` to handle namespaces. * Rewrote `api_path2xpath` to handle namespaces.
* `api_path2xml_vec` strict mode check added if list key length mismatch
* `startup_extraxml` triggers unnecessary validation * `startup_extraxml` triggers unnecessary validation
* Renamed startup_db_reset -> xmldb_db_reset (its a general function) * Renamed startup_db_reset -> xmldb_db_reset (its a general function)
* In startup_extraxml(), check if reset callbacks or extraxml file actually makes and changes to the tmp db. * In startup_extraxml(), check if reset callbacks or extraxml file actually makes and changes to the tmp db.
@ -260,6 +270,9 @@
### Corrected Bugs ### Corrected Bugs
* Return 404 Not found error if restconf GET does not return requested instance
* Fixed [Wrong yang-generated cli code for typeref identityref combination #88](https://github.com/clicon/clixon/issues/88)
* Fixed [identityref validation fails when using typedef #87](https://github.com/clicon/clixon/issues/87)
* Fixed a problem with some netconf error messages caused restconf daemon to exit due to no XML encoding * Fixed a problem with some netconf error messages caused restconf daemon to exit due to no XML encoding
* Check cligen tab mode, dont start if CLICON_CLI_TAB_MODE is undefined * Check cligen tab mode, dont start if CLICON_CLI_TAB_MODE is undefined
* Startup transactions did not mark added tree with XML_FLAG_ADD as it should. * Startup transactions did not mark added tree with XML_FLAG_ADD as it should.

View file

@ -214,7 +214,8 @@ startup_common(clicon_handle h,
xt = NULL; xt = NULL;
x = NULL; x = NULL;
while ((x = xml_child_each(td->td_target, x, CX_ELMNT)) != NULL){ while ((x = xml_child_each(td->td_target, x, CX_ELMNT)) != NULL){
xml_flag_set(x, XML_FLAG_ADD); xml_flag_set(x, XML_FLAG_ADD); /* Also down */
xml_apply(x, CX_ELMNT, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_ADD);
if (cxvec_append(x, &td->td_avec, &td->td_alen) < 0) if (cxvec_append(x, &td->td_avec, &td->td_alen) < 0)
goto done; goto done;
} }

View file

@ -107,7 +107,7 @@ cli_notification_register(clicon_handle h,
goto done; goto done;
} }
snprintf(logname, len, "log_socket_%s", stream); snprintf(logname, len, "log_socket_%s", stream);
if ((p = hash_value(cdat, logname, &len)) != NULL) if ((p = clicon_hash_value(cdat, logname, &len)) != NULL)
s_exist = *(int*)p; s_exist = *(int*)p;
if (status){ /* start */ if (status){ /* start */
@ -119,14 +119,14 @@ cli_notification_register(clicon_handle h,
goto done; goto done;
if (cligen_regfd(s, fn, arg) < 0) if (cligen_regfd(s, fn, arg) < 0)
goto done; goto done;
if (hash_add(cdat, logname, &s, sizeof(s)) == NULL) if (clicon_hash_add(cdat, logname, &s, sizeof(s)) == NULL)
goto done; goto done;
} }
else{ /* stop */ else{ /* stop */
if (s_exist != -1){ if (s_exist != -1){
cligen_unregfd(s_exist); cligen_unregfd(s_exist);
} }
hash_del(cdat, logname); clicon_hash_del(cdat, logname);
#if 0 /* cant turn off */ #if 0 /* cant turn off */
if (clicon_rpc_create_subscription(h, status, stream, format, filter, NULL) < 0) if (clicon_rpc_create_subscription(h, status, stream, format, filter, NULL) < 0)
goto done; goto done;

View file

@ -163,7 +163,6 @@ cli_callback_generate(clicon_handle h,
return retval; return retval;
} }
/*! Generate identityref statements for CLI variables /*! Generate identityref statements for CLI variables
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] ytype Yang union type being resolved * @param[in] ytype Yang union type being resolved
@ -186,13 +185,13 @@ yang2cli_var_identityref(yang_stmt *ys,
char *id; char *id;
int i; int i;
if ((ybaseref = yang_find(ytype, Y_BASE, NULL)) != NULL &&
(ybaseid = yang_find_identity(ys, yang_argument_get(ybaseref))) != NULL){
if (cvec_len(yang_cvec_get(ybaseid)) > 0){
/* Add a wildchar string first -let validate take it for default prefix */ /* Add a wildchar string first -let validate take it for default prefix */
cprintf(cb, ">"); cprintf(cb, ">");
if (helptext) if (helptext)
cprintf(cb, "(\"%s\")", helptext); cprintf(cb, "(\"%s\")", helptext);
if ((ybaseref = yang_find(ytype, Y_BASE, NULL)) != NULL &&
(ybaseid = yang_find_identity(ys, yang_argument_get(ybaseref))) != NULL){
if (cvec_len(yang_cvec_get(ybaseid)) > 0){
cprintf(cb, "|<%s:%s choice:", yang_argument_get(ys), cvtypestr); cprintf(cb, "|<%s:%s choice:", yang_argument_get(ys), cvtypestr);
i = 0; i = 0;
while ((cv = cvec_each(yang_cvec_get(ybaseid), cv)) != NULL){ while ((cv = cvec_each(yang_cvec_get(ybaseid), cv)) != NULL){

View file

@ -55,7 +55,7 @@ int test(FCGX_Request *r, int dbg);
cbuf *readdata(FCGX_Request *r); cbuf *readdata(FCGX_Request *r);
int get_user_cookie(char *cookiestr, char *attribute, char **val); int get_user_cookie(char *cookiestr, char *attribute, char **val);
int api_return_err(clicon_handle h, FCGX_Request *r, cxobj *xerr, int api_return_err(clicon_handle h, FCGX_Request *r, cxobj *xerr,
int pretty, int use_xml); int pretty, int use_xml, int code);
#endif /* _CLIXON_RESTCONF_H_ */ #endif /* _CLIXON_RESTCONF_H_ */

View file

@ -394,13 +394,16 @@ get_user_cookie(char *cookiestr,
* @param[in] xerr XML error message from backend * @param[in] xerr XML error message from backend
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] use_xml Set to 0 for JSON and 1 for XML * @param[in] use_xml Set to 0 for JSON and 1 for XML
* @param[in] code If 0 use rfc8040 sec 7 netconf2restconf error-tag mapping
* otherwise use this code
*/ */
int int
api_return_err(clicon_handle h, api_return_err(clicon_handle h,
FCGX_Request *r, FCGX_Request *r,
cxobj *xerr, cxobj *xerr,
int pretty, int pretty,
int use_xml) int use_xml,
int code0)
{ {
int retval = -1; int retval = -1;
cbuf *cb = NULL; cbuf *cb = NULL;
@ -417,8 +420,12 @@ api_return_err(clicon_handle h,
goto ok; goto ok;
} }
tagstr = xml_body(xtag); tagstr = xml_body(xtag);
if (code0 != 0)
code = code0;
else{
if ((code = restconf_err2code(tagstr)) < 0) if ((code = restconf_err2code(tagstr)) < 0)
code = 500; /* internal server error */ code = 500; /* internal server error */
}
if ((reason_phrase = restconf_code2reason(code)) == NULL) if ((reason_phrase = restconf_code2reason(code)) == NULL)
reason_phrase=""; reason_phrase="";
if (xml_name_set(xerr, "error") < 0) if (xml_name_set(xerr, "error") < 0)

View file

@ -60,7 +60,7 @@ int test(FCGX_Request *r, int dbg);
cbuf *readdata(FCGX_Request *r); cbuf *readdata(FCGX_Request *r);
int get_user_cookie(char *cookiestr, char *attribute, char **val); int get_user_cookie(char *cookiestr, char *attribute, char **val);
int api_return_err(clicon_handle h, FCGX_Request *r, cxobj *xerr, int api_return_err(clicon_handle h, FCGX_Request *r, cxobj *xerr,
int pretty, int use_xml); int pretty, int use_xml, int code);
int restconf_terminate(clicon_handle h); int restconf_terminate(clicon_handle h);
#endif /* _RESTCONF_LIB_H_ */ #endif /* _RESTCONF_LIB_H_ */

View file

@ -397,7 +397,7 @@ api_restconf(clicon_handle h,
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0) if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
goto done; goto done;
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, r, xerr, pretty, use_xml) < 0) if (api_return_err(h, r, xerr, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }

View file

@ -216,7 +216,7 @@ api_data_get2(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -233,7 +233,7 @@ api_data_get2(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -252,7 +252,7 @@ api_data_get2(clicon_handle h,
#endif #endif
/* Check if error return */ /* Check if error return */
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -283,7 +283,20 @@ api_data_get2(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done;
goto ok;
}
/* Check if not exists */
if (xlen == 0){
/* 4.3: If a retrieval request for a data resource represents an
instance that does not exist, then an error response containing
a "404 Not Found" status-line MUST be returned by the server.
The error-tag value "invalid-value" is used in this case. */
if (netconf_invalid_value_xml(&xe, "application", "Instance does not exist") < 0)
goto done;
/* override invalid-value default 400 with 404 */
if (api_return_err(h, r, xe, pretty, use_xml, 404) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -495,7 +508,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -509,7 +522,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -522,7 +535,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -531,7 +544,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -546,7 +559,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -568,14 +581,15 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
#if 0
if (debug){ if (debug){
cbuf *ccc=cbuf_new(); cbuf *ccc=cbuf_new();
if (clicon_xml2cbuf(ccc, xe, 0, 0) < 0) if (clicon_xml2cbuf(ccc, xe, 0, 0) < 0)
goto done; goto done;
clicon_debug(1, "%s XE:%s", __FUNCTION__, cbuf_get(ccc)); clicon_debug(1, "%s XE:%s", __FUNCTION__, cbuf_get(ccc));
} }
#endif
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -607,7 +621,7 @@ api_data_post(clicon_handle h,
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -629,7 +643,7 @@ api_data_post(clicon_handle h,
/* log errors from discard, but ignore */ /* log errors from discard, but ignore */
if ((xpath_first(xretdis, NULL, "//rpc-error")) != NULL) if ((xpath_first(xretdis, NULL, "//rpc-error")) != NULL)
clicon_log(LOG_WARNING, "%s: discard-changes failed which may lead candidate in an inconsistent state", __FUNCTION__); clicon_log(LOG_WARNING, "%s: discard-changes failed which may lead candidate in an inconsistent state", __FUNCTION__);
if (api_return_err(h, r, xe, pretty, use_xml) < 0) /* Use original xe */ if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0) /* Use original xe */
goto done; goto done;
goto ok; goto ok;
} }
@ -843,7 +857,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -858,7 +872,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -871,7 +885,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -880,7 +894,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -895,7 +909,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -915,7 +929,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -955,7 +969,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -980,7 +994,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1004,7 +1018,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1039,9 +1053,8 @@ api_data_put(clicon_handle h,
clicon_debug(1, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path); clicon_debug(1, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path);
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1062,7 +1075,7 @@ api_data_put(clicon_handle h,
/* log errors from discard, but ignore */ /* log errors from discard, but ignore */
if ((xpath_first(xretdis, NULL, "//rpc-error")) != NULL) if ((xpath_first(xretdis, NULL, "//rpc-error")) != NULL)
clicon_log(LOG_WARNING, "%s: discard-changes failed which may lead candidate in an inconsistent state", __FUNCTION__); clicon_log(LOG_WARNING, "%s: discard-changes failed which may lead candidate in an inconsistent state", __FUNCTION__);
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1195,7 +1208,7 @@ api_data_delete(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1219,7 +1232,7 @@ api_data_delete(clicon_handle h,
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1241,7 +1254,7 @@ api_data_delete(clicon_handle h,
/* log errors from discard, but ignore */ /* log errors from discard, but ignore */
if ((xpath_first(xretdis, NULL, "//rpc-error")) != NULL) if ((xpath_first(xretdis, NULL, "//rpc-error")) != NULL)
clicon_log(LOG_WARNING, "%s: discard-changes failed which may lead candidate in an inconsistent state", __FUNCTION__); clicon_log(LOG_WARNING, "%s: discard-changes failed which may lead candidate in an inconsistent state", __FUNCTION__);
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1433,7 +1446,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -1446,7 +1459,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -1455,7 +1468,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -1488,7 +1501,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -1562,7 +1575,7 @@ api_operations_post_output(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -1599,7 +1612,7 @@ api_operations_post_output(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -1732,7 +1745,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1751,7 +1764,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1762,7 +1775,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1791,7 +1804,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done; goto done;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1831,7 +1844,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)"); clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto ok; goto ok;
} }
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1860,7 +1873,7 @@ api_operations_post(clicon_handle h,
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){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -1869,7 +1882,7 @@ api_operations_post(clicon_handle h,
if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0) if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "rpc-reply/rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "rpc-reply/rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }

View file

@ -269,7 +269,7 @@ restconf_stream(clicon_handle h,
if (clicon_rpc_netconf(h, cbuf_get(cb), &xret, &s) < 0) if (clicon_rpc_netconf(h, cbuf_get(cb), &xret, &s) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "rpc-reply/rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "rpc-reply/rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -417,7 +417,7 @@ api_stream(clicon_handle h,
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0) if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
goto done; goto done;
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, r, xerr, pretty, use_xml) < 0) if (api_return_err(h, r, xerr, pretty, use_xml, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }

View file

@ -42,6 +42,51 @@ Docker is used to build Alpine Linux
### Build docker image ### Build docker image
## FreeBSD ## FreeBSD
### Package install
FreeBSD has ports for both cligen and clixon available.
You can install them as binary packages, or you can build
them in a ports source tree locally.
If you install using binary packages or build from the
ports collection, the installation locations comply
with FreeBSD standards and you have some assurance
that the installed package is correct and functional.
The nginx setup for RESTCONF is altered - the system user
www is used, and the restconf daemon is placed in
/usr/local/sbin.
### Binary package install
To install the pre-built binary package, use the FreeBSD
pkg command.
```
% pkg install clixon
```
This will install clixon and all the dependencies needed.
### Build from source ### Build from source
If you prefer you can also build clixon from the
[FreeBSD ports collection](https://www.freebsd.org/doc/handbook/ports-using.html)
Once you have the Ports Collection installed, you build
clixon like this:
```
% cd /usr/ports/devel/clixon
% make && make install
```
One issue with using the Ports Collection is that it may
not install the latest version from GitHub. The port is
generally updated soon after an official release, but there
is still a lag between it and the master branch. The maintainer
for the port tries to assure that the master branch will
compile always, but no FreeBSD specific functional testing
is done.

View file

@ -44,14 +44,14 @@ struct clicon_hash {
}; };
typedef struct clicon_hash *clicon_hash_t; typedef struct clicon_hash *clicon_hash_t;
clicon_hash_t *hash_init (void); clicon_hash_t *clicon_hash_init (void);
void hash_free (clicon_hash_t *); void clicon_hash_free (clicon_hash_t *);
clicon_hash_t hash_lookup (clicon_hash_t *head, const char *key); clicon_hash_t clicon_hash_lookup (clicon_hash_t *head, const char *key);
void *hash_value (clicon_hash_t *head, const char *key, size_t *vlen); void *clicon_hash_value (clicon_hash_t *head, const char *key, size_t *vlen);
clicon_hash_t hash_add (clicon_hash_t *head, const char *key, void *val, size_t vlen); clicon_hash_t clicon_hash_add (clicon_hash_t *head, const char *key, void *val, size_t vlen);
int hash_del (clicon_hash_t *head, const char *key); int clicon_hash_del (clicon_hash_t *head, const char *key);
int hash_dump(clicon_hash_t *head, FILE *f); int clicon_hash_dump(clicon_hash_t *head, FILE *f);
int hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys); int clicon_hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys);
/* /*
* Macros to iterate over hash contents. * Macros to iterate over hash contents.
@ -59,24 +59,23 @@ int hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys);
* *
* Example: * Example:
* char *k; * char *k;
* clicon_hash_t *h = hash_init(); * clicon_hash_t *h = clicon_hash_init();
* *
* hash_add(h, "colour", "red", 6); * clicon_hash_add(h, "colour", "red", 6);
* hash_add(h, "name", "rudolf" 7); * clicon_hash_add(h, "name", "rudolf" 7);
* hash_add(h, "species", "reindeer" 9); * clicon_hash_add(h, "species", "reindeer" 9);
* *
* hash_each(h, k) { * clicon_hash_each(h, k) {
* printf ("%s = %s\n", k, (char *)hash_value(h, k, NULL)); * printf ("%s = %s\n", k, (char *)clicon_hash_value(h, k, NULL));
* } hash_each_end(); * } hash_each_end();
*/ */
#define hash_each(__hash__, __key__) \ #define clicon_hash_each(__hash__, __key__) \
{ \ { \
int __i__; \ int __i__; \
size_t __n__; \ size_t __n__; \
char **__k__ = hash_keys((__hash__),&__n__); \ char **__k__ = hash_keys((__hash__),&__n__); \
if (__k__) { \ if (__k__) { \
for(__i__ = 0; __i__ < __n__ && ((__key__) = __k__[__i__]); __i__++) for(__i__ = 0; __i__ < __n__ && ((__key__) = __k__[__i__]); __i__++)
#define hash_each_end(__hash__) if (__k__) free(__k__); } } #define clicon_hash_each_end(__hash__) if (__k__) free(__k__); } }
#endif /* _CLIXON_HASH_H_ */ #endif /* _CLIXON_HASH_H_ */

View file

@ -43,6 +43,7 @@
*/ */
int netconf_in_use(cbuf *cb, char *type, char *message); int netconf_in_use(cbuf *cb, char *type, char *message);
int netconf_invalid_value(cbuf *cb, char *type, char *message); int netconf_invalid_value(cbuf *cb, char *type, char *message);
int netconf_invalid_value_xml(cxobj **xret, char *type, char *message);
int netconf_too_big(cbuf *cb, char *type, char *message); int netconf_too_big(cbuf *cb, char *type, char *message);
int netconf_missing_attribute(cbuf *cb, char *type, char *info, char *message); int netconf_missing_attribute(cbuf *cb, char *type, char *info, char *message);
int netconf_bad_attribute(cbuf *cb, char *type, char *info, char *message); int netconf_bad_attribute(cbuf *cb, char *type, char *info, char *message);

View file

@ -75,31 +75,61 @@ enum axis_type{
A_ROOT /* XXX Not in https://www.w3.org/TR/xpath-10 */ A_ROOT /* XXX Not in https://www.w3.org/TR/xpath-10 */
}; };
/* /* used as non-terminal type in yacc rules */
* Variables enum xp_type{
*/ XP_EXP,
extern const map_str2int xpopmap[]; XP_AND,
XP_RELEX,
XP_ADD,
XP_UNION,
XP_PATHEXPR,
XP_LOCPATH,
XP_ABSPATH,
XP_RELLOCPATH,
XP_STEP,
XP_NODE, /* s0 is namespace prefix, s1 is name */
XP_NODE_FN,
XP_PRED,
XP_PRI0,
XP_PRIME_NR,
XP_PRIME_STR,
XP_PRIME_FN,
};
extern int xpatherrordiff; /*! XPATH Parsing generates a tree of nodes that is later traversed
*/
struct xpath_tree{
enum xp_type xs_type;
int xs_int;
double xs_double;
char *xs_s0;
char *xs_s1;
struct xpath_tree *xs_c0; /* child 0 */
struct xpath_tree *xs_c1; /* child 1 */
};
typedef struct xpath_tree xpath_tree;
/* /*
* Prototypes * Prototypes
*/ */
char* xpath_tree_int2str(int nodetype);
int xpath_tree_print(cbuf *cb, xpath_tree *xs);
int xpath_tree_free(xpath_tree *xs);
int xpath_parse(cvec *nsc, char *xpath, xpath_tree **xptree);
#if defined(__GNUC__) && __GNUC__ >= 3 #if defined(__GNUC__) && __GNUC__ >= 3
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *format, ...) __attribute__ ((format (printf, 3, 4)));
int xpath_vec(cxobj *xcur, cvec *nsc, char *format, cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 6))); int xpath_vec(cxobj *xcur, cvec *nsc, char *format, cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 6)));
int xpath_vec_flag(cxobj *xcur, cvec *nsc, char *format, uint16_t flags, int xpath_vec_flag(cxobj *xcur, cvec *nsc, char *format, uint16_t flags,
cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 7))); cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 7)));
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *format, ...) __attribute__ ((format (printf, 3, 4)));
int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *format, ...) __attribute__ ((format (printf, 3, 4))); int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *format, ...) __attribute__ ((format (printf, 3, 4)));
#else #else
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *format, ...);
int xpath_vec(cxobj *xcur, cvec *nsc, char *format, cxobj ***vec, size_t *veclen, ...); int xpath_vec(cxobj *xcur, cvec *nsc, char *format, cxobj ***vec, size_t *veclen, ...);
int xpath_vec_flag(cxobj *xcur, cvec *nsc, char *format, uint16_t flags, int xpath_vec_flag(cxobj *xcur, cvec *nsc, char *format, uint16_t flags,
cxobj ***vec, size_t *veclen, ...); cxobj ***vec, size_t *veclen, ...);
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *format, ...);
int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *format, ...); int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *format, ...);
#endif #endif
int xpath_vec_ctx(cxobj *xcur, cvec *nsc, char *xpath, xp_ctx **xrp); int xpath_vec_ctx(cxobj *xcur, cvec *nsc, char *xpath, xp_ctx **xrp);
#endif /* _CLIXON_XPATH_H */ #endif /* _CLIXON_XPATH_H */

View file

@ -73,7 +73,7 @@ SRC = clixon_sig.c clixon_log.c clixon_err.c clixon_event.c \
clixon_yang_cardinality.c clixon_xml_changelog.c clixon_xml_nsctx.c \ clixon_yang_cardinality.c clixon_xml_changelog.c clixon_xml_nsctx.c \
clixon_hash.c clixon_options.c clixon_data.c clixon_plugin.c \ clixon_hash.c clixon_options.c clixon_data.c clixon_plugin.c \
clixon_proto.c clixon_proto_client.c \ clixon_proto.c clixon_proto_client.c \
clixon_xpath.c clixon_xpath_ctx.c clixon_sha1.c \ clixon_xpath.c clixon_xpath_ctx.c clixon_xpath_eval.c clixon_sha1.c \
clixon_datastore.c clixon_datastore_write.c clixon_datastore_read.c \ clixon_datastore.c clixon_datastore_write.c clixon_datastore_read.c \
clixon_datastore_tree.c \ clixon_datastore_tree.c \
clixon_netconf_lib.c clixon_stream.c clixon_nacm.c clixon_netconf_lib.c clixon_stream.c clixon_nacm.c

View file

@ -83,7 +83,7 @@ clicon_dbspec_yang(clicon_handle h)
size_t len; size_t len;
void *p; void *p;
if ((p = hash_value(cdat, "dbspec_yang", &len)) != NULL) if ((p = clicon_hash_value(cdat, "dbspec_yang", &len)) != NULL)
return *(yang_stmt **)p; return *(yang_stmt **)p;
return NULL; return NULL;
} }
@ -100,7 +100,7 @@ clicon_dbspec_yang_set(clicon_handle h,
/* It is the pointer to ys that should be copied by hash, /* It is the pointer to ys that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy. so we send a ptr to the ptr to indicate what to copy.
*/ */
if (hash_add(cdat, "dbspec_yang", &ys, sizeof(ys)) == NULL) if (clicon_hash_add(cdat, "dbspec_yang", &ys, sizeof(ys)) == NULL)
return -1; return -1;
return 0; return 0;
} }
@ -118,7 +118,7 @@ clicon_nacm_ext(clicon_handle h)
size_t len; size_t len;
void *p; void *p;
if ((p = hash_value(cdat, "nacm_xml", &len)) != NULL) if ((p = clicon_hash_value(cdat, "nacm_xml", &len)) != NULL)
return *(cxobj **)p; return *(cxobj **)p;
return NULL; return NULL;
} }
@ -141,7 +141,7 @@ clicon_nacm_ext_set(clicon_handle h,
/* It is the pointer to xn that should be copied by hash, /* It is the pointer to xn that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy. so we send a ptr to the ptr to indicate what to copy.
*/ */
if (hash_add(cdat, "nacm_xml", &xn, sizeof(xn)) == NULL) if (clicon_hash_add(cdat, "nacm_xml", &xn, sizeof(xn)) == NULL)
return -1; return -1;
return 0; return 0;
} }
@ -158,7 +158,7 @@ clicon_config_yang(clicon_handle h)
size_t len; size_t len;
void *p; void *p;
if ((p = hash_value(cdat, "control_yang", &len)) != NULL) if ((p = clicon_hash_value(cdat, "control_yang", &len)) != NULL)
return *(yang_stmt **)p; return *(yang_stmt **)p;
return NULL; return NULL;
} }
@ -175,7 +175,7 @@ clicon_config_yang_set(clicon_handle h,
/* It is the pointer to ys that should be copied by hash, /* It is the pointer to ys that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy. so we send a ptr to the ptr to indicate what to copy.
*/ */
if (hash_add(cdat, "control_yang", &ys, sizeof(ys)) == NULL) if (clicon_hash_add(cdat, "control_yang", &ys, sizeof(ys)) == NULL)
return -1; return -1;
return 0; return 0;
} }
@ -192,7 +192,7 @@ clicon_conf_xml(clicon_handle h)
size_t len; size_t len;
void *p; void *p;
if ((p = hash_value(cdat, "clixon_conf", &len)) != NULL) if ((p = clicon_hash_value(cdat, "clixon_conf", &len)) != NULL)
return *(cxobj **)p; return *(cxobj **)p;
return NULL; return NULL;
} }
@ -209,7 +209,7 @@ clicon_conf_xml_set(clicon_handle h,
/* It is the pointer to x that should be copied by hash, /* It is the pointer to x that should be copied by hash,
* so we send a ptr to the ptr to indicate what to copy. * so we send a ptr to the ptr to indicate what to copy.
*/ */
if (hash_add(cdat, "clixon_conf", &x, sizeof(x)) == NULL) if (clicon_hash_add(cdat, "clixon_conf", &x, sizeof(x)) == NULL)
return -1; return -1;
return 0; return 0;
} }
@ -223,7 +223,7 @@ clicon_username_get(clicon_handle h)
{ {
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
return (char*)hash_value(cdat, "username", NULL); return (char*)clicon_hash_value(cdat, "username", NULL);
} }
/*! Set authorized user name /*! Set authorized user name
@ -238,8 +238,8 @@ clicon_username_set(clicon_handle h,
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
if (username == NULL) if (username == NULL)
return hash_del(cdat, "username"); return clicon_hash_del(cdat, "username");
return hash_add(cdat, "username", username, strlen(username)+1)==NULL?-1:0; return clicon_hash_add(cdat, "username", username, strlen(username)+1)==NULL?-1:0;
} }
/*! Get backend daemon startup status /*! Get backend daemon startup status
@ -252,7 +252,7 @@ clicon_startup_status_get(clicon_handle h)
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
void *p; void *p;
if ((p = hash_value(cdat, "startup_status", NULL)) != NULL) if ((p = clicon_hash_value(cdat, "startup_status", NULL)) != NULL)
return *(enum startup_status *)p; return *(enum startup_status *)p;
return STARTUP_ERR; return STARTUP_ERR;
} }
@ -268,7 +268,7 @@ clicon_startup_status_set(clicon_handle h,
enum startup_status status) enum startup_status status)
{ {
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
if (hash_add(cdat, "startup_status", &status, sizeof(status))==NULL) if (clicon_hash_add(cdat, "startup_status", &status, sizeof(status))==NULL)
return -1; return -1;
return 0; return 0;
} }
@ -284,7 +284,7 @@ clicon_socket_get(clicon_handle h)
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
void *p; void *p;
if ((p = hash_value(cdat, "socket", NULL)) == NULL) if ((p = clicon_hash_value(cdat, "socket", NULL)) == NULL)
return -1; return -1;
return *(int*)p; return *(int*)p;
} }
@ -302,8 +302,8 @@ clicon_socket_set(clicon_handle h,
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
if (s == -1) if (s == -1)
return hash_del(cdat, "socket"); return clicon_hash_del(cdat, "socket");
return hash_add(cdat, "socket", &s, sizeof(int))==NULL?-1:0; return clicon_hash_add(cdat, "socket", &s, sizeof(int))==NULL?-1:0;
} }
/*! Get module state cache /*! Get module state cache
@ -319,7 +319,7 @@ clicon_modst_cache_get(clicon_handle h,
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
void *p; void *p;
if ((p = hash_value(cdat, brief?"modst_brief":"modst_full", NULL)) != NULL) if ((p = clicon_hash_value(cdat, brief?"modst_brief":"modst_full", NULL)) != NULL)
return *(cxobj **)p; return *(cxobj **)p;
return NULL; return NULL;
} }
@ -346,7 +346,7 @@ clicon_modst_cache_set(clicon_handle h,
assert(strcmp(xml_name(xms),"modules-state")==0); assert(strcmp(xml_name(xms),"modules-state")==0);
if ((x = xml_dup(xms)) == NULL) if ((x = xml_dup(xms)) == NULL)
return -1; return -1;
if (hash_add(cdat, brief?"modst_brief":"modst_full", &x, sizeof(x))==NULL) if (clicon_hash_add(cdat, brief?"modst_brief":"modst_full", &x, sizeof(x))==NULL)
return -1; return -1;
ok: ok:
return 0; return 0;
@ -363,7 +363,7 @@ clicon_xml_changelog_get(clicon_handle h)
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
void *p; void *p;
if ((p = hash_value(cdat, "xml-changelog", NULL)) != NULL) if ((p = clicon_hash_value(cdat, "xml-changelog", NULL)) != NULL)
return *(cxobj **)p; return *(cxobj **)p;
return NULL; return NULL;
} }
@ -381,7 +381,7 @@ clicon_xml_changelog_set(clicon_handle h,
{ {
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
if (hash_add(cdat, "xml-changelog", &xchlog, sizeof(xchlog))==NULL) if (clicon_hash_add(cdat, "xml-changelog", &xchlog, sizeof(xchlog))==NULL)
return -1; return -1;
return 0; return 0;
} }
@ -403,12 +403,12 @@ clicon_argv_get(clicon_handle h,
void *p; void *p;
if (argc){ if (argc){
if ((p = hash_value(cdat, "argc", NULL)) == NULL) if ((p = clicon_hash_value(cdat, "argc", NULL)) == NULL)
return -1; return -1;
*argc = *(int*)p; *argc = *(int*)p;
} }
if (argv){ if (argv){
if ((p = hash_value(cdat, "argv", NULL)) == NULL) if ((p = clicon_hash_value(cdat, "argv", NULL)) == NULL)
return -1; return -1;
*argv = (char**)p; *argv = (char**)p;
} }
@ -444,10 +444,10 @@ clicon_argv_set(clicon_handle h,
memcpy(argvv+1, argv, argc*sizeof(char*)); memcpy(argvv+1, argv, argc*sizeof(char*));
argvv[0] = prgm; argvv[0] = prgm;
/* Note the value is the argv vector (which is copied) */ /* Note the value is the argv vector (which is copied) */
if (hash_add(cdat, "argv", argvv, len*sizeof(char*))==NULL) if (clicon_hash_add(cdat, "argv", argvv, len*sizeof(char*))==NULL)
goto done; goto done;
argc += 1; argc += 1;
if (hash_add(cdat, "argc", &argc, sizeof(argc))==NULL) if (clicon_hash_add(cdat, "argc", &argc, sizeof(argc))==NULL)
goto done; goto done;
retval = 0; retval = 0;
done: done:
@ -470,7 +470,7 @@ clicon_db_elmnt_get(clicon_handle h,
clicon_hash_t *cdat = clicon_db_elmnt(h); clicon_hash_t *cdat = clicon_db_elmnt(h);
void *p; void *p;
if ((p = hash_value(cdat, db, NULL)) != NULL) if ((p = clicon_hash_value(cdat, db, NULL)) != NULL)
return (db_elmnt *)p; return (db_elmnt *)p;
return NULL; return NULL;
} }
@ -491,7 +491,7 @@ clicon_db_elmnt_set(clicon_handle h,
{ {
clicon_hash_t *cdat = clicon_db_elmnt(h); clicon_hash_t *cdat = clicon_db_elmnt(h);
if (hash_add(cdat, db, de, sizeof(*de))==NULL) if (clicon_hash_add(cdat, db, de, sizeof(*de))==NULL)
return -1; return -1;
return 0; return 0;
} }

View file

@ -161,10 +161,10 @@ xmldb_disconnect(clicon_handle h)
int i; int i;
db_elmnt *de; db_elmnt *de;
if (hash_keys(clicon_db_elmnt(h), &keys, &klen) < 0) if (clicon_hash_keys(clicon_db_elmnt(h), &keys, &klen) < 0)
goto done; goto done;
for(i = 0; i < klen; i++) for(i = 0; i < klen; i++)
if ((de = hash_value(clicon_db_elmnt(h), keys[i], NULL)) != NULL){ if ((de = clicon_hash_value(clicon_db_elmnt(h), keys[i], NULL)) != NULL){
if (de->de_xml){ if (de->de_xml){
xml_free(de->de_xml); xml_free(de->de_xml);
de->de_xml = NULL; de->de_xml = NULL;
@ -311,7 +311,7 @@ xmldb_unlock_all(clicon_handle h,
int i; int i;
db_elmnt *de; db_elmnt *de;
if (hash_keys(clicon_db_elmnt(h), &keys, &klen) < 0) if (clicon_hash_keys(clicon_db_elmnt(h), &keys, &klen) < 0)
goto done; goto done;
for (i = 0; i < klen; i++) for (i = 0; i < klen; i++)
if ((de = clicon_db_elmnt_get(h, keys[i])) != NULL && if ((de = clicon_db_elmnt_get(h, keys[i])) != NULL &&

View file

@ -596,10 +596,6 @@ xmldb_get_zerocopy(clicon_handle h,
db_elmnt *de = NULL; db_elmnt *de = NULL;
db_elmnt de0 = {0,}; db_elmnt de0 = {0,};
if (!clicon_option_bool(h, "CLICON_XMLDB_CACHE")){
clicon_err(OE_CFG, 0, "CLICON_XMLDB_CACHE must be set");
goto done;
}
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "No yang spec"); clicon_err(OE_YANG, ENOENT, "No yang spec");
goto done; goto done;

View file

@ -111,15 +111,15 @@ clicon_handle_init0(int size)
} }
memset(ch, 0, size); memset(ch, 0, size);
ch->ch_magic = CLICON_MAGIC; ch->ch_magic = CLICON_MAGIC;
if ((ch->ch_copt = hash_init()) == NULL){ if ((ch->ch_copt = clicon_hash_init()) == NULL){
clicon_handle_exit((clicon_handle)ch); clicon_handle_exit((clicon_handle)ch);
goto done; goto done;
} }
if ((ch->ch_data = hash_init()) == NULL){ if ((ch->ch_data = clicon_hash_init()) == NULL){
clicon_handle_exit((clicon_handle)ch); clicon_handle_exit((clicon_handle)ch);
goto done; goto done;
} }
if ((ch->ch_db_elmnt = hash_init()) == NULL){ if ((ch->ch_db_elmnt = clicon_hash_init()) == NULL){
clicon_handle_exit((clicon_handle)ch); clicon_handle_exit((clicon_handle)ch);
goto done; goto done;
} }
@ -154,12 +154,12 @@ clicon_handle_exit(clicon_handle h)
clicon_hash_t *ha; clicon_hash_t *ha;
if ((ha = clicon_options(h)) != NULL) if ((ha = clicon_options(h)) != NULL)
hash_free(ha); clicon_hash_free(ha);
if ((ha = clicon_data(h)) != NULL) if ((ha = clicon_data(h)) != NULL)
hash_free(ha); clicon_hash_free(ha);
if ((ha = clicon_db_elmnt(h)) != NULL) if ((ha = clicon_db_elmnt(h)) != NULL)
hash_free(ha); clicon_hash_free(ha);
stream_delete_all(h, 1); stream_delete_all(h, 1);
free(ch); free(ch);
retval = 0; retval = 0;

View file

@ -115,7 +115,7 @@ hash_bucket(const char *str)
* @see hash_free For freeing the hash-table * @see hash_free For freeing the hash-table
*/ */
clicon_hash_t * clicon_hash_t *
hash_init(void) clicon_hash_init(void)
{ {
clicon_hash_t *hash; clicon_hash_t *hash;
@ -133,7 +133,7 @@ hash_init(void)
* @retval void * @retval void
*/ */
void void
hash_free(clicon_hash_t *hash) clicon_hash_free(clicon_hash_t *hash)
{ {
int i; int i;
clicon_hash_t tmp; clicon_hash_t tmp;
@ -157,7 +157,7 @@ hash_free(clicon_hash_t *hash)
* @retval NULL Not found * @retval NULL Not found
*/ */
clicon_hash_t clicon_hash_t
hash_lookup(clicon_hash_t *hash, clicon_hash_lookup(clicon_hash_t *hash,
const char *key) const char *key)
{ {
uint32_t bkt; uint32_t bkt;
@ -183,13 +183,13 @@ hash_lookup(clicon_hash_t *hash,
* @retval NULL Key not found or value NULL * @retval NULL Key not found or value NULL
*/ */
void * void *
hash_value(clicon_hash_t *hash, clicon_hash_value(clicon_hash_t *hash,
const char *key, const char *key,
size_t *vlen) size_t *vlen)
{ {
clicon_hash_t h; clicon_hash_t h;
h = hash_lookup(hash, key); h = clicon_hash_lookup(hash, key);
if (h == NULL) if (h == NULL)
return NULL; /* OK, key not found */ return NULL; /* OK, key not found */
@ -209,7 +209,7 @@ hash_value(clicon_hash_t *hash,
* @note special case val is NULL and vlen==0 * @note special case val is NULL and vlen==0
*/ */
clicon_hash_t clicon_hash_t
hash_add(clicon_hash_t *hash, clicon_hash_add(clicon_hash_t *hash,
const char *key, const char *key,
void *val, void *val,
size_t vlen) size_t vlen)
@ -225,7 +225,7 @@ hash_add(clicon_hash_t *hash,
goto catch; goto catch;
} }
/* If variable exist, don't allocate a new. just replace value */ /* If variable exist, don't allocate a new. just replace value */
h = hash_lookup(hash, key); h = clicon_hash_lookup(hash, key);
if (h == NULL) { if (h == NULL) {
if ((new = (clicon_hash_t)malloc(sizeof(*new))) == NULL){ if ((new = (clicon_hash_t)malloc(sizeof(*new))) == NULL){
clicon_err(OE_UNIX, errno, "malloc: %s", strerror(errno)); clicon_err(OE_UNIX, errno, "malloc: %s", strerror(errno));
@ -283,12 +283,12 @@ catch:
* @retval -1 Key not found * @retval -1 Key not found
*/ */
int int
hash_del(clicon_hash_t *hash, clicon_hash_del(clicon_hash_t *hash,
const char *key) const char *key)
{ {
clicon_hash_t h; clicon_hash_t h;
h = hash_lookup(hash, key); h = clicon_hash_lookup(hash, key);
if (h == NULL) if (h == NULL)
return -1; return -1;
@ -311,7 +311,7 @@ hash_del(clicon_hash_t *hash,
* @note: vector needs to be deallocated with free * @note: vector needs to be deallocated with free
*/ */
int int
hash_keys(clicon_hash_t *hash, clicon_hash_keys(clicon_hash_t *hash,
char ***vector, char ***vector,
size_t *nkeys) size_t *nkeys)
{ {
@ -357,7 +357,7 @@ catch:
* @retval -1 Error * @retval -1 Error
*/ */
int int
hash_dump(clicon_hash_t *hash, clicon_hash_dump(clicon_hash_t *hash,
FILE *f) FILE *f)
{ {
int retval = -1; int retval = -1;
@ -369,10 +369,10 @@ hash_dump(clicon_hash_t *hash,
if (hash == NULL) if (hash == NULL)
goto ok; goto ok;
if (hash_keys(hash, &keys, &klen) < 0) if (clicon_hash_keys(hash, &keys, &klen) < 0)
goto done; goto done;
for(i = 0; i < klen; i++) { for(i = 0; i < klen; i++) {
val = hash_value(hash, keys[i], &vlen); val = clicon_hash_value(hash, keys[i], &vlen);
printf("%s =\t 0x%p , length %zu\n", keys[i], val, vlen); printf("%s =\t 0x%p , length %zu\n", keys[i], val, vlen);
} }

View file

@ -108,6 +108,48 @@ netconf_in_use(cbuf *cb,
goto done; goto done;
} }
/*! Create Netconf invalid-value error XML tree according to RFC 6241 Appendix A
*
* The request specifies an unacceptable value for one or more parameters.
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] type Error type: "application" or "protocol"
* @param[in] message Error message (will be XML encoded)
*/
int
netconf_invalid_value_xml(cxobj **xret,
char *type,
char *message)
{
int retval =-1;
cxobj *xerr;
char *encstr = NULL;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
goto done;
}
else if (xml_name_set(*xret, "rpc-reply") < 0)
goto done;
if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL)
goto done;
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
"<error-tag>invalid-value</error-tag>"
"<error-severity>error</error-severity>", type) < 0)
goto done;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
goto done;
if (xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
encstr) < 0)
goto done;
}
retval = 0;
done:
if (encstr)
free(encstr);
return retval;
}
/*! Create Netconf invalid-value error XML tree according to RFC 6241 Appendix A /*! Create Netconf invalid-value error XML tree according to RFC 6241 Appendix A
* *
* The request specifies an unacceptable value for one or more parameters. * The request specifies an unacceptable value for one or more parameters.
@ -120,6 +162,20 @@ netconf_invalid_value(cbuf *cb,
char *type, char *type,
char *message) char *message)
{ {
#if 1
int retval = -1;
cxobj *xret = NULL;
if (netconf_invalid_value_xml(&xret, type, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
retval = 0;
done:
if (xret)
xml_free(xret);
return retval;
#else
int retval = -1; int retval = -1;
char *encstr = NULL; char *encstr = NULL;
@ -145,6 +201,7 @@ netconf_invalid_value(cbuf *cb,
err: err:
clicon_err(OE_XML, errno, "cprintf"); clicon_err(OE_XML, errno, "cprintf");
goto done; goto done;
#endif
} }
/*! Create Netconf too-big error XML tree according to RFC 6241 Appendix A /*! Create Netconf too-big error XML tree according to RFC 6241 Appendix A

View file

@ -112,10 +112,10 @@ clicon_option_dump(clicon_handle h,
size_t vlen; size_t vlen;
cxobj *x = NULL; cxobj *x = NULL;
if (hash_keys(hash, &keys, &klen) < 0) if (clicon_hash_keys(hash, &keys, &klen) < 0)
goto done; goto done;
for(i = 0; i < klen; i++) { for(i = 0; i < klen; i++) {
val = hash_value(hash, keys[i], &vlen); val = clicon_hash_value(hash, keys[i], &vlen);
if (vlen){ if (vlen){
if (((char*)val)[vlen-1]=='\0') /* assume string */ if (((char*)val)[vlen-1]=='\0') /* assume string */
clicon_debug(dbglevel, "%s =\t \"%s\"", keys[i], (char*)val); clicon_debug(dbglevel, "%s =\t \"%s\"", keys[i], (char*)val);
@ -234,7 +234,7 @@ parse_configfile(clicon_handle h,
/* Used as an arg to this fn */ /* Used as an arg to this fn */
if (strcmp(name,"CLICON_CONFIGFILE")==0) if (strcmp(name,"CLICON_CONFIGFILE")==0)
continue; continue;
if (hash_add(copt, if (clicon_hash_add(copt,
name, name,
body, body,
strlen(body)+1) == NULL) strlen(body)+1) == NULL)
@ -284,7 +284,7 @@ clicon_option_add(clicon_handle h,
name, value, name) < 0) name, value, name) < 0)
goto done; goto done;
} }
if (hash_add(copt, if (clicon_hash_add(copt,
name, name,
value, value,
strlen(value)+1) == NULL) strlen(value)+1) == NULL)
@ -319,10 +319,10 @@ clicon_options_main(clicon_handle h,
/* /*
* Set configure file if not set by command-line above * Set configure file if not set by command-line above
*/ */
if (!hash_lookup(copt, "CLICON_CONFIGFILE")){ if (!clicon_hash_lookup(copt, "CLICON_CONFIGFILE")){
clicon_option_str_set(h, "CLICON_CONFIGFILE", CLIXON_DEFAULT_CONFIG); clicon_option_str_set(h, "CLICON_CONFIGFILE", CLIXON_DEFAULT_CONFIG);
} }
configfile = hash_value(copt, "CLICON_CONFIGFILE", NULL); configfile = clicon_hash_value(copt, "CLICON_CONFIGFILE", NULL);
clicon_debug(1, "CLICON_CONFIGFILE=%s", configfile); clicon_debug(1, "CLICON_CONFIGFILE=%s", configfile);
/* File must end with .xml */ /* File must end with .xml */
if ((suffix = rindex(configfile, '.')) != NULL){ if ((suffix = rindex(configfile, '.')) != NULL){
@ -385,7 +385,7 @@ clicon_option_exists(clicon_handle h,
{ {
clicon_hash_t *copt = clicon_options(h); clicon_hash_t *copt = clicon_options(h);
return (hash_lookup(copt, (char*)name) != NULL); return (clicon_hash_lookup(copt, (char*)name) != NULL);
} }
/*! Get a single string option string via handle /*! Get a single string option string via handle
@ -404,9 +404,9 @@ clicon_option_str(clicon_handle h,
{ {
clicon_hash_t *copt = clicon_options(h); clicon_hash_t *copt = clicon_options(h);
if (hash_lookup(copt, (char*)name) == NULL) if (clicon_hash_lookup(copt, (char*)name) == NULL)
return NULL; return NULL;
return hash_value(copt, (char*)name, NULL); return clicon_hash_value(copt, (char*)name, NULL);
} }
/*! Set a single string option via handle /*! Set a single string option via handle
@ -423,7 +423,7 @@ clicon_option_str_set(clicon_handle h,
{ {
clicon_hash_t *copt = clicon_options(h); clicon_hash_t *copt = clicon_options(h);
return hash_add(copt, (char*)name, val, strlen(val)+1)==NULL?-1:0; return clicon_hash_add(copt, (char*)name, val, strlen(val)+1)==NULL?-1:0;
} }
/*! Get options as integer but stored as string /*! Get options as integer but stored as string
@ -518,7 +518,7 @@ clicon_option_del(clicon_handle h,
{ {
clicon_hash_t *copt = clicon_options(h); clicon_hash_t *copt = clicon_options(h);
return hash_del(copt, (char*)name); return clicon_hash_del(copt, (char*)name);
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------

View file

@ -343,11 +343,12 @@ validate_identityref(cxobj *xt,
{ {
int retval = -1; int retval = -1;
char *node; char *node = NULL;
yang_stmt *ybaseref; /* This is the type's base reference */ yang_stmt *ybaseref; /* This is the type's base reference */
yang_stmt *ybaseid; yang_stmt *ybaseid;
char *prefix = NULL; char *prefix = NULL;
cbuf *cb = NULL; cbuf *cb = NULL;
cbuf *cb2 = NULL;
/* Get idref value. Then see if this value is derived from ytype. /* Get idref value. Then see if this value is derived from ytype.
* Always add default prefix because derived identifiers are stored with * Always add default prefix because derived identifiers are stored with
@ -380,10 +381,13 @@ validate_identityref(cxobj *xt,
* The derived node list is a cvec computed XXX * The derived node list is a cvec computed XXX
*/ */
if (cvec_find(yang_cvec_get(ybaseid), node) == NULL){ if (cvec_find(yang_cvec_get(ybaseid), node) == NULL){
cbuf_reset(cb); if ((cb2 = cbuf_new()) == NULL){
cprintf(cb, "Identityref validation failed, %s not derived from %s", clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cb2, "Identityref validation failed, %s not derived from %s",
node, yang_argument_get(ybaseid)); node, yang_argument_get(ybaseid));
if (netconf_operation_failed_xml(xret, "application", cbuf_get(cb)) < 0) if (netconf_operation_failed_xml(xret, "application", cbuf_get(cb2)) < 0)
goto done; goto done;
goto fail; goto fail;
} }
@ -391,6 +395,8 @@ validate_identityref(cxobj *xt,
done: done:
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
if (cb2)
cbuf_free(cb2);
return retval; return retval;
fail: fail:
retval = 0; retval = 0;
@ -1221,20 +1227,21 @@ xml_yang_validate_all(clicon_handle h,
/* Special case if leaf is leafref, then first check against /* Special case if leaf is leafref, then first check against
current xml tree current xml tree
*/ */
if ((yc = yang_find(ys, Y_TYPE, NULL)) != NULL){ /* Get base type yc */
if (strcmp(yc->ys_argument, "leafref") == 0){ if (yang_type_get(ys, NULL, &yc, NULL, NULL, NULL, NULL, NULL) < 0)
goto done;
if (strcmp(yang_argument_get(yc), "leafref") == 0){
if ((ret = validate_leafref(xt, yc, xret)) < 0) if ((ret = validate_leafref(xt, yc, xret)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;
} }
else if (strcmp(yc->ys_argument, "identityref") == 0){ else if (strcmp(yang_argument_get(yc), "identityref") == 0){
if ((ret = validate_identityref(xt, ys, yc, xret)) < 0) if ((ret = validate_identityref(xt, ys, yc, xret)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;
} }
}
break; break;
default: default:
break; break;
@ -2557,7 +2564,7 @@ api_path2xml_vec(char **vec,
else{ else{
if ((valvec = clicon_strsep(restval, ",", &nvalvec)) == NULL) if ((valvec = clicon_strsep(restval, ",", &nvalvec)) == NULL)
goto done; goto done;
if (nvalvec != cvec_len(cvk)){ if ((nvalvec != cvec_len(cvk)) && strict){
clicon_err(OE_XML, EINVAL, "List key %s length mismatch", name); clicon_err(OE_XML, EINVAL, "List key %s length mismatch", name);
goto fail; goto fail;
} }

File diff suppressed because it is too large Load diff

View file

@ -59,8 +59,9 @@
#include "clixon_handle.h" #include "clixon_handle.h"
#include "clixon_yang.h" #include "clixon_yang.h"
#include "clixon_xml.h" #include "clixon_xml.h"
#include "clixon_xpath_parse.h"
#include "clixon_xpath_ctx.h" #include "clixon_xpath_ctx.h"
#include "clixon_xpath.h"
#include "clixon_xpath_parse.h"
/* /*
* Variables * Variables

1062
lib/src/clixon_xpath_eval.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
* Clixon XML XPATH 1.0 according to https://www.w3.org/TR/xpath-10
*/
#ifndef _CLIXON_XPATH_EVAL_H
#define _CLIXON_XPATH_EVAL_H
/*
* Variables
*/
extern const map_str2int xpopmap[];
/*
* Prototypes
*/
int xp_eval(xp_ctx *xc, xpath_tree *xs, cvec *nsc, xp_ctx **xrp);
#endif /* _CLIXON_XPATH_EVAL_H */

View file

@ -39,40 +39,6 @@
/* /*
* Types * Types
*/ */
/* used as non-terminal type in yacc rules */
enum xp_type{
XP_EXP,
XP_AND,
XP_RELEX,
XP_ADD,
XP_UNION,
XP_PATHEXPR,
XP_LOCPATH,
XP_ABSPATH,
XP_RELLOCPATH,
XP_STEP,
XP_NODE, /* s0 is namespace prefix, s1 is name */
XP_NODE_FN,
XP_PRED,
XP_PRI0,
XP_PRIME_NR,
XP_PRIME_STR,
XP_PRIME_FN,
};
/*! XPATH Parsing generates a tree of nodes that is later traversed
*/
struct xpath_tree{
enum xp_type xs_type;
int xs_int;
double xs_double;
char *xs_s0;
char *xs_s1;
struct xpath_tree *xs_c0; /* child 0 */
struct xpath_tree *xs_c1; /* child 1 */
};
typedef struct xpath_tree xpath_tree;
struct clicon_xpath_yacc_arg{ /* XXX: mostly unrelevant */ struct clicon_xpath_yacc_arg{ /* XXX: mostly unrelevant */
const char *xy_name; /* Name of syntax (for error string) */ const char *xy_name; /* Name of syntax (for error string) */
int xy_linenum; /* Number of \n in parsed buffer */ int xy_linenum; /* Number of \n in parsed buffer */

View file

@ -57,6 +57,7 @@
#include "clixon_xpath_ctx.h" #include "clixon_xpath_ctx.h"
#include "clixon_xpath.h" #include "clixon_xpath.h"
#include "clixon_xpath_parse.h" #include "clixon_xpath_parse.h"
#include "clixon_xpath_eval.h"
/* Redefine main lex function so that you can send arguments to it: _yy is added to arg list */ /* Redefine main lex function so that you can send arguments to it: _yy is added to arg list */
#define YY_DECL int clixon_xpath_parselex(void *_yy) #define YY_DECL int clixon_xpath_parselex(void *_yy)

View file

@ -588,6 +588,105 @@ cv_validate_pattern(clicon_handle h,
(rmax && (i) > cv_##type##_get(rmax))) (rmax && (i) > cv_##type##_get(rmax)))
/*! Error messsage for int violating ranges
* @note contains kludge - duplicate loop
*/
static int
outofrange(cg_var *cv0,
cvec *cvv,
char **reason)
{
int retval = -1;
cbuf *cb = NULL;
cg_var *cv1;
cg_var *cv2;
int i;
if ((cb = cbuf_new()) == NULL)
goto done;
cprintf(cb, "Number ");
cv2cbuf(cv0, cb);
cprintf(cb, " out of range: ");
/* Kludge: need to repeat the same loop as in the main function in
cv_validate1 */
i = 0;
while (i<cvec_len(cvv)){
cv1 = cvec_i(cvv, i++); /* Increment to check for max pair */
if (strcmp(cv_name_get(cv1),"range_min") != 0){
clicon_err(OE_YANG, EINVAL, "Internal error, expected range_min");
goto done;
}
if (i<cvec_len(cvv) &&
(cv2 = cvec_i(cvv, i)) != NULL &&
strcmp(cv_name_get(cv2),"range_max") == 0){
i++;
}
else
cv2 = cv1;
if (i>2)
cprintf(cb, ", ");
cv2cbuf(cv1, cb);
cprintf(cb, " - ");
cv2cbuf(cv2, cb);
}
if (reason && (*reason = strdup(cbuf_get(cb))) == NULL)
goto done;
if (cb)
cbuf_free(cb);
retval = 0;
done:
return retval;
}
/*! Error messsage for string violating string limits
* @note contains kludge - duplicate loop
*/
static int
outoflength(uint64_t u64,
cvec *cvv,
char **reason)
{
int retval = -1;
cbuf *cb = NULL;
cg_var *cv1;
cg_var *cv2;
int i;
if ((cb = cbuf_new()) == NULL)
goto done;
cprintf(cb, "String length %" PRIu64 " out of range: ", u64);
/* Kludge: need to repeat the same loop as in the main function in
cv_validate1 */
i = 0;
while (i<cvec_len(cvv)){
cv1 = cvec_i(cvv, i++); /* Increment to check for max pair */
if (strcmp(cv_name_get(cv1),"range_min") != 0){
clicon_err(OE_YANG, EINVAL, "Internal error, expected range_min");
goto done;
}
if (i<cvec_len(cvv) &&
(cv2 = cvec_i(cvv, i)) != NULL &&
strcmp(cv_name_get(cv2),"range_max") == 0){
i++;
}
else
cv2 = cv1;
if (i>2)
cprintf(cb, ", ");
cv2cbuf(cv1, cb);
cprintf(cb, " - ");
cv2cbuf(cv2, cb);
}
if (reason && (*reason = strdup(cbuf_get(cb))) == NULL)
goto done;
if (cb)
cbuf_free(cb);
retval = 0;
done:
return retval;
}
/*! Validate CLIgen variable /*! Validate CLIgen variable
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] cv A cligen variable to validate. This is a correctly parsed cv. * @param[in] cv A cligen variable to validate. This is a correctly parsed cv.
@ -600,6 +699,7 @@ cv_validate_pattern(clicon_handle h,
* @retval 0 Validation not OK, malloced reason is returned. Free reason with free() * @retval 0 Validation not OK, malloced reason is returned. Free reason with free()
* @retval 1 Validation OK * @retval 1 Validation OK
* @note reason if given must be freed by caller * @note reason if given must be freed by caller
* @see cv_validate Corresponding type check in cligen
*/ */
static int static int
cv_validate1(clicon_handle h, cv_validate1(clicon_handle h,
@ -705,14 +805,13 @@ cv_validate1(clicon_handle h,
/* Check fails */ /* Check fails */
if (i==cvec_len(cvv)){ /* And it is last */ if (i==cvec_len(cvv)){ /* And it is last */
if (reason){ if (reason){
if (reti) if (reti || retu){
*reason = cligen_reason("Number out of range: %" if (outofrange(cv, cvv, reason) < 0)
PRId64, ii); goto done;
else if (retu) }
*reason = cligen_reason("Number out of range: %"
PRIu64, uu);
else else
*reason = cligen_reason("string length out of range: %" PRIu64, uu); if (outoflength(uu, cvv, reason) < 0)
goto done;
} }
goto fail; goto fail;
} }
@ -1317,13 +1416,14 @@ yang_type_resolve(yang_stmt *yorig,
* *
* @code * @code
* yang_stmt *yrestype; * yang_stmt *yrestype;
* char *origtype = NULL;
* int options; * int options;
* cvec *cvv = NULL; * cvec *cvv = NULL;
* cvec *patterns = cvec_new(0); * cvec *patterns = cvec_new(0);
* cvec *regexps = cvec_new(0); * cvec *regexps = cvec_new(0);
* uint8_t fraction; * uint8_t fraction;
* *
* if (yang_type_get(ys, &type, &yrestype, &options, &cvv, * if (yang_type_get(ys, &origtype, &yrestype, &options, &cvv,
* patterns, regexps, &fraction) < 0) * patterns, regexps, &fraction) < 0)
* goto err; * goto err;
* if (yrestype == NULL) # unresolved * if (yrestype == NULL) # unresolved

View file

@ -6,7 +6,8 @@
: ${pattern:=test_*.sh} : ${pattern:=test_*.sh}
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
echo "usage: $0 # detailed logs and stopon first error" echo "usage: $0 # detailed logs and stop on first error. Use pattern=\"\" $0 to"
echo " Use pattern=<pattern> $0 to narrow down test cases"
exit -1 exit -1
fi fi

View file

@ -86,7 +86,20 @@ done
testnr=0 testnr=0
for c in $cmds; do for c in $cmds; do
if [ $testnr != 0 ]; then echo; fi if [ $testnr != 0 ]; then echo; fi
echo "Mem test for $c" echo "Mem test $c begin"
echo "=================" length=$(echo "Mem test $c begin" | wc -c)
let i=1
while [ $i -lt $length ]; do
echo -n "="
let i++
done
echo
memonce $c memonce $c
echo "Mem test $c done"
let i=1
while [ $i -lt $length ]; do
echo -n "="
let i++
done
echo
done done

View file

@ -154,7 +154,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
# mandatory-leaf See RFC7950 Sec 7.17 # mandatory-leaf See RFC7950 Sec 7.17

View file

@ -124,7 +124,9 @@ new "start restconf daemon"
start_restconf -f $cfg start_restconf -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
# First vanilla (protocol) case # First vanilla (protocol) case
new "netconf validate empty" new "netconf validate empty"

View file

@ -48,7 +48,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "cli read and add entry to existing history" new "cli read and add entry to existing history"

View file

@ -85,7 +85,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "cli enabled feature" new "cli enabled feature"

View file

@ -106,6 +106,36 @@ cat <<EOF > $fyang
container aes-parameters { container aes-parameters {
when "../crypto = 'mc:aes'"; when "../crypto = 'mc:aes'";
} }
identity acl-base;
typedef acl-type {
description "problem detected in ietf-access-control-list.yang";
type identityref {
base acl-base;
}
}
identity ipv4-acl-type {
base mc:acl-base;
}
identity ipv6-acl-type {
base mc:acl-base;
}
container acls {
list acl {
key name;
leaf name {
type string;
}
leaf type {
type acl-type;
}
}
}
identity empty; /* some errors with an empty identity set */
leaf e {
type identityref {
base mc:empty;
}
}
} }
EOF EOF
@ -120,7 +150,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set crypto to aes" new "Set crypto to aes"
@ -186,6 +216,43 @@ expectfn "$clixon_cli -1 -f $cfg -l o set crypto des:des3" 0 "^$"
new "cli validate" new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$" expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
new "Netconf set acl-type"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><acls xmlns="urn:example:my-crypto"><acl><name>x</name><type>mc:ipv4-acl-type</type></acl></acls></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "netconf validate "
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Netconf set undefined acl-type"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><acls xmlns="urn:example:my-crypto"><acl><name>x</name><type>undefined</type></acl></acls></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "netconf validate fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, mc:undefined not derived from acl-base</error-message></rpc-error></rpc-reply>]]>]]>'
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "CLI set acl-type"
expectfn "$clixon_cli -1 -f $cfg -l o set acls acl x type mc:ipv4-acl-type" 0 "^$"
new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
new "CLI set wrong acl-type"
expectfn "$clixon_cli -1 -f $cfg -l o set acls acl x type undefined" 0 "^$"
new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 255 "Identityref validation failed"
# test empty identityref list
new "cli set empty"
expectfn "$clixon_cli -1 -f $cfg -l o set e undefined" 0 "^$"
new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 255 "Identityref validation failed"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
if [ $BE -eq 0 ]; then if [ $BE -eq 0 ]; then
exit # BE exit # BE
fi fi

View file

@ -26,7 +26,6 @@ cat <<EOF > $cfg
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK> <CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<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_CACHE>true</CLICON_XMLDB_CACHE>
</clixon-config> </clixon-config>
EOF EOF

View file

@ -125,7 +125,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "leafref base config" new "leafref base config"

View file

@ -115,7 +115,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "minmax: minimal" new "minmax: minimal"

View file

@ -124,16 +124,15 @@ fi
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf" sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)" new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a start_restconf -f $cfg -- -a
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "auth get" new "auth get"
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'null expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}} '
'
# explicitly disable nacm (regression on netgate bug) # explicitly disable nacm (regression on netgate bug)
new "disable nacm" new "disable nacm"

View file

@ -101,7 +101,6 @@ EOF
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf" sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)" new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a start_restconf -f $cfg -- -a
@ -109,7 +108,6 @@ EOF
wait_backend wait_backend
wait_restconf wait_restconf
#----------- First get #----------- First get
case "$ret1" in case "$ret1" in
0) ret='{"nacm-example:x": 42} 0) ret='{"nacm-example:x": 42}
@ -117,8 +115,7 @@ EOF
;; ;;
1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' 1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} '
;; ;;
2) ret='null 2) ret='{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}} '
'
;; ;;
esac esac
@ -142,8 +139,7 @@ EOF
;; ;;
1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' 1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} '
;; ;;
2) ret='null 2) ret='{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}} '
'
;; ;;
3) ret='{"nacm-example:x": 42} 3) ret='{"nacm-example:x": 42}
' '

View file

@ -139,12 +139,12 @@ fi
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf" sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)" new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a start_restconf -f $cfg -- -a
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "auth set authentication config" new "auth set authentication config"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -200,8 +200,7 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/clixon-e
' '
new "limit read other module fail" new "limit read other module fail"
expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'null expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}} '
'
new "limit read state OK" new "limit read state OK"
expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" 0 '{"clixon-example:state": {"op": ["42","41","43"]}} expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" 0 '{"clixon-example:state": {"op": ["42","41","43"]}}

View file

@ -148,12 +148,12 @@ fi
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf" sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)" new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a start_restconf -f $cfg -- -a
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
# Set nacm from scratch # Set nacm from scratch
nacm(){ nacm(){

View file

@ -148,12 +148,12 @@ fi
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf" sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)" new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a start_restconf -f $cfg -- -a
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "auth set authentication config" new "auth set authentication config"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -191,9 +191,8 @@ expecteq "$(curl -u guest:bar -sS -X DELETE http://localhost/restconf/data)" 0 '
new "deny-delete-config: limited fail (restconf) ok" new "deny-delete-config: limited fail (restconf) ok"
expecteq "$(curl -u wilma:bar -sS -X DELETE http://localhost/restconf/data)" 0 '' expecteq "$(curl -u wilma:bar -sS -X DELETE http://localhost/restconf/data)" 0 ''
new "admin get nacm (should be null)" new "admin get nacm (should fail)"
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'null expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}} '
'
new "deny-delete-config: admin ok (restconf)" new "deny-delete-config: admin ok (restconf)"
expecteq "$(curl -u andy:bar -sS -X DELETE http://localhost/restconf/data)" 0 '' expecteq "$(curl -u andy:bar -sS -X DELETE http://localhost/restconf/data)" 0 ''

View file

@ -162,7 +162,7 @@ if [ $BE -ne 0 ]; then
start_backend -s running -f $cfg -- -s start_backend -s running -f $cfg -- -s
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
# STATE (should not be ordered) # STATE (should not be ordered)

View file

@ -137,7 +137,7 @@ new "restconf DELETE"
expectfn 'curl -s -X DELETE http://localhost/restconf/data/example:cont1' 0 "" expectfn 'curl -s -X DELETE http://localhost/restconf/data/example:cont1' 0 ""
new "restconf GET null datastore" new "restconf GET null datastore"
expectfn "curl -s -X GET http://localhost/restconf/data/example:cont1" 0 'null' expectfn "curl -s -X GET http://localhost/restconf/data/example:cont1" 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}}'
new "restconf POST initial tree" new "restconf POST initial tree"
expectfn 'curl -s -X POST -d {"example:cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 "" expectfn 'curl -s -X POST -d {"example:cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
@ -149,7 +149,7 @@ new "restconf DELETE whole datastore"
expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 "" expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 ""
new "restconf GET null datastore" new "restconf GET null datastore"
expectfn "curl -s -X GET http://localhost/restconf/data/example:cont1" 0 'null' expectfn "curl -s -X GET http://localhost/restconf/data/example:cont1" 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}}'
new "restconf PUT initial datastore" new "restconf PUT initial datastore"
expectfn 'curl -s -X PUT -d {"data":{"example:cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 "" expectfn 'curl -s -X PUT -d {"data":{"example:cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""

120
test/test_restconf_err.sh Executable file
View file

@ -0,0 +1,120 @@
#!/bin/bash
# Restconf error-code functionality
# See RFC8040
# Testcases:
# Sec 4.3 (GET): If a retrieval request for a data resource represents an
# instance that does not exist, then an error response containing a "404 Not
# Found" status-line MUST be returned by the server. The error-tag
# value "invalid-value" is used in this case.
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
APPNAME=example
cfg=$dir/conf.xml
fyang=$dir/restconf.yang
fxml=$dir/initial.xml
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>$dir/restconf.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
</clixon-config>
EOF
cat <<EOF > $fyang
module example{
yang-version 1.1;
namespace "urn:example:clixon";
prefix ex;
list a {
key k;
leaf k {
type int32;
}
leaf description{
type string;
}
leaf b{
type string;
}
container c{
presence "for test";
}
list d{
key k;
leaf k {
type string;
}
}
}
}
EOF
# Initial tree
XML=$(cat <<EOF
<a xmlns="urn:example:clixon"><k>0</k><description>No leaf b, No container c, No leaf d</description></a>
EOF
)
new "test params: -f $cfg"
if [ $BE -ne 0 ]; then
new "kill old backend"
sudo clixon_backend -zf $cfg
if [ $? -ne 0 ]; then
err
fi
sudo pkill clixon_backend # to be sure
new "start backend -s init -f $cfg"
start_backend -s init -f $cfg
fi
new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
new "start restconf daemon"
start_restconf -f $cfg
new "waiting"
wait_backend
wait_restconf
new "restconf POST initial tree"
expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+xml' -d "$XML" http://localhost/restconf/data)" 0 ''
new "restconf GET initial datastore"
expecteq "$(curl -s -X GET -H 'Accept: application/yang-data+xml' http://localhost/restconf/data/example:a)" 0 "$XML
"
new "restconf GET non-existent container header"
expectfn "curl -s -I -X GET http://localhost/restconf/data/example:a/c" 0 "HTTP/1.1 404 Not Found"
new "restconf GET non-existent container body"
expectfn "curl -s -X GET http://localhost/restconf/data/example:a/c" 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-type": "application","error-tag": "invalid-value","error-severity": "error","error-message": "Instance does not exist"}}}}'
new "Kill restconf daemon"
stop_restconf
if [ $BE -eq 0 ]; then
exit # BE
fi
new "Kill backend"
# Check if premature kill
pid=`pgrep -u root -f clixon_backend`
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
stop_backend -f $cfg
rm -rf $dir

View file

@ -68,7 +68,8 @@ testrun(){
start_restconf -f $cfg -y $fyang $option start_restconf -f $cfg -y $fyang $option
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "restconf put 42" new "restconf put 42"
expecteq "$(curl -s -X PUT http://localhost/restconf/data/example:x/y=42 -d '{"example:y":{"a":"42","b":"42"}}')" 0 "" expecteq "$(curl -s -X PUT http://localhost/restconf/data/example:x/y=42 -d '{"example:y":{"a":"42","b":"42"}}')" 0 ""

View file

@ -50,7 +50,9 @@ new "start restconf daemon"
start_restconf -f $cfg start_restconf -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "rpc tests" new "rpc tests"

View file

@ -86,7 +86,7 @@ testrun(){
start_backend -s $mode -f $cfg -c $dir/extra_db start_backend -s $mode -f $cfg -c $dir/extra_db
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
else else
new "Restart backend as eg follows: -Ff $cfg -s $mode -c $dir/extra_db # $BETIMEOUT s" new "Restart backend as eg follows: -Ff $cfg -s $mode -c $dir/extra_db # $BETIMEOUT s"
sleep $BETIMEOUT sleep $BETIMEOUT

View file

@ -121,8 +121,9 @@ if [ $BE -ne 0 ]; then
fi fi
new "start backend -s init -f $cfg -l f$flog -- -t /x/y[a=$errnr]" new "start backend -s init -f $cfg -l f$flog -- -t /x/y[a=$errnr]"
start_backend -s init -f $cfg -l f$flog -- -t /x/y[a=$errnr] # -t means transaction logging start_backend -s init -f $cfg -l f$flog -- -t /x/y[a=$errnr] # -t means transaction logging
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
let nr=0 let nr=0
@ -177,7 +178,7 @@ new "3. Validate system-error config (9999 not in range)"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config><x xmlns='urn:example:clixon'><y><a>$nr</a><b>9999</b></y></x></config></edit-config></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config><x xmlns='urn:example:clixon'><y><a>$nr</a><b>9999</b></y></x></config></edit-config></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
new "Validate system-error validate (should fail)" new "Validate system-error validate (should fail)"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>b</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range: 9999</error-message></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>b</bad-element></error-info><error-severity>error</error-severity><error-message>Number 9999 out of range: 0 - 100</error-message></rpc-error></rpc-reply>]]>]]>$'
new "Validate system-error discard-changes" new "Validate system-error 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>]]>]]>$"

View file

@ -192,6 +192,10 @@ module example{
pattern '[a-zA-Z_][a-zA-Z0-9_\-.]*'; pattern '[a-zA-Z_][a-zA-Z0-9_\-.]*';
} }
} }
leaf bool {
description "For testing different truth values in CLI";
type boolean;
}
} }
EOF EOF
@ -231,14 +235,14 @@ EOF
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "cli set transitive string. type is alpha followed by number and is defined in three levels of modules" new "cli set transitive string. type is alpha followed by number and is defined in three levels of modules"
expectfn "$clixon_cli -1f $cfg -l o set c talle x99" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set c talle x99" 0 '^$'
new "cli set transitive string error. Wrong type" new "cli set transitive string error. Wrong type"
expectfn "$clixon_cli -1f $cfg -l o set c talle 9xx" 255 '^CLI syntax error: "set c talle 9xx": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set c talle 9xx" 255 '^CLI syntax error: "set c talle 9xx": regexp match fail: 9xx does not match \[a-z\]\[0-9\]\*$'
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>]]>]]>$"
@ -266,10 +270,10 @@ EOF
expectfn "$clixon_cli -1f $cfg -l o -l o validate" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o -l o validate" 0 '^$'
new "cli set transitive union error. should fail" new "cli set transitive union error. should fail"
expectfn "$clixon_cli -1f $cfg -l o set c ulle kalle" 255 '^CLI syntax error: "set c ulle kalle": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set c ulle kalle" 255 "^CLI syntax error: \"set c ulle kalle\": 'kalle' is not a number$"
new "cli set transitive union error int" new "cli set transitive union error int"
expectfn "$clixon_cli -1f $cfg -l o set c ulle 55" 255 '^CLI syntax error: "set c ulle 55": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set c ulle 55" 255 '^CLI syntax error: "set c ulle 55": Number 55 out of range: 4 - 44$'
new "netconf set transitive union error int" new "netconf set transitive union error int"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><c xmlns="urn:example:clixon"><ulle>55</ulle></c></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><c xmlns="urn:example:clixon"><ulle>55</ulle></c></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>"
@ -354,13 +358,13 @@ EOF
#expectfn "$clixon_cli -1f $cfg -l o set num1 \-100" 0 '^$' #expectfn "$clixon_cli -1f $cfg -l o set num1 \-100" 0 '^$'
new "cli range test num1 2 error" new "cli range test num1 2 error"
expectfn "$clixon_cli -1f $cfg -l o set num1 2" 255 '^CLI syntax error: "set num1 2": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set num1 2" 255 '^CLI syntax error: "set num1 2": Number 2 out of range: 1 - 1$'
new "netconf range set num1 -1" new "netconf range set num1 -1"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num1 xmlns="urn:example:clixon">-1</num1></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num1 xmlns="urn:example:clixon">-1</num1></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate num1 -1 wrong" new "netconf validate num1 -1 wrong"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num1</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range: -1</error-message></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num1</bad-element></error-info><error-severity>error</error-severity><error-message>Number -1 out of range: 1 - 1</error-message></rpc-error></rpc-reply>]]>]]>$'
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>]]>]]>$"
@ -368,19 +372,19 @@ EOF
#-------- num2 range and blanks #-------- num2 range and blanks
new "cli range test num2 3 error" new "cli range test num2 3 error"
expectfn "$clixon_cli -1f $cfg -l o set num2 3" 255 '^CLI syntax error: "set num2 3": Number out of range: 3$' expectfn "$clixon_cli -1f $cfg -l o set num2 3" 255 '^CLI syntax error: "set num2 3": Number 3 out of range: 4 - 4000$'
new "cli range test num2 1000 ok" new "cli range test num2 1000 ok"
expectfn "$clixon_cli -1f $cfg -l o set num2 1000" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set num2 1000" 0 '^$'
new "cli range test num2 5000 error" new "cli range test num2 5000 error"
expectfn "$clixon_cli -1f $cfg -l o set num2 5000" 255 '^CLI syntax error: "set num2 5000": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set num2 5000" 255 '^CLI syntax error: "set num2 5000": Number 5000 out of range: 4 - 4000$'
new "netconf range set num2 3 fail" new "netconf range set num2 3 fail"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num2 xmlns="urn:example:clixon">3</num2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num2 xmlns="urn:example:clixon">3</num2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate num2 3 fail" new "netconf validate num2 3 fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num2</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range: 3</error-message></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num2</bad-element></error-info><error-severity>error</error-severity><error-message>Number 3 out of range: 4 - 4000</error-message></rpc-error></rpc-reply>]]>]]>$'
new "netconf range set num2 1000 ok" new "netconf range set num2 1000 ok"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num2 xmlns="urn:example:clixon">1000</num2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num2 xmlns="urn:example:clixon">1000</num2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -392,7 +396,7 @@ EOF
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num2 xmlns="urn:example:clixon">5000</num2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num2 xmlns="urn:example:clixon">5000</num2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate num2 5000 fail" new "netconf validate num2 5000 fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num2</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range: 5000</error-message></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num2</bad-element></error-info><error-severity>error</error-severity><error-message>Number 5000 out of range: 4 - 4000</error-message></rpc-error></rpc-reply>]]>]]>$'
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>]]>]]>$"
@ -403,7 +407,7 @@ EOF
expectfn "$clixon_cli -1f $cfg -l o set num3 42" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set num3 42" 0 '^$'
new "cli range test num3 260 fail" new "cli range test num3 260 fail"
expectfn "$clixon_cli -1f $cfg -l o set num3 260" 255 '^CLI syntax error: "set num3 260": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set num3 260" 255 '^CLI syntax error: "set num3 260": Number 260 out of range: 0 - 255$'
new "cli range test num3 -1 fail" new "cli range test num3 -1 fail"
expectfn "$clixon_cli -1f $cfg -l o set num3 -1" 255 "CLI syntax error:" expectfn "$clixon_cli -1f $cfg -l o set num3 -1" 255 "CLI syntax error:"
@ -412,7 +416,7 @@ EOF
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num3 xmlns="urn:example:clixon">260</num3></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num3 xmlns="urn:example:clixon">260</num3></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate num3 260 fail" new "netconf validate num3 260 fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num3</bad-element></error-info><error-severity>error</error-severity><error-message>260 is out of range(type is uint8)</error-message></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num3</bad-element></error-info><error-severity>error</error-severity><error-message>Number 260 out of range: 0 - 255</error-message></rpc-error></rpc-reply>]]>]]>$'
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>]]>]]>$"
@ -420,19 +424,19 @@ EOF
#-------- num4 multiple ranges 1..2 | 42..50 #-------- num4 multiple ranges 1..2 | 42..50
new "cli range test num4 multiple 0 fail" new "cli range test num4 multiple 0 fail"
expectfn "$clixon_cli -1f $cfg -l o set num4 0" 255 '^CLI syntax error: "set num4 0": Number out of range: 0$' expectfn "$clixon_cli -1f $cfg -l o set num4 0" 255 '^CLI syntax error: "set num4 0": Number 0 out of range: 1 - 2, 42 - 50$'
new "cli range test num4 multiple 2 ok" new "cli range test num4 multiple 2 ok"
expectfn "$clixon_cli -1f $cfg -l e set num4 2" 0 '^$' expectfn "$clixon_cli -1f $cfg -l e set num4 2" 0 '^$'
new "cli range test num4 multiple 20 fail" new "cli range test num4 multiple 20 fail"
expectfn "$clixon_cli -1f $cfg -l o set num4 20" 255 '^CLI syntax error: "set num4 20": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set num4 20" 255 '^CLI syntax error: "set num4 20": Number 20 out of range: 1 - 2, 42 - 50$'
new "cli range test num4 multiple 42 ok" new "cli range test num4 multiple 42 ok"
expectfn "$clixon_cli -1f $cfg -l o set num4 42" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set num4 42" 0 '^$'
new "cli range test num4 multiple 99 fail" new "cli range test num4 multiple 99 fail"
expectfn "$clixon_cli -1f $cfg -l o set num4 99" 255 '^CLI syntax error: "set num4 99": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set num4 99" 255 '^CLI syntax error: "set num4 99": Number 99 out of range: 1 - 2, 42 - 50$'
new "netconf range set num4 multiple 2" new "netconf range set num4 multiple 2"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num4 xmlns="urn:example:clixon">42</num4></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><num4 xmlns="urn:example:clixon">42</num4></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -467,7 +471,7 @@ EOF
expectfn "$clixon_cli -1f $cfg -l o set dec 15.0" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set dec 15.0" 0 '^$'
new "cli range dec64 multiple 30.0 fail" new "cli range dec64 multiple 30.0 fail"
expectfn "$clixon_cli -1f $cfg -l o set dec 30.0" 255 '^CLI syntax error: "set dec 30.0": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set dec 30.0" 255 '^CLI syntax error: "set dec 30.0": Number 30.000 out of range: -3.500 - -2.500, 0.000 - 0.000, 10.000 - 20.000$'
new "dec64 discard-changes" new "dec64 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>]]>]]>$"
@ -477,7 +481,7 @@ EOF
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-3.59</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-3.59</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf range dec64 -3.59 validate fail" new "netconf range dec64 -3.59 validate fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number -3.590 out of range'
new "netconf range dec64 -3.5" new "netconf range dec64 -3.5"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-3.500</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-3.500</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -489,13 +493,13 @@ EOF
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-2</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-2</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf range dec64 -2 validate fail" new "netconf range dec64 -2 validate fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number -2.000 out of range'
new "netconf range dec64 -0.001" new "netconf range dec64 -0.001"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-0.001</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">-0.001</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf range dec64 -0.001 validate fail" new "netconf range dec64 -0.001 validate fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number -0.001 out of range'
new "netconf range dec64 0.0" new "netconf range dec64 0.0"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">0.0</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">0.0</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -507,18 +511,18 @@ EOF
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">+0.001</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><dec xmlns="urn:example:clixon">+0.001</dec></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf range dec64 +0.001 validate fail" new "netconf range dec64 +0.001 validate fail"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>dec</bad-element></error-info><error-severity>error</error-severity><error-message>Number 0.001 out of range'
#----------------string ranges--------------------- #----------------string ranges---------------------
#-------- len1 single range (2) #-------- len1 single range (2)
new "cli length test len1 1 fail" new "cli length test len1 1 fail"
expectfn "$clixon_cli -1f $cfg -l o set len1 x" 255 '^CLI syntax error: "set len1 x": String length not within limits: 1$' expectfn "$clixon_cli -1f $cfg -l o set len1 x" 255 '^CLI syntax error: "set len1 x": String length 1 out of range: 2 - 2$'
new "cli length test len1 2 OK" new "cli length test len1 2 OK"
expectfn "$clixon_cli -1f $cfg -l o set len1 xy" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set len1 xy" 0 '^$'
new "cli length test len1 3 error" new "cli length test len1 3 error"
expectfn "$clixon_cli -1f $cfg -l o set len1 hej" 255 '^CLI syntax error: "set len1 hej": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set len1 hej" 255 '^CLI syntax error: "set len1 hej": String length 3 out of range: 2 - 2$'
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>]]>]]>$"
@ -527,12 +531,12 @@ EOF
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><len1 xmlns="urn:example:clixon">x</len1></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><len1 xmlns="urn:example:clixon">x</len1></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate len1 1 wrong" new "netconf validate len1 1 wrong"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>len1</bad-element></error-info><error-severity>error</error-severity><error-message>string length out of range: 1</error-message></rpc-error></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>len1</bad-element></error-info><error-severity>error</error-severity><error-message>String length 1 out of range: 2 - 2</error-message></rpc-error></rpc-reply>]]>]]>$'
#-------- len2 range and blanks #-------- len2 range and blanks
new "cli length test len2 3 error" new "cli length test len2 3 error"
expectfn "$clixon_cli -1f $cfg -l o set len2 ab" 255 '^CLI syntax error: "set len2 ab": String length not within limits: 2$' expectfn "$clixon_cli -1f $cfg -l o set len2 ab" 255 '^CLI syntax error: "set len2 ab": String length 2 out of range: 4 - 4000$'
new "cli length test len2 42 ok" new "cli length test len2 42 ok"
expectfn "$clixon_cli -1f $cfg -l o set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 '^$'
@ -547,32 +551,32 @@ EOF
#-------- len4 multiple ranges 2..3 | 20-29 #-------- len4 multiple ranges 2..3 | 20-29
new "cli length test len4 1 error" new "cli length test len4 1 error"
expectfn "$clixon_cli -1f $cfg -l o set len4 a" 255 '^CLI syntax error: "set len4 a": String length not within limits: 1$' expectfn "$clixon_cli -1f $cfg -l o set len4 a" 255 '^CLI syntax error: "set len4 a": String length 1 out of range: 2 - 3, 20 - 29$'
new "cli length test len4 2 ok" new "cli length test len4 2 ok"
expectfn "$clixon_cli -1f $cfg -l o set len4 ab" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set len4 ab" 0 '^$'
new "cli length test len4 10 error" new "cli length test len4 10 error"
expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghij" 255 '^CLI syntax error: "set len4 abcdefghij": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghij" 255 '^CLI syntax error: "set len4 abcdefghij": String length 10 out of range: 2 - 3, 20 - 29$'
new "cli length test len4 20 ok" new "cli length test len4 20 ok"
expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghija" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghija" 0 '^$'
new "cli length test len4 30 error" new "cli length test len4 30 error"
expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghijabcdefghij" 255 '^CLI syntax error: "set len4 abcdefghijabcdefghijabcdefghij": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghijabcdefghij" 255 '^CLI syntax error: "set len4 abcdefghijabcdefghijabcdefghij": String length 30 out of range: 2 - 3, 20 - 29$'
# XSD schema -> POSIX ECE translation # XSD schema -> POSIX ECE translation
new "cli yang pattern \d ok" new "cli yang pattern \d ok"
expectfn "$clixon_cli -1f $cfg -l o set digit4 0123" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set digit4 0123" 0 '^$'
new "cli yang pattern \d error" new "cli yang pattern \d error"
expectfn "$clixon_cli -1f $cfg -l o set digit4 01b2" 255 '^CLI syntax error: "set digit4 01b2": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set digit4 01b2" 255 '^CLI syntax error: "set digit4 01b2": regexp match fail: 01b2 does not match'
new "cli yang pattern \w ok" new "cli yang pattern \w ok"
expectfn "$clixon_cli -1f $cfg -l o set word4 abc9" 0 '^$' expectfn "$clixon_cli -1f $cfg -l o set word4 abc9" 0 '^$'
new "cli yang pattern \w error" new "cli yang pattern \w error"
expectfn "$clixon_cli -1f $cfg -l o set word4 ab%3" 255 '^CLI syntax error: "set word4 ab%3": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set word4 ab%3" 255 '^CLI syntax error: "set word4 ab%3": regexp match fail: ab%3 does not match'
new "netconf pattern \w" new "netconf pattern \w"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><word4 xmlns="urn:example:clixon">aXG9</word4></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><word4 xmlns="urn:example:clixon">aXG9</word4></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -589,7 +593,6 @@ EOF
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>]]>]]>$"
#------ minus #------ minus
new "type with minus" new "type with minus"
@ -601,6 +604,27 @@ EOF
#new "cli type with minus" #new "cli type with minus"
#expectfn "$clixon_cli -1f $cfg -l o set name my-name" 0 '^$' #expectfn "$clixon_cli -1f $cfg -l o set name my-name" 0 '^$'
#------ cli truth-values: true/on/enable false/off/disable
new "cli truth: true"
expectfn "$clixon_cli -1f $cfg -l o set bool true" 0 '^$'
new "cli truth: false"
expectfn "$clixon_cli -1f $cfg -l o set bool false" 0 '^$'
new "cli truth: on"
expectfn "$clixon_cli -1f $cfg -l o set bool on" 0 '^$'
new "cli verify on translates to true"
expectfn "$clixon_cli -1f $cfg -l o show conf" 0 'bool true;'
new "cli truth: off"
expectfn "$clixon_cli -1f $cfg -l o set bool off" 0 '^$'
new "cli verify off translates to false"
expectfn "$clixon_cli -1f $cfg -l o show conf" 0 'bool false;'
new "cli truth: enable"
expectfn "$clixon_cli -1f $cfg -l o set bool enable" 0 '^$'
new "cli truth: disable"
expectfn "$clixon_cli -1f $cfg -l o set bool disable" 0 '^$'
new "cli truth: wrong"
expectfn "$clixon_cli -1f $cfg -l o set bool wrong" 255 "'wrong' is not a boolean value"
if [ $BE -ne 0 ]; then if [ $BE -ne 0 ]; then
new "Kill backend" new "Kill backend"
# Check if premature kill # Check if premature kill
@ -619,7 +643,7 @@ testrun nocache
# Run with db cache # Run with db cache
testrun cache testrun cache
# Run with # Run with zero-copy XXX does not work
testrun cache-zerocopy #testrun cache-zerocopy
rm -rf $dir rm -rf $dir

317
test/test_type_range.sh Executable file
View file

@ -0,0 +1,317 @@
#!/bin/bash
# Range type tests.
# Mainly error messages and multiple ranges
# Tests all int types including decimal64 and string length ranges
# See also test_type.sh
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
APPNAME=example
# Which format to use as datastore format internally
: ${format:=xml}
cfg=$dir/conf_yang.xml
fyang=$dir/type.yang
dclispec=$dir/clispec/
# XXX: add more types, now only uint8 and int8
cat <<EOF > $fyang
module example{
yang-version 1.1;
namespace "urn:example:clixon";
prefix ex;
typedef tint8{
type int8{
range "1..10 | 14..20";
}
}
typedef tint16{
type int16{
range "1..10 | 14..20";
}
}
typedef tint32{
type int32{
range "1..10 | 14..20";
}
}
typedef tint64{
type int64{
range "1..10 | 14..20";
}
}
typedef tuint8{
type uint8{
range "1..10 | 14..20";
}
}
typedef tuint16{
type uint16{
range "1..10 | 14..20";
}
}
typedef tuint32{
type uint32{
range "1..10 | 14..20";
}
}
typedef tuint64{
type uint64{
range "1..10 | 14..20";
}
}
typedef tdecimal64{
type decimal64{
fraction-digits 3;
range "1..10 | 14..20";
}
}
typedef tstring{
type string{
length "1..10 | 14..20";
}
}
/* here follows constrained ints */
leaf lint8 {
type tint8;
}
leaf lint16 {
type tint16;
}
leaf lint32 {
type tint32;
}
leaf lint64 {
type tint64;
}
leaf luint8 {
type tuint8;
}
leaf luint16 {
type tuint16;
}
leaf luint32 {
type tuint32;
}
leaf luint64 {
type tuint64;
}
leaf ldecimal64 {
type tdecimal64;
}
leaf lstring {
type tstring;
}
/* here follows unlimited ints */
leaf rint8 {
type int8;
}
leaf rint16 {
type int16;
}
leaf rint32 {
type int32;
}
leaf rint64 {
type int64;
}
leaf ruint8 {
type uint8;
}
leaf ruint16 {
type uint16;
}
leaf ruint32 {
type uint32;
}
leaf ruint64 {
type uint64;
}
leaf rdecimal64 {
type decimal64{
fraction-digits 3;
}
}
}
EOF
mkdir $dclispec
# clispec for both generated cli and a hardcoded range check
cat <<EOF > $dclispec/clispec.cli
CLICON_MODE="example";
CLICON_PROMPT="%U@%H> ";
CLICON_PLUGIN="example_cli";
# Manually added (not generated)
manual hint8 <id:int8 range[1:10] range[14:20]>;
manual hint16 <id:int16 range[1:10] range[14:20]>;
manual hint32 <id:int32 range[1:10] range[14:20]>;
manual hint64 <id:int64 range[1:10] range[14:20]>;
manual huint8 <id:uint8 range[1:10] range[14:20]>;
manual huint16 <id:uint16 range[1:10] range[14:20]>;
manual huint32 <id:uint32 range[1:10] range[14:20]>;
manual huint64 <id:uint64 range[1:10] range[14:20]>;
manual hdecimal64 <id:decimal64 range[1:10] range[14:20]>;
manual hstring <id:string length[1:10] length[14:20]>;
# Generated cli
set @datamodel, cli_set();
merge @datamodel, cli_merge();
create @datamodel, cli_create();
show, cli_show_config("candidate", "text", "/");
quit("Quit"), cli_quit();
EOF
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_CLISPEC_DIR>$dclispec</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
<CLICON_XMLDB_FORMAT>$format</CLICON_XMLDB_FORMAT>
</clixon-config>
EOF
# Type range tests.
# Parameters: 1: type (eg uint8)
# 2: val OK
# 3: eval Invalid value
# 4: post (eg .000 - special for decimal64, others should have "")
testrange(){
t=$1
val=$2
eval=$3
post=$4
if [ $t = "string" ]; then # special case for string type error msg
len=$(echo -n "$eval" | wc -c)
errmsg="String length $len out of range: 1$post - 10$post, 14$post - 20$post"
else
errmsg="Number $eval$post out of range: 1$post - 10$post, 14$post - 20$post"
fi
new "generated cli set $t leaf invalid"
expectfn "$clixon_cli -1f $cfg -l o set l$t $eval" 255 "$errmsg";
new "generated cli set $t leaf OK"
expectfn "$clixon_cli -1f $cfg -l o set l$t $val" 0 '^$'
# XXX Error in cligen order: Unknown command vs Number out of range
# olof@vandal> set luint8 0
# CLI syntax error: "set luint8 0": Number 0 is out of range: 14 - 20
# olof@vandal> set luint8 1
# olof@vandal> set luint8 0
# CLI syntax error: "set luint8 0": Unknown command
# (SAME AS FIRST ^)
new "generated cli set $t leaf invalid"
expectfn "$clixon_cli -1f $cfg -l o set l$t $eval" 255 "$errmsg"
new "manual cli set $t leaf OK"
expectfn "$clixon_cli -1f $cfg -l o man h$t $val" 0 '^$'
new "manual cli set $t leaf invalid"
echo "$clixon_cli -1f $cfg -l o set h$t $eval"
expectfn "$clixon_cli -1f $cfg -l o set l$t $eval" 255 "$errmsg"
new "discard"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Netconf set invalid $t leaf"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config><l$t xmlns=\"urn:example:clixon\">$eval</l$t></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get config"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><l$t xmlns=\"urn:example:clixon\">$eval</l$t></data></rpc-reply>]]>]]>$"
new "netconf validate invalid range"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>l$t</bad-element></error-info><error-severity>error</error-severity><error-message>$errmsg</error-message></rpc-error></rpc-reply>]]>]]>$"
new "discard"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
}
# Type unlimited value range test. Only test invalid number out of range of type
# Parameters: 1: type (eg uint8)
# 2: val
# 3: post (eg .000 - special for decimal64, others should have "")
testunlimit(){
t=$1
val=$2
rmin=$3
rmax=$4
post=$5
errmsg="Number $val$post out of range: $rmin$post - $rmax$post"
new "Netconf set invalid $t leaf"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><edit-config><target><candidate/></target><config><r$t xmlns=\"urn:example:clixon\">$val</r$t></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate invalid range"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>r$t</bad-element></error-info><error-severity>error</error-severity><error-message>$errmsg</error-message></rpc-error></rpc-reply>]]>]]>$"
new "discard"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
}
if [ $BE -ne 0 ]; then
new "kill old backend"
sudo clixon_backend -zf $cfg
if [ $? -ne 0 ]; then
err
fi
new "start backend -s init -f $cfg"
start_backend -s init -f $cfg
new "waiting"
wait_backend
fi
new "test params: -f $cfg"
# Test all int types
testunlimit int8 300 -128 127 ""
testunlimit int16 73000 -32768 32767 ""
testunlimit int32 4900000000 -2147483648 2147483647 ""
testunlimit int64 49739274983274983274983274 -9223372036854775808 9223372036854775807 ""
testunlimit uint8 300 0 255 ""
testunlimit uint16 73000 0 65535 ""
testunlimit uint32 4900000000 0 4294967295 ""
testunlimit uint64 49739274983274983274983274 0 18446744073709551615 ""
#testunlimit decimal64 49739274983274983274983274 -9223372036854775808 9223372036854775807 ".000"
# Test all int types
for t in int8 int16 int32 int64 uint8 uint16 uint32 uint64; do
testrange $t 1 0 ""
done
# decimal64 requires 3 decimals as postfix
testrange decimal64 1 0 ".000"
# test string with lengthlimit
testrange string "012" "01234567890" ""
if [ $BE -ne 0 ]; then
new "Kill backend"
# Check if premature kill
pid=`pgrep -u root -f clixon_backend`
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
stop_backend -f $cfg
fi
rm -rf $dir

View file

@ -89,7 +89,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "cli set transitive string" new "cli set transitive string"
@ -99,7 +99,7 @@ new "cli set transitive union"
expectfn "$clixon_cli -1f $cfg -l o set c ulle 33" 0 "^$" expectfn "$clixon_cli -1f $cfg -l o set c ulle 33" 0 "^$"
new "cli set transitive union error" new "cli set transitive union error"
expectfn "$clixon_cli -1f $cfg -l o set c ulle kalle" 255 '^CLI syntax error: "set c ulle kalle": Unknown command$' expectfn "$clixon_cli -1f $cfg -l o set c ulle kalle" 255 "^CLI syntax error: \"set c ulle kalle\": 'kalle' is not a number$"
if [ $BE -eq 0 ]; then if [ $BE -eq 0 ]; then
exit # BE exit # BE

View file

@ -92,7 +92,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
# RFC test two-field caes # RFC test two-field caes

View file

@ -265,7 +265,7 @@ runtest(){
start_backend -s $mode -f $cfg -o "CLICON_XMLDB_MODSTATE=$modstate" start_backend -s $mode -f $cfg -o "CLICON_XMLDB_MODSTATE=$modstate"
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
else else
new "Restart backend as eg follows: -Ff $cfg -s $mode -o \"CLICON_XMLDB_MODSTATE=$modstate\" ($BETIMEOUT s)" new "Restart backend as eg follows: -Ff $cfg -s $mode -o \"CLICON_XMLDB_MODSTATE=$modstate\" ($BETIMEOUT s)"
sleep $BETIMEOUT sleep $BETIMEOUT

View file

@ -254,8 +254,6 @@ if [ $BE -ne 0 ]; then
new "start backend -s $mode -f $cfg" new "start backend -s $mode -f $cfg"
start_backend -s $mode -f $cfg start_backend -s $mode -f $cfg
fi fi
new "waiting"
sleep $RCWAIT
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf sudo pkill -u www-data clixon_restconf
@ -264,7 +262,8 @@ new "start restconf daemon"
start_restconf -f $cfg start_restconf -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "Check running db content" new "Check running db content"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply><data>$XML</data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply><data>$XML</data></rpc-reply>]]>]]>$"

View file

@ -265,8 +265,6 @@ testrun(){
new "start backend -s startup -f $cfg -- -u" new "start backend -s startup -f $cfg -- -u"
start_backend -s startup -f $cfg -- -u start_backend -s startup -f $cfg -- -u
fi fi
new "waiting"
sleep $RCWAIT
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf sudo pkill -u www-data clixon_restconf
@ -275,7 +273,8 @@ testrun(){
start_restconf -f $cfg start_restconf -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "Check running db content" new "Check running db content"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply><data>$runxml</data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply><data>$runxml</data></rpc-reply>]]>]]>$"

View file

@ -112,8 +112,6 @@ if [ $BE -ne 0 ]; then
new "start backend -s $mode -f $cfg" new "start backend -s $mode -f $cfg"
start_backend -s $mode -f $cfg start_backend -s $mode -f $cfg
fi fi
new "waiting"
sleep $RCWAIT
new "kill old restconf daemon" new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf sudo pkill -u www-data clixon_restconf
@ -122,7 +120,8 @@ new "start restconf daemon"
start_restconf -f $cfg start_restconf -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "Check running db content is failsafe" new "Check running db content is failsafe"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply><data>$SAMEXML</data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply><data>$SAMEXML</data></rpc-reply>]]>]]>$"

View file

@ -102,7 +102,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "when: add static route" new "when: add static route"

View file

@ -85,7 +85,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "1. Set newex" new "1. Set newex"
@ -134,7 +134,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set oldex" new "Set oldex"
@ -178,7 +178,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set newex" new "Set newex"
@ -222,7 +222,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set oldex" new "Set oldex"
@ -266,7 +266,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set newex" new "Set newex"
@ -312,7 +312,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set oldex" new "Set oldex"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
@ -357,7 +357,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set oldex" new "Set oldex"
@ -403,7 +403,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg start_backend -s init -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "Set oldex" new "Set oldex"

View file

@ -83,7 +83,8 @@ new "start restconf daemon"
start_restconf -f $cfg start_restconf -f $cfg
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
wait_restconf
new "netconf set x in example1" new "netconf set x in example1"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><edit-config><target><candidate/></target><config><x xmlns="urn:example:clixon1">42</x></config></edit-config></rpc>]]>]]>' '^<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><ok/></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><edit-config><target><candidate/></target><config><x xmlns="urn:example:clixon1">42</x></config></edit-config></rpc>]]>]]>' '^<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><ok/></rpc-reply>]]>]]>$'