* New clixon-config@2022-03-21.yang revision

* Added option:
    * `CLICON_NETCONF_BASE_CAPABILITY`
* Removed `NETCONF_1_1_ANNOUNCE` compile option
This commit is contained in:
Olof hagsand 2022-03-21 11:02:49 +01:00
parent cee735e586
commit bf983d7ca4
8 changed files with 177 additions and 389 deletions

View file

@ -1,184 +0,0 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2019 Olof Hagsand
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
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 *****
*
* netconf lib
*****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <syslog.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/param.h>
/* cligen */
#include <cligen/cligen.h>
/* clicon */
#include <clixon/clixon.h>
#include "netconf_rpc.h"
#include "netconf_lib.h"
/*
* Exported variables
*/
enum transport_type transport = NETCONF_SSH; /* XXX Remove SOAP support */
int cc_closed = 0; /* XXX Please remove (or at least hide in handle) this global variable */
/*! Add netconf xml postamble of message. I.e, xml after the body of the message.
* @param[in] cb Netconf packet (cligen buffer)
*/
int
add_preamble(cbuf *cb)
{
return 0;
}
/*! Add netconf xml postamble of message. I.e, xml after the body of the message.
* for soap this is the envelope stuff, for ssh this is ]]>]]>
* @param[in] cb Netconf packet (cligen buffer)
*/
int
add_postamble(cbuf *cb)
{
switch (transport){
case NETCONF_SSH:
cprintf(cb, "]]>]]>"); /* Add RFC4742 end-of-message marker */
break;
}
return 0;
}
/*! Add error postamble
* compared to regular messages (see add_postamble), error message differ in some
* protocols (eg soap) by adding a longer and deeper header.
* @param[in] cb Netconf packet (cligen buffer)
*/
int
add_error_postamble(cbuf *cb)
{
switch (transport){
default: /* fall through */
if (add_postamble(cb) < 0)
return -1;
break;
}
return 0;
}
/*! Send netconf message from cbuf on socket
* @param[in] s
* @param[in] cb Cligen buffer that contains the XML message
* @param[in] msg Only for debug
* @retval 0 OK
* @retval -1 Error
* @see netconf_output_encap for function with encapsulation
*/
int
netconf_output(int s,
cbuf *cb,
char *msg)
{
char *buf = cbuf_get(cb);
int len = cbuf_len(cb);
int retval = -1;
clicon_debug(1, "SEND %s", msg);
if (clicon_debug_get() > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */
cxobj *xt = NULL;
if (clixon_xml_parse_string(buf, YB_NONE, NULL, &xt, NULL) == 0){
clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0);
fprintf(stderr, "\n");
xml_free(xt);
}
}
if (write(s, buf, len) < 0){
if (errno == EPIPE)
;
else
clicon_log(LOG_ERR, "%s: write: %s", __FUNCTION__, strerror(errno));
goto done;
}
retval = 0;
done:
return retval;
}
/*! Encapsulate and send outgoing netconf packet as cbuf on socket
* @param[in] s
* @param[in] cb Cligen buffer that contains the XML message
* @param[in] msg Only for debug
* @retval 0 OK
* @retval -1 Error
* @note Assumes "cb" contains valid XML
* @see netconf_output without encapsulation
*/
int
netconf_output_encap(int s,
cbuf *cb,
char *msg)
{
int retval = -1;
cbuf *cb1 = NULL;
if ((cb1 = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new");
goto done;
}
add_preamble(cb1);
cprintf(cb1, "%s", cbuf_get(cb));
add_postamble(cb1);
retval = netconf_output(s, cb1, msg);
done:
if (cb1)
cbuf_free(cb1);
return retval;
}

View file

@ -1,78 +0,0 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2019 Olof Hagsand
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC (Netgate)
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 *****
*
* Netconf lib
*****************************************************************************/
#ifndef _NETCONF_LIB_H_
#define _NETCONF_LIB_H_
/*
* Types
*/
enum target_type{ /* netconf */
RUNNING,
CANDIDATE
};
enum transport_type{
NETCONF_SSH, /* RFC 4742 */
};
enum test_option{ /* edit-config */
SET,
TEST_THEN_SET,
TEST_ONLY
};
enum error_option{ /* edit-config */
STOP_ON_ERROR,
CONTINUE_ON_ERROR
};
/*
* Variables
*/
extern enum transport_type transport;
extern int cc_closed;
/*
* Prototypes
*/
int add_preamble(cbuf *xf);
int add_postamble(cbuf *xf);
int netconf_output(int s, cbuf *xf, char *msg);
int netconf_output_encap(int s, cbuf *cb, char *msg);
#endif /* _NETCONF_LIB_H_ */

View file

@ -157,9 +157,3 @@
*/
#define PROTO_RESTART_RECONNECT
/*! Announce Netconf 1.1 capability as defined by RFC 6242
* Problem wih 1.1 is it requires "chunked framing" which Clixon at this point does not
* support.
* See https://github.com/clicon/clixon/issues/50 and https://github.com/clicon/clixon/issues/314
*/
#undef NETCONF_1_1_ANNOUNCE

View file

@ -1690,12 +1690,12 @@ netconf_hello_server(clicon_handle h,
cprintf(cb, "<hello xmlns=\"%s\" message-id=\"%u\">", NETCONF_BASE_NAMESPACE, 42);
cprintf(cb, "<capabilities>");
#ifdef NETCONF_1_1_ANNOUNCE
if (clicon_option_int(h, "CLICON_NETCONF_BASE_CAPABILITY") > 0){
/* Each peer MUST send at least the base NETCONF capability, "urn:ietf:params:netconf:base:1.1"
* RFC 6241 Sec 8.1
*/
cprintf(cb, "<capability>%s</capability>", NETCONF_BASE_CAPABILITY_1_1);
#endif
}
/* A peer MAY include capabilities for previous NETCONF versions, to indicate
that it supports multiple protocol versions. */
cprintf(cb, "<capability>%s</capability>", NETCONF_BASE_CAPABILITY_1_0);

91
test/test_netconf_framing.sh Executable file
View file

@ -0,0 +1,91 @@
#!/usr/bin/env bash
# Netconf framing functionality
# See RFC6242 and RFC 4742
# See test_netconf_hello.sh for hello protocol negotiation only
# 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_yang.xml
fyang=$dir/clixon-example.yang
tmp=$dir/tmp.x
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
<CLICON_NETCONF_DIR>/usr/local/lib/$APPNAME/netconf</CLICON_NETCONF_DIR>
<CLICON_NETCONF_BASE_CAPABILITY>1</CLICON_NETCONF_BASE_CAPABILITY>
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>$dir/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
<CLICON_YANG_LIBRARY>true</CLICON_YANG_LIBRARY>
</clixon-config>
EOF
cat <<EOF > $fyang
module clixon-example{
yang-version 1.1;
namespace "urn:example:clixon";
prefix ex;
/* Generic config data */
container table{
list parameter{
key name;
leaf name{
type string;
}
leaf value{
type string;
}
}
}
}
EOF
new "test params: -f $cfg -- -s"
# Bring your own backend
if [ $BE -ne 0 ]; then
# kill old backend (if any)
new "kill old backend"
sudo clixon_backend -zf $cfg
if [ $? -ne 0 ]; then
err
fi
new "start backend -s init -f $cfg -- -s"
start_backend -s init -f $cfg -- -s
fi
new "wait backend"
wait_backend
# Hello
new "Netconf 1.0 eom framing"
expecteof "$clixon_netconf -qef $cfg -o CLICON_NETCONF_BASE_CAPABILITY=0" 0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><hello $DEFAULTNS><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability></capabilities></hello>]]>]]><rpc $DEFAULTNS><edit-config><default-operation>merge</default-operation><target><candidate/></target><config><table xmlns=\"urn:example:clixon\"><parameter><name>a</name></parameter></table></config></edit-config></rpc>]]>]]>$" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
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
new "endtest"
endtest

View file

@ -42,7 +42,7 @@ datarootdir = @datarootdir@
YANG_INSTALLDIR = @YANG_INSTALLDIR@
# Note: mirror these to test/config.sh.in
YANGSPECS = clixon-config@2022-02-11.yang # 5.6
YANGSPECS = clixon-config@2022-03-21.yang # 5.7
YANGSPECS += clixon-lib@2021-12-05.yang # 5.5
YANGSPECS += clixon-rfc5277@2008-07-01.yang
YANGSPECS += clixon-xml-changelog@2019-03-21.yang

View file

@ -73,7 +73,7 @@ module clixon-config {
CLICON_CLI_GENMODEL (use autocli/enable-autocli instead)
CLICON_CLI_GENMODEL_TYPE (use autocli/list-keyword-default and compress rules instead)
CLICON_CLI_GENMODEL_COMPLETION (use autocli/completion-default instead)
CLICON_CLI_AUTOCLI_EXCLUDE (use autocli/exclude logic instead)
CLICON_CLI_AUTOCLI_EXCLUDE (use autocli/module-default, rule/enable logic instead)
CLICON_CLI_MODEL_TREENAME (use constant AUTOCLI_TREENAME instead)
Released in Clixon 5.5";
}

View file

@ -19,7 +19,7 @@ module clixon-config {
"Clixon configuration file
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
This file is part of CLIXON
@ -46,6 +46,29 @@ module clixon-config {
***** END LICENSE BLOCK *****";
revision 2022-03-21 {
description
"Added option:
CLICON_NETCONF_BASE_CAPABILITY
Released in Clixon 5.7";
}
revision 2022-02-11 {
description
"Added option:
CLICON_LOG_STRING_LIMIT
CLICON_YANG_LIBRARY
Changed default value:
CLICON_MODULE_LIBRARY_RFC7895 to false
Removed (previosly marked) obsolete options:
CLICON_RESTCONF_PATH
CLICON_RESTCONF_PRETTY
CLICON_CLI_GENMODEL
CLICON_CLI_GENMODEL_TYPE
CLICON_CLI_GENMODEL_COMPLETION
CLICON_CLI_AUTOCLI_EXCLUDE
CLICON_CLI_MODEL_TREENAME
Released in Clixon 5.6";
}
revision 2021-12-05 {
description
"Imported
@ -56,7 +79,7 @@ module clixon-config {
CLICON_CLI_GENMODEL (use autocli/enable-autocli instead)
CLICON_CLI_GENMODEL_TYPE (use autocli/list-keyword-default and compress rules instead)
CLICON_CLI_GENMODEL_COMPLETION (use autocli/completion-default instead)
CLICON_CLI_AUTOCLI_EXCLUDE (use autocli/exclude logic instead)
CLICON_CLI_AUTOCLI_EXCLUDE (use autocli/module-default, rule/enable logic instead)
CLICON_CLI_MODEL_TREENAME (use constant AUTOCLI_TREENAME instead)
Released in Clixon 5.5";
}
@ -257,28 +280,6 @@ module clixon-config {
}
}
}
typedef cli_genmodel_type{
description
"How to generate auto CLI from YANG model,
eg {container c {list a{ key x; leaf x; leaf y;}}";
type enumeration{
enum NONE{
description "No extra keywords: c a <x> <y>";
}
enum VARS{
description "Keywords on non-key variables: c a <x> y <y>";
}
enum ALL{
description "Keywords on all variables: c a x <x> y <y>";
}
enum HIDE{
description "Keywords on non-key variables and hide container around lists: a <x> y <y>";
}
enum OC_COMPRESS{
description "See: https://github.com/openconfig/ygot/blob/master/docs/design.md#openconfig-path-compression";
}
}
}
typedef nacm_mode{
description
"Mode of RFC8341 Network Configuration Access Control Model.
@ -476,16 +477,6 @@ module clixon-config {
only loading from startup but may occur in other circumstances as well. This
means that sanity checks of erroneous XML/JSON may not be properly signalled.";
}
leaf CLICON_RESTCONF_PATH {
type string;
default "/www-data/fastcgi_restconf.sock";
description
"FastCGI unix socket. Should be specified in webserver
Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock
Only if with-restconf=fcgi, NOT native
Note: Obsolete, use fcgi-socket in clixon-restconf.yang instead";
status obsolete;
}
leaf CLICON_BACKEND_DIR {
type string;
description
@ -526,6 +517,20 @@ module clixon-config {
If true, an RPC can be sent without a message-id.
This applies to both external NETCONF and internal (IPC) netconf";
}
leaf CLICON_NETCONF_BASE_CAPABILITY {
type int32;
default 1;
description
"This option relates to RFC6241 Sec 8.1 capabilities exchange.
This number is the highest netconf base capability announced during
the hello protocol.
Specifically, If the option number is 0, only 'urn:ietf:params:netconf:base:1.0'
is announced, if it is 1, both 'urn:ietf:params:netconf:base:1.0' and
'urn:ietf:params:netconf:base:1.1' are announced.
Base capability '1' includes switching over to chunked framing as defined in
RFC6242 for example.
This only applies to the external NETCONF";
}
leaf CLICON_RESTCONF_DIR {
type string;
description
@ -562,21 +567,6 @@ module clixon-config {
automatically updated.
If this option is false, the startup is autoamtically updated following the RFC";
}
leaf CLICON_RESTCONF_PRETTY {
type boolean;
default true;
description
"Restconf return value pretty print.
Restconf clients may add HTTP header:
Accept: application/yang-data+json, or
Accept: application/yang-data+xml
to get return value in XML or JSON.
RFC 8040 examples print XML and JSON in pretty-printed form.
Setting this value to false makes restconf return not pretty-printed
which may be desirable for performance or tests
Note: Obsolete, use pretty in clixon-restconf.yang instead";
status obsolete;
}
leaf CLICON_RESTCONF_USER {
type string;
description
@ -635,59 +625,6 @@ module clixon-config {
"Startup CLI mode. This should match a CLICON_MODE variable set in
one of the clispec files";
}
leaf CLICON_CLI_GENMODEL {
type int32;
default 1;
description
"0: Do not generate CLISPEC syntax for the auto-cli.
1: Generate a CLI specification for CLI completion of all loaded Yang modules.
This CLI tree can be accessed in CLI-spec files using the tree reference syntax (eg
@datamodel).
2: Same including state syntax in a tree called @datamodelstate and @datamodelshow
See also CLICON_CLI_MODEL_TREENAME.
Obsolete, use clixon-autocli.yang enable-autocli instead";
status obsolete;
}
leaf CLICON_CLI_MODEL_TREENAME {
type string;
default "datamodel";
description
"If CLICON_CLI_GENMODEL is set, CLI specs can reference the
model syntax using a model tree set by this option.
Three trees are generated with this name as a base, (assuming base is datamodel):
- @datamodel - a clispec for navigating in editing a configuration (set/merge/delete)
- @datamodelshow - a clispec for navigating in showing a configuration
- @datamodelstate - a clispec for navigating in showing a configuration WITH state
Example: set @datamodel, cli_set();
show @datamodelshow, cli_show_auto();
show state @datamodelstate, cli_show_auto_state();
Obsolete, use constant AUTOCLI_TREENAME instead;
";
status obsolete;
}
leaf CLICON_CLI_GENMODEL_COMPLETION {
type int32;
default 1;
description "Generate code for CLI completion of existing db symbols.
Obsolete, use autocli/completion-default instead";
status obsolete;
}
leaf CLICON_CLI_GENMODEL_TYPE {
type cli_genmodel_type;
default "VARS";
description "How to generate and show auto CLI syntax: VARS|ALL|HIDE|OC_COMPRESS";
}
leaf CLICON_CLI_AUTOCLI_EXCLUDE {
type string;
description
"List of module names that should not be generated autocli from
Example:
<CLICON_CLI_AUTOCLI_EXCLUDE>clixon-restconf</CLICON_CLI_AUTOCLI_EXCLUDE>
means generate autocli for all models except clixon-restconf.yang
The value can be a list of space separated module names
Obsolete, use autocli/exclude logic instead";
status obsolete;
}
leaf CLICON_CLI_VARONLY {
type int32;
default 1;
@ -885,7 +822,9 @@ module clixon-config {
default cache;
description
"Clixon datastore cache behaviour. There are three values: no cache,
cache with copy, or cache without copy.";
cache with copy, or cache without copy.
Note: 'cache' is default value and supported with regressions etc.
Others are experimental (in Clixon 5.5)";
}
leaf CLICON_XMLDB_FORMAT {
type datastore_format;
@ -1043,24 +982,41 @@ module clixon-config {
If this option is set, Clixon disables NACM if a datastore does NOT contain a
NACM config on load.";
}
leaf CLICON_MODULE_LIBRARY_RFC7895 {
leaf CLICON_YANG_LIBRARY {
type boolean;
default true;
description
"Enable RFC 7895 YANG Module library support as state data. If
enabled, module info will appear when doing netconf get or
"Enable YANG library support as state data according to RFC8525.
If enabled, module info will appear when doing netconf get or
restconf GET.
See also CLICON_XMLDB_MODSTATE";
The module state data is on the form:
<yang-library><module-set>...
If CLICON_MODULE_LIBRARY_RFC7895 is set (as well), the module state uses RFC7895
instead where the modile state is on the form:
<modules-state>...
See also CLICON_XMLDB_MODSTATE where the module state info is used to tag datastores
with module information.";
}
leaf CLICON_MODULE_LIBRARY_RFC7895 {
type boolean;
default false;
description
"Enable RFC 7895 YANG Module library support as state data, instead of RFC8525.
Note CLICON_YANG_LIBRARY must be enabled for this to have effect.
See also CLICON_YANG_LIBRARY and CLICON_MODULE_SET_ID";
status obsolete;
}
leaf CLICON_MODULE_SET_ID {
type string;
default "0";
description "If RFC 7895 YANG Module library enabled:
Contains a server-specific identifier representing
the current set of modules and submodules. The
server MUST change the value of this leaf if the
information represented by the 'module' list instances
has changed.";
description
"Only if CLICON_YANG_LIBRARY enabled.
Contains a server-specific identifier representing the current set of modules
and submodules. The server MUST change the value of this leaf if the
information represented by the 'module' list instances has changed.
The /yang-library/content-id state-data leaf is set with this value
If CLICON_MODULE_LIBRARY_RFC7895 is enabled, it sets the modules-state/module-set-id
instead";
}
leaf CLICON_STREAM_DISCOVERY_RFC5277 {
type boolean;
@ -1111,5 +1067,14 @@ module clixon-config {
data to store before dropping. 0 means no retention";
}
leaf CLICON_LOG_STRING_LIMIT {
type uint32;
default 0;
description
"Length limitation of debug and log strings.
Especially useful for dynamic debug strings, such as packet dumps.
0 means no limit";
}
}
}