summaryrefslogtreecommitdiff
path: root/libfdcore/cnxctx.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfdcore/cnxctx.c')
-rw-r--r--libfdcore/cnxctx.c430
1 files changed, 224 insertions, 206 deletions
diff --git a/libfdcore/cnxctx.c b/libfdcore/cnxctx.c
index 04934e0..dab6812 100644
--- a/libfdcore/cnxctx.c
+++ b/libfdcore/cnxctx.c
@@ -2,7 +2,7 @@
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@freediameter.net> *
* *
-* Copyright (c) 2015, WIDE Project and NICT *
+* Copyright (c) 2020, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -176,7 +176,7 @@ struct cnxctx * fd_cnx_serv_sctp(uint16_t port, struct fd_list * ep_list)
} else {
cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */
}
-
+
/* Create the socket */
CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error );
@@ -226,41 +226,41 @@ struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv)
TRACE_ENTRY("%p", serv);
CHECK_PARAMS_DO(serv, return NULL);
-
+
/* Accept the new connection -- this is blocking until new client enters or until cancellation */
CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL );
-
+
CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } );
cli->cc_socket = cli_sock;
cli->cc_family = serv->cc_family;
cli->cc_proto = serv->cc_proto;
-
+
/* Set the timeout */
fd_cnx_s_setto(cli->cc_socket);
-
+
/* Generate the name for the connection object */
{
char addrbuf[INET6_ADDRSTRLEN];
char portbuf[10];
int rc;
-
+
rc = getnameinfo((sSA *)&ss, ss_len, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
if (rc) {
snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
portbuf[0] = '\0';
}
-
+
/* Numeric values for debug... */
- snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)",
+ snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)",
IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket);
-
-
+
+
/* ...Name for log messages */
rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0);
if (rc)
snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc));
}
-
+
LOG_D("Incoming connection: '%s' <- '%s' {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id);
#ifndef DISABLE_SCTP
@@ -272,7 +272,7 @@ struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv)
cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_out;
else
cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in;
-
+
LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out);
}
#endif /* DISABLE_SCTP */
@@ -286,14 +286,14 @@ struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa /* contains the port already */,
int sock = 0;
struct cnxctx * cnx = NULL;
char sa_buf[sSA_DUMP_STRLEN];
-
+
TRACE_ENTRY("%p %d", sa, addrlen);
CHECK_PARAMS_DO( sa && addrlen, return NULL );
-
+
fd_sa_sdump_numeric(sa_buf, sa);
-
+
LOG_D("Connecting to TCP %s...", sa_buf);
-
+
/* Create the socket and connect, which can take some time and/or fail */
{
int ret = fd_tcp_client( &sock, sa, addrlen );
@@ -302,36 +302,37 @@ struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa /* contains the port already */,
return NULL;
}
}
-
+
/* Once the socket is created successfuly, prepare the remaining of the cnx */
CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } );
-
+
cnx->cc_socket = sock;
cnx->cc_family = sa->sa_family;
cnx->cc_proto = IPPROTO_TCP;
-
+
/* Set the timeout */
fd_cnx_s_setto(cnx->cc_socket);
-
+
/* Generate the names for the object */
{
int rc;
-
+
snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf);
-
+
/* ...Name for log messages */
rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
if (rc)
snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
}
-
+
LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock);
-
+
return cnx;
}
-/* Same for SCTP, accepts a list of remote addresses to connect to (see sctp_connectx for how they are used) */
-struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list)
+/* Same for SCTP, accepts a list of remote addresses to connect to (see sctp_connectx for how they are used).
+ * If src_list is not NULL and not empty, list of local addresses to connect from via sctp_bindx(). */
+struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list, struct fd_list * src_list)
{
#ifdef DISABLE_SCTP
TRACE_DEBUG(INFO, "This function should never be called when SCTP is disabled...");
@@ -343,55 +344,72 @@ struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_lis
struct cnxctx * cnx = NULL;
char sa_buf[sSA_DUMP_STRLEN];
sSS primary;
-
- TRACE_ENTRY("%p", list);
+
+ TRACE_ENTRY("%p %p", list, src_list);
CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL );
-
+
+ /* Log SCTP association source and destination endpoints */
+ {
+ char * buf = NULL;
+ size_t len = 0, offset = 0;
+ CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset, "Connecting SCTP endpoints"), );
+ CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset, " source: "), );
+ if (src_list && !FD_IS_LIST_EMPTY(src_list)) {
+ CHECK_MALLOC_DO( fd_ep_dump( &buf, &len, &offset, 0, 0, src_list ), );
+ } else {
+ CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset, "(ANY)"), );
+ }
+ CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset, ", destination: "), );
+ CHECK_MALLOC_DO( fd_ep_dump( &buf, &len, &offset, 0, 0, list ), );
+ LOG_D("%s", buf ?: "Error determining SCTP endpoints");
+ free(buf);
+ }
+
fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa);
-
+
LOG_D("Connecting to SCTP %s:%hu...", sa_buf, port);
-
+
{
- int ret = fd_sctp_client( &sock, no_ip6, port, list );
+ int ret = fd_sctp_client( &sock, no_ip6, port, list, src_list );
if (ret != 0) {
LOG_D("SCTP connection to [%s,...] failed: %s", sa_buf, strerror(ret));
return NULL;
}
}
-
+
/* Once the socket is created successfuly, prepare the remaining of the cnx */
CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } );
-
+
cnx->cc_socket = sock;
cnx->cc_family = no_ip6 ? AF_INET : AF_INET6;
cnx->cc_proto = IPPROTO_SCTP;
-
+
/* Set the timeout */
fd_cnx_s_setto(cnx->cc_socket);
-
+
/* Retrieve the number of streams and primary address */
CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error );
if (cnx->cc_sctp_para.str_out < cnx->cc_sctp_para.str_in)
cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_out;
else
cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in;
-
+
fd_sa_sdump_numeric(sa_buf, (sSA *)&primary);
-
+
/* Generate the names for the object */
{
int rc;
-
+
snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf);
-
+
/* ...Name for log messages */
rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
if (rc)
snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
}
-
+
LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out);
-
+
return cnx;
error:
@@ -444,17 +462,17 @@ void fd_cnx_update_id(struct cnxctx * conn) {
conn->cc_id[1] = 'C';
else
conn->cc_id[1] = '-';
-
+
if (conn->cc_state & CC_STATUS_ERROR)
conn->cc_id[2] = 'E';
else
conn->cc_id[2] = '-';
-
+
if (conn->cc_state & CC_STATUS_SIGNALED)
conn->cc_id[3] = 'S';
else
conn->cc_id[3] = '-';
-
+
if (conn->cc_state & CC_STATUS_TLS)
conn->cc_id[4] = 'T';
else
@@ -508,7 +526,7 @@ int fd_cnx_getremoteeps(struct cnxctx * conn, struct fd_list * eps)
{
TRACE_ENTRY("%p %p", conn, eps);
CHECK_PARAMS(conn && eps);
-
+
/* Check we have a full connection object, not a listening socket (with no remote) */
CHECK_PARAMS( conn->cc_incoming );
@@ -546,16 +564,16 @@ char * fd_cnx_getremoteid(struct cnxctx * conn)
static int fd_cnx_may_dtls(struct cnxctx * conn);
/* Get a short string representing the connection */
-int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len)
+int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len)
{
CHECK_PARAMS( conn );
-
+
if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket);
} else {
snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket);
}
-
+
return 0;
}
@@ -563,27 +581,27 @@ int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len)
int fd_cnx_get_local_eps(struct fd_list * list)
{
struct ifaddrs *iflist, *cur;
-
+
CHECK_SYS(getifaddrs(&iflist));
-
+
for (cur = iflist; cur != NULL; cur = cur->ifa_next) {
if (cur->ifa_flags & IFF_LOOPBACK)
continue;
-
+
if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */
continue;
-
+
if (fd_g_config->cnf_flags.no_ip4 && (cur->ifa_addr->sa_family == AF_INET))
continue;
-
+
if (fd_g_config->cnf_flags.no_ip6 && (cur->ifa_addr->sa_family == AF_INET6))
continue;
-
+
CHECK_FCT(fd_ep_add_merge( list, cur->ifa_addr, sSAlen(cur->ifa_addr), EP_FL_LL ));
}
-
+
freeifaddrs(iflist);
-
+
return 0;
}
@@ -597,31 +615,31 @@ void fd_cnx_markerror(struct cnxctx * conn)
{
TRACE_ENTRY("%p", conn);
CHECK_PARAMS_DO( conn, goto fatal );
-
+
TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid);
/* Mark the error */
fd_cnx_addstate(conn, CC_STATUS_ERROR);
-
+
/* Report the error if not reported yet, and not closing */
if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING | CC_STATUS_SIGNALED )) {
TRACE_DEBUG(FULL, "Sending FDEVP_CNX_ERROR event");
CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_ERROR, 0, NULL), goto fatal);
fd_cnx_addstate(conn, CC_STATUS_SIGNALED);
}
-
+
return;
fatal:
/* An unrecoverable error occurred, stop the daemon */
ASSERT(0);
- CHECK_FCT_DO(fd_core_shutdown(), );
+ CHECK_FCT_DO(fd_core_shutdown(), );
}
/* Set the timeout option on the socket */
-void fd_cnx_s_setto(int sock)
+void fd_cnx_s_setto(int sock)
{
struct timeval tv;
-
+
/* Set a timeout on the socket so that in any case we are not stuck waiting for something */
memset(&tv, 0, sizeof(tv));
tv.tv_usec = 100000L; /* 100ms, to react quickly to head-of-the-line blocking. */
@@ -636,15 +654,15 @@ static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms)
{
fd_set rfds;
struct timeval tv;
-
+
FD_ZERO (&rfds);
FD_SET (conn->cc_socket, &rfds);
-
+
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms * 1000) % 1000000;
-
+
return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv);
-}
+}
#endif /* GNUTLS_VERSION_300 */
/* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */
@@ -664,13 +682,13 @@ again:
goto again;
}
}
-
+
/* Mark the error */
if (ret <= 0) {
CHECK_SYS_DO(ret, /* continue, this is only used to log the error here */);
fd_cnx_markerror(conn);
}
-
+
return ret;
}
@@ -686,7 +704,7 @@ again:
if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
ret = -errno;
pthread_testcancel();
-
+
/* Check how much time we were blocked for this sending. */
CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 );
if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
@@ -694,17 +712,17 @@ again:
} else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
goto again; /* don't care, just ignore */
}
-
+
/* propagate the error */
errno = -ret;
ret = -1;
CHECK_SYS_DO(ret, /* continue */);
}
-
+
/* Mark the error */
if (ret <= 0)
fd_cnx_markerror(conn);
-
+
return ret;
}
@@ -730,7 +748,7 @@ size_t fd_msg_pmdl_sizewithoverhead(size_t datalen)
struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen)
{
return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen));
-}
+}
static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
{
@@ -743,7 +761,7 @@ static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct
static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl)
{
uint8_t * ret = NULL;
-
+
CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
return ret;
@@ -753,14 +771,14 @@ static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl
static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
{
uint8_t * ret = NULL;
-
+
CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
return ret;
}
#endif /* DISABLE_SCTP */
-static void free_rcvdata(void * arg)
+static void free_rcvdata(void * arg)
{
struct fd_cnx_rcvdata * data = arg;
struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length);
@@ -772,21 +790,21 @@ static void free_rcvdata(void * arg)
static void * rcvthr_notls_tcp(void * arg)
{
struct cnxctx * conn = arg;
-
+
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
-
+
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Receiver (%d) TCP/noTLS)", conn->cc_socket);
fd_log_threadname ( buf );
}
-
+
ASSERT( conn->cc_proto == IPPROTO_TCP );
ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) );
ASSERT( fd_cnx_target_queue(conn) );
-
+
/* Receive from a TCP connection: we have to rebuild the message boundaries */
do {
uint8_t header[4];
@@ -802,7 +820,7 @@ static void * rcvthr_notls_tcp(void * arg)
}
received += ret;
-
+
if (header[0] != DIAMETER_VERSION)
break; /* No need to wait for 4 bytes in this case */
} while (received < sizeof(header));
@@ -833,22 +851,22 @@ static void * rcvthr_notls_tcp(void * arg)
}
received += ret;
}
-
+
fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
-
+
/* We have received a complete message, pass it to the daemon */
- CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
- {
+ CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
+ {
free_rcvdata(&rcv_data);
- goto fatal;
+ goto fatal;
} );
-
+
} while (conn->cc_loop);
-
+
out:
- TRACE_DEBUG(FULL, "Thread terminated");
+ TRACE_DEBUG(FULL, "Thread terminated");
return NULL;
-
+
fatal:
/* An unrecoverable error occurred, stop the daemon */
CHECK_FCT_DO(fd_core_shutdown(), );
@@ -862,21 +880,21 @@ static void * rcvthr_notls_sctp(void * arg)
struct cnxctx * conn = arg;
struct fd_cnx_rcvdata rcv_data;
int event;
-
+
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal);
-
+
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Receiver (%d) SCTP/noTLS)", conn->cc_socket);
fd_log_threadname ( buf );
}
-
+
ASSERT( conn->cc_proto == IPPROTO_SCTP );
ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) );
ASSERT( fd_cnx_target_queue(conn) );
-
+
do {
struct fd_msg_pmdl *pmdl=NULL;
CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal );
@@ -884,7 +902,7 @@ static void * rcvthr_notls_sctp(void * arg)
fd_cnx_markerror(conn);
goto out;
}
-
+
if (event == FDEVP_CNX_SHUTDOWN) {
/* Just ignore the notification for now, we will get another error later anyway */
continue;
@@ -895,11 +913,11 @@ static void * rcvthr_notls_sctp(void * arg)
fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
}
CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal );
-
+
} while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV));
-
+
out:
- TRACE_DEBUG(FULL, "Thread terminated");
+ TRACE_DEBUG(FULL, "Thread terminated");
return NULL;
fatal:
@@ -913,15 +931,15 @@ fatal:
int fd_cnx_start_clear(struct cnxctx * conn, int loop)
{
TRACE_ENTRY("%p %i", conn, loop);
-
+
CHECK_PARAMS( conn && fd_cnx_target_queue(conn) && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && (!conn->cc_loop));
-
+
/* Release resources in case of a previous call was already made */
CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
-
+
/* Save the loop request */
conn->cc_loop = loop;
-
+
switch (conn->cc_proto) {
case IPPROTO_TCP:
/* Start the tcp_notls thread */
@@ -938,7 +956,7 @@ int fd_cnx_start_clear(struct cnxctx * conn, int loop)
ASSERT(0);
return ENOTSUP;
}
-
+
return 0;
}
@@ -949,11 +967,11 @@ int fd_cnx_start_clear(struct cnxctx * conn, int loop)
static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
{
ssize_t ret;
-again:
- CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
+again:
+ CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
{
switch (ret) {
- case GNUTLS_E_REHANDSHAKE:
+ case GNUTLS_E_REHANDSHAKE:
if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) {
CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
{
@@ -975,7 +993,7 @@ again:
/* The connection is closed */
TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed...");
break;
-
+
default:
if (gnutls_error_is_fatal (ret) == 0) {
LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret));
@@ -984,11 +1002,11 @@ again:
LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret));
}
} );
-
+
if (ret == 0)
CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), );
-
-end:
+
+end:
if (ret <= 0)
fd_cnx_markerror(conn);
return ret;
@@ -1000,12 +1018,12 @@ static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t s
ssize_t ret;
struct timespec ts, now;
CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 );
-again:
+again:
CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz),
{
pthread_testcancel();
switch (ret) {
- case GNUTLS_E_REHANDSHAKE:
+ case GNUTLS_E_REHANDSHAKE:
if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) {
CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
{
@@ -1034,10 +1052,10 @@ again:
LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret));
}
} );
-end:
+end:
if (ret <= 0)
fd_cnx_markerror(conn);
-
+
return ret;
}
@@ -1045,8 +1063,8 @@ end:
/* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
/* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered.
Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single
- record, as far as I understand.
- For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved.
+ record, as far as I understand.
+ For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved.
As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the
messages. */
int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
@@ -1095,19 +1113,19 @@ int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
}
received += ret;
}
-
+
fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
-
+
/* We have received a complete message, pass it to the daemon */
- CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
- {
+ CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
+ {
free_rcvdata(&rcv_data);
CHECK_FCT_DO(fd_core_shutdown(), );
- return ret;
+ return ret;
} );
-
+
} while (1);
-
+
out:
return (ret == 0) ? 0 : ENOTCONN;
}
@@ -1116,24 +1134,24 @@ out:
static void * rcvthr_tls_single(void * arg)
{
struct cnxctx * conn = arg;
-
+
TRACE_ENTRY("%p", arg);
CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL );
-
+
/* Set the thread name */
{
char buf[48];
snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket);
fd_log_threadname ( buf );
}
-
+
ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) );
ASSERT( fd_cnx_target_queue(conn) );
- /* The next function only returns when there is an error on the socket */
+ /* The next function only returns when there is an error on the socket */
CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
- TRACE_DEBUG(FULL, "Thread terminated");
+ TRACE_DEBUG(FULL, "Thread terminated");
return NULL;
}
@@ -1151,7 +1169,7 @@ int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priori
/* Set the algorithm suite */
if (priority) {
const char * errorpos;
- CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ),
+ CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ),
{ TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'", priority, errorpos); return EINVAL; } );
} else {
CHECK_GNUTLS_DO( gnutls_priority_set( *session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL );
@@ -1164,7 +1182,7 @@ int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priori
if (mode == GNUTLS_SERVER) {
gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE);
}
-
+
return 0;
}
@@ -1179,17 +1197,17 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
unsigned int cert_list_size;
gnutls_x509_crt_t cert;
time_t now;
-
+
TRACE_ENTRY("%p %d", conn, verbose);
CHECK_PARAMS(conn);
-
+
/* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
#ifdef DEBUG
if (verbose) {
const char *tmp;
gnutls_kx_algorithm_t kx;
gnutls_credentials_type_t cred;
-
+
LOG_D("TLS Session information for connection '%s':", conn->cc_id);
/* print the key exchange's algorithm name */
@@ -1229,7 +1247,7 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
gnutls_dh_get_prime_bits (session));
}
break;
-#ifdef ENABLE_SRP
+#ifdef ENABLE_SRP
case GNUTLS_CRD_SRP:
LOG_D("\t - SRP session with username %s",
gnutls_srp_server_get_username (session));
@@ -1263,7 +1281,7 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
LOG_D("\t - MAC: %s", tmp);
}
#endif /* DEBUG */
-
+
/* First, use built-in verification */
CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &gtret), return EINVAL );
if (gtret) {
@@ -1280,33 +1298,33 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
LOG_E(" - The certificate signature uses a weak algorithm.");
return EINVAL;
}
-
+
/* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */
if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
LOG_E("TLS: Remote peer did not present a certificate, other mechanisms are not supported yet. socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
return EINVAL;
}
-
+
GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) );
if (cert_list == NULL)
return EINVAL;
-
+
now = time(NULL);
-
+
#ifdef DEBUG
char serial[40];
char dn[128];
size_t size;
unsigned int algo, bits;
time_t expiration_time, activation_time;
-
+
LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size);
for (i = 0; i < cert_list_size; i++)
{
CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
-
+
LOG_A(" Certificate %d info:", i);
GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) );
@@ -1318,7 +1336,7 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
/* Print the serial number of the certificate. */
size = sizeof (serial);
gnutls_x509_crt_get_serial (cert, serial, &size);
-
+
{
int j;
char buf[1024];
@@ -1354,24 +1372,24 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
for (i = 0; i < cert_list_size; i++)
{
time_t deadline;
-
+
CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
-
+
GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) );
if ((deadline != (time_t)-1) && (deadline < now)) {
LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
LOG_E(" - The certificate %d in the chain is expired", i);
ret = EINVAL;
}
-
+
GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) );
if ((deadline != (time_t)-1) && (deadline > now)) {
LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
LOG_E(" - The certificate %d in the chain is not yet activated", i);
ret = EINVAL;
}
-
+
if ((i == 0) && (conn->cc_tls_para.cn)) {
if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
@@ -1379,7 +1397,7 @@ int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, in
ret = EINVAL;
}
}
-
+
GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) );
}
@@ -1400,10 +1418,10 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
int hostname_verified = 0;
TRACE_ENTRY("%p", session);
-
+
/* get the associated connection */
conn = gnutls_session_get_ptr (session);
-
+
/* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
#ifdef DEBUG
const char *tmp;
@@ -1414,7 +1432,7 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
dhe = ecdh = 0;
LOG_A("TLS Session information for connection '%s':", conn->cc_id);
-
+
/* print the key exchange's algorithm name
*/
GNUTLS_TRACE( kx = gnutls_kx_get (session) );
@@ -1474,7 +1492,7 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
dhe = 1;
else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA)
ecdh = 1;
-
+
/* Now print some info on the remote certificate */
if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) {
gnutls_datum_t cinfo;
@@ -1504,7 +1522,7 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
LOG_D("\t\t%s", cinfo.data);
gnutls_free (cinfo.data);
}
-
+
if (conn->cc_tls_para.cn) {
if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
LOG_E("\tTLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
@@ -1512,7 +1530,7 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
gnutls_x509_crt_deinit (cert);
return GNUTLS_E_CERTIFICATE_ERROR;
}
-
+
}
hostname_verified = 1;
@@ -1535,7 +1553,7 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
LOG_D("\t - Ephemeral DH using prime of %d bits",
gnutls_dh_get_prime_bits (session));
- /* print the protocol's name (ie TLS 1.0)
+ /* print the protocol's name (ie TLS 1.0)
*/
tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
LOG_D("\t - Protocol: %s", tmp);
@@ -1557,8 +1575,8 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
*/
tmp = gnutls_mac_get_name (gnutls_mac_get (session));
LOG_D("\t - MAC: %s", tmp);
-
-#endif /* DEBUG */
+
+#endif /* DEBUG */
/* This verification function uses the trusted CAs in the credentials
* structure. So you must have installed one or more CA certificates.
@@ -1577,12 +1595,12 @@ int fd_tls_verify_credentials_2(gnutls_session_t session)
if (status & GNUTLS_CERT_NOT_ACTIVATED)
LOG_E(" - The certificate is not yet activated.");
- }
+ }
if (status & GNUTLS_CERT_INVALID)
{
return GNUTLS_E_CERTIFICATE_ERROR;
}
-
+
/* Up to here the process is the same for X.509 certificates and
* OpenPGP keys. From now on X.509 certificates are assumed. This can
* be easily extended to work with openpgp keys as well.
@@ -1634,22 +1652,22 @@ static int fd_cnx_uses_dtls(struct cnxctx * conn) {
int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds)
{
int dtls = 0;
-
+
TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds);
CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
/* Save the mode */
conn->cc_tls_para.mode = mode;
conn->cc_tls_para.algo = algo;
-
+
/* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */
CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
-
+
/* Once TLS handshake is done, we don't stop after the first message */
conn->cc_loop = 1;
-
+
dtls = fd_cnx_may_dtls(conn);
-
+
/* Prepare the master session credentials and priority */
CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) );
@@ -1682,32 +1700,32 @@ int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority,
return ENOTSUP;
}
}
-
+
/* additional initialization for gnutls 3.x */
#ifdef GNUTLS_VERSION_300
/* the verify function has already been set in the global initialization in config.c */
-
+
/* fd_tls_verify_credentials_2 uses the connection */
gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn);
-
+
if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) {
/* this might allow virtual hosting on the remote peer */
CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */);
}
-
+
#endif /* GNUTLS_VERSION_300 */
#ifdef GNUTLS_VERSION_310
GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));
#endif /* GNUTLS_VERSION_310 */
-
+
/* Mark the connection as protected from here, so that the gnutls credentials will be freed */
fd_cnx_addstate(conn, CC_STATUS_TLS);
-
+
/* Handshake master session */
{
int ret;
-
+
CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session),
{
if (TRACE_BOOL(INFO)) {
@@ -1719,15 +1737,15 @@ int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority,
#ifndef GNUTLS_VERSION_300
/* Now verify the remote credentials are valid -- only simple tests here */
- CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1),
- {
+ CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1),
+ {
CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), );
fd_cnx_markerror(conn);
return EINVAL;
});
#endif /* GNUTLS_VERSION_300 */
}
-
+
/* Multi-stream TLS: handshake other streams as well */
if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
#ifndef DISABLE_SCTP
@@ -1750,7 +1768,7 @@ int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority,
return ENOTSUP;
}
}
-
+
return 0;
}
@@ -1759,10 +1777,10 @@ int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsig
{
TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size);
CHECK_PARAMS( conn && fd_cnx_teststate(conn, CC_STATUS_TLS) && cert_list && cert_list_size );
-
+
/* This function only works for X.509 certificates. */
CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 );
-
+
GNUTLS_TRACE( *cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size) );
if (*cert_list == NULL) {
TRACE_DEBUG(INFO, "No certificate was provided by remote peer / an error occurred.");
@@ -1770,7 +1788,7 @@ int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsig
}
TRACE_DEBUG( FULL, "Saved certificate chain (%d certificates) in peer structure.", *cert_list_size);
-
+
return 0;
}
@@ -1781,7 +1799,7 @@ int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned cha
int ev;
size_t ev_sz;
void * ev_data;
-
+
TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len);
CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len);
CHECK_PARAMS(conn->cc_rcvthr != (pthread_t)NULL);
@@ -1794,27 +1812,27 @@ get_next:
} else {
CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) );
}
-
+
switch (ev) {
case FDEVP_CNX_MSG_RECV:
/* We got one */
*len = ev_sz;
*buf = ev_data;
return 0;
-
+
case FDEVP_PSM_TIMEOUT:
TRACE_DEBUG(FULL, "Timeout event received");
return ETIMEDOUT;
-
+
case FDEVP_CNX_EP_CHANGE:
/* We ignore this event */
goto get_next;
-
+
case FDEVP_CNX_ERROR:
TRACE_DEBUG(FULL, "Received ERROR event on the connection");
return ENOTCONN;
}
-
+
TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev));
return EINVAL;
}
@@ -1835,12 +1853,12 @@ int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo)
int ret;
TRACE_ENTRY( "%p %p", conn, alt_fifo );
CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming );
-
+
/* The magic function does it all */
CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
CHECK_FCT_DO( ret = fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ), );
CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
-
+
return ret;
}
@@ -1861,7 +1879,7 @@ static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len)
}
if (ret <= 0)
return ENOTCONN;
-
+
sent += ret;
} while ( sent < len );
return 0;
@@ -1871,16 +1889,16 @@ static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len)
int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
{
TRACE_ENTRY("%p %p %zd", conn, buf, len);
-
+
CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len);
TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, fd_cnx_teststate(conn, CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id);
-
+
switch (conn->cc_proto) {
case IPPROTO_TCP:
CHECK_FCT( send_simple(conn, buf, len) );
break;
-
+
#ifndef DISABLE_SCTP
case IPPROTO_SCTP: {
int dtls = fd_cnx_uses_dtls(conn);
@@ -1892,14 +1910,14 @@ int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
limit = conn->cc_sctp_para.pairs;
else
limit = conn->cc_sctp_para.str_out;
-
+
if (limit > 1) {
conn->cc_sctp_para.next += 1;
conn->cc_sctp_para.next %= limit;
stream = conn->cc_sctp_para.next;
}
}
-
+
if (stream == 0) {
/* We can use default function, it sends over stream #0 */
CHECK_FCT( send_simple(conn, buf, len) );
@@ -1908,7 +1926,7 @@ int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
struct iovec iov;
iov.iov_base = buf;
iov.iov_len = len;
-
+
CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } );
} else {
/* push the data to the appropriate session */
@@ -1932,13 +1950,13 @@ int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
}
break;
#endif /* DISABLE_SCTP */
-
+
default:
TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
ASSERT(0);
return ENOTSUP; /* or EINVAL... */
}
-
+
return 0;
}
@@ -1951,11 +1969,11 @@ int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
void fd_cnx_destroy(struct cnxctx * conn)
{
TRACE_ENTRY("%p", conn);
-
+
CHECK_PARAMS_DO(conn, return);
-
+
fd_cnx_addstate(conn, CC_STATUS_CLOSING);
-
+
/* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */
if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
#ifndef DISABLE_SCTP
@@ -1985,7 +2003,7 @@ void fd_cnx_destroy(struct cnxctx * conn)
GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) );
conn->cc_tls_para.session = NULL;
}
-
+
/* Destroy the wrapper (also stops the demux thread) */
fd_sctp3436_destroy(conn);
@@ -2007,7 +2025,7 @@ void fd_cnx_destroy(struct cnxctx * conn)
/* Cancel the receiver thread in case it did not already terminate */
CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
}
-
+
/* Free the resources of the TLS session */
if (conn->cc_tls_para.session) {
GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) );
@@ -2017,25 +2035,25 @@ void fd_cnx_destroy(struct cnxctx * conn)
}
#endif /* DISABLE_SCTP */
}
-
+
/* Terminate the thread in case it is not done yet -- is there any such case left ?*/
CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
-
+
/* Shut the connection down */
if (conn->cc_socket > 0) {
shutdown(conn->cc_socket, SHUT_RDWR);
close(conn->cc_socket);
conn->cc_socket = -1;
}
-
+
/* Empty and destroy FIFO list */
if (conn->cc_incoming) {
fd_event_destroy( &conn->cc_incoming, free );
}
-
+
/* Free the object */
free(conn);
-
+
/* Done! */
return;
}