* Restconf configuration has a new configure model: clixon-restconf.yang enabling restconf daemon configuration from datastore instead of from config file.
This commit is contained in:
parent
40da4421e6
commit
7a0838da3a
14 changed files with 1718 additions and 900 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
|
@ -27,6 +27,23 @@
|
||||||
|
|
||||||
## 4.9.0 Expected: 15 Dec 2020
|
## 4.9.0 Expected: 15 Dec 2020
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
|
* Restconf configuration has a new configure model: `clixon-restconf.yang` enabling restconf daemon configuration from datastore instead of from config file.
|
||||||
|
* Restconf config data, such as addresses, authentication type, etc, is read from the backend datastore instead of the clixon-config file on startup.
|
||||||
|
* This is enabled by setting `CLIXON_RESTCONF_CONFIG` to true (or start clixon-restconf with `-b`), in which case restconf data can be set in the datastore.
|
||||||
|
* This only applies to the evhtp restconf daemon, not fcgi/nginx.
|
||||||
|
* If enabled, most RESTCONF clixon-config options are obsolete
|
||||||
|
* Thanks to Dave Cornejo for the idea
|
||||||
|
* Example: instead of setting `<CLICON_SSL_SERVER_CERT>file</CLICON_SSL_SERVER_CERT>` in clixon.xml, set: `arestconf><socket><server-cert-path>file</server-cert-path></socket></restconf>` in the running datastore before starting restconf.
|
||||||
|
|
||||||
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* New clixon-config@2020-11-03.yang revision
|
||||||
|
* Added option: `CLICON_RESTCONF_CONFIG` for reading restconf daemon config frm datastore
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
|
||||||
* Added new backend plugin: ca_pre-demon called if backend is daemonized just prior to forking.
|
* Added new backend plugin: ca_pre-demon called if backend is daemonized just prior to forking.
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ autocli_tree(clicon_handle h,
|
||||||
enum genmodel_type gt,
|
enum genmodel_type gt,
|
||||||
int state,
|
int state,
|
||||||
int printgen,
|
int printgen,
|
||||||
int show_tree)
|
int show_tree)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
parse_tree *pt = NULL; /* cli parse tree */
|
parse_tree *pt = NULL; /* cli parse tree */
|
||||||
|
|
|
||||||
|
|
@ -79,26 +79,35 @@
|
||||||
#include "restconf_err.h"
|
#include "restconf_err.h"
|
||||||
#include "restconf_root.h"
|
#include "restconf_root.h"
|
||||||
|
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:ro:scP:"
|
#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:ro:bscP:"
|
||||||
|
|
||||||
/* See see listen(5) */
|
/* See see listen(5) */
|
||||||
#define SOCKET_LISTEN_BACKLOG 16
|
#define SOCKET_LISTEN_BACKLOG 16
|
||||||
|
|
||||||
/* Need global variable to for signal handler XXX */
|
/* clixon evhtp handle */
|
||||||
static clicon_handle _CLICON_HANDLE = NULL;
|
typedef struct {
|
||||||
|
|
||||||
static struct evhtp_handle{
|
|
||||||
evhtp_t *eh_htp;
|
evhtp_t *eh_htp;
|
||||||
struct event_base *eh_evbase;
|
struct event_base *eh_evbase;
|
||||||
evhtp_ssl_cfg_t *eh_ssl_config;
|
evhtp_ssl_cfg_t *eh_ssl_config;
|
||||||
} _EVHTP_HANDLE = {0,};
|
} cx_evhtp_handle;
|
||||||
|
|
||||||
|
/* Need this global to pass to signal handler
|
||||||
|
* XXX Try to get rid of code in signal handler
|
||||||
|
*/
|
||||||
|
static cx_evhtp_handle *_EVHTP_HANDLE = NULL;
|
||||||
|
|
||||||
|
/* Need global variable to for signal handler XXX */
|
||||||
|
static clicon_handle _CLICON_HANDLE = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
evhtp_terminate(struct evhtp_handle *eh)
|
evhtp_terminate(cx_evhtp_handle *eh)
|
||||||
{
|
{
|
||||||
evhtp_ssl_cfg_t *sc;
|
evhtp_ssl_cfg_t *sc;
|
||||||
|
|
||||||
|
if (eh == NULL)
|
||||||
|
return;
|
||||||
if (eh->eh_htp){
|
if (eh->eh_htp){
|
||||||
evhtp_unbind_socket(eh->eh_htp);
|
evhtp_unbind_socket(eh->eh_htp);
|
||||||
evhtp_free(eh->eh_htp);
|
evhtp_free(eh->eh_htp);
|
||||||
|
|
@ -114,9 +123,11 @@ evhtp_terminate(struct evhtp_handle *eh)
|
||||||
free(sc->privfile);
|
free(sc->privfile);
|
||||||
free(sc);
|
free(sc);
|
||||||
}
|
}
|
||||||
|
free(eh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Signall terminates process
|
/*! Signall terminates process
|
||||||
|
* XXX Try to get rid of code in signal handler -> so we can get rid of global variables
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
restconf_sig_term(int arg)
|
restconf_sig_term(int arg)
|
||||||
|
|
@ -128,7 +139,8 @@ restconf_sig_term(int arg)
|
||||||
__PROGRAM__, __FUNCTION__, getpid(), arg);
|
__PROGRAM__, __FUNCTION__, getpid(), arg);
|
||||||
else
|
else
|
||||||
exit(-1);
|
exit(-1);
|
||||||
evhtp_terminate(&_EVHTP_HANDLE);
|
if (_EVHTP_HANDLE) /* global */
|
||||||
|
evhtp_terminate(_EVHTP_HANDLE);
|
||||||
if (_CLICON_HANDLE){
|
if (_CLICON_HANDLE){
|
||||||
// stream_child_freeall(_CLICON_HANDLE);
|
// stream_child_freeall(_CLICON_HANDLE);
|
||||||
restconf_terminate(_CLICON_HANDLE);
|
restconf_terminate(_CLICON_HANDLE);
|
||||||
|
|
@ -492,9 +504,84 @@ cx_path_restconf(evhtp_request_t *req,
|
||||||
return; /* void */
|
return; /* void */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get Server cert ssl info
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] server_cert_path Path to server ssl cert file
|
||||||
|
* @param[in] server_key_path Path to server ssl key file
|
||||||
|
* @param[in,out] ssl_config evhtp ssl config struct
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cx_get_ssl_server_certs(clicon_handle h,
|
||||||
|
const char *server_cert_path,
|
||||||
|
const char *server_key_path,
|
||||||
|
evhtp_ssl_cfg_t *ssl_config)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
struct stat f_stat;
|
||||||
|
|
||||||
|
if (ssl_config == NULL || server_cert_path == NULL){
|
||||||
|
clicon_err(OE_CFG, EINVAL, "Input parameter is NULL");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((ssl_config->pemfile = strdup(server_cert_path)) == NULL){
|
||||||
|
clicon_err(OE_CFG, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (stat(ssl_config->pemfile, &f_stat) != 0) {
|
||||||
|
clicon_err(OE_FATAL, errno, "Cannot load SSL cert '%s'", ssl_config->pemfile);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((ssl_config->privfile = strdup(server_key_path)) == NULL){
|
||||||
|
clicon_err(OE_CFG, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (stat(ssl_config->privfile, &f_stat) != 0) {
|
||||||
|
clicon_err(OE_FATAL, errno, "Cannot load SSL key '%s'", ssl_config->privfile);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Get client ssl cert info
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] server_ca_cert_path Path to server ssl CA file for client certs
|
||||||
|
* @param[in,out] ssl_config evhtp ssl config struct
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cx_get_ssl_client_certs(clicon_handle h,
|
||||||
|
const char *server_ca_cert_path,
|
||||||
|
evhtp_ssl_cfg_t *ssl_config)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
struct stat f_stat;
|
||||||
|
|
||||||
|
if (ssl_config == NULL || server_ca_cert_path == NULL){
|
||||||
|
clicon_err(OE_CFG, EINVAL, "Input parameter is NULL");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((ssl_config->cafile = strdup(server_ca_cert_path)) == NULL){
|
||||||
|
clicon_err(OE_CFG, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (stat(ssl_config->cafile, &f_stat) != 0) {
|
||||||
|
clicon_err(OE_FATAL, errno, "Cannot load SSL key '%s'", ssl_config->privfile);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Get Server cert info
|
/*! Get Server cert info
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[out] ssl_config evhtp ssl config struct
|
* @param[in] ssl_verify_clients If true, verify client certs
|
||||||
|
* @param[out] ssl_config evhtp ssl config struct
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cx_get_certs(clicon_handle h,
|
cx_get_certs(clicon_handle h,
|
||||||
|
|
@ -602,10 +689,11 @@ usage(clicon_handle h,
|
||||||
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||||
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
|
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
|
||||||
"\t-r \t\t Do not drop privileges if run as root\n"
|
"\t-r \t\t Do not drop privileges if run as root\n"
|
||||||
|
"\t-b \t\t Read config from backend - not local (same as CLICON_RESTCONF_CONF=true) \n"
|
||||||
"\t-o <option>=<value> Set configuration option overriding config file (see clixon-config.yang)\n"
|
"\t-o <option>=<value> Set configuration option overriding config file (see clixon-config.yang)\n"
|
||||||
"\t-s\t\t SSL server, https\n"
|
"\t-s\t\t SSL server, https (local config)\n"
|
||||||
"\t-c\t\t SSL verify client certs\n"
|
"\t-c\t\t SSL verify client certs (local config)\n"
|
||||||
"\t-P <port>\t HTTP port (default 80, or 443 if -s is given)\n"
|
"\t-P <port>\t HTTP port (default 80, or 443 if -s is given) (local config)\n"
|
||||||
,
|
,
|
||||||
argv0,
|
argv0,
|
||||||
clicon_restconf_dir(h)
|
clicon_restconf_dir(h)
|
||||||
|
|
@ -613,37 +701,255 @@ usage(clicon_handle h,
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! Main routine for libevhtp restconf
|
/*! Main routine for libevhtp restconf
|
||||||
*/
|
*/
|
||||||
|
/*! Phase 2 of start per-socket config
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] xs socket config
|
||||||
|
* @param[in] nsc Namespace context
|
||||||
|
* @param[out] namespace
|
||||||
|
* @param[out] address
|
||||||
|
* @param[out] port
|
||||||
|
* @param[out] ssl
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cx_evhtp_socket(clicon_handle h,
|
||||||
|
cxobj *xs,
|
||||||
|
cvec *nsc,
|
||||||
|
char **namespace,
|
||||||
|
char **address,
|
||||||
|
uint16_t *port,
|
||||||
|
uint16_t *ssl)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *x;
|
||||||
|
char *str = NULL;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((x = xpath_first(xs, nsc, "namespace")) == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Mandatory namespace not given");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
*namespace = xml_body(x);
|
||||||
|
if ((x = xpath_first(xs, nsc, "address")) == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Mandatory address not given");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
*address = xml_body(x);
|
||||||
|
if ((x = xpath_first(xs, nsc, "port")) != NULL &&
|
||||||
|
(str = xml_body(x)) != NULL){
|
||||||
|
if ((ret = parse_uint16(str, port, &reason)) < 0){
|
||||||
|
clicon_err(OE_XML, errno, "parse_uint16");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Unrecognized value of port: %s", str);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((x = xpath_first(xs, nsc, "ssl")) != NULL &&
|
||||||
|
(str = xml_body(x)) != NULL){
|
||||||
|
/* XXX use parse_bool but it is legacy static */
|
||||||
|
if (strcmp(str, "false") == 0)
|
||||||
|
*ssl = 0;
|
||||||
|
else if (strcmp(str, "true") == 0)
|
||||||
|
*ssl = 1;
|
||||||
|
else {
|
||||||
|
clicon_err(OE_XML, EINVAL, "Unrecognized value of ssl: %s", str);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Phase 2 of evhtp init, config has been retrieved from backend
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] xconfig XML config
|
||||||
|
* @param[in] nsc Namespace context
|
||||||
|
* @param[in] eh Evhtp handle
|
||||||
|
* @note only one socket allowed in this implementation
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cx_evhtp_init(clicon_handle h,
|
||||||
|
cxobj *xconfig,
|
||||||
|
cvec *nsc,
|
||||||
|
cx_evhtp_handle *eh)
|
||||||
|
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int auth_type_client_certifificate = 0;
|
||||||
|
uint16_t port = 0;
|
||||||
|
cxobj *xrestconf;
|
||||||
|
cxobj **vec = NULL;
|
||||||
|
size_t veclen;
|
||||||
|
char *auth_type = NULL;
|
||||||
|
char *server_cert_path = NULL;
|
||||||
|
char *server_key_path = NULL;
|
||||||
|
char *server_ca_cert_path = NULL;
|
||||||
|
//XXX char *client_cert_ca = NULL;
|
||||||
|
cxobj *x;
|
||||||
|
char *namespace = NULL;
|
||||||
|
char *address = NULL;
|
||||||
|
uint16_t use_ssl_server = 0;
|
||||||
|
|
||||||
|
/* Extract socket fields from xconfig */
|
||||||
|
if ((xrestconf = xpath_first(xconfig, nsc, "restconf")) == NULL){
|
||||||
|
clicon_err(OE_CFG, ENOENT, "restconf top symbol not found");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* get common fields */
|
||||||
|
if ((x = xpath_first(xrestconf, nsc, "auth-type")) != NULL) /* XXX: leaf-list? */
|
||||||
|
auth_type = xml_body(x);
|
||||||
|
if (auth_type && strcmp(auth_type, "client-certificate") == 0)
|
||||||
|
auth_type_client_certifificate = 1;
|
||||||
|
if ((x = xpath_first(xrestconf, nsc, "server-cert-path")) != NULL)
|
||||||
|
server_cert_path = xml_body(x);
|
||||||
|
if ((x = xpath_first(xrestconf, nsc, "server-key-path")) != NULL)
|
||||||
|
server_key_path = xml_body(x);
|
||||||
|
if ((x = xpath_first(xrestconf, nsc, "server-ca-cert-path")) != NULL)
|
||||||
|
server_ca_cert_path = xml_body(x);
|
||||||
|
// XXX if ((x = xpath_first(xrestconf, nsc, "client-cert-ca")) != NULL)
|
||||||
|
// XXX client_cert_ca = xml_body(x);
|
||||||
|
/* get the list of socket config-data */
|
||||||
|
if (xpath_vec(xrestconf, nsc, "socket", &vec, &veclen) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Accept only a single socket XXX */
|
||||||
|
if (veclen != 1){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Only single socket supported"); /* XXX warning: accept more? */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (cx_evhtp_socket(h, vec[0], nsc, &namespace, &address, &port, &use_ssl_server) < 0)
|
||||||
|
goto done;
|
||||||
|
if (use_ssl_server &&
|
||||||
|
(server_cert_path==NULL || server_key_path == NULL)){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Enabled SSL server requires server_cert_path and server_key_path");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (auth_type_client_certifificate){
|
||||||
|
if (!use_ssl_server){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Client certificate authentication type requires SSL");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (server_ca_cert_path == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Client certificate authentication type requires server-ca-cert-path");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Init evhtp */
|
||||||
|
if ((eh->eh_evbase = event_base_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "event_base_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* create a new evhtp_t instance */
|
||||||
|
if ((eh->eh_htp = evhtp_new(eh->eh_evbase, NULL)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (use_ssl_server){
|
||||||
|
/* Init evhtp ssl config struct */
|
||||||
|
if ((eh->eh_ssl_config = malloc(sizeof(evhtp_ssl_cfg_t))) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(eh->eh_ssl_config, 0, sizeof(evhtp_ssl_cfg_t));
|
||||||
|
eh->eh_ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
|
||||||
|
|
||||||
|
if (cx_get_ssl_server_certs(h, server_cert_path,
|
||||||
|
server_key_path,
|
||||||
|
eh->eh_ssl_config) < 0)
|
||||||
|
goto done;
|
||||||
|
if (auth_type_client_certifificate)
|
||||||
|
if (cx_get_ssl_client_certs(h, server_ca_cert_path, eh->eh_ssl_config) < 0)
|
||||||
|
goto done;
|
||||||
|
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||||
|
if (auth_type_client_certifificate){
|
||||||
|
eh->eh_ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||||
|
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs;
|
||||||
|
eh->eh_ssl_config->verify_depth = 2;
|
||||||
|
}
|
||||||
|
// ssl_verify_mode = htp_sslutil_verify2opts(optarg);
|
||||||
|
}
|
||||||
|
assert(SSL_VERIFY_NONE == 0);
|
||||||
|
|
||||||
|
/* Init evhtp */
|
||||||
|
if ((eh->eh_evbase = event_base_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "event_base_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* create a new evhtp_t instance */
|
||||||
|
if ((eh->eh_htp = evhtp_new(eh->eh_evbase, NULL)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Here the daemon either uses SSL or not, ie you cant seem to mix http and https :-( */
|
||||||
|
if (use_ssl_server){
|
||||||
|
if (evhtp_ssl_init(eh->eh_htp, eh->eh_ssl_config) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef EVHTP_DISABLE_EVTHR /* threads */
|
||||||
|
evhtp_use_threads_wexit(eh->eh_htp, NULL, NULL, 4, NULL);
|
||||||
|
#endif
|
||||||
|
/* Callback before the connection is accepted. */
|
||||||
|
evhtp_set_pre_accept_cb(eh->eh_htp, cx_pre_accept, h);
|
||||||
|
/* Callback right after a connection is accepted. */
|
||||||
|
evhtp_set_post_accept_cb(eh->eh_htp, cx_post_accept, h);
|
||||||
|
/* Callback to be executed for all /restconf api calls */
|
||||||
|
if (evhtp_set_cb(eh->eh_htp, "/" RESTCONF_API, cx_path_restconf, h) == NULL){
|
||||||
|
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Callback to be executed for all /restconf api calls */
|
||||||
|
if (evhtp_set_cb(eh->eh_htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, h) == NULL){
|
||||||
|
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Generic callback called if no other callbacks are matched */
|
||||||
|
evhtp_set_gencb(eh->eh_htp, cx_gencb, h);
|
||||||
|
|
||||||
|
if (evhtp_bind_socket(eh->eh_htp, /* evhtp handle */
|
||||||
|
address, /* string address, eg ipv4:<ipv4addr> */
|
||||||
|
port, /* port */
|
||||||
|
SOCKET_LISTEN_BACKLOG /* backlog flag, see listen(5) */
|
||||||
|
) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "evhtp_bind_socket");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (vec)
|
||||||
|
free(vec);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Read config from backend */
|
||||||
int
|
int
|
||||||
main(int argc,
|
restconf_config_backend(clicon_handle h,
|
||||||
char **argv)
|
int argc,
|
||||||
|
char **argv,
|
||||||
|
int drop_privileges)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *argv0 = argv[0];
|
char *argv0 = argv[0];
|
||||||
int c;
|
|
||||||
clicon_handle h;
|
|
||||||
char *dir;
|
char *dir;
|
||||||
int logdst = CLICON_LOG_SYSLOG;
|
|
||||||
yang_stmt *yspec = NULL;
|
yang_stmt *yspec = NULL;
|
||||||
char *str;
|
char *str;
|
||||||
clixon_plugin *cp = NULL;
|
clixon_plugin *cp = NULL;
|
||||||
cvec *nsctx_global = NULL; /* Global namespace context */
|
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||||
size_t cligen_buflen;
|
size_t cligen_buflen;
|
||||||
size_t cligen_bufthreshold;
|
size_t cligen_bufthreshold;
|
||||||
uint16_t defaultport;
|
cvec *nsc = NULL;
|
||||||
uint16_t port = 0;
|
cxobj *xconfig = NULL;
|
||||||
int dbg = 0;
|
uint32_t id = 0; /* Session id, to poll backend up */
|
||||||
int use_ssl = 0;
|
cx_evhtp_handle *eh = NULL;
|
||||||
int ssl_verify_clients = 0;
|
|
||||||
char *restconf_ipv4_addr = NULL;
|
|
||||||
char *restconf_ipv6_addr = NULL;
|
|
||||||
int i;
|
|
||||||
struct evhtp_handle *eh = &_EVHTP_HANDLE;
|
|
||||||
int drop_priveleges = 1;
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* In the startup, logs to stderr & debug flag set later */
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||||
|
|
||||||
|
|
@ -705,13 +1011,6 @@ main(int argc,
|
||||||
/* Find and read configfile */
|
/* Find and read configfile */
|
||||||
if (clicon_options_main(h) < 0)
|
if (clicon_options_main(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
// stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
|
|
||||||
/* Start with http default port, but change this later if -s is set to https default port */
|
|
||||||
if ((i = clicon_option_int(h, "CLICON_RESTCONF_HTTP_PORT")) < 0){
|
|
||||||
clicon_err(OE_CFG, EINVAL, "CLICON_RESTCONF_HTTP_PORT not found");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
defaultport = (uint16_t)i;
|
|
||||||
|
|
||||||
/* Now rest of options, some overwrite option file */
|
/* Now rest of options, some overwrite option file */
|
||||||
optind = 1;
|
optind = 1;
|
||||||
|
|
@ -745,7 +1044,7 @@ main(int argc,
|
||||||
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||||
break;
|
break;
|
||||||
case 'r':{ /* Do not drop privileges if run as root */
|
case 'r':{ /* Do not drop privileges if run as root */
|
||||||
drop_priveleges = 0;
|
drop_privileges = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'o':{ /* Configuration option */
|
case 'o':{ /* Configuration option */
|
||||||
|
|
@ -757,32 +1056,178 @@ main(int argc,
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 's': /* ssl: use https */
|
|
||||||
use_ssl = 1;
|
|
||||||
/* Set to port - note can be overrifden by -P */
|
|
||||||
if ((i = clicon_option_int(h, "CLICON_RESTCONF_HTTPS_PORT")) < 0){
|
|
||||||
clicon_err(OE_CFG, EINVAL, "CLICON_RESTCONF_HTTPS_PORT not found");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
defaultport = (uint16_t)i;
|
|
||||||
break;
|
|
||||||
case 'c': /* ssl: verify clients */
|
|
||||||
ssl_verify_clients = 1;
|
|
||||||
break;
|
|
||||||
case 'P': /* http port */
|
|
||||||
if (!strlen(optarg))
|
|
||||||
usage(h, argv0);
|
|
||||||
port=atoi(optarg);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
usage(h, argv0);
|
usage(h, argv0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
#endif
|
||||||
|
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
|
||||||
|
xml_nsctx_namespace_netconf_default(h);
|
||||||
|
|
||||||
|
assert(SSL_VERIFY_NONE == 0);
|
||||||
|
|
||||||
|
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||||
|
clicon_argv_set(h, argv0, argc, argv);
|
||||||
|
|
||||||
|
#if 0 /* Drop privileges after evhtp and server key/cert read */
|
||||||
|
if (drop_privileges){
|
||||||
|
/* Drop privileges to WWWUSER if started as root */
|
||||||
|
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Init cligen buffers */
|
||||||
|
cligen_buflen = clicon_option_int(h, "CLICON_CLI_BUF_START");
|
||||||
|
cligen_bufthreshold = clicon_option_int(h, "CLICON_CLI_BUF_THRESHOLD");
|
||||||
|
cbuf_alloc_set(cligen_buflen, cligen_bufthreshold);
|
||||||
|
|
||||||
|
/* Add (hardcoded) netconf features in case ietf-netconf loaded here
|
||||||
|
* Otherwise it is loaded in netconf_module_load below
|
||||||
|
*/
|
||||||
|
if (netconf_module_features(h) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Create top-level yang spec and store as option */
|
||||||
|
if ((yspec = yspec_new()) == NULL)
|
||||||
|
goto done;
|
||||||
|
clicon_dbspec_yang_set(h, yspec);
|
||||||
|
/* Treat unknown XML as anydata */
|
||||||
|
if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1)
|
||||||
|
xml_bind_yang_unknown_anydata(1);
|
||||||
|
|
||||||
|
/* Load restconf plugins before yangs are loaded (eg extension callbacks) */
|
||||||
|
if ((dir = clicon_restconf_dir(h)) != NULL)
|
||||||
|
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
/* Create a pseudo-plugin to create extension callback to set the ietf-routing
|
||||||
|
* yang-data extension for api-root top-level restconf function.
|
||||||
|
*/
|
||||||
|
if (clixon_pseudo_plugin(h, "pseudo restconf", &cp) < 0)
|
||||||
|
goto done;
|
||||||
|
cp->cp_api.ca_extension = restconf_main_extension_cb;
|
||||||
|
|
||||||
|
/* Load Yang modules
|
||||||
|
* 1. Load a yang module as a specific absolute filename */
|
||||||
|
if ((str = clicon_yang_main_file(h)) != NULL){
|
||||||
|
if (yang_spec_parse_file(h, str, yspec) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* 2. Load a (single) main module */
|
||||||
|
if ((str = clicon_yang_module_main(h)) != NULL){
|
||||||
|
if (yang_spec_parse_module(h, str, clicon_yang_module_revision(h),
|
||||||
|
yspec) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* 3. Load all modules in a directory */
|
||||||
|
if ((str = clicon_yang_main_dir(h)) != NULL){
|
||||||
|
if (yang_spec_load_dir(h, str, yspec) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Load clixon lib yang module */
|
||||||
|
if (yang_spec_parse_module(h, "clixon-lib", NULL, yspec) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Load yang module library, RFC7895 */
|
||||||
|
if (yang_modules_init(h) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Load yang restconf module */
|
||||||
|
if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Add netconf yang spec, used as internal protocol */
|
||||||
|
if (netconf_module_load(h) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Add system modules */
|
||||||
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||||
|
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
||||||
|
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Here all modules are loaded
|
||||||
|
* Compute and set canonical namespace context
|
||||||
|
*/
|
||||||
|
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Query backend of config.
|
||||||
|
* Before evhtp, try again if not done */
|
||||||
|
while (1){
|
||||||
|
if (clicon_session_id_get(h, &id) < 0){
|
||||||
|
if (errno == ENOENT){
|
||||||
|
fprintf(stderr, "waiting");
|
||||||
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clicon_session_id_set(h, id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((nsc = xml_nsctx_init(NULL, "https://clicon.org/restconf")) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (clicon_rpc_get_config(h, NULL, "running", "/restconf", nsc, &xconfig) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Initialize evhtp handle - fill it in cx_evhtp_init */
|
||||||
|
if ((eh = malloc(sizeof *eh)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(eh, 0, sizeof *eh);
|
||||||
|
_EVHTP_HANDLE = eh; /* global */
|
||||||
|
if (cx_evhtp_init(h, xconfig, nsc, eh) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Drop privileges after evhtp and server key/cert read */
|
||||||
|
if (drop_privileges){
|
||||||
|
/* Drop privileges to WWWUSER if started as root */
|
||||||
|
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* libevent main loop */
|
||||||
|
event_base_loop(eh->eh_evbase, 0); /* XXX: replace with clixon_event_loop() */
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (xconfig)
|
||||||
|
xml_free(xconfig);
|
||||||
|
if (nsc)
|
||||||
|
cvec_free(nsc);
|
||||||
|
clicon_debug(1, "restconf_main_evhtp done");
|
||||||
|
// stream_child_freeall(h);
|
||||||
|
evhtp_terminate(eh);
|
||||||
|
restconf_terminate(h);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Read config locally */
|
||||||
|
int
|
||||||
|
restconf_config_local(clicon_handle h,
|
||||||
|
int argc,
|
||||||
|
char **argv,
|
||||||
|
uint16_t port,
|
||||||
|
int ssl_verify_clients,
|
||||||
|
int use_ssl,
|
||||||
|
int drop_privileges)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *argv0 = argv[0];
|
||||||
|
char *dir;
|
||||||
|
yang_stmt *yspec = NULL;
|
||||||
|
char *str;
|
||||||
|
clixon_plugin *cp = NULL;
|
||||||
|
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||||
|
size_t cligen_buflen;
|
||||||
|
size_t cligen_bufthreshold;
|
||||||
|
char *restconf_ipv4_addr = NULL;
|
||||||
|
char *restconf_ipv6_addr = NULL;
|
||||||
|
cx_evhtp_handle *eh = NULL;
|
||||||
|
|
||||||
/* port = defaultport unless explicitly set -P */
|
/* port = defaultport unless explicitly set -P */
|
||||||
if (port == 0)
|
|
||||||
port = defaultport;
|
|
||||||
if (port == 0){
|
if (port == 0){
|
||||||
clicon_err(OE_DAEMON, EINVAL, "Restconf bind port is 0");
|
clicon_err(OE_DAEMON, EINVAL, "Restconf bind port is 0");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -790,6 +1235,13 @@ main(int argc,
|
||||||
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
|
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
|
||||||
xml_nsctx_namespace_netconf_default(h);
|
xml_nsctx_namespace_netconf_default(h);
|
||||||
|
|
||||||
|
/* Initialize evhtp handle */
|
||||||
|
if ((eh = malloc(sizeof *eh)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(eh, 0, sizeof *eh);
|
||||||
|
_EVHTP_HANDLE = eh; /* global */
|
||||||
/* Check server ssl certs */
|
/* Check server ssl certs */
|
||||||
if (use_ssl){
|
if (use_ssl){
|
||||||
/* Init evhtp ssl config struct */
|
/* Init evhtp ssl config struct */
|
||||||
|
|
@ -835,7 +1287,6 @@ main(int argc,
|
||||||
#ifndef EVHTP_DISABLE_EVTHR
|
#ifndef EVHTP_DISABLE_EVTHR
|
||||||
evhtp_use_threads_wexit(eh->eh_htp, NULL, NULL, 4, NULL);
|
evhtp_use_threads_wexit(eh->eh_htp, NULL, NULL, 4, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Callback before the connection is accepted. */
|
/* Callback before the connection is accepted. */
|
||||||
evhtp_set_pre_accept_cb(eh->eh_htp, cx_pre_accept, h);
|
evhtp_set_pre_accept_cb(eh->eh_htp, cx_pre_accept, h);
|
||||||
|
|
||||||
|
|
@ -901,7 +1352,8 @@ main(int argc,
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
}
|
}
|
||||||
if (drop_priveleges){
|
|
||||||
|
if (drop_privileges){
|
||||||
/* Drop privileges to WWWUSER if started as root */
|
/* Drop privileges to WWWUSER if started as root */
|
||||||
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -984,9 +1436,10 @@ main(int argc,
|
||||||
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Dump configuration options on debug */
|
/* Call start function in all plugins before we go interactive
|
||||||
if (dbg)
|
*/
|
||||||
clicon_option_dump(h, dbg);
|
if (clixon_plugin_start_all(h) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Call start function in all plugins before we go interactive
|
/* Call start function in all plugins before we go interactive
|
||||||
*/
|
*/
|
||||||
|
|
@ -999,7 +1452,196 @@ main(int argc,
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "restconf_main_evhtp done");
|
clicon_debug(1, "restconf_main_evhtp done");
|
||||||
// stream_child_freeall(h);
|
// stream_child_freeall(h);
|
||||||
evhtp_terminate(&_EVHTP_HANDLE);
|
evhtp_terminate(eh);
|
||||||
|
restconf_terminate(h);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *argv0 = argv[0];
|
||||||
|
int c;
|
||||||
|
clicon_handle h;
|
||||||
|
int logdst = CLICON_LOG_SYSLOG;
|
||||||
|
int dbg = 0;
|
||||||
|
int i;
|
||||||
|
cx_evhtp_handle *eh = NULL;
|
||||||
|
int drop_privileges = 1;
|
||||||
|
uint16_t defaultport = 0;
|
||||||
|
int use_ssl = 0;
|
||||||
|
int ssl_verify_clients = 0;
|
||||||
|
uint16_t port = 0;
|
||||||
|
|
||||||
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
|
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||||
|
|
||||||
|
/* Create handle */
|
||||||
|
if ((h = restconf_handle_init()) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
_CLICON_HANDLE = h; /* for termination handling */
|
||||||
|
|
||||||
|
while ((c = getopt(argc, argv, RESTCONF_OPTS)) != -1)
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
usage(h, argv0);
|
||||||
|
break;
|
||||||
|
case 'D' : /* debug */
|
||||||
|
if (sscanf(optarg, "%d", &dbg) != 1)
|
||||||
|
usage(h, argv0);
|
||||||
|
break;
|
||||||
|
case 'f': /* override config file */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv0);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
|
break;
|
||||||
|
case 'E': /* extra config directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
|
||||||
|
break;
|
||||||
|
case 'l': /* Log destination: s|e|o */
|
||||||
|
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
||||||
|
usage(h, argv0);
|
||||||
|
if (logdst == CLICON_LOG_FILE &&
|
||||||
|
strlen(optarg)>1 &&
|
||||||
|
clicon_log_file(optarg+1) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
} /* switch getopt */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Logs, error and debug to stderr or syslog, set debug level
|
||||||
|
*/
|
||||||
|
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
|
||||||
|
|
||||||
|
clicon_debug_init(dbg, NULL);
|
||||||
|
clicon_log(LOG_NOTICE, "%s: %u Started", __PROGRAM__, getpid());
|
||||||
|
if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){
|
||||||
|
clicon_err(OE_DAEMON, errno, "Setting signal");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (set_signal(SIGINT, restconf_sig_term, NULL) < 0){
|
||||||
|
clicon_err(OE_DAEMON, errno, "Setting signal");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (set_signal(SIGCHLD, restconf_sig_child, NULL) < 0){
|
||||||
|
clicon_err(OE_DAEMON, errno, "Setting signal");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find and read configfile */
|
||||||
|
if (clicon_options_main(h) < 0)
|
||||||
|
goto done;
|
||||||
|
// stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
|
||||||
|
/* XXX only local conf */
|
||||||
|
defaultport = (uint16_t)clicon_option_int(h, "CLICON_RESTCONF_HTTP_PORT");
|
||||||
|
|
||||||
|
/* Now rest of options, some overwrite option file */
|
||||||
|
optind = 1;
|
||||||
|
opterr = 0;
|
||||||
|
while ((c = getopt(argc, argv, RESTCONF_OPTS)) != -1)
|
||||||
|
switch (c) {
|
||||||
|
case 'h' : /* help */
|
||||||
|
case 'D' : /* debug */
|
||||||
|
case 'f': /* config file */
|
||||||
|
case 'E': /* extra config dir */
|
||||||
|
case 'l': /* log */
|
||||||
|
break; /* see above */
|
||||||
|
case 'p' : /* yang dir path */
|
||||||
|
if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case 'd': /* Plugin directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv0);
|
||||||
|
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
|
||||||
|
break;
|
||||||
|
case 'y' : /* Load yang spec file (override yang main module) */
|
||||||
|
clicon_option_str_set(h, "CLICON_YANG_MAIN_FILE", optarg);
|
||||||
|
break;
|
||||||
|
case 'a': /* internal backend socket address family */
|
||||||
|
clicon_option_str_set(h, "CLICON_SOCK_FAMILY", optarg);
|
||||||
|
break;
|
||||||
|
case 'u': /* internal backend socket unix domain path or ip host */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv0);
|
||||||
|
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||||
|
break;
|
||||||
|
case 'r':{ /* Do not drop privileges if run as root */
|
||||||
|
drop_privileges = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'o':{ /* Configuration option */
|
||||||
|
char *val;
|
||||||
|
if ((val = index(optarg, '=')) == NULL)
|
||||||
|
usage(h, argv0);
|
||||||
|
*val++ = '\0';
|
||||||
|
if (clicon_option_add(h, optarg, val) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b': /* Read config from backend - not local */
|
||||||
|
clicon_option_bool_set(h, "CLICON_RESTCONF_CONFIG", 1);
|
||||||
|
break;
|
||||||
|
case 's': /* ssl: use https */
|
||||||
|
use_ssl = 1;
|
||||||
|
/* Set to port - note can be overrifden by -P */
|
||||||
|
if ((i = clicon_option_int(h, "CLICON_RESTCONF_HTTPS_PORT")) < 0){
|
||||||
|
clicon_err(OE_CFG, EINVAL, "CLICON_RESTCONF_HTTPS_PORT not found");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
defaultport = (uint16_t)i;
|
||||||
|
break;
|
||||||
|
case 'c': /* ssl: verify clients */
|
||||||
|
ssl_verify_clients = 1;
|
||||||
|
break;
|
||||||
|
case 'P': /* http port */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv0);
|
||||||
|
port=atoi(optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(h, argv0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
/* Dump configuration options on debug */
|
||||||
|
if (dbg)
|
||||||
|
clicon_option_dump(h, dbg);
|
||||||
|
|
||||||
|
/* port = defaultport unless explicitly set -P */
|
||||||
|
if (port == 0)
|
||||||
|
port = defaultport;
|
||||||
|
|
||||||
|
if (clicon_option_bool(h, "CLICON_RESTCONF_CONFIG") == 0){
|
||||||
|
/* Read config locally */
|
||||||
|
if (restconf_config_local(h, argc, argv,
|
||||||
|
port,
|
||||||
|
ssl_verify_clients,
|
||||||
|
use_ssl,
|
||||||
|
drop_privileges
|
||||||
|
) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Read config from backend */
|
||||||
|
if (restconf_config_backend(h, argc, argv, drop_privileges) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_base_loop(eh->eh_evbase, 0);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
clicon_debug(1, "restconf_main_evhtp done");
|
||||||
|
// stream_child_freeall(h);
|
||||||
|
evhtp_terminate(eh);
|
||||||
restconf_terminate(h);
|
restconf_terminate(h);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1379,6 +1379,10 @@ netconf_module_load(clicon_handle h)
|
||||||
if (clicon_option_bool(h, "CLICON_XML_CHANGELOG"))
|
if (clicon_option_bool(h, "CLICON_XML_CHANGELOG"))
|
||||||
if (yang_spec_parse_module(h, "clixon-xml-changelog", NULL, yspec)< 0)
|
if (yang_spec_parse_module(h, "clixon-xml-changelog", NULL, yspec)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Clixon restconf daemon */
|
||||||
|
if (clicon_option_bool(h, "CLICON_RESTCONF_CONFIG"))
|
||||||
|
if (yang_spec_parse_module(h, "clixon-restconf", NULL, yspec)< 0)
|
||||||
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ fi
|
||||||
fi # false
|
fi # false
|
||||||
|
|
||||||
new "netconf module ietf-inet-types"
|
new "netconf module ietf-inet-types"
|
||||||
expect="<module><name>ietf-inet-types</name><revision>2013-07-15</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace><conformance-type>implement</conformance-type></module>"
|
expect="<module><name>ietf-inet-types</name><revision>2020-07-06</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace><conformance-type>implement</conformance-type></module>"
|
||||||
match=`echo "$ret" | grep --null -Go "$expect"`
|
match=`echo "$ret" | grep --null -Go "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
|
|
|
||||||
120
test/test_restconf_backend_config.sh
Executable file
120
test/test_restconf_backend_config.sh
Executable file
|
|
@ -0,0 +1,120 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# New Restconf config using backend config
|
||||||
|
# DOES NOT WORK WITH FCGI
|
||||||
|
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
# Skip it other than evhtp
|
||||||
|
if [ "${WITH_RESTCONF}" != "evhtp" ]; then
|
||||||
|
if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip
|
||||||
|
fi
|
||||||
|
|
||||||
|
APPNAME=example
|
||||||
|
cfg=$dir/conf.xml
|
||||||
|
|
||||||
|
# Use yang in example
|
||||||
|
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_MODULE_MAIN>clixon-example</CLICON_YANG_MODULE_MAIN>
|
||||||
|
<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
|
||||||
|
<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_RESTCONF_CONFIG>true</CLICON_RESTCONF_CONFIG>
|
||||||
|
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
||||||
|
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [ ${RCPROTO} = "https" ]; then
|
||||||
|
ssl=true
|
||||||
|
port=443
|
||||||
|
else
|
||||||
|
ssl=false
|
||||||
|
port=80
|
||||||
|
fi
|
||||||
|
cat<<EOF > $dir/startup_db
|
||||||
|
<config>
|
||||||
|
<restconf xmlns="https://clicon.org/restconf">
|
||||||
|
<socket>
|
||||||
|
<namespace>default</namespace>
|
||||||
|
<address>0.0.0.0</address>
|
||||||
|
<port>$port</port>
|
||||||
|
<ssl>$ssl</ssl>
|
||||||
|
</socket>
|
||||||
|
<auth-type>password</auth-type>
|
||||||
|
<server-cert-path>/etc/ssl/certs/clixon-server-crt.pem</server-cert-path>
|
||||||
|
<server-key-path>/etc/ssl/private/clixon-server-key.pem</server-key-path>
|
||||||
|
<server-ca-cert-path>/etc/ssl/certs/clixon-ca_crt.pem</server-ca-cert-path>
|
||||||
|
<client-cert-ca></client-cert-ca>
|
||||||
|
</restconf>
|
||||||
|
</config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "test params: -f $cfg"
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
|
new "kill old backend"
|
||||||
|
sudo clixon_backend -zf $cfg -s startup
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
sudo pkill -f clixon_backend # to be sure
|
||||||
|
|
||||||
|
new "start backend -s startup -f $cfg"
|
||||||
|
start_backend -s startup -f $cfg
|
||||||
|
fi
|
||||||
|
|
||||||
|
new "wait backend"
|
||||||
|
wait_backend
|
||||||
|
|
||||||
|
if [ $RC -ne 0 ]; then
|
||||||
|
new "kill old restconf daemon"
|
||||||
|
stop_restconf_pre
|
||||||
|
|
||||||
|
new "start restconf daemon"
|
||||||
|
start_restconf -f $cfg
|
||||||
|
|
||||||
|
fi
|
||||||
|
new "wait restconf"
|
||||||
|
wait_restconf
|
||||||
|
|
||||||
|
new "restconf root discovery. RFC 8040 3.1 (xml+xrd)"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/.well-known/host-meta)" 0 'HTTP/1.1 200 OK' "<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>" "<Link rel='restconf' href='/restconf'/>" "</XRD>"
|
||||||
|
|
||||||
|
new "restconf get restconf resource. RFC 8040 3.3 (json)"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+json" $RCPROTO://localhost/restconf)" 0 'HTTP/1.1 200 OK' '{"ietf-restconf:restconf":{"data":{},"operations":{},"yang-library-version":"2016-06-21"}}'
|
||||||
|
|
||||||
|
new "restconf get restconf resource. RFC 8040 3.3 (xml)"
|
||||||
|
# Get XML instead of JSON?
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf)" 0 'HTTP/1.1 200 OK' '<restconf xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf"><data/><operations/><yang-library-version>2016-06-21</yang-library-version></restconf>'
|
||||||
|
|
||||||
|
if [ $RC -ne 0 ]; then
|
||||||
|
new "Kill restconf daemon"
|
||||||
|
stop_restconf
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $BE -eq 0 ]; then
|
||||||
|
exit # BE
|
||||||
|
fi
|
||||||
|
|
||||||
|
new "Kill backend"
|
||||||
|
# Check if premature kill
|
||||||
|
pid=$(pgrep -u root -f clixon_backend)
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
err "backend already dead"
|
||||||
|
fi
|
||||||
|
# kill backend
|
||||||
|
stop_backend -f $cfg
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
|
@ -101,7 +101,7 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR
|
||||||
# This just catches the header and the jukebox module, the RFC has foo and bar which
|
# This just catches the header and the jukebox module, the RFC has foo and bar which
|
||||||
# seems wrong to recreate
|
# seems wrong to recreate
|
||||||
new "B.1.2. Retrieve the Server Module Information"
|
new "B.1.2. Retrieve the Server Module Information"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},'
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"}'
|
||||||
|
|
||||||
new "B.1.3. Retrieve the Server Capability Information"
|
new "B.1.3. Retrieve the Server Capability Information"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' '<capabilities xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"><capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability><capability>urn:ietf:params:restconf:capability:depth</capability>
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' '<capabilities xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"><capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability><capability>urn:ietf:params:restconf:capability:depth</capability>
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ cat <<EOF > $dir/startup_db
|
||||||
</config>
|
</config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
MODSTATE='<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"><module-set-id>0</module-set-id><module><name>clixon-lib</name><revision>2020-04-23</revision><namespace>http://clicon.org/lib</namespace></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-netconf</name><revision>2011-06-01</revision><namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace></module><module><name>ietf-restconf</name><revision>2017-01-26</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-restconf</namespace></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><module><name>interfaces</name><revision>2018-02-20</revision><namespace>urn:example:interfaces</namespace></module></modules-state>'
|
MODSTATE='<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"><module-set-id>0</module-set-id><module><name>clixon-lib</name><revision>2020-04-23</revision><namespace>http://clicon.org/lib</namespace></module><module><name>ietf-inet-types</name><revision>2020-07-06</revision><namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace></module><module><name>ietf-netconf</name><revision>2011-06-01</revision><namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace></module>'
|
||||||
|
|
||||||
XML='<interfaces xmlns="urn:example:interfaces"><interface><name>e0</name><docs><descr>First interface</descr></docs><type>eth</type><admin-status>up</admin-status><statistics><in-octets>54326.432</in-octets><in-unicast-pkts>8458765</in-unicast-pkts></statistics></interface><interface><name>e1</name><type>eth</type><admin-status>down</admin-status></interface></interfaces>'
|
XML='<interfaces xmlns="urn:example:interfaces"><interface><name>e0</name><docs><descr>First interface</descr></docs><type>eth</type><admin-status>up</admin-status><statistics><in-octets>54326.432</in-octets><in-unicast-pkts>8458765</in-unicast-pkts></statistics></interface><interface><name>e1</name><type>eth</type><admin-status>down</admin-status></interface></interfaces>'
|
||||||
|
|
||||||
|
|
@ -315,12 +315,18 @@ sudo clixon_backend -zf $cfg
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "start backend -s startup -f $cfg -q -- -u"
|
new "start backend -s startup -f $cfg -q -- -u"
|
||||||
output=$(sudo $clixon_backend -F -D $DBG -s startup -f $cfg -q -- -u)
|
output=$(sudo $clixon_backend -F -D $DBG -s startup -f $cfg -q -- -u)
|
||||||
#echo "$output"
|
|
||||||
|
|
||||||
if [ "$ALL" != "$output" ]; then
|
match=$(echo "$output" | grep --null -o "$MODSTATE")
|
||||||
err "$ALL" "$output"
|
if [ -z "$match" ]; then
|
||||||
|
err "$MODSTATE" "$output"
|
||||||
|
fi
|
||||||
|
|
||||||
|
match=$(echo "$output" | grep --null -o "$XML")
|
||||||
|
if [ -z "$match" ]; then
|
||||||
|
err "$XML" "$output"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,11 @@ datarootdir = @datarootdir@
|
||||||
# See also OPT_YANG_INSTALLDIR for the standard yang files
|
# See also OPT_YANG_INSTALLDIR for the standard yang files
|
||||||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
YANGSPECS = clixon-config@2020-10-01.yang
|
YANGSPECS = clixon-config@2020-11-03.yang
|
||||||
YANGSPECS += clixon-lib@2020-04-23.yang
|
YANGSPECS += clixon-lib@2020-04-23.yang
|
||||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||||
|
YANGSPECS += clixon-restconf@2020-10-30.yang
|
||||||
|
|
||||||
APPNAME = clixon # subdir ehere these files are installed
|
APPNAME = clixon # subdir ehere these files are installed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,803 +0,0 @@
|
||||||
module clixon-config {
|
|
||||||
yang-version 1.1;
|
|
||||||
namespace "http://clicon.org/config";
|
|
||||||
prefix cc;
|
|
||||||
|
|
||||||
organization
|
|
||||||
"Clicon / Clixon";
|
|
||||||
|
|
||||||
contact
|
|
||||||
"Olof Hagsand <olof@hagsand.se>";
|
|
||||||
|
|
||||||
description
|
|
||||||
"Clixon configuration file
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
Copyright (C) 2009-2019 Olof Hagsand
|
|
||||||
Copyright (C) 2020 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 *****";
|
|
||||||
|
|
||||||
/* Deleted: clixon-stats state for clixon XML and memory statistics. (moved to clixon-lib)
|
|
||||||
*/
|
|
||||||
revision 2020-06-17 {
|
|
||||||
description
|
|
||||||
"Added: CLICON_CLI_LINES_DEFAULT
|
|
||||||
Added enum HIDE to CLICON_CLI_GENMODEL
|
|
||||||
Added CLICON_SSL_SERVER_CERT, CLICON_SSL_SERVER_KEY, CLICON_SSL_CA_CERT
|
|
||||||
Added CLICON_NACM_DISABLED_ON_EMPTY
|
|
||||||
Removed default valude of CLICON_NACM_RECOVERY_USER";
|
|
||||||
}
|
|
||||||
revision 2020-04-23 {
|
|
||||||
description
|
|
||||||
"Added: CLICON_YANG_UNKNOWN_ANYDATA to treat unknown XML (wrt YANG) as anydata.
|
|
||||||
Deleted: xml-stats non-config data (replaced by rpc stats in clixon-lib.yang)";
|
|
||||||
}
|
|
||||||
revision 2020-02-22 {
|
|
||||||
description
|
|
||||||
"Added: search index extension,
|
|
||||||
Added: clixon-stats state for clixon XML and memory statistics.
|
|
||||||
Added: CLICON_CLI_BUF_START and CLICON_CLI_BUF_THRESHOLD for quadratic and linear
|
|
||||||
growth of CLIgen buffers (cbuf:s)
|
|
||||||
Added: CLICON_VALIDATE_STATE_XML for controling validation of user state XML
|
|
||||||
Added: CLICON_CLICON_YANG_LIST_CHECK to skip list key checks";
|
|
||||||
}
|
|
||||||
revision 2019-09-11 {
|
|
||||||
description
|
|
||||||
"Added: CLICON_BACKEND_USER: drop of privileges to user,
|
|
||||||
CLICON_BACKEND_PRIVILEGES: how to drop privileges
|
|
||||||
CLICON_NACM_CREDENTIALS: If and how to check backend sock priveleges with NACM
|
|
||||||
CLICON_NACM_RECOVERY_USER: Name of NACM recovery user.";
|
|
||||||
}
|
|
||||||
revision 2019-06-05 {
|
|
||||||
description
|
|
||||||
"Added: CLICON_YANG_REGEXP, CLICON_CLI_TAB_MODE,
|
|
||||||
CLICON_CLI_HIST_FILE, CLICON_CLI_HIST_SIZE,
|
|
||||||
CLICON_XML_CHANGELOG, CLICON_XML_CHANGELOG_FILE;
|
|
||||||
Renamed CLICON_XMLDB_CACHE to CLICON_DATASTORE_CACHE (changed type)
|
|
||||||
Deleted: CLICON_XMLDB_PLUGIN, CLICON_USE_STARTUP_CONFIG";
|
|
||||||
}
|
|
||||||
revision 2019-03-05{
|
|
||||||
description
|
|
||||||
"Changed URN. Changed top-level symbol to clixon-config.
|
|
||||||
Released in Clixon 3.10";
|
|
||||||
}
|
|
||||||
revision 2019-02-06 {
|
|
||||||
description
|
|
||||||
"Released in Clixon 3.9";
|
|
||||||
}
|
|
||||||
revision 2018-10-21 {
|
|
||||||
description
|
|
||||||
"Released in Clixon 3.8";
|
|
||||||
}
|
|
||||||
extension search_index {
|
|
||||||
description "This list argument acts as a search index using optimized binary search.
|
|
||||||
";
|
|
||||||
}
|
|
||||||
typedef startup_mode{
|
|
||||||
description
|
|
||||||
"Which method to boot/start clicon backend.
|
|
||||||
The methods differ in how they reach a running state
|
|
||||||
Which source database to commit from, if any.";
|
|
||||||
type enumeration{
|
|
||||||
enum none{
|
|
||||||
description
|
|
||||||
"Do not touch running state
|
|
||||||
Typically after crash when running state and db are synched";
|
|
||||||
}
|
|
||||||
enum init{
|
|
||||||
description
|
|
||||||
"Initialize running state.
|
|
||||||
Start with a completely clean running state";
|
|
||||||
}
|
|
||||||
enum running{
|
|
||||||
description
|
|
||||||
"Commit running db configuration into running state
|
|
||||||
After reboot if a persistent running db exists";
|
|
||||||
}
|
|
||||||
enum startup{
|
|
||||||
description
|
|
||||||
"Commit startup configuration into running state
|
|
||||||
After reboot when no persistent running db exists";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef datastore_format{
|
|
||||||
description
|
|
||||||
"Datastore format.";
|
|
||||||
type enumeration{
|
|
||||||
enum xml{
|
|
||||||
description "Save and load xmldb as XML";
|
|
||||||
}
|
|
||||||
enum json{
|
|
||||||
description "Save and load xmldb as JSON";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef datastore_cache{
|
|
||||||
description
|
|
||||||
"XML configuration, ie running/candididate/ datastore cache behaviour.";
|
|
||||||
type enumeration{
|
|
||||||
enum nocache{
|
|
||||||
description "No cache always work directly with file";
|
|
||||||
}
|
|
||||||
enum cache{
|
|
||||||
description "Use in-memory cache.
|
|
||||||
Make copies when accessing internally.";
|
|
||||||
}
|
|
||||||
enum cache-zerocopy{
|
|
||||||
description "Use in-memory cache and dont copy.
|
|
||||||
Fastest but opens up for callbacks changing cache.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef cli_genmodel_type{
|
|
||||||
description
|
|
||||||
"How to generate 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>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef nacm_mode{
|
|
||||||
description
|
|
||||||
"Mode of RFC8341 Network Configuration Access Control Model.
|
|
||||||
It is unclear from the RFC whether NACM rules are internal
|
|
||||||
in a configuration (ie embedded in regular config) or external/OOB
|
|
||||||
in s separate, specific NACM-config";
|
|
||||||
type enumeration{
|
|
||||||
enum disabled{
|
|
||||||
description "NACM is disabled";
|
|
||||||
}
|
|
||||||
enum internal{
|
|
||||||
description "NACM is enabled and available in the regular config";
|
|
||||||
}
|
|
||||||
enum external{
|
|
||||||
description "NACM is enabled and available in a separate config";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef regexp_mode{
|
|
||||||
description
|
|
||||||
"The regular expression engine Clixon uses in its validation of
|
|
||||||
Yang patterns, and in the CLI.
|
|
||||||
Yang RFC 7950 stipulates XSD XML Schema regexps
|
|
||||||
according to W3 CXML Schema Part 2: Datatypes Second Edition,
|
|
||||||
see http://www.w3.org/TR/2004/REC-xmlschema-2-20041028#regexs";
|
|
||||||
type enumeration{
|
|
||||||
enum posix {
|
|
||||||
description
|
|
||||||
"Translate XSD XML Schema regexp:s to Posix regexp. This is
|
|
||||||
not a complete translation, but can be considered good-enough
|
|
||||||
for Yang use-cases as defined by openconfig and yang-models
|
|
||||||
for example.";
|
|
||||||
}
|
|
||||||
enum libxml2 {
|
|
||||||
description
|
|
||||||
"Use libxml2 XSD XML Schema regexp engine. This is a complete
|
|
||||||
XSD regexp engine..
|
|
||||||
Requires libxml2 to be available at configure time
|
|
||||||
(HAVE_LIBXML2 should be set)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef priv_mode{
|
|
||||||
description
|
|
||||||
"Privilege mode, used for dropping (or not) priveleges to a non-provileged
|
|
||||||
user after initialization";
|
|
||||||
type enumeration{
|
|
||||||
enum none {
|
|
||||||
description
|
|
||||||
"Make no drop/change in privileges.";
|
|
||||||
}
|
|
||||||
enum drop_perm {
|
|
||||||
description
|
|
||||||
"After initialization, drop privileges permanently to a uid";
|
|
||||||
}
|
|
||||||
enum drop_temp {
|
|
||||||
description
|
|
||||||
"After initialization, drop privileges temporarily to a euid";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef nacm_cred_mode{
|
|
||||||
description
|
|
||||||
"How NACM user should be matched with unix socket peer credentials.
|
|
||||||
This means nacm user must match socket peer user accessing the
|
|
||||||
backend socket. For IP sockets only mode none makes sense.";
|
|
||||||
type enumeration{
|
|
||||||
enum none {
|
|
||||||
description
|
|
||||||
"Dont match NACM user to any user credentials. Any user can pose
|
|
||||||
as any other user. Set this for IP sockets, or dont use NACM.";
|
|
||||||
}
|
|
||||||
enum exact {
|
|
||||||
description
|
|
||||||
"Exact match between NACM user and unix socket peer user.";
|
|
||||||
}
|
|
||||||
enum except {
|
|
||||||
description
|
|
||||||
"Exact match between NACM user and unix socket peer user, except
|
|
||||||
for root and www user (restconf).";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
container clixon-config {
|
|
||||||
leaf-list CLICON_FEATURE {
|
|
||||||
description
|
|
||||||
"Supported features as used by YANG feature/if-feature
|
|
||||||
value is: <module>:<feature>, where <module> and <feature>
|
|
||||||
are either names, or the special character '*'.
|
|
||||||
*:* means enable all features
|
|
||||||
<module>:* means enable all features in the specified module
|
|
||||||
*:<feature> means enable the specific feature in all modules";
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
leaf CLICON_CONFIGFILE{
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Location of configuration-file for default values (this file).
|
|
||||||
Default is CLIXON_DEFAULT_CONFIG=/usr/local/etc/clicon.xml
|
|
||||||
set in configure. Note that due to bootstrapping, a default
|
|
||||||
value here does not work.";
|
|
||||||
}
|
|
||||||
leaf-list CLICON_YANG_DIR {
|
|
||||||
ordered-by user;
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Yang directory path for finding module and submodule files.
|
|
||||||
A list of these options should be in the configuration.
|
|
||||||
When loading a Yang module, Clixon searches this list in the order
|
|
||||||
they appear. Ensure that YANG_INSTALLDIR(default
|
|
||||||
/usr/local/share/clixon) is present in the path";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_MAIN_FILE {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"If specified load a yang module in a specific absolute filename.
|
|
||||||
This corresponds to the -y command-line option in most CLixon
|
|
||||||
programs.";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_MAIN_DIR {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"If given, load all modules in this directory (all .yang files)
|
|
||||||
See also CLICON_YANG_DIR which specifies a path of dirs";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_MODULE_MAIN {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Option used to construct initial yang file:
|
|
||||||
<module>[@<revision>]";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_MODULE_REVISION {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Option used to construct initial yang file:
|
|
||||||
<module>[@<revision>].
|
|
||||||
Used together with CLICON_YANG_MODULE_MAIN";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_REGEXP {
|
|
||||||
type regexp_mode;
|
|
||||||
default posix;
|
|
||||||
description
|
|
||||||
"The regular expression engine Clixon uses in its validation of
|
|
||||||
Yang patterns, and in the CLI.
|
|
||||||
There is a 'good-enough' posix translation mode and a complete
|
|
||||||
libxml2 mode";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_LIST_CHECK {
|
|
||||||
type boolean;
|
|
||||||
default true;
|
|
||||||
description
|
|
||||||
"If false, skip Yang list check sanity checks from RFC 7950, Sec 7.8.2:
|
|
||||||
The 'key' statement, which MUST be present if the list represents configuration.
|
|
||||||
Some yang specs seem not to fulfil this. However, if you reset this, there may
|
|
||||||
be follow-up errors due to code that assumes a configuration list has keys";
|
|
||||||
}
|
|
||||||
leaf CLICON_YANG_UNKNOWN_ANYDATA{
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description
|
|
||||||
"Treat unknown XML/JSON nodes as anydata when loading from startup db.
|
|
||||||
This does not apply to namespaces, which means a top-level node: xxx:yyy
|
|
||||||
is accepted only if yyy is unknown, not xxx.
|
|
||||||
Note that this option has several caveats which needs to be fixed. Please
|
|
||||||
use with care.
|
|
||||||
The primary issue is that the unknown->anydata handling is not restricted to
|
|
||||||
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_BACKEND_DIR {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Location of backend .so plugins. Load all .so
|
|
||||||
plugins in this dir as backend plugins";
|
|
||||||
}
|
|
||||||
leaf CLICON_BACKEND_REGEXP {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Regexp of matching backend plugins in CLICON_BACKEND_DIR";
|
|
||||||
default "(.so)$";
|
|
||||||
}
|
|
||||||
leaf CLICON_NETCONF_DIR {
|
|
||||||
type string;
|
|
||||||
description "Location of netconf (frontend) .so plugins";
|
|
||||||
}
|
|
||||||
leaf CLICON_RESTCONF_DIR {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Location of restconf (frontend) .so plugins. Load all .so
|
|
||||||
plugins in this dir as restconf code plugins";
|
|
||||||
}
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
leaf CLICON_SSL_SERVER_CERT {
|
|
||||||
type string;
|
|
||||||
default "/etc/ssl/certs/clixon-server-crt.pem";
|
|
||||||
description
|
|
||||||
"SSL server cert for restconf https. This is not required if you use
|
|
||||||
--with-restconf=fcgi, ie a reverse-proxy based such as nginx over fcgi";
|
|
||||||
}
|
|
||||||
leaf CLICON_SSL_SERVER_KEY {
|
|
||||||
type string;
|
|
||||||
default "/etc/ssl/private/clixon-server-key.pem";
|
|
||||||
description
|
|
||||||
"SSL server private key for restconf https. This is not required if you use
|
|
||||||
--with-restconf=fcgi, ie a reverse-proxy based such as nginx over fcgi";
|
|
||||||
}
|
|
||||||
leaf CLICON_SSL_CA_CERT {
|
|
||||||
type string;
|
|
||||||
default "/etc/ssl/certs/clixon-ca_crt.pem";
|
|
||||||
description
|
|
||||||
"SSL CA cert for client authentication. This is not required if you use
|
|
||||||
--with-restconf=fcgi, ie a reverse-proxy based such as nginx over fcgi";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_DIR {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Directory containing frontend cli loadable plugins. Load all .so
|
|
||||||
plugins in this directory as CLI object plugins";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLISPEC_DIR {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Directory containing frontend cligen spec files. Load all .cli
|
|
||||||
files in this directory as CLI specification files.
|
|
||||||
See also CLICON_CLISPEC_FILE.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLISPEC_FILE {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Specific frontend cligen spec file as aletrnative or complement
|
|
||||||
to CLICON_CLISPEC_DIR. Also available as -c in clixon_cli.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_MODE {
|
|
||||||
type string;
|
|
||||||
default "base";
|
|
||||||
description
|
|
||||||
"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.
|
|
||||||
See also CLICON_CLI_MODEL_TREENAME.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_MODEL_TREENAME {
|
|
||||||
type string;
|
|
||||||
default "datamodel";
|
|
||||||
description
|
|
||||||
"If set, CLI specs can reference the
|
|
||||||
model syntax using this reference.
|
|
||||||
Example: set @datamodel, cli_set();
|
|
||||||
A second tree called eg @datamodelstate is created that
|
|
||||||
also contains state together with config.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
|
||||||
type int32;
|
|
||||||
default 1;
|
|
||||||
description "Generate code for CLI completion of existing db symbols.
|
|
||||||
(consider boolean)";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_GENMODEL_TYPE {
|
|
||||||
type cli_genmodel_type;
|
|
||||||
default "VARS";
|
|
||||||
description "How to generate and show CLI syntax: VARS|ALL";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_VARONLY {
|
|
||||||
type int32;
|
|
||||||
default 1;
|
|
||||||
description
|
|
||||||
"Dont include keys in cvec in cli vars callbacks,
|
|
||||||
ie a & k in 'a <b> k <c>' ignored
|
|
||||||
(consider boolean)";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_LINESCROLLING {
|
|
||||||
type int32;
|
|
||||||
default 1;
|
|
||||||
description
|
|
||||||
"Set to 0 if you want CLI to wrap to next line.
|
|
||||||
Set to 1 if you want CLI to scroll sideways when approaching
|
|
||||||
right margin";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_LINES_DEFAULT {
|
|
||||||
type int32;
|
|
||||||
default 24;
|
|
||||||
description
|
|
||||||
"Set to number of CLI terminal rows for pageing/scrolling. 0 means unlimited.
|
|
||||||
The number is set statically UNLESS:
|
|
||||||
- there is no terminal, such as file input, in which case nr lines is 0
|
|
||||||
- there is a terminal sufficiently powerful to read the number of lines from
|
|
||||||
ioctl calls.
|
|
||||||
In other words, this setting is used ONLY on raw terminals such as serial
|
|
||||||
consoles.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_TAB_MODE {
|
|
||||||
type int8;
|
|
||||||
default 0;
|
|
||||||
description
|
|
||||||
"Set CLI tab mode. This is actually a bitfield of three
|
|
||||||
combinations:
|
|
||||||
bit 1: 0: <tab> shows short info of available commands
|
|
||||||
1: <tab> has same output as <?>, ie line per command
|
|
||||||
bit 2: 0: On <tab>, select a command over a <var> if both exist
|
|
||||||
1: Commands and vars have same preference.
|
|
||||||
bit 3: 0: On <tab>, never complete more than one level per <tab>
|
|
||||||
1: Complete all levels at once if possible.
|
|
||||||
";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_UTF8 {
|
|
||||||
type int8;
|
|
||||||
default 0;
|
|
||||||
description
|
|
||||||
"Set to 1 to enable CLIgen UTF-8 experimental mode.
|
|
||||||
Note that this feature is EXPERIMENTAL and may not properly handle
|
|
||||||
scrolling, control characters, etc
|
|
||||||
(consider boolean)";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_HIST_FILE {
|
|
||||||
type string;
|
|
||||||
default "~/.clixon_cli_history";
|
|
||||||
description
|
|
||||||
"Name of CLI history file. If not given, history is not saved.
|
|
||||||
The number of lines is saved is given by CLICON_CLI_HIST_SIZE.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_HIST_SIZE {
|
|
||||||
type int32;
|
|
||||||
default 300;
|
|
||||||
description
|
|
||||||
"Number of lines to save in CLI history.
|
|
||||||
Also, if CLICON_CLI_HIST_FILE is set, also the size in lines
|
|
||||||
of the saved history.";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_BUF_START {
|
|
||||||
type uint32;
|
|
||||||
default 256;
|
|
||||||
description
|
|
||||||
"CLIgen buffer (cbuf) initial size.
|
|
||||||
When the buffer needs to grow, the allocation grows quadratic up to a threshold
|
|
||||||
after which linear growth continues.
|
|
||||||
See CLICON_CLI_BUF_THRESHOLD";
|
|
||||||
}
|
|
||||||
leaf CLICON_CLI_BUF_THRESHOLD {
|
|
||||||
type uint32;
|
|
||||||
default 65536;
|
|
||||||
description
|
|
||||||
"CLIgen buffer (cbuf) threshold size.
|
|
||||||
When the buffer exceeds the threshold, the allocation grows by adding the threshold
|
|
||||||
value to the buffer length.
|
|
||||||
If 0, the growth continues with quadratic growth.
|
|
||||||
See CLICON_CLI_BUF_THRESHOLD";
|
|
||||||
}
|
|
||||||
leaf CLICON_SOCK_FAMILY {
|
|
||||||
type string;
|
|
||||||
default "UNIX";
|
|
||||||
description
|
|
||||||
"Address family for communicating with clixon_backend
|
|
||||||
(UNIX|IPv4). IPv6 not yet implemented.
|
|
||||||
Note that UNIX socket makes credential check as follows:
|
|
||||||
(1) client needs rw access to the socket
|
|
||||||
(2) NACM credentials can be checked according to CLICON_NACM_CREDENTIALS
|
|
||||||
Warning: IPv4 and IPv6 sockets have no credential mechanism.
|
|
||||||
";
|
|
||||||
}
|
|
||||||
leaf CLICON_SOCK {
|
|
||||||
type string;
|
|
||||||
mandatory true;
|
|
||||||
description
|
|
||||||
"If family above is AF_UNIX: Unix socket for communicating
|
|
||||||
with clixon_backend. If family is AF_INET: IPv4 address";
|
|
||||||
}
|
|
||||||
leaf CLICON_SOCK_PORT {
|
|
||||||
type int32;
|
|
||||||
default 4535;
|
|
||||||
description
|
|
||||||
"Inet socket port for communicating with clixon_backend
|
|
||||||
(only IPv4|IPv6)";
|
|
||||||
}
|
|
||||||
leaf CLICON_SOCK_GROUP {
|
|
||||||
type string;
|
|
||||||
default "clicon";
|
|
||||||
description
|
|
||||||
"Group membership to access clixon_backend unix socket and gid for
|
|
||||||
deamon";
|
|
||||||
}
|
|
||||||
leaf CLICON_BACKEND_USER {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"User name for backend (both foreground and daemonized).
|
|
||||||
If you set this value the backend if started as root will lower
|
|
||||||
the privileges after initialization.
|
|
||||||
The ownership of files created by the backend will also be set to this
|
|
||||||
user (eg datastores).
|
|
||||||
It also sets the backend unix socket owner to this user, but its group
|
|
||||||
is set by CLICON_SOCK_GROUP.
|
|
||||||
See also CLICON_PRIVILEGES setting";
|
|
||||||
}
|
|
||||||
leaf CLICON_BACKEND_PRIVILEGES {
|
|
||||||
type priv_mode;
|
|
||||||
default none;
|
|
||||||
description
|
|
||||||
"Backend privileges mode.
|
|
||||||
If CLICON_BACKEND_USER user is set, mode can be set to drop_perm or
|
|
||||||
drop_temp.";
|
|
||||||
}
|
|
||||||
leaf CLICON_BACKEND_PIDFILE {
|
|
||||||
type string;
|
|
||||||
mandatory true;
|
|
||||||
description "Process-id file of backend daemon";
|
|
||||||
}
|
|
||||||
leaf CLICON_AUTOCOMMIT {
|
|
||||||
type int32;
|
|
||||||
default 0;
|
|
||||||
description
|
|
||||||
"Set if all configuration changes are committed automatically
|
|
||||||
on every edit change. Explicit commit commands unnecessary
|
|
||||||
(consider boolean)";
|
|
||||||
}
|
|
||||||
leaf CLICON_XMLDB_DIR {
|
|
||||||
type string;
|
|
||||||
mandatory true;
|
|
||||||
description
|
|
||||||
"Directory where \"running\", \"candidate\" and \"startup\" are placed.";
|
|
||||||
}
|
|
||||||
leaf CLICON_DATASTORE_CACHE {
|
|
||||||
type datastore_cache;
|
|
||||||
default cache;
|
|
||||||
description
|
|
||||||
"Clixon datastore cache behaviour. There are three values: no cache,
|
|
||||||
cache with copy, or cache without copy.";
|
|
||||||
}
|
|
||||||
leaf CLICON_XMLDB_FORMAT {
|
|
||||||
type datastore_format;
|
|
||||||
default xml;
|
|
||||||
description "XMLDB datastore format.";
|
|
||||||
}
|
|
||||||
leaf CLICON_XMLDB_PRETTY {
|
|
||||||
type boolean;
|
|
||||||
default true;
|
|
||||||
description
|
|
||||||
"XMLDB datastore pretty print.
|
|
||||||
If set, insert spaces and line-feeds making the XML/JSON human
|
|
||||||
readable. If not set, make the XML/JSON more compact.";
|
|
||||||
}
|
|
||||||
leaf CLICON_XMLDB_MODSTATE {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description
|
|
||||||
"If set, tag datastores with RFC 7895 YANG Module Library
|
|
||||||
info. When loaded at startup, a check is made if the system
|
|
||||||
yang modules match.
|
|
||||||
See also CLICON_MODULE_LIBRARY_RFC7895";
|
|
||||||
}
|
|
||||||
leaf CLICON_XML_CHANGELOG {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description "If true enable automatic upgrade using yang clixon
|
|
||||||
changelog.";
|
|
||||||
}
|
|
||||||
leaf CLICON_XML_CHANGELOG_FILE {
|
|
||||||
type string;
|
|
||||||
description "Name of file with module revision changelog.
|
|
||||||
If CLICON_XML_CHANGELOG is true, Clixon
|
|
||||||
reads the module changelog from this file.";
|
|
||||||
}
|
|
||||||
leaf CLICON_VALIDATE_STATE_XML {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description
|
|
||||||
"Validate user state callback content.
|
|
||||||
Users may register state callbacks using ca_statedata callback
|
|
||||||
When set, the XML returned from the callback is validated after merging with
|
|
||||||
the running db. If it fails, an internal error is returned to the originating
|
|
||||||
user.
|
|
||||||
If the option is not set, the XML returned by the user is not validated.
|
|
||||||
Note that enabling currently causes a large performance overhead for large
|
|
||||||
lists, therefore it is recommended to enable it during development and debugging
|
|
||||||
but disable it in production, until this has been resolved.";
|
|
||||||
}
|
|
||||||
leaf CLICON_STARTUP_MODE {
|
|
||||||
type startup_mode;
|
|
||||||
description "Which method to boot/start clicon backend";
|
|
||||||
}
|
|
||||||
leaf CLICON_TRANSACTION_MOD {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description "If set, modifications in validation and commit
|
|
||||||
callbacks are written back into the datastore.
|
|
||||||
This is a bad idea and therefore obsoleted.";
|
|
||||||
status obsolete;
|
|
||||||
}
|
|
||||||
leaf CLICON_NACM_MODE {
|
|
||||||
type nacm_mode;
|
|
||||||
default disabled;
|
|
||||||
description
|
|
||||||
"RFC8341 network access configuration control model (NACM) mode: disabled,
|
|
||||||
in regular (internal) config or separate external file given by CLICON_NACM_FILE";
|
|
||||||
}
|
|
||||||
leaf CLICON_NACM_FILE {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"RFC8341 NACM external configuration file (if CLIXON_NACM_MODE is external)";
|
|
||||||
}
|
|
||||||
leaf CLICON_NACM_CREDENTIALS {
|
|
||||||
type nacm_cred_mode;
|
|
||||||
default except;
|
|
||||||
description
|
|
||||||
"Verify nacm user credentials with unix socket peer cred.
|
|
||||||
This means nacm user must match unix user accessing the backend
|
|
||||||
socket.";
|
|
||||||
}
|
|
||||||
leaf CLICON_NACM_RECOVERY_USER {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"RFC8341 defines a 'recovery session' as outside its scope. Clixon
|
|
||||||
defines this user as having special admin rights to exempt from
|
|
||||||
all access control enforcements.
|
|
||||||
Note setting of CLICON_NACM_CREDENTIALS is important, if set to
|
|
||||||
exact for example, this user must exist and be used, otherwise
|
|
||||||
another user (such as root or www) can pose as the recovery user.";
|
|
||||||
}
|
|
||||||
leaf CLICON_NACM_DISABLED_ON_EMPTY {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description
|
|
||||||
"RFC 8341 and ietf-netconf-acm@2018-02-14.yang defines enable-nacm as true by
|
|
||||||
default. Since also write-default is deny by default it leads to that empty
|
|
||||||
configs can not be edited.
|
|
||||||
This means that a startup config must always have a NACM configuration or
|
|
||||||
that the NACM recovery session is used to edit an empty config.
|
|
||||||
If this option is set, Clixon disables NACM if a datastore is empty on load.
|
|
||||||
Note that it only makes the check on initial load, not if a store 'becomes'
|
|
||||||
empty, but enables a clixon nacm system to start empty and add an NACM
|
|
||||||
config after boot.";
|
|
||||||
}
|
|
||||||
leaf CLICON_MODULE_LIBRARY_RFC7895 {
|
|
||||||
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
|
|
||||||
restconf GET.
|
|
||||||
See also CLICON_XMLDB_MODSTATE";
|
|
||||||
}
|
|
||||||
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.";
|
|
||||||
}
|
|
||||||
leaf CLICON_STREAM_DISCOVERY_RFC5277 {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description "Enable event stream discovery as described in RFC 5277
|
|
||||||
sections 3.2. If enabled, available streams will appear
|
|
||||||
when doing netconf get or restconf GET";
|
|
||||||
}
|
|
||||||
leaf CLICON_STREAM_DISCOVERY_RFC8040 {
|
|
||||||
type boolean;
|
|
||||||
default false;
|
|
||||||
description
|
|
||||||
"Enable monitoring information for the RESTCONF protocol from RFC 8040";
|
|
||||||
}
|
|
||||||
leaf CLICON_STREAM_PATH {
|
|
||||||
type string;
|
|
||||||
default "streams";
|
|
||||||
description "Stream path appended to CLICON_STREAM_URL to form
|
|
||||||
stream subscription URL.";
|
|
||||||
}
|
|
||||||
leaf CLICON_STREAM_URL {
|
|
||||||
type string;
|
|
||||||
default "https://localhost";
|
|
||||||
description "Prepend this to CLICON_STREAM_PATH to form URL.
|
|
||||||
See RFC 8040 Sec 9.3 location leaf:
|
|
||||||
'Contains a URL that represents the entry point for
|
|
||||||
establishing notification delivery via server-sent events.'
|
|
||||||
Prepend this constant to name of stream.
|
|
||||||
Example: https://localhost/streams/NETCONF. Note this is the
|
|
||||||
external URL, not local behind a reverse-proxy.
|
|
||||||
Note that -s <stream> command-line option to clixon_restconf
|
|
||||||
should correspond to last path of url (eg 'streams')";
|
|
||||||
}
|
|
||||||
leaf CLICON_STREAM_PUB {
|
|
||||||
type string;
|
|
||||||
description "For stream publish using eg nchan, the base address
|
|
||||||
to publish to. Example value: http://localhost/pub
|
|
||||||
Example: stream NETCONF would then be pushed to
|
|
||||||
http://localhost/pub/NETCONF.
|
|
||||||
Note this may be a local/provate URL behind reverse-proxy.
|
|
||||||
If not given, do NOT enable stream publishing using NCHAN.";
|
|
||||||
}
|
|
||||||
leaf CLICON_STREAM_RETENTION {
|
|
||||||
type uint32;
|
|
||||||
default 3600;
|
|
||||||
units s;
|
|
||||||
description "Retention for stream replay buffers in seconds, ie how much
|
|
||||||
data to store before dropping. 0 means no retention";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -40,8 +40,14 @@ module clixon-config {
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****";
|
***** END LICENSE BLOCK *****";
|
||||||
|
|
||||||
/* Deleted: clixon-stats state for clixon XML and memory statistics. (moved to clixon-lib)
|
revision 2020-11-03 {
|
||||||
*/
|
description
|
||||||
|
"Added: CLICON_RESTCONF_CONFIG";
|
||||||
|
}
|
||||||
|
revision 2020-10-01 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_CONFIGDIR.";
|
||||||
|
}
|
||||||
revision 2020-08-17 {
|
revision 2020-08-17 {
|
||||||
description
|
description
|
||||||
"Added: CLICON_RESTCONF_IPV4_ADDR, CLICON_RESTCONF_IPV6_ADDR,
|
"Added: CLICON_RESTCONF_IPV4_ADDR, CLICON_RESTCONF_IPV6_ADDR,
|
||||||
|
|
@ -274,14 +280,6 @@ module clixon-config {
|
||||||
*:<feature> means enable the specific feature in all modules";
|
*:<feature> means enable the specific feature in all modules";
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
leaf CLICON_CONFIGFILE{
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Location of configuration-file for default values (this file).
|
|
||||||
Default is CLIXON_DEFAULT_CONFIG=/usr/local/etc/clicon.xml
|
|
||||||
set in configure. Note that due to bootstrapping, a default
|
|
||||||
value here does not work.";
|
|
||||||
}
|
|
||||||
leaf-list CLICON_YANG_DIR {
|
leaf-list CLICON_YANG_DIR {
|
||||||
ordered-by user;
|
ordered-by user;
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -292,6 +290,28 @@ module clixon-config {
|
||||||
they appear. Ensure that YANG_INSTALLDIR(default
|
they appear. Ensure that YANG_INSTALLDIR(default
|
||||||
/usr/local/share/clixon) is present in the path";
|
/usr/local/share/clixon) is present in the path";
|
||||||
}
|
}
|
||||||
|
leaf CLICON_CONFIGFILE{
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Location of the main configuration-file.
|
||||||
|
Default is CLIXON_DEFAULT_CONFIG=/usr/local/etc/clicon.xml set in configure.
|
||||||
|
Note that due to bootstrapping, this value is not actually read from file
|
||||||
|
and therefore a default value would be meaningless.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CONFIGDIR{
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Location of directory of extra configuration files.
|
||||||
|
If not given, only main configfile is read.
|
||||||
|
If given, and if the directory exists, all files in this directory will be loaded
|
||||||
|
AFTER the main config file (CLICON_CONFIGFILE) in the following way:
|
||||||
|
- leaf values are overwritten
|
||||||
|
- leaf-list values are appended
|
||||||
|
The files in this directory will be loaded alphabetically.
|
||||||
|
If the dir is given but does not exist will result in an error.
|
||||||
|
You can override file setting with -E <dir> command-line option.
|
||||||
|
Note that due to bootstraping this value is only meaningful in the main config file";
|
||||||
|
}
|
||||||
leaf CLICON_YANG_MAIN_FILE {
|
leaf CLICON_YANG_MAIN_FILE {
|
||||||
type string;
|
type string;
|
||||||
description
|
description
|
||||||
|
|
@ -332,7 +352,7 @@ module clixon-config {
|
||||||
default true;
|
default true;
|
||||||
description
|
description
|
||||||
"If false, skip Yang list check sanity checks from RFC 7950, Sec 7.8.2:
|
"If false, skip Yang list check sanity checks from RFC 7950, Sec 7.8.2:
|
||||||
The 'key' statement, which MUST be present if the list represents configuration.
|
The 'key' statement, which MUST be present if the list represents configuration.
|
||||||
Some yang specs seem not to fulfil this. However, if you reset this, there may
|
Some yang specs seem not to fulfil this. However, if you reset this, there may
|
||||||
be follow-up errors due to code that assumes a configuration list has keys";
|
be follow-up errors due to code that assumes a configuration list has keys";
|
||||||
}
|
}
|
||||||
|
|
@ -376,7 +396,8 @@ module clixon-config {
|
||||||
default "/www-data/fastcgi_restconf.sock";
|
default "/www-data/fastcgi_restconf.sock";
|
||||||
description
|
description
|
||||||
"FastCGI unix socket. Should be specified in webserver
|
"FastCGI unix socket. Should be specified in webserver
|
||||||
Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock";
|
Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock
|
||||||
|
Only if with-restconf=fcgi, NOT evhtp";
|
||||||
}
|
}
|
||||||
leaf CLICON_RESTCONF_PRETTY {
|
leaf CLICON_RESTCONF_PRETTY {
|
||||||
type boolean;
|
type boolean;
|
||||||
|
|
@ -391,19 +412,40 @@ module clixon-config {
|
||||||
Setting this value to false makes restconf return not pretty-printed
|
Setting this value to false makes restconf return not pretty-printed
|
||||||
which may be desirable for performance or tests";
|
which may be desirable for performance or tests";
|
||||||
}
|
}
|
||||||
|
leaf CLICON_RESTCONF_CONFIG {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"If set, load clixon-restconf module automatically. This also means
|
||||||
|
that the clixon restconf daemon gets its restconf-specific configuration
|
||||||
|
from that yang loaded in the backend running datastore instead of from
|
||||||
|
the clixon XML config file.
|
||||||
|
This only works with-restconf=evhtp, NOT with restconf=fcgi (nginx)
|
||||||
|
A consequence is that if set, the following option in this YANG are obsolete:
|
||||||
|
CLICON_RESTCONF_IPV4_ADDR
|
||||||
|
CLICON_RESTCONF_IPV6_ADDR
|
||||||
|
CLICON_RESTCONF_HTTP_PORT
|
||||||
|
CLICON_RESTCONF_HTTPS_PORT
|
||||||
|
CLICON_SSL_SERVER_CERT
|
||||||
|
CLICON_SSL_SERVER_KEY
|
||||||
|
CLICON_SSL_CA_CERT
|
||||||
|
";
|
||||||
|
}
|
||||||
leaf CLICON_RESTCONF_IPV4_ADDR {
|
leaf CLICON_RESTCONF_IPV4_ADDR {
|
||||||
type string;
|
type string;
|
||||||
default "0.0.0.0";
|
default "0.0.0.0";
|
||||||
description
|
description
|
||||||
"RESTCONF IPv4 socket binding address.
|
"RESTCONF IPv4 socket binding address.
|
||||||
Applies to native http by config option --with-restconf=evhtp.";
|
Applies to native http by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_RESTCONF_IPV6_ADDR {
|
leaf CLICON_RESTCONF_IPV6_ADDR {
|
||||||
type string;
|
type string;
|
||||||
default "::";
|
default "::";
|
||||||
description
|
description
|
||||||
"RESTCONF IPv6 socket binding address.
|
"RESTCONF IPv6 socket binding address.
|
||||||
Applies to native http by config option --with-restconf=evhtp.";
|
Applies to native http by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_RESTCONF_HTTP_PORT {
|
leaf CLICON_RESTCONF_HTTP_PORT {
|
||||||
type uint16;
|
type uint16;
|
||||||
|
|
@ -411,7 +453,8 @@ module clixon-config {
|
||||||
description
|
description
|
||||||
"RESTCONF socket binding port, non-ssl
|
"RESTCONF socket binding port, non-ssl
|
||||||
In the restconf daemon, it can be overriden by -P <port>
|
In the restconf daemon, it can be overriden by -P <port>
|
||||||
Applies to native http only by config option --with-restconf=evhtp.";
|
Applies to native http only by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_RESTCONF_HTTPS_PORT {
|
leaf CLICON_RESTCONF_HTTPS_PORT {
|
||||||
type uint16;
|
type uint16;
|
||||||
|
|
@ -420,28 +463,32 @@ module clixon-config {
|
||||||
"RESTCONF socket binding port, ssl
|
"RESTCONF socket binding port, ssl
|
||||||
In the restconf daemon, this is the port chosen if -s is given.
|
In the restconf daemon, this is the port chosen if -s is given.
|
||||||
Note it can be overriden by -P <port>
|
Note it can be overriden by -P <port>
|
||||||
Applies to native http by config option --with-restconf=evhtp.";
|
Applies to native http by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_SSL_SERVER_CERT {
|
leaf CLICON_SSL_SERVER_CERT {
|
||||||
type string;
|
type string;
|
||||||
default "/etc/ssl/certs/clixon-server-crt.pem";
|
default "/etc/ssl/certs/clixon-server-crt.pem";
|
||||||
description
|
description
|
||||||
"SSL server cert for restconf https.
|
"SSL server cert for restconf https.
|
||||||
Applies to native http only by config option --with-restconf=evhtp.";
|
Applies to native http only by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_SSL_SERVER_KEY {
|
leaf CLICON_SSL_SERVER_KEY {
|
||||||
type string;
|
type string;
|
||||||
default "/etc/ssl/private/clixon-server-key.pem";
|
default "/etc/ssl/private/clixon-server-key.pem";
|
||||||
description
|
description
|
||||||
"SSL server private key for restconf https.
|
"SSL server private key for restconf https.
|
||||||
Applies to native http only by config option --with-restconf=evhtp.";
|
Applies to native http only by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_SSL_CA_CERT {
|
leaf CLICON_SSL_CA_CERT {
|
||||||
type string;
|
type string;
|
||||||
default "/etc/ssl/certs/clixon-ca_crt.pem";
|
default "/etc/ssl/certs/clixon-ca_crt.pem";
|
||||||
description
|
description
|
||||||
"SSL CA cert for client authentication.
|
"SSL CA cert for client authentication.
|
||||||
Applies to native http only by config option --with-restconf=evhtp.";
|
Applies to native http only by config option --with-restconf=evhtp.
|
||||||
|
Obsolete if CLICON_RESTCONF_CONFIG is true";
|
||||||
}
|
}
|
||||||
leaf CLICON_CLI_DIR {
|
leaf CLICON_CLI_DIR {
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -477,18 +524,23 @@ module clixon-config {
|
||||||
1: Generate a CLI specification for CLI completion of all loaded Yang modules.
|
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
|
This CLI tree can be accessed in CLI-spec files using the tree reference syntax (eg
|
||||||
@datamodel).
|
@datamodel).
|
||||||
2: Same including state syntax in a tree called @datamodelstate.
|
2: Same including state syntax in a tree called @datamodelstate and @datamodelshow
|
||||||
See also CLICON_CLI_MODEL_TREENAME.";
|
See also CLICON_CLI_MODEL_TREENAME.";
|
||||||
}
|
}
|
||||||
leaf CLICON_CLI_MODEL_TREENAME {
|
leaf CLICON_CLI_MODEL_TREENAME {
|
||||||
type string;
|
type string;
|
||||||
default "datamodel";
|
default "datamodel";
|
||||||
description
|
description
|
||||||
"If set, CLI specs can reference the
|
"If CLICON_CLI_GENMOEL is set, CLI specs can reference the
|
||||||
model syntax using this reference.
|
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();
|
Example: set @datamodel, cli_set();
|
||||||
A second tree called eg @datamodelstate is created that
|
show @datamodelshow, cli_show_auto();
|
||||||
also contains state together with config.";
|
show state @datamodelstate, cli_show_auto_state();
|
||||||
|
";
|
||||||
}
|
}
|
||||||
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
||||||
type int32;
|
type int32;
|
||||||
190
yang/clixon/clixon-restconf@2020-10-30.yang
Normal file
190
yang/clixon/clixon-restconf@2020-10-30.yang
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
module clixon-restconf {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "https://clicon.org/restconf";
|
||||||
|
prefix "clrc";
|
||||||
|
|
||||||
|
import ietf-inet-types {
|
||||||
|
prefix inet;
|
||||||
|
}
|
||||||
|
|
||||||
|
organization
|
||||||
|
"Clixon";
|
||||||
|
|
||||||
|
contact
|
||||||
|
"Olof Hagsand <olof@hagsand.se>";
|
||||||
|
|
||||||
|
description
|
||||||
|
"This YANG module provides a data-model for the Clixon RESTCONF daemon.
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
Copyright (C) 2020 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 *****";
|
||||||
|
|
||||||
|
revision 2020-10-30 {
|
||||||
|
description
|
||||||
|
"Initial release";
|
||||||
|
}
|
||||||
|
typedef http-auth-type {
|
||||||
|
type enumeration {
|
||||||
|
enum client-certificate {
|
||||||
|
description
|
||||||
|
"TLS client certificate";
|
||||||
|
}
|
||||||
|
enum password {
|
||||||
|
description
|
||||||
|
"PAM password auth";
|
||||||
|
}
|
||||||
|
enum none {
|
||||||
|
description
|
||||||
|
"No authentication, no security.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"Enumeration of HTTP authorization types.";
|
||||||
|
}
|
||||||
|
typedef service-operation {
|
||||||
|
type enumeration {
|
||||||
|
enum start {
|
||||||
|
description
|
||||||
|
"Start if not already running";
|
||||||
|
}
|
||||||
|
enum stop {
|
||||||
|
description
|
||||||
|
"Stop if running";
|
||||||
|
}
|
||||||
|
enum restart {
|
||||||
|
description
|
||||||
|
"Stop if running, then start";
|
||||||
|
}
|
||||||
|
enum status {
|
||||||
|
description
|
||||||
|
"Check status";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"Common operations that can be performed on a service";
|
||||||
|
}
|
||||||
|
container restconf {
|
||||||
|
presence "Enables RESTCONF";
|
||||||
|
description
|
||||||
|
"HTTP daemon configuration.";
|
||||||
|
list socket {
|
||||||
|
key "namespace address port";
|
||||||
|
leaf namespace {
|
||||||
|
type string;
|
||||||
|
description "indicates a namespace for instance. On platforms where namespaces are not suppported, always 'default'";
|
||||||
|
}
|
||||||
|
leaf address {
|
||||||
|
type inet:ip-address;
|
||||||
|
description "IP address to bind to";
|
||||||
|
}
|
||||||
|
leaf port {
|
||||||
|
type inet:port-number;
|
||||||
|
description "IP port to bind to";
|
||||||
|
}
|
||||||
|
leaf ssl {
|
||||||
|
type boolean;
|
||||||
|
default true;
|
||||||
|
description "Enable for HTTPS otherwise HTTP protocol";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf auth-type {
|
||||||
|
type http-auth-type;
|
||||||
|
description
|
||||||
|
"The authentication type.
|
||||||
|
Note client-certificate applies only if socket has ssl enabled";
|
||||||
|
}
|
||||||
|
leaf server-cert-path {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Path to server certificate file.
|
||||||
|
Note only applies if socket has ssl enabled";
|
||||||
|
default "/etc/ssl/private/clixon-server-crt.pem";
|
||||||
|
/* See CLICON_SSL_SERVER_CERT */
|
||||||
|
}
|
||||||
|
leaf server-key-path {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Path to server key file
|
||||||
|
Note only applies if socket has ssl enabled";
|
||||||
|
default "/etc/ssl/private/clixon-server-key.pem";
|
||||||
|
/* See CLICON_SSL_SERVER_KEY */
|
||||||
|
}
|
||||||
|
leaf server-ca-cert-path {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Path to server CA cert file
|
||||||
|
Note only applies if socket has ssl enabled";
|
||||||
|
default "/etc/ssl/certs/clixon-ca_crt.pem";
|
||||||
|
/* CLICON_SSL_CA_CERT */
|
||||||
|
}
|
||||||
|
leaf client-cert-ca {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Path to client certificate file
|
||||||
|
Note only applies if socket has ssl enabled AND auth-type has client-certificate
|
||||||
|
XXX: Is this relevant?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc restconf-control {
|
||||||
|
input {
|
||||||
|
leaf operation {
|
||||||
|
type service-operation;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"One of the strings 'start', 'stop', 'restart', or 'status'.";
|
||||||
|
}
|
||||||
|
leaf namespace {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Network namespace.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output {
|
||||||
|
leaf stdout {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc restconf-coredump {
|
||||||
|
input {
|
||||||
|
leaf operation {
|
||||||
|
type boolean;
|
||||||
|
mandatory true;
|
||||||
|
}
|
||||||
|
leaf namespace {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Network namespace.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output {
|
||||||
|
leaf stdout {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ datarootdir = @datarootdir@
|
||||||
# See also YANG_INSTALLDIR for the clixon-specific yang files
|
# See also YANG_INSTALLDIR for the clixon-specific yang files
|
||||||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
YANGSPECS = ietf-inet-types@2013-07-15.yang
|
YANGSPECS = ietf-inet-types@2020-07-06.yang
|
||||||
YANGSPECS += ietf-netconf@2011-06-01.yang
|
YANGSPECS += ietf-netconf@2011-06-01.yang
|
||||||
YANGSPECS += ietf-netconf-acm@2018-02-14.yang
|
YANGSPECS += ietf-netconf-acm@2018-02-14.yang
|
||||||
YANGSPECS += ietf-restconf@2017-01-26.yang
|
YANGSPECS += ietf-restconf@2017-01-26.yang
|
||||||
|
|
|
||||||
589
yang/mandatory/ietf-inet-types@2020-07-06.yang
Normal file
589
yang/mandatory/ietf-inet-types@2020-07-06.yang
Normal file
|
|
@ -0,0 +1,589 @@
|
||||||
|
module ietf-inet-types {
|
||||||
|
|
||||||
|
namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
|
||||||
|
prefix "inet";
|
||||||
|
|
||||||
|
organization
|
||||||
|
"IETF Network Modeling (NETMOD) Working Group";
|
||||||
|
|
||||||
|
contact
|
||||||
|
"WG Web: <https://datatracker.ietf.org/wg/netmod/>
|
||||||
|
WG List: <mailto:netmod@ietf.org>
|
||||||
|
|
||||||
|
Editor: Juergen Schoenwaelder
|
||||||
|
<mailto:j.schoenwaelder@jacobs-university.de>";
|
||||||
|
|
||||||
|
description
|
||||||
|
"This module contains a collection of generally useful derived
|
||||||
|
YANG data types for Internet addresses and related things.
|
||||||
|
|
||||||
|
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
|
||||||
|
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
|
||||||
|
'MAY', and 'OPTIONAL' in this document are to be interpreted as
|
||||||
|
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
|
||||||
|
they appear in all capitals, as shown here.
|
||||||
|
|
||||||
|
Copyright (c) 2020 IETF Trust and the persons identified as
|
||||||
|
authors of the code. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or
|
||||||
|
without modification, is permitted pursuant to, and subject
|
||||||
|
to the license terms contained in, the Simplified BSD License
|
||||||
|
set forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||||
|
Relating to IETF Documents
|
||||||
|
(http://trustee.ietf.org/license-info).
|
||||||
|
|
||||||
|
This version of this YANG module is part of RFC XXXX;
|
||||||
|
see the RFC itself for full legal notices.";
|
||||||
|
revision 2020-07-06 {
|
||||||
|
description
|
||||||
|
"This revision adds the following new data types:
|
||||||
|
- ip-address-and-prefix
|
||||||
|
- ipv4-address-and-prefix
|
||||||
|
- ipv6-address-and-prefix
|
||||||
|
- email-address";
|
||||||
|
reference
|
||||||
|
"RFC XXXX: Common YANG Data Types";
|
||||||
|
}
|
||||||
|
|
||||||
|
revision 2013-07-15 {
|
||||||
|
description
|
||||||
|
"This revision adds the following new data types:
|
||||||
|
- ip-address-no-zone
|
||||||
|
- ipv4-address-no-zone
|
||||||
|
- ipv6-address-no-zone";
|
||||||
|
reference
|
||||||
|
"RFC 6991: Common YANG Data Types";
|
||||||
|
}
|
||||||
|
|
||||||
|
revision 2010-09-24 {
|
||||||
|
description
|
||||||
|
"Initial revision.";
|
||||||
|
reference
|
||||||
|
"RFC 6021: Common YANG Data Types";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** collection of types related to protocol fields ***/
|
||||||
|
|
||||||
|
typedef ip-version {
|
||||||
|
type enumeration {
|
||||||
|
enum unknown {
|
||||||
|
value "0";
|
||||||
|
description
|
||||||
|
"An unknown or unspecified version of the Internet
|
||||||
|
protocol.";
|
||||||
|
}
|
||||||
|
enum ipv4 {
|
||||||
|
value "1";
|
||||||
|
description
|
||||||
|
"The IPv4 protocol as defined in RFC 791.";
|
||||||
|
}
|
||||||
|
enum ipv6 {
|
||||||
|
value "2";
|
||||||
|
description
|
||||||
|
"The IPv6 protocol as defined in RFC 2460.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"This value represents the version of the IP protocol.
|
||||||
|
|
||||||
|
In the value set and its semantics, this type is equivalent
|
||||||
|
to the InetVersion textual convention of the SMIv2.";
|
||||||
|
reference
|
||||||
|
"RFC 791: Internet Protocol
|
||||||
|
RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
|
||||||
|
RFC 4001: Textual Conventions for Internet Network Addresses";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef dscp {
|
||||||
|
type uint8 {
|
||||||
|
range "0..63";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The dscp type represents a Differentiated Services Code Point
|
||||||
|
that may be used for marking packets in a traffic stream.
|
||||||
|
|
||||||
|
In the value set and its semantics, this type is equivalent
|
||||||
|
to the Dscp textual convention of the SMIv2.";
|
||||||
|
reference
|
||||||
|
"RFC 3289: Management Information Base for the Differentiated
|
||||||
|
Services Architecture
|
||||||
|
RFC 2474: Definition of the Differentiated Services Field
|
||||||
|
(DS Field) in the IPv4 and IPv6 Headers
|
||||||
|
RFC 2780: IANA Allocation Guidelines For Values In
|
||||||
|
the Internet Protocol and Related Headers";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv6-flow-label {
|
||||||
|
type uint32 {
|
||||||
|
range "0..1048575";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv6-flow-label type represents the flow identifier or
|
||||||
|
Flow Label in an IPv6 packet header that may be used to
|
||||||
|
discriminate traffic flows.
|
||||||
|
|
||||||
|
In the value set and its semantics, this type is equivalent
|
||||||
|
to the IPv6FlowLabel textual convention of the SMIv2.";
|
||||||
|
reference
|
||||||
|
"RFC 3595: Textual Conventions for IPv6 Flow Label
|
||||||
|
RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef port-number {
|
||||||
|
type uint16 {
|
||||||
|
range "0..65535";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The port-number type represents a 16-bit port number of an
|
||||||
|
Internet transport-layer protocol such as UDP, TCP, DCCP, or
|
||||||
|
SCTP. Port numbers are assigned by IANA. A current list of
|
||||||
|
all assignments is available from <http://www.iana.org/>.
|
||||||
|
|
||||||
|
Note that the port number value zero is reserved by IANA. In
|
||||||
|
situations where the value zero does not make sense, it can
|
||||||
|
be excluded by subtyping the port-number type.
|
||||||
|
|
||||||
|
In the value set and its semantics, this type is equivalent
|
||||||
|
to the InetPortNumber textual convention of the SMIv2.";
|
||||||
|
reference
|
||||||
|
"RFC 768: User Datagram Protocol
|
||||||
|
RFC 793: Transmission Control Protocol
|
||||||
|
RFC 4960: Stream Control Transmission Protocol
|
||||||
|
RFC 4340: Datagram Congestion Control Protocol (DCCP)
|
||||||
|
RFC 4001: Textual Conventions for Internet Network Addresses";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** collection of types related to autonomous systems ***/
|
||||||
|
|
||||||
|
typedef as-number {
|
||||||
|
type uint32;
|
||||||
|
description
|
||||||
|
"The as-number type represents autonomous system numbers
|
||||||
|
which identify an Autonomous System (AS). An AS is a set
|
||||||
|
of routers under a single technical administration, using
|
||||||
|
an interior gateway protocol and common metrics to route
|
||||||
|
packets within the AS, and using an exterior gateway
|
||||||
|
protocol to route packets to other ASes. IANA maintains
|
||||||
|
the AS number space and has delegated large parts to the
|
||||||
|
regional registries.
|
||||||
|
|
||||||
|
Autonomous system numbers were originally limited to 16
|
||||||
|
bits. BGP extensions have enlarged the autonomous system
|
||||||
|
number space to 32 bits. This type therefore uses an uint32
|
||||||
|
base type without a range restriction in order to support
|
||||||
|
a larger autonomous system number space.
|
||||||
|
|
||||||
|
In the value set and its semantics, this type is equivalent
|
||||||
|
to the InetAutonomousSystemNumber textual convention of
|
||||||
|
the SMIv2.";
|
||||||
|
reference
|
||||||
|
"RFC 1930: Guidelines for creation, selection, and registration
|
||||||
|
of an Autonomous System (AS)
|
||||||
|
RFC 4271: A Border Gateway Protocol 4 (BGP-4)
|
||||||
|
RFC 4001: Textual Conventions for Internet Network Addresses
|
||||||
|
RFC 6793: BGP Support for Four-Octet Autonomous System (AS)
|
||||||
|
Number Space";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** collection of types related to IP addresses and hostnames ***/
|
||||||
|
|
||||||
|
typedef ip-address {
|
||||||
|
type union {
|
||||||
|
type inet:ipv4-address;
|
||||||
|
type inet:ipv6-address;
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ip-address type represents an IP address and is IP
|
||||||
|
version neutral. The format of the textual representation
|
||||||
|
implies the IP version. This type supports scoped addresses
|
||||||
|
by allowing zone identifiers in the address format.";
|
||||||
|
reference
|
||||||
|
"RFC 4007: IPv6 Scoped Address Architecture";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv4-address {
|
||||||
|
type string {
|
||||||
|
pattern
|
||||||
|
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
|
||||||
|
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
|
||||||
|
+ '(%[\p{N}\p{L}]+)?';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv4-address type represents an IPv4 address in
|
||||||
|
dotted-quad notation. The IPv4 address may include a zone
|
||||||
|
index, separated by a % sign.
|
||||||
|
|
||||||
|
The zone index is used to disambiguate identical address
|
||||||
|
values. For link-local addresses, the zone index will
|
||||||
|
typically be the interface index number or the name of an
|
||||||
|
interface. If the zone index is not present, the default
|
||||||
|
zone of the device will be used.
|
||||||
|
|
||||||
|
The canonical format for the zone index is the numerical
|
||||||
|
format";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv6-address {
|
||||||
|
type string {
|
||||||
|
pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
|
||||||
|
+ '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
|
||||||
|
+ '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
|
||||||
|
+ '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
|
||||||
|
+ '(%[\p{N}\p{L}]+)?';
|
||||||
|
pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
|
||||||
|
+ '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
|
||||||
|
+ '(%.+)?';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv6-address type represents an IPv6 address in full,
|
||||||
|
mixed, shortened, and shortened-mixed notation. The IPv6
|
||||||
|
address may include a zone index, separated by a % sign.
|
||||||
|
|
||||||
|
The zone index is used to disambiguate identical address
|
||||||
|
values. For link-local addresses, the zone index will
|
||||||
|
typically be the interface index number or the name of an
|
||||||
|
interface. If the zone index is not present, the default
|
||||||
|
zone of the device will be used.
|
||||||
|
|
||||||
|
The canonical format of IPv6 addresses uses the textual
|
||||||
|
representation defined in Section 4 of RFC 5952. The
|
||||||
|
canonical format for the zone index is the numerical
|
||||||
|
format as described in Section 11.2 of RFC 4007.";
|
||||||
|
reference
|
||||||
|
"RFC 4291: IP Version 6 Addressing Architecture
|
||||||
|
RFC 4007: IPv6 Scoped Address Architecture
|
||||||
|
RFC 5952: A Recommendation for IPv6 Address Text
|
||||||
|
Representation";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ip-address-no-zone {
|
||||||
|
type union {
|
||||||
|
type inet:ipv4-address-no-zone;
|
||||||
|
type inet:ipv6-address-no-zone;
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ip-address-no-zone type represents an IP address and is
|
||||||
|
IP version neutral. The format of the textual representation
|
||||||
|
implies the IP version. This type does not support scoped
|
||||||
|
addresses since it does not allow zone identifiers in the
|
||||||
|
address format.";
|
||||||
|
reference
|
||||||
|
"RFC 4007: IPv6 Scoped Address Architecture";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv4-address-no-zone {
|
||||||
|
type inet:ipv4-address {
|
||||||
|
pattern '[0-9\.]*';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"An IPv4 address without a zone index. This type, derived from
|
||||||
|
ipv4-address, may be used in situations where the zone is known
|
||||||
|
from the context and hence no zone index is needed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv6-address-no-zone {
|
||||||
|
type inet:ipv6-address {
|
||||||
|
pattern '[0-9a-fA-F:\.]*';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"An IPv6 address without a zone index. This type, derived from
|
||||||
|
ipv6-address, may be used in situations where the zone is known
|
||||||
|
from the context and hence no zone index is needed.";
|
||||||
|
reference
|
||||||
|
"RFC 4291: IP Version 6 Addressing Architecture
|
||||||
|
RFC 4007: IPv6 Scoped Address Architecture
|
||||||
|
RFC 5952: A Recommendation for IPv6 Address Text
|
||||||
|
Representation";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ip-prefix {
|
||||||
|
type union {
|
||||||
|
type inet:ipv4-prefix;
|
||||||
|
type inet:ipv6-prefix;
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ip-prefix type represents an IP prefix and is IP
|
||||||
|
version neutral. The format of the textual representations
|
||||||
|
implies the IP version.";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv4-prefix {
|
||||||
|
type string {
|
||||||
|
pattern
|
||||||
|
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
|
||||||
|
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
|
||||||
|
+ '/(([0-9])|([1-2][0-9])|(3[0-2]))';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv4-prefix type represents an IPv4 prefix.
|
||||||
|
The prefix length is given by the number following the
|
||||||
|
slash character and must be less than or equal to 32.
|
||||||
|
|
||||||
|
A prefix length value of n corresponds to an IP address
|
||||||
|
mask that has n contiguous 1-bits from the most
|
||||||
|
significant bit (MSB) and all other bits set to 0.
|
||||||
|
The canonical format of an IPv4 prefix has all bits of
|
||||||
|
the IPv4 address set to zero that are not part of the
|
||||||
|
IPv4 prefix.
|
||||||
|
|
||||||
|
The definition of ipv4-prefix does not require that bits,
|
||||||
|
which are not part of the prefix, are set to zero. However,
|
||||||
|
implementations have to return values in canonical format,
|
||||||
|
which requires non-prefix bits to be set to zero. This means
|
||||||
|
that 192.0.2.1/24 must be accepted as a valid value but it
|
||||||
|
will be converted into the canonical format 192.0.2.0/24.";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv6-prefix {
|
||||||
|
type string {
|
||||||
|
pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
|
||||||
|
+ '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
|
||||||
|
+ '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
|
||||||
|
+ '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
|
||||||
|
+ '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
|
||||||
|
pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
|
||||||
|
+ '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
|
||||||
|
+ '(/.+)';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv6-prefix type represents an IPv6 prefix.
|
||||||
|
The prefix length is given by the number following the
|
||||||
|
slash character and must be less than or equal to 128.
|
||||||
|
|
||||||
|
A prefix length value of n corresponds to an IP address
|
||||||
|
mask that has n contiguous 1-bits from the most
|
||||||
|
significant bit (MSB) and all other bits set to 0.
|
||||||
|
|
||||||
|
The canonical format of an IPv6 prefix has all bits of
|
||||||
|
the IPv6 address set to zero that are not part of the
|
||||||
|
IPv6 prefix. Furthermore, the IPv6 address is represented
|
||||||
|
as defined in Section 4 of RFC 5952.
|
||||||
|
|
||||||
|
The definition of ipv6-prefix does not require that bits,
|
||||||
|
which are not part of the prefix, are set to zero. However,
|
||||||
|
implementations have to return values in canonical format,
|
||||||
|
which requires non-prefix bits to be set to zero. This means
|
||||||
|
that 2001:db8::1/64 must be accepted as a valid value but it
|
||||||
|
will be converted into the canonical format 2001:db8::/64.";
|
||||||
|
reference
|
||||||
|
"RFC 5952: A Recommendation for IPv6 Address Text
|
||||||
|
Representation";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ip-address-and-prefix {
|
||||||
|
type union {
|
||||||
|
type inet:ipv4-address-and-prefix;
|
||||||
|
type inet:ipv6-address-and-prefix;
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ip-address-and-prefix type represents an IP address and
|
||||||
|
prefix and is IP version neutral. The format of the textual
|
||||||
|
representations implies the IP version.";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv4-address-and-prefix {
|
||||||
|
type string {
|
||||||
|
pattern
|
||||||
|
'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
|
||||||
|
+ '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
|
||||||
|
+ '/(([0-9])|([1-2][0-9])|(3[0-2]))';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv4-address-and-prefix type represents an IPv4
|
||||||
|
address and an associated ipv4 prefix.
|
||||||
|
The prefix length is given by the number following the
|
||||||
|
slash character and must be less than or equal to 32.
|
||||||
|
|
||||||
|
A prefix length value of n corresponds to an IP address
|
||||||
|
mask that has n contiguous 1-bits from the most
|
||||||
|
significant bit (MSB) and all other bits set to 0.";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ipv6-address-and-prefix {
|
||||||
|
type string {
|
||||||
|
pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
|
||||||
|
+ '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
|
||||||
|
+ '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
|
||||||
|
+ '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
|
||||||
|
+ '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
|
||||||
|
pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
|
||||||
|
+ '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
|
||||||
|
+ '(/.+)';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The ipv6-address-and-prefix type represents an IPv6
|
||||||
|
address and an associated ipv4 prefix.
|
||||||
|
The prefix length is given by the number following the
|
||||||
|
slash character and must be less than or equal to 128.
|
||||||
|
|
||||||
|
A prefix length value of n corresponds to an IP address
|
||||||
|
mask that has n contiguous 1-bits from the most
|
||||||
|
significant bit (MSB) and all other bits set to 0.
|
||||||
|
|
||||||
|
The canonical format requires that the IPv6 address is
|
||||||
|
represented as defined in Section 4 of RFC 5952.";
|
||||||
|
reference
|
||||||
|
"RFC 5952: A Recommendation for IPv6 Address Text
|
||||||
|
Representation";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** collection of domain name and URI types ***/
|
||||||
|
|
||||||
|
typedef domain-name {
|
||||||
|
type string {
|
||||||
|
length "1..253";
|
||||||
|
pattern
|
||||||
|
'((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
|
||||||
|
+ '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
|
||||||
|
+ '|\.';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The domain-name type represents a DNS domain name. The
|
||||||
|
name SHOULD be fully qualified whenever possible. This
|
||||||
|
type does not support wildcards (see RFC 4592) or
|
||||||
|
classless in-addr.arpa delegations (see RFC 2317).
|
||||||
|
|
||||||
|
Internet domain names are only loosely specified. Section
|
||||||
|
3.5 of RFC 1034 recommends a syntax (modified in Section
|
||||||
|
2.1 of RFC 1123). The pattern above is intended to allow
|
||||||
|
for current practice in domain name use, and some possible
|
||||||
|
future expansion. Note that Internet host names have a
|
||||||
|
stricter syntax (described in RFC 952) than the DNS
|
||||||
|
recommendations in RFCs 1034 and 1123, and that systems
|
||||||
|
that want to store host names in schema node instances
|
||||||
|
using the domain-name type are recommended to adhere to
|
||||||
|
this stricter standard to ensure interoperability.
|
||||||
|
|
||||||
|
The encoding of DNS names in the DNS protocol is limited
|
||||||
|
to 255 characters. Since the encoding consists of labels
|
||||||
|
prefixed by a length bytes and there is a trailing NULL
|
||||||
|
byte, only 253 characters can appear in the textual dotted
|
||||||
|
notation.
|
||||||
|
|
||||||
|
The description clause of schema nodes using the domain-name
|
||||||
|
type MUST describe when and how these names are resolved to
|
||||||
|
IP addresses. Note that the resolution of a domain-name value
|
||||||
|
may require to query multiple DNS records (e.g., A for IPv4
|
||||||
|
and AAAA for IPv6). The order of the resolution process and
|
||||||
|
which DNS record takes precedence can either be defined
|
||||||
|
explicitly or may depend on the configuration of the
|
||||||
|
resolver.
|
||||||
|
|
||||||
|
Domain-name values use the US-ASCII encoding. Their canonical
|
||||||
|
format uses lowercase US-ASCII characters. Internationalized
|
||||||
|
domain names MUST be A-labels as per RFC 5890.";
|
||||||
|
reference
|
||||||
|
"RFC 952: DoD Internet Host Table Specification
|
||||||
|
RFC 1034: Domain Names - Concepts and Facilities
|
||||||
|
RFC 1123: Requirements for Internet Hosts -- Application
|
||||||
|
and Support
|
||||||
|
RFC 2317: Classless IN-ADDR.ARPA delegation
|
||||||
|
RFC 2782: A DNS RR for specifying the location of services
|
||||||
|
(DNS SRV)
|
||||||
|
RFC 4592: The Role of Wildcards in the Domain Name System
|
||||||
|
RFC 5890: Internationalized Domain Names in Applications
|
||||||
|
(IDNA): Definitions and Document Framework";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef host {
|
||||||
|
type union {
|
||||||
|
type inet:ip-address;
|
||||||
|
type inet:domain-name;
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The host type represents either an IP address or a DNS
|
||||||
|
domain name.";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DISCUSS:
|
||||||
|
* - Lada suggested to replace the inet:domain-name usage in
|
||||||
|
* the union with a new host-name definition that follows
|
||||||
|
* the NR-LDH definition in RFC 5890.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef uri {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"The uri type represents a Uniform Resource Identifier
|
||||||
|
(URI) as defined by STD 66.
|
||||||
|
|
||||||
|
Objects using the uri type MUST be in US-ASCII encoding,
|
||||||
|
and MUST be normalized as described by RFC 3986 Sections
|
||||||
|
6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
|
||||||
|
percent-encoding is removed, and all case-insensitive
|
||||||
|
characters are set to lowercase except for hexadecimal
|
||||||
|
digits, which are normalized to uppercase as described in
|
||||||
|
Section 6.2.2.1.
|
||||||
|
|
||||||
|
The purpose of this normalization is to help provide
|
||||||
|
unique URIs. Note that this normalization is not
|
||||||
|
sufficient to provide uniqueness. Two URIs that are
|
||||||
|
textually distinct after this normalization may still be
|
||||||
|
equivalent.
|
||||||
|
|
||||||
|
Objects using the uri type may restrict the schemes that
|
||||||
|
they permit. For example, 'data:' and 'urn:' schemes
|
||||||
|
might not be appropriate.
|
||||||
|
|
||||||
|
A zero-length URI is not a valid URI. This can be used to
|
||||||
|
express 'URI absent' where required.
|
||||||
|
|
||||||
|
In the value set and its semantics, this type is equivalent
|
||||||
|
to the Uri SMIv2 textual convention defined in RFC 5017.";
|
||||||
|
reference
|
||||||
|
"RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
|
||||||
|
RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
|
||||||
|
Group: Uniform Resource Identifiers (URIs), URLs,
|
||||||
|
and Uniform Resource Names (URNs): Clarifications
|
||||||
|
and Recommendations
|
||||||
|
RFC 5017: MIB Textual Conventions for Uniform Resource
|
||||||
|
Identifiers (URIs)";
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef email-address {
|
||||||
|
type string {
|
||||||
|
// dot-atom-text "@" ...
|
||||||
|
pattern '[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+'
|
||||||
|
+ '(\.[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+)*'
|
||||||
|
+ '@'
|
||||||
|
+ '[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+'
|
||||||
|
+ '(\.[a-zA-Z0-9!#$%&'+"'"+'*+/=?^_`{|}~-]+)*';
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The email-address type represents an email address as
|
||||||
|
defined as addr-spec in RFC 5322 section 3.4.1.";
|
||||||
|
reference
|
||||||
|
"RFC 5322: Internet Message Format";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DISCUSS:
|
||||||
|
* - It was suggested to add email types following RFC 5322
|
||||||
|
* email-address (addr-spec, per Section 3.4.1)
|
||||||
|
* named-email-address (name-addr, per Section 3.4)
|
||||||
|
* - This sounds useful but the devil is in the details,
|
||||||
|
* in particular name-addr is a quite complex construct;
|
||||||
|
* perhaps addr-spec is sufficient, this is also the
|
||||||
|
* format allowed in mailto: URIs (mailto: seems to use
|
||||||
|
* only a subset of addr-spec which may be good enough
|
||||||
|
* here as well).
|
||||||
|
* - Need to define a pattern that has a meaningful trade-off
|
||||||
|
* between precision and complexity (there are very tight
|
||||||
|
* pattern that are very long and complex). The current
|
||||||
|
* pattern does not take care of quoted-string, obs-local-part,
|
||||||
|
* domain-literal, obs-domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DISCUSS:
|
||||||
|
* - There was a request to add types for URI fields (scheme,
|
||||||
|
* authority, path, query, fragment) but it is not clear how
|
||||||
|
* commonly useful these types are, the WG was pretty silent
|
||||||
|
* about this proposal. On the technical side, it is unclear
|
||||||
|
* whether data is represented with percent escapes resolved
|
||||||
|
* or not. (Mahesh's proposal does not spell this out, the
|
||||||
|
* pattern does not allow the % character, which may be wrong.)
|
||||||
|
*/
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue