[Code formatting: Change indentation style to space](https://github.com/clicon/clixon/issues/379)
* Applies to all c/h/y/l/sh files and .editorconfig
This commit is contained in:
parent
a9d1ab006c
commit
d84c529ff1
376 changed files with 38147 additions and 38133 deletions
|
|
@ -129,7 +129,7 @@ sh> clixon_netconf -qf /usr/local/etc/example.xml
|
|||
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||
<interface>
|
||||
<name>eth1</name>
|
||||
<type>ianaift:ip</type>
|
||||
<type>ianaift:ip</type>
|
||||
<enabled>true</enabled>
|
||||
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
|
||||
<address>
|
||||
|
|
@ -179,9 +179,9 @@ In the example, a restconf config is included in the [config file](example.xml):
|
|||
<auth-type>none</auth-type>
|
||||
<socket>
|
||||
<namespace>default</namespace>
|
||||
<address>0.0.0.0</address>
|
||||
<port>80</port>
|
||||
<ssl>false</ssl>
|
||||
<address>0.0.0.0</address>
|
||||
<port>80</port>
|
||||
<ssl>false</ssl>
|
||||
</socket>
|
||||
</restconf>
|
||||
```
|
||||
|
|
@ -221,20 +221,20 @@ For example, using nginx, install, and edit config file: /etc/nginx/sites-availa
|
|||
```
|
||||
server {
|
||||
...
|
||||
location / {
|
||||
root /usr/share/nginx/html/restconf;
|
||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||
include fastcgi_params;
|
||||
location / {
|
||||
root /usr/share/nginx/html/restconf;
|
||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||
include fastcgi_params;
|
||||
}
|
||||
location /restconf {
|
||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||
include fastcgi_params;
|
||||
location /restconf {
|
||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||
include fastcgi_params;
|
||||
}
|
||||
location /streams {
|
||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||
include fastcgi_params;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
location /streams {
|
||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||
include fastcgi_params;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -315,10 +315,10 @@ curl -X POST http://localhost/restconf/operations/clixon-example:example -H "Co
|
|||
The example works by defining an RPC in clixon-example.yang:
|
||||
```
|
||||
rpc example {
|
||||
description "Some example input/output for testing RFC7950 7.14.
|
||||
description "Some example input/output for testing RFC7950 7.14.
|
||||
RPC simply echoes the input for debugging.";
|
||||
input {
|
||||
leaf x {
|
||||
input {
|
||||
leaf x {
|
||||
...
|
||||
```
|
||||
|
||||
|
|
@ -328,10 +328,10 @@ The clixon backend plugin [example_backend.c] reveives the netconf call and rep
|
|||
```
|
||||
static int
|
||||
example_rpc(clicon_handle h,
|
||||
cxobj *xe, /* Request: <rpc><xn></rpc> */
|
||||
cbuf *cbret, /* Reply eg <rpc-reply>... */
|
||||
void *arg, /* Client session */
|
||||
void *regarg) /* Argument given at register */
|
||||
cxobj *xe, /* Request: <rpc><xn></rpc> */
|
||||
cbuf *cbret, /* Reply eg <rpc-reply>... */
|
||||
void *arg, /* Client session */
|
||||
void *regarg) /* Argument given at register */
|
||||
{
|
||||
/* code that echoes the request */
|
||||
return 0;
|
||||
|
|
@ -375,9 +375,9 @@ The example backend implements an "example:e4" Yang extension, as follows:
|
|||
```
|
||||
extension e4 {
|
||||
description
|
||||
"The first child of the ex:e4 (unknown) statement is inserted into
|
||||
the module as a regular data statement. This means that 'uses bar;'
|
||||
in the ex:e4 statement below is a valid data node";
|
||||
"The first child of the ex:e4 (unknown) statement is inserted into
|
||||
the module as a regular data statement. This means that 'uses bar;'
|
||||
in the ex:e4 statement below is a valid data node";
|
||||
argument arg;
|
||||
}
|
||||
ex:e4 arg1{
|
||||
|
|
|
|||
|
|
@ -3,231 +3,231 @@ module clixon-example {
|
|||
namespace "urn:example:clixon";
|
||||
prefix ex;
|
||||
import ietf-interfaces {
|
||||
/* is in yang/optional which means clixon must be installed using --opt-yang-installdir */
|
||||
prefix if;
|
||||
/* is in yang/optional which means clixon must be installed using --opt-yang-installdir */
|
||||
prefix if;
|
||||
}
|
||||
import ietf-ip {
|
||||
prefix ip;
|
||||
prefix ip;
|
||||
}
|
||||
import iana-if-type {
|
||||
prefix ianaift;
|
||||
prefix ianaift;
|
||||
}
|
||||
import ietf-datastores {
|
||||
prefix ds;
|
||||
prefix ds;
|
||||
}
|
||||
import clixon-autocli{
|
||||
prefix autocli;
|
||||
prefix autocli;
|
||||
}
|
||||
description
|
||||
"Clixon example used as a part of the Clixon test suite.
|
||||
"Clixon example used as a part of the Clixon test suite.
|
||||
It can be used as a basis for making new Clixon applications.
|
||||
Note, may change without updating revision, just for testing current master.
|
||||
";
|
||||
revision 2020-12-01 {
|
||||
description "Added table/parameter/value as the primary data example";
|
||||
description "Added table/parameter/value as the primary data example";
|
||||
}
|
||||
revision 2020-03-11 {
|
||||
description "Added container around translation list. Released in Clixon 4.4.0";
|
||||
description "Added container around translation list. Released in Clixon 4.4.0";
|
||||
}
|
||||
revision 2019-11-05 {
|
||||
description "Augment interface. Released in Clixon 4.3.0";
|
||||
description "Augment interface. Released in Clixon 4.3.0";
|
||||
}
|
||||
revision 2019-07-23 {
|
||||
description "Extension e4. Released in Clixon 4.1.0";
|
||||
description "Extension e4. Released in Clixon 4.1.0";
|
||||
}
|
||||
revision 2019-01-13 {
|
||||
description "Released in Clixon 3.9";
|
||||
description "Released in Clixon 3.9";
|
||||
}
|
||||
/* Example interface type for tests, local callbacks, etc */
|
||||
identity eth {
|
||||
base if:interface-type;
|
||||
base if:interface-type;
|
||||
}
|
||||
identity loopback {
|
||||
base if:interface-type;
|
||||
base if:interface-type;
|
||||
}
|
||||
/* Generic config data */
|
||||
container table{
|
||||
list parameter{
|
||||
key name;
|
||||
leaf name{
|
||||
type string;
|
||||
}
|
||||
leaf value{
|
||||
type string;
|
||||
}
|
||||
leaf hidden{
|
||||
type string;
|
||||
autocli:hide;
|
||||
}
|
||||
leaf stat{
|
||||
description "Inline state data for example application";
|
||||
config false;
|
||||
type int32;
|
||||
}
|
||||
}
|
||||
list parameter{
|
||||
key name;
|
||||
leaf name{
|
||||
type string;
|
||||
}
|
||||
leaf value{
|
||||
type string;
|
||||
}
|
||||
leaf hidden{
|
||||
type string;
|
||||
autocli:hide;
|
||||
}
|
||||
leaf stat{
|
||||
description "Inline state data for example application";
|
||||
config false;
|
||||
type int32;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* State data (not config) for the example application*/
|
||||
container state {
|
||||
config false;
|
||||
description "state data for the example application (must be here for example get operation)";
|
||||
leaf-list op {
|
||||
config false;
|
||||
description "state data for the example application (must be here for example get operation)";
|
||||
leaf-list op {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
augment "/if:interfaces/if:interface" {
|
||||
container my-status {
|
||||
config false;
|
||||
description "For testing augment+state";
|
||||
leaf int {
|
||||
type int32;
|
||||
}
|
||||
leaf str {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
container my-status {
|
||||
config false;
|
||||
description "For testing augment+state";
|
||||
leaf int {
|
||||
type int32;
|
||||
}
|
||||
leaf str {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* yang extension implemented by the example backend code. */
|
||||
extension e4 {
|
||||
description
|
||||
"The first child of the ex:e4 (unknown) statement is inserted into
|
||||
the module as a regular data statement. This means that 'uses bar;'
|
||||
in the ex:e4 statement below is a valid data node";
|
||||
argument arg;
|
||||
description
|
||||
"The first child of the ex:e4 (unknown) statement is inserted into
|
||||
the module as a regular data statement. This means that 'uses bar;'
|
||||
in the ex:e4 statement below is a valid data node";
|
||||
argument arg;
|
||||
}
|
||||
grouping bar {
|
||||
leaf bar{
|
||||
type string;
|
||||
}
|
||||
leaf bar{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
ex:e4 arg1{
|
||||
uses bar;
|
||||
uses bar;
|
||||
}
|
||||
/* Example notification as used in RFC 5277 and RFC 8040 */
|
||||
notification event {
|
||||
description "Example notification event.";
|
||||
leaf event-class {
|
||||
type string;
|
||||
description "Event class identifier.";
|
||||
}
|
||||
container reportingEntity {
|
||||
description "Event specific information.";
|
||||
leaf card {
|
||||
type string;
|
||||
description "Line card identifier.";
|
||||
}
|
||||
}
|
||||
leaf severity {
|
||||
type string;
|
||||
description "Event severity description.";
|
||||
}
|
||||
description "Example notification event.";
|
||||
leaf event-class {
|
||||
type string;
|
||||
description "Event class identifier.";
|
||||
}
|
||||
container reportingEntity {
|
||||
description "Event specific information.";
|
||||
leaf card {
|
||||
type string;
|
||||
description "Line card identifier.";
|
||||
}
|
||||
}
|
||||
leaf severity {
|
||||
type string;
|
||||
description "Event severity description.";
|
||||
}
|
||||
}
|
||||
rpc client-rpc {
|
||||
description "Example local client-side RPC that is processed by the
|
||||
description "Example local client-side RPC that is processed by the
|
||||
the netconf/restconf and not sent to the backend.
|
||||
This is a clixon implementation detail: some rpc:s
|
||||
are better processed by the client for API or perf reasons";
|
||||
input {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
output {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
input {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
output {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
rpc empty {
|
||||
description "Smallest possible RPC with no input or output sections";
|
||||
description "Smallest possible RPC with no input or output sections";
|
||||
}
|
||||
rpc optional {
|
||||
description "Small RPC with optional input and output";
|
||||
input {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
output {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
description "Small RPC with optional input and output";
|
||||
input {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
output {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
rpc example {
|
||||
description "Some example input/output for testing RFC7950 7.14.
|
||||
description "Some example input/output for testing RFC7950 7.14.
|
||||
RPC simply echoes the input for debugging.";
|
||||
input {
|
||||
leaf x {
|
||||
description
|
||||
"If a leaf in the input tree has a 'mandatory' statement with
|
||||
input {
|
||||
leaf x {
|
||||
description
|
||||
"If a leaf in the input tree has a 'mandatory' statement with
|
||||
the value 'true', the leaf MUST be present in an RPC invocation.";
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf y {
|
||||
description
|
||||
"If a leaf in the input tree has a 'mandatory' statement with the
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf y {
|
||||
description
|
||||
"If a leaf in the input tree has a 'mandatory' statement with the
|
||||
value 'true', the leaf MUST be present in an RPC invocation.";
|
||||
type string;
|
||||
default "42";
|
||||
}
|
||||
leaf-list z {
|
||||
description
|
||||
"If a leaf-list in the input tree has one or more default
|
||||
type string;
|
||||
default "42";
|
||||
}
|
||||
leaf-list z {
|
||||
description
|
||||
"If a leaf-list in the input tree has one or more default
|
||||
values, the server MUST use these values (XXX not supported)";
|
||||
type string;
|
||||
}
|
||||
leaf w {
|
||||
description
|
||||
"If any node has a 'when' statement that would evaluate to
|
||||
type string;
|
||||
}
|
||||
leaf w {
|
||||
description
|
||||
"If any node has a 'when' statement that would evaluate to
|
||||
'false',then this node MUST NOT be present in the input tree.
|
||||
(XXX not supported)";
|
||||
type string;
|
||||
}
|
||||
list u0 {
|
||||
description "list without key";
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
list u1 {
|
||||
description "list with key";
|
||||
key uk;
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
leaf val{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
leaf y {
|
||||
type string;
|
||||
}
|
||||
leaf z {
|
||||
type string;
|
||||
}
|
||||
leaf w {
|
||||
type string;
|
||||
}
|
||||
list u0 {
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
list u1 {
|
||||
key uk;
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
leaf val{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
type string;
|
||||
}
|
||||
list u0 {
|
||||
description "list without key";
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
list u1 {
|
||||
description "list with key";
|
||||
key uk;
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
leaf val{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
output {
|
||||
leaf x {
|
||||
type string;
|
||||
}
|
||||
leaf y {
|
||||
type string;
|
||||
}
|
||||
leaf z {
|
||||
type string;
|
||||
}
|
||||
leaf w {
|
||||
type string;
|
||||
}
|
||||
list u0 {
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
list u1 {
|
||||
key uk;
|
||||
leaf uk{
|
||||
type string;
|
||||
}
|
||||
leaf val{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -82,37 +82,37 @@ static int _validate_fail_toggle = 0; /* fail at validate and commit */
|
|||
|
||||
int
|
||||
nacm_begin(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
/*! This is called on validate (and commit). Check validity of candidate
|
||||
*/
|
||||
int
|
||||
nacm_validate(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
if (_validate_fail_xpath){
|
||||
if (_validate_fail_toggle==0 &&
|
||||
xpath_first(transaction_target(td), NULL, "%s", _validate_fail_xpath)){
|
||||
_validate_fail_toggle = 1; /* toggle if triggered */
|
||||
clicon_err(OE_XML, 0, "User error");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
if (_validate_fail_toggle==0 &&
|
||||
xpath_first(transaction_target(td), NULL, "%s", _validate_fail_xpath)){
|
||||
_validate_fail_toggle = 1; /* toggle if triggered */
|
||||
clicon_err(OE_XML, 0, "User error");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nacm_complete(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -120,54 +120,54 @@ nacm_complete(clicon_handle h,
|
|||
*/
|
||||
int
|
||||
nacm_commit(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
if (_validate_fail_xpath){
|
||||
if (_validate_fail_toggle==1 &&
|
||||
xpath_first(transaction_target(td), NULL, "%s", _validate_fail_xpath)){
|
||||
_validate_fail_toggle = 0; /* toggle if triggered */
|
||||
clicon_err(OE_XML, 0, "User error");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
if (_validate_fail_toggle==1 &&
|
||||
xpath_first(transaction_target(td), NULL, "%s", _validate_fail_xpath)){
|
||||
_validate_fail_toggle = 0; /* toggle if triggered */
|
||||
clicon_err(OE_XML, 0, "User error");
|
||||
return -1; /* induce fail */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nacm_commit_done(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nacm_revert(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nacm_end(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nacm_abort(clicon_handle h,
|
||||
transaction_data td)
|
||||
transaction_data td)
|
||||
{
|
||||
if (_transaction_log)
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
transaction_log(h, td, LOG_NOTICE, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -184,24 +184,24 @@ nacm_abort(clicon_handle h,
|
|||
*/
|
||||
int
|
||||
nacm_statedata(clicon_handle h,
|
||||
cvec *nsc,
|
||||
char *xpath,
|
||||
cxobj *xstate)
|
||||
cvec *nsc,
|
||||
char *xpath,
|
||||
cxobj *xstate)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj **xvec = NULL;
|
||||
|
||||
/* Example of (static) statedata, real code would poll state */
|
||||
if (clixon_xml_parse_string("<nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\">"
|
||||
"<denied-data-writes>0</denied-data-writes>"
|
||||
"<denied-operations>0</denied-operations>"
|
||||
"<denied-notifications>0</denied-notifications>"
|
||||
"</nacm>", YB_NONE, NULL, &xstate, NULL) < 0)
|
||||
goto done;
|
||||
"<denied-data-writes>0</denied-data-writes>"
|
||||
"<denied-operations>0</denied-operations>"
|
||||
"<denied-notifications>0</denied-notifications>"
|
||||
"</nacm>", YB_NONE, NULL, &xstate, NULL) < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
if (xvec)
|
||||
free(xvec);
|
||||
free(xvec);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -239,25 +239,25 @@ clixon_plugin_init(clicon_handle h)
|
|||
clicon_debug(1, "%s backend nacm", __FUNCTION__);
|
||||
/* Get user command-line options (after --) */
|
||||
if (clicon_argv_get(h, &argc, &argv) < 0)
|
||||
goto done;
|
||||
goto done;
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, BACKEND_NACM_OPTS)) != -1)
|
||||
switch (c) {
|
||||
case 't': /* transaction log */
|
||||
_transaction_log = 1;
|
||||
break;
|
||||
case 'v': /* validate fail */
|
||||
_validate_fail_xpath = optarg;
|
||||
break;
|
||||
}
|
||||
switch (c) {
|
||||
case 't': /* transaction log */
|
||||
_transaction_log = 1;
|
||||
break;
|
||||
case 'v': /* validate fail */
|
||||
_validate_fail_xpath = optarg;
|
||||
break;
|
||||
}
|
||||
|
||||
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
|
||||
if (nacm_mode==NULL || strcmp(nacm_mode, "disabled") == 0){
|
||||
clicon_log(LOG_DEBUG, "%s CLICON_NACM_MODE not enabled: example nacm module disabled", __FUNCTION__);
|
||||
/* Skip nacm module if not enabled _unless_ we use transaction tests */
|
||||
if (_transaction_log == 0)
|
||||
return NULL;
|
||||
clicon_log(LOG_DEBUG, "%s CLICON_NACM_MODE not enabled: example nacm module disabled", __FUNCTION__);
|
||||
/* Skip nacm module if not enabled _unless_ we use transaction tests */
|
||||
if (_transaction_log == 0)
|
||||
return NULL;
|
||||
}
|
||||
/* Return plugin API */
|
||||
return &api;
|
||||
|
|
|
|||
|
|
@ -67,29 +67,29 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv)
|
|||
fprintf(stderr, "arg = %s\n", cv_string_get(cvec_i(argv,0))); /* get string value */
|
||||
|
||||
if ((nsc = xml_nsctx_init(NULL, "urn:example:clixon")) == NULL)
|
||||
goto done;
|
||||
goto done;
|
||||
/* Show eth0 interfaces config using XPATH */
|
||||
if (clicon_rpc_get_config(h, NULL, "running",
|
||||
"/interfaces/interface[name='eth0']",
|
||||
nsc, NULL,
|
||||
&xret) < 0)
|
||||
goto done;
|
||||
"/interfaces/interface[name='eth0']",
|
||||
nsc, NULL,
|
||||
&xret) < 0)
|
||||
goto done;
|
||||
if (clixon_xml2file(stdout, xret, 0, 1, cligen_output, 0, 1) < 0)
|
||||
goto done;
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
if (nsc)
|
||||
xml_nsctx_free(nsc);
|
||||
xml_nsctx_free(nsc);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Example "downcall", ie initiate an RPC to the backend */
|
||||
int
|
||||
example_client_rpc(clicon_handle h,
|
||||
cvec *cvv,
|
||||
cvec *argv)
|
||||
cvec *cvv,
|
||||
cvec *argv)
|
||||
{
|
||||
int retval = -1;
|
||||
cg_var *cva;
|
||||
|
|
@ -102,25 +102,25 @@ example_client_rpc(clicon_handle h,
|
|||
cva = cvec_find(cvv, "a"); /* get a cligen variable from vector */
|
||||
/* Create XML for example netconf RPC */
|
||||
if (clixon_xml_parse_va(YB_NONE, NULL, &xtop, NULL,
|
||||
"<rpc xmlns=\"%s\" username=\"%s\" %s>"
|
||||
"<example xmlns=\"urn:example:clixon\"><x>%s</x></example></rpc>",
|
||||
NETCONF_BASE_NAMESPACE,
|
||||
clicon_username_get(h),
|
||||
NETCONF_MESSAGE_ID_ATTR,
|
||||
cv_string_get(cva)) < 0)
|
||||
goto done;
|
||||
"<rpc xmlns=\"%s\" username=\"%s\" %s>"
|
||||
"<example xmlns=\"urn:example:clixon\"><x>%s</x></example></rpc>",
|
||||
NETCONF_BASE_NAMESPACE,
|
||||
clicon_username_get(h),
|
||||
NETCONF_MESSAGE_ID_ATTR,
|
||||
cv_string_get(cva)) < 0)
|
||||
goto done;
|
||||
/* Skip top-level */
|
||||
xrpc = xml_child_i(xtop, 0);
|
||||
/* Send to backend */
|
||||
if (clicon_rpc_netconf_xml(h, xrpc, &xret, NULL) < 0)
|
||||
goto done;
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
clixon_netconf_error(xerr, "Get configuration", NULL);
|
||||
goto done;
|
||||
clixon_netconf_error(xerr, "Get configuration", NULL);
|
||||
goto done;
|
||||
}
|
||||
/* Print result */
|
||||
if (clixon_xml2file(stdout, xml_child_i(xret, 0), 0, 0, cligen_output, 0, 1) < 0)
|
||||
goto done;
|
||||
goto done;
|
||||
fprintf(stdout,"\n");
|
||||
|
||||
/* pretty-print:
|
||||
|
|
@ -129,9 +129,9 @@ example_client_rpc(clicon_handle h,
|
|||
retval = 0;
|
||||
done:
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
xml_free(xret);
|
||||
if (xtop)
|
||||
xml_free(xtop);
|
||||
xml_free(xtop);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ clixon_plugin_init(clicon_handle h)
|
|||
*/
|
||||
int
|
||||
cli_incstr(cligen_handle h,
|
||||
cg_var *cv)
|
||||
cg_var *cv)
|
||||
{
|
||||
char *str;
|
||||
int i;
|
||||
|
|
@ -176,12 +176,12 @@ cli_incstr(cligen_handle h,
|
|||
/* Filter out other than strings
|
||||
* this is specific to this example, one can do translation */
|
||||
if (cv == NULL || cv_type_get(cv) != CGV_STRING)
|
||||
return 0;
|
||||
return 0;
|
||||
if ((str = cv_string_get(cv)) == NULL){
|
||||
clicon_err(OE_PLUGIN, EINVAL, "cv string is NULL");
|
||||
return -1;
|
||||
clicon_err(OE_PLUGIN, EINVAL, "cv string is NULL");
|
||||
return -1;
|
||||
}
|
||||
for (i=0; i<strlen(str); i++)
|
||||
str[i]++;
|
||||
str[i]++;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@ plugin_exit(clicon_handle h)
|
|||
*/
|
||||
int
|
||||
netconf_client_rpc(clicon_handle h,
|
||||
cxobj *xe,
|
||||
cbuf *cbret,
|
||||
void *arg,
|
||||
void *regarg)
|
||||
cxobj *xe,
|
||||
cbuf *cbret,
|
||||
void *arg,
|
||||
void *regarg)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x = NULL;
|
||||
|
|
@ -79,19 +79,19 @@ netconf_client_rpc(clicon_handle h,
|
|||
|
||||
/* get namespace from rpc name, return back in each output parameter */
|
||||
if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){
|
||||
clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe));
|
||||
goto done;
|
||||
clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe));
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\">", NETCONF_BASE_NAMESPACE);
|
||||
if (!xml_child_nr_type(xe, CX_ELMNT))
|
||||
cprintf(cbret, "<ok/>");
|
||||
cprintf(cbret, "<ok/>");
|
||||
else{
|
||||
while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) {
|
||||
if (xmlns_set(x, NULL, namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (clixon_xml2cbuf(cbret, xe, 0, 0, -1, 1) < 0)
|
||||
goto done;
|
||||
while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) {
|
||||
if (xmlns_set(x, NULL, namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (clixon_xml2cbuf(cbret, xe, 0, 0, -1, 1) < 0)
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbret, "</rpc-reply>");
|
||||
retval = 0;
|
||||
|
|
@ -121,8 +121,8 @@ clixon_plugin_init(clicon_handle h)
|
|||
clicon_debug(1, "%s restconf", __FUNCTION__);
|
||||
/* Register local netconf rpc client (note not backend rpc client) */
|
||||
if (rpc_callback_register(h, netconf_client_rpc, NULL,
|
||||
"urn:example:clixon", "client-rpc") < 0)
|
||||
return NULL;
|
||||
"urn:example:clixon", "client-rpc") < 0)
|
||||
return NULL;
|
||||
return &api;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
#define RESTCONF_EXAMPLE_OPTS ""
|
||||
|
||||
static const char Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
||||
/* skips all whitespace anywhere.
|
||||
|
|
@ -65,8 +65,8 @@ static const char Pad64 = '=';
|
|||
*/
|
||||
int
|
||||
b64_decode(const char *src,
|
||||
char *target,
|
||||
size_t targsize)
|
||||
char *target,
|
||||
size_t targsize)
|
||||
{
|
||||
int tarindex, state, ch;
|
||||
char *pos;
|
||||
|
|
@ -75,59 +75,59 @@ b64_decode(const char *src,
|
|||
tarindex = 0;
|
||||
|
||||
while ((ch = *src++) != '\0') {
|
||||
if (isspace(ch)) /* Skip whitespace anywhere. */
|
||||
continue;
|
||||
if (isspace(ch)) /* Skip whitespace anywhere. */
|
||||
continue;
|
||||
|
||||
if (ch == Pad64)
|
||||
break;
|
||||
if (ch == Pad64)
|
||||
break;
|
||||
|
||||
pos = strchr(Base64, ch);
|
||||
if (pos == 0) /* A non-base64 character. */
|
||||
return (-1);
|
||||
pos = strchr(Base64, ch);
|
||||
if (pos == 0) /* A non-base64 character. */
|
||||
return (-1);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if ((size_t)tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] = (pos - Base64) << 2;
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (target) {
|
||||
if ((size_t)tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 4;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x0f)
|
||||
<< 4 ;
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (target) {
|
||||
if ((size_t)tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 2;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x03)
|
||||
<< 6;
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
case 3:
|
||||
if (target) {
|
||||
if ((size_t)tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if ((size_t)tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] = (pos - Base64) << 2;
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (target) {
|
||||
if ((size_t)tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 4;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x0f)
|
||||
<< 4 ;
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (target) {
|
||||
if ((size_t)tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 2;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x03)
|
||||
<< 6;
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
case 3:
|
||||
if (target) {
|
||||
if ((size_t)tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -135,50 +135,50 @@ b64_decode(const char *src,
|
|||
* on a byte boundary, and/or with erroneous trailing characters.
|
||||
*/
|
||||
|
||||
if (ch == Pad64) { /* We got a pad char. */
|
||||
ch = *src++; /* Skip it, get next. */
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (-1);
|
||||
if (ch == Pad64) { /* We got a pad char. */
|
||||
ch = *src++; /* Skip it, get next. */
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (-1);
|
||||
|
||||
case 2: /* Valid, means one byte of info */
|
||||
/* Skip any number of spaces. */
|
||||
for ((void)NULL; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
break;
|
||||
/* Make sure there is another trailing = sign. */
|
||||
if (ch != Pad64)
|
||||
return (-1);
|
||||
ch = *src++; /* Skip the = */
|
||||
/* Fall through to "single trailing =" case. */
|
||||
/* FALLTHROUGH */
|
||||
case 2: /* Valid, means one byte of info */
|
||||
/* Skip any number of spaces. */
|
||||
for ((void)NULL; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
break;
|
||||
/* Make sure there is another trailing = sign. */
|
||||
if (ch != Pad64)
|
||||
return (-1);
|
||||
ch = *src++; /* Skip the = */
|
||||
/* Fall through to "single trailing =" case. */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, means two bytes of info */
|
||||
/*
|
||||
* We know this char is an =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for ((void)NULL; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
return (-1);
|
||||
case 3: /* Valid, means two bytes of info */
|
||||
/*
|
||||
* We know this char is an =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for ((void)NULL; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Now make sure for cases 2 and 3 that the "extra"
|
||||
* bits that slopped past the last full byte were
|
||||
* zeros. If we don't check them, they become a
|
||||
* subliminal channel.
|
||||
*/
|
||||
if (target && target[tarindex] != 0)
|
||||
return (-1);
|
||||
}
|
||||
/*
|
||||
* Now make sure for cases 2 and 3 that the "extra"
|
||||
* bits that slopped past the last full byte were
|
||||
* zeros. If we don't check them, they become a
|
||||
* subliminal channel.
|
||||
*/
|
||||
if (target && target[tarindex] != 0)
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We ended by seeing the end of the string. Make sure we
|
||||
* have no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (-1);
|
||||
/*
|
||||
* We ended by seeing the end of the string. Make sure we
|
||||
* have no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (tarindex);
|
||||
|
|
@ -198,8 +198,8 @@ b64_decode(const char *src,
|
|||
*/
|
||||
static int
|
||||
example_basic_auth(clicon_handle h,
|
||||
void *req,
|
||||
char **authp)
|
||||
void *req,
|
||||
char **authp)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xt = NULL;
|
||||
|
|
@ -213,41 +213,41 @@ example_basic_auth(clicon_handle h,
|
|||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (authp == NULL){
|
||||
clicon_err(OE_PLUGIN, EINVAL, "Authp output parameter is NULL");
|
||||
goto done;
|
||||
clicon_err(OE_PLUGIN, EINVAL, "Authp output parameter is NULL");
|
||||
goto done;
|
||||
}
|
||||
/* At this point in the code we must use HTTP basic authentication */
|
||||
if ((auth = restconf_param_get(h, "HTTP_AUTHORIZATION")) == NULL)
|
||||
goto fail;
|
||||
goto fail;
|
||||
if (strlen(auth) < strlen("Basic "))
|
||||
goto fail;
|
||||
goto fail;
|
||||
if (strncmp("Basic ", auth, strlen("Basic ")))
|
||||
goto fail;
|
||||
goto fail;
|
||||
auth += strlen("Basic ");
|
||||
authlen = strlen(auth)*2;
|
||||
if ((user = malloc(authlen)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(user, 0, authlen);
|
||||
if ((ret = b64_decode(auth, user, authlen)) < 0)
|
||||
goto done;
|
||||
goto done;
|
||||
/* auth string is on the format user:passwd */
|
||||
if ((passwd = index(user,':')) == NULL)
|
||||
goto fail;
|
||||
goto fail;
|
||||
*passwd = '\0';
|
||||
passwd++;
|
||||
clicon_debug(1, "%s http user:%s passwd:%s", __FUNCTION__, user, passwd);
|
||||
/* Here get auth sub-tree where all the users are */
|
||||
if ((cb = cbuf_new()) == NULL)
|
||||
goto done;
|
||||
goto done;
|
||||
/* XXX Three hardcoded user/passwd (from RFC8341 A.1)*/
|
||||
if (strcmp(user, "wilma")==0 || strcmp(user, "andy")==0 ||
|
||||
strcmp(user, "guest")==0){
|
||||
passwd2 = "bar";
|
||||
strcmp(user, "guest")==0){
|
||||
passwd2 = "bar";
|
||||
}
|
||||
if (strcmp(passwd, passwd2))
|
||||
goto fail;
|
||||
goto fail;
|
||||
*authp = user; /* authenticated */
|
||||
user=NULL; /* to avoid free below */
|
||||
retval = 1;
|
||||
|
|
@ -256,7 +256,7 @@ example_basic_auth(clicon_handle h,
|
|||
if (user)
|
||||
free(user);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
cbuf_free(cb);
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
return retval;
|
||||
|
|
@ -280,24 +280,24 @@ example_basic_auth(clicon_handle h,
|
|||
*/
|
||||
int
|
||||
example_restconf_credentials(clicon_handle h,
|
||||
void *req,
|
||||
clixon_auth_type_t auth_type,
|
||||
char **authp)
|
||||
void *req,
|
||||
clixon_auth_type_t auth_type,
|
||||
char **authp)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
clicon_debug(1, "%s auth:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type));
|
||||
switch (auth_type){
|
||||
case CLIXON_AUTH_NONE: /* FEATURE clixon-restconf:allow-auth-none must be enabled */
|
||||
retval = 0;
|
||||
break;
|
||||
retval = 0;
|
||||
break;
|
||||
case CLIXON_AUTH_CLIENT_CERTIFICATE:
|
||||
retval = 0; /* Ignore, use default */
|
||||
break;
|
||||
retval = 0; /* Ignore, use default */
|
||||
break;
|
||||
case CLIXON_AUTH_USER:
|
||||
if ((retval = example_basic_auth(h, req, authp)) < 0)
|
||||
goto done;
|
||||
break;
|
||||
if ((retval = example_basic_auth(h, req, authp)) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, *authp);
|
||||
|
|
@ -308,10 +308,10 @@ example_restconf_credentials(clicon_handle h,
|
|||
*/
|
||||
int
|
||||
restconf_client_rpc(clicon_handle h,
|
||||
cxobj *xe,
|
||||
cbuf *cbret,
|
||||
void *arg,
|
||||
void *regarg)
|
||||
cxobj *xe,
|
||||
cbuf *cbret,
|
||||
void *arg,
|
||||
void *regarg)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x = NULL;
|
||||
|
|
@ -319,19 +319,19 @@ restconf_client_rpc(clicon_handle h,
|
|||
|
||||
/* get namespace from rpc name, return back in each output parameter */
|
||||
if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){
|
||||
clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe));
|
||||
goto done;
|
||||
clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe));
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\">", NETCONF_BASE_NAMESPACE);
|
||||
if (!xml_child_nr_type(xe, CX_ELMNT))
|
||||
cprintf(cbret, "<ok/>");
|
||||
cprintf(cbret, "<ok/>");
|
||||
else {
|
||||
while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) {
|
||||
if (xmlns_set(x, NULL, namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (clixon_xml2cbuf(cbret, xe, 0, 0, -1, 1) < 0)
|
||||
goto done;
|
||||
while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) {
|
||||
if (xmlns_set(x, NULL, namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (clixon_xml2cbuf(cbret, xe, 0, 0, -1, 1) < 0)
|
||||
goto done;
|
||||
}
|
||||
cprintf(cbret, "</rpc-reply>");
|
||||
retval = 0;
|
||||
|
|
@ -374,16 +374,16 @@ clixon_plugin_init(clicon_handle h)
|
|||
clicon_debug(1, "%s restconf", __FUNCTION__);
|
||||
/* Get user command-line options (after --) */
|
||||
if (clicon_argv_get(h, &argc, &argv) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, RESTCONF_EXAMPLE_OPTS)) != -1)
|
||||
switch (c) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (c) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Register local netconf rpc client (note not backend rpc client) */
|
||||
if (rpc_callback_register(h, restconf_client_rpc, NULL, "urn:example:clixon", "client-rpc") < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
return &api;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue