Preparations for 6.2.0
Openssl 3.0 and autoconf 2.71
This commit is contained in:
parent
4643540391
commit
5d1c6b5759
8 changed files with 2764 additions and 2151 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
|
@ -1,6 +1,6 @@
|
|||
# Clixon Changelog
|
||||
|
||||
* [6.2.0](#620) Expected: April 2023
|
||||
* [6.2.0](#620) 30 April 2023
|
||||
* [6.1.0](#610) 19 Feb 2023
|
||||
* [6.0.0](#600) 29 Nov 2022
|
||||
* [5.9.0](#590) 24 September 2022
|
||||
|
|
@ -40,9 +40,11 @@
|
|||
* [3.3.1](#331) June 7 2017
|
||||
|
||||
## 6.2.0
|
||||
Expected: April 2023
|
||||
30 April 2023
|
||||
|
||||
### New features
|
||||
Clixon 6.2.0 brings no new major feature changes, but completes YANG
|
||||
schema mount and other features required by the clixon controller
|
||||
project, along with minor improvements and bugfixes.
|
||||
|
||||
### API changes on existing protocol/config features
|
||||
|
||||
|
|
@ -73,13 +75,12 @@ Developers may need to change their code
|
|||
|
||||
### Minor features
|
||||
|
||||
* Removed previous backward compatible compile-time options introduced in 6.0:
|
||||
* NETCONF_DEFAULT_RETRIEVAL_REPORT_AL
|
||||
* AUTOCLI_OBSOLETE_SKIP
|
||||
* Adjusted to Openssl 3.0
|
||||
* Unified netconf input function
|
||||
* Three different implementations were used in external, internal and controller code
|
||||
* Internal netconf still not moved to unified
|
||||
* The new clixon_netconf_input API unifies all three uses
|
||||
* Code still experimental controlled by `NEW_NETCONF_INPUT`
|
||||
* Code still experimental controlled by `NETCONF_INPUT_UNIFIED_INTERNAL`
|
||||
* RFC 8528 YANG schema mount
|
||||
* Made cli/autocli mount-point-aware
|
||||
* Internal NETCONF (client <-> backend)
|
||||
|
|
@ -92,7 +93,7 @@ Developers may need to change their code
|
|||
|
||||
### Corrected Bugs
|
||||
|
||||
* Fixed RESTCONF race conditions on SSL_shutdown sslerr ZERO_RETURN appears occasionally and exist.
|
||||
* Fixed RESTCONF race conditions on SSL_shutdown sslerr ZERO_RETURN appears occasionally and exits.
|
||||
* Fixed: RESTCONF: some client cert failure leads to restconf exit. Instead close and continue
|
||||
|
||||
## 6.1.0
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ See [documentation](https://clixon-docs.readthedocs.io), [project page](https://
|
|||
Clixon is open-source and dual licensed. Either Apache License, Version 2.0 or GNU
|
||||
General Public License Version 2; you choose, see [LICENSE.md](LICENSE.md).
|
||||
|
||||
Clixon has a master branch continuously tested with CI, but releases are made ca every second month. Latest 6.0.0 release is from November 2022. Next is planned for February 19 2023. See [CHANGELOG.md](CHANGELOG.md) release history.
|
||||
Clixon has a master branch continuously tested with CI, but releases are made ca every second month, see [Releases](https://github.com/clicon/clixon/releases) and [CHANGELOG.md](CHANGELOG.md) release history.
|
||||
|
||||
Clixon interaction is best done posting issues, pull requests, or joining the
|
||||
Matrix clixon forum https://matrix.to/#/#clixonforum:matrix.org.
|
||||
|
||||
Other clixon projects include [CLIgen](https://github.com/clicon/cligen), [the Clixon controller](https://github.com/clicon/clixon-controller), [clixon applications](https://github.com/clicon/clixon-examples) and others.
|
||||
|
||||
Clixon is sponsored by [Rubicon Communications LLC(Netgate)](https://www.netgate.com/) and [Akamai Technologies, Inc.](https://www.akamai.com).
|
||||
|
|
|
|||
|
|
@ -380,143 +380,6 @@ netconf_input_packet(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifndef NETCONF_INPUT_UNIFIED_EXTERN
|
||||
/*! Process incoming frame, ie a char message framed by ]]>]]>
|
||||
* Parse string to xml, check only one netconf message within a frame
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] cb Packet buffer
|
||||
* @param[out] eof Set to 1 if pending close socket
|
||||
* @retval 0 OK
|
||||
* @retval -1 Fatal error
|
||||
* @note there are errors detected here prior to whether you know what kind if message it is, and
|
||||
* these errors are returned as "rpc-error".
|
||||
* This is problematic since RFC6241 only says to return rpc-error on errors to <rpc>.
|
||||
* Not at this early stage, the incoming message can be something else such as <hello> or
|
||||
* something else.
|
||||
* In section 8.1 regarding handling of <hello> it says just to "terminate" the session which I
|
||||
* interpret as not sending anything back, just closing the session.
|
||||
* Anyway, clixon therefore does the following on error:
|
||||
* - Before we know what it is: send rpc-error
|
||||
* - Hello messages: terminate
|
||||
* - RPC messages: send rpc-error
|
||||
*/
|
||||
static int
|
||||
netconf_input_frame1(clicon_handle h,
|
||||
cbuf *cb,
|
||||
int *eof)
|
||||
{
|
||||
int retval = -1;
|
||||
char *str = NULL;
|
||||
cxobj *xtop = NULL; /* Request (in) */
|
||||
cxobj *xreq = NULL;
|
||||
cxobj *xret = NULL; /* Return (out) */
|
||||
cbuf *cbret = NULL;
|
||||
yang_stmt *yspec;
|
||||
int ret;
|
||||
netconf_framing_type framing;
|
||||
|
||||
clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
|
||||
clicon_debug(CLIXON_DBG_MSG, "Recv ext: %s", cbuf_get(cb));
|
||||
framing = clicon_data_int_get(h, NETCONF_FRAMING_TYPE);
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if ((str = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
/* Special case: */
|
||||
if (strlen(str) == 0){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_operation_failed(cbret, "rpc", "Empty XML")< 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Parse incoming XML message */
|
||||
if ((ret = clixon_xml_parse_string(str, YB_RPC, yspec, &xtop, &xret)) < 0){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_operation_failed(cbret, "rpc", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (ret == 0){
|
||||
/* Note: xtop can be "hello" in which case one (maybe) should drop the session and log
|
||||
* However, its not until netconf_input_packet that rpc vs hello vs other identification is
|
||||
* actually made.
|
||||
* Actually, there are no error replies to hello messages according to any RFC, so
|
||||
* rpc error reply here is non-standard, but may be useful.
|
||||
*/
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Check for empty frame (no mesaages), return empty message, not clear from RFC what to do */
|
||||
if (xml_child_nr_type(xtop, CX_ELMNT) == 0){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Check for multi-messages in frame */
|
||||
if (xml_child_nr_type(xtop, CX_ELMNT) != 1){
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_malformed_message(cbret, "More than one message in netconf rpc frame")< 0)
|
||||
goto done;
|
||||
if (netconf_output_encap(framing, cbret) < 0)
|
||||
goto done;
|
||||
if (netconf_output(1, cbret, "rpc-error") < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if ((xreq = xml_child_i_type(xtop, 0, CX_ELMNT)) == NULL){ /* Shouldnt happen */
|
||||
clicon_err(OE_XML, EFAULT, "No xml req (shouldnt happen)");
|
||||
goto done;
|
||||
}
|
||||
if (netconf_input_packet(h, xreq, yspec, eof) < 0)
|
||||
goto done;
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (str)
|
||||
free(str);
|
||||
if (xtop)
|
||||
xml_free(xtop);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
return retval;
|
||||
}
|
||||
#endif /* NETCONF_INPUT_UNIFIED_EXTERN */
|
||||
|
||||
/*! Get netconf message: detect end-of-msg
|
||||
* @param[in] s Socket where input arrived. read from this.
|
||||
* @param[in] arg Clixon handle.
|
||||
|
|
@ -528,7 +391,6 @@ netconf_input_frame1(clicon_handle h,
|
|||
* <a>foo ..pause.. </a>]]>]]>
|
||||
* then only "</a>" would be delivered to netconf_input_frame().
|
||||
*/
|
||||
#ifdef NETCONF_INPUT_UNIFIED_EXTERN
|
||||
static int
|
||||
netconf_input_cb(int s,
|
||||
void *arg)
|
||||
|
|
@ -659,137 +521,6 @@ netconf_input_cb(int s,
|
|||
return retval;
|
||||
}
|
||||
|
||||
#else /* NETCONF_INPUT_UNIFIED_EXTERN */
|
||||
|
||||
static int
|
||||
netconf_input_cb(int s,
|
||||
void *arg)
|
||||
{
|
||||
int retval = -1;
|
||||
unsigned char buf[BUFSIZ]; /* from stdio.h, typically 8K */
|
||||
clicon_handle h = arg;
|
||||
cbuf *cb=NULL;
|
||||
void *ptr;
|
||||
size_t cdatlen = 0;
|
||||
clicon_hash_t *cdat = clicon_data(h); /* Save cbuf between calls if not done */
|
||||
int poll;
|
||||
int i;
|
||||
int len;
|
||||
int frame_state;
|
||||
size_t frame_size;
|
||||
int ret;
|
||||
int eof = 0; /* Set to 1 if pending close socket */
|
||||
|
||||
if (clicon_option_exists(h, NETCONF_FRAME_STATE) == 0)
|
||||
frame_state = 0;
|
||||
else
|
||||
if ((frame_state = clicon_option_int(h, NETCONF_FRAME_STATE)) < 0)
|
||||
goto done;
|
||||
if (clicon_option_exists(h, NETCONF_FRAME_SIZE) == 0)
|
||||
frame_size = 0;
|
||||
else{
|
||||
if ((ret = clicon_option_int(h, NETCONF_FRAME_SIZE)) < 0)
|
||||
goto done;
|
||||
frame_size = (size_t)ret;
|
||||
}
|
||||
if ((ptr = clicon_hash_value(cdat, NETCONF_FRAME_MSG, &cdatlen)) != NULL){
|
||||
if (cdatlen != sizeof(cb)){
|
||||
clicon_err(OE_XML, errno, "size mismatch %lu %lu",
|
||||
(unsigned long)cdatlen, (unsigned long)sizeof(cb));
|
||||
goto done;
|
||||
}
|
||||
cb = *(cbuf**)ptr;
|
||||
clicon_hash_del(cdat, NETCONF_FRAME_MSG);
|
||||
}
|
||||
else{
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_XML, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
while (1){
|
||||
if ((len = read(s, buf, sizeof(buf))) < 0){
|
||||
if (errno == ECONNRESET)
|
||||
len = 0; /* emulate EOF */
|
||||
else{
|
||||
clicon_log(LOG_ERR, "%s: read: %s", __FUNCTION__, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
} /* read */
|
||||
if (len == 0){ /* EOF */
|
||||
clicon_debug(1, "%s len==0, closing", __FUNCTION__);
|
||||
clixon_event_unreg_fd(s, netconf_input_cb);
|
||||
close(s);
|
||||
clixon_exit_set(1);
|
||||
goto ok;
|
||||
}
|
||||
for (i=0; i<len; i++){
|
||||
if (buf[i] == 0)
|
||||
continue; /* Skip NULL chars (eg from terminals) */
|
||||
if (clicon_data_int_get(h, NETCONF_FRAMING_TYPE) == NETCONF_SSH_CHUNKED){
|
||||
/* Track chunked framing defined in RFC6242 */
|
||||
if ((ret = netconf_input_chunked_framing(buf[i], &frame_state, &frame_size)) < 0)
|
||||
goto done;
|
||||
switch (ret){
|
||||
case 1: /* chunk-data */
|
||||
cprintf(cb, "%c", buf[i]);
|
||||
break;
|
||||
case 2: /* end-of-data */
|
||||
/* Somewhat complex error-handling:
|
||||
* Ignore packet errors, UNLESS an explicit termination request (eof)
|
||||
*/
|
||||
if (netconf_input_frame1(h, cb, &eof) < 0 &&
|
||||
!ignore_packet_errors)
|
||||
goto done;
|
||||
if (eof)
|
||||
goto done;
|
||||
cbuf_reset(cb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
cprintf(cb, "%c", buf[i]);
|
||||
if (detect_endtag("]]>]]>", buf[i], &frame_state)){
|
||||
frame_state = 0;
|
||||
/* OK, we have an xml string from a client */
|
||||
/* Remove trailer */
|
||||
*(((char*)cbuf_get(cb)) + cbuf_len(cb) - strlen("]]>]]>")) = '\0';
|
||||
if (netconf_input_frame1(h, cb, &eof) < 0 &&
|
||||
!ignore_packet_errors) // default is to ignore errors
|
||||
goto done;
|
||||
if (eof)
|
||||
goto done;
|
||||
cbuf_reset(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* poll==1 if more, poll==0 if none */
|
||||
if ((poll = clixon_event_poll(s)) < 0)
|
||||
goto done;
|
||||
if (poll == 0){
|
||||
/* No data to read, save data and continue on next round */
|
||||
if (cbuf_len(cb) != 0){
|
||||
if (clicon_hash_add(cdat, NETCONF_FRAME_MSG, &cb, sizeof(cb)) == NULL)
|
||||
goto done;
|
||||
cb = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} /* while */
|
||||
ok:
|
||||
clicon_option_int_set(h, NETCONF_FRAME_STATE, frame_state);
|
||||
clicon_option_int_set(h, NETCONF_FRAME_SIZE, frame_size);
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return retval;
|
||||
}
|
||||
#endif /* NETCONF_INPUT_UNIFIED_EXTERN */
|
||||
|
||||
/*! Send netconf hello message
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] s File descriptor to write on (eg 1 - stdout)
|
||||
|
|
|
|||
|
|
@ -254,8 +254,13 @@ ssl_x509_name_oneline(SSL *ssl,
|
|||
clicon_err(OE_RESTCONF, EINVAL, "ssl or cn is NULL");
|
||||
goto done;
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
if ((cert = SSL_get_peer_certificate(ssl)) == NULL)
|
||||
goto ok;
|
||||
#else
|
||||
if ((cert = SSL_get1_peer_certificate(ssl)) == NULL)
|
||||
goto ok;
|
||||
#endif
|
||||
if ((name = X509_get_subject_name(cert)) == NULL)
|
||||
goto ok;
|
||||
if ((p = X509_NAME_oneline(name, NULL, 0)) == NULL)
|
||||
|
|
@ -1355,10 +1360,16 @@ 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);
|
||||
}
|
||||
#else
|
||||
if ((peercert = SSL_get1_peer_certificate(rc->rc_ssl)) != NULL){
|
||||
X509_free(peercert);
|
||||
}
|
||||
#endif
|
||||
else { /* Get certificates (if available) */
|
||||
if (proto != HTTP_2 &&
|
||||
native_send_badrequest(h, rc->rc_s, rc->rc_ssl, "application/yang-data+xml",
|
||||
|
|
|
|||
14
configure.ac
14
configure.ac
|
|
@ -38,7 +38,8 @@
|
|||
# in the directory containing this script.
|
||||
#
|
||||
|
||||
AC_INIT(lib/clixon/clixon.h.in)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([lib/clixon/clixon.h.in])
|
||||
|
||||
# Default CFLAGS and INSTALLFLAGS unless set by environment
|
||||
: ${INSTALLFLAGS="-s"}
|
||||
|
|
@ -148,7 +149,7 @@ AC_MSG_RESULT(LDFLAGS is $LDFLAGS)
|
|||
AC_MSG_RESULT(INSTALLFLAGS is $INSTALLFLAGS)
|
||||
|
||||
AC_PROG_YACC
|
||||
AC_PROG_LEX
|
||||
AC_PROG_LEX(noyywrap)
|
||||
if test "$LEX" = ":"; then
|
||||
AC_MSG_ERROR(CLIXON does not find lex or flex.)
|
||||
fi
|
||||
|
|
@ -368,8 +369,8 @@ fi
|
|||
|
||||
# Checks for getsockopt options for getting unix socket peer credentials on
|
||||
# Linux
|
||||
AC_TRY_COMPILE([#include <sys/socket.h>], [getsockopt(1, SOL_SOCKET, SO_PEERCRED, 0, 0);], [AC_DEFINE(HAVE_SO_PEERCRED, 1, [Have getsockopt SO_PEERCRED])
|
||||
AC_MSG_RESULT(Have getsockopt SO_PEERCRED)])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[getsockopt(1, SOL_SOCKET, SO_PEERCRED, 0, 0);]])],[AC_DEFINE(HAVE_SO_PEERCRED, 1, [Have getsockopt SO_PEERCRED])
|
||||
AC_MSG_RESULT(Have getsockopt SO_PEERCRED)],[])
|
||||
|
||||
# YANG_INSTALLDIR is where clixon installs the Clixon yang files and mandatory
|
||||
# standard yang files: the files in in yang/clixon and yang/mandatory
|
||||
|
|
@ -410,7 +411,7 @@ LIBDIR=`eval echo $libdir`
|
|||
LIBDIR=`eval echo $LIBDIR`
|
||||
LOCALSTATEDIR=`eval echo $localstatedir`
|
||||
|
||||
AC_OUTPUT(Makefile
|
||||
AC_CONFIG_FILES([Makefile
|
||||
lib/Makefile
|
||||
lib/src/Makefile
|
||||
lib/clixon/Makefile
|
||||
|
|
@ -440,4 +441,5 @@ AC_OUTPUT(Makefile
|
|||
test/config.sh
|
||||
test/cicd/Makefile
|
||||
test/vagrant/Makefile
|
||||
)
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
|
|
|||
|
|
@ -197,24 +197,3 @@
|
|||
* Introduced in 6.1, remove in 6.3
|
||||
*/
|
||||
#define AUTOCLI_DEPRECATED_HIDE
|
||||
|
||||
/*! Unified netconf input function
|
||||
* Replace external, internal and controller netconf eventually
|
||||
* New file: clixon_netconf_input.c with functions:
|
||||
* - netconf_input_read2
|
||||
* - netconf_input_msg2
|
||||
* - netconf_input_frame2
|
||||
* The following code should use this:
|
||||
* X - netconf_main.c external netconf
|
||||
* - netconf_proto.c internal netconf
|
||||
* - controller device control
|
||||
*/
|
||||
/*! Use unified netconf input function for external use
|
||||
* Introduced in 6.2
|
||||
*/
|
||||
#define NETCONF_INPUT_UNIFIED_EXTERN
|
||||
|
||||
/*! Use unified netconf input function for internal use
|
||||
* Introduced in 6.2
|
||||
*/
|
||||
#undef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ function memonce(){
|
|||
valgrindtest=2 # This means backend valgrind test
|
||||
: ${DEMWAIT:=10} # valgrind backend needs some time to get up
|
||||
# trace-children=no for test_restconf_rpc.sh
|
||||
sudo chown root $valgrindfile
|
||||
sudo chmod 777 $valgrindfile
|
||||
clixon_backend="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --log-file=$valgrindfile clixon_backend"
|
||||
;;
|
||||
'restconf')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue