* Added -U <user> command line to clixon_cli and clixon_netconf for NACM pseudo-user tests
This commit is contained in:
parent
de69b253dc
commit
5cabc11bfb
15 changed files with 132 additions and 48 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
* Example extended with inclusion of iana-if-type RFC 7224 interface identities
|
* Example extended with inclusion of iana-if-type RFC 7224 interface identities
|
||||||
* Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified.
|
* Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified.
|
||||||
### Minor changes:
|
### Minor changes:
|
||||||
|
* Added -U <user> command line to clixon_cli and clixon_netconf for NACM pseudo-user tests
|
||||||
* Added a generated CLI show command that works on the generated parse tree with auto completion.
|
* Added a generated CLI show command that works on the generated parse tree with auto completion.
|
||||||
* A typical call is: show @datamodel:example, cli_show_auto("candidate", "json");
|
* A typical call is: show @datamodel:example, cli_show_auto("candidate", "json");
|
||||||
* The example contains a more elaborate example.
|
* The example contains a more elaborate example.
|
||||||
|
|
|
||||||
|
|
@ -803,7 +803,7 @@ from_client_debug(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Match nacm access operations according to RFC8321 3.4.4.
|
/*! Match nacm access operations according to RFC8341 3.4.4.
|
||||||
* Incoming RPC Message Validation Step 7 (c)
|
* Incoming RPC Message Validation Step 7 (c)
|
||||||
* The rule's "access-operations" leaf has the "exec" bit set or
|
* The rule's "access-operations" leaf has the "exec" bit set or
|
||||||
* has the special value "*".
|
* has the special value "*".
|
||||||
|
|
@ -832,7 +832,7 @@ nacm_match_access(char *access_operations,
|
||||||
* @retval 0 Matching rule AND Not access and cbret set
|
* @retval 0 Matching rule AND Not access and cbret set
|
||||||
* @retval 1 Matchung rule AND Access
|
* @retval 1 Matchung rule AND Access
|
||||||
* @retval 2 No matching rule Goto step 10
|
* @retval 2 No matching rule Goto step 10
|
||||||
* From RFC8321 3.4.4. Incoming RPC Message Validation
|
* From RFC8341 3.4.4. Incoming RPC Message Validation
|
||||||
+---------+-----------------+---------------------+-----------------+
|
+---------+-----------------+---------------------+-----------------+
|
||||||
| Method | Resource class | NETCONF operation | Access |
|
| Method | Resource class | NETCONF operation | Access |
|
||||||
| | | | operation |
|
| | | | operation |
|
||||||
|
|
@ -911,7 +911,7 @@ nacm_match_rule(clicon_handle h,
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 Not access and cbret set
|
* @retval 0 Not access and cbret set
|
||||||
* @retval 1 Access
|
* @retval 1 Access
|
||||||
* From RFC8321 3.4.4. Incoming RPC Message Validation
|
* From RFC8341 3.4.4. Incoming RPC Message Validation
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nacm_access(clicon_handle h,
|
nacm_access(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ backend_sig_term(int arg)
|
||||||
/*! usage
|
/*! usage
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
usage(char *argv0, clicon_handle h)
|
usage(clicon_handle h,
|
||||||
|
char *argv0)
|
||||||
{
|
{
|
||||||
char *plgdir = clicon_backend_dir(h);
|
char *plgdir = clicon_backend_dir(h);
|
||||||
char *confsock = clicon_sock(h);
|
char *confsock = clicon_sock(h);
|
||||||
|
|
@ -581,11 +582,11 @@ main(int argc,
|
||||||
break;
|
break;
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
if (sscanf(optarg, "%d", &debug) != 1)
|
if (sscanf(optarg, "%d", &debug) != 1)
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
break;
|
break;
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -602,7 +603,7 @@ main(int argc,
|
||||||
/* Find and read configfile */
|
/* Find and read configfile */
|
||||||
if (clicon_options_main(h) < 0){
|
if (clicon_options_main(h) < 0){
|
||||||
if (help)
|
if (help)
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* External NACM file? */
|
/* External NACM file? */
|
||||||
|
|
@ -621,12 +622,12 @@ main(int argc,
|
||||||
break; /* see above */
|
break; /* see above */
|
||||||
case 'd': /* Plugin directory */
|
case 'd': /* Plugin directory */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_BACKEND_DIR", optarg);
|
clicon_option_str_set(h, "CLICON_BACKEND_DIR", optarg);
|
||||||
break;
|
break;
|
||||||
case 'b': /* XMLDB database directory */
|
case 'b': /* XMLDB database directory */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_XMLDB_DIR", optarg);
|
clicon_option_str_set(h, "CLICON_XMLDB_DIR", optarg);
|
||||||
break;
|
break;
|
||||||
case 'F' : /* foreground */
|
case 'F' : /* foreground */
|
||||||
|
|
@ -640,7 +641,7 @@ main(int argc,
|
||||||
break;
|
break;
|
||||||
case 'u': /* config unix domain path / ip address */
|
case 'u': /* config unix domain path / ip address */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||||
break;
|
break;
|
||||||
case 'P': /* pidfile */
|
case 'P': /* pidfile */
|
||||||
|
|
@ -650,7 +651,7 @@ main(int argc,
|
||||||
clicon_option_str_set(h, "CLICON_STARTUP_MODE", optarg);
|
clicon_option_str_set(h, "CLICON_STARTUP_MODE", optarg);
|
||||||
if (clicon_startup_mode(h) < 0){
|
if (clicon_startup_mode(h) < 0){
|
||||||
fprintf(stderr, "Invalid startup mode: %s\n", optarg);
|
fprintf(stderr, "Invalid startup mode: %s\n", optarg);
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'c': /* Load application config */
|
case 'c': /* Load application config */
|
||||||
|
|
@ -668,7 +669,7 @@ main(int argc,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -677,7 +678,7 @@ main(int argc,
|
||||||
|
|
||||||
/* Defer: Wait to the last minute to print help message */
|
/* Defer: Wait to the last minute to print help message */
|
||||||
if (help)
|
if (help)
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
|
|
||||||
/* Check pid-file, if zap kil the old daemon, else return here */
|
/* Check pid-file, if zap kil the old daemon, else return here */
|
||||||
if ((pidfile = clicon_backend_pidfile(h)) == NULL){
|
if ((pidfile = clicon_backend_pidfile(h)) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,8 @@ clixon_plugin_statedata(clicon_handle h,
|
||||||
if (reason){
|
if (reason){
|
||||||
while ((xc = xml_child_i(*xtop, 0)) != NULL)
|
while ((xc = xml_child_i(*xtop, 0)) != NULL)
|
||||||
xml_purge(xc);
|
xml_purge(xc);
|
||||||
|
clicon_log(LOG_NOTICE, "%s: Plugin '%s' state callback failed",
|
||||||
|
__FUNCTION__, cp->cp_name);
|
||||||
if (netconf_operation_failed_xml(xtop, "rpc", reason)< 0)
|
if (netconf_operation_failed_xml(xtop, "rpc", reason)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
#include "cli_handle.h"
|
#include "cli_handle.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define CLI_OPTS "hD:f:xl:F:1u:d:m:qpGLy:c:"
|
#define CLI_OPTS "hD:f:xl:F:1u:d:m:qpGLy:c:U:"
|
||||||
|
|
||||||
/*! terminate cli application */
|
/*! terminate cli application */
|
||||||
static int
|
static int
|
||||||
|
|
@ -194,7 +194,8 @@ dump_configfile_xml_fn(FILE *fout,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(char *argv0, clicon_handle h)
|
usage(clicon_handle h,
|
||||||
|
char *argv0)
|
||||||
{
|
{
|
||||||
char *confsock = clicon_sock(h);
|
char *confsock = clicon_sock(h);
|
||||||
char *plgdir = clicon_cli_dir(h);
|
char *plgdir = clicon_cli_dir(h);
|
||||||
|
|
@ -217,7 +218,8 @@ usage(char *argv0, clicon_handle h)
|
||||||
"\t-L \t\tDebug print dynamic CLI syntax including completions and expansions\n"
|
"\t-L \t\tDebug print dynamic CLI syntax including completions and expansions\n"
|
||||||
"\t-l <s|e|o> \tLog on (s)yslog, std(e)rr or std(o)ut (stderr is default)\n"
|
"\t-l <s|e|o> \tLog on (s)yslog, std(e)rr or std(o)ut (stderr is default)\n"
|
||||||
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n"
|
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n"
|
||||||
"\t-c <file>\tSpecify cli spec file.\n",
|
"\t-c <file>\tSpecify cli spec file.\n"
|
||||||
|
"\t-U <user>\tOver-ride unix user with a pseudo user for NACM.\n",
|
||||||
argv0,
|
argv0,
|
||||||
confsock ? confsock : "none",
|
confsock ? confsock : "none",
|
||||||
plgdir ? plgdir : "none"
|
plgdir ? plgdir : "none"
|
||||||
|
|
@ -256,7 +258,9 @@ main(int argc, char **argv)
|
||||||
/* Initiate CLICON handle */
|
/* Initiate CLICON handle */
|
||||||
if ((h = cli_handle_init()) == NULL)
|
if ((h = cli_handle_init()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Set username to clicon handle. Use in all communication to backend */
|
/* Set username to clicon handle. Use in all communication to backend
|
||||||
|
* Note, can be overridden by -U
|
||||||
|
*/
|
||||||
if ((pw = getpwuid(getuid())) == NULL){
|
if ((pw = getpwuid(getuid())) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "getpwuid");
|
clicon_err(OE_UNIX, errno, "getpwuid");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -283,11 +287,11 @@ main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
if (sscanf(optarg, "%d", &debug) != 1)
|
if (sscanf(optarg, "%d", &debug) != 1)
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
break;
|
break;
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
case 'x': /* dump config file as xml (migration from .conf file)*/
|
case 'x': /* dump config file as xml (migration from .conf file)*/
|
||||||
|
|
@ -305,9 +309,9 @@ main(int argc, char **argv)
|
||||||
logdst = CLICON_LOG_STDOUT;
|
logdst = CLICON_LOG_STDOUT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Logs, error and debug to stderr or syslog, set debug level
|
* Logs, error and debug to stderr or syslog, set debug level
|
||||||
|
|
@ -327,7 +331,7 @@ main(int argc, char **argv)
|
||||||
/* Find and read configfile */
|
/* Find and read configfile */
|
||||||
if (clicon_options_main(h) < 0){
|
if (clicon_options_main(h) < 0){
|
||||||
if (help)
|
if (help)
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,17 +356,17 @@ main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'u': /* config unix domain path/ ip host */
|
case 'u': /* config unix domain path/ ip host */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||||
break;
|
break;
|
||||||
case 'd': /* Plugin directory: overrides configfile */
|
case 'd': /* Plugin directory: overrides configfile */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CLI_DIR", optarg);
|
clicon_option_str_set(h, "CLICON_CLI_DIR", optarg);
|
||||||
break;
|
break;
|
||||||
case 'm': /* CLI syntax mode */
|
case 'm': /* CLI syntax mode */
|
||||||
if (!strlen(optarg))
|
if (!strlen(optarg))
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CLI_MODE", optarg);
|
clicon_option_str_set(h, "CLICON_CLI_MODE", optarg);
|
||||||
break;
|
break;
|
||||||
case 'q' : /* Quiet mode */
|
case 'q' : /* Quiet mode */
|
||||||
|
|
@ -385,8 +389,14 @@ main(int argc, char **argv)
|
||||||
clicon_option_str_set(h, "CLICON_CLISPEC_FILE", optarg);
|
clicon_option_str_set(h, "CLICON_CLISPEC_FILE", optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'U': /* Clixon 'pseudo' user */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
if (clicon_username_set(h, optarg) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,7 +405,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* Defer: Wait to the last minute to print help message */
|
/* Defer: Wait to the last minute to print help message */
|
||||||
if (help)
|
if (help)
|
||||||
usage(argv[0], h);
|
usage(h, argv[0]);
|
||||||
|
|
||||||
/* Setup signal handlers */
|
/* Setup signal handlers */
|
||||||
cli_signal_init(h);
|
cli_signal_init(h);
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
#include "netconf_rpc.h"
|
#include "netconf_rpc.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define NETCONF_OPTS "hDqf:d:Sy:"
|
#define NETCONF_OPTS "hDqf:d:Sy:U:"
|
||||||
|
|
||||||
/*! Process incoming packet
|
/*! Process incoming packet
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -292,7 +292,8 @@ usage(clicon_handle h,
|
||||||
"\t-f <file>\tConfiguration file (mandatory)\n"
|
"\t-f <file>\tConfiguration file (mandatory)\n"
|
||||||
"\t-d <dir>\tSpecify netconf plugin directory dir (default: %s)\n"
|
"\t-d <dir>\tSpecify netconf plugin directory dir (default: %s)\n"
|
||||||
"\t-S\t\tLog on syslog\n"
|
"\t-S\t\tLog on syslog\n"
|
||||||
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n",
|
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n"
|
||||||
|
"\t-U <user>\tOver-ride unix user with a pseudo user for NACM.\n",
|
||||||
argv0,
|
argv0,
|
||||||
clicon_netconf_dir(h)
|
clicon_netconf_dir(h)
|
||||||
);
|
);
|
||||||
|
|
@ -379,6 +380,12 @@ main(int argc,
|
||||||
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
|
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'U': /* Clixon 'pseudo' user */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
if (clicon_username_set(h, optarg) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ empty(clicon_handle h, /* Clicon handle */
|
||||||
* Real code would poll state
|
* Real code would poll state
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
plugin_statedata(clicon_handle h,
|
example_statedata(clicon_handle h,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cxobj *xstate)
|
cxobj *xstate)
|
||||||
{
|
{
|
||||||
|
|
@ -214,8 +214,8 @@ plugin_statedata(clicon_handle h,
|
||||||
* @note This assumes example yang with interfaces/interface
|
* @note This assumes example yang with interfaces/interface
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
plugin_reset(clicon_handle h,
|
example_reset(clicon_handle h,
|
||||||
const char *db)
|
const char *db)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
|
|
@ -250,7 +250,7 @@ plugin_reset(clicon_handle h,
|
||||||
* can be processed with the standard getopt(3).
|
* can be processed with the standard getopt(3).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
plugin_start(clicon_handle h,
|
example_start(clicon_handle h,
|
||||||
int argc,
|
int argc,
|
||||||
char **argv)
|
char **argv)
|
||||||
{
|
{
|
||||||
|
|
@ -261,11 +261,11 @@ clixon_plugin_api *clixon_plugin_init(clicon_handle h);
|
||||||
|
|
||||||
static clixon_plugin_api api = {
|
static clixon_plugin_api api = {
|
||||||
"example", /* name */
|
"example", /* name */
|
||||||
clixon_plugin_init, /* init */
|
clixon_plugin_init, /* init - must be called clixon_plugin_init */
|
||||||
plugin_start, /* start */
|
example_start, /* start */
|
||||||
NULL, /* exit */
|
NULL, /* exit */
|
||||||
.ca_reset=plugin_reset, /* reset */
|
.ca_reset=example_reset, /* reset */
|
||||||
.ca_statedata=plugin_statedata, /* statedata */
|
.ca_statedata=example_statedata, /* statedata */
|
||||||
.ca_trans_begin=NULL, /* trans begin */
|
.ca_trans_begin=NULL, /* trans begin */
|
||||||
.ca_trans_validate=transaction_validate,/* trans validate */
|
.ca_trans_validate=transaction_validate,/* trans validate */
|
||||||
.ca_trans_complete=NULL, /* trans complete */
|
.ca_trans_complete=NULL, /* trans complete */
|
||||||
|
|
|
||||||
|
|
@ -90,17 +90,24 @@ fib_route_rpc(clicon_handle h,
|
||||||
cxobj *xtop = NULL;
|
cxobj *xtop = NULL;
|
||||||
cxobj *xrpc;
|
cxobj *xrpc;
|
||||||
cxobj *xret = NULL;
|
cxobj *xret = NULL;
|
||||||
|
cxobj *xerr;
|
||||||
|
|
||||||
/* User supplied variable in CLI command */
|
/* User supplied variable in CLI command */
|
||||||
instance = cvec_find(cvv, "instance"); /* get a cligen variable from vector */
|
instance = cvec_find(cvv, "instance"); /* get a cligen variable from vector */
|
||||||
/* Create XML for fib-route netconf RPC */
|
/* Create XML for fib-route netconf RPC */
|
||||||
if (xml_parse_va(&xtop, NULL, "<rpc><fib-route><routing-instance-name>%s</routing-instance-name></fib-route></rpc>", cv_string_get(instance)) < 0)
|
if (xml_parse_va(&xtop, NULL, "<rpc username=\"%s\"><fib-route><routing-instance-name>%s</routing-instance-name></fib-route></rpc>",
|
||||||
|
clicon_username_get(h),
|
||||||
|
cv_string_get(instance)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Skip top-level */
|
/* Skip top-level */
|
||||||
xrpc = xml_child_i(xtop, 0);
|
xrpc = xml_child_i(xtop, 0);
|
||||||
/* Send to backend */
|
/* Send to backend */
|
||||||
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if ((xerr = xpath_first(xret, "/rpc-error")) != NULL){
|
||||||
|
clicon_rpc_generate_error("Get configuration", xerr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* Print result */
|
/* Print result */
|
||||||
xml_print(stdout, xml_child_i(xret, 0));
|
xml_print(stdout, xml_child_i(xret, 0));
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -47,3 +47,11 @@ int strverscmp (__const char *__s1, __const char *__s2);
|
||||||
* This was obsoleted in 3.7
|
* This was obsoleted in 3.7
|
||||||
*/
|
*/
|
||||||
#undef COMPAT_CLIV
|
#undef COMPAT_CLIV
|
||||||
|
|
||||||
|
/* Set if you want to assert that all rpc messages have set username
|
||||||
|
*/
|
||||||
|
#undef RPC_USERNAME_ASSERT
|
||||||
|
|
||||||
|
/* Full xmlns validation check is made only if XML has associated YANG spec
|
||||||
|
*/
|
||||||
|
#define XMLNS_YANG_ONLY 1
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,6 @@ typedef int (xml_applyfn_t)(cxobj *x, void *arg);
|
||||||
#define XML_FLAG_CHANGE 0x08 /* Node is changed (commits) or child changed rec */
|
#define XML_FLAG_CHANGE 0x08 /* Node is changed (commits) or child changed rec */
|
||||||
#define XML_FLAG_NONE 0x10 /* Node is added as NONE */
|
#define XML_FLAG_NONE 0x10 /* Node is added as NONE */
|
||||||
|
|
||||||
/* Full xmlns validation check is made only if XML has associated YANG spec */
|
|
||||||
#define XMLNS_YANG_ONLY 1
|
|
||||||
|
|
||||||
/* Sort and binary search of XML children
|
/* Sort and binary search of XML children
|
||||||
* Experimental
|
* Experimental
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,9 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
cxobj *xret = NULL;
|
cxobj *xret = NULL;
|
||||||
yang_spec *yspec;
|
yang_spec *yspec;
|
||||||
|
|
||||||
|
#ifdef RPC_USERNAME_ASSERT
|
||||||
|
assert(strstr(msg->op_body, "username")!=NULL); /* XXX */
|
||||||
|
#endif
|
||||||
clicon_debug(1, "%s request:%s", __FUNCTION__, msg->op_body);
|
clicon_debug(1, "%s request:%s", __FUNCTION__, msg->op_body);
|
||||||
if ((sock = clicon_sock(h)) == NULL){
|
if ((sock = clicon_sock(h)) == NULL){
|
||||||
clicon_err(OE_FATAL, 0, "CLICON_SOCK option not set");
|
clicon_err(OE_FATAL, 0, "CLICON_SOCK option not set");
|
||||||
|
|
|
||||||
|
|
@ -1779,7 +1779,7 @@ xml_merge1(cxobj *x0,
|
||||||
* @param[in] x0 Base xml tree (can be NULL in add scenarios)
|
* @param[in] x0 Base xml tree (can be NULL in add scenarios)
|
||||||
* @param[in] x1 xml tree which modifies base
|
* @param[in] x1 xml tree which modifies base
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[out] reason If retval=0 a malloced string. Needs to be freed by caller
|
* @param[out] reason If retval=0, reason is set. Malloced. Needs to be freed by caller
|
||||||
* @retval 0 OK. If reason is set, Yang error
|
* @retval 0 OK. If reason is set, Yang error
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @note both x0 and x1 need to be top-level trees
|
* @note both x0 and x1 need to be top-level trees
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Authentication and authorization and IETF NACM
|
# Authentication and authorization and IETF NACM
|
||||||
# See RFC 8321 A.2
|
# See RFC 8341 A.2
|
||||||
# But replaced ietf-netconf-monitoring with *
|
# But replaced ietf-netconf-monitoring with *
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Authentication and authorization and IETF NACM
|
# Authentication and authorization and IETF NACM
|
||||||
# External NACM file
|
# External NACM file
|
||||||
# See RFC 8321 A.2
|
# See RFC 8341 A.2
|
||||||
# But replaced ietf-netconf-monitoring with *
|
# But replaced ietf-netconf-monitoring with *
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
@ -16,9 +16,11 @@ nacmfile=$dir/nacmfile
|
||||||
cat <<EOF > $cfg
|
cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
|
||||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
<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_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
|
@ -36,6 +38,12 @@ EOF
|
||||||
cat <<EOF > $fyang
|
cat <<EOF > $fyang
|
||||||
module $APPNAME{
|
module $APPNAME{
|
||||||
prefix ex;
|
prefix ex;
|
||||||
|
import ietf-interfaces {
|
||||||
|
prefix if;
|
||||||
|
}
|
||||||
|
import iana-if-type {
|
||||||
|
prefix ianaift;
|
||||||
|
}
|
||||||
container authentication {
|
container authentication {
|
||||||
description "Example code for enabling www basic auth and some example
|
description "Example code for enabling www basic auth and some example
|
||||||
users";
|
users";
|
||||||
|
|
@ -61,6 +69,21 @@ module $APPNAME{
|
||||||
type int32;
|
type int32;
|
||||||
description "something to edit";
|
description "something to edit";
|
||||||
}
|
}
|
||||||
|
container interfaces-state {
|
||||||
|
config false;
|
||||||
|
list interface{
|
||||||
|
key "name";
|
||||||
|
leaf name{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf type{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf if-index {
|
||||||
|
type int32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -75,7 +98,6 @@ cat <<EOF > $nacmfile
|
||||||
<name>admin</name>
|
<name>admin</name>
|
||||||
<user-name>admin</user-name>
|
<user-name>admin</user-name>
|
||||||
<user-name>adm1</user-name>
|
<user-name>adm1</user-name>
|
||||||
<user-name>olof</user-name>
|
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<name>limited</name>
|
<name>limited</name>
|
||||||
|
|
@ -167,7 +189,7 @@ new "restconf DELETE whole datastore"
|
||||||
expecteq "$(curl -u adm1:bar -sS -X DELETE http://localhost/restconf/data)" ""
|
expecteq "$(curl -u adm1:bar -sS -X DELETE http://localhost/restconf/data)" ""
|
||||||
|
|
||||||
new2 "auth get"
|
new2 "auth get"
|
||||||
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data": null}
|
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "Set x to 0"
|
new "Set x to 0"
|
||||||
|
|
@ -203,6 +225,24 @@ expecteq "$(curl -u wilma:bar -sS -X PUT -d '{"x": 2}' http://localhost/restconf
|
||||||
new2 "guest edit nacm"
|
new2 "guest edit nacm"
|
||||||
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"x": 3}' http://localhost/restconf/data/x)" '{"ietf-restconf:errors" : {"error": {"error-tag": "access-denied","error-type": "protocol","error-severity": "error","error-message": "The requested URL was unauthorized"}}}
'
|
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"x": 3}' http://localhost/restconf/data/x)" '{"ietf-restconf:errors" : {"error": {"error-tag": "access-denied","error-type": "protocol","error-severity": "error","error-message": "The requested URL was unauthorized"}}}
'
|
||||||
|
|
||||||
|
new "cli show conf as admin"
|
||||||
|
expectfn "$clixon_cli -1 -U adm1 -f $cfg -y $fyang show conf" 0 "^x 1;$"
|
||||||
|
|
||||||
|
new "cli show conf as limited"
|
||||||
|
expectfn "$clixon_cli -1 -U wilma -f $cfg -y $fyang show conf" 0 "^x 1;$"
|
||||||
|
|
||||||
|
new "cli show conf as guest"
|
||||||
|
expectfn "$clixon_cli -1 -U guest -f $cfg -y $fyang show conf" 255 "CLI command error"
|
||||||
|
|
||||||
|
new "cli rpc as admin"
|
||||||
|
expectfn "$clixon_cli -1 -U adm1 -f $cfg -y $fyang rpc ipv4" 0 "<next-hop-list>2.3.4.5</next-hop-list>"
|
||||||
|
|
||||||
|
new "cli rpc as limited"
|
||||||
|
expectfn "$clixon_cli -1 -U wilma -f $cfg -y $fyang rpc ipv4" 0 "<error-tag>access-denied</error-tag>"
|
||||||
|
|
||||||
|
new "cli rpc as guest"
|
||||||
|
expectfn "$clixon_cli -1 -U guest -f $cfg -y $fyang rpc ipv4" 0 "<error-tag>access-denied</error-tag>"
|
||||||
|
|
||||||
new "Kill restconf daemon"
|
new "Kill restconf daemon"
|
||||||
sudo pkill -u www-data clixon_restconf
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,12 +143,19 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candi
|
||||||
new "netconf validate"
|
new "netconf validate"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
#new "Set crypto to x:des3"
|
new "Set crypto to des:des3 using xmlns"
|
||||||
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:x=\"urn:example:des\">x:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:des=\"urn:example:des\">des:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf validate"
|
new "netconf validate"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
# XXX this is not supported
|
||||||
|
#new "Set crypto to x:des3 using xmlns"
|
||||||
|
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:x=\"urn:example:des\">x:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
#new "netconf validate"
|
||||||
|
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "Set crypto to foo:bar"
|
new "Set crypto to foo:bar"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>foo:bar</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>foo:bar</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue