C-style update: Unified comment, retvals in order, remove trailing spaces
Changed function name for `clicon_debug` functions
This commit is contained in:
parent
6e314dd96f
commit
62348fc9c7
204 changed files with 6047 additions and 4904 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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_ */
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_ */
|
||||||
|
|
|
||||||
|
|
@ -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..
|
||||||
|
|
|
||||||
|
|
@ -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){
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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], '=', ¶m, &val) < 0)
|
if (clixon_strsplit(envp[i], '=', ¶m, &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){
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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++) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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){
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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] */
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -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_ */
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue