Netconf monitoring RFC 6022 Sessions (https://github.com/clicon/clixon/issues/370)
- statistics and transport/source-host parameters - extended internal NETCONF hello with transport and source-host attributes clixon-lib,yang - Moved all extended internal NETCONF attributes to the clicon-lib namespace C-API: - wrapped most attribute creation into new fn xml_add_attr()
This commit is contained in:
parent
7558d40faa
commit
3916fa919c
36 changed files with 883 additions and 402 deletions
|
|
@ -44,8 +44,8 @@ Expected: beginning of 2023
|
||||||
### New features
|
### New features
|
||||||
|
|
||||||
* Netconf monitoring, part 2
|
* Netconf monitoring, part 2
|
||||||
* Datastores
|
* Datastores and sessions
|
||||||
* Remaining: sessions and statistics state
|
* Remaining: statistics state
|
||||||
* Standards
|
* Standards
|
||||||
* RFC 6022 "YANG Module for NETCONF Monitoring"
|
* RFC 6022 "YANG Module for NETCONF Monitoring"
|
||||||
* See [Feature Request: Support RFC 6022 (NETCONF Monitoring)](https://github.com/clicon/clixon/issues/370)
|
* See [Feature Request: Support RFC 6022 (NETCONF Monitoring)](https://github.com/clicon/clixon/issues/370)
|
||||||
|
|
@ -54,6 +54,9 @@ Expected: beginning of 2023
|
||||||
|
|
||||||
Users may have to change how they access the system
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* clixon-lib,yang
|
||||||
|
* Moved all extended internal NETCONF attributes to the clicon-lib namespace
|
||||||
|
* The internal attributes are documented in https://clixon-docs.readthedocs.io/en/latest/netconf.html
|
||||||
* With-defaults default retrieval mode has changed from `REPORT-ALL` to `EXPLICIT`
|
* With-defaults default retrieval mode has changed from `REPORT-ALL` to `EXPLICIT`
|
||||||
* This means that all get operations without `with-defaults` parameter do no longer
|
* This means that all get operations without `with-defaults` parameter do no longer
|
||||||
return implicit default values, only explicitly set values.
|
return implicit default values, only explicitly set values.
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
*/
|
*/
|
||||||
static struct client_entry *
|
static struct client_entry *
|
||||||
ce_find_byid(struct client_entry *ce_list,
|
ce_find_byid(struct client_entry *ce_list,
|
||||||
uint32_t id)
|
uint32_t id)
|
||||||
{
|
{
|
||||||
struct client_entry *ce;
|
struct client_entry *ce;
|
||||||
|
|
||||||
|
|
@ -154,6 +154,81 @@ release_all_dbs(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get backend-specific client netconf monitoring state
|
||||||
|
*
|
||||||
|
* Backend-specific netconf monitoring state is:
|
||||||
|
* sessions
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[in] xpath XML Xpath
|
||||||
|
* @param[in] nsc XML Namespace context for xpath
|
||||||
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
|
* @param[out] xerr XML error tree, if retval = 0
|
||||||
|
* @retval -1 Error (fatal)
|
||||||
|
* @retval 0 Statedata callback failed, error in xerr
|
||||||
|
* @retval 1 OK
|
||||||
|
* @see RFC 6022
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
backend_monitoring_state_get(clicon_handle h,
|
||||||
|
yang_stmt *yspec,
|
||||||
|
char *xpath,
|
||||||
|
cvec *nsc,
|
||||||
|
cxobj **xret,
|
||||||
|
cxobj **xerr)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
struct client_entry *ce;
|
||||||
|
char timestr[28];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) ==NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cprintf(cb, "<netconf-state xmlns=\"%s\">", NETCONF_MONITORING_NAMESPACE);
|
||||||
|
cprintf(cb, "<sessions>");
|
||||||
|
for (ce = backend_client_list(h); ce; ce = ce->ce_next){
|
||||||
|
cprintf(cb, "<session>");
|
||||||
|
cprintf(cb, "<session-id>%u</session-id>", ce->ce_id);
|
||||||
|
if (ce->ce_transport)
|
||||||
|
cprintf(cb, "<transport xmlns:%s=\"%s\">%s</transport>",
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS,
|
||||||
|
ce->ce_transport);
|
||||||
|
cprintf(cb, "<username>%s</username>", ce->ce_username);
|
||||||
|
if (ce->ce_source_host)
|
||||||
|
cprintf(cb, "<source-host>%s</source-host>", ce->ce_source_host);
|
||||||
|
if (ce->ce_time.tv_sec != 0){
|
||||||
|
if (time2str(ce->ce_time, timestr, sizeof(timestr)) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "time2str");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cprintf(cb, "<login-time>%s</login-time>", timestr);
|
||||||
|
}
|
||||||
|
cprintf(cb, "<in-rpcs>%u</in-rpcs>", ce->ce_in_rpcs);
|
||||||
|
cprintf(cb, "<in-bad-rpcs>%u</in-bad-rpcs>", ce->ce_in_bad_rpcs);
|
||||||
|
cprintf(cb, "<out-rpc-errors>%u</out-rpc-errors>", ce->ce_out_rpc_errors);
|
||||||
|
cprintf(cb, "<out-notifications>%u</out-notifications>", 0);
|
||||||
|
cprintf(cb, "</session>");
|
||||||
|
}
|
||||||
|
cprintf(cb, "</sessions>");
|
||||||
|
cprintf(cb, "</netconf-state>");
|
||||||
|
if ((ret = clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, xerr)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0)
|
||||||
|
goto fail;
|
||||||
|
retval = 1;
|
||||||
|
done:
|
||||||
|
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
fail:
|
||||||
|
retval = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Remove client entry state
|
/*! Remove client entry state
|
||||||
* Close down everything wrt clients (eg sockets, subscriptions)
|
* Close down everything wrt clients (eg sockets, subscriptions)
|
||||||
* Finally actually remove client struct in handle
|
* Finally actually remove client struct in handle
|
||||||
|
|
@ -451,7 +526,7 @@ from_client_edit_config(clicon_handle h,
|
||||||
xmldb_modified_set(h, target, 1); /* mark as dirty */
|
xmldb_modified_set(h, target, 1); /* mark as dirty */
|
||||||
/* Clixon extension: autocommit */
|
/* Clixon extension: autocommit */
|
||||||
if ((attr = xml_find_value(xn, "autocommit")) != NULL &&
|
if ((attr = xml_find_value(xn, "autocommit")) != NULL &&
|
||||||
strcmp(attr,"true")==0)
|
strcmp(attr,"true") == 0)
|
||||||
autocommit = 1;
|
autocommit = 1;
|
||||||
/* If autocommit option is set or requested by client */
|
/* If autocommit option is set or requested by client */
|
||||||
if (clicon_autocommit(h) || autocommit) {
|
if (clicon_autocommit(h) || autocommit) {
|
||||||
|
|
@ -513,7 +588,9 @@ from_client_edit_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok", NETCONF_BASE_NAMESPACE);
|
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok", NETCONF_BASE_NAMESPACE);
|
||||||
if (clicon_data_get(h, "objectexisted", &val) == 0)
|
if (clicon_data_get(h, "objectexisted", &val) == 0)
|
||||||
cprintf(cbret, " objectexisted=\"%s\"", val);
|
cprintf(cbret, " %s:objectexisted=\"%s\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX, val,
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
cprintf(cbret, "/></rpc-reply>");
|
cprintf(cbret, "/></rpc-reply>");
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1375,6 +1452,11 @@ from_client_process_control(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Clixon hello to check liveness
|
/*! Clixon hello to check liveness
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] x Incoming XML of hello request
|
||||||
|
* @param[in] ce Client entry (from)
|
||||||
|
* @param[out] cbret Hello reply
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
|
|
@ -1386,11 +1468,24 @@ from_client_hello(clicon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
char *val;
|
||||||
|
|
||||||
if (clicon_session_id_get(h, &id) < 0){
|
if (clicon_session_id_get(h, &id) < 0){
|
||||||
clicon_err(OE_NETCONF, ENOENT, "session_id not set");
|
clicon_err(OE_NETCONF, ENOENT, "session_id not set");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if ((val = xml_find_type_value(x, "cl", "transport", CX_ATTR)) != NULL){
|
||||||
|
if ((ce->ce_transport = strdup(val)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((val = xml_find_type_value(x, "cl", "source-host", CX_ATTR)) != NULL){
|
||||||
|
if ((ce->ce_source_host = strdup(val)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
id++;
|
id++;
|
||||||
clicon_session_id_set(h, id);
|
clicon_session_id_set(h, id);
|
||||||
cprintf(cbret, "<hello xmlns=\"%s\"><session-id>%u</session-id></hello>",
|
cprintf(cbret, "<hello xmlns=\"%s\"><session-id>%u</session-id></hello>",
|
||||||
|
|
@ -1498,7 +1593,7 @@ from_client_msg(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(rpcname, "rpc") == 0){
|
if (strcmp(rpcname, "rpc") == 0){
|
||||||
; /* continue below */
|
ce->ce_in_rpcs++; /* Track all RPCs */
|
||||||
}
|
}
|
||||||
else if (strcmp(rpcname, "hello") == 0){
|
else if (strcmp(rpcname, "hello") == 0){
|
||||||
if ((ret = from_client_hello(h, x, ce, cbret)) <0)
|
if ((ret = from_client_hello(h, x, ce, cbret)) <0)
|
||||||
|
|
@ -1508,9 +1603,12 @@ from_client_msg(clicon_handle h,
|
||||||
else{
|
else{
|
||||||
if (netconf_unknown_element(cbret, "protocol", rpcname, "Unrecognized netconf operation")< 0)
|
if (netconf_unknown_element(cbret, "protocol", rpcname, "Unrecognized netconf operation")< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
ce->ce_in_bad_rpcs++;
|
||||||
|
ce->ce_out_rpc_errors++; /* Number of <rpc-reply> messages sent that contained an <rpc-error> */
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
ce->ce_id = id;
|
ce->ce_id = id;
|
||||||
|
|
||||||
/* As a side-effect, this expands xt with default values according to "report-all"
|
/* As a side-effect, this expands xt with default values according to "report-all"
|
||||||
* This may not be correct, the RFC does not mention expanding default values for
|
* This may not be correct, the RFC does not mention expanding default values for
|
||||||
* input RPC
|
* input RPC
|
||||||
|
|
@ -1520,6 +1618,8 @@ from_client_msg(clicon_handle h,
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, -1, 0) < 0)
|
if (clixon_xml2cbuf(cbret, xret, 0, 0, -1, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
ce->ce_in_bad_rpcs++;
|
||||||
|
ce->ce_in_rpcs--; /* Track all RPCs */
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
xe = NULL;
|
xe = NULL;
|
||||||
|
|
@ -1531,6 +1631,7 @@ from_client_msg(clicon_handle h,
|
||||||
if ((ye = xml_spec(xe)) == NULL){
|
if ((ye = xml_spec(xe)) == NULL){
|
||||||
if (netconf_operation_not_supported(cbret, "protocol", rpc) < 0)
|
if (netconf_operation_not_supported(cbret, "protocol", rpc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
ce->ce_out_rpc_errors++;
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
if ((ymod = ys_module(ye)) == NULL){
|
if ((ymod = ys_module(ye)) == NULL){
|
||||||
|
|
@ -1557,26 +1658,34 @@ from_client_msg(clicon_handle h,
|
||||||
creds = clicon_nacm_credentials(h);
|
creds = clicon_nacm_credentials(h);
|
||||||
if ((ret = verify_nacm_user(h, creds, ce->ce_username, username, cbret)) < 0)
|
if ((ret = verify_nacm_user(h, creds, ce->ce_username, username, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0) /* credentials fail */
|
if (ret == 0){ /* credentials fail */
|
||||||
|
ce->ce_out_rpc_errors++;
|
||||||
goto reply;
|
goto reply;
|
||||||
|
}
|
||||||
/* NACM rpc operation exec validation */
|
/* NACM rpc operation exec validation */
|
||||||
if ((ret = nacm_rpc(rpc, module, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_rpc(rpc, module, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0) /* Not permitted and cbret set */
|
if (ret == 0){ /* Not permitted and cbret set */
|
||||||
|
ce->ce_out_rpc_errors++;
|
||||||
goto reply;
|
goto reply;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clicon_err_reset();
|
clicon_err_reset();
|
||||||
if ((ret = rpc_callback_call(h, xe, ce, &nr, cbret)) < 0){
|
if ((ret = rpc_callback_call(h, xe, ce, &nr, cbret)) < 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;
|
||||||
clicon_log(LOG_NOTICE, "%s Error in rpc_callback_call:%s", __FUNCTION__, xml_name(xe));
|
clicon_log(LOG_NOTICE, "%s Error in rpc_callback_call:%s", __FUNCTION__, xml_name(xe));
|
||||||
|
ce->ce_out_rpc_errors++;
|
||||||
goto reply; /* Dont quit here on user callbacks */
|
goto reply; /* Dont quit here on user callbacks */
|
||||||
}
|
}
|
||||||
if (ret == 0)
|
if (ret == 0){
|
||||||
|
ce->ce_out_rpc_errors++;
|
||||||
goto reply;
|
goto reply;
|
||||||
|
}
|
||||||
if (nr == 0){ /* not handled by callback */
|
if (nr == 0){ /* not handled by callback */
|
||||||
if (netconf_operation_not_supported(cbret, "application", "RPC operation not supported")< 0)
|
if (netconf_operation_not_supported(cbret, "application", "RPC operation not supported")< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
ce->ce_out_rpc_errors++;
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
if (xnacm){
|
if (xnacm){
|
||||||
|
|
|
||||||
|
|
@ -41,24 +41,33 @@
|
||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Client entry.
|
* Backend client entry.
|
||||||
* Keep state about every connected client.
|
* Keep state about every connected client.
|
||||||
|
* References from RFC 6022, ietf-netconf-monitoring.yang sessions container
|
||||||
*/
|
*/
|
||||||
struct client_entry{
|
struct client_entry{
|
||||||
struct client_entry *ce_next; /* The clients linked list */
|
struct client_entry *ce_next; /* The clients linked list */
|
||||||
struct sockaddr ce_addr; /* The clients (UNIX domain) address */
|
struct sockaddr ce_addr; /* The clients (UNIX domain) address */
|
||||||
int ce_s; /* stream socket to client */
|
int ce_s; /* stream socket to client */
|
||||||
int ce_nr; /* Client number (for dbg/tracing) */
|
int ce_nr; /* Client number (for dbg/tracing) */
|
||||||
int ce_stat_in; /* Nr of received msgs from client */
|
|
||||||
int ce_stat_out;/* Nr of sent msgs to client */
|
|
||||||
uint32_t ce_id; /* Session id, accessor functions: clicon_session_id_get/set */
|
uint32_t ce_id; /* Session id, accessor functions: clicon_session_id_get/set */
|
||||||
char *ce_username;/* Translated from peer user cred */
|
char *ce_username;/* Translated from peer user cred */
|
||||||
clicon_handle ce_handle; /* clicon config handle (all clients have same?) */
|
clicon_handle ce_handle; /* clicon config handle (all clients have same?) */
|
||||||
|
char *ce_transport; /* Identifies the transport for each session.
|
||||||
|
Clixon-lib.yang extends these values by prefixing with
|
||||||
|
"cl:", where cl is ensured to be declared ie by
|
||||||
|
netconf-monitoring state */
|
||||||
|
char *ce_source_host; /* Host identifier of the NETCONF client */
|
||||||
|
struct timeval ce_time; /* Time at the server at which the session was established. */
|
||||||
|
uint32_t ce_in_rpcs ; /* Number of correct <rpc> messages received. */
|
||||||
|
uint32_t ce_in_bad_rpcs; /* Not correct <rpc> messages */
|
||||||
|
uint32_t ce_out_rpc_errors; /* <rpc-error> messages*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
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);
|
||||||
int backend_rpc_init(clicon_handle h);
|
int backend_rpc_init(clicon_handle h);
|
||||||
|
|
|
||||||
|
|
@ -181,10 +181,22 @@ client_get_streams(clicon_handle h,
|
||||||
* @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
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this
|
* @param[in,out] xret Existing XML tree, merge x into this, or rpc-error
|
||||||
* @retval -1 Error (fatal)
|
* @retval -1 Error (fatal)
|
||||||
* @retval 0 Statedata callback failed (clicon_err called)
|
* @retval 0 Statedata callback failed (error in xret)
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
|
* @note This code in general does not look at xpath, needs to be filtered in retrospect
|
||||||
|
* @note Awkward error handling. Even if most of this is during development phase, except for plugin
|
||||||
|
* state callbacks.
|
||||||
|
* Present behavior:
|
||||||
|
* - Present behavior: should be returned in xret with retval 0(error) or 1(ok)
|
||||||
|
* - On error, previous content of xret is not freed
|
||||||
|
* - xret is in turn translated to cbuf in calling function
|
||||||
|
* Instead, I think there should be a second out argument **xerr with the error message, see code
|
||||||
|
* for CLICON_NETCONF_MONITORING which is transformed in calling function(?) to an internal error
|
||||||
|
* message. But this needs to be explored in all sub-functions
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_client_statedata(clicon_handle h,
|
get_client_statedata(clicon_handle h,
|
||||||
|
|
@ -196,9 +208,11 @@ get_client_statedata(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
|
cxobj *x1 = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
char *namespace;
|
char *namespace;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
|
cxobj *xerr = NULL;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
|
|
@ -236,7 +250,6 @@ get_client_statedata(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cbuf_reset(cb);
|
cbuf_reset(cb);
|
||||||
/* XXX This code does not filter state data with xpath */
|
|
||||||
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
||||||
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -254,7 +267,32 @@ get_client_statedata(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_NETCONF_MONITORING")){
|
if (clicon_option_bool(h, "CLICON_NETCONF_MONITORING")){
|
||||||
if ((ret = netconf_monitoring_state_get(h, yspec, xpath, nsc, 0, xret)) < 0)
|
if ((ret = netconf_monitoring_state_get(h, yspec, xpath, nsc, xret, &xerr)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
if (clixon_netconf_internal_error(xerr, " . Internal error, netconf_monitoring_state returned invalid XML", NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (*xret)
|
||||||
|
xml_free(*xret);
|
||||||
|
*xret = xerr;
|
||||||
|
xerr = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* Some state, client state, is avaliable in backend only, not in lib
|
||||||
|
* Needs merge since same subtree as previous lib state
|
||||||
|
*/
|
||||||
|
if ((ret = backend_monitoring_state_get(h, yspec, xpath, nsc, &x1, &xerr)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
if (clixon_netconf_internal_error(xerr, " . Internal error, baenckend_monitoring_state_get returned invalid XML", NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (*xret)
|
||||||
|
xml_free(*xret);
|
||||||
|
*xret = xerr;
|
||||||
|
xerr = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((ret = netconf_trymerge(x1, yspec, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -320,6 +358,10 @@ get_client_statedata(clicon_handle h,
|
||||||
retval = 1; /* OK */
|
retval = 1; /* OK */
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||||
|
if (xerr)
|
||||||
|
xml_free(xerr);
|
||||||
|
if (x1)
|
||||||
|
xml_free(x1);
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -734,19 +776,13 @@ get_list_pagination(clicon_handle h,
|
||||||
cbuf *cba = NULL;
|
cbuf *cba = NULL;
|
||||||
|
|
||||||
/* Add remaining attribute */
|
/* Add remaining attribute */
|
||||||
if ((xa = xml_new("remaining", x1, CX_ATTR)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if ((cba = cbuf_new()) == NULL){
|
if ((cba = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cba, "%u", remaining);
|
cprintf(cba, "%u", remaining);
|
||||||
if (xml_value_set(xa, cbuf_get(cba)) < 0)
|
if (xml_add_attr(x1, "remaining", cbuf_get(cba), "cp", "http://clicon.org/clixon-netconf-list-pagination") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_prefix_set(xa, "cp") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xmlns_set(x1, "cp", "http://clicon.org/clixon-netconf-list-pagination") < 0)
|
|
||||||
goto done;
|
|
||||||
if (cba)
|
if (cba)
|
||||||
cbuf_free(cba);
|
cbuf_free(cba);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,6 @@ 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;
|
||||||
ce->ce_handle = h;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get credentials of connected peer - only for unix socket
|
* Get credentials of connected peer - only for unix socket
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,8 @@ backend_client_add(clicon_handle h,
|
||||||
ce->ce_nr = bh->bh_ce_nr++; /* Session-id ? */
|
ce->ce_nr = bh->bh_ce_nr++; /* Session-id ? */
|
||||||
memcpy(&ce->ce_addr, addr, sizeof(*addr));
|
memcpy(&ce->ce_addr, addr, sizeof(*addr));
|
||||||
ce->ce_next = bh->bh_ce_list;
|
ce->ce_next = bh->bh_ce_list;
|
||||||
|
ce->ce_handle = h;
|
||||||
|
gettimeofday(&ce->ce_time, NULL);
|
||||||
bh->bh_ce_list = ce;
|
bh->bh_ce_list = ce;
|
||||||
return ce;
|
return ce;
|
||||||
}
|
}
|
||||||
|
|
@ -180,6 +182,10 @@ backend_client_delete(clicon_handle h,
|
||||||
*ce_prev = c->ce_next;
|
*ce_prev = c->ce_next;
|
||||||
if (ce->ce_username)
|
if (ce->ce_username)
|
||||||
free(ce->ce_username);
|
free(ce->ce_username);
|
||||||
|
if (ce->ce_transport)
|
||||||
|
free(ce->ce_transport);
|
||||||
|
if (ce->ce_source_host)
|
||||||
|
free(ce->ce_source_host);
|
||||||
free(ce);
|
free(ce);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +209,9 @@ backend_client_print(clicon_handle h,
|
||||||
fprintf(f, "Client: %d\n", ce->ce_nr);
|
fprintf(f, "Client: %d\n", ce->ce_nr);
|
||||||
fprintf(f, " Session: %d\n", ce->ce_id);
|
fprintf(f, " Session: %d\n", ce->ce_id);
|
||||||
fprintf(f, " Socket: %d\n", ce->ce_s);
|
fprintf(f, " Socket: %d\n", ce->ce_s);
|
||||||
fprintf(f, " Msgs in: %d\n", ce->ce_stat_in);
|
fprintf(f, " RPCs in: %u\n", ce->ce_in_rpcs);
|
||||||
fprintf(f, " Msgs out: %d\n", ce->ce_stat_out);
|
fprintf(f, " Bad RPCs in: %u\n", ce->ce_in_bad_rpcs);
|
||||||
|
fprintf(f, " Err RPCs out: %u\n", ce->ce_out_rpc_errors);
|
||||||
fprintf(f, " Username: %s\n", ce->ce_username);
|
fprintf(f, " Username: %s\n", ce->ce_username);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,6 @@ cli_dbxml(clicon_handle h,
|
||||||
cxobj *xbot = NULL; /* xpath, NULL if datastore */
|
cxobj *xbot = NULL; /* xpath, NULL if datastore */
|
||||||
yang_stmt *y = NULL; /* yang spec of xpath */
|
yang_stmt *y = NULL; /* yang spec of xpath */
|
||||||
cxobj *xtop = NULL; /* xpath root */
|
cxobj *xtop = NULL; /* xpath root */
|
||||||
cxobj *xa; /* attribute */
|
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
|
@ -338,11 +337,7 @@ cli_dbxml(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((xa = xml_new("operation", xbot, CX_ATTR)) == NULL)
|
if (xml_add_attr(xbot, "operation", xml_operation2str(op), NETCONF_BASE_PREFIX, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xa, NETCONF_BASE_PREFIX) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, xml_operation2str(op)) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
/* Add body last in case of leaf */
|
/* Add body last in case of leaf */
|
||||||
if (cvec_len(cvv) > 1 &&
|
if (cvec_len(cvv) > 1 &&
|
||||||
|
|
|
||||||
|
|
@ -818,7 +818,12 @@ main(int argc,
|
||||||
if (evalresult < 0)
|
if (evalresult < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
/* Set RFC6022 session parameters that will be sent in first hello,
|
||||||
|
* @see clicon_hello_req
|
||||||
|
*/
|
||||||
|
clicon_data_set(h, "session-transport", "cl:cli");
|
||||||
|
clicon_data_set(h, "session-source-host", "localhost");
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,15 @@ netconf_add_request_attr(cxobj *xrpc,
|
||||||
/* If attribute already exists, dont copy it */
|
/* If attribute already exists, dont copy it */
|
||||||
if (xml_find_type(xrep, NULL, xml_name(xa), CX_ATTR) != NULL)
|
if (xml_find_type(xrep, NULL, xml_name(xa), CX_ATTR) != NULL)
|
||||||
continue; /* Skip already present (dont overwrite) */
|
continue; /* Skip already present (dont overwrite) */
|
||||||
|
/* Filter all clixon-lib attributes and namespace declaration
|
||||||
|
* to acvoid leaking internal attributes to external NETCONF
|
||||||
|
* note this is only done on top-level.
|
||||||
|
*/
|
||||||
|
if (xml_prefix(xa) && strcmp(xml_prefix(xa), CLIXON_LIB_PREFIX) == 0)
|
||||||
|
continue;
|
||||||
|
if (xml_prefix(xa) && strcmp(xml_prefix(xa), "xmlns") == 0 &&
|
||||||
|
strcmp(xml_name(xa), CLIXON_LIB_PREFIX) == 0)
|
||||||
|
continue;
|
||||||
if ((xa2 = xml_dup(xa)) ==NULL)
|
if ((xa2 = xml_dup(xa)) ==NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_addsub(xrep, xa2) < 0)
|
if (xml_addsub(xrep, xa2) < 0)
|
||||||
|
|
@ -192,11 +201,11 @@ netconf_rpc_message(clicon_handle h,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
int *eof)
|
int *eof)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xret = NULL; /* Return (out) */
|
cxobj *xret = NULL; /* Return (out) */
|
||||||
int ret;
|
int ret;
|
||||||
cbuf *cbret = NULL;
|
cbuf *cbret = NULL;
|
||||||
cxobj *xc;
|
cxobj *xc;
|
||||||
netconf_framing_type framing;
|
netconf_framing_type framing;
|
||||||
|
|
||||||
framing = clicon_option_int(h, "netconf-framing");
|
framing = clicon_option_int(h, "netconf-framing");
|
||||||
|
|
@ -240,9 +249,9 @@ netconf_rpc_message(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (netconf_rpc_dispatch(h, xrpc, &xret, eof) < 0){
|
if (netconf_rpc_dispatch(h, xrpc, &xret, eof) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
/* Is there a return message in xret? */
|
/* Is there a return message in xret? */
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
if (netconf_operation_failed_xml(&xret, "rpc", "Internal error: no xml return")< 0)
|
if (netconf_operation_failed_xml(&xret, "rpc", "Internal error: no xml return")< 0)
|
||||||
|
|
@ -988,7 +997,7 @@ main(int argc,
|
||||||
* used by the client, even though new TCP sessions are created for
|
* used by the client, even though new TCP sessions are created for
|
||||||
* each message sent to the backend.
|
* each message sent to the backend.
|
||||||
*/
|
*/
|
||||||
if (clicon_hello_req(h, &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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -704,9 +704,7 @@ netconf_rpc_dispatch(clicon_handle h,
|
||||||
* 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?
|
||||||
*/
|
*/
|
||||||
if ((username = clicon_username_get(h)) != NULL){
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
if ((xa = xml_new("username", xn, CX_ATTR)) == NULL)
|
if (xml_add_attr(xn, "username", username, CLIXON_LIB_PREFIX, CLIXON_LIB_NS) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, username) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Many of these calls are now calling generic clicon_rpc_netconf_xml
|
/* Many of these calls are now calling generic clicon_rpc_netconf_xml
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,6 @@ restconf_insert_attributes(cxobj *xdata,
|
||||||
cvec *qvec)
|
cvec *qvec)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xa;
|
|
||||||
char *instr;
|
char *instr;
|
||||||
char *pstr;
|
char *pstr;
|
||||||
yang_stmt *y;
|
yang_stmt *y;
|
||||||
|
|
@ -422,12 +421,7 @@ restconf_insert_attributes(cxobj *xdata,
|
||||||
/* First add xmlns:yang attribute */
|
/* First add xmlns:yang attribute */
|
||||||
if (xmlns_set(xdata, "yang", YANG_XML_NAMESPACE) < 0)
|
if (xmlns_set(xdata, "yang", YANG_XML_NAMESPACE) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Then add insert attribute */
|
if (xml_add_attr(xdata, "insert", instr, "yang", NULL) < 0)
|
||||||
if ((xa = xml_new("insert", xdata, CX_ATTR)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xa, "yang") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, instr) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((pstr = cvec_find_str(qvec, "point")) != NULL){
|
if ((pstr = cvec_find_str(qvec, "point")) != NULL){
|
||||||
|
|
@ -439,11 +433,7 @@ restconf_insert_attributes(cxobj *xdata,
|
||||||
attrname="key";
|
attrname="key";
|
||||||
else
|
else
|
||||||
attrname="value";
|
attrname="value";
|
||||||
/* Then add value/key attribute */
|
|
||||||
if ((xa = xml_new(attrname, xdata, CX_ATTR)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xa, "yang") < 0)
|
|
||||||
goto done;
|
|
||||||
if ((ret = api_path2xpath(pstr, ys_spec(y), &xpath, &nsc, NULL)) < 0)
|
if ((ret = api_path2xpath(pstr, ys_spec(y), &xpath, &nsc, NULL)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
|
@ -471,7 +461,7 @@ restconf_insert_attributes(cxobj *xdata,
|
||||||
p++;
|
p++;
|
||||||
cprintf(cb, "%s", p);
|
cprintf(cb, "%s", p);
|
||||||
}
|
}
|
||||||
if (xml_value_set(xa, cbuf_get(cb)) < 0)
|
if (xml_add_attr(xdata, attrname, cbuf_get(cb), "yang", NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Add prefix/namespaces used in attributes */
|
/* Add prefix/namespaces used in attributes */
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ restconf_main_config(clicon_handle h,
|
||||||
else {
|
else {
|
||||||
/* Loop to wait for backend starting, try again if not done */
|
/* Loop to wait for backend starting, try again if not done */
|
||||||
while (1){
|
while (1){
|
||||||
if (clicon_hello_req(h, &id) < 0){
|
if (clicon_hello_req(h, "cl:restconf", NULL, &id) < 0){
|
||||||
if (errno == ENOENT){
|
if (errno == ENOENT){
|
||||||
fprintf(stderr, "waiting");
|
fprintf(stderr, "waiting");
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,7 @@ restconf_clixon_backend(clicon_handle h,
|
||||||
|
|
||||||
/* Loop to wait for backend starting, try again if not done */
|
/* Loop to wait for backend starting, try again if not done */
|
||||||
while (1){
|
while (1){
|
||||||
if (clicon_hello_req(h, &id) < 0){
|
if (clicon_hello_req(h, "cl:restconf", NULL, &id) < 0){
|
||||||
if (errno == ENOENT){
|
if (errno == ENOENT){
|
||||||
fprintf(stderr, "waiting");
|
fprintf(stderr, "waiting");
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
|
||||||
|
|
@ -384,24 +384,12 @@ api_data_write(clicon_handle h,
|
||||||
/* Add operation create as attribute. If that fails with Conflict, then
|
/* Add operation create as attribute. If that fails with Conflict, then
|
||||||
* try "replace" (see comment in function header)
|
* try "replace" (see comment in function header)
|
||||||
*/
|
*/
|
||||||
if ((xa = xml_new("operation", xdata, CX_ATTR)) == NULL)
|
if (xml_add_attr(xdata, "operation", xml_operation2str(op), NETCONF_BASE_PREFIX, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_prefix_set(xa, NETCONF_BASE_PREFIX) < 0)
|
if (xml_add_attr(xdata, "objectcreate",
|
||||||
|
plain_patch?"false":"true",
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_value_set(xa, xml_operation2str(op)) < 0) /* XXX here is where op is used */
|
|
||||||
goto done;
|
|
||||||
if ((xa = xml_new("objectcreate", xdata, CX_ATTR)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (plain_patch){
|
|
||||||
/* RFC 8040 4.6. PATCH:
|
|
||||||
* If the target resource instance does not exist, the server MUST NOT create it.
|
|
||||||
*/
|
|
||||||
if (xml_value_set(xa, "false") < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (xml_value_set(xa, "true") < 0)
|
|
||||||
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
|
||||||
*/
|
*/
|
||||||
|
|
@ -512,16 +500,20 @@ api_data_write(clicon_handle h,
|
||||||
} /* api-path != NULL */
|
} /* api-path != NULL */
|
||||||
/* For internal XML protocol: add username attribute for access control
|
/* For internal XML protocol: add username attribute for access control
|
||||||
*/
|
*/
|
||||||
username = clicon_username_get(h);
|
|
||||||
/* Create text buffer for transfer to backend */
|
/* Create text buffer for transfer to backend */
|
||||||
if ((cbx = cbuf_new()) == NULL)
|
if ((cbx = cbuf_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cbx, "<rpc xmlns=\"%s\" username=\"%s\" xmlns:%s=\"%s\" %s>",
|
cprintf(cbx, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_BASE_NAMESPACE,
|
cprintf(cbx, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
username?username:"",
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cbx, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cbx, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cbx, " xmlns:%s=\"%s\"",
|
||||||
NETCONF_BASE_PREFIX,
|
NETCONF_BASE_PREFIX,
|
||||||
NETCONF_BASE_NAMESPACE, /* bind nc to netconf namespace */
|
NETCONF_BASE_NAMESPACE); /* bind nc to netconf namespace */
|
||||||
NETCONF_MESSAGE_ID_ATTR);
|
cprintf(cbx, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cbx, ">");
|
||||||
cprintf(cbx, "<edit-config");
|
cprintf(cbx, "<edit-config");
|
||||||
/* RFC8040 Sec 1.4:
|
/* RFC8040 Sec 1.4:
|
||||||
* If this is a "data" request and the NETCONF server supports :startup,
|
* If this is a "data" request and the NETCONF server supports :startup,
|
||||||
|
|
@ -532,9 +524,11 @@ api_data_write(clicon_handle h,
|
||||||
if ((IETF_DS_NONE == ds) &&
|
if ((IETF_DS_NONE == ds) &&
|
||||||
if_feature(yspec, "ietf-netconf", "startup") &&
|
if_feature(yspec, "ietf-netconf", "startup") &&
|
||||||
!clicon_option_bool(h, "CLICON_RESTCONF_STARTUP_DONTUPDATE")){
|
!clicon_option_bool(h, "CLICON_RESTCONF_STARTUP_DONTUPDATE")){
|
||||||
cprintf(cbx, " copystartup=\"true\"");
|
cprintf(cbx, " %s:copystartup=\"true\"", CLIXON_LIB_PREFIX);
|
||||||
|
cprintf(cbx, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
}
|
}
|
||||||
cprintf(cbx, " autocommit=\"true\"");
|
cprintf(cbx, " %s:autocommit=\"true\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
cprintf(cbx, "><target><candidate /></target>");
|
cprintf(cbx, "><target><candidate /></target>");
|
||||||
cprintf(cbx, "<default-operation>none</default-operation>");
|
cprintf(cbx, "<default-operation>none</default-operation>");
|
||||||
if (clixon_xml2cbuf(cbx, xtop, 0, 0, -1, 0) < 0)
|
if (clixon_xml2cbuf(cbx, xtop, 0, 0, -1, 0) < 0)
|
||||||
|
|
@ -759,14 +753,17 @@ api_data_delete(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
/* For internal XML protocol: add username attribute for access control
|
/* For internal XML protocol: add username attribute for access control
|
||||||
*/
|
*/
|
||||||
username = clicon_username_get(h);
|
cprintf(cbx, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cbx, "<rpc xmlns=\"%s\" username=\"%s\" xmlns:%s=\"%s\" %s>",
|
cprintf(cbx, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_BASE_NAMESPACE,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
username?username:"",
|
cprintf(cbx, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cbx, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cbx, " xmlns:%s=\"%s\"",
|
||||||
NETCONF_BASE_PREFIX,
|
NETCONF_BASE_PREFIX,
|
||||||
NETCONF_BASE_NAMESPACE,
|
NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR); /* bind nc to netconf namespace */
|
cprintf(cbx, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cbx, ">");
|
||||||
cprintf(cbx, "<edit-config");
|
cprintf(cbx, "<edit-config");
|
||||||
/* RFC8040 Sec 1.4:
|
/* RFC8040 Sec 1.4:
|
||||||
* If this is a "data" request and the NETCONF server supports :startup,
|
* If this is a "data" request and the NETCONF server supports :startup,
|
||||||
|
|
@ -777,9 +774,11 @@ api_data_delete(clicon_handle h,
|
||||||
if ((IETF_DS_NONE == ds) &&
|
if ((IETF_DS_NONE == ds) &&
|
||||||
if_feature(yspec, "ietf-netconf", "startup") &&
|
if_feature(yspec, "ietf-netconf", "startup") &&
|
||||||
!clicon_option_bool(h, "CLICON_RESTCONF_STARTUP_DONTUPDATE")){
|
!clicon_option_bool(h, "CLICON_RESTCONF_STARTUP_DONTUPDATE")){
|
||||||
cprintf(cbx, " copystartup=\"true\"");
|
cprintf(cbx, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
cprintf(cbx, " %s:copystartup=\"true\"", CLIXON_LIB_PREFIX);
|
||||||
}
|
}
|
||||||
cprintf(cbx, " autocommit=\"true\"");
|
cprintf(cbx, " %s:autocommit=\"true\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
cprintf(cbx, "><target><candidate /></target>");
|
cprintf(cbx, "><target><candidate /></target>");
|
||||||
cprintf(cbx, "<default-operation>none</default-operation>");
|
cprintf(cbx, "<default-operation>none</default-operation>");
|
||||||
if (clixon_xml2cbuf(cbx, xtop, 0, 0, -1, 0) < 0)
|
if (clixon_xml2cbuf(cbx, xtop, 0, 0, -1, 0) < 0)
|
||||||
|
|
|
||||||
|
|
@ -337,14 +337,15 @@ api_data_post(clicon_handle h,
|
||||||
}
|
}
|
||||||
/* For internal XML protocol: add username attribute for access control
|
/* For internal XML protocol: add username attribute for access control
|
||||||
*/
|
*/
|
||||||
username = clicon_username_get(h);
|
cprintf(cbx, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cbx, "<rpc xmlns=\"%s\" username=\"%s\" xmlns:%s=\"%s\" %s>",
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
NETCONF_BASE_NAMESPACE,
|
cprintf(cbx, " %s:username=\"%s\" xmlns:%s=\"%s\"",
|
||||||
username?username:"",
|
NETCONF_BASE_PREFIX,
|
||||||
NETCONF_BASE_PREFIX,
|
username?username:"",
|
||||||
NETCONF_BASE_NAMESPACE,
|
NETCONF_BASE_PREFIX,
|
||||||
NETCONF_MESSAGE_ID_ATTR); /* bind nc to netconf namespace */
|
NETCONF_BASE_NAMESPACE);
|
||||||
|
}
|
||||||
|
cprintf(cbx, " %s>", NETCONF_MESSAGE_ID_ATTR); /* bind nc to netconf namespace */
|
||||||
cprintf(cbx, "<edit-config");
|
cprintf(cbx, "<edit-config");
|
||||||
/* RFC8040 Sec 1.4:
|
/* RFC8040 Sec 1.4:
|
||||||
* If this is a "data" request and the NETCONF server supports :startup,
|
* If this is a "data" request and the NETCONF server supports :startup,
|
||||||
|
|
@ -355,9 +356,11 @@ api_data_post(clicon_handle h,
|
||||||
if ((IETF_DS_NONE == ds) &&
|
if ((IETF_DS_NONE == ds) &&
|
||||||
if_feature(yspec, "ietf-netconf", "startup") &&
|
if_feature(yspec, "ietf-netconf", "startup") &&
|
||||||
!clicon_option_bool(h, "CLICON_RESTCONF_STARTUP_DONTUPDATE")){
|
!clicon_option_bool(h, "CLICON_RESTCONF_STARTUP_DONTUPDATE")){
|
||||||
cprintf(cbx, " copystartup=\"true\"");
|
cprintf(cbx, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
cprintf(cbx, " %s:copystartup=\"true\"", CLIXON_LIB_PREFIX);
|
||||||
}
|
}
|
||||||
cprintf(cbx, " autocommit=\"true\"");
|
cprintf(cbx, " %s:autocommit=\"true\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
cprintf(cbx, "><target><candidate /></target>");
|
cprintf(cbx, "><target><candidate /></target>");
|
||||||
cprintf(cbx, "<default-operation>none</default-operation>");
|
cprintf(cbx, "<default-operation>none</default-operation>");
|
||||||
if (clixon_xml2cbuf(cbx, xtop, 0, 0, -1, 0) < 0)
|
if (clixon_xml2cbuf(cbx, xtop, 0, 0, -1, 0) < 0)
|
||||||
|
|
|
||||||
32
apps/snmp/README.md
Normal file
32
apps/snmp/README.md
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
SNMP
|
||||||
|
====
|
||||||
|
|
||||||
|
The SNMP frontend acts as an intermediate daemon between the Net-SNMP
|
||||||
|
daemon (snmpd) and the Clixon backend. Clixon-snmp communicates over the AgentX
|
||||||
|
protocol to snmpd typically via a UNIX socket, and over the internal IPC protocol to the Clixon
|
||||||
|
backend.
|
||||||
|
|
||||||
|
Use Net-SNMP version 5.9 or later
|
||||||
|
|
||||||
|
To set up AgentX communication between ``clixon_snmp`` and ``snmpd`` a
|
||||||
|
Unix or TCP socket is configured. This socket is also configured in
|
||||||
|
Clixon (see below). An example `/etc/snmpd/snmpd.conf` is as follows::
|
||||||
|
|
||||||
|
master agentx
|
||||||
|
agentaddress 127.0.0.1,[::1]
|
||||||
|
rwcommunity public localhost
|
||||||
|
agentXSocket unix:/var/run/snmp.sock
|
||||||
|
agentxperms 777 777
|
||||||
|
|
||||||
|
It is necessary to ensure snmpd does `not` to load modules
|
||||||
|
implemented by Clixon. For example, if Clixon implements the IF-MIB and
|
||||||
|
system MIBs, snmpd should not load those modules. This can be done
|
||||||
|
using the "-I" flag and prepending a "-" before each module::
|
||||||
|
|
||||||
|
-I -ifTable -I -system_mib -I -sysORTable
|
||||||
|
|
||||||
|
Net-snmp must be started via systemd or some other external mechanism before clixon_snmp is started.
|
||||||
|
|
||||||
|
To build the snmp support, netsnmp is enabled at configure time. Two configure options are added for SNMP:
|
||||||
|
* ``--enable-netsnmp`` Enable SNMP support.
|
||||||
|
* ``--with-mib-generated-yang-dir`` For tests: Directory of generated YANG specs (default: $prefix/share/mibyang)
|
||||||
|
|
@ -525,7 +525,7 @@ main(int argc,
|
||||||
* used by the client, even though new TCP sessions are created for
|
* used by the client, even though new TCP sessions are created for
|
||||||
* each message sent to the backend.
|
* each message sent to the backend.
|
||||||
*/
|
*/
|
||||||
if (clicon_hello_req(h, &id) < 0)
|
if (clicon_hello_req(h, "cl:snmp", "localhost", &id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_session_id_set(h, id);
|
clicon_session_id_set(h, id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,6 @@
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int netconf_monitoring_state_get(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, int brief, cxobj **xret);
|
int netconf_monitoring_state_get(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, cxobj **xret, cxobj **xerr);
|
||||||
|
|
||||||
#endif /* _CLIXON_NETCONF_MONITORING_H_ */
|
#endif /* _CLIXON_NETCONF_MONITORING_H_ */
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,9 @@
|
||||||
* @see clixon-lib.yang
|
* @see clixon-lib.yang
|
||||||
*/
|
*/
|
||||||
#define CLIXON_CONF_NS "http://clicon.org/config"
|
#define CLIXON_CONF_NS "http://clicon.org/config"
|
||||||
|
#define CLIXON_CONF_PREFIX "cc"
|
||||||
#define CLIXON_LIB_NS "http://clicon.org/lib"
|
#define CLIXON_LIB_NS "http://clicon.org/lib"
|
||||||
|
#define CLIXON_LIB_PREFIX "cl"
|
||||||
#define CLIXON_AUTOCLI_NS "http://clicon.org/autocli"
|
#define CLIXON_AUTOCLI_NS "http://clicon.org/autocli"
|
||||||
#define CLIXON_RESTCONF_NS "http://clicon.org/restconf"
|
#define CLIXON_RESTCONF_NS "http://clicon.org/restconf"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ int clicon_rpc_discard_changes(clicon_handle h);
|
||||||
int clicon_rpc_create_subscription(clicon_handle h, char *stream, char *filter, int *s);
|
int clicon_rpc_create_subscription(clicon_handle h, char *stream, char *filter, int *s);
|
||||||
int clicon_rpc_debug(clicon_handle h, int level);
|
int clicon_rpc_debug(clicon_handle h, int level);
|
||||||
int clicon_rpc_restconf_debug(clicon_handle h, int level);
|
int clicon_rpc_restconf_debug(clicon_handle h, int level);
|
||||||
int clicon_hello_req(clicon_handle h, uint32_t *id);
|
int clicon_hello_req(clicon_handle h, char *transport, char *source_host, uint32_t *id);
|
||||||
int clicon_rpc_restart_plugin(clicon_handle h, char *plugin);
|
int clicon_rpc_restart_plugin(clicon_handle h, char *plugin);
|
||||||
|
|
||||||
#endif /* _CLIXON_PROTO_CLIENT_H_ */
|
#endif /* _CLIXON_PROTO_CLIENT_H_ */
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,9 @@ cxobj *xml_root(cxobj *xn);
|
||||||
int xml_operation(char *opstr, enum operation_type *op);
|
int xml_operation(char *opstr, enum operation_type *op);
|
||||||
char *xml_operation2str(enum operation_type op);
|
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 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)));
|
||||||
|
|
||||||
#ifdef XML_EXPLICIT_INDEX
|
#ifdef XML_EXPLICIT_INDEX
|
||||||
int xml_search_index_p(cxobj *x);
|
int xml_search_index_p(cxobj *x);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,6 @@ check_body_namespace(cxobj *x0,
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
char *ns0 = NULL;
|
char *ns0 = NULL;
|
||||||
char *ns1 = NULL;
|
char *ns1 = NULL;
|
||||||
cxobj *xa;
|
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
int isroot;
|
int isroot;
|
||||||
cbuf *cberr = NULL;
|
cbuf *cberr = NULL;
|
||||||
|
|
@ -210,17 +209,12 @@ bad-attribue?
|
||||||
goto done;
|
goto done;
|
||||||
/* Create xmlns attribute to x0 XXX same code ^*/
|
/* Create xmlns attribute to x0 XXX same code ^*/
|
||||||
if (prefix){
|
if (prefix){
|
||||||
if ((xa = xml_new(prefix, x, CX_ATTR)) == NULL)
|
if (xml_add_attr(x, prefix, ns0, "xmlns", NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xa, "xmlns") < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
if ((xa = xml_new("xmlns", x, CX_ATTR)) == NULL)
|
if (xml_add_attr(x, "xmlns", ns0, NULL, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
if (xml_value_set(xa, ns0) < 0)
|
|
||||||
goto done;
|
|
||||||
xml_sort(x); /* Ensure attr is first / XXX xml_insert? */
|
xml_sort(x); /* Ensure attr is first / XXX xml_insert? */
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -237,11 +231,7 @@ bad-attribue?
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
else{ /* Add it according to the kludge,... */
|
else{ /* Add it according to the kludge,... */
|
||||||
if ((xa = xml_new(prefix, x0, CX_ATTR)) == NULL)
|
if (xml_add_attr(x0, prefix, ns0, "xmlns", NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xa, "xmlns") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, ns0) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,6 @@ json2xml_decode_identityref(cxobj *x,
|
||||||
char *ns;
|
char *ns;
|
||||||
char *body;
|
char *body;
|
||||||
cxobj *xb;
|
cxobj *xb;
|
||||||
cxobj *xa;
|
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
char *id = NULL;
|
char *id = NULL;
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
|
|
@ -333,12 +332,9 @@ json2xml_decode_identityref(cxobj *x,
|
||||||
if (prefix2 == NULL)
|
if (prefix2 == NULL)
|
||||||
prefix2 = yang_find_myprefix(ymod);
|
prefix2 = yang_find_myprefix(ymod);
|
||||||
/* Add "xmlns:prefix2=namespace" */
|
/* Add "xmlns:prefix2=namespace" */
|
||||||
if ((xa = xml_new(prefix2, x, CX_ATTR)) == NULL)
|
if (xml_add_attr(x, prefix2, ns, "xmlns", NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xa, "xmlns") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, ns) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* Here prefix2 is valid and can be NULL
|
/* Here prefix2 is valid and can be NULL
|
||||||
Change body prefix to prefix2:id */
|
Change body prefix to prefix2:id */
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,6 @@ netconf_invalid_value_xml(cxobj **xret,
|
||||||
int retval =-1;
|
int retval =-1;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -173,9 +172,7 @@ netconf_invalid_value_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -282,7 +279,6 @@ netconf_missing_attribute_xml(cxobj **xret,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -294,9 +290,7 @@ netconf_missing_attribute_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -394,7 +388,6 @@ netconf_bad_attribute_xml(cxobj **xret,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -406,9 +399,7 @@ netconf_bad_attribute_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -491,7 +482,6 @@ netconf_common_xml(cxobj **xret,
|
||||||
int retval =-1;
|
int retval =-1;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -500,9 +490,7 @@ netconf_common_xml(cxobj **xret,
|
||||||
if (*xret == NULL){
|
if (*xret == NULL){
|
||||||
if ((*xret = xml_new("rpc-reply", NULL, CX_ELMNT)) == NULL)
|
if ((*xret = xml_new("rpc-reply", NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
|
|
@ -751,7 +739,6 @@ netconf_access_denied_xml(cxobj **xret,
|
||||||
int retval =-1;
|
int retval =-1;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -763,9 +750,7 @@ netconf_access_denied_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -987,7 +972,6 @@ netconf_data_missing_xml(cxobj **xret,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -999,9 +983,7 @@ netconf_data_missing_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1045,7 +1027,6 @@ netconf_missing_choice_xml(cxobj **xret,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
cxobj *xa;
|
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
char *encpath = NULL;
|
char *encpath = NULL;
|
||||||
|
|
||||||
|
|
@ -1059,9 +1040,7 @@ netconf_missing_choice_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1122,7 +1101,6 @@ netconf_operation_not_supported_xml(cxobj **xret,
|
||||||
int retval =-1;
|
int retval =-1;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -1134,9 +1112,7 @@ netconf_operation_not_supported_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1237,7 +1213,6 @@ netconf_operation_failed_xml(cxobj **xret,
|
||||||
int retval =-1;
|
int retval =-1;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -1249,9 +1224,7 @@ netconf_operation_failed_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1325,8 +1298,7 @@ netconf_malformed_message_xml(cxobj **xret,
|
||||||
int retval =-1;
|
int retval =-1;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1337,9 +1309,7 @@ netconf_malformed_message_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1408,7 +1378,6 @@ netconf_data_not_unique_xml(cxobj **xret,
|
||||||
cg_var *cvi = NULL;
|
cg_var *cvi = NULL;
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
cxobj *xinfo;
|
cxobj *xinfo;
|
||||||
cxobj *xa;
|
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
char *encpath = NULL;
|
char *encpath = NULL;
|
||||||
|
|
||||||
|
|
@ -1422,9 +1391,7 @@ netconf_data_not_unique_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1482,7 +1449,6 @@ netconf_minmax_elements_xml(cxobj **xret,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
char *encpath = NULL;
|
char *encpath = NULL;
|
||||||
cxobj *xa;
|
|
||||||
|
|
||||||
if (xret == NULL){
|
if (xret == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
clicon_err(OE_NETCONF, EINVAL, "xret is NULL");
|
||||||
|
|
@ -1494,9 +1460,7 @@ netconf_minmax_elements_xml(cxobj **xret,
|
||||||
}
|
}
|
||||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xa = xml_new("xmlns", *xret, CX_ATTR)) == NULL)
|
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xa, NETCONF_BASE_NAMESPACE) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1528,9 +1492,9 @@ netconf_minmax_elements_xml(cxobj **xret,
|
||||||
* @param[in] x XML tree
|
* @param[in] x XML tree
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
* @retval -1 Error (fatal)
|
|
||||||
* @retval 0 Statedata callback failed
|
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
|
* @retval 0 Statedata callback failed, error in xret?
|
||||||
|
* @retval -1 Error (fatal)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_trymerge(cxobj *x,
|
netconf_trymerge(cxobj *x,
|
||||||
|
|
@ -1995,9 +1959,9 @@ clixon_netconf_internal_error(cxobj *xerr,
|
||||||
* @param[in] defaultstr If given, default string which is accepted and sets value to 0
|
* @param[in] defaultstr If given, default string which is accepted and sets value to 0
|
||||||
* @param[in,out] cbret Output buffer for internal RPC message if invalid
|
* @param[in,out] cbret Output buffer for internal RPC message if invalid
|
||||||
* @param[out] value Value if valid
|
* @param[out] value Value if valid
|
||||||
* @retval -1 Error
|
|
||||||
* @retval 0 Invalid, cbret set
|
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
|
* @retval 0 Invalid, cbret set
|
||||||
|
* @retval -1 Error
|
||||||
* @code
|
* @code
|
||||||
* char *name = "a";
|
* char *name = "a";
|
||||||
* char *valstr = "322";
|
* char *valstr = "322";
|
||||||
|
|
@ -2238,10 +2202,10 @@ netconf_output_encap(netconf_framing_type framing,
|
||||||
* @param[in] ch New input character
|
* @param[in] ch New input character
|
||||||
* @param[in,out] state State machine state
|
* @param[in,out] state State machine state
|
||||||
* @param[in,out] size Remaining expecting chunk bytes.
|
* @param[in,out] size Remaining expecting chunk bytes.
|
||||||
* @retval -1 Error
|
|
||||||
* @retval 0 Framing char, not data
|
|
||||||
* @retval 1 Chunk-data
|
|
||||||
* @retval 2 End-of-frame
|
* @retval 2 End-of-frame
|
||||||
|
* @retval 1 Chunk-data
|
||||||
|
* @retval 0 Framing char, not data
|
||||||
|
* @retval -1 Error
|
||||||
* Example:
|
* Example:
|
||||||
C: \n#4\n
|
C: \n#4\n
|
||||||
C: <rpc
|
C: <rpc
|
||||||
|
|
@ -2352,3 +2316,4 @@ netconf_input_chunked_framing(char ch,
|
||||||
retval = -1; /* Error */
|
retval = -1; /* Error */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ per_datastore(clicon_handle h,
|
||||||
cprintf(cb, "<datastore><name>%s</name>", db);
|
cprintf(cb, "<datastore><name>%s</name>", db);
|
||||||
if ((sid = xmldb_islocked(h, db)) > 0){
|
if ((sid = xmldb_islocked(h, db)) > 0){
|
||||||
cprintf(cb, "<locks>");
|
cprintf(cb, "<locks>");
|
||||||
|
cprintf(cb, "<global-lock>");
|
||||||
cprintf(cb, "<locked-by-session>%u</locked-by-session>", sid);
|
cprintf(cb, "<locked-by-session>%u</locked-by-session>", sid);
|
||||||
xmldb_lock_timestamp(h, db, &tv);
|
xmldb_lock_timestamp(h, db, &tv);
|
||||||
if (time2str(tv, timestr, sizeof(timestr)) < 0){
|
if (time2str(tv, timestr, sizeof(timestr)) < 0){
|
||||||
|
|
@ -85,6 +86,7 @@ per_datastore(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cb, "<locked-time>%s</locked-time>", timestr);
|
cprintf(cb, "<locked-time>%s</locked-time>", timestr);
|
||||||
|
cprintf(cb, "</global-lock>");
|
||||||
cprintf(cb, "</locks>");
|
cprintf(cb, "</locks>");
|
||||||
}
|
}
|
||||||
cprintf(cb, "</datastore>");
|
cprintf(cb, "</datastore>");
|
||||||
|
|
@ -175,28 +177,6 @@ netconf_monitoring_schemas(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get netconf monitoring sessions state
|
|
||||||
*
|
|
||||||
* @param[in] h Clicon handle
|
|
||||||
* @param[in] yspec Yang spec
|
|
||||||
* @param[in,out] cb CLIgen buffer
|
|
||||||
* @retval -1 Error (fatal)
|
|
||||||
* @retval 0 OK
|
|
||||||
* @see RFC 6022 Section 2.1.4
|
|
||||||
* XXX: NYI
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
netconf_monitoring_sessions(clicon_handle h,
|
|
||||||
yang_stmt *yspec,
|
|
||||||
cbuf *cb)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
retval = 0;
|
|
||||||
//done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Get netconf monitoring statistics state
|
/*! Get netconf monitoring statistics state
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -227,11 +207,12 @@ netconf_monitoring_statistics(clicon_handle h,
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in] xpath XML Xpath
|
* @param[in] xpath XML Xpath
|
||||||
* @param[in] nsc XML Namespace context for xpath
|
* @param[in] nsc XML Namespace context for xpath
|
||||||
* @param[in] brief Just name, revision and uri (no cache)
|
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
|
* @param[out] xerr XML error tree, if retval = 0
|
||||||
* @retval -1 Error (fatal)
|
* @retval -1 Error (fatal)
|
||||||
* @retval 0 Statedata callback failed
|
* @retval 0 Statedata callback failed, error in xret
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
|
* @see backend_monitoring_state_get
|
||||||
* @see RFC 6022
|
* @see RFC 6022
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -239,11 +220,12 @@ netconf_monitoring_state_get(clicon_handle h,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
int brief,
|
cxobj **xret,
|
||||||
cxobj **xret)
|
cxobj **xerr)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if ((cb = cbuf_new()) ==NULL){
|
if ((cb = cbuf_new()) ==NULL){
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
|
@ -256,20 +238,22 @@ netconf_monitoring_state_get(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (netconf_monitoring_schemas(h, yspec, cb) < 0)
|
if (netconf_monitoring_schemas(h, yspec, cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (netconf_monitoring_sessions(h, yspec, cb) < 0)
|
/* sessions is backend-specific */
|
||||||
goto done;
|
|
||||||
if (netconf_monitoring_statistics(h, yspec, cb) < 0)
|
if (netconf_monitoring_statistics(h, yspec, cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, "</netconf-state>");
|
cprintf(cb, "</netconf-state>");
|
||||||
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
if ((ret = clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
// fail:
|
fail:
|
||||||
// retval = 0;
|
retval = 0;
|
||||||
// goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,11 @@
|
||||||
#define TIMEOUT_XML_FMT "<confirm-timeout>%u</confirm-timeout>"
|
#define TIMEOUT_XML_FMT "<confirm-timeout>%u</confirm-timeout>"
|
||||||
|
|
||||||
/*! Connect to internal netconf socket
|
/*! Connect to internal netconf socket
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[out] sockp Socket
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_connect(clicon_handle h,
|
clicon_rpc_connect(clicon_handle h,
|
||||||
|
|
@ -133,10 +138,13 @@ clicon_rpc_connect(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Connect to backend or use cached socket and send RPC
|
/*! Connect to backend or use cached socket and send RPC
|
||||||
* @param[in] h Clixonhandle
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
* @param[in] msg Encoded message
|
* @param[in] msg Encoded message
|
||||||
* @param[out] xret Returned data as netconf xml tree.
|
* @param[out] xret Returned data as netconf xml tree.
|
||||||
* @param[out] eof Set if eof encountered
|
* @param[out] eof Set if eof encountered
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
clicon_rpc_msg_once(clicon_handle h,
|
clicon_rpc_msg_once(clicon_handle h,
|
||||||
|
|
@ -168,9 +176,12 @@ clicon_rpc_msg_once(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send internal netconf rpc from client to backend
|
/*! Send internal netconf rpc from client to backend
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] msg Encoded message. Deallocate with free
|
* @param[in] msg Encoded message. Deallocate with free
|
||||||
* @param[out] xret0 Return value from backend as xml tree. Free w xml_free
|
* @param[out] xret0 Return value from backend as xml tree. Free w xml_free
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
* @note xret is populated with yangspec according to standard handle yangspec
|
* @note xret is populated with yangspec according to standard handle yangspec
|
||||||
* @note side-effect, a socket created here is cached
|
* @note side-effect, a socket created here is cached
|
||||||
* @see clicon_rpc_msg_persistent
|
* @see clicon_rpc_msg_persistent
|
||||||
|
|
@ -242,11 +253,14 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send internal netconf rpc from client to backend and return a persistent socket
|
/*! Send internal netconf rpc from client to backend and return a persistent socket
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] msg Encoded message. Deallocate with free
|
* @param[in] msg Encoded message. Deallocate with free
|
||||||
* @param[out] xret0 Return value from backend as xml tree. Free w xml_free
|
* @param[out] xret0 Return value from backend as xml tree. Free w xml_free
|
||||||
* @param[out] sock0 If pointer exists, do not close socket to backend on success
|
* @param[out] sock0 If pointer exists, do not close socket to backend on success
|
||||||
* and return it here. For keeping a notify socket open
|
* and return it here. For keeping a notify socket open
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
* @note xret is populated with yangspec according to standard handle yangspec
|
* @note xret is populated with yangspec according to standard handle yangspec
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -311,6 +325,7 @@ clicon_rpc_msg_persistent(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Check if there is a valid (cached) session-id. If not, send a hello request to backend
|
/*! Check if there is a valid (cached) session-id. If not, send a hello request to backend
|
||||||
|
*
|
||||||
* Session-ids survive TCP sessions that are created for each message sent to the backend.
|
* Session-ids survive TCP sessions that are created for each message sent to the backend.
|
||||||
* Clients use two approaches, either:
|
* Clients use two approaches, either:
|
||||||
* (1) Once at the beginning of the session. Netconf and restconf does this
|
* (1) Once at the beginning of the session. Netconf and restconf does this
|
||||||
|
|
@ -329,7 +344,7 @@ session_id_check(clicon_handle h,
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
if (clicon_session_id_get(h, &id) < 0){ /* Not set yet */
|
if (clicon_session_id_get(h, &id) < 0){ /* Not set yet */
|
||||||
if (clicon_hello_req(h, &id) < 0)
|
if (clicon_hello_req(h, NULL, NULL, &id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_session_id_set(h, id);
|
clicon_session_id_set(h, id);
|
||||||
}
|
}
|
||||||
|
|
@ -345,6 +360,8 @@ session_id_check(clicon_handle h,
|
||||||
* @param[in] xmlstr XML netconf tree as string
|
* @param[in] xmlstr XML netconf tree as string
|
||||||
* @param[out] xret Return XML netconf tree, error or OK (need to be freed)
|
* @param[out] xret Return XML netconf tree, error or OK (need to be freed)
|
||||||
* @param[out] sp Socket pointer for notification, otherwise NULL
|
* @param[out] sp Socket pointer for notification, otherwise NULL
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xret = NULL;
|
* cxobj *xret = NULL;
|
||||||
* int s = -1;
|
* int s = -1;
|
||||||
|
|
@ -383,6 +400,7 @@ clicon_rpc_netconf(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Generic xml netconf clicon rpc
|
/*! Generic xml netconf clicon rpc
|
||||||
|
*
|
||||||
* Want to go over to use netconf directly between client and server,...
|
* Want to go over to use netconf directly between client and server,...
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
* @param[in] xml XML netconf tree
|
* @param[in] xml XML netconf tree
|
||||||
|
|
@ -397,7 +415,6 @@ clicon_rpc_netconf(clicon_handle h,
|
||||||
* err;
|
* err;
|
||||||
* xml_free(xret);
|
* xml_free(xret);
|
||||||
* @endcode
|
* @endcode
|
||||||
|
|
||||||
* @see clicon_rpc_netconf xml as string instead of tree
|
* @see clicon_rpc_netconf xml as string instead of tree
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -456,6 +473,7 @@ clicon_rpc_netconf_xml(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get database configuration
|
/*! Get database configuration
|
||||||
|
*
|
||||||
* Same as clicon_proto_change just with a cvec instead of lvec
|
* Same as clicon_proto_change just with a cvec instead of lvec
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] username If NULL, use default
|
* @param[in] username If NULL, use default
|
||||||
|
|
@ -490,7 +508,7 @@ clicon_rpc_netconf_xml(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_get_config(clicon_handle h,
|
clicon_rpc_get_config(clicon_handle h,
|
||||||
char *username,
|
char *username, // XXX: why is this only rpc call with username parameter?
|
||||||
char *db,
|
char *db,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
|
|
@ -510,16 +528,20 @@ clicon_rpc_get_config(clicon_handle h,
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cb = cbuf_new()) == NULL)
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
if (username == NULL)
|
if (username == NULL)
|
||||||
username = clicon_username_get(h);
|
username = clicon_username_get(h);
|
||||||
if (username != NULL)
|
if (username != NULL){
|
||||||
cprintf(cb, " username=\"%s\"", username);
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
cprintf(cb, " xmlns:%s=\"%s\"",
|
cprintf(cb, " xmlns:%s=\"%s\"",
|
||||||
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
cprintf(cb, "><get-config><source><%s/></source>", db);
|
cprintf(cb, "><get-config><source><%s/></source>", db);
|
||||||
if (xpath && strlen(xpath)){
|
if (xpath && strlen(xpath)){
|
||||||
cprintf(cb, "<%s:filter %s:type=\"xpath\" %s:select=\"%s\"",
|
cprintf(cb, "<%s:filter %s:type=\"xpath\" %s:select=\"%s\"",
|
||||||
|
|
@ -591,6 +613,7 @@ clicon_rpc_get_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send database entries as XML to backend daemon
|
/*! Send database entries as XML to backend daemon
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] db Name of database
|
* @param[in] db Name of database
|
||||||
* @param[in] op Operation on database item: OP_MERGE, OP_REPLACE
|
* @param[in] op Operation on database item: OP_MERGE, OP_REPLACE
|
||||||
|
|
@ -620,13 +643,17 @@ clicon_rpc_edit_config(clicon_handle h,
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cb = cbuf_new()) == NULL)
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
if ((username = clicon_username_get(h)) != NULL)
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
cprintf(cb, " username=\"%s\"", username);
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
cprintf(cb, "><edit-config><target><%s/></target>", db);
|
cprintf(cb, "><edit-config><target><%s/></target>", db);
|
||||||
cprintf(cb, "<default-operation>%s</default-operation>",
|
cprintf(cb, "<default-operation>%s</default-operation>",
|
||||||
xml_operation2str(op));
|
xml_operation2str(op));
|
||||||
|
|
@ -653,6 +680,7 @@ clicon_rpc_edit_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send a request to backend to copy a file from one location to another
|
/*! Send a request to backend to copy a file from one location to another
|
||||||
|
*
|
||||||
* Note this assumes the backend can access these files and (usually) assumes
|
* Note this assumes the backend can access these files and (usually) assumes
|
||||||
* clients and servers have the access to the same filesystem.
|
* clients and servers have the access to the same filesystem.
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
|
|
@ -676,17 +704,25 @@ clicon_rpc_copy_config(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s>"
|
goto done;
|
||||||
"<copy-config><source><%s/></source><target><%s/></target></copy-config></rpc>",
|
}
|
||||||
NETCONF_BASE_NAMESPACE,
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
username?username:"",
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
db1, db2)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<copy-config><source><%s/></source><target><%s/></target></copy-config></rpc>",
|
||||||
|
db1, db2);
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -696,6 +732,8 @@ clicon_rpc_copy_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -704,6 +742,7 @@ clicon_rpc_copy_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send a request to backend to delete a config database
|
/*! Send a request to backend to delete a config database
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] db database, eg "running"
|
* @param[in] db database, eg "running"
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -723,17 +762,25 @@ clicon_rpc_delete_config(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s>"
|
goto done;
|
||||||
"<edit-config><target><%s/></target><default-operation>none</default-operation><config operation=\"delete\"/></edit-config></rpc>",
|
}
|
||||||
NETCONF_BASE_NAMESPACE,
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
username?username:"",
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
db)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<edit-config><target><%s/></target><default-operation>none</default-operation><config operation=\"delete\"/></edit-config>", db);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -743,6 +790,8 @@ clicon_rpc_delete_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -766,17 +815,25 @@ clicon_rpc_lock(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s>"
|
goto done;
|
||||||
"<lock><target><%s/></target></lock></rpc>",
|
}
|
||||||
NETCONF_BASE_NAMESPACE,
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
username?username:"",
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
db)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<lock><target><%s/></target></lock>", db);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -786,6 +843,8 @@ clicon_rpc_lock(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -809,17 +868,25 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s>"
|
goto done;
|
||||||
"<unlock><target><%s/></target></unlock></rpc>",
|
}
|
||||||
NETCONF_BASE_NAMESPACE,
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
username?username:"",
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
db)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<unlock><target><%s/></target></unlock>", db);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -829,6 +896,8 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -846,8 +915,8 @@ clicon_rpc_unlock(clicon_handle h,
|
||||||
* @param[in] defaults Value of the with-defaults mode, rfc6243, or NULL
|
* @param[in] defaults Value of the with-defaults mode, rfc6243, or NULL
|
||||||
* @param[out] xt XML tree. Free with xml_free.
|
* @param[out] xt XML tree. Free with xml_free.
|
||||||
* Either <config> or <rpc-error>.
|
* Either <config> or <rpc-error>.
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error, fatal or xml
|
* @retval -1 Error, fatal or xml
|
||||||
* @note if xpath is set but namespace is NULL, the default, netconf base
|
* @note if xpath is set but namespace is NULL, the default, netconf base
|
||||||
* namespace will be used which is most probably wrong.
|
* namespace will be used which is most probably wrong.
|
||||||
* @code
|
* @code
|
||||||
|
|
@ -894,21 +963,30 @@ clicon_rpc_get(clicon_handle h,
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cb = cbuf_new()) == NULL)
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, "<rpc xmlns=\"%s\" ", NETCONF_BASE_NAMESPACE);
|
}
|
||||||
if ((username = clicon_username_get(h)) != NULL)
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " username=\"%s\"", username);
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " xmlns:%s=\"%s\"",
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
cprintf(cb, "><get");
|
cprintf(cb, "><get");
|
||||||
/* Clixon extension, content=all,config, or nonconfig */
|
/* Clixon extension, content=all,config, or nonconfig */
|
||||||
if ((int)content != -1)
|
if ((int)content != -1)
|
||||||
cprintf(cb, " content=\"%s\"", netconf_content_int2str(content));
|
cprintf(cb, " %s:content=\"%s\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX,
|
||||||
|
netconf_content_int2str(content),
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
/* Clixon extension, depth=<level> */
|
/* Clixon extension, depth=<level> */
|
||||||
if (depth != -1)
|
if (depth != -1)
|
||||||
cprintf(cb, " depth=\"%d\"", depth);
|
cprintf(cb, " %s:depth=\"%d\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX,
|
||||||
|
depth,
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
cprintf(cb, ">"); /* get */
|
cprintf(cb, ">"); /* get */
|
||||||
/* If xpath, add a filter */
|
/* If xpath, add a filter */
|
||||||
if (xpath && strlen(xpath)) {
|
if (xpath && strlen(xpath)) {
|
||||||
|
|
@ -980,6 +1058,7 @@ clicon_rpc_get(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get database configuration and state data collection
|
/*! Get database configuration and state data collection
|
||||||
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] xpath To identify a list/leaf-list
|
* @param[in] xpath To identify a list/leaf-list
|
||||||
* @param[in] namespace Namespace associated w xpath
|
* @param[in] namespace Namespace associated w xpath
|
||||||
|
|
@ -1033,21 +1112,31 @@ clicon_rpc_get_pageable_list(clicon_handle h,
|
||||||
}
|
}
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cb = cbuf_new()) == NULL)
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
if ((username = clicon_username_get(h)) != NULL)
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
cprintf(cb, " username=\"%s\"", username);
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
cprintf(cb, " xmlns:%s=\"%s\"",
|
cprintf(cb, " xmlns:%s=\"%s\"",
|
||||||
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
cprintf(cb, "><get ");
|
cprintf(cb, "><get ");
|
||||||
/* Clixon extension, content=all,config, or nonconfig */
|
/* Clixon extension, content=all,config, or nonconfig */
|
||||||
if ((int)content != -1)
|
if ((int)content != -1)
|
||||||
cprintf(cb, " content=\"%s\"", netconf_content_int2str(content));
|
cprintf(cb, " %s:content=\"%s\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX,
|
||||||
|
netconf_content_int2str(content),
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
/* Clixon extension, depth=<level> */
|
/* Clixon extension, depth=<level> */
|
||||||
if (depth != -1)
|
if (depth != -1)
|
||||||
cprintf(cb, " depth=\"%d\"", depth);
|
cprintf(cb, " %s:depth=\"%d\" xmlns:%s=\"%s\"",
|
||||||
|
CLIXON_LIB_PREFIX,
|
||||||
|
depth,
|
||||||
|
CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
/* declare lp prefix in get, so sub-elements dont need to */
|
/* declare lp prefix in get, so sub-elements dont need to */
|
||||||
cprintf(cb, ">"); /* get */
|
cprintf(cb, ">"); /* get */
|
||||||
/* If xpath, add a filter */
|
/* If xpath, add a filter */
|
||||||
|
|
@ -1152,14 +1241,25 @@ clicon_rpc_close_session(clicon_handle h)
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
int s;
|
int s;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><close-session/></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE, username?username:"",
|
}
|
||||||
NETCONF_MESSAGE_ID_ATTR)) == NULL)
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<close-session/>");
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1173,6 +1273,8 @@ clicon_rpc_close_session(clicon_handle h)
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -1181,10 +1283,11 @@ clicon_rpc_close_session(clicon_handle h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Kill other user sessions
|
/*! Kill other user sessions
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] session_id Session id of other user session
|
* @param[in] session_id Session id of other user session
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error and logged to syslog
|
* @retval -1 Error and logged to syslog
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_kill_session(clicon_handle h,
|
clicon_rpc_kill_session(clicon_handle h,
|
||||||
|
|
@ -1196,16 +1299,25 @@ clicon_rpc_kill_session(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t my_session_id; /* Not the one to kill */
|
uint32_t my_session_id; /* Not the one to kill */
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &my_session_id) < 0)
|
if (session_id_check(h, &my_session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(my_session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><kill-session><session-id>%u</session-id></kill-session></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
username?username:"",
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
session_id)) == NULL)
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<kill-session><session-id>%u</session-id></kill-session>", session_id);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(my_session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1215,6 +1327,8 @@ clicon_rpc_kill_session(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -1223,6 +1337,7 @@ clicon_rpc_kill_session(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send validate request to backend daemon
|
/*! Send validate request to backend daemon
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] db Name of database
|
* @param[in] db Name of database
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
|
|
@ -1240,16 +1355,25 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><validate><source><%s/></source></validate></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
username?username:"",
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
db)) == NULL)
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<validate><source><%s/></source></validate>", db);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1260,6 +1384,8 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (msg)
|
if (msg)
|
||||||
free(msg);
|
free(msg);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
@ -1268,6 +1394,7 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Commit changes send a commit request to backend daemon
|
/*! Commit changes send a commit request to backend daemon
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] confirmed If set, send commit/confirmed
|
* @param[in] confirmed If set, send commit/confirmed
|
||||||
* @param[in] cancel If set, send cancel-commit
|
* @param[in] cancel If set, send cancel-commit
|
||||||
|
|
@ -1297,6 +1424,7 @@ clicon_rpc_commit(clicon_handle h,
|
||||||
char *persist_id_xml = NULL;
|
char *persist_id_xml = NULL;
|
||||||
char *persist_xml = NULL;
|
char *persist_xml = NULL;
|
||||||
char *timeout_xml = NULL;
|
char *timeout_xml = NULL;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (persist_id) {
|
if (persist_id) {
|
||||||
if ((persist_id_xml = malloc(strlen(persist_id) + strlen(PERSIST_ID_XML_FMT) + 1)) == NULL) {
|
if ((persist_id_xml = malloc(strlen(persist_id) + strlen(PERSIST_ID_XML_FMT) + 1)) == NULL) {
|
||||||
|
|
@ -1325,32 +1453,34 @@ clicon_rpc_commit(clicon_handle h,
|
||||||
}
|
}
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
|
||||||
if (cancel) {
|
if ((cb = cbuf_new()) == NULL){
|
||||||
msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><cancel-commit>%s</cancel-commit></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
|
||||||
username ? username : "",
|
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
|
||||||
persist_id ? persist_id_xml : "");
|
|
||||||
} else if (confirmed) {
|
|
||||||
msg = clicon_msg_encode(session_id,
|
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><commit><confirmed/>%s%s%s</commit></rpc>",
|
|
||||||
NETCONF_BASE_NAMESPACE,
|
|
||||||
username ? username : "",
|
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
|
||||||
timeout ? timeout_xml : "",
|
|
||||||
persist_id ? persist_id_xml : "",
|
|
||||||
persist ? persist_xml : "");
|
|
||||||
} else {
|
|
||||||
msg = clicon_msg_encode(session_id,
|
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><commit>%s</commit></rpc>",
|
|
||||||
NETCONF_BASE_NAMESPACE,
|
|
||||||
username ? username : "",
|
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
|
||||||
persist ? persist_xml : "");
|
|
||||||
}
|
}
|
||||||
if (msg == NULL)
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
if (cancel) {
|
||||||
|
cprintf(cb, "<cancel-commit>%s</cancel-commit>",
|
||||||
|
persist_id ? persist_id_xml : "");
|
||||||
|
}
|
||||||
|
else if (confirmed) {
|
||||||
|
cprintf(cb, "<commit><confirmed/>%s%s%s</commit>",
|
||||||
|
timeout ? timeout_xml : "",
|
||||||
|
persist_id ? persist_id_xml : "",
|
||||||
|
persist ? persist_xml : "");
|
||||||
|
} else {
|
||||||
|
cprintf(cb, "<commit>%s</commit>",
|
||||||
|
persist ? persist_xml : "");
|
||||||
|
}
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1361,6 +1491,8 @@ clicon_rpc_commit(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -1375,6 +1507,7 @@ clicon_rpc_commit(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Discard all changes in candidate / revert to running
|
/*! Discard all changes in candidate / revert to running
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error and logged to syslog
|
* @retval -1 Error and logged to syslog
|
||||||
|
|
@ -1388,15 +1521,25 @@ clicon_rpc_discard_changes(clicon_handle h)
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><discard-changes/></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
username?username:"",
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR)) == NULL)
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<discard-changes/>");
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1406,6 +1549,8 @@ clicon_rpc_discard_changes(clicon_handle h)
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -1414,13 +1559,13 @@ clicon_rpc_discard_changes(clicon_handle h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create a new notification subscription
|
/*! Create a new notification subscription
|
||||||
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param{in] stream name of notificatio/log stream (CLICON is predefined)
|
* @param{in] stream name of notificatio/log stream (CLICON is predefined)
|
||||||
* @param{in] filter message filter, eg xpath for xml notifications
|
* @param{in] filter message filter, eg xpath for xml notifications
|
||||||
* @param[out] s0 socket returned where notification mesages will appear
|
* @param[out] s0 socket returned where notification mesages will appear
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error and logged to syslog
|
* @retval -1 Error and logged to syslog
|
||||||
|
|
||||||
* @note When using netconf create-subsrciption,status and format is not supported
|
* @note When using netconf create-subsrciption,status and format is not supported
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -1435,20 +1580,31 @@ clicon_rpc_create_subscription(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><create-subscription xmlns=\"%s\">"
|
goto done;
|
||||||
"<stream>%s</stream>"
|
}
|
||||||
"<filter type=\"xpath\" select=\"%s\" />"
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
"</create-subscription></rpc>",
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_BASE_NAMESPACE,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
username?username:"",
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
EVENT_RFC5277_NAMESPACE,
|
}
|
||||||
stream?stream:"", filter?filter:"")) == NULL)
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<create-subscription xmlns=\"%s\">"
|
||||||
|
"<stream>%s</stream>"
|
||||||
|
"<filter type=\"xpath\" select=\"%s\" />"
|
||||||
|
"</create-subscription>",
|
||||||
|
EVENT_RFC5277_NAMESPACE,
|
||||||
|
stream?stream:"",
|
||||||
|
filter?filter:"");
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg_persistent(h, msg, &xret, s0) < 0)
|
if (clicon_rpc_msg_persistent(h, msg, &xret, s0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1458,6 +1614,8 @@ clicon_rpc_create_subscription(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
if (msg)
|
if (msg)
|
||||||
|
|
@ -1466,6 +1624,7 @@ clicon_rpc_create_subscription(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send a debug request to backend server
|
/*! Send a debug request to backend server
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] level Debug level
|
* @param[in] level Debug level
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -1481,17 +1640,26 @@ clicon_rpc_debug(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><debug xmlns=\"%s\"><level>%d</level></debug></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
username?username:"",
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
CLIXON_LIB_NS,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
level)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<debug xmlns=\"%s\"><level>%d</level></debug>", CLIXON_LIB_NS, level);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1505,6 +1673,8 @@ clicon_rpc_debug(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (msg)
|
if (msg)
|
||||||
free(msg);
|
free(msg);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
@ -1532,17 +1702,29 @@ clicon_rpc_restconf_debug(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><edit-config><target><candidate/></target><config><restconf xmlns=\"%s\"><debug>%d</debug></restconf></config></edit-config></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
username?username:"",
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
CLIXON_RESTCONF_NS,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
level)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<edit-config><target><candidate/></target><config>");
|
||||||
|
cprintf(cb, "<restconf xmlns=\"%s\"><debug>%d</debug></restconf>",
|
||||||
|
CLIXON_RESTCONF_NS,
|
||||||
|
level);
|
||||||
|
cprintf(cb, "</config></edit-config>");
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1557,6 +1739,8 @@ clicon_rpc_restconf_debug(clicon_handle h,
|
||||||
if ((retval = clicon_rpc_commit(h, 0, 0, 0, NULL, NULL)) < 1)
|
if ((retval = clicon_rpc_commit(h, 0, 0, 0, NULL, NULL)) < 1)
|
||||||
goto done;
|
goto done;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (msg)
|
if (msg)
|
||||||
free(msg);
|
free(msg);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
@ -1564,17 +1748,25 @@ clicon_rpc_restconf_debug(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send a hello request to the backend server
|
/*! Send a hello request to the backend server on INTERNAL netconf connection
|
||||||
* @param[in] h CLICON handle
|
*
|
||||||
* @param[in] level Debug level
|
* @param[in] h Clixon handle
|
||||||
* @retval 0 OK
|
* @param[in] transport RFC 6022 transport.
|
||||||
* @retval -1 Error and logged to syslog
|
* @param[in] source_host RFC 6022 source-host
|
||||||
|
* @param[out] id Session id returned by backend
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error and logged to syslog
|
||||||
* @note this is internal netconf to backend, not northbound to user client
|
* @note this is internal netconf to backend, not northbound to user client
|
||||||
* @note this deviates from RFC6241 slightly in that it waits for a reply, the RFC does not
|
* @note this deviates from RFC6241 slightly in that it waits for a reply, the RFC does not
|
||||||
* stipulate that.
|
* stipulate that.
|
||||||
|
* @note transport is an identity defined in RFC6022 with added values in clixon-lib.yang for clixon,
|
||||||
|
* and should in those cases be prefixed with the localname "cl:",
|
||||||
|
* Example: cl:cli, cl:restconf, cl:netconf
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_hello_req(clicon_handle h,
|
clicon_hello_req(clicon_handle h,
|
||||||
|
char *transport,
|
||||||
|
char *source_host,
|
||||||
uint32_t *id)
|
uint32_t *id)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -1585,12 +1777,39 @@ clicon_hello_req(clicon_handle h,
|
||||||
char *username;
|
char *username;
|
||||||
char *b;
|
char *b;
|
||||||
int ret;
|
int ret;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
int clixon_lib = 0;
|
||||||
|
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(0, "<hello username=\"%s\" xmlns=\"%s\"><capabilities><capability>%s</capability></capabilities></hello>",
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
username?username:"",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
NETCONF_BASE_CAPABILITY_1_1)) == NULL)
|
cprintf(cb, "<hello xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
clixon_lib++;
|
||||||
|
}
|
||||||
|
/* RFC 6022 session parameters transport and source-host */
|
||||||
|
if (transport == NULL)
|
||||||
|
clicon_data_get(h, "session-transport", &transport);
|
||||||
|
if (transport){
|
||||||
|
cprintf(cb, " %s:transport=\"%s\"", CLIXON_LIB_PREFIX, transport);
|
||||||
|
clixon_lib++;
|
||||||
|
}
|
||||||
|
if (source_host == NULL)
|
||||||
|
clicon_data_get(h, "session-source-host", &source_host);
|
||||||
|
if (source_host){
|
||||||
|
cprintf(cb, " %s:source-host=\"%s\"", CLIXON_LIB_PREFIX, source_host);
|
||||||
|
clixon_lib++;
|
||||||
|
}
|
||||||
|
if (clixon_lib)
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<capabilities><capability>%s</capability></capabilities>",
|
||||||
|
NETCONF_BASE_CAPABILITY_1_1);
|
||||||
|
cprintf(cb, "</hello>");
|
||||||
|
|
||||||
|
if ((msg = clicon_msg_encode(0, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1609,6 +1828,8 @@ clicon_hello_req(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (msg)
|
if (msg)
|
||||||
free(msg);
|
free(msg);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
@ -1617,6 +1838,7 @@ clicon_hello_req(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Send a restart plugin request to backend server
|
/*! Send a restart plugin request to backend server
|
||||||
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] level Debug level
|
* @param[in] level Debug level
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -1632,17 +1854,26 @@ clicon_rpc_restart_plugin(clicon_handle h,
|
||||||
cxobj *xerr;
|
cxobj *xerr;
|
||||||
char *username;
|
char *username;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if (session_id_check(h, &session_id) < 0)
|
if (session_id_check(h, &session_id) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
username = clicon_username_get(h);
|
if ((cb = cbuf_new()) == NULL){
|
||||||
if ((msg = clicon_msg_encode(session_id,
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
"<rpc xmlns=\"%s\" username=\"%s\" %s><restart-plugin xmlns=\"%s\"><plugin>%s</plugin></restart-plugin></rpc>",
|
goto done;
|
||||||
NETCONF_BASE_NAMESPACE,
|
}
|
||||||
username?username:"",
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
NETCONF_MESSAGE_ID_ATTR,
|
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
CLIXON_LIB_NS,
|
if ((username = clicon_username_get(h)) != NULL){
|
||||||
plugin)) == NULL)
|
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
|
}
|
||||||
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
cprintf(cb, "<restart-plugin xmlns=\"%s\"><plugin>%s</plugin></restart-plugin>",
|
||||||
|
CLIXON_LIB_NS, plugin);
|
||||||
|
cprintf(cb, "</rpc>");
|
||||||
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1656,6 +1887,8 @@ clicon_rpc_restart_plugin(clicon_handle h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
if (msg)
|
if (msg)
|
||||||
free(msg);
|
free(msg);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
|
||||||
|
|
@ -2332,6 +2332,42 @@ xml_attr_insert2val(char *instr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Add attribute and value to an xml element as well as namespace mapping
|
||||||
|
*
|
||||||
|
* @param[in] xn XML element
|
||||||
|
* @param[in] name Attribute name
|
||||||
|
* @param[in] value Attribute value
|
||||||
|
* @param[in] prefix Attribute prefix, or NULL
|
||||||
|
* @param[in] namespace Attribute prefix, if NULL do not add namespace mapping
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xml_add_attr(cxobj *xn,
|
||||||
|
char *name,
|
||||||
|
char *value,
|
||||||
|
char *prefix,
|
||||||
|
char *namespace)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xa;
|
||||||
|
char *ns = NULL;
|
||||||
|
|
||||||
|
if ((xa = xml_new(name, xn, CX_ATTR)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (prefix && xml_prefix_set(xa, prefix) < 0) /* clixon lib */
|
||||||
|
goto done;
|
||||||
|
if (xml_value_set(xa, value) < 0)
|
||||||
|
goto done;
|
||||||
|
if (namespace){
|
||||||
|
if (xml2ns(xn, prefix, &ns) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ns == NULL && xmlns_set(xn, prefix, namespace) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Specialization of clicon_debug with xml tree
|
/*! Specialization of clicon_debug with xml tree
|
||||||
* @param[in] level log level, eg LOG_DEBUG,LOG_INFO,...,LOG_EMERG.
|
* @param[in] level log level, eg LOG_DEBUG,LOG_INFO,...,LOG_EMERG.
|
||||||
* @param[in] x XML tree that is logged without prettyprint
|
* @param[in] x XML tree that is logged without prettyprint
|
||||||
|
|
|
||||||
|
|
@ -611,15 +611,10 @@ xml_add_default_tag(cxobj *x,
|
||||||
uint16_t flags)
|
uint16_t flags)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xattr;
|
|
||||||
|
|
||||||
if (xml_flag(x, flags)) {
|
if (xml_flag(x, flags)) {
|
||||||
/* set default attribute */
|
/* set default attribute */
|
||||||
if ((xattr = xml_new("default", x, CX_ATTR)) == NULL)
|
if (xml_add_attr(x, "default", "true", IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, NULL) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_value_set(xattr, "true") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_prefix_set(xattr, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -648,7 +648,6 @@ xml_namespace_change(cxobj *x,
|
||||||
/* Add prefix to x, if any */
|
/* Add prefix to x, if any */
|
||||||
if (prefix && xml_prefix_set(x, prefix) < 0)
|
if (prefix && xml_prefix_set(x, prefix) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
}
|
}
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -569,6 +569,7 @@ xml2ns_recurse(cxobj *xt)
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see xml2ns
|
* @see xml2ns
|
||||||
|
* @see xml_add_attr generic method for adding an attribute
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmlns_set(cxobj *x,
|
xmlns_set(cxobj *x,
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@
|
||||||
#include "clixon_xml_map.h"
|
#include "clixon_xml_map.h"
|
||||||
#include "clixon_yang_parse_lib.h"
|
#include "clixon_yang_parse_lib.h"
|
||||||
|
|
||||||
|
/*! Create modstate structure
|
||||||
|
*
|
||||||
|
* @retval md modstate struct
|
||||||
|
* @retval NULL Error
|
||||||
|
* @see modstate_diff_free
|
||||||
|
*/
|
||||||
modstate_diff_t *
|
modstate_diff_t *
|
||||||
modstate_diff_new(void)
|
modstate_diff_new(void)
|
||||||
{
|
{
|
||||||
|
|
@ -95,6 +101,12 @@ modstate_diff_new(void)
|
||||||
return md;
|
return md;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Free modstate structure
|
||||||
|
*
|
||||||
|
* @param[in] md Modstate struct
|
||||||
|
* @retval 0 OK
|
||||||
|
* @see modstate_diff_new
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
modstate_diff_free(modstate_diff_t *md)
|
modstate_diff_free(modstate_diff_t *md)
|
||||||
{
|
{
|
||||||
|
|
@ -111,7 +123,9 @@ modstate_diff_free(modstate_diff_t *md)
|
||||||
/*! Init the Yang module library
|
/*! Init the Yang module library
|
||||||
*
|
*
|
||||||
* Load RFC7895 yang spec, module-set-id, etc.
|
* Load RFC7895 yang spec, module-set-id, etc.
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
* @see netconf_module_load
|
* @see netconf_module_load
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -167,6 +181,13 @@ yang_modules_revision(clicon_handle h)
|
||||||
|
|
||||||
/*! Actually build the yang modules state XML tree according to RFC8525
|
/*! Actually build the yang modules state XML tree according to RFC8525
|
||||||
*
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] yspec
|
||||||
|
* @param[in] msid
|
||||||
|
* @param[in] brief
|
||||||
|
* @param[out] cb
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
* This assumes CLICON_YANG_LIBRARY is enabled
|
* This assumes CLICON_YANG_LIBRARY is enabled
|
||||||
* If also CLICON_MODULE_LIBRARY_RFC7895 is set, module-state is built according to RFC7895 instead
|
* If also CLICON_MODULE_LIBRARY_RFC7895 is set, module-state is built according to RFC7895 instead
|
||||||
* @see RFC8525
|
* @see RFC8525
|
||||||
|
|
@ -277,9 +298,9 @@ yms_build(clicon_handle h,
|
||||||
* @param[in] nsc XML Namespace context for xpath
|
* @param[in] nsc XML Namespace context for xpath
|
||||||
* @param[in] brief Just name, revision and uri (no cache)
|
* @param[in] brief Just name, revision and uri (no cache)
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
* @retval -1 Error (fatal)
|
|
||||||
* @retval 0 Statedata callback failed
|
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
|
* @retval 0 Statedata callback failed
|
||||||
|
* @retval -1 Error (fatal)
|
||||||
* @notes NYI: schema, deviation
|
* @notes NYI: schema, deviation
|
||||||
x +--ro modules-state
|
x +--ro modules-state
|
||||||
x +--ro module-set-id string
|
x +--ro module-set-id string
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ DATASTORE_TOP="config"
|
||||||
|
|
||||||
# clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in)
|
# clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in)
|
||||||
CLIXON_AUTOCLI_REV="2022-02-11"
|
CLIXON_AUTOCLI_REV="2022-02-11"
|
||||||
CLIXON_LIB_REV="2021-12-05"
|
CLIXON_LIB_REV="2022-12-01"
|
||||||
CLIXON_CONFIG_REV="2022-03-21"
|
CLIXON_CONFIG_REV="2022-12-01"
|
||||||
CLIXON_RESTCONF_REV="2022-08-01"
|
CLIXON_RESTCONF_REV="2022-08-01"
|
||||||
CLIXON_EXAMPLE_REV="2022-11-01"
|
CLIXON_EXAMPLE_REV="2022-11-01"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,16 +68,13 @@ new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
new "Retrieving all state via <get> operation"
|
new "Retrieving all state via <get> operation"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get/></rpc>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:base:1.1</capability>.*<capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</capability>.*</capabilities><datastores><datastore><name>candidate</name></datastore><datastore><name>running</name></datastore></datastores><schemas>.*</schemas></netconf-state></data></rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get/></rpc>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:base:1.1</capability>.*<capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</capability>.*</capabilities><datastores><datastore><name>candidate</name></datastore><datastore><name>running</name></datastore></datastores><schemas>.*</schemas><sessions>.*</sessions></netconf-state></data></rpc-reply>"
|
||||||
|
|
||||||
# send multiple frames
|
# send multiple frames
|
||||||
rpc=$(chunked_framing "<rpc $DEFAULTNS><lock><target><candidate/></target></lock></rpc>")
|
rpc=$(chunked_framing "<rpc $DEFAULTNS><lock><target><candidate/></target></lock></rpc>")
|
||||||
rpc="${rpc}
|
rpc="${rpc}
|
||||||
$(chunked_framing "<rpc $DEFAULTNS><get><filter type=\"subtree\"><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><datastores><datastore><name>candidate</name></datastore></datastores></netconf-state></filter></get></rpc>")"
|
$(chunked_framing "<rpc $DEFAULTNS><get><filter type=\"subtree\"><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><datastores><datastore><name>candidate</name></datastore></datastores></netconf-state></filter></get></rpc>")"
|
||||||
|
|
||||||
reply=$(chunked_framing "<rpc-reply $DEFAULTNS><ok/>/rpc-reply")
|
|
||||||
reply=${reply}$(chunked_framing "<rpc-reply $DEFAULTNS><data><netconf-state xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"><datastores><datastore><name>candidate</name><locks><locked-by-session>3</locked-by-session><locked-time>2022-12-23T13:18:57.112204Z</locked-time></locks></datastore></datastores></netconf-state></data></rpc-reply")
|
|
||||||
|
|
||||||
new "Get databases with lock"
|
new "Get databases with lock"
|
||||||
ret=$($clixon_netconf -q -f $cfg <<EOF
|
ret=$($clixon_netconf -q -f $cfg <<EOF
|
||||||
$DEFAULTHELLO$rpc
|
$DEFAULTHELLO$rpc
|
||||||
|
|
@ -87,7 +84,7 @@ r=$?
|
||||||
if [ $r -ne 0 ]; then
|
if [ $r -ne 0 ]; then
|
||||||
err "0" "$r"
|
err "0" "$r"
|
||||||
fi
|
fi
|
||||||
for expect in "<rpc-reply $DEFAULTNS><ok/></rpc-reply>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><datastores><datastore><name>candidate</name><locks><locked-by-session>[0-9]+</locked-by-session><locked-time>202.*Z</locked-time></locks></datastore></datastores></netconf-state></data></rpc-reply"; do
|
for expect in "<rpc-reply $DEFAULTNS><ok/></rpc-reply>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><datastores><datastore><name>candidate</name><locks><global-lock><locked-by-session>[0-9]+</locked-by-session><locked-time>202.*Z</locked-time></global-lock></locks></datastore></datastores></netconf-state></data></rpc-reply"; do
|
||||||
new "expect:$expect"
|
new "expect:$expect"
|
||||||
match=`echo $ret | grep --null -Eo "$expect"`
|
match=`echo $ret | grep --null -Eo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
|
|
@ -100,6 +97,10 @@ done
|
||||||
new "Retrieving Schema List via <get> Operation"
|
new "Retrieving Schema List via <get> Operation"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get><filter type=\"subtree\"><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas/></netconf-state></filter></get></rpc>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema><identifier>clixon-example</identifier><version>2022-01-01</version><format>yang</format><namespace>urn:example:clixon</namespace><location>NETCONF</location></schema>.*<schema><identifier>clixon-sub</identifier><version>2022-01-01</version><format>yang</format><namespace>urn:example:clixon</namespace><location>NETCONF</location></schema><schema>.*</schemas></netconf-state></data></rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get><filter type=\"subtree\"><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas/></netconf-state></filter></get></rpc>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><schemas><schema><identifier>clixon-example</identifier><version>2022-01-01</version><format>yang</format><namespace>urn:example:clixon</namespace><location>NETCONF</location></schema>.*<schema><identifier>clixon-sub</identifier><version>2022-01-01</version><format>yang</format><namespace>urn:example:clixon</namespace><location>NETCONF</location></schema><schema>.*</schemas></netconf-state></data></rpc-reply>"
|
||||||
|
|
||||||
|
# Session
|
||||||
|
new "Retrieve Session"
|
||||||
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get><filter type=\"subtree\"><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><sessions/></netconf-state></filter></get></rpc>" "<rpc-reply $DEFAULTNS><data><netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\"><sessions><session><session-id>[1-9][0-9]*</session-id><transport xmlns:cl=\"http://clicon.org/lib\">cl:netconf</transport><username>.*</username><login-time>.*</login-time><in-rpcs>[0-9][0-9]*</in-rpcs><in-bad-rpcs>[0-9][0-9]*</in-bad-rpcs><out-rpc-errors>[0-9][0-9]*</out-rpc-errors><out-notifications>[0-9][0-9]*</out-notifications></session>.*</sessions></netconf-state></data></rpc-reply>"
|
||||||
|
|
||||||
# 4.2. Retrieving Schema Instances
|
# 4.2. Retrieving Schema Instances
|
||||||
# From 2b. bar, version 2008-06-1 in YANG format, via get-schema
|
# From 2b. bar, version 2008-06-1 in YANG format, via get-schema
|
||||||
new "Retrieving clixon-example schema instance using id, version, format"
|
new "Retrieving clixon-example schema instance using id, version, format"
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
# Note: mirror these to test/config.sh.in
|
# Note: mirror these to test/config.sh.in
|
||||||
YANGSPECS = clixon-config@2022-12-01.yang # 6.1
|
YANGSPECS = clixon-config@2022-12-01.yang # 6.1
|
||||||
YANGSPECS += clixon-lib@2021-12-05.yang # 5.5
|
YANGSPECS += clixon-lib@2022-12-01.yang # 6.1
|
||||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||||
YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9
|
YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,19 @@ module clixon-lib {
|
||||||
|
|
||||||
description
|
description
|
||||||
"Clixon Netconf extensions for communication between clients and backend.
|
"Clixon Netconf extensions for communication between clients and backend.
|
||||||
|
|
||||||
|
Clixon extends NETCONF for internal use with some internal attributes. These
|
||||||
|
are not visible for external usage bit belongs to the namespace of this YANG.
|
||||||
|
The internal attributes are:
|
||||||
|
- content (also RESTCONF)
|
||||||
|
- depth (also RESTCONF)
|
||||||
|
- username
|
||||||
|
- autocommit
|
||||||
|
- copystartup
|
||||||
|
- transport (see RFC6022)
|
||||||
|
- source-host (see RFC6022)
|
||||||
|
- objectcreate
|
||||||
|
- objectexisted
|
||||||
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
***** BEGIN LICENSE BLOCK *****
|
||||||
Copyright (C) 2009-2019 Olof Hagsand
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ module clixon-lib {
|
||||||
import ietf-yang-types {
|
import ietf-yang-types {
|
||||||
prefix yang;
|
prefix yang;
|
||||||
}
|
}
|
||||||
|
import ietf-netconf-monitoring {
|
||||||
|
prefix ncm;
|
||||||
|
}
|
||||||
organization
|
organization
|
||||||
"Clicon / Clixon";
|
"Clicon / Clixon";
|
||||||
|
|
||||||
|
|
@ -13,9 +16,7 @@ module clixon-lib {
|
||||||
"Olof Hagsand <olof@hagsand.se>";
|
"Olof Hagsand <olof@hagsand.se>";
|
||||||
|
|
||||||
description
|
description
|
||||||
"Clixon Netconf extensions for communication between clients and backend.
|
"***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
Copyright (C) 2009-2019 Olof Hagsand
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
|
@ -42,8 +43,37 @@ module clixon-lib {
|
||||||
the provisions above, a recipient may use your version of this file under
|
the provisions above, a recipient may use your version of this file under
|
||||||
the terms of any one of the Apache License version 2 or the GPL.
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****";
|
***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Clixon Netconf extensions for communication between clients and backend.
|
||||||
|
This scheme adds:
|
||||||
|
- Added values of RFC6022 transport identityref
|
||||||
|
- RPCs for debug, stats and process-control
|
||||||
|
- Informal description of attributes
|
||||||
|
|
||||||
|
Additionally, Clixon extends NETCONF for internal use with some internal attributes. These
|
||||||
|
are not visible for external usage bit belongs to the namespace of this YANG.
|
||||||
|
The internal attributes are:
|
||||||
|
- content (also RESTCONF)
|
||||||
|
- depth (also RESTCONF)
|
||||||
|
- username
|
||||||
|
- autocommit
|
||||||
|
- copystartup
|
||||||
|
- transport (see RFC6022)
|
||||||
|
- source-host (see RFC6022)
|
||||||
|
- objectcreate
|
||||||
|
- objectexisted
|
||||||
|
";
|
||||||
|
|
||||||
|
revision 2022-12-01 {
|
||||||
|
description
|
||||||
|
"Added values of RFC6022 transport identityref
|
||||||
|
Added description of internal netconf attributes";
|
||||||
|
}
|
||||||
|
revision 2021-12-05 {
|
||||||
|
description
|
||||||
|
"Obsoleted: extension autocli-op";
|
||||||
|
}
|
||||||
revision 2021-11-11 {
|
revision 2021-11-11 {
|
||||||
description
|
description
|
||||||
"Changed: RPC stats extended with YANG stats";
|
"Changed: RPC stats extended with YANG stats";
|
||||||
|
|
@ -101,6 +131,23 @@ module clixon-lib {
|
||||||
description
|
description
|
||||||
"Common operations that can be performed on a service";
|
"Common operations that can be performed on a service";
|
||||||
}
|
}
|
||||||
|
identity snmp {
|
||||||
|
description
|
||||||
|
"SNMP";
|
||||||
|
base ncm:transport;
|
||||||
|
}
|
||||||
|
identity netconf {
|
||||||
|
description
|
||||||
|
"Just NETCONF without specitic underlying transport,
|
||||||
|
Clixon uses stdio for its netconf client and therefore does not know whether it is
|
||||||
|
invoked in a script, by a NETCONF/SSH subsystem, etc";
|
||||||
|
base ncm:transport;
|
||||||
|
}
|
||||||
|
identity restconf {
|
||||||
|
description
|
||||||
|
"RESTCONF either as HTTP/1 or /2, TLS or not, reverese proxy (eg fcgi/nginx) or native";
|
||||||
|
base ncm:transport;
|
||||||
|
}
|
||||||
extension autocli-op {
|
extension autocli-op {
|
||||||
description
|
description
|
||||||
"Takes an argument an operation defing how to modify the clispec at
|
"Takes an argument an operation defing how to modify the clispec at
|
||||||
|
|
@ -109,8 +156,10 @@ module clixon-lib {
|
||||||
Operations is expected to be extended, but the following operations are defined:
|
Operations is expected to be extended, but the following operations are defined:
|
||||||
- hide This command is active but not shown by ? or TAB (meaning, it hides the auto-completion of commands)
|
- hide This command is active but not shown by ? or TAB (meaning, it hides the auto-completion of commands)
|
||||||
- hide-database This command hides the database
|
- hide-database This command hides the database
|
||||||
- hide-database-auto-completion This command hides the database and the auto completion (meaning, this command acts as both commands above)";
|
- hide-database-auto-completion This command hides the database and the auto completion (meaning, this command acts as both commands above)
|
||||||
|
Obsolete: use clixon-autocli:hide and clixon-autocli:hide-show instead";
|
||||||
argument cliop;
|
argument cliop;
|
||||||
|
status obsolete;
|
||||||
}
|
}
|
||||||
rpc debug {
|
rpc debug {
|
||||||
description "Set debug level of backend.";
|
description "Set debug level of backend.";
|
||||||
Loading…
Add table
Add a link
Reference in a new issue