C-style update: Unified comment, retvals in order, remove trailing spaces

Changed function name for `clicon_debug` functions
This commit is contained in:
Olof hagsand 2023-10-22 18:04:47 +02:00
parent 6e314dd96f
commit 62348fc9c7
204 changed files with 6047 additions and 4904 deletions

View file

@ -45,6 +45,14 @@
## 6.5.0 ## 6.5.0
Expected: December 2023 Expected: December 2023
### C/CLI-API changes on existing features
Developers may need to change their code
* Changed function name for `clicon_debug` functions. You need to rename as follows:
* clicon_debug() -> clixon_debug()
* clicon_debug_init() -> clixon_debug_init()
* clicon_debug_get() -> clixon_debug_get()
### Corrected Bugs ### Corrected Bugs
* Fixed: [Does clixon cli support autocompletion for leafrefs pointed to another module?](https://github.com/clicon/clixon/issues/455) * Fixed: [Does clixon cli support autocompletion for leafrefs pointed to another module?](https://github.com/clicon/clixon/issues/455)

View file

@ -104,8 +104,8 @@ ce_event_cb(clicon_handle h,
void *arg) void *arg)
{ {
struct client_entry *ce = (struct client_entry *)arg; struct client_entry *ce = (struct client_entry *)arg;
clicon_debug(1, "%s op:%d", __FUNCTION__, op); clixon_debug(CLIXON_DBG_DEFAULT, "%s op:%d", __FUNCTION__, op);
switch (op){ switch (op){
case 1: case 1:
/* Risk of recursion here */ /* Risk of recursion here */
@ -140,7 +140,7 @@ ce_client_string(struct client_entry *ce,
int retval = -1; int retval = -1;
cbuf *cb = NULL; cbuf *cb = NULL;
char *id = NULL; char *id = NULL;
if (ce == NULL || cbp == NULL){ if (ce == NULL || cbp == NULL){
clicon_err(OE_UNIX, EINVAL, "ce or cbp is NULL"); clicon_err(OE_UNIX, EINVAL, "ce or cbp is NULL");
goto done; goto done;
@ -273,7 +273,7 @@ backend_monitoring_state_get(clicon_handle h,
goto fail; goto fail;
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
return retval; return retval;
@ -293,7 +293,7 @@ backend_monitoring_state_get(clicon_handle h,
* @see backend_client_delete for actual deallocation of client entry struct * @see backend_client_delete for actual deallocation of client entry struct
*/ */
int int
backend_client_rm(clicon_handle h, backend_client_rm(clicon_handle h,
struct client_entry *ce) struct client_entry *ce)
{ {
struct client_entry *c; struct client_entry *c;
@ -311,10 +311,10 @@ backend_client_rm(clicon_handle h,
if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) { if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) {
if (confirmed_commit_state_get(h) == EPHEMERAL) { if (confirmed_commit_state_get(h) == EPHEMERAL) {
/* See if this client is the origin */ /* See if this client is the origin */
clicon_debug(1, "session_id: %u, confirmed_commit.session_id: %u", ce->ce_id, confirmed_commit_session_id_get(h)); clixon_debug(CLIXON_DBG_DEFAULT, "session_id: %u, confirmed_commit.session_id: %u", ce->ce_id, confirmed_commit_session_id_get(h));
if (myid == confirmed_commit_session_id_get(h)) { if (myid == confirmed_commit_session_id_get(h)) {
clicon_debug(1, "ok, rolling back"); clixon_debug(CLIXON_DBG_DEFAULT, "ok, rolling back");
clicon_log(LOG_NOTICE, "a client with an active ephemeral confirmed-commit has disconnected; rolling back"); clicon_log(LOG_NOTICE, "a client with an active ephemeral confirmed-commit has disconnected; rolling back");
/* do_rollback errors are logged internally and there is no client to report errors to, so errors are /* do_rollback errors are logged internally and there is no client to report errors to, so errors are
@ -326,7 +326,7 @@ backend_client_rm(clicon_handle h,
} }
} }
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* for all streams: XXX better to do it top-level? */ /* for all streams: XXX better to do it top-level? */
stream_ss_delete_all(h, ce_event_cb, (void*)ce); stream_ss_delete_all(h, ce_event_cb, (void*)ce);
c0 = backend_client_list(h); c0 = backend_client_list(h);
@ -367,8 +367,8 @@ clixon_stats_datastore_get(clicon_handle h,
uint64_t nr = 0; uint64_t nr = 0;
size_t sz = 0; size_t sz = 0;
cxobj *xn = NULL; cxobj *xn = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s %s", __FUNCTION__, dbname); clixon_debug(CLIXON_DBG_DETAIL, "%s %s", __FUNCTION__, dbname);
/* This is the db cache */ /* This is the db cache */
if ((xt = xmldb_cache_get(h, dbname)) == NULL){ if ((xt = xmldb_cache_get(h, dbname)) == NULL){
/* Trigger cache if no exist (trick to ensure cache is present) */ /* Trigger cache if no exist (trick to ensure cache is present) */
@ -409,7 +409,7 @@ clixon_stats_module_get(clicon_handle h,
uint64_t nr = 0; uint64_t nr = 0;
size_t sz = 0; size_t sz = 0;
cxobj *xn = NULL; cxobj *xn = NULL;
if (ys == NULL) if (ys == NULL)
return 0; return 0;
if (yang_stats(ys, &nr, &sz) < 0) if (yang_stats(ys, &nr, &sz) < 0)
@ -439,7 +439,7 @@ clixon_stats_module_get(clicon_handle h,
* However, what really should be done is to apply the change to the datastore and then * However, what really should be done is to apply the change to the datastore and then
* validate, if error, discard to previous state. * validate, if error, discard to previous state.
* But this could discard other previous changes to candidate. * But this could discard other previous changes to candidate.
*/ */
static int static int
from_client_edit_config(clicon_handle h, from_client_edit_config(clicon_handle h,
cxobj *xn, cxobj *xn,
@ -480,7 +480,7 @@ from_client_edit_config(clicon_handle h,
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
/* Check if target locked by other client */ /* Check if target locked by other client */
iddb = xmldb_islocked(h, target); iddb = xmldb_islocked(h, target);
if (iddb && myid != iddb){ if (iddb && myid != iddb){
@ -645,22 +645,21 @@ from_client_edit_config(clicon_handle h,
xml_free(xret); xml_free(xret);
if (cbx) if (cbx)
cbuf_free(cbx); cbuf_free(cbx);
clicon_debug(1, "%s done cbret:%s", __FUNCTION__, cbuf_get(cbret)); clixon_debug(CLIXON_DBG_DEFAULT, "%s done cbret:%s", __FUNCTION__, cbuf_get(cbret));
return retval; return retval;
} /* from_client_edit_config */ } /* from_client_edit_config */
/*! Create or replace an entire config with another complete config db /*! Create or replace an entire config with another complete config db
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* NACM: If source running and target startup --> only exec permission * NACM: If source running and target startup --> only exec permission
* else: * else:
* - omit data nodes to which the client does not have read access * - omit data nodes to which the client does not have read access
* - access denied if user lacks create/delete/update * - access denied if user lacks create/delete/update
*/ */
@ -679,7 +678,7 @@ from_client_copy_config(clicon_handle h,
uint32_t myid = ce->ce_id; uint32_t myid = ce->ce_id;
cbuf *cbx = NULL; /* Assist cbuf */ cbuf *cbx = NULL; /* Assist cbuf */
cbuf *cbmsg = NULL; cbuf *cbmsg = NULL;
if ((source = netconf_db_find(xe, "source")) == NULL){ if ((source = netconf_db_find(xe, "source")) == NULL){
if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0) if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0)
goto done; goto done;
@ -688,7 +687,7 @@ from_client_copy_config(clicon_handle h,
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
if ((target = netconf_db_find(xe, "target")) == NULL){ if ((target = netconf_db_find(xe, "target")) == NULL){
if (netconf_missing_element(cbret, "protocol", "target", NULL) < 0) if (netconf_missing_element(cbret, "protocol", "target", NULL) < 0)
goto done; goto done;
@ -727,10 +726,10 @@ from_client_copy_config(clicon_handle h,
/*! Delete a configuration datastore. /*! Delete a configuration datastore.
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -738,7 +737,7 @@ static int
from_client_delete_config(clicon_handle h, from_client_delete_config(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
int retval = -1; int retval = -1;
@ -759,7 +758,7 @@ from_client_delete_config(clicon_handle h,
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
/* Check if target locked by other client */ /* Check if target locked by other client */
iddb = xmldb_islocked(h, target); iddb = xmldb_islocked(h, target);
if (iddb && myid != iddb){ if (iddb && myid != iddb){
@ -801,12 +800,12 @@ from_client_delete_config(clicon_handle h,
} }
/*! Lock the configuration system of a device /*! Lock the configuration system of a device
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -814,7 +813,7 @@ static int
from_client_lock(clicon_handle h, from_client_lock(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
int retval = -1; int retval = -1;
@ -838,7 +837,7 @@ from_client_lock(clicon_handle h,
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
/* /*
* A lock MUST not be granted if either of the following conditions is true: * A lock MUST not be granted if either of the following conditions is true:
* 1) A lock is already held by any NETCONF session or another entity. * 1) A lock is already held by any NETCONF session or another entity.
@ -889,11 +888,11 @@ from_client_lock(clicon_handle h,
/*! Release a configuration lock previously obtained with the 'lock' operation /*! Release a configuration lock previously obtained with the 'lock' operation
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -919,9 +918,9 @@ from_client_unlock(clicon_handle h,
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
iddb = xmldb_islocked(h, db); iddb = xmldb_islocked(h, db);
/* /*
* An unlock operation will not succeed if any of the following * An unlock operation will not succeed if any of the following
* conditions are true: * conditions are true:
* 1) the specified lock is not currently active * 1) the specified lock is not currently active
@ -944,7 +943,7 @@ from_client_unlock(clicon_handle h,
else{ else{
xmldb_unlock(h, db); xmldb_unlock(h, db);
/* user callback */ /* user callback */
if (clixon_plugin_lockdb_all(h, db, 0, id) < 0) if (clixon_plugin_lockdb_all(h, db, 0, id) < 0)
goto done; goto done;
if (cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE) < 0) if (cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE) < 0)
goto done; goto done;
@ -959,7 +958,7 @@ from_client_unlock(clicon_handle h,
/*! Request graceful termination of a NETCONF session. /*! Request graceful termination of a NETCONF session.
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
@ -971,7 +970,7 @@ static int
from_client_close_session(clicon_handle h, from_client_close_session(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
struct client_entry *ce = (struct client_entry *)arg; struct client_entry *ce = (struct client_entry *)arg;
@ -986,11 +985,11 @@ from_client_close_session(clicon_handle h,
/*! Internal message: Force the termination of a NETCONF session. /*! Internal message: Force the termination of a NETCONF session.
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -1009,7 +1008,7 @@ from_client_kill_session(clicon_handle h,
cxobj *x; cxobj *x;
int ret; int ret;
char *reason = NULL; char *reason = NULL;
if ((x = xml_find(xe, "session-id")) == NULL || if ((x = xml_find(xe, "session-id")) == NULL ||
(str = xml_find_value(x, "body")) == NULL){ (str = xml_find_value(x, "body")) == NULL){
if (netconf_missing_element(cbret, "protocol", "session-id", NULL) < 0) if (netconf_missing_element(cbret, "protocol", "session-id", NULL) < 0)
@ -1029,7 +1028,7 @@ from_client_kill_session(clicon_handle h,
if (xmldb_islocked(h, db) == id){ if (xmldb_islocked(h, db) == id){
xmldb_unlock(h, db); xmldb_unlock(h, db);
/* user callback */ /* user callback */
if (clixon_plugin_lockdb_all(h, db, 0, id) < 0) if (clixon_plugin_lockdb_all(h, db, 0, id) < 0)
goto done; goto done;
} }
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE); cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
@ -1043,11 +1042,11 @@ from_client_kill_session(clicon_handle h,
/*! Create a notification subscription /*! Create a notification subscription
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @see RFC5277 2.1 * @see RFC5277 2.1
@ -1063,7 +1062,7 @@ static int
from_client_create_subscription(clicon_handle h, from_client_create_subscription(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
int retval = -1; int retval = -1;
@ -1078,7 +1077,7 @@ from_client_create_subscription(clicon_handle h,
struct timeval start; struct timeval start;
struct timeval stop; struct timeval stop;
cvec *nsc = NULL; cvec *nsc = NULL;
/* XXX should use prefix cf edit_config */ /* XXX should use prefix cf edit_config */
if ((nsc = xml_nsctx_init(NULL, EVENT_RFC5277_NAMESPACE)) == NULL) if ((nsc = xml_nsctx_init(NULL, EVENT_RFC5277_NAMESPACE)) == NULL)
goto done; goto done;
@ -1089,7 +1088,7 @@ from_client_create_subscription(clicon_handle h,
str2time(stoptime, &stop) < 0){ str2time(stoptime, &stop) < 0){
if (netconf_bad_element(cbret, "application", "stopTime", "Expected timestamp") < 0) if (netconf_bad_element(cbret, "application", "stopTime", "Expected timestamp") < 0)
goto done; goto done;
goto ok; goto ok;
} }
} }
if ((x = xpath_first(xe, nsc, "//startTime")) != NULL){ if ((x = xpath_first(xe, nsc, "//startTime")) != NULL){
@ -1097,8 +1096,8 @@ from_client_create_subscription(clicon_handle h,
str2time(starttime, &start) < 0){ str2time(starttime, &start) < 0){
if (netconf_bad_element(cbret, "application", "startTime", "Expected timestamp") < 0) if (netconf_bad_element(cbret, "application", "startTime", "Expected timestamp") < 0)
goto done; goto done;
goto ok; goto ok;
} }
} }
if ((xfilter = xpath_first(xe, nsc, "//filter")) != NULL){ if ((xfilter = xpath_first(xe, nsc, "//filter")) != NULL){
if ((ftype = xml_find_value(xfilter, "type")) != NULL){ if ((ftype = xml_find_value(xfilter, "type")) != NULL){
@ -1122,13 +1121,13 @@ from_client_create_subscription(clicon_handle h,
starttime?&start:NULL, stoptime?&stop:NULL, starttime?&start:NULL, stoptime?&stop:NULL,
ce_event_cb, (void*)ce) < 0) ce_event_cb, (void*)ce) < 0)
goto done; goto done;
/* Replay of this stream to specific subscription according to start and /* Replay of this stream to specific subscription according to start and
* stop (if present). * stop (if present).
* RFC 5277: If <startTime> is not present, this is not a replay * RFC 5277: If <startTime> is not present, this is not a replay
* subscription. * subscription.
* Schedule the replay to occur right after this RPC completes, eg "now" * Schedule the replay to occur right after this RPC completes, eg "now"
*/ */
if (starttime){ if (starttime){
if (stream_replay_trigger(h, stream, ce_event_cb, (void*)ce) < 0) if (stream_replay_trigger(h, stream, ce_event_cb, (void*)ce) < 0)
goto done; goto done;
} }
@ -1143,7 +1142,7 @@ from_client_create_subscription(clicon_handle h,
/*! Retrieve a schema from the NETCONF server. /*! Retrieve a schema from the NETCONF server.
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
@ -1156,7 +1155,7 @@ static int
from_client_get_schema(clicon_handle h, from_client_get_schema(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
int retval = -1; int retval = -1;
@ -1171,7 +1170,7 @@ from_client_get_schema(clicon_handle h,
yang_stmt *yrev; yang_stmt *yrev;
cbuf *cbyang = NULL; cbuf *cbyang = NULL;
cbuf *cbmsg = NULL; cbuf *cbmsg = NULL;
const char *filename; const char *filename;
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "No yang spec"); clicon_err(OE_YANG, ENOENT, "No yang spec");
@ -1221,7 +1220,7 @@ from_client_get_schema(clicon_handle h,
if ((cbmsg = cbuf_new()) == NULL){ if ((cbmsg = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
if (version) if (version)
cprintf(cbmsg, "No schema matching: %s@%s", identifier, version); cprintf(cbmsg, "No schema matching: %s@%s", identifier, version);
else else
@ -1234,7 +1233,7 @@ from_client_get_schema(clicon_handle h,
if ((cbmsg = cbuf_new()) == NULL){ if ((cbmsg = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
cprintf(cbmsg, "Format not supported: %s", format); cprintf(cbmsg, "Format not supported: %s", format);
if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbmsg)) < 0) if (netconf_invalid_value(cbret, "protocol", cbuf_get(cbmsg)) < 0)
goto done; goto done;
@ -1264,11 +1263,11 @@ from_client_get_schema(clicon_handle h,
return retval; return retval;
} }
/*! Set debug level. /*! Set debug level.
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
@ -1284,7 +1283,7 @@ from_client_debug(clicon_handle h,
int retval = -1; int retval = -1;
uint32_t level; uint32_t level;
char *valstr; char *valstr;
if ((valstr = xml_find_body(xe, "level")) == NULL){ if ((valstr = xml_find_body(xe, "level")) == NULL){
if (netconf_missing_element(cbret, "application", "level", NULL) < 0) if (netconf_missing_element(cbret, "application", "level", NULL) < 0)
goto done; goto done;
@ -1292,9 +1291,9 @@ from_client_debug(clicon_handle h,
} }
level = atoi(valstr); level = atoi(valstr);
clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */ clixon_debug_init(level, NULL); /* 0: dont debug, 1:debug */
setlogmask(LOG_UPTO(level?LOG_DEBUG:LOG_INFO)); /* for syslog */ setlogmask(LOG_UPTO(level?LOG_DEBUG:LOG_INFO)); /* for syslog */
clicon_log(LOG_NOTICE, "%s debug:%d", __FUNCTION__, clicon_debug_get()); clicon_log(LOG_NOTICE, "%s debug:%d", __FUNCTION__, clixon_debug_get());
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE); cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
ok: ok:
retval = 0; retval = 0;
@ -1304,11 +1303,11 @@ from_client_debug(clicon_handle h,
/*! Check liveness of backend daemon, just send a reply /*! Check liveness of backend daemon, just send a reply
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -1325,11 +1324,11 @@ from_client_ping(clicon_handle h,
/*! Check liveness of backend daemon, just send a reply /*! Check liveness of backend daemon, just send a reply
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -1348,7 +1347,7 @@ from_client_stats(clicon_handle h,
yang_stmt *yspec; yang_stmt *yspec;
yang_stmt *ymodext; yang_stmt *ymodext;
cxobj *xt = NULL; cxobj *xt = NULL;
if ((str = xml_find_body(xe, "modules")) != NULL) if ((str = xml_find_body(xe, "modules")) != NULL)
modules = strcmp(str, "true") == 0; modules = strcmp(str, "true") == 0;
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
@ -1378,7 +1377,7 @@ from_client_stats(clicon_handle h,
goto done; goto done;
if (modules){ if (modules){
ym = NULL; ym = NULL;
while ((ym = yn_each(yspec, ym)) != NULL) { while ((ym = yn_each(yspec, ym)) != NULL) {
cprintf(cbret, "<module><name>%s</name>", yang_argument_get(ym)); cprintf(cbret, "<module><name>%s</name>", yang_argument_get(ym));
if (clixon_stats_module_get(h, ym, cbret) < 0) if (clixon_stats_module_get(h, ym, cbret) < 0)
goto done; goto done;
@ -1418,11 +1417,11 @@ from_client_stats(clicon_handle h,
/*! Request restart of specific plugins /*! Request restart of specific plugins
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -1440,8 +1439,8 @@ from_client_restart_plugin(clicon_handle h,
int i; int i;
clixon_plugin_t *cp; clixon_plugin_t *cp;
int ret; int ret;
if (xpath_vec(xe, NULL, "plugin", &vec, &veclen) < 0) if (xpath_vec(xe, NULL, "plugin", &vec, &veclen) < 0)
goto done; goto done;
for (i=0; i<veclen; i++){ for (i=0; i<veclen; i++){
name = xml_body(vec[i]); name = xml_body(vec[i]);
@ -1466,11 +1465,11 @@ from_client_restart_plugin(clicon_handle h,
/*! Control a specific process or daemon: start/stop, etc /*! Control a specific process or daemon: start/stop, etc
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -1486,7 +1485,7 @@ from_client_process_control(clicon_handle h,
char *name = NULL; char *name = NULL;
char *opstr = NULL; char *opstr = NULL;
proc_operation op = PROC_OP_NONE; proc_operation op = PROC_OP_NONE;
if ((x = xml_find_type(xe, NULL, "name", CX_ELMNT)) != NULL) if ((x = xml_find_type(xe, NULL, "name", CX_ELMNT)) != NULL)
name = xml_body(x); name = xml_body(x);
if ((x = xml_find_type(xe, NULL, "operation", CX_ELMNT)) != NULL){ if ((x = xml_find_type(xe, NULL, "operation", CX_ELMNT)) != NULL){
@ -1557,7 +1556,7 @@ from_client_hello(clicon_handle h,
*/ */
static int static int
from_client_msg(clicon_handle h, from_client_msg(clicon_handle h,
struct client_entry *ce, struct client_entry *ce,
struct clicon_msg *msg) struct clicon_msg *msg)
{ {
int retval = -1; int retval = -1;
@ -1581,9 +1580,9 @@ from_client_msg(clicon_handle h,
char *namespace = NULL; char *namespace = NULL;
int nr = 0; int nr = 0;
cbuf *cbce = NULL; cbuf *cbce = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
/* Return netconf message. Should be filled in by the dispatch(sub) functions /* Return netconf message. Should be filled in by the dispatch(sub) functions
* as wither rpc-error or by positive response. * as wither rpc-error or by positive response.
*/ */
@ -1629,7 +1628,7 @@ from_client_msg(clicon_handle h,
* 3. Its a create-subscription message that uses a separate socket(=client) * 3. Its a create-subscription message that uses a separate socket(=client)
*/ */
if (op_id != 0 && ce->ce_id != op_id && strcmp(rpcname, "create-subscription")){ if (op_id != 0 && ce->ce_id != op_id && strcmp(rpcname, "create-subscription")){
clicon_debug(1, "%s Warning: incoming session-id:%u does not match ce_id:%u on socket: %d", __FUNCTION__, op_id, ce->ce_id, ce->ce_s); clixon_debug(CLIXON_DBG_DEFAULT, "%s Warning: incoming session-id:%u does not match ce_id:%u on socket: %d", __FUNCTION__, op_id, ce->ce_id, ce->ce_s);
} }
/* Note that this validation is also made in xml_yang_validate_rpc, but not for hello /* Note that this validation is also made in xml_yang_validate_rpc, but not for hello
*/ */
@ -1707,7 +1706,7 @@ from_client_msg(clicon_handle h,
goto done; goto done;
} }
module = yang_argument_get(ymod); module = yang_argument_get(ymod);
clicon_debug(CLIXON_DBG_DEFAULT, "%s module:%s rpc:%s ce_id:%u s:%d", __FUNCTION__, module, clixon_debug(CLIXON_DBG_DEFAULT, "%s module:%s rpc:%s ce_id:%u s:%d", __FUNCTION__, module,
rpc, ce->ce_id, ce->ce_s); rpc, ce->ce_id, ce->ce_s);
/* Pre-NACM access step */ /* Pre-NACM access step */
xnacm = NULL; xnacm = NULL;
@ -1773,7 +1772,7 @@ from_client_msg(clicon_handle h,
if (cbuf_len(cbret) == 0) if (cbuf_len(cbret) == 0)
if (netconf_operation_failed(cbret, "application", clicon_errno?clicon_err_reason:"unknown")< 0) if (netconf_operation_failed(cbret, "application", clicon_errno?clicon_err_reason:"unknown")< 0)
goto done; goto done;
// XXX clicon_debug(CLIXON_DBG_MSG, "Reply:%s", cbuf_get(cbret)); // XXX clixon_debug(CLIXON_DBG_MSG, "Reply:%s", cbuf_get(cbret));
/* XXX problem here is that cbret has not been parsed so may contain /* XXX problem here is that cbret has not been parsed so may contain
parse errors */ parse errors */
if (ce_client_string(ce, &cbce) < 0) if (ce_client_string(ce, &cbce) < 0)
@ -1797,8 +1796,8 @@ from_client_msg(clicon_handle h,
} }
// ok: // ok:
retval = 0; retval = 0;
done: done:
clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
if (xnacm){ if (xnacm){
xml_free(xnacm); xml_free(xnacm);
if (clicon_nacm_cache_set(h, NULL) < 0) if (clicon_nacm_cache_set(h, NULL) < 0)
@ -1813,10 +1812,10 @@ from_client_msg(clicon_handle h,
if (cbret) if (cbret)
cbuf_free(cbret); cbuf_free(cbret);
/* Sanity: log if clicon_err() is not called ! */ /* Sanity: log if clicon_err() is not called ! */
if (retval < 0 && clicon_errno < 0) if (retval < 0 && clicon_errno < 0)
clicon_log(LOG_NOTICE, "%s: Internal error: No clicon_err call on RPC error (message: %s)", clicon_log(LOG_NOTICE, "%s: Internal error: No clicon_err call on RPC error (message: %s)",
__FUNCTION__, rpc?rpc:""); __FUNCTION__, rpc?rpc:"");
// clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); // clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval;// -1 here terminates backend return retval;// -1 here terminates backend
} }
@ -1829,7 +1828,7 @@ from_client_msg(clicon_handle h,
* propagated back to client. * propagated back to client.
*/ */
int int
from_client(int s, from_client(int s,
void* arg) void* arg)
{ {
int retval = -1; int retval = -1;
@ -1839,7 +1838,7 @@ from_client(int s,
int eof = 0; int eof = 0;
cbuf *cbce = NULL; cbuf *cbce = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
if (s != ce->ce_s){ if (s != ce->ce_s){
clicon_err(OE_NETCONF, EINVAL, "Internal error: s != ce->ce_s"); clicon_err(OE_NETCONF, EINVAL, "Internal error: s != ce->ce_s");
goto done; goto done;
@ -1849,7 +1848,7 @@ from_client(int s,
if (clicon_msg_rcv(ce->ce_s, cbuf_get(cbce), 0, &msg, &eof) < 0) if (clicon_msg_rcv(ce->ce_s, cbuf_get(cbce), 0, &msg, &eof) < 0)
goto done; goto done;
if (eof){ if (eof){
backend_client_rm(h, ce); backend_client_rm(h, ce);
netconf_monitoring_counter_inc(h, "dropped-sessions"); netconf_monitoring_counter_inc(h, "dropped-sessions");
} }
else else
@ -1857,7 +1856,7 @@ from_client(int s,
goto done; goto done;
retval = 0; retval = 0;
done: done:
clicon_debug(CLIXON_DBG_DETAIL, "%s retval=%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DETAIL, "%s retval=%d", __FUNCTION__, retval);
if (cbce) if (cbce)
cbuf_free(cbce); cbuf_free(cbce);
if (msg) if (msg)

View file

@ -39,7 +39,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int backend_monitoring_state_get(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, cxobj **xret, cxobj **xerr); int backend_monitoring_state_get(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, cxobj **xret, cxobj **xerr);
int backend_client_rm(clicon_handle h, struct client_entry *ce); int backend_client_rm(clicon_handle h, struct client_entry *ce);
int from_client(int fd, void *arg); int from_client(int fd, void *arg);

View file

@ -102,7 +102,7 @@ generic_validate(clicon_handle h,
cbuf *cb = NULL; cbuf *cb = NULL;
/* All entries */ /* All entries */
if ((ret = xml_yang_validate_all_top(h, td->td_target, xret)) < 0) if ((ret = xml_yang_validate_all_top(h, td->td_target, xret)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;
@ -135,10 +135,11 @@ generic_validate(clicon_handle h,
} }
/*! Common startup validation /*! Common startup validation
*
* Get db, upgrade it w potential transformed XML, populate it w yang spec, * Get db, upgrade it w potential transformed XML, populate it w yang spec,
* sort it, validate it by triggering a transaction * sort it, validate it by triggering a transaction
* and call application callback validations. * and call application callback validations.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db The startup database. The wanted backend state * @param[in] db The startup database. The wanted backend state
* @param[in] td Transaction data * @param[in] td Transaction data
* @param[out] cbret CLIgen buffer w error stmt if retval = 0 * @param[out] cbret CLIgen buffer w error stmt if retval = 0
@ -157,7 +158,7 @@ generic_validate(clicon_handle h,
* @see validate_common for incoming validate/commit * @see validate_common for incoming validate/commit
*/ */
static int static int
startup_common(clicon_handle h, startup_common(clicon_handle h,
char *db, char *db,
transaction_data_t *td, transaction_data_t *td,
cbuf *cbret) cbuf *cbret)
@ -177,7 +178,7 @@ startup_common(clicon_handle h,
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE")) if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE"))
if ((msdiff = modstate_diff_new()) == NULL) if ((msdiff = modstate_diff_new()) == NULL)
goto done; goto done;
clicon_debug(1, "Reading initial config from %s", db); clixon_debug(CLIXON_DBG_DEFAULT, "Reading initial config from %s", db);
/* Get the startup datastore WITHOUT binding to YANG, sorting and default setting. /* Get the startup datastore WITHOUT binding to YANG, sorting and default setting.
* It is done below, later in this function * It is done below, later in this function
*/ */
@ -189,7 +190,7 @@ startup_common(clicon_handle h,
if (clicon_quit_upgrade_get(h) == 1){ if (clicon_quit_upgrade_get(h) == 1){
xml_print(stderr, xerr); xml_print(stderr, xerr);
clicon_err(OE_XML, 0, "invalid configuration before upgrade"); clicon_err(OE_XML, 0, "invalid configuration before upgrade");
exit(0); /* This is fairly abrupt , but need to avoid side-effects of rewinding exit(0); /* This is fairly abrupt , but need to avoid side-effects of rewinding
* See similar clause below * See similar clause below
*/ */
} }
@ -202,7 +203,7 @@ startup_common(clicon_handle h,
if (xmldb_get0(h, db, YB_NONE, NULL, "/", 0, 0, &xt, msdiff, &xerr) < 0) if (xmldb_get0(h, db, YB_NONE, NULL, "/", 0, 0, &xt, msdiff, &xerr) < 0)
goto done; goto done;
} }
clicon_debug_xml(CLIXON_DBG_DETAIL, xt, "startup"); clixon_debug_xml(CLIXON_DBG_DETAIL, xt, "startup");
if (msdiff && msdiff->md_status == 0){ // Possibly check for CLICON_XMLDB_MODSTATE if (msdiff && msdiff->md_status == 0){ // Possibly check for CLICON_XMLDB_MODSTATE
clicon_log(LOG_WARNING, "Modstate expected in startup datastore but not found\n" clicon_log(LOG_WARNING, "Modstate expected in startup datastore but not found\n"
"This may indicate that the datastore is not initialized corrrectly, such as copy/pasted.\n" "This may indicate that the datastore is not initialized corrrectly, such as copy/pasted.\n"
@ -212,7 +213,7 @@ startup_common(clicon_handle h,
clicon_err(OE_YANG, 0, "Yang spec not set"); clicon_err(OE_YANG, 0, "Yang spec not set");
goto done; goto done;
} }
clicon_debug(1, "Reading startup config done"); clixon_debug(CLIXON_DBG_DEFAULT, "Reading startup config done");
/* Clear flags xpath for get */ /* Clear flags xpath for get */
xml_apply0(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, xml_apply0(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
(void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)); (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE));
@ -253,7 +254,7 @@ startup_common(clicon_handle h,
stack. Alternative is to make a separate function stack for this. */ stack. Alternative is to make a separate function stack for this. */
} }
/* If empty skip. Note upgrading can add children, so it may be empty before that. */ /* If empty skip. Note upgrading can add children, so it may be empty before that. */
if (xml_child_nr(xt) == 0){ if (xml_child_nr(xt) == 0){
td->td_target = xt; td->td_target = xt;
xt = NULL; xt = NULL;
goto ok; goto ok;
@ -264,7 +265,7 @@ startup_common(clicon_handle h,
if (ret == 0){ if (ret == 0){
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
/* After upgrade check no state data */ /* After upgrade check no state data */
if ((ret = xml_non_config_data(xt, &xret)) < 0) if ((ret = xml_non_config_data(xt, &xret)) < 0)
@ -272,7 +273,7 @@ startup_common(clicon_handle h,
if (ret == 0){ if (ret == 0){
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
/* Sort xml */ /* Sort xml */
if (xml_sort_recurse(xt) < 0) if (xml_sort_recurse(xt) < 0)
@ -283,7 +284,7 @@ startup_common(clicon_handle h,
/* Apply default values (removed in clear function) */ /* Apply default values (removed in clear function) */
if (xml_default_recurse(xt, 0) < 0) if (xml_default_recurse(xt, 0) < 0)
goto done; goto done;
/* Handcraft transition with with only add tree */ /* Handcraft transition with with only add tree */
td->td_target = xt; td->td_target = xt;
xt = NULL; xt = NULL;
@ -291,7 +292,7 @@ startup_common(clicon_handle h,
while ((x = xml_child_each(td->td_target, x, CX_ELMNT)) != NULL){ while ((x = xml_child_each(td->td_target, x, CX_ELMNT)) != NULL){
xml_flag_set(x, XML_FLAG_ADD); /* Also down */ xml_flag_set(x, XML_FLAG_ADD); /* Also down */
xml_apply(x, CX_ELMNT, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_ADD); xml_apply(x, CX_ELMNT, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_ADD);
if (cxvec_append(x, &td->td_avec, &td->td_alen) < 0) if (cxvec_append(x, &td->td_avec, &td->td_alen) < 0)
goto done; goto done;
} }
@ -301,7 +302,7 @@ startup_common(clicon_handle h,
/* 5. Make generic validation on all new or changed data. /* 5. Make generic validation on all new or changed data.
Note this is only call that uses 3-values */ Note this is only call that uses 3-values */
clicon_debug(1, "Validating startup %s", db); clixon_debug(CLIXON_DBG_DEFAULT, "Validating startup %s", db);
if ((ret = generic_validate(h, yspec, td, &xret)) < 0) if ((ret = generic_validate(h, yspec, td, &xret)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
@ -328,14 +329,14 @@ startup_common(clicon_handle h,
if (msdiff) if (msdiff)
modstate_diff_free(msdiff); modstate_diff_free(msdiff);
return retval; return retval;
fail: fail:
retval = 0; retval = 0;
goto done; goto done;
} }
/*! Read startup db, check upgrades and validate it, return upgraded XML /*! Read startup db, check upgrades and validate it, return upgraded XML
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db The startup database. The wanted backend state * @param[in] db The startup database. The wanted backend state
* @param[out] xtr (Potentially) transformed XML * @param[out] xtr (Potentially) transformed XML
* @param[out] cbret CLIgen buffer w error stmt if retval = 0 * @param[out] cbret CLIgen buffer w error stmt if retval = 0
@ -344,7 +345,7 @@ startup_common(clicon_handle h,
* @retval -1 Error - or validation failed (but cbret not set) * @retval -1 Error - or validation failed (but cbret not set)
*/ */
int int
startup_validate(clicon_handle h, startup_validate(clicon_handle h,
char *db, char *db,
cxobj **xtr, cxobj **xtr,
cbuf *cbret) cbuf *cbret)
@ -369,7 +370,7 @@ startup_validate(clicon_handle h,
if (xmldb_get0_clear(h, td->td_target) < 0) if (xmldb_get0_clear(h, td->td_target) < 0)
goto done; goto done;
if (xtr){ if (xtr){
*xtr = td->td_target; *xtr = td->td_target;
td->td_target = NULL; td->td_target = NULL;
} }
retval = 1; retval = 1;
@ -386,7 +387,7 @@ startup_validate(clicon_handle h,
/*! Read startup db, check upgrades and commit it /*! Read startup db, check upgrades and commit it
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db The startup database. The wanted backend state * @param[in] db The startup database. The wanted backend state
* @param[out] cbret CLIgen buffer w error stmt if retval = 0 * @param[out] cbret CLIgen buffer w error stmt if retval = 0
* @retval 1 Validation OK * @retval 1 Validation OK
@ -395,7 +396,7 @@ startup_validate(clicon_handle h,
* Only called from startup_mode_startup * Only called from startup_mode_startup
*/ */
int int
startup_commit(clicon_handle h, startup_commit(clicon_handle h,
char *db, char *db,
cbuf *cbret) cbuf *cbret)
{ {
@ -426,7 +427,7 @@ startup_commit(clicon_handle h,
/* [Delete and] create running db */ /* [Delete and] create running db */
if (xmldb_exists(h, "running") == 1){ if (xmldb_exists(h, "running") == 1){
if (xmldb_delete(h, "running") != 0 && errno != ENOENT) if (xmldb_delete(h, "running") != 0 && errno != ENOENT)
goto done;; goto done;;
} }
if (xmldb_create(h, "running") < 0) if (xmldb_create(h, "running") < 0)
@ -463,9 +464,10 @@ startup_commit(clicon_handle h,
} }
/*! Validate a candidate db and comnpare to running /*! Validate a candidate db and comnpare to running
*
* Get both source and dest datastore, validate target, compute diffs * Get both source and dest datastore, validate target, compute diffs
* and call application callback validations. * and call application callback validations.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db The (candidate) database. The wanted backend state * @param[in] db The (candidate) database. The wanted backend state
* @param[in] td Transaction data * @param[in] td Transaction data
* @param[out] xret Error XML tree, if retval is 0. Free with xml_free after use * @param[out] xret Error XML tree, if retval is 0. Free with xml_free after use
@ -477,7 +479,7 @@ startup_commit(clicon_handle h,
* @see startup_common for startup scenario * @see startup_common for startup scenario
*/ */
static int static int
validate_common(clicon_handle h, validate_common(clicon_handle h,
char *db, char *db,
transaction_data_t *td, transaction_data_t *td,
cxobj **xret) cxobj **xret)
@ -487,11 +489,11 @@ validate_common(clicon_handle h,
int i; int i;
cxobj *xn; cxobj *xn;
int ret; int ret;
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
} }
/* This is the state we are going to */ /* This is the state we are going to */
if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &td->td_target, NULL, xret)) < 0) if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &td->td_target, NULL, xret)) < 0)
goto done; goto done;
@ -500,7 +502,7 @@ validate_common(clicon_handle h,
/* Clear flags xpath for get */ /* Clear flags xpath for get */
xml_apply0(td->td_target, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, xml_apply0(td->td_target, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset,
(void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)); (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE));
/* 2. Parse xml trees /* 2. Parse xml trees
* This is the state we are going from */ * This is the state we are going from */
if ((ret = xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, 0, &td->td_src, NULL, xret)) < 0) if ((ret = xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, 0, &td->td_src, NULL, xret)) < 0)
goto done; goto done;
@ -520,7 +522,7 @@ validate_common(clicon_handle h,
&td->td_tcvec, /* changed: wanted values */ &td->td_tcvec, /* changed: wanted values */
&td->td_clen) < 0) &td->td_clen) < 0)
goto done; goto done;
if (clicon_debug_get() & CLIXON_DBG_DETAIL) if (clixon_debug_get() & CLIXON_DBG_DETAIL)
transaction_dbg(h, CLIXON_DBG_DETAIL, td, __FUNCTION__); transaction_dbg(h, CLIXON_DBG_DETAIL, td, __FUNCTION__);
/* Mark as changed in tree */ /* Mark as changed in tree */
for (i=0; i<td->td_dlen; i++){ /* Also down */ for (i=0; i<td->td_dlen; i++){ /* Also down */
@ -571,7 +573,7 @@ validate_common(clicon_handle h,
/*! Start a validate transaction /*! Start a validate transaction
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db A candidate database, typically "candidate" but not necessarily so * @param[in] db A candidate database, typically "candidate" but not necessarily so
* @param[out] cbret CLIgen buffer w error stmt if retval = 0 * @param[out] cbret CLIgen buffer w error stmt if retval = 0
* @retval 1 Validation OK * @retval 1 Validation OK
@ -579,7 +581,7 @@ validate_common(clicon_handle h,
* @retval -1 Error - or validation failed * @retval -1 Error - or validation failed
*/ */
int int
candidate_validate(clicon_handle h, candidate_validate(clicon_handle h,
char *db, char *db,
cbuf *cbret) cbuf *cbret)
{ {
@ -587,8 +589,8 @@ candidate_validate(clicon_handle h,
transaction_data_t *td = NULL; transaction_data_t *td = NULL;
cxobj *xret = NULL; cxobj *xret = NULL;
int ret; int ret;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (db == NULL || cbret == NULL){ if (db == NULL || cbret == NULL){
clicon_err(OE_CFG, EINVAL, "db or cbret is NULL"); clicon_err(OE_CFG, EINVAL, "db or cbret is NULL");
goto done; goto done;
@ -647,7 +649,7 @@ candidate_validate(clicon_handle h,
* The code reverts changes if the commit fails. But if the revert * The code reverts changes if the commit fails. But if the revert
* fails, we just ignore the errors and proceed. Maybe we should * fails, we just ignore the errors and proceed. Maybe we should
* do something more drastic? * do something more drastic?
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> (or NULL) * @param[in] xe Request: <rpc><xn></rpc> (or NULL)
* @param[in] db A candidate database, not necessarily "candidate" * @param[in] db A candidate database, not necessarily "candidate"
* @param[in] myid Client id of triggering incoming message (or 0) * @param[in] myid Client id of triggering incoming message (or 0)
@ -658,7 +660,7 @@ candidate_validate(clicon_handle h,
* @retval -1 Error - or validation failed * @retval -1 Error - or validation failed
*/ */
int int
candidate_commit(clicon_handle h, candidate_commit(clicon_handle h,
cxobj *xe, cxobj *xe,
char *db, char *db,
uint32_t myid, uint32_t myid,
@ -713,7 +715,7 @@ candidate_commit(clicon_handle h,
/* After commit, make a post-commit call (sure that all plugins have committed) */ /* After commit, make a post-commit call (sure that all plugins have committed) */
if (plugin_transaction_commit_done_all(h, td) < 0) if (plugin_transaction_commit_done_all(h, td) < 0)
goto done; goto done;
/* Clear cached trees from default values and marking */ /* Clear cached trees from default values and marking */
if (xmldb_get0_clear(h, td->td_target) < 0) if (xmldb_get0_clear(h, td->td_target) < 0)
goto done; goto done;
@ -738,7 +740,6 @@ candidate_commit(clicon_handle h,
/* 9. Call plugin transaction end callbacks */ /* 9. Call plugin transaction end callbacks */
plugin_transaction_end_all(h, td); plugin_transaction_end_all(h, td);
retval = 1; retval = 1;
done: done:
/* In case of failure (or error), call plugin transaction termination callbacks */ /* In case of failure (or error), call plugin transaction termination callbacks */
@ -759,11 +760,11 @@ candidate_commit(clicon_handle h,
/*! Commit the candidate configuration as the device's new current configuration /*! Commit the candidate configuration as the device's new current configuration
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @note NACM: The server MUST determine the exact nodes in the running * @note NACM: The server MUST determine the exact nodes in the running
@ -815,13 +816,13 @@ from_client_commit(clicon_handle h,
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
if (netconf_in_use(cbret, "protocol", "Operation failed, lock is already held") < 0) if (netconf_in_use(cbret, "protocol", "Operation failed, lock is already held") < 0)
goto done; goto done;
goto ok; goto ok;
} }
if ((ret = candidate_commit(h, xe, "candidate", myid, 0, cbret)) < 0){ /* Assume validation fail, nofatal */ if ((ret = candidate_commit(h, xe, "candidate", myid, 0, cbret)) < 0){ /* Assume validation fail, nofatal */
clicon_debug(1, "Commit candidate failed"); clixon_debug(CLIXON_DBG_DEFAULT, "Commit candidate failed");
if (ret < 0) if (ret < 0)
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0) if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
goto done; goto done;
@ -839,13 +840,12 @@ from_client_commit(clicon_handle h,
/*! Revert the candidate configuration to the current running configuration. /*! Revert the candidate configuration to the current running configuration.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK. This may indicate both ok and err msg back to client * @retval 0 OK. This may indicate both ok and err msg back to client
* @retval 0 OK
* @retval -1 Error * @retval -1 Error
* NACM: No datastore permissions are needed. * NACM: No datastore permissions are needed.
*/ */
@ -861,14 +861,14 @@ from_client_discard_changes(clicon_handle h,
uint32_t myid = ce->ce_id; uint32_t myid = ce->ce_id;
uint32_t iddb; uint32_t iddb;
cbuf *cbx = NULL; /* Assist cbuf */ cbuf *cbx = NULL; /* Assist cbuf */
/* Check if target locked by other client */ /* Check if target locked by other client */
iddb = xmldb_islocked(h, "candidate"); iddb = xmldb_islocked(h, "candidate");
if (iddb && myid != iddb){ if (iddb && myid != iddb){
if ((cbx = cbuf_new()) == NULL){ if ((cbx = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
cprintf(cbx, "<session-id>%u</session-id>", iddb); cprintf(cbx, "<session-id>%u</session-id>", iddb);
if (netconf_lock_denied(cbret, cbuf_get(cbx), "Operation failed, lock is already held") < 0) if (netconf_lock_denied(cbret, cbuf_get(cbx), "Operation failed, lock is already held") < 0)
goto done; goto done;
@ -890,11 +890,12 @@ from_client_discard_changes(clicon_handle h,
} }
/*! Validates the contents of the specified configuration. /*! Validates the contents of the specified configuration.
* @param[in] h Clicon handle *
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] h Clixon handle
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK. This may indicate both ok and err msg back to client * @retval 0 OK. This may indicate both ok and err msg back to client
* (eg invalid) * (eg invalid)
* @retval -1 Error * @retval -1 Error
@ -910,7 +911,7 @@ from_client_validate(clicon_handle h,
int ret; int ret;
char *db; char *db;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((db = netconf_db_find(xe, "source")) == NULL){ if ((db = netconf_db_find(xe, "source")) == NULL){
if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0) if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0)
goto done; goto done;
@ -927,6 +928,7 @@ from_client_validate(clicon_handle h,
} /* from_client_validate */ } /* from_client_validate */
/*! Restart specific backend plugins without full backend restart /*! Restart specific backend plugins without full backend restart
*
* Note, depending on plugin callbacks, there may be other dependencies which may make this * Note, depending on plugin callbacks, there may be other dependencies which may make this
* difficult in the general case. * difficult in the general case.
*/ */
@ -945,7 +947,7 @@ from_client_restart_one(clicon_handle h,
int i; int i;
cxobj *xn; cxobj *xn;
void *wh = NULL; void *wh = NULL;
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if (xmldb_db_reset(h, db) < 0) if (xmldb_db_reset(h, db) < 0)
goto done; goto done;
@ -955,7 +957,7 @@ from_client_restart_one(clicon_handle h,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if ((retval = resetfn(h, db)) < 0) { if ((retval = resetfn(h, db)) < 0) {
clicon_debug(1, "plugin_start() failed"); clixon_debug(CLIXON_DBG_DEFAULT, "plugin_start() failed");
goto done; goto done;
} }
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -1049,7 +1051,7 @@ from_client_restart_one(clicon_handle h,
} }
/*! Reset running and start in failsafe mode. If no failsafe then quit. /*! Reset running and start in failsafe mode. If no failsafe then quit.
* *
* param[in] h Clixon handle * param[in] h Clixon handle
* param[in] phase Debug string * param[in] phase Debug string
Typically done when startup status is not OK so Typically done when startup status is not OK so

View file

@ -105,6 +105,7 @@ confirmed_commit_init(clicon_handle h)
} }
/*! If confirm commit persist-id exists, free it /*! If confirm commit persist-id exists, free it
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval 0 OK * @retval 0 OK
*/ */
@ -112,7 +113,7 @@ int
confirmed_commit_free(clicon_handle h) confirmed_commit_free(clicon_handle h)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
if (cc != NULL){ if (cc != NULL){
if (cc->cc_persist_id != NULL) if (cc->cc_persist_id != NULL)
@ -130,7 +131,7 @@ enum confirmed_commit_state
confirmed_commit_state_get(clicon_handle h) confirmed_commit_state_get(clicon_handle h)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
return cc->cc_state; return cc->cc_state;
} }
@ -140,7 +141,7 @@ confirmed_commit_state_set(clicon_handle h,
enum confirmed_commit_state state) enum confirmed_commit_state state)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
cc->cc_state = state; cc->cc_state = state;
return 0; return 0;
@ -150,7 +151,7 @@ char *
confirmed_commit_persist_id_get(clicon_handle h) confirmed_commit_persist_id_get(clicon_handle h)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
return cc->cc_persist_id; return cc->cc_persist_id;
} }
@ -160,7 +161,7 @@ confirmed_commit_persist_id_set(clicon_handle h,
char *persist_id) char *persist_id)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
if (cc->cc_persist_id) if (cc->cc_persist_id)
free(cc->cc_persist_id); free(cc->cc_persist_id);
@ -179,7 +180,7 @@ uint32_t
confirmed_commit_session_id_get(clicon_handle h) confirmed_commit_session_id_get(clicon_handle h)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
return cc->cc_session_id; return cc->cc_session_id;
} }
@ -189,7 +190,7 @@ confirmed_commit_session_id_set(clicon_handle h,
uint32_t session_id) uint32_t session_id)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
cc->cc_session_id = session_id; cc->cc_session_id = session_id;
return 0; return 0;
@ -201,7 +202,7 @@ confirmed_commit_fn_arg_get(clicon_handle h,
void **arg) void **arg)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
*fn = cc->cc_fn; *fn = cc->cc_fn;
*arg = cc->cc_arg; *arg = cc->cc_arg;
@ -214,7 +215,7 @@ confirmed_commit_fn_arg_set(clicon_handle h,
void *arg) void *arg)
{ {
struct confirmed_commit *cc = NULL; struct confirmed_commit *cc = NULL;
clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc); clicon_ptr_get(h, "confirmed-commit-struct", (void**)&cc);
cc->cc_fn = fn; cc->cc_fn = fn;
cc->cc_arg = arg; cc->cc_arg = arg;
@ -222,6 +223,7 @@ confirmed_commit_fn_arg_set(clicon_handle h,
} }
/*! Return if confirmed tag found /*! Return if confirmed tag found
*
* @param[in] xe Commit rpc xml * @param[in] xe Commit rpc xml
* @retval 1 Confirmed tag exists * @retval 1 Confirmed tag exists
* @retval 0 Confirmed tag does not exist * @retval 0 Confirmed tag does not exist
@ -233,6 +235,7 @@ xe_confirmed(cxobj *xe)
} }
/*! Return if persist exists and its string value field /*! Return if persist exists and its string value field
*
* @param[in] xe Commit rpc xml * @param[in] xe Commit rpc xml
* @param[out] str Pointer to persist * @param[out] str Pointer to persist
* @retval 1 Persist field exists * @retval 1 Persist field exists
@ -274,6 +277,7 @@ xe_persist_id(cxobj *xe,
} }
/*! Return timeout /*! Return timeout
*
* @param[in] xe Commit rpc xml * @param[in] xe Commit rpc xml
* @retval sec Timeout in seconds, can be 0 if no timeout exists or is zero * @retval sec Timeout in seconds, can be 0 if no timeout exists or is zero
*/ */
@ -282,7 +286,7 @@ xe_timeout(cxobj *xe)
{ {
cxobj *xml; cxobj *xml;
char *str; char *str;
if ((xml = xml_find_type(xe, NULL, "confirm-timeout", CX_ELMNT)) != NULL && if ((xml = xml_find_type(xe, NULL, "confirm-timeout", CX_ELMNT)) != NULL &&
(str = xml_body(xml)) != NULL) (str = xml_body(xml)) != NULL)
return strtoul(str, NULL, 10); return strtoul(str, NULL, 10);
@ -293,7 +297,7 @@ xe_timeout(cxobj *xe)
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval 0 Rollback event successfully cancelled * @retval 0 Rollback event successfully cancelled
* @retval -1 No Rollback event was found * @retval -1 No Rollback event was found
*/ */
int int
cancel_rollback_event(clicon_handle h) cancel_rollback_event(clicon_handle h)
@ -317,7 +321,7 @@ cancel_rollback_event(clicon_handle h)
* @param[in] fd a dummy argument per the event callback semantics * @param[in] fd a dummy argument per the event callback semantics
* @param[in] arg a void pointer to a clicon_handle * @param[in] arg a void pointer to a clicon_handle
* @retval 0 the rollback was successful * @retval 0 the rollback was successful
* @retval -1 the rollback failed * @retval -1 the rollback failed
* @see do_rollback() * @see do_rollback()
*/ */
static int static int
@ -337,7 +341,7 @@ rollback_fn(int fd,
* @param[in] timeout a uint32 representing the number of seconds before the rollback event should fire * @param[in] timeout a uint32 representing the number of seconds before the rollback event should fire
* *
* @retval 0 Rollback event successfully scheduled * @retval 0 Rollback event successfully scheduled
* @retval -1 Rollback event was not scheduled * @retval -1 Rollback event was not scheduled
*/ */
static int static int
schedule_rollback_event(clicon_handle h, schedule_rollback_event(clicon_handle h,
@ -373,6 +377,7 @@ schedule_rollback_event(clicon_handle h,
} }
/*! Cancel a confirming commit by removing rollback, and free state /*! Cancel a confirming commit by removing rollback, and free state
*
* @param[in] h * @param[in] h
* @param[out] cbret * @param[out] cbret
* @retval 0 OK * @retval 0 OK
@ -401,12 +406,12 @@ cancel_confirmed_commit(clicon_handle h)
* without a <persist> value, OR * without a <persist> value, OR
* 2) be presented with a <persist-id> value that matches the <persist> value accompanying the prior confirmed-commit * 2) be presented with a <persist-id> value that matches the <persist> value accompanying the prior confirmed-commit
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[in] myid current client session-id * @param[in] myid current client session-id
* @retval 1 The confirming-commit is valid * @retval 1 The confirming-commit is valid
* @retval 0 The confirming-commit is not valid * @retval 0 The confirming-commit is not valid
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
check_valid_confirming_commit(clicon_handle h, check_valid_confirming_commit(clicon_handle h,
@ -452,7 +457,7 @@ check_valid_confirming_commit(clicon_handle h,
"not issued on the same session as the confirmed-commit"); "not issued on the same session as the confirmed-commit");
goto invalid; goto invalid;
default: default:
clicon_debug(1, "commit-confirmed state !? %d", confirmed_commit_state_get(h)); clixon_debug(CLIXON_DBG_DEFAULT, "commit-confirmed state !? %d", confirmed_commit_state_get(h));
goto invalid; goto invalid;
} }
retval = 1; // valid retval = 1; // valid
@ -471,11 +476,11 @@ check_valid_confirming_commit(clicon_handle h,
* In the second phase, the action taken is to handle both confirming- and confirmed-commit by creating the * In the second phase, the action taken is to handle both confirming- and confirmed-commit by creating the
* rollback database as required, then deleting it once the sequence is complete. * rollback database as required, then deleting it once the sequence is complete.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Commit rpc xml or NULL * @param[in] xe Commit rpc xml or NULL
* @param[in] myid Current session-id, only valid > 0 if call is made as a result of an incoming message * @param[in] myid Current session-id, only valid > 0 if call is made as a result of an incoming message
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @note There are some calls to this function where myid is 0 (which is invalid). It is unclear if such calls * @note There are some calls to this function where myid is 0 (which is invalid). It is unclear if such calls
* actually occur, and if so, if they are correctly handled. The calls are from do_rollback() and load_failsafe() * actually occur, and if so, if they are correctly handled. The calls are from do_rollback() and load_failsafe()
*/ */
@ -622,9 +627,9 @@ handle_confirmed_commit(clicon_handle h,
* 2. from_client_cancel_commit() (invoked either by netconf client, or CLI) * 2. from_client_cancel_commit() (invoked either by netconf client, or CLI)
* 3. rollback_fn() (invoked by expiration of the rollback event timer) * 3. rollback_fn() (invoked by expiration of the rollback event timer)
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval -1 Error
* @retval 0 Success * @retval 0 Success
* @retval -1 Error
* @see backend_client_rm() * @see backend_client_rm()
* @see from_client_cancel_commit() * @see from_client_cancel_commit()
* @see rollback_fn() * @see rollback_fn()
@ -696,12 +701,13 @@ do_rollback(clicon_handle h,
} }
/*! Cancel an ongoing confirmed commit. /*! Cancel an ongoing confirmed commit.
*
* If the confirmed commit is persistent, the parameter 'persist-id' must be * If the confirmed commit is persistent, the parameter 'persist-id' must be
* given, and it must match the value of the 'persist' parameter. * given, and it must match the value of the 'persist' parameter.
* If the confirmed-commit is ephemeral, the 'persist-id' must not be given and both the confirmed-commit and the * If the confirmed-commit is ephemeral, the 'persist-id' must not be given and both the confirmed-commit and the
* cancel-commit must originate from the same session. * cancel-commit must originate from the same session.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
@ -777,7 +783,8 @@ from_client_cancel_commit(clicon_handle h,
} }
/*! Incoming commit handler for confirmed commit /*! Incoming commit handler for confirmed commit
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[in] myid Client-id * @param[in] myid Client-id
* @param[out] cbret Return xml tree * @param[out] cbret Return xml tree

View file

@ -72,12 +72,15 @@
#include "backend_handle.h" #include "backend_handle.h"
#include "backend_get.h" #include "backend_get.h"
/*! /*! restrconf get capabilities
*
* Maybe should be in the restconf client instead of backend? * Maybe should be in the restconf client instead of backend?
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] yspec Yang spec * @param[in] yspec Yang spec
* @param[in] xpath Xpath selection, not used but may be to filter early * @param[in] xpath Xpath selection, not used but may be to filter early
* @param[out] xrs XML restconf-state node * @param[out] xrs XML restconf-state node
* @retval 0 OK
* @retval -1 Error
* @see netconf_hello_server * @see netconf_hello_server
* @see rfc8040 Sections 9.1 * @see rfc8040 Sections 9.1
*/ */
@ -114,7 +117,8 @@ restconf_client_get_capabilities(clicon_handle h,
} }
/*! Get streams state according to RFC 8040 or RFC5277 common function /*! Get streams state according to RFC 8040 or RFC5277 common function
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] yspec Yang spec * @param[in] yspec Yang spec
* @param[in] xpath Xpath selection, not used but may be to filter early * @param[in] xpath Xpath selection, not used but may be to filter early
* @param[in] module Name of yang module * @param[in] module Name of yang module
@ -176,7 +180,8 @@ client_get_streams(clicon_handle h,
} }
/*! Get system state-data, including streams and plugins /*! Get system state-data, including streams and plugins
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] xpath XPath selection, may be used to filter early * @param[in] xpath XPath selection, may be used to filter early
* @param[in] nsc XML Namespace context for xpath * @param[in] nsc XML Namespace context for xpath
* @param[in] wdef With-defaults parameter, see RFC 6243 * @param[in] wdef With-defaults parameter, see RFC 6243
@ -213,7 +218,7 @@ get_statedata(clicon_handle h,
cbuf *cb = NULL; cbuf *cb = NULL;
cxobj *xerr = NULL; cxobj *xerr = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "No yang spec"); clicon_err(OE_YANG, ENOENT, "No yang spec");
goto done; goto done;
@ -368,7 +373,7 @@ get_statedata(clicon_handle h,
} /* switch wdef */ } /* switch wdef */
retval = 1; /* OK */ retval = 1; /* OK */
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
if (xerr) if (xerr)
xml_free(xerr); xml_free(xerr);
if (x1) if (x1)
@ -390,7 +395,7 @@ get_statedata(clicon_handle h,
* and we need to re-add it. * and we need to re-add it.
* Note original xpath * Note original xpath
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] yspec Yang spec * @param[in] yspec Yang spec
* @param[in] xret Result XML tree * @param[in] xret Result XML tree
* @param[in] xvec xpath lookup result on xret * @param[in] xvec xpath lookup result on xret
@ -438,7 +443,7 @@ filter_xpath_again(clicon_handle h,
/*! Help function for NACM access and return message /*! Help function for NACM access and return message
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xret Result XML tree * @param[in] xret Result XML tree
* @param[in] xvec xpath lookup result on xret * @param[in] xvec xpath lookup result on xret
* @param[in] xlen length of xvec * @param[in] xlen length of xvec
@ -520,7 +525,7 @@ element2value(clicon_handle h,
/*! Extract offset and limit from get/list-pagination /*! Extract offset and limit from get/list-pagination
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] offset Number of entries in the working result-set that should be skipped * @param[out] offset Number of entries in the working result-set that should be skipped
* @param[out] limit Limits the number of entries returned from the working result-set * @param[out] limit Limits the number of entries returned from the working result-set
@ -552,7 +557,7 @@ list_pagination_hdr(clicon_handle h,
* *
* It is specialized enough to have its own function. Specifically, extra attributes as well * It is specialized enough to have its own function. Specifically, extra attributes as well
* as the list-paginaiton API * as the list-paginaiton API
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] ce Client entry, for locking * @param[in] ce Client entry, for locking
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[in] content Get config/state/both * @param[in] content Get config/state/both
@ -764,7 +769,7 @@ get_list_pagination(clicon_handle h,
if ((ret = xml_bind_yang(h, xret, YB_MODULE, yspec, &xerr)) < 0) if ((ret = xml_bind_yang(h, xret, YB_MODULE, yspec, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug_xml(1, xret, "Yang bind pagination state"); clixon_debug_xml(1, xret, "Yang bind pagination state");
if (clixon_netconf_internal_error(xerr, if (clixon_netconf_internal_error(xerr,
". Internal error, state callback returned invalid XML", ". Internal error, state callback returned invalid XML",
NULL) < 0) NULL) < 0)
@ -821,7 +826,7 @@ get_list_pagination(clicon_handle h,
/*! Common get/get-config code for retrieving configuration and state information. /*! Common get/get-config code for retrieving configuration and state information.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] ce Client entry, for locking * @param[in] ce Client entry, for locking
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[in] content Get config/state/both * @param[in] content Get config/state/both
@ -867,7 +872,7 @@ get_common(clicon_handle h,
char *wdefstr; char *wdefstr;
wdef = WITHDEFAULTS_EXPLICIT; wdef = WITHDEFAULTS_EXPLICIT;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
username = clicon_username_get(h); username = clicon_username_get(h);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "No yang spec9"); clicon_err(OE_YANG, ENOENT, "No yang spec9");
@ -1013,7 +1018,7 @@ get_common(clicon_handle h,
(ret = xml_yang_validate_add(h, xret, &xerr)) < 0) (ret = xml_yang_validate_add(h, xret, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug_xml(1, xret, "VALIDATE_STATE"); clixon_debug_xml(1, xret, "VALIDATE_STATE");
if (clixon_netconf_internal_error(xerr, if (clixon_netconf_internal_error(xerr,
". Internal error, state callback returned invalid XML", ". Internal error, state callback returned invalid XML",
NULL) < 0) NULL) < 0)
@ -1044,7 +1049,7 @@ get_common(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
if (xvec) if (xvec)
free(xvec); free(xvec);
if (xret) if (xret)
@ -1067,12 +1072,12 @@ get_common(clicon_handle h,
} }
/*! Retrieve all or part of a specified configuration. /*! Retrieve all or part of a specified configuration.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @see from_client_get * @see from_client_get
@ -1099,11 +1104,11 @@ from_client_get_config(clicon_handle h,
/*! Retrieve running configuration and device state information. /*! Retrieve running configuration and device state information.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xe Request: <rpc><xn></rpc> * @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. * @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry * @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register() * @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* *
@ -1113,13 +1118,13 @@ int
from_client_get(clicon_handle h, from_client_get(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
netconf_content content = CONTENT_ALL; netconf_content content = CONTENT_ALL;
char *attr; char *attr;
struct client_entry *ce = (struct client_entry *)arg; struct client_entry *ce = (struct client_entry *)arg;
/* Clixon extensions: content */ /* Clixon extensions: content */
if ((attr = xml_find_value(xe, "content")) != NULL) if ((attr = xml_find_value(xe, "content")) != NULL)
content = netconf_content_str2int(attr); content = netconf_content_str2int(attr);

View file

@ -39,7 +39,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int from_client_get_config(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); int from_client_get_config(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_get(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); int from_client_get(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_get_pageable_list(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); /* XXX */ int from_client_get_pageable_list(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); /* XXX */

View file

@ -84,6 +84,7 @@
#define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log" #define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log"
/*! Clean and close all state of backend (but dont exit). /*! Clean and close all state of backend (but dont exit).
*
* Cannot use h after this * Cannot use h after this
* @param[in] h Clixon handle * @param[in] h Clixon handle
*/ */
@ -99,7 +100,7 @@ backend_terminate(clicon_handle h)
int ss; int ss;
cvec *nsctx; cvec *nsctx;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((ss = clicon_socket_get(h)) != -1) if ((ss = clicon_socket_get(h)) != -1)
close(ss); close(ss);
/* Disconnect datastore */ /* Disconnect datastore */
@ -142,7 +143,7 @@ backend_terminate(clicon_handle h)
unlink(sockpath); unlink(sockpath);
backend_handle_exit(h); /* Also deletes streams. Cannot use h after this. */ backend_handle_exit(h); /* Also deletes streams. Cannot use h after this. */
clixon_event_exit(); clixon_event_exit();
clicon_debug(1, "%s done", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s done", __FUNCTION__);
clixon_err_exit(); clixon_err_exit();
clicon_log_exit(); clicon_log_exit();
return 0; return 0;
@ -163,19 +164,21 @@ backend_sig_term(int arg)
clixon_exit_set(1); /* checked in clixon_event_loop() */ clixon_exit_set(1); /* checked in clixon_event_loop() */
} }
/*! wait for killed child /*! Wait for killed child
*
* primary use in case restconf daemon forked using process-control API * primary use in case restconf daemon forked using process-control API
* This may cause EINTR in eg select() in clixon_event_loop() which will be ignored * This may cause EINTR in eg select() in clixon_event_loop() which will be ignored
*/ */
static void static void
backend_sig_child(int arg) backend_sig_child(int arg)
{ {
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
clicon_sig_child_set(1); clicon_sig_child_set(1);
} }
/*! Create backend server socket and register callback /*! Create backend server socket and register callback
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval s Server socket file descriptor (see socket(2)) * @retval s Server socket file descriptor (see socket(2))
* @retval -1 Error * @retval -1 Error
*/ */
@ -278,7 +281,7 @@ xmldb_drop_priv(clicon_handle h,
* - uid is currently 0 (started as root) * - uid is currently 0 (started as root)
* - CLICON_BACKEND_USER is set * - CLICON_BACKEND_USER is set
* - CLICON_BACKEND_PRIVILEGES is not "none" * - CLICON_BACKEND_PRIVILEGES is not "none"
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] gid Group id (assume already known) * @param[in] gid Group id (assume already known)
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -425,7 +428,7 @@ backend_timer_setup(int fd,
struct timeval t; struct timeval t;
struct timeval t1 = {10, 0}; struct timeval t1 = {10, 0};
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
backend_client_print(h, stderr); backend_client_print(h, stderr);
@ -588,7 +591,7 @@ main(int argc,
* double syslogs until fork below. * double syslogs until fork below.
*/ */
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst); clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
yang_init(h); yang_init(h);
/* Find and read configfile */ /* Find and read configfile */
@ -1082,7 +1085,7 @@ main(int argc,
clicon_session_id_set(h, 1); clicon_session_id_set(h, 1);
#if 0 /* debug */ #if 0 /* debug */
/* Enable this to get prints of datastore and session status */ /* Enable this to get prints of datastore and session status */
if (0 && clicon_debug_get() && if (clixon_debug_get() &&
backend_timer_setup(0, h) < 0) backend_timer_setup(0, h) < 0)
goto done; goto done;
#endif #endif

View file

@ -68,7 +68,7 @@
* *
* The system 'state' should be the same as the contents of running_db * The system 'state' should be the same as the contents of running_db
* @param[in] cp Plugin handle * @param[in] cp Plugin handle
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db Name of datastore * @param[in] db Name of datastore
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -89,7 +89,7 @@ clixon_plugin_reset_one(clixon_plugin_t *cp,
if (fn(h, db) < 0) { if (fn(h, db) < 0) {
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (clicon_errno < 0) if (clicon_errno < 0)
clicon_log(LOG_WARNING, "%s: Internal error: Reset callback in plugin: %s returned -1 but did not make a clicon_err call", clicon_log(LOG_WARNING, "%s: Internal error: Reset callback in plugin: %s returned -1 but did not make a clicon_err call",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
@ -101,7 +101,7 @@ clixon_plugin_reset_one(clixon_plugin_t *cp,
done: done:
return retval; return retval;
} }
/*! Call all plugins reset callbacks /*! Call all plugins reset callbacks
* *
* The system 'state' should be the same as the contents of running_db * The system 'state' should be the same as the contents of running_db
@ -114,10 +114,10 @@ int
clixon_plugin_reset_all(clicon_handle h, clixon_plugin_reset_all(clicon_handle h,
char *db) char *db)
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
/* Loop through all plugins, call callbacks in each */ /* Loop through all plugins, call callbacks in each */
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_reset_one(cp, h, db) < 0) if (clixon_plugin_reset_one(cp, h, db) < 0)
@ -169,7 +169,7 @@ clixon_plugin_pre_daemon_one(clixon_plugin_t *cp,
* This point in time is after "start" and before * This point in time is after "start" and before
* before daemonization/fork, * before daemonization/fork,
* It is not called if backend is started in daemon mode. * It is not called if backend is started in daemon mode.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
@ -179,7 +179,7 @@ clixon_plugin_pre_daemon_all(clicon_handle h)
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
/* Loop through all plugins, call callbacks in each */ /* Loop through all plugins, call callbacks in each */
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_pre_daemon_one(cp, h) < 0) if (clixon_plugin_pre_daemon_one(cp, h) < 0)
@ -202,7 +202,7 @@ clixon_plugin_daemon_one(clixon_plugin_t *cp,
clicon_handle h) clicon_handle h)
{ {
int retval = -1; int retval = -1;
plgdaemon_t *fn; /* Daemonize plugin callback function */ plgdaemon_t *fn; /* Daemonize plugin callback function */
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_daemon) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_daemon) != NULL){
@ -212,7 +212,7 @@ clixon_plugin_daemon_one(clixon_plugin_t *cp,
if (fn(h) < 0) { if (fn(h) < 0) {
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (clicon_errno < 0) if (clicon_errno < 0)
clicon_log(LOG_WARNING, "%s: Internal error: Daemon callback in plugin: %s returned -1 but did not make a clicon_err call", clicon_log(LOG_WARNING, "%s: Internal error: Daemon callback in plugin: %s returned -1 but did not make a clicon_err call",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
@ -224,14 +224,14 @@ clixon_plugin_daemon_one(clixon_plugin_t *cp,
done: done:
return retval; return retval;
} }
/*! Call all plugins "post-" daemonize callbacks /*! Call all plugins "post-" daemonize callbacks
* *
* This point in time is after "start" and after "pre-daemon" and * This point in time is after "start" and after "pre-daemon" and
* after daemonization/fork, ie when * after daemonization/fork, ie when
* daemon is in the background but before dropped privileges. * daemon is in the background but before dropped privileges.
* In case of foreground mode (-F) it is still called but no fork has occured. * In case of foreground mode (-F) it is still called but no fork has occured.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @note Also called for non-background mode * @note Also called for non-background mode
@ -241,8 +241,8 @@ clixon_plugin_daemon_all(clicon_handle h)
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
/* Loop through all plugins, call callbacks in each */ /* Loop through all plugins, call callbacks in each */
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_daemon_one(cp, h) < 0) if (clixon_plugin_daemon_one(cp, h) < 0)
@ -289,7 +289,7 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
plgstatedata_t *fn; /* Plugin statedata fn */ plgstatedata_t *fn; /* Plugin statedata fn */
cxobj *x = NULL; cxobj *x = NULL;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
if ((x = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL) if ((x = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
goto done; goto done;
@ -299,7 +299,7 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
if (fn(h, nsc, xpath, x) < 0){ if (fn(h, nsc, xpath, x) < 0){
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (clicon_errno < 0) if (clicon_errno < 0)
clicon_log(LOG_WARNING, "%s: Internal error: State callback in plugin: %s returned -1 but did not make a clicon_err call", clicon_log(LOG_WARNING, "%s: Internal error: State callback in plugin: %s returned -1 but did not make a clicon_err call",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto fail; /* Dont quit here on user callbacks */ goto fail; /* Dont quit here on user callbacks */
@ -344,10 +344,10 @@ clixon_plugin_statedata_all(clicon_handle h,
int ret; int ret;
cxobj *x = NULL; cxobj *x = NULL;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
cbuf *cberr = NULL; cbuf *cberr = NULL;
cxobj *xerr = NULL; cxobj *xerr = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, &x)) < 0) if ((ret = clixon_plugin_statedata_one(cp, h, nsc, xpath, &x)) < 0)
goto done; goto done;
@ -373,7 +373,7 @@ clixon_plugin_statedata_all(clicon_handle h,
x = NULL; x = NULL;
continue; continue;
} }
clicon_debug_xml(CLIXON_DBG_DETAIL, x, "%s %s STATE:", __FUNCTION__, clixon_plugin_name_get(cp)); clixon_debug_xml(CLIXON_DBG_DETAIL, x, "%s %s STATE:", __FUNCTION__, clixon_plugin_name_get(cp));
/* XXX: ret == 0 invalid yang binding should be handled as internal error */ /* XXX: ret == 0 invalid yang binding should be handled as internal error */
if ((ret = xml_bind_yang(h, x, YB_MODULE, yspec, &xerr)) < 0) if ((ret = xml_bind_yang(h, x, YB_MODULE, yspec, &xerr)) < 0)
goto done; goto done;
@ -436,13 +436,13 @@ clixon_plugin_lockdb_one(clixon_plugin_t *cp,
int retval = -1; int retval = -1;
plglockdb_t *fn; /* Plugin statedata fn */ plglockdb_t *fn; /* Plugin statedata fn */
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_lockdb) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_lockdb) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (fn(h, db, lock, id) < 0) if (fn(h, db, lock, id) < 0)
goto done; goto done;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
} }
@ -470,12 +470,12 @@ clixon_plugin_lockdb_all(clicon_handle h,
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (clixon_plugin_lockdb_one(cp, h, db, lock, id) < 0) if (clixon_plugin_lockdb_one(cp, h, db, lock, id) < 0)
goto done; goto done;
} }
retval = 0; retval = 0;
done: done:
return retval; return retval;
@ -485,6 +485,8 @@ clixon_plugin_lockdb_all(clicon_handle h,
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xpath Registered XPath using canonical prefixes * @param[in] xpath Registered XPath using canonical prefixes
* @retval 1 OK
* @retval -1 Error
*/ */
int int
clixon_pagination_cb_call(clicon_handle h, clixon_pagination_cb_call(clicon_handle h,
@ -505,17 +507,19 @@ clixon_pagination_cb_call(clicon_handle h,
clicon_ptr_get(h, "pagination-entries", (void**)&htable); clicon_ptr_get(h, "pagination-entries", (void**)&htable);
if (htable && dispatcher_call_handlers(htable, h, xpath, &pd) < 0) if (htable && dispatcher_call_handlers(htable, h, xpath, &pd) < 0)
goto done; goto done;
retval = 1; retval = 1; // XXX 0?
done: done:
return retval; return retval;
} }
/*! Register a state data callback /*! Register a state data callback
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] fn Callback * @param[in] fn Callback
* @param[in] xpath Registered XPath using canonical prefixes * @param[in] xpath Registered XPath using canonical prefixes
* @param[in] arg Domain-specific argument to send to callback * @param[in] arg Domain-specific argument to send to callback
* @retval 0 OK
* @retval -1 Error
*/ */
int int
clixon_pagination_cb_register(clicon_handle h, clixon_pagination_cb_register(clicon_handle h,
@ -526,7 +530,7 @@ clixon_pagination_cb_register(clicon_handle h,
int retval = -1; int retval = -1;
dispatcher_definition x = {xpath, fn, arg}; dispatcher_definition x = {xpath, fn, arg};
dispatcher_entry_t *htable = NULL; dispatcher_entry_t *htable = NULL;
clicon_ptr_get(h, "pagination-entries", (void**)&htable); clicon_ptr_get(h, "pagination-entries", (void**)&htable);
if (dispatcher_register_handler(&htable, &x) < 0){ if (dispatcher_register_handler(&htable, &x) < 0){
clicon_err(OE_PLUGIN, errno, "dispatcher"); clicon_err(OE_PLUGIN, errno, "dispatcher");
@ -547,7 +551,7 @@ int
clixon_pagination_free(clicon_handle h) clixon_pagination_free(clicon_handle h)
{ {
dispatcher_entry_t *htable = NULL; dispatcher_entry_t *htable = NULL;
clicon_ptr_get(h, "pagination-entries", (void**)&htable); clicon_ptr_get(h, "pagination-entries", (void**)&htable);
if (htable) if (htable)
dispatcher_free(htable); dispatcher_free(htable);
@ -579,7 +583,7 @@ transaction_new(void)
* *
* @param[in] td Transaction data will be deallocated after the call * @param[in] td Transaction data will be deallocated after the call
*/ */
int int
transaction_free(transaction_data_t *td) transaction_free(transaction_data_t *td)
{ {
if (td->td_src) if (td->td_src)
@ -608,13 +612,13 @@ transaction_free(transaction_data_t *td)
*/ */
int int
plugin_transaction_begin_one(clixon_plugin_t *cp, plugin_transaction_begin_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_trans_begin) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_begin) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -623,7 +627,7 @@ plugin_transaction_begin_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
@ -639,19 +643,19 @@ plugin_transaction_begin_one(clixon_plugin_t *cp,
/*! Call transaction_begin() in all plugins before a validate/commit. /*! Call transaction_begin() in all plugins before a validate/commit.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK * @retval 0 OK
* @retval -1 Error: one of the plugin callbacks returned error * @retval -1 Error: one of the plugin callbacks returned error
*/ */
int int
plugin_transaction_begin_all(clicon_handle h, plugin_transaction_begin_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (plugin_transaction_begin_one(cp, h, td) < 0) if (plugin_transaction_begin_one(cp, h, td) < 0)
goto done; goto done;
@ -670,8 +674,8 @@ plugin_transaction_begin_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_validate_one(clixon_plugin_t *cp, plugin_transaction_validate_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
@ -686,7 +690,7 @@ plugin_transaction_validate_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
@ -701,13 +705,13 @@ plugin_transaction_validate_one(clixon_plugin_t *cp,
/*! Call transaction_validate callbacks in all backend plugins /*! Call transaction_validate callbacks in all backend plugins
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK. Validation succeeded in all plugins * @retval 0 OK. Validation succeeded in all plugins
* @retval -1 Error: one of the plugin callbacks returned validation fail * @retval -1 Error: one of the plugin callbacks returned validation fail
*/ */
int int
plugin_transaction_validate_all(clicon_handle h, plugin_transaction_validate_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
@ -732,14 +736,14 @@ plugin_transaction_validate_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_complete_one(clixon_plugin_t *cp, plugin_transaction_complete_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_trans_complete) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_complete) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -748,7 +752,7 @@ plugin_transaction_complete_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
@ -762,7 +766,7 @@ plugin_transaction_complete_one(clixon_plugin_t *cp,
/*! Call transaction_complete() in all plugins after validation (before commit) /*! Call transaction_complete() in all plugins after validation (before commit)
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK * @retval 0 OK
* @retval -1 Error: one of the plugin callbacks returned error * @retval -1 Error: one of the plugin callbacks returned error
@ -770,7 +774,7 @@ plugin_transaction_complete_one(clixon_plugin_t *cp,
* @note Rename to transaction_complete? * @note Rename to transaction_complete?
*/ */
int int
plugin_transaction_complete_all(clicon_handle h, plugin_transaction_complete_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
@ -796,21 +800,21 @@ plugin_transaction_complete_all(clicon_handle h,
* plugin 2, then the revert will be made in plugins 1 and 0. * plugin 2, then the revert will be made in plugins 1 and 0.
*/ */
static int static int
plugin_transaction_revert_all(clicon_handle h, plugin_transaction_revert_all(clicon_handle h,
transaction_data_t *td, transaction_data_t *td,
int nr) int nr)
{ {
int retval = 0; int retval = 0;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
trans_cb_t *fn; trans_cb_t *fn;
while ((cp = clixon_plugin_each_revert(h, cp, nr)) != NULL) { while ((cp = clixon_plugin_each_revert(h, cp, nr)) != NULL) {
if ((fn = clixon_plugin_api_get(cp)->ca_trans_revert) == NULL) if ((fn = clixon_plugin_api_get(cp)->ca_trans_revert) == NULL)
continue; continue;
if ((retval = fn(h, (transaction_data)td)) < 0){ if ((retval = fn(h, (transaction_data)td)) < 0){
clicon_log(LOG_NOTICE, "%s: Plugin '%s' trans_revert callback failed", clicon_log(LOG_NOTICE, "%s: Plugin '%s' trans_revert callback failed",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
break; break;
} }
} }
return retval; /* ignore errors */ return retval; /* ignore errors */
@ -827,13 +831,13 @@ plugin_transaction_revert_all(clicon_handle h,
*/ */
int int
plugin_transaction_commit_one(clixon_plugin_t *cp, plugin_transaction_commit_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -842,7 +846,7 @@ plugin_transaction_commit_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
@ -856,7 +860,7 @@ plugin_transaction_commit_one(clixon_plugin_t *cp,
/*! Call transaction_commit callbacks in all backend plugins /*! Call transaction_commit callbacks in all backend plugins
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK * @retval 0 OK
* @retval -1 Error: one of the plugin callbacks returned error * @retval -1 Error: one of the plugin callbacks returned error
@ -865,18 +869,18 @@ plugin_transaction_commit_one(clixon_plugin_t *cp,
* and in reverse order. * and in reverse order.
*/ */
int int
plugin_transaction_commit_all(clicon_handle h, plugin_transaction_commit_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
int i=0; int i=0;
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
i++; i++;
if (plugin_transaction_commit_one(cp, h, td) < 0){ if (plugin_transaction_commit_one(cp, h, td) < 0){
/* Make an effort to revert transaction */ /* Make an effort to revert transaction */
plugin_transaction_revert_all(h, td, i-1); plugin_transaction_revert_all(h, td, i-1);
goto done; goto done;
} }
} }
@ -894,14 +898,14 @@ plugin_transaction_commit_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_commit_done_one(clixon_plugin_t *cp, plugin_transaction_commit_done_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit_done) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit_done) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -910,7 +914,7 @@ plugin_transaction_commit_done_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
@ -924,14 +928,14 @@ plugin_transaction_commit_done_one(clixon_plugin_t *cp,
/*! Call transaction_commit_done callbacks in all backend plugins /*! Call transaction_commit_done callbacks in all backend plugins
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK * @retval 0 OK
* @retval -1 Error: one of the plugin callbacks returned error * @retval -1 Error: one of the plugin callbacks returned error
* @note no revert is done * @note no revert is done
*/ */
int int
plugin_transaction_commit_done_all(clicon_handle h, plugin_transaction_commit_done_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
@ -955,14 +959,14 @@ plugin_transaction_commit_done_all(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_end_one(clixon_plugin_t *cp, plugin_transaction_end_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_trans_end) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_end) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -971,7 +975,7 @@ plugin_transaction_end_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
@ -985,7 +989,7 @@ plugin_transaction_end_one(clixon_plugin_t *cp,
/*! Call transaction_end() in all plugins after a successful commit. /*! Call transaction_end() in all plugins after a successful commit.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -997,7 +1001,7 @@ plugin_transaction_end_all(clicon_handle h,
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (plugin_transaction_end_one(cp, h, td) < 0) if (plugin_transaction_end_one(cp, h, td) < 0)
goto done; goto done;
@ -1008,14 +1012,14 @@ plugin_transaction_end_all(clicon_handle h,
} }
int int
plugin_transaction_abort_one(clixon_plugin_t *cp, plugin_transaction_abort_one(clixon_plugin_t *cp,
clicon_handle h, clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
trans_cb_t *fn; trans_cb_t *fn;
void *wh = NULL; void *wh = NULL;
if ((fn = clixon_plugin_api_get(cp)->ca_trans_abort) != NULL){ if ((fn = clixon_plugin_api_get(cp)->ca_trans_abort) != NULL){
wh = NULL; wh = NULL;
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
@ -1024,7 +1028,7 @@ plugin_transaction_abort_one(clixon_plugin_t *cp,
if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0)
goto done; goto done;
if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error", clicon_log(LOG_NOTICE, "%s: Plugin '%s' callback does not make clicon_err call on error",
__FUNCTION__, clixon_plugin_name_get(cp)); __FUNCTION__, clixon_plugin_name_get(cp));
goto done; goto done;
} }
@ -1038,19 +1042,19 @@ plugin_transaction_abort_one(clixon_plugin_t *cp,
/*! Call transaction_abort() in all plugins after a failed validation/commit. /*! Call transaction_abort() in all plugins after a failed validation/commit.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] td Transaction data * @param[in] td Transaction data
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int int
plugin_transaction_abort_all(clicon_handle h, plugin_transaction_abort_all(clicon_handle h,
transaction_data_t *td) transaction_data_t *td)
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
while ((cp = clixon_plugin_each(h, cp)) != NULL) { while ((cp = clixon_plugin_each(h, cp)) != NULL) {
if (plugin_transaction_abort_one(cp, h, td) < 0) if (plugin_transaction_abort_one(cp, h, td) < 0)
; /* dont abort on error */ ; /* dont abort on error */

View file

@ -70,6 +70,8 @@
* is started. * is started.
* @param[in] h Clixon backend * @param[in] h Clixon backend
* @param[in] xt XML target * @param[in] xt XML target
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
restconf_pseudo_set_log(clicon_handle h, restconf_pseudo_set_log(clicon_handle h,
@ -78,8 +80,8 @@ restconf_pseudo_set_log(clicon_handle h,
int retval = -1; int retval = -1;
char **argv; char **argv;
int argc; int argc;
int i; int i;
char *log = NULL; char *log = NULL;
char *dbg = NULL; char *dbg = NULL;
cxobj *xb; cxobj *xb;
@ -138,6 +140,8 @@ restconf_pseudo_set_log(clicon_handle h,
* and insert it as a optimization to reading it from the backend. * and insert it as a optimization to reading it from the backend.
* @param[in] h Clixon backend * @param[in] h Clixon backend
* @param[in] xt XML target * @param[in] xt XML target
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
restconf_pseudo_set_inline(clicon_handle h, restconf_pseudo_set_inline(clicon_handle h,
@ -146,11 +150,11 @@ restconf_pseudo_set_inline(clicon_handle h,
int retval = -1; int retval = -1;
char **argv; char **argv;
int argc; int argc;
int i; int i;
cxobj *xrestconf; cxobj *xrestconf;
cbuf *cb = NULL; cbuf *cb = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (clixon_process_argv_get(h, RESTCONF_PROCESS, &argv, &argc) < 0) if (clixon_process_argv_get(h, RESTCONF_PROCESS, &argv, &argc) < 0)
goto done; goto done;
if ((xrestconf = xpath_first(xt, NULL, "restconf")) != NULL) if ((xrestconf = xpath_first(xt, NULL, "restconf")) != NULL)
@ -170,7 +174,7 @@ restconf_pseudo_set_inline(clicon_handle h,
clicon_err(OE_XML, errno, "stdup"); clicon_err(OE_XML, errno, "stdup");
goto done; goto done;
} }
clicon_debug(1, "%s str:%s", __FUNCTION__, str); clixon_debug(CLIXON_DBG_DEFAULT, "%s str:%s", __FUNCTION__, str);
if (argv[i+1]) if (argv[i+1])
free(argv[i+1]); free(argv[i+1]);
argv[i+1] = str; argv[i+1] = str;
@ -186,6 +190,7 @@ restconf_pseudo_set_inline(clicon_handle h,
} }
/*! Process rpc callback function /*! Process rpc callback function
*
* - if RPC op is start, if enable is true, start the service, if false, error or ignore it * - if RPC op is start, if enable is true, start the service, if false, error or ignore it
* - if RPC op is stop, stop the service * - if RPC op is stop, stop the service
* These rules give that if RPC op is start and enable is false -> change op to none * These rules give that if RPC op is start and enable is false -> change op to none
@ -197,14 +202,14 @@ restconf_rpc_wrapper(clicon_handle h,
{ {
int retval = -1; int retval = -1;
cxobj *xt = NULL; cxobj *xt = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
switch (*operation){ switch (*operation){
case PROC_OP_STOP: case PROC_OP_STOP:
/* if RPC op is stop, stop the service */ /* if RPC op is stop, stop the service */
break; break;
case PROC_OP_START: case PROC_OP_START:
/* RPC op is start & enable is true, then start the service, /* RPC op is start & enable is true, then start the service,
& enable is false, error or ignore it */ & enable is false, error or ignore it */
if (xmldb_get(h, "running", NULL, "/restconf", &xt) < 0) if (xmldb_get(h, "running", NULL, "/restconf", &xt) < 0)
goto done; goto done;
@ -235,7 +240,8 @@ restconf_rpc_wrapper(clicon_handle h,
} }
/*! Enable process-control of restconf daemon, ie start/stop restconf by registering restconf process /*! Enable process-control of restconf daemon, ie start/stop restconf by registering restconf process
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @note Could also look in clixon-restconf and start process if enable is true, but that needs to * @note Could also look in clixon-restconf and start process if enable is true, but that needs to
* be in start callback using a pseudo plugin. * be in start callback using a pseudo plugin.
* - Debug flag inheritance only works if backend is started with debug. If debug is set later * - Debug flag inheritance only works if backend is started with debug. If debug is set later
@ -277,24 +283,24 @@ restconf_pseudo_process_control(clicon_handle h)
cprintf(cb, "%s/clixon_restconf", dir0); cprintf(cb, "%s/clixon_restconf", dir0);
pgm = cbuf_get(cb); pgm = cbuf_get(cb);
if (stat(pgm, &fstat) == 0){ /* Sanity check: program exists */ if (stat(pgm, &fstat) == 0){ /* Sanity check: program exists */
clicon_debug(1, "Found %s", pgm); clixon_debug(CLIXON_DBG_DEFAULT, "Found %s", pgm);
found++; found++;
} }
else else
clicon_debug(1, "Not found: %s", pgm); clixon_debug(CLIXON_DBG_DEFAULT, "Not found: %s", pgm);
} }
if (!found && if (!found &&
(dir1 = CLIXON_CONFIG_SBINDIR) != NULL){ (dir1 = CLIXON_CONFIG_SBINDIR) != NULL){
cbuf_reset(cb); cbuf_reset(cb);
cprintf(cb, "%s/clixon_restconf", dir1); cprintf(cb, "%s/clixon_restconf", dir1);
pgm = cbuf_get(cb); pgm = cbuf_get(cb);
clicon_debug(1, "Looking for %s", pgm); clixon_debug(CLIXON_DBG_DEFAULT, "Looking for %s", pgm);
if (stat(pgm, &fstat) == 0){ /* Sanity check: program exists */ if (stat(pgm, &fstat) == 0){ /* Sanity check: program exists */
clicon_debug(1, "Found %s", pgm); clixon_debug(CLIXON_DBG_DEFAULT, "Found %s", pgm);
found++; found++;
} }
else else
clicon_debug(1, "Not found: %s", pgm); clixon_debug(CLIXON_DBG_DEFAULT, "Not found: %s", pgm);
} }
if (!found){ if (!found){
clicon_err(OE_RESTCONF, 0, "clixon_restconf not found in neither CLICON_RESTCONF_INSTALLDIR(%s) nor CLIXON_CONFIG_SBINDIR(%s). Try overriding with CLICON_RESTCONF_INSTALLDIR", clicon_err(OE_RESTCONF, 0, "clixon_restconf not found in neither CLICON_RESTCONF_INSTALLDIR(%s) nor CLIXON_CONFIG_SBINDIR(%s). Try overriding with CLICON_RESTCONF_INSTALLDIR",
@ -343,7 +349,7 @@ restconf_pseudo_process_validate(clicon_handle h,
int retval = -1; int retval = -1;
cxobj *xtarget; cxobj *xtarget;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
xtarget = transaction_target(td); xtarget = transaction_target(td);
/* If ssl-enable is true and (at least a) socket has ssl, /* If ssl-enable is true and (at least a) socket has ssl,
* then server-cert-path and server-key-path must exist */ * then server-cert-path and server-key-path must exist */
@ -374,8 +380,8 @@ restconf_pseudo_process_commit(clicon_handle h,
cxobj *xsource; cxobj *xsource;
cxobj *cx; cxobj *cx;
int enabled = 0; int enabled = 0;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
xtarget = transaction_target(td); xtarget = transaction_target(td);
xsource = transaction_src(td); xsource = transaction_src(td);
if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL) if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL)
@ -425,13 +431,16 @@ restconf_pseudo_process_commit(clicon_handle h,
} }
/*! Register start/stop restconf RPC and create pseudo-plugin to monitor enable flag /*! Register start/stop restconf RPC and create pseudo-plugin to monitor enable flag
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/ */
int int
backend_plugin_restconf_register(clicon_handle h, backend_plugin_restconf_register(clicon_handle h,
yang_stmt *yspec) yang_stmt *yspec)
{ {
int retval = -1; int retval = -1;
clixon_plugin_t *cp = NULL; clixon_plugin_t *cp = NULL;
if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0) if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0)

View file

@ -78,7 +78,7 @@
/*! Open an INET stream socket and bind it to a file descriptor /*! Open an INET stream socket and bind it to a file descriptor
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] dst IPv4 address (see inet_pton(3)) * @param[in] dst IPv4 address (see inet_pton(3))
* @retval s Socket file descriptor (see socket(2)) * @retval s Socket file descriptor (see socket(2))
* @retval -1 Error * @retval -1 Error
@ -111,7 +111,7 @@ config_socket_init_ipv4(clicon_handle h,
clicon_err(OE_UNIX, errno, "bind"); clicon_err(OE_UNIX, errno, "bind");
goto err; goto err;
} }
clicon_debug(1, "Listen on server socket at %s:%hu", dst, port); clixon_debug(CLIXON_DBG_DEFAULT, "Listen on server socket at %s:%hu", dst, port);
if (listen(s, 5) < 0){ if (listen(s, 5) < 0){
clicon_err(OE_UNIX, errno, "listen"); clicon_err(OE_UNIX, errno, "listen");
goto err; goto err;
@ -126,7 +126,7 @@ config_socket_init_ipv4(clicon_handle h,
* *
* The socket is accessed via CLICON_SOCK option, has 770 permissions * The socket is accessed via CLICON_SOCK option, has 770 permissions
* and group according to CLICON_SOCK_GROUP option. * and group according to CLICON_SOCK_GROUP option.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] sock Unix file-system path * @param[in] sock Unix file-system path
* @retval s Socket file descriptor (see socket(2)) * @retval s Socket file descriptor (see socket(2))
* @retval -1 Error * @retval -1 Error
@ -154,7 +154,7 @@ config_socket_init_unix(clicon_handle h,
if (group_name2gid(config_group, &gid) < 0) if (group_name2gid(config_group, &gid) < 0)
return -1; return -1;
#if 0 #if 0
if (gid == 0) if (gid == 0)
clicon_log(LOG_WARNING, "%s: No such group: %s", __FUNCTION__, config_group); clicon_log(LOG_WARNING, "%s: No such group: %s", __FUNCTION__, config_group);
#endif #endif
/* create unix socket */ /* create unix socket */
@ -169,16 +169,16 @@ config_socket_init_unix(clicon_handle h,
old_mask = umask(S_IRWXO | S_IXGRP | S_IXUSR); old_mask = umask(S_IRWXO | S_IXGRP | S_IXUSR);
if (bind(s, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0){ if (bind(s, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0){
clicon_err(OE_UNIX, errno, "bind"); clicon_err(OE_UNIX, errno, "bind");
umask(old_mask); umask(old_mask);
goto err; goto err;
} }
umask(old_mask); umask(old_mask);
/* change socket path file group */ /* change socket path file group */
if (lchown(sock, -1, gid) < 0){ if (lchown(sock, -1, gid) < 0){
clicon_err(OE_UNIX, errno, "lchown(%s, %s)", sock, config_group); clicon_err(OE_UNIX, errno, "lchown(%s, %s)", sock, config_group);
goto err; goto err;
} }
clicon_debug(1, "Listen on server socket at %s", addr.sun_path); clixon_debug(CLIXON_DBG_DEFAULT, "Listen on server socket at %s", addr.sun_path);
if (listen(s, 5) < 0){ if (listen(s, 5) < 0){
clicon_err(OE_UNIX, errno, "listen"); clicon_err(OE_UNIX, errno, "listen");
goto err; goto err;
@ -190,8 +190,8 @@ config_socket_init_unix(clicon_handle h,
} }
/*! Open backend socket, the one clients send requests to, either ip or unix /*! Open backend socket, the one clients send requests to, either ip or unix
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval s Socket file descriptor (see socket(2)) * @retval s Socket file descriptor (see socket(2))
* @retval -1 Error * @retval -1 Error
*/ */
@ -220,12 +220,15 @@ backend_socket_init(clicon_handle h)
} }
/*! Accept new socket client /*! Accept new socket client
*
* @param[in] fd Socket (unix or ip) * @param[in] fd Socket (unix or ip)
* @param[in] arg typecast clicon_handle * @param[in] arg typecast clicon_handle
* @retval 0 OK
* @retval -1 Error
*/ */
int int
backend_accept_client(int fd, backend_accept_client(int fd,
void *arg) void *arg)
{ {
int retval = -1; int retval = -1;
clicon_handle h = (clicon_handle)arg; clicon_handle h = (clicon_handle)arg;
@ -242,7 +245,7 @@ backend_accept_client(int fd,
uid_t guid; uid_t guid;
#endif #endif
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
len = sizeof(from); len = sizeof(from);
if ((s = accept(fd, &from, &len)) < 0){ if ((s = accept(fd, &from, &len)) < 0){
clicon_err(OE_UNIX, errno, "accept"); clicon_err(OE_UNIX, errno, "accept");
@ -251,7 +254,7 @@ backend_accept_client(int fd,
if ((ce = backend_client_add(h, &from)) == NULL) if ((ce = backend_client_add(h, &from)) == NULL)
goto done; goto done;
/* /*
* Get credentials of connected peer - only for unix socket * Get credentials of connected peer - only for unix socket
*/ */
switch (from.sa_family){ switch (from.sa_family){
@ -281,7 +284,7 @@ backend_accept_client(int fd,
name = NULL; name = NULL;
} }
break; break;
case AF_INET: case AF_INET:
break; break;
case AF_INET6: case AF_INET6:
default: default:

View file

@ -41,7 +41,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int backend_socket_init(clicon_handle h); int backend_socket_init(clicon_handle h);
int backend_accept_client(int fd, void *arg); int backend_accept_client(int fd, void *arg);

View file

@ -85,7 +85,7 @@ db_merge(clicon_handle h,
{ {
int retval = -1; int retval = -1;
cxobj *xt = NULL; cxobj *xt = NULL;
/* Get data as xml from db1 */ /* Get data as xml from db1 */
if (xmldb_get0(h, (char*)db1, YB_MODULE, NULL, NULL, 1, WITHDEFAULTS_EXPLICIT, &xt, NULL, NULL) < 0) if (xmldb_get0(h, (char*)db1, YB_MODULE, NULL, NULL, 1, WITHDEFAULTS_EXPLICIT, &xt, NULL, NULL) < 0)
goto done; goto done;
@ -138,7 +138,7 @@ startup_mode_startup(clicon_handle h,
int ret = 0; int ret = 0;
int rollback_exists; int rollback_exists;
yang_stmt *yspec = clicon_dbspec_yang(h); yang_stmt *yspec = clicon_dbspec_yang(h);
if (strcmp(db, "running")==0){ if (strcmp(db, "running")==0){
clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db); clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db);
goto done; goto done;
@ -273,8 +273,6 @@ load_extraxml(clicon_handle h,
* @retval 1 OK * @retval 1 OK
* @retval 0 Validation failed * @retval 0 Validation failed
* @retval -1 Error * @retval -1 Error
running -----------------+----+------> running -----------------+----+------>
reset loadfile / merge reset loadfile / merge
@ -289,14 +287,14 @@ startup_extraxml(clicon_handle h,
int retval = -1; int retval = -1;
char *tmp_db = "tmp"; char *tmp_db = "tmp";
int ret; int ret;
cxobj *xt0 = NULL; cxobj *xt0 = NULL;
cxobj *xt = NULL; cxobj *xt = NULL;
/* Clear tmp db */ /* Clear tmp db */
if (xmldb_db_reset(h, tmp_db) < 0) if (xmldb_db_reset(h, tmp_db) < 0)
goto done; goto done;
/* Application may define extra xml in its reset function */ /* Application may define extra xml in its reset function */
if (clixon_plugin_reset_all(h, tmp_db) < 0) if (clixon_plugin_reset_all(h, tmp_db) < 0)
goto done; goto done;
/* Extra XML can also be added via file */ /* Extra XML can also be added via file */
if (file){ if (file){
@ -306,7 +304,7 @@ startup_extraxml(clicon_handle h,
if (ret == 0) if (ret == 0)
goto fail; goto fail;
} }
/* /*
* Check if tmp db is empty. * Check if tmp db is empty.
* It should be empty if extra-xml is null and reset plugins did nothing * It should be empty if extra-xml is null and reset plugins did nothing
* then skip validation. * then skip validation.
@ -325,7 +323,7 @@ startup_extraxml(clicon_handle h,
goto done; goto done;
if (ret == 0) if (ret == 0)
goto fail; goto fail;
if (xt==NULL || xml_child_nr(xt)==0) if (xt==NULL || xml_child_nr(xt)==0)
goto ok; goto ok;
/* Merge tmp into running (no commit) */ /* Merge tmp into running (no commit) */
if ((ret = db_merge(h, tmp_db, "running", cbret)) < 0) if ((ret = db_merge(h, tmp_db, "running", cbret)) < 0)
@ -338,7 +336,7 @@ startup_extraxml(clicon_handle h,
if (xt0) if (xt0)
xml_free(xt0); xml_free(xt0);
xmldb_get0_free(h, &xt); xmldb_get0_free(h, &xt);
if (xmldb_delete(h, tmp_db) != 0 && errno != ENOENT) if (xmldb_delete(h, tmp_db) != 0 && errno != ENOENT)
return -1; return -1;
return retval; return retval;
fail: fail:
@ -360,10 +358,10 @@ startup_module_state(clicon_handle h,
int retval = -1; int retval = -1;
cxobj *x = NULL; cxobj *x = NULL;
int ret; int ret;
if (!clicon_option_bool(h, "CLICON_XMLDB_MODSTATE")) if (!clicon_option_bool(h, "CLICON_XMLDB_MODSTATE"))
goto ok; goto ok;
/* Set up cache /* Set up cache
* Now, access brief module cache with clicon_modst_cache_get(h, 1) */ * Now, access brief module cache with clicon_modst_cache_get(h, 1) */
if ((ret = yang_modules_state_get(h, yspec, NULL, NULL, 1, &x)) < 0) if ((ret = yang_modules_state_get(h, yspec, NULL, NULL, 1, &x)) < 0)
goto done; goto done;

View file

@ -41,7 +41,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int startup_mode_startup(clicon_handle h, char *db, cbuf *cbret); int startup_mode_startup(clicon_handle h, char *db, cbuf *cbret);
int startup_extraxml(clicon_handle h, char *file, cbuf *cbret); int startup_extraxml(clicon_handle h, char *file, cbuf *cbret);
int startup_module_state(clicon_handle h, yang_stmt *yspec); int startup_module_state(clicon_handle h, yang_stmt *yspec);

View file

@ -78,6 +78,7 @@
* entries in the struct below. * entries in the struct below.
*/ */
/*! Backend specific handle added to header CLICON handle /*! Backend specific handle added to header CLICON handle
*
* This file should only contain access functions for the _specific_ * This file should only contain access functions for the _specific_
* entries in the struct below. * entries in the struct below.
* @note The top part must be equivalent to struct clicon_handle in clixon_handle.c * @note The top part must be equivalent to struct clicon_handle in clixon_handle.c
@ -89,7 +90,7 @@ struct backend_handle {
clicon_hash_t *bh_data; /* internal clicon data (HDR) */ clicon_hash_t *bh_data; /* internal clicon data (HDR) */
clicon_hash_t *ch_db_elmnt; /* xml datastore element cache data */ clicon_hash_t *ch_db_elmnt; /* xml datastore element cache data */
event_stream_t *bh_stream; /* notification streams, see clixon_stream.[ch] */ event_stream_t *bh_stream; /* notification streams, see clixon_stream.[ch] */
/* ------ end of common handle ------ */ /* ------ end of common handle ------ */
struct client_entry *bh_ce_list; /* The client list */ struct client_entry *bh_ce_list; /* The client list */
int bh_ce_nr; /* Number of clients, just increment */ int bh_ce_nr; /* Number of clients, just increment */
@ -104,7 +105,8 @@ backend_handle_init(void)
} }
/*! Deallocates a backend handle, including all client structs /*! Deallocates a backend handle, including all client structs
* @Note: handle 'h' cannot be used in calls after this *
* @note: handle 'h' cannot be used in calls after this
* @see backend_client_rm * @see backend_client_rm
*/ */
int int
@ -125,13 +127,14 @@ backend_handle_exit(clicon_handle h)
} }
/*! Add new client, typically frontend such as cli, netconf, restconf /*! Add new client, typically frontend such as cli, netconf, restconf
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] addr Address of client * @param[in] addr Address of client
* @retval ce Client entry * @retval ce Client entry
* @retval NULL Error * @retval NULL Error
*/ */
struct client_entry * struct client_entry *
backend_client_add(clicon_handle h, backend_client_add(clicon_handle h,
struct sockaddr *addr) struct sockaddr *addr)
{ {
struct backend_handle *bh = handle(h); struct backend_handle *bh = handle(h);
@ -158,7 +161,8 @@ backend_client_add(clicon_handle h,
} }
/*! Return client list /*! Return client list
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval ce_list Client entry list (all sessions) * @retval ce_list Client entry list (all sessions)
*/ */
struct client_entry * struct client_entry *
@ -170,7 +174,8 @@ backend_client_list(clicon_handle h)
} }
/*! Actually remove client from client list /*! Actually remove client from client list
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] ce Client handle * @param[in] ce Client handle
* @see backend_client_rm which is more high-level * @see backend_client_rm which is more high-level
*/ */
@ -201,7 +206,8 @@ backend_client_delete(clicon_handle h,
} }
/*! Debug print backend clients /*! Debug print backend clients
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] f UNIX output stream * @param[in] f UNIX output stream
*/ */
int int

View file

@ -43,6 +43,7 @@
*/ */
/*! Transaction data describing a system transition from a src to target state /*! Transaction data describing a system transition from a src to target state
*
* Clixon internal, presented as void* to app's callback in the 'transaction_data' * Clixon internal, presented as void* to app's callback in the 'transaction_data'
* type in clicon_backend_api.h * type in clicon_backend_api.h
* The struct contains source and target XML tree (e.g. candidate/running) * The struct contains source and target XML tree (e.g. candidate/running)
@ -68,6 +69,7 @@ typedef struct {
} transaction_data_t; } transaction_data_t;
/*! Pagination userdata /*! Pagination userdata
*
* Pagination can use a lock/transaction mechanism * Pagination can use a lock/transaction mechanism
* If locking is not used, the plugin cannot expect more pagination calls, and no state or * If locking is not used, the plugin cannot expect more pagination calls, and no state or
* caching should be used * caching should be used
@ -104,7 +106,7 @@ int clixon_plugin_lockdb_all(clicon_handle h, char *db, int lock, int id);
int clixon_pagination_cb_register(clicon_handle h, handler_function fn, char *path, void *arg); int clixon_pagination_cb_register(clicon_handle h, handler_function fn, char *path, void *arg);
int clixon_pagination_cb_call(clicon_handle h, char *xpath, int locked, int clixon_pagination_cb_call(clicon_handle h, char *xpath, int locked,
uint32_t offset, uint32_t limit, uint32_t offset, uint32_t limit,
cxobj *xstate); cxobj *xstate);
int clixon_pagination_free(clicon_handle h); int clixon_pagination_free(clicon_handle h);

View file

@ -69,6 +69,7 @@
* would give running in source and 'a' and candidate in 'target'. * would give running in source and 'a' and candidate in 'target'.
*/ */
/*! Get transaction id /*! Get transaction id
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval id transaction id * @retval id transaction id
*/ */
@ -79,6 +80,7 @@ transaction_id(transaction_data td)
} }
/*! Get plugin/application specific callback argument /*! Get plugin/application specific callback argument
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval arg callback argument * @retval arg callback argument
*/ */
@ -89,6 +91,7 @@ transaction_arg(transaction_data td)
} }
/*! Set plugin/application specific callback argument /*! Set plugin/application specific callback argument
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @param[in] arg callback argument * @param[in] arg callback argument
*/ */
@ -101,6 +104,7 @@ transaction_arg_set(transaction_data td,
} }
/*! Get source database xml tree /*! Get source database xml tree
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval src source xml tree containing original state * @retval src source xml tree containing original state
*/ */
@ -111,6 +115,7 @@ transaction_src(transaction_data td)
} }
/*! Get target database xml tree /*! Get target database xml tree
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval xml target xml tree containing wanted state * @retval xml target xml tree containing wanted state
*/ */
@ -121,6 +126,7 @@ transaction_target(transaction_data td)
} }
/*! Get delete xml vector, ie vector of xml nodes that are deleted src->target /*! Get delete xml vector, ie vector of xml nodes that are deleted src->target
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval vec Vector of xml nodes * @retval vec Vector of xml nodes
*/ */
@ -131,6 +137,7 @@ transaction_dvec(transaction_data td)
} }
/*! Get length of delete xml vector /*! Get length of delete xml vector
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval len Length of vector of xml nodes * @retval len Length of vector of xml nodes
* @see transaction_dvec * @see transaction_dvec
@ -142,6 +149,7 @@ transaction_dlen(transaction_data td)
} }
/*! Get add xml vector, ie vector of xml nodes that are added src->target /*! Get add xml vector, ie vector of xml nodes that are added src->target
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval vec Vector of xml nodes * @retval vec Vector of xml nodes
*/ */
@ -152,6 +160,7 @@ transaction_avec(transaction_data td)
} }
/*! Get length of add xml vector /*! Get length of add xml vector
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval len Length of vector of xml nodes * @retval len Length of vector of xml nodes
* @see transaction_avec * @see transaction_avec
@ -163,6 +172,7 @@ transaction_alen(transaction_data td)
} }
/*! Get source changed xml vector, ie vector of xml nodes that changed /*! Get source changed xml vector, ie vector of xml nodes that changed
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval vec Vector of xml nodes * @retval vec Vector of xml nodes
* These are only nodes of type LEAF. * These are only nodes of type LEAF.
@ -177,6 +187,7 @@ transaction_scvec(transaction_data td)
} }
/*! Get target changed xml vector, ie vector of xml nodes that changed /*! Get target changed xml vector, ie vector of xml nodes that changed
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval vec Vector of xml nodes * @retval vec Vector of xml nodes
* These are only nodes of type LEAF. * These are only nodes of type LEAF.
@ -191,6 +202,7 @@ transaction_tcvec(transaction_data td)
} }
/*! Get length of changed xml vector /*! Get length of changed xml vector
*
* @param[in] td transaction_data * @param[in] td transaction_data
* @retval len Length of vector of xml nodes * @retval len Length of vector of xml nodes
* This is the length of both the src change vector and the target change vector * This is the length of both the src change vector and the target change vector
@ -211,8 +223,8 @@ int
transaction_print(FILE *f, transaction_print(FILE *f,
transaction_data th) transaction_data th)
{ {
cxobj *xn; cxobj *xn;
int i; int i;
transaction_data_t *td; transaction_data_t *td;
td = (transaction_data_t *)th; td = (transaction_data_t *)th;
@ -267,7 +279,7 @@ transaction_dbg(clicon_handle h,
goto done; goto done;
} }
if (i) if (i)
clicon_debug(dbglevel, "%s %" PRIu64 " %s del: %s", clixon_debug(dbglevel, "%s %" PRIu64 " %s del: %s",
__FUNCTION__, td->td_id, msg, cbuf_get(cb)); __FUNCTION__, td->td_id, msg, cbuf_get(cb));
cbuf_reset(cb); cbuf_reset(cb);
for (i=0; i<td->td_alen; i++){ for (i=0; i<td->td_alen; i++){
@ -276,7 +288,7 @@ transaction_dbg(clicon_handle h,
goto done; goto done;
} }
if (i) if (i)
clicon_debug(dbglevel, "%s %" PRIu64 " %s add: %s", clixon_debug(dbglevel, "%s %" PRIu64 " %s add: %s",
__FUNCTION__, td->td_id, msg, cbuf_get(cb)); __FUNCTION__, td->td_id, msg, cbuf_get(cb));
cbuf_reset(cb); cbuf_reset(cb);
for (i=0; i<td->td_clen; i++){ for (i=0; i<td->td_clen; i++){
@ -290,7 +302,7 @@ transaction_dbg(clicon_handle h,
goto done; goto done;
} }
if (i) if (i)
clicon_debug(dbglevel, "%s %" PRIu64 " %s change: %s", clixon_debug(dbglevel, "%s %" PRIu64 " %s change: %s",
__FUNCTION__, td->td_id, msg, cbuf_get(cb)); __FUNCTION__, td->td_id, msg, cbuf_get(cb));
done: done:
if (cb) if (cb)
@ -299,7 +311,6 @@ transaction_dbg(clicon_handle h,
} }
/*! Log a transaction /*! Log a transaction
*
*/ */
int int
transaction_log(clicon_handle h, transaction_log(clicon_handle h,

View file

@ -69,9 +69,9 @@ int transaction_log(clicon_handle h, transaction_data th, int level, const char
/* Pagination callbacks /* Pagination callbacks
* @see pagination_data_t internal structure * @see pagination_data_t internal structure
*/ */
uint32_t pagination_offset(pagination_data pd); uint32_t pagination_offset(pagination_data pd);
uint32_t pagination_limit(pagination_data pd); uint32_t pagination_limit(pagination_data pd);
int pagination_locked(pagination_data pd); int pagination_locked(pagination_data pd);
cxobj *pagination_xstate(pagination_data pd); cxobj *pagination_xstate(pagination_data pd);
#endif /* _CLIXON_BACKEND_TRANSACTION_H_ */ #endif /* _CLIXON_BACKEND_TRANSACTION_H_ */

View file

@ -86,7 +86,7 @@ co2apipath(cg_obj *co)
cg_callback *cb; cg_callback *cb;
cvec *cvv; cvec *cvv;
cg_var *cv; cg_var *cv;
if (co == NULL) if (co == NULL)
return NULL; return NULL;
if ((cb = co->co_callbacks) == NULL) if ((cb = co->co_callbacks) == NULL)
@ -121,7 +121,7 @@ cli_auto_edit(clicon_handle h,
char *api_path_fmt; /* xml key format */ char *api_path_fmt; /* xml key format */
char *api_path = NULL; char *api_path = NULL;
char *treename; char *treename;
pt_head *ph; pt_head *ph;
cg_obj *co; cg_obj *co;
cg_obj *coorig; cg_obj *coorig;
cvec *cvv2 = NULL; /* cvv2 = cvv0 + cvv1 */ cvec *cvv2 = NULL; /* cvv2 = cvv0 + cvv1 */
@ -137,7 +137,7 @@ cli_auto_edit(clicon_handle h,
str = cv_string_get(cvec_i(argv, argc++)); str = cv_string_get(cvec_i(argv, argc++));
if (str && strncmp(str, "mtpoint:", strlen("mtpoint:")) == 0){ if (str && strncmp(str, "mtpoint:", strlen("mtpoint:")) == 0){
mtpoint = str + strlen("mtpoint:"); mtpoint = str + strlen("mtpoint:");
clicon_debug(1, "%s mtpoint:%s", __FUNCTION__, mtpoint); clixon_debug(CLIXON_DBG_DEFAULT, "%s mtpoint:%s", __FUNCTION__, mtpoint);
treename = cv_string_get(cvec_i(argv, argc++)); treename = cv_string_get(cvec_i(argv, argc++));
} }
else else
@ -181,7 +181,7 @@ cli_auto_edit(clicon_handle h,
char *mtpoint2; char *mtpoint2;
if ((mtpoint2 = strdup(mtpoint)) == NULL){ if ((mtpoint2 = strdup(mtpoint)) == NULL){
clicon_err(OE_UNIX, errno, "strdup"); clicon_err(OE_UNIX, errno, "strdup");
goto done; goto done;
} }
if (clicon_data_set(h, "cli-edit-mtpoint", mtpoint2) < 0) if (clicon_data_set(h, "cli-edit-mtpoint", mtpoint2) < 0)
goto done; goto done;
@ -205,9 +205,12 @@ cli_auto_edit(clicon_handle h,
} }
/*! CLI callback: Working point tree up to parent /*! CLI callback: Working point tree up to parent
*
* @param[in] h CLICON handle * @param[in] h CLICON handle
* @param[in] cvv Vector of variables from CLIgen command-line * @param[in] cvv Vector of variables from CLIgen command-line
* @param[in] argv Vector of user-supplied keywords * @param[in] argv Vector of user-supplied keywords
* @retval 0 OK
* @retval -1 Error
* Format of argv: * Format of argv:
* <treename> Name of generated cligen parse-tree, eg "datamodel" * <treename> Name of generated cligen parse-tree, eg "datamodel"
*/ */
@ -231,7 +234,7 @@ cli_auto_up(clicon_handle h,
int j; int j;
size_t len; size_t len;
cvec *cvv_filter = NULL; cvec *cvv_filter = NULL;
if (cvec_len(argv) != 1){ if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, EINVAL, "Usage: %s(<treename>)", __FUNCTION__); clicon_err(OE_PLUGIN, EINVAL, "Usage: %s(<treename>)", __FUNCTION__);
goto done; goto done;
@ -283,7 +286,7 @@ cli_auto_up(clicon_handle h,
cvv1 = cvec_new(0); cvv1 = cvec_new(0);
for (i=0; i<cvec_len(cvv0)-j; i++){ for (i=0; i<cvec_len(cvv0)-j; i++){
cv = cvec_i(cvv0, i); cv = cvec_i(cvv0, i);
cvec_append_var(cvv1, cv); cvec_append_var(cvv1, cv);
} }
/* get api-path and xpath */ /* get api-path and xpath */
if (api_path_fmt2api_path(api_path_fmt1, cvv1, &api_path, NULL) < 0) if (api_path_fmt2api_path(api_path_fmt1, cvv1, &api_path, NULL) < 0)
@ -300,9 +303,12 @@ cli_auto_up(clicon_handle h,
} }
/*! CLI callback: Working point tree reset to top level /*! CLI callback: Working point tree reset to top level
*
* @param[in] h CLICON handle * @param[in] h CLICON handle
* @param[in] cvv Vector of variables from CLIgen command-line * @param[in] cvv Vector of variables from CLIgen command-line
* @param[in] argv Vector of user-supplied keywords * @param[in] argv Vector of user-supplied keywords
* @retval 0 OK
* @retval -1 Error
* Format of argv: * Format of argv:
* <treename> Name of generated cligen parse-tree, eg "datamodel" * <treename> Name of generated cligen parse-tree, eg "datamodel"
*/ */
@ -315,7 +321,7 @@ cli_auto_top(clicon_handle h,
cg_var *cv; cg_var *cv;
char *treename; char *treename;
pt_head *ph; pt_head *ph;
cv = cvec_i(argv, 0); cv = cvec_i(argv, 0);
treename = cv_string_get(cv); treename = cv_string_get(cv);
if ((ph = cligen_ph_find(cli_cligen(h), treename)) == NULL){ if ((ph = cligen_ph_find(cli_cligen(h), treename)) == NULL){
@ -333,20 +339,23 @@ cli_auto_top(clicon_handle h,
} }
/*! CLI callback: set auto db item /*! CLI callback: set auto db item
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv Vector. First element xml key format string, eg "/aaa/%s" * @param[in] argv Vector. First element xml key format string, eg "/aaa/%s"
* @retval 0 OK
* @retval -1 Error
* Format of argv: * Format of argv:
* <api-path-fmt> Generated * <api-path-fmt> Generated
*/ */
int int
cli_auto_set(clicon_handle h, cli_auto_set(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
cvec *cvv2 = NULL; cvec *cvv2 = NULL;
cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv); cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv);
if (cli_dbxml(h, cvv2, argv, OP_REPLACE, NULL) < 0) if (cli_dbxml(h, cvv2, argv, OP_REPLACE, NULL) < 0)
goto done; goto done;
@ -358,18 +367,21 @@ cli_auto_set(clicon_handle h,
} }
/*! Merge datastore xml entry /*! Merge datastore xml entry
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv Vector. First element xml key format string, eg "/aaa/%s" * @param[in] argv Vector. First element xml key format string, eg "/aaa/%s"
* @retval 0 OK
* @retval -1 Error
*/ */
int int
cli_auto_merge(clicon_handle h, cli_auto_merge(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
cvec *cvv2 = NULL; cvec *cvv2 = NULL;
cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv); cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv);
if (cli_dbxml(h, cvv2, argv, OP_MERGE, NULL) < 0) if (cli_dbxml(h, cvv2, argv, OP_MERGE, NULL) < 0)
goto done; goto done;
@ -381,18 +393,21 @@ cli_auto_merge(clicon_handle h,
} }
/*! Create datastore xml entry /*! Create datastore xml entry
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv Vector. First element xml key format string, eg "/aaa/%s" * @param[in] argv Vector. First element xml key format string, eg "/aaa/%s"
* @retval 0 OK
* @retval -1 Error
*/ */
int int
cli_auto_create(clicon_handle h, cli_auto_create(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
cvec *cvv2 = NULL; cvec *cvv2 = NULL;
cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv); cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv);
if (cli_dbxml(h, cvv2, argv, OP_CREATE, NULL) < 0) if (cli_dbxml(h, cvv2, argv, OP_CREATE, NULL) < 0)
goto done; goto done;
@ -404,18 +419,21 @@ cli_auto_create(clicon_handle h,
} }
/*! Delete datastore xml /*! Delete datastore xml
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv Vector. First element xml key format string, eg "/aaa/%s" * @param[in] argv Vector. First element xml key format string, eg "/aaa/%s"
* @retval 0 OK
* @retval -1 Error
*/ */
int int
cli_auto_del(clicon_handle h, cli_auto_del(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
cvec *cvv2 = NULL; cvec *cvv2 = NULL;
cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv); cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv);
if (cli_dbxml(h, cvv2, argv, OP_REMOVE, NULL) < 0) if (cli_dbxml(h, cvv2, argv, OP_REMOVE, NULL) < 0)
goto done; goto done;
@ -438,7 +456,6 @@ struct findpt_arg{
* @param[in] arg Argument, cast to application-specific info * @param[in] arg Argument, cast to application-specific info
* @retval 1 OK and return (abort iteration) * @retval 1 OK and return (abort iteration)
* @retval 0 OK and continue * @retval 0 OK and continue
* @retval -1 Error: break and return
*/ */
static int static int
cli_auto_findpt(cg_obj *co, cli_auto_findpt(cg_obj *co,
@ -456,9 +473,12 @@ cli_auto_findpt(cg_obj *co,
} }
/*! Enter edit mode /*! Enter edit mode
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv Vector of args to function in command. * @param[in] argv Vector of args to function in command.
* @retval 0 OK
* @retval -1 Error
* Format of argv: * Format of argv:
* <api_path_fmt> Generated API PATH FORMAT (print-like for variables) * <api_path_fmt> Generated API PATH FORMAT (print-like for variables)
* <vars>* List of static variables that can be used as values for api_path_fmt * <vars>* List of static variables that can be used as values for api_path_fmt
@ -471,7 +491,7 @@ cli_auto_findpt(cg_obj *co,
* api_path: /a/b=42,99/c * api_path: /a/b=42,99/c
* @see cli_auto_edit * @see cli_auto_edit
*/ */
int int
cli_auto_sub_enter(clicon_handle h, cli_auto_sub_enter(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
@ -486,7 +506,7 @@ cli_auto_sub_enter(clicon_handle h,
cg_var *cv = NULL; cg_var *cv = NULL;
pt_head *ph; pt_head *ph;
struct findpt_arg fa = {0,}; struct findpt_arg fa = {0,};
if (cvec_len(argv) < 2){ if (cvec_len(argv) < 2){
clicon_err(OE_PLUGIN, EINVAL, "Usage: %s(<tree> <api_path_fmt> (,vars)*)", __FUNCTION__); clicon_err(OE_PLUGIN, EINVAL, "Usage: %s(<tree> <api_path_fmt> (,vars)*)", __FUNCTION__);
goto done; goto done;
@ -506,7 +526,7 @@ cli_auto_sub_enter(clicon_handle h,
* argv, but this can be done differently * argv, but this can be done differently
*/ */
/* Create a cvv with variables to add to api-path */ /* Create a cvv with variables to add to api-path */
if ((cvv1 = cvec_new(0)) == NULL){ if ((cvv1 = cvec_new(0)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_new"); clicon_err(OE_UNIX, errno, "cvec_new");
goto done; goto done;
} }

View file

@ -106,8 +106,8 @@ autocli_listkw_int2str(int listkw)
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] modname Name of YANG module, or NULL for ANY module (eg default) * @param[in] modname Name of YANG module, or NULL for ANY module (eg default)
* @param[out] enablep Include this module in autocli * @param[out] enablep Include this module in autocli
* @retval -1 Error
* @retval 0 OK, and enablep set * @retval 0 OK, and enablep set
* @retval -1 Error
*/ */
int int
autocli_module(clicon_handle h, autocli_module(clicon_handle h,
@ -171,7 +171,7 @@ autocli_module(clicon_handle h,
} }
ok: ok:
*enablep = enable; *enablep = enable;
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
@ -190,7 +190,7 @@ autocli_compress_extension(yang_stmt *ys,
char *ns = NULL; char *ns = NULL;
int exist = 0; int exist = 0;
int ret; int ret;
if (nodeid_split(body, &prefix, &id) < 0) if (nodeid_split(body, &prefix, &id) < 0)
goto done; goto done;
if (prefix != NULL){ if (prefix != NULL){
@ -228,9 +228,8 @@ autocli_compress_extension(yang_stmt *ys,
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[out] compress * @param[out] compress
* @retval -1 Error
* @retval 0 OK, and compress set * @retval 0 OK, and compress set
* @retval -1 Error
* Canonical examples: * Canonical examples:
The config and state containers are "compressed" out of the schema. The config and state containers are "compressed" out of the schema.
+ op=COMPRESS + op=COMPRESS
@ -261,7 +260,7 @@ autocli_compress(clicon_handle h,
char *keywstr; char *keywstr;
int match = 0; int match = 0;
char *body; char *body;
if (compress == NULL){ if (compress == NULL){
clicon_err(OE_YANG, EINVAL, "Argument is NULL"); clicon_err(OE_YANG, EINVAL, "Argument is NULL");
goto done; goto done;
@ -346,8 +345,8 @@ autocli_compress(clicon_handle h,
* Currently only returns list-keyword-default, could be extended to rules * Currently only returns list-keyword-default, could be extended to rules
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[out] completion Completion enabled * @param[out] completion Completion enabled
* @retval -1 Error
* @retval 0 OK * @retval 0 OK
* @retval -1 Error
*/ */
int int
autocli_completion(clicon_handle h, autocli_completion(clicon_handle h,
@ -359,7 +358,7 @@ autocli_completion(clicon_handle h,
char *reason = NULL; char *reason = NULL;
int ret; int ret;
cxobj *xautocli; cxobj *xautocli;
if (completion == NULL){ if (completion == NULL){
clicon_err(OE_YANG, EINVAL, "Argument is NULL"); clicon_err(OE_YANG, EINVAL, "Argument is NULL");
goto done; goto done;
@ -377,7 +376,7 @@ autocli_completion(clicon_handle h,
goto done; goto done;
} }
*completion = val; *completion = val;
retval = 0; retval = 0;
done: done:
if (reason) if (reason)
free(reason); free(reason);
@ -389,8 +388,8 @@ autocli_completion(clicon_handle h,
* When false replaces uses with grouping, when true use tree reference * When false replaces uses with grouping, when true use tree reference
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[out] treeref grouping using treerefs enabled * @param[out] treeref grouping using treerefs enabled
* @retval -1 Error
* @retval 0 OK * @retval 0 OK
* @retval -1 Error
*/ */
int int
autocli_grouping_treeref(clicon_handle h, autocli_grouping_treeref(clicon_handle h,
@ -402,7 +401,7 @@ autocli_grouping_treeref(clicon_handle h,
char *reason = NULL; char *reason = NULL;
int ret; int ret;
cxobj *xautocli; cxobj *xautocli;
if (treeref == NULL){ if (treeref == NULL){
clicon_err(OE_YANG, EINVAL, "Argument is NULL"); clicon_err(OE_YANG, EINVAL, "Argument is NULL");
goto done; goto done;
@ -420,7 +419,7 @@ autocli_grouping_treeref(clicon_handle h,
goto done; goto done;
} }
*treeref = val; *treeref = val;
retval = 0; retval = 0;
done: done:
if (reason) if (reason)
free(reason); free(reason);
@ -432,8 +431,8 @@ autocli_grouping_treeref(clicon_handle h,
* Currently only returns list-keyword-default, could be extended to rules * Currently only returns list-keyword-default, could be extended to rules
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[out] listkw List keyword setting * @param[out] listkw List keyword setting
* @retval -1 Error
* @retval 0 OK * @retval 0 OK
* @retval -1 Error
*/ */
int int
autocli_list_keyword(clicon_handle h, autocli_list_keyword(clicon_handle h,
@ -442,7 +441,7 @@ autocli_list_keyword(clicon_handle h,
int retval = -1; int retval = -1;
char *str; char *str;
cxobj *xautocli = NULL; cxobj *xautocli = NULL;
if (listkw == NULL){ if (listkw == NULL){
clicon_err(OE_YANG, EINVAL, "Argument is NULL"); clicon_err(OE_YANG, EINVAL, "Argument is NULL");
goto done; goto done;
@ -456,7 +455,7 @@ autocli_list_keyword(clicon_handle h,
goto done; goto done;
} }
*listkw = autocli_listkw_str2int(str); *listkw = autocli_listkw_str2int(str);
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
@ -465,8 +464,8 @@ autocli_list_keyword(clicon_handle h,
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[out] treeref_state If true, generate CLI from state * @param[out] treeref_state If true, generate CLI from state
* @retval -1 Error
* @retval 0 OK * @retval 0 OK
* @retval -1 Error
*/ */
int int
autocli_treeref_state(clicon_handle h, autocli_treeref_state(clicon_handle h,
@ -478,7 +477,7 @@ autocli_treeref_state(clicon_handle h,
char *reason = NULL; char *reason = NULL;
int ret; int ret;
cxobj *xautocli; cxobj *xautocli;
if (treeref_state == NULL){ if (treeref_state == NULL){
clicon_err(OE_YANG, EINVAL, "Argument is NULL"); clicon_err(OE_YANG, EINVAL, "Argument is NULL");
goto done; goto done;
@ -496,7 +495,7 @@ autocli_treeref_state(clicon_handle h,
goto done; goto done;
} }
*treeref_state = val; *treeref_state = val;
retval = 0; retval = 0;
done: done:
if (reason) if (reason)
free(reason); free(reason);
@ -508,8 +507,8 @@ autocli_treeref_state(clicon_handle h,
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] keyw YANG keyword * @param[in] keyw YANG keyword
* @param[out] flag If 0 keyw is not a part of default edit-mode, if 1 it is. * @param[out] flag If 0 keyw is not a part of default edit-mode, if 1 it is.
* @retval -1 Error
* @retval 0 OK, see result in keyw * @retval 0 OK, see result in keyw
* @retval -1 Error
* @note keyw is a sub/superset of RFC 6020, see clixon-autocli.yang on which are defined * @note keyw is a sub/superset of RFC 6020, see clixon-autocli.yang on which are defined
*/ */
int int
@ -524,7 +523,7 @@ autocli_edit_mode(clicon_handle h,
int nvec; int nvec;
char *v; char *v;
int i; int i;
if (flag == NULL){ if (flag == NULL){
clicon_err(OE_YANG, EINVAL, "Argument is NULL"); clicon_err(OE_YANG, EINVAL, "Argument is NULL");
goto done; goto done;
@ -547,7 +546,7 @@ autocli_edit_mode(clicon_handle h,
break; break;
} }
} }
retval = 0; retval = 0;
done: done:
if (vec) if (vec)
free(vec); free(vec);

File diff suppressed because it is too large Load diff

View file

@ -122,8 +122,8 @@ You can see which CLISPEC it generates via clixon_cli -D 2:
* @note XXX only fraction_digits handled,should also have mincv, maxcv, pattern * @note XXX only fraction_digits handled,should also have mincv, maxcv, pattern
*/ */
static int static int
cli_expand_var_generate(clicon_handle h, cli_expand_var_generate(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
const char *cvtypestr, const char *cvtypestr,
int options, int options,
uint8_t fraction_digits, uint8_t fraction_digits,
@ -135,12 +135,12 @@ cli_expand_var_generate(clicon_handle h,
int extvalue = 0; int extvalue = 0;
yang_stmt *yspec; yang_stmt *yspec;
cg_var *cv = NULL; cg_var *cv = NULL;
if ((yspec = ys_spec(ys)) != NULL) if ((yspec = ys_spec(ys)) != NULL)
cv = yang_cv_get(yspec); cv = yang_cv_get(yspec);
if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0) if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0)
goto done; goto done;
if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL) if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL)
goto hide; goto hide;
if (yang2api_path_fmt(ys, 1, &api_path_fmt) < 0) if (yang2api_path_fmt(ys, 1, &api_path_fmt) < 0)
goto done; goto done;
@ -167,15 +167,18 @@ cli_expand_var_generate(clicon_handle h,
} }
/*! Create callback with api_path format string as argument /*! Create callback with api_path format string as argument
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys yang_stmt of the node at hand * @param[in] ys yang_stmt of the node at hand
* @param[out] cb The string where the result format string is inserted. * @param[out] cb The string where the result format string is inserted.
* @retval 0 OK
* @retval -1 Error
* @see cli_dbxml This is where the xmlkeyfmt string is used * @see cli_dbxml This is where the xmlkeyfmt string is used
* @see pt_callback_reference in CLIgen where the actual callback overwrites the template * @see pt_callback_reference in CLIgen where the actual callback overwrites the template
*/ */
static int static int
cli_callback_generate(clicon_handle h, cli_callback_generate(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
cbuf *cb) cbuf *cb)
{ {
int retval = -1; int retval = -1;
@ -200,6 +203,7 @@ cli_callback_generate(clicon_handle h,
} }
/*! Print cligen help string as ("<helpstring>") /*! Print cligen help string as ("<helpstring>")
*
* @param[in] cb CLIgen buf holding generated CLIspec * @param[in] cb CLIgen buf holding generated CLIspec
* @param[in] helptext Help text * @param[in] helptext Help text
*/ */
@ -243,10 +247,13 @@ yang2cli_print_alias(cbuf *cb,
} }
/*! Generate identityref statements for CLI variables /*! Generate identityref statements for CLI variables
*
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] ytype Resolved yang type. * @param[in] ytype Resolved yang type.
* @param[in] helptext CLI help text * @param[in] helptext CLI help text
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
* @see yang2cli_var_sub Its sub-function * @see yang2cli_var_sub Its sub-function
*/ */
static int static int
@ -267,7 +274,7 @@ yang2cli_var_identityref(yang_stmt *ys,
yang_stmt *ymod; yang_stmt *ymod;
yang_stmt *yprefix; yang_stmt *yprefix;
yang_stmt *yspec; yang_stmt *yspec;
if ((ybaseref = yang_find(ytype, Y_BASE, NULL)) == NULL) if ((ybaseref = yang_find(ytype, Y_BASE, NULL)) == NULL)
goto ok; goto ok;
if ((ybaseid = yang_find_identity(ytype, yang_argument_get(ybaseref))) == NULL) if ((ybaseid = yang_find_identity(ytype, yang_argument_get(ybaseref))) == NULL)
@ -316,10 +323,13 @@ yang2cli_var_identityref(yang_stmt *ys,
} }
/*! Generate range check statements for CLI variables /*! Generate range check statements for CLI variables
*
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] options Flags field of optional values, eg YANG_OPTIONS_RANGE * @param[in] options Flags field of optional values, eg YANG_OPTIONS_RANGE
* @param[in] cvv Cvec with array of range_min/range_max cv:s (if YANG_OPTIONS_RANGE is set in options) * @param[in] cvv Cvec with array of range_min/range_max cv:s (if YANG_OPTIONS_RANGE is set in options)
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
* @see yang2cli_var_sub which is the main function * @see yang2cli_var_sub which is the main function
* In yang ranges are given as range 1 or range 1 .. 16, encoded in a cvv * In yang ranges are given as range 1 or range 1 .. 16, encoded in a cvv
* 0 : range_min = x * 0 : range_min = x
@ -349,7 +359,7 @@ yang2cli_var_range(yang_stmt *ys,
int i; int i;
cg_var *cv1; /* lower limit */ cg_var *cv1; /* lower limit */
cg_var *cv2; /* upper limit */ cg_var *cv2; /* upper limit */
/* Loop through range_min and range_min..range_max */ /* Loop through range_min and range_min..range_max */
i = 0; i = 0;
while (i<cvec_len(cvv)){ while (i<cvec_len(cvv)){
@ -376,9 +386,12 @@ yang2cli_var_range(yang_stmt *ys,
} }
/*! Generate CLI code for Yang variable pattern statement /*! Generate CLI code for Yang variable pattern statement
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] patterns Cvec of regexp patterns * @param[in] patterns Cvec of regexp patterns
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
* @see cv_validate_pattern for netconf validate code * @see cv_validate_pattern for netconf validate code
* @note for cligen, need to escape " -> \" * @note for cligen, need to escape " -> \"
*/ */
@ -387,14 +400,14 @@ yang2cli_var_pattern(clicon_handle h,
cvec *patterns, cvec *patterns,
cbuf *cb) cbuf *cb)
{ {
int retval = -1; int retval = -1;
enum regexp_mode mode; enum regexp_mode mode;
cg_var *cvp; cg_var *cvp;
char *pattern; char *pattern;
int invert; int invert;
char *posix = NULL; char *posix = NULL;
int i; int i;
mode = clicon_yang_regexp(h); mode = clicon_yang_regexp(h);
cvp = NULL; /* Loop over compiled regexps */ cvp = NULL; /* Loop over compiled regexps */
while ((cvp = cvec_each(patterns, cvp)) != NULL){ while ((cvp = cvec_each(patterns, cvp)) != NULL){
@ -439,6 +452,7 @@ static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
yang_stmt *ytype, char *helptext, cbuf *cb); yang_stmt *ytype, char *helptext, cbuf *cb);
/*! Generate CLI code for Yang leaf state ment to CLIgen variable of specific type /*! Generate CLI code for Yang leaf state ment to CLIgen variable of specific type
*
* Check for completion (of already existent values), ranges (eg range[min:max]) and * Check for completion (of already existent values), ranges (eg range[min:max]) and
* patterns, (eg regexp:"[0.9]*"). * patterns, (eg regexp:"[0.9]*").
* @param[in] h Clixon handle * @param[in] h Clixon handle
@ -451,11 +465,13 @@ static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
* @param[in] patterns Cvec of regexp patterns * @param[in] patterns Cvec of regexp patterns
* @param[in] fraction for decimal64, how many digits after period * @param[in] fraction for decimal64, how many digits after period
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
* @see yang_type_resolve for options and other arguments * @see yang_type_resolve for options and other arguments
*/ */
static int static int
yang2cli_var_sub(clicon_handle h, yang2cli_var_sub(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
yang_stmt *ytype, /* resolved type */ yang_stmt *ytype, /* resolved type */
char *helptext, char *helptext,
enum cv_type cvtype, enum cv_type cvtype,
@ -481,7 +497,6 @@ yang2cli_var_sub(clicon_handle h,
} }
type = ytype?yang_argument_get(ytype):NULL; type = ytype?yang_argument_get(ytype):NULL;
cvtypestr = cv_type2str(cvtype); cvtypestr = cv_type2str(cvtype);
if (type && strcmp(type, "identityref") == 0) if (type && strcmp(type, "identityref") == 0)
cprintf(cb, "("); cprintf(cb, "(");
cprintf(cb, "<%s:%s", yang_argument_get(ys), cvtypestr); cprintf(cb, "<%s:%s", yang_argument_get(ys), cvtypestr);
@ -533,17 +548,20 @@ yang2cli_var_sub(clicon_handle h,
} }
/*! Resolve a single Yang union and generate code /*! Resolve a single Yang union and generate code
*
* Part of generating CLI code for Yang leaf statement to CLIgen variable * Part of generating CLI code for Yang leaf statement to CLIgen variable
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement (caller of type) * @param[in] ys Yang statement (caller of type)
* @param[in] origtype Name of original type in the call * @param[in] origtype Name of original type in the call
* @param[in] ytsub Yang type invocation, a sub-type of a resolved union type * @param[in] ytsub Yang type invocation, a sub-type of a resolved union type
* @param[in] cb Buffer where cligen code is written * @param[in] cb Buffer where cligen code is written
* @param[in] helptext CLI help text * @param[in] helptext CLI help text
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang2cli_var_union_one(clicon_handle h, yang2cli_var_union_one(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
char *origtype, char *origtype,
yang_stmt *ytsub, yang_stmt *ytsub,
char *helptext, char *helptext,
@ -581,7 +599,7 @@ yang2cli_var_union_one(clicon_handle h,
else { else {
if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0) if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0)
goto done; goto done;
if ((retval = yang2cli_var_sub(h, ys, ytype, helptext, cvtype, if ((retval = yang2cli_var_sub(h, ys, ytype, helptext, cvtype,
options, cvv, patterns, fraction_digits, cb)) < 0) options, cvv, patterns, fraction_digits, cb)) < 0)
goto done; goto done;
} }
@ -593,17 +611,20 @@ yang2cli_var_union_one(clicon_handle h,
} }
/*! Loop over all sub-types of a Yang union /*! Loop over all sub-types of a Yang union
*
* Part of generating CLI code for Yang leaf statement to CLIgen variable * Part of generating CLI code for Yang leaf statement to CLIgen variable
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement (caller) * @param[in] ys Yang statement (caller)
* @param[in] origtype Name of original type in the call * @param[in] origtype Name of original type in the call
* @param[in] ytype Yang resolved type (a union in this case) * @param[in] ytype Yang resolved type (a union in this case)
* @param[in] helptext CLI help text * @param[in] helptext CLI help text
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang2cli_var_union(clicon_handle h, yang2cli_var_union(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
char *origtype, char *origtype,
yang_stmt *ytype, yang_stmt *ytype,
char *helptext, char *helptext,
@ -633,7 +654,7 @@ yang2cli_var_union(clicon_handle h,
static int static int
yang2cli_var_leafref(clicon_handle h, yang2cli_var_leafref(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
yang_stmt *yrestype, yang_stmt *yrestype,
char *helptext, char *helptext,
enum cv_type cvtype, enum cv_type cvtype,
@ -669,11 +690,11 @@ yang2cli_var_leafref(clicon_handle h,
if (completionp && regular_value) if (completionp && regular_value)
cprintf(cb, "("); cprintf(cb, "(");
if (regular_value) if (regular_value)
if (yang2cli_var_sub(h, ys, yrestype, helptext, cvtype, if (yang2cli_var_sub(h, ys, yrestype, helptext, cvtype,
options, cvv, patterns, fraction_digits, cb) < 0) options, cvv, patterns, fraction_digits, cb) < 0)
goto done; goto done;
if (completionp){ if (completionp){
if ((ret = cli_expand_var_generate(h, ys, cvtypestr, if ((ret = cli_expand_var_generate(h, ys, cvtypestr,
options, fraction_digits, regular_value, options, fraction_digits, regular_value,
cb)) < 0) cb)) < 0)
goto done; goto done;
@ -688,11 +709,14 @@ yang2cli_var_leafref(clicon_handle h,
} }
/*! Generate CLI code for Yang leaf statement to CLIgen variable /*! Generate CLI code for Yang leaf statement to CLIgen variable
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement of original leaf * @param[in] ys Yang statement of original leaf
* @param[in] yreferred Yang statement of referred node for type (leafref) * @param[in] yreferred Yang statement of referred node for type (leafref)
* @param[in] helptext CLI help text * @param[in] helptext CLI help text
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
* *
* Make a type lookup and complete a cligen variable expression such as <a:string>. * Make a type lookup and complete a cligen variable expression such as <a:string>.
* One complication is yang union, that needs a recursion since it consists of * One complication is yang union, that needs a recursion since it consists of
@ -707,7 +731,7 @@ yang2cli_var_leafref(clicon_handle h,
static int static int
yang2cli_var(clicon_handle h, yang2cli_var(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
yang_stmt *yreferred, yang_stmt *yreferred,
char *helptext, char *helptext,
cbuf *cb) cbuf *cb)
{ {
@ -723,12 +747,12 @@ yang2cli_var(clicon_handle h,
int options = 0; int options = 0;
int completionp; int completionp;
int ret; int ret;
if ((patterns = cvec_new(0)) == NULL){ if ((patterns = cvec_new(0)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_new"); clicon_err(OE_UNIX, errno, "cvec_new");
goto done; goto done;
} }
if (yang_type_get(yreferred, &origtype, &yrestype, if (yang_type_get(yreferred, &origtype, &yrestype,
&options, &cvv, patterns, NULL, &fraction_digits) < 0) &options, &cvv, patterns, NULL, &fraction_digits) < 0)
goto done; goto done;
restype = yang_argument_get(yrestype); restype = yang_argument_get(yrestype);
@ -739,7 +763,7 @@ yang2cli_var(clicon_handle h,
cvtypestr = cv_type2str(cvtype); cvtypestr = cv_type2str(cvtype);
/* Note restype can be NULL here for example with unresolved hardcoded uuid */ /* Note restype can be NULL here for example with unresolved hardcoded uuid */
if (strcmp(restype, "union") == 0){ if (strcmp(restype, "union") == 0){
/* Union: loop over resolved type's sub-types (can also be recursive unions) */ /* Union: loop over resolved type's sub-types (can also be recursive unions) */
cprintf(cb, "("); cprintf(cb, "(");
if (yang2cli_var_union(h, ys, origtype, yrestype, helptext, cb) < 0) if (yang2cli_var_union(h, ys, origtype, yrestype, helptext, cb) < 0)
@ -747,7 +771,7 @@ yang2cli_var(clicon_handle h,
if (autocli_completion(h, &completionp) < 0) if (autocli_completion(h, &completionp) < 0)
goto done; goto done;
if (completionp){ if (completionp){
if ((ret = cli_expand_var_generate(h, ys, cvtypestr, if ((ret = cli_expand_var_generate(h, ys, cvtypestr,
options, fraction_digits, 1, cb)) < 0) options, fraction_digits, 1, cb)) < 0)
goto done; goto done;
if (ret == 1) if (ret == 1)
@ -770,15 +794,15 @@ yang2cli_var(clicon_handle h,
} }
if (yang_path_arg(yreferred, path_arg, &yref) < 0) if (yang_path_arg(yreferred, path_arg, &yref) < 0)
goto done; goto done;
if (yref == NULL){ if (yref == NULL){
/* Give up: use yreferred /* Give up: use yreferred
*/ */
if (yang2cli_var_leafref(h, ys, yrestype, helptext, cvtype, options, if (yang2cli_var_leafref(h, ys, yrestype, helptext, cvtype, options,
cvv, patterns, fraction_digits, cb) < 0) cvv, patterns, fraction_digits, cb) < 0)
goto done; goto done;
} }
else { else {
if (yreferred == yref){ if (yreferred == yref){
clicon_err(OE_YANG, 0, "Referred YANG node for leafref path %s points to self", path_arg); clicon_err(OE_YANG, 0, "Referred YANG node for leafref path %s points to self", path_arg);
goto done; goto done;
} }
@ -803,26 +827,29 @@ yang2cli_var(clicon_handle h,
} }
/*! Generate CLI code for Yang leaf statement /*! Generate CLI code for Yang leaf statement
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] level Indentation level * @param[in] level Indentation level
* @param[in] callback If set, include a "; cli_set()" callback, otherwise not * @param[in] callback If set, include a "; cli_set()" callback, otherwise not
* @param[in] key_leaf 0: ordinary leaf, 1:prekey, 2: lastkey * @param[in] key_leaf 0: ordinary leaf, 1:prekey, 2: lastkey
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
* Some complexity in callback, key_leaf and extralevel logic. * Some complexity in callback, key_leaf and extralevel logic.
* If extralevel -> add extra { } level * If extralevel -> add extra { } level
* + if callbacks add: cb();{} * + if callbacks add: cb();{}
*/ */
static int static int
yang2cli_leaf(clicon_handle h, yang2cli_leaf(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
int level, int level,
int callback, int callback,
int key_leaf, int key_leaf,
cbuf *cb) cbuf *cb)
{ {
yang_stmt *yd; /* description */
int retval = -1; int retval = -1;
yang_stmt *yd; /* description */
char *helptext = NULL; char *helptext = NULL;
char *s; char *s;
autocli_listkw_t listkw; autocli_listkw_t listkw;
@ -841,7 +868,7 @@ yang2cli_leaf(clicon_handle h,
} }
cprintf(cb, "%*s", level*3, ""); cprintf(cb, "%*s", level*3, "");
/* Called a second time in yang2cli_var, room for optimization */ /* Called a second time in yang2cli_var, room for optimization */
if (yang_type_get(ys, NULL, &yrestype, if (yang_type_get(ys, NULL, &yrestype,
NULL, NULL, NULL, NULL, NULL) < 0) NULL, NULL, NULL, NULL, NULL) < 0)
goto done; goto done;
if (key_leaf == 0 && strcmp(yang_argument_get(yrestype), "empty") != 0) if (key_leaf == 0 && strcmp(yang_argument_get(yrestype), "empty") != 0)
@ -905,27 +932,30 @@ yang2cli_leaf(clicon_handle h,
} }
/*! Generate CLI code for Yang container statement /*! Generate CLI code for Yang container statement
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] level Indentation level * @param[in] level Indentation level
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang2cli_container(clicon_handle h, yang2cli_container(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
int level, int level,
cbuf *cb) cbuf *cb)
{ {
int retval = -1;
yang_stmt *yc; yang_stmt *yc;
yang_stmt *yd; yang_stmt *yd;
int retval = -1;
char *helptext = NULL; char *helptext = NULL;
char *s; char *s;
int compress = 0; int compress = 0;
yang_stmt *ymod = NULL; yang_stmt *ymod = NULL;
int extvalue = 0; int extvalue = 0;
int ret; int ret;
if (ys_real_module(ys, &ymod) < 0) if (ys_real_module(ys, &ymod) < 0)
goto done; goto done;
/* If non-presence container && HIDE mode && only child is /* If non-presence container && HIDE mode && only child is
@ -964,7 +994,7 @@ yang2cli_container(clicon_handle h,
} }
} }
yc = NULL; yc = NULL;
while ((yc = yn_each(ys, yc)) != NULL) while ((yc = yn_each(ys, yc)) != NULL)
if (yang2cli_stmt(h, yc, level+1, cb) < 0) if (yang2cli_stmt(h, yc, level+1, cb) < 0)
goto done; goto done;
if (!compress) if (!compress)
@ -977,24 +1007,27 @@ yang2cli_container(clicon_handle h,
} }
/*! Generate CLI code for Yang list statement /*! Generate CLI code for Yang list statement
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] level Indentation level * @param[in] level Indentation level
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang2cli_list(clicon_handle h, yang2cli_list(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
int level, int level,
cbuf *cb) cbuf *cb)
{ {
int retval = -1;
yang_stmt *yc; yang_stmt *yc;
yang_stmt *yd; yang_stmt *yd;
yang_stmt *yleaf; yang_stmt *yleaf;
cg_var *cvi; cg_var *cvi;
char *keyname; char *keyname;
cvec *cvk = NULL; /* vector of index keys */ cvec *cvk = NULL; /* vector of index keys */
int retval = -1;
char *helptext = NULL; char *helptext = NULL;
char *s; char *s;
int last_key = 0; int last_key = 0;
@ -1023,7 +1056,7 @@ yang2cli_list(clicon_handle h,
while ((cvi = cvec_each(cvk, cvi)) != NULL) { while ((cvi = cvec_each(cvk, cvi)) != NULL) {
keyname = cv_string_get(cvi); keyname = cv_string_get(cvi);
if ((yleaf = yang_find(ys, Y_LEAF, keyname)) == NULL){ if ((yleaf = yang_find(ys, Y_LEAF, keyname)) == NULL){
clicon_err(OE_XML, 0, "List statement \"%s\" has no key leaf \"%s\"", clicon_err(OE_XML, 0, "List statement \"%s\" has no key leaf \"%s\"",
yang_argument_get(ys), keyname); yang_argument_get(ys), keyname);
goto done; goto done;
} }
@ -1066,7 +1099,7 @@ yang2cli_list(clicon_handle h,
} }
cprintf(cb, "%*s}\n", level*3, ""); cprintf(cb, "%*s}\n", level*3, "");
/* Close with } for each key */ /* Close with } for each key */
while (keynr--) while (keynr--)
cprintf(cb, "%*s}\n", level*3, ""); cprintf(cb, "%*s}\n", level*3, "");
retval = 0; retval = 0;
done: done:
@ -1081,18 +1114,20 @@ yang2cli_list(clicon_handle h,
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] level Indentation level * @param[in] level Indentation level
* @param[out] cb Buffer where cligen code is written * @param[out] cb Buffer where cligen code is written
@example * @retval 0 OK
* @retval -1 Error
* @code
choice interface-type { choice interface-type {
container ethernet { ... } container ethernet { ... }
container fddi { ... } container fddi { ... }
} }
@example.end * @code.end
@Note Removes 'meta-syntax' from cli syntax. They are not shown when xml is @note Removes 'meta-syntax' from cli syntax. They are not shown when xml is
translated to cli. and therefore input-syntax != output syntax. Which is bad translated to cli. and therefore input-syntax != output syntax. Which is bad
*/ */
static int static int
yang2cli_choice(clicon_handle h, yang2cli_choice(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
int level, int level,
cbuf *cb) cbuf *cb)
{ {
@ -1206,6 +1241,7 @@ yang2cli_uses(clicon_handle h,
} }
/*! Generate CLI code for Yang statement /*! Generate CLI code for Yang statement
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] level Indentation level * @param[in] level Indentation level
@ -1214,9 +1250,9 @@ yang2cli_uses(clicon_handle h,
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
yang2cli_stmt(clicon_handle h, yang2cli_stmt(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
int level, int level,
cbuf *cb) cbuf *cb)
{ {
int retval = -1; int retval = -1;
@ -1230,11 +1266,11 @@ yang2cli_stmt(clicon_handle h,
goto done; goto done;
} }
if (yang_find(ys, Y_STATUS, "obsolete") != NULL){ if (yang_find(ys, Y_STATUS, "obsolete") != NULL){
clicon_debug(4, "%s obsolete: %s %s, skipped", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys))); clixon_debug(CLIXON_DBG_DETAIL, "%s obsolete: %s %s, skipped", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys)));
goto ok; goto ok;
} }
if (yang_find(ys, Y_STATUS, "deprecated") != NULL){ if (yang_find(ys, Y_STATUS, "deprecated") != NULL){
clicon_debug(4, "%s deprecated: %s %s", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys))); clixon_debug(CLIXON_DBG_DETAIL, "%s deprecated: %s %s", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys)));
} }
/* Check if autocli skip */ /* Check if autocli skip */
if (yang_extension_value(ys, "skip", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0) if (yang_extension_value(ys, "skip", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0)
@ -1252,7 +1288,7 @@ yang2cli_stmt(clicon_handle h,
#ifdef AUTOCLI_GROUPING_TOPLEVEL_SKIP #ifdef AUTOCLI_GROUPING_TOPLEVEL_SKIP
cornercase = yang_keyword_get(yang_parent_get(ys)) == Y_MODULE || yang_keyword_get(yang_parent_get(ys)) == Y_SUBMODULE; cornercase = yang_keyword_get(yang_parent_get(ys)) == Y_MODULE || yang_keyword_get(yang_parent_get(ys)) == Y_SUBMODULE;
#endif #endif
if (yang_keyword_get(ys) != Y_USES && yang_flag_get(ys, YANG_FLAG_GROUPING) if (yang_keyword_get(ys) != Y_USES && yang_flag_get(ys, YANG_FLAG_GROUPING)
&& !cornercase && !cornercase
) )
goto ok; goto ok;
@ -1301,6 +1337,7 @@ yang2cli_stmt(clicon_handle h,
} }
/*! Add cv with name to cvec /*! Add cv with name to cvec
*
* @param[in] cvv Either existing or NULL * @param[in] cvv Either existing or NULL
* @param[in] name Name of cv to add * @param[in] name Name of cv to add
* @retval cvv Either same as in cvv parameter or new * @retval cvv Either same as in cvv parameter or new
@ -1310,7 +1347,7 @@ cvec_add_name(cvec *cvv,
char *name) char *name)
{ {
cg_var *cv= NULL; cg_var *cv= NULL;
if (cvv == NULL && if (cvv == NULL &&
(cvv = cvec_new(0)) == NULL){ (cvv = cvec_new(0)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_new"); clicon_err(OE_UNIX, errno, "cvec_new");
@ -1382,7 +1419,7 @@ yang2cli_post(clicon_handle h,
char *name; char *name;
cg_var *cv = NULL; cg_var *cv = NULL;
int j=0; int j=0;
cv = NULL; cv = NULL;
while ((cv = cvec_each(cop->co_cvec, cv)) != NULL){ while ((cv = cvec_each(cop->co_cvec, cv)) != NULL){
name = cv_name_get(cv); name = cv_name_get(cv);
@ -1480,7 +1517,7 @@ yang2cli_post(clicon_handle h,
* XXX merge with yang2cli_yspec * XXX merge with yang2cli_yspec
*/ */
static int static int
yang2cli_grouping(clicon_handle h, yang2cli_grouping(clicon_handle h,
yang_stmt *ys, yang_stmt *ys,
char *treename) char *treename)
{ {
@ -1495,7 +1532,7 @@ yang2cli_grouping(clicon_handle h,
cg_obj *co; cg_obj *co;
int config; int config;
int i; int i;
if ((pt0 = pt_new()) == NULL){ if ((pt0 = pt_new()) == NULL){
clicon_err(OE_UNIX, errno, "pt_new"); clicon_err(OE_UNIX, errno, "pt_new");
goto done; goto done;
@ -1506,11 +1543,11 @@ yang2cli_grouping(clicon_handle h,
} }
/* Traverse YANG, loop through all modules and generate CLI, inline of yang2cli_stmt */ /* Traverse YANG, loop through all modules and generate CLI, inline of yang2cli_stmt */
if (yang_find(ys, Y_STATUS, "obsolete") != NULL){ if (yang_find(ys, Y_STATUS, "obsolete") != NULL){
clicon_debug(4, "%s obsolete: %s %s, skipped", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys))); clixon_debug(CLIXON_DBG_DETAIL, "%s obsolete: %s %s, skipped", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys)));
goto empty; goto empty;
} }
if (yang_find(ys, Y_STATUS, "deprecated") != NULL){ if (yang_find(ys, Y_STATUS, "deprecated") != NULL){
clicon_debug(4, "%s deprecated: %s %s", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys))); clixon_debug(CLIXON_DBG_DETAIL, "%s deprecated: %s %s", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys)));
} }
/* Only produce autocli for YANG non-config only if autocli-treeref-state is true */ /* Only produce autocli for YANG non-config only if autocli-treeref-state is true */
if (autocli_treeref_state(h, &treeref_state) < 0) if (autocli_treeref_state(h, &treeref_state) < 0)
@ -1539,12 +1576,12 @@ yang2cli_grouping(clicon_handle h,
fprintf(stderr, "%s\n", cbuf_get(cb)); fprintf(stderr, "%s\n", cbuf_get(cb));
goto done; goto done;
} }
clicon_debug(CLIXON_DBG_DEFAULT, "%s Generated auto-cli for grouping:%s", clixon_debug(CLIXON_DBG_DEFAULT, "%s Generated auto-cli for grouping:%s",
__FUNCTION__, yang_argument_get(ys)); __FUNCTION__, yang_argument_get(ys));
/* Add prefix: assume new are appended */ /* Add prefix: assume new are appended */
for (i=0; i<pt_len_get(pt); i++){ for (i=0; i<pt_len_get(pt); i++){
if ((co = pt_vec_i_get(pt, i)) != NULL){ if ((co = pt_vec_i_get(pt, i)) != NULL){
clicon_debug(CLIXON_DBG_DEFAULT, "%s command: %s", clixon_debug(CLIXON_DBG_DEFAULT, "%s command: %s",
__FUNCTION__, co->co_command); __FUNCTION__, co->co_command);
co_prefix_set(co, prefix); co_prefix_set(co, prefix);
} }
@ -1562,7 +1599,7 @@ yang2cli_grouping(clicon_handle h,
clicon_log(LOG_NOTICE, "%s: Top-level cli-spec %s:\n%s", clicon_log(LOG_NOTICE, "%s: Top-level cli-spec %s:\n%s",
__FUNCTION__, treename, cbuf_get(cb)); __FUNCTION__, treename, cbuf_get(cb));
else else
clicon_debug(CLIXON_DBG_DETAIL, "%s: Top-level cli-spec %s:\n%s", clixon_debug(CLIXON_DBG_DETAIL, "%s: Top-level cli-spec %s:\n%s",
__FUNCTION__, treename, cbuf_get(cb)); __FUNCTION__, treename, cbuf_get(cb));
if (cligen_parsetree_merge(pt0, NULL, pt) < 0){ if (cligen_parsetree_merge(pt0, NULL, pt) < 0){
clicon_err(OE_YANG, errno, "cligen_parsetree_merge"); clicon_err(OE_YANG, errno, "cligen_parsetree_merge");
@ -1614,7 +1651,7 @@ yang2cli_grouping(clicon_handle h,
* @note Tie-break of same top-level symbol: prefix is NYI * @note Tie-break of same top-level symbol: prefix is NYI
*/ */
int int
yang2cli_yspec(clicon_handle h, yang2cli_yspec(clicon_handle h,
yang_stmt *yspec, yang_stmt *yspec,
char *treename) char *treename)
{ {
@ -1629,7 +1666,7 @@ yang2cli_yspec(clicon_handle h,
cg_obj *co; cg_obj *co;
int i; int i;
int config; int config;
if ((pt0 = pt_new()) == NULL){ if ((pt0 = pt_new()) == NULL){
clicon_err(OE_UNIX, errno, "pt_new"); clicon_err(OE_UNIX, errno, "pt_new");
goto done; goto done;
@ -1669,12 +1706,12 @@ yang2cli_yspec(clicon_handle h,
fprintf(stderr, "%s\n", cbuf_get(cb)); fprintf(stderr, "%s\n", cbuf_get(cb));
goto done; goto done;
} }
clicon_debug(CLIXON_DBG_DEFAULT, "%s Generated auto-cli for module:%s", clixon_debug(CLIXON_DBG_DEFAULT, "%s Generated auto-cli for module:%s",
__FUNCTION__, yang_argument_get(ymod)); __FUNCTION__, yang_argument_get(ymod));
/* Add prefix: assume new are appended */ /* Add prefix: assume new are appended */
for (i=0; i<pt_len_get(pt); i++){ for (i=0; i<pt_len_get(pt); i++){
if ((co = pt_vec_i_get(pt, i)) != NULL){ if ((co = pt_vec_i_get(pt, i)) != NULL){
clicon_debug(CLIXON_DBG_DEFAULT, "%s command: %s", clixon_debug(CLIXON_DBG_DEFAULT, "%s command: %s",
__FUNCTION__, co->co_command); __FUNCTION__, co->co_command);
co_prefix_set(co, prefix); co_prefix_set(co, prefix);
} }
@ -1693,7 +1730,7 @@ yang2cli_yspec(clicon_handle h,
clicon_log(LOG_NOTICE, "%s: Top-level cli-spec %s:\n%s", clicon_log(LOG_NOTICE, "%s: Top-level cli-spec %s:\n%s",
__FUNCTION__, treename, cbuf_get(cb)); __FUNCTION__, treename, cbuf_get(cb));
else else
clicon_debug(CLIXON_DBG_DETAIL, "%s: Top-level cli-spec %s:\n%s", clixon_debug(CLIXON_DBG_DETAIL, "%s: Top-level cli-spec %s:\n%s",
__FUNCTION__, treename, cbuf_get(cb)); __FUNCTION__, treename, cbuf_get(cb));
if (cligen_parsetree_merge(pt0, NULL, pt) < 0){ if (cligen_parsetree_merge(pt0, NULL, pt) < 0){
clicon_err(OE_YANG, errno, "cligen_parsetree_merge"); clicon_err(OE_YANG, errno, "cligen_parsetree_merge");

View file

@ -72,7 +72,8 @@
#define handle(h) (assert(clicon_handle_check(h)==0),(struct cli_handle *)(h)) #define handle(h) (assert(clicon_handle_check(h)==0),(struct cli_handle *)(h))
#define cligen(h) (handle(h)->cl_cligen) #define cligen(h) (handle(h)->cl_cligen)
/*! CLI specific handle added to header CLICON handle /*! CLI specific handle added to header Clixon handle
*
* This file should only contain access functions for the _specific_ * This file should only contain access functions for the _specific_
* entries in the struct below. * entries in the struct below.
* @note The top part must be equivalent to struct clicon_handle in clixon_handle.c * @note The top part must be equivalent to struct clicon_handle in clixon_handle.c
@ -115,6 +116,8 @@ cli_handle_init(void)
} }
/*! Free clicon handle /*! Free clicon handle
*
* @param[in] h Clixon handle
*/ */
int int
cli_handle_exit(clicon_handle h) cli_handle_exit(clicon_handle h)
@ -130,7 +133,10 @@ cli_handle_exit(clicon_handle h)
* cli-specific handle access functions * cli-specific handle access functions
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/*! Return clicon handle */ /*! Return clicon handle
*
* @param[in] h Clixon handle
*/
cligen_handle cligen_handle
cli_cligen(clicon_handle h) cli_cligen(clicon_handle h)
{ {
@ -156,8 +162,9 @@ cli_susp_hook(clicon_handle h,
cligen_handle ch = cligen(h); cligen_handle ch = cligen(h);
/* This assume first arg of fn can be treated as void* */ /* This assume first arg of fn can be treated as void* */
return cligen_susp_hook(ch, fn); return cligen_susp_hook(ch, fn);
} }
int int
cli_interrupt_hook(clicon_handle h, cli_interrupt_hook(clicon_handle h,
cligen_interrupt_cb_t *fn) cligen_interrupt_cb_t *fn)
@ -165,7 +172,7 @@ cli_interrupt_hook(clicon_handle h,
cligen_handle ch = cligen(h); cligen_handle ch = cligen(h);
/* This assume first arg of fn can be treated as void* */ /* This assume first arg of fn can be treated as void* */
return cligen_interrupt_hook(ch, fn); return cligen_interrupt_hook(ch, fn);
} }
int int

View file

@ -76,8 +76,11 @@
#define CLI_OPTS "+hD:f:E:l:C:F:1a:u:d:m:qp:GLy:c:U:o:" #define CLI_OPTS "+hD:f:E:l:C:F:1a:u:d:m:qp:GLy:c:U:o:"
/*! Check if there is a CLI history file and if so dump the CLI histiry to it /*! Check if there is a CLI history file and if so dump the CLI histiry to it
*
* Just log if file does not exist or is not readable * Just log if file does not exist or is not readable
* @param[in] h CLICON handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
cli_history_load(clicon_handle h) cli_history_load(clicon_handle h)
@ -121,8 +124,11 @@ cli_history_load(clicon_handle h)
} }
/*! Start CLI history and load from file /*! Start CLI history and load from file
*
* Just log if file does not exist or is not readable * Just log if file does not exist or is not readable
* @param[in] h CLICON handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
cli_history_save(clicon_handle h) cli_history_save(clicon_handle h)
@ -157,6 +163,7 @@ cli_history_save(clicon_handle h)
} }
/*! Clean and close all state of cli process (but dont exit). /*! Clean and close all state of cli process (but dont exit).
*
* Cannot use h after this * Cannot use h after this
* @param[in] h Clixon handle * @param[in] h Clixon handle
*/ */
@ -170,7 +177,7 @@ cli_terminate(clicon_handle h)
if (clixon_exit_get() == 0) if (clixon_exit_get() == 0)
clixon_exit_set(1); clixon_exit_set(1);
if (clicon_data_get(h, "session-transport", NULL) == 0) if (clicon_data_get(h, "session-transport", NULL) == 0)
clicon_rpc_close_session(h); clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL) if ((yspec = clicon_dbspec_yang(h)) != NULL)
ys_free(yspec); ys_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL) if ((yspec = clicon_config_yang(h)) != NULL)
@ -195,11 +202,11 @@ cli_terminate(clicon_handle h)
} }
/*! Unlink pidfile and quit /*! Unlink pidfile and quit
*/ */
static void static void
cli_sig_term(int arg) cli_sig_term(int arg)
{ {
clicon_log(LOG_NOTICE, "%s: %u Terminated (killed by sig %d)", clicon_log(LOG_NOTICE, "%s: %u Terminated (killed by sig %d)",
__PROGRAM__, getpid(), arg); __PROGRAM__, getpid(), arg);
exit(1); exit(1);
} }
@ -226,7 +233,8 @@ cli_signal_init (clicon_handle h)
} }
/*! Interactive CLI command loop /*! Interactive CLI command loop
* @param[in] h CLICON handle *
* @param[in] h Clixon handle
* @retval 0 * @retval 0
* @retval -1 * @retval -1
* @see cligen_loop * @see cligen_loop
@ -269,6 +277,7 @@ cli_interactive(clicon_handle h)
} }
/*! Create pre-5.5 tree-refs for backward compatibility /*! Create pre-5.5 tree-refs for backward compatibility
*
* should probably be moved to clispec default * should probably be moved to clispec default
*/ */
static int static int
@ -382,8 +391,8 @@ autocli_start(clicon_handle h)
int retval = -1; int retval = -1;
yang_stmt *yspec; yang_stmt *yspec;
int enable = 0; int enable = 0;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* There is no single "enable-autocli" flag, /* There is no single "enable-autocli" flag,
* but set * but set
* <module-default>false</module-default> * <module-default>false</module-default>
@ -394,7 +403,7 @@ autocli_start(clicon_handle h)
if (autocli_module(h, NULL, &enable) < 0) if (autocli_module(h, NULL, &enable) < 0)
goto done; goto done;
if (!enable){ if (!enable){
clicon_debug(1, "%s Autocli not enabled (clixon-autocli)", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s Autocli not enabled (clixon-autocli)", __FUNCTION__);
goto ok; goto ok;
} }
/* Init yang2cli */ /* Init yang2cli */
@ -404,7 +413,7 @@ autocli_start(clicon_handle h)
/* The actual generating call from yang to clispec for the complete yang spec, @basemodel */ /* The actual generating call from yang to clispec for the complete yang spec, @basemodel */
if (yang2cli_yspec(h, yspec, AUTOCLI_TREENAME) < 0) if (yang2cli_yspec(h, yspec, AUTOCLI_TREENAME) < 0)
goto done; goto done;
/* XXX Create pre-5.5 tree-refs for backward compatibility */ /* XXX Create pre-5.5 tree-refs for backward compatibility */
if (autocli_trees_default(h) < 0) if (autocli_trees_default(h) < 0)
goto done; goto done;
ok: ok:
@ -469,7 +478,7 @@ usage(clicon_handle h,
fprintf(stderr, "usage:%s [options] [commands] [-- extra-options]\n" fprintf(stderr, "usage:%s [options] [commands] [-- extra-options]\n"
"where commands is a CLI command\n" "where commands is a CLI command\n"
"and extra-options are app-dependent and passed to the plugin init function\n" "and extra-options are app-dependent and passed to the plugin init function\n"
"where options are\n" "where options are\n"
"\t-h \t\tHelp\n" "\t-h \t\tHelp\n"
"\t-D <level> \tDebug level\n" "\t-D <level> \tDebug level\n"
@ -525,7 +534,7 @@ main(int argc,
int nr; int nr;
int config_dump; int config_dump;
enum format_enum config_dump_format = FORMAT_XML; enum format_enum config_dump_format = FORMAT_XML;
/* Defaults */ /* Defaults */
once = 0; once = 0;
config_dump = 0; config_dump = 0;
@ -533,7 +542,7 @@ main(int argc,
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
/* Initiate CLICON handle. CLIgen is also initialized */ /* Initiate Clixon handle. CLIgen is also initialized */
if ((h = cli_handle_init()) == NULL) if ((h = cli_handle_init()) == NULL)
goto done; goto done;
@ -549,7 +558,7 @@ main(int argc,
cligen_comment_set(cli_cligen(h), '#'); /* Default to handle #! clicon_cli scripts */ cligen_comment_set(cli_cligen(h), '#'); /* Default to handle #! clicon_cli scripts */
cligen_lexicalorder_set(cli_cligen(h), 1); cligen_lexicalorder_set(cli_cligen(h), 1);
/* /*
* First-step command-line options for help, debug, config-file and log, * First-step command-line options for help, debug, config-file and log,
*/ */
@ -588,11 +597,11 @@ main(int argc,
goto done; goto done;
break; break;
} }
/* /*
* Logs, error and debug to stderr or syslog, set debug level * Logs, error and debug to stderr or syslog, set debug level
*/ */
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst); clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
yang_init(h); yang_init(h);
/* Find, read and parse configfile */ /* Find, read and parse configfile */
@ -601,7 +610,7 @@ main(int argc,
usage(h, argv[0]); usage(h, argv[0]);
goto done; goto done;
} }
/* Now rest of options */ /* Now rest of options */
opterr = 0; opterr = 0;
optind = 1; optind = 1;
while ((c = getopt(argc, argv, CLI_OPTS)) != -1){ while ((c = getopt(argc, argv, CLI_OPTS)) != -1){
@ -698,7 +707,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(h, argv[0]); usage(h, argv[0]);
/* Split remaining argv/argc into <cmd> and <extra-options> */ /* Split remaining argv/argc into <cmd> and <extra-options> */
if (options_split(h, argv0, argc, argv, &restarg) < 0) if (options_split(h, argv0, argc, argv, &restarg) < 0)
goto done; goto done;
@ -713,7 +722,7 @@ main(int argc,
nr = clicon_option_int(h, "CLICON_CLI_LINES_DEFAULT"); nr = clicon_option_int(h, "CLICON_CLI_LINES_DEFAULT");
cligen_terminal_rows_set(cli_cligen(h), nr); cligen_terminal_rows_set(cli_cligen(h), nr);
} }
if (clicon_yang_regexp(h) == REGEXP_LIBXML2){ if (clicon_yang_regexp(h) == REGEXP_LIBXML2){
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
/* Enable XSD libxml2 regex engine */ /* Enable XSD libxml2 regex engine */
@ -732,7 +741,7 @@ main(int argc,
if ((nr = clicon_option_int(h, "CLICON_LOG_STRING_LIMIT")) != 0) if ((nr = clicon_option_int(h, "CLICON_LOG_STRING_LIMIT")) != 0)
clicon_log_string_limit_set(nr); clicon_log_string_limit_set(nr);
/* Setup signal handlers */ /* Setup signal handlers */
if (cli_signal_init(h) < 0) if (cli_signal_init(h) < 0)
goto done; goto done;
@ -757,7 +766,7 @@ main(int argc,
goto done; goto done;
} }
#endif #endif
/* Add (hardcoded) netconf features in case ietf-netconf loaded here /* Add (hardcoded) netconf features in case ietf-netconf loaded here
* Otherwise it is loaded in netconf_module_load below * Otherwise it is loaded in netconf_module_load below
*/ */
@ -772,7 +781,7 @@ main(int argc,
if ((yspec = yspec_new()) == NULL) if ((yspec = yspec_new()) == NULL)
goto done; goto done;
clicon_dbspec_yang_set(h, yspec); clicon_dbspec_yang_set(h, yspec);
/* Load Yang modules /* Load Yang modules
* 1. Load a yang module as a specific absolute filename */ * 1. Load a yang module as a specific absolute filename */
if ((str = clicon_yang_main_file(h)) != NULL){ if ((str = clicon_yang_main_file(h)) != NULL){
@ -802,7 +811,6 @@ main(int argc,
/* Add netconf yang spec, used as internal protocol */ /* Add netconf yang spec, used as internal protocol */
if (netconf_module_load(h) < 0) if (netconf_module_load(h) < 0)
goto done; goto done;
/* Here all modules are loaded /* Here all modules are loaded
* Compute and set canonical namespace context * Compute and set canonical namespace context
*/ */
@ -868,7 +876,7 @@ main(int argc,
clicon_option_dump(h, 1); clicon_option_dump(h, 1);
cligen_line_scrolling_set(cli_cligen(h), clicon_option_int(h,"CLICON_CLI_LINESCROLLING")); cligen_line_scrolling_set(cli_cligen(h), clicon_option_int(h,"CLICON_CLI_LINESCROLLING"));
/*! Start CLI history and load from file */ /* Start CLI history and load from file */
if (cli_history_load(h) < 0) if (cli_history_load(h) < 0)
goto done; goto done;
/* Experimental utf8 mode */ /* Experimental utf8 mode */
@ -893,7 +901,7 @@ main(int argc,
if (evalresult < 0) if (evalresult < 0)
goto done; goto done;
} }
/* Go into event-loop unless -1 command-line */ /* Go into event-loop unless -1 command-line */
if (!once){ if (!once){
retval = cli_interactive(h); retval = cli_interactive(h);

View file

@ -92,7 +92,7 @@ pipe_arg_fn(clicon_handle h,
struct stat fstat; struct stat fstat;
char **argv = NULL; char **argv = NULL;
int i; int i;
if (cmd == NULL || strlen(cmd) == 0){ if (cmd == NULL || strlen(cmd) == 0){
clicon_err(OE_PLUGIN, EINVAL, "cmd '%s' NULL or empty", cmd); clicon_err(OE_PLUGIN, EINVAL, "cmd '%s' NULL or empty", cmd);
goto done; goto done;
@ -123,7 +123,7 @@ pipe_arg_fn(clicon_handle h,
/* Grep pipe output function /* Grep pipe output function
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv String vector of options. Format: <option> <value> * @param[in] argv String vector of options. Format: <option> <value>
* @note Any vertical bar (|] in the patterns field is quoted for OR function * @note Any vertical bar (|] in the patterns field is quoted for OR function
@ -182,9 +182,11 @@ pipe_grep_fn(clicon_handle h,
/*! wc pipe output function /*! wc pipe output function
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv String vector of options. Format: <option> <value> * @param[in] argv String vector of options. Format: <option> <value>
* @retval 0 OK
* @retval -1 Error
*/ */
int int
pipe_wc_fn(clicon_handle h, pipe_wc_fn(clicon_handle h,
@ -195,7 +197,7 @@ pipe_wc_fn(clicon_handle h,
cg_var *cv; cg_var *cv;
char *str; char *str;
char *option = NULL; char *option = NULL;
if (cvec_len(argv) != 1){ if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: <NUM>", cvec_len(argv)); clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: <NUM>", cvec_len(argv));
goto done; goto done;
@ -211,9 +213,11 @@ pipe_wc_fn(clicon_handle h,
/*! wc pipe output function /*! wc pipe output function
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv String vector of options. Format: <option> <value> * @param[in] argv String vector of options. Format: <option> <value>
* @retval 0 OK
* @retval -1 Error
*/ */
int int
pipe_tail_fn(clicon_handle h, pipe_tail_fn(clicon_handle h,
@ -252,12 +256,14 @@ pipe_tail_fn(clicon_handle h,
/*! Output pipe translate from xml to other format: json,text, /*! Output pipe translate from xml to other format: json,text,
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv String vector of show options, format: * @param[in] argv String vector of show options, format:
* <format> "text"|"xml"|"json"|"cli"|"netconf" (see format_enum), default: xml * <format> "text"|"xml"|"json"|"cli"|"netconf" (see format_enum), default: xml
* <pretty> true|false: pretty-print or not * <pretty> true|false: pretty-print or not
* <prepend> CLI prefix: prepend before cli syntax output * <prepend> CLI prefix: prepend before cli syntax output
* @retval 0 OK
* @retval -1 Error
* @see cli_show_auto_devs * @see cli_show_auto_devs
*/ */
int int
@ -350,7 +356,7 @@ output_fn(cligen_handle handle,
cvec *argv) cvec *argv)
{ {
cg_var *cv; cg_var *cv;
cv = NULL; cv = NULL;
while ((cv = cvec_each(argv, cv)) != NULL){ while ((cv = cvec_each(argv, cv)) != NULL){
cligen_output(stdout, "%s\n", cv_string_get(cv)); cligen_output(stdout, "%s\n", cv_string_get(cv));

View file

@ -81,8 +81,10 @@
/*! Generate CLIgen parse tree for syntax mode /*! Generate CLIgen parse tree for syntax mode
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] m Syntax mode struct * @param[in] m Syntax mode struct
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
gen_parse_tree(clicon_handle h, gen_parse_tree(clicon_handle h,
@ -92,7 +94,7 @@ gen_parse_tree(clicon_handle h,
{ {
int retval = -1; int retval = -1;
pt_head *ph; pt_head *ph;
if ((ph = cligen_ph_add(cli_cligen(h), name)) == NULL) if ((ph = cligen_ph_add(cli_cligen(h), name)) == NULL)
goto done; goto done;
if (cligen_ph_parsetree_set(ph, pt) < 0) if (cligen_ph_parsetree_set(ph, pt) < 0)
@ -123,12 +125,12 @@ gen_parse_tree(clicon_handle h,
* @note the returned function is not type-checked which may result in segv at runtime * @note the returned function is not type-checked which may result in segv at runtime
*/ */
void * void *
clixon_str2fn(char *name, clixon_str2fn(char *name,
void *handle, void *handle,
char **error) char **error)
{ {
void *fn = NULL; void *fn = NULL;
/* Reset error */ /* Reset error */
*error = NULL; *error = NULL;
/* Special check for auto-cli. If the virtual callback is used, it should be overwritten later /* Special check for auto-cli. If the virtual callback is used, it should be overwritten later
@ -160,16 +162,14 @@ clixon_str2fn(char *name,
* signal an error. However, just checking the function pointer for NULL * signal an error. However, just checking the function pointer for NULL
* should work in most cases, although it's not 100% correct. * should work in most cases, although it's not 100% correct.
*/ */
return NULL; return NULL;
} }
/*! Set output pipe flag in all callbacks /*! Set output pipe flag in all callbacks
* *
* @param[in] co CLIgen parse-tree object * @param[in] co CLIgen parse-tree object
* @param[in] arg Argument, cast to application-specific info * @param[in] arg Argument, cast to application-specific info
* @retval 1 OK and return (abort iteration) * @retval 0 OK
* @retval 0 OK and continue
* @retval -1 Error: break and return
*/ */
static int static int
cli_mark_output_pipes(cg_obj *co, cli_mark_output_pipes(cg_obj *co,
@ -193,6 +193,8 @@ cli_mark_output_pipes(cg_obj *co,
* @param[in] dir Name of dir, or NULL * @param[in] dir Name of dir, or NULL
* @param[out] ptall Universal CLIgen parse tree: apply to all modes * @param[out] ptall Universal CLIgen parse tree: apply to all modes
* @param[out] modes Keep track of all modes * @param[out] modes Keep track of all modes
* @retval 0 OK
* @retval -1 Error
* @see clixon_plugins_load Where .so plugin code has been loaded prior to this * @see clixon_plugins_load Where .so plugin code has been loaded prior to this
*/ */
static int static int
@ -202,10 +204,10 @@ clispec_load_file(clicon_handle h,
parse_tree *ptall, parse_tree *ptall,
cvec *modes) cvec *modes)
{ {
int retval = -1;
void *handle = NULL; /* Handle to plugin .so module */ void *handle = NULL; /* Handle to plugin .so module */
char *mode = NULL; /* Name of syntax mode to append new syntax */ char *mode = NULL; /* Name of syntax mode to append new syntax */
parse_tree *pt = NULL; parse_tree *pt = NULL;
int retval = -1;
FILE *f; FILE *f;
char filepath[MAXPATHLEN]; char filepath[MAXPATHLEN];
cvec *cvv = NULL; cvec *cvv = NULL;
@ -265,8 +267,8 @@ clispec_load_file(clicon_handle h,
if ((cp = clixon_plugin_find(h, plgnam)) != NULL) if ((cp = clixon_plugin_find(h, plgnam)) != NULL)
handle = clixon_plugin_handle_get(cp); handle = clixon_plugin_handle_get(cp);
if (handle == NULL){ if (handle == NULL){
clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s", clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s",
plgnam, filename, plgnam, plgnam, filename, plgnam,
clicon_cli_dir(h)); clicon_cli_dir(h));
goto done; goto done;
} }
@ -281,27 +283,27 @@ clispec_load_file(clicon_handle h,
} }
/* Resolve callback names to function pointers. */ /* Resolve callback names to function pointers. */
if (cligen_callbackv_str2fn(pt, (cgv_str2fn_t*)clixon_str2fn, handle) < 0){ if (cligen_callbackv_str2fn(pt, (cgv_str2fn_t*)clixon_str2fn, handle) < 0){
clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)", clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)",
filename, plgnam, plgnam); filename, plgnam, plgnam);
goto done; goto done;
} }
if (cligen_expandv_str2fn(pt, (expandv_str2fn_t*)clixon_str2fn, handle) < 0) if (cligen_expandv_str2fn(pt, (expandv_str2fn_t*)clixon_str2fn, handle) < 0)
goto done; goto done;
/* Variable translation functions */ /* Variable translation functions */
if (cligen_translate_str2fn(pt, (translate_str2fn_t*)clixon_str2fn, handle) < 0) if (cligen_translate_str2fn(pt, (translate_str2fn_t*)clixon_str2fn, handle) < 0)
goto done; goto done;
/* Make sure we have a syntax mode specified */ /* Make sure we have a syntax mode specified */
if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */ if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */
mode = clicon_cli_mode(h); mode = clicon_cli_mode(h);
if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */ if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */
clicon_err(OE_PLUGIN, 0, "No syntax mode specified in %s", filepath); clicon_err(OE_PLUGIN, 0, "No syntax mode specified in %s", filepath);
goto done; goto done;
} }
} }
/* Find all modes in CLICON_MODE string: where to append the pt syntax tree */ /* Find all modes in CLICON_MODE string: where to append the pt syntax tree */
if ((vec = clicon_strsep(mode, ":", &nvec)) == NULL) if ((vec = clicon_strsep(mode, ":", &nvec)) == NULL)
goto done; goto done;
if (nvec == 1 && strcmp(vec[0], "*") == 0){ if (nvec == 1 && strcmp(vec[0], "*") == 0){
@ -369,7 +371,9 @@ done:
* *
* CLI .so plugins have been loaded: syntax table in place. * CLI .so plugins have been loaded: syntax table in place.
* Now load cligen syntax files and create cligen pt trees. * Now load cligen syntax files and create cligen pt trees.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
* XXX The parsetree loading needs a rewrite for multiple parse-trees * XXX The parsetree loading needs a rewrite for multiple parse-trees
*/ */
int int
@ -413,7 +417,7 @@ clispec_load(clicon_handle h)
goto done; goto done;
/* Load the syntax parse trees into cli_syntax stx structure */ /* Load the syntax parse trees into cli_syntax stx structure */
for (i = 0; i < ndp; i++) { for (i = 0; i < ndp; i++) {
clicon_debug(CLIXON_DBG_DEFAULT, "Loading clispec syntax: '%s/%s'", clixon_debug(CLIXON_DBG_DEFAULT, "Loading clispec syntax: '%s/%s'",
clispec_dir, dp[i].d_name); clispec_dir, dp[i].d_name);
if (clispec_load_file(h, dp[i].d_name, clispec_dir, ptall, modes) < 0) if (clispec_load_file(h, dp[i].d_name, clispec_dir, ptall, modes) < 0)
goto done; goto done;
@ -461,7 +465,8 @@ done:
} }
/*! Free resources in plugin /*! Free resources in plugin
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
*/ */
int int
cli_plugin_finish(clicon_handle h) cli_plugin_finish(clicon_handle h)
@ -470,13 +475,14 @@ cli_plugin_finish(clicon_handle h)
} }
/*! Help function to print a meaningful error string. /*! Help function to print a meaningful error string.
*
* Sometimes the libraries specify an error string, if so print that. * Sometimes the libraries specify an error string, if so print that.
* Otherwise just print 'command error'. * Otherwise just print 'command error'.
* But do not print it if error is already logged in eg clicon_err() using STDERR logging * But do not print it if error is already logged in eg clicon_err() using STDERR logging
* See eg https://github.com/clicon/clixon/issues/325 * See eg https://github.com/clicon/clixon/issues/325
* @param[in] f File handler to write error to. * @param[in] f File handler to write error to.
*/ */
int int
cli_handler_err(FILE *f) cli_handler_err(FILE *f)
{ {
if (clicon_errno){ if (clicon_errno){
@ -494,6 +500,7 @@ cli_handler_err(FILE *f)
} }
/*! Given a command string, parse and if match single command, eval it. /*! Given a command string, parse and if match single command, eval it.
*
* Parse and evaluate the string according to * Parse and evaluate the string according to
* the syntax parse tree of the syntax mode specified by *mode. * the syntax parse tree of the syntax mode specified by *mode.
* If there is no match in the tree for the command, the parse hook * If there is no match in the tree for the command, the parse hook
@ -501,19 +508,19 @@ cli_handler_err(FILE *f)
* match is found in another mode, the mode variable is updated to point at * match is found in another mode, the mode variable is updated to point at
* the new mode string. * the new mode string.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] cmd Command string * @param[in] cmd Command string
* @param[in,out] modenamep Pointer to the mode string pointer * @param[in,out] modenamep Pointer to the mode string pointer
* @param[out] result CLIgen match result, < 0: errors, >=0 number of matches * @param[out] result CLIgen match result, < 0: errors, >=0 number of matches
* @param[out] evalres Evaluation result if result=1 * @param[out] evalres Evaluation result if result=1
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int int
clicon_parse(clicon_handle h, clicon_parse(clicon_handle h,
char *cmd, char *cmd,
char **modenamep, char **modenamep,
cligen_result *result, cligen_result *result,
int *evalres) int *evalres)
{ {
int retval = -1; int retval = -1;
@ -526,7 +533,7 @@ clicon_parse(clicon_handle h,
char *reason = NULL; char *reason = NULL;
cligen_handle ch; cligen_handle ch;
pt_head *ph; pt_head *ph;
ch = cli_cligen(h); ch = cli_cligen(h);
if (clicon_get_logflags()&CLICON_LOG_STDOUT) if (clicon_get_logflags()&CLICON_LOG_STDOUT)
f = stdout; f = stdout;
@ -546,10 +553,10 @@ clicon_parse(clicon_handle h,
if (cliread_parse(ch, cmd, pt, &match_obj, &cvv, result, &reason) < 0) if (cliread_parse(ch, cmd, pt, &match_obj, &cvv, result, &reason) < 0)
goto done; goto done;
/* Debug command and result code */ /* Debug command and result code */
clicon_debug(1, "%s result:%d command: \"%s\"", __FUNCTION__, *result, cmd); clixon_debug(CLIXON_DBG_DEFAULT, "%s result:%d command: \"%s\"", __FUNCTION__, *result, cmd);
switch (*result) { switch (*result) {
case CG_EOF: /* eof */ case CG_EOF: /* eof */
case CG_ERROR: case CG_ERROR:
fprintf(f, "CLI parse error: %s\n", cmd); // In practice never happens fprintf(f, "CLI parse error: %s\n", cmd); // In practice never happens
break; break;
case CG_NOMATCH: /* no match */ case CG_NOMATCH: /* no match */
@ -561,7 +568,7 @@ clicon_parse(clicon_handle h,
cli_set_syntax_mode(h, modename); cli_set_syntax_mode(h, modename);
} }
cli_output_reset(); cli_output_reset();
if (!cligen_exiting(ch)) { if (!cligen_exiting(ch)) {
clicon_err_reset(); clicon_err_reset();
if ((ret = cligen_eval(ch, match_obj, cvv)) < 0) { if ((ret = cligen_eval(ch, match_obj, cvv)) < 0) {
cli_handler_err(stdout); cli_handler_err(stdout);
@ -596,6 +603,7 @@ done:
} }
/*! Return a malloced expanded prompt string from printf-like format /*! Return a malloced expanded prompt string from printf-like format
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] fmt Format string, using %H, % * @param[in] fmt Format string, using %H, %
* @retval prompt Malloced string, free after use * @retval prompt Malloced string, free after use
@ -654,7 +662,7 @@ cli_prompt_get(clicon_handle h,
else else
cprintf(cb, "/"); cprintf(cb, "/");
break; break;
case 'w': /* Full Working edit path */ case 'w': /* Full Working edit path */
if (clicon_data_get(h, "cli-edit-mode", &path) == 0 && if (clicon_data_get(h, "cli-edit-mode", &path) == 0 &&
strlen(path)) strlen(path))
cprintf(cb, "%s", path); cprintf(cb, "%s", path);
@ -676,7 +684,7 @@ cli_prompt_get(clicon_handle h,
cprintf(cb, "%c", *s); cprintf(cb, "%c", *s);
} }
} }
else else
cprintf(cb, "%c", *s); cprintf(cb, "%c", *s);
s++; s++;
} }
@ -693,7 +701,7 @@ cli_prompt_get(clicon_handle h,
/*! Read command from CLIgen's cliread() using current syntax mode. /*! Read command from CLIgen's cliread() using current syntax mode.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] ph Parse-tree head * @param[in] ph Parse-tree head
* @param[out] stringp Pointer to command buffer or NULL on EOF * @param[out] stringp Pointer to command buffer or NULL on EOF
* @retval 1 OK * @retval 1 OK
@ -756,7 +764,8 @@ clicon_cliread(clicon_handle h,
*/ */
/*! Set syntax mode mode for existing current plugin group. /*! Set syntax mode mode for existing current plugin group.
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval 1 OK * @retval 1 OK
* @retval 0 Not found / error * @retval 0 Not found / error
*/ */
@ -774,13 +783,14 @@ cli_set_syntax_mode(clicon_handle h,
} }
/*! Get syntax mode name /*! Get syntax mode name
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
*/ */
char * char *
cli_syntax_mode(clicon_handle h) cli_syntax_mode(clicon_handle h)
{ {
pt_head *ph; pt_head *ph;
if ((ph = cligen_pt_head_active_get(cli_cligen(h))) == NULL) if ((ph = cligen_pt_head_active_get(cli_cligen(h))) == NULL)
return NULL; return NULL;
return cligen_ph_name_get(ph); return cligen_ph_name_get(ph);

View file

@ -182,7 +182,7 @@ xpath_append(cbuf *cb0,
free(prefix); free(prefix);
if (id) if (id)
free(id); free(id);
free(vec); free(vec);
return retval; return retval;
} }
@ -201,13 +201,15 @@ xpath_append(cbuf *cb0,
* [<mt-point>] Optional YANG path-arg/xpath from mount-point * [<mt-point>] Optional YANG path-arg/xpath from mount-point
* @param[out] commands vector of function pointers to callback functions * @param[out] commands vector of function pointers to callback functions
* @param[out] helptxt vector of pointers to helptexts * @param[out] helptxt vector of pointers to helptexts
* @retval 0 OK
* @retval -1 Error
* @see cli_expand_var_generate where api_path_fmt + mt-point are generated * @see cli_expand_var_generate where api_path_fmt + mt-point are generated
*/ */
int int
expand_dbvar(void *h, expand_dbvar(void *h,
char *name, char *name,
cvec *cvv, cvec *cvv,
cvec *argv, cvec *argv,
cvec *commands, cvec *commands,
cvec *helptexts) cvec *helptexts)
{ {
@ -246,7 +248,7 @@ expand_dbvar(void *h,
char *str; char *str;
int grouping_treeref; int grouping_treeref;
cvec *callback_cvv; cvec *callback_cvv;
if (argv == NULL || (cvec_len(argv) != 2 && cvec_len(argv) != 3)){ if (argv == NULL || (cvec_len(argv) != 2 && cvec_len(argv) != 3)){
clicon_err(OE_PLUGIN, EINVAL, "requires arguments: <db> <apipathfmt> [<mountpt>]"); clicon_err(OE_PLUGIN, EINVAL, "requires arguments: <db> <apipathfmt> [<mountpt>]");
goto done; goto done;
@ -263,7 +265,7 @@ expand_dbvar(void *h,
if (strcmp(dbstr, "running") != 0 && if (strcmp(dbstr, "running") != 0 &&
strcmp(dbstr, "candidate") != 0 && strcmp(dbstr, "candidate") != 0 &&
strcmp(dbstr, "startup") != 0){ strcmp(dbstr, "startup") != 0){
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr); clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
goto done; goto done;
} }
if ((cv = cvec_i(argv, 1)) == NULL){ if ((cv = cvec_i(argv, 1)) == NULL){
@ -273,18 +275,18 @@ expand_dbvar(void *h,
if (autocli_grouping_treeref(h, &grouping_treeref) < 0) if (autocli_grouping_treeref(h, &grouping_treeref) < 0)
goto done; goto done;
if ((api_path_fmt_cb = cbuf_new()) == NULL){ if ((api_path_fmt_cb = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "cbuf_new"); clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done; goto done;
} }
if (grouping_treeref && if (grouping_treeref &&
(callback_cvv = cligen_callback_arguments_get(cli_cligen(h))) != NULL){ (callback_cvv = cligen_callback_arguments_get(cli_cligen(h))) != NULL){
/* Concatenate callback arguments to a singel prepend string */ /* Concatenate callback arguments to a singel prepend string */
if (cvec_concat_cb(callback_cvv, api_path_fmt_cb) < 0) if (cvec_concat_cb(callback_cvv, api_path_fmt_cb) < 0)
goto done; goto done;
} }
cprintf(api_path_fmt_cb, "%s", cv_string_get(cv)); cprintf(api_path_fmt_cb, "%s", cv_string_get(cv));
api_path_fmt = cbuf_get(api_path_fmt_cb); api_path_fmt = cbuf_get(api_path_fmt_cb);
if (cvec_len(argv) > 2){ if (cvec_len(argv) > 2){
cv = cvec_i(argv, 2); cv = cvec_i(argv, 2);
str = cv_string_get(cv); str = cv_string_get(cv);
if (strncmp(str, "mtpoint:", strlen("mtpoint:")) != 0){ if (strncmp(str, "mtpoint:", strlen("mtpoint:")) != 0){
@ -379,13 +381,13 @@ expand_dbvar(void *h,
goto done; goto done;
} }
/* Get configuration based on cbxpath */ /* Get configuration based on cbxpath */
if (clicon_rpc_get_config(h, NULL, dbstr, cbuf_get(cbxpath), nsc, NULL, &xt) < 0) if (clicon_rpc_get_config(h, NULL, dbstr, cbuf_get(cbxpath), nsc, NULL, &xt) < 0)
goto done; goto done;
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){ if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
clixon_netconf_error(xe, "Get configuration", NULL); clixon_netconf_error(xe, "Get configuration", NULL);
goto ok; goto ok;
} }
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, cbuf_get(cbxpath)) < 0) if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, cbuf_get(cbxpath)) < 0)
goto done; goto done;
/* Loop for inserting into commands cvec. /* Loop for inserting into commands cvec.
* Detect duplicates: for ordered-by system assume list is ordered, so you need * Detect duplicates: for ordered-by system assume list is ordered, so you need
@ -446,15 +448,22 @@ expand_dbvar(void *h,
xml_free(xtop); xml_free(xtop);
if (xt) if (xt)
xml_free(xt); xml_free(xt);
if (xpath) if (xpath)
free(xpath); free(xpath);
return retval; return retval;
} }
/*! CLI callback show yang spec. If arg given matches yang argument string */ /*! CLI callback show yang spec. If arg given matches yang argument string
*
* @param[in] h Clixon handle
* @param[in] cvv Vector of command variables
* @param[in] argv
* @retval 0 OK
* @retval -1 Error
*/
int int
show_yang(clicon_handle h, show_yang(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
@ -462,7 +471,7 @@ show_yang(clicon_handle h,
char *str = NULL; char *str = NULL;
yang_stmt *yspec; yang_stmt *yspec;
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if (cvec_len(argv) > 0){ if (cvec_len(argv) > 0){
if ((str = cv_string_get(cvec_i(argv, 0))) != NULL && if ((str = cv_string_get(cvec_i(argv, 0))) != NULL &&
(yn = yang_find(yspec, 0, str)) != NULL) (yn = yang_find(yspec, 0, str)) != NULL)
@ -495,6 +504,8 @@ show_yang(clicon_handle h,
* @param[in] fromroot If 0, display config from node of XPATH, if 1 display from root * @param[in] fromroot If 0, display config from node of XPATH, if 1 display from root
* @param[in] nsc Namespace mapping for xpath * @param[in] nsc Namespace mapping for xpath
* @param[in] skiptop If set, do not show object itself, only its children * @param[in] skiptop If set, do not show object itself, only its children
* @retval 0 OK
* @retval -1 Error
*/ */
int int
cli_show_common(clicon_handle h, cli_show_common(clicon_handle h,
@ -511,7 +522,7 @@ cli_show_common(clicon_handle h,
int skiptop int skiptop
) )
{ {
int retval = -1; int retval = -1;
cxobj *xt = NULL; cxobj *xt = NULL;
cxobj *xerr; cxobj *xerr;
cxobj **vec = NULL; cxobj **vec = NULL;
@ -542,19 +553,19 @@ cli_show_common(clicon_handle h,
if (purge_tagged_nodes(xt, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE, "default", "true", if (purge_tagged_nodes(xt, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE, "default", "true",
strcmp(extdefault, "report-all-tagged-strip") strcmp(extdefault, "report-all-tagged-strip")
) < 0) ) < 0)
goto done; goto done;
/* Remove empty containers */ /* Remove empty containers */
if (xml_defaults_nopresence(xt, 2) < 0) if (xml_defaults_nopresence(xt, 2) < 0)
goto done; goto done;
} }
if (fromroot) if (fromroot)
xpath="/"; xpath="/";
if (xpath_vec(xt, nsc, "%s", &vec, &veclen, xpath) < 0) if (xpath_vec(xt, nsc, "%s", &vec, &veclen, xpath) < 0)
goto done; goto done;
if (veclen){ if (veclen){
/* Special case LIST */ /* Special case LIST */
if (format == FORMAT_JSON){ if (format == FORMAT_JSON){
switch (format){ switch (format){
case FORMAT_JSON: case FORMAT_JSON:
if (xml2json_vec(stdout, vec, veclen, pretty, cligen_output, skiptop) < 0) if (xml2json_vec(stdout, vec, veclen, pretty, cligen_output, skiptop) < 0)
goto done; goto done;
@ -619,7 +630,7 @@ done:
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int int
cli_show_option_format(cvec *argv, cli_show_option_format(cvec *argv,
int argc, int argc,
enum format_enum *format) enum format_enum *format)
@ -645,7 +656,7 @@ cli_show_option_format(cvec *argv,
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int int
cli_show_option_bool(cvec *argv, cli_show_option_bool(cvec *argv,
int argc, int argc,
int *result int *result
@ -685,7 +696,7 @@ cli_show_option_bool(cvec *argv,
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
int int
cli_show_option_withdefault(cvec *argv, cli_show_option_withdefault(cvec *argv,
int argc, int argc,
char **withdefault, char **withdefault,
@ -722,7 +733,7 @@ cli_show_option_withdefault(cvec *argv,
/*! Generic show configuration callback /*! Generic show configuration callback
* *
* Does not need to be used with the autocli as cli_show_auto does * Does not need to be used with the autocli as cli_show_auto does
* @param[in] h CLICON handle * @param[in] h Clixon handle
* @param[in] cvv Vector of variables from CLIgen command-line * @param[in] cvv Vector of variables from CLIgen command-line
* @param[in] argv String vector of show options, format: * @param[in] argv String vector of show options, format:
* <dbname> Name of datastore, such as "running" * <dbname> Name of datastore, such as "running"
@ -735,6 +746,8 @@ cli_show_option_withdefault(cvec *argv,
* <default> Retrieval mode: report-all, trim, explicit, report-all-tagged, * <default> Retrieval mode: report-all, trim, explicit, report-all-tagged,
* NULL, report-all-tagged-default, report-all-tagged-strip (extended) * NULL, report-all-tagged-default, report-all-tagged-strip (extended)
* <prepend> CLI prefix: prepend before cli syntax output * <prepend> CLI prefix: prepend before cli syntax output
* @retval 0 OK
* @retval -1 Error
* @code * @code
* clispec: * clispec:
* show config, cli_show_config("running","xml"); * show config, cli_show_config("running","xml");
@ -752,8 +765,8 @@ cli_show_option_withdefault(cvec *argv,
* @see cli_show_auto_mode autocli with edit menu support * @see cli_show_auto_mode autocli with edit menu support
*/ */
int int
cli_show_config(clicon_handle h, cli_show_config(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
@ -769,7 +782,7 @@ cli_show_config(clicon_handle h,
char *xpath = "/"; char *xpath = "/";
char *namespace = NULL; char *namespace = NULL;
int fromroot = 0; int fromroot = 0;
if (cvec_len(argv) < 2 || cvec_len(argv) > 8){ if (cvec_len(argv) < 2 || cvec_len(argv) > 8){
clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: <dbname> [<format><xpath> <namespace> <pretty> <state> <default> <prepend>]", cvec_len(argv)); clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: <dbname> [<format><xpath> <namespace> <pretty> <state> <default> <prepend>]", cvec_len(argv));
goto done; goto done;
@ -815,29 +828,18 @@ cli_show_config(clicon_handle h,
return retval; return retval;
} }
/*! Show configuration and state CLIGEN callback function /*! Show configuration xpath
* *
* @param[in] h CLICON handle * @param[in] h Clixon handle
* @param[in] cvv Vector of variables from CLIgen command-line * @param[in] cvv Vector of variables from CLIgen command-line
* @param[in] argv String vector of show options, format: * @param[in] argv String vector of show options, format:
* <dbname> "running"|"candidate"|"startup" * <dbname> "running"|"candidate"|"startup"
* @code * @retval 0 OK
* show config id <n:string>, cli_show_config("running","xml","iface[name='foo']","urn:example:example"); * @retval -1 Error
* @endcode
* @see cli_show_config_state For config and state data (not only config)
*/
/*! Show configuration as text given an xpath using canonical namespace
*
* Utility function used by cligen spec file
* @param[in] h CLICON handle
* @param[in] cvv Vector of variables from CLIgen command-line must contain xpath and default namespace (if any)
* @param[in] argv A string: <dbname>
* @note Different from cli_show_conf: values taken cvv "xpath" and "ns" instead of argv
*/ */
int int
show_conf_xpath(clicon_handle h, show_conf_xpath(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
@ -847,7 +849,7 @@ show_conf_xpath(clicon_handle h,
cvec *nsc = NULL; cvec *nsc = NULL;
yang_stmt *yspec; yang_stmt *yspec;
int fromroot = 0; int fromroot = 0;
if (cvec_len(argv) != 1){ if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, EINVAL, "Requires one element to be <dbname>"); clicon_err(OE_PLUGIN, EINVAL, "Requires one element to be <dbname>");
goto done; goto done;
@ -886,7 +888,7 @@ done:
*/ */
int int
cli_show_version(clicon_handle h, cli_show_version(clicon_handle h,
cvec *vars, cvec *cvv,
cvec *argv) cvec *argv)
{ {
cligen_output(stdout, "Clixon: %s\n", CLIXON_VERSION_STRING); cligen_output(stdout, "Clixon: %s\n", CLIXON_VERSION_STRING);
@ -914,6 +916,8 @@ cli_show_version(clicon_handle h,
* NULL, report-all-tagged-default, report-all-tagged-strip (extended) * NULL, report-all-tagged-default, report-all-tagged-strip (extended)
* <prepend> CLI prefix: prepend before cli syntax output * <prepend> CLI prefix: prepend before cli syntax output
* <fromroot> true|false: Show from root * <fromroot> true|false: Show from root
* @retval 0 OK
* @retval -1 Error
* @code * @code
* clispec: * clispec:
* show config @datamodelshow, cli_show_auto("candidate", "xml"); * show config @datamodelshow, cli_show_auto("candidate", "xml");
@ -931,7 +935,7 @@ cli_show_version(clicon_handle h,
* XXX merge cli_show_auto and cli_show_auto_mode * XXX merge cli_show_auto and cli_show_auto_mode
* @see cli_callback_generate where api_path_fmt + mt-point are generated * @see cli_callback_generate where api_path_fmt + mt-point are generated
*/ */
int int
cli_show_auto(clicon_handle h, cli_show_auto(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
@ -955,7 +959,7 @@ cli_show_auto(clicon_handle h,
char *str; char *str;
char *mtpoint = NULL; char *mtpoint = NULL;
int fromroot = 0; int fromroot = 0;
if (cvec_len(argv) < 2 || cvec_len(argv) > 9){ if (cvec_len(argv) < 2 || cvec_len(argv) > 9){
clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected:: <api-path-fmt>* <database> [<format> <pretty> <state> <default> <prepend> <fromroot>]", cvec_len(argv)); clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected:: <api-path-fmt>* <database> [<format> <pretty> <state> <default> <prepend> <fromroot>]", cvec_len(argv));
goto done; goto done;
@ -996,7 +1000,7 @@ cli_show_auto(clicon_handle h,
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
} }
if (mtpoint){ if (mtpoint){
/* Get and combined api-path01 */ /* Get and combined api-path01 */
if (mtpoint_paths(yspec0, mtpoint, api_path_fmt, &api_path_fmt01) < 0) if (mtpoint_paths(yspec0, mtpoint, api_path_fmt, &api_path_fmt01) < 0)
goto done; goto done;
@ -1046,6 +1050,8 @@ cli_show_auto(clicon_handle h,
* <default> Retrieval mode: report-all, trim, explicit, report-all-tagged, * <default> Retrieval mode: report-all, trim, explicit, report-all-tagged,
* NULL, report-all-tagged-default, report-all-tagged-strip (extended) * NULL, report-all-tagged-default, report-all-tagged-strip (extended)
* <prepend> CLI prefix: prepend before cli syntax output * <prepend> CLI prefix: prepend before cli syntax output
* @retval 0 OK
* @retval -1 Error
* @cli_show_auto_ctrl * @cli_show_auto_ctrl
code code
* clispec: * clispec:
@ -1088,7 +1094,7 @@ cli_show_auto_mode(clicon_handle h,
cvec *nsc0 = NULL; cvec *nsc0 = NULL;
cg_var *cv; cg_var *cv;
int fromroot = 0; int fromroot = 0;
if (cvec_len(argv) < 2 || cvec_len(argv) > 7){ if (cvec_len(argv) < 2 || cvec_len(argv) > 7){
clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: <database> [ <format> <pretty> <state> <default> <cli-prefix>]", cvec_len(argv)); clicon_err(OE_PLUGIN, EINVAL, "Received %d arguments. Expected: <database> [ <format> <pretty> <state> <default> <cli-prefix>]", cvec_len(argv));
goto done; goto done;
@ -1142,7 +1148,7 @@ cli_show_auto_mode(clicon_handle h,
goto done; goto done;
} }
if (mtpoint){ if (mtpoint){
cprintf(cbxpath, "%s", mtpoint); cprintf(cbxpath, "%s", mtpoint);
if (xml_nsctx_yangspec(yspec0, &nsc0) < 0) if (xml_nsctx_yangspec(yspec0, &nsc0) < 0)
goto done; goto done;
cv = NULL; /* Append cvv1 to cvv2 */ cv = NULL; /* Append cvv1 to cvv2 */
@ -1170,9 +1176,14 @@ cli_show_auto_mode(clicon_handle h,
/*! Show clixon configuration options as loaded /*! Show clixon configuration options as loaded
* *
* @param[in] h Clixon handle
* @param[in] cvv Vector of command variables
* @param[in] argv
* @retval 0 OK
* @retval -1 Error
'* @see clicon_option_dump clicon_option_dump1 '* @see clicon_option_dump clicon_option_dump1
*/ */
int int
cli_show_options(clicon_handle h, cli_show_options(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
@ -1185,7 +1196,7 @@ cli_show_options(clicon_handle h,
size_t klen; size_t klen;
size_t vlen; size_t vlen;
cxobj *x = NULL; cxobj *x = NULL;
if (clicon_hash_keys(hash, &keys, &klen) < 0) if (clicon_hash_keys(hash, &keys, &klen) < 0)
goto done; goto done;
for(i = 0; i < klen; i++) { for(i = 0; i < klen; i++) {
@ -1228,9 +1239,12 @@ cli_show_options(clicon_handle h,
} }
/*! Show pagination /*! Show pagination
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] cvv Vector of cli string and instantiated variables * @param[in] cvv Vector of cli string and instantiated variables
* @param[in] argv Vector. Format: <xpath> <prefix> <namespace> <format> <limit> * @param[in] argv Vector. Format: <xpath> <prefix> <namespace> <format> <limit>
* @retval 0 OK
* @retval -1 Error
* Also, if there is a cligen variable called "xpath" it will override argv xpath arg * Also, if there is a cligen variable called "xpath" it will override argv xpath arg
*/ */
int int
@ -1239,7 +1253,7 @@ cli_pagination(clicon_handle h,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
cbuf *cb = NULL; cbuf *cb = NULL;
char *xpath = NULL; char *xpath = NULL;
char *prefix = NULL; char *prefix = NULL;
char *namespace = NULL; char *namespace = NULL;
@ -1256,7 +1270,7 @@ cli_pagination(clicon_handle h,
cxobj **xvec = NULL; cxobj **xvec = NULL;
size_t xlen; size_t xlen;
int locked = 0; int locked = 0;
if (cvec_len(argv) != 5){ if (cvec_len(argv) != 5){
clicon_err(OE_PLUGIN, 0, "Expected usage: <xpath> <prefix> <namespace> <format> <limit>"); clicon_err(OE_PLUGIN, 0, "Expected usage: <xpath> <prefix> <namespace> <format> <limit>");
goto done; goto done;
@ -1363,7 +1377,7 @@ cli_pagination(clicon_handle h,
* *
* Howto: join strings and pass them down. * Howto: join strings and pass them down.
* Identify unique/index keywords for correct set syntax. * Identify unique/index keywords for correct set syntax.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in,out] cb Cligen buffer to write to * @param[in,out] cb Cligen buffer to write to
* @param[in] xn XML Parse-tree (to translate) * @param[in] xn XML Parse-tree (to translate)
* @param[in] prepend Print this text in front of all commands. * @param[in] prepend Print this text in front of all commands.
@ -1421,7 +1435,7 @@ cli2cbuf(clicon_handle h,
} }
/* Create prepend variable string */ /* Create prepend variable string */
if ((cbpre = cbuf_new()) == NULL){ if ((cbpre = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "cbuf_new"); clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done; goto done;
} }
if (prepend) if (prepend)
@ -1466,7 +1480,7 @@ cli2cbuf(clicon_handle h,
/* For lists, print cbpre before its elements */ /* For lists, print cbpre before its elements */
if (yang_keyword_get(ys) == Y_LIST) if (yang_keyword_get(ys) == Y_LIST)
cprintf(cb, "%s\n", cbuf_get(cbpre)); cprintf(cb, "%s\n", cbuf_get(cbpre));
/* Then loop through all other (non-keys) */ /* Then loop through all other (non-keys) */
xe = NULL; xe = NULL;
while ((xe = xml_child_each(xn, xe, -1)) != NULL){ while ((xe = xml_child_each(xn, xe, -1)) != NULL){
@ -1491,15 +1505,17 @@ cli2cbuf(clicon_handle h,
* *
* Howto: join strings and pass them down. * Howto: join strings and pass them down.
* Identify unique/index keywords for correct set syntax. * Identify unique/index keywords for correct set syntax.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] f Output FILE (eg stdout) * @param[in] f Output FILE (eg stdout)
* @param[in] xn XML Parse-tree (to translate) * @param[in] xn XML Parse-tree (to translate)
* @param[in] prepend Print this text in front of all commands. * @param[in] prepend Print this text in front of all commands.
* @param[in] fn Callback to make print function * @param[in] fn Callback to make print function
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
cli2file(clicon_handle h, cli2file(clicon_handle h,
FILE *f, FILE *f,
cxobj *xn, cxobj *xn,
char *prepend, char *prepend,
clicon_output_cb *fn) clicon_output_cb *fn)
@ -1548,7 +1564,7 @@ cli2file(clicon_handle h,
} }
/* Create prepend variable string */ /* Create prepend variable string */
if ((cbpre = cbuf_new()) == NULL){ if ((cbpre = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "cbuf_new"); clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done; goto done;
} }
if (prepend) if (prepend)
@ -1593,7 +1609,7 @@ cli2file(clicon_handle h,
/* For lists, print cbpre before its elements */ /* For lists, print cbpre before its elements */
if (yang_keyword_get(ys) == Y_LIST) if (yang_keyword_get(ys) == Y_LIST)
(*fn)(f, "%s\n", cbuf_get(cbpre)); (*fn)(f, "%s\n", cbuf_get(cbpre));
/* Then loop through all other (non-keys) */ /* Then loop through all other (non-keys) */
xe = NULL; xe = NULL;
while ((xe = xml_child_each(xn, xe, -1)) != NULL){ while ((xe = xml_child_each(xn, xe, -1)) != NULL){
@ -1618,7 +1634,7 @@ cli2file(clicon_handle h,
* *
* Howto: join strings and pass them down. * Howto: join strings and pass them down.
* Identify unique/index keywords for correct set syntax. * Identify unique/index keywords for correct set syntax.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] f Output FILE (eg stdout) * @param[in] f Output FILE (eg stdout)
* @param[in] xn XML Parse-tree (to translate) * @param[in] xn XML Parse-tree (to translate)
* @param[in] prepend Print this text in front of all commands. * @param[in] prepend Print this text in front of all commands.
@ -1630,7 +1646,7 @@ cli2file(clicon_handle h,
*/ */
int int
clixon_cli2file(clicon_handle h, clixon_cli2file(clicon_handle h,
FILE *f, FILE *f,
cxobj *xn, cxobj *xn,
char *prepend, char *prepend,
clicon_output_cb *fn, clicon_output_cb *fn,
@ -1660,7 +1676,7 @@ clixon_cli2file(clicon_handle h,
* *
* Howto: join strings and pass them down. * Howto: join strings and pass them down.
* Identify unique/index keywords for correct set syntax. * Identify unique/index keywords for correct set syntax.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] f Output FILE (eg stdout) * @param[in] f Output FILE (eg stdout)
* @param[in] xn XML Parse-tree (to translate) * @param[in] xn XML Parse-tree (to translate)
* @param[in] prepend Print this text in front of all commands. * @param[in] prepend Print this text in front of all commands.
@ -1698,8 +1714,8 @@ clixon_cli2cbuf(clicon_handle h,
/*! CLI callback show statistics /*! CLI callback show statistics
*/ */
int int
cli_show_statistics(clicon_handle h, cli_show_statistics(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
@ -1712,7 +1728,7 @@ cli_show_statistics(clicon_handle h,
parse_tree *pt; parse_tree *pt;
uint64_t nr = 0; uint64_t nr = 0;
size_t sz = 0; size_t sz = 0;
if (argv != NULL && cvec_len(argv) != 1){ if (argv != NULL && cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, EINVAL, "Expected arguments: [modules]"); clicon_err(OE_PLUGIN, EINVAL, "Expected arguments: [modules]");
goto done; goto done;
@ -1734,7 +1750,7 @@ cli_show_statistics(clicon_handle h,
nr = 0; sz = 0; nr = 0; sz = 0;
pt_stats(pt, &nr, &sz); pt_stats(pt, &nr, &sz);
cligen_output(stdout, "%s: nr=%" PRIu64 " size:%zu\n", cligen_output(stdout, "%s: nr=%" PRIu64 " size:%zu\n",
cligen_ph_name_get(ph), nr, sz); cligen_ph_name_get(ph), nr, sz);
} }
/* Backend */ /* Backend */
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE); cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);

View file

@ -50,6 +50,7 @@ extern "C" {
*/ */
/*! Called when plugin loaded. Only mandadory callback. All others optional /*! Called when plugin loaded. Only mandadory callback. All others optional
*
* @see plginit_t * @see plginit_t
*/ */
int plugin_init(clicon_handle h); int plugin_init(clicon_handle h);

View file

@ -43,10 +43,11 @@
* Types * Types
*/ */
/*! Autocli list keyword type, see clixon-autocli.yang list-keyword-type /*! Autocli list keyword type, see clixon-autocli.yang list-keyword-type
*
* Assume a YANG LIST: * Assume a YANG LIST:
* list a { * list a {
* key x; * key x;
* leaf x; * leaf x;
* leaf y; * leaf y;
* } * }
* Maybe this type should be in cli_autocli.h * Maybe this type should be in cli_autocli.h
@ -77,7 +78,7 @@ cligen_handle cli_cligen(clicon_handle h);
/* cli_common.c */ /* cli_common.c */
int cli_notification_register(clicon_handle h, char *stream, enum format_enum format, int cli_notification_register(clicon_handle h, char *stream, enum format_enum format,
char *filter, int status, char *filter, int status,
int (*fn)(int, void*), void *arg); int (*fn)(int, void*), void *arg);
int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01); int mtpoint_paths(yang_stmt *yspec0, char *mtpoint, char *api_path_fmt1, char **api_path_fmt01);
@ -115,7 +116,7 @@ int cvec_concat_cb(cvec *cvv, cbuf *cb);
int cli_process_control(clicon_handle h, cvec *vars, cvec *argv); int cli_process_control(clicon_handle h, cvec *vars, cvec *argv);
/* In cli_show.c */ /* In cli_show.c */
int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv, int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv,
cvec *commands, cvec *helptexts); cvec *commands, cvec *helptexts);
int clixon_cli2file(clicon_handle h, FILE *f, cxobj *xn, char *prepend, clicon_output_cb *fn, int skiptop); int clixon_cli2file(clicon_handle h, FILE *f, cxobj *xn, char *prepend, clicon_output_cb *fn, int skiptop);
int clixon_cli2cbuf(clicon_handle h, cbuf *cb, cxobj *xn, char *prepend, int skiptop); int clixon_cli2cbuf(clicon_handle h, cbuf *cb, cxobj *xn, char *prepend, int skiptop);

View file

@ -46,8 +46,8 @@
* (Duplicated. Also in netconf_*.h) * (Duplicated. Also in netconf_*.h)
*/ */
int netconf_xpath(cxobj *xsearch, int netconf_xpath(cxobj *xsearch,
cxobj *xfilter, cxobj *xfilter,
cbuf *xf, cbuf *xf_err, cbuf *xf, cbuf *xf_err,
cxobj *xt); cxobj *xt);

View file

@ -97,16 +97,17 @@ leafstring(cxobj *x)
} }
/*! Internal recursive part where configuration xml tree is pruned from filter /*! Internal recursive part where configuration xml tree is pruned from filter
*
* assume parent has been selected and filter match (same name) as parent * assume parent has been selected and filter match (same name) as parent
* parent is pruned according to selection. * parent is pruned according to selection.
* @param[in] xfilter Filter xml * @param[in] xfilter Filter xml
* @param[out] xconf Configuration xml * @param[out] xconf Configuration xml
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
xml_filter_recursive(cxobj *xfilter, xml_filter_recursive(cxobj *xfilter,
cxobj *xparent, cxobj *xparent,
int *remove_me) int *remove_me)
{ {
cxobj *s; cxobj *s;
@ -122,7 +123,7 @@ xml_filter_recursive(cxobj *xfilter,
*remove_me = 0; *remove_me = 0;
/* 1. Check selection */ /* 1. Check selection */
if (xml_child_nr(xfilter) == 0) if (xml_child_nr(xfilter) == 0)
goto match; goto match;
/* Count containment/selection nodes in filter */ /* Count containment/selection nodes in filter */
@ -190,6 +191,7 @@ xml_filter_recursive(cxobj *xfilter,
} }
/*! Remove parts of configuration xml tree that does not match filter xml tree /*! Remove parts of configuration xml tree that does not match filter xml tree
*
* @param[in] xfilter Filter xml * @param[in] xfilter Filter xml
* @param[out] xconf Configuration xml * @param[out] xconf Configuration xml
* @retval 0 OK * @retval 0 OK
@ -197,15 +199,15 @@ xml_filter_recursive(cxobj *xfilter,
* This is the top-level function, calls a recursive variant. * This is the top-level function, calls a recursive variant.
*/ */
int int
xml_filter(cxobj *xfilter, xml_filter(cxobj *xfilter,
cxobj *xconfig) cxobj *xconfig)
{ {
int retval; int retval;
int remove_s; int remove_s;
/* Call recursive variant */ /* Call recursive variant */
retval = xml_filter_recursive(xfilter, retval = xml_filter_recursive(xfilter,
xconfig, xconfig,
&remove_s); &remove_s);
return retval; return retval;
} }

View file

@ -41,7 +41,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int xml_filter(cxobj *xf, cxobj *xn); int xml_filter(cxobj *xf, cxobj *xn);
#endif /* _NETCONF_FILTER_H_ */ #endif /* _NETCONF_FILTER_H_ */

View file

@ -99,6 +99,8 @@ static int _netconf_hello_nr = 0;
* includes any "xmlns" attributes. * includes any "xmlns" attributes.
* @param[in] xrpc Incoming message on the form <rpc>... * @param[in] xrpc Incoming message on the form <rpc>...
* @param[in,out] xrep Reply message on the form <rpc-reply>... * @param[in,out] xrep Reply message on the form <rpc-reply>...
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
netconf_add_request_attr(cxobj *xrpc, netconf_add_request_attr(cxobj *xrpc,
@ -133,9 +135,14 @@ netconf_add_request_attr(cxobj *xrpc,
} }
/*! Process netconf hello message /*! Process netconf hello message
*
* A server receiving a <hello> message with a <session-id> element MUST * A server receiving a <hello> message with a <session-id> element MUST
* terminate the NETCONF session. * terminate the NETCONF session.
* @param[out] eof Request termination * @param[in] h Clixon handle
* @param[in] xn
* @param[out] eof Request termination
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
netconf_hello_msg(clicon_handle h, netconf_hello_msg(clicon_handle h,
@ -152,7 +159,7 @@ netconf_hello_msg(clicon_handle h,
int foundbase_11 = 0; int foundbase_11 = 0;
char *body; char *body;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
_netconf_hello_nr++; _netconf_hello_nr++;
if (xml_find_type(xn, NULL, "session-id", CX_ELMNT) != NULL) { if (xml_find_type(xn, NULL, "session-id", CX_ELMNT) != NULL) {
clicon_err(OE_XML, errno, "Server received hello with session-id from client, terminating (see RFC 6241 Sec 8.1"); clicon_err(OE_XML, errno, "Server received hello with session-id from client, terminating (see RFC 6241 Sec 8.1");
@ -172,12 +179,12 @@ netconf_hello_msg(clicon_handle h,
* event any parameters are encoded at the end of the URI string. */ * event any parameters are encoded at the end of the URI string. */
if (strncmp(body, NETCONF_BASE_CAPABILITY_1_0, strlen(NETCONF_BASE_CAPABILITY_1_0)) == 0){ /* RFC 4741 */ if (strncmp(body, NETCONF_BASE_CAPABILITY_1_0, strlen(NETCONF_BASE_CAPABILITY_1_0)) == 0){ /* RFC 4741 */
foundbase_10++; foundbase_10++;
clicon_debug(1, "%s foundbase10", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s foundbase10", __FUNCTION__);
} }
else if (strncmp(body, NETCONF_BASE_CAPABILITY_1_1, strlen(NETCONF_BASE_CAPABILITY_1_1)) == 0 && else if (strncmp(body, NETCONF_BASE_CAPABILITY_1_1, strlen(NETCONF_BASE_CAPABILITY_1_1)) == 0 &&
clicon_option_int(h, "CLICON_NETCONF_BASE_CAPABILITY") > 0){ /* RFC 6241 */ clicon_option_int(h, "CLICON_NETCONF_BASE_CAPABILITY") > 0){ /* RFC 6241 */
foundbase_11++; foundbase_11++;
clicon_debug(1, "%s foundbase11", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s foundbase11", __FUNCTION__);
clicon_data_int_set(h, NETCONF_FRAMING_TYPE, NETCONF_SSH_CHUNKED); /* enable chunked enc */ clicon_data_int_set(h, NETCONF_FRAMING_TYPE, NETCONF_SSH_CHUNKED); /* enable chunked enc */
} }
} }
@ -195,6 +202,7 @@ netconf_hello_msg(clicon_handle h,
} }
/*! Process incoming Netconf RPC netconf message /*! Process incoming Netconf RPC netconf message
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xreq XML tree containing netconf RPC message * @param[in] xreq XML tree containing netconf RPC message
* @param[in] yspec YANG spec * @param[in] yspec YANG spec
@ -223,7 +231,7 @@ netconf_rpc_message(clicon_handle h,
/* Copy attributes from incoming request to reply. Skip already present (dont overwrite) */ /* Copy attributes from incoming request to reply. Skip already present (dont overwrite) */
if (netconf_add_request_attr(xrpc, xret) < 0) if (netconf_add_request_attr(xrpc, xret) < 0)
goto done; goto done;
if ((cbret = cbuf_new()) == NULL){ if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
@ -239,12 +247,12 @@ netconf_rpc_message(clicon_handle h,
if ((ret = xml_bind_yang_rpc(h, xrpc, yspec, &xret)) < 0) if ((ret = xml_bind_yang_rpc(h, xrpc, yspec, &xret)) < 0)
goto done; goto done;
if (ret > 0 && if (ret > 0 &&
(ret = xml_yang_validate_rpc(h, xrpc, 0, &xret)) < 0) (ret = xml_yang_validate_rpc(h, xrpc, 0, &xret)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
if (netconf_add_request_attr(xrpc, xret) < 0) if (netconf_add_request_attr(xrpc, xret) < 0)
goto done; goto done;
if ((cbret = cbuf_new()) == NULL){ if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
@ -265,7 +273,7 @@ netconf_rpc_message(clicon_handle h,
goto done; goto done;
if (netconf_add_request_attr(xrpc, xret) < 0) if (netconf_add_request_attr(xrpc, xret) < 0)
goto done; goto done;
if ((cbret = cbuf_new()) == NULL){ if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
@ -281,7 +289,7 @@ netconf_rpc_message(clicon_handle h,
/* Copy attributes from incoming request to reply. Skip already present (dont overwrite) */ /* Copy attributes from incoming request to reply. Skip already present (dont overwrite) */
if (netconf_add_request_attr(xrpc, xc) < 0) if (netconf_add_request_attr(xrpc, xc) < 0)
goto done; goto done;
if ((cbret = cbuf_new()) == NULL){ if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
@ -303,6 +311,7 @@ netconf_rpc_message(clicon_handle h,
} }
/*! Process incoming a single netconf message parsed as XML /*! Process incoming a single netconf message parsed as XML
*
* Identify what netconf message it is * Identify what netconf message it is
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] xreq XML tree containing netconf * @param[in] xreq XML tree containing netconf
@ -325,8 +334,8 @@ netconf_input_packet(clicon_handle h,
cxobj *xret = NULL; cxobj *xret = NULL;
netconf_framing_type framing; netconf_framing_type framing;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
clicon_debug_xml(1, xreq, "%s", __FUNCTION__); clixon_debug_xml(1, xreq, "%s", __FUNCTION__);
rpcname = xml_name(xreq); rpcname = xml_name(xreq);
rpcprefix = xml_prefix(xreq); rpcprefix = xml_prefix(xreq);
framing = clicon_data_int_get(h, NETCONF_FRAMING_TYPE); framing = clicon_data_int_get(h, NETCONF_FRAMING_TYPE);
@ -339,7 +348,7 @@ netconf_input_packet(clicon_handle h,
goto done; goto done;
if (netconf_add_request_attr(xreq, xret) < 0) if (netconf_add_request_attr(xreq, xret) < 0)
goto done; goto done;
if ((cbret = cbuf_new()) == NULL){ if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
goto done; goto done;
} }
@ -381,8 +390,11 @@ netconf_input_packet(clicon_handle h,
} }
/*! Get netconf message: detect end-of-msg /*! Get netconf message: detect end-of-msg
* @param[in] s Socket where input arrived. read from this. *
* @param[in] arg Clixon handle. * @param[in] s Socket where input arrived. read from this.
* @param[in] arg Clixon handle.
* @retval 0 OK
* @retval -1 Error
* This routine continuously reads until no more data on s. There could * This routine continuously reads until no more data on s. There could
* be risk of starvation, but the netconf client does little else than * be risk of starvation, but the netconf client does little else than
* read data so I do not see a danger of true starvation here. * read data so I do not see a danger of true starvation here.
@ -418,7 +430,7 @@ netconf_input_cb(int s,
unsigned char *p = buf; unsigned char *p = buf;
ssize_t len; ssize_t len;
size_t plen; size_t plen;
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
/* Get unfinished frame */ /* Get unfinished frame */
if ((ptr = clicon_hash_value(cdat, NETCONF_FRAME_MSG, &cdatlen)) != NULL){ if ((ptr = clicon_hash_value(cdat, NETCONF_FRAME_MSG, &cdatlen)) != NULL){
@ -457,14 +469,14 @@ netconf_input_cb(int s,
&eom) < 0) &eom) < 0)
goto done; goto done;
if (eom == 0){ /* frame not complete */ if (eom == 0){ /* frame not complete */
clicon_debug(CLIXON_DBG_DETAIL, "%s: frame: %lu", __FUNCTION__, cbuf_len(cbmsg)); clixon_debug(CLIXON_DBG_DETAIL, "%s: frame: %lu", __FUNCTION__, cbuf_len(cbmsg));
/* Extra data to read, save data and continue on next round */ /* Extra data to read, save data and continue on next round */
if (clicon_hash_add(cdat, NETCONF_FRAME_MSG, &cbmsg, sizeof(cbmsg)) == NULL) if (clicon_hash_add(cdat, NETCONF_FRAME_MSG, &cbmsg, sizeof(cbmsg)) == NULL)
goto done; goto done;
cbmsg = NULL; cbmsg = NULL;
break; break;
} }
clicon_debug(CLIXON_DBG_MSG, "Recv ext: %s", cbuf_get(cbmsg)); clixon_debug(CLIXON_DBG_MSG, "Recv ext: %s", cbuf_get(cbmsg));
if ((ret = netconf_input_frame2(cbmsg, YB_RPC, yspec, &xtop, &xerr)) < 0) if ((ret = netconf_input_frame2(cbmsg, YB_RPC, yspec, &xtop, &xerr)) < 0)
goto done; goto done;
cbuf_reset(cbmsg); cbuf_reset(cbmsg);
@ -499,7 +511,7 @@ netconf_input_cb(int s,
} }
} }
if (eof){ /* socket closed / read returns 0 */ if (eof){ /* socket closed / read returns 0 */
clicon_debug(1, "%s len==0, closing", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s len==0, closing", __FUNCTION__);
clixon_event_unreg_fd(s, netconf_input_cb); clixon_event_unreg_fd(s, netconf_input_cb);
close(s); close(s);
clixon_exit_set(1); clixon_exit_set(1);
@ -522,16 +534,19 @@ netconf_input_cb(int s,
} }
/*! Send netconf hello message /*! Send netconf hello message
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] s File descriptor to write on (eg 1 - stdout) * @param[in] s File descriptor to write on (eg 1 - stdout)
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
send_hello(clicon_handle h, send_hello(clicon_handle h,
int s, int s,
uint32_t id) uint32_t id)
{ {
int retval = -1; int retval = -1;
cbuf *cb; cbuf *cb;
netconf_framing_type framing; netconf_framing_type framing;
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
@ -553,6 +568,7 @@ send_hello(clicon_handle h,
} }
/*! Clean and close all state of netconf process (but dont exit). /*! Clean and close all state of netconf process (but dont exit).
*
* Cannot use h after this * Cannot use h after this
* @param[in] h Clixon handle * @param[in] h Clixon handle
*/ */
@ -562,7 +578,7 @@ netconf_terminate(clicon_handle h)
yang_stmt *yspec; yang_stmt *yspec;
cvec *nsctx; cvec *nsctx;
cxobj *x; cxobj *x;
if (clixon_exit_get() == 0) if (clixon_exit_get() == 0)
clixon_exit_set(1); clixon_exit_set(1);
/* Delete all plugins, and RPC callbacks */ /* Delete all plugins, and RPC callbacks */
@ -591,7 +607,7 @@ static int
netconf_signal_init (clicon_handle h) netconf_signal_init (clicon_handle h)
{ {
int retval = -1; int retval = -1;
if (set_signal(SIGPIPE, SIG_IGN, NULL) < 0){ if (set_signal(SIGPIPE, SIG_IGN, NULL) < 0){
clicon_err(OE_UNIX, errno, "Setting DIGPIPE signal"); clicon_err(OE_UNIX, errno, "Setting DIGPIPE signal");
goto done; goto done;
@ -606,10 +622,11 @@ timeout_fn(int s,
void *arg) void *arg)
{ {
clicon_err(OE_EVENTS, ETIMEDOUT, "User request timeout"); clicon_err(OE_EVENTS, ETIMEDOUT, "User request timeout");
return -1; return -1;
} }
/*! Usage help routine /*! Usage help routine
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] argv0 command line * @param[in] argv0 command line
*/ */
@ -666,12 +683,12 @@ main(int argc,
size_t sz; size_t sz;
int config_dump = 0; int config_dump = 0;
enum format_enum config_dump_format = FORMAT_XML; enum format_enum config_dump_format = FORMAT_XML;
/* Create handle */ /* Create handle */
if ((h = clicon_handle_init()) == NULL) if ((h = clicon_handle_init()) == NULL)
return -1; return -1;
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
/* Set username to clixon handle. Use in all communication to backend */ /* Set username to clixon handle. Use in all communication to backend */
if ((pw = getpwuid(getuid())) == NULL){ if ((pw = getpwuid(getuid())) == NULL){
@ -712,14 +729,14 @@ main(int argc,
/* /*
* Logs, error and debug to stderr or syslog, set debug level * Logs, error and debug to stderr or syslog, set debug level
*/ */
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst); clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
yang_init(h); yang_init(h);
/* Find, read and parse configfile */ /* Find, read and parse configfile */
if (clicon_options_main(h) < 0) if (clicon_options_main(h) < 0)
goto done; goto done;
/* Now rest of options */ /* Now rest of options */
optind = 1; optind = 1;
opterr = 0; opterr = 0;
@ -822,23 +839,23 @@ main(int argc,
/* Setup signal handlers, int particular PIPE that occurs if backend closes / restarts */ /* Setup signal handlers, int particular PIPE that occurs if backend closes / restarts */
if (netconf_signal_init(h) < 0) if (netconf_signal_init(h) < 0)
goto done; goto done;
/* Initialize plugin module by creating a handle holding plugin and callback lists */ /* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0) if (clixon_plugin_module_init(h) < 0)
goto done; goto done;
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */ /* In case ietf-yang-metadata is loaded by application, handle annotation extension */
if (yang_metadata_init(h) < 0) if (yang_metadata_init(h) < 0)
goto done; goto done;
/* Create top-level yang spec and store as option */ /* Create top-level yang spec and store as option */
if ((yspec = yspec_new()) == NULL) if ((yspec = yspec_new()) == NULL)
goto done; goto done;
clicon_dbspec_yang_set(h, yspec); clicon_dbspec_yang_set(h, yspec);
/* Load netconf plugins before yangs are loaded (eg extension callbacks) */ /* Load netconf plugins before yangs are loaded (eg extension callbacks) */
if ((dir = clicon_netconf_dir(h)) != NULL && if ((dir = clicon_netconf_dir(h)) != NULL &&
clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0) clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
goto done; goto done;
/* Load Yang modules /* Load Yang modules
* 1. Load a yang module as a specific absolute filename */ * 1. Load a yang module as a specific absolute filename */
if ((str = clicon_yang_main_file(h)) != NULL){ if ((str = clicon_yang_main_file(h)) != NULL){
@ -865,7 +882,7 @@ main(int argc,
/* Add netconf yang spec, used by netconf client and as internal protocol */ /* Add netconf yang spec, used by netconf client and as internal protocol */
if (netconf_module_load(h) < 0) if (netconf_module_load(h) < 0)
goto done; goto done;
/* Here all modules are loaded /* Here all modules are loaded
* Compute and set canonical namespace context * Compute and set canonical namespace context
*/ */
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0) if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
@ -894,7 +911,7 @@ main(int argc,
if (clicon_hello_req(h, "cl:netconf", NULL, &id) < 0) if (clicon_hello_req(h, "cl:netconf", NULL, &id) < 0)
goto done; goto done;
clicon_session_id_set(h, id); clicon_session_id_set(h, id);
/* Send hello to northbound client /* Send hello to northbound client
* Note that this is a violation of RDFC 6241 Sec 8.1: * Note that this is a violation of RDFC 6241 Sec 8.1:
* When the NETCONF session is opened, each peer(both client and server) MUST send a <hello.. * When the NETCONF session is opened, each peer(both client and server) MUST send a <hello..

View file

@ -80,13 +80,13 @@
*/ */
static int static int
netconf_get_config_subtree(clicon_handle h, netconf_get_config_subtree(clicon_handle h,
cxobj *xfilter, cxobj *xfilter,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
cxobj *xdata; cxobj *xdata;
/* a subtree filter is comprised of zero or more element subtrees*/ /* a subtree filter is comprised of zero or more element subtrees*/
if ((xdata = xpath_first(*xret, NULL, "/rpc-reply/data")) == NULL) if ((xdata = xpath_first(*xret, NULL, "/rpc-reply/data")) == NULL)
goto ok; goto ok;
@ -107,9 +107,12 @@ ok:
} }
/*! Get configuration /*! Get configuration
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] xn Sub-tree (under xorig) at <rpc>...</rpc> level. * @param[in] xn Sub-tree (under xorig) at <rpc>...</rpc> level.
* @param[out] xret Return XML, error or OK * @param[out] xret Return XML, error or OK
* @retval 0 OK
* @retval -1 Error
* @note filter type subtree and xpath is supported, but xpath is preferred, and * @note filter type subtree and xpath is supported, but xpath is preferred, and
* better performance and tested. Please use xpath. * better performance and tested. Please use xpath.
* *
@ -155,8 +158,8 @@ ok:
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface/ipv4"/></get-config></rpc>]]>]]> <rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface/ipv4"/></get-config></rpc>]]>]]>
*/ */
static int static int
netconf_get_config(clicon_handle h, netconf_get_config(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
@ -206,13 +209,14 @@ netconf_get_config(clicon_handle h,
} }
/*! Get options from netconf edit-config /*! Get options from netconf edit-config
*
* @param[in] xn Sub-tree (under xorig) at <rpc>...</rpc> level. * @param[in] xn Sub-tree (under xorig) at <rpc>...</rpc> level.
* @param[out] op Operation type, eg merge,replace,... * @param[out] op Operation type, eg merge,replace,...
* @param[out] testopt test option, eg set, test * @param[out] testopt test option, eg set, test
* @param[out] erropt Error option, eg stop-on-error * @param[out] erropt Error option, eg stop-on-error
* @retval -1 Fatal Error
* @retval 0 parameter error, xret returns error
* @retval 1 OK, op, testopt and erropt set * @retval 1 OK, op, testopt and erropt set
* @retval 0 parameter error, xret returns error
* @retval -1 Fatal Error
* @example * @example
* <edit-config> * <edit-config>
* <config>...</config> * <config>...</config>
@ -230,7 +234,7 @@ get_edit_opts(cxobj *xn,
int retval = -1; int retval = -1;
cxobj *x; cxobj *x;
char *optstr; char *optstr;
if ((x = xpath_first(xn, NULL, "test-option")) != NULL){ if ((x = xpath_first(xn, NULL, "test-option")) != NULL){
if ((optstr = xml_body(x)) != NULL){ if ((optstr = xml_body(x)) != NULL){
if (strcmp(optstr, "test-then-set") == 0) if (strcmp(optstr, "test-then-set") == 0)
@ -267,6 +271,7 @@ get_edit_opts(cxobj *xn,
} }
/*! Netconf edit configuration /*! Netconf edit configuration
*
Write the change on a tmp file, then load that into candidate configuration. Write the change on a tmp file, then load that into candidate configuration.
<edit-config> <edit-config>
<target> <target>
@ -317,7 +322,7 @@ CLIXON addition:
*/ */
static int static int
netconf_edit_config(clicon_handle h, netconf_edit_config(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
@ -353,9 +358,11 @@ netconf_edit_config(clicon_handle h,
/*! Get running configuration and device state information /*! Get running configuration and device state information
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xn Sub-tree (under xorig) at <rpc>...</rpc> level. * @param[in] xn Sub-tree (under xorig) at <rpc>...</rpc> level.
* @param[out] xret Return XML, error or OK * @param[out] xret Return XML, error or OK
* @retval 0 OK
* @retval -1 Error
* @note filter type subtree and xpath is supported, but xpath is preferred, and * @note filter type subtree and xpath is supported, but xpath is preferred, and
* better performance and tested. Please use xpath. * better performance and tested. Please use xpath.
* *
@ -364,8 +371,8 @@ netconf_edit_config(clicon_handle h,
* </get></rpc>]]>]]> * </get></rpc>]]>]]>
*/ */
static int static int
netconf_get(clicon_handle h, netconf_get(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
@ -409,11 +416,12 @@ netconf_get(clicon_handle h,
retval = 0; retval = 0;
done: done:
if(nsc) if(nsc)
cvec_free(nsc); cvec_free(nsc);
return retval; return retval;
} }
/*! Called when a notification has happened on backend /*! Called when a notification has happened on backend
*
* and this session has registered for that event. * and this session has registered for that event.
* Filter it and forward it. * Filter it and forward it.
<notification> <notification>
@ -436,7 +444,7 @@ netconf_get(clicon_handle h,
* beyond the scope of this document. * beyond the scope of this document.
*/ */
static int static int
netconf_notification_cb(int s, netconf_notification_cb(int s,
void *arg) void *arg)
{ {
struct clicon_msg *reply = NULL; struct clicon_msg *reply = NULL;
@ -449,9 +457,9 @@ netconf_notification_cb(int s,
yang_stmt *yspec = NULL; yang_stmt *yspec = NULL;
cvec *nsc = NULL; cvec *nsc = NULL;
int ret; int ret;
cxobj *xerr = NULL; cxobj *xerr = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* get msg (this is the reason this function is called) */ /* get msg (this is the reason this function is called) */
if (clicon_msg_rcv(s, NULL, 0, &reply, &eof) < 0) if (clicon_msg_rcv(s, NULL, 0, &reply, &eof) < 0)
goto done; goto done;
@ -464,7 +472,7 @@ netconf_notification_cb(int s,
goto done; goto done;
} }
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if ((ret = clicon_msg_decode(reply, yspec, NULL, &xt, &xerr)) < 0) if ((ret = clicon_msg_decode(reply, yspec, NULL, &xt, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ /* XXX use xerr */ if (ret == 0){ /* XXX use xerr */
clicon_err(OE_NETCONF, EFAULT, "Notification malformed"); clicon_err(OE_NETCONF, EFAULT, "Notification malformed");
@ -496,7 +504,7 @@ netconf_notification_cb(int s,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
if (nsc) if (nsc)
@ -524,12 +532,12 @@ netconf_notification_cb(int s,
* @see netconf_notification_cb for asynchronous stream notifications * @see netconf_notification_cb for asynchronous stream notifications
*/ */
static int static int
netconf_create_subscription(clicon_handle h, netconf_create_subscription(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
cxobj *xfilter; cxobj *xfilter;
int s; int s;
char *ftype; char *ftype;
@ -552,8 +560,8 @@ netconf_create_subscription(clicon_handle h,
goto done; goto done;
if (xpath_first(*xret, NULL, "rpc-reply/rpc-error") != NULL) if (xpath_first(*xret, NULL, "rpc-reply/rpc-error") != NULL)
goto ok; goto ok;
if (clixon_event_reg_fd(s, if (clixon_event_reg_fd(s,
netconf_notification_cb, netconf_notification_cb,
h, h,
"notification socket") < 0) "notification socket") < 0)
goto done; goto done;
@ -571,15 +579,14 @@ netconf_create_subscription(clicon_handle h,
* @param[in] h clicon handle * @param[in] h clicon handle
* @param[in] xn Sub-tree (under xorig) at child of rpc: <rpc><xn></rpc>. * @param[in] xn Sub-tree (under xorig) at child of rpc: <rpc><xn></rpc>.
* @param[out] xret Return XML, error or OK * @param[out] xret Return XML, error or OK
*
* @retval -1 Error
* @retval 0 OK, not found handler.
* @retval 1 OK, handler called * @retval 1 OK, handler called
* @retval 0 OK, not found handler.
* @retval -1 Error
* @see netconf_input_packet Assume bind and validation made there * @see netconf_input_packet Assume bind and validation made there
*/ */
static int static int
netconf_application_rpc(clicon_handle h, netconf_application_rpc(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret) cxobj **xret)
{ {
int retval = -1; int retval = -1;
@ -593,7 +600,7 @@ netconf_application_rpc(clicon_handle h,
cbuf *cbret = NULL; cbuf *cbret = NULL;
int ret; int ret;
int nr = 0; int nr = 0;
/* First check system / netconf RPC:s */ /* First check system / netconf RPC:s */
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, 0, "cbuf_new"); clicon_err(OE_UNIX, 0, "cbuf_new");
@ -658,7 +665,7 @@ netconf_application_rpc(clicon_handle h,
goto done; goto done;
if (ret == 0){ if (ret == 0){
if (clixon_xml2cbuf(cbret, xerr, 0, 0, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cbret, xerr, 0, 0, NULL, -1, 0) < 0)
goto done; goto done;
clicon_log(LOG_WARNING, "Errors in output netconf %s", cbuf_get(cbret)); clicon_log(LOG_WARNING, "Errors in output netconf %s", cbuf_get(cbret));
goto ok; goto ok;
} }
@ -679,6 +686,7 @@ netconf_application_rpc(clicon_handle h,
} }
/*! The central netconf rpc dispatcher. Look at first tag and dispach to sub-functions. /*! The central netconf rpc dispatcher. Look at first tag and dispach to sub-functions.
*
* Call plugin handler if tag not found. If not handled by any handler, return * Call plugin handler if tag not found. If not handled by any handler, return
* error. * error.
* @param[in] h clicon handle * @param[in] h clicon handle
@ -690,7 +698,7 @@ netconf_application_rpc(clicon_handle h,
*/ */
int int
netconf_rpc_dispatch(clicon_handle h, netconf_rpc_dispatch(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret, cxobj **xret,
int *eof) int *eof)
{ {
@ -698,7 +706,7 @@ netconf_rpc_dispatch(clicon_handle h,
cxobj *xe; cxobj *xe;
char *username; char *username;
cxobj *xa; cxobj *xa;
/* Tag username on all incoming requests in case they are forwarded as internal messages /* Tag username on all incoming requests in case they are forwarded as internal messages
* This may be unecesary since not all are forwarded. * This may be unecesary since not all are forwarded.
* It may even be wrong if something else is done with the incoming message? * It may even be wrong if something else is done with the incoming message?
@ -721,12 +729,12 @@ netconf_rpc_dispatch(clicon_handle h,
strcmp(xml_name(xe), "kill-session") == 0 || strcmp(xml_name(xe), "kill-session") == 0 ||
strcmp(xml_name(xe), "validate") == 0 || /* :validate */ strcmp(xml_name(xe), "validate") == 0 || /* :validate */
strcmp(xml_name(xe), "commit") == 0 || /* :candidate */ strcmp(xml_name(xe), "commit") == 0 || /* :candidate */
strcmp(xml_name(xe), "cancel-commit") == 0 || strcmp(xml_name(xe), "cancel-commit") == 0 ||
strcmp(xml_name(xe), "discard-changes") == 0 || strcmp(xml_name(xe), "discard-changes") == 0 ||
strcmp(xml_name(xe), "action") == 0 strcmp(xml_name(xe), "action") == 0
){ ){
if (clicon_rpc_netconf_xml(h, xml_parent(xe), xret, NULL) < 0) if (clicon_rpc_netconf_xml(h, xml_parent(xe), xret, NULL) < 0)
goto done; goto done;
} }
else if (strcmp(xml_name(xe), "get-config") == 0){ else if (strcmp(xml_name(xe), "get-config") == 0){
if (netconf_get_config(h, xe, xret) < 0) if (netconf_get_config(h, xe, xret) < 0)
@ -743,7 +751,7 @@ netconf_rpc_dispatch(clicon_handle h,
else if (strcmp(xml_name(xe), "close-session") == 0){ else if (strcmp(xml_name(xe), "close-session") == 0){
*eof = 1; /* Pending close */ *eof = 1; /* Pending close */
if (clicon_rpc_netconf_xml(h, xml_parent(xe), xret, NULL) < 0) if (clicon_rpc_netconf_xml(h, xml_parent(xe), xret, NULL) < 0)
goto done; goto done;
} }
/* RFC 5277 :notification */ /* RFC 5277 :notification */
else if (strcmp(xml_name(xe), "create-subscription") == 0){ else if (strcmp(xml_name(xe), "create-subscription") == 0){

View file

@ -41,10 +41,10 @@
/* /*
* Prototypes * Prototypes
*/ */
int int
netconf_rpc_dispatch(clicon_handle h, netconf_rpc_dispatch(clicon_handle h,
cxobj *xn, cxobj *xn,
cxobj **xret, cxobj **xret,
int *eof); int *eof);

View file

@ -39,7 +39,7 @@
/* /*
* Types * Types
*/ */
struct clixon_http1_yacc { struct clixon_http1_yacc {
const char *hy_name; /* Name of syntax (for error string) */ const char *hy_name; /* Name of syntax (for error string) */
clicon_handle hy_h; /* Clixon handle */ clicon_handle hy_h; /* Clixon handle */
restconf_conn *hy_rc; /* Connection handle */ restconf_conn *hy_rc; /* Connection handle */

View file

@ -75,7 +75,7 @@
#define _HY ((clixon_http1_yacc *)_hy) #define _HY ((clixon_http1_yacc *)_hy)
#undef clixon_api_path_parsewrap #undef clixon_api_path_parsewrap
int int
clixon_http1_parsewrap(void) clixon_http1_parsewrap(void)
{ {
return 1; return 1;
@ -100,35 +100,35 @@ query [A-Za-z0-9\-\._~!$&'()*+,;=:@?/]|%[0-9a-fA-F][0-9a-fA-F]
<REQLINE,REQTARG,REQUERY,REQHTTP,FLDNAME,FLDVALUE><<EOF>> { return X_EOF; } <REQLINE,REQTARG,REQUERY,REQHTTP,FLDNAME,FLDVALUE><<EOF>> { return X_EOF; }
<REQLINE>[ ] { BEGIN(REQTARG); return SP; } <REQLINE>[ ] { BEGIN(REQTARG); return SP; }
<REQLINE>{token} { clixon_http1_parselval.string = strdup(yytext); <REQLINE>{token} { clixon_http1_parselval.string = strdup(yytext);
return TOKEN; } return TOKEN; }
<REQLINE>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; } <REQLINE>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; }
<REQTARG>\? { BEGIN(REQUERY); return QMARK; } <REQTARG>\? { BEGIN(REQUERY); return QMARK; }
<REQTARG>\/ { return SLASH; } <REQTARG>\/ { return SLASH; }
<REQTARG>[ ] { BEGIN(REQHTTP); return SP; } <REQTARG>[ ] { BEGIN(REQHTTP); return SP; }
<REQTARG>{pchar}+ { clixon_http1_parselval.string = yytext; <REQTARG>{pchar}+ { clixon_http1_parselval.string = yytext;
return PCHARS; } return PCHARS; }
<REQTARG>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; } <REQTARG>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; }
<REQUERY>\/ { return SLASH; } <REQUERY>\/ { return SLASH; }
<REQUERY>[ ] { BEGIN(REQHTTP); return SP; } <REQUERY>[ ] { BEGIN(REQHTTP); return SP; }
<REQUERY>{query}+ { clixon_http1_parselval.string = strdup(yytext); <REQUERY>{query}+ { clixon_http1_parselval.string = strdup(yytext);
return QUERY; } return QUERY; }
<REQUERY>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; } <REQUERY>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; }
<REQHTTP>\r\n { BEGIN(FLDNAME); return CRLF; _HY->hy_linenum++; } <REQHTTP>\r\n { BEGIN(FLDNAME); return CRLF; _HY->hy_linenum++; }
<REQHTTP>\/ { return SLASH; } <REQHTTP>\/ { return SLASH; }
<REQHTTP>\. { return DOT; } <REQHTTP>\. { return DOT; }
<REQHTTP>HTTP { BEGIN(REQHTTP); return HTTP; } <REQHTTP>HTTP { BEGIN(REQHTTP); return HTTP; }
<REQHTTP>[0-9] { clixon_http1_parselval.intval = atoi(yytext); <REQHTTP>[0-9] { clixon_http1_parselval.intval = atoi(yytext);
return DIGIT; } return DIGIT; }
<REQHTTP>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; } <REQHTTP>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; }
<FLDNAME>: { BEGIN(FLDVALUE); return COLON; } <FLDNAME>: { BEGIN(FLDVALUE); return COLON; }
<FLDNAME>\r\n { BEGIN(BODYM); return CRLF; _HY->hy_linenum++; } <FLDNAME>\r\n { BEGIN(BODYM); return CRLF; _HY->hy_linenum++; }
<FLDNAME>[ \t]+ { return RWS; } <FLDNAME>[ \t]+ { return RWS; }
<FLDNAME>{token} { clixon_http1_parselval.string = strdup(yytext); <FLDNAME>{token} { clixon_http1_parselval.string = strdup(yytext);
return TOKEN; } return TOKEN; }
<FLDNAME>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; } <FLDNAME>. { clixon_http1_parseerror(_HY, "LEXICAL ERROR\n"); return -1; }
<FLDVALUE>\r\n { BEGIN(FLDNAME); return CRLF; _HY->hy_linenum++; } <FLDVALUE>\r\n { BEGIN(FLDNAME); return CRLF; _HY->hy_linenum++; }
@ -141,7 +141,7 @@ query [A-Za-z0-9\-\._~!$&'()*+,;=:@?/]|%[0-9a-fA-F][0-9a-fA-F]
return BODY; } return BODY; }
<BODYM>\n { clixon_http1_parselval.string = strdup(yytext); <BODYM>\n { clixon_http1_parselval.string = strdup(yytext);
_HY->hy_linenum++; _HY->hy_linenum++;
return BODY; } return BODY; }
<BODYM><<EOF>> { return X_EOF; } <BODYM><<EOF>> { return X_EOF; }
%% %%
@ -155,7 +155,7 @@ http1_scan_init(clixon_http1_yacc *hy)
hy->hy_lexbuf = yy_scan_string(hy->hy_parse_string); hy->hy_lexbuf = yy_scan_string(hy->hy_parse_string);
#if 1 /* XXX: just to use unput to avoid warning */ #if 1 /* XXX: just to use unput to avoid warning */
if (0) if (0)
yyunput(0, ""); yyunput(0, "");
#endif #endif
return 0; return 0;
@ -172,4 +172,3 @@ http1_scan_exit(clixon_http1_yacc *hy)
clixon_http1_parselex_destroy(); /* modern */ clixon_http1_parselex_destroy(); /* modern */
return 0; return 0;
} }

View file

@ -81,7 +81,7 @@
#define _YYERROR(msg) {clicon_err(OE_XML, 0, "YYERROR %s '%s' %d", (msg), clixon_http1_parsetext, _HY->hy_linenum); YYERROR;} #define _YYERROR(msg) {clicon_err(OE_XML, 0, "YYERROR %s '%s' %d", (msg), clixon_http1_parsetext, _HY->hy_linenum); YYERROR;}
/* add _yy to error parameters */ /* add _yy to error parameters */
#define YY_(msgid) msgid #define YY_(msgid) msgid
#include "clixon_config.h" #include "clixon_config.h"
@ -106,29 +106,29 @@
/* Best debugging is to enable PARSE_DEBUG below and add -d to the LEX compile statement in the Makefile /* Best debugging is to enable PARSE_DEBUG below and add -d to the LEX compile statement in the Makefile
* And then run the testcase with -D 1 * And then run the testcase with -D 1
* Disable it to stop any calls to clicon_debug. Having it on by default would mean very large debug outputs. * Disable it to stop any calls to clixon_debug. Having it on by default would mean very large debug outputs.
*/ */
#if 0 #if 0
#define _PARSE_DEBUG(s) clicon_debug(1,(s)) #define _PARSE_DEBUG(s) clixon_debug(1,(s))
#define _PARSE_DEBUG1(s, s1) clicon_debug(1,(s), (s1)) #define _PARSE_DEBUG1(s, s1) clixon_debug(1,(s), (s1))
#else #else
#define _PARSE_DEBUG(s) #define _PARSE_DEBUG(s)
#define _PARSE_DEBUG1(s, s1) #define _PARSE_DEBUG1(s, s1)
#endif #endif
/* /*
also called from yacc generated code * also called from yacc generated code *
*/ */
void void
clixon_http1_parseerror(void *_hy, clixon_http1_parseerror(void *_hy,
char *s) char *s)
{ {
clicon_err(OE_RESTCONF, 0, "%s on line %d: %s at or before: '%s'", clicon_err(OE_RESTCONF, 0, "%s on line %d: %s at or before: '%s'",
_HY->hy_name, _HY->hy_name,
_HY->hy_linenum , _HY->hy_linenum,
s, s,
clixon_http1_parsetext); clixon_http1_parsetext);
return; return;
} }
@ -151,7 +151,7 @@ http1_parse_query(clixon_http1_yacc *hy,
int retval = -1; int retval = -1;
restconf_stream_data *sd = NULL; restconf_stream_data *sd = NULL;
clicon_debug(1, "%s: ?%s ", __FUNCTION__, query); clixon_debug(CLIXON_DBG_DEFAULT, "%s: ?%s ", __FUNCTION__, query);
if ((sd = restconf_stream_find(hy->hy_rc, 0)) == NULL){ if ((sd = restconf_stream_find(hy->hy_rc, 0)) == NULL){
clicon_err(OE_RESTCONF, 0, "stream 0 not found"); clicon_err(OE_RESTCONF, 0, "stream 0 not found");
goto done; goto done;
@ -170,7 +170,7 @@ http1_body(clixon_http1_yacc *hy,
int retval = -1; int retval = -1;
restconf_stream_data *sd = NULL; restconf_stream_data *sd = NULL;
clicon_debug(1, "%s: %s ", __FUNCTION__, body); clixon_debug(CLIXON_DBG_DEFAULT, "%s: %s ", __FUNCTION__, body);
if ((sd = restconf_stream_find(hy->hy_rc, 0)) == NULL){ if ((sd = restconf_stream_find(hy->hy_rc, 0)) == NULL){
clicon_err(OE_RESTCONF, 0, "stream 0 not found"); clicon_err(OE_RESTCONF, 0, "stream 0 not found");
goto done; goto done;
@ -200,11 +200,11 @@ http1_parse_header_field(clixon_http1_yacc *hy,
return retval; return retval;
} }
%} %}
%% %%
/* start-line *( header-field CRLF ) CRLF [ message-body ] /* start-line *( header-field CRLF ) CRLF [ message-body ]
* start-line = request-line / status-line (only request-line here, ignore status-line) * start-line = request-line / status-line (only request-line here, ignore status-line)
*/ */
http_message : request_line header_fields CRLF body X_EOF http_message : request_line header_fields CRLF body X_EOF
@ -215,7 +215,7 @@ http_message : request_line header_fields CRLF body X_EOF
} }
_PARSE_DEBUG("http-message -> request-line header-fields body"); _PARSE_DEBUG("http-message -> request-line header-fields body");
YYACCEPT; YYACCEPT;
} }
; ;
body : body BODY body : body BODY
@ -224,22 +224,22 @@ body : body BODY
free($2); free($2);
YYABORT; YYABORT;
} }
else else
free($2); free($2);
_PARSE_DEBUG("body -> body BODY"); _PARSE_DEBUG("body -> body BODY");
} }
| ERROR { _PARSE_DEBUG("body -> ERROR"); YYABORT; /* shouldnt happen */ } | ERROR { _PARSE_DEBUG("body -> ERROR"); YYABORT; /* shouldnt happen */ }
| { _PARSE_DEBUG("body -> "); $$ = NULL; } | { _PARSE_DEBUG("body -> "); $$ = NULL; }
; ;
/* request-line = method SP request-target SP HTTP-version CRLF */ /* request-line = method SP request-target SP HTTP-version CRLF */
request_line : method SP request_target SP HTTP_version CRLF request_line : method SP request_target SP HTTP_version CRLF
{ {
_PARSE_DEBUG("request-line -> method request-target HTTP_version CRLF"); _PARSE_DEBUG("request-line -> method request-target HTTP_version CRLF");
} }
; ;
/* /*
The request methods defined by this specification can be found in The request methods defined by this specification can be found in
Section 4 of [RFC7231], along with information regarding the HTTP Section 4 of [RFC7231], along with information regarding the HTTP
http://www.iana.org/assignments/http-methods/http-methods.xhtml http://www.iana.org/assignments/http-methods/http-methods.xhtml
@ -331,7 +331,7 @@ HTTP_version : HTTP SLASH DIGIT DOT DIGIT
/* make sanity check later */ /* make sanity check later */
_HY->hy_rc->rc_proto_d1 = $3; _HY->hy_rc->rc_proto_d1 = $3;
_HY->hy_rc->rc_proto_d2 = $5; _HY->hy_rc->rc_proto_d2 = $5;
clicon_debug(1, "clixon_http1_parse: http/%d.%d", $3, $5); clixon_debug(CLIXON_DBG_DEFAULT, "clixon_http1_parse: http/%d.%d", $3, $5);
_PARSE_DEBUG("HTTP-version -> HTTP / DIGIT . DIGIT"); _PARSE_DEBUG("HTTP-version -> HTTP / DIGIT . DIGIT");
} }
; ;
@ -388,7 +388,7 @@ field_vchars : field_vchars RWS VCHARS
RWS = 1*( SP / HTAB ) RWS = 1*( SP / HTAB )
; required whitespace ; required whitespace
*/ */
ows : RWS ows : RWS
| |
; ;

View file

@ -87,8 +87,8 @@ static const map_str2str mime_map[] = {
/*! Check if uri path denotes a data path /*! Check if uri path denotes a data path
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval 0 No, not a data path, or not enabled
* @retval 1 Yes, a data path and "data" points to www-data if given * @retval 1 Yes, a data path and "data" points to www-data if given
* @retval 0 No, not a data path, or not enabled
*/ */
int int
api_path_is_data(clicon_handle h) api_path_is_data(clicon_handle h)
@ -103,7 +103,7 @@ api_path_is_data(clicon_handle h)
goto done; goto done;
if ((http_data_path = clicon_option_str(h, "CLICON_HTTP_DATA_PATH")) == NULL) if ((http_data_path = clicon_option_str(h, "CLICON_HTTP_DATA_PATH")) == NULL)
goto done; goto done;
if (strlen(path) < strlen(http_data_path)) if (strlen(path) < strlen(http_data_path))
goto done; goto done;
if (path[0] != '/') if (path[0] != '/')
goto done; goto done;
@ -117,6 +117,7 @@ api_path_is_data(clicon_handle h)
} }
/*! Generic restconf error function on get/head request /*! Generic restconf error function on get/head request
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic http handle * @param[in] req Generic http handle
* @param[in] code Error code * @param[in] code Error code
@ -130,7 +131,7 @@ api_http_data_err(clicon_handle h,
int retval = -1; int retval = -1;
cbuf *cb = NULL; cbuf *cb = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
@ -152,23 +153,24 @@ api_http_data_err(clicon_handle h,
// ok: // ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
return retval; return retval;
} }
/*! Check validity of path, may only be regular dir or file /*! Check validity of path, may only be regular dir or file
*
* No .., soft link, ~, etc * No .., soft link, ~, etc
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] prefix Prefix of path0, where to start file check * @param[in] prefix Prefix of path0, where to start file check
* @param[in,out] cbpath Filepath as cbuf, internal redirection may change it * @param[in,out] cbpath Filepath as cbuf, internal redirection may change it
* @param[out] fp Open file, if retval = 1 * @param[out] fp Open file, if retval = 1
* @param[out] fsz Size of file, if retval = 1 * @param[out] fsz Size of file, if retval = 1
* @retval -1 Error
* @retval 0 Invalid
* @retval 1 OK, fp,fsz set * @retval 1 OK, fp,fsz set
* @retval 0 Invalid
* @retval -1 Error
*/ */
static int static int
http_data_check_file_path(clicon_handle h, http_data_check_file_path(clicon_handle h,
@ -190,7 +192,7 @@ http_data_check_file_path(clicon_handle h,
goto done; goto done;
} }
p = cbuf_get(cbpath); p = cbuf_get(cbpath);
clicon_debug(1, "%s %s", __FUNCTION__, p); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, p);
if (strncmp(prefix, p, strlen(prefix)) != 0){ if (strncmp(prefix, p, strlen(prefix)) != 0){
clicon_err(OE_UNIX, EINVAL, "prefix is not prefix of cbpath"); clicon_err(OE_UNIX, EINVAL, "prefix is not prefix of cbpath");
goto done; goto done;
@ -200,31 +202,31 @@ http_data_check_file_path(clicon_handle h,
p[i] = '\0'; p[i] = '\0';
/* Ensure not soft link */ /* Ensure not soft link */
if (lstat(p, &fstat) < 0){ if (lstat(p, &fstat) < 0){
clicon_debug(1, "%s Error lstat(%s):%s", __FUNCTION__, p, strerror(errno)); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s):%s", __FUNCTION__, p, strerror(errno));
code = 404; code = 404;
goto invalid; goto invalid;
} }
if (!S_ISDIR(fstat.st_mode)){ if (!S_ISDIR(fstat.st_mode)){
clicon_debug(1, "%s Error lstat(%s): Not dir", __FUNCTION__, p); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s): Not dir", __FUNCTION__, p);
code = 403; code = 403;
goto invalid; goto invalid;
} }
p[i] = '/'; p[i] = '/';
} }
else if (p[i] == '~'){ else if (p[i] == '~'){
clicon_debug(1, "%s Error lstat(%s): ~ not allowed in file path", __FUNCTION__, p); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s): ~ not allowed in file path", __FUNCTION__, p);
code = 403; code = 403;
goto invalid; goto invalid;
} }
else if (p[i] == '.' && i>strlen(prefix) && p[i-1] == '.'){ else if (p[i] == '.' && i>strlen(prefix) && p[i-1] == '.'){
clicon_debug(1, "%s Error lstat(%s): .. not allowed in file path", __FUNCTION__, p); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s): .. not allowed in file path", __FUNCTION__, p);
code = 403; code = 403;
goto invalid; goto invalid;
} }
} }
/* Resulting file (ensure not soft link) */ /* Resulting file (ensure not soft link) */
if (lstat(p, &fstat) < 0){ if (lstat(p, &fstat) < 0){
clicon_debug(1, "%s Error lstat(%s):%s", __FUNCTION__, p, strerror(errno)); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s):%s", __FUNCTION__, p, strerror(errno));
code = 404; code = 404;
goto invalid; goto invalid;
} }
@ -233,22 +235,22 @@ http_data_check_file_path(clicon_handle h,
if (S_ISDIR(fstat.st_mode)){ if (S_ISDIR(fstat.st_mode)){
cprintf(cbpath, "/%s", HTTP_DATA_INTERNAL_REDIRECT); cprintf(cbpath, "/%s", HTTP_DATA_INTERNAL_REDIRECT);
p = cbuf_get(cbpath); p = cbuf_get(cbpath);
clicon_debug(1, "%s internal redirect: %s", __FUNCTION__, p); clixon_debug(CLIXON_DBG_DEFAULT, "%s internal redirect: %s", __FUNCTION__, p);
if (lstat(p, &fstat) < 0){ if (lstat(p, &fstat) < 0){
clicon_debug(1, "%s Error lstat(%s):%s", __FUNCTION__, p, strerror(errno)); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s):%s", __FUNCTION__, p, strerror(errno));
code = 404; code = 404;
goto invalid; goto invalid;
} }
} }
#endif #endif
if (!S_ISREG(fstat.st_mode)){ if (!S_ISREG(fstat.st_mode)){
clicon_debug(1, "%s Error lstat(%s): Not regular file", __FUNCTION__, p); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error lstat(%s): Not regular file", __FUNCTION__, p);
code = 403; code = 403;
goto invalid; goto invalid;
} }
*fsz = fstat.st_size; *fsz = fstat.st_size;
if ((f = fopen(p, "rb")) == NULL){ if ((f = fopen(p, "rb")) == NULL){
clicon_debug(1, "%s Error fopen(%s) %s", __FUNCTION__, p, strerror(errno)); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error fopen(%s) %s", __FUNCTION__, p, strerror(errno));
code = 403; code = 403;
goto invalid; goto invalid;
} }
@ -257,17 +259,20 @@ http_data_check_file_path(clicon_handle h,
done: done:
return retval; return retval;
invalid: invalid:
if (api_http_data_err(h, req, code) < 0) if (api_http_data_err(h, req, code) < 0)
goto done; goto done;
retval = 0; retval = 0;
goto done; goto done;
} }
/*! Read file data request /*! Read file data request
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] pathname With stripped prefix (eg /data), ultimately a filename * @param[in] pathname With stripped prefix (eg /data), ultimately a filename
* @param[in] head HEAD not GET * @param[in] head HEAD not GET
* @retval 0 OK
* @retval -1 Error
* @note: primitive file handling, just check if file exists and read it all * @note: primitive file handling, just check if file exists and read it all
* XXX 1: Buffer copying once too many, see #if 0 below * XXX 1: Buffer copying once too many, see #if 0 below
*/ */
@ -291,7 +296,7 @@ api_http_data_file(clicon_handle h,
char *buf = NULL; char *buf = NULL;
size_t sz; size_t sz;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((cbfile = cbuf_new()) == NULL){ if ((cbfile = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
@ -304,9 +309,9 @@ api_http_data_file(clicon_handle h,
cprintf(cbfile, "%s", www_data_root); cprintf(cbfile, "%s", www_data_root);
if (pathname){ if (pathname){
if (strlen(pathname) && pathname[0] != '/'){ if (strlen(pathname) && pathname[0] != '/'){
clicon_debug(1, "%s Error fopen(%s) pathname not prefixed with /", clixon_debug(CLIXON_DBG_DEFAULT, "%s Error fopen(%s) pathname not prefixed with /",
__FUNCTION__, pathname); __FUNCTION__, pathname);
if (api_http_data_err(h, req, 404) < 0) if (api_http_data_err(h, req, 404) < 0)
goto done; goto done;
goto ok; goto ok;
} }
@ -333,7 +338,7 @@ api_http_data_file(clicon_handle h,
fsize = ftell(f); fsize = ftell(f);
/* Extra sanity check, had some problems with wrong file types */ /* Extra sanity check, had some problems with wrong file types */
if (fsz != fsize){ if (fsz != fsize){
clicon_debug(1, "%s Error file %s size mismatch sz:%zu vs %li", clixon_debug(CLIXON_DBG_DEFAULT, "%s Error file %s size mismatch sz:%zu vs %li",
__FUNCTION__, filename, (size_t)fsz, fsize); __FUNCTION__, filename, (size_t)fsz, fsize);
if (api_http_data_err(h, req, 500) < 0) /* Internal error? */ if (api_http_data_err(h, req, 500) < 0) /* Internal error? */
goto done; goto done;
@ -357,7 +362,7 @@ api_http_data_file(clicon_handle h,
} }
sz = (size_t)ret; sz = (size_t)ret;
if (sz != 1){ if (sz != 1){
clicon_debug(1, "%s Error fread(%s) sz:%zu", __FUNCTION__, filename, sz); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error fread(%s) sz:%zu", __FUNCTION__, filename, sz);
if (api_http_data_err(h, req, 500) < 0) /* Internal error? */ if (api_http_data_err(h, req, 500) < 0) /* Internal error? */
goto done; goto done;
goto ok; goto ok;
@ -371,7 +376,7 @@ api_http_data_file(clicon_handle h,
if (restconf_reply_send(req, 200, cbdata, head) < 0) if (restconf_reply_send(req, 200, cbdata, head) < 0)
goto done; goto done;
cbdata = NULL; /* consumed by reply-send */ cbdata = NULL; /* consumed by reply-send */
clicon_debug(1, "%s Read %s OK", __FUNCTION__, filename); clixon_debug(CLIXON_DBG_DEFAULT, "%s Read %s OK", __FUNCTION__, filename);
ok: ok:
retval = 0; retval = 0;
done: done:
@ -396,10 +401,12 @@ api_http_data_file(clicon_handle h,
* 5. indata should be NULL (no write operations) * 5. indata should be NULL (no write operations)
* 6. Limited media: text/html, JavaScript, image, and css * 6. Limited media: text/html, JavaScript, image, and css
* 7. Authentication as restconf * 7. Authentication as restconf
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff * @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff
* @param[in] pathname With stripped prefix (eg /data), ultimately a filename * @param[in] pathname With stripped prefix (eg /data), ultimately a filename
* @retval 0 OK
* @retval -1 Error
* Need to enable clixon-restconf.yang www-data feature * Need to enable clixon-restconf.yang www-data feature
*/ */
int int
@ -416,7 +423,7 @@ api_http_data(clicon_handle h,
cbuf *indata = NULL; cbuf *indata = NULL;
char *path = NULL; char *path = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (req == NULL){ if (req == NULL){
errno = EINVAL; errno = EINVAL;
goto done; goto done;
@ -442,7 +449,7 @@ api_http_data(clicon_handle h,
else { else {
if (api_http_data_err(h, req, 405) < 0) /* method not allowed */ if (api_http_data_err(h, req, 405) < 0) /* method not allowed */
goto done; goto done;
goto ok; goto ok;
} }
/* 3. query parameters not accepted */ /* 3. query parameters not accepted */
if (qvec != NULL){ if (qvec != NULL){
@ -460,7 +467,7 @@ api_http_data(clicon_handle h,
goto done; goto done;
goto ok; goto ok;
} }
/* 5. Accepted media_out: should check text/html, JavaScript, image, and css /* 5. Accepted media_out: should check text/html, JavaScript, image, and css
*/ */
if ((media_str = restconf_param_get(h, "HTTP_ACCEPT")) == NULL){ if ((media_str = restconf_param_get(h, "HTTP_ACCEPT")) == NULL){
} }
@ -491,6 +498,6 @@ api_http_data(clicon_handle h,
done: done:
if (path) if (path)
free(path); free(path);
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }

View file

@ -45,6 +45,7 @@ extern "C" {
* Types * Types
*/ */
/*! RESTCONF media types /*! RESTCONF media types
*
* @see http_media_map * @see http_media_map
* @note DUPLICATED in restconf_lib.h * @note DUPLICATED in restconf_lib.h
*/ */

View file

@ -69,6 +69,7 @@
/*! HTTP headers done, if there is a message body coming next /*! HTTP headers done, if there is a message body coming next
*
* @param[in] req Fastcgi request handle * @param[in] req Fastcgi request handle
* @retval body Handle for body handling (in fcgi same as req) * @retval body Handle for body handling (in fcgi same as req)
* *
@ -86,9 +87,12 @@ restconf_reply_body_start(void *req0)
} }
/*! Add HTTP header field name and value to reply, fcgi specific /*! Add HTTP header field name and value to reply, fcgi specific
*
* @param[in] req Fastcgi request handle * @param[in] req Fastcgi request handle
* @param[in] name HTTP header field name * @param[in] name HTTP header field name
* @param[in] vfmt HTTP header field value format string w variable parameter * @param[in] vfmt HTTP header field value format string w variable parameter
* @retval 0 OK
* @retval -1 Error
* @see eg RFC 7230 * @see eg RFC 7230
*/ */
int int
@ -102,7 +106,7 @@ restconf_reply_header(void *req0,
size_t vlen; size_t vlen;
char *value = NULL; char *value = NULL;
va_list ap; va_list ap;
if (req == NULL || name == NULL || vfmt == NULL){ if (req == NULL || name == NULL || vfmt == NULL){
clicon_err(OE_CFG, EINVAL, "req, name or value is NULL"); clicon_err(OE_CFG, EINVAL, "req, name or value is NULL");
return -1; return -1;
@ -116,14 +120,14 @@ restconf_reply_header(void *req0,
goto done; goto done;
} }
/* second round: compute actual value */ /* second round: compute actual value */
va_start(ap, vfmt); va_start(ap, vfmt);
if (vsnprintf(value, vlen+1, vfmt, ap) < 0){ if (vsnprintf(value, vlen+1, vfmt, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf"); clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap); va_end(ap);
goto done; goto done;
} }
va_end(ap); va_end(ap);
FCGX_FPrintF(req->out, "%s: %s\r\n", name, value); FCGX_FPrintF(req->out, "%s: %s\r\n", name, value);
retval = 0; retval = 0;
done: done:
if (value) if (value)
@ -132,9 +136,12 @@ restconf_reply_header(void *req0,
} }
/*! Add HTTP message body to reply, fcgi specific /*! Add HTTP message body to reply, fcgi specific
*
* @param[in] req Fastcgi request handle * @param[in] req Fastcgi request handle
* @param[in,out] content_len This is for Content-Length header * @param[in,out] content_len This is for Content-Length header
* @param[in] bfmt HTTP message body format string w variable parameter * @param[in] bfmt HTTP message body format string w variable parameter
* @retval 0 OK
* @retval -1 Error
* @see eg RFC 7230 * @see eg RFC 7230
*/ */
int int
@ -163,14 +170,14 @@ restconf_reply_body_add(void *req0,
goto done; goto done;
} }
/* second round: compute actual body */ /* second round: compute actual body */
va_start(ap, bfmt); va_start(ap, bfmt);
if (vsnprintf(body, blen+1, bfmt, ap) < 0){ if (vsnprintf(body, blen+1, bfmt, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf"); clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap); va_end(ap);
goto done; goto done;
} }
va_end(ap); va_end(ap);
FCGX_FPrintF(req->out, "%s", body); FCGX_FPrintF(req->out, "%s", body);
/* Increment in/out Content-Length parameter */ /* Increment in/out Content-Length parameter */
if (content_len){ if (content_len){
sz = strlen(body); sz = strlen(body);
@ -184,12 +191,14 @@ restconf_reply_body_add(void *req0,
} }
/*! Send HTTP reply with potential message body /*! Send HTTP reply with potential message body
* @param[in] req Fastcgi request handle *
* @param[in] code Status code
* @param[in] cb Body as a cbuf if non-NULL. Note is consumed
* @param[in] head Only send headers, dont send body.
*
* Prerequisites: status code set, headers given, body if wanted set * Prerequisites: status code set, headers given, body if wanted set
* @param[in] req Fastcgi request handle
* @param[in] code Status code
* @param[in] cb Body as a cbuf if non-NULL. Note is consumed
* @param[in] head Only send headers, dont send body.
* @retval 0 OK
* @retval -1 Error
*/ */
int int
restconf_reply_send(void *req0, restconf_reply_send(void *req0,
@ -222,6 +231,7 @@ restconf_reply_send(void *req0,
} }
/*! Get input data from http request, eg such as curl -X PUT http://... <indata> /*! Get input data from http request, eg such as curl -X PUT http://... <indata>
*
* @param[in] req Fastcgi request handle * @param[in] req Fastcgi request handle
* @retval indata * @retval indata
* @retval NULL Error * @retval NULL Error

View file

@ -65,9 +65,12 @@
#include "restconf_native.h" #include "restconf_native.h"
/*! Add HTTP header field name and value to reply /*! Add HTTP header field name and value to reply
*
* @param[in] req request handle * @param[in] req request handle
* @param[in] name HTTP header field name * @param[in] name HTTP header field name
* @param[in] vfmt HTTP header field value format string w variable parameter * @param[in] vfmt HTTP header field value format string w variable parameter
* @retval 0 OK
* @retval -1 Error
* @see eg RFC 7230 * @see eg RFC 7230
*/ */
int int
@ -83,7 +86,7 @@ restconf_reply_header(void *req0,
char *value = NULL; char *value = NULL;
va_list ap; va_list ap;
clicon_debug(1, "%s %s", __FUNCTION__, name); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, name);
if (sd == NULL || name == NULL || vfmt == NULL){ if (sd == NULL || name == NULL || vfmt == NULL){
clicon_err(OE_CFG, EINVAL, "sd, name or value is NULL"); clicon_err(OE_CFG, EINVAL, "sd, name or value is NULL");
goto done; goto done;
@ -102,7 +105,7 @@ restconf_reply_header(void *req0,
goto done; goto done;
} }
/* Second round: compute actual value */ /* Second round: compute actual value */
va_start(ap, vfmt); va_start(ap, vfmt);
if (vsnprintf(value, vlen+1, vfmt, ap) < 0){ if (vsnprintf(value, vlen+1, vfmt, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf"); clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap); va_end(ap);
@ -121,11 +124,13 @@ restconf_reply_header(void *req0,
} }
/*! Send HTTP reply with potential message body /*! Send HTTP reply with potential message body
* @param[in] req http request handle *
* @param[in] code Status code * @param[in] req http request handle
* @param[in] cb Body as a cbuf if non-NULL. Note: is consumed * @param[in] code Status code
* @param[in] head Only send headers, dont send body. * @param[in] cb Body as a cbuf if non-NULL. Note: is consumed
* * @param[in] head Only send headers, dont send body.
* @retval 0 OK
* @retval -1 Error
* Prerequisites: status code set, headers given, body if wanted set * Prerequisites: status code set, headers given, body if wanted set
*/ */
int int
@ -137,7 +142,7 @@ restconf_reply_send(void *req0,
int retval = -1; int retval = -1;
restconf_stream_data *sd = (restconf_stream_data *)req0; restconf_stream_data *sd = (restconf_stream_data *)req0;
clicon_debug(1, "%s code:%d", __FUNCTION__, code); clixon_debug(CLIXON_DBG_DEFAULT, "%s code:%d", __FUNCTION__, code);
if (sd == NULL){ if (sd == NULL){
clicon_err(OE_CFG, EINVAL, "sd is NULL"); clicon_err(OE_CFG, EINVAL, "sd is NULL");
goto done; goto done;
@ -145,7 +150,7 @@ restconf_reply_send(void *req0,
sd->sd_code = code; sd->sd_code = code;
if (cb != NULL){ if (cb != NULL){
if (cbuf_len(cb)){ if (cbuf_len(cb)){
sd->sd_body_len = cbuf_len(cb); sd->sd_body_len = cbuf_len(cb);
if (head){ if (head){
cbuf_free(cb); cbuf_free(cb);
} }
@ -156,17 +161,18 @@ restconf_reply_send(void *req0,
} }
else{ else{
cbuf_free(cb); cbuf_free(cb);
sd->sd_body_len = 0; sd->sd_body_len = 0;
} }
} }
else else
sd->sd_body_len = 0; sd->sd_body_len = 0;
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
/*! Get input data from http request, eg such as curl -X PUT http://... <indata> /*! Get input data from http request, eg such as curl -X PUT http://... <indata>
*
* @param[in] req Request handle * @param[in] req Request handle
* @note: reuses cbuf from stream-data * @note: reuses cbuf from stream-data
*/ */
@ -175,7 +181,7 @@ restconf_get_indata(void *req0)
{ {
restconf_stream_data *sd = (restconf_stream_data *)req0; restconf_stream_data *sd = (restconf_stream_data *)req0;
cbuf *cb = NULL; cbuf *cb = NULL;
if (sd == NULL){ if (sd == NULL){
clicon_err(OE_CFG, EINVAL, "sd is NULL"); clicon_err(OE_CFG, EINVAL, "sd is NULL");
goto done; goto done;

View file

@ -70,10 +70,13 @@
#include "restconf_err.h" #include "restconf_err.h"
/*! HTTP error 405 Not Allowed /*! HTTP error 405 Not Allowed
*
* @param[in] req Generic http handle * @param[in] req Generic http handle
* @param[in] allow Which methods are allowed * @param[in] allow Which methods are allowed
* @param[in] pretty Pretty-print of reply * @param[in] pretty Pretty-print of reply
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
* @retval 0 OK
* @retval -1 Error
*/ */
int int
restconf_method_notallowed(clicon_handle h, restconf_method_notallowed(clicon_handle h,
@ -100,7 +103,10 @@ restconf_method_notallowed(clicon_handle h,
} }
/*! HTTP error 415 Unsupported media /*! HTTP error 415 Unsupported media
*
* @param[in] req Generic http handle * @param[in] req Generic http handle
* @retval 0 OK
* @retval -1 Error
* RFC8040, section 5.2: * RFC8040, section 5.2:
* If the server does not support the requested input encoding for a request, then it MUST * If the server does not support the requested input encoding for a request, then it MUST
* return an error response with a "415 Unsupported Media Type" status-line * return an error response with a "415 Unsupported Media Type" status-line
@ -117,7 +123,7 @@ restconf_unsupported_media(clicon_handle h,
if (netconf_operation_not_supported_xml(&xerr, "protocol", "Unsupported Media Type") < 0) if (netconf_operation_not_supported_xml(&xerr, "protocol", "Unsupported Media Type") < 0)
goto done; goto done;
/* override with 415 netconf->restoconf translation which gives a 405 */ /* override with 415 netconf->restoconf translation which gives a 405 */
if (api_return_err0(h, req, xerr, pretty, media, 415) < 0) if (api_return_err0(h, req, xerr, pretty, media, 415) < 0)
goto done; goto done;
retval = 0; retval = 0;
done: done:
@ -129,7 +135,9 @@ restconf_unsupported_media(clicon_handle h,
/*! HTTP error 406 Not acceptable /*! HTTP error 406 Not acceptable
* *
* @param[in] req Generic http handle * @param[in] req Generic http handle
* RFC8040, section 5.2: * @retval 0 OK
* @retval -1 Error
* @see RFC8040, section 5.2:
* If the server does not support any of the requested output encodings for a request, then it MUST * If the server does not support any of the requested output encodings for a request, then it MUST
* return an error response with a "406 Not Acceptable" status-line. * return an error response with a "406 Not Acceptable" status-line.
*/ */
@ -145,7 +153,7 @@ restconf_not_acceptable(clicon_handle h,
if (netconf_operation_not_supported_xml(&xerr, "protocol", "Unacceptable output encoding") < 0) if (netconf_operation_not_supported_xml(&xerr, "protocol", "Unacceptable output encoding") < 0)
goto done; goto done;
/* Override with 415 netconf->restoconf translation which gives a 405 */ /* Override with 415 netconf->restoconf translation which gives a 405 */
if (api_return_err0(h, req, xerr, pretty, media, 415) < 0) if (api_return_err0(h, req, xerr, pretty, media, 415) < 0)
goto done; goto done;
if (restconf_reply_send(req, 415, NULL, 0) < 0) if (restconf_reply_send(req, 415, NULL, 0) < 0)
goto done; goto done;
@ -179,6 +187,7 @@ restconf_notimplemented(clicon_handle h,
} }
/*! Generic restconf error function on get/head request /*! Generic restconf error function on get/head request
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic http handle * @param[in] req Generic http handle
* @param[in] xerr XML error message (eg from backend, or from a clixon_netconf_lib function) * @param[in] xerr XML error message (eg from backend, or from a clixon_netconf_lib function)
@ -186,6 +195,8 @@ restconf_notimplemented(clicon_handle h,
* @param[in] media Output media * @param[in] media Output media
* @param[in] code If 0 use rfc8040 sec 7 netconf2restconf error-tag mapping * @param[in] code If 0 use rfc8040 sec 7 netconf2restconf error-tag mapping
* otherwise use this code * otherwise use this code
* @retval 0 OK
* @retval -1 Error
* xerr should be on the form: <rpc-error>... otherwise an internal error is generated * xerr should be on the form: <rpc-error>... otherwise an internal error is generated
* @note there are special cases see code * @note there are special cases see code
*/ */
@ -202,12 +213,12 @@ api_return_err(clicon_handle h,
cbuf *cberr = NULL; cbuf *cberr = NULL;
cxobj *xtag; cxobj *xtag;
char *tagstr; char *tagstr;
int code; int code;
cxobj *xerr2 = NULL; cxobj *xerr2 = NULL;
cxobj *xmsg; cxobj *xmsg;
char *mb; char *mb;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
@ -238,7 +249,7 @@ api_return_err(clicon_handle h,
} }
} }
#if 1 #if 1
clicon_debug_xml(1, xerr, "%s Send error:", __FUNCTION__); clixon_debug_xml(CLIXON_DBG_DEFAULT, xerr, "%s Send error:", __FUNCTION__);
#endif #endif
if (xml_name_set(xerr, "error") < 0) if (xml_name_set(xerr, "error") < 0)
goto done; goto done;
@ -265,17 +276,17 @@ api_return_err(clicon_handle h,
if (strcmp(tagstr, "invalid-value") == 0 && if (strcmp(tagstr, "invalid-value") == 0 &&
(xmsg = xpath_first(xerr, NULL, "error-message")) != NULL && (xmsg = xpath_first(xerr, NULL, "error-message")) != NULL &&
(mb = xml_body(xmsg)) != NULL && (mb = xml_body(xmsg)) != NULL &&
strcmp(mb, "Invalid HTTP data method") == 0) strcmp(mb, "Invalid HTTP data method") == 0)
code = 404; /* Not found */ code = 404; /* Not found */
} }
} }
if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media)) < 0) // XXX if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media)) < 0) // XXX
goto done; goto done;
switch (media){ switch (media){
case YANG_DATA_XML: case YANG_DATA_XML:
case YANG_PATCH_XML: case YANG_PATCH_XML:
case YANG_PAGINATION_XML: case YANG_PAGINATION_XML:
clicon_debug(1, "%s code:%d", __FUNCTION__, code); clixon_debug(CLIXON_DBG_DEFAULT, "%s code:%d", __FUNCTION__, code);
if (pretty){ if (pretty){
cprintf(cb, " <errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">\n"); cprintf(cb, " <errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">\n");
if (clixon_xml2cbuf(cb, xerr, 2, pretty, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cb, xerr, 2, pretty, NULL, -1, 0) < 0)
@ -291,7 +302,7 @@ api_return_err(clicon_handle h,
break; break;
case YANG_DATA_JSON: case YANG_DATA_JSON:
case YANG_PATCH_JSON: case YANG_PATCH_JSON:
clicon_debug(1, "%s code:%d", __FUNCTION__, code); clixon_debug(CLIXON_DBG_DEFAULT, "%s code:%d", __FUNCTION__, code);
if (pretty){ if (pretty){
cprintf(cb, "{\n\"ietf-restconf:errors\" : "); cprintf(cb, "{\n\"ietf-restconf:errors\" : ");
if (clixon_json2cbuf(cb, xerr, pretty, 0, 0) < 0) if (clixon_json2cbuf(cb, xerr, pretty, 0, 0) < 0)
@ -318,7 +329,7 @@ api_return_err(clicon_handle h,
// ok: // ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
if (cberr) if (cberr)
@ -337,6 +348,8 @@ api_return_err(clicon_handle h,
* @param[in] media Output media * @param[in] media Output media
* @param[in] code If 0 use rfc8040 sec 7 netconf2restconf error-tag mapping * @param[in] code If 0 use rfc8040 sec 7 netconf2restconf error-tag mapping
* otherwise use this code * otherwise use this code
* @retval 0 OK
* @retval -1 Error
* @see api_return_err where top level is expected to be <rpc-error> * @see api_return_err where top level is expected to be <rpc-error>
*/ */
int int

View file

@ -77,6 +77,7 @@
* entries in the struct below. * entries in the struct below.
*/ */
/*! Backend specific handle added to header CLICON handle /*! Backend specific handle added to header CLICON handle
*
* This file should only contain access functions for the _specific_ * This file should only contain access functions for the _specific_
* entries in the struct below. * entries in the struct below.
* @note The top part must be equivalent to struct clicon_handle in clixon_handle.c * @note The top part must be equivalent to struct clicon_handle in clixon_handle.c
@ -88,7 +89,7 @@ struct restconf_handle {
clicon_hash_t *rh_data; /* internal clicon data (HDR) */ clicon_hash_t *rh_data; /* internal clicon data (HDR) */
clicon_hash_t *rh_db_elmnt; /* xml datastore element cache data */ clicon_hash_t *rh_db_elmnt; /* xml datastore element cache data */
event_stream_t *rh_stream; /* notification streams, see clixon_stream.[ch] */ event_stream_t *rh_stream; /* notification streams, see clixon_stream.[ch] */
/* ------ end of common handle ------ */ /* ------ end of common handle ------ */
clicon_hash_t *rh_params; /* restconf parameters, including http headers */ clicon_hash_t *rh_params; /* restconf parameters, including http headers */
clixon_auth_type_t rh_auth_type; /* authentication type */ clixon_auth_type_t rh_auth_type; /* authentication type */
@ -110,6 +111,7 @@ restconf_handle_init(void)
} }
/*! Deallocates a backend handle, including all client structs /*! Deallocates a backend handle, including all client structs
*
* @note: handle 'h' cannot be used in calls after this * @note: handle 'h' cannot be used in calls after this
* @see backend_client_rm * @see backend_client_rm
*/ */
@ -117,7 +119,7 @@ int
restconf_handle_exit(clicon_handle h) restconf_handle_exit(clicon_handle h)
{ {
struct restconf_handle *rh = handle(h); struct restconf_handle *rh = handle(h);
if (rh->rh_fcgi_socket) if (rh->rh_fcgi_socket)
free(rh->rh_fcgi_socket); free(rh->rh_fcgi_socket);
clicon_handle_exit(h); /* frees h and options (and streams) */ clicon_handle_exit(h); /* frees h and options (and streams) */
@ -125,7 +127,8 @@ restconf_handle_exit(clicon_handle h)
} }
/*! Get restconf http parameter /*! Get restconf http parameter
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] name Data name * @param[in] name Data name
* @retval val Data value as string * @retval val Data value as string
* Currently using clixon runtime data but there is risk for colliding names * Currently using clixon runtime data but there is risk for colliding names
@ -142,7 +145,8 @@ restconf_param_get(clicon_handle h,
} }
/*! Set restconf http parameter /*! Set restconf http parameter
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] name Data name * @param[in] name Data name
* @param[in] val Data value as null-terminated string * @param[in] val Data value as null-terminated string
* @retval 0 OK * @retval 0 OK
@ -156,7 +160,7 @@ restconf_param_set(clicon_handle h,
{ {
struct restconf_handle *rh = handle(h); struct restconf_handle *rh = handle(h);
clicon_debug(1, "%s: %s=%s", __FUNCTION__, param, val); clixon_debug(CLIXON_DBG_DEFAULT, "%s: %s=%s", __FUNCTION__, param, val);
if (rh->rh_params == NULL) if (rh->rh_params == NULL)
if ((rh->rh_params = clicon_hash_init()) == NULL) if ((rh->rh_params = clicon_hash_init()) == NULL)
return -1; return -1;
@ -164,7 +168,8 @@ restconf_param_set(clicon_handle h,
} }
/*! Delete all restconf http parameter /*! Delete all restconf http parameter
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] name Data name * @param[in] name Data name
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -175,7 +180,7 @@ restconf_param_del_all(clicon_handle h)
{ {
int retval = -1; int retval = -1;
struct restconf_handle *rh = handle(h); struct restconf_handle *rh = handle(h);
if (rh->rh_params != NULL){ if (rh->rh_params != NULL){
if (clicon_hash_free(rh->rh_params) < 0) if (clicon_hash_free(rh->rh_params) < 0)
goto done; goto done;
@ -187,7 +192,8 @@ restconf_param_del_all(clicon_handle h)
} }
/*! Get restconf http parameter /*! Get restconf http parameter
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval auth_type * @retval auth_type
*/ */
clixon_auth_type_t clixon_auth_type_t
@ -199,7 +205,8 @@ restconf_auth_type_get(clicon_handle h)
} }
/*! Set restconf http parameter /*! Set restconf http parameter
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] name Data name * @param[in] name Data name
* @param[in] val Data value as null-terminated string * @param[in] val Data value as null-terminated string
* @retval 0 OK * @retval 0 OK
@ -217,7 +224,8 @@ restconf_auth_type_set(clicon_handle h,
} }
/*! Get restconf pretty-print (for replies) /*! Get restconf pretty-print (for replies)
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval pretty * @retval pretty
*/ */
int int
@ -229,7 +237,8 @@ restconf_pretty_get(clicon_handle h)
} }
/*! Set restconf pretty-print /*! Set restconf pretty-print
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] pretty 0 or 1 * @param[in] pretty 0 or 1
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -245,6 +254,7 @@ restconf_pretty_set(clicon_handle h,
} }
/*! Get restconf http-data /*! Get restconf http-data
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval 0 Yes, http-data enabled * @retval 0 Yes, http-data enabled
* @retval 1 No, http-data disabled * @retval 1 No, http-data disabled
@ -258,6 +268,7 @@ restconf_http_data_get(clicon_handle h)
} }
/*! Set restconf http-data /*! Set restconf http-data
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -273,7 +284,8 @@ restconf_http_data_set(clicon_handle h,
} }
/*! Get restconf fcgi socket path /*! Get restconf fcgi socket path
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval socketpath * @retval socketpath
*/ */
char* char*
@ -285,7 +297,8 @@ restconf_fcgi_socket_get(clicon_handle h)
} }
/*! Set restconf fcgi socketpath /*! Set restconf fcgi socketpath
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] name Data name * @param[in] name Data name
* @param[in] val Data value as null-terminated string * @param[in] val Data value as null-terminated string
* @retval 0 OK * @retval 0 OK

View file

@ -69,7 +69,7 @@
#include "clixon_http_data.h" #include "clixon_http_data.h"
/* Size of xml read buffer */ /* Size of xml read buffer */
#define BUFLEN 1024 #define BUFLEN 1024
/*! HTTP/1 parsing function. Input is string and side-effect is populating connection structs /*! HTTP/1 parsing function. Input is string and side-effect is populating connection structs
* *
@ -80,7 +80,7 @@
* @retval 0 Parse OK * @retval 0 Parse OK
* @retval -1 Error with clicon_err called. * @retval -1 Error with clicon_err called.
*/ */
static int static int
_http1_parse(clicon_handle h, _http1_parse(clicon_handle h,
restconf_conn *rc, restconf_conn *rc,
char *str, char *str,
@ -90,7 +90,7 @@ _http1_parse(clicon_handle h,
clixon_http1_yacc hy = {0,}; clixon_http1_yacc hy = {0,};
int ret; int ret;
clicon_debug(1, "%s:\n%s", __FUNCTION__, str); clixon_debug(CLIXON_DBG_DEFAULT, "%s:\n%s", __FUNCTION__, str);
if (strlen(str) == 0) if (strlen(str) == 0)
goto ok; goto ok;
hy.hy_parse_string = str; hy.hy_parse_string = str;
@ -119,7 +119,7 @@ _http1_parse(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }
@ -147,7 +147,7 @@ clixon_http1_parse_file(clicon_handle h,
int len = 0; int len = 0;
int oldbuflen; int oldbuflen;
clicon_debug(1, "%s %s", __FUNCTION__, filename); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, filename);
if (f == NULL){ if (f == NULL){
clicon_err(OE_RESTCONF, EINVAL, "f is NULL"); clicon_err(OE_RESTCONF, EINVAL, "f is NULL");
goto done; goto done;
@ -197,7 +197,7 @@ clixon_http1_parse_file(clicon_handle h,
* @retval 0 Parse OK * @retval 0 Parse OK
* @retval -1 Error with clicon_err called. * @retval -1 Error with clicon_err called.
*/ */
int int
clixon_http1_parse_string(clicon_handle h, clixon_http1_parse_string(clicon_handle h,
restconf_conn *rc, restconf_conn *rc,
char *str) char *str)
@ -217,7 +217,7 @@ clixon_http1_parse_string(clicon_handle h,
* @note Had preferred to do this without copying, OR * @note Had preferred to do this without copying, OR
* input flex with a non-null terminated string * input flex with a non-null terminated string
*/ */
int int
clixon_http1_parse_buf(clicon_handle h, clixon_http1_parse_buf(clicon_handle h,
restconf_conn *rc, restconf_conn *rc,
char *buf, char *buf,
@ -225,7 +225,7 @@ clixon_http1_parse_buf(clicon_handle h,
{ {
char *str = NULL; char *str = NULL;
int ret; int ret;
if ((str = malloc(n+1)) == NULL){ if ((str = malloc(n+1)) == NULL){
clicon_err(OE_RESTCONF, errno, "malloc"); clicon_err(OE_RESTCONF, errno, "malloc");
return -1; return -1;
@ -239,6 +239,7 @@ clixon_http1_parse_buf(clicon_handle h,
#ifdef HAVE_LIBNGHTTP2 #ifdef HAVE_LIBNGHTTP2
/*! Check http/1 UPGRADE to http/2 /*! Check http/1 UPGRADE to http/2
*
* If upgrade headers are encountered AND http/2 is configured, then * If upgrade headers are encountered AND http/2 is configured, then
* - add upgrade headers or signal error * - add upgrade headers or signal error
* - set http2 flag get settings to and signal to upper layer to do the actual transition. * - set http2 flag get settings to and signal to upper layer to do the actual transition.
@ -256,13 +257,13 @@ http1_upgrade_http2(clicon_handle h,
char *str; char *str;
char *settings; char *settings;
cxobj *xerr = NULL; cxobj *xerr = NULL;
if ((str = restconf_param_get(h, "HTTP_UPGRADE")) != NULL && if ((str = restconf_param_get(h, "HTTP_UPGRADE")) != NULL &&
clicon_option_bool(h, "CLICON_RESTCONF_HTTP2_PLAIN") == 1){ clicon_option_bool(h, "CLICON_RESTCONF_HTTP2_PLAIN") == 1){
/* Only accept "h2c" */ /* Only accept "h2c" */
if (strcmp(str, "h2c") != 0){ if (strcmp(str, "h2c") != 0){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid upgrade token") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid upgrade token") < 0)
goto done; goto done;
if (api_return_err0(h, sd, xerr, 1, YANG_DATA_JSON, 0) < 0) if (api_return_err0(h, sd, xerr, 1, YANG_DATA_JSON, 0) < 0)
goto done; goto done;
if (xerr) if (xerr)
@ -301,7 +302,7 @@ restconf_http1_reply(restconf_conn *rc,
int retval = -1; int retval = -1;
cg_var *cv; cg_var *cv;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* If body, add a content-length header /* If body, add a content-length header
* A server MUST NOT send a Content-Length header field in any response * A server MUST NOT send a Content-Length header field in any response
* with a status code of 1xx (Informational) or 204 (No Content). A * with a status code of 1xx (Informational) or 204 (No Content). A
@ -311,7 +312,7 @@ restconf_http1_reply(restconf_conn *rc,
*/ */
if (sd->sd_code != 204 && sd->sd_code > 199) if (sd->sd_code != 204 && sd->sd_code > 199)
if (restconf_reply_header(sd, "Content-Length", "%zu", sd->sd_body_len) < 0) if (restconf_reply_header(sd, "Content-Length", "%zu", sd->sd_body_len) < 0)
goto done; goto done;
/* Create reply and write headers */ /* Create reply and write headers */
#if 0 /* XXX need some keep-alive logic here */ #if 0 /* XXX need some keep-alive logic here */
/* protocol is HTTP/1.0 and clients wants to keep established */ /* protocol is HTTP/1.0 and clients wants to keep established */
@ -342,9 +343,12 @@ restconf_http1_reply(restconf_conn *rc,
return retval; return retval;
} }
/*! /*! restconf http1 path root
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] rc Clixon request connect pointer * @param[in] rc Clixon request connect pointer
* @retval 0 OK
* @retval -1 Error
*/ */
int int
restconf_http1_path_root(clicon_handle h, restconf_http1_path_root(clicon_handle h,
@ -360,8 +364,8 @@ restconf_http1_path_root(clicon_handle h,
#ifdef HAVE_LIBNGHTTP2 #ifdef HAVE_LIBNGHTTP2
int ret; int ret;
#endif #endif
clicon_debug(1, "------------"); clixon_debug(CLIXON_DBG_DEFAULT, "------------");
pretty = restconf_pretty_get(h); pretty = restconf_pretty_get(h);
if ((sd = restconf_stream_find(rc, 0)) == NULL){ if ((sd = restconf_stream_find(rc, 0)) == NULL){
clicon_err(OE_RESTCONF, EINVAL, "No stream_data"); clicon_err(OE_RESTCONF, EINVAL, "No stream_data");
@ -392,7 +396,7 @@ restconf_http1_path_root(clicon_handle h,
*/ */
if (sd->sd_path != NULL){ if (sd->sd_path != NULL){
free(sd->sd_path); free(sd->sd_path);
sd->sd_path = NULL; sd->sd_path = NULL;
} }
#endif #endif
if ((sd->sd_path = restconf_uripath(rc->rc_h)) == NULL) if ((sd->sd_path = restconf_uripath(rc->rc_h)) == NULL)
@ -459,7 +463,7 @@ restconf_http1_path_root(clicon_handle h,
goto done; goto done;
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
if (subject) if (subject)
free(subject); free(subject);
if (xerr) if (xerr)
@ -486,7 +490,7 @@ http1_check_expect(clicon_handle h,
{ {
int retval = -1; int retval = -1;
char *val; char *val;
if ((val = restconf_param_get(h, "HTTP_EXPECT")) != NULL && if ((val = restconf_param_get(h, "HTTP_EXPECT")) != NULL &&
strcmp(val, "100-continue") == 0){ /* just drop if not well-formed */ strcmp(val, "100-continue") == 0){ /* just drop if not well-formed */
sd->sd_code = 100; sd->sd_code = 100;
@ -521,7 +525,7 @@ http1_check_content_length(clicon_handle h,
int retval = -1; int retval = -1;
char *val; char *val;
int len; int len;
if ((val = restconf_param_get(h, "HTTP_CONTENT_LENGTH")) == NULL || if ((val = restconf_param_get(h, "HTTP_CONTENT_LENGTH")) == NULL ||
(len = atoi(val)) == 0) (len = atoi(val)) == 0)
*status = 0; *status = 0;

View file

@ -125,7 +125,7 @@ Mapping netconf error-tag -> status code
static const map_str2int netconf_restconf_map[] = { static const map_str2int netconf_restconf_map[] = {
{"in-use", 409}, {"in-use", 409},
{"invalid-value", 400}, /* or 404 special case if msg is: "Invalid HTTP data method" handled in api_return_err */ {"invalid-value", 400}, /* or 404 special case if msg is: "Invalid HTTP data method" handled in api_return_err */
{"invalid-value", 404}, {"invalid-value", 404},
{"invalid-value", 406}, {"invalid-value", 406},
{"too-big", 413}, /* request */ {"too-big", 413}, /* request */
{"too-big", 400}, /* response */ {"too-big", 400}, /* response */
@ -137,7 +137,7 @@ static const map_str2int netconf_restconf_map[] = {
{"unknown-element", 400}, {"unknown-element", 400},
{"unknown-namespace", 400}, {"unknown-namespace", 400},
{"access-denied", 403}, /* or 401 special case if msg is: "The requested URL was unauthorized" handled in api_return_err */ {"access-denied", 403}, /* or 401 special case if msg is: "The requested URL was unauthorized" handled in api_return_err */
{"access-denied", 401}, {"access-denied", 401},
{"lock-denied", 409}, {"lock-denied", 409},
{"resource-denied", 409}, {"resource-denied", 409},
{"rollback-failed", 500}, {"rollback-failed", 500},
@ -157,7 +157,7 @@ static const map_str2int netconf_restconf_map[] = {
static const map_str2int http_reason_phrase_map[] = { static const map_str2int http_reason_phrase_map[] = {
{"Continue", 100}, {"Continue", 100},
{"Switching Protocols", 101}, {"Switching Protocols", 101},
{"OK", 200}, {"OK", 200},
{"Created", 201}, {"Created", 201},
{"Accepted", 202}, {"Accepted", 202},
{"Non-Authoritative Information", 203}, {"Non-Authoritative Information", 203},
@ -215,7 +215,7 @@ static const map_str2int http_media_map[] = {
static const map_str2int http_proto_map[] = { static const map_str2int http_proto_map[] = {
{"http/1.0", HTTP_10}, {"http/1.0", HTTP_10},
{"http/1.1", HTTP_11}, {"http/1.1", HTTP_11},
{"http/2", HTTP_2}, {"http/2", HTTP_2},
{NULL, -1} {NULL, -1}
}; };
@ -262,7 +262,7 @@ restconf_proto2str(int proto)
* media-type = type "/" subtype *( OWS ";" OWS parameter ) * media-type = type "/" subtype *( OWS ";" OWS parameter )
* type = token * type = token
* subtype = token * subtype = token
* *
*/ */
restconf_media restconf_media
restconf_content_type(clicon_handle h) restconf_content_type(clicon_handle h)
@ -291,7 +291,7 @@ restconf_convert_hdr(clicon_handle h,
int i; int i;
char c; char c;
size_t len; size_t len;
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
@ -322,10 +322,12 @@ restconf_convert_hdr(clicon_handle h,
* @param[in] cookiestr cookie string according to rfc6265 (modified) * @param[in] cookiestr cookie string according to rfc6265 (modified)
* @param[in] attribute cookie attribute * @param[in] attribute cookie attribute
* @param[out] val malloced cookie value, free with free() * @param[out] val malloced cookie value, free with free()
* @retval 0 OK
* @retval -1 Error
*/ */
int int
get_user_cookie(char *cookiestr, get_user_cookie(char *cookiestr,
char *attribute, char *attribute,
char **val) char **val)
{ {
int retval = -1; int retval = -1;
@ -345,7 +347,7 @@ get_user_cookie(char *cookiestr,
return retval; return retval;
} }
/*! Clean and close all state of restconf process (but dont exit). /*! Clean and close all state of restconf process (but dont exit).
* *
* Cannot use h after this * Cannot use h after this
* @param[in] h Clixon handle * @param[in] h Clixon handle
@ -358,7 +360,7 @@ restconf_terminate(clicon_handle h)
cxobj *x; cxobj *x;
int fs; /* fgcx socket */ int fs; /* fgcx socket */
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((fs = clicon_socket_get(h)) != -1) if ((fs = clicon_socket_get(h)) != -1)
close(fs); close(fs);
/* Delete all plugins, and RPC callbacks */ /* Delete all plugins, and RPC callbacks */
@ -376,8 +378,8 @@ restconf_terminate(clicon_handle h)
xpath_optimize_exit(); xpath_optimize_exit();
restconf_handle_exit(h); restconf_handle_exit(h);
clixon_err_exit(); clixon_err_exit();
clicon_debug(1, "%s pid:%u done", __FUNCTION__, getpid()); clixon_debug(CLIXON_DBG_DEFAULT, "%s pid:%u done", __FUNCTION__, getpid());
clicon_log_exit(); /* Must be after last clicon_debug */ clicon_log_exit(); /* Must be after last clixon_debug */
return 0; return 0;
} }
@ -492,10 +494,10 @@ restconf_insert_attributes(cxobj *xdata,
/*! Callback for yang extensions ietf-restconf:yang-data /*! Callback for yang extensions ietf-restconf:yang-data
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] yext Yang node of extension * @param[in] yext Yang node of extension
* @param[in] ys Yang node of (unknown) statement belonging to extension * @param[in] ys Yang node of (unknown) statement belonging to extension
* @retval 0 OK, all callbacks executed OK * @retval 0 OK, all callbacks executed OK
* @retval -1 Error in one callback * @retval -1 Error in one callback
* @note This extension adds semantics to YANG according to RFC8040 as follows: * @note This extension adds semantics to YANG according to RFC8040 as follows:
* - The list-stmt is not required to have a key-stmt defined.(NB!!) * - The list-stmt is not required to have a key-stmt defined.(NB!!)
* - The if-feature-stmt is ignored if present. * - The if-feature-stmt is ignored if present.
@ -516,13 +518,13 @@ restconf_main_extension_cb(clicon_handle h,
yang_stmt *ymod; yang_stmt *ymod;
yang_stmt *yc; yang_stmt *yc;
yang_stmt *yn = NULL; yang_stmt *yn = NULL;
ymod = ys_module(yext); ymod = ys_module(yext);
modname = yang_argument_get(ymod); modname = yang_argument_get(ymod);
extname = yang_argument_get(yext); extname = yang_argument_get(yext);
if (strcmp(modname, "ietf-restconf") != 0 || strcmp(extname, "yang-data") != 0) if (strcmp(modname, "ietf-restconf") != 0 || strcmp(extname, "yang-data") != 0)
goto ok; goto ok;
clicon_debug(1, "%s Enabled extension:%s:%s", __FUNCTION__, modname, extname); clixon_debug(CLIXON_DBG_DEFAULT, "%s Enabled extension:%s:%s", __FUNCTION__, modname, extname);
if ((yc = yang_find(ys, 0, NULL)) == NULL) if ((yc = yang_find(ys, 0, NULL)) == NULL)
goto ok; goto ok;
if ((yn = ys_dup(yc)) == NULL) if ((yn = ys_dup(yc)) == NULL)
@ -566,7 +568,9 @@ restconf_uripath(clicon_handle h)
/*! Drop privileges from root to user (or already at user) /*! Drop privileges from root to user (or already at user)
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
* Group set to CLICON_SOCK_GROUP to communicate with backend * Group set to CLICON_SOCK_GROUP to communicate with backend
*/ */
int int
@ -579,8 +583,8 @@ restconf_drop_privileges(clicon_handle h)
gid_t gid = -1; gid_t gid = -1;
char *user; char *user;
enum priv_mode_t priv_mode = PM_NONE; enum priv_mode_t priv_mode = PM_NONE;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* Sanity check: backend group exists */ /* Sanity check: backend group exists */
if ((group = clicon_sock_group(h)) == NULL){ if ((group = clicon_sock_group(h)) == NULL){
clicon_err(OE_FATAL, 0, "clicon_sock_group option not set"); clicon_err(OE_FATAL, 0, "clicon_sock_group option not set");
@ -635,7 +639,7 @@ restconf_drop_privileges(clicon_handle h)
case PM_NONE: case PM_NONE:
break; /* catched above */ break; /* catched above */
} }
clicon_debug(1, "%s dropped privileges from root to %s(%d)", clixon_debug(CLIXON_DBG_DEFAULT, "%s dropped privileges from root to %s(%d)",
__FUNCTION__, user, newuid); __FUNCTION__, user, newuid);
ok: ok:
retval = 0; retval = 0;
@ -643,8 +647,9 @@ restconf_drop_privileges(clicon_handle h)
return retval; return retval;
} }
/*! /*! restconf auth cb
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] pretty Pretty-print * @param[in] pretty Pretty-print
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
@ -666,9 +671,9 @@ restconf_authentication_cb(clicon_handle h,
cxobj *xret = NULL; cxobj *xret = NULL;
cxobj *xerr; cxobj *xerr;
char *anonymous = NULL; char *anonymous = NULL;
auth_type = restconf_auth_type_get(h); auth_type = restconf_auth_type_get(h);
clicon_debug(1, "%s auth-type:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type)); clixon_debug(CLIXON_DBG_DEFAULT, "%s auth-type:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type));
ret = 0; ret = 0;
authenticated = 0; authenticated = 0;
/* ret: -1 Error, 0: Ignore/not handled, 1: OK see authenticated parameter */ /* ret: -1 Error, 0: Ignore/not handled, 1: OK see authenticated parameter */
@ -689,7 +694,7 @@ restconf_authentication_cb(clicon_handle h,
if ((anonymous = clicon_option_str(h, "CLICON_ANONYMOUS_USER")) == NULL){ if ((anonymous = clicon_option_str(h, "CLICON_ANONYMOUS_USER")) == NULL){
break; /* not authenticated */ break; /* not authenticated */
} }
clicon_username_set(h, anonymous); clicon_username_set(h, anonymous);
authenticated = 1; authenticated = 1;
break; break;
case CLIXON_AUTH_CLIENT_CERTIFICATE: { case CLIXON_AUTH_CLIENT_CERTIFICATE: {
@ -701,7 +706,7 @@ restconf_authentication_cb(clicon_handle h,
} }
break; break;
} }
case CLIXON_AUTH_USER: case CLIXON_AUTH_USER:
authenticated = 0; authenticated = 0;
break; break;
} }
@ -720,7 +725,7 @@ restconf_authentication_cb(clicon_handle h,
/* If set but no user, set a dummy user */ /* If set but no user, set a dummy user */
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval:%d authenticated:%d user:%s", clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d authenticated:%d user:%s",
__FUNCTION__, retval, authenticated, clicon_username_get(h)); __FUNCTION__, retval, authenticated, clicon_username_get(h));
if (username) if (username)
free(username); free(username);
@ -752,7 +757,7 @@ restconf_config_init(clicon_handle h,
int auth_type; int auth_type;
yang_stmt *yspec; yang_stmt *yspec;
yang_stmt *y; yang_stmt *y;
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -763,7 +768,7 @@ restconf_config_init(clicon_handle h,
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL && if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
(enable = xml_body(x)) != NULL){ (enable = xml_body(x)) != NULL){
if (strcmp(enable, "false") == 0){ if (strcmp(enable, "false") == 0){
clicon_debug(1, "%s restconf disabled", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s restconf disabled", __FUNCTION__);
goto disable; goto disable;
} }
} }
@ -794,7 +799,7 @@ restconf_config_init(clicon_handle h,
strcmp(bstr, "true") == 0) { strcmp(bstr, "true") == 0) {
restconf_http_data_set(h, 1); restconf_http_data_set(h, 1);
} }
else else
restconf_http_data_set(h, 0); restconf_http_data_set(h, 0);
/* Check if fcgi-socket is true and that feature is enabled /* Check if fcgi-socket is true and that feature is enabled
@ -817,14 +822,16 @@ restconf_config_init(clicon_handle h,
} }
/*! Create and bind restconf socket /*! Create and bind restconf socket
* *
* @param[in] netns0 Network namespace, special value "default" is same as NULL * @param[in] netns0 Network namespace, special value "default" is same as NULL
* @param[in] addrstr Address as string, eg "0.0.0.0", "::" * @param[in] addrstr Address as string, eg "0.0.0.0", "::"
* @param[in] addrtype One of inet:ipv4-address or inet:ipv6-address * @param[in] addrtype One of inet:ipv4-address or inet:ipv6-address
* @param[in] port TCP port * @param[in] port TCP port
* @param[in] backlog Listen backlog, queie of pending connections * @param[in] backlog Listen backlog, queie of pending connections
* @param[in] flags Socket flags OR:ed in with the socket(2) type parameter * @param[in] flags Socket flags OR:ed in with the socket(2) type parameter
* @param[out] ss Server socket (bound for accept) * @param[out] ss Server socket (bound for accept)
* @retval 0 OK
* @retval -1 Error
*/ */
int int
restconf_socket_init(const char *netns0, restconf_socket_init(const char *netns0,
@ -841,7 +848,7 @@ restconf_socket_init(const char *netns0,
size_t sa_len; size_t sa_len;
const char *netns; const char *netns;
clicon_debug(1, "%s %s %s %s %hu", __FUNCTION__, netns0, addrtype, addrstr, port); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s %s %s %hu", __FUNCTION__, netns0, addrtype, addrstr, port);
/* netns default -> NULL */ /* netns default -> NULL */
if (netns0 != NULL && strcmp(netns0, RESTCONF_NETNS_DEFAULT)==0) if (netns0 != NULL && strcmp(netns0, RESTCONF_NETNS_DEFAULT)==0)
netns = NULL; netns = NULL;
@ -851,10 +858,10 @@ restconf_socket_init(const char *netns0,
goto done; goto done;
if (clixon_netns_socket(netns, sa, sa_len, backlog, flags, addrstr, ss) < 0) if (clixon_netns_socket(netns, sa, sa_len, backlog, flags, addrstr, ss) < 0)
goto done; goto done;
clicon_debug(1, "%s ss=%d", __FUNCTION__, *ss); clixon_debug(CLIXON_DBG_DEFAULT, "%s ss=%d", __FUNCTION__, *ss);
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }

View file

@ -45,6 +45,7 @@ extern "C" {
* Types * Types
*/ */
/*! RESTCONF media types /*! RESTCONF media types
*
* @see http_media_map * @see http_media_map
* @note DUPLICATED in clixon_restconf.h * @note DUPLICATED in clixon_restconf.h
*/ */
@ -76,7 +77,7 @@ enum restconf_http_proto{
HTTP_2 HTTP_2
}; };
typedef enum restconf_http_proto restconf_http_proto; typedef enum restconf_http_proto restconf_http_proto;
/* /*
* Prototypes * Prototypes
*/ */

View file

@ -91,8 +91,11 @@
#define RESTCONF_OPTS "hD:f:E:l:C:p:d:y:a:u:rW:R:o:" #define RESTCONF_OPTS "hD:f:E:l:C:p:d:y:a:u:rW:R:o:"
/*! Convert FCGI parameters to clixon runtime data /*! Convert FCGI parameters to clixon runtime data
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] envp Fastcgi request handle parameter array on the format "<param>=<value>" * @param[in] envp Fastcgi request handle parameter array on the format "<param>=<value>"
* @retval 0 OK
* @retval -1 Error
* @see https://nginx.org/en/docs/http/ngx_http_core_module.html#var_https * @see https://nginx.org/en/docs/http/ngx_http_core_module.html#var_https
*/ */
static int static int
@ -104,7 +107,7 @@ fcgi_params_set(clicon_handle h,
char *param = NULL; char *param = NULL;
char *val = NULL; char *val = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
for (i = 0; envp[i] != NULL; i++){ /* on the form <param>=<value> */ for (i = 0; envp[i] != NULL; i++){ /* on the form <param>=<value> */
if (clixon_strsplit(envp[i], '=', &param, &val) < 0) if (clixon_strsplit(envp[i], '=', &param, &val) < 0)
goto done; goto done;
@ -121,7 +124,7 @@ fcgi_params_set(clicon_handle h,
} }
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }
@ -134,7 +137,7 @@ restconf_main_config(clicon_handle h,
{ {
int retval = -1; int retval = -1;
struct passwd *pw; struct passwd *pw;
cxobj *xconfig = NULL; cxobj *xconfig = NULL;
cxobj *xrestconf = NULL; cxobj *xrestconf = NULL;
uint32_t id = 0; uint32_t id = 0;
cxobj *xerr = NULL; cxobj *xerr = NULL;
@ -144,7 +147,7 @@ restconf_main_config(clicon_handle h,
/* 1. try inline configure option */ /* 1. try inline configure option */
if (inline_config != NULL && strlen(inline_config)){ if (inline_config != NULL && strlen(inline_config)){
clicon_debug(1, "restconf_main_fcgi using restconf inline config"); clixon_debug(CLIXON_DBG_DEFAULT, "restconf_main_fcgi using restconf inline config");
if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf, &xerr)) < 0) if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
@ -217,19 +220,19 @@ static clicon_handle _CLICON_HANDLE = NULL;
*/ */
static int _MYSOCK; static int _MYSOCK;
/*! Signall terminates process /*! Signal terminates process
*/ */
static void static void
restconf_sig_term(int arg) restconf_sig_term(int arg)
{ {
static int i=0; static int i=0;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (i++ == 0) if (i++ == 0)
clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d", clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d",
__PROGRAM__, __FUNCTION__, getpid(), arg); __PROGRAM__, __FUNCTION__, getpid(), arg);
else{ else{
clicon_debug(1, "%s done", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s done", __FUNCTION__);
exit(-1); exit(-1);
} }
@ -237,11 +240,12 @@ restconf_sig_term(int arg)
* is entered, it will terminate. * is entered, it will terminate.
* However there may be a case of sockets closing rather abruptly for clients * However there may be a case of sockets closing rather abruptly for clients
*/ */
clixon_exit_set(1); clixon_exit_set(1);
close(_MYSOCK); close(_MYSOCK);
} }
/*! Reap stream child /*! Reap stream child
*
* XXX The -1 should be changed to proper pid, see eg clixon_process_waitpid * XXX The -1 should be changed to proper pid, see eg clixon_process_waitpid
*/ */
static void static void
@ -255,8 +259,9 @@ restconf_sig_child(int arg)
} }
/*! Usage help routine /*! Usage help routine
*
* @param[in] h Clixon handle
* @param[in] argv0 command line * @param[in] argv0 command line
* @param[in] h Clicon handle
*/ */
static void static void
usage(clicon_handle h, usage(clicon_handle h,
@ -285,9 +290,9 @@ usage(clicon_handle h,
} }
/*! Main routine for fastcgi restconf */ /*! Main routine for fastcgi restconf */
int int
main(int argc, main(int argc,
char **argv) char **argv)
{ {
int retval = -1; int retval = -1;
int sock; int sock;
@ -318,7 +323,7 @@ main(int argc,
enum format_enum config_dump_format = FORMAT_XML; enum format_enum config_dump_format = FORMAT_XML;
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
/* Create handle */ /* Create handle */
if ((h = restconf_handle_init()) == NULL) if ((h = restconf_handle_init()) == NULL)
@ -355,12 +360,12 @@ main(int argc,
break; break;
} /* switch getopt */ } /* switch getopt */
/* /*
* Logs, error and debug to stderr or syslog, set debug level * Logs, error and debug to stderr or syslog, set debug level
*/ */
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst); clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
clicon_log(LOG_NOTICE, "%s fcgi: %u Started", __PROGRAM__, getpid()); clicon_log(LOG_NOTICE, "%s fcgi: %u Started", __PROGRAM__, getpid());
if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){ if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){
clicon_err(OE_DAEMON, errno, "Setting signal"); clicon_err(OE_DAEMON, errno, "Setting signal");
@ -450,10 +455,10 @@ main(int argc,
if ((sz = clicon_option_int(h, "CLICON_LOG_STRING_LIMIT")) != 0) if ((sz = clicon_option_int(h, "CLICON_LOG_STRING_LIMIT")) != 0)
clicon_log_string_limit_set(sz); clicon_log_string_limit_set(sz);
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */ /* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
xml_nsctx_namespace_netconf_default(h); xml_nsctx_namespace_netconf_default(h);
/* Add (hardcoded) netconf features in case ietf-netconf loaded here /* Add (hardcoded) netconf features in case ietf-netconf loaded here
* Otherwise it is loaded in netconf_module_load below * Otherwise it is loaded in netconf_module_load below
*/ */
@ -470,7 +475,7 @@ main(int argc,
goto done; goto done;
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */ /* In case ietf-yang-metadata is loaded by application, handle annotation extension */
if (yang_metadata_init(h) < 0) if (yang_metadata_init(h) < 0)
goto done; goto done;
/* Load restconf plugins before yangs are loaded (eg extension callbacks) */ /* Load restconf plugins before yangs are loaded (eg extension callbacks) */
if ((dir = clicon_restconf_dir(h)) != NULL) if ((dir = clicon_restconf_dir(h)) != NULL)
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0) if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
@ -510,7 +515,7 @@ main(int argc,
/* Load yang restconf module */ /* Load yang restconf module */
if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0) if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0)
goto done; goto done;
#ifdef CLIXON_YANG_PATCH #ifdef CLIXON_YANG_PATCH
/* Load yang restconf patch module */ /* Load yang restconf patch module */
if (yang_spec_parse_module(h, "ietf-yang-patch", NULL, yspec)< 0) if (yang_spec_parse_module(h, "ietf-yang-patch", NULL, yspec)< 0)
@ -520,7 +525,7 @@ main(int argc,
/* Add netconf yang spec, used as internal protocol */ /* Add netconf yang spec, used as internal protocol */
if (netconf_module_load(h) < 0) if (netconf_module_load(h) < 0)
goto done; goto done;
/* Add system modules */ /* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") && if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0) yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0)
@ -561,7 +566,7 @@ main(int argc,
clicon_err(OE_CFG, errno, "FCGX_Init"); clicon_err(OE_CFG, errno, "FCGX_Init");
goto done; goto done;
} }
clicon_debug(1, "restconf_main: Opening FCGX socket: %s", sockpath); clixon_debug(CLIXON_DBG_DEFAULT, "restconf_main: Opening FCGX socket: %s", sockpath);
if ((sock = FCGX_OpenSocket(sockpath, 10)) < 0){ if ((sock = FCGX_OpenSocket(sockpath, 10)) < 0){
clicon_err(OE_CFG, errno, "FCGX_OpenSocket"); clicon_err(OE_CFG, errno, "FCGX_OpenSocket");
goto done; goto done;
@ -596,7 +601,7 @@ main(int argc,
* @see clicon_hello_req * @see clicon_hello_req
*/ */
clicon_data_set(h, "session-transport", "cl:restconf"); clicon_data_set(h, "session-transport", "cl:restconf");
if (FCGX_InitRequest(req, sock, 0) != 0){ if (FCGX_InitRequest(req, sock, 0) != 0){
clicon_err(OE_CFG, errno, "FCGX_InitRequest"); clicon_err(OE_CFG, errno, "FCGX_InitRequest");
goto done; goto done;
@ -608,7 +613,7 @@ main(int argc,
clicon_err(OE_CFG, errno, "FCGX_Accept_r"); clicon_err(OE_CFG, errno, "FCGX_Accept_r");
goto done; goto done;
} }
clicon_debug(1, "------------"); clixon_debug(CLIXON_DBG_DEFAULT, "------------");
/* Translate from FCGI parameter form to Clixon runtime data /* Translate from FCGI parameter form to Clixon runtime data
* XXX: potential name collision? * XXX: potential name collision?
@ -616,7 +621,7 @@ main(int argc,
if (fcgi_params_set(h, req->envp) < 0) if (fcgi_params_set(h, req->envp) < 0)
goto done; goto done;
if ((path = restconf_param_get(h, "REQUEST_URI")) == NULL){ if ((path = restconf_param_get(h, "REQUEST_URI")) == NULL){
clicon_debug(1, "NULL URI"); clixon_debug(CLIXON_DBG_DEFAULT, "NULL URI");
} }
else { else {
/* Matching algorithm: /* Matching algorithm:
@ -637,7 +642,7 @@ main(int argc,
if (uri_str2cvec(query, '&', '=', 1, &qvec) < 0) if (uri_str2cvec(query, '&', '=', 1, &qvec) < 0)
goto done; goto done;
if (api_root_restconf(h, req, qvec) < 0) if (api_root_restconf(h, req, qvec) < 0)
goto done; goto done;
} }
else if (api_path_is_stream(h)){ else if (api_path_is_stream(h)){
query = restconf_param_get(h, "QUERY_STRING"); query = restconf_param_get(h, "QUERY_STRING");
@ -648,9 +653,9 @@ main(int argc,
(void)api_stream(h, req, qvec, &finish); (void)api_stream(h, req, qvec, &finish);
} }
else{ else{
clicon_debug(1, "top-level %s not found", path); clixon_debug(CLIXON_DBG_DEFAULT, "top-level %s not found", path);
if (netconf_invalid_value_xml(&xerr, "protocol", "Top-level path not found") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Top-level path not found") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, 1, YANG_DATA_JSON, 0) < 0) if (api_return_err0(h, req, xerr, 1, YANG_DATA_JSON, 0) < 0)
goto done; goto done;
if (xerr){ if (xerr){

View file

@ -180,11 +180,13 @@ static int session_id_context = 1;
/*! Set restconf native handle /*! Set restconf native handle
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] rh Restconf native handle (malloced pointer) * @param[in] rh Restconf native handle (malloced pointer)
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
restconf_native_handle_set(clicon_handle h, restconf_native_handle_set(clicon_handle h,
restconf_native_handle *rh) restconf_native_handle *rh)
{ {
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
@ -215,7 +217,7 @@ clixon_openssl_log_cb(void *handle,
int suberr, int suberr,
cbuf *cb) cbuf *cb)
{ {
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
ERR_print_errors_cb(print_cb, cb); ERR_print_errors_cb(print_cb, cb);
return 0; return 0;
} }
@ -224,7 +226,7 @@ clixon_openssl_log_cb(void *handle,
*/ */
static int static int
init_openssl(void) init_openssl(void)
{ {
int retval = -1; int retval = -1;
/* In Openssl 1.1 lib inits itself (?) /* In Openssl 1.1 lib inits itself (?)
@ -241,7 +243,8 @@ init_openssl(void)
return retval; return retval;
} }
/*! /*! Verify cert
*
* The verify_callback function is used to control the behaviour when the SSL_VERIFY_PEER flag * The verify_callback function is used to control the behaviour when the SSL_VERIFY_PEER flag
* is set. It must be supplied by the application and receives two arguments: preverify_ok * is set. It must be supplied by the application and receives two arguments: preverify_ok
* indicates, whether the verification of the certificate in question was passed * indicates, whether the verification of the certificate in question was passed
@ -258,23 +261,22 @@ restconf_verify_certs(int preverify_ok,
int depth; int depth;
// SSL *ssl; // SSL *ssl;
// clicon_handle h; // clicon_handle h;
err_cert = X509_STORE_CTX_get_current_cert(store); err_cert = X509_STORE_CTX_get_current_cert(store);
err = X509_STORE_CTX_get_error(store); err = X509_STORE_CTX_get_error(store);
depth = X509_STORE_CTX_get_error_depth(store); depth = X509_STORE_CTX_get_error_depth(store);
// ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()); // ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
clicon_debug(1, "%s preverify_ok:%d err:%d depth:%d", __FUNCTION__, preverify_ok, err, depth); clixon_debug(CLIXON_DBG_DEFAULT, "%s preverify_ok:%d err:%d depth:%d", __FUNCTION__, preverify_ok, err, depth);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
switch (err){ switch (err){
case X509_V_ERR_HOSTNAME_MISMATCH: case X509_V_ERR_HOSTNAME_MISMATCH:
clicon_debug(1, "%s X509_V_ERR_HOSTNAME_MISMATCH", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s X509_V_ERR_HOSTNAME_MISMATCH", __FUNCTION__);
break; break;
case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CERT_HAS_EXPIRED:
clicon_debug(1, "%s X509_V_ERR_CERT_HAS_EXPIRED", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s X509_V_ERR_CERT_HAS_EXPIRED", __FUNCTION__);
break; break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
clicon_debug(1, "%s X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT", __FUNCTION__);
break; break;
} }
/* Catch a too long certificate chain. should be +1 in SSL_CTX_set_verify_depth() */ /* Catch a too long certificate chain. should be +1 in SSL_CTX_set_verify_depth() */
@ -282,7 +284,7 @@ restconf_verify_certs(int preverify_ok,
preverify_ok = 0; preverify_ok = 0;
err = X509_V_ERR_CERT_CHAIN_TOO_LONG; err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
X509_STORE_CTX_set_error(store, err); X509_STORE_CTX_set_error(store, err);
} }
else{ else{
/* Verify the CA name */ /* Verify the CA name */
} }
@ -303,7 +305,7 @@ alpn_proto_dump(const char *label,
const char *inp, const char *inp,
unsigned len) unsigned len)
{ {
clicon_debug(1, "%s %.*s", label, (int)len, inp); clixon_debug(CLIXON_DBG_DEFAULT, "%s %.*s", label, (int)len, inp);
return 0; return 0;
} }
@ -325,13 +327,13 @@ alpn_select_proto_cb(SSL *ssl,
unsigned char len; unsigned char len;
int pref = 0; int pref = 0;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* select http/1.1 */ /* select http/1.1 */
inp = (unsigned char*)in; inp = (unsigned char*)in;
while ((inp-in) < inlen) { while ((inp-in) < inlen) {
len = *inp; len = *inp;
inp++; inp++;
if (clicon_debug_get()) /* debug print the protoocol */ if (clixon_debug_get()) /* debug print the protoocol */
alpn_proto_dump(__FUNCTION__, (const char*)inp, len); alpn_proto_dump(__FUNCTION__, (const char*)inp, len);
#ifdef HAVE_HTTP1 #ifdef HAVE_HTTP1
if (pref < 10 && len == 8 && strncmp((char*)inp, "http/1.1", len) == 0){ if (pref < 10 && len == 8 && strncmp((char*)inp, "http/1.1", len) == 0){
@ -454,18 +456,18 @@ restconf_listcerts(SSL *ssl)
X509 *cert; X509 *cert;
char *line; char *line;
clicon_debug(1, "%s get peer certificates:", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s get peer certificates:", __FUNCTION__);
if ((cert = SSL_get_peer_certificate(ssl)) != NULL) { /* Get certificates (if available) */ if ((cert = SSL_get_peer_certificate(ssl)) != NULL) { /* Get certificates (if available) */
if ((line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) != NULL){ if ((line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) != NULL){
clicon_debug(1, "Subject: %s", line); clixon_debug(CLIXON_DBG_DEFAULT, "Subject: %s", line);
free(line); free(line);
} }
if ((line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) != NULL){ if ((line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) != NULL){
clicon_debug(1, "Issuer: %s", line); clixon_debug(CLIXON_DBG_DEFAULT, "Issuer: %s", line);
free(line); free(line);
} }
if ((line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) != NULL){ if ((line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) != NULL){
clicon_debug(1, "Subject: %s", line); clixon_debug(CLIXON_DBG_DEFAULT, "Subject: %s", line);
free(line); free(line);
} }
X509_free(cert); X509_free(cert);
@ -475,7 +477,7 @@ restconf_listcerts(SSL *ssl)
#endif/* debug */ #endif/* debug */
/*! Check if a "cert" file exists /*! Check if a "cert" file exists
* *
* @param[in] xrestconf XML tree containing restconf config * @param[in] xrestconf XML tree containing restconf config
* @param[in] name Name of configured "cert" name * @param[in] name Name of configured "cert" name
* @param[out] var String variable * @param[out] var String variable
@ -515,6 +517,8 @@ restconf_checkcert_file(cxobj *xrestconf,
* *
* @param[in] fd Socket (unix or ip) * @param[in] fd Socket (unix or ip)
* @param[in] arg typecast clicon_handle * @param[in] arg typecast clicon_handle
* @retval 0 OK
* @retval -1 Error
* @see openssl_init_socket where this callback is registered * @see openssl_init_socket where this callback is registered
*/ */
static int static int
@ -530,11 +534,11 @@ restconf_accept_client(int fd,
char *name = NULL; char *name = NULL;
void *addr; void *addr;
clicon_debug(1, "%s %d", __FUNCTION__, fd); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, fd);
if ((rsock = (restconf_socket *)arg) == NULL){ if ((rsock = (restconf_socket *)arg) == NULL){
clicon_err(OE_YANG, EINVAL, "rsock is NULL"); clicon_err(OE_YANG, EINVAL, "rsock is NULL");
goto done; goto done;
} }
h = rsock->rs_h; h = rsock->rs_h;
len = sizeof(from); len = sizeof(from);
if ((s = accept(rsock->rs_ss, &from, &len)) < 0){ if ((s = accept(rsock->rs_ss, &from, &len)) < 0){
@ -566,7 +570,7 @@ restconf_accept_client(int fd,
} }
if (inet_ntop(from.sa_family, addr, rsock->rs_from_addr, INET6_ADDRSTRLEN) < 0) if (inet_ntop(from.sa_family, addr, rsock->rs_from_addr, INET6_ADDRSTRLEN) < 0)
goto done; goto done;
clicon_debug(1, "%s type:%s from:%s, dest:%s port:%hu", __FUNCTION__, clixon_debug(CLIXON_DBG_DEFAULT, "%s type:%s from:%s, dest:%s port:%hu", __FUNCTION__,
rsock->rs_addrtype, rsock->rs_addrtype,
rsock->rs_from_addr, rsock->rs_from_addr,
rsock->rs_addrstr, rsock->rs_addrstr,
@ -577,7 +581,7 @@ restconf_accept_client(int fd,
goto done; goto done;
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval %d", __FUNCTION__, retval);
if (name) if (name)
free(name); free(name);
return retval; return retval;
@ -592,7 +596,7 @@ restconf_native_terminate(clicon_handle h)
restconf_socket *rsock; restconf_socket *rsock;
restconf_conn *rc; restconf_conn *rc;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((rn = restconf_native_handle_get(h)) != NULL){ if ((rn = restconf_native_handle_get(h)) != NULL){
while ((rsock = rn->rn_sockets) != NULL){ while ((rsock = rn->rn_sockets) != NULL){
while ((rc = rsock->rs_conns) != NULL){ while ((rc = rsock->rs_conns) != NULL){
@ -702,11 +706,11 @@ restconf_clixon_backend(clicon_handle h,
/*! Per-socket openssl inits /*! Per-socket openssl inits
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xs XML config of single restconf socket * @param[in] xs XML config of single restconf socket
* @param[in] nsc Namespace context * @param[in] nsc Namespace context
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
openssl_init_socket(clicon_handle h, openssl_init_socket(clicon_handle h,
@ -723,7 +727,7 @@ openssl_init_socket(clicon_handle h,
restconf_socket *rsock = NULL; /* openssl per socket struct */ restconf_socket *rsock = NULL; /* openssl per socket struct */
struct timeval now; struct timeval now;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* /*
* Create per-socket openssl handle * Create per-socket openssl handle
* See restconf_native_terminate for freeing * See restconf_native_terminate for freeing
@ -782,7 +786,7 @@ openssl_init_socket(clicon_handle h,
/* ss is a server socket that the clients connect to. The callback /* ss is a server socket that the clients connect to. The callback
therefore accepts clients on ss */ therefore accepts clients on ss */
rsock->rs_ss = ss; rsock->rs_ss = ss;
if (clixon_event_reg_fd(rsock->rs_ss, restconf_accept_client, rsock, "restconf socket") < 0) if (clixon_event_reg_fd(rsock->rs_ss, restconf_accept_client, rsock, "restconf socket") < 0)
goto done; goto done;
} }
retval = 0; retval = 0;
@ -793,7 +797,7 @@ openssl_init_socket(clicon_handle h,
/*! Init openssl, open and register server socket (ready for accept) /*! Init openssl, open and register server socket (ready for accept)
* *
* Given a fully populated configuration tree. * Given a fully populated configuration tree.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] dbg0 Manually set debug flag, if set overrides configuration setting * @param[in] dbg0 Manually set debug flag, if set overrides configuration setting
* @param[in] xrestconf XML tree containing restconf config * @param[in] xrestconf XML tree containing restconf config
* @retval 0 OK * @retval 0 OK
@ -820,7 +824,7 @@ restconf_openssl_init(clicon_handle h,
size_t veclen; size_t veclen;
int i; int i;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* flag used for sanity of certs */ /* flag used for sanity of certs */
ssl_enable = xpath_first(xrestconf, nsc, "socket[ssl='true']") != NULL; ssl_enable = xpath_first(xrestconf, nsc, "socket[ssl='true']") != NULL;
/* Auth type set in config */ /* Auth type set in config */
@ -830,7 +834,7 @@ restconf_openssl_init(clicon_handle h,
(x = xpath_first(xrestconf, nsc, "debug")) != NULL && (x = xpath_first(xrestconf, nsc, "debug")) != NULL &&
(bstr = xml_body(x)) != NULL){ (bstr = xml_body(x)) != NULL){
dbg = atoi(bstr); dbg = atoi(bstr);
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
/* If debug was enabled here from config and not initially, /* If debug was enabled here from config and not initially,
* print clixn options and loaded yang files * print clixn options and loaded yang files
*/ */
@ -889,7 +893,7 @@ restconf_openssl_init(clicon_handle h,
return retval; return retval;
} }
/*! Read restconf from config /*! Read restconf from config
* *
* After SEVERAL iterations the code now does as follows: * After SEVERAL iterations the code now does as follows:
* - init clixon * - init clixon
@ -897,13 +901,13 @@ restconf_openssl_init(clicon_handle h,
* - if local config found, open sockets accordingly and exit function * - if local config found, open sockets accordingly and exit function
* - If no local config found, query backend for config and open sockets. * - If no local config found, query backend for config and open sockets.
* That is, EITHER local config OR read config from backend once * That is, EITHER local config OR read config from backend once
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] inline_config If set, restconf conf is given by -R command-line * @param[in] inline_config If set, restconf conf is given by -R command-line
* @param[out] xrestconf XML restconf config, malloced (if retval = 1) * @param[out] xrestconf XML restconf config, malloced (if retval = 1)
* @retval 1 OK (and xrestconf set) * @retval 1 OK (and xrestconf set)
* @retval 0 Fail - no config * @retval 0 Fail - no config
* @retval -1 Error * @retval -1 Error
*/ */
int int
restconf_clixon_init(clicon_handle h, restconf_clixon_init(clicon_handle h,
char *inline_config, char *inline_config,
@ -984,7 +988,6 @@ restconf_clixon_init(clicon_handle h,
/* Load yang restconf module */ /* Load yang restconf module */
if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0) if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0)
goto done; goto done;
#ifdef CLIXON_YANG_PATCH #ifdef CLIXON_YANG_PATCH
/* Load yang restconf patch module */ /* Load yang restconf patch module */
if (yang_spec_parse_module(h, "ietf-yang-patch", NULL, yspec)< 0) if (yang_spec_parse_module(h, "ietf-yang-patch", NULL, yspec)< 0)
@ -1010,7 +1013,7 @@ restconf_clixon_init(clicon_handle h,
if (clicon_nsctx_global_set(h, nsctx_global) < 0) if (clicon_nsctx_global_set(h, nsctx_global) < 0)
goto done; goto done;
if (inline_config != NULL && strlen(inline_config)){ if (inline_config != NULL && strlen(inline_config)){
clicon_debug(1, "%s reading from inline config", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s reading from inline config", __FUNCTION__);
if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf, &xerr)) < 0) if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
@ -1032,10 +1035,10 @@ restconf_clixon_init(clicon_handle h,
goto done; goto done;
} }
else if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){ else if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
clicon_debug(1, "%s reading from clixon config", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s reading from clixon config", __FUNCTION__);
/* If not read from backend, try to get restconf config from local config-file */ /* If not read from backend, try to get restconf config from local config-file */
if ((xrestconf = clicon_conf_restconf(h)) != NULL){ if ((xrestconf = clicon_conf_restconf(h)) != NULL){
/*! Basic config init, set auth-type, pretty, etc ret 0 means disabled */ /* Basic config init, set auth-type, pretty, etc ret 0 means disabled */
if ((ret = restconf_config_init(h, xrestconf)) < 0) if ((ret = restconf_config_init(h, xrestconf)) < 0)
goto done; goto done;
/* ret == 1 means this config is OK */ /* ret == 1 means this config is OK */
@ -1050,7 +1053,7 @@ restconf_clixon_init(clicon_handle h,
/* If no local config, or it is disabled, try to query backend of config. /* If no local config, or it is disabled, try to query backend of config.
*/ */
else { else {
clicon_debug(1, "%s reading from backend datastore config", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s reading from backend datastore config", __FUNCTION__);
if ((ret = restconf_clixon_backend(h, xrestconfp)) < 0) if ((ret = restconf_clixon_backend(h, xrestconfp)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
@ -1075,7 +1078,7 @@ restconf_sig_term(int arg)
{ {
static int i=0; static int i=0;
clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d", clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d",
__PROGRAM__, __FUNCTION__, getpid(), arg); __PROGRAM__, __FUNCTION__, getpid(), arg);
if (i++ > 0) /* Allow one sigterm before proper exit */ if (i++ > 0) /* Allow one sigterm before proper exit */
exit(-1); exit(-1);
@ -1083,13 +1086,13 @@ restconf_sig_term(int arg)
* is entered, it will terminate. * is entered, it will terminate.
* However there may be a case of sockets closing rather abruptly for clients * However there may be a case of sockets closing rather abruptly for clients
*/ */
clixon_exit_set(1); clixon_exit_set(1);
} }
/*! Usage help routine /*! Usage help routine
* *
* @param[in] argv0 command line * @param[in] argv0 command line
* @param[in] h Clicon handle * @param[in] h Clixon handle
*/ */
static void static void
usage(clicon_handle h, usage(clicon_handle h,
@ -1138,7 +1141,7 @@ main(int argc,
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
/* Create handle */ /* Create handle */
if ((h = restconf_handle_init()) == NULL) if ((h = restconf_handle_init()) == NULL)
goto done; goto done;
@ -1175,7 +1178,7 @@ main(int argc,
/* /*
* Logs, error and debug to stderr or syslog, set debug level * Logs, error and debug to stderr or syslog, set debug level
*/ */
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst); clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
/* /*
* Register error category and error/log callbacks for openssl special error handling * Register error category and error/log callbacks for openssl special error handling
@ -1195,7 +1198,7 @@ main(int argc,
) < 0) ) < 0)
goto done; goto done;
#endif #endif
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
clicon_log(LOG_NOTICE, "%s native %u Started", __PROGRAM__, getpid()); clicon_log(LOG_NOTICE, "%s native %u Started", __PROGRAM__, getpid());
if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){ if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){
clicon_err(OE_DAEMON, errno, "Setting signal"); clicon_err(OE_DAEMON, errno, "Setting signal");
@ -1214,7 +1217,6 @@ main(int argc,
if (clicon_options_main(h) < 0) if (clicon_options_main(h) < 0)
goto done; goto done;
// stream_path = clicon_option_str(h, "CLICON_STREAM_PATH"); // stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
/* Now rest of options, some overwrite option file */ /* Now rest of options, some overwrite option file */
optind = 1; optind = 1;
opterr = 0; opterr = 0;
@ -1280,7 +1282,7 @@ main(int argc,
/* Init restconf auth-type */ /* Init restconf auth-type */
restconf_auth_type_set(h, CLIXON_AUTH_NONE); restconf_auth_type_set(h, CLIXON_AUTH_NONE);
/* Explicit dump of config (also debug dump below). */ /* Explicit dump of config (also debug dump below). */
if (config_dump){ if (config_dump){
if (clicon_option_dump1(h, stdout, config_dump_format, 1) < 0) if (clicon_option_dump1(h, stdout, config_dump_format, 1) < 0)
@ -1297,7 +1299,7 @@ main(int argc,
if (clixon_plugin_start_all(h) < 0) if (clixon_plugin_start_all(h) < 0)
goto done; goto done;
/* Clixon inits / configs */ /* Clixon inits / configs */
if ((ret = restconf_clixon_init(h, inline_config, &xrestconf)) < 0) if ((ret = restconf_clixon_init(h, inline_config, &xrestconf)) < 0)
goto done; goto done;
if (ret == 0){ /* restconf disabled */ if (ret == 0){ /* restconf disabled */
@ -1305,7 +1307,7 @@ main(int argc,
retval = 0; retval = 0;
goto done; goto done;
} }
/* Create and stroe global openssl handle */ /* Create and stroe global openssl handle */
if ((rn = malloc(sizeof *rn)) == NULL){ if ((rn = malloc(sizeof *rn)) == NULL){
clicon_err(OE_UNIX, errno, "malloc"); clicon_err(OE_UNIX, errno, "malloc");
goto done; goto done;
@ -1313,7 +1315,7 @@ main(int argc,
memset(rn, 0, sizeof *rn); memset(rn, 0, sizeof *rn);
if (restconf_native_handle_set(h, rn) < 0) if (restconf_native_handle_set(h, rn) < 0)
goto done; goto done;
/* Openssl inits */ /* Openssl inits */
if (restconf_openssl_init(h, dbg, xrestconf) < 0) if (restconf_openssl_init(h, dbg, xrestconf) < 0)
goto done; goto done;
/* Drop privileges if started as root to CLICON_RESTCONF_USER /* Drop privileges if started as root to CLICON_RESTCONF_USER
@ -1327,13 +1329,13 @@ main(int argc,
*/ */
clicon_data_set(h, "session-transport", "cl:restconf"); clicon_data_set(h, "session-transport", "cl:restconf");
/* Main event loop */ /* Main event loop */
if (clixon_event_loop(h) < 0) if (clixon_event_loop(h) < 0)
goto done; goto done;
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "restconf_main_openssl done"); clixon_debug(CLIXON_DBG_DEFAULT, "restconf_main_openssl done");
if (xrestconf) if (xrestconf)
xml_free(xrestconf); xml_free(xrestconf);
restconf_native_terminate(h); restconf_native_terminate(h);

View file

@ -78,10 +78,12 @@
#include "restconf_methods.h" #include "restconf_methods.h"
/*! REST OPTIONS method /*! REST OPTIONS method
*
* According to restconf * According to restconf
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* * @retval 0 OK
* @retval -1 Error
* @code * @code
* curl -G http://localhost/restconf/data/interfaces/interface=eth0 * curl -G http://localhost/restconf/data/interfaces/interface=eth0
* @endcode * @endcode
@ -96,7 +98,7 @@ api_data_options(clicon_handle h,
{ {
int retval = -1; int retval = -1;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (restconf_reply_header(req, "Allow", "OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE") < 0) if (restconf_reply_header(req, "Allow", "OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE") < 0)
goto done; goto done;
if (restconf_reply_header(req, "Accept-Patch", "application/yang-data+xml,application/yang-data+json") < 0) if (restconf_reply_header(req, "Accept-Patch", "application/yang-data+xml,application/yang-data+json") < 0)
@ -117,7 +119,7 @@ api_data_options(clicon_handle h,
* @param[in] x1 First XML tree (eg data) * @param[in] x1 First XML tree (eg data)
* @param[in] x2 Second XML tree (eg api-path) * @param[in] x2 Second XML tree (eg api-path)
* @retval 0 Yes, keys match * @retval 0 Yes, keys match
* @retval -1 No, keys do not match * @retval -1 No, keys do not match
* If the target resource represents a YANG leaf-list, then the PUT * If the target resource represents a YANG leaf-list, then the PUT
* method MUST NOT change the value of the leaf-list instance. * method MUST NOT change the value of the leaf-list instance.
* *
@ -140,14 +142,14 @@ match_list_keys(yang_stmt *y,
char *key1; char *key1;
char *key2; char *key2;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
switch (yang_keyword_get(y)){ switch (yang_keyword_get(y)){
case Y_LIST: case Y_LIST:
if ((cvk = yang_cvec_get(y)) == NULL) /* Use Y_LIST cache, see ys_populate_list() */ if ((cvk = yang_cvec_get(y)) == NULL) /* Use Y_LIST cache, see ys_populate_list() */
break; break;
cvi = NULL; cvi = NULL;
while ((cvi = cvec_each(cvk, cvi)) != NULL) { while ((cvi = cvec_each(cvk, cvi)) != NULL) {
keyname = cv_string_get(cvi); keyname = cv_string_get(cvi);
if ((xkey2 = xml_find(x2, keyname)) == NULL) if ((xkey2 = xml_find(x2, keyname)) == NULL)
goto done; /* No key in api-path */ goto done; /* No key in api-path */
if ((key2 = xml_body(xkey2)) == NULL) if ((key2 = xml_body(xkey2)) == NULL)
@ -174,11 +176,12 @@ match_list_keys(yang_stmt *y,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
} }
/*! Common PUT plain PATCH method /*! Common PUT plain PATCH method
*
* Code checks if object exists. * Code checks if object exists.
* PUT: If it does not, set op to create, otherwise replace * PUT: If it does not, set op to create, otherwise replace
* PATCH: If it does not, fail, otherwise replace/merge * PATCH: If it does not, fail, otherwise replace/merge
@ -187,13 +190,15 @@ match_list_keys(yang_stmt *y,
* @param[in] pretty Pretty-print * @param[in] pretty Pretty-print
* @param[in] media_in Restconf input media * @param[in] media_in Restconf input media
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
*/ * @retval 0 OK
* @retval -1 Error
*/
int int
api_data_write(clicon_handle h, api_data_write(clicon_handle h,
void *req, void *req,
char *api_path0, char *api_path0,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_in, restconf_media media_in,
@ -230,9 +235,9 @@ api_data_write(clicon_handle h,
yang_bind yb; yang_bind yb;
char *xpath = NULL; char *xpath = NULL;
char *attr; char *attr;
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path0); clixon_debug(CLIXON_DBG_DEFAULT, "%s api_path:\"%s\"", __FUNCTION__, api_path0);
clicon_debug(1, "%s data:\"%s\"", __FUNCTION__, data); clixon_debug(CLIXON_DBG_DEFAULT, "%s data:\"%s\"", __FUNCTION__, data);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -290,7 +295,7 @@ api_data_write(clicon_handle h,
if (api_path){ /* XXX mv to copy? */ if (api_path){ /* XXX mv to copy? */
cxobj *xfrom; cxobj *xfrom;
cxobj *xac; cxobj *xac;
if (api_path && (strcmp(api_path, "/") != 0)) if (api_path && (strcmp(api_path, "/") != 0))
xfrom = xml_parent(xbot); xfrom = xml_parent(xbot);
else else
@ -393,7 +398,7 @@ api_data_write(clicon_handle h,
goto done; goto done;
/* Top-of tree, no api-path /* Top-of tree, no api-path
* Replace xparent with x, ie bottom of api-path with data * Replace xparent with x, ie bottom of api-path with data
*/ */
dname = xml_name(xdata); dname = xml_name(xdata);
if (api_path==NULL) { if (api_path==NULL) {
if (strcmp(dname, NETCONF_OUTPUT_DATA)!=0){ if (strcmp(dname, NETCONF_OUTPUT_DATA)!=0){
@ -422,9 +427,9 @@ api_data_write(clicon_handle h,
/* There is an api-path that defines an element in the datastore tree. /* There is an api-path that defines an element in the datastore tree.
* Not top-of-tree. * Not top-of-tree.
*/ */
clicon_debug(1, "%s Comparing bottom-of api-path (%s) with top-of-data (%s)",__FUNCTION__, xml_name(xbot), dname); clixon_debug(CLIXON_DBG_DEFAULT, "%s Comparing bottom-of api-path (%s) with top-of-data (%s)",__FUNCTION__, xml_name(xbot), dname);
/* Check same symbol in api-path as data */ /* Check same symbol in api-path as data */
if (strcmp(dname, xml_name(xbot))){ if (strcmp(dname, xml_name(xbot))){
if (netconf_bad_element_xml(&xerr, "application", dname, if (netconf_bad_element_xml(&xerr, "application", dname,
"Data element does not match api-path") < 0) "Data element does not match api-path") < 0)
@ -439,7 +444,7 @@ api_data_write(clicon_handle h,
* or the object is the key element: * or the object is the key element:
* eg xpath:obj=a/key data:<key>b</key> * eg xpath:obj=a/key data:<key>b</key>
* That is why the conditional is somewhat hairy * That is why the conditional is somewhat hairy
*/ */
xparent = xml_parent(xbot); xparent = xml_parent(xbot);
if (ybot){ if (ybot){
/* Ensure list keys match between uri and data. That is: /* Ensure list keys match between uri and data. That is:
@ -479,7 +484,7 @@ api_data_write(clicon_handle h,
} }
if (xtop != xbot) /* Should always be true */ if (xtop != xbot) /* Should always be true */
xml_purge(xbot); xml_purge(xbot);
if (xml_addsub(xparent, xdata) < 0) if (xml_addsub(xparent, xdata) < 0)
goto done; goto done;
/* If restconf insert/point attributes are present, translate to netconf */ /* If restconf insert/point attributes are present, translate to netconf */
if (restconf_insert_attributes(xdata, qvec) < 0) if (restconf_insert_attributes(xdata, qvec) < 0)
@ -487,11 +492,11 @@ api_data_write(clicon_handle h,
/* If we already have that default namespace, remove it in child */ /* If we already have that default namespace, remove it in child */
if ((xa = xml_find_type(xdata, NULL, "xmlns", CX_ATTR)) != NULL){ if ((xa = xml_find_type(xdata, NULL, "xmlns", CX_ATTR)) != NULL){
if (xml2ns(xparent, NULL, &namespace) < 0){ if (xml2ns(xparent, NULL, &namespace) < 0){
clicon_debug(1, "%s G done", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s G done", __FUNCTION__);
goto done; goto done;
} }
if (namespace == NULL){ if (namespace == NULL){
clicon_debug_xml(1, xparent, "%s xparent:", __FUNCTION__); clixon_debug_xml(1, xparent, "%s xparent:", __FUNCTION__);
/* XXX */ /* XXX */
} }
/* Set xmlns="" default namespace attribute (if diff from default) */ /* Set xmlns="" default namespace attribute (if diff from default) */
@ -535,12 +540,12 @@ api_data_write(clicon_handle h,
if (clixon_xml2cbuf(cbx, xtop, 0, 0, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cbx, xtop, 0, 0, NULL, -1, 0) < 0)
goto done; goto done;
cprintf(cbx, "</edit-config></rpc>"); cprintf(cbx, "</edit-config></rpc>");
clicon_debug(1, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path); clixon_debug(CLIXON_DBG_DEFAULT, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path);
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
if (api_return_err(h, req, xe, pretty, media_out, 0) < 0) if (api_return_err(h, req, xe, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
if ((xe = xpath_first(xret, NULL, "//ok")) != NULL && if ((xe = xpath_first(xret, NULL, "//ok")) != NULL &&
@ -551,11 +556,11 @@ api_data_write(clicon_handle h,
} }
else else
if (restconf_reply_send(req, 204, NULL, 0) < 0) /* No content */ if (restconf_reply_send(req, 204, NULL, 0) < 0) /* No content */
goto done; goto done;
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (xpath) if (xpath)
free(xpath); free(xpath);
if (nsc) if (nsc)
@ -578,6 +583,7 @@ api_data_write(clicon_handle h,
} /* api_data_write */ } /* api_data_write */
/*! Generic REST PUT method /*! Generic REST PUT method
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040)
@ -587,6 +593,8 @@ api_data_write(clicon_handle h,
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* @retval 0 OK
* @retval -1 Error
* @note restconf PUT is mapped to edit-config replace. * @note restconf PUT is mapped to edit-config replace.
* @see RFC8040 Sec 4.5 PUT * @see RFC8040 Sec 4.5 PUT
* @see api_data_post * @see api_data_post
@ -613,10 +621,10 @@ api_data_write(clicon_handle h,
*/ */
int int
api_data_put(clicon_handle h, api_data_put(clicon_handle h,
void *req, void *req,
char *api_path0, char *api_path0,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_out, restconf_media media_out,
@ -627,9 +635,10 @@ api_data_put(clicon_handle h,
media_in = restconf_content_type(h); media_in = restconf_content_type(h);
return api_data_write(h, req, api_path0, pi, qvec, data, pretty, return api_data_write(h, req, api_path0, pi, qvec, data, pretty,
media_in, media_out, 0, ds); media_in, media_out, 0, ds);
} }
/*! Generic REST PATCH method for plain patch /*! Generic REST PATCH method for plain patch
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040)
@ -639,6 +648,8 @@ api_data_put(clicon_handle h,
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* @retval 0 OK
* @retval -1 Error
* Netconf: <edit-config> (nc:operation="merge") * Netconf: <edit-config> (nc:operation="merge")
* See RFC8040 Sec 4.6.1 * See RFC8040 Sec 4.6.1
* Plain patch can be used to create or update, but not delete, a child * Plain patch can be used to create or update, but not delete, a child
@ -648,10 +659,10 @@ api_data_put(clicon_handle h,
*/ */
int int
api_data_patch(clicon_handle h, api_data_patch(clicon_handle h,
void *req, void *req,
char *api_path0, char *api_path0,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_out, restconf_media media_out,
@ -682,9 +693,10 @@ api_data_patch(clicon_handle h,
break; break;
} }
return ret; return ret;
} }
/*! Generic REST DELETE method translated to edit-config /*! Generic REST DELETE method translated to edit-config
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040)
@ -692,6 +704,8 @@ api_data_patch(clicon_handle h,
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* @retval 0 OK
* @retval -1 Error
* See RFC 8040 Sec 4.7 * See RFC 8040 Sec 4.7
* Example: * Example:
* curl -X DELETE http://127.0.0.1/restconf/data/interfaces/interface=eth0 * curl -X DELETE http://127.0.0.1/restconf/data/interfaces/interface=eth0
@ -699,7 +713,7 @@ api_data_patch(clicon_handle h,
*/ */
int int
api_data_delete(clicon_handle h, api_data_delete(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
int pi, int pi,
int pretty, int pretty,
@ -723,7 +737,7 @@ api_data_delete(clicon_handle h,
int ret; int ret;
cxobj *xe; /* xml error, no free */ cxobj *xe; /* xml error, no free */
clicon_debug(1, "%s api_path:%s", __FUNCTION__, api_path); clixon_debug(CLIXON_DBG_DEFAULT, "%s api_path:%s", __FUNCTION__, api_path);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -793,12 +807,12 @@ api_data_delete(clicon_handle h,
goto ok; goto ok;
} }
if (restconf_reply_send(req, 204, NULL, 0) < 0) if (restconf_reply_send(req, 204, NULL, 0) < 0)
goto done; goto done;
ok: ok:
retval = 0; retval = 0;
done: done:
if (cbx) if (cbx)
cbuf_free(cbx); cbuf_free(cbx);
if (xret) if (xret)
xml_free(xret); xml_free(xret);
if (xretcom) if (xretcom)
@ -807,7 +821,7 @@ api_data_delete(clicon_handle h,
xml_free(xretdis); xml_free(xretdis);
if (xtop) if (xtop)
xml_free(xtop); xml_free(xtop);
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
} }

View file

@ -35,7 +35,6 @@
* Restconf method implementation * Restconf method implementation
*/ */
#ifndef _RESTCONF_METHODS_H_ #ifndef _RESTCONF_METHODS_H_
#define _RESTCONF_METHODS_H_ #define _RESTCONF_METHODS_H_
@ -43,19 +42,19 @@
* Prototypes * Prototypes
*/ */
int api_data_options(clicon_handle h, void *req); int api_data_options(clicon_handle h, void *req);
int api_data_write(clicon_handle h, void *req, char *api_path0, int api_data_write(clicon_handle h, void *req, char *api_path0,
int pi, int pi,
cvec *qvec, char *data, cvec *qvec, char *data,
int pretty, restconf_media media_in, restconf_media media_out, int pretty, restconf_media media_in, restconf_media media_out,
int plain_patch, ietf_ds_t ds); int plain_patch, ietf_ds_t ds);
int api_data_put(clicon_handle h, void *req, char *api_path, int api_data_put(clicon_handle h, void *req, char *api_path,
int pi, int pi,
cvec *qvec, char *data, cvec *qvec, char *data,
int pretty, restconf_media media_out, ietf_ds_t ds); int pretty, restconf_media media_out, ietf_ds_t ds);
int api_data_patch(clicon_handle h, void *req, char *api_path, int api_data_patch(clicon_handle h, void *req, char *api_path,
int pi, int pi,
cvec *qvec, char *data, int pretty, cvec *qvec, char *data, int pretty,
restconf_media media_out, ietf_ds_t ds); restconf_media media_out, ietf_ds_t ds);

View file

@ -75,7 +75,9 @@ static int api_data_pagination(clicon_handle h, void *req, char *api_path, int p
* @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] qvec Vector of query string (QUERY_STRING)
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] head If 1 is HEAD, otherwise GET * @param[in] head If 1 is HEAD, otherwise GET
* @retval 0 OK
* @retval -1 Error
* @code * @code
* curl -X GET http://localhost/restconf/data/interfaces/interface=eth0 * curl -X GET http://localhost/restconf/data/interfaces/interface=eth0
* @endcode * @endcode
@ -97,7 +99,7 @@ static int api_data_pagination(clicon_handle h, void *req, char *api_path, int p
static int static int
api_data_get2(clicon_handle h, api_data_get2(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
int pi, int pi,
cvec *qvec, cvec *qvec,
int pretty, int pretty,
@ -125,8 +127,8 @@ api_data_get2(clicon_handle h,
yang_stmt *y = NULL; yang_stmt *y = NULL;
char *defaults = NULL; char *defaults = NULL;
cvec *nscd = NULL; cvec *nscd = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -137,7 +139,7 @@ api_data_get2(clicon_handle h,
if (api_path){ if (api_path){
if ((xtop = xml_new("top", NULL, CX_ELMNT)) == NULL) if ((xtop = xml_new("top", NULL, CX_ELMNT)) == NULL)
goto done; goto done;
/* Translate api-path to xml, but to validate the api-path, note: strict=1 /* Translate api-path to xml, but to validate the api-path, note: strict=1
* xtop and xbot unnecessary for this function but needed by function * xtop and xbot unnecessary for this function but needed by function
*/ */
if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 1, &xbot, &y, &xerr)) < 0) if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 1, &xbot, &y, &xerr)) < 0)
@ -166,7 +168,7 @@ api_data_get2(clicon_handle h,
} }
/* Check for content attribute */ /* Check for content attribute */
if ((attr = cvec_find_str(qvec, "content")) != NULL){ if ((attr = cvec_find_str(qvec, "content")) != NULL){
clicon_debug(1, "%s content=%s", __FUNCTION__, attr); clixon_debug(CLIXON_DBG_DEFAULT, "%s content=%s", __FUNCTION__, attr);
if ((int)(content = netconf_content_str2int(attr)) == -1){ if ((int)(content = netconf_content_str2int(attr)) == -1){
if (netconf_bad_attribute_xml(&xerr, "application", if (netconf_bad_attribute_xml(&xerr, "application",
"content", "Unrecognized value of content attribute") < 0) "content", "Unrecognized value of content attribute") < 0)
@ -178,7 +180,7 @@ api_data_get2(clicon_handle h,
} }
/* Check for depth attribute */ /* Check for depth attribute */
if ((attr = cvec_find_str(qvec, "depth")) != NULL){ if ((attr = cvec_find_str(qvec, "depth")) != NULL){
clicon_debug(1, "%s depth=%s", __FUNCTION__, attr); clixon_debug(CLIXON_DBG_DEFAULT, "%s depth=%s", __FUNCTION__, attr);
if (strcmp(attr, "unbounded") != 0){ if (strcmp(attr, "unbounded") != 0){
char *reason = NULL; char *reason = NULL;
if ((ret = parse_int32(attr, &depth, &reason)) < 0){ if ((ret = parse_int32(attr, &depth, &reason)) < 0){
@ -196,11 +198,11 @@ api_data_get2(clicon_handle h,
} }
} }
if ((attr = cvec_find_str(qvec, "with-defaults")) != NULL){ if ((attr = cvec_find_str(qvec, "with-defaults")) != NULL){
clicon_debug(1, "%s with_defaults=%s", __FUNCTION__, attr); clixon_debug(CLIXON_DBG_DEFAULT, "%s with_defaults=%s", __FUNCTION__, attr);
defaults = attr; defaults = attr;
} }
clicon_debug(1, "%s path:%s", __FUNCTION__, xpath); clixon_debug(CLIXON_DBG_DEFAULT, "%s path:%s", __FUNCTION__, xpath);
ret = clicon_rpc_get(h, xpath, nsc, content, depth, defaults, &xret); ret = clicon_rpc_get(h, xpath, nsc, content, depth, defaults, &xret);
if (ret < 0){ if (ret < 0){
@ -214,8 +216,8 @@ api_data_get2(clicon_handle h,
* We need to cut that tree to only the object. * We need to cut that tree to only the object.
*/ */
#if 0 /* DEBUG */ #if 0 /* DEBUG */
if (clicon_debug_get()) if (clixon_debug_get())
clicon_debug_xml(1, xret, "%s xret:", __FUNCTION__); clixon_debug_xml(CLIXON_DBG_DEFAULT, xret, "%s xret:", __FUNCTION__);
#endif #endif
/* Check if error return */ /* Check if error return */
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
@ -290,7 +292,7 @@ api_data_get2(clicon_handle h,
break; break;
} }
} }
clicon_debug(1, "%s cbuf:%s", __FUNCTION__, cbuf_get(cbx)); clixon_debug(CLIXON_DBG_DEFAULT, "%s cbuf:%s", __FUNCTION__, cbuf_get(cbx));
if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0) if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0)
goto done; goto done;
if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0) if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0)
@ -301,7 +303,7 @@ api_data_get2(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (xpath) if (xpath)
free(xpath); free(xpath);
if (nscd) if (nscd)
@ -322,6 +324,7 @@ api_data_get2(clicon_handle h,
} }
/*! GET Collection /*! GET Collection
*
* According to restconf collection draft. Lists, work in progress * According to restconf collection draft. Lists, work in progress
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
@ -330,7 +333,9 @@ api_data_get2(clicon_handle h,
* @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] qvec Vector of query string (QUERY_STRING)
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] head If 1 is HEAD, otherwise GET * @param[in] head If 1 is HEAD, otherwise GET
* @retval 0 OK
* @retval -1 Error
* @code * @code
* curl -X GET http://localhost/restconf/data/interfaces * curl -X GET http://localhost/restconf/data/interfaces
* @endcode * @endcode
@ -342,7 +347,7 @@ api_data_get2(clicon_handle h,
static int static int
api_data_pagination(clicon_handle h, api_data_pagination(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
int pi, int pi,
cvec *qvec, cvec *qvec,
int pretty, int pretty,
@ -375,8 +380,8 @@ api_data_pagination(clicon_handle h,
char *sort; char *sort;
char *where; char *where;
char *ns; char *ns;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -425,7 +430,7 @@ api_data_pagination(clicon_handle h,
/* Check for content attribute */ /* Check for content attribute */
if ((attr = cvec_find_str(qvec, "content")) != NULL){ if ((attr = cvec_find_str(qvec, "content")) != NULL){
clicon_debug(1, "%s content=%s", __FUNCTION__, attr); clixon_debug(CLIXON_DBG_DEFAULT, "%s content=%s", __FUNCTION__, attr);
if ((int)(content = netconf_content_str2int(attr)) == -1){ if ((int)(content = netconf_content_str2int(attr)) == -1){
if (netconf_bad_attribute_xml(&xerr, "application", if (netconf_bad_attribute_xml(&xerr, "application",
"content", "Unrecognized value of content attribute") < 0) "content", "Unrecognized value of content attribute") < 0)
@ -439,7 +444,7 @@ api_data_pagination(clicon_handle h,
goto ok; goto ok;
} }
} }
clicon_debug(1, "%s path:%s", __FUNCTION__, xpath); clixon_debug(CLIXON_DBG_DEFAULT, "%s path:%s", __FUNCTION__, xpath);
if (content != CONTENT_CONFIG && content != CONTENT_NONCONFIG && content != CONTENT_ALL){ if (content != CONTENT_CONFIG && content != CONTENT_NONCONFIG && content != CONTENT_ALL){
clicon_err(OE_XML, EINVAL, "Invalid content attribute %d", content); clicon_err(OE_XML, EINVAL, "Invalid content attribute %d", content);
goto done; goto done;
@ -447,7 +452,7 @@ api_data_pagination(clicon_handle h,
/* Clixon extensions and collection attributes */ /* Clixon extensions and collection attributes */
/* Check for depth attribute */ /* Check for depth attribute */
if ((attr = cvec_find_str(qvec, "depth")) != NULL){ if ((attr = cvec_find_str(qvec, "depth")) != NULL){
clicon_debug(1, "%s depth=%s", __FUNCTION__, attr); clixon_debug(CLIXON_DBG_DEFAULT, "%s depth=%s", __FUNCTION__, attr);
if (strcmp(attr, "unbounded") != 0){ if (strcmp(attr, "unbounded") != 0){
char *reason = NULL; char *reason = NULL;
if ((ret = parse_int32(attr, &depth, &reason)) < 0){ if ((ret = parse_int32(attr, &depth, &reason)) < 0){
@ -486,7 +491,7 @@ api_data_pagination(clicon_handle h,
sort = cvec_find_str(qvec, "sort-by"); sort = cvec_find_str(qvec, "sort-by");
where = cvec_find_str(qvec, "where"); where = cvec_find_str(qvec, "where");
if (clicon_rpc_get_pageable_list(h, "running", xpath, nsc, content, if (clicon_rpc_get_pageable_list(h, "running", xpath, nsc, content,
depth, NULL, offset, limit, direction, sort, where, depth, NULL, offset, limit, direction, sort, where,
&xret) < 0){ &xret) < 0){
if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0) if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0)
goto done; goto done;
@ -502,7 +507,7 @@ api_data_pagination(clicon_handle h,
* We need to cut that tree to only the object. * We need to cut that tree to only the object.
*/ */
#if 0 /* DEBUG */ #if 0 /* DEBUG */
clicon_debug_xml(1, xret, "%s xret:", __FUNCTION__); clixon_debug_xml(CLIXON_DBG_DEFAULT, xret, "%s xret:", __FUNCTION__);
#endif #endif
/* Check if error return */ /* Check if error return */
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
@ -538,7 +543,7 @@ api_data_pagination(clicon_handle h,
} }
if (xml_rm(xp) < 0) if (xml_rm(xp) < 0)
goto done; goto done;
if (xml_insert(xpr, xp, INS_LAST, NULL, NULL) < 0) if (xml_insert(xpr, xp, INS_LAST, NULL, NULL) < 0)
goto done; goto done;
} }
if (clixon_xml2cbuf(cbx, xpr, 0, pretty, NULL, -1, 0) < 0) /* Dont print top object? */ if (clixon_xml2cbuf(cbx, xpr, 0, pretty, NULL, -1, 0) < 0) /* Dont print top object? */
@ -551,7 +556,7 @@ api_data_pagination(clicon_handle h,
default: default:
break; break;
} }
clicon_debug(1, "%s cbuf:%s", __FUNCTION__, cbuf_get(cbx)); clixon_debug(CLIXON_DBG_DEFAULT, "%s cbuf:%s", __FUNCTION__, cbuf_get(cbx));
if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0) if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0)
goto done; goto done;
if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0) if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0)
@ -562,7 +567,7 @@ api_data_pagination(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (cbrpc) if (cbrpc)
cbuf_free(cbrpc); cbuf_free(cbrpc);
if (xpath) if (xpath)
@ -585,6 +590,11 @@ api_data_pagination(clicon_handle h,
} }
/*! REST HEAD method /*! REST HEAD method
*
* The HEAD method is sent by the client to retrieve just the header fields
* that would be returned for the comparable GET method, without the
* response message-body.
* Relation to netconf: none
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040)
@ -593,11 +603,8 @@ api_data_pagination(clicon_handle h,
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* * @retval 0 OK
* The HEAD method is sent by the client to retrieve just the header fields * @retval -1 Error
* that would be returned for the comparable GET method, without the
* response message-body.
* Relation to netconf: none
*/ */
int int
api_data_head(clicon_handle h, api_data_head(clicon_handle h,
@ -613,6 +620,7 @@ api_data_head(clicon_handle h,
} }
/*! REST GET method /*! REST GET method
*
* According to restconf * According to restconf
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
@ -623,6 +631,8 @@ api_data_head(clicon_handle h,
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @param[in] ds RFC8527 datastore * @param[in] ds RFC8527 datastore
* @retval 0 OK
* @retval -1 Error
* @code * @code
* curl -G http://localhost/restconf/data/interfaces/interface=eth0 * curl -G http://localhost/restconf/data/interfaces/interface=eth0
* @endcode * @endcode
@ -640,7 +650,7 @@ api_data_head(clicon_handle h,
int int
api_data_get(clicon_handle h, api_data_get(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
int pi, int pi,
cvec *qvec, cvec *qvec,
int pretty, int pretty,
@ -648,7 +658,7 @@ api_data_get(clicon_handle h,
ietf_ds_t ds) ietf_ds_t ds)
{ {
int retval = -1; int retval = -1;
switch (media_out){ switch (media_out){
case YANG_DATA_XML: case YANG_DATA_XML:
case YANG_DATA_JSON: /* ad-hoc algorithm in get to determine if a paginated request */ case YANG_DATA_JSON: /* ad-hoc algorithm in get to determine if a paginated request */
@ -667,6 +677,7 @@ api_data_get(clicon_handle h,
} }
/*! GET restconf/operations resource /*! GET restconf/operations resource
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] path According to restconf (Sec 3.5.1.1 in [draft]) * @param[in] path According to restconf (Sec 3.5.1.1 in [draft])
@ -675,11 +686,12 @@ api_data_get(clicon_handle h,
* @param[in] data Stream input data * @param[in] data Stream input data
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* * @retval 0 OK
* @retval -1 Error
* @code * @code
* curl -G http://localhost/restconf/operations * curl -G http://localhost/restconf/operations
* @endcode * @endcode
* RFC8040 Sec 3.3.2: * @see RFC8040 Sec 3.3.2:
* This optional resource is a container that provides access to the * This optional resource is a container that provides access to the
* data-model-specific RPC operations supported by the server. The * data-model-specific RPC operations supported by the server. The
* server MAY omit this resource if no data-model-specific RPC * server MAY omit this resource if no data-model-specific RPC
@ -693,9 +705,9 @@ api_data_get(clicon_handle h,
int int
api_operations_get(clicon_handle h, api_operations_get(clicon_handle h,
void *req, void *req,
char *path, char *path,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_out) restconf_media media_out)
@ -708,8 +720,8 @@ api_operations_get(clicon_handle h,
cbuf *cbx = NULL; cbuf *cbx = NULL;
cxobj *xt = NULL; cxobj *xt = NULL;
int i; int i;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if ((cbx = cbuf_new()) == NULL) if ((cbx = cbuf_new()) == NULL)
goto done; goto done;
@ -730,7 +742,7 @@ api_operations_get(clicon_handle h,
i = 0; i = 0;
while ((ymod = yn_each(yspec, ymod)) != NULL) { while ((ymod = yn_each(yspec, ymod)) != NULL) {
namespace = yang_find_mynamespace(ymod); namespace = yang_find_mynamespace(ymod);
yc = NULL; yc = NULL;
while ((yc = yn_each(ymod, yc)) != NULL) { while ((yc = yn_each(ymod, yc)) != NULL) {
if (yang_keyword_get(yc) != Y_RPC) if (yang_keyword_get(yc) != Y_RPC)
continue; continue;
@ -777,7 +789,7 @@ api_operations_get(clicon_handle h,
// ok: // ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (cbx) if (cbx)
cbuf_free(cbx); cbuf_free(cbx);
if (xt) if (xt)

View file

@ -41,11 +41,11 @@
/* /*
* Prototypes * Prototypes
*/ */
int api_data_head(clicon_handle h, void *req, char *api_path, int pi, int api_data_head(clicon_handle h, void *req, char *api_path, int pi,
cvec *qvec, int pretty, restconf_media media_out, ietf_ds_t ds); cvec *qvec, int pretty, restconf_media media_out, ietf_ds_t ds);
int api_data_get(clicon_handle h, void *req, char *api_path, int pi, int api_data_get(clicon_handle h, void *req, char *api_path, int pi,
cvec *qvec, int pretty, restconf_media media_out, ietf_ds_t ds); cvec *qvec, int pretty, restconf_media media_out, ietf_ds_t ds);
int api_operations_get(clicon_handle h, void *req, int api_operations_get(clicon_handle h, void *req,
char *api_path, int pi, cvec *qvec, char *data, char *api_path, int pi, cvec *qvec, char *data,
int pretty, restconf_media media_out); int pretty, restconf_media media_out);

View file

@ -100,11 +100,12 @@ yang_patch_op2int(char *op)
} }
/*! Add square brackets after the surrounding curly brackets in JSON /*! Add square brackets after the surrounding curly brackets in JSON
*
* Needed, in order to modify the result of clixon_json2cbuf() to be valid input * Needed, in order to modify the result of clixon_json2cbuf() to be valid input
* to api_data_post() and api_data_write() * to api_data_post() and api_data_write()
* @param[in] x_simple_patch a cxobj to pass to clixon_json2cbuf() * @param[in] x_simple_patch a cxobj to pass to clixon_json2cbuf()
* @retva cbuf With the modified json * @retval cbuf With the modified json
* @retva NULL Error * @retval NULL Error
*/ */
static cbuf* static cbuf*
yang_patch_xml2json_modified_cbuf(cxobj *x_simple_patch) yang_patch_xml2json_modified_cbuf(cxobj *x_simple_patch)
@ -150,7 +151,7 @@ yang_patch_xml2json_modified_cbuf(cxobj *x_simple_patch)
return json_simple_patch; return json_simple_patch;
} }
/*!yang_patch_strip_after_last_slash /*! yang_patch_strip_after_last_slash
* *
* Strip /... from end of val * Strip /... from end of val
* so that e.g. "/interface=eth2" becomes "/" * so that e.g. "/interface=eth2" becomes "/"
@ -187,6 +188,7 @@ yang_patch_strip_after_last_slash(char* val)
} }
/*! YANG PATCH replace method /*! YANG PATCH replace method
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] pi Offset, where to start api-path * @param[in] pi Offset, where to start api-path
@ -199,6 +201,8 @@ yang_patch_strip_after_last_slash(char* val)
* @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch * @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch
* @param[in] value_vec pointer to the "value" array of an edit in YANG patch * @param[in] value_vec pointer to the "value" array of an edit in YANG patch
* @param[in] x_simple_patch pointer to XML containing module name, e.g. <ietf-interfaces:interface/> * @param[in] x_simple_patch pointer to XML containing module name, e.g. <ietf-interfaces:interface/>
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang_patch_do_replace(clicon_handle h, yang_patch_do_replace(clicon_handle h,
@ -287,6 +291,7 @@ yang_patch_do_replace(clicon_handle h,
} }
/*! YANG PATCH create method /*! YANG PATCH create method
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] pi Offset, where to start api-path * @param[in] pi Offset, where to start api-path
@ -298,6 +303,8 @@ yang_patch_do_replace(clicon_handle h,
* @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch * @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch
* @param[in] value_vec pointer to the "value" array of an edit in YANG patch * @param[in] value_vec pointer to the "value" array of an edit in YANG patch
* @param[in] x_simple_patch pointer to XML containing module name, e.g. <ietf-interfaces:interface/> * @param[in] x_simple_patch pointer to XML containing module name, e.g. <ietf-interfaces:interface/>
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang_patch_do_create(clicon_handle h, yang_patch_do_create(clicon_handle h,
@ -343,12 +350,13 @@ yang_patch_do_create(clicon_handle h,
} }
/*! YANG PATCH insert method /*! YANG PATCH insert method
* @param[in] h Clixon handle *
* @param[in] req Generic Www handle * @param[in] h Clixon handle
* @param[in] pi Offset, where to start api-path * @param[in] req Generic Www handle
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pi Offset, where to start api-path
* @param[in] media_out Output media * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] media_out Output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* @param[in] simple_patch_request_uri URI for patch request, e.g. "/restconf/data/ietf-interfaces:interfaces" * @param[in] simple_patch_request_uri URI for patch request, e.g. "/restconf/data/ietf-interfaces:interfaces"
* @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch * @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch
* @param[in] value_vec pointer to the "value" array of an edit in YANG patch * @param[in] value_vec pointer to the "value" array of an edit in YANG patch
@ -356,6 +364,8 @@ yang_patch_do_create(clicon_handle h,
* @param[in] where_val value in "where" field of edit in YANG patch * @param[in] where_val value in "where" field of edit in YANG patch
* @param[in] api_path full API path, e.g. "/restconf/data/example-jukebox:jukebox/playlist=Foo-One" * @param[in] api_path full API path, e.g. "/restconf/data/example-jukebox:jukebox/playlist=Foo-One"
* @param[in] point_val value in "point" field of edit in YANG patch * @param[in] point_val value in "point" field of edit in YANG patch
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang_patch_do_insert(clicon_handle h, yang_patch_do_insert(clicon_handle h,
@ -431,19 +441,22 @@ yang_patch_do_insert(clicon_handle h,
} }
/*! YANG PATCH merge method /*! YANG PATCH merge method
* @param[in] h Clixon handle *
* @param[in] req Generic Www handle * @param[in] h Clixon handle
* @param[in] pi Offset, where to start api-path * @param[in] req Generic Www handle
* @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] pi Offset, where to start api-path
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] qvec Vector of query string (QUERY_STRING)
* @param[in] media_out Output media * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] media_out Output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* @param[in] simple_patch_request_uri URI for patch request, e.g. "/restconf/data/ietf-interfaces:interfaces" * @param[in] simple_patch_request_uri URI for patch request, e.g. "/restconf/data/ietf-interfaces:interfaces"
* @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch * @param[in] value_vec_len number of elements in the "value" array of an edit in YANG patch
* @param[in] value_vec pointer to the "value" array of an edit in YANG patch * @param[in] value_vec pointer to the "value" array of an edit in YANG patch
* @param[in] x_simple_patch pointer to XML containing module name, e.g. "<ietf-interfaces:interface/>" * @param[in] x_simple_patch pointer to XML containing module name, e.g. "<ietf-interfaces:interface/>"
* @param[in] where_val value in "where" field of edit in YANG patch * @param[in] where_val value in "where" field of edit in YANG patch
* @param[in] key_xn XML with key tag and value, e.g. "<name>Foo-One</name>" * @param[in] key_xn XML with key tag and value, e.g. "<name>Foo-One</name>"
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
yang_patch_do_merge(clicon_handle h, yang_patch_do_merge(clicon_handle h,
@ -622,7 +635,7 @@ yang_patch_do_edit(clicon_handle h,
yang_stmt *ybot = NULL; yang_stmt *ybot = NULL;
yang_stmt *ymod; yang_stmt *ymod;
clicon_debug_xml(1, xn, "%s %d xn:", __FUNCTION__, __LINE__); clixon_debug_xml(1, xn, "%s %d xn:", __FUNCTION__, __LINE__);
/* Create cbufs:s */ /* Create cbufs:s */
if ((simple_patch_request_uri = cbuf_new()) == NULL){ if ((simple_patch_request_uri = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
@ -655,7 +668,7 @@ yang_patch_do_edit(clicon_handle h,
if (point_val == NULL || where_val == NULL){ if (point_val == NULL || where_val == NULL){
clicon_err(OE_YANG, 0, "point/where: expected element not found"); clicon_err(OE_YANG, 0, "point/where: expected element not found");
goto done; goto done;
} }
} }
// Construct request URI // Construct request URI
cprintf(simple_patch_request_uri, "%s", uripath0); cprintf(simple_patch_request_uri, "%s", uripath0);
@ -704,7 +717,7 @@ yang_patch_do_edit(clicon_handle h,
} else { } else {
// TODO - do not send error // TODO - do not send error
} }
api_data_delete(h, req, cbuf_get(simple_patch_request_uri), pi, pretty, YANG_DATA_JSON, ds); api_data_delete(h, req, cbuf_get(simple_patch_request_uri), pi, pretty, YANG_DATA_JSON, ds);
} }
ok: ok:
retval = 0; retval = 0;
@ -723,6 +736,7 @@ yang_patch_do_edit(clicon_handle h,
} }
/*! YANG PATCH method /*! YANG PATCH method
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path0 According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path0 According to restconf (Sec 3.5.3.1 in rfc8040)
@ -755,7 +769,7 @@ api_data_yang_patch(clicon_handle h,
{ {
int retval = -1; int retval = -1;
int i; int i;
cxobj *xpatch = NULL; cxobj *xpatch = NULL;
yang_stmt *yspec; yang_stmt *yspec;
char *api_path; char *api_path;
cxobj *xerr = NULL; /* malloced must be freed */ cxobj *xerr = NULL; /* malloced must be freed */
@ -764,7 +778,7 @@ api_data_yang_patch(clicon_handle h,
size_t veclen; size_t veclen;
cxobj **vec = NULL; cxobj **vec = NULL;
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path0); clixon_debug(CLIXON_DBG_DEFAULT, "%s api_path:\"%s\"", __FUNCTION__, api_path0);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -805,7 +819,7 @@ api_data_yang_patch(clicon_handle h,
goto done; goto done;
goto ok; goto ok;
} }
/* /*
* RFC 8072 2.1: The message-body MUST identify exactly one resource instance * RFC 8072 2.1: The message-body MUST identify exactly one resource instance
*/ */
if (xml_child_nr_type(xpatch, CX_ELMNT) != 1){ if (xml_child_nr_type(xpatch, CX_ELMNT) != 1){
@ -819,7 +833,7 @@ api_data_yang_patch(clicon_handle h,
if ((uripath0 = restconf_uripath(h)) == NULL) if ((uripath0 = restconf_uripath(h)) == NULL)
goto done; goto done;
/* Find all edit operations and loop over them /* Find all edit operations and loop over them
*/ */
if (xpath_vec(xpatch, NULL, "yang-patch/edit", &vec, &veclen) < 0) if (xpath_vec(xpatch, NULL, "yang-patch/edit", &vec, &veclen) < 0)
goto done; goto done;
for (i = 0; i < veclen; i++) { for (i = 0; i < veclen; i++) {

View file

@ -66,8 +66,11 @@
#include "restconf_methods_post.h" #include "restconf_methods_post.h"
/*! Print location header from /*! Print location header from
*
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] xobj If set (eg POST) add to api-path * @param[in] xobj If set (eg POST) add to api-path
* @retval 0 OK
* @retval -1 Error
* $https on if connection operates in SSL mode, or an empty string otherwise * $https on if connection operates in SSL mode, or an empty string otherwise
* @note ports are ignored * @note ports are ignored
*/ */
@ -116,6 +119,7 @@ http_location_header(clicon_handle h,
} }
/*! Generic REST POST method /*! Generic REST POST method
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040)
@ -153,9 +157,9 @@ http_location_header(clicon_handle h,
int int
api_data_post(clicon_handle h, api_data_post(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_in, restconf_media media_in,
@ -179,14 +183,14 @@ api_data_post(clicon_handle h,
cxobj *xretdis = NULL; /* return from discard-changes */ cxobj *xretdis = NULL; /* return from discard-changes */
cxobj *xerr = NULL; /* malloced must be freed */ cxobj *xerr = NULL; /* malloced must be freed */
cxobj *xe; /* dont free */ cxobj *xe; /* dont free */
cxobj *x; cxobj *x;
char *username; char *username;
int ret; int ret;
int nrchildren0 = 0; int nrchildren0 = 0;
yang_bind yb; yang_bind yb;
clicon_debug(1, "%s api_path:\"%s\"", __FUNCTION__, api_path); clixon_debug(CLIXON_DBG_DEFAULT, "%s api_path:\"%s\"", __FUNCTION__, api_path);
clicon_debug(1, "%s data:\"%s\"", __FUNCTION__, data); clixon_debug(CLIXON_DBG_DEFAULT, "%s data:\"%s\"", __FUNCTION__, data);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -249,7 +253,7 @@ api_data_post(clicon_handle h,
goto ok; goto ok;
} }
break; break;
case YANG_DATA_JSON: case YANG_DATA_JSON:
if ((ret = clixon_json_parse_string(data, 1, yb, yspec, &xbot, &xerr)) < 0){ if ((ret = clixon_json_parse_string(data, 1, yb, yspec, &xbot, &xerr)) < 0){
if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0) if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done; goto done;
@ -272,7 +276,7 @@ api_data_post(clicon_handle h,
/* RFC 8040 4.4.1: The message-body MUST contain exactly one instance of the /* RFC 8040 4.4.1: The message-body MUST contain exactly one instance of the
* expected data resource. * expected data resource.
*/ */
clicon_debug(1, "%s nrchildren0: %d", __FUNCTION__, nrchildren0); clixon_debug(CLIXON_DBG_DEFAULT, "%s nrchildren0: %d", __FUNCTION__, nrchildren0);
if (xml_child_nr_type(xbot, CX_ELMNT) - nrchildren0 != 1){ if (xml_child_nr_type(xbot, CX_ELMNT) - nrchildren0 != 1){
if (netconf_malformed_message_xml(&xerr, "The message-body MUST contain exactly one instance of the expected data resource") < 0) if (netconf_malformed_message_xml(&xerr, "The message-body MUST contain exactly one instance of the expected data resource") < 0)
goto done; goto done;
@ -283,7 +287,7 @@ api_data_post(clicon_handle h,
/* Find the actual (new) object, the single unmarked one */ /* Find the actual (new) object, the single unmarked one */
x = NULL; x = NULL;
while ((x = xml_child_each(xbot, x, CX_ELMNT)) != NULL){ while ((x = xml_child_each(xbot, x, CX_ELMNT)) != NULL){
if (xml_flag(x, XML_FLAG_MARK)){ if (xml_flag(x, XML_FLAG_MARK)){
xml_flag_reset(x, XML_FLAG_MARK); xml_flag_reset(x, XML_FLAG_MARK);
continue; continue;
} }
@ -326,7 +330,7 @@ api_data_post(clicon_handle h,
if (restconf_insert_attributes(xdata, qvec) < 0) if (restconf_insert_attributes(xdata, qvec) < 0)
goto done; goto done;
#if 1 #if 1
clicon_debug_xml(1, xdata, "%s xdata:", __FUNCTION__); clixon_debug_xml(1, xdata, "%s xdata:", __FUNCTION__);
#endif #endif
/* Create text buffer for transfer to backend */ /* Create text buffer for transfer to backend */
@ -365,7 +369,7 @@ api_data_post(clicon_handle h,
if (clixon_xml2cbuf(cbx, xtop, 0, 0, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cbx, xtop, 0, 0, NULL, -1, 0) < 0)
goto done; goto done;
cprintf(cbx, "</edit-config></rpc>"); cprintf(cbx, "</edit-config></rpc>");
clicon_debug(1, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path); clixon_debug(CLIXON_DBG_DEFAULT, "%s xml: %s api_path:%s",__FUNCTION__, cbuf_get(cbx), api_path);
if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0) if (clicon_rpc_netconf(h, cbuf_get(cbx), &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, NULL, "//rpc-error")) != NULL){
@ -376,11 +380,11 @@ api_data_post(clicon_handle h,
if (http_location_header(h, req, xdata) < 0) if (http_location_header(h, req, xdata) < 0)
goto done; goto done;
if (restconf_reply_send(req, 201, NULL, 0) < 0) if (restconf_reply_send(req, 201, NULL, 0) < 0)
goto done; goto done;
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (xret) if (xret)
xml_free(xret); xml_free(xret);
if (xerr) if (xerr)
@ -392,11 +396,12 @@ api_data_post(clicon_handle h,
if (xtop) if (xtop)
xml_free(xtop); xml_free(xtop);
if (cbx) if (cbx)
cbuf_free(cbx); cbuf_free(cbx);
return retval; return retval;
} /* api_data_post */ } /* api_data_post */
/*! Handle input data to api_operations_post /*! Handle input data to api_operations_post
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] data Stream input data * @param[in] data Stream input data
@ -436,7 +441,7 @@ api_operations_post_input(clicon_handle h,
int ret; int ret;
restconf_media media_in; restconf_media media_in;
clicon_debug(1, "%s %s", __FUNCTION__, data); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, data);
if ((cbret = cbuf_new()) == NULL){ if ((cbret = cbuf_new()) == NULL){
clicon_err(OE_UNIX, 0, "cbuf_new"); clicon_err(OE_UNIX, 0, "cbuf_new");
goto done; goto done;
@ -486,7 +491,7 @@ api_operations_post_input(clicon_handle h,
* <data><input xmlns="urn:example:clixon">...</input></data> * <data><input xmlns="urn:example:clixon">...</input></data>
*/ */
#if 1 #if 1
clicon_debug_xml(1, xdata, "%s xdata:", __FUNCTION__); clixon_debug_xml(1, xdata, "%s xdata:", __FUNCTION__);
#endif #endif
/* Validate that exactly only <input> tag */ /* Validate that exactly only <input> tag */
if ((xinput = xml_child_i_type(xdata, 0, CX_ELMNT)) == NULL || if ((xinput = xml_child_i_type(xdata, 0, CX_ELMNT)) == NULL ||
@ -499,23 +504,23 @@ api_operations_post_input(clicon_handle h,
} }
else else
if (netconf_malformed_message_xml(&xerr, "restconf RPC has malformed input statement (multiple or not called input)") < 0) if (netconf_malformed_message_xml(&xerr, "restconf RPC has malformed input statement (multiple or not called input)") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
// clicon_debug(1, "%s input validation passed", __FUNCTION__); // clixon_debug(CLIXON_DBG_DEFAULT, "%s input validation passed", __FUNCTION__);
/* Add all input under <rpc>path */ /* Add all input under <rpc>path */
x = NULL; x = NULL;
while ((x = xml_child_i_type(xinput, 0, CX_ELMNT)) != NULL) while ((x = xml_child_i_type(xinput, 0, CX_ELMNT)) != NULL)
if (xml_addsub(xrpc, x) < 0) if (xml_addsub(xrpc, x) < 0)
goto done; goto done;
/* Here xrpc is: <myfn xmlns="uri"><x>42</x></myfn> /* Here xrpc is: <myfn xmlns="uri"><x>42</x></myfn>
*/ */
// ok: // ok:
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval: %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval: %d", __FUNCTION__, retval);
if (cbret) if (cbret)
cbuf_free(cbret); cbuf_free(cbret);
if (xerr) if (xerr)
@ -529,6 +534,7 @@ api_operations_post_input(clicon_handle h,
} }
/*! Handle output data to api_operations_post /*! Handle output data to api_operations_post
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] xret XML reply messages from backend/handler * @param[in] xret XML reply messages from backend/handler
@ -552,7 +558,6 @@ api_operations_post_output(clicon_handle h,
int pretty, int pretty,
restconf_media media_out, restconf_media media_out,
cxobj **xoutputp) cxobj **xoutputp)
{ {
int retval = -1; int retval = -1;
cxobj *xoutput = NULL; cxobj *xoutput = NULL;
@ -561,8 +566,8 @@ api_operations_post_output(clicon_handle h,
cxobj *x; cxobj *x;
cxobj *xok; cxobj *xok;
int isempty; int isempty;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* Validate that exactly only <rpc-reply> tag with exactly one element child */ /* Validate that exactly only <rpc-reply> tag with exactly one element child */
if ((xoutput = xml_child_i_type(xret, 0, CX_ELMNT)) == NULL || if ((xoutput = xml_child_i_type(xret, 0, CX_ELMNT)) == NULL ||
strcmp(xml_name(xoutput),"rpc-reply") != 0 strcmp(xml_name(xoutput),"rpc-reply") != 0
@ -573,7 +578,7 @@ api_operations_post_output(clicon_handle h,
*/ */
){ ){
if (netconf_malformed_message_xml(&xerr, "restconf RPC does not have single input") < 0) if (netconf_malformed_message_xml(&xerr, "restconf RPC does not have single input") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto fail; goto fail;
@ -583,7 +588,7 @@ api_operations_post_output(clicon_handle h,
xml_name_set(xoutput, "output"); xml_name_set(xoutput, "output");
/* xoutput should now look: <output><x xmlns="uri">0</x></output> */ /* xoutput should now look: <output><x xmlns="uri">0</x></output> */
#if 1 #if 1
clicon_debug_xml(1, xoutput, "%s xoutput:", __FUNCTION__); clixon_debug_xml(1, xoutput, "%s xoutput:", __FUNCTION__);
#endif #endif
/* Remove original netconf default namespace. Somewhat unsure what "output" belongs to? */ /* Remove original netconf default namespace. Somewhat unsure what "output" belongs to? */
if ((xa = xml_find_type(xoutput, NULL, "xmlns", CX_ATTR)) != NULL) if ((xa = xml_find_type(xoutput, NULL, "xmlns", CX_ATTR)) != NULL)
@ -628,7 +633,7 @@ api_operations_post_output(clicon_handle h,
if (isempty) { if (isempty) {
/* Internal error - invalid output from rpc handler */ /* Internal error - invalid output from rpc handler */
if (restconf_reply_send(req, 204, NULL, 0) < 0) if (restconf_reply_send(req, 204, NULL, 0) < 0)
goto done; goto done;
goto fail; goto fail;
} }
/* Clear namespace of parameters */ /* Clear namespace of parameters */
@ -644,7 +649,7 @@ api_operations_post_output(clicon_handle h,
*xoutputp = xoutput; *xoutputp = xoutput;
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval: %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval: %d", __FUNCTION__, retval);
if (xerr) if (xerr)
xml_free(xerr); xml_free(xerr);
return retval; return retval;
@ -654,6 +659,7 @@ api_operations_post_output(clicon_handle h,
} }
/*! REST operation POST method /*! REST operation POST method
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] req Generic Www handle * @param[in] req Generic Www handle
* @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040) * @param[in] api_path According to restconf (Sec 3.5.3.1 in rfc8040)
@ -661,6 +667,8 @@ api_operations_post_output(clicon_handle h,
* @param[in] data Stream input data * @param[in] data Stream input data
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Output media * @param[in] media_out Output media
* @retval 0 OK
* @retval -1 Error
* See RFC 8040 Sec 3.6 / 4.4.2 * See RFC 8040 Sec 3.6 / 4.4.2
* @note We map post to edit-config create. * @note We map post to edit-config create.
* POST {+restconf}/operations/<operation> * POST {+restconf}/operations/<operation>
@ -685,9 +693,9 @@ api_operations_post_output(clicon_handle h,
int int
api_operations_post(clicon_handle h, api_operations_post(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_out) restconf_media media_out)
@ -713,8 +721,8 @@ api_operations_post(clicon_handle h,
yang_stmt *ys = NULL; yang_stmt *ys = NULL;
char *namespace = NULL; char *namespace = NULL;
int nr = 0; int nr = 0;
clicon_debug(1, "%s json:\"%s\" path:\"%s\"", __FUNCTION__, data, api_path); clixon_debug(CLIXON_DBG_DEFAULT, "%s json:\"%s\" path:\"%s\"", __FUNCTION__, data, api_path);
/* 1. Initialize */ /* 1. Initialize */
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
@ -784,7 +792,7 @@ api_operations_post(clicon_handle h,
* XML: <input xmlns="uri"><x>0</x></input> * XML: <input xmlns="uri"><x>0</x></input>
*/ */
namespace = xml_find_type_value(xbot, NULL, "xmlns", CX_ATTR); namespace = xml_find_type_value(xbot, NULL, "xmlns", CX_ATTR);
clicon_debug(1, "%s : 4. Parse input data: %s", __FUNCTION__, data); clixon_debug(CLIXON_DBG_DEFAULT, "%s : 4. Parse input data: %s", __FUNCTION__, data);
if (data && strlen(data)){ if (data && strlen(data)){
if ((ret = api_operations_post_input(h, req, data, yspec, yrpc, xbot, if ((ret = api_operations_post_input(h, req, data, yspec, yrpc, xbot,
pretty, media_out)) < 0) pretty, media_out)) < 0)
@ -795,7 +803,7 @@ api_operations_post(clicon_handle h,
/* Here xtop is: /* Here xtop is:
<rpc username="foo"><myfn xmlns="uri"><x>42</x></myfn></rpc> */ <rpc username="foo"><myfn xmlns="uri"><x>42</x></myfn></rpc> */
#if 1 #if 1
clicon_debug_xml(1, xtop, "%s 5. Translate input args:", __FUNCTION__); clixon_debug_xml(1, xtop, "%s 5. Translate input args:", __FUNCTION__);
#endif #endif
/* 6. Validate outgoing RPC and fill in defaults */ /* 6. Validate outgoing RPC and fill in defaults */
if ((ret = xml_bind_yang_rpc(h, xtop, yspec, &xerr)) < 0) /* */ if ((ret = xml_bind_yang_rpc(h, xtop, yspec, &xerr)) < 0) /* */
@ -816,7 +824,7 @@ api_operations_post(clicon_handle h,
* <rpc username="foo"><myfn xmlns="uri"><x>42</x><y>99</y></myfn></rpc> * <rpc username="foo"><myfn xmlns="uri"><x>42</x><y>99</y></myfn></rpc>
*/ */
#if 0 #if 0
clicon_debug_xml(1, xtop, "%s 6. Validate and defaults:", __FUNCTION__); clixon_debug_xml(1, xtop, "%s 6. Validate and defaults:", __FUNCTION__);
#endif #endif
/* 7. Send to RPC handler, either local or backend /* 7. Send to RPC handler, either local or backend
* Note (1) xtop is <rpc><method> xbot is <method> * Note (1) xtop is <rpc><method> xbot is <method>
@ -857,7 +865,7 @@ api_operations_post(clicon_handle h,
* <rpc-reply><x xmlns="uri">0</x></rpc-reply> * <rpc-reply><x xmlns="uri">0</x></rpc-reply>
*/ */
#if 1 #if 1
clicon_debug_xml(1, xret, "%s Receive reply:", __FUNCTION__); clixon_debug_xml(1, xret, "%s Receive reply:", __FUNCTION__);
#endif #endif
youtput = yang_find(yrpc, Y_OUTPUT, NULL); youtput = yang_find(yrpc, Y_OUTPUT, NULL);
if ((ret = api_operations_post_output(h, req, xret, yspec, youtput, namespace, if ((ret = api_operations_post_output(h, req, xret, yspec, youtput, namespace,
@ -889,7 +897,7 @@ api_operations_post(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (prefix) if (prefix)
free(prefix); free(prefix);
if (id) if (id)

View file

@ -44,7 +44,7 @@
int api_data_post(clicon_handle h, void *req, char *api_path, int api_data_post(clicon_handle h, void *req, char *api_path,
int pi, cvec *qvec, char *data, int pi, cvec *qvec, char *data,
int pretty, int pretty,
restconf_media media_in, restconf_media media_in,
restconf_media media_out, ietf_ds_t ds); restconf_media media_out, ietf_ds_t ds);
int api_operations_post(clicon_handle h, void *req, char *api_path, int api_operations_post(clicon_handle h, void *req, char *api_path,

View file

@ -80,7 +80,8 @@
/* Forward */ /* Forward */
static int restconf_idle_cb(int fd, void *arg); static int restconf_idle_cb(int fd, void *arg);
/*! /*! Create restconf stream
*
* @param[in] rc Restconf connection handle * @param[in] rc Restconf connection handle
* @see restconf_stream_free * @see restconf_stream_free
*/ */
@ -118,7 +119,8 @@ restconf_stream_data_new(restconf_conn *rc,
return sd; return sd;
} }
/*! /*! Find restconf stream data
*
* @param[in] rc Restconf connection handle * @param[in] rc Restconf connection handle
*/ */
restconf_stream_data * restconf_stream_data *
@ -190,11 +192,12 @@ restconf_conn_new(clicon_handle h,
rc->rc_callhome = rsock->rs_callhome; rc->rc_callhome = rsock->rs_callhome;
rc->rc_socket = rsock; rc->rc_socket = rsock;
INSQ(rc, rsock->rs_conns); INSQ(rc, rsock->rs_conns);
clicon_debug(1, "%s %p", __FUNCTION__, rc); clixon_debug(CLIXON_DBG_DEFAULT, "%s %p", __FUNCTION__, rc);
return rc; return rc;
} }
/*! Free clixon/cbuf resources related to a connection /*! Free clixon/cbuf resources related to a connection
*
* @param[in] rc restconf connection * @param[in] rc restconf connection
*/ */
static int static int
@ -205,7 +208,7 @@ restconf_conn_free(restconf_conn *rc)
restconf_socket *rsock; restconf_socket *rsock;
restconf_conn *rc1; restconf_conn *rc1;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (rc == NULL){ if (rc == NULL){
clicon_err(OE_RESTCONF, EINVAL, "rc is NULL"); clicon_err(OE_RESTCONF, EINVAL, "rc is NULL");
goto done; goto done;
@ -238,8 +241,11 @@ restconf_conn_free(restconf_conn *rc)
} }
/*! Given SSL connection, get peer certificate one-line name /*! Given SSL connection, get peer certificate one-line name
*
* @param[in] ssl SSL session * @param[in] ssl SSL session
* @param[out] oneline Cert name one-line * @param[out] oneline Cert name one-line
* @retval 0 OK
* @retval -1 Error
*/ */
int int
ssl_x509_name_oneline(SSL *ssl, ssl_x509_name_oneline(SSL *ssl,
@ -261,7 +267,7 @@ ssl_x509_name_oneline(SSL *ssl,
if ((cert = SSL_get1_peer_certificate(ssl)) == NULL) if ((cert = SSL_get1_peer_certificate(ssl)) == NULL)
goto ok; goto ok;
#endif #endif
if ((name = X509_get_subject_name(cert)) == NULL) if ((name = X509_get_subject_name(cert)) == NULL)
goto ok; goto ok;
if ((p = X509_NAME_oneline(name, NULL, 0)) == NULL) if ((p = X509_NAME_oneline(name, NULL, 0)) == NULL)
goto ok; goto ok;
@ -308,7 +314,7 @@ restconf_connection_sanity(clicon_handle h,
restconf_media media_out = YANG_DATA_JSON; restconf_media media_out = YANG_DATA_JSON;
char *media_str = NULL; char *media_str = NULL;
char *oneline = NULL; char *oneline = NULL;
/* 1) Check if http/2 non-tls is disabled */ /* 1) Check if http/2 non-tls is disabled */
if (rc->rc_ssl == NULL && if (rc->rc_ssl == NULL &&
rc->rc_proto == HTTP_2 && rc->rc_proto == HTTP_2 &&
@ -383,7 +389,7 @@ native_buf_write(clicon_handle h,
char *buf, char *buf,
size_t buflen, size_t buflen,
restconf_conn *rc, restconf_conn *rc,
const char *callfn) const char *callfn)
{ {
int retval = -1; int retval = -1;
ssize_t len; ssize_t len;
@ -400,7 +406,7 @@ native_buf_write(clicon_handle h,
* 1. they are not "strings" in the sense they are not NULL-terminated * 1. they are not "strings" in the sense they are not NULL-terminated
* 2. they are often very long * 2. they are often very long
*/ */
if (clicon_debug_get()) { if (clixon_debug_get()) {
char *dbgstr = NULL; char *dbgstr = NULL;
size_t sz; size_t sz;
sz = buflen>256?256:buflen; /* Truncate to 256 */ sz = buflen>256?256:buflen; /* Truncate to 256 */
@ -410,7 +416,7 @@ native_buf_write(clicon_handle h,
} }
memcpy(dbgstr, buf, sz); memcpy(dbgstr, buf, sz);
dbgstr[sz] = '\0'; dbgstr[sz] = '\0';
clicon_debug(1, "%s %s buflen:%zu buf:\n%s", __FUNCTION__, callfn, buflen, dbgstr); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s buflen:%zu buf:\n%s", __FUNCTION__, callfn, buflen, dbgstr);
free(dbgstr); free(dbgstr);
} }
while (totlen < buflen){ while (totlen < buflen){
@ -424,7 +430,7 @@ native_buf_write(clicon_handle h,
goto closed; /* Close socket and ssl */ goto closed; /* Close socket and ssl */
} }
else if (er == EAGAIN){ else if (er == EAGAIN){
clicon_debug(1, "%s write EAGAIN", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s write EAGAIN", __FUNCTION__);
usleep(10000); usleep(10000);
continue; continue;
} }
@ -445,7 +451,7 @@ native_buf_write(clicon_handle h,
if ((len = write(rc->rc_s, buf+totlen, buflen-totlen)) < 0){ if ((len = write(rc->rc_s, buf+totlen, buflen-totlen)) < 0){
switch (errno){ switch (errno){
case EAGAIN: /* Operation would block */ case EAGAIN: /* Operation would block */
clicon_debug(1, "%s write EAGAIN", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s write EAGAIN", __FUNCTION__);
usleep(10000); usleep(10000);
continue; continue;
break; break;
@ -465,7 +471,7 @@ native_buf_write(clicon_handle h,
} /* while */ } /* while */
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
closed: closed:
retval = 0; retval = 0;
@ -473,13 +479,14 @@ native_buf_write(clicon_handle h,
} }
/*! Send early handcoded bad request reply before actual packet received, just after accept /*! Send early handcoded bad request reply before actual packet received, just after accept
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] media * @param[in] media
* @param[in] body If given add message body using media * @param[in] body If given add message body using media
* @param[in] rc Restconf connection, note may be closed in this * @param[in] rc Restconf connection, note may be closed in this
* @retval 1 OK * @retval 1 OK
* @retval 0 OK, but socket write returned error, caller should close rc * @retval 0 OK, but socket write returned error, caller should close rc
* @retval -1 Error * @retval -1 Error
* @see restconf_badrequest which can only be called in a request context * @see restconf_badrequest which can only be called in a request context
*/ */
static int static int
@ -490,8 +497,8 @@ native_send_badrequest(clicon_handle h,
{ {
int retval = -1; int retval = -1;
cbuf *cb = NULL; cbuf *cb = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
@ -548,8 +555,8 @@ http1_native_clear_input(clicon_handle h,
* @param[in] sz Size of input buffer * @param[in] sz Size of input buffer
* @param[out] np Bytes read * @param[out] np Bytes read
* @param[out] again If set, read data again, do not continue processing * @param[out] again If set, read data again, do not continue processing
* @retval -1 Error
* @retval 0 OK * @retval 0 OK
* @retval -1 Error
*/ */
static int static int
read_ssl(restconf_conn *rc, read_ssl(restconf_conn *rc,
@ -560,10 +567,10 @@ read_ssl(restconf_conn *rc,
{ {
int retval = -1; int retval = -1;
int sslerr; int sslerr;
if ((*np = SSL_read(rc->rc_ssl, buf, sz)) <= 0){ if ((*np = SSL_read(rc->rc_ssl, buf, sz)) <= 0){
sslerr = SSL_get_error(rc->rc_ssl, *np); sslerr = SSL_get_error(rc->rc_ssl, *np);
clicon_debug(1, "%s SSL_read() n:%zd errno:%d sslerr:%d", __FUNCTION__, *np, errno, sslerr); clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_read() n:%zd errno:%d sslerr:%d", __FUNCTION__, *np, errno, sslerr);
switch (sslerr){ switch (sslerr){
case SSL_ERROR_WANT_READ: /* 2 */ case SSL_ERROR_WANT_READ: /* 2 */
/* SSL_ERROR_WANT_READ is returned when the last operation was a read operation /* SSL_ERROR_WANT_READ is returned when the last operation was a read operation
@ -571,7 +578,7 @@ read_ssl(restconf_conn *rc,
* That is, it can happen if restconf_socket_init() below is called * That is, it can happen if restconf_socket_init() below is called
* with SOCK_NONBLOCK * with SOCK_NONBLOCK
*/ */
clicon_debug(1, "%s SSL_read SSL_ERROR_WANT_READ", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_read SSL_ERROR_WANT_READ", __FUNCTION__);
usleep(1000); usleep(1000);
*again = 1; *again = 1;
break; break;
@ -580,13 +587,13 @@ read_ssl(restconf_conn *rc,
break; break;
default: default:
clicon_log(LOG_WARNING, "%s SSL_read(): %s sslerr:%d", __FUNCTION__, strerror(errno), sslerr); clicon_log(LOG_WARNING, "%s SSL_read(): %s sslerr:%d", __FUNCTION__, strerror(errno), sslerr);
*np = 0; *np = 0;
break; break;
} /* switch */ } /* switch */
} }
retval = 0; retval = 0;
// done: // done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }
@ -597,9 +604,9 @@ read_ssl(restconf_conn *rc,
* @param[in] sz Size of input buffer * @param[in] sz Size of input buffer
* @param[out] np Bytes read * @param[out] np Bytes read
* @param[out] again If set, read data again, do not continue processing * @param[out] again If set, read data again, do not continue processing
* @retval -1 Error
* @retval 0 Socket closed, quit
* @retval 1 OK * @retval 1 OK
* @retval 0 Socket closed, quit
* @retval -1 Error
* XXX: * XXX:
* readmore/continue * readmore/continue
* goto ok * goto ok
@ -612,18 +619,18 @@ read_regular(restconf_conn *rc,
int *again) int *again)
{ {
int retval = -1; int retval = -1;
if ((*np = read(rc->rc_s, buf, sz)) < 0){ /* XXX atomicio ? */ if ((*np = read(rc->rc_s, buf, sz)) < 0){ /* XXX atomicio ? */
switch(errno){ switch(errno){
case ECONNRESET:/* Connection reset by peer */ case ECONNRESET:/* Connection reset by peer */
clicon_debug(1, "%s %d Connection reset by peer", __FUNCTION__, rc->rc_s); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d Connection reset by peer", __FUNCTION__, rc->rc_s);
if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0)
goto done; goto done;
retval = 0; /* Close socket and ssl */ retval = 0; /* Close socket and ssl */
goto done; goto done;
break; break;
case EAGAIN: case EAGAIN:
clicon_debug(1, "%s read EAGAIN", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s read EAGAIN", __FUNCTION__);
usleep(1000); usleep(1000);
*again = 1; *again = 1;
break; break;
@ -646,9 +653,9 @@ read_regular(restconf_conn *rc,
* @param[in] buf Input buffer * @param[in] buf Input buffer
* @param[in] n Length of data in input buffer * @param[in] n Length of data in input buffer
* @param[out] readmore If set, read data again, do not continue processing * @param[out] readmore If set, read data again, do not continue processing
* @retval -1 Error
* @retval 0 Socket closed, quit
* @retval 1 OK * @retval 1 OK
* @retval 0 Socket closed, quit
* @retval -1 Error
*/ */
static int static int
restconf_http1_process(restconf_conn *rc, restconf_http1_process(restconf_conn *rc,
@ -662,7 +669,7 @@ restconf_http1_process(restconf_conn *rc,
int ret; int ret;
int status; int status;
cbuf *cberr = NULL; cbuf *cberr = NULL;
h = rc->rc_h; h = rc->rc_h;
if ((sd = restconf_stream_find(rc, 0)) == NULL){ if ((sd = restconf_stream_find(rc, 0)) == NULL){
clicon_err(OE_RESTCONF, EINVAL, "restconf stream not found"); clicon_err(OE_RESTCONF, EINVAL, "restconf stream not found");
@ -803,7 +810,7 @@ restconf_http2_upgrade(restconf_conn *rc)
{ {
int retval = -1; int retval = -1;
restconf_stream_data *sd; restconf_stream_data *sd;
if ((sd = restconf_stream_find(rc, 0)) == NULL){ if ((sd = restconf_stream_find(rc, 0)) == NULL){
clicon_err(OE_RESTCONF, EINVAL, "restconf stream not found"); clicon_err(OE_RESTCONF, EINVAL, "restconf stream not found");
goto done; goto done;
@ -854,19 +861,20 @@ restconf_http2_upgrade(restconf_conn *rc)
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
#endif /* HAVE_LIBHTTP1 */ #endif /* HAVE_LIBHTTP1 */
/*! Restconf HTTP/2 processing after chunk of bytes read /*! Restconf HTTP/2 processing after chunk of bytes read
*
* @param[in] rc Restconf connection * @param[in] rc Restconf connection
* @param[in] buf Input buffer * @param[in] buf Input buffer
* @param[in] n Size of input buffer * @param[in] n Size of input buffer
* @param[in] n Length of data in input buffer * @param[in] n Length of data in input buffer
* @param[out] readmore If set, read data again, do not continue processing * @param[out] readmore If set, read data again, do not continue processing
* @retval -1 Error
* @retval 0 Socket closed, quit
* @retval 1 OK * @retval 1 OK
* @retval 0 Socket closed, quit
* @retval -1 Error
*/ */
static int static int
restconf_http2_process(restconf_conn *rc, restconf_http2_process(restconf_conn *rc,
@ -878,7 +886,7 @@ restconf_http2_process(restconf_conn *rc,
int ret; int ret;
nghttp2_error ngerr; nghttp2_error ngerr;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (rc->rc_exit){ /* Server-initiated exit for http/2 */ if (rc->rc_exit){ /* Server-initiated exit for http/2 */
if ((ngerr = nghttp2_session_terminate_session(rc->rc_ngsession, 0)) < 0){ if ((ngerr = nghttp2_session_terminate_session(rc->rc_ngsession, 0)) < 0){
clicon_err(OE_NGHTTP2, ngerr, "nghttp2_session_terminate_session %d", ngerr); clicon_err(OE_NGHTTP2, ngerr, "nghttp2_session_terminate_session %d", ngerr);
@ -905,13 +913,14 @@ restconf_http2_process(restconf_conn *rc,
} }
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }
#endif /* HAVE_LIBNGHTTP2 */ #endif /* HAVE_LIBNGHTTP2 */
/*! Get restconf native handle /*! Get restconf native handle
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @retval rn Restconf native handle * @retval rn Restconf native handle
*/ */
restconf_native_handle * restconf_native_handle *
@ -933,7 +942,7 @@ restconf_native_handle_get(clicon_handle h)
* @param[in] s Socket where message arrived. read from this. * @param[in] s Socket where message arrived. read from this.
* @param[in] arg Client entry (from). * @param[in] arg Client entry (from).
* @retval 0 OK * @retval 0 OK
* @retval -1 Error Terminates backend and is never called). Instead errors are * @retval -1 Error Terminates backend and is never called). Instead errors are
* propagated back to client. * propagated back to client.
* @see restconf_accept_client where this callback is registered * @see restconf_accept_client where this callback is registered
* @note read buffer is limited. More data can be read in two ways: returns a buffer * @note read buffer is limited. More data can be read in two ways: returns a buffer
@ -952,7 +961,7 @@ restconf_connection(int s,
int readmore = 1; int readmore = 1;
int ret; int ret;
clicon_debug(1, "%s %d", __FUNCTION__, s); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, s);
if ((rc = (restconf_conn*)arg) == NULL){ if ((rc = (restconf_conn*)arg) == NULL){
clicon_err(OE_RESTCONF, EINVAL, "arg is NULL"); clicon_err(OE_RESTCONF, EINVAL, "arg is NULL");
goto done; goto done;
@ -963,7 +972,7 @@ restconf_connection(int s,
} }
gettimeofday(&rc->rc_t, NULL); /* activity timer */ gettimeofday(&rc->rc_t, NULL); /* activity timer */
while (readmore) { while (readmore) {
clicon_debug(1, "%s readmore", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s readmore", __FUNCTION__);
readmore = 0; readmore = 0;
/* Example: curl -Ssik -u wilma:bar -X GET https://localhost/restconf/data/example:x */ /* Example: curl -Ssik -u wilma:bar -X GET https://localhost/restconf/data/example:x */
if (rc->rc_ssl){ if (rc->rc_ssl){
@ -976,11 +985,11 @@ restconf_connection(int s,
if (ret == 0) if (ret == 0)
goto ok; /* abort here */ goto ok; /* abort here */
} }
clicon_debug(1, "%s read:%zd", __FUNCTION__, n); clixon_debug(CLIXON_DBG_DEFAULT, "%s read:%zd", __FUNCTION__, n);
if (readmore) if (readmore)
continue; continue;
if (n == 0){ if (n == 0){
clicon_debug(1, "%s n=0 closing socket", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s n=0 closing socket", __FUNCTION__);
if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0)
goto done; goto done;
rc = NULL; rc = NULL;
@ -1020,15 +1029,18 @@ restconf_connection(int s,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval %d", __FUNCTION__, retval);
return retval; return retval;
} /* restconf_connection */ } /* restconf_connection */
/*----------------------------- Close socket ------------------------------*/ /*----------------------------- Close socket ------------------------------*/
/*! Close Restconf native connection socket and unregister callback /*! Close Restconf native connection socket and unregister callback
*
* For callhome also start reconnect timer * For callhome also start reconnect timer
* @param[in] rc rstconf connection * @param[in] rc rstconf connection
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
restconf_connection_close1(restconf_conn *rc) restconf_connection_close1(restconf_conn *rc)
@ -1041,7 +1053,7 @@ restconf_connection_close1(restconf_conn *rc)
goto done; goto done;
} }
rsock = rc->rc_socket; rsock = rc->rc_socket;
clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\"", __FUNCTION__, rsock->rs_description);
if (close(rc->rc_s) < 0){ if (close(rc->rc_s) < 0){
clicon_err(OE_UNIX, errno, "close"); clicon_err(OE_UNIX, errno, "close");
goto done; goto done;
@ -1056,16 +1068,19 @@ restconf_connection_close1(restconf_conn *rc)
} }
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }
/*! Utility function to close restconf server ssl socket. /*! Utility function to close restconf server ssl socket.
*
* There are many variants to closing, one could probably make this more generic * There are many variants to closing, one could probably make this more generic
* and always use this function, but it is difficult. * and always use this function, but it is difficult.
* @param[in] rc restconf connection * @param[in] rc restconf connection
* @param[in] callfn For debug * @param[in] callfn For debug
* @param[in] dontshutdown If != 0, do not shutdown * @param[in] dontshutdown If != 0, do not shutdown
* @retval 0 OK
* @retval -1 Error
*/ */
int int
restconf_close_ssl_socket(restconf_conn *rc, restconf_close_ssl_socket(restconf_conn *rc,
@ -1077,16 +1092,15 @@ restconf_close_ssl_socket(restconf_conn *rc,
int sslerr; int sslerr;
int er; int er;
clicon_debug(1, "%s %s", __FUNCTION__, callfn); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, callfn);
if (rc->rc_ssl != NULL){ if (rc->rc_ssl != NULL){
if (!dontshutdown && if (!dontshutdown &&
(ret = SSL_shutdown(rc->rc_ssl)) < 0){ (ret = SSL_shutdown(rc->rc_ssl)) < 0){
er = errno; er = errno;
sslerr = SSL_get_error(rc->rc_ssl, ret); sslerr = SSL_get_error(rc->rc_ssl, ret);
clicon_debug(1, "%s errno:%s(%d) sslerr:%d", __FUNCTION__, strerror(er), er, sslerr); clixon_debug(CLIXON_DBG_DEFAULT, "%s errno:%s(%d) sslerr:%d", __FUNCTION__, strerror(er), er, sslerr);
if (sslerr == SSL_ERROR_SSL || /* 1 */ if (sslerr == SSL_ERROR_SSL || /* 1 */
sslerr == SSL_ERROR_ZERO_RETURN){ /* 6 */ sslerr == SSL_ERROR_ZERO_RETURN){ /* 6 */
} }
else if (sslerr == SSL_ERROR_SYSCALL){ /* 5 */ else if (sslerr == SSL_ERROR_SYSCALL){ /* 5 */
/* Some non-recoverable, fatal I/O error occurred. The OpenSSL error queue /* Some non-recoverable, fatal I/O error occurred. The OpenSSL error queue
@ -1112,14 +1126,16 @@ restconf_close_ssl_socket(restconf_conn *rc,
goto done; goto done;
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
} }
/*------------------------------ Accept--------------------------------*/ /*------------------------------ Accept--------------------------------*/
/*! Check ALPN result /*! Check ALPN result
* @proto[out] proto *
* @param[in] h Clixon handle
* @param[out] proto
* @retval 1 OK with proto set * @retval 1 OK with proto set
* @retval 0 Fail, ALPN null or not recognized * @retval 0 Fail, ALPN null or not recognized
* @retval -1 Error * @retval -1 Error
@ -1133,8 +1149,8 @@ ssl_alpn_check(clicon_handle h,
{ {
int retval = -1; int retval = -1;
cbuf *cberr = NULL; cbuf *cberr = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* Alternatively, call restconf_str2proto but alpn is not a proper string */ /* Alternatively, call restconf_str2proto but alpn is not a proper string */
if (alpn && alpnlen == 8 && memcmp("http/1.1", alpn, 8) == 0){ if (alpn && alpnlen == 8 && memcmp("http/1.1", alpn, 8) == 0){
*proto = HTTP_11; *proto = HTTP_11;
@ -1152,7 +1168,7 @@ ssl_alpn_check(clicon_handle h,
if (alpn != NULL){ if (alpn != NULL){
cprintf(cberr, "<errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"><error><error-type>protocol</error-type><error-tag>malformed-message</error-tag><error-message>ALPN: protocol not recognized: %s</error-message></error></errors>", alpn); cprintf(cberr, "<errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"><error><error-type>protocol</error-type><error-tag>malformed-message</error-tag><error-message>ALPN: protocol not recognized: %s</error-message></error></errors>", alpn);
clicon_log(LOG_INFO, "%s Warning: %s", __FUNCTION__, cbuf_get(cberr)); clicon_log(LOG_INFO, "%s Warning: %s", __FUNCTION__, cbuf_get(cberr));
if (native_send_badrequest(h, if (native_send_badrequest(h,
"application/yang-data+xml", "application/yang-data+xml",
cbuf_get(cberr), rc) < 0) cbuf_get(cberr), rc) < 0)
goto done; goto done;
@ -1165,7 +1181,7 @@ ssl_alpn_check(clicon_handle h,
#if defined(HAVE_LIBNGHTTP2) #if defined(HAVE_LIBNGHTTP2)
char *pstr; /* Both http/1 and http/2 */ char *pstr; /* Both http/1 and http/2 */
int p = -1; int p = -1;
pstr = clicon_option_str(h, "CLICON_NOALPN_DEFAULT"); pstr = clicon_option_str(h, "CLICON_NOALPN_DEFAULT");
if (pstr) if (pstr)
p = restconf_str2proto(pstr); p = restconf_str2proto(pstr);
@ -1186,7 +1202,7 @@ ssl_alpn_check(clicon_handle h,
} }
retval = 1; retval = 1;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (cberr) if (cberr)
cbuf_free(cberr); cbuf_free(cberr);
return retval; return retval;
@ -1196,6 +1212,7 @@ ssl_alpn_check(clicon_handle h,
} /* ssl_alpn_check */ } /* ssl_alpn_check */
/*! Accept new socket client. Note SSL not ip, this applies also to callhome /*! Accept new socket client. Note SSL not ip, this applies also to callhome
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] s Socket (unix or ip) * @param[in] s Socket (unix or ip)
* @param[in] rsock Socket struct * @param[in] rsock Socket struct
@ -1223,7 +1240,7 @@ restconf_ssl_accept_client(clicon_handle h,
unsigned int alpnlen = 0; unsigned int alpnlen = 0;
restconf_http_proto proto = HTTP_11; /* Non-SSL negotiation NYI */ restconf_http_proto proto = HTTP_11; /* Non-SSL negotiation NYI */
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
#ifdef HAVE_LIBNGHTTP2 #ifdef HAVE_LIBNGHTTP2
#ifndef HAVE_HTTP1 #ifndef HAVE_HTTP1
proto = HTTP_2; /* If nghttp2 only let default be 2.0 */ proto = HTTP_2; /* If nghttp2 only let default be 2.0 */
@ -1238,13 +1255,13 @@ restconf_ssl_accept_client(clicon_handle h,
*/ */
if ((rc = restconf_conn_new(h, s, rsock)) == NULL) if ((rc = restconf_conn_new(h, s, rsock)) == NULL)
goto done; goto done;
clicon_debug(1, "%s s:%d", __FUNCTION__, rc->rc_s); clixon_debug(CLIXON_DBG_DEFAULT, "%s s:%d", __FUNCTION__, rc->rc_s);
if (rsock->rs_ssl){ if (rsock->rs_ssl){
if ((rc->rc_ssl = SSL_new(rn->rn_ctx)) == NULL){ if ((rc->rc_ssl = SSL_new(rn->rn_ctx)) == NULL){
clicon_err(OE_SSL, 0, "SSL_new"); clicon_err(OE_SSL, 0, "SSL_new");
goto done; goto done;
} }
clicon_debug(1, "%s SSL_new(%p)", __FUNCTION__, rc->rc_ssl); clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_new(%p)", __FUNCTION__, rc->rc_ssl);
/* CCL_CTX_set_verify already set, need not call SSL_set_verify again for this server /* CCL_CTX_set_verify already set, need not call SSL_set_verify again for this server
*/ */
/* X509_CHECK_FLAG_NO_WILDCARDS disables wildcard expansion */ /* X509_CHECK_FLAG_NO_WILDCARDS disables wildcard expansion */
@ -1281,11 +1298,11 @@ restconf_ssl_accept_client(clicon_handle h,
* Both error cases: Call SSL_get_error() with the return value ret * Both error cases: Call SSL_get_error() with the return value ret
*/ */
if ((ret = SSL_accept(rc->rc_ssl)) != 1) { if ((ret = SSL_accept(rc->rc_ssl)) != 1) {
clicon_debug(1, "%s SSL_accept() ret:%d errno:%d", __FUNCTION__, ret, er=errno); clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_accept() ret:%d errno:%d", __FUNCTION__, ret, er=errno);
e = SSL_get_error(rc->rc_ssl, ret); e = SSL_get_error(rc->rc_ssl, ret);
switch (e){ switch (e){
case SSL_ERROR_SSL: /* 1 */ case SSL_ERROR_SSL: /* 1 */
clicon_debug(1, "%s SSL_ERROR_SSL (non-ssl message on ssl socket)", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_ERROR_SSL (non-ssl message on ssl socket)", __FUNCTION__);
#ifdef HTTP_ON_HTTPS_REPLY #ifdef HTTP_ON_HTTPS_REPLY
SSL_free(rc->rc_ssl); SSL_free(rc->rc_ssl);
rc->rc_ssl = NULL; rc->rc_ssl = NULL;
@ -1298,12 +1315,12 @@ restconf_ssl_accept_client(clicon_handle h,
goto closed; goto closed;
break; break;
case SSL_ERROR_SYSCALL: /* 5 */ case SSL_ERROR_SYSCALL: /* 5 */
/* Some non-recoverable, fatal I/O error occurred. The OpenSSL error queue /* Some non-recoverable, fatal I/O error occurred. The OpenSSL error queue
may contain more information on the error. For socket I/O on Unix systems, may contain more information on the error. For socket I/O on Unix systems,
consult errno for details. If this error occurs then no further I/O consult errno for details. If this error occurs then no further I/O
operations should be performed on the connection and SSL_shutdown() must operations should be performed on the connection and SSL_shutdown() must
not be called.*/ not be called.*/
clicon_debug(1, "%s SSL_accept() SSL_ERROR_SYSCALL %d", __FUNCTION__, er); clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_accept() SSL_ERROR_SYSCALL %d", __FUNCTION__, er);
if (restconf_close_ssl_socket(rc, __FUNCTION__, 1) < 0) if (restconf_close_ssl_socket(rc, __FUNCTION__, 1) < 0)
goto done; goto done;
rc = NULL; rc = NULL;
@ -1316,7 +1333,7 @@ restconf_ssl_accept_client(clicon_handle h,
* That is, it can happen if restconf_socket_init() below is called * That is, it can happen if restconf_socket_init() below is called
* with SOCK_NONBLOCK * with SOCK_NONBLOCK
*/ */
clicon_debug(1, "%s write SSL_ERROR_WANT_READ", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s write SSL_ERROR_WANT_READ", __FUNCTION__);
usleep(10000); usleep(10000);
readmore = 1; readmore = 1;
break; break;
@ -1350,7 +1367,7 @@ restconf_ssl_accept_client(clicon_handle h,
if (ret == 0){ if (ret == 0){
goto closed; goto closed;
} }
clicon_debug(1, "%s proto:%s", __FUNCTION__, restconf_proto2str(proto)); clixon_debug(CLIXON_DBG_DEFAULT, "%s proto:%s", __FUNCTION__, restconf_proto2str(proto));
#if 0 /* Seems too early to fail here, instead let authentication callback deal with this */ #if 0 /* Seems too early to fail here, instead let authentication callback deal with this */
/* For client-cert authentication, check if any certs are present, /* For client-cert authentication, check if any certs are present,
@ -1388,7 +1405,7 @@ restconf_ssl_accept_client(clicon_handle h,
const char *peername = SSL_get0_peername(rc->rc_ssl); const char *peername = SSL_get0_peername(rc->rc_ssl);
if (peername != NULL) { if (peername != NULL) {
/* Name checks were in scope and matched the peername */ /* Name checks were in scope and matched the peername */
clicon_debug(1, "%s peername:%s", __FUNCTION__, peername); clixon_debug(CLIXON_DBG_DEFAULT, "%s peername:%s", __FUNCTION__, peername);
} }
} }
#if 0 #if 0
@ -1402,7 +1419,7 @@ restconf_ssl_accept_client(clicon_handle h,
} }
#endif #endif
#if 0 /* debug */ #if 0 /* debug */
if (clicon_debug_get()) if (clixon_debug_get())
restconf_listcerts(rc->rc_ssl); restconf_listcerts(rc->rc_ssl);
#endif #endif
} /* if ssl */ } /* if ssl */
@ -1441,7 +1458,7 @@ restconf_ssl_accept_client(clicon_handle h,
*rcp = rc; *rcp = rc;
retval = 1; /* OK, up */ retval = 1; /* OK, up */
done: done:
clicon_debug(1, "%s retval %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval %d", __FUNCTION__, retval);
if (name) if (name)
free(name); free(name);
return retval; return retval;
@ -1457,7 +1474,7 @@ restconf_idle_timer_set(struct timeval t,
{ {
int retval = -1; int retval = -1;
cbuf *cb = NULL; cbuf *cb = NULL;
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
@ -1475,8 +1492,11 @@ restconf_idle_timer_set(struct timeval t,
return retval; return retval;
} }
/*! idle timeout timer callback /*! Idle timeout timer callback
* @param[in] rc restconf connection, more specifically: callhome connection *
* @param[in] rc Restconf connection, more specifically: callhome connection
* @retval 0 OK
* @retval -1 Error
* *
* t0 tp t1 tn * t0 tp t1 tn
* |---------|-----------|--------------------| * |---------|-----------|--------------------|
@ -1509,7 +1529,7 @@ restconf_idle_cb(int fd,
clicon_err(OE_YANG, EINVAL, "rsock is NULL"); clicon_err(OE_YANG, EINVAL, "rsock is NULL");
goto done; goto done;
} }
clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\"", __FUNCTION__, rsock->rs_description);
if (rc->rc_callhome && rsock->rs_periodic && rc->rc_s > 0 && rsock->rs_idle_timeout){ if (rc->rc_callhome && rsock->rs_periodic && rc->rc_s > 0 && rsock->rs_idle_timeout){
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
timersub(&now, &rc->rc_t, &td); /* Last packet timestamp */ timersub(&now, &rc->rc_t, &td); /* Last packet timestamp */
@ -1520,7 +1540,7 @@ restconf_idle_cb(int fd,
else{ else{
to.tv_sec = rsock->rs_idle_timeout; to.tv_sec = rsock->rs_idle_timeout;
timeradd(&now, &to, &tn); timeradd(&now, &to, &tn);
clicon_debug(1, "%s now:%lu timeout:%lu.%lu", __FUNCTION__, clixon_debug(CLIXON_DBG_DEFAULT, "%s now:%lu timeout:%lu.%lu", __FUNCTION__,
now.tv_sec, tn.tv_sec, tn.tv_usec); now.tv_sec, tn.tv_sec, tn.tv_usec);
if (restconf_idle_timer_set(tn, rc, rsock->rs_description) < 0) if (restconf_idle_timer_set(tn, rc, rsock->rs_description) < 0)
goto done; goto done;
@ -1538,6 +1558,7 @@ restconf_idle_timer_unreg(restconf_conn *rc)
} }
/*! Set callhome periodic idle-timeout /*! Set callhome periodic idle-timeout
*
* 1) If callhome and periodic, set timer for t0+idle-timeout(ti) * 1) If callhome and periodic, set timer for t0+idle-timeout(ti)
* 2) Timestamp any data passing on the socket(td) * 2) Timestamp any data passing on the socket(td)
* 3) At timeout (ti) check if ti = td+idle-timeout (for first timeout same as t0=td), * 3) At timeout (ti) check if ti = td+idle-timeout (for first timeout same as t0=td),
@ -1559,13 +1580,13 @@ restconf_idle_timer(restconf_conn *rc)
if (rc == NULL || !rc->rc_callhome){ if (rc == NULL || !rc->rc_callhome){
clicon_err(OE_RESTCONF, EINVAL, "rc is NULL or not callhome"); clicon_err(OE_RESTCONF, EINVAL, "rc is NULL or not callhome");
goto done; goto done;
} }
rsock = rc->rc_socket; rsock = rc->rc_socket;
if (rsock == NULL || !rsock->rs_periodic || rsock->rs_idle_timeout==0){ if (rsock == NULL || !rsock->rs_periodic || rsock->rs_idle_timeout==0){
clicon_err(OE_YANG, EINVAL, "rsock is NULL or not periodic"); clicon_err(OE_YANG, EINVAL, "rsock is NULL or not periodic");
goto done; goto done;
} }
clicon_debug(1, "%s \"%s\" register", __FUNCTION__, rsock->rs_description); clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\" register", __FUNCTION__, rsock->rs_description);
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
to.tv_sec = rsock->rs_idle_timeout; to.tv_sec = rsock->rs_idle_timeout;
timeradd(&now, &to, &t); timeradd(&now, &to, &t);
@ -1603,7 +1624,7 @@ restconf_callhome_cb(int fd,
clicon_err(OE_YANG, EINVAL, "rsock is NULL"); clicon_err(OE_YANG, EINVAL, "rsock is NULL");
goto done; goto done;
} }
clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\"", __FUNCTION__, rsock->rs_description);
h = rsock->rs_h; h = rsock->rs_h;
/* Already computed in restconf_socket_init, could be saved in rsock? */ /* Already computed in restconf_socket_init, could be saved in rsock? */
if (clixon_inet2sin(rsock->rs_addrtype, rsock->rs_addrstr, rsock->rs_port, sa, &sa_len) < 0) if (clixon_inet2sin(rsock->rs_addrtype, rsock->rs_addrstr, rsock->rs_port, sa, &sa_len) < 0)
@ -1613,7 +1634,7 @@ restconf_callhome_cb(int fd,
goto done; goto done;
} }
if (connect(s, sa, sa_len) < 0){ if (connect(s, sa, sa_len) < 0){
clicon_debug(1, "%s connect %hu fail:%d %s", __FUNCTION__, rsock->rs_port, errno, strerror(errno)); clixon_debug(CLIXON_DBG_DEFAULT, "%s connect %hu fail:%d %s", __FUNCTION__, rsock->rs_port, errno, strerror(errno));
close(s); close(s);
rsock->rs_attempts++; rsock->rs_attempts++;
/* Fail: Initiate new timer */ /* Fail: Initiate new timer */
@ -1621,7 +1642,7 @@ restconf_callhome_cb(int fd,
goto done; goto done;
} }
else { else {
clicon_debug(1, "%s connect %hu OK", __FUNCTION__, rsock->rs_port); clixon_debug(CLIXON_DBG_DEFAULT, "%s connect %hu OK", __FUNCTION__, rsock->rs_port);
rsock->rs_attempts = 0; rsock->rs_attempts = 0;
if ((ret = restconf_ssl_accept_client(h, s, rsock, &rc)) < 0) if ((ret = restconf_ssl_accept_client(h, s, rsock, &rc)) < 0)
goto done; goto done;
@ -1648,6 +1669,8 @@ restconf_callhome_timer_unreg(restconf_socket *rsock)
* NYI: start-with, anchor-time * NYI: start-with, anchor-time
* @param[in] rsock restconf_socket * @param[in] rsock restconf_socket
* @param[in] new if periodic: 1: Force a new period * @param[in] new if periodic: 1: Force a new period
* @retval 0 OK
* @retval -1 Error
* @see restconf_callhome_timer_unreg * @see restconf_callhome_timer_unreg
*/ */
int int
@ -1659,12 +1682,12 @@ restconf_callhome_timer(restconf_socket *rsock,
struct timeval t; struct timeval t;
struct timeval t1 = {0, 0}; struct timeval t1 = {0, 0};
cbuf *cb = NULL; cbuf *cb = NULL;
if (rsock == NULL || !rsock->rs_callhome){ if (rsock == NULL || !rsock->rs_callhome){
clicon_err(OE_YANG, EINVAL, "rsock is NULL or not callhome"); clicon_err(OE_YANG, EINVAL, "rsock is NULL or not callhome");
goto done; goto done;
} }
clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\"", __FUNCTION__, rsock->rs_description);
if (!rsock->rs_callhome) if (!rsock->rs_callhome)
goto ok; /* shouldnt happen */ goto ok; /* shouldnt happen */
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
@ -1692,9 +1715,9 @@ restconf_callhome_timer(restconf_socket *rsock,
} }
cprintf(cb, "restconf callhome timer %s", rsock->rs_description); cprintf(cb, "restconf callhome timer %s", rsock->rs_description);
if (rsock->rs_description) if (rsock->rs_description)
clicon_debug(1, "%s registering \"%s\": +%lu", __FUNCTION__, rsock->rs_description, t.tv_sec-now.tv_sec); clixon_debug(CLIXON_DBG_DEFAULT, "%s registering \"%s\": +%lu", __FUNCTION__, rsock->rs_description, t.tv_sec-now.tv_sec);
else else
clicon_debug(1, "%s: %lu", __FUNCTION__, t.tv_sec); clixon_debug(CLIXON_DBG_DEFAULT, "%s: %lu", __FUNCTION__, t.tv_sec);
/* Should be only place restconf_callhome_cb is registered */ /* Should be only place restconf_callhome_cb is registered */
if (clixon_event_reg_timeout(t, if (clixon_event_reg_timeout(t,
restconf_callhome_cb, restconf_callhome_cb,
@ -1710,7 +1733,8 @@ restconf_callhome_timer(restconf_socket *rsock,
} }
/*! Extract socket info from backend config /*! Extract socket info from backend config
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] xs socket config * @param[in] xs socket config
* @param[in] nsc Namespace context * @param[in] nsc Namespace context
* @param[out] rsock restconf socket data, filled in with many fields * @param[out] rsock restconf socket data, filled in with many fields
@ -1718,6 +1742,8 @@ restconf_callhome_timer(restconf_socket *rsock,
* @param[out] address Address as string, eg "0.0.0.0", "::" * @param[out] address Address as string, eg "0.0.0.0", "::"
* @param[out] addrtype One of inet:ipv4-address or inet:ipv6-address * @param[out] addrtype One of inet:ipv4-address or inet:ipv6-address
* @param[out] port TCP Port * @param[out] port TCP Port
* @retval 0 OK
* @retval -1 Error
*/ */
int int
restconf_socket_extract(clicon_handle h, restconf_socket_extract(clicon_handle h,
@ -1789,7 +1815,7 @@ restconf_socket_extract(clicon_handle h,
* type inet:ipv6-address; <--- * type inet:ipv6-address; <---
* } * }
*/ */
*addrtype = yang_argument_get(ysub); *addrtype = yang_argument_get(ysub);
if ((x = xpath_first(xs, nsc, "port")) != NULL && if ((x = xpath_first(xs, nsc, "port")) != NULL &&
(str = xml_body(x)) != NULL){ (str = xml_body(x)) != NULL){
if ((ret = parse_uint16(str, port, &reason)) < 0){ if ((ret = parse_uint16(str, port, &reason)) < 0){
@ -1820,7 +1846,7 @@ restconf_socket_extract(clicon_handle h,
} }
else if (xpath_first(xs, nsc, "call-home/connection-type/periodic") != NULL){ else if (xpath_first(xs, nsc, "call-home/connection-type/periodic") != NULL){
rsock->rs_periodic = 1; rsock->rs_periodic = 1;
if ((x = xpath_first(xs, nsc, "call-home/connection-type/periodic/period")) != NULL && if ((x = xpath_first(xs, nsc, "call-home/connection-type/periodic/period")) != NULL &&
(str = xml_body(x)) != NULL){ (str = xml_body(x)) != NULL){
if ((ret = parse_uint32(str, &rsock->rs_period, &reason)) < 0){ if ((ret = parse_uint32(str, &rsock->rs_period, &reason)) < 0){
clicon_err(OE_XML, errno, "parse_uint16"); clicon_err(OE_XML, errno, "parse_uint16");
@ -1829,9 +1855,9 @@ restconf_socket_extract(clicon_handle h,
if (ret == 0){ if (ret == 0){
clicon_err(OE_XML, EINVAL, "Unrecognized value of period: %s", str); clicon_err(OE_XML, EINVAL, "Unrecognized value of period: %s", str);
goto done; goto done;
} }
} }
if ((x = xpath_first(xs, nsc, "call-home/connection-type/periodic/idle-timeout")) != NULL && if ((x = xpath_first(xs, nsc, "call-home/connection-type/periodic/idle-timeout")) != NULL &&
(str = xml_body(x)) != NULL){ (str = xml_body(x)) != NULL){
if ((ret = parse_uint16(str, &rsock->rs_idle_timeout, &reason)) < 0){ if ((ret = parse_uint16(str, &rsock->rs_idle_timeout, &reason)) < 0){
clicon_err(OE_XML, errno, "parse_uint16"); clicon_err(OE_XML, errno, "parse_uint16");
@ -1840,10 +1866,10 @@ restconf_socket_extract(clicon_handle h,
if (ret == 0){ if (ret == 0){
clicon_err(OE_XML, EINVAL, "Unrecognized value of idle-timeout: %s", str); clicon_err(OE_XML, EINVAL, "Unrecognized value of idle-timeout: %s", str);
goto done; goto done;
} }
} }
} }
if ((x = xpath_first(xs, nsc, "call-home/reconnect-strategy/max-attempts")) != NULL && if ((x = xpath_first(xs, nsc, "call-home/reconnect-strategy/max-attempts")) != NULL &&
(str = xml_body(x)) != NULL){ (str = xml_body(x)) != NULL){
if ((ret = parse_uint8(str, &rsock->rs_max_attempts, &reason)) < 0){ if ((ret = parse_uint8(str, &rsock->rs_max_attempts, &reason)) < 0){
clicon_err(OE_XML, errno, "parse_uint8"); clicon_err(OE_XML, errno, "parse_uint8");
@ -1852,7 +1878,7 @@ restconf_socket_extract(clicon_handle h,
if (ret == 0){ if (ret == 0){
clicon_err(OE_XML, EINVAL, "Unrecognized value of max-attempts: %s", str); clicon_err(OE_XML, EINVAL, "Unrecognized value of max-attempts: %s", str);
goto done; goto done;
} }
} }
} }
retval = 0; retval = 0;

View file

@ -67,7 +67,7 @@ extern "C" {
/* /*
* Types * Types
*/ */
/* Forward */ /* Forward */
struct restconf_conn; struct restconf_conn;
@ -95,13 +95,13 @@ typedef struct {
} restconf_stream_data; } restconf_stream_data;
typedef struct restconf_socket restconf_socket; typedef struct restconf_socket restconf_socket;
/* Restconf connection handle /* Restconf connection handle
* Per connection request * Per connection request
*/ */
typedef struct restconf_conn { typedef struct restconf_conn {
qelem_t rc_qelem; /* List header */ qelem_t rc_qelem; /* List header */
/* XXX rc_proto and rc_proto_d1/d2 may not both be necessary. /* XXX rc_proto and rc_proto_d1/d2 may not both be necessary.
* remove rc_proto? * remove rc_proto?
*/ */
int rc_callhome; /* 0: listen, 1: callhome */ int rc_callhome; /* 0: listen, 1: callhome */
@ -188,7 +188,7 @@ int restconf_callhome_timer_unreg(restconf_socket *rsock);
int restconf_callhome_timer(restconf_socket *rsock, int status); int restconf_callhome_timer(restconf_socket *rsock, int status);
int restconf_socket_extract(clicon_handle h, cxobj *xs, cvec *nsc, restconf_socket *rsock, int restconf_socket_extract(clicon_handle h, cxobj *xs, cvec *nsc, restconf_socket *rsock,
char **namespace, char **address, char **addrtype, uint16_t *port); char **namespace, char **address, char **addrtype, uint16_t *port);
#endif /* _RESTCONF_NATIVE_H_ */ #endif /* _RESTCONF_NATIVE_H_ */
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -92,7 +92,8 @@
#define ARRLEN(x) (sizeof(x) / sizeof(x[0])) #define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
/*! Map http2 frame types in nghttp2 /*! Map http2 frame types in nghttp2
* I had expected it in in libnghttp2 but havent found it *
* Had expected it in in libnghttp2 but havent found it
*/ */
static const map_str2int nghttp2_frame_type_map[] = { static const map_str2int nghttp2_frame_type_map[] = {
{"DATA", NGHTTP2_DATA}, {"DATA", NGHTTP2_DATA},
@ -119,7 +120,7 @@ clixon_nghttp2_log_cb(void *handle,
int suberr, int suberr,
cbuf *cb) cbuf *cb)
{ {
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
cprintf(cb, "Fatal error: %s", nghttp2_strerror(suberr)); cprintf(cb, "Fatal error: %s", nghttp2_strerror(suberr));
return 0; return 0;
} }
@ -131,24 +132,28 @@ nghttp2_print_header(const uint8_t *name,
const uint8_t *value, const uint8_t *value,
size_t valuelen) size_t valuelen)
{ {
clicon_debug(1, "%s %s", name, value); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", name, value);
} }
/* Print HTTP headers to |f|. Please note that this function does not /*! Print HTTP headers to |f|.
take into account that header name and value are sequence of *
octets, therefore they may contain non-printable characters. */ * Please note that this function does not
* take into account that header name and value are sequence of
* octets, therefore they may contain non-printable characters.
*/
static void static void
nghttp2_print_headers(nghttp2_nv *nva, nghttp2_print_headers(nghttp2_nv *nva,
size_t nvlen) size_t nvlen)
{ {
size_t i; size_t i;
for (i = 0; i < nvlen; ++i) for (i = 0; i < nvlen; ++i)
nghttp2_print_header(nva[i].name, nva[i].namelen, nva[i].value, nva[i].valuelen); nghttp2_print_header(nva[i].name, nva[i].namelen, nva[i].value, nva[i].valuelen);
} }
#endif /* NOTUSED */ #endif /* NOTUSED */
/*! Send data to remote peer, Send at most the |length| bytes of |data|. /*! Send data to remote peer, Send at most the |length| bytes of |data|.
*
* This callback is required if the application uses * This callback is required if the application uses
* `nghttp2_session_send()` to send data to the remote endpoint. If * `nghttp2_session_send()` to send data to the remote endpoint. If
* the application uses solely `nghttp2_session_mem_send()` instead, * the application uses solely `nghttp2_session_mem_send()` instead,
@ -172,21 +177,21 @@ session_send_callback(nghttp2_session *session,
ssize_t totlen = 0; ssize_t totlen = 0;
int s; int s;
int sslerr; int sslerr;
clicon_debug(1, "%s buflen:%zu", __FUNCTION__, buflen); clixon_debug(CLIXON_DBG_DEFAULT, "%s buflen:%zu", __FUNCTION__, buflen);
s = rc->rc_s; s = rc->rc_s;
while (totlen < buflen){ while (totlen < buflen){
if (rc->rc_ssl){ if (rc->rc_ssl){
if ((len = SSL_write(rc->rc_ssl, buf+totlen, buflen-totlen)) <= 0){ if ((len = SSL_write(rc->rc_ssl, buf+totlen, buflen-totlen)) <= 0){
er = errno; er = errno;
sslerr = SSL_get_error(rc->rc_ssl, len); sslerr = SSL_get_error(rc->rc_ssl, len);
clicon_debug(1, "%s SSL_write: errno:%s(%d) sslerr:%d", __FUNCTION__, clixon_debug(CLIXON_DBG_DEFAULT, "%s SSL_write: errno:%s(%d) sslerr:%d", __FUNCTION__,
strerror(er), strerror(er),
er, er,
sslerr); sslerr);
switch (sslerr){ switch (sslerr){
case SSL_ERROR_WANT_WRITE: /* 3 */ case SSL_ERROR_WANT_WRITE: /* 3 */
clicon_debug(1, "%s write SSL_ERROR_WANT_WRITE", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s write SSL_ERROR_WANT_WRITE", __FUNCTION__);
usleep(1000); usleep(1000);
continue; continue;
break; break;
@ -196,11 +201,11 @@ session_send_callback(nghttp2_session *session,
goto done; /* Cleanup in http2_recv() */ goto done; /* Cleanup in http2_recv() */
} }
else if (er == EAGAIN){ else if (er == EAGAIN){
/* same as want_write above, but different behaviour on different /* same as want_write above, but different behaviour on different
* platforms, linux here, freebsd want_write, or possibly differnt * platforms, linux here, freebsd want_write, or possibly differnt
* ssl lib versions? * ssl lib versions?
*/ */
clicon_debug(1, "%s write EAGAIN", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s write EAGAIN", __FUNCTION__);
usleep(1000); usleep(1000);
continue; continue;
} }
@ -220,7 +225,7 @@ session_send_callback(nghttp2_session *session,
else{ else{
if ((len = write(s, buf+totlen, buflen-totlen)) < 0){ if ((len = write(s, buf+totlen, buflen-totlen)) < 0){
if (errno == EAGAIN){ if (errno == EAGAIN){
clicon_debug(1, "%s write EAGAIN", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s write EAGAIN", __FUNCTION__);
usleep(10000); usleep(10000);
continue; continue;
} }
@ -247,10 +252,10 @@ session_send_callback(nghttp2_session *session,
retval = 0; retval = 0;
done: done:
if (retval < 0){ if (retval < 0){
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
} }
clicon_debug(1, "%s retval:%zd", __FUNCTION__, totlen); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%zd", __FUNCTION__, totlen);
return retval == 0 ? totlen : retval; return retval == 0 ? totlen : retval;
} }
@ -264,7 +269,7 @@ recv_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -288,8 +293,8 @@ restconf_nghttp2_path(restconf_stream_data *sd)
char *oneline = NULL; char *oneline = NULL;
cvec *cvv = NULL; cvec *cvv = NULL;
char *cn; char *cn;
clicon_debug(1, "------------"); clixon_debug(CLIXON_DBG_DEFAULT, "------------");
rc = sd->sd_conn; rc = sd->sd_conn;
if ((h = rc->rc_h) == NULL){ if ((h = rc->rc_h) == NULL){
clicon_err(OE_RESTCONF, EINVAL, "arg is NULL"); clicon_err(OE_RESTCONF, EINVAL, "arg is NULL");
@ -327,21 +332,21 @@ restconf_nghttp2_path(restconf_stream_data *sd)
} }
else if (api_path_is_restconf(h)){ else if (api_path_is_restconf(h)){
if (api_root_restconf(h, sd, sd->sd_qvec) < 0) if (api_root_restconf(h, sd, sd->sd_qvec) < 0)
goto done; goto done;
} }
else if (api_path_is_data(h)){ else if (api_path_is_data(h)){
if (api_http_data(h, sd, sd->sd_qvec) < 0) if (api_http_data(h, sd, sd->sd_qvec) < 0)
goto done; goto done;
} }
else if (api_root_restconf(h, sd, sd->sd_qvec) < 0) /* error handling */ else if (api_root_restconf(h, sd, sd->sd_qvec) < 0) /* error handling */
goto done; goto done;
} }
/* Clear (fcgi) paramaters from this request */ /* Clear (fcgi) paramaters from this request */
if (restconf_param_del_all(h) < 0) if (restconf_param_del_all(h) < 0)
goto done; goto done;
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
if (cvv) if (cvv)
cvec_free(cvv); cvec_free(cvv);
if (oneline) if (oneline)
@ -350,6 +355,7 @@ restconf_nghttp2_path(restconf_stream_data *sd)
} }
/*! data callback, just pass pointer to cbuf /*! data callback, just pass pointer to cbuf
*
* XXX handle several chunks with cbuf * XXX handle several chunks with cbuf
*/ */
static ssize_t static ssize_t
@ -384,7 +390,7 @@ restconf_sd_read(nghttp2_session *session,
#endif #endif
assert(cbuf_len(cb) > sd->sd_body_offset); assert(cbuf_len(cb) > sd->sd_body_offset);
remain = cbuf_len(cb) - sd->sd_body_offset; remain = cbuf_len(cb) - sd->sd_body_offset;
clicon_debug(1, "%s length:%zu totlen:%zu, offset:%zu remain:%zu", clixon_debug(CLIXON_DBG_DEFAULT, "%s length:%zu totlen:%zu, offset:%zu remain:%zu",
__FUNCTION__, __FUNCTION__,
length, length,
cbuf_len(cb), cbuf_len(cb),
@ -400,7 +406,7 @@ restconf_sd_read(nghttp2_session *session,
} }
memcpy(buf, cbuf_get(cb) + sd->sd_body_offset, len); memcpy(buf, cbuf_get(cb) + sd->sd_body_offset, len);
sd->sd_body_offset += len; sd->sd_body_offset += len;
clicon_debug(1, "%s retval:%zu", __FUNCTION__, len); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%zu", __FUNCTION__, len);
return len; return len;
} }
@ -428,7 +434,7 @@ restconf_submit_response(nghttp2_session *session,
hdr = &hdrs[i++]; hdr = &hdrs[i++];
hdr->name = (uint8_t*)":status"; hdr->name = (uint8_t*)":status";
snprintf(valstr, 15, "%u", sd->sd_code); snprintf(valstr, 15, "%u", sd->sd_code);
clicon_debug(1, "%s status %d", __FUNCTION__, sd->sd_code); clixon_debug(CLIXON_DBG_DEFAULT, "%s status %d", __FUNCTION__, sd->sd_code);
hdr->value = (uint8_t*)valstr; hdr->value = (uint8_t*)valstr;
hdr->namelen = strlen(":status"); hdr->namelen = strlen(":status");
hdr->valuelen = strlen(valstr); hdr->valuelen = strlen(valstr);
@ -438,7 +444,7 @@ restconf_submit_response(nghttp2_session *session,
while ((cv = cvec_each(sd->sd_outp_hdrs, cv)) != NULL){ while ((cv = cvec_each(sd->sd_outp_hdrs, cv)) != NULL){
hdr = &hdrs[i++]; hdr = &hdrs[i++];
hdr->name = (uint8_t*)cv_name_get(cv); hdr->name = (uint8_t*)cv_name_get(cv);
clicon_debug(1, "%s hdr: %s", __FUNCTION__, hdr->name); clixon_debug(CLIXON_DBG_DEFAULT, "%s hdr: %s", __FUNCTION__, hdr->name);
hdr->value = (uint8_t*)cv_string_get(cv); hdr->value = (uint8_t*)cv_string_get(cv);
hdr->namelen = strlen(cv_name_get(cv)); hdr->namelen = strlen(cv_name_get(cv));
hdr->valuelen = strlen(cv_string_get(cv)); hdr->valuelen = strlen(cv_string_get(cv));
@ -453,7 +459,7 @@ restconf_submit_response(nghttp2_session *session,
} }
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (hdrs) if (hdrs)
free(hdrs); free(hdrs);
return retval; return retval;
@ -469,7 +475,7 @@ http2_exec(restconf_conn *rc,
{ {
int retval = -1; int retval = -1;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (sd->sd_path){ if (sd->sd_path){
free(sd->sd_path); free(sd->sd_path);
sd->sd_path = NULL; sd->sd_path = NULL;
@ -498,7 +504,7 @@ http2_exec(restconf_conn *rc,
*/ */
if (sd->sd_code != 204 && sd->sd_code > 199 && sd->sd_body_len) if (sd->sd_code != 204 && sd->sd_code > 199 && sd->sd_body_len)
if (restconf_reply_header(sd, "Content-Length", "%zu", sd->sd_body_len) < 0) if (restconf_reply_header(sd, "Content-Length", "%zu", sd->sd_body_len) < 0)
goto done; goto done;
if (sd->sd_code){ if (sd->sd_code){
if (restconf_submit_response(session, rc, stream_id, sd) < 0) if (restconf_submit_response(session, rc, stream_id, sd) < 0)
goto done; goto done;
@ -508,7 +514,7 @@ http2_exec(restconf_conn *rc,
} }
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
} }
@ -523,8 +529,8 @@ on_frame_recv_callback(nghttp2_session *session,
restconf_conn *rc = (restconf_conn *)user_data; restconf_conn *rc = (restconf_conn *)user_data;
restconf_stream_data *sd = NULL; restconf_stream_data *sd = NULL;
char *query; char *query;
clicon_debug(1, "%s %s %d", __FUNCTION__, clixon_debug(CLIXON_DBG_DEFAULT, "%s %s %d", __FUNCTION__,
clicon_int2str(nghttp2_frame_type_map, frame->hd.type), clicon_int2str(nghttp2_frame_type_map, frame->hd.type),
frame->hd.stream_id); frame->hd.stream_id);
switch (frame->hd.type) { switch (frame->hd.type) {
@ -566,7 +572,7 @@ on_invalid_frame_recv_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -588,9 +594,9 @@ on_data_chunk_recv_callback(nghttp2_session *session,
restconf_conn *rc = (restconf_conn *)user_data; restconf_conn *rc = (restconf_conn *)user_data;
restconf_stream_data *sd; restconf_stream_data *sd;
clicon_debug(1, "%s %d", __FUNCTION__, stream_id); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, stream_id);
if ((sd = restconf_stream_find(rc, stream_id)) != NULL){ if ((sd = restconf_stream_find(rc, stream_id)) != NULL){
cbuf_append_buf(sd->sd_indata, (void*)data, len); cbuf_append_buf(sd->sd_indata, (void*)data, len);
} }
return 0; return 0;
} }
@ -603,7 +609,7 @@ before_frame_send_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -615,7 +621,7 @@ on_frame_send_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -628,7 +634,7 @@ on_frame_not_send_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -642,7 +648,7 @@ on_stream_close_callback(nghttp2_session *session,
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s %d %s", __FUNCTION__, error_code, nghttp2_strerror(error_code)); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d %s", __FUNCTION__, error_code, nghttp2_strerror(error_code));
#if 0 // NOTNEEDED /* XXX think this is not necessary? */ #if 0 // NOTNEEDED /* XXX think this is not necessary? */
if (error_code){ if (error_code){
if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0)
@ -662,7 +668,7 @@ on_begin_headers_callback(nghttp2_session *session,
restconf_conn *rc = (restconf_conn *)user_data; restconf_conn *rc = (restconf_conn *)user_data;
restconf_stream_data *sd; restconf_stream_data *sd;
clicon_debug(1, "%s %s", __FUNCTION__, clicon_int2str(nghttp2_frame_type_map, frame->hd.type)); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, clicon_int2str(nghttp2_frame_type_map, frame->hd.type));
if (frame->hd.type == NGHTTP2_HEADERS && if (frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) { frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
sd = restconf_stream_data_new(rc, frame->hd.stream_id); sd = restconf_stream_data_new(rc, frame->hd.stream_id);
@ -672,6 +678,7 @@ on_begin_headers_callback(nghttp2_session *session,
} }
/*! Map from nghttp2 headers to "fcgi" type parameters used in clixon code /*! Map from nghttp2 headers to "fcgi" type parameters used in clixon code
*
* Both |name| and |value| are guaranteed to be NULL-terminated. * Both |name| and |value| are guaranteed to be NULL-terminated.
*/ */
static int static int
@ -683,7 +690,7 @@ nghttp2_hdr2clixon(clicon_handle h,
if (strcmp(name, ":path") == 0){ if (strcmp(name, ":path") == 0){
/* Including ?args, call restconf_uripath() to get only path */ /* Including ?args, call restconf_uripath() to get only path */
if (restconf_param_set(h, "REQUEST_URI", value) < 0) if (restconf_param_set(h, "REQUEST_URI", value) < 0)
goto done; goto done;
} }
else if (strcmp(name, ":method") == 0){ else if (strcmp(name, ":method") == 0){
@ -707,6 +714,7 @@ nghttp2_hdr2clixon(clicon_handle h,
} }
/*! Header name/value pair is received /*! Header name/value pair is received
*
* Both |name| and |value| are guaranteed to be NULL-terminated. * Both |name| and |value| are guaranteed to be NULL-terminated.
* If the application uses `nghttp2_session_mem_recv()`, it can return * If the application uses `nghttp2_session_mem_recv()`, it can return
* :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
@ -728,12 +736,12 @@ on_header_callback(nghttp2_session *session,
switch (frame->hd.type){ switch (frame->hd.type){
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
assert (frame->headers.cat == NGHTTP2_HCAT_REQUEST); assert (frame->headers.cat == NGHTTP2_HCAT_REQUEST);
clicon_debug(1, "%s HEADERS %s %s", __FUNCTION__, name, value); clixon_debug(CLIXON_DBG_DEFAULT, "%s HEADERS %s %s", __FUNCTION__, name, value);
if (nghttp2_hdr2clixon(rc->rc_h, (char*)name, (char*)value) < 0) if (nghttp2_hdr2clixon(rc->rc_h, (char*)name, (char*)value) < 0)
goto done; goto done;
break; break;
default: default:
clicon_debug(1, "%s %s %s", __FUNCTION__, clicon_int2str(nghttp2_frame_type_map, frame->hd.type), name); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s %s", __FUNCTION__, clicon_int2str(nghttp2_frame_type_map, frame->hd.type), name);
break; break;
} }
retval = 0; retval = 0;
@ -751,7 +759,7 @@ select_padding_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return frame->hd.length; return frame->hd.length;
} }
@ -767,12 +775,13 @@ data_source_read_length_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
#endif /* NOTUSED */ #endif /* NOTUSED */
/*! Invoked when a frame header is received. /*! Invoked when a frame header is received.
*
* Unlike :type:`nghttp2_on_frame_recv_callback`, this callback will * Unlike :type:`nghttp2_on_frame_recv_callback`, this callback will
* also be called when frame header of CONTINUATION frame is received. * also be called when frame header of CONTINUATION frame is received.
*/ */
@ -782,13 +791,14 @@ on_begin_frame_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s %s", __FUNCTION__, clicon_int2str(nghttp2_frame_type_map, hd->type)); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, clicon_int2str(nghttp2_frame_type_map, hd->type));
if (hd->type == NGHTTP2_CONTINUATION) if (hd->type == NGHTTP2_CONTINUATION)
assert(0); assert(0);
return 0; return 0;
} }
/*! Send complete DATA frame for no-copy /*! Send complete DATA frame for no-copy
*
* Callback function invoked when :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is * Callback function invoked when :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is
* used in :type:`nghttp2_data_source_read_callback` to send complete * used in :type:`nghttp2_data_source_read_callback` to send complete
* DATA frame. * DATA frame.
@ -801,7 +811,7 @@ send_data_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -815,7 +825,7 @@ pack_extension_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -828,7 +838,7 @@ unpack_extension_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
#endif /* NOTUSED */ #endif /* NOTUSED */
@ -843,7 +853,7 @@ on_extension_chunk_recv_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -856,7 +866,7 @@ error_callback(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -871,7 +881,7 @@ error_callback2(nghttp2_session *session,
void *user_data) void *user_data)
{ {
// restconf_conn *rc = (restconf_conn *)user_data; // restconf_conn *rc = (restconf_conn *)user_data;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
clicon_err(OE_NGHTTP2, lib_error_code, "%s", msg); clicon_err(OE_NGHTTP2, lib_error_code, "%s", msg);
return 0; return 0;
} }
@ -893,11 +903,11 @@ http2_recv(restconf_conn *rc,
{ {
int retval = -1; int retval = -1;
nghttp2_error ngerr; nghttp2_error ngerr;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (rc->rc_ngsession == NULL){ if (rc->rc_ngsession == NULL){
/* http2_session_init not called */ /* http2_session_init not called */
clicon_err(OE_RESTCONF, EINVAL, "No nghttp2 session"); clicon_err(OE_RESTCONF, EINVAL, "No nghttp2 session");
goto done; goto done;
} }
/* may make additional pending frames */ /* may make additional pending frames */
@ -924,14 +934,14 @@ http2_recv(restconf_conn *rc,
*/ */
clicon_err_reset(); clicon_err_reset();
if ((ngerr = nghttp2_session_send(rc->rc_ngsession)) != 0){ if ((ngerr = nghttp2_session_send(rc->rc_ngsession)) != 0){
if (clicon_errno) if (clicon_errno)
goto done; goto done;
else else
goto fail; /* Not fatal error */ goto fail; /* Not fatal error */
} }
retval = 1; /* OK */ retval = 1; /* OK */
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
fail: fail:
retval = 0; retval = 0;
@ -948,7 +958,7 @@ http2_send_server_connection(restconf_conn *rc)
,{NGHTTP2_SETTINGS_ENABLE_PUSH, 0}}; ,{NGHTTP2_SETTINGS_ENABLE_PUSH, 0}};
nghttp2_error ngerr; nghttp2_error ngerr;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((ngerr = nghttp2_submit_settings(rc->rc_ngsession, if ((ngerr = nghttp2_submit_settings(rc->rc_ngsession,
NGHTTP2_FLAG_NONE, NGHTTP2_FLAG_NONE,
iv, iv,
@ -962,7 +972,7 @@ http2_send_server_connection(restconf_conn *rc)
} }
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, retval);
return retval; return retval;
} }

View file

@ -98,8 +98,11 @@ api_path_is_restconf(clicon_handle h)
} }
/*! Determine the root of the RESTCONF API by accessing /.well-known /*! Determine the root of the RESTCONF API by accessing /.well-known
* @param[in] h Clicon handle *
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] h Clixon handle
* @param[in] req Generic Www handle (can be part of clixon handle)
* @retval 0 OK
* @retval -1 Error
* @see RFC8040 3.1 and RFC7320 * @see RFC8040 3.1 and RFC7320
* In line with the best practices defined by [RFC7320], RESTCONF * In line with the best practices defined by [RFC7320], RESTCONF
* enables deployments to specify where the RESTCONF API is located. * enables deployments to specify where the RESTCONF API is located.
@ -113,7 +116,7 @@ api_well_known(clicon_handle h,
cbuf *cb = NULL; cbuf *cb = NULL;
int head; int head;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (req == NULL){ if (req == NULL){
errno = EINVAL; errno = EINVAL;
goto done; goto done;
@ -150,12 +153,14 @@ api_well_known(clicon_handle h,
} }
/*! Retrieve the Top-Level API Resource /restconf/ (exact) /*! Retrieve the Top-Level API Resource /restconf/ (exact)
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] req Generic request handle * @param[in] req Generic request handle
* @param[in] method Http method * @param[in] method Http method
* @param[in] pretty Pretty print * @param[in] pretty Pretty print
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
* @retval 0 OK
* @retval -1 Error
* @note Only returns null for operations and data,... * @note Only returns null for operations and data,...
* See RFC8040 3.3 * See RFC8040 3.3
* @see api_root_restconf for accessing /restconf/ * * @see api_root_restconf for accessing /restconf/ *
@ -174,7 +179,7 @@ api_root_restconf_exact(clicon_handle h,
cbuf *cb = NULL; cbuf *cb = NULL;
int head; int head;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
head = strcmp(request_method, "HEAD") == 0; head = strcmp(request_method, "HEAD") == 0;
if (!head && strcmp(request_method, "GET") != 0){ if (!head && strcmp(request_method, "GET") != 0){
if (restconf_method_notallowed(h, req, "GET", pretty, media_out) < 0) if (restconf_method_notallowed(h, req, "GET", pretty, media_out) < 0)
@ -208,7 +213,7 @@ api_root_restconf_exact(clicon_handle h,
goto done; goto done;
break; break;
case YANG_DATA_JSON: case YANG_DATA_JSON:
case YANG_PATCH_JSON: case YANG_PATCH_JSON:
if (clixon_json2cbuf(cb, xt, pretty, 0, 0) < 0) if (clixon_json2cbuf(cb, xt, pretty, 0, 0) < 0)
goto done; goto done;
break; break;
@ -230,7 +235,7 @@ api_root_restconf_exact(clicon_handle h,
/** A stub implementation of the operational state datastore. The full /** A stub implementation of the operational state datastore. The full
* implementation is required by https://tools.ietf.org/html/rfc8527#section-3.1 * implementation is required by https://tools.ietf.org/html/rfc8527#section-3.1
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] req Generic http handle * @param[in] req Generic http handle
* @param[in] pretty Pretty-print * @param[in] pretty Pretty-print
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
@ -243,31 +248,33 @@ api_operational_state(clicon_handle h,
restconf_media media_out) restconf_media media_out)
{ {
clicon_debug(1, "%s request method:%s", __FUNCTION__, request_method); clixon_debug(CLIXON_DBG_DEFAULT, "%s request method:%s", __FUNCTION__, request_method);
/* We are not implementing this method at this time, 20201105 despite it /* We are not implementing this method at this time, 20201105 despite it
* being mandatory https://tools.ietf.org/html/rfc8527#section-3.1 */ * being mandatory https://tools.ietf.org/html/rfc8527#section-3.1 */
return restconf_notimplemented(h, req, pretty, media_out); return restconf_notimplemented(h, req, pretty, media_out);
} }
/*! /*! get yang lib version
*
* See https://tools.ietf.org/html/rfc7895 * See https://tools.ietf.org/html/rfc7895
* @param[in] pretty Pretty-print * @param[in] pretty Pretty-print
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
api_yang_library_version(clicon_handle h, api_yang_library_version(clicon_handle h,
void *req, void *req,
int pretty, int pretty,
restconf_media media_out) restconf_media media_out)
{ {
int retval = -1; int retval = -1;
cxobj *xt = NULL; cxobj *xt = NULL;
cbuf *cb = NULL; cbuf *cb = NULL;
yang_stmt *yspec; yang_stmt *yspec;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0) if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0)
goto done; goto done;
if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0) if (restconf_reply_header(req, "Cache-Control", "no-cache") < 0)
@ -312,6 +319,7 @@ api_yang_library_version(clicon_handle h,
} }
/*! Generic REST method, GET, PUT, DELETE, etc /*! Generic REST method, GET, PUT, DELETE, etc
*
* @param[in] h CLIXON handle * @param[in] h CLIXON handle
* @param[in] r Fastcgi request handle * @param[in] r Fastcgi request handle
* @param[in] api_path According to restconf (Sec 3.5.1.1 in [draft]) * @param[in] api_path According to restconf (Sec 3.5.1.1 in [draft])
@ -320,15 +328,17 @@ api_yang_library_version(clicon_handle h,
* @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] qvec Vector of query string (QUERY_STRING)
* @param[in] pretty Set to 1 for pretty-printed xml/json output * @param[in] pretty Set to 1 for pretty-printed xml/json output
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
* @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource * @param[in] ds 0 if "data" resource, 1 if rfc8527 "ds" resource
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
api_data(clicon_handle h, api_data(clicon_handle h,
void *req, void *req,
char *api_path, char *api_path,
cvec *pcvec, cvec *pcvec,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_out, restconf_media media_out,
@ -339,9 +349,9 @@ api_data(clicon_handle h,
char *request_method; char *request_method;
cxobj *xerr = NULL; cxobj *xerr = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
request_method = restconf_param_get(h, "REQUEST_METHOD"); request_method = restconf_param_get(h, "REQUEST_METHOD");
clicon_debug(1, "%s method:%s", __FUNCTION__, request_method); clixon_debug(CLIXON_DBG_DEFAULT, "%s method:%s", __FUNCTION__, request_method);
/* https://tools.ietf.org/html/rfc8527#section-3.2 */ /* https://tools.ietf.org/html/rfc8527#section-3.2 */
/* We assume that dynamic datastores are read only at this time 20201105 */ /* We assume that dynamic datastores are read only at this time 20201105 */
@ -355,7 +365,7 @@ api_data(clicon_handle h,
if (strcmp(request_method, "OPTIONS")==0) if (strcmp(request_method, "OPTIONS")==0)
retval = api_data_options(h, req); retval = api_data_options(h, req);
else if (strcmp(request_method, "HEAD")==0) { else if (strcmp(request_method, "HEAD")==0) {
if (dynamic) if (dynamic)
retval = restconf_method_notallowed(h, req, "GET,POST", pretty, media_out); retval = restconf_method_notallowed(h, req, "GET,POST", pretty, media_out);
else else
retval = api_data_head(h, req, api_path, pi, qvec, pretty, media_out, ds); retval = api_data_head(h, req, api_path, pi, qvec, pretty, media_out, ds);
@ -367,7 +377,7 @@ api_data(clicon_handle h,
retval = api_data_post(h, req, api_path, pi, qvec, data, pretty, restconf_content_type(h), media_out, ds); retval = api_data_post(h, req, api_path, pi, qvec, data, pretty, restconf_content_type(h), media_out, ds);
} }
else if (strcmp(request_method, "PUT")==0) { else if (strcmp(request_method, "PUT")==0) {
if (read_only) if (read_only)
retval = restconf_method_notallowed(h, req, "GET,POST", pretty, media_out); retval = restconf_method_notallowed(h, req, "GET,POST", pretty, media_out);
else else
retval = api_data_put(h, req, api_path, pi, qvec, data, pretty, media_out, ds); retval = api_data_put(h, req, api_path, pi, qvec, data, pretty, media_out, ds);
@ -379,17 +389,17 @@ api_data(clicon_handle h,
retval = api_data_patch(h, req, api_path, pi, qvec, data, pretty, media_out, ds); retval = api_data_patch(h, req, api_path, pi, qvec, data, pretty, media_out, ds);
} }
else if (strcmp(request_method, "DELETE")==0) { else if (strcmp(request_method, "DELETE")==0) {
if (read_only) if (read_only)
retval = restconf_method_notallowed(h, req, "GET,POST", pretty, media_out); retval = restconf_method_notallowed(h, req, "GET,POST", pretty, media_out);
else else
retval = api_data_delete(h, req, api_path, pi, pretty, media_out, ds); retval = api_data_delete(h, req, api_path, pi, pretty, media_out, ds);
} }
else{ else{
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid HTTP data method") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid HTTP data method") < 0)
goto done; goto done;
retval = api_return_err0(h, req, xerr, pretty, media_out, 0); retval = api_return_err0(h, req, xerr, pretty, media_out, 0);
} }
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
done: done:
if (xerr) if (xerr)
xml_free(xerr); xml_free(xerr);
@ -397,6 +407,7 @@ api_data(clicon_handle h,
} }
/*! Operations REST method, POST /*! Operations REST method, POST
*
* @param[in] h CLIXON handle * @param[in] h CLIXON handle
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] request_method eg GET,... * @param[in] request_method eg GET,...
@ -406,15 +417,17 @@ api_data(clicon_handle h,
* @param[in] qvec Vector of query string (QUERY_STRING) * @param[in] qvec Vector of query string (QUERY_STRING)
* @param[in] data Stream input data * @param[in] data Stream input data
* @param[in] media_out Output media * @param[in] media_out Output media
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
api_operations(clicon_handle h, api_operations(clicon_handle h,
void *req, void *req,
char *request_method, char *request_method,
char *path, char *path,
cvec *pcvec, cvec *pcvec,
int pi, int pi,
cvec *qvec, cvec *qvec,
char *data, char *data,
int pretty, int pretty,
restconf_media media_out) restconf_media media_out)
@ -422,7 +435,7 @@ api_operations(clicon_handle h,
int retval = -1; int retval = -1;
cxobj *xerr = NULL; cxobj *xerr = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (strcmp(request_method, "GET")==0) if (strcmp(request_method, "GET")==0)
retval = api_operations_get(h, req, path, pi, qvec, data, pretty, media_out); retval = api_operations_get(h, req, path, pi, qvec, data, pretty, media_out);
else if (strcmp(request_method, "POST")==0) else if (strcmp(request_method, "POST")==0)
@ -430,7 +443,7 @@ api_operations(clicon_handle h,
pretty, media_out); pretty, media_out);
else{ else{
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid HTTP operations method") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid HTTP operations method") < 0)
goto done; goto done;
retval = api_return_err0(h, req, xerr, pretty, media_out, 0); retval = api_return_err0(h, req, xerr, pretty, media_out, 0);
} }
done: done:
@ -440,9 +453,12 @@ api_operations(clicon_handle h,
} }
/*! Process a /restconf root input, this is the root of the restconf processing /*! Process a /restconf root input, this is the root of the restconf processing
* @param[in] h Clicon handle *
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] h Clixon handle
* @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff
* @retval 0 OK
* @retval -1 Error
* @see api_root_restconf_exact for accessing /restconf/ exact * @see api_root_restconf_exact for accessing /restconf/ exact
*/ */
int int
@ -466,7 +482,7 @@ api_root_restconf(clicon_handle h,
int ret; int ret;
cxobj *xerr = NULL; cxobj *xerr = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (req == NULL){ if (req == NULL){
errno = EINVAL; errno = EINVAL;
goto done; goto done;
@ -476,7 +492,7 @@ api_root_restconf(clicon_handle h,
goto done; goto done;
pretty = restconf_pretty_get(h); pretty = restconf_pretty_get(h);
/* Get media for output (proactive negotiation) RFC7231 by using /* Get media for output (proactive negotiation) RFC7231 by using
* Accept:. This is for methods that have output, such as GET, * Accept:. This is for methods that have output, such as GET,
* operation POST, etc * operation POST, etc
* If accept is * default is yang-json * If accept is * default is yang-json
*/ */
@ -496,7 +512,7 @@ api_root_restconf(clicon_handle h,
goto ok; goto ok;
} }
} }
clicon_debug(1, "%s ACCEPT: %s %s", __FUNCTION__, media_str, restconf_media_int2str(media_out)); clixon_debug(CLIXON_DBG_DEFAULT, "%s ACCEPT: %s %s", __FUNCTION__, media_str, restconf_media_int2str(media_out));
if ((pvec = clicon_strsep(path, "/", &pn)) == NULL) if ((pvec = clicon_strsep(path, "/", &pn)) == NULL)
goto done; goto done;
@ -504,14 +520,14 @@ api_root_restconf(clicon_handle h,
/* Sanity check of path. Should be /restconf/ */ /* Sanity check of path. Should be /restconf/ */
if (pn < 2){ if (pn < 2){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /restconf/ expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /restconf/ expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
if (strlen(pvec[0]) != 0){ if (strlen(pvec[0]) != 0){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, restconf api root expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, restconf api root expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
@ -522,19 +538,19 @@ api_root_restconf(clicon_handle h,
} }
if ((api_resource = pvec[2]) == NULL){ if ((api_resource = pvec[2]) == NULL){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /restconf/ expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /restconf/ expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
clicon_debug(1, "%s: api_resource=%s", __FUNCTION__, api_resource); clixon_debug(CLIXON_DBG_DEFAULT, "%s: api_resource=%s", __FUNCTION__, api_resource);
if (uri_str2cvec(path, '/', '=', 1, &pcvec) < 0) /* rest url eg /album=ricky/foo */ if (uri_str2cvec(path, '/', '=', 1, &pcvec) < 0) /* rest url eg /album=ricky/foo */
goto done; goto done;
/* data */ /* data */
if ((cb = restconf_get_indata(req)) == NULL) /* XXX NYI ACTUALLY not always needed, do this later? */ if ((cb = restconf_get_indata(req)) == NULL) /* XXX NYI ACTUALLY not always needed, do this later? */
goto done; goto done;
indata = cbuf_get(cb); indata = cbuf_get(cb);
clicon_debug(1, "%s DATA=%s", __FUNCTION__, indata); clixon_debug(CLIXON_DBG_DEFAULT, "%s DATA=%s", __FUNCTION__, indata);
/* If present, check credentials. See "plugin_credentials" in plugin /* If present, check credentials. See "plugin_credentials" in plugin
* retvals: * retvals:
@ -564,7 +580,7 @@ api_root_restconf(clicon_handle h,
if (4 > pn) { /* Malformed request, no "ietf-datastores:<datastore>" component */ if (4 > pn) { /* Malformed request, no "ietf-datastores:<datastore>" component */
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, No ietf-datastores:<datastore> component") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, No ietf-datastores:<datastore> component") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
@ -587,7 +603,7 @@ api_root_restconf(clicon_handle h,
} }
else { /* Malformed request, unsupported datastore type */ else { /* Malformed request, unsupported datastore type */
if (netconf_invalid_value_xml(&xerr, "protocol", "Unsupported datastore type") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Unsupported datastore type") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
@ -597,13 +613,13 @@ api_root_restconf(clicon_handle h,
goto done; goto done;
} }
else if (strcmp(api_resource, "operations") == 0){ /* rpc */ else if (strcmp(api_resource, "operations") == 0){ /* rpc */
if (api_operations(h, req, request_method, path, pcvec, 2, qvec, indata, if (api_operations(h, req, request_method, path, pcvec, 2, qvec, indata,
pretty, media_out) < 0) pretty, media_out) < 0)
goto done; goto done;
} }
else{ else{
if (netconf_invalid_value_xml(&xerr, "protocol", "API-resource type") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "API-resource type") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
@ -611,7 +627,7 @@ api_root_restconf(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
#ifdef WITH_RESTCONF_FCGI #ifdef WITH_RESTCONF_FCGI
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);

View file

@ -116,12 +116,12 @@ struct stream_child{
/* Linked list of children /* Linked list of children
* @note could hang STREAM_CHILD list on clicon handle instead. * @note could hang STREAM_CHILD list on clicon handle instead.
*/ */
static struct stream_child *STREAM_CHILD = NULL; static struct stream_child *STREAM_CHILD = NULL;
/*! Check if uri path denotes a stream/notification path /*! Check if uri path denotes a stream/notification path
* *
* @retval 0 No, not a stream path
* @retval 1 Yes, a stream path * @retval 1 Yes, a stream path
* @retval 0 No, not a stream path
*/ */
int int
api_path_is_stream(clicon_handle h) api_path_is_stream(clicon_handle h)
@ -151,7 +151,7 @@ api_path_is_stream(clicon_handle h)
/*! Find restconf child using PID and cleanup FCGI Request data /*! Find restconf child using PID and cleanup FCGI Request data
* *
* For forked, called on SIGCHILD * For forked, called on SIGCHILD
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] pid Process id of child * @param[in] pid Process id of child
* @note could hang STREAM_CHILD list on clicon handle instead. * @note could hang STREAM_CHILD list on clicon handle instead.
*/ */
@ -160,7 +160,7 @@ stream_child_free(clicon_handle h,
int pid) int pid)
{ {
struct stream_child *sc; struct stream_child *sc;
if ((sc = STREAM_CHILD) != NULL){ if ((sc = STREAM_CHILD) != NULL){
do { do {
if (pid == sc->sc_pid){ if (pid == sc->sc_pid){
@ -177,6 +177,7 @@ stream_child_free(clicon_handle h,
} }
/*! Free all streams /*! Free all streams
*
* Typically called on restconf exit * Typically called on restconf exit
*/ */
int int
@ -193,12 +194,15 @@ stream_child_freeall(clicon_handle h)
} }
/*! Callback when stream notifications arrive from backend /*! Callback when stream notifications arrive from backend
*
* @param[in] s Socket * @param[in] s Socket
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @retval 0 OK
* @retval -1 Error
* @see netconf_notification_cb * @see netconf_notification_cb
*/ */
static int static int
restconf_stream_cb(int s, restconf_stream_cb(int s,
void *arg) void *arg)
{ {
int retval = -1; int retval = -1;
@ -210,23 +214,23 @@ restconf_stream_cb(int s,
cbuf *cb = NULL; cbuf *cb = NULL;
int pretty = 0; /* XXX should be via arg */ int pretty = 0; /* XXX should be via arg */
int ret; int ret;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* get msg (this is the reason this function is called) */ /* get msg (this is the reason this function is called) */
if (clicon_msg_rcv(s, NULL, 0, &reply, &eof) < 0){ if (clicon_msg_rcv(s, NULL, 0, &reply, &eof) < 0){
clicon_debug(1, "%s msg_rcv error", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s msg_rcv error", __FUNCTION__);
goto done; goto done;
} }
clicon_debug(1, "%s msg: %s", __FUNCTION__, reply?reply->op_body:"null"); clixon_debug(CLIXON_DBG_DEFAULT, "%s msg: %s", __FUNCTION__, reply?reply->op_body:"null");
/* handle close from remote end: this will exit the client */ /* handle close from remote end: this will exit the client */
if (eof){ if (eof){
clicon_debug(1, "%s eof", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s eof", __FUNCTION__);
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close"); clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
errno = ESHUTDOWN; errno = ESHUTDOWN;
FCGX_FPrintF(r->out, "SHUTDOWN\r\n"); FCGX_FPrintF(r->out, "SHUTDOWN\r\n");
FCGX_FPrintF(r->out, "\r\n"); FCGX_FPrintF(r->out, "\r\n");
FCGX_FFlush(r->out); FCGX_FFlush(r->out);
clixon_exit_set(1); clixon_exit_set(1);
goto done; goto done;
} }
if ((ret = clicon_msg_decode(reply, NULL, NULL, &xtop, NULL)) < 0) /* XXX pass yang_spec */ if ((ret = clicon_msg_decode(reply, NULL, NULL, &xtop, NULL)) < 0) /* XXX pass yang_spec */
@ -262,7 +266,7 @@ restconf_stream_cb(int s,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval: %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval: %d", __FUNCTION__, retval);
if (xtop != NULL) if (xtop != NULL)
xml_free(xtop); xml_free(xtop);
if (reply) if (reply)
@ -273,19 +277,22 @@ restconf_stream_cb(int s,
} }
/*! Send subscription to backend /*! Send subscription to backend
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[in] name Stream name * @param[in] name Stream name
* @param[in] qvec * @param[in] qvec
* @param[in] pretty Pretty-print json/xml reply * @param[in] pretty Pretty-print json/xml reply
* @param[in] media_out Restconf output media * @param[in] media_out Restconf output media
* @param[out] sp Socket -1 if not set * @param[out] sp Socket -1 if not set
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
restconf_stream(clicon_handle h, restconf_stream(clicon_handle h,
void *req, void *req,
char *name, char *name,
cvec *qvec, cvec *qvec,
int pretty, int pretty,
restconf_media media_out, restconf_media media_out,
int *sp) int *sp)
@ -299,7 +306,7 @@ restconf_stream(clicon_handle h,
cg_var *cv; cg_var *cv;
char *vname; char *vname;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
*sp = -1; *sp = -1;
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); clicon_err(OE_XML, errno, "cbuf_new");
@ -346,7 +353,7 @@ restconf_stream(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval: %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval: %d", __FUNCTION__, retval);
if (xret) if (xret)
xml_free(xret); xml_free(xret);
if (cb) if (cb)
@ -359,18 +366,19 @@ restconf_stream(clicon_handle h,
#include "restconf_stream.h" #include "restconf_stream.h"
/*! Listen sock callback (from proxy?) /*! Listen sock callback (from proxy?)
*
* @param[in] s Socket * @param[in] s Socket
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] req Generic Www handle (can be part of clixon handle)
*/ */
static int static int
stream_checkuplink(int s, stream_checkuplink(int s,
void *arg) void *arg)
{ {
FCGX_Request *r = (FCGX_Request *)arg; FCGX_Request *r = (FCGX_Request *)arg;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (FCGX_GetError(r->out) != 0){ /* break loop */ if (FCGX_GetError(r->out) != 0){ /* break loop */
clicon_debug(1, "%s FCGX_GetError upstream", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s FCGX_GetError upstream", __FUNCTION__);
clixon_exit_set(1); clixon_exit_set(1);
} }
return 0; return 0;
@ -383,10 +391,10 @@ stream_timeout(int s,
struct timeval t; struct timeval t;
struct timeval t1; struct timeval t1;
FCGX_Request *r = (FCGX_Request *)arg; FCGX_Request *r = (FCGX_Request *)arg;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (FCGX_GetError(r->out) != 0){ /* break loop */ if (FCGX_GetError(r->out) != 0){ /* break loop */
clicon_debug(1, "%s FCGX_GetError upstream", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s FCGX_GetError upstream", __FUNCTION__);
clixon_exit_set(1); clixon_exit_set(1);
} }
else{ else{
@ -396,13 +404,16 @@ stream_timeout(int s,
clixon_event_reg_timeout(t, stream_timeout, arg, "Stream timeout"); clixon_event_reg_timeout(t, stream_timeout, arg, "Stream timeout");
} }
return 0; return 0;
} }
/*! Process a stream request /*! Process a stream request
* @param[in] h Clicon handle *
* @param[in] req Generic Www handle (can be part of clixon handle) * @param[in] h Clixon handle
* @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff * @param[in] req Generic Www handle (can be part of clixon handle)
* @param[out] finish Set to zero, if request should not be finnished by upper layer * @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff
* @param[out] finish Set to zero, if request should not be finnished by upper layer
* @retval 0 OK
* @retval -1 Error
*/ */
int int
api_stream(clicon_handle h, api_stream(clicon_handle h,
@ -431,7 +442,7 @@ api_stream(clicon_handle h,
struct stream_child *sc; struct stream_child *sc;
#endif #endif
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
streampath = clicon_option_str(h, "CLICON_STREAM_PATH"); streampath = clicon_option_str(h, "CLICON_STREAM_PATH");
if ((path = restconf_uripath(h)) == NULL) if ((path = restconf_uripath(h)) == NULL)
goto done; goto done;
@ -441,33 +452,33 @@ api_stream(clicon_handle h,
/* Sanity check of path. Should be /stream/<name> */ /* Sanity check of path. Should be /stream/<name> */
if (pn != 3){ if (pn != 3){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
if (strlen(pvec[0]) != 0){ if (strlen(pvec[0]) != 0){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
if (strcmp(pvec[1], streampath)){ if (strcmp(pvec[1], streampath)){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
if ((method = pvec[2]) == NULL){ if ((method = pvec[2]) == NULL){
if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0) if (netconf_invalid_value_xml(&xerr, "protocol", "Invalid path, /stream/<name> expected") < 0)
goto done; goto done;
if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0) if (api_return_err0(h, req, xerr, pretty, media_out, 0) < 0)
goto done; goto done;
goto ok; goto ok;
} }
clicon_debug(1, "%s: method=%s", __FUNCTION__, method); clixon_debug(CLIXON_DBG_DEFAULT, "%s: method=%s", __FUNCTION__, method);
if (uri_str2cvec(path, '/', '=', 1, &pcvec) < 0) /* rest url eg /album=ricky/foo */ if (uri_str2cvec(path, '/', '=', 1, &pcvec) < 0) /* rest url eg /album=ricky/foo */
goto done; goto done;
@ -475,7 +486,7 @@ api_stream(clicon_handle h,
if ((cb = restconf_get_indata(req)) == NULL) if ((cb = restconf_get_indata(req)) == NULL)
goto done; goto done;
indata = cbuf_get(cb); indata = cbuf_get(cb);
clicon_debug(1, "%s DATA=%s", __FUNCTION__, indata); clixon_debug(CLIXON_DBG_DEFAULT, "%s DATA=%s", __FUNCTION__, indata);
/* If present, check credentials. See "plugin_credentials" in plugin /* If present, check credentials. See "plugin_credentials" in plugin
* See RFC 8040 section 2.5 * See RFC 8040 section 2.5
@ -501,22 +512,22 @@ api_stream(clicon_handle h,
cbuf_free(cbret); cbuf_free(cbret);
#endif /* STREAM_FORK */ #endif /* STREAM_FORK */
/* Listen to backend socket */ /* Listen to backend socket */
if (clixon_event_reg_fd(s, if (clixon_event_reg_fd(s,
restconf_stream_cb, restconf_stream_cb,
req,
"stream socket") < 0)
goto done;
if (clixon_event_reg_fd(rfcgi->listen_sock,
stream_checkuplink,
req, req,
"stream socket") < 0) "stream socket") < 0)
goto done; goto done;
clicon_debug(1, "%s before loop", __FUNCTION__); if (clixon_event_reg_fd(rfcgi->listen_sock,
stream_checkuplink,
req,
"stream socket") < 0)
goto done;
clixon_debug(CLIXON_DBG_DEFAULT, "%s before loop", __FUNCTION__);
/* Poll upstream errors */ /* Poll upstream errors */
stream_timeout(0, req); stream_timeout(0, req);
/* Start loop */ /* Start loop */
clixon_event_loop(h); clixon_event_loop(h);
clicon_debug(1, "%s after loop", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s after loop", __FUNCTION__);
clicon_rpc_close_session(h); clicon_rpc_close_session(h);
clixon_event_unreg_fd(s, restconf_stream_cb); clixon_event_unreg_fd(s, restconf_stream_cb);
close(s); close(s);
@ -551,7 +562,7 @@ api_stream(clicon_handle h,
ok: ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
if (xerr) if (xerr)
xml_free(xerr); xml_free(xerr);
if (pvec) if (pvec)

View file

@ -97,10 +97,10 @@ snmp_common_handler(netsnmp_mib_handler *handler,
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
} }
oid_cbuf(cb, (*shp)->sh_oid, (*shp)->sh_oidlen); oid_cbuf(cb, (*shp)->sh_oid, (*shp)->sh_oidlen);
if (oid_eq(requestvb->name, requestvb->name_length, if (oid_eq(requestvb->name, requestvb->name_length,
(*shp)->sh_oid, (*shp)->sh_oidlen) == 0){ /* equal */ (*shp)->sh_oid, (*shp)->sh_oidlen) == 0){ /* equal */
clicon_debug(1, "%s \"%s\" %s inclusive:%d %s", __FUNCTION__, clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\" %s inclusive:%d %s", __FUNCTION__,
cbuf_get(cb), cbuf_get(cb),
snmp_msg_int2str(reqinfo->mode), snmp_msg_int2str(reqinfo->mode),
request->inclusive, tablehandler?"table":"scalar"); request->inclusive, tablehandler?"table":"scalar");
@ -110,7 +110,7 @@ snmp_common_handler(netsnmp_mib_handler *handler,
oid_cbuf(cb, requestvb->name, requestvb->name_length); oid_cbuf(cb, requestvb->name, requestvb->name_length);
cprintf(cb, ")"); cprintf(cb, ")");
// nhreg->rootoid same as shp // nhreg->rootoid same as shp
clicon_debug(1, "%s \"%s\" %s inclusive:%d %s", __FUNCTION__, clixon_debug(CLIXON_DBG_DEFAULT, "%s \"%s\" %s inclusive:%d %s", __FUNCTION__,
cbuf_get(cb), cbuf_get(cb),
snmp_msg_int2str(reqinfo->mode), snmp_msg_int2str(reqinfo->mode),
request->inclusive, tablehandler?"table":"scalar"); request->inclusive, tablehandler?"table":"scalar");
@ -122,7 +122,8 @@ snmp_common_handler(netsnmp_mib_handler *handler,
return retval; return retval;
} }
/*! /*! scalar return
*
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] request The netsnmp request info structure. * @param[in] request The netsnmp request info structure.
* @retval 0 OK * @retval 0 OK
@ -138,7 +139,7 @@ snmp_scalar_return(cxobj *xs,
{ {
int retval = -1; int retval = -1;
int asn1type; int asn1type;
char *xmlstr = NULL; char *xmlstr = NULL;
char *defaultval = NULL; char *defaultval = NULL;
u_char *snmpval = NULL; u_char *snmpval = NULL;
size_t snmplen = 0; size_t snmplen = 0;
@ -180,7 +181,7 @@ snmp_scalar_return(cxobj *xs,
if ((ret = type_xml2snmp(xmlstr, &asn1type, &snmpval, &snmplen, &reason)) < 0) if ((ret = type_xml2snmp(xmlstr, &asn1type, &snmpval, &snmplen, &reason)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug(1, "%s %s", __FUNCTION__, reason); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, reason);
if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto done; goto done;
@ -210,15 +211,16 @@ snmp_scalar_return(cxobj *xs,
} }
/*! Scalar handler, set a value to clixon /*! Scalar handler, set a value to clixon
*
* get xpath: see yang2api_path_fmt / api_path2xpath * get xpath: see yang2api_path_fmt / api_path2xpath
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang node * @param[in] ys Yang node
* @param[in] cvk Vector of index/Key variables, if any * @param[in] cvk Vector of index/Key variables, if any
* @param[in] defaultval Default value * @param[in] defaultval Default value
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] request The netsnmp request info structure. * @param[in] request The netsnmp request info structure.
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
snmp_scalar_get(clicon_handle h, snmp_scalar_get(clicon_handle h,
@ -244,7 +246,7 @@ snmp_scalar_get(clicon_handle h,
cxobj *xcache = NULL; cxobj *xcache = NULL;
char *body = NULL; char *body = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* Prepare backend call by constructing namespace context */ /* Prepare backend call by constructing namespace context */
if (xml_nsctx_yang(ys, &nsc) < 0) if (xml_nsctx_yang(ys, &nsc) < 0)
goto done; goto done;
@ -266,7 +268,7 @@ snmp_scalar_get(clicon_handle h,
} }
x = xpath_first(xt, nsc, "%s", xpath); x = xpath_first(xt, nsc, "%s", xpath);
} }
/* /*
* The xml to snmp value conversion is done in two steps: * The xml to snmp value conversion is done in two steps:
* 1. From XML to SNMP string, there is a special case for enumeration, and for default value * 1. From XML to SNMP string, there is a special case for enumeration, and for default value
* 2. From SNMP string to SNMP binary value which invloves parsing * 2. From SNMP string to SNMP binary value which invloves parsing
@ -298,7 +300,7 @@ snmp_scalar_get(clicon_handle h,
if ((ret = type_xml2snmp(xmlstr, &asn1type, &snmpval, &snmplen, &reason)) < 0) if ((ret = type_xml2snmp(xmlstr, &asn1type, &snmpval, &snmplen, &reason)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug(1, "%s %s", __FUNCTION__, reason); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, reason);
if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto done; goto done;
@ -344,7 +346,7 @@ snmp_yang2xml(cxobj *xtop,
int i; int i;
int ret; int ret;
yang_stmt *yspec; yang_stmt *yspec;
yspec = ys_spec(ys); yspec = ys_spec(ys);
if (yang2api_path_fmt(ys, 0, &api_path_fmt) < 0) if (yang2api_path_fmt(ys, 0, &api_path_fmt) < 0)
goto done; goto done;
@ -374,15 +376,16 @@ snmp_yang2xml(cxobj *xtop,
return retval; return retval;
} }
/*! Scalar handler, get a value from clixon /*! Scalar handler, get a value from clixon
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ys Yang node * @param[in] ys Yang node
* @param[in] cvk Vector of index/Key variables, if any * @param[in] cvk Vector of index/Key variables, if any
* @param[in] valstr0 Pre-set value string, ignore requestvb * @param[in] valstr0 Pre-set value string, ignore requestvb
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] request The netsnmp request info structure. * @param[in] request The netsnmp request info structure.
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @note contains special logic for rowstatus handling * @note contains special logic for rowstatus handling
*/ */
static int static int
@ -404,13 +407,13 @@ snmp_scalar_set(clicon_handle h,
int asn1_type; int asn1_type;
enum operation_type op = OP_MERGE; enum operation_type op = OP_MERGE;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((xtop = xml_new(NETCONF_INPUT_CONFIG, NULL, CX_ELMNT)) == NULL) if ((xtop = xml_new(NETCONF_INPUT_CONFIG, NULL, CX_ELMNT)) == NULL)
goto done; goto done;
if (snmp_yang2xml(xtop, ys, cvk, &xbot) < 0) if (snmp_yang2xml(xtop, ys, cvk, &xbot) < 0)
goto done; goto done;
if ((xb = xml_new("body", xbot, CX_BODY)) == NULL) if ((xb = xml_new("body", xbot, CX_BODY)) == NULL)
goto done; goto done;
/* Extended */ /* Extended */
if (type_yang2asn1(ys, &asn1_type, 1) < 0) if (type_yang2asn1(ys, &asn1_type, 1) < 0)
goto done; goto done;
@ -473,7 +476,7 @@ snmp_cache_row_op(clicon_handle h,
cxobj *xbot = NULL; cxobj *xbot = NULL;
cxobj *xa; cxobj *xa;
cxobj *xcache; cxobj *xcache;
if (xml_nsctx_yang(yp, &nsc) < 0) if (xml_nsctx_yang(yp, &nsc) < 0)
goto done; goto done;
/* Create xpath from yang */ /* Create xpath from yang */
@ -499,7 +502,7 @@ snmp_cache_row_op(clicon_handle h,
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
goto done; goto done;
} }
if (clixon_xml2cbuf(cb, xtop, 0, 0, NULL, -1, 0) < 0) if (clixon_xml2cbuf(cb, xtop, 0, 0, NULL, -1, 0) < 0)
goto done; goto done;
if (clicon_rpc_edit_config(h, "candidate", OP_NONE, cbuf_get(cb)) < 0) if (clicon_rpc_edit_config(h, "candidate", OP_NONE, cbuf_get(cb)) < 0)
@ -552,8 +555,8 @@ snmp_cache_set(clicon_handle h,
yang_stmt *yspec; yang_stmt *yspec;
int isrowstatus = 0; int isrowstatus = 0;
cxobj *xcache = NULL; cxobj *xcache = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((yspec = clicon_dbspec_yang(h)) == NULL){ if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_FATAL, 0, "No DB_SPEC"); clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done; goto done;
@ -563,7 +566,7 @@ snmp_cache_set(clicon_handle h,
if (snmp_yang2xml(xtop, ys, cvk, &xbot) < 0) if (snmp_yang2xml(xtop, ys, cvk, &xbot) < 0)
goto done; goto done;
if ((xb = xml_new("body", xbot, CX_BODY)) == NULL) if ((xb = xml_new("body", xbot, CX_BODY)) == NULL)
goto done; goto done;
/* Extended */ /* Extended */
if (type_yang2asn1(ys, &asn1_type, 1) < 0) if (type_yang2asn1(ys, &asn1_type, 1) < 0)
goto done; goto done;
@ -596,8 +599,8 @@ snmp_cache_set(clicon_handle h,
if (snmp_cache_row_op(h, yang_parent_get(ys), cvk, "merge", 1) < 0) if (snmp_cache_row_op(h, yang_parent_get(ys), cvk, "merge", 1) < 0)
goto done; goto done;
} }
else if (strcmp(valstr, "destroy") == 0){ else if (strcmp(valstr, "destroy") == 0){
clicon_debug(1, "%s %d", __FUNCTION__, rowstatus); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, rowstatus);
/* Dont send delete to backend if notInService(2) */ /* Dont send delete to backend if notInService(2) */
if (snmp_cache_row_op(h, yang_parent_get(ys), cvk, "delete", rowstatus!=2) < 0) if (snmp_cache_row_op(h, yang_parent_get(ys), cvk, "delete", rowstatus!=2) < 0)
goto done; goto done;
@ -640,7 +643,7 @@ snmp_cache_set(clicon_handle h,
* @param[in] cvk Vector of index/Key variables, if any * @param[in] cvk Vector of index/Key variables, if any
* @param[out] rowstatus Enmu rowstatus: 0 invalid, 1 active, etc * @param[out] rowstatus Enmu rowstatus: 0 invalid, 1 active, etc
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
*/ */
static int static int
snmp_table_rowstatus_get(clicon_handle h, snmp_table_rowstatus_get(clicon_handle h,
@ -658,8 +661,8 @@ snmp_table_rowstatus_get(clicon_handle h,
char *body; char *body;
char *intstr; char *intstr;
char *reason = NULL; char *reason = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
/* Prepare backend call by constructing namespace context */ /* Prepare backend call by constructing namespace context */
if (xml_nsctx_yang(ys, &nsc) < 0) if (xml_nsctx_yang(ys, &nsc) < 0)
goto done; goto done;
@ -672,14 +675,14 @@ snmp_table_rowstatus_get(clicon_handle h,
if ((ret = yang_enum2valstr(yrestype, body, &intstr)) < 0) if ((ret = yang_enum2valstr(yrestype, body, &intstr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug(1, "%s %s invalid or not found", __FUNCTION__, body); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s invalid or not found", __FUNCTION__, body);
*rowstatus = 0; *rowstatus = 0;
} }
else { else {
if ((ret = parse_int32(intstr, rowstatus, &reason)) < 0) if ((ret = parse_int32(intstr, rowstatus, &reason)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug(1, "%s parse_int32: %s", __FUNCTION__, reason); clixon_debug(CLIXON_DBG_DEFAULT, "%s parse_int32: %s", __FUNCTION__, reason);
*rowstatus = 0; *rowstatus = 0;
} }
} }
@ -718,7 +721,7 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
netsnmp_variable_list *requestvb = request->requestvb; netsnmp_variable_list *requestvb = request->requestvb;
int ret; int ret;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
if (snmp_common_handler(handler, nhreg, reqinfo, request, 0, &sh) < 0) if (snmp_common_handler(handler, nhreg, reqinfo, request, 0, &sh) < 0)
goto done; goto done;
/* see net-snmp/agent/snmp_agent.h / net-snmp/library/snmp.h */ /* see net-snmp/agent/snmp_agent.h / net-snmp/library/snmp.h */
@ -740,7 +743,7 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
if (type_yang2asn1(sh->sh_ys, &asn1_type, 0) < 0) if (type_yang2asn1(sh->sh_ys, &asn1_type, 0) < 0)
goto done; goto done;
if (requestvb->type != asn1_type){ if (requestvb->type != asn1_type){
clicon_debug(1, "%s Expected type:%d, got: %d", __FUNCTION__, requestvb->type, asn1_type); clixon_debug(CLIXON_DBG_DEFAULT, "%s Expected type:%d, got: %d", __FUNCTION__, requestvb->type, asn1_type);
if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto ok; goto ok;
@ -753,7 +756,7 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
if (snmp_scalar_set(sh->sh_h, sh->sh_ys, NULL, NULL, reqinfo, request) < 0) if (snmp_scalar_set(sh->sh_h, sh->sh_ys, NULL, NULL, reqinfo, request) < 0)
goto done; goto done;
/* /*
* There does not seem to be a separate validation action and commit does not * There does not seem to be a separate validation action and commit does not
* return an error. * return an error.
* Therefore validation is done here directly as well as discard if it fails. * Therefore validation is done here directly as well as discard if it fails.
*/ */
@ -781,13 +784,13 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
break; break;
case MODE_SET_UNDO: /* 5 */ case MODE_SET_UNDO: /* 5 */
if (clicon_rpc_discard_changes(sh->sh_h) < 0) if (clicon_rpc_discard_changes(sh->sh_h) < 0)
goto done; goto done;
break; break;
} }
ok: ok:
retval = SNMP_ERR_NOERROR; retval = SNMP_ERR_NOERROR;
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval);
return retval; return retval;
} }
@ -797,6 +800,8 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
* @param[in] nhreg Root registration info. * @param[in] nhreg Root registration info.
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] requests The netsnmp request info structure. * @param[in] requests The netsnmp request info structure.
* @retval SNMP_ERR_NOERROR OK
* @retval -1 Error
* @see clixon_snmp_table_handler * @see clixon_snmp_table_handler
*/ */
int int
@ -809,7 +814,7 @@ clixon_snmp_scalar_handler(netsnmp_mib_handler *handler,
netsnmp_request_info *req; netsnmp_request_info *req;
int ret; int ret;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
for (req = requests; req; req = req->next){ for (req = requests; req; req = req->next){
ret = clixon_snmp_scalar_handler1(handler, nhreg, reqinfo, req); ret = clixon_snmp_scalar_handler1(handler, nhreg, reqinfo, req);
if (ret != SNMP_ERR_NOERROR){ if (ret != SNMP_ERR_NOERROR){
@ -836,9 +841,9 @@ clixon_snmp_scalar_handler(netsnmp_mib_handler *handler,
* @param[in] oidslen OID length of scalar * @param[in] oidslen OID length of scalar
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] request The netsnmp request info structure. * @param[in] request The netsnmp request info structure.
* @retval -1 Error
* @retval 0 Object not found
* @retval 1 OK * @retval 1 OK
* @retval 0 Object not found
* @retval -1 Error
*/ */
static int static int
snmp_table_get(clicon_handle h, snmp_table_get(clicon_handle h,
@ -889,7 +894,7 @@ snmp_table_get(clicon_handle h,
*/ */
if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &defaultval) < 0) if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &defaultval) < 0)
goto done; goto done;
/* Create xpath with right keys from later part of OID /* Create xpath with right keys from later part of OID
* Inverse of snmp_str2oid * Inverse of snmp_str2oid
*/ */
@ -906,12 +911,12 @@ snmp_table_get(clicon_handle h,
oidi = oids+oidtlen+1; oidi = oids+oidtlen+1;
/* Add keys */ /* Add keys */
for (i=0; i<cvec_len(cvk_val); i++){ for (i=0; i<cvec_len(cvk_val); i++){
cv = cvec_i(cvk_val, i); cv = cvec_i(cvk_val, i);
if ((yk = yang_find(yt, Y_LEAF, cv_string_get(cv))) == NULL){ if ((yk = yang_find(yt, Y_LEAF, cv_string_get(cv))) == NULL){
clicon_err(OE_YANG, 0, "List key %s not found", cv_string_get(cv)); clicon_err(OE_YANG, 0, "List key %s not found", cv_string_get(cv));
goto done; goto done;
} }
if (snmp_oid2str(&oidi, &oidilen, yk, cv) < 0) if (snmp_oid2str(&oidi, &oidilen, yk, cv) < 0)
goto done; goto done;
} }
if (oidilen != 0){ if (oidilen != 0){
@ -938,6 +943,7 @@ snmp_table_get(clicon_handle h,
} }
/*! Set value in table /*! Set value in table
*
* Get yang of leaf from first part of OID * Get yang of leaf from first part of OID
* Create xpath with right keys from later part of OID * Create xpath with right keys from later part of OID
* Query clixon if object exists, if so return value * Query clixon if object exists, if so return value
@ -948,9 +954,9 @@ snmp_table_get(clicon_handle h,
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] request The netsnmp request info structure. * @param[in] request The netsnmp request info structure.
* @param[out] err Error code if failed (retval = 0) * @param[out] err Error code if failed (retval = 0)
* @retval -1 Error
* @retval 0 Failed, err set
* @retval 1 OK * @retval 1 OK
* @retval 0 Failed, err set
* @retval -1 Error
*/ */
static int static int
snmp_table_set(clicon_handle h, snmp_table_set(clicon_handle h,
@ -1047,7 +1053,7 @@ snmp_table_set(clicon_handle h,
goto done; goto done;
requestvb = request->requestvb; requestvb = request->requestvb;
if (requestvb->type != asn1_type){ if (requestvb->type != asn1_type){
clicon_debug(1, "%s Expected type:%d, got: %d", __FUNCTION__, requestvb->type, asn1_type); clixon_debug(CLIXON_DBG_DEFAULT, "%s Expected type:%d, got: %d", __FUNCTION__, requestvb->type, asn1_type);
if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto ok; goto ok;
@ -1069,12 +1075,12 @@ snmp_table_set(clicon_handle h,
oidi = oids+oidtlen+1; oidi = oids+oidtlen+1;
/* Add keys */ /* Add keys */
for (i=0; i<cvec_len(cvk_val); i++){ for (i=0; i<cvec_len(cvk_val); i++){
cv = cvec_i(cvk_val, i); cv = cvec_i(cvk_val, i);
if ((yk = yang_find(yt, Y_LEAF, cv_string_get(cv))) == NULL){ if ((yk = yang_find(yt, Y_LEAF, cv_string_get(cv))) == NULL){
clicon_err(OE_YANG, 0, "List key %s not found", cv_string_get(cv)); clicon_err(OE_YANG, 0, "List key %s not found", cv_string_get(cv));
goto done; goto done;
} }
if (snmp_oid2str(&oidi, &oidilen, yk, cv) < 0) if (snmp_oid2str(&oidi, &oidilen, yk, cv) < 0)
goto done; goto done;
} }
if (oidilen != 0){ if (oidilen != 0){
@ -1090,7 +1096,7 @@ snmp_table_set(clicon_handle h,
cvk_val, cvk_val,
&rowstatus)) < 0) &rowstatus)) < 0)
goto done; goto done;
} }
else{ else{
/* If no rowstatus object, default to active */ /* If no rowstatus object, default to active */
rowstatus = 1; rowstatus = 1;
@ -1152,6 +1158,7 @@ snmp_table_set(clicon_handle h,
} }
/*! Find "next" object from oids minus key and return that. /*! Find "next" object from oids minus key and return that.
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] ylist Yang of table (of list type) * @param[in] ylist Yang of table (of list type)
* @param[in] oids OID of ultimate scalar value * @param[in] oids OID of ultimate scalar value
@ -1189,12 +1196,12 @@ snmp_table_getnext(clicon_handle h,
size_t oidklen = MAX_OID_LEN; size_t oidklen = MAX_OID_LEN;
oid oidnext[MAX_OID_LEN] = {0x7fffffff,}; /* Next oid: start with high value */ oid oidnext[MAX_OID_LEN] = {0x7fffffff,}; /* Next oid: start with high value */
size_t oidnextlen = MAX_OID_LEN; size_t oidnextlen = MAX_OID_LEN;
int found = 0; int found = 0;
cxobj *xnext = NULL; cxobj *xnext = NULL;
yang_stmt *ynext = NULL; yang_stmt *ynext = NULL;
cbuf *cb = NULL; cbuf *cb = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((ys = yang_parent_get(ylist)) == NULL || if ((ys = yang_parent_get(ylist)) == NULL ||
yang_keyword_get(ys) != Y_CONTAINER){ yang_keyword_get(ys) != Y_CONTAINER){
clicon_err(OE_YANG, EINVAL, "ylist parent is not list"); clicon_err(OE_YANG, EINVAL, "ylist parent is not list");
@ -1256,7 +1263,7 @@ snmp_table_getnext(clicon_handle h,
goto done; goto done;
} }
oid_cbuf(cb, oidnext, oidnextlen); oid_cbuf(cb, oidnext, oidnextlen);
clicon_debug(1, "%s next: %s", __FUNCTION__, cbuf_get(cb)); clixon_debug(CLIXON_DBG_DEFAULT, "%s next: %s", __FUNCTION__, cbuf_get(cb));
} }
retval = found; retval = found;
done: done:
@ -1267,7 +1274,7 @@ snmp_table_getnext(clicon_handle h,
if (xt) if (xt)
xml_free(xt); xml_free(xt);
if (nsc) if (nsc)
xml_nsctx_free(nsc); xml_nsctx_free(nsc);
return retval; return retval;
} }
@ -1277,6 +1284,8 @@ snmp_table_getnext(clicon_handle h,
* @param[in] nhreg Root registration info. * @param[in] nhreg Root registration info.
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] request The netsnmp request info structure. * @param[in] request The netsnmp request info structure.
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
clixon_snmp_table_handler1(netsnmp_mib_handler *handler, clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
@ -1292,12 +1301,12 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
int ret; int ret;
netsnmp_variable_list *requestvb; netsnmp_variable_list *requestvb;
int err = 0; int err = 0;
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
if ((ret = snmp_common_handler(handler, nhreg, reqinfo, request, 1, &sh)) < 0) if ((ret = snmp_common_handler(handler, nhreg, reqinfo, request, 1, &sh)) < 0)
goto done; goto done;
if (sh->sh_ys == NULL){ if (sh->sh_ys == NULL){
clicon_debug(1, "%s Error table not registered", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s Error table not registered", __FUNCTION__);
goto ok; goto ok;
} }
requestvb = request->requestvb; requestvb = request->requestvb;
@ -1306,7 +1315,7 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
/* Create xpath from YANG table OID + 1 + n + cvk/key = requestvb->name /* Create xpath from YANG table OID + 1 + n + cvk/key = requestvb->name
*/ */
if ((ret = snmp_table_get(sh->sh_h, sh->sh_ys, if ((ret = snmp_table_get(sh->sh_h, sh->sh_ys,
sh->sh_oid2, sh->sh_oid2len, sh->sh_oid2, sh->sh_oid2len,
requestvb->name, requestvb->name_length, requestvb->name, requestvb->name_length,
reqinfo, request)) < 0) reqinfo, request)) < 0)
goto done; goto done;
@ -1315,7 +1324,7 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto done; goto done;
} }
clicon_debug(1, "%s Nosuchinstance", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s Nosuchinstance", __FUNCTION__);
} }
break; break;
case MODE_GETNEXT: // 161 case MODE_GETNEXT: // 161
@ -1330,13 +1339,13 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto done; goto done;
} }
clicon_debug(1, "%s No such object", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s No such object", __FUNCTION__);
} }
break; break;
case MODE_SET_RESERVE1: // 0 case MODE_SET_RESERVE1: // 0
if (!yang_config_ancestor(sh->sh_ys)){ if (!yang_config_ancestor(sh->sh_ys)){
netsnmp_request_set_error(request, SNMP_ERR_NOTWRITABLE); netsnmp_request_set_error(request, SNMP_ERR_NOTWRITABLE);
goto done;; goto done;
} }
// Check types: compare type in requestvb to yang type (or do later) // Check types: compare type in requestvb to yang type (or do later)
break; break;
@ -1352,7 +1361,7 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto done; goto done;
} }
clicon_debug(1, "%s Nosuchinstance", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s Nosuchinstance", __FUNCTION__);
} }
/* /*
* There does not seem to be a separate validation action and commit does not * There does not seem to be a separate validation action and commit does not
@ -1380,7 +1389,7 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
break; break;
case MODE_SET_UNDO : // 5 case MODE_SET_UNDO : // 5
if (clicon_rpc_discard_changes(sh->sh_h) < 0) if (clicon_rpc_discard_changes(sh->sh_h) < 0)
goto done; goto done;
break; break;
} }
ok: ok:
@ -1401,6 +1410,8 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
* @param[in] nhreg Root registration info. * @param[in] nhreg Root registration info.
* @param[in] reqinfo Agent transaction request structure * @param[in] reqinfo Agent transaction request structure
* @param[in] requests The netsnmp request info structure. * @param[in] requests The netsnmp request info structure.
* @retval 0 OK
* @retval -1 Error
* @see clixon_snmp_scalar_handler * @see clixon_snmp_scalar_handler
*/ */
int int
@ -1413,7 +1424,7 @@ clixon_snmp_table_handler(netsnmp_mib_handler *handler,
netsnmp_request_info *req; netsnmp_request_info *req;
int ret; int ret;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
for (req = requests; req; req = req->next){ for (req = requests; req; req = req->next){
ret = clixon_snmp_table_handler1(handler, nhreg, reqinfo, req); ret = clixon_snmp_table_handler1(handler, nhreg, reqinfo, req);
if (ret != SNMP_ERR_NOERROR){ if (ret != SNMP_ERR_NOERROR){

View file

@ -217,6 +217,7 @@ yang_type_to_snmp(yang_stmt *ytype,
} }
/*! Translate from snmp string to int representation /*! Translate from snmp string to int representation
*
* @note Internal snmpd, maybe find something in netsnmpd? * @note Internal snmpd, maybe find something in netsnmpd?
*/ */
int int
@ -237,8 +238,8 @@ snmp_msg_int2str(int msg)
* @param[in] objid0len Length of first OID vector * @param[in] objid0len Length of first OID vector
* @param[in] objid1 Second OID vector * @param[in] objid1 Second OID vector
* @param[in] objid1len Length of second OID vector * @param[in] objid1len Length of second OID vector
* @retval 0 Equal * @retval 0 Equal
* @retval !=0 Not equal, see man memcmp * @retval !=0 Not equal, see man memcmp
* Should really be netsnmp lib function, but cant find any? * Should really be netsnmp lib function, but cant find any?
*/ */
int int
@ -268,6 +269,7 @@ oid_eq(const oid *objid0,
} }
/*! Append a second OID to a first /*! Append a second OID to a first
*
* @param[in,out] objid0 First OID vector * @param[in,out] objid0 First OID vector
* @param[in,out] objid0len Length of first OID vector * @param[in,out] objid0len Length of first OID vector
* @param[in] objid1 Second OID vector * @param[in] objid1 Second OID vector
@ -295,6 +297,7 @@ oid_append(const oid *objid0,
} }
/*! Print objid to file /*! Print objid to file
*
* @see fprint_objid but prints symbolic * @see fprint_objid but prints symbolic
*/ */
int int
@ -359,7 +362,7 @@ snmp_yang_type_get(yang_stmt *ys,
} }
if (yang_path_arg(ys, yang_argument_get(ypath), &yref) < 0) if (yang_path_arg(ys, yang_argument_get(ypath), &yref) < 0)
goto done; goto done;
if (yref == NULL){ if (yref == NULL){
clicon_err(OE_YANG, 0, "No referred YANG node found for leafref path %s", yang_argument_get(ypath)); clicon_err(OE_YANG, 0, "No referred YANG node found for leafref path %s", yang_argument_get(ypath));
goto done; goto done;
} }
@ -401,7 +404,7 @@ snmp_yang_type_get(yang_stmt *ys,
* @param[out] exist The extension exists. * @param[out] exist The extension exists.
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free * @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free
* @retval 0 OK: Look in exist and value for return value * @retval 0 OK: Look in exist and value for return value
* @retval -1 Error * @retval -1 Error
* *
* @note This optimizatoin may not work if the unknown statements are augmented in ys. * @note This optimizatoin may not work if the unknown statements are augmented in ys.
* @see yang_extension_value for the generic function * @see yang_extension_value for the generic function
@ -443,6 +446,7 @@ yang_extension_value_opt(yang_stmt *ys,
} }
/*! Given a YANG node, return SMIv2 oid extension as OID /*! Given a YANG node, return SMIv2 oid extension as OID
*
* @param[in] yn Yang node * @param[in] yn Yang node
* @param[out] objid OID vector, assume allocated with MAX_OID_LEN > oidlen * @param[out] objid OID vector, assume allocated with MAX_OID_LEN > oidlen
* @param[out] objidlen Length of OID vector on return * @param[out] objidlen Length of OID vector on return
@ -461,7 +465,7 @@ yangext_oid_get(yang_stmt *yn,
int exist = 0; int exist = 0;
char *oidstr = NULL; char *oidstr = NULL;
yang_stmt *yref = NULL; yang_stmt *yref = NULL;
if (yang_keyword_get(yn) == Y_LEAF){ if (yang_keyword_get(yn) == Y_LEAF){
if (snmp_yang_type_get(yn, &yref, NULL, NULL, NULL) < 0) if (snmp_yang_type_get(yn, &yref, NULL, NULL, NULL) < 0)
goto done; goto done;
@ -472,7 +476,7 @@ yangext_oid_get(yang_stmt *yn,
if (yang_extension_value_opt(yref, "smiv2:oid", &exist, &oidstr) < 0) if (yang_extension_value_opt(yref, "smiv2:oid", &exist, &oidstr) < 0)
goto done; goto done;
if (exist == 0 || oidstr == NULL){ if (exist == 0 || oidstr == NULL){
clicon_debug(1, "OID not found as SMIv2 yang extension of %s", yang_argument_get(yref)); clixon_debug(CLIXON_DBG_DEFAULT, "OID not found as SMIv2 yang extension of %s", yang_argument_get(yref));
goto fail; goto fail;
} }
if (snmp_parse_oid(oidstr, objid, objidlen) == NULL){ if (snmp_parse_oid(oidstr, objid, objidlen) == NULL){
@ -490,22 +494,23 @@ yangext_oid_get(yang_stmt *yn,
} }
/*! Given a YANG node, return 1 if leaf has oid directive in it, otherwise 0 /*! Given a YANG node, return 1 if leaf has oid directive in it, otherwise 0
*
* @param[in] yn Yang node * @param[in] yn Yang node
* @retval 1 found * @retval 1 found
* @retval 0 not found * @retval 0 not found
*/ */
int int
yangext_is_oid_exist(yang_stmt *yn) { yangext_is_oid_exist(yang_stmt *yn)
{
int exist = 0; int exist = 0;
char *oidstr = NULL; char *oidstr = NULL;
if ((yang_keyword_get(yn) != Y_LEAF) || if ((yang_keyword_get(yn) != Y_LEAF) ||
(yang_extension_value_opt(yn, "smiv2:oid", &exist, &oidstr) < 0) || (yang_extension_value_opt(yn, "smiv2:oid", &exist, &oidstr) < 0) ||
(exist == 0) || (exist == 0) ||
(oidstr == NULL)) { (oidstr == NULL)) {
return 0; return 0;
} }
else { else {
return 1; return 1;
} }
@ -513,6 +518,7 @@ yangext_is_oid_exist(yang_stmt *yn) {
/*! Duplicate clixon snmp handler struct /*! Duplicate clixon snmp handler struct
*
* Use signature of libnetsnmp data_clone field of netsnmp_mib_handler in agent_handler.h * Use signature of libnetsnmp data_clone field of netsnmp_mib_handler in agent_handler.h
* @param[in] arg * @param[in] arg
*/ */
@ -538,6 +544,7 @@ snmp_handle_clone(void *arg)
} }
/*! Free clixon snmp handler struct /*! Free clixon snmp handler struct
*
* Use signature of libnetsnmp data_free field of netsnmp_mib_handler in agent_handler.h * Use signature of libnetsnmp data_free field of netsnmp_mib_handler in agent_handler.h
* @param[in] arg * @param[in] arg
*/ */
@ -564,8 +571,8 @@ snmp_handle_free(void *arg)
* @param[in] ys YANG leaf node * @param[in] ys YANG leaf node
* @param[out] asn1_type ASN.1 type id * @param[out] asn1_type ASN.1 type id
* @param[in] extended Special case clixon extended types used in xml<->asn1 data conversions * @param[in] extended Special case clixon extended types used in xml<->asn1 data conversions
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @see type_yang2snmp, yang only * @see type_yang2snmp, yang only
* @note there are some special cases where extended clixon asn1-types are used to convey info * @note there are some special cases where extended clixon asn1-types are used to convey info
* to type_snmpstr2val, these types are prefixed with CLIXON_ASN_ * to type_snmpstr2val, these types are prefixed with CLIXON_ASN_
@ -602,7 +609,7 @@ type_yang2asn1(yang_stmt *ys,
char *display_hint = NULL; char *display_hint = NULL;
yrp = yang_parent_get(yrestype); yrp = yang_parent_get(yrestype);
if (yang_extension_value_opt(yrp, "smiv2:display-hint", NULL, &display_hint) < 0) if (yang_extension_value_opt(yrp, "smiv2:display-hint", NULL, &display_hint) < 0)
goto done; goto done;
/* RFC2578/2579 but maybe all strings with display-hint should use this, eg exist>0? */ /* RFC2578/2579 but maybe all strings with display-hint should use this, eg exist>0? */
if (display_hint && if (display_hint &&
@ -628,7 +635,7 @@ type_yang2asn1(yang_stmt *ys,
* @param[out] valstr Clixon/yang/xml string value, free after use) * @param[out] valstr Clixon/yang/xml string value, free after use)
* @retval 1 OK, and valstr set * @retval 1 OK, and valstr set
* @retval 0 Invalid value or type * @retval 0 Invalid value or type
* @retval -1 Error * @retval -1 Error
* @see type_xml2snmp for snmpget * @see type_xml2snmp for snmpget
*/ */
int int
@ -648,7 +655,7 @@ type_snmp2xml(yang_stmt *ys,
yang_stmt *yrestype = NULL; yang_stmt *yrestype = NULL;
int ret; int ret;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (valstr == NULL){ if (valstr == NULL){
clicon_err(OE_UNIX, EINVAL, "valstr is NULL"); clicon_err(OE_UNIX, EINVAL, "valstr is NULL");
goto done; goto done;
@ -668,7 +675,7 @@ type_snmp2xml(yang_stmt *ys,
cvtype = cv_str2type(cvstr); cvtype = cv_str2type(cvstr);
if ((cv = cv_new(cvtype)) == NULL){ if ((cv = cv_new(cvtype)) == NULL){
clicon_err(OE_UNIX, errno, "cv_new"); clicon_err(OE_UNIX, errno, "cv_new");
goto done; goto done;
} }
switch (*asn1type){ switch (*asn1type){
case CLIXON_ASN_ROWSTATUS: case CLIXON_ASN_ROWSTATUS:
@ -706,7 +713,7 @@ type_snmp2xml(yang_stmt *ys,
break; break;
case ASN_IPADDRESS:{ case ASN_IPADDRESS:{
struct in_addr addr; struct in_addr addr;
memcpy(&addr.s_addr, requestvb->val.string, 4); memcpy(&addr.s_addr, requestvb->val.string, 4);
cv_string_set(cv, inet_ntoa(addr)); cv_string_set(cv, inet_ntoa(addr));
break; break;
} }
@ -716,7 +723,7 @@ type_snmp2xml(yang_stmt *ys,
break; break;
case CLIXON_ASN_PHYS_ADDR: case CLIXON_ASN_PHYS_ADDR:
cv_string_set(cv, ether_ntoa((const struct ether_addr *)requestvb->val.string)); cv_string_set(cv, ether_ntoa((const struct ether_addr *)requestvb->val.string));
*asn1type = ASN_OCTET_STR; *asn1type = ASN_OCTET_STR;
break; break;
case ASN_OCTET_STR: // 4 case ASN_OCTET_STR: // 4
cv_string_set(cv, (char*)requestvb->val.string); cv_string_set(cv, (char*)requestvb->val.string);
@ -732,7 +739,7 @@ type_snmp2xml(yang_stmt *ys,
} }
default: default:
assert(0); // XXX assert(0); // XXX
clicon_debug(1, "%s %s not supported", __FUNCTION__, cv_type2str(cvtype)); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s not supported", __FUNCTION__, cv_type2str(cvtype));
if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_request_set_error(request, SNMP_ERR_WRONGTYPE)) != SNMPERR_SUCCESS){
clicon_err(OE_SNMP, ret, "netsnmp_request_set_error"); clicon_err(OE_SNMP, ret, "netsnmp_request_set_error");
goto done; goto done;
@ -746,7 +753,7 @@ type_snmp2xml(yang_stmt *ys,
} }
retval = 1; retval = 1;
done: done:
clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval);
if (origtype) if (origtype)
free(origtype); free(origtype);
if (cv) if (cv)
@ -766,7 +773,7 @@ type_snmp2xml(yang_stmt *ys,
* @param[out] xmlstr1 XML string ready for translation * @param[out] xmlstr1 XML string ready for translation
* @retval 1 OK * @retval 1 OK
* @retval 0 Invalid type * @retval 0 Invalid type
* @retval -1 Error * @retval -1 Error
* @see type_snmp2xml for snmpset * @see type_snmp2xml for snmpset
*/ */
int int
@ -793,7 +800,7 @@ type_xml2snmp_pre(char *xmlstr0,
if ((ret = yang_enum2valstr(yrestype, xmlstr0, &str)) < 0) if ((ret = yang_enum2valstr(yrestype, xmlstr0, &str)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug(1, "Invalid enum valstr %s", xmlstr0); clixon_debug(CLIXON_DBG_DEFAULT, "Invalid enum valstr %s", xmlstr0);
goto fail; goto fail;
} }
} }
@ -802,7 +809,7 @@ type_xml2snmp_pre(char *xmlstr0,
* 1) there is no code for ASN_BOOLEAN and * 1) there is no code for ASN_BOOLEAN and
* 2) Truthvalue actually translates to enum true(1)/false(2) * 2) Truthvalue actually translates to enum true(1)/false(2)
*/ */
else if (strcmp(restype, "boolean") == 0){ else if (strcmp(restype, "boolean") == 0){
if (strcmp(xmlstr0, "false")==0) if (strcmp(xmlstr0, "false")==0)
str = "2"; str = "2";
else else
@ -819,7 +826,7 @@ type_xml2snmp_pre(char *xmlstr0,
if ((ret = parse_dec64(xmlstr0, cv_dec64_n_get(cv), &num, NULL)) < 0) if ((ret = parse_dec64(xmlstr0, cv_dec64_n_get(cv), &num, NULL)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug(1, "Invalid decimal64 valstr %s", xmlstr0); clixon_debug(CLIXON_DBG_DEFAULT, "Invalid decimal64 valstr %s", xmlstr0);
goto fail; goto fail;
} }
cv_dec64_i_set(cv, num); cv_dec64_i_set(cv, num);
@ -835,7 +842,7 @@ type_xml2snmp_pre(char *xmlstr0,
} }
retval = 1; retval = 1;
done: done:
clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
return retval; return retval;
@ -904,7 +911,7 @@ type_xml2snmp(char *snmpstr,
oid oid1[MAX_OID_LEN] = {0,}; oid oid1[MAX_OID_LEN] = {0,};
size_t sz1 = MAX_OID_LEN; size_t sz1 = MAX_OID_LEN;
if (snmp_parse_oid(snmpstr, oid1, &sz1) == NULL){ if (snmp_parse_oid(snmpstr, oid1, &sz1) == NULL){
clicon_debug(1, "Failed to parse OID %s", snmpstr); clixon_debug(CLIXON_DBG_DEFAULT, "Failed to parse OID %s", snmpstr);
goto fail; goto fail;
} }
*snmplen = sizeof(oid)*sz1; *snmplen = sizeof(oid)*sz1;
@ -960,7 +967,7 @@ type_xml2snmp(char *snmpstr,
} }
memset(*snmpval, 0, *snmplen + 1); memset(*snmpval, 0, *snmplen + 1);
if ((eaddr = ether_aton(snmpstr)) == NULL){ if ((eaddr = ether_aton(snmpstr)) == NULL){
clicon_debug(1, "ether_aton(%s)", snmpstr); clixon_debug(CLIXON_DBG_DEFAULT, "ether_aton(%s)", snmpstr);
goto fail; goto fail;
} }
memcpy(*snmpval, eaddr, sizeof(*eaddr)); memcpy(*snmpval, eaddr, sizeof(*eaddr));
@ -980,7 +987,7 @@ type_xml2snmp(char *snmpstr,
} }
retval = 1; retval = 1;
done: done:
clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval); clixon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval);
return retval; return retval;
fail: fail:
retval = 0; retval = 0;
@ -988,6 +995,7 @@ type_xml2snmp(char *snmpstr,
} }
/*! Construct an xpath from yang statement, internal fn using cb /*! Construct an xpath from yang statement, internal fn using cb
*
* Recursively construct it to the top. * Recursively construct it to the top.
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] keyvec Cvec of key values * @param[in] keyvec Cvec of key values
@ -995,9 +1003,9 @@ type_xml2snmp(char *snmpstr,
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @see yang2xpath * @see yang2xpath
*/ */
static int static int
snmp_yang2xpath_cb(yang_stmt *ys, snmp_yang2xpath_cb(yang_stmt *ys,
cvec *keyvec, cvec *keyvec,
cbuf *cb) cbuf *cb)
{ {
@ -1006,13 +1014,13 @@ snmp_yang2xpath_cb(yang_stmt *ys,
cvec *cvk = NULL; /* vector of index keys */ cvec *cvk = NULL; /* vector of index keys */
int retval = -1; int retval = -1;
char *prefix = NULL; char *prefix = NULL;
if ((yp = yang_parent_get(ys)) == NULL){ if ((yp = yang_parent_get(ys)) == NULL){
clicon_err(OE_YANG, EINVAL, "yang expected parent %s", yang_argument_get(ys)); clicon_err(OE_YANG, EINVAL, "yang expected parent %s", yang_argument_get(ys));
goto done; goto done;
} }
if (yp != NULL && /* XXX rm */ if (yp != NULL && /* XXX rm */
yang_keyword_get(yp) != Y_MODULE && yang_keyword_get(yp) != Y_MODULE &&
yang_keyword_get(yp) != Y_SUBMODULE){ yang_keyword_get(yp) != Y_SUBMODULE){
if (snmp_yang2xpath_cb(yp, keyvec, cb) < 0) /* recursive call */ if (snmp_yang2xpath_cb(yp, keyvec, cb) < 0) /* recursive call */
goto done; goto done;
@ -1053,16 +1061,17 @@ snmp_yang2xpath_cb(yang_stmt *ys,
} }
/*! Construct an xpath from yang statement, limited to SNMP table translations /*! Construct an xpath from yang statement, limited to SNMP table translations
*
* Recursively construct it to the top. * Recursively construct it to the top.
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] keyvec Cvec of key values * @param[in] keyvec Cvec of key values
* @param[out] xpath Malloced xpath string, use free() after use * @param[out] xpath Malloced xpath string, use free() after use
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @note * @note
* 1. This should really be in a core .c file, like clixon_yang, BUT * 1. This should really be in a core .c file, like clixon_yang, BUT
* 2. It is far from complete so maybe keep it here as a special case * 2. It is far from complete so maybe keep it here as a special case
*/ */
int int
snmp_yang2xpath(yang_stmt *ys, snmp_yang2xpath(yang_stmt *ys,
cvec *keyvec, cvec *keyvec,
@ -1089,18 +1098,21 @@ snmp_yang2xpath(yang_stmt *ys,
} }
/*! Translate from xml body string to SMI OID representation /*! Translate from xml body string to SMI OID representation
*
* For ints this is one to one, eg 42 -> 42 * For ints this is one to one, eg 42 -> 42
* But for eg strings this is more complex, eg foo -> 3.6.22.22 (or something,...) * But for eg strings this is more complex, eg foo -> 3.6.22.22 (or something,...)
* @param[in] str XML body string * @param[in] str XML body string
* @param[in] yi Yang statement * @param[in] yi Yang statement
* @param[out] objid OID vector * @param[out] objid OID vector
* @param[out] objidlen Length of OID vector * @param[out] objidlen Length of OID vector
* @retval 0 OK
* @retval -1 Error
*/ */
int int
snmp_str2oid(char *str, snmp_str2oid(char *str,
yang_stmt *yi, yang_stmt *yi,
oid *objid, oid *objid,
size_t *objidlen) size_t *objidlen)
{ {
int retval = -1; int retval = -1;
int asn1_type; int asn1_type;
@ -1135,12 +1147,15 @@ snmp_str2oid(char *str,
} }
/*! Translate from SMI OID representation to name /*! Translate from SMI OID representation to name
*
* For ints this is one to one, eg 42 -> 42 * For ints this is one to one, eg 42 -> 42
* But for eg strings this is more complex, eg foo -> 3.6.22.22 (or something,...) * But for eg strings this is more complex, eg foo -> 3.6.22.22 (or something,...)
* @param[in,out] oidi ObjID vector * @param[in,out] oidi ObjID vector
* @param[in,out] oidilen Length of ObjID vector * @param[in,out] oidilen Length of ObjID vector
* @param[in] yk Yang statement of key * @param[in] yk Yang statement of key
* @param[out] cv CLIgen variable string notation as "x.y.z" * @param[out] cv CLIgen variable string notation as "x.y.z"
* @retval 0 OK
* @retval -1 Error
* @see rfc2578 Section 7.7 * @see rfc2578 Section 7.7
*/ */
int int
@ -1223,7 +1238,7 @@ clixon_snmp_err_cb(void *handle,
{ {
const char *errstr; const char *errstr;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (suberr < 0){ if (suberr < 0){
if (suberr < -CLIXON_ERR_SNMP_MIB){ if (suberr < -CLIXON_ERR_SNMP_MIB){
switch (suberr+CLIXON_ERR_SNMP_MIB){ switch (suberr+CLIXON_ERR_SNMP_MIB){
@ -1262,9 +1277,9 @@ clixon_snmp_err_cb(void *handle,
* @param[in] cvk_name Vector of list keys * @param[in] cvk_name Vector of list keys
* @param[out] cvk_val Vector of XML key values * @param[out] cvk_val Vector of XML key values
* @param[out] objidk OID key part, to be appended to node OID * @param[out] objidk OID key part, to be appended to node OID
* @retval -1 Error
* @retval 0 Invalid (not all indexes present)
* @retval 1 OK * @retval 1 OK
* @retval 0 Invalid (not all indexes present)
* @retval -1 Error
* Both cvk_val and cvk_oid can be re-used in successive calls but need to be freed w cvec_free after use * Both cvk_val and cvk_oid can be re-used in successive calls but need to be freed w cvec_free after use
*/ */
int int
@ -1281,7 +1296,7 @@ snmp_xmlkey2val_oid(cxobj *xentry,
cg_var *cv0; cg_var *cv0;
oid objid[MAX_OID_LEN] = {0,}; oid objid[MAX_OID_LEN] = {0,};
size_t objidlen = MAX_OID_LEN; size_t objidlen = MAX_OID_LEN;
*objidklen = 0; *objidklen = 0;
if (cvk_val){ if (cvk_val){
if (*cvk_val){ if (*cvk_val){
@ -1297,11 +1312,11 @@ snmp_xmlkey2val_oid(cxobj *xentry,
} }
} }
for (i=0; i<cvec_len(cvk_name); i++){ for (i=0; i<cvec_len(cvk_name); i++){
cv0 = cvec_i(cvk_name, i); cv0 = cvec_i(cvk_name, i);
if ((xi = xml_find_type(xentry, NULL, cv_string_get(cv0), CX_ELMNT)) == NULL) if ((xi = xml_find_type(xentry, NULL, cv_string_get(cv0), CX_ELMNT)) == NULL)
break; break;
if (cvk_val){ if (cvk_val){
cv = cvec_i(*cvk_val, i); cv = cvec_i(*cvk_val, i);
if (cv_string_set(cv, xml_body(xi)) < 0){ if (cv_string_set(cv, xml_body(xi)) < 0){
clicon_err(OE_UNIX, errno, "cv_string_set"); clicon_err(OE_UNIX, errno, "cv_string_set");
goto done; goto done;
@ -1326,6 +1341,7 @@ snmp_xmlkey2val_oid(cxobj *xentry,
* Peeks into internal lib global variables, may be sensitive to library change * Peeks into internal lib global variables, may be sensitive to library change
*/ */
/*! Check if netsnmp is connected /*! Check if netsnmp is connected
*
* @retval 1 yes, running * @retval 1 yes, running
* @retval 0 No, not running * @retval 0 No, not running
* XXX: this peeks into the "main_session" global variable in agent/snmp_agent.c * XXX: this peeks into the "main_session" global variable in agent/snmp_agent.c
@ -1335,11 +1351,12 @@ int
clixon_snmp_api_agent_check(void) clixon_snmp_api_agent_check(void)
{ {
extern netsnmp_session *main_session; extern netsnmp_session *main_session;
return (main_session != NULL) ? 1 : 0; return (main_session != NULL) ? 1 : 0;
} }
/*! Cleanup remaining libnetsnmb memory /*! Cleanup remaining libnetsnmb memory
*
* XXX: this peeks into the "tclist" global variable in snmplib/parse.c * XXX: this peeks into the "tclist" global variable in snmplib/parse.c
* Tried to find API function but failed * Tried to find API function but failed
*/ */
@ -1347,19 +1364,20 @@ int
clixon_snmp_api_agent_cleanup(void) clixon_snmp_api_agent_cleanup(void)
{ {
extern void *tclist; extern void *tclist;
if (tclist) if (tclist)
free(tclist); free(tclist);
return 0; return 0;
} }
/*! See if oid is registered /*! See if oid is registered
*
* This is good enough for add, * This is good enough for add,
* But for delete a more advanced function is needed * But for delete a more advanced function is needed
* @see netsnmp_subtree_load * @see netsnmp_subtree_load
* @retval -1 Error
* @retval 0 Not found
* @retval 1 Found * @retval 1 Found
* @retval 0 Not found
* @retval -1 Error
*/ */
int int
clixon_snmp_api_oid_find(oid *oid0, clixon_snmp_api_oid_find(oid *oid0,
@ -1367,7 +1385,7 @@ clixon_snmp_api_oid_find(oid *oid0,
{ {
int retval = -1; int retval = -1;
netsnmp_subtree *tree1 = NULL; netsnmp_subtree *tree1 = NULL;
if ((tree1 = netsnmp_subtree_find(oid0, oid0len, NULL, "")) != NULL && if ((tree1 = netsnmp_subtree_find(oid0, oid0len, NULL, "")) != NULL &&
oid_eq(oid0, oid0len, tree1->name_a, tree1->namelen)==0){ oid_eq(oid0, oid0len, tree1->name_a, tree1->namelen)==0){
retval = 1; retval = 1;

View file

@ -57,7 +57,7 @@ extern "C" {
#define CLIXON_ASN_EXTRAS 253 /* Special case clixon address >= this */ #define CLIXON_ASN_EXTRAS 253 /* Special case clixon address >= this */
#define CLIXON_ASN_PHYS_ADDR 253 /* Special case phy-address */ #define CLIXON_ASN_PHYS_ADDR 253 /* Special case phy-address */
#define CLIXON_ASN_FIXED_STRING 254 /* RFC2578 Sec 7.7: String-valued, fixed-length */ #define CLIXON_ASN_FIXED_STRING 254 /* RFC2578 Sec 7.7: String-valued, fixed-length */
#define CLIXON_ASN_ROWSTATUS 255 #define CLIXON_ASN_ROWSTATUS 255
/* /*
* Types * Types
@ -70,10 +70,10 @@ struct clixon_snmp_handle {
oid sh_oid[MAX_OID_LEN]; /* OID of registered table (list) */ oid sh_oid[MAX_OID_LEN]; /* OID of registered table (list) */
size_t sh_oidlen; size_t sh_oidlen;
oid sh_oid2[MAX_OID_LEN]; /* OID of registered container */ oid sh_oid2[MAX_OID_LEN]; /* OID of registered container */
size_t sh_oid2len; size_t sh_oid2len;
char *sh_default; /* MIB default value leaf only */ char *sh_default; /* MIB default value leaf only */
cvec *sh_cvk_orig; /* Index/Key variable values (original) */ cvec *sh_cvk_orig; /* Index/Key variable values (original) */
netsnmp_table_registration_info *sh_table_info; /* To mimic table-handler in libnetsnmp code netsnmp_table_registration_info *sh_table_info; /* To mimic table-handler in libnetsnmp code
* save only to free properly */ * save only to free properly */
}; };
typedef struct clixon_snmp_handle clixon_snmp_handle; typedef struct clixon_snmp_handle clixon_snmp_handle;

View file

@ -74,7 +74,7 @@
/* Forward */ /* Forward */
static int clixon_snmp_input_cb(int s, void *arg); static int clixon_snmp_input_cb(int s, void *arg);
/*! Return (hardcoded) pid file /*! Return (hardcoded) pid file
*/ */
static char* static char*
@ -84,22 +84,24 @@ clicon_snmp_pidfile(clicon_handle h)
} }
/*! Signal terminates process /*! Signal terminates process
*
* Just set exit flag for proper exit in event loop * Just set exit flag for proper exit in event loop
*/ */
static void static void
clixon_snmp_sig_term(int arg) clixon_snmp_sig_term(int arg)
{ {
clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d", clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d",
__PROGRAM__, __FUNCTION__, getpid(), arg); __PROGRAM__, __FUNCTION__, getpid(), arg);
/* This should ensure no more accepts or incoming packets are processed because next time eventloop /* This should ensure no more accepts or incoming packets are processed because next time eventloop
* is entered, it will terminate. * is entered, it will terminate.
* However there may be a case of sockets closing rather abruptly for clients * However there may be a case of sockets closing rather abruptly for clients
*/ */
clixon_exit_set(1); clixon_exit_set(1);
} }
/*! Clean and close all state of netconf process (but dont exit). /*! Clean and close all state of netconf process (but dont exit).
* Cannot use h after this *
* Cannot use h after this
* @param[in] h Clixon handle * @param[in] h Clixon handle
*/ */
static int static int
@ -139,10 +141,12 @@ snmp_terminate(clicon_handle h)
/*! Get which sockets are used from SNMP API, the register single sockets into clixon event system /*! Get which sockets are used from SNMP API, the register single sockets into clixon event system
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] register if 1 register snmp sockets with event handler. If 0 close and unregister * @param[in] register If 1 register snmp sockets with event handler. If 0 close and unregister
* @retval 0 OK
* @retval -1 Error
* This is a workaround for netsnmps API usiing fdset:s, instead an fdset is created before calling * This is a workaround for netsnmps API usiing fdset:s, instead an fdset is created before calling
* the snmp api * the snmp api
* if you use select(), see snmp_select_info() in snmp_api(3) * if you use select(), see snmp_select_info() in snmp_api(3)
* snmp_select_info(int *numfds, fd_set *fdset, struct timeval *timeout, int *block) * snmp_select_info(int *numfds, fd_set *fdset, struct timeval *timeout, int *block)
* @see clixon_snmp_input_cb * @see clixon_snmp_input_cb
*/ */
@ -166,7 +170,7 @@ clixon_snmp_fdset_register(clicon_handle h,
/* eg 4, 6, 8 */ /* eg 4, 6, 8 */
for (s=0; s<numfds; s++){ for (s=0; s<numfds; s++){
if (FD_ISSET(s, &readfds)){ if (FD_ISSET(s, &readfds)){
clicon_debug(1, "%s %d", __FUNCTION__, s); clixon_debug(CLIXON_DBG_DEFAULT, "%s %d", __FUNCTION__, s);
if (regfd){ if (regfd){
if (clixon_event_reg_fd(s, clixon_snmp_input_cb, h, "snmp socket") < 0) if (clixon_event_reg_fd(s, clixon_snmp_input_cb, h, "snmp socket") < 0)
goto done; goto done;
@ -183,14 +187,17 @@ clixon_snmp_fdset_register(clicon_handle h,
return retval; return retval;
} }
/*! Callback for single socket /*! Callback for single socket
*
* This is a workaround for netsnmps API usiing fdset:s, instead an fdset is created before calling * This is a workaround for netsnmps API usiing fdset:s, instead an fdset is created before calling
* the snmp api * the snmp api
* @param[in] s Read socket * @param[in] s Read socket
* @param[in] arg Clixon handle * @param[in] arg Clixon handle
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
clixon_snmp_input_cb(int s, clixon_snmp_input_cb(int s,
void *arg) void *arg)
{ {
int retval = -1; int retval = -1;
@ -198,7 +205,7 @@ clixon_snmp_input_cb(int s,
clicon_handle h = (clicon_handle)arg; clicon_handle h = (clicon_handle)arg;
int ret; int ret;
clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, s); clixon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, s);
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(s, &readfds); FD_SET(s, &readfds);
(void)snmp_read(&readfds); (void)snmp_read(&readfds);
@ -232,8 +239,11 @@ clixon_snmp_input_cb(int s,
} }
/*! Init netsnmp agent connection /*! Init netsnmp agent connection
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] logdst Log destination, see clixon_log.h * @param[in] logdst Log destination, see clixon_log.h
* @retval 0 OK
* @retval -1 Error
* @see snmp_terminate * @see snmp_terminate
*/ */
static int static int
@ -243,7 +253,7 @@ clixon_snmp_init_subagent(clicon_handle h,
int retval = -1; int retval = -1;
char *sockpath = NULL; char *sockpath = NULL;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (logdst == CLICON_LOG_SYSLOG) if (logdst == CLICON_LOG_SYSLOG)
snmp_enable_calllog(); snmp_enable_calllog();
else else
@ -253,11 +263,11 @@ clixon_snmp_init_subagent(clicon_handle h,
/* don't load config and don't load/save persistent file */ /* don't load config and don't load/save persistent file */
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
/* don't load persistent file */ /* don't load persistent file */
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD, 1);
/* don't save persistent file */ /* don't save persistent file */
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_SAVE, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_SAVE, 1);
if (clicon_debug_get()) if (clixon_debug_get())
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_VERBOSE, 1); netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_VERBOSE, 1);
if ((sockpath = clicon_option_str(h, "CLICON_SNMP_AGENT_SOCK")) == NULL){ if ((sockpath = clicon_option_str(h, "CLICON_SNMP_AGENT_SOCK")) == NULL){
@ -277,7 +287,6 @@ clixon_snmp_init_subagent(clicon_handle h,
clicon_err(OE_DAEMON, 0, "Connection to SNMP agent failed"); clicon_err(OE_DAEMON, 0, "Connection to SNMP agent failed");
goto done; goto done;
} }
if (set_signal(SIGTERM, clixon_snmp_sig_term, NULL) < 0){ if (set_signal(SIGTERM, clixon_snmp_sig_term, NULL) < 0){
clicon_err(OE_DAEMON, errno, "Setting signal"); clicon_err(OE_DAEMON, errno, "Setting signal");
goto done; goto done;
@ -299,6 +308,7 @@ clixon_snmp_init_subagent(clicon_handle h,
} }
/*! Usage help routine /*! Usage help routine
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] argv0 command line * @param[in] argv0 command line
*/ */
@ -344,12 +354,12 @@ main(int argc,
int zap = 0; int zap = 0;
int config_dump = 0; int config_dump = 0;
enum format_enum config_dump_format = FORMAT_XML; enum format_enum config_dump_format = FORMAT_XML;
/* Create handle */ /* Create handle */
if ((h = clicon_handle_init()) == NULL) if ((h = clicon_handle_init()) == NULL)
return -1; return -1;
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
/* Set username to clixon handle. Use in all communication to backend */ /* Set username to clixon handle. Use in all communication to backend */
if ((pw = getpwuid(getuid())) == NULL){ if ((pw = getpwuid(getuid())) == NULL){
@ -382,11 +392,11 @@ main(int argc,
break; break;
} }
/* /*
* Logs, error and debug to stderr or syslog, set debug level * Logs, error and debug to stderr or syslog, set debug level
*/ */
clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst); clicon_log_init(__PROGRAM__, dbg?LOG_DEBUG:LOG_INFO, logdst);
clicon_debug_init(dbg, NULL); clixon_debug_init(dbg, NULL);
/* This is netsnmplib debugging which is quite extensive + only if compiled w debug */ /* This is netsnmplib debugging which is quite extensive + only if compiled w debug */
if (dbg > 1) if (dbg > 1)
snmp_set_do_debugging(1); snmp_set_do_debugging(1);
@ -398,13 +408,10 @@ main(int argc,
clixon_snmp_err_cb /* log fn */ clixon_snmp_err_cb /* log fn */
) < 0) ) < 0)
goto done; goto done;
yang_init(h); yang_init(h);
/* Find, read and parse configfile */ /* Find, read and parse configfile */
if (clicon_options_main(h) < 0) if (clicon_options_main(h) < 0)
goto done; goto done;
/* Now rest of options */ /* Now rest of options */
optind = 1; optind = 1;
opterr = 0; opterr = 0;
@ -455,18 +462,18 @@ main(int argc,
if (pid && pidfile_zapold(pid) < 0) if (pid && pidfile_zapold(pid) < 0)
return -1; return -1;
if (lstat(pidfile, &st) == 0) if (lstat(pidfile, &st) == 0)
unlink(pidfile); unlink(pidfile);
snmp_terminate(h); snmp_terminate(h);
exit(0); /* OK */ exit(0); /* OK */
} }
else if (pid){ else if (pid){
clicon_err(OE_DAEMON, 0, "Clixon_snmp daemon already running with pid %d\n(Try killing it with %s -z)", clicon_err(OE_DAEMON, 0, "Clixon_snmp daemon already running with pid %d\n(Try killing it with %s -z)",
pid, argv0); pid, argv0);
return -1; /* goto done deletes pidfile */ return -1; /* goto done deletes pidfile */
} }
/* Here there is either no old process or we have killed it,.. */ /* Here there is either no old process or we have killed it,.. */
if (lstat(pidfile, &st) == 0) if (lstat(pidfile, &st) == 0)
unlink(pidfile); unlink(pidfile);
/* Init cligen buffers */ /* Init cligen buffers */
cligen_buflen = clicon_option_int(h, "CLICON_CLI_BUF_START"); cligen_buflen = clicon_option_int(h, "CLICON_CLI_BUF_START");
@ -488,7 +495,7 @@ main(int argc,
/* Create top-level yang spec and store as option */ /* Create top-level yang spec and store as option */
if ((yspec = yspec_new()) == NULL) if ((yspec = yspec_new()) == NULL)
goto done; goto done;
clicon_dbspec_yang_set(h, yspec); clicon_dbspec_yang_set(h, yspec);
/* Load Yang modules /* Load Yang modules
* 1. Load a yang module as a specific absolute filename */ * 1. Load a yang module as a specific absolute filename */
@ -530,7 +537,7 @@ main(int argc,
goto ok; goto ok;
} }
clicon_option_dump(h, 1); clicon_option_dump(h, 1);
/* Send hello request to backend to get session-id back /* Send hello request to backend to get session-id back
* This is done once at the beginning of the session and then this is * This is done once at the beginning of the session and then this is
* used by the client, even though new TCP sessions are created for * used by the client, even though new TCP sessions are created for
@ -540,7 +547,6 @@ main(int argc,
if (clicon_hello_req(h, "cl:snmp", NULL, &id) < 0) if (clicon_hello_req(h, "cl:snmp", NULL, &id) < 0)
goto done; goto done;
clicon_session_id_set(h, id); clicon_session_id_set(h, id);
/* Init snmp as subagent */ /* Init snmp as subagent */
if (clixon_snmp_init_subagent(h, logdst) < 0) if (clixon_snmp_init_subagent(h, logdst) < 0)
goto done; goto done;

View file

@ -80,6 +80,7 @@
#include "snmp_handler.h" #include "snmp_handler.h"
/*! Parse smiv2 extensions for YANG leaf /*! Parse smiv2 extensions for YANG leaf
*
* Typical leaf: * Typical leaf:
* smiv2:oid "1.3.6.1.4.1.8072.2.1.1"; * smiv2:oid "1.3.6.1.4.1.8072.2.1.1";
* smiv2:max-access "read-write"; * smiv2:max-access "read-write";
@ -143,7 +144,7 @@ mibyang_leaf_register(clicon_handle h,
if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &default_str) < 0) if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &default_str) < 0)
goto done; goto done;
name = yang_argument_get(ys); name = yang_argument_get(ys);
/* Stateless function, just returns ptr */ /* Stateless function, just returns ptr */
if ((handler = netsnmp_create_handler(name, clixon_snmp_scalar_handler)) == NULL){ if ((handler = netsnmp_create_handler(name, clixon_snmp_scalar_handler)) == NULL){
clicon_err(OE_XML, errno, "netsnmp_create_handler"); clicon_err(OE_XML, errno, "netsnmp_create_handler");
goto done; goto done;
@ -167,7 +168,7 @@ mibyang_leaf_register(clicon_handle h,
clicon_err(OE_UNIX, errno, "cvec_dup"); clicon_err(OE_UNIX, errno, "cvec_dup");
goto done; goto done;
} }
/* Stateless function, just returns ptr */ /* Stateless function, just returns ptr */
if ((nhreg = netsnmp_handler_registration_create(name, handler, if ((nhreg = netsnmp_handler_registration_create(name, handler,
oid1, oid1len, oid1, oid1len,
modes)) == NULL){ modes)) == NULL){
@ -180,7 +181,7 @@ mibyang_leaf_register(clicon_handle h,
handler->data_clone = snmp_handle_clone; handler->data_clone = snmp_handle_clone;
handler->data_free = snmp_handle_free; handler->data_free = snmp_handle_free;
/* /*
* XXX: nhreg->agent_data * XXX: nhreg->agent_data
*/ */
if ((ret = netsnmp_register_instance(nhreg)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_register_instance(nhreg)) != SNMPERR_SUCCESS){
@ -189,7 +190,7 @@ mibyang_leaf_register(clicon_handle h,
goto done; goto done;
} }
oid_cbuf(cboid, oid1, oid1len); oid_cbuf(cboid, oid1, oid1len);
clicon_debug(1, "%s register: %s %s", __FUNCTION__, name, cbuf_get(cboid)); clixon_debug(CLIXON_DBG_DEFAULT, "%s register: %s %s", __FUNCTION__, name, cbuf_get(cboid));
ok: ok:
retval = 0; retval = 0;
done: done:
@ -236,7 +237,7 @@ mibyang_table_register(clicon_handle h,
int asn1type; int asn1type;
yang_stmt *ys; yang_stmt *ys;
char *name; char *name;
if ((ys = yang_parent_get(ylist)) == NULL || if ((ys = yang_parent_get(ylist)) == NULL ||
yang_keyword_get(ys) != Y_CONTAINER){ yang_keyword_get(ys) != Y_CONTAINER){
clicon_err(OE_YANG, EINVAL, "ylist parent is not list"); clicon_err(OE_YANG, EINVAL, "ylist parent is not list");
@ -247,7 +248,7 @@ mibyang_table_register(clicon_handle h,
* the original and ifXTable for the augmented. * the original and ifXTable for the augmented.
* But the name does not seem to have semantic significance, so I leave it as is. * But the name does not seem to have semantic significance, so I leave it as is.
*/ */
name = yang_argument_get(ys); name = yang_argument_get(ys);
/* Userdata to pass around in netsmp callbacks /* Userdata to pass around in netsmp callbacks
* XXX: not deallocated * XXX: not deallocated
*/ */
@ -278,7 +279,7 @@ mibyang_table_register(clicon_handle h,
handler->myvoid =(void*)sh; handler->myvoid =(void*)sh;
handler->data_clone = snmp_handle_clone; handler->data_clone = snmp_handle_clone;
handler->data_free = snmp_handle_free; handler->data_free = snmp_handle_free;
/* See netsnmp_register_table_data_set */ /* See netsnmp_register_table_data_set */
if ((table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL){ if ((table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL){
clicon_err(OE_UNIX, errno, "SNMP_MALLOC_TYPEDEF"); clicon_err(OE_UNIX, errno, "SNMP_MALLOC_TYPEDEF");
@ -294,7 +295,7 @@ mibyang_table_register(clicon_handle h,
while ((cvi = cvec_each(cvk, cvi)) != NULL) { while ((cvi = cvec_each(cvk, cvi)) != NULL) {
keyname = cv_string_get(cvi); keyname = cv_string_get(cvi);
if ((yleaf = yang_find(ylist, Y_LEAF, keyname)) == NULL){ if ((yleaf = yang_find(ylist, Y_LEAF, keyname)) == NULL){
clicon_err(OE_XML, 0, "List statement \"%s\" has no key leaf \"%s\"", clicon_err(OE_XML, 0, "List statement \"%s\" has no key leaf \"%s\"",
yang_argument_get(ylist), keyname); yang_argument_get(ylist), keyname);
goto done; goto done;
} }
@ -315,19 +316,18 @@ mibyang_table_register(clicon_handle h,
/* Count columns */ /* Count columns */
yleaf = NULL; yleaf = NULL;
table_info->max_column = 0; table_info->max_column = 0;
while ((yleaf = yn_each(ylist, yleaf)) != NULL) { while ((yleaf = yn_each(ylist, yleaf)) != NULL) {
if ((yang_keyword_get(yleaf) != Y_LEAF) || (ret = yangext_is_oid_exist(yleaf)) != 1) if ((yang_keyword_get(yleaf) != Y_LEAF) || (ret = yangext_is_oid_exist(yleaf)) != 1)
continue; continue;
table_info->max_column++;
table_info->max_column++;
} }
if ((ret = netsnmp_register_table(nhreg, table_info)) != SNMPERR_SUCCESS){ if ((ret = netsnmp_register_table(nhreg, table_info)) != SNMPERR_SUCCESS){
clicon_err(OE_SNMP, ret, "netsnmp_register_table"); clicon_err(OE_SNMP, ret, "netsnmp_register_table");
goto done; goto done;
} }
sh->sh_table_info = table_info; /* Keep to free at exit */ sh->sh_table_info = table_info; /* Keep to free at exit */
clicon_debug(1, "%s register: %s %s", __FUNCTION__, name, oidstr); clixon_debug(CLIXON_DBG_DEFAULT, "%s register: %s %s", __FUNCTION__, name, oidstr);
ok: ok:
retval = 0; retval = 0;
done: done:
@ -375,7 +375,7 @@ mibyang_list_register(clicon_handle h,
goto done; goto done;
if (ret == 0) if (ret == 0)
goto ok; goto ok;
if (mibyang_table_register(h, ylist, if (mibyang_table_register(h, ylist,
oid1, oid1len, oid1, oid1len,
oid2, oid2len, oid2, oid2len,
oidstr) < 0) oidstr) < 0)
@ -446,6 +446,7 @@ mibyang_augment_register(clicon_handle h,
} }
/*! Register table sub-oid:s of existing entries in clixon /*! Register table sub-oid:s of existing entries in clixon
*
* This assumes a table contains a set of keys and a list of leafs only * This assumes a table contains a set of keys and a list of leafs only
* The function makes a query to the datastore and registers all table entries that * The function makes a query to the datastore and registers all table entries that
* currently exists. This means it registers for a static table. If new rows or columns * currently exists. This means it registers for a static table. If new rows or columns
@ -476,8 +477,8 @@ mibyang_table_poll(clicon_handle h,
int ret; int ret;
oid oidk[MAX_OID_LEN] = {0,}; oid oidk[MAX_OID_LEN] = {0,};
size_t oidklen = MAX_OID_LEN; size_t oidklen = MAX_OID_LEN;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if ((ys = yang_parent_get(ylist)) == NULL || if ((ys = yang_parent_get(ylist)) == NULL ||
yang_keyword_get(ys) != Y_CONTAINER){ yang_keyword_get(ys) != Y_CONTAINER){
clicon_err(OE_YANG, EINVAL, "ylist parent is not list"); clicon_err(OE_YANG, EINVAL, "ylist parent is not list");
@ -509,7 +510,7 @@ mibyang_table_poll(clicon_handle h,
while ((xcol = xml_child_each(xrow, xcol, CX_ELMNT)) != NULL) { while ((xcol = xml_child_each(xrow, xcol, CX_ELMNT)) != NULL) {
if ((y = xml_spec(xcol)) == NULL) if ((y = xml_spec(xcol)) == NULL)
continue; continue;
if (mibyang_leaf_register(h, y, cvk_val, oidk, oidklen) < 0) if (mibyang_leaf_register(h, y, cvk_val, oidk, oidklen) < 0)
goto done; goto done;
} }
} }
@ -523,7 +524,7 @@ mibyang_table_poll(clicon_handle h,
if (xt) if (xt)
xml_free(xt); xml_free(xt);
if (nsc) if (nsc)
xml_nsctx_free(nsc); xml_nsctx_free(nsc);
return retval; return retval;
} }
@ -557,8 +558,8 @@ mibyang_traverse(clicon_handle h,
yang_stmt *yp; yang_stmt *yp;
int ret; int ret;
static oid zero_oid = 0; static oid zero_oid = 0;
clicon_debug(1, "%s %s", __FUNCTION__, yang_argument_get(yn)); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s", __FUNCTION__, yang_argument_get(yn));
switch(yang_keyword_get(yn)){ switch(yang_keyword_get(yn)){
case Y_AUGMENT: case Y_AUGMENT:
if (mibyang_augment_register(h, yn) < 0) if (mibyang_augment_register(h, yn) < 0)
@ -588,7 +589,7 @@ mibyang_traverse(clicon_handle h,
ys = NULL; ys = NULL;
while ((ys = yn_each(yn, ys)) != NULL) { while ((ys = yn_each(yn, ys)) != NULL) {
/* augment special case of table */ /* augment special case of table */
if (!yang_schemanode(ys) && yang_keyword_get(ys) != Y_AUGMENT) if (!yang_schemanode(ys) && yang_keyword_get(ys) != Y_AUGMENT)
continue; continue;
if ((ret = mibyang_traverse(h, ys)) < 0) if ((ret = mibyang_traverse(h, ys)) < 0)
goto done; goto done;
@ -601,7 +602,7 @@ mibyang_traverse(clicon_handle h,
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
/*! Init mib-translated yangs and register callbacks by traversing the yang /*! Init mib-translated yangs and register callbacks by traversing the yang
* *
@ -631,7 +632,7 @@ clixon_snmp_traverse_mibyangs(clicon_handle h)
continue; continue;
if ((modname = xml_body(x)) == NULL) if ((modname = xml_body(x)) == NULL)
continue; continue;
clicon_debug(1, "%s %s: \"%s\"", __FUNCTION__, xml_name(x), modname); clixon_debug(CLIXON_DBG_DEFAULT, "%s %s: \"%s\"", __FUNCTION__, xml_name(x), modname);
/* Note, here we assume the Yang is loaded by some other mechanism and /* Note, here we assume the Yang is loaded by some other mechanism and
* error if it not found. * error if it not found.
* Alternatively, that YANG could be loaded. * Alternatively, that YANG could be loaded.

View file

@ -489,7 +489,7 @@ information on added, deleted and changed entries. You access this
information using access functions as defined in clixon_backend_transaction.h information using access functions as defined in clixon_backend_transaction.h
## How do I check what has changed on commit? ## How do I check what has changed on commit?
You use XPATHs on the XML trees in the transaction commit callback. You use XPaths on the XML trees in the transaction commit callback.
Suppose you want to print all added interfaces: Suppose you want to print all added interfaces:
``` ```
cxobj *target = transaction_target(td); # wanted XML tree cxobj *target = transaction_target(td); # wanted XML tree
@ -500,7 +500,7 @@ Suppose you want to print all added interfaces:
You can look for added, deleted and changed entries in this way. You can look for added, deleted and changed entries in this way.
## How do I access the XML tree? ## How do I access the XML tree?
Using XPATH, find and iteration functions defined in the XML library. Example library functions: Using XPath, find and iteration functions defined in the XML library. Example library functions:
``` ```
xml_child_each(), xml_child_each(),
xml_find(), xml_find(),

View file

@ -67,7 +67,7 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
/* These include signatures for plugin and transaction callbacks. */ /* These include signatures for plugin and transaction callbacks. */
#include <clixon/clixon_backend.h> #include <clixon/clixon_backend.h>
/* Command line options to be passed to getopt(3) */ /* Command line options to be passed to getopt(3) */
#define BACKEND_EXAMPLE_OPTS "a:m:M:nrsS:x:iuUtV:" #define BACKEND_EXAMPLE_OPTS "a:m:M:nrsS:x:iuUtV:"
@ -123,7 +123,7 @@ static int _state = 0;
*/ */
static char *_state_file = NULL; static char *_state_file = NULL;
/*! XPath to register for pagination state XML from file, /*! XPath to register for pagination state XML from file,
* *
* if _state is true -- -sS <file> -x <xpath> * if _state is true -- -sS <file> -x <xpath>
* Primarily for testing * Primarily for testing
@ -185,7 +185,7 @@ static int _validate_fail_toggle = 0; /* fail at validate and commit */
static int example_stream_timer_setup(clicon_handle h); static int example_stream_timer_setup(clicon_handle h);
int int
main_begin(clicon_handle h, main_begin(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -196,7 +196,7 @@ main_begin(clicon_handle h,
/*! This is called on validate (and commit). Check validity of candidate /*! This is called on validate (and commit). Check validity of candidate
*/ */
int int
main_validate(clicon_handle h, main_validate(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -213,7 +213,7 @@ main_validate(clicon_handle h,
} }
int int
main_complete(clicon_handle h, main_complete(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -224,7 +224,7 @@ main_complete(clicon_handle h,
/*! This is called on commit. Identify modifications and adjust machine state /*! This is called on commit. Identify modifications and adjust machine state
*/ */
int int
main_commit(clicon_handle h, main_commit(clicon_handle h,
transaction_data td) transaction_data td)
{ {
cxobj *target = transaction_target(td); /* wanted XML tree */ cxobj *target = transaction_target(td); /* wanted XML tree */
@ -251,7 +251,7 @@ main_commit(clicon_handle h,
/* Get all added i/fs */ /* Get all added i/fs */
if (xpath_vec_flag(target, nsc, "//interface", XML_FLAG_ADD, &vec, &len) < 0) if (xpath_vec_flag(target, nsc, "//interface", XML_FLAG_ADD, &vec, &len) < 0)
return -1; return -1;
if (clicon_debug_get()) if (clixon_debug_get())
for (i=0; i<len; i++) /* Loop over added i/fs */ for (i=0; i<len; i++) /* Loop over added i/fs */
xml_print(stdout, vec[i]); /* Print the added interface */ xml_print(stdout, vec[i]); /* Print the added interface */
done: done:
@ -263,7 +263,7 @@ main_commit(clicon_handle h,
} }
int int
main_commit_done(clicon_handle h, main_commit_done(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -272,7 +272,7 @@ main_commit_done(clicon_handle h,
} }
int int
main_revert(clicon_handle h, main_revert(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -281,7 +281,7 @@ main_revert(clicon_handle h,
} }
int int
main_end(clicon_handle h, main_end(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -290,7 +290,7 @@ main_end(clicon_handle h,
} }
int int
main_abort(clicon_handle h, main_abort(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -301,7 +301,7 @@ main_abort(clicon_handle h,
/*! Routing example notification timer handler. Here is where the periodic action is /*! Routing example notification timer handler. Here is where the periodic action is
*/ */
static int static int
example_stream_timer(int fd, example_stream_timer(int fd,
void *arg) void *arg)
{ {
int retval = -1; int retval = -1;
@ -337,8 +337,8 @@ example_stream_timer_setup(clicon_handle h)
* are returned, the <rpc-reply> contains a single <ok/> element defined * are returned, the <rpc-reply> contains a single <ok/> element defined
* in [RFC6241]. * in [RFC6241].
*/ */
static int static int
empty_rpc(clicon_handle h, /* Clicon handle */ empty_rpc(clicon_handle h, /* Clixon handle */
cxobj *xe, /* Request: <rpc><xn></rpc> */ cxobj *xe, /* Request: <rpc><xn></rpc> */
cbuf *cbret, /* Reply eg <rpc-reply>... */ cbuf *cbret, /* Reply eg <rpc-reply>... */
void *arg, /* client_entry */ void *arg, /* client_entry */
@ -352,8 +352,8 @@ empty_rpc(clicon_handle h, /* Clicon handle */
* *
* The RPC returns the incoming parameters * The RPC returns the incoming parameters
*/ */
static int static int
example_rpc(clicon_handle h, /* Clicon handle */ example_rpc(clicon_handle h, /* Clixon handle */
cxobj *xe, /* Request: <rpc><xn></rpc> */ cxobj *xe, /* Request: <rpc><xn></rpc> */
cbuf *cbret, /* Reply eg <rpc-reply>... */ cbuf *cbret, /* Reply eg <rpc-reply>... */
void *arg, /* client_entry */ void *arg, /* client_entry */
@ -394,8 +394,8 @@ example_rpc(clicon_handle h, /* Clicon handle */
/*! This will be called as a hook right after the original system copy-config /*! This will be called as a hook right after the original system copy-config
*/ */
static int static int
example_copy_extra(clicon_handle h, /* Clicon handle */ example_copy_extra(clicon_handle h, /* Clixon handle */
cxobj *xe, /* Request: <rpc><xn></rpc> */ cxobj *xe, /* Request: <rpc><xn></rpc> */
cbuf *cbret, /* Reply eg <rpc-reply>... */ cbuf *cbret, /* Reply eg <rpc-reply>... */
void *arg, /* client_entry */ void *arg, /* client_entry */
@ -413,8 +413,8 @@ example_copy_extra(clicon_handle h, /* Clicon handle */
* *
* @note callback is hardcoded C, while registration is controlled by -- -a option * @note callback is hardcoded C, while registration is controlled by -- -a option
*/ */
static int static int
example_action_reset(clicon_handle h, /* Clicon handle */ example_action_reset(clicon_handle h, /* Clixon handle */
cxobj *xe, /* Request: <rpc><xn></rpc> */ cxobj *xe, /* Request: <rpc><xn></rpc> */
cbuf *cbret, /* Reply eg <rpc-reply>... */ cbuf *cbret, /* Reply eg <rpc-reply>... */
void *arg, /* client_entry */ void *arg, /* client_entry */
@ -434,7 +434,7 @@ example_action_reset(clicon_handle h, /* Clicon handle */
/*! Called to get state data from plugin by programmatically adding state /*! Called to get state data from plugin by programmatically adding state
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] nsc External XML namespace context, or NULL * @param[in] nsc External XML namespace context, or NULL
* @param[in] xpath String with XPATH syntax. or NULL for all * @param[in] xpath String with XPATH syntax. or NULL for all
* @param[out] xstate XML tree, <config/> on entry. * @param[out] xstate XML tree, <config/> on entry.
@ -452,8 +452,8 @@ example_action_reset(clicon_handle h, /* Clicon handle */
* This yang snippet is present in clixon-example.yang for example. * This yang snippet is present in clixon-example.yang for example.
* @see example_statefile where state is read from file and also pagination * @see example_statefile where state is read from file and also pagination
*/ */
int int
example_statedata(clicon_handle h, example_statedata(clicon_handle h,
cvec *nsc, cvec *nsc,
char *xpath, char *xpath,
cxobj *xstate) cxobj *xstate)
@ -539,7 +539,7 @@ example_statedata(clicon_handle h,
* *
* The example shows how to read and parse a state XML file, (which is cached in the -i case). * The example shows how to read and parse a state XML file, (which is cached in the -i case).
* Return the requested xpath / pagination xstate by copying from the parsed state XML file * Return the requested xpath / pagination xstate by copying from the parsed state XML file
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] nsc External XML namespace context, or NULL * @param[in] nsc External XML namespace context, or NULL
* @param[in] xpath String with XPATH syntax. or NULL for all * @param[in] xpath String with XPATH syntax. or NULL for all
* @param[out] xstate XML tree, <config/> on entry. Copy to this * @param[out] xstate XML tree, <config/> on entry. Copy to this
@ -548,8 +548,8 @@ example_statedata(clicon_handle h,
* @see xmldb_get * @see xmldb_get
* @see example_statefile where state is programmatically added * @see example_statefile where state is programmatically added
*/ */
int int
example_statefile(clicon_handle h, example_statefile(clicon_handle h,
cvec *nsc, cvec *nsc,
char *xpath, char *xpath,
cxobj *xstate) cxobj *xstate)
@ -587,8 +587,8 @@ example_statefile(clicon_handle h,
if (_state_file_cached) if (_state_file_cached)
xt = _state_xml_cache; xt = _state_xml_cache;
#ifdef _STATEFILTER #ifdef _STATEFILTER
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0) if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0)
goto done; goto done;
/* Mark elements to copy: /* Mark elements to copy:
* For every node found in x0, mark the tree as changed * For every node found in x0, mark the tree as changed
*/ */
@ -601,7 +601,7 @@ example_statefile(clicon_handle h,
/* Copy the marked elements: /* Copy the marked elements:
* note is yang-aware for copying of keys which means XML must be bound * note is yang-aware for copying of keys which means XML must be bound
*/ */
if (xml_copy_marked(xt, xstate) < 0) if (xml_copy_marked(xt, xstate) < 0)
goto done; goto done;
/* Unmark original tree */ /* Unmark original tree */
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0) if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
@ -610,7 +610,7 @@ example_statefile(clicon_handle h,
if (xml_apply(xstate, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0) if (xml_apply(xstate, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
goto done; goto done;
#else #else
if (xml_copy(xt, xstate) < 0) if (xml_copy(xt, xstate) < 0)
goto done; goto done;
#endif #endif
if (_state_file_cached) if (_state_file_cached)
@ -634,7 +634,7 @@ example_statefile(clicon_handle h,
* @param[in] userargs Per-call user arguments * @param[in] userargs Per-call user arguments
* @param[in] arg Per-path user argument (at register time) * @param[in] arg Per-path user argument (at register time)
*/ */
int int
example_pagination(void *h0, example_pagination(void *h0,
char *xpath, char *xpath,
pagination_data pd, pagination_data pd,
@ -657,16 +657,16 @@ example_pagination(void *h0,
uint32_t upper; uint32_t upper;
int ret; int ret;
cvec *nsc = NULL; cvec *nsc = NULL;
/* If -S is set, then read state data from file */ /* If -S is set, then read state data from file */
if (!_state || !_state_file) if (!_state || !_state_file)
goto ok; goto ok;
locked = pagination_locked(pd); locked = pagination_locked(pd);
offset = pagination_offset(pd); offset = pagination_offset(pd);
limit = pagination_limit(pd); limit = pagination_limit(pd);
xstate = pagination_xstate(pd); xstate = pagination_xstate(pd);
/* Get canonical namespace context */ /* Get canonical namespace context */
if (xml_nsctx_yangspec(yspec, &nsc) < 0) if (xml_nsctx_yangspec(yspec, &nsc) < 0)
goto done; goto done;
@ -687,8 +687,8 @@ example_pagination(void *h0,
} }
if (_state_file_cached) if (_state_file_cached)
xt = _state_xml_cache; xt = _state_xml_cache;
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0) if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0)
goto done; goto done;
lower = offset; lower = offset;
if (limit == 0) if (limit == 0)
upper = xlen; upper = xlen;
@ -732,7 +732,7 @@ example_pagination(void *h0,
free(xvec); free(xvec);
if (nsc) if (nsc)
cvec_free(nsc); cvec_free(nsc);
return retval; return retval;
} }
/*! Lock databse status has changed status /*! Lock databse status has changed status
@ -752,7 +752,7 @@ example_lockdb(clicon_handle h,
{ {
int retval = -1; int retval = -1;
clicon_debug(1, "%s Lock callback: db%s: locked:%d", __FUNCTION__, db, lock); clixon_debug(CLIXON_DBG_DEFAULT, "%s Lock callback: db%s: locked:%d", __FUNCTION__, db, lock);
/* Part of cached pagination example /* Part of cached pagination example
*/ */
if (strcmp(db, "running") == 0 && lock == 0 && if (strcmp(db, "running") == 0 && lock == 0 &&
@ -769,15 +769,15 @@ example_lockdb(clicon_handle h,
} }
/*! Callback for yang extensions example:e4 /*! Callback for yang extensions example:e4
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] yext Yang node of extension * @param[in] yext Yang node of extension
* @param[in] ys Yang node of (unknown) statement belonging to extension * @param[in] ys Yang node of (unknown) statement belonging to extension
* @retval 0 OK, all callbacks executed OK * @retval 0 OK, all callbacks executed OK
* @retval -1 Error in one callback * @retval -1 Error in one callback
*/ */
int int
example_extension(clicon_handle h, example_extension(clicon_handle h,
yang_stmt *yext, yang_stmt *yext,
yang_stmt *ys) yang_stmt *ys)
{ {
@ -787,13 +787,13 @@ example_extension(clicon_handle h,
yang_stmt *ymod; yang_stmt *ymod;
yang_stmt *yc; yang_stmt *yc;
yang_stmt *yn = NULL; yang_stmt *yn = NULL;
ymod = ys_module(yext); ymod = ys_module(yext);
modname = yang_argument_get(ymod); modname = yang_argument_get(ymod);
extname = yang_argument_get(yext); extname = yang_argument_get(yext);
if (strcmp(modname, "example") != 0 || strcmp(extname, "e4") != 0) if (strcmp(modname, "example") != 0 || strcmp(extname, "e4") != 0)
goto ok; goto ok;
clicon_debug(1, "%s Enabled extension:%s:%s", __FUNCTION__, modname, extname); clixon_debug(CLIXON_DBG_DEFAULT, "%s Enabled extension:%s:%s", __FUNCTION__, modname, extname);
if ((yc = yang_find(ys, 0, NULL)) == NULL) if ((yc = yang_find(ys, 0, NULL)) == NULL)
goto ok; goto ok;
if ((yn = ys_dup(yc)) == NULL) if ((yn = ys_dup(yc)) == NULL)
@ -833,7 +833,7 @@ static const map_str2str namespace_map[] = {
* *
* Gets called on startup after initial XML parsing, but before module-specific upgrades * Gets called on startup after initial XML parsing, but before module-specific upgrades
* and before validation. * and before validation.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db Name of datastore, eg "running", "startup" or "tmp" * @param[in] db Name of datastore, eg "running", "startup" or "tmp"
* @param[in] xt XML tree. Upgrade this "in place" * @param[in] xt XML tree. Upgrade this "in place"
* @param[in] msd Info on datastore module-state, if any * @param[in] msd Info on datastore module-state, if any
@ -848,10 +848,10 @@ example_upgrade(clicon_handle h,
{ {
int retval = -1; int retval = -1;
cvec *nsc = NULL; /* Canonical namespace */ cvec *nsc = NULL; /* Canonical namespace */
yang_stmt *yspec; yang_stmt *yspec;
const struct map_str2str *ms; /* map iterator */ const struct map_str2str *ms; /* map iterator */
cxobj **xvec = NULL; /* vector of result nodes */ cxobj **xvec = NULL; /* vector of result nodes */
size_t xlen; size_t xlen;
int i; int i;
const char **pp; const char **pp;
@ -868,7 +868,7 @@ example_upgrade(clicon_handle h,
/* 1. Remove paths */ /* 1. Remove paths */
for (pp = remove_map; *pp; ++pp){ for (pp = remove_map; *pp; ++pp){
/* Find all nodes matching n */ /* Find all nodes matching n */
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, *pp) < 0) if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, *pp) < 0)
goto done; goto done;
/* Remove them */ /* Remove them */
/* Loop through all nodes matching mypath and change theoir namespace */ /* Loop through all nodes matching mypath and change theoir namespace */
@ -896,11 +896,11 @@ example_upgrade(clicon_handle h,
goto done; goto done;
} }
/* Find all nodes matching mypath */ /* Find all nodes matching mypath */
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, mypath) < 0) if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, mypath) < 0)
goto done; goto done;
/* Loop through all nodes matching mypath and change theoir namespace */ /* Loop through all nodes matching mypath and change theoir namespace */
for (i=0; i<xlen; i++){ for (i=0; i<xlen; i++){
/* Change namespace of this node (using myprefix) */ /* Change namespace of this node (using myprefix) */
if (xml_namespace_change(xvec[i], mynamespace, myprefix) < 0) if (xml_namespace_change(xvec[i], mynamespace, myprefix) < 0)
goto done; goto done;
} }
@ -977,7 +977,7 @@ main_yang_mount(clicon_handle h,
/*! Testcase module-specific upgrade function moving interfaces-state to interfaces /*! Testcase module-specific upgrade function moving interfaces-state to interfaces
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xn XML tree to be updated * @param[in] xn XML tree to be updated
* @param[in] ns Namespace of module (for info) * @param[in] ns Namespace of module (for info)
* @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE * @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE
@ -999,13 +999,13 @@ main_yang_mount(clicon_handle h,
* - Rename /interfaces/interface/description to descr * - Rename /interfaces/interface/description to descr
*/ */
static int static int
upgrade_2014_to_2016(clicon_handle h, upgrade_2014_to_2016(clicon_handle h,
cxobj *xt, cxobj *xt,
char *ns, char *ns,
uint16_t op, uint16_t op,
uint32_t from, uint32_t from,
uint32_t to, uint32_t to,
void *arg, void *arg,
cbuf *cbret) cbuf *cbret)
{ {
int retval = -1; int retval = -1;
@ -1020,11 +1020,11 @@ upgrade_2014_to_2016(clicon_handle h,
int i; int i;
char *name; char *name;
clicon_debug(1, "%s from:%d to:%d", __FUNCTION__, from, to); clixon_debug(CLIXON_DBG_DEFAULT, "%s from:%d to:%d", __FUNCTION__, from, to);
if (op != XML_FLAG_CHANGE) /* Only treat fully present modules */ if (op != XML_FLAG_CHANGE) /* Only treat fully present modules */
goto ok; goto ok;
/* Get Yang module for this namespace. Note it may not exist (if obsolete) */ /* Get Yang module for this namespace. Note it may not exist (if obsolete) */
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if ((ym = yang_find_module_by_namespace(yspec, ns)) == NULL) if ((ym = yang_find_module_by_namespace(yspec, ns)) == NULL)
goto ok; /* shouldnt happen */ goto ok; /* shouldnt happen */
/* Get all XML nodes with that namespace */ /* Get all XML nodes with that namespace */
@ -1045,7 +1045,7 @@ upgrade_2014_to_2016(clicon_handle h,
continue; /* shouldnt happen */ continue; /* shouldnt happen */
/* Get corresponding /interfaces/interface entry */ /* Get corresponding /interfaces/interface entry */
xif = xpath_first(xt, NULL, "/interfaces/interface[name=\"%s\"]", name); xif = xpath_first(xt, NULL, "/interfaces/interface[name=\"%s\"]", name);
/* - Move /if:interfaces-state/if:interface/if:admin-status to /* - Move /if:interfaces-state/if:interface/if:admin-status to
* /if:interfaces/if:interface/ */ * /if:interfaces/if:interface/ */
if ((x = xml_find(xi, "admin-status")) != NULL && xif){ if ((x = xml_find(xi, "admin-status")) != NULL && xif){
if (xml_addsub(xif, x) < 0) if (xml_addsub(xif, x) < 0)
@ -1082,7 +1082,7 @@ upgrade_2014_to_2016(clicon_handle h,
/*! Testcase upgrade function removing interfaces-state /*! Testcase upgrade function removing interfaces-state
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xn XML tree to be updated * @param[in] xn XML tree to be updated
* @param[in] ns Namespace of module (for info) * @param[in] ns Namespace of module (for info)
* @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE * @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE
@ -1103,13 +1103,13 @@ upgrade_2014_to_2016(clicon_handle h,
* fraction-digits 3 and divide all values with 1000 * fraction-digits 3 and divide all values with 1000
*/ */
static int static int
upgrade_2016_to_2018(clicon_handle h, upgrade_2016_to_2018(clicon_handle h,
cxobj *xt, cxobj *xt,
char *ns, char *ns,
uint16_t op, uint16_t op,
uint32_t from, uint32_t from,
uint32_t to, uint32_t to,
void *arg, void *arg,
cbuf *cbret) cbuf *cbret)
{ {
int retval = -1; int retval = -1;
@ -1123,14 +1123,14 @@ upgrade_2016_to_2018(clicon_handle h,
size_t vlen; size_t vlen;
int i; int i;
clicon_debug(1, "%s from:%d to:%d", __FUNCTION__, from, to); clixon_debug(CLIXON_DBG_DEFAULT, "%s from:%d to:%d", __FUNCTION__, from, to);
if (op != XML_FLAG_CHANGE) /* Only treat fully present modules */ if (op != XML_FLAG_CHANGE) /* Only treat fully present modules */
goto ok; goto ok;
/* Get Yang module for this namespace. Note it may not exist (if obsolete) */ /* Get Yang module for this namespace. Note it may not exist (if obsolete) */
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if ((ym = yang_find_module_by_namespace(yspec, ns)) == NULL) if ((ym = yang_find_module_by_namespace(yspec, ns)) == NULL)
goto ok; /* shouldnt happen */ goto ok; /* shouldnt happen */
clicon_debug(1, "%s module %s", __FUNCTION__, ym?yang_argument_get(ym):"none"); clixon_debug(CLIXON_DBG_DEFAULT, "%s module %s", __FUNCTION__, ym?yang_argument_get(ym):"none");
/* Get all XML nodes with that namespace */ /* Get all XML nodes with that namespace */
if (xml_namespace_vec(h, xt, ns, &vec, &vlen) < 0) if (xml_namespace_vec(h, xt, ns, &vec, &vlen) < 0)
goto done; goto done;
@ -1182,7 +1182,7 @@ upgrade_2016_to_2018(clicon_handle h,
/*! Testcase module-specific upgrade function moving interfaces-state to interfaces /*! Testcase module-specific upgrade function moving interfaces-state to interfaces
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] xn XML tree to be updated * @param[in] xn XML tree to be updated
* @param[in] ns Namespace of module (for info) * @param[in] ns Namespace of module (for info)
* @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE * @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE
@ -1204,13 +1204,13 @@ upgrade_2016_to_2018(clicon_handle h,
* - Rename /interfaces/interface/description to descr * - Rename /interfaces/interface/description to descr
*/ */
static int static int
upgrade_interfaces(clicon_handle h, upgrade_interfaces(clicon_handle h,
cxobj *xt, cxobj *xt,
char *ns, char *ns,
uint16_t op, uint16_t op,
uint32_t from, uint32_t from,
uint32_t to, uint32_t to,
void *arg, void *arg,
cbuf *cbret) cbuf *cbret)
{ {
int retval = -1; int retval = -1;
@ -1247,8 +1247,10 @@ upgrade_interfaces(clicon_handle h,
* is well defined. * is well defined.
* This involves creating default configuration files for various daemons, set interface * This involves creating default configuration files for various daemons, set interface
* flags etc. * flags etc.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @param[in] db Name of database. Not3 may be other than "running" * @param[in] db Name of database. Not3 may be other than "running"
* @retval 0 OK
* @retval -1 Error
* In this example, a loopback parameter is added * In this example, a loopback parameter is added
*/ */
int int
@ -1264,15 +1266,14 @@ example_reset(clicon_handle h,
if (!_reset) if (!_reset)
goto ok; /* Note not enabled by default */ goto ok; /* Note not enabled by default */
yspec = clicon_dbspec_yang(h);
yspec = clicon_dbspec_yang(h);
/* Parse extra XML */ /* Parse extra XML */
if ((ret = clixon_xml_parse_string("<table xmlns=\"urn:example:clixon\">" if ((ret = clixon_xml_parse_string("<table xmlns=\"urn:example:clixon\">"
"<parameter><name>loopback</name><value>99</value></parameter>" "<parameter><name>loopback</name><value>99</value></parameter>"
"</table>", YB_MODULE, yspec, &xt, &xerr)) < 0) "</table>", YB_MODULE, yspec, &xt, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
clicon_debug_xml(1, xerr, "Error when parsing XML"); clixon_debug_xml(CLIXON_DBG_DEFAULT, xerr, "Error when parsing XML");
goto ok; goto ok;
} }
/* xmldb_put requires modification tree to be: <config>... */ /* xmldb_put requires modification tree to be: <config>... */
@ -1306,7 +1307,9 @@ example_reset(clicon_handle h,
* Called when application is "started", (almost) all initialization is complete * Called when application is "started", (almost) all initialization is complete
* Backend: daemon is in the background. If daemon privileges are dropped * Backend: daemon is in the background. If daemon privileges are dropped
* this callback is called *before* privileges are dropped. * this callback is called *before* privileges are dropped.
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/ */
int int
example_start(clicon_handle h) example_start(clicon_handle h)
@ -1338,7 +1341,9 @@ example_start(clicon_handle h)
/*! Plugin daemon. /*! Plugin daemon.
* *
* @param[in] h Clicon handle * @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
* plugin_daemon is called once after daemonization has been made but before lowering of privileges * plugin_daemon is called once after daemonization has been made but before lowering of privileges
* the main event loop is entered. * the main event loop is entered.
*/ */
@ -1376,7 +1381,7 @@ example_daemon(clicon_handle h)
return retval; return retval;
} }
int int
example_exit(clicon_handle h) example_exit(clicon_handle h)
{ {
if (_state_xml_cache){ if (_state_xml_cache){
@ -1390,7 +1395,7 @@ example_exit(clicon_handle h)
clixon_plugin_api *clixon_plugin_init(clicon_handle h); 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 - must be called clixon_plugin_init */ clixon_plugin_init, /* init - must be called clixon_plugin_init */
example_start, /* start */ example_start, /* start */
example_exit, /* exit */ example_exit, /* exit */
@ -1427,7 +1432,7 @@ clixon_plugin_init(clicon_handle h)
char **argv; char **argv;
int c; int c;
clicon_debug(1, "%s backend", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s backend", __FUNCTION__);
/* Get user command-line options (after --) */ /* Get user command-line options (after --) */
if (clicon_argv_get(h, &argc, &argv) < 0) if (clicon_argv_get(h, &argc, &argv) < 0)
@ -1491,7 +1496,7 @@ clixon_plugin_init(clicon_handle h)
goto done; goto done;
} }
} }
if (_notification_stream){ if (_notification_stream){
/* Example stream initialization: /* Example stream initialization:
* 1) Register EXAMPLE stream * 1) Register EXAMPLE stream
@ -1514,22 +1519,22 @@ clixon_plugin_init(clicon_handle h)
/* Register callback for routing rpc calls /* Register callback for routing rpc calls
*/ */
/* From example.yang (clicon) */ /* From example.yang (clicon) */
if (rpc_callback_register(h, empty_rpc, if (rpc_callback_register(h, empty_rpc,
NULL, NULL,
"urn:example:clixon", "urn:example:clixon",
"empty"/* Xml tag when callback is made */ "empty"/* Xml tag when callback is made */
) < 0) ) < 0)
goto done; goto done;
/* Same as example but with optional input/output */ /* Same as example but with optional input/output */
if (rpc_callback_register(h, example_rpc, if (rpc_callback_register(h, example_rpc,
NULL, NULL,
"urn:example:clixon", "urn:example:clixon",
"optional"/* Xml tag when callback is made */ "optional"/* Xml tag when callback is made */
) < 0) ) < 0)
goto done; goto done;
/* Same as example but with optional input/output */ /* Same as example but with optional input/output */
if (rpc_callback_register(h, example_rpc, if (rpc_callback_register(h, example_rpc,
NULL, NULL,
"urn:example:clixon", "urn:example:clixon",
"example"/* Xml tag when callback is made */ "example"/* Xml tag when callback is made */
) < 0) ) < 0)
@ -1538,8 +1543,8 @@ clixon_plugin_init(clicon_handle h)
* If you want to have it called _after_ the system callback, place this call in * If you want to have it called _after_ the system callback, place this call in
* the _start function. * the _start function.
*/ */
if (rpc_callback_register(h, example_copy_extra, if (rpc_callback_register(h, example_copy_extra,
NULL, NULL,
NETCONF_BASE_NAMESPACE, NETCONF_BASE_NAMESPACE,
"copy-config" "copy-config"
) < 0) ) < 0)

View file

@ -56,18 +56,20 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
/* These include signatures for plugin and transaction callbacks. */ /* These include signatures for plugin and transaction callbacks. */
#include <clixon/clixon_backend.h> #include <clixon/clixon_backend.h>
/* Command line options to be passed to getopt(3) */ /* Command line options to be passed to getopt(3) */
#define BACKEND_NACM_OPTS "tv:" #define BACKEND_NACM_OPTS "tv:"
/*! Variable to control transaction logging (for debug) /*! Variable to control transaction logging (for debug)
*
* If set, call syslog for every transaction callback * If set, call syslog for every transaction callback
* Start backend with -- -t * Start backend with -- -t
*/ */
static int _transaction_log = 0; static int _transaction_log = 0;
/*! Variable to trigger validation/commit errors (synthetic errors) for tests /*! Variable to trigger validation/commit errors (synthetic errors) for tests
*
* XPath to trigger validation error, ie if the XPath matches, then validate fails * XPath to trigger validation error, ie if the XPath matches, then validate fails
* This is to make tests where a transaction fails midway and aborts/reverts the transaction. * This is to make tests where a transaction fails midway and aborts/reverts the transaction.
* Start backend with -- -v <xpath> * Start backend with -- -v <xpath>
@ -76,12 +78,13 @@ static int _transaction_log = 0;
static char *_validate_fail_xpath = NULL; static char *_validate_fail_xpath = NULL;
/*! Sub state variable to fail on validate/commit (not configured) /*! Sub state variable to fail on validate/commit (not configured)
*
* Obscure, but a way to first trigger a validation error, next time to trigger a commit error * Obscure, but a way to first trigger a validation error, next time to trigger a commit error
*/ */
static int _validate_fail_toggle = 0; /* fail at validate and commit */ static int _validate_fail_toggle = 0; /* fail at validate and commit */
int int
nacm_begin(clicon_handle h, nacm_begin(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -91,7 +94,7 @@ nacm_begin(clicon_handle h,
/*! This is called on validate (and commit). Check validity of candidate /*! This is called on validate (and commit). Check validity of candidate
*/ */
int int
nacm_validate(clicon_handle h, nacm_validate(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -108,7 +111,7 @@ nacm_validate(clicon_handle h,
} }
int int
nacm_complete(clicon_handle h, nacm_complete(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -119,7 +122,7 @@ nacm_complete(clicon_handle h,
/*! This is called on commit. Identify modifications and adjust machine state /*! This is called on commit. Identify modifications and adjust machine state
*/ */
int int
nacm_commit(clicon_handle h, nacm_commit(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -136,7 +139,7 @@ nacm_commit(clicon_handle h,
} }
int int
nacm_commit_done(clicon_handle h, nacm_commit_done(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -145,7 +148,7 @@ nacm_commit_done(clicon_handle h,
} }
int int
nacm_revert(clicon_handle h, nacm_revert(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -154,7 +157,7 @@ nacm_revert(clicon_handle h,
} }
int int
nacm_end(clicon_handle h, nacm_end(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -163,7 +166,7 @@ nacm_end(clicon_handle h,
} }
int int
nacm_abort(clicon_handle h, nacm_abort(clicon_handle h,
transaction_data td) transaction_data td)
{ {
if (_transaction_log) if (_transaction_log)
@ -172,9 +175,10 @@ nacm_abort(clicon_handle h,
} }
/*! Called to get NACM state data /*! Called to get NACM state data
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] nsc External XML namespace context, or NULL * @param[in] nsc External XML namespace context, or NULL
* @param[in] xpath String with XPATH syntax. or NULL for all * @param[in] xpath String with XPath syntax. or NULL for all
* @param[in] xtop XML tree, <config/> on entry. * @param[in] xtop XML tree, <config/> on entry.
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
@ -182,8 +186,8 @@ nacm_abort(clicon_handle h,
* @note this example code returns a static statedata used in testing. * @note this example code returns a static statedata used in testing.
* Real code would poll state * Real code would poll state
*/ */
int int
nacm_statedata(clicon_handle h, nacm_statedata(clicon_handle h,
cvec *nsc, cvec *nsc,
char *xpath, char *xpath,
cxobj *xstate) cxobj *xstate)
@ -224,6 +228,7 @@ static clixon_plugin_api api = {
}; };
/*! Backend plugin initialization /*! Backend plugin initialization
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval NULL Error with clicon_err set * @retval NULL Error with clicon_err set
* @retval api Pointer to API struct * @retval api Pointer to API struct
@ -235,8 +240,8 @@ clixon_plugin_init(clicon_handle h)
int argc; /* command-line options (after --) */ int argc; /* command-line options (after --) */
char **argv; char **argv;
int c; int c;
clicon_debug(1, "%s backend nacm", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s backend nacm", __FUNCTION__);
/* Get user command-line options (after --) */ /* Get user command-line options (after --) */
if (clicon_argv_get(h, &argc, &argv) < 0) if (clicon_argv_get(h, &argc, &argv) < 0)
goto done; goto done;
@ -256,7 +261,7 @@ clixon_plugin_init(clicon_handle h)
if (nacm_mode==NULL || strcmp(nacm_mode, "disabled") == 0){ if (nacm_mode==NULL || strcmp(nacm_mode, "disabled") == 0){
clicon_log(LOG_DEBUG, "%s CLICON_NACM_MODE not enabled: example nacm module disabled", __FUNCTION__); 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 */ /* Skip nacm module if not enabled _unless_ we use transaction tests */
if (_transaction_log == 0) if (_transaction_log == 0)
return NULL; return NULL;
} }
/* Return plugin API */ /* Return plugin API */

View file

@ -64,7 +64,8 @@
static char *_mount_yang = NULL; static char *_mount_yang = NULL;
static char *_mount_namespace = NULL; static char *_mount_namespace = NULL;
/*! Example cli function */ /*! Example cli function
*/
int int
mycallback(clicon_handle h, cvec *cvv, cvec *argv) mycallback(clicon_handle h, cvec *cvv, cvec *argv)
{ {
@ -80,10 +81,10 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv)
if ((nsc = xml_nsctx_init(NULL, "urn:example:clixon")) == NULL) if ((nsc = xml_nsctx_init(NULL, "urn:example:clixon")) == NULL)
goto done; goto done;
/* Show eth0 interfaces config using XPATH */ /* Show eth0 interfaces config using XPath */
if (clicon_rpc_get_config(h, NULL, "running", if (clicon_rpc_get_config(h, NULL, "running",
"/interfaces/interface[name='eth0']", "/interfaces/interface[name='eth0']",
nsc, NULL, nsc, NULL,
&xret) < 0) &xret) < 0)
goto done; goto done;
if (clixon_xml2file(stdout, xret, 0, 1, NULL, cligen_output, 0, 1) < 0) if (clixon_xml2file(stdout, xret, 0, 1, NULL, cligen_output, 0, 1) < 0)
@ -97,10 +98,11 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv)
return retval; return retval;
} }
/*! Example "downcall", ie initiate an RPC to the backend */ /*! Example "downcall", ie initiate an RPC to the backend
*/
int int
example_client_rpc(clicon_handle h, example_client_rpc(clicon_handle h,
cvec *cvv, cvec *cvv,
cvec *argv) cvec *argv)
{ {
int retval = -1; int retval = -1;
@ -148,7 +150,11 @@ example_client_rpc(clicon_handle h,
} }
/*! Translate function from an original value to a new. /*! Translate function from an original value to a new.
*
* In this case, assume string and increment characters, eg HAL->IBM * In this case, assume string and increment characters, eg HAL->IBM
* @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/ */
int int
cli_incstr(cligen_handle h, cli_incstr(cligen_handle h,
@ -156,8 +162,8 @@ cli_incstr(cligen_handle h,
{ {
char *str; char *str;
int i; int i;
/* Filter out other than strings /* Filter out other than strings
* this is specific to this example, one can do translation */ * this is specific to this example, one can do translation */
if (cv == NULL || cv_type_get(cv) != CGV_STRING) if (cv == NULL || cv_type_get(cv) != CGV_STRING)
return 0; return 0;
@ -239,6 +245,7 @@ static clixon_plugin_api api = {
}; };
/*! CLI plugin initialization /*! CLI plugin initialization
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval NULL Error with clicon_err set * @retval NULL Error with clicon_err set
* @retval api Pointer to API struct * @retval api Pointer to API struct

View file

@ -49,8 +49,10 @@
#include <clixon/clixon_netconf.h> #include <clixon/clixon_netconf.h>
/*! Plugin start /*! Plugin start
*
* Called once everything has been initialized, right before * Called once everything has been initialized, right before
* the main event loop is entered. * the main event loop is entered.
* @param[in] h Clixon handle
*/ */
int int
plugin_start(clicon_handle h) plugin_start(clicon_handle h)
@ -67,9 +69,9 @@ plugin_exit(clicon_handle h)
/*! Local example netconf rpc callback /*! Local example netconf rpc callback
*/ */
int int
netconf_client_rpc(clicon_handle h, netconf_client_rpc(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
@ -111,6 +113,7 @@ static struct clixon_plugin_api api = {
}; };
/*! Netconf plugin initialization /*! Netconf plugin initialization
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval NULL Error with clicon_err set * @retval NULL Error with clicon_err set
* @retval api Pointer to API struct * @retval api Pointer to API struct
@ -118,7 +121,7 @@ static struct clixon_plugin_api api = {
clixon_plugin_api * clixon_plugin_api *
clixon_plugin_init(clicon_handle h) clixon_plugin_init(clicon_handle h)
{ {
clicon_debug(1, "%s restconf", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s restconf", __FUNCTION__);
/* Register local netconf rpc client (note not backend rpc client) */ /* Register local netconf rpc client (note not backend rpc client) */
if (rpc_callback_register(h, netconf_client_rpc, NULL, if (rpc_callback_register(h, netconf_client_rpc, NULL,
"urn:example:clixon", "client-rpc") < 0) "urn:example:clixon", "client-rpc") < 0)

View file

@ -64,8 +64,8 @@ static const char Pad64 = '=';
@note what is copyright of this? @note what is copyright of this?
*/ */
int int
b64_decode(const char *src, b64_decode(const char *src,
char *target, char *target,
size_t targsize) size_t targsize)
{ {
int tarindex, state, ch; int tarindex, state, ch;
@ -185,14 +185,15 @@ b64_decode(const char *src,
} }
/*! HTTP basic authentication example (note hardwired) /*! HTTP basic authentication example (note hardwired)
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] req Per-message request www handle to use with restconf_api.h * @param[in] req Per-message request www handle to use with restconf_api.h
* @param[out] authp NULL: Credentials failed, no user set (401 returned). * @param[out] authp NULL: Credentials failed, no user set (401 returned).
* String: Credentials OK, the associated user, must be mallloc:ed * String: Credentials OK, the associated user, must be mallloc:ed
* Parameter signtificant only if retval is 1/OK * Parameter signtificant only if retval is 1/OK
* @retval -1 Fatal error
* @retval 0 Ignore, undecided, not handled, same as no callback
* @retval 1 OK, see authp parameter for result. * @retval 1 OK, see authp parameter for result.
* @retval 0 Ignore, undecided, not handled, same as no callback
* @retval -1 Fatal error
* @note authp should be malloced * @note authp should be malloced
* @note: Three hardwired users: andy, wilma, guest w password "bar". * @note: Three hardwired users: andy, wilma, guest w password "bar".
*/ */
@ -211,14 +212,14 @@ example_basic_auth(clicon_handle h,
size_t authlen; size_t authlen;
int ret; int ret;
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
if (authp == NULL){ if (authp == NULL){
clicon_err(OE_PLUGIN, EINVAL, "Authp output parameter is NULL"); clicon_err(OE_PLUGIN, EINVAL, "Authp output parameter is NULL");
goto done; goto done;
} }
/* At this point in the code we must use HTTP basic authentication */ /* At this point in the code we must use HTTP basic authentication */
if ((auth = restconf_param_get(h, "HTTP_AUTHORIZATION")) == NULL) if ((auth = restconf_param_get(h, "HTTP_AUTHORIZATION")) == NULL)
goto fail; goto fail;
if (strlen(auth) < strlen("Basic ")) if (strlen(auth) < strlen("Basic "))
goto fail; goto fail;
if (strncmp("Basic ", auth, strlen("Basic "))) if (strncmp("Basic ", auth, strlen("Basic ")))
@ -237,7 +238,7 @@ example_basic_auth(clicon_handle h,
goto fail; goto fail;
*passwd = '\0'; *passwd = '\0';
passwd++; passwd++;
clicon_debug(1, "%s http user:%s passwd:%s", __FUNCTION__, user, passwd); clixon_debug(CLIXON_DBG_DEFAULT, "%s http user:%s passwd:%s", __FUNCTION__, user, passwd);
/* Here get auth sub-tree where all the users are */ /* Here get auth sub-tree where all the users are */
if ((cb = cbuf_new()) == NULL) if ((cb = cbuf_new()) == NULL)
goto done; goto done;
@ -252,7 +253,7 @@ example_basic_auth(clicon_handle h,
user=NULL; /* to avoid free below */ user=NULL; /* to avoid free below */
retval = 1; retval = 1;
done: /* error */ done: /* error */
clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, authp?"":*authp); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d authp:%s", __FUNCTION__, retval, authp?"":*authp);
if (user) if (user)
free(user); free(user);
if (cb) if (cb)
@ -267,15 +268,16 @@ example_basic_auth(clicon_handle h,
} }
/*! Authentication callback /*! Authentication callback
* @param[in] h Clicon handle *
* @param[in] h Clixon handle
* @param[in] req Per-message request www handle to use with restconf_api.h * @param[in] req Per-message request www handle to use with restconf_api.h
* @param[in] auth_type Authentication type: none, user-defined, or client-cert * @param[in] auth_type Authentication type: none, user-defined, or client-cert
* @param[out] authp NULL: Credentials failed, no user set (401 returned). * @param[out] authp NULL: Credentials failed, no user set (401 returned).
* String: Credentials OK, the associated user, must be mallloc:ed * String: Credentials OK, the associated user, must be mallloc:ed
* Parameter signtificant only if retval is 1/OK * Parameter signtificant only if retval is 1/OK
* @retval -1 Fatal error
* @retval 0 Ignore, undecided, not handled, same as no callback
* @retval 1 OK, see authp parameter for result. * @retval 1 OK, see authp parameter for result.
* @retval 0 Ignore, undecided, not handled, same as no callback
* @retval -1 Fatal error
* @note authp should be malloced * @note authp should be malloced
*/ */
int int
@ -285,8 +287,8 @@ example_restconf_credentials(clicon_handle h,
char **authp) char **authp)
{ {
int retval = -1; int retval = -1;
clicon_debug(1, "%s auth:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type)); clixon_debug(CLIXON_DBG_DEFAULT, "%s auth:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type));
switch (auth_type){ switch (auth_type){
case CLIXON_AUTH_NONE: /* FEATURE clixon-restconf:allow-auth-none must be enabled */ case CLIXON_AUTH_NONE: /* FEATURE clixon-restconf:allow-auth-none must be enabled */
retval = 0; retval = 0;
@ -300,16 +302,16 @@ example_restconf_credentials(clicon_handle h,
break; break;
} }
done: done:
clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, *authp); clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d authp:%s", __FUNCTION__, retval, *authp);
return retval; return retval;
} }
/*! Local example restconf rpc callback /*! Local example restconf rpc callback
*/ */
int int
restconf_client_rpc(clicon_handle h, restconf_client_rpc(clicon_handle h,
cxobj *xe, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
@ -344,7 +346,7 @@ restconf_client_rpc(clicon_handle h,
int int
example_restconf_start(clicon_handle h) example_restconf_start(clicon_handle h)
{ {
clicon_debug(1, "%s", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__);
return 0; return 0;
} }
@ -359,6 +361,7 @@ static clixon_plugin_api api = {
}; };
/*! Restconf plugin initialization /*! Restconf plugin initialization
*
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @retval NULL Error with clicon_err set * @retval NULL Error with clicon_err set
* @retval api Pointer to API struct * @retval api Pointer to API struct
@ -370,8 +373,8 @@ clixon_plugin_init(clicon_handle h)
int argc; /* command-line options (after --) */ int argc; /* command-line options (after --) */
char **argv = NULL; char **argv = NULL;
int c; int c;
clicon_debug(1, "%s restconf", __FUNCTION__); clixon_debug(CLIXON_DBG_DEFAULT, "%s restconf", __FUNCTION__);
/* Get user command-line options (after --) */ /* Get user command-line options (after --) */
if (clicon_argv_get(h, &argc, &argv) < 0) if (clicon_argv_get(h, &argc, &argv) < 0)
return NULL; return NULL;

View file

@ -39,7 +39,7 @@
or apps or apps
*/ */
#ifndef HAVE_STRNDUP #ifndef HAVE_STRNDUP
#define strndup(s, n) clicon_strndup(s, n) #define strndup(s, n) clicon_strndup(s, n)
#endif #endif
@ -48,6 +48,7 @@
#undef RPC_USERNAME_ASSERT #undef RPC_USERNAME_ASSERT
/*! Tag for wrong handling of identityref prefixes (XML encoding) /*! Tag for wrong handling of identityref prefixes (XML encoding)
*
* See https://github.com/clicon/clixon/issues/90 * See https://github.com/clicon/clixon/issues/90
* Instead of using generic xmlns prefix bindings, the module's own prefix * Instead of using generic xmlns prefix bindings, the module's own prefix
* is used. * is used.
@ -60,7 +61,8 @@
*/ */
#undef IDENTITYREF_KLUDGE #undef IDENTITYREF_KLUDGE
/*! Optimize special list key searches in XPATH finds /*! Optimize special list key searches in XPath finds
*
* Identify xpaths that search for exactly a list key, eg: "y[k='3']" and then call * Identify xpaths that search for exactly a list key, eg: "y[k='3']" and then call
* binary search. This only works if "y" has proper yang binding and is sorted by system * binary search. This only works if "y" has proper yang binding and is sorted by system
* Dont optimize on "hierarchical" lists such as: a/y[k='3'], where a is another list. * Dont optimize on "hierarchical" lists such as: a/y[k='3'], where a is another list.
@ -68,6 +70,7 @@
#define XPATH_LIST_OPTIMIZE #define XPATH_LIST_OPTIMIZE
/*! Add explicit search indexes, so that binary search can be made for non-key list indexes /*! Add explicit search indexes, so that binary search can be made for non-key list indexes
*
* This also applies if there are multiple keys and you want to search on only the second for * This also applies if there are multiple keys and you want to search on only the second for
* example. * example.
* There may be some cases where the index vector is not updated, need to verify before * There may be some cases where the index vector is not updated, need to verify before
@ -76,6 +79,7 @@
#define XML_EXPLICIT_INDEX #define XML_EXPLICIT_INDEX
/*! Let state data be ordered-by system /*! Let state data be ordered-by system
*
* RFC 7950 is cryptic about this * RFC 7950 is cryptic about this
* It says in 7.7.7: * It says in 7.7.7:
* This statement (red:The "ordered-by" Statement) is ignored if the list represents * This statement (red:The "ordered-by" Statement) is ignored if the list represents
@ -87,6 +91,7 @@
#define STATE_ORDERED_BY_SYSTEM #define STATE_ORDERED_BY_SYSTEM
/*! Top-symbol in clixon datastores /*! Top-symbol in clixon datastores
*
* This is traditionally same as NETCONF_INPUT_CONFIG ("config") but can be different * This is traditionally same as NETCONF_INPUT_CONFIG ("config") but can be different
* If you change this, you need to change test shell variable in lib.sh: DATASTORE_TOP * If you change this, you need to change test shell variable in lib.sh: DATASTORE_TOP
* Consider making this an option (but this has bootstrap problems) or configure option * Consider making this an option (but this has bootstrap problems) or configure option
@ -94,12 +99,14 @@
#define DATASTORE_TOP_SYMBOL "config" #define DATASTORE_TOP_SYMBOL "config"
/*! If set make an internal redirect if URI path indetifies a directory /*! If set make an internal redirect if URI path indetifies a directory
*
* For example, path is /local, and redirect is 'index.html, the request * For example, path is /local, and redirect is 'index.html, the request
* will be redirected to /local/index.html * will be redirected to /local/index.html
*/ */
#define HTTP_DATA_INTERNAL_REDIRECT "index.html" #define HTTP_DATA_INTERNAL_REDIRECT "index.html"
/*! Set a temporary parent for use in special case "when" xpath calls /*! Set a temporary parent for use in special case "when" xpath calls
*
* Problem is when changing an existing (candidate) in-memory datastore that yang "when" conditionals * Problem is when changing an existing (candidate) in-memory datastore that yang "when" conditionals
* should be changed in clixon_datastore_write.c:text_modify(). * should be changed in clixon_datastore_write.c:text_modify().
* Problem is that the tree is in an intermediate state so that a when condition may not see the * Problem is that the tree is in an intermediate state so that a when condition may not see the
@ -115,16 +122,19 @@
#define XML_PARENT_CANDIDATE #define XML_PARENT_CANDIDATE
/*! Enable "remaining" attribute (sub-feature of list pagination) /*! Enable "remaining" attribute (sub-feature of list pagination)
*
* As defined in draft-wwlh-netconf-list-pagination-00 using Yang metadata value [RFC7952] * As defined in draft-wwlh-netconf-list-pagination-00 using Yang metadata value [RFC7952]
*/ */
#undef LIST_PAGINATION_REMAINING #undef LIST_PAGINATION_REMAINING
/*! Use Ancestor config cache /*! Use Ancestor config cache
*
* The cache uses two yang stmt flag bits. One to say it is active, the second its value * The cache uses two yang stmt flag bits. One to say it is active, the second its value
*/ */
#define USE_CONFIG_FLAG_CACHE #define USE_CONFIG_FLAG_CACHE
/*! If backend is restarted, cli and netconf client will retry (once) and reconnect /*! If backend is restarted, cli and netconf client will retry (once) and reconnect
*
* Note, if client has locked or had edits in progress, these will be lost * Note, if client has locked or had edits in progress, these will be lost
* A warning will be printed * A warning will be printed
* If not set, client will exit * If not set, client will exit
@ -132,12 +142,14 @@
#define PROTO_RESTART_RECONNECT #define PROTO_RESTART_RECONNECT
/*! Disable top-level prefix for text syntax printing and parsing introduced in 5.8 /*! Disable top-level prefix for text syntax printing and parsing introduced in 5.8
*
* Note this is for showing/saving/printing, it is NOT for parsing/loading. * Note this is for showing/saving/printing, it is NOT for parsing/loading.
* This means that text output can not be parsed and loaded. * This means that text output can not be parsed and loaded.
*/ */
#undef TEXT_SYNTAX_NOPREFIX #undef TEXT_SYNTAX_NOPREFIX
/*! Reply with HTTP error when HTTP request on HTTPS socket /*! Reply with HTTP error when HTTP request on HTTPS socket
*
* If not set, just close socket and return with TCP reset. * If not set, just close socket and return with TCP reset.
* If set: Incoming request on an SSL socket is known to be non-TLS. * If set: Incoming request on an SSL socket is known to be non-TLS.
* Problematic part is it is not known it is proper non-TLS HTTP, for that it * Problematic part is it is not known it is proper non-TLS HTTP, for that it
@ -153,6 +165,7 @@
#define HTTP_ON_HTTPS_REPLY #define HTTP_ON_HTTPS_REPLY
/*! Indentation number of spaces for XML, JSON and TEXT pretty-printed output. /*! Indentation number of spaces for XML, JSON and TEXT pretty-printed output.
*
* Consider moving to configure.ac(compile-time) or to clixon-config.yang(run-time) * Consider moving to configure.ac(compile-time) or to clixon-config.yang(run-time)
*/ */
#define PRETTYPRINT_INDENT 3 #define PRETTYPRINT_INDENT 3

View file

@ -50,17 +50,17 @@ typedef enum {
* see https://clixon-docs.readthedocs.io/en/latest/netconf.html#ipc * see https://clixon-docs.readthedocs.io/en/latest/netconf.html#ipc
* Must be local on device * Must be local on device
*/ */
CLIXON_CLIENT_IPC, CLIXON_CLIENT_IPC,
/* Regular NETCONF via local netconf binary /* Regular NETCONF via local netconf binary
* Fork clixon_netconf locally which in turn communicates with backend * Fork clixon_netconf locally which in turn communicates with backend
* Must be local on device * Must be local on device
*/ */
CLIXON_CLIENT_NETCONF, CLIXON_CLIENT_NETCONF,
/* Regular NETCONF using ssh sub-system via local SSH (openssh) client binary /* Regular NETCONF using ssh sub-system via local SSH (openssh) client binary
* Fork ssh locally which in turn communicates remotely to device * Fork ssh locally which in turn communicates remotely to device
* Must have openssh installed locally and device must have ssh sub-subsystem * Must have openssh installed locally and device must have ssh sub-subsystem
*/ */
CLIXON_CLIENT_SSH CLIXON_CLIENT_SSH
} clixon_client_type; } clixon_client_type;
/* /*
@ -70,7 +70,7 @@ typedef enum {
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
clixon_handle clixon_client_init(const char *config_file); clixon_handle clixon_client_init(const char *config_file);
int clixon_client_terminate(clixon_handle h); int clixon_client_terminate(clixon_handle h);
int clixon_client_lock(int sock, const char *descr, const int lock, const char *db); int clixon_client_lock(int sock, const char *descr, const int lock, const char *db);
@ -83,7 +83,7 @@ int clixon_client_get_uint8(clixon_client_handle ch, uint8_t *rval, const char
int clixon_client_get_uint16(clixon_client_handle ch, uint16_t *rval, const char *xnamespace, const char *xpath); int clixon_client_get_uint16(clixon_client_handle ch, uint16_t *rval, const char *xnamespace, const char *xpath);
int clixon_client_get_uint32(clixon_client_handle ch, uint32_t *rval, const char *xnamespace, const char *xpath); int clixon_client_get_uint32(clixon_client_handle ch, uint32_t *rval, const char *xnamespace, const char *xpath);
int clixon_client_get_uint64(clixon_client_handle ch, uint64_t *rval, const char *xnamespace, const char *xpath); int clixon_client_get_uint64(clixon_client_handle ch, uint64_t *rval, const char *xnamespace, const char *xpath);
/* Access functions */ /* Access functions */
int clixon_client_socket_get(clixon_client_handle ch); int clixon_client_socket_get(clixon_client_handle ch);

View file

@ -125,19 +125,19 @@ int clicon_socket_set(clicon_handle h, int s);
int clicon_client_socket_get(clicon_handle h); int clicon_client_socket_get(clicon_handle h);
int clicon_client_socket_set(clicon_handle h, int s); int clicon_client_socket_set(clicon_handle h, int s);
/*! Set and get module state full and brief cached tree */ /* Set and get module state full and brief cached tree */
cxobj *clicon_modst_cache_get(clicon_handle h, int brief); cxobj *clicon_modst_cache_get(clicon_handle h, int brief);
int clicon_modst_cache_set(clicon_handle h, int brief, cxobj *xms); int clicon_modst_cache_set(clicon_handle h, int brief, cxobj *xms);
/*! Set and get yang/xml module revision changelog */ /* Set and get yang/xml module revision changelog */
cxobj *clicon_xml_changelog_get(clicon_handle h); cxobj *clicon_xml_changelog_get(clicon_handle h);
int clicon_xml_changelog_set(clicon_handle h, cxobj *xchlog); int clicon_xml_changelog_set(clicon_handle h, cxobj *xchlog);
/*! Set and get user command-line options (after --) */ /* Set and get user command-line options (after --) */
int clicon_argv_get(clicon_handle h, int *argc, char ***argv); int clicon_argv_get(clicon_handle h, int *argc, char ***argv);
int clicon_argv_set(clicon_handle h, char *argv0, int argc, char **argv); int clicon_argv_set(clicon_handle h, char *argv0, int argc, char **argv);
/*! Set and get (client/backend) session id */ /* Set and get (client/backend) session id */
int clicon_session_id_set(clicon_handle h, uint32_t id); int clicon_session_id_set(clicon_handle h, uint32_t id);
int clicon_session_id_get(clicon_handle h, uint32_t *id); int clicon_session_id_get(clicon_handle h, uint32_t *id);
int clicon_session_id_del(clicon_handle h); int clicon_session_id_del(clicon_handle h);

View file

@ -52,7 +52,7 @@ int xmldb_disconnect(clicon_handle h);
int xmldb_get(clicon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **xtop); int xmldb_get(clicon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **xtop);
int xmldb_get0(clicon_handle h, const char *db, yang_bind yb, int xmldb_get0(clicon_handle h, const char *db, yang_bind yb,
cvec *nsc, const char *xpath, int copy, withdefaults_type wdef, cvec *nsc, const char *xpath, int copy, withdefaults_type wdef,
cxobj **xtop, modstate_diff_t *msd, cxobj **xerr); cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
int xmldb_get0_clear(clicon_handle h, cxobj *x); int xmldb_get0_clear(clicon_handle h, cxobj *x);
int xmldb_get0_free(clicon_handle h, cxobj **xp); int xmldb_get0_free(clicon_handle h, cxobj **xp);
int xmldb_put(clicon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */ int xmldb_put(clicon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */

View file

@ -38,6 +38,7 @@
#define _CLIXON_DISPATCH_DISPATCHER_H #define _CLIXON_DISPATCH_DISPATCHER_H
/*! Prototype for a function to handle a path /*! Prototype for a function to handle a path
*
* minimally needs the path it's working on, but probably * minimally needs the path it's working on, but probably
* we want to hand down cached data somehow * we want to hand down cached data somehow
* @param[in] h Generic handler * @param[in] h Generic handler

View file

@ -45,7 +45,7 @@
/* /*
* Constants * Constants
*/ */
#define ERR_STRLEN 256 #define ERR_STRLEN 256
/* Special error number for clicon_suberrno /* Special error number for clicon_suberrno
@ -57,9 +57,9 @@
* Types * Types
* Add error category here, * Add error category here,
* @see EV variable in clixon_err.c but must also add an entry there * @see EV variable in clixon_err.c but must also add an entry there
*/ */
enum clicon_err{ enum clicon_err{
/* 0 means error not set) */ /* 0 means error not set) */
OE_DB = 1, /* database registries */ OE_DB = 1, /* database registries */
OE_DAEMON, /* daemons: pidfiles, etc */ OE_DAEMON, /* daemons: pidfiles, etc */
OE_EVENTS, /* events, filedescriptors, timeouts */ OE_EVENTS, /* events, filedescriptors, timeouts */
@ -79,11 +79,12 @@ enum clicon_err{
OE_UNDEF, OE_UNDEF,
/*-- From here error extensions using clixon_err_cat_reg, XXX register dynamically? --*/ /*-- From here error extensions using clixon_err_cat_reg, XXX register dynamically? --*/
OE_SSL, /* Openssl errors, see eg ssl_get_error and clixon_openssl_log_cb */ OE_SSL, /* Openssl errors, see eg ssl_get_error and clixon_openssl_log_cb */
OE_SNMP , /* Netsnmp error */ OE_SNMP , /* Netsnmp error */
OE_NGHTTP2, /* nghttp2 errors, see HAVE_LIBNGHTTP2 */ OE_NGHTTP2, /* nghttp2 errors, see HAVE_LIBNGHTTP2 */
}; };
/* Clixon error category log callback /*! Clixon error category log callback
*
* @param[in] handle Application-specific handle * @param[in] handle Application-specific handle
* @param[in] suberr Application-specific handle * @param[in] suberr Application-specific handle
* @param[out] cb Read log/error string into this buffer * @param[out] cb Read log/error string into this buffer

View file

@ -59,7 +59,7 @@ int clixon_event_reg_fd(int fd, int (*fn)(int, void*), void *arg, char *str);
int clixon_event_unreg_fd(int s, int (*fn)(int, void*)); int clixon_event_unreg_fd(int s, int (*fn)(int, void*));
int clixon_event_reg_timeout(struct timeval t, int (*fn)(int, void*), int clixon_event_reg_timeout(struct timeval t, int (*fn)(int, void*),
void *arg, char *str); void *arg, char *str);
int clixon_event_unreg_timeout(int (*fn)(int, void*), void *arg); int clixon_event_unreg_timeout(int (*fn)(int, void*), void *arg);

View file

@ -40,7 +40,7 @@
#define _CLIXON_FILE_H_ #define _CLIXON_FILE_H_
int clicon_file_dirent(const char *dir, struct dirent **ent, int clicon_file_dirent(const char *dir, struct dirent **ent,
const char *regexp, mode_t type); const char *regexp, mode_t type);
int clicon_files_recursive(const char *dir, const char *regexp, cvec *cvv); int clicon_files_recursive(const char *dir, const char *regexp, cvec *cvv);
int clicon_file_copy(char *src, char *target); int clicon_file_copy(char *src, char *target);

View file

@ -60,7 +60,7 @@ typedef void *plghndl_t;
*/ */
typedef int (clicon_output_cb)( typedef int (clicon_output_cb)(
FILE *f, FILE *f,
const char *templ, ... const char *templ, ...
) __attribute__ ((format (printf, 2, 3))); ) __attribute__ ((format (printf, 2, 3)));
/* /*

View file

@ -67,10 +67,15 @@ size_t clicon_log_string_limit_get(void);
int clicon_get_logflags(void); int clicon_get_logflags(void);
int clicon_log_str(int level, char *msg); int clicon_log_str(int level, char *msg);
int clicon_log(int level, const char *format, ...) __attribute__ ((format (printf, 2, 3))); int clicon_log(int level, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int clicon_debug(int dbglevel, const char *format, ...) __attribute__ ((format (printf, 2, 3))); int clixon_debug(int dbglevel, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int clicon_debug_init(int dbglevel, FILE *f); int clixon_debug_init(int dbglevel, FILE *f);
int clicon_debug_get(void); int clixon_debug_get(void);
char *mon2name(int md); char *mon2name(int md);
/* 6.4 backward compatability */
#if 1
#define clicon_debug clixon_debug
#define clicon_debug_init clixon_debug_init
#define clicon_debug_get clixon_debug_get
#endif
#endif /* _CLIXON_LOG_H_ */ #endif /* _CLIXON_LOG_H_ */

View file

@ -49,7 +49,7 @@ extern "C" {
#endif #endif
ssize_t netconf_input_read2(int s, unsigned char *buf, ssize_t buflen, int *eof); ssize_t netconf_input_read2(int s, unsigned char *buf, ssize_t buflen, int *eof);
int netconf_input_msg2(unsigned char **bufp, size_t *lenp, cbuf *cbmsg, int netconf_input_msg2(unsigned char **bufp, size_t *lenp, cbuf *cbmsg,
netconf_framing_type framing, int *frame_state, size_t *frame_size, netconf_framing_type framing, int *frame_state, size_t *frame_size,
int *eom); int *eom);
int netconf_input_frame2(cbuf *cb, yang_bind yb, yang_stmt *yspec, cxobj **xrecv, cxobj **xerr); int netconf_input_frame2(cbuf *cb, yang_bind yb, yang_stmt *yspec, cxobj **xrecv, cxobj **xerr);

View file

@ -97,7 +97,8 @@
/* /*
* Types * Types
*/ */
/*! Content query parameter RFC 8040 Sec 4.8.1 /*! Content query parameter RFC 8040 Sec 4.8.1
*
* Clixon extention: content so that RFC8040 content attribute can be conveyed * Clixon extention: content so that RFC8040 content attribute can be conveyed
* internally used in <get> * internally used in <get>
*/ */
@ -111,7 +112,7 @@ typedef enum netconf_content netconf_content;
enum target_type{ /* netconf */ enum target_type{ /* netconf */
RUNNING, RUNNING,
CANDIDATE CANDIDATE
}; };
enum test_option{ /* edit-config */ enum test_option{ /* edit-config */
SET, SET,
@ -126,7 +127,7 @@ enum error_option{ /* edit-config */
/* NETCONF framing /* NETCONF framing
*/ */
enum framing_type{ enum framing_type{
NETCONF_SSH_EOM=0, /* RFC 4742, RFC 6242 hello msg (end-of-msg: ]]>]]>)*/ NETCONF_SSH_EOM=0, /* RFC 4742, RFC 6242 hello msg (end-of-msg: ]]>]]>)*/
NETCONF_SSH_CHUNKED, /* RFC 6242 Chunked framing */ NETCONF_SSH_CHUNKED, /* RFC 6242 Chunked framing */
}; };
@ -135,7 +136,7 @@ typedef enum framing_type netconf_framing_type;
/* NETCONF with-defaults /* NETCONF with-defaults
* @see RFC 6243 * @see RFC 6243
*/ */
enum withdefaults_type{ enum withdefaults_type{
WITHDEFAULTS_REPORT_ALL = 0, /* default behavior: <= Clixon 6.0 */ WITHDEFAULTS_REPORT_ALL = 0, /* default behavior: <= Clixon 6.0 */
WITHDEFAULTS_TRIM, WITHDEFAULTS_TRIM,
WITHDEFAULTS_EXPLICIT, /* default behavior: > Clixon 6.0 */ WITHDEFAULTS_EXPLICIT, /* default behavior: > Clixon 6.0 */
@ -147,6 +148,7 @@ typedef enum withdefaults_type withdefaults_type;
* Macros * Macros
*/ */
/*! Generate textual error log from Netconf error message /*! Generate textual error log from Netconf error message
*
* @param[in] xerr Netconf error xml tree on the form: <rpc-error> * @param[in] xerr Netconf error xml tree on the form: <rpc-error>
* @param[in] format Format string * @param[in] format Format string
* @param[in] arg String argument to format (optional) * @param[in] arg String argument to format (optional)

View file

@ -46,6 +46,7 @@
* Constants * Constants
*/ */
/*! Clixon configuration namespace /*! Clixon configuration namespace
*
* Probably should be defined somewhere else or extracted from yang * Probably should be defined somewhere else or extracted from yang
* @see clixon-config.yang * @see clixon-config.yang
* @see clixon-lib.yang * @see clixon-lib.yang
@ -85,6 +86,7 @@ enum nacm_credentials_t{
}; };
/*! Datastore cache behaviour, see clixon_datastore.[ch] /*! Datastore cache behaviour, see clixon_datastore.[ch]
*
* See config option type datastore_cache in clixon-config.yang * See config option type datastore_cache in clixon-config.yang
*/ */
enum datastore_cache{ enum datastore_cache{
@ -94,6 +96,7 @@ enum datastore_cache{
}; };
/*! yang clixon regexp engine /*! yang clixon regexp engine
*
* @see regexp_mode in clixon-config.yang * @see regexp_mode in clixon-config.yang
*/ */
enum regexp_mode{ enum regexp_mode{

View file

@ -65,7 +65,7 @@ typedef struct {
qelem_t cp_qelem; /* List header */ qelem_t cp_qelem; /* List header */
char *cp_prefix; /* Prefix or module name, should be resolved + id to cp_yang */ char *cp_prefix; /* Prefix or module name, should be resolved + id to cp_yang */
char *cp_id; /* Identifier */ char *cp_id; /* Identifier */
cvec *cp_cvk; /* Key values: list of (name:value) pairs alt (NULL:value) cvec *cp_cvk; /* Key values: list of (name:value) pairs alt (NULL:value)
* Can also be single uint32, if so positional eg x/y[42] * Can also be single uint32, if so positional eg x/y[42]
* This seems kludgy but follows RFC 7950 Sec 9.13 * This seems kludgy but follows RFC 7950 Sec 9.13
*/ */
@ -81,7 +81,7 @@ int yang2api_path_fmt(yang_stmt *ys, int inclkey, char **api_path_fmt);
int api_path_fmt2api_path(const char *api_path_fmt, cvec *cvv, char **api_path, int *cvvi); int api_path_fmt2api_path(const char *api_path_fmt, cvec *cvv, char **api_path, int *cvvi);
int api_path_fmt2xpath(char *api_path_fmt, cvec *cvv, char **xpath); int api_path_fmt2xpath(char *api_path_fmt, cvec *cvv, char **xpath);
int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, cvec **nsc, cxobj **xerr); int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, cvec **nsc, cxobj **xerr);
int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop, int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
yang_class nodeclass, int strict, yang_class nodeclass, int strict,
cxobj **xpathp, yang_stmt **ypathp, cxobj **xerr); cxobj **xpathp, yang_stmt **ypathp, cxobj **xerr);
int xml2api_path_1(cxobj *x, cbuf *cb); int xml2api_path_1(cxobj *x, cbuf *cb);

View file

@ -50,7 +50,7 @@
/* /*
* Types * Types
*/ */
/*! Registered RPC callback function /*! Registered RPC callback function
* *
* @param[in] h Clicon handle * @param[in] h Clicon handle
@ -62,11 +62,11 @@
* @retval -1 Error * @retval -1 Error
*/ */
typedef int (*clicon_rpc_cb)( typedef int (*clicon_rpc_cb)(
clicon_handle h, clicon_handle h,
cxobj *xn, cxobj *xn,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg void *regarg
); );
/*! Registered Upgrade callback function /*! Registered Upgrade callback function
@ -84,22 +84,22 @@ typedef int (*clicon_rpc_cb)(
* @retval -1 Error * @retval -1 Error
*/ */
typedef int (*clicon_upgrade_cb)( typedef int (*clicon_upgrade_cb)(
clicon_handle h, clicon_handle h,
cxobj *xn, cxobj *xn,
char *ns, char *ns,
uint16_t op, uint16_t op,
uint32_t from, uint32_t from,
uint32_t to, uint32_t to,
void *arg, void *arg,
cbuf *cbret cbuf *cbret
); );
/* Clixon authentication type /* Clixon authentication type
* @see http-auth-type in clixon-restconf.yang * @see http-auth-type in clixon-restconf.yang
* For now only used by restconf frontend * For now only used by restconf frontend
*/ */
enum clixon_auth_type { enum clixon_auth_type {
CLIXON_AUTH_NONE = 0, /* Message is authenticated automatically to CLIXON_AUTH_NONE = 0, /* Message is authenticated automatically to
anonymous user, maye be changed by ca-auth callback anonymous user, maye be changed by ca-auth callback
FEATURE clixon-restconf:allow-auth-none must be enabled */ FEATURE clixon-restconf:allow-auth-none must be enabled */
CLIXON_AUTH_CLIENT_CERTIFICATE, /* TLS Client certification authentication */ CLIXON_AUTH_CLIENT_CERTIFICATE, /* TLS Client certification authentication */
@ -108,13 +108,15 @@ enum clixon_auth_type {
}; };
typedef enum clixon_auth_type clixon_auth_type_t; typedef enum clixon_auth_type clixon_auth_type_t;
/* Common plugin function names, function types and signatures. /*! Common plugin function names, function types and signatures.
*
* This plugin code is exytended by backend, cli, netconf, restconf plugins * This plugin code is exytended by backend, cli, netconf, restconf plugins
* Cli see cli_plugin.c * Cli see cli_plugin.c
* Backend see config_plugin.c * Backend see config_plugin.c
*/ */
/* Called when application is "started", (almost) all initialization is complete /*! Called when application is "started", (almost) all initialization is complete
*
* Backend: daemon is in the background. If daemon privileges are dropped * Backend: daemon is in the background. If daemon privileges are dropped
* this callback is called *before* privileges are dropped. * this callback is called *before* privileges are dropped.
* @param[in] h Clixon handle * @param[in] h Clixon handle
@ -203,7 +205,7 @@ typedef int (plgauth_t)(clicon_handle h, void *req, clixon_auth_type_t auth_type
* @retval 0 OK * @retval 0 OK
* @retval -1 Fatal error * @retval -1 Fatal error
*/ */
typedef int (plgreset_t)(clicon_handle h, const char *db); typedef int (plgreset_t)(clicon_handle h, const char *db);
/* Provide state data from plugin /* Provide state data from plugin
* *
@ -215,7 +217,7 @@ typedef int (plgreset_t)(clicon_handle h, const char *db);
* *
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] xpath Part of state requested * @param[in] xpath Part of state requested
* @param[in] nsc XPATH namespace context. * @param[in] nsc XPath namespace context.
* @param[out] xtop XML tree where statedata is added * @param[out] xtop XML tree where statedata is added
* @retval 0 OK * @retval 0 OK
* @retval -1 Fatal error * @retval -1 Fatal error
@ -226,7 +228,8 @@ typedef int (plgreset_t)(clicon_handle h, const char *db);
*/ */
typedef int (plgstatedata_t)(clicon_handle h, cvec *nsc, char *xpath, cxobj *xtop); typedef int (plgstatedata_t)(clicon_handle h, cvec *nsc, char *xpath, cxobj *xtop);
/* Pagination-data type /*! Pagination-data type
*
* @see pagination_data_t in for full pagination data structure * @see pagination_data_t in for full pagination data structure
* @see pagination_offset() and other accessor functions * @see pagination_offset() and other accessor functions
*/ */
@ -243,7 +246,8 @@ typedef void *pagination_data;
*/ */
typedef int (plglockdb_t)(clicon_handle h, char *db, int lock, int id); typedef int (plglockdb_t)(clicon_handle h, char *db, int lock, int id);
/* Transaction-data type /*! Transaction-data type
*
* @see transaction_data_t and clixon_backend_transaction.h for full transaction API * @see transaction_data_t and clixon_backend_transaction.h for full transaction API
*/ */
typedef void *transaction_data; typedef void *transaction_data;
@ -252,6 +256,7 @@ typedef void *transaction_data;
typedef int (trans_cb_t)(clicon_handle h, transaction_data td); typedef int (trans_cb_t)(clicon_handle h, transaction_data td);
/*! Hook to override default prompt with explicit function /*! Hook to override default prompt with explicit function
*
* Format prompt before each getline * Format prompt before each getline
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] mode Cligen syntax mode * @param[in] mode Cligen syntax mode
@ -311,6 +316,7 @@ typedef int (yang_mount_t)(clicon_handle h, cxobj *xt, int *config,
typedef int (yang_patch_t)(clicon_handle h, yang_stmt *ymod); typedef int (yang_patch_t)(clicon_handle h, yang_stmt *ymod);
/*! Startup status for use in startup-callback /*! Startup status for use in startup-callback
*
* Note that for STARTUP_ERR and STARTUP_INVALID, running runs in failsafe mode * Note that for STARTUP_ERR and STARTUP_INVALID, running runs in failsafe mode
* and startup contains the erroneous or invalid database. * and startup contains the erroneous or invalid database.
* The user should repair the startup and * The user should repair the startup and
@ -400,6 +406,7 @@ typedef struct clixon_plugin_api clixon_plugin_api;
typedef struct clixon_plugin clixon_plugin_t; typedef struct clixon_plugin clixon_plugin_t;
/*! Structure for checking status before and after a plugin call /*! Structure for checking status before and after a plugin call
*
* The internal struct is defined in clixon_plugin.c */ * The internal struct is defined in clixon_plugin.c */
typedef struct plugin_context plugin_context_t; typedef struct plugin_context plugin_context_t;

View file

@ -40,7 +40,7 @@
/* /*
* Types * Types
*/ */
typedef struct process_entry_t process_entry_t; typedef struct process_entry_t process_entry_t;
/* Process operations */ /* Process operations */
@ -52,7 +52,7 @@ typedef enum proc_operation {
PROC_OP_STATUS PROC_OP_STATUS
} proc_operation; } proc_operation;
/*! Process RPC callback function /*! Process RPC callback function
* *
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] pe Process entry * @param[in] pe Process entry
@ -64,7 +64,7 @@ typedef int (proc_cb_t)(clicon_handle h,
/* /*
* Prototypes * Prototypes
*/ */
int clixon_proc_socket(char **argv, int sock_flags, pid_t *pid, int *sock); int clixon_proc_socket(char **argv, int sock_flags, pid_t *pid, int *sock);
int clixon_proc_socket_close(pid_t pid, int sock); int clixon_proc_socket_close(pid_t pid, int sock);
int clixon_process_pid(clicon_handle h, const char *name, pid_t *pid); int clixon_process_pid(clicon_handle h, const char *name, pid_t *pid);

View file

@ -53,7 +53,7 @@ struct clicon_msg {
/* /*
* Prototypes * Prototypes
*/ */
char *format_int2str(enum format_enum showas); char *format_int2str(enum format_enum showas);
enum format_enum format_str2int(char *str); enum format_enum format_str2int(char *str);
@ -68,7 +68,7 @@ int clicon_rpc_connect_unix(clicon_handle h,
int *sock0); int *sock0);
int clicon_rpc_connect_inet(clicon_handle h, int clicon_rpc_connect_inet(clicon_handle h,
char *dst, char *dst,
uint16_t port, uint16_t port,
int *sock0); int *sock0);

View file

@ -48,7 +48,7 @@ int clicon_rpc_msg_persistent(clicon_handle h, struct clicon_msg *msg, cxobj **x
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp); int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp); int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp);
int clicon_rpc_get_config(clicon_handle h, char *username, char *db, char *xpath, cvec *nsc, char *defaults, cxobj **xret); int clicon_rpc_get_config(clicon_handle h, char *username, char *db, char *xpath, cvec *nsc, char *defaults, cxobj **xret);
int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op, int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op,
char *xml); char *xml);
int clicon_rpc_copy_config(clicon_handle h, char *db1, char *db2); int clicon_rpc_copy_config(clicon_handle h, char *db1, char *db2);
int clicon_rpc_delete_config(clicon_handle h, char *db); int clicon_rpc_delete_config(clicon_handle h, char *db);
@ -56,7 +56,7 @@ int clicon_rpc_lock(clicon_handle h, char *db);
int clicon_rpc_unlock(clicon_handle h, char *db); int clicon_rpc_unlock(clicon_handle h, char *db);
int clicon_rpc_get2(clicon_handle h, char *xpath, cvec *nsc, netconf_content content, int32_t depth, char *defaults, int bind, cxobj **xret); int clicon_rpc_get2(clicon_handle h, char *xpath, cvec *nsc, netconf_content content, int32_t depth, char *defaults, int bind, cxobj **xret);
int clicon_rpc_get(clicon_handle h, char *xpath, cvec *nsc, netconf_content content, int32_t depth, char *defaults, cxobj **xret); int clicon_rpc_get(clicon_handle h, char *xpath, cvec *nsc, netconf_content content, int32_t depth, char *defaults, cxobj **xret);
int clicon_rpc_get_pageable_list(clicon_handle h, char *datastore, char *xpath, int clicon_rpc_get_pageable_list(clicon_handle h, char *datastore, char *xpath,
cvec *nsc, netconf_content content, int32_t depth, char *defaults, cvec *nsc, netconf_content content, int32_t depth, char *defaults,
uint32_t offset, uint32_t limit, uint32_t offset, uint32_t limit,
char *direction, char *sort, char *where, char *direction, char *sort, char *where,

View file

@ -40,6 +40,7 @@
#define _CLIXON_QUEUE_H_ #define _CLIXON_QUEUE_H_
/*! Circular queue structure for use as first entry in a parent structure. /*! Circular queue structure for use as first entry in a parent structure.
*
* Add qelem_t as first element in struct * Add qelem_t as first element in struct
* @code * @code
* struct a{ * struct a{
@ -55,6 +56,7 @@ typedef struct _qelem_t {
} qelem_t; } qelem_t;
/*! Append element 'elem' to queue. /*! Append element 'elem' to queue.
*
* @param[in] elem Element to be added * @param[in] elem Element to be added
* @param[in,out] pred Add element after this * @param[in,out] pred Add element after this
* @code * @code
@ -78,6 +80,7 @@ typedef struct _qelem_t {
} }
/*! Insert element 'elem' in queue after 'pred' /*! Insert element 'elem' in queue after 'pred'
*
* @param[in] elem Element to be added * @param[in] elem Element to be added
* @param[in,out] pred Add element after this * @param[in,out] pred Add element after this
* @code * @code
@ -100,7 +103,8 @@ typedef struct _qelem_t {
pred = elem; \ pred = elem; \
} }
/*! Remove element 'elem' from queue. 'head' is the pointer to the queue and /*! Remove element 'elem' from queue. 'head' is the pointer to the queue and
*
* is of 'type'. * is of 'type'.
* @param[in] elem * @param[in] elem
* @param[in] head * @param[in] head
@ -121,6 +125,7 @@ typedef struct _qelem_t {
} }
/*! Get next entry in list /*! Get next entry in list
*
* @param[in] type Type of element * @param[in] type Type of element
* @param[in] el Return next element after elem. * @param[in] el Return next element after elem.
* @code * @code

View file

@ -40,7 +40,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int regexp_xsd2posix(char *xsd, char **posix); int regexp_xsd2posix(char *xsd, char **posix);
int regex_compile(clicon_handle h, char *regexp, void **recomp); int regex_compile(clicon_handle h, char *regexp, void **recomp);
int regex_exec(clicon_handle h, void *recomp, char *string); int regex_exec(clicon_handle h, void *recomp, char *string);

View file

@ -45,7 +45,7 @@ typedef void (*sigfn_t)(int);
/* /*
* Prototypes * Prototypes
*/ */
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int)); int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
int set_signal_flags(int signo, int flags, void (*handler)(int), void (**oldhandler)(int)); int set_signal_flags(int signo, int flags, void (*handler)(int), void (**oldhandler)(int));
int clixon_signal_save(sigset_t *sigset, struct sigaction sigaction_vec[32]); int clixon_signal_save(sigset_t *sigset, struct sigaction sigaction_vec[32]);

View file

@ -45,7 +45,8 @@
/* /*
* Types * Types
*/ */
/* Subscription callback /*! Subscription callback
*
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] op Operation: 0 OK, 1 Close * @param[in] op Operation: 0 OK, 1 Close
* @param[in] event Event as XML * @param[in] event Event as XML

View file

@ -39,12 +39,13 @@
#define _CLIXON_STRING_H_ #define _CLIXON_STRING_H_
/*! Struct used to map between int and strings. Typically used to map between /*! Struct used to map between int and strings. Typically used to map between
*
* values and their names. Note NULL terminated * values and their names. Note NULL terminated
* Example: * Example:
* @code * @code
static const map_str2int atmap[] = { static const map_str2int atmap[] = {
{"One", 1}, {"One", 1},
{"Two", 2}, {"Two", 2},
{NULL, -1} {NULL, -1}
}; };
* @endcode * @endcode
@ -73,7 +74,7 @@ typedef struct map_str2str map_str2str;
#include <string.h> #include <string.h>
/*! A strdup version that aligns on 4 bytes. To avoid warning from valgrind */ /*! A strdup version that aligns on 4 bytes. To avoid warning from valgrind */
static inline char * strdup4(char *str) static inline char * strdup4(char *str)
{ {
char *dup; char *dup;
size_t len; size_t len;
@ -86,7 +87,7 @@ static inline char * strdup4(char *str)
/* /*
* Prototypes * Prototypes
*/ */
char **clicon_strsep(char *string, char *delim, int *nvec0); char **clicon_strsep(char *string, char *delim, int *nvec0);
char *clicon_strjoin (int argc, char **argv, char *delim); char *clicon_strjoin (int argc, char **argv, char *delim);
char *clixon_string_del_join(char *str1, char *del, char *str2); char *clixon_string_del_join(char *str1, char *del, char *str2);

View file

@ -41,7 +41,7 @@
/* /*
* Prototypes * Prototypes
*/ */
int group_name2gid(const char *name, gid_t *gid); int group_name2gid(const char *name, gid_t *gid);
int name2uid(const char *name, uid_t *uid); int name2uid(const char *name, uid_t *uid);
int uid2name(const uid_t uid, char **name); int uid2name(const uid_t uid, char **name);

View file

@ -85,7 +85,7 @@
* This is a "neutral" symbol without any meaning as opposed to the previous symbols ^ * This is a "neutral" symbol without any meaning as opposed to the previous symbols ^
* @see DATASTORE_TOP_SYMBOL which should be used for clixon top-level config trees * @see DATASTORE_TOP_SYMBOL which should be used for clixon top-level config trees
*/ */
#define XML_TOP_SYMBOL "top" #define XML_TOP_SYMBOL "top"
/* /*
* Types * Types
@ -102,16 +102,16 @@ enum operation_type{ /* edit-config operation */
/* Netconf insert type (see RFC7950 Sec 7.8.6) */ /* Netconf insert type (see RFC7950 Sec 7.8.6) */
enum insert_type{ /* edit-config insert */ enum insert_type{ /* edit-config insert */
INS_FIRST, INS_FIRST,
INS_LAST, INS_LAST,
INS_BEFORE, INS_BEFORE,
INS_AFTER, INS_AFTER,
}; };
/* XML object types */ /* XML object types */
enum cxobj_type {CX_ERROR=-1, enum cxobj_type {CX_ERROR=-1,
CX_ELMNT, CX_ELMNT,
CX_ATTR, CX_ATTR,
CX_BODY}; CX_BODY};
/* How to bind yang to XML top-level when parsing /* How to bind yang to XML top-level when parsing
@ -145,7 +145,7 @@ enum cxobj_type {CX_ERROR=-1,
* / \ / \ * / \ / \
* x1 x2 - - y1 y2 * x1 x2 - - y1 y2
*/ */
enum yang_bind{ enum yang_bind{
YB_NONE=0, /* Dont do Yang binding */ YB_NONE=0, /* Dont do Yang binding */
YB_MODULE, /* Search for matching yang binding among top-level symbols of Yang modules of direct YB_MODULE, /* Search for matching yang binding among top-level symbols of Yang modules of direct
* children * children
@ -165,7 +165,7 @@ typedef enum yang_bind yang_bind;
typedef struct xml cxobj; /* struct defined in clicon_xml.c */ typedef struct xml cxobj; /* struct defined in clicon_xml.c */
/*! Callback function type for xml_apply /*! Callback function type for xml_apply
* *
* @param[in] x XML node * @param[in] x XML node
* @param[in] arg General-purpose argument * @param[in] arg General-purpose argument
@ -182,9 +182,9 @@ typedef struct clixon_xml_vec clixon_xvec; /* struct defined in clicon_xml_vec.c
* @see format_int2str, format_str2int * @see format_int2str, format_str2int
*/ */
enum format_enum{ enum format_enum{
FORMAT_XML, FORMAT_XML,
FORMAT_JSON, FORMAT_JSON,
FORMAT_TEXT, FORMAT_TEXT,
FORMAT_CLI, FORMAT_CLI,
FORMAT_NETCONF FORMAT_NETCONF
}; };
@ -304,7 +304,7 @@ char *xml_operation2str(enum operation_type op);
int xml_attr_insert2val(char *instr, enum insert_type *ins); int xml_attr_insert2val(char *instr, enum insert_type *ins);
int xml_add_attr(cxobj *xn, char *name, char *value, char *prefix, char *ns); int xml_add_attr(cxobj *xn, char *name, char *value, char *prefix, char *ns);
int clicon_log_xml(int level, cxobj *x, const char *format, ...) __attribute__ ((format (printf, 3, 4))); int clicon_log_xml(int level, cxobj *x, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
int clicon_debug_xml(int dbglevel, cxobj *x, const char *format, ...) __attribute__ ((format (printf, 3, 4))); int clixon_debug_xml(int dbglevel, cxobj *x, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
#ifdef XML_EXPLICIT_INDEX #ifdef XML_EXPLICIT_INDEX
int xml_search_index_p(cxobj *x); int xml_search_index_p(cxobj *x);

View file

@ -50,7 +50,7 @@ int clixon_xml2cbuf(cbuf *cb, cxobj *x, int level, int prettyprint, char *pref
int xmltree2cbuf(cbuf *cb, cxobj *x, int level); int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
int clixon_xml_parse_file(FILE *f, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr); int clixon_xml_parse_file(FILE *f, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
int clixon_xml_parse_string(const char *str, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr); int clixon_xml_parse_string(const char *str, yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr);
int clixon_xml_parse_va(yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr, int clixon_xml_parse_va(yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr,
const char *format, ...) __attribute__ ((format (printf, 5, 6))); const char *format, ...) __attribute__ ((format (printf, 5, 6)));
int clixon_xml_attr_copy(cxobj *xin, cxobj *xout, char *name); int clixon_xml_attr_copy(cxobj *xin, cxobj *xout, char *name);
int clixon_xml_diff2cbuf(cbuf *cb, cxobj *x0, cxobj *x1); int clixon_xml_diff2cbuf(cbuf *cb, cxobj *x0, cxobj *x1);

View file

@ -53,9 +53,9 @@ int isxmlns(cxobj *x);
int xmlns_assign(cxobj *x); int xmlns_assign(cxobj *x);
int xml2cvec(cxobj *xt, yang_stmt *ys, cvec **cvv0); int xml2cvec(cxobj *xt, yang_stmt *ys, cvec **cvv0);
int cvec2xml_1(cvec *cvv, char *toptag, cxobj *xp, cxobj **xt0); int cvec2xml_1(cvec *cvv, char *toptag, cxobj *xp, cxobj **xt0);
int xml_diff(cxobj *x0, cxobj *x1, int xml_diff(cxobj *x0, cxobj *x1,
cxobj ***first, int *firstlen, cxobj ***first, int *firstlen,
cxobj ***second, int *secondlen, cxobj ***second, int *secondlen,
cxobj ***changed_x0, cxobj ***changed_x1, int *changedlen); cxobj ***changed_x0, cxobj ***changed_x1, int *changedlen);
int xml_tree_equal(cxobj *x0, cxobj *x1); int xml_tree_equal(cxobj *x0, cxobj *x1);
int xml_tree_prune_flagged_sub(cxobj *xt, int flag, int test, int *upmark); int xml_tree_prune_flagged_sub(cxobj *xt, int flag, int test, int *upmark);

View file

@ -32,7 +32,7 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
* Clixon XML XPATH 1.0 according to https://www.w3.org/TR/xpath-10 * Clixon XML XPath 1.0 according to https://www.w3.org/TR/xpath-10
*/ */
#ifndef _CLIXON_XPATH_H #ifndef _CLIXON_XPATH_H
#define _CLIXON_XPATH_H #define _CLIXON_XPATH_H
@ -66,10 +66,10 @@ enum axis_type{
A_ANCESTOR_OR_SELF, A_ANCESTOR_OR_SELF,
A_ATTRIBUTE, A_ATTRIBUTE,
A_CHILD, A_CHILD,
A_DESCENDANT, A_DESCENDANT,
A_DESCENDANT_OR_SELF, A_DESCENDANT_OR_SELF,
A_FOLLOWING, A_FOLLOWING,
A_FOLLOWING_SIBLING, A_FOLLOWING_SIBLING,
A_NAMESPACE, A_NAMESPACE,
A_PARENT, A_PARENT,
A_PRECEDING, A_PRECEDING,
@ -103,9 +103,10 @@ enum xp_type{
}; };
/*! XPATH Parsing generates a tree of nodes that is later traversed /*! XPATH Parsing generates a tree of nodes that is later traversed
* That is, a tree-structured XPATH. *
* Note that the structure follows XPATH 1.0 closely. The drawback wit this is that the tree gets * That is, a tree-structured XPath.
* very deep very quickly, even for simple XPATHs. * Note that the structure follows XPath 1.0 closely. The drawback wit this is that the tree gets
* very deep very quickly, even for simple XPaths.
*/ */
struct xpath_tree{ struct xpath_tree{
enum xp_type xs_type; enum xp_type xs_type;
@ -136,7 +137,7 @@ int xpath_parse(const char *xpath, xpath_tree **xptree);
int xpath_vec_ctx(cxobj *xcur, cvec *nsc, const char *xpath, int localonly, xp_ctx **xrp); int xpath_vec_ctx(cxobj *xcur, cvec *nsc, const char *xpath, int localonly, xp_ctx **xrp);
int xpath_vec_bool(cxobj *xcur, cvec *nsc, const char *xpformat, ...) __attribute__ ((format (printf, 3, 4))); int xpath_vec_bool(cxobj *xcur, cvec *nsc, const char *xpformat, ...) __attribute__ ((format (printf, 3, 4)));
int xpath_vec_flag(cxobj *xcur, cvec *nsc, const char *xpformat, uint16_t flags, int xpath_vec_flag(cxobj *xcur, cvec *nsc, const char *xpformat, uint16_t flags,
cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 7))); cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 3, 7)));
/* Functions with explicit namespace context (nsc) set. If you do not need /* Functions with explicit namespace context (nsc) set. If you do not need

Some files were not shown because too many files have changed in this diff Show more