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
util/clixon_util_datastore
util/clixon_util_insert
util/clixon_util_json
util/clixon_util_stream
util/clixon_util_xml

View file

@ -86,7 +86,15 @@
* 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);`
* `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.
* Accepted:
```
@ -209,7 +217,9 @@
### Minor changes
* Added new API function `xpath_parse()` to split parsing and xml evaluation.
* Rewrote `api_path2xpath` to handle namespaces.
* `api_path2xml_vec` strict mode check added if list key length mismatch
* `startup_extraxml` triggers unnecessary validation
* 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.
@ -260,6 +270,9 @@
### 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
* 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.

View file

@ -214,7 +214,8 @@ startup_common(clicon_handle h,
xt = NULL;
x = 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)
goto done;
}

View file

@ -107,7 +107,7 @@ cli_notification_register(clicon_handle h,
goto done;
}
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;
if (status){ /* start */
@ -119,14 +119,14 @@ cli_notification_register(clicon_handle h,
goto done;
if (cligen_regfd(s, fn, arg) < 0)
goto done;
if (hash_add(cdat, logname, &s, sizeof(s)) == NULL)
if (clicon_hash_add(cdat, logname, &s, sizeof(s)) == NULL)
goto done;
}
else{ /* stop */
if (s_exist != -1){
cligen_unregfd(s_exist);
}
hash_del(cdat, logname);
clicon_hash_del(cdat, logname);
#if 0 /* cant turn off */
if (clicon_rpc_create_subscription(h, status, stream, format, filter, NULL) < 0)
goto done;

View file

@ -163,7 +163,6 @@ cli_callback_generate(clicon_handle h,
return retval;
}
/*! Generate identityref statements for CLI variables
* @param[in] ys Yang statement
* @param[in] ytype Yang union type being resolved
@ -186,13 +185,13 @@ yang2cli_var_identityref(yang_stmt *ys,
char *id;
int i;
/* Add a wildchar string first -let validate take it for default prefix */
cprintf(cb, ">");
if (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){
/* Add a wildchar string first -let validate take it for default prefix */
cprintf(cb, ">");
if (helptext)
cprintf(cb, "(\"%s\")", helptext);
cprintf(cb, "|<%s:%s choice:", yang_argument_get(ys), cvtypestr);
i = 0;
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);
int get_user_cookie(char *cookiestr, char *attribute, char **val);
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_ */

View file

@ -394,13 +394,16 @@ get_user_cookie(char *cookiestr,
* @param[in] xerr XML error message from backend
* @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] code If 0 use rfc8040 sec 7 netconf2restconf error-tag mapping
* otherwise use this code
*/
int
api_return_err(clicon_handle h,
FCGX_Request *r,
cxobj *xerr,
int pretty,
int use_xml)
int use_xml,
int code0)
{
int retval = -1;
cbuf *cb = NULL;
@ -417,8 +420,12 @@ api_return_err(clicon_handle h,
goto ok;
}
tagstr = xml_body(xtag);
if ((code = restconf_err2code(tagstr)) < 0)
code = 500; /* internal server error */
if (code0 != 0)
code = code0;
else{
if ((code = restconf_err2code(tagstr)) < 0)
code = 500; /* internal server error */
}
if ((reason_phrase = restconf_code2reason(code)) == NULL)
reason_phrase="";
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);
int get_user_cookie(char *cookiestr, char *attribute, char **val);
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);
#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)
goto done;
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 ok;
}

View file

@ -216,7 +216,7 @@ api_data_get2(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -233,7 +233,7 @@ api_data_get2(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -252,7 +252,7 @@ api_data_get2(clicon_handle h,
#endif
/* Check if error return */
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 ok;
}
@ -283,7 +283,20 @@ api_data_get2(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 ok;
}
@ -495,7 +508,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -509,7 +522,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -522,7 +535,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -531,7 +544,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -546,7 +559,7 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -568,14 +581,15 @@ api_data_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
goto done;
}
if (debug){
cbuf *ccc=cbuf_new();
if (clicon_xml2cbuf(ccc, xe, 0, 0) < 0)
goto done;
clicon_debug(1, "%s XE:%s", __FUNCTION__, cbuf_get(ccc));
}
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
#if 0
if (debug){
cbuf *ccc=cbuf_new();
if (clicon_xml2cbuf(ccc, xe, 0, 0) < 0)
goto done;
clicon_debug(1, "%s XE:%s", __FUNCTION__, cbuf_get(ccc));
}
#endif
if (api_return_err(h, r, xe, pretty, use_xml, 0) < 0)
goto done;
goto ok;
}
@ -607,7 +621,7 @@ api_data_post(clicon_handle h,
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done;
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 ok;
}
@ -629,7 +643,7 @@ api_data_post(clicon_handle h,
/* log errors from discard, but ignore */
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__);
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 ok;
}
@ -843,7 +857,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -858,7 +872,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -871,7 +885,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -880,7 +894,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -895,7 +909,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -915,7 +929,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -955,7 +969,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -980,7 +994,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -1004,7 +1018,7 @@ api_data_put(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -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);
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done;
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 ok;
}
@ -1062,7 +1075,7 @@ api_data_put(clicon_handle h,
/* log errors from discard, but ignore */
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__);
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;
}
@ -1195,7 +1208,7 @@ api_data_delete(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -1219,7 +1232,7 @@ api_data_delete(clicon_handle h,
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done;
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 ok;
}
@ -1241,7 +1254,7 @@ api_data_delete(clicon_handle h,
/* log errors from discard, but ignore */
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__);
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;
}
@ -1433,7 +1446,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 fail;
}
@ -1446,7 +1459,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 fail;
}
@ -1455,7 +1468,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 fail;
}
@ -1488,7 +1501,7 @@ api_operations_post_input(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 fail;
}
@ -1562,7 +1575,7 @@ api_operations_post_output(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 fail;
}
@ -1599,7 +1612,7 @@ api_operations_post_output(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 fail;
}
@ -1732,7 +1745,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -1751,7 +1764,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -1762,7 +1775,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -1791,7 +1804,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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;
}
@ -1831,7 +1844,7 @@ api_operations_post(clicon_handle h,
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
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 ok;
}
@ -1860,7 +1873,7 @@ api_operations_post(clicon_handle h,
goto done;
/* Local error: return it and quit */
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 ok;
}
@ -1869,7 +1882,7 @@ api_operations_post(clicon_handle h,
if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0)
goto done;
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 ok;
}

View file

@ -269,7 +269,7 @@ restconf_stream(clicon_handle h,
if (clicon_rpc_netconf(h, cbuf_get(cb), &xret, &s) < 0)
goto done;
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 ok;
}
@ -417,7 +417,7 @@ api_stream(clicon_handle h,
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
goto done;
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 ok;
}

View file

@ -42,6 +42,51 @@ Docker is used to build Alpine Linux
### Build docker image
## 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
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;
clicon_hash_t *hash_init (void);
void hash_free (clicon_hash_t *);
clicon_hash_t hash_lookup (clicon_hash_t *head, const char *key);
void *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);
int hash_del (clicon_hash_t *head, const char *key);
int hash_dump(clicon_hash_t *head, FILE *f);
int hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys);
clicon_hash_t *clicon_hash_init (void);
void clicon_hash_free (clicon_hash_t *);
clicon_hash_t clicon_hash_lookup (clicon_hash_t *head, const char *key);
void *clicon_hash_value (clicon_hash_t *head, const char *key, size_t *vlen);
clicon_hash_t clicon_hash_add (clicon_hash_t *head, const char *key, void *val, size_t vlen);
int clicon_hash_del (clicon_hash_t *head, const char *key);
int clicon_hash_dump(clicon_hash_t *head, FILE *f);
int clicon_hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys);
/*
* Macros to iterate over hash contents.
@ -59,24 +59,23 @@ int hash_keys(clicon_hash_t *hash, char ***vector, size_t *nkeys);
*
* Example:
* char *k;
* clicon_hash_t *h = hash_init();
* clicon_hash_t *h = clicon_hash_init();
*
* hash_add(h, "colour", "red", 6);
* hash_add(h, "name", "rudolf" 7);
* hash_add(h, "species", "reindeer" 9);
* clicon_hash_add(h, "colour", "red", 6);
* clicon_hash_add(h, "name", "rudolf" 7);
* clicon_hash_add(h, "species", "reindeer" 9);
*
* hash_each(h, k) {
* printf ("%s = %s\n", k, (char *)hash_value(h, k, NULL));
* clicon_hash_each(h, k) {
* printf ("%s = %s\n", k, (char *)clicon_hash_value(h, k, NULL));
* } hash_each_end();
*/
#define hash_each(__hash__, __key__) \
#define clicon_hash_each(__hash__, __key__) \
{ \
int __i__; \
size_t __n__; \
char **__k__ = hash_keys((__hash__),&__n__); \
if (__k__) { \
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_ */

View file

@ -43,6 +43,7 @@
*/
int netconf_in_use(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_missing_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 */
};
/*
* Variables
*/
extern const map_str2int xpopmap[];
/* 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,
};
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
*/
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
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_flag(cxobj *xcur, cvec *nsc, char *format, uint16_t flags,
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)));
#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_flag(cxobj *xcur, cvec *nsc, char *format, uint16_t flags,
cxobj ***vec, size_t *veclen, ...);
cxobj *xpath_first(cxobj *xcur, cvec *nsc, char *format, ...);
int xpath_vec_bool(cxobj *xcur, cvec *nsc, char *format, ...);
#endif
int xpath_vec_ctx(cxobj *xcur, cvec *nsc, char *xpath, xp_ctx **xrp);
#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_hash.c clixon_options.c clixon_data.c clixon_plugin.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_tree.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;
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 NULL;
}
@ -100,7 +100,7 @@ clicon_dbspec_yang_set(clicon_handle h,
/* 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.
*/
if (hash_add(cdat, "dbspec_yang", &ys, sizeof(ys)) == NULL)
if (clicon_hash_add(cdat, "dbspec_yang", &ys, sizeof(ys)) == NULL)
return -1;
return 0;
}
@ -118,7 +118,7 @@ clicon_nacm_ext(clicon_handle h)
size_t len;
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 NULL;
}
@ -141,7 +141,7 @@ clicon_nacm_ext_set(clicon_handle h,
/* 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.
*/
if (hash_add(cdat, "nacm_xml", &xn, sizeof(xn)) == NULL)
if (clicon_hash_add(cdat, "nacm_xml", &xn, sizeof(xn)) == NULL)
return -1;
return 0;
}
@ -158,7 +158,7 @@ clicon_config_yang(clicon_handle h)
size_t len;
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 NULL;
}
@ -175,7 +175,7 @@ clicon_config_yang_set(clicon_handle h,
/* 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.
*/
if (hash_add(cdat, "control_yang", &ys, sizeof(ys)) == NULL)
if (clicon_hash_add(cdat, "control_yang", &ys, sizeof(ys)) == NULL)
return -1;
return 0;
}
@ -192,7 +192,7 @@ clicon_conf_xml(clicon_handle h)
size_t len;
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 NULL;
}
@ -209,7 +209,7 @@ clicon_conf_xml_set(clicon_handle h,
/* 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.
*/
if (hash_add(cdat, "clixon_conf", &x, sizeof(x)) == NULL)
if (clicon_hash_add(cdat, "clixon_conf", &x, sizeof(x)) == NULL)
return -1;
return 0;
}
@ -223,7 +223,7 @@ clicon_username_get(clicon_handle 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
@ -238,8 +238,8 @@ clicon_username_set(clicon_handle h,
clicon_hash_t *cdat = clicon_data(h);
if (username == NULL)
return hash_del(cdat, "username");
return hash_add(cdat, "username", username, strlen(username)+1)==NULL?-1:0;
return clicon_hash_del(cdat, "username");
return clicon_hash_add(cdat, "username", username, strlen(username)+1)==NULL?-1:0;
}
/*! Get backend daemon startup status
@ -252,7 +252,7 @@ clicon_startup_status_get(clicon_handle h)
clicon_hash_t *cdat = clicon_data(h);
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 STARTUP_ERR;
}
@ -268,7 +268,7 @@ clicon_startup_status_set(clicon_handle h,
enum startup_status status)
{
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 0;
}
@ -284,7 +284,7 @@ clicon_socket_get(clicon_handle h)
clicon_hash_t *cdat = clicon_data(h);
void *p;
if ((p = hash_value(cdat, "socket", NULL)) == NULL)
if ((p = clicon_hash_value(cdat, "socket", NULL)) == NULL)
return -1;
return *(int*)p;
}
@ -302,8 +302,8 @@ clicon_socket_set(clicon_handle h,
clicon_hash_t *cdat = clicon_data(h);
if (s == -1)
return hash_del(cdat, "socket");
return hash_add(cdat, "socket", &s, sizeof(int))==NULL?-1:0;
return clicon_hash_del(cdat, "socket");
return clicon_hash_add(cdat, "socket", &s, sizeof(int))==NULL?-1:0;
}
/*! Get module state cache
@ -319,7 +319,7 @@ clicon_modst_cache_get(clicon_handle h,
clicon_hash_t *cdat = clicon_data(h);
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 NULL;
}
@ -346,7 +346,7 @@ clicon_modst_cache_set(clicon_handle h,
assert(strcmp(xml_name(xms),"modules-state")==0);
if ((x = xml_dup(xms)) == NULL)
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;
ok:
return 0;
@ -363,7 +363,7 @@ clicon_xml_changelog_get(clicon_handle h)
clicon_hash_t *cdat = clicon_data(h);
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 NULL;
}
@ -381,7 +381,7 @@ clicon_xml_changelog_set(clicon_handle 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 0;
}
@ -403,12 +403,12 @@ clicon_argv_get(clicon_handle h,
void *p;
if (argc){
if ((p = hash_value(cdat, "argc", NULL)) == NULL)
if ((p = clicon_hash_value(cdat, "argc", NULL)) == NULL)
return -1;
*argc = *(int*)p;
}
if (argv){
if ((p = hash_value(cdat, "argv", NULL)) == NULL)
if ((p = clicon_hash_value(cdat, "argv", NULL)) == NULL)
return -1;
*argv = (char**)p;
}
@ -444,10 +444,10 @@ clicon_argv_set(clicon_handle h,
memcpy(argvv+1, argv, argc*sizeof(char*));
argvv[0] = prgm;
/* 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;
argc += 1;
if (hash_add(cdat, "argc", &argc, sizeof(argc))==NULL)
if (clicon_hash_add(cdat, "argc", &argc, sizeof(argc))==NULL)
goto done;
retval = 0;
done:
@ -470,7 +470,7 @@ clicon_db_elmnt_get(clicon_handle h,
clicon_hash_t *cdat = clicon_db_elmnt(h);
void *p;
if ((p = hash_value(cdat, db, NULL)) != NULL)
if ((p = clicon_hash_value(cdat, db, NULL)) != NULL)
return (db_elmnt *)p;
return NULL;
}
@ -491,7 +491,7 @@ clicon_db_elmnt_set(clicon_handle 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 0;
}

View file

@ -161,10 +161,10 @@ xmldb_disconnect(clicon_handle h)
int i;
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;
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){
xml_free(de->de_xml);
de->de_xml = NULL;
@ -311,7 +311,7 @@ xmldb_unlock_all(clicon_handle h,
int i;
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;
for (i = 0; i < klen; i++)
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 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){
clicon_err(OE_YANG, ENOENT, "No yang spec");
goto done;

View file

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

View file

@ -115,7 +115,7 @@ hash_bucket(const char *str)
* @see hash_free For freeing the hash-table
*/
clicon_hash_t *
hash_init(void)
clicon_hash_init(void)
{
clicon_hash_t *hash;
@ -133,7 +133,7 @@ hash_init(void)
* @retval void
*/
void
hash_free(clicon_hash_t *hash)
clicon_hash_free(clicon_hash_t *hash)
{
int i;
clicon_hash_t tmp;
@ -157,8 +157,8 @@ hash_free(clicon_hash_t *hash)
* @retval NULL Not found
*/
clicon_hash_t
hash_lookup(clicon_hash_t *hash,
const char *key)
clicon_hash_lookup(clicon_hash_t *hash,
const char *key)
{
uint32_t bkt;
clicon_hash_t h;
@ -183,13 +183,13 @@ hash_lookup(clicon_hash_t *hash,
* @retval NULL Key not found or value NULL
*/
void *
hash_value(clicon_hash_t *hash,
const char *key,
size_t *vlen)
clicon_hash_value(clicon_hash_t *hash,
const char *key,
size_t *vlen)
{
clicon_hash_t h;
h = hash_lookup(hash, key);
h = clicon_hash_lookup(hash, key);
if (h == NULL)
return NULL; /* OK, key not found */
@ -209,10 +209,10 @@ hash_value(clicon_hash_t *hash,
* @note special case val is NULL and vlen==0
*/
clicon_hash_t
hash_add(clicon_hash_t *hash,
const char *key,
void *val,
size_t vlen)
clicon_hash_add(clicon_hash_t *hash,
const char *key,
void *val,
size_t vlen)
{
void *newval = NULL;
clicon_hash_t h;
@ -225,7 +225,7 @@ hash_add(clicon_hash_t *hash,
goto catch;
}
/* 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 ((new = (clicon_hash_t)malloc(sizeof(*new))) == NULL){
clicon_err(OE_UNIX, errno, "malloc: %s", strerror(errno));
@ -283,12 +283,12 @@ catch:
* @retval -1 Key not found
*/
int
hash_del(clicon_hash_t *hash,
const char *key)
clicon_hash_del(clicon_hash_t *hash,
const char *key)
{
clicon_hash_t h;
h = hash_lookup(hash, key);
h = clicon_hash_lookup(hash, key);
if (h == NULL)
return -1;
@ -311,9 +311,9 @@ hash_del(clicon_hash_t *hash,
* @note: vector needs to be deallocated with free
*/
int
hash_keys(clicon_hash_t *hash,
char ***vector,
size_t *nkeys)
clicon_hash_keys(clicon_hash_t *hash,
char ***vector,
size_t *nkeys)
{
int retval = -1;
int bkt;
@ -357,8 +357,8 @@ catch:
* @retval -1 Error
*/
int
hash_dump(clicon_hash_t *hash,
FILE *f)
clicon_hash_dump(clicon_hash_t *hash,
FILE *f)
{
int retval = -1;
int i;
@ -369,10 +369,10 @@ hash_dump(clicon_hash_t *hash,
if (hash == NULL)
goto ok;
if (hash_keys(hash, &keys, &klen) < 0)
if (clicon_hash_keys(hash, &keys, &klen) < 0)
goto done;
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);
}

View file

@ -108,6 +108,48 @@ netconf_in_use(cbuf *cb,
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
*
* The request specifies an unacceptable value for one or more parameters.
@ -120,6 +162,20 @@ netconf_invalid_value(cbuf *cb,
char *type,
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;
char *encstr = NULL;
@ -145,6 +201,7 @@ netconf_invalid_value(cbuf *cb,
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
#endif
}
/*! 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;
cxobj *x = NULL;
if (hash_keys(hash, &keys, &klen) < 0)
if (clicon_hash_keys(hash, &keys, &klen) < 0)
goto done;
for(i = 0; i < klen; i++) {
val = hash_value(hash, keys[i], &vlen);
val = clicon_hash_value(hash, keys[i], &vlen);
if (vlen){
if (((char*)val)[vlen-1]=='\0') /* assume string */
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 */
if (strcmp(name,"CLICON_CONFIGFILE")==0)
continue;
if (hash_add(copt,
if (clicon_hash_add(copt,
name,
body,
strlen(body)+1) == NULL)
@ -284,7 +284,7 @@ clicon_option_add(clicon_handle h,
name, value, name) < 0)
goto done;
}
if (hash_add(copt,
if (clicon_hash_add(copt,
name,
value,
strlen(value)+1) == NULL)
@ -319,10 +319,10 @@ clicon_options_main(clicon_handle h,
/*
* 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);
}
configfile = hash_value(copt, "CLICON_CONFIGFILE", NULL);
configfile = clicon_hash_value(copt, "CLICON_CONFIGFILE", NULL);
clicon_debug(1, "CLICON_CONFIGFILE=%s", configfile);
/* File must end with .xml */
if ((suffix = rindex(configfile, '.')) != NULL){
@ -385,7 +385,7 @@ clicon_option_exists(clicon_handle 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
@ -404,9 +404,9 @@ clicon_option_str(clicon_handle 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 hash_value(copt, (char*)name, NULL);
return clicon_hash_value(copt, (char*)name, NULL);
}
/*! 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);
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
@ -518,7 +518,7 @@ clicon_option_del(clicon_handle 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;
char *node;
char *node = NULL;
yang_stmt *ybaseref; /* This is the type's base reference */
yang_stmt *ybaseid;
char *prefix = NULL;
cbuf *cb = NULL;
cbuf *cb2 = NULL;
/* Get idref value. Then see if this value is derived from ytype.
* 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
*/
if (cvec_find(yang_cvec_get(ybaseid), node) == NULL){
cbuf_reset(cb);
cprintf(cb, "Identityref validation failed, %s not derived from %s",
if ((cb2 = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cb2, "Identityref validation failed, %s not derived from %s",
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 fail;
}
@ -391,6 +395,8 @@ validate_identityref(cxobj *xt,
done:
if (cb)
cbuf_free(cb);
if (cb2)
cbuf_free(cb2);
return retval;
fail:
retval = 0;
@ -1221,19 +1227,20 @@ xml_yang_validate_all(clicon_handle h,
/* Special case if leaf is leafref, then first check against
current xml tree
*/
if ((yc = yang_find(ys, Y_TYPE, NULL)) != NULL){
if (strcmp(yc->ys_argument, "leafref") == 0){
if ((ret = validate_leafref(xt, yc, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
else if (strcmp(yc->ys_argument, "identityref") == 0){
if ((ret = validate_identityref(xt, ys, yc, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
/* Get base type yc */
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)
goto done;
if (ret == 0)
goto fail;
}
else if (strcmp(yang_argument_get(yc), "identityref") == 0){
if ((ret = validate_identityref(xt, ys, yc, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
break;
default:
@ -2557,7 +2564,7 @@ api_path2xml_vec(char **vec,
else{
if ((valvec = clicon_strsep(restval, ",", &nvalvec)) == NULL)
goto done;
if (nvalvec != cvec_len(cvk)){
if ((nvalvec != cvec_len(cvk)) && strict){
clicon_err(OE_XML, EINVAL, "List key %s length mismatch", name);
goto fail;
}

File diff suppressed because it is too large Load diff

View file

@ -59,8 +59,9 @@
#include "clixon_handle.h"
#include "clixon_yang.h"
#include "clixon_xml.h"
#include "clixon_xpath_parse.h"
#include "clixon_xpath_ctx.h"
#include "clixon_xpath.h"
#include "clixon_xpath_parse.h"
/*
* 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
*/
/* 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 */
const char *xy_name; /* Name of syntax (for error string) */
int xy_linenum; /* Number of \n in parsed buffer */

View file

@ -57,6 +57,7 @@
#include "clixon_xpath_ctx.h"
#include "clixon_xpath.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 */
#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)))
/*! 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
* @param[in] h Clicon handle
* @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 1 Validation OK
* @note reason if given must be freed by caller
* @see cv_validate Corresponding type check in cligen
*/
static int
cv_validate1(clicon_handle h,
@ -705,14 +805,13 @@ cv_validate1(clicon_handle h,
/* Check fails */
if (i==cvec_len(cvv)){ /* And it is last */
if (reason){
if (reti)
*reason = cligen_reason("Number out of range: %"
PRId64, ii);
else if (retu)
*reason = cligen_reason("Number out of range: %"
PRIu64, uu);
if (reti || retu){
if (outofrange(cv, cvv, reason) < 0)
goto done;
}
else
*reason = cligen_reason("string length out of range: %" PRIu64, uu);
if (outoflength(uu, cvv, reason) < 0)
goto done;
}
goto fail;
}
@ -1317,13 +1416,14 @@ yang_type_resolve(yang_stmt *yorig,
*
* @code
* yang_stmt *yrestype;
* char *origtype = NULL;
* int options;
* cvec *cvv = NULL;
* cvec *patterns = cvec_new(0);
* cvec *regexps = cvec_new(0);
* 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)
* goto err;
* if (yrestype == NULL) # unresolved

View file

@ -6,7 +6,8 @@
: ${pattern:=test_*.sh}
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
fi

View file

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

View file

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

View file

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

View file

@ -48,7 +48,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
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
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "cli enabled feature"

View file

@ -106,7 +106,37 @@ cat <<EOF > $fyang
container aes-parameters {
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
new "test params: -f $cfg"
@ -120,7 +150,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
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"
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
exit # BE
fi

View file

@ -26,7 +26,6 @@ cat <<EOF > $cfg
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
<CLICON_XMLDB_CACHE>true</CLICON_XMLDB_CACHE>
</clixon-config>
EOF

View file

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

View file

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

View file

@ -124,16 +124,15 @@ fi
new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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)
new "disable nacm"

View file

@ -101,7 +101,6 @@ EOF
new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a
@ -109,7 +108,6 @@ EOF
wait_backend
wait_restconf
#----------- First get
case "$ret1" in
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"}}} '
;;
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
@ -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"}}} '
;;
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}
'

View file

@ -139,12 +139,12 @@ fi
new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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>]]>]]>$"
@ -200,8 +200,7 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/clixon-e
'
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"
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"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
# Set nacm from scratch
nacm(){

View file

@ -148,12 +148,12 @@ fi
new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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>]]>]]>$"
@ -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"
expecteq "$(curl -u wilma:bar -sS -X DELETE http://localhost/restconf/data)" 0 ''
new "admin get nacm (should be null)"
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'null
'
new "admin get nacm (should fail)"
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)"
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
new "waiting"
sleep $RCWAIT
wait_backend
fi
# 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 ""
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"
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 ""
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"
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
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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 ""

View file

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

View file

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

View file

@ -121,8 +121,9 @@ if [ $BE -ne 0 ]; then
fi
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
new "waiting"
sleep $RCWAIT
wait_backend
fi
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>]]>]]>$'
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"
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_\-.]*';
}
}
leaf bool {
description "For testing different truth values in CLI";
type boolean;
}
}
EOF
@ -231,14 +235,14 @@ EOF
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
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 '^$'
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"
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 '^$'
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"
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"
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 '^$'
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"
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"
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"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -368,19 +372,19 @@ EOF
#-------- num2 range and blanks
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"
expectfn "$clixon_cli -1f $cfg -l o set num2 1000" 0 '^$'
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"
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"
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"
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>]]>]]>$"
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"
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 '^$'
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"
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>]]>]]>$"
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"
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
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"
expectfn "$clixon_cli -1f $cfg -l e set num4 2" 0 '^$'
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"
expectfn "$clixon_cli -1f $cfg -l o set num4 42" 0 '^$'
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"
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 '^$'
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"
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>]]>]]>$"
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"
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>]]>]]>$"
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"
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"
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"
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>]]>]]>$"
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---------------------
#-------- len1 single range (2)
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"
expectfn "$clixon_cli -1f $cfg -l o set len1 xy" 0 '^$'
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"
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>]]>]]>$"
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
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"
expectfn "$clixon_cli -1f $cfg -l o set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 '^$'
@ -547,32 +551,32 @@ EOF
#-------- len4 multiple ranges 2..3 | 20-29
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"
expectfn "$clixon_cli -1f $cfg -l o set len4 ab" 0 '^$'
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"
expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghija" 0 '^$'
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
new "cli yang pattern \d ok"
expectfn "$clixon_cli -1f $cfg -l o set digit4 0123" 0 '^$'
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"
expectfn "$clixon_cli -1f $cfg -l o set word4 abc9" 0 '^$'
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"
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"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
#------ minus
new "type with minus"
@ -601,6 +604,27 @@ EOF
#new "cli type with minus"
#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
new "Kill backend"
# Check if premature kill
@ -619,7 +643,7 @@ testrun nocache
# Run with db cache
testrun cache
# Run with
testrun cache-zerocopy
# Run with zero-copy XXX does not work
#testrun cache-zerocopy
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
new "waiting"
sleep $RCWAIT
wait_backend
fi
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 "^$"
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
exit # BE

View file

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

View file

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

View file

@ -254,8 +254,6 @@ if [ $BE -ne 0 ]; then
new "start backend -s $mode -f $cfg"
start_backend -s $mode -f $cfg
fi
new "waiting"
sleep $RCWAIT
new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf
@ -264,7 +262,8 @@ new "start restconf daemon"
start_restconf -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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>]]>]]>$"

View file

@ -265,8 +265,6 @@ testrun(){
new "start backend -s startup -f $cfg -- -u"
start_backend -s startup -f $cfg -- -u
fi
new "waiting"
sleep $RCWAIT
new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf
@ -275,7 +273,8 @@ testrun(){
start_restconf -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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>]]>]]>$"

View file

@ -112,8 +112,6 @@ if [ $BE -ne 0 ]; then
new "start backend -s $mode -f $cfg"
start_backend -s $mode -f $cfg
fi
new "waiting"
sleep $RCWAIT
new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf
@ -122,7 +120,8 @@ new "start restconf daemon"
start_restconf -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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>]]>]]>$"

View file

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

View file

@ -85,7 +85,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "1. Set newex"
@ -134,7 +134,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "Set oldex"
@ -178,7 +178,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "Set newex"
@ -222,7 +222,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "Set oldex"
@ -266,7 +266,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "Set newex"
@ -312,7 +312,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
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>]]>]]>$'
@ -357,7 +357,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "Set oldex"
@ -403,7 +403,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
fi
new "Set oldex"

View file

@ -83,7 +83,8 @@ new "start restconf daemon"
start_restconf -f $cfg
new "waiting"
sleep $RCWAIT
wait_backend
wait_restconf
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>]]>]]>$'