Skip to content

Commit

Permalink
* ietf-netconf yang module added with candidate, validate, startup an…
Browse files Browse the repository at this point in the history
…d xpath features enabled.

* Added urn:ietf:params:netconf:capability:yang-library:1.0
* Thanks SCadilhac for helping out, see #39
* uri_percent_encode() and xml_chardata_encode() changed to use stdarg parameters
  • Loading branch information
olofhagsand committed Oct 17, 2018
1 parent 7046925 commit 40cda7b
Show file tree
Hide file tree
Showing 19 changed files with 245 additions and 93 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<CLICON_FEATURE>*:*</CLICON_FEATURE>
```
* 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
* 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.
Expand All @@ -32,7 +33,8 @@

### 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
* 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
* If you used old event callbacks API, you need to switch to the streams API
* See clixon_stream.[ch]
Expand Down Expand Up @@ -72,8 +74,8 @@
goto done;
```


### 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).
* Yang 1.1 action syntax added (but function is not supported)
* New function: clicon_conf_xml() returns configuration tree
Expand Down
3 changes: 3 additions & 0 deletions apps/backend/backend_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,9 @@ main(int argc,
/* 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 */
if (netconf_module_load(h) < 0)
goto done;
/* Load yang Restconf stream discovery */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
Expand Down
3 changes: 3 additions & 0 deletions apps/cli/cli_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ main(int argc, char **argv)
clicon_yang_module_revision(h),
yspec) < 0)
goto done;
/* Load yang module library, RFC7895 */
if (yang_modules_init(h) < 0)
goto done;
if (printspec)
yang_print(stdout, (yang_node*)yspec);

Expand Down
56 changes: 48 additions & 8 deletions apps/netconf/netconf_hello.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,46 @@ netconf_hello_dispatch(cxobj *xn)
}

/*! 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] cb Msg buffer
* @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
netconf_create_hello(clicon_handle h,
Expand All @@ -121,21 +155,27 @@ netconf_create_hello(clicon_handle h,
int retval = -1;
char *module_set_id;
char *ietf_yang_library_revision;
char *encstr = NULL;

module_set_id = clicon_option_str(h, "CLICON_MODULE_SET_ID");
if ((ietf_yang_library_revision = yang_modules_revision(h)) == NULL)
goto done;
add_preamble(cb);
cprintf(cb, "<hello>");
cprintf(cb, "<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
cprintf(cb, "<capabilities>");
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=\"%s\"&module-set-id=%s</capability>",
ietf_yang_library_revision,
module_set_id);
cprintf(cb, "</capabilities>");
cprintf(cb, "<capability>urn:ietf:params:netconf:base:1.1</capability>");
if (xml_chardata_encode(&encstr, "urn:ietf:params:netconf:capability:yang-library:1.0?revision=\"%s\"&module-set-id=%s",
ietf_yang_library_revision,
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, "</hello>");
add_postamble(cb);
retval = 0;
done:
if (encstr)
free(encstr);
return retval;
}
3 changes: 3 additions & 0 deletions apps/netconf/netconf_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ netconf_get_target(cxobj *xn,
* @param[in] s
* @param[in] cb Cligen buffer that contains the XML message
* @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
netconf_output(int s,
Expand Down
10 changes: 7 additions & 3 deletions apps/netconf/netconf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,11 @@ main(int argc,
argc -= optind;
argv += optind;

/* Create first yang spec */
if ((yspec = yspec_new()) == NULL)
goto done;
clicon_dbspec_yang_set(h, yspec);

/* Parse yang database spec file */
if (yang_filename){
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
Expand All @@ -446,10 +448,12 @@ main(int argc,
yspec) < 0)
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 */
if (yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;

if (netconf_module_load(h) < 0)
goto done;
/* Initialize plugins group */
if ((dir = clicon_netconf_dir(h)) != NULL)
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
Expand Down
8 changes: 5 additions & 3 deletions apps/restconf/restconf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,16 +635,18 @@ main(int argc,
clicon_yang_module_revision(h),
yspec) < 0)
goto done;

/* Load yang module library, RFC7895 */
if (yang_modules_init(h) < 0)
goto done;
/* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec)< 0)
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)
goto done;
Expand Down
6 changes: 3 additions & 3 deletions datastore/keyvalue/clixon_keyvalue.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ append_listkeys(cbuf *ckey,
xml_name(xt), keyname);
goto done;
}
if (uri_percent_encode(xml_body(xkey), &bodyenc) < 0)
if (uri_percent_encode(&bodyenc, "%s", xml_body(xkey)) < 0)
goto done;
if (i++)
cprintf(ckey, ",");
Expand Down Expand Up @@ -328,7 +328,7 @@ get(char *dbname,
* If xml element is a leaf-list, then the next element is expected to
* be a value
*/
if (uri_percent_decode(restval, &argdec) < 0)
if (uri_percent_decode(&argdec, restval) < 0)
goto done;
if ((xc = xml_find(x, name))==NULL ||
(xb = xml_find(xc, argdec))==NULL){
Expand Down Expand Up @@ -681,7 +681,7 @@ put(char *dbfile,
goto done;
break;
case Y_LEAF_LIST:
if (uri_percent_encode(body, &bodyenc) < 0)
if (uri_percent_encode(&bodyenc, "%s", body) < 0)
goto done;
cprintf(cbxk, "=%s", bodyenc);
break;
Expand Down
1 change: 1 addition & 0 deletions lib/clixon/clixon_netconf_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_xml(cxobj **xret, char *message);
int netconf_trymerge(cxobj *x, yang_spec *yspec, cxobj **xret);
int netconf_module_load(clicon_handle h);

#endif /* _CLIXON_NETCONF_LIB_H */
11 changes: 8 additions & 3 deletions lib/clixon/clixon_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@ static inline char * strdup4(char *str)
char **clicon_strsep(char *string, char *delim, int *nvec0);
char *clicon_strjoin (int argc, char **argv, char *delim);
int str2cvec(char *string, char delim1, char delim2, cvec **cvp);
int uri_percent_encode(char *str, char **escp);
int uri_percent_decode(char *esc, char **str);
int xml_chardata_encode(char *str, char **escp);
#if defined(__GNUC__) && __GNUC__ >= 3
int uri_percent_encode(char **encp, char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
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);
int clicon_str2int(const map_str2int *mstab, char *str);

Expand Down
Loading

0 comments on commit 40cda7b

Please sign in to comment.