diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index ab8d0b6c..0b4d8df1 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -89,44 +89,7 @@ ce_find_byid(struct client_entry *ce_list, return NULL; } -/*! Stream callback for netconf stream notification (RFC 5277) - * - * @param[in] h Clixon handle - * @param[in] op 0:event, 1:rm - * @param[in] event Event as XML - * @param[in] arg Extra argument provided in stream_ss_add - * @see stream_ss_add - */ -int -ce_event_cb(clicon_handle h, - int op, - cxobj *event, - void *arg) -{ - struct client_entry *ce = (struct client_entry *)arg; - - clixon_debug(CLIXON_DBG_DEFAULT, "%s op:%d", __FUNCTION__, op); - switch (op){ - case 1: - /* Risk of recursion here */ - if (ce->ce_s) - backend_client_rm(h, ce); - break; - default: - if (send_msg_notify_xml(h, ce->ce_s, ce->ce_source_host, event) < 0){ - if (errno == ECONNRESET || errno == EPIPE){ - clicon_log(LOG_WARNING, "client %d reset", ce->ce_nr); - } - break; - } - /* note there may be other notifications than RFC5277 streams */ - ce->ce_out_notifications++; - netconf_monitoring_counter_inc(h, "out-notifications"); - } - return 0; -} - -/*! Construct a client string from client_entry information for logging +/*! Construct a client string description from client_entry information for logging * * @param[in] ce Client entry struct * @param[out] cbp Cligen buffer, deallocate with cbuf_free @@ -134,8 +97,8 @@ ce_event_cb(clicon_handle h, * @retval -1 Error */ static int -ce_client_string(struct client_entry *ce, - cbuf **cbp) +ce_client_descr(struct client_entry *ce, + cbuf **cbp) { int retval = -1; cbuf *cb = NULL; @@ -148,12 +111,11 @@ ce_client_string(struct client_entry *ce, if ((cb = cbuf_new()) == NULL){ clicon_err(OE_UNIX, errno, "cbuf_new"); goto done; - } if (ce->ce_transport){ if (nodeid_split(ce->ce_transport, NULL, &id) < 0) goto done; - cprintf(cb, "%s", id); + cprintf(cb, "%s:", id); } cprintf(cb, "%u", ce->ce_id); *cbp = cb; @@ -164,6 +126,54 @@ ce_client_string(struct client_entry *ce, return retval; } +/*! Stream callback for netconf stream notification (RFC 5277) + * + * @param[in] h Clixon handle + * @param[in] op 0:event, 1:rm + * @param[in] event Event as XML + * @param[in] arg Extra argument provided in stream_ss_add + * @retval 0 OK + * @retval -1 Error + * @see stream_ss_add + */ +int +ce_event_cb(clicon_handle h, + int op, + cxobj *event, + void *arg) +{ + int retval = -1; + struct client_entry *ce = (struct client_entry *)arg; + cbuf *cbce = NULL; + + clixon_debug(CLIXON_DBG_DEFAULT, "%s op:%d", __FUNCTION__, op); + switch (op){ + case 1: + /* Risk of recursion here */ + if (ce->ce_s) + backend_client_rm(h, ce); + break; + default: + if (ce_client_descr(ce, &cbce) < 0) + goto done; + if (send_msg_notify_xml(h, ce->ce_s, cbuf_get(cbce), event) < 0){ + if (errno == ECONNRESET || errno == EPIPE){ + clicon_log(LOG_WARNING, "client %d reset", ce->ce_nr); + } + break; + } + /* note there may be other notifications than RFC5277 streams */ + ce->ce_out_notifications++; + netconf_monitoring_counter_inc(h, "out-notifications"); + } + retval = 0; + done: + if (cbce) + cbuf_free(cbce); + return retval; +} + + /*! Unlock all db:s of a client and call user unlock calback * * @see xmldb_unlock_all unlocks, but does not call user callbacks which is a backend thing @@ -290,6 +300,7 @@ backend_monitoring_state_get(clicon_handle h, * @param[in] ce Client handle * @retval 0 Ok * @retval -1 Error (fatal) + * @see backend_client_add for adding * @see backend_client_delete for actual deallocation of client entry struct */ int @@ -1628,7 +1639,18 @@ from_client_msg(clicon_handle h, * 3. Its a create-subscription message that uses a separate socket(=client) */ if (op_id != 0 && ce->ce_id != op_id && strcmp(rpcname, "create-subscription")){ + client_entry *ce0; + clixon_debug(CLIXON_DBG_DEFAULT, "%s Warning: incoming session-id:%u does not match ce_id:%u on socket: %d", __FUNCTION__, op_id, ce->ce_id, ce->ce_s); + /* Copy transport from orig client-entry */ + if (ce->ce_transport == NULL && + (ce0 = ce_find_byid(backend_client_list(h), op_id)) != NULL && + ce0->ce_transport){ + if ((ce->ce_transport = strdup(ce0->ce_transport)) == NULL){ + clicon_err(OE_UNIX, errno, "strdup"); + goto done; + } + } } /* Note that this validation is also made in xml_yang_validate_rpc, but not for hello */ @@ -1775,7 +1797,7 @@ from_client_msg(clicon_handle h, // XXX clixon_debug(CLIXON_DBG_MSG, "Reply:%s", cbuf_get(cbret)); /* XXX problem here is that cbret has not been parsed so may contain parse errors */ - if (ce_client_string(ce, &cbce) < 0) + if (ce_client_descr(ce, &cbce) < 0) goto done; if (send_msg_reply(ce->ce_s, cbuf_get(cbce), cbuf_get(cbret), cbuf_len(cbret)+1) < 0){ switch (errno){ @@ -1843,7 +1865,7 @@ from_client(int s, clicon_err(OE_NETCONF, EINVAL, "Internal error: s != ce->ce_s"); goto done; } - if (ce_client_string(ce, &cbce) < 0) + if (ce_client_descr(ce, &cbce) < 0) goto done; if (clicon_msg_rcv(ce->ce_s, cbuf_get(cbce), 0, &msg, &eof) < 0) goto done; diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index da1eb2a8..b1d8b8d0 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -828,7 +828,9 @@ from_client_commit(clicon_handle h, goto done; goto ok; } - if (ret == 1) + if (ret == 0) + clixon_debug(CLIXON_DBG_DEFAULT, "Commit candidate failed"); + else cprintf(cbret, "", NETCONF_BASE_NAMESPACE); ok: retval = 0; @@ -929,13 +931,13 @@ from_client_validate(clicon_handle h, /*! Restart specific backend plugins without full backend restart * - * Note, depending on plugin callbacks, there may be other dependencies which may make this + * @note, depending on plugin callbacks, there may be other dependencies which may make this * difficult in the general case. */ int -from_client_restart_one(clicon_handle h, +from_client_restart_one(clicon_handle h, clixon_plugin_t *cp, - cbuf *cbret) + cbuf *cbret) { int retval = -1; char *db = "tmp"; diff --git a/apps/backend/clixon_backend_client.h b/apps/backend/clixon_backend_client.h index c972afe7..bc31befa 100644 --- a/apps/backend/clixon_backend_client.h +++ b/apps/backend/clixon_backend_client.h @@ -53,6 +53,7 @@ * client socket and a separate notification client socket. * But they are the same session. * But the clixon client-entry do not differentiate + * @see backend_client_add */ struct client_entry{ struct client_entry *ce_next; /* The clients linked list */ diff --git a/apps/backend/clixon_backend_handle.c b/apps/backend/clixon_backend_handle.c index cdcccb62..65f41c8a 100644 --- a/apps/backend/clixon_backend_handle.c +++ b/apps/backend/clixon_backend_handle.c @@ -101,7 +101,11 @@ struct backend_handle { clicon_handle backend_handle_init(void) { - return clicon_handle_init0(sizeof(struct backend_handle)); + struct backend_handle *bh; + + bh = (struct backend_handle *)clicon_handle_init0(sizeof(struct backend_handle)); + bh->bh_ce_nr = 1; /* To align with session-id */ + return (clicon_handle)bh; } /*! Deallocates a backend handle, including all client structs diff --git a/apps/restconf/restconf_native.c b/apps/restconf/restconf_native.c index 373c7e71..e70f53b4 100644 --- a/apps/restconf/restconf_native.c +++ b/apps/restconf/restconf_native.c @@ -1377,7 +1377,6 @@ restconf_ssl_accept_client(clicon_handle h, */ if (restconf_auth_type_get(h) == CLIXON_AUTH_CLIENT_CERTIFICATE){ X509 *peercert; - // XXX SSL_get1_peer_certificate(ssl) #if OPENSSL_VERSION_NUMBER < 0x30000000L if ((peercert = SSL_get_peer_certificate(rc->rc_ssl)) != NULL){ X509_free(peercert); diff --git a/example/main/autocli.xml b/example/main/autocli.xml new file mode 100644 index 00000000..6d92bd0a --- /dev/null +++ b/example/main/autocli.xml @@ -0,0 +1,14 @@ + + + false + kw-nokey + false + list container + true + + include clixon-example + clixon-example + enable + + + diff --git a/example/main/restconf.xml b/example/main/restconf.xml new file mode 100644 index 00000000..ac878aae --- /dev/null +++ b/example/main/restconf.xml @@ -0,0 +1,7 @@ + + + true + none + default
0.0.0.0
80false
+
+
diff --git a/lib/src/clixon_proto.c b/lib/src/clixon_proto.c index 3e5d404e..8d67cd7d 100644 --- a/lib/src/clixon_proto.c +++ b/lib/src/clixon_proto.c @@ -812,7 +812,7 @@ send_msg_reply(int s, static int send_msg_notify(int s, const char *descr, - char *event) + char *event) { int retval = -1; struct clicon_msg *msg = NULL; diff --git a/test/test_transaction_restart.sh b/test/test_transaction_restart.sh index 0781bc97..1f3281e8 100755 --- a/test/test_transaction_restart.sh +++ b/test/test_transaction_restart.sh @@ -128,7 +128,7 @@ for op in begin validate complete commit commit_done end; do done # Negative test: restart a plugin that does not exist -new "Send restart to nonexistatn plugin expect fail" +new "Send restart to nonexisting plugin expect fail" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xxx" "" "applicationbad-elementpluginerrorNo such plugin" if [ $BE -ne 0 ]; then diff --git a/yang/clixon/clixon-lib@2023-11-01.yang b/yang/clixon/clixon-lib@2023-11-01.yang index cadc51ca..620bfedc 100644 --- a/yang/clixon/clixon-lib@2023-11-01.yang +++ b/yang/clixon/clixon-lib@2023-11-01.yang @@ -185,7 +185,7 @@ module clixon-lib { } identity restconf { description - "RESTCONF either as HTTP/1 or /2, TLS or not, reverese proxy (eg fcgi/nginx) or native"; + "RESTCONF either as HTTP/1 or /2, TLS or not, reverse proxy (eg fcgi/nginx) or native"; base ncm:transport; } identity cli {