[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:
Olof hagsand 2022-10-27 14:21:17 +02:00
parent a9d1ab006c
commit d84c529ff1
376 changed files with 38147 additions and 38133 deletions

View file

@ -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{

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}