diff --git a/CHANGELOG.md b/CHANGELOG.md index 73006c3b..cee95211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,20 +3,24 @@ ## 3.6.0 (Upcoming) ### Major changes: -* Experimental NACM RFC8341 Network Configuration Access Control Model. - * CLICON_NACM_MODE config option, default is disabled. - * CLICON_NACM_FILE config option, if CLICON_NACM_MODE is "external" - * Added username attribute to all rpc:s from frontend to backend +* Experimental NACM RFC8341 Network Configuration Access Control Model, see [NACM](README_NACM.md). + * New CLICON_NACM_MODE config option, default is disabled. + * New CLICON_NACM_FILE config option, if CLICON_NACM_MODE is "external" + * Added username attribute to all internal RPC:s from frontend to backend * Added NACM backend module in example -* Restructure and more generic plugin API (cli,backend,restconf,netconf). - * New design change `plugin_init()` to a single `clixon_plugin_init()` returning an api struct with function pointers, see example below. This means that there are no hardcoded plugin functions, except `clixon_plugin_init()`. - * Plugin RPC callback interface have been unified between backend, netconf and restconf. - * Backend RPC register callback function (Netconf RPC or restconf operation POST) has been changed from: `backend_rpc_cb_register()` to `rpc_callback_register()` - * Backend RPC callback signature has been changed from: `int cb(clicon_handle h, cxobj *xe, struct client_entry *ce, cbuf *cbret, void *arg)` has been changed to : `int cb(clicon_handle h, cxobj *xe, struct client_entry *ce, cbuf *cbret, void *arg)` - * Frontend netconf and restconf plugins can register callbacks as well with same API as backends. +* Restructure and more generic plugin API for cli, backend, restconf, and netconf. See example further down and the [example](example/README.md) + * Changed `plugin_init()` to `clixon_plugin_init()` returning an api struct with function pointers. There are no other hardcoded plugin functions. * Master plugins have been removed. Plugins are loaded alphabetically. You can ensure plugin load order by prefixing them with an ordering number, for example. + * Plugin RPC callback interface have been unified between backend, netconf and restconf. + * Backend RPC register callback function (Netconf RPC or restconf operation POST) has been changed from: + `backend_rpc_cb_register()` to `rpc_callback_register()` + * Backend RPC callback signature has been changed from: + `int cb(clicon_handle h, cxobj *xe, struct client_entry *ce, cbuf *cbret, void *arg)` + to: + `int cb(clicon_handle h, cxobj *xe, struct client_entry *ce, cbuf *cbret, void *arg)` + * Frontend netconf and restconf plugins can register callbacks as well with same API as backends. * Moved specific plugin functions from apps/ to generic functions in lib/ - * New config option CLICON_BACKEND_REGEXP to match backkend plugins (if you do not all loaded). + * New config option CLICON_BACKEND_REGEXP to match backend plugins (if you do not want to load all). * Added authentication plugin callback (ca_auth) * Added clicon_username_get() / clicon_username_set() * Removed some obscure plugin code that seem not to be used (please report if needed!) @@ -59,15 +63,14 @@ clixon_plugin_api *clixon_plugin_init(clicon_handle h) } ``` -* Added Clixon Restconf library - * Builds and installs a new restconf library: libclixon_restconf.so and clixon_restconf.h +* Builds and installs a new restconf library: `libclixon_restconf.so` and clixon_restconf.h * The restconf library can be included by a restconf plugin. * Example code in example/Makefile.in and example/restconf_lib.c -* Restconf error handling for get, put and post. Several cornercases remain. Available both as xml and json (set accept header), pretty-printed and not (set clixon config option). +* Restconf error handling for get, put and post. (thanks Stephen Jones, Netgate) + * Available both as xml and json (set accept header). * Proper RFC 6241 Netconf error handling * New functions added in clixon_netconf_lib.[ch] * Datastore code modified for RFC 6241 - * Remaining: validate, generic restconf and netconf code ### Minor changes: @@ -81,20 +84,19 @@ clixon_plugin_api *clixon_plugin_init(clicon_handle h) * Removed username to rpc calls (added below) * README.md extended with new yang, netconf, restconf, datastore, and auth sections. * The key-value datastore is no longer supported. Use the default text datastore. -* Add username to rpc calls to prepare for authorization for backend: - clicon_rpc_config_get(h, db, xpath, xt) --> clicon_rpc_config_get(h, db, xpath, username, xt) - clicon_rpc_get(h, xpath, xt) --> clicon_rpc_get(h, xpath, username, xt) - +* Added username to rpc calls to prepare for authorization for backend: + * clicon_rpc_config_get(h, db, xpath, xt) --> clicon_rpc_config_get(h, db, xpath, username, xt) + * clicon_rpc_get(h, xpath, xt) --> clicon_rpc_get(h, xpath, username, xt) * Experimental: Added CLICON_TRANSACTION_MOD configuration option. If set, modifications in validation and commit callbacks are written back - into the datastore. + into the datastore. Requested by Stephen Jones, Netgate. * Invalid key to api_path2xml gives warning instead of error and quit. * Added restconf/operations get, see RFC8040 Sec 3.3.2: * yang_find_topnode() and api_path2xml() schemanode parameter replaced with yang_class. Replace as follows: 0 -> YC_DATANODE, 1 -> YC_SCHEMANODE * xml2json: include prefix in translation, so is translated to {"a:b" ..} -* Use instead of when save/load configuration to file. This -enables saved files to be used as datastore without any editing. Thanks Matt. +* Use `` instead of `` when save/load configuration to file. This +enables saved files to be used as datastore without any editing. Thanks Matt, Netgate. * Added Yang "extension" statement. This includes parsing unknown statements and identifying them as extensions or not. However, @@ -108,7 +110,7 @@ enables saved files to be used as datastore without any editing. Thanks Matt. * Showing syntax using CLI commands was broekn and is fixed. * Fixed issue https://github.com/clicon/clixon/issues/18 RPC response issues reported by Stephen Jones at Netgate * Fixed issue https://github.com/clicon/clixon/issues/17 special character in strings can break RPCs reported by David Cornejo at Netgate. - * This was a large rewright of XML parsing and output due to CharData not correctly encoded according to https://www.w3.org/TR/2008/REC-xml-20081126. + * This was a large rewrite of XML parsing and output due to CharData not correctly encoded according to https://www.w3.org/TR/2008/REC-xml-20081126. * Fixed three-key list entry problem (reported by jdl@netgate) * Translate xml->json \n correctly * Fix issue: https://github.com/clicon/clixon/issues/15 Replace whole config diff --git a/README.md b/README.md index 31043311..44198776 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ transaction support from a YANG specification. * [Example](example/) * [Changelog](CHANGELOG.md) * [Runtime](#runtime) - * [Clicon and Clixon project page](http://www.clicon.org) + * [Clixon project page](http://www.clicon.org) * [Tests](test/) * [Reference manual](http://www.clicon.org/doxygen/index.html) (Note: the link may not be up-to-date. It is better to build your own: `cd doc; make doc`) @@ -27,9 +27,7 @@ Background ========== Clixon was implemented to provide an open-source generic configuration -tool. The existing [CLIgen](http://www.cligen.se) tool was extended to -a framework. Most of the user projects are for embedded network and -measuring devices, but can be deployed for more general use. +tool. The existing [CLIgen](http://www.cligen.se) tool was for command-lines only, whilke clixon is a system with config-db, xml and rest interfaces. Most of the projects using clixon are for embedded network and measuring devices. But Clixon is more generic than that. Users of clixon currently include: * [Netgate](https://www.netgate.com) @@ -51,7 +49,7 @@ A typical installation is as follows: ``` One [example application](example/README.md) is provided, a IETF IP YANG datamodel with -generated CLI and configuration interface. +generated CLI, Netconf and restconf interface. Licenses ======== @@ -63,8 +61,7 @@ See [LICENSE.md](LICENSE.md) for the license. Dependencies ============ Clixon depends on the following software packages, which need to exist on the target machine. -- [CLIgen](http://www.cligen.se) is required for building Clixon. If you need -to build and install CLIgen: +- [CLIgen](http://www.cligen.se) If you need to build and install CLIgen: ``` git clone https://github.com/olofhagsand/cligen.git cd cligen; configure; make; make install @@ -77,7 +74,9 @@ There is no yum/apt/ostree package for Clixon (please help?) Support ======= -Clixon interaction is best done posting issues, pull requests, or joining the [slack channel](https://join.slack.com/t/clixondev/shared_invite/enQtMzI3OTM4MzA3Nzk3LTA3NWM4OWYwYWMxZDhiYTNhNjRkNjQ1NWI1Zjk5M2JjMDk4MTUzMTljYTZiYmNhODkwMDI2ZTkyNWU3ZWMyN2U). +Clixon interaction is best done posting issues, pull requests, or joining the +[slack channel](https://clixondev.slack.com). +[Slack invite](https://join.slack.com/t/clixondev/shared_invite/enQtMzI3OTM4MzA3Nzk3LTA3NWM4OWYwYWMxZDhiYTNhNjRkNjQ1NWI1Zjk5M2JjMDk4MTUzMTljYTZiYmNhODkwMDI2ZTkyNWU3ZWMyN2U). Extending ========= @@ -103,7 +102,7 @@ Clixon mainly follows [YANG 1.0 RFC 6020](https://www.rfc-editor.org/rfc/rfc6020 - identity, base, identityref - list features: min/max-elements, unique -The aim is also to cover new featires in YANG 1.1 [YANG RFC 7950](https://www.rfc-editor.org/rfc/rfc7950.txt) +The aim is also to cover new features in YANG 1.1 [YANG RFC 7950](https://www.rfc-editor.org/rfc/rfc7950.txt) Clixon has its own XML library designed for performance. @@ -111,12 +110,12 @@ Netconf ======= Clixon implements the following NETCONF proposals or standards: - [NETCONF Configuration Protocol](http://www.rfc-base.org/txt/rfc-4741.txt) -- [Using the NETCONF Configuration Protocol over Secure SHell (SSH)](http://www.rfc-base.org/txt/rfc-4742.txt) +- [Using the NETCONF Configuration Protocol over Secure Shell (SSH)](http://www.rfc-base.org/txt/rfc-4742.txt) - [NETCONF Event Notifications](http://www.rfc-base.org/txt/rfc-5277.txt) Some updates are being made to RFC 6241 and RFC 6242. -Clixon does not support the following features: +Clixon does not yet support the following netconf features: - :url capability - copy-config source config @@ -157,14 +156,22 @@ Auth Authentication is managed outside Clixon using SSH, SSL, Oauth2, etc. -For CLI, login is typically made via SSH. For netconf, SSH netconf subsystem can be used. +For CLI, login is typically made via SSH. For netconf, SSH netconf +subsystem can be used. Restconf however needs credentials. This is done by writing a credentials callback in a restconf plugin. See: * [FAQ](doc/FAQ.md#how-do-i-write-an-authentication-callback). * [Example](example/README.md) has an example how to do this with HTTP basic auth. - * It would be possible for do this for more advanced mechanisms such as Oauth2 or (https://github.com/CESNET/Netopeer2/tree/master/server/configuration) + * I have done this for another project using Oauth2 or (https://github.com/CESNET/Netopeer2/tree/master/server/configuration) -There is an ongoing effort to implement authorization for Clixon according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341), at least a subset of the functionality. +The clients send the ID of the user using a "username" attribute with +the RPC calls to the backend. Note that the backend trusts the clients +so the clients can in principle fake a username. + +There is an ongoing effort to implement authorization for Clixon +according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341), at +least a subset of the functionality. See more information here: +[NACM](README_NACM.md). Runtime diff --git a/README_NACM.md b/README_NACM.md new file mode 100644 index 00000000..84e9906f --- /dev/null +++ b/README_NACM.md @@ -0,0 +1,34 @@ +# NACM + +Clixon includes an experimental NACM implementation according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341). + +The support is as follows: + +* There is a yang config variable `CLICON_NACM_MODE` to set whether NACM is disabled, uses internal(embedded) NACM configuration, or external configuration. (See yang/clixon-config.yang) +* If the mode is internal, NACM configurations is expected to be in the regular configuration, managed by regular candidate/runing/commit procedures. This mode may have some problems with bootstrapping. +* If the mode is `external`, the `CLICON_NACM_FILE` yang config variable contains the name of a separate configuration file containing the NACM configurations. After changes in this file, the backend needs to be restarted. +* The [example](example/README.md) contains a http basic auth and a NACM backend callback for state variable. +* There are two [tests](test/README.md) using internal and external NACM config +* The backend provides a limited NACM support (when enabled) decscribed below + +NACM functionality +================== + +NACM is implemented in the backend and the access checks are made at a +single point: in from_client_msg() when an internal netconf RPC has +just been received and decoded. The code is in nacm_access(). + +The functionality is as follows: +* Notification is not supported +* Groups are supported +* Rule-lists are supported +* Rules are supported as follows + * module-name: Only '*' supported + * access-operations: only '*' and 'exec' supported + * rpc-name: fully supported (eg edit-config/get-config, etc) + * action: fully supported (permit/deny) + +The tests outlines an example of three groups (taken from the RFC): admin, limited and guest: +* admin: Full access +* limited: Read access (get and get-config) +* guest: No access diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 6714413a..f4753f3c 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -94,8 +94,8 @@ expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv, - cvec *commands, - cvec *helptexts) + cvec *commands, + cvec *helptexts) { int retval = -1; char *api_path_fmt; diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index 4781ea8d..eb6cb00f 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -186,7 +186,8 @@ api_data_get2(clicon_handle h, cbuf *cbx = NULL; yang_spec *yspec; cxobj *xret = NULL; - cxobj *xerr = NULL; + cxobj *xerr = NULL; /* malloced */ + cxobj *xe; cxobj **xvec = NULL; size_t xlen; int i; @@ -227,8 +228,8 @@ api_data_get2(clicon_handle h, } #endif /* Check if error return XXX this needs more work */ - if ((xerr = xpath_first(xret, "/rpc-error")) != NULL){ - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if ((xe = xpath_first(xret, "/rpc-error")) != NULL){ + if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; } @@ -278,6 +279,8 @@ api_data_get2(clicon_handle h, cbuf_free(cbpath); if (xret) xml_free(xret); + if (xerr) + xml_free(xerr); if (xvec) free(xvec); return retval; @@ -403,7 +406,8 @@ api_data_post(clicon_handle h, cxobj *xa; cxobj *xret = NULL; cxobj *xretcom = NULL; - cxobj *xerr = NULL; + cxobj *xerr = NULL; /* malloced must be freed */ + cxobj *xe; char *username; clicon_debug(1, "%s api_path:\"%s\" json:\"%s\"", @@ -474,8 +478,8 @@ api_data_post(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 ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if ((xe = xpath_first(xret, "//rpc-error")) != NULL){ + if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; } @@ -485,10 +489,10 @@ api_data_post(clicon_handle h, cprintf(cbx, ""); if (clicon_rpc_netconf(h, cbuf_get(cbx), &xretcom, NULL) < 0) goto done; - if ((xerr = xpath_first(xretcom, "//rpc-error")) != NULL){ + if ((xe = xpath_first(xretcom, "//rpc-error")) != NULL){ if (clicon_rpc_discard_changes(h) < 0) goto done; - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; } @@ -501,6 +505,8 @@ api_data_post(clicon_handle h, clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); if (xret) xml_free(xret); + if (xerr) + xml_free(xerr); if (xretcom) xml_free(xretcom); if (xtop) @@ -615,7 +621,8 @@ api_data_put(clicon_handle h, char *api_path; cxobj *xret = NULL; cxobj *xretcom = NULL; - cxobj *xerr = NULL; + cxobj *xerr = NULL; /* malloced must be freed */ + cxobj *xe; char *username; clicon_debug(1, "%s api_path:\"%s\" json:\"%s\"", @@ -718,8 +725,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 ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if ((xe = xpath_first(xret, "//rpc-error")) != NULL){ + if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; } @@ -728,10 +735,10 @@ api_data_put(clicon_handle h, cprintf(cbx, ""); if (clicon_rpc_netconf(h, cbuf_get(cbx), &xretcom, NULL) < 0) goto done; - if ((xerr = xpath_first(xretcom, "//rpc-error")) != NULL){ + if ((xe = xpath_first(xretcom, "//rpc-error")) != NULL){ if (clicon_rpc_discard_changes(h) < 0) goto done; - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if (api_return_err(h, r, xe, pretty, use_xml) < 0) goto done; goto ok; } @@ -744,6 +751,8 @@ api_data_put(clicon_handle h, clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); if (xret) xml_free(xret); + if (xerr) + xml_free(xerr); if (xretcom) xml_free(xretcom); if (xtop) @@ -1007,16 +1016,17 @@ api_operations_post(clicon_handle h, yang_stmt *youtput; cxobj *xdata = NULL; cxobj *xret = NULL; - cxobj *xerr = NULL; + cxobj *xerr = NULL; /* malloced must be freed */ + cxobj *xer; /* non-malloced error */ cbuf *cbx = NULL; cxobj *xtop = NULL; /* xpath root */ - cxobj *xe; cxobj *xbot = NULL; yang_node *y = NULL; cxobj *xinput; cxobj *xoutput; cxobj *x; cxobj *xa; + cxobj *xe; char *username; cbuf *cbret = NULL; int ret = 0; @@ -1139,7 +1149,6 @@ api_operations_post(clicon_handle h, goto done; } xe = NULL; - while ((xe = xml_child_each(xtop, xe, CX_ELMNT)) != NULL) { /* Look for local (client-side) restconf plugins. */ if ((ret = rpc_callback_call(h, xe, cbret, r)) < 0) @@ -1148,8 +1157,8 @@ api_operations_post(clicon_handle h, if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0) goto done; /* Local error: return it and quit */ - if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if ((xer = xpath_first(xret, "//rpc-error")) != NULL){ + if (api_return_err(h, r, xer, pretty, use_xml) < 0) goto done; goto ok; } @@ -1159,8 +1168,8 @@ api_operations_post(clicon_handle h, if (ret == 0){ /* Send to backend */ if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0) goto done; - if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){ - if (api_return_err(h, r, xerr, pretty, use_xml) < 0) + if ((xer = xpath_first(xret, "//rpc-error")) != NULL){ + if (api_return_err(h, r, xer, pretty, use_xml) < 0) goto done; goto ok; } @@ -1221,6 +1230,8 @@ api_operations_post(clicon_handle h, xml_free(xtop); if (xret) xml_free(xret); + if (xerr) + xml_free(xerr); if (cbx) cbuf_free(cbx); if (cbret) diff --git a/example/README.md b/example/README.md index 86e70769..cafd796f 100644 --- a/example/README.md +++ b/example/README.md @@ -11,7 +11,7 @@ routing example. It contains the following files: * notification, * rpc handler * state-data handler, ie non-config data -* example_backend_secondary.c Secondary backend plugin. Plugins are loaded alphabetically. +* example_backend_nacm.c Secondary backend plugin. Plugins are loaded alphabetically. * example_restconf.c Restconf callback plugin containing an HTTP basic authentication callback * example_netconf.c Netconf callback plugin * Makefile.in Example makefile where plugins are built and installed @@ -182,8 +182,15 @@ a real example would poll or get the interface counters via a system call, as well as use the "xpath" argument to identify the requested state data. +## Authentication and NACM +The example contains some stubs for authorization according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341): +* A basic auth HTTP callback, see: example_restconf_credentials() containing three example users: adm1, wilma, and guest, according to the examples in Appendix A in the RFC. +* A NACM backend plugin reporting the mandatory NACM state variables. + ## Run as docker container + +(Note not updated) ``` cd docker # look in README diff --git a/example/example_restconf.c b/example/example_restconf.c index fd579954..2b22ce16 100644 --- a/example/example_restconf.c +++ b/example/example_restconf.c @@ -204,7 +204,7 @@ example_restconf_credentials(clicon_handle h, char *auth; char *user = NULL; char *passwd; - char *passwd2; + char *passwd2 = ""; size_t authlen; cbuf *cb = NULL; int ret; diff --git a/lib/src/clixon_xml_parse.l b/lib/src/clixon_xml_parse.l index c6f1726a..e0c39884 100644 --- a/lib/src/clixon_xml_parse.l +++ b/lib/src/clixon_xml_parse.l @@ -108,11 +108,11 @@ int clixon_xml_parsewrap(void) \n { clixon_xml_parselval.string = yytext;_YA->ya_linenum++; return (CHARDATA);} . { clixon_xml_parselval.string = yytext; return CHARDATA; /*XXX:optimize*/} /* @see xml_chardata_encode */ -"amp; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = strdup("&"); return CHARDATA;} -"lt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = strdup("<"); return CHARDATA;} -"gt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = strdup(">"); return CHARDATA;} -"apos; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = strdup("'"); return CHARDATA;} -"aquot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = strdup("'"); return CHARDATA;} +"amp; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "&"; return CHARDATA;} +"lt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "<"; return CHARDATA;} +"gt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = ">"; return CHARDATA;} +"apos; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;} +"aquot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;} "-->" { BEGIN(START); return ECOMMENT; } diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index 7cf0d253..eb48253f 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -1042,8 +1042,8 @@ extension_substmt : argument_stmt { clicon_debug(2,"extension-substmt -> argu | { clicon_debug(2,"extension-substmt -> "); } ; -argument_stmt : K_ARGUMENT id_arg_str ';' - | K_ARGUMENT id_arg_str '{' '}' +argument_stmt : K_ARGUMENT id_arg_str ';' { free($2); } + | K_ARGUMENT id_arg_str '{' '}' { free($2); } ; /* Feature */ @@ -1403,7 +1403,7 @@ qstring : DQ ustring DQ { $$=$2; clicon_debug(2,"string-> \" ustring \"" ustring : ustring CHAR { int len = strlen($1); - $$ = realloc($1, len+strlen($2) + 1); + $$ = realloc($1, len+strlen($2) + 1); sprintf($$+len, "%s", $2); free($2); } diff --git a/test/README.md b/test/README.md index 7598af48..08c92f1a 100644 --- a/test/README.md +++ b/test/README.md @@ -4,6 +4,8 @@ This directory contains testing code for clixon and the example routing application. Assumes setup of http daemon as describe under apps/restonf - clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script - all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically. +- test_auth.sh Auth tests using internal NACM +- test_auth_ext.sh Auth tests using external NACM - test_cli.sh CLI tests - test_netconf.sh Netconf tests - test_restconf.sh Restconf tests diff --git a/test/lib.sh b/test/lib.sh index 6a6f0e0b..061730f6 100755 --- a/test/lib.sh +++ b/test/lib.sh @@ -18,6 +18,7 @@ clixon_netconf=clixon_netconf #sudo su -c "/www-data/clixon_restconf -f $cfg -D" -s /bin/sh www-data #sudo su -c "valgrind --leak-check=full --show-leak-kinds=all /www-data/clixon_restconf -f $cfg -D" -s /bin/sh www-data +#clixon_backend="valgrind --leak-check=full --show-leak-kinds=all clixon_backend" clixon_backend=clixon_backend dir=/var/tmp/$0