* ietf-netconf yang module added with candidate, validate, startup and xpath features enabled.
* Added urn:ietf:params:netconf:capability:yang-library:1.0 * Thanks SCadilhac for helping out, see https://github.com/clicon/clixon/issues/39 * uri_percent_encode() and xml_chardata_encode() changed to use stdarg parameters
This commit is contained in:
parent
7046925fc3
commit
40cda7b6a4
19 changed files with 245 additions and 93 deletions
|
|
@ -13,6 +13,7 @@
|
||||||
<CLICON_FEATURE>*:*</CLICON_FEATURE>
|
<CLICON_FEATURE>*:*</CLICON_FEATURE>
|
||||||
```
|
```
|
||||||
* logical combination of features not implemented, eg if-feature "not foo or bar and baz";
|
* logical combination of features not implemented, eg if-feature "not foo or bar and baz";
|
||||||
|
* ietf-netconf yang module added with candidate, validate, startup and xpath features enabled.
|
||||||
* YANG Module Library support
|
* YANG Module Library support
|
||||||
* According to RFC 7895 and implemented by ietf-yang-library.yang
|
* According to RFC 7895 and implemented by ietf-yang-library.yang
|
||||||
* Changed Netconf hello to single capabilty urn:ietf:params:netconf:capability:yang-library:1.0 according to YANG 1.1 RFC7950 Sec 5.6.4.
|
* Changed Netconf hello to single capabilty urn:ietf:params:netconf:capability:yang-library:1.0 according to YANG 1.1 RFC7950 Sec 5.6.4.
|
||||||
|
|
@ -32,7 +33,8 @@
|
||||||
|
|
||||||
### API changes on existing features (you may need to change your code)
|
### API changes on existing features (you may need to change your code)
|
||||||
* Netconf hello capability updated to YANG 1.1 RFC7950 Sec 5.6.4
|
* Netconf hello capability updated to YANG 1.1 RFC7950 Sec 5.6.4
|
||||||
* A single capability is announced instead of many.
|
* Added urn:ietf:params:netconf:capability:yang-library:1.0
|
||||||
|
* Thanks SCadilhac for helping out, see https://github.com/clicon/clixon/issues/39
|
||||||
* Major rewrite of event streams
|
* Major rewrite of event streams
|
||||||
* If you used old event callbacks API, you need to switch to the streams API
|
* If you used old event callbacks API, you need to switch to the streams API
|
||||||
* See clixon_stream.[ch]
|
* See clixon_stream.[ch]
|
||||||
|
|
@ -72,8 +74,8 @@
|
||||||
goto done;
|
goto done;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
* uri_percent_encode() and xml_chardata_encode() changed to stdarg parameters
|
||||||
* Added CLIXON_DEFAULT_CONFIG=/usr/local/etc/clixon.xml as option and in example (so you dont need to provide -f command-line option).
|
* Added CLIXON_DEFAULT_CONFIG=/usr/local/etc/clixon.xml as option and in example (so you dont need to provide -f command-line option).
|
||||||
* Yang 1.1 action syntax added (but function is not supported)
|
* Yang 1.1 action syntax added (but function is not supported)
|
||||||
* New function: clicon_conf_xml() returns configuration tree
|
* New function: clicon_conf_xml() returns configuration tree
|
||||||
|
|
|
||||||
|
|
@ -751,6 +751,9 @@ main(int argc,
|
||||||
/* Load yang module library, RFC7895 */
|
/* Load yang module library, RFC7895 */
|
||||||
if (yang_modules_init(h) < 0)
|
if (yang_modules_init(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
||||||
|
if (netconf_module_load(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Load yang Restconf stream discovery */
|
/* Load yang Restconf stream discovery */
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
|
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
|
||||||
|
|
|
||||||
|
|
@ -432,6 +432,9 @@ main(int argc, char **argv)
|
||||||
clicon_yang_module_revision(h),
|
clicon_yang_module_revision(h),
|
||||||
yspec) < 0)
|
yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Load yang module library, RFC7895 */
|
||||||
|
if (yang_modules_init(h) < 0)
|
||||||
|
goto done;
|
||||||
if (printspec)
|
if (printspec)
|
||||||
yang_print(stdout, (yang_node*)yspec);
|
yang_print(stdout, (yang_node*)yspec);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,12 +106,46 @@ netconf_hello_dispatch(cxobj *xn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf hello. Single cap and defer individual to querying modules
|
/*! Create Netconf hello. Single cap and defer individual to querying modules
|
||||||
* This follows YANG 1.1 RFC7950 Sec 5.6.4, where a single capability announced
|
|
||||||
* and a client may query supported modules using RFC 7895 (Yang Module
|
|
||||||
* Library).
|
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] cb Msg buffer
|
* @param[in] cb Msg buffer
|
||||||
* @param[in] session_id Id of client session
|
* @param[in] session_id Id of client session
|
||||||
|
* Lots of dependencies here. regarding the hello protocol.
|
||||||
|
* RFC6241 NETCONF Protocol says: (8.1)
|
||||||
|
* MUST send a <hello> element containing a list of that peer's capabilities
|
||||||
|
* MUST send at least the base NETCONF capability, urn:ietf:params:netconf:base:1.1
|
||||||
|
* MAY include capabilities for previous NETCONF versions
|
||||||
|
* MUST include a <session-id>
|
||||||
|
* the example shows urn:ietf:params:netconf:capability:startup:1.0
|
||||||
|
|
||||||
|
* RFC5277 NETCONF Event Notifications
|
||||||
|
* urn:ietf:params:netconf:capability:notification:1.0 is advertised during the capability exchange
|
||||||
|
*
|
||||||
|
* RFC6022 YANG Module for NETCONF Monitoring
|
||||||
|
* MUST advertise the capability URI "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"
|
||||||
|
* RFC7895 Yang module library defines how to announce module features (not hell capabilities)
|
||||||
|
* RFC7950 YANG 1.1 says (5.6.4);
|
||||||
|
* MUST announce the modules it implements by implementing the YANG module
|
||||||
|
* "ietf-yang-library" (RFC7895) and listing all implemented modules in the
|
||||||
|
* "/modules-state/module" list.
|
||||||
|
* MUST advertise urn:ietf:params:netconf:capability:yang-library:1.0?
|
||||||
|
* revision=<date>&module-set-id=<id> in the <hello> message.
|
||||||
|
*
|
||||||
|
* Question: should the NETCONF in RFC6241 sections 8.2-8.9 be announced both
|
||||||
|
* as features and as capabilities in the <hello> message according to RFC6241?
|
||||||
|
* urn:ietf:params:netconf:capability:candidate:1:0 (8.3)
|
||||||
|
* urn:ietf:params:netconf:capability:validate:1.1 (8.6)
|
||||||
|
* urn:ietf:params:netconf:capability:startup:1.0 (8.7)
|
||||||
|
* urn:ietf:params:netconf:capability:xpath:1.0 (8.9)
|
||||||
|
* urn:ietf:params:netconf:capability:notification:1.0 (RFC5277)
|
||||||
|
*
|
||||||
|
* @note the hello message is created bythe netconf application, not the
|
||||||
|
* backend, and backend may implement more modules - please consider if using
|
||||||
|
* library routines for detecting capabilities here. In contrast, yang module
|
||||||
|
* list (RFC7895) is processed by the backend.
|
||||||
|
* @note encode bodies, see xml_chardata_encode()
|
||||||
|
* @see yang_modules_state_get
|
||||||
|
* @see netconf_module_load
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_create_hello(clicon_handle h,
|
netconf_create_hello(clicon_handle h,
|
||||||
|
|
@ -121,21 +155,27 @@ netconf_create_hello(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *module_set_id;
|
char *module_set_id;
|
||||||
char *ietf_yang_library_revision;
|
char *ietf_yang_library_revision;
|
||||||
|
char *encstr = NULL;
|
||||||
|
|
||||||
module_set_id = clicon_option_str(h, "CLICON_MODULE_SET_ID");
|
module_set_id = clicon_option_str(h, "CLICON_MODULE_SET_ID");
|
||||||
if ((ietf_yang_library_revision = yang_modules_revision(h)) == NULL)
|
if ((ietf_yang_library_revision = yang_modules_revision(h)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
add_preamble(cb);
|
add_preamble(cb);
|
||||||
cprintf(cb, "<hello>");
|
cprintf(cb, "<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
|
||||||
cprintf(cb, "<capabilities>");
|
cprintf(cb, "<capabilities>");
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=\"%s\"&module-set-id=%s</capability>",
|
cprintf(cb, "<capability>urn:ietf:params:netconf:base:1.1</capability>");
|
||||||
ietf_yang_library_revision,
|
if (xml_chardata_encode(&encstr, "urn:ietf:params:netconf:capability:yang-library:1.0?revision=\"%s\"&module-set-id=%s",
|
||||||
module_set_id);
|
ietf_yang_library_revision,
|
||||||
cprintf(cb, "</capabilities>");
|
module_set_id) < 0)
|
||||||
|
goto done;
|
||||||
|
cprintf(cb, "<capability>%s</capability>", encstr);
|
||||||
|
cprintf(cb, "</capabilities>");
|
||||||
cprintf(cb, "<session-id>%lu</session-id>", (long unsigned int)42+session_id);
|
cprintf(cb, "<session-id>%lu</session-id>", (long unsigned int)42+session_id);
|
||||||
cprintf(cb, "</hello>");
|
cprintf(cb, "</hello>");
|
||||||
add_postamble(cb);
|
add_postamble(cb);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (encstr)
|
||||||
|
free(encstr);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,9 @@ netconf_get_target(cxobj *xn,
|
||||||
* @param[in] s
|
* @param[in] s
|
||||||
* @param[in] cb Cligen buffer that contains the XML message
|
* @param[in] cb Cligen buffer that contains the XML message
|
||||||
* @param[in] msg Only for debug
|
* @param[in] msg Only for debug
|
||||||
|
* @note Assumes "cb" contains valid XML, ie encoding is correct. This is done
|
||||||
|
* if it is output by a xml render routine (xml_print et al), but NOT
|
||||||
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_output(int s,
|
netconf_output(int s,
|
||||||
|
|
|
||||||
|
|
@ -432,9 +432,11 @@ main(int argc,
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
/* Create first yang spec */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_dbspec_yang_set(h, yspec);
|
clicon_dbspec_yang_set(h, yspec);
|
||||||
|
|
||||||
/* Parse yang database spec file */
|
/* Parse yang database spec file */
|
||||||
if (yang_filename){
|
if (yang_filename){
|
||||||
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
|
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
|
||||||
|
|
@ -446,10 +448,12 @@ main(int argc,
|
||||||
yspec) < 0)
|
yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* Load yang module library, RFC7895 */
|
||||||
|
if (yang_modules_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
||||||
if (yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
|
if (netconf_module_load(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Initialize plugins group */
|
/* Initialize plugins group */
|
||||||
if ((dir = clicon_netconf_dir(h)) != NULL)
|
if ((dir = clicon_netconf_dir(h)) != NULL)
|
||||||
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
||||||
|
|
|
||||||
|
|
@ -635,6 +635,10 @@ main(int argc,
|
||||||
clicon_yang_module_revision(h),
|
clicon_yang_module_revision(h),
|
||||||
yspec) < 0)
|
yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* Load yang module library, RFC7895 */
|
||||||
|
if (yang_modules_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Add system modules */
|
/* Add system modules */
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
|
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
|
||||||
|
|
@ -642,9 +646,7 @@ main(int argc,
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
||||||
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec)< 0)
|
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Load yang module library, RFC7895 */
|
|
||||||
if (yang_modules_init(h) < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (stream_register(h, "NETCONF", "default NETCONF event stream") < 0)
|
if (stream_register(h, "NETCONF", "default NETCONF event stream") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ append_listkeys(cbuf *ckey,
|
||||||
xml_name(xt), keyname);
|
xml_name(xt), keyname);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (uri_percent_encode(xml_body(xkey), &bodyenc) < 0)
|
if (uri_percent_encode(&bodyenc, "%s", xml_body(xkey)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (i++)
|
if (i++)
|
||||||
cprintf(ckey, ",");
|
cprintf(ckey, ",");
|
||||||
|
|
@ -328,7 +328,7 @@ get(char *dbname,
|
||||||
* If xml element is a leaf-list, then the next element is expected to
|
* If xml element is a leaf-list, then the next element is expected to
|
||||||
* be a value
|
* be a value
|
||||||
*/
|
*/
|
||||||
if (uri_percent_decode(restval, &argdec) < 0)
|
if (uri_percent_decode(&argdec, restval) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xc = xml_find(x, name))==NULL ||
|
if ((xc = xml_find(x, name))==NULL ||
|
||||||
(xb = xml_find(xc, argdec))==NULL){
|
(xb = xml_find(xc, argdec))==NULL){
|
||||||
|
|
@ -681,7 +681,7 @@ put(char *dbfile,
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case Y_LEAF_LIST:
|
case Y_LEAF_LIST:
|
||||||
if (uri_percent_encode(body, &bodyenc) < 0)
|
if (uri_percent_encode(&bodyenc, "%s", body) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cbxk, "=%s", bodyenc);
|
cprintf(cbxk, "=%s", bodyenc);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -63,5 +63,6 @@ int netconf_operation_failed_xml(cxobj **xret, char *type, char *message);
|
||||||
int netconf_malformed_message(cbuf *cb, char *message);
|
int netconf_malformed_message(cbuf *cb, char *message);
|
||||||
int netconf_malformed_message_xml(cxobj **xret, char *message);
|
int netconf_malformed_message_xml(cxobj **xret, char *message);
|
||||||
int netconf_trymerge(cxobj *x, yang_spec *yspec, cxobj **xret);
|
int netconf_trymerge(cxobj *x, yang_spec *yspec, cxobj **xret);
|
||||||
|
int netconf_module_load(clicon_handle h);
|
||||||
|
|
||||||
#endif /* _CLIXON_NETCONF_LIB_H */
|
#endif /* _CLIXON_NETCONF_LIB_H */
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,14 @@ static inline char * strdup4(char *str)
|
||||||
char **clicon_strsep(char *string, char *delim, int *nvec0);
|
char **clicon_strsep(char *string, char *delim, int *nvec0);
|
||||||
char *clicon_strjoin (int argc, char **argv, char *delim);
|
char *clicon_strjoin (int argc, char **argv, char *delim);
|
||||||
int str2cvec(char *string, char delim1, char delim2, cvec **cvp);
|
int str2cvec(char *string, char delim1, char delim2, cvec **cvp);
|
||||||
int uri_percent_encode(char *str, char **escp);
|
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||||
int uri_percent_decode(char *esc, char **str);
|
int uri_percent_encode(char **encp, char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
int xml_chardata_encode(char *str, char **escp);
|
int xml_chardata_encode(char **escp, char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
#else
|
||||||
|
int uri_percent_encode(char **encp, char *str, ...);
|
||||||
|
int xml_chardata_encode(char **escp, char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
int uri_percent_decode(char *enc, char **str);
|
||||||
const char *clicon_int2str(const map_str2int *mstab, int i);
|
const char *clicon_int2str(const map_str2int *mstab, int i);
|
||||||
int clicon_str2int(const map_str2int *mstab, char *str);
|
int clicon_str2int(const map_str2int *mstab, char *str);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ netconf_in_use(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -125,7 +125,7 @@ netconf_invalid_value(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -165,7 +165,7 @@ netconf_too_big(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -207,7 +207,7 @@ netconf_missing_attribute(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -248,7 +248,7 @@ netconf_bad_attribute(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -290,7 +290,7 @@ netconf_unknown_attribute(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -332,7 +332,7 @@ netconf_missing_element(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -375,7 +375,7 @@ netconf_bad_element(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -417,7 +417,7 @@ netconf_unknown_element(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -459,7 +459,7 @@ netconf_unknown_namespace(cbuf *cb,
|
||||||
type, info) <0)
|
type, info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -498,7 +498,7 @@ netconf_access_denied(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -574,7 +574,7 @@ netconf_lock_denied(cbuf *cb,
|
||||||
info) <0)
|
info) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -613,7 +613,7 @@ netconf_resource_denied(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -653,7 +653,7 @@ netconf_rollback_failed(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -691,7 +691,7 @@ netconf_data_exists(cbuf *cb,
|
||||||
"<error-severity>error</error-severity>") <0)
|
"<error-severity>error</error-severity>") <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -729,7 +729,7 @@ netconf_data_missing(cbuf *cb,
|
||||||
"<error-severity>error</error-severity>") <0)
|
"<error-severity>error</error-severity>") <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -769,7 +769,7 @@ netconf_operation_not_supported(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -809,7 +809,7 @@ netconf_operation_failed(cbuf *cb,
|
||||||
type) <0)
|
type) <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -884,7 +884,7 @@ netconf_malformed_message(cbuf *cb,
|
||||||
"<error-severity>error</error-severity>") <0)
|
"<error-severity>error</error-severity>") <0)
|
||||||
goto err;
|
goto err;
|
||||||
if (message){
|
if (message){
|
||||||
if (xml_chardata_encode(message, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -970,3 +970,40 @@ netconf_trymerge(cxobj *x,
|
||||||
free(reason);
|
free(reason);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Load ietf netconf yang module and set enabled features
|
||||||
|
* The features added are:
|
||||||
|
* candidate (8.3)
|
||||||
|
* validate (8.6)
|
||||||
|
* startup (8.7)
|
||||||
|
* xpath (8.9)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
netconf_module_load(clicon_handle h)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xc;
|
||||||
|
// cxobj *x;
|
||||||
|
yang_spec *yspec;
|
||||||
|
|
||||||
|
yspec = clicon_dbspec_yang(h);
|
||||||
|
/* Load yang spec */
|
||||||
|
if (yang_spec_parse_module(h, "ietf-netconf", CLIXON_DATADIR, NULL, yspec)< 0)
|
||||||
|
goto done;
|
||||||
|
if ((xc = clicon_conf_xml(h)) == NULL){
|
||||||
|
clicon_err(OE_CFG, ENOENT, "Clicon configuration not loaded");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Enable features (hardcoded here) */
|
||||||
|
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:candidate</CLICON_FEATURE>", yspec, &xc) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:validate</CLICON_FEATURE>", yspec, &xc) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>", yspec, &xc) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_parse_string("<CLICON_FEATURE>ietf-netconf:xpath</CLICON_FEATURE>", yspec, &xc) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,8 +249,10 @@ clicon_options_main(clicon_handle h)
|
||||||
xml_child_sort = 0;
|
xml_child_sort = 0;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (yspec) /* The clixon yang-spec is not used after this */
|
#if 0 /* XXX yspec should be part of top-level yang but cant since it will be main module */
|
||||||
|
if (yspec)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
|
#endif
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -589,6 +591,7 @@ clicon_dbspec_yang_set(clicon_handle h,
|
||||||
|
|
||||||
/*! Get YANG specification for Clixon system options and features
|
/*! Get YANG specification for Clixon system options and features
|
||||||
* Must use hash functions directly since they are not strings.
|
* Must use hash functions directly since they are not strings.
|
||||||
|
* Example: features are typically accessed directly in the config tree.
|
||||||
*/
|
*/
|
||||||
cxobj *
|
cxobj *
|
||||||
clicon_conf_xml(clicon_handle h)
|
clicon_conf_xml(clicon_handle h)
|
||||||
|
|
|
||||||
|
|
@ -174,49 +174,77 @@ uri_unreserved(unsigned char in)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Percent encoding according to RFC 3986 URI Syntax
|
/*! Percent encoding according to RFC 3986 URI Syntax
|
||||||
* @param[in] str Not-encoded input string
|
* @param[out] encp Encoded malloced output string
|
||||||
* @param[out] escp Encoded/escaped malloced output string
|
* @param[in] fmt Not-encoded input string (stdarg format string)
|
||||||
|
* @param[in] ... stdarg variable parameters
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
* @code
|
||||||
|
* char *enc;
|
||||||
|
* if (uri_percent_encode(&enc, "formatstr: <>= %s", "substr<>") < 0)
|
||||||
|
* err;
|
||||||
|
* if(enc)
|
||||||
|
* free(enc);
|
||||||
|
* @endcode
|
||||||
* @see RFC 3986 Uniform Resource Identifier (URI): Generic Syntax
|
* @see RFC 3986 Uniform Resource Identifier (URI): Generic Syntax
|
||||||
* @see uri_percent_decode
|
* @see uri_percent_decode
|
||||||
* @see xml_chardata_encode
|
* @see xml_chardata_encode
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
uri_percent_encode(char *str,
|
uri_percent_encode(char **encp,
|
||||||
char **escp)
|
char *fmt, ...)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *esc = NULL;
|
char *str = NULL; /* Expanded format string w stdarg */
|
||||||
int len;
|
char *enc = NULL;
|
||||||
int i, j;
|
int fmtlen;
|
||||||
|
int len;
|
||||||
|
int i, j;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
/* Two steps: (1) read in the complete format string */
|
||||||
|
va_start(args, fmt); /* dryrun */
|
||||||
|
fmtlen = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
if ((str = malloc(fmtlen)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(str, 0, fmtlen);
|
||||||
|
va_start(args, fmt); /* real */
|
||||||
|
fmtlen = vsnprintf(str, fmtlen, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
/* Now str is the combined fmt + ... */
|
||||||
|
|
||||||
|
/* Step (2) encode and expand str --> enc */
|
||||||
/* This is max */
|
/* This is max */
|
||||||
len = strlen(str)*3+1;
|
len = strlen(str)*3+1;
|
||||||
if ((esc = malloc(len)) == NULL){
|
if ((enc = malloc(len)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memset(esc, 0, len);
|
memset(enc, 0, len);
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i=0; i<strlen(str); i++){
|
for (i=0; i<strlen(str); i++){
|
||||||
if (uri_unreserved(str[i]))
|
if (uri_unreserved(str[i]))
|
||||||
esc[j++] = str[i];
|
enc[j++] = str[i];
|
||||||
else{
|
else{
|
||||||
snprintf(&esc[j], 4, "%%%02X", str[i]&0xff);
|
snprintf(&enc[j], 4, "%%%02X", str[i]&0xff);
|
||||||
j += 3;
|
j += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*escp = esc;
|
*encp = enc;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (retval < 0 && esc)
|
if (str)
|
||||||
free(esc);
|
free(str);
|
||||||
|
if (retval < 0 && enc)
|
||||||
|
free(enc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Percent decoding according to RFC 3986 URI Syntax
|
/*! Percent decoding according to RFC 3986 URI Syntax
|
||||||
* @param[in] esc Escaped/encoded input string
|
* @param[in] enc Encoded input string
|
||||||
* @param[out] strp Decoded malloced output string. Deallocate with free()
|
* @param[out] strp Decoded malloced output string. Deallocate with free()
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -224,7 +252,7 @@ uri_percent_encode(char *str,
|
||||||
* @see uri_percent_encode
|
* @see uri_percent_encode
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
uri_percent_decode(char *esc,
|
uri_percent_decode(char *enc,
|
||||||
char **strp)
|
char **strp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -235,24 +263,24 @@ uri_percent_decode(char *esc,
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
/* This is max */
|
/* This is max */
|
||||||
len = strlen(esc)+1;
|
len = strlen(enc)+1;
|
||||||
if ((str = malloc(len)) == NULL){
|
if ((str = malloc(len)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memset(str, 0, len);
|
memset(str, 0, len);
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i=0; i<strlen(esc); i++){
|
for (i=0; i<strlen(enc); i++){
|
||||||
if (esc[i] == '%' && strlen(esc)-i > 2 &&
|
if (enc[i] == '%' && strlen(enc)-i > 2 &&
|
||||||
isxdigit(esc[i+1]) && isxdigit(esc[i+2])){
|
isxdigit(enc[i+1]) && isxdigit(enc[i+2])){
|
||||||
hstr[0] = esc[i+1];
|
hstr[0] = enc[i+1];
|
||||||
hstr[1] = esc[i+2];
|
hstr[1] = enc[i+2];
|
||||||
hstr[2] = 0;
|
hstr[2] = 0;
|
||||||
str[j] = strtoul(hstr, &ptr, 16);
|
str[j] = strtoul(hstr, &ptr, 16);
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
str[j] = esc[i];
|
str[j] = enc[i];
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
str[j++] = '\0';
|
str[j++] = '\0';
|
||||||
|
|
@ -265,8 +293,9 @@ uri_percent_decode(char *esc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Escape characters according to XML definition
|
/*! Escape characters according to XML definition
|
||||||
* @param[in] str Not-encoded input string
|
* @param[out] encp Encoded malloced output string
|
||||||
* @param[out] escp Encoded/escaped malloced output string
|
* @param[in] fmt Not-encoded input string (stdarg format string)
|
||||||
|
* @param[in] ... stdarg variable parameters
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#syntax chapter 2.6
|
* @see https://www.w3.org/TR/2008/REC-xml-20081126/#syntax chapter 2.6
|
||||||
|
|
@ -274,8 +303,7 @@ uri_percent_decode(char *esc,
|
||||||
* @see AMPERSAND mode in clixon_xml_parse.l
|
* @see AMPERSAND mode in clixon_xml_parse.l
|
||||||
* @code
|
* @code
|
||||||
* char *encstr = NULL;
|
* char *encstr = NULL;
|
||||||
* char *val = "a<>b";
|
* if (xml_chardata_encode(&encstr, "fmtstr<>& %s", "substr<>") < 0)
|
||||||
* if (xml_chardata_encode(str, &encstr) < 0)
|
|
||||||
* err;
|
* err;
|
||||||
* if (encstr)
|
* if (encstr)
|
||||||
* free(encstr);
|
* free(encstr);
|
||||||
|
|
@ -289,16 +317,34 @@ uri_percent_decode(char *esc,
|
||||||
* Optionally >
|
* Optionally >
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_chardata_encode(char *str,
|
xml_chardata_encode(char **escp,
|
||||||
char **escp)
|
char *fmt,...)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *esc = NULL;
|
char *str = NULL; /* Expanded format string w stdarg */
|
||||||
int l;
|
int fmtlen;
|
||||||
int len;
|
char *esc = NULL;
|
||||||
int i, j;
|
int l;
|
||||||
int cdata; /* when set, skip encoding */
|
int len;
|
||||||
|
int i, j;
|
||||||
|
int cdata; /* when set, skip encoding */
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
/* Two steps: (1) read in the complete format string */
|
||||||
|
va_start(args, fmt); /* dryrun */
|
||||||
|
fmtlen = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
if ((str = malloc(fmtlen)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(str, 0, fmtlen);
|
||||||
|
va_start(args, fmt); /* real */
|
||||||
|
fmtlen = vsnprintf(str, fmtlen, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
/* Now str is the combined fmt + ... */
|
||||||
|
|
||||||
|
/* Step (2) encode and expand str --> enc */
|
||||||
/* First compute length (do nothing) */
|
/* First compute length (do nothing) */
|
||||||
len = 0; cdata = 0;
|
len = 0; cdata = 0;
|
||||||
for (i=0; i<strlen(str); i++){
|
for (i=0; i<strlen(str); i++){
|
||||||
|
|
@ -381,6 +427,8 @@ xml_chardata_encode(char *str,
|
||||||
*escp = esc;
|
*escp = esc;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (str)
|
||||||
|
free(str);
|
||||||
if (retval < 0 && esc)
|
if (retval < 0 && esc)
|
||||||
free(esc);
|
free(esc);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -1018,7 +1018,7 @@ clicon_xml2file(FILE *f,
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
if ((val = xml_value(x)) == NULL) /* incomplete tree */
|
if ((val = xml_value(x)) == NULL) /* incomplete tree */
|
||||||
break;
|
break;
|
||||||
if (xml_chardata_encode(val, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", val) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
fprintf(f, "%s", encstr);
|
fprintf(f, "%s", encstr);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1142,7 +1142,7 @@ clicon_xml2cbuf(cbuf *cb,
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
if ((val = xml_value(x)) == NULL) /* incomplete tree */
|
if ((val = xml_value(x)) == NULL) /* incomplete tree */
|
||||||
break;
|
break;
|
||||||
if (xml_chardata_encode(val, &encstr) < 0)
|
if (xml_chardata_encode(&encstr, "%s", val) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, "%s", encstr);
|
cprintf(cb, "%s", encstr);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1006,7 +1006,7 @@ api_path_fmt2api_path(char *api_path_fmt,
|
||||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (uri_percent_encode(str, &strenc) < 0)
|
if (uri_percent_encode(&strenc, "%s", str) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, "%s", strenc);
|
cprintf(cb, "%s", strenc);
|
||||||
free(strenc); strenc = NULL;
|
free(strenc); strenc = NULL;
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,7 @@ x +--ro namespace inet:uri
|
||||||
+--ro name yang:yang-identifier
|
+--ro name yang:yang-identifier
|
||||||
+--ro revision union
|
+--ro revision union
|
||||||
+--ro schema? inet:uri
|
+--ro schema? inet:uri
|
||||||
|
* @see netconf_create_hello
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_modules_state_get(clicon_handle h,
|
yang_modules_state_get(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,10 @@ expecteof(){
|
||||||
ret=$($cmd<<EOF
|
ret=$($cmd<<EOF
|
||||||
$input
|
$input
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
if [ $? -ne $retval ]; then
|
r=$?
|
||||||
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
if [ $r -ne $retval ]; then
|
||||||
|
echo -e "\e[31m\nError ($r != $retval) in Test$testnr [$testname]:"
|
||||||
echo -e "\e[0m:"
|
echo -e "\e[0m:"
|
||||||
exit -1
|
exit -1
|
||||||
fi
|
fi
|
||||||
|
|
@ -141,7 +142,7 @@ EOF
|
||||||
if [ -z "$ret" -a -z "$expect" ]; then
|
if [ -z "$ret" -a -z "$expect" ]; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
match=`echo "$ret" | grep -Eo "$expect"`
|
match=`echo "$ret" | grep -GZo "$expect"`
|
||||||
# echo "ret:\"$ret\""
|
# echo "ret:\"$ret\""
|
||||||
# echo "expect:\"$expect\""
|
# echo "expect:\"$expect\""
|
||||||
# echo "match:\"$match\""
|
# echo "match:\"$match\""
|
||||||
|
|
|
||||||
|
|
@ -91,10 +91,11 @@ new "netconf validate enabled feature"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf disabled feature"
|
new "netconf disabled feature"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><A>foo</A></config></edit-config></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>protocol</error-type><error-severity>error</error-severity><error-message>XML node config/A has no corresponding yang specification \(Invalid XML or wrong Yang spec?'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><A>foo</A></config></edit-config></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>protocol</error-type><error-severity>error</error-severity><error-message>XML node config/A has no corresponding yang specification (Invalid XML or wrong Yang spec?'
|
||||||
|
|
||||||
|
# This is difficult test since changes to the module list are frequent
|
||||||
new "netconf schema resource, RFC 7895"
|
new "netconf schema resource, RFC 7895"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="modules-state/module" xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"/></get></rpc>]]>]]>' '^<rpc-reply><data><modules-state><module><name>example</name><revision/><namespace/><feature>A</feature></module><module><name>ietf-inet-types</name><revision>2013-07-15</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace></module><module><name>ietf-interfaces</name><revision>2014-05-08</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-interfaces</namespace></module><module><name>ietf-routing</name><revision>2014-10-26</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-routing</namespace><feature>router-id</feature></module><module><name>ietf-yang-library</name><revision>2016-06-21</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace></module><module><name>ietf-yang-types</name><revision>2013-07-15</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace></module></modules-state></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="modules-state/module" xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"/></get></rpc>]]>]]>' '^<rpc-reply><data><modules-state><module><name>example</name><revision/><namespace/><feature>A</feature></module><module><name>ietf-inet-types</name><revision>2013-07-15</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace></module><module><name>ietf-interfaces</name><revision>2014-05-08</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-interfaces</namespace></module><module><name>ietf-netconf</name><revision>2011-06-01</revision><namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace></module><module><name>ietf-routing</name><revision>2014-10-26</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-routing</namespace><feature>router-id</feature></module><module><name>ietf-yang-library</name><revision>2016-06-21</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace></module><module><name>ietf-yang-types</name><revision>2013-07-15</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace></module></modules-state></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# kill backend
|
# kill backend
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@ if [ $? -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "netconf hello"
|
new "netconf hello"
|
||||||
expecteof "$clixon_netconf -f $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<hello><capabilities><capability>urn:ietf:params:netconf:capability:yang-library:1.0\?revision="2016-06-21"\&module-set-id=42</capability></capabilities><session-id>'
|
expecteof "$clixon_netconf -f $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability><capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision="2016-06-21"& module-set-id=42</capability></capabilities><session-id>[0-9]*</session-id></hello>]]>]]><rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
||||||
exit
|
|
||||||
new "netconf get-config"
|
new "netconf get-config"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
|
@ -112,6 +112,7 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101"><get-con
|
||||||
new "Add subtree eth/0/0 using none and create which should add eth/0/0"
|
new "Add subtree eth/0/0 using none and create which should add eth/0/0"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
|
||||||
# Too many quotes, (single inside double inside single) need to fool bash
|
# Too many quotes, (single inside double inside single) need to fool bash
|
||||||
cat <<EOF > $tmp # new
|
cat <<EOF > $tmp # new
|
||||||
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth/0/0']"/></get-config></rpc>]]>]]>
|
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth/0/0']"/></get-config></rpc>]]>]]>
|
||||||
|
|
@ -243,9 +244,6 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><ex:empty/></rpc>]]>]]>"
|
||||||
new "netconf client-side rpc"
|
new "netconf client-side rpc"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><ex:client-rpc><request>example</request></ex:client-rpc></rpc>]]>]]>" "^<rpc-reply><result>ok</result></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><ex:client-rpc><request>example</request></ex:client-rpc></rpc>]]>]]>" "^<rpc-reply><result>ok</result></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf subscription"
|
|
||||||
expectwait "$clixon_netconf -qf $cfg -y $fyang" "<rpc><create-subscription><stream>NETCONF</stream></create-subscription></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]><notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>201' 10
|
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# kill backend
|
# kill backend
|
||||||
sudo clixon_backend -zf $cfg
|
sudo clixon_backend -zf $cfg
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue