* clicon_msg_rcv: Added intr parameter for interrupting on ^C (default 0)
* Internal NETCONF (client <-> backend) * Ensure message-id increments * Separated rpc from notification socket in same session * Removed coverage icon from homepage since it stopped working some time ago
This commit is contained in:
parent
453e97ef6b
commit
5822c1a72a
21 changed files with 140 additions and 68 deletions
|
|
@ -55,11 +55,15 @@ Users may have to change how they access the system
|
||||||
Developers may need to change their code
|
Developers may need to change their code
|
||||||
|
|
||||||
* C-API
|
* C-API
|
||||||
|
* `clicon_msg_rcv`: Added `intr` parameter for interrupting on `^C` (default 0)
|
||||||
* Renamed include file: `clixon_backend_handle.h`to `clixon_backend_client.h`
|
* Renamed include file: `clixon_backend_handle.h`to `clixon_backend_client.h`
|
||||||
* `candidate_commit()`: validate_level (added in 6.1) marked obsolete
|
* `candidate_commit()`: validate_level (added in 6.1) marked obsolete
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
* Internal NETCONF (client <-> backend)
|
||||||
|
* Ensure message-id increments
|
||||||
|
* Separated rpc from notification socket in same session
|
||||||
* Restconf: Added fallback mechanism for non-ALPN HTTPS
|
* Restconf: Added fallback mechanism for non-ALPN HTTPS
|
||||||
* Set `CLICON_RESTCONF_NOALPN_DEFAULT` to `http/2` or `http/1.1`
|
* Set `CLICON_RESTCONF_NOALPN_DEFAULT` to `http/2` or `http/1.1`
|
||||||
* For http/1 or http/2 only, that will be the default if no ALPN is set.
|
* For http/1 or http/2 only, that will be the default if no ALPN is set.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<img src="https://www.clicon.org/Clixon_logga_liggande_med-ikon.png" width="400">
|
<img src="https://www.clicon.org/Clixon_logga_liggande_med-ikon.png" width="400">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[](https://github.com/clicon/clixon/actions/workflows/ci.yml) [](https://clixon-docs.readthedocs.io/en/latest/?badge=latest) [](https://codecov.io/gh/clicon/clixon)
|
[](https://github.com/clicon/clixon/actions/workflows/ci.yml) [](https://clixon-docs.readthedocs.io/en/latest/?badge=latest)
|
||||||
|
|
||||||
Clixon is a YANG-based configuration manager, with interactive CLI,
|
Clixon is a YANG-based configuration manager, with interactive CLI,
|
||||||
NETCONF and RESTCONF interfaces, an embedded database and transaction
|
NETCONF and RESTCONF interfaces, an embedded database and transaction
|
||||||
|
|
|
||||||
|
|
@ -1554,14 +1554,6 @@ from_client_msg(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
/* Sanity check:
|
|
||||||
* op_id from internal message can be out-of-sync from client's sessions-id for the following reasons:
|
|
||||||
* 1. Its a hello when the client starts with op_id=0 to get its proper id on hello reply
|
|
||||||
* 2. The backend has restarted and the client uses an old op_id
|
|
||||||
*/
|
|
||||||
if (op_id != 0 && ce->ce_id != op_id){
|
|
||||||
clicon_debug(1, "%s Warning: incoming session-id:%u does not match socket ce_id:%u", __FUNCTION__, op_id, ce->ce_id);
|
|
||||||
}
|
|
||||||
/* Check for empty frame (no mesaages), return empty message, not clear from RFC what to do */
|
/* Check for empty frame (no mesaages), return empty message, not clear from RFC what to do */
|
||||||
if (xml_child_nr_type(xt, CX_ELMNT) == 0){
|
if (xml_child_nr_type(xt, CX_ELMNT) == 0){
|
||||||
if (netconf_malformed_message(cbret, "Empty message in netconf rpc frame")< 0)
|
if (netconf_malformed_message(cbret, "Empty message in netconf rpc frame")< 0)
|
||||||
|
|
@ -1580,6 +1572,15 @@ from_client_msg(clicon_handle h,
|
||||||
}
|
}
|
||||||
rpcname = xml_name(x);
|
rpcname = xml_name(x);
|
||||||
rpcprefix = xml_prefix(x);
|
rpcprefix = xml_prefix(x);
|
||||||
|
/* Sanity check:
|
||||||
|
* op_id from internal message can be out-of-sync from client's sessions-id for the following reasons:
|
||||||
|
* 1. Its a hello when the client starts with op_id=0 to get its proper id on hello reply
|
||||||
|
* 2. The backend has restarted and the client uses an old op_id
|
||||||
|
* 3. Its a create-subsciption message that uses a separate socket(=client)
|
||||||
|
*/
|
||||||
|
if (op_id != 0 && ce->ce_id != op_id && strcmp(rpcname, "create-subscription")){
|
||||||
|
clicon_debug(1, "%s Warning: incoming session-id:%u does not match ce_id:%u on socket: %d", __FUNCTION__, op_id, ce->ce_id, ce->ce_s);
|
||||||
|
}
|
||||||
/* Note that this validation is also made in xml_yang_validate_rpc, but not for hello
|
/* Note that this validation is also made in xml_yang_validate_rpc, but not for hello
|
||||||
*/
|
*/
|
||||||
if (xml2ns(x, rpcprefix, &namespace) < 0)
|
if (xml2ns(x, rpcprefix, &namespace) < 0)
|
||||||
|
|
@ -1786,7 +1787,7 @@ from_client(int s,
|
||||||
clicon_err(OE_NETCONF, EINVAL, "Internal error: s != ce->ce_s");
|
clicon_err(OE_NETCONF, EINVAL, "Internal error: s != ce->ce_s");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_msg_rcv(ce->ce_s, &msg, &eof) < 0)
|
if (clicon_msg_rcv(ce->ce_s, 0, &msg, &eof) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (eof){
|
if (eof){
|
||||||
backend_client_rm(h, ce);
|
backend_client_rm(h, ce);
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,11 @@
|
||||||
/* Backend 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
|
* References from RFC 6022, ietf-netconf-monitoring.yang sessions container
|
||||||
|
* @note that there is a discrepancy here between a client and a session
|
||||||
|
* A session may have multiple client endpoints, most notably a regular
|
||||||
|
* client socket and a separate notification client socket.
|
||||||
|
* But they are the same session.
|
||||||
|
* But the clixon client-entry do not differentiate
|
||||||
*/
|
*/
|
||||||
struct client_entry{
|
struct client_entry{
|
||||||
struct client_entry *ce_next; /* The clients linked list */
|
struct client_entry *ce_next; /* The clients linked list */
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,9 @@ cli_notification_register(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signal functions, not exported to API */
|
/* Signal functions
|
||||||
|
* This is for CLIgen to handle these signals, eg ^Ĉ means abort command, not program
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cli_signal_block(clicon_handle h)
|
cli_signal_block(clicon_handle h)
|
||||||
{
|
{
|
||||||
|
|
@ -1139,7 +1141,7 @@ cli_notification_cb(int s,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* get msg (this is the reason this function is called) */
|
/* get msg (this is the reason this function is called) */
|
||||||
if (clicon_msg_rcv(s, &reply, &eof) < 0)
|
if (clicon_msg_rcv(s, 0, &reply, &eof) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (eof){
|
if (eof){
|
||||||
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
|
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,8 @@ cli_terminate(clicon_handle h)
|
||||||
cvec *nsctx;
|
cvec *nsctx;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
|
if (clixon_exit_get() == 0)
|
||||||
|
clixon_exit_set(1);
|
||||||
if (clicon_data_get(h, "session-transport", NULL) == 0)
|
if (clicon_data_get(h, "session-transport", NULL) == 0)
|
||||||
clicon_rpc_close_session(h);
|
clicon_rpc_close_session(h);
|
||||||
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
||||||
|
|
|
||||||
|
|
@ -686,6 +686,8 @@ netconf_terminate(clicon_handle h)
|
||||||
cvec *nsctx;
|
cvec *nsctx;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
|
if (clixon_exit_get() == 0)
|
||||||
|
clixon_exit_set(1);
|
||||||
/* Delete all plugins, and RPC callbacks */
|
/* Delete all plugins, and RPC callbacks */
|
||||||
clixon_plugin_module_exit(h);
|
clixon_plugin_module_exit(h);
|
||||||
clicon_rpc_close_session(h);
|
clicon_rpc_close_session(h);
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ netconf_notification_cb(int s,
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
/* get msg (this is the reason this function is called) */
|
/* get msg (this is the reason this function is called) */
|
||||||
if (clicon_msg_rcv(s, &reply, &eof) < 0)
|
if (clicon_msg_rcv(s, 0, &reply, &eof) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* handle close from remote end: this will exit the client */
|
/* handle close from remote end: this will exit the client */
|
||||||
if (eof){
|
if (eof){
|
||||||
|
|
|
||||||
|
|
@ -913,7 +913,7 @@ restconf_openssl_init(clicon_handle h,
|
||||||
* - If no local config found, query backend for config and open sockets.
|
* - If no local config found, query backend for config and open sockets.
|
||||||
* That is, EITHER local config OR read config from backend once
|
* That is, EITHER local config OR read config from backend once
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] inline_config XML restconf config, malloced (if retval = 1)
|
* @param[in] inline_config If set, restconf conf is given by -R command-line
|
||||||
* @param[out] xrestconf XML restconf config, malloced (if retval = 1)
|
* @param[out] xrestconf XML restconf config, malloced (if retval = 1)
|
||||||
* @retval 1 OK (and xrestconf set)
|
* @retval 1 OK (and xrestconf set)
|
||||||
* @retval 0 Fail - no config
|
* @retval 0 Fail - no config
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ restconf_stream_cb(int s,
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
/* get msg (this is the reason this function is called) */
|
/* get msg (this is the reason this function is called) */
|
||||||
if (clicon_msg_rcv(s, &reply, &eof) < 0){
|
if (clicon_msg_rcv(s, 0, &reply, &eof) < 0){
|
||||||
clicon_debug(1, "%s msg_rcv error", __FUNCTION__);
|
clicon_debug(1, "%s msg_rcv error", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ int clixon_netconf_error_fn(const char *fn, const int line, cxobj *xerr, const c
|
||||||
int clixon_netconf_internal_error(cxobj *xerr, char *msg, char *arg);
|
int clixon_netconf_internal_error(cxobj *xerr, char *msg, char *arg);
|
||||||
int netconf_parse_uint32(char *name, char *valstr, char *defaultstr, uint32_t defaultval, cbuf *cbret, uint32_t *value);
|
int netconf_parse_uint32(char *name, char *valstr, char *defaultstr, uint32_t defaultval, cbuf *cbret, uint32_t *value);
|
||||||
int netconf_parse_uint32_xml(char *name, char *valstr, char *defaultstr, uint32_t defaultval, cxobj **xerr, uint32_t *value);
|
int netconf_parse_uint32_xml(char *name, char *valstr, char *defaultstr, uint32_t defaultval, cxobj **xerr, uint32_t *value);
|
||||||
|
int netconf_message_id_next(clicon_handle h);
|
||||||
int netconf_framing_preamble(netconf_framing_type framing, cbuf *cb);
|
int netconf_framing_preamble(netconf_framing_type framing, cbuf *cb);
|
||||||
int netconf_framing_postamble(netconf_framing_type framing, cbuf *cb);
|
int netconf_framing_postamble(netconf_framing_type framing, cbuf *cb);
|
||||||
int netconf_output(int s, cbuf *xf, char *msg);
|
int netconf_output(int s, cbuf *xf, char *msg);
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ int clicon_msg_send(int s, struct clicon_msg *msg);
|
||||||
|
|
||||||
int clicon_msg_send1(int s, cbuf *cb);
|
int clicon_msg_send1(int s, cbuf *cb);
|
||||||
|
|
||||||
int clicon_msg_rcv(int s, struct clicon_msg **msg, int *eof);
|
int clicon_msg_rcv(int s, int intr, struct clicon_msg **msg, int *eof);
|
||||||
|
|
||||||
int clicon_msg_rcv1(int s, cbuf *cb, int *eof);
|
int clicon_msg_rcv1(int s, cbuf *cb, int *eof);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ typedef void (*sigfn_t)(int);
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
|
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
|
||||||
|
int set_signal_flags(int signo, int flags, void (*handler)(int), void (**oldhandler)(int));
|
||||||
int clixon_signal_save(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
int clixon_signal_save(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
||||||
int clixon_signal_restore(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
int clixon_signal_restore(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
||||||
void clicon_signal_block(int);
|
void clicon_signal_block(int);
|
||||||
|
|
|
||||||
|
|
@ -504,6 +504,8 @@ xmldb_create(clicon_handle h,
|
||||||
* Utility function.
|
* Utility function.
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] db Symbolic database name, eg "candidate", "running"
|
* @param[in] db Symbolic database name, eg "candidate", "running"
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmldb_db_reset(clicon_handle h,
|
xmldb_db_reset(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -367,12 +367,7 @@ clicon_debug_get(void)
|
||||||
* print message if level >= dbglevel.
|
* print message if level >= dbglevel.
|
||||||
* The message is sent to clicon_log. EIther to syslog, stderr or both, depending on
|
* The message is sent to clicon_log. EIther to syslog, stderr or both, depending on
|
||||||
* clicon_log_init() setting
|
* clicon_log_init() setting
|
||||||
* The dbgdebug level strategy is a mask of the following masks:
|
* @param[in] dbglevel Mask of CLIXON_DBG_DEFAULT and other masks
|
||||||
* 1: Basic debug message, espcially initialization
|
|
||||||
* 2: Input and output packets, read datastore
|
|
||||||
* 4: Details: traces, parse trees, etc
|
|
||||||
* 8: Extra detailed logs, temporary logs
|
|
||||||
* @param[in] dbglevel Debug level 0: No debug, 1-7 combined of the CLIXON_DBG_ flags above
|
|
||||||
* @param[in] format Message to print as argv.
|
* @param[in] format Message to print as argv.
|
||||||
* @see clicon_debug_xml Specialization for XML tree
|
* @see clicon_debug_xml Specialization for XML tree
|
||||||
* @see CLIXON_DBG_DEFAULT and other flags
|
* @see CLIXON_DBG_DEFAULT and other flags
|
||||||
|
|
|
||||||
|
|
@ -2063,6 +2063,28 @@ netconf_parse_uint32_xml(char *name,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get next netconf rpc message-id
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @retval msgid Next message id
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
netconf_message_id_next(clicon_handle h)
|
||||||
|
{
|
||||||
|
int msgid;
|
||||||
|
|
||||||
|
if ((msgid=clicon_option_int(h, "netconf-message-id")) < 0){
|
||||||
|
clicon_option_str_set(h, "netconf-message-id", NETCONF_MESSAGE_ID_DEFAULT);
|
||||||
|
msgid = clicon_option_int(h, "netconf-message-id");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msgid++;
|
||||||
|
msgid %= 0x7ffffff; /* Wrap at some number */
|
||||||
|
clicon_option_int_set(h, "netconf-message-id", msgid);
|
||||||
|
}
|
||||||
|
return msgid;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Add netconf xml postamble of message. I.e, xml after the body of the message.
|
/*! Add netconf xml postamble of message. I.e, xml after the body of the message.
|
||||||
*
|
*
|
||||||
* @param[in] framing Netconf framing
|
* @param[in] framing Netconf framing
|
||||||
|
|
|
||||||
|
|
@ -679,7 +679,7 @@ api_path2xpath_cvv(cvec *api_path,
|
||||||
/* api-path: prefix points to module */
|
/* api-path: prefix points to module */
|
||||||
if (nodeid_split(nodeid, &prefix, &name) < 0)
|
if (nodeid_split(nodeid, &prefix, &name) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_debug(1, "%s [%d] cvname: %s:%s",
|
clicon_debug(CLIXON_DBG_DETAIL, "%s [%d] cvname: %s:%s",
|
||||||
__FUNCTION__, i, prefix?prefix:"", name);
|
__FUNCTION__, i, prefix?prefix:"", name);
|
||||||
/* top-node must have prefix */
|
/* top-node must have prefix */
|
||||||
if (i == offset && prefix == NULL){
|
if (i == offset && prefix == NULL){
|
||||||
|
|
@ -713,7 +713,7 @@ api_path2xpath_cvv(cvec *api_path,
|
||||||
*/
|
*/
|
||||||
if (xml_nsctx_get_prefix(nsc, namespace, &xprefix) == 0){
|
if (xml_nsctx_get_prefix(nsc, namespace, &xprefix) == 0){
|
||||||
xprefix = yang_find_myprefix(y);
|
xprefix = yang_find_myprefix(y);
|
||||||
clicon_debug(1, "%s prefix not found add it %s", __FUNCTION__, xprefix);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s prefix not found add it %s", __FUNCTION__, xprefix);
|
||||||
/* not found, add it to nsc
|
/* not found, add it to nsc
|
||||||
* XXX: do we always have to add it? It could be default?
|
* XXX: do we always have to add it? It could be default?
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ atomicio(ssize_t (*fn) (int, void *, size_t),
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case -1:
|
case -1:
|
||||||
if (errno == EINTR){
|
if (errno == EINTR){
|
||||||
if (!_atomicio_sig)
|
if (_atomicio_sig == 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (errno == EAGAIN)
|
else if (errno == EAGAIN)
|
||||||
|
|
@ -377,6 +377,7 @@ clicon_msg_send(int s,
|
||||||
* Now, ^C will interrupt the whole process, and this may not be what you want.
|
* Now, ^C will interrupt the whole process, and this may not be what you want.
|
||||||
*
|
*
|
||||||
* @param[in] s socket (unix or inet) to communicate with backend
|
* @param[in] s socket (unix or inet) to communicate with backend
|
||||||
|
* @param[in] intr If set, make a ^C cause an error
|
||||||
* @param[out] msg CLICON msg data reply structure. Free with free()
|
* @param[out] msg CLICON msg data reply structure. Free with free()
|
||||||
* @param[out] eof Set if eof encountered
|
* @param[out] eof Set if eof encountered
|
||||||
* Note: caller must ensure that s is closed if eof is set after call.
|
* Note: caller must ensure that s is closed if eof is set after call.
|
||||||
|
|
@ -384,6 +385,7 @@ clicon_msg_send(int s,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_msg_rcv(int s,
|
clicon_msg_rcv(int s,
|
||||||
|
int intr,
|
||||||
struct clicon_msg **msg,
|
struct clicon_msg **msg,
|
||||||
int *eof)
|
int *eof)
|
||||||
{
|
{
|
||||||
|
|
@ -396,10 +398,14 @@ clicon_msg_rcv(int s,
|
||||||
|
|
||||||
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
||||||
*eof = 0;
|
*eof = 0;
|
||||||
if (0)
|
if (intr){
|
||||||
set_signal(SIGINT, atomicio_sig_handler, &oldhandler);
|
clicon_signal_unblock(SIGINT);
|
||||||
|
set_signal_flags(SIGINT, 0, atomicio_sig_handler, &oldhandler);
|
||||||
|
}
|
||||||
if ((hlen = atomicio(read, s, &hdr, sizeof(hdr))) < 0){
|
if ((hlen = atomicio(read, s, &hdr, sizeof(hdr))) < 0){
|
||||||
|
if (intr && _atomicio_sig)
|
||||||
|
;
|
||||||
|
else
|
||||||
clicon_err(OE_CFG, errno, "atomicio");
|
clicon_err(OE_CFG, errno, "atomicio");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -413,14 +419,13 @@ clicon_msg_rcv(int s,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
mlen = ntohl(hdr.op_len);
|
mlen = ntohl(hdr.op_len);
|
||||||
clicon_debug(16, "op-len:%u op-id:%u",
|
clicon_debug(CLIXON_DBG_EXTRA, "op-len:%u op-id:%u",
|
||||||
mlen, ntohl(hdr.op_id));
|
mlen, ntohl(hdr.op_id));
|
||||||
clicon_debug(CLIXON_DBG_DETAIL, "%s: rcv msg len=%d",
|
clicon_debug(CLIXON_DBG_DETAIL, "%s: rcv msg len=%d",
|
||||||
__FUNCTION__, mlen);
|
__FUNCTION__, mlen);
|
||||||
if (mlen <= sizeof(hdr)){
|
if (mlen <= sizeof(hdr)){
|
||||||
clicon_err(OE_PROTO, 0, "op_len:%u too short", mlen);
|
clicon_err(OE_PROTO, 0, "op_len:%u too short", mlen);
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
assert(0);
|
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((*msg = (struct clicon_msg *)malloc(mlen+1)) == NULL){
|
if ((*msg = (struct clicon_msg *)malloc(mlen+1)) == NULL){
|
||||||
|
|
@ -449,8 +454,10 @@ clicon_msg_rcv(int s,
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
|
||||||
if (0)
|
if (intr){
|
||||||
set_signal(SIGINT, oldhandler, NULL);
|
set_signal(SIGINT, oldhandler, NULL);
|
||||||
|
clicon_signal_block(SIGINT);
|
||||||
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,7 +522,7 @@ clicon_msg_rcv1(int s,
|
||||||
clicon_debug(CLIXON_DBG_MSG, "Recv: %s", cbuf_get(cb));
|
clicon_debug(CLIXON_DBG_MSG, "Recv: %s", cbuf_get(cb));
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s done", __FUNCTION__);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s done", __FUNCTION__);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -564,7 +571,7 @@ clicon_rpc_connect_unix(clicon_handle h,
|
||||||
int s = -1;
|
int s = -1;
|
||||||
struct stat sb = {0,};
|
struct stat sb = {0,};
|
||||||
|
|
||||||
clicon_debug(1, "Send msg on %s", sockpath);
|
clicon_debug(CLIXON_DBG_DETAIL, "Send msg on %s", sockpath);
|
||||||
if (sock0 == NULL){
|
if (sock0 == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "sock0 expected");
|
clicon_err(OE_NETCONF, EINVAL, "sock0 expected");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -607,7 +614,7 @@ clicon_rpc_connect_inet(clicon_handle h,
|
||||||
int s = -1;
|
int s = -1;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
|
||||||
clicon_debug(1, "Send msg to %s:%hu", dst, port);
|
clicon_debug(CLIXON_DBG_DETAIL, "Send msg to %s:%hu", dst, port);
|
||||||
if (sock0 == NULL){
|
if (sock0 == NULL){
|
||||||
clicon_err(OE_NETCONF, EINVAL, "sock0 expected");
|
clicon_err(OE_NETCONF, EINVAL, "sock0 expected");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -662,7 +669,7 @@ clicon_rpc(int sock,
|
||||||
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
||||||
if (clicon_msg_send(sock, msg) < 0)
|
if (clicon_msg_send(sock, msg) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_msg_rcv(sock, &reply, eof) < 0)
|
if (clicon_msg_rcv(sock, 0, &reply, eof) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (*eof)
|
if (*eof)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -701,7 +708,7 @@ clicon_rpc1(int sock,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
||||||
if (netconf_framing_preamble(NETCONF_SSH_CHUNKED, msg) < 0)
|
if (netconf_framing_preamble(NETCONF_SSH_CHUNKED, msg) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (netconf_framing_postamble(NETCONF_SSH_CHUNKED, msg) < 0)
|
if (netconf_framing_postamble(NETCONF_SSH_CHUNKED, msg) < 0)
|
||||||
|
|
@ -712,7 +719,7 @@ clicon_rpc1(int sock,
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -803,7 +810,7 @@ send_msg_notify_xml(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval);
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -141,14 +141,17 @@ clicon_rpc_connect(clicon_handle h,
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @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[in] cache Use cached (client) socket, otherwise generate new socket
|
||||||
|
* @param[out] retdate Returned data as string
|
||||||
* @param[out] eof Set if eof encountered
|
* @param[out] eof Set if eof encountered
|
||||||
|
* @param[out] sp Returned socket
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
clicon_rpc_msg_once(clicon_handle h,
|
clicon_rpc_msg_once(clicon_handle h,
|
||||||
struct clicon_msg *msg,
|
struct clicon_msg *msg,
|
||||||
|
int cache,
|
||||||
char **retdata,
|
char **retdata,
|
||||||
int *eof,
|
int *eof,
|
||||||
int *sp)
|
int *sp)
|
||||||
|
|
@ -156,11 +159,15 @@ clicon_rpc_msg_once(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
|
if (cache){
|
||||||
if ((s = clicon_client_socket_get(h)) < 0){
|
if ((s = clicon_client_socket_get(h)) < 0){
|
||||||
if (clicon_rpc_connect(h, &s) < 0)
|
if (clicon_rpc_connect(h, &s) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_client_socket_set(h, s);
|
clicon_client_socket_set(h, s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (clicon_rpc_connect(h, &s) < 0)
|
||||||
|
goto done;
|
||||||
if (clicon_rpc(s, msg, retdata, eof) < 0){
|
if (clicon_rpc(s, msg, retdata, eof) < 0){
|
||||||
/* 2. check socket shutdown AFTER rpc */
|
/* 2. check socket shutdown AFTER rpc */
|
||||||
close(s);
|
close(s);
|
||||||
|
|
@ -203,7 +210,7 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
assert(strstr(msg->op_body, "username")!=NULL); /* XXX */
|
assert(strstr(msg->op_body, "username")!=NULL); /* XXX */
|
||||||
#endif
|
#endif
|
||||||
/* Create a socket and connect to it, either UNIX, IPv4 or IPv6 per config options */
|
/* Create a socket and connect to it, either UNIX, IPv4 or IPv6 per config options */
|
||||||
if (clicon_rpc_msg_once(h, msg, &retdata, &eof, &s) < 0)
|
if (clicon_rpc_msg_once(h, msg, 1, &retdata, &eof, &s) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (eof){
|
if (eof){
|
||||||
/* 2. check socket shutdown AFTER rpc */
|
/* 2. check socket shutdown AFTER rpc */
|
||||||
|
|
@ -212,7 +219,7 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
clicon_client_socket_set(h, -1);
|
clicon_client_socket_set(h, -1);
|
||||||
#ifdef PROTO_RESTART_RECONNECT
|
#ifdef PROTO_RESTART_RECONNECT
|
||||||
if (!clixon_exit_get()) { /* May be part of termination */
|
if (!clixon_exit_get()) { /* May be part of termination */
|
||||||
if (clicon_rpc_msg_once(h, msg, &retdata, &eof, NULL) < 0)
|
if (clicon_rpc_msg_once(h, msg, 1, &retdata, &eof, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (eof){
|
if (eof){
|
||||||
close(s);
|
close(s);
|
||||||
|
|
@ -286,7 +293,7 @@ clicon_rpc_msg_persistent(clicon_handle h,
|
||||||
#endif
|
#endif
|
||||||
clicon_debug(1, "%s request:%s", __FUNCTION__, msg->op_body);
|
clicon_debug(1, "%s request:%s", __FUNCTION__, msg->op_body);
|
||||||
/* Create a socket and connect to it, either UNIX, IPv4 or IPv6 per config options */
|
/* Create a socket and connect to it, either UNIX, IPv4 or IPv6 per config options */
|
||||||
if (clicon_rpc_msg_once(h, msg, &retdata, &eof, &s) < 0)
|
if (clicon_rpc_msg_once(h, msg, 0, &retdata, &eof, &s) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (eof){
|
if (eof){
|
||||||
/* 2. check socket shutdown AFTER rpc */
|
/* 2. check socket shutdown AFTER rpc */
|
||||||
|
|
@ -976,7 +983,7 @@ clicon_rpc_get(clicon_handle h,
|
||||||
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, 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\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
|
||||||
}
|
}
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR); /* XXX: use incrementing sequence */
|
cprintf(cb, " message-id=\"%d\"", netconf_message_id_next(h));
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,34 @@ int
|
||||||
set_signal(int signo,
|
set_signal(int signo,
|
||||||
void (*handler)(int),
|
void (*handler)(int),
|
||||||
void (**oldhandler)(int))
|
void (**oldhandler)(int))
|
||||||
|
{
|
||||||
|
return set_signal_flags(signo,
|
||||||
|
#if defined(HAVE_SIGACTION)
|
||||||
|
SA_RESTART,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
handler, oldhandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Set a signal handler, but without SA_RESTART
|
||||||
|
* @param[in] signo Signal number
|
||||||
|
* @param[in] flags Flags (to sigaction)
|
||||||
|
* @param[in] handler Function to call when signal occurs
|
||||||
|
* @param[out] oldhandler Pointer to old handler
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
set_signal_flags(int signo,
|
||||||
|
int flags,
|
||||||
|
void (*handler)(int),
|
||||||
|
void (**oldhandler)(int))
|
||||||
{
|
{
|
||||||
#if defined(HAVE_SIGACTION)
|
#if defined(HAVE_SIGACTION)
|
||||||
struct sigaction sold, snew;
|
struct sigaction sold, snew;
|
||||||
|
|
||||||
snew.sa_handler = handler;
|
snew.sa_handler = handler;
|
||||||
sigemptyset(&snew.sa_mask);
|
sigemptyset(&snew.sa_mask);
|
||||||
snew.sa_flags = SA_RESTART;
|
snew.sa_flags = flags;
|
||||||
if (sigaction(signo, &snew, &sold) < 0){
|
if (sigaction(signo, &snew, &sold) < 0){
|
||||||
clicon_err(OE_UNIX, errno, "sigaction");
|
clicon_err(OE_UNIX, errno, "sigaction");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -2432,7 +2432,7 @@ clicon_log_xml(int level,
|
||||||
|
|
||||||
/*! Specialization of clicon_debug with xml tree
|
/*! Specialization of clicon_debug with xml tree
|
||||||
*
|
*
|
||||||
* @param[in] dbglevel
|
* @param[in] dbglevel Mask of CLIXON_DBG_DEFAULT and other masks
|
||||||
* @param[in] x XML tree that is logged without prettyprint
|
* @param[in] x XML tree that is logged without prettyprint
|
||||||
* @param[in] format Message to print as argv.
|
* @param[in] format Message to print as argv.
|
||||||
* @see clicon_log_xml For syslog
|
* @see clicon_log_xml For syslog
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue