Commit dd9351e9 authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Backup before typhoon... Progress on server side

parent d95897c7
......@@ -8,7 +8,7 @@ cmake ../
make
You can enable the unary tests by doing:
cmake -DNO_TESTS:BOOL=OFF ../
cmake -DSKIP_TESTS:BOOL=OFF ../
make
make tests
......@@ -37,3 +37,5 @@ BUILD_SAMPLE:BOOL=ON
You can change the default configuration file pathname:
DEFAULT_CONF_FILE:STRING=/path/to/some/freeDiameter.conf
Build binary with symbols, for debug:
CMAKE_BUILD_TYPE:STRING=Debug
# This is a sample configuration file for freeDiameter daemon.
# Only the "TLS_Cred" directive is really mandatory in this file.
##############################################################
## Peer identity and realm
......@@ -30,11 +32,11 @@
# Default: use RFC3588bis method with separate port for TLS.
#TLS_old_method;
# Disable use of TCP protocol (only SCTP)
# Disable use of TCP protocol (only listen and connect in SCTP)
# Default : TCP enabled
#No_TCP;
# Disable use of SCTP protocol (only TCP)
# Disable use of SCTP protocol (only listen and connect in TCP)
# Default : SCTP enabled
#No_SCTP;
# This option has no effect if freeDiameter is compiled with DISABLE_SCTP option,
......@@ -92,6 +94,7 @@
# The information about revoked certificates.
# The file contains a list of trusted CRLs in PEM format. They should have been verified before.
# (This parameter is passed to gnutls_certificate_set_x509_crl_file function)
# Note: currently, openssl CRL seems not supported...
# Default : GNUTLS default behavior
#TLS_CRL = "<file.PEM>";
......@@ -210,3 +213,7 @@ LoadExtension = "extensions/dict_nasreq.fdx";
LoadExtension = "extensions/dict_eap.fdx";
ConnectPeer = "jules.nautilus6.org" ;
ConnectPeer = "aaa.nautilus6.org" { No_TLS; No_IP; No_TCP; SCTP_streams = 60; } ;
TLS_Cred = "/etc/openssl-ca/clients/certs/fdtest.cert" , "/etc/openssl-ca/clients/privkeys/fdtest.key.pem";
TLS_CA = "/etc/openssl-ca/public-www/cacert.pem";
# TLS_CRL = "/etc/openssl-ca/public-www/crl.pem";
......@@ -10,6 +10,7 @@ SET_SOURCE_FILES_PROPERTIES(lex.fdd.c fdd.tab.c PROPERTIES COMPILE_FLAGS "-I ${C
SET(FD_COMMON_SRC
fD.h
config.c
cnxctx.c
dispatch.c
extensions.c
dict_base_proto.c
......@@ -18,8 +19,13 @@ SET(FD_COMMON_SRC
peers.c
p_expiry.c
p_psm.c
server.c
)
IF(NOT DISABLE_SCTP)
SET(FD_COMMON_SRC ${FD_COMMON_SRC} sctp.c)
ENDIF(NOT DISABLE_SCTP)
SET(FD_COMMON_GEN_SRC
lex.fdd.c
fdd.tab.c
......
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
#include "fD.h"
/* Initialize a connection context */
struct cnxctx * fd_cnx_init(int sock, int proto)
{
struct cnxctx * conn = NULL;
TRACE_ENTRY("%d %d", sock, proto);
CHECK_PARAMS_DO( (proto == IPPROTO_TCP) || (proto == IPPROTO_SCTP), return NULL);
CHECK_MALLOC_DO( conn = malloc(sizeof(struct cnxctx)), return NULL );
memset(conn, 0, sizeof(struct cnxctx));
conn->cc_socket = sock;
conn->cc_proto = proto;
fd_list_init(&conn->cc_ep_remote, conn);
fd_list_init(&conn->cc_ep_local, conn);
if (proto == IPPROTO_SCTP) {
#ifndef DISABLE_SCTP
CHECK_FCT_DO( fd_sctp_get_str_info( sock, &conn->cc_sctp_para.str_in, &conn->cc_sctp_para.str_out ),
{ free(conn); return NULL; } );
conn->cc_sctp_para.pairs = (conn->cc_sctp_para.str_out < conn->cc_sctp_para.str_in) ? conn->cc_sctp_para.str_out : conn->cc_sctp_para.str_in;
#else /* DISABLE_SCTP */
ASSERT(0);
#endif /* DISABLE_SCTP */
}
return conn;
}
/* TLS handshake the connection */
int fd_cnx_handshake(struct cnxctx * conn, int mode)
{
TRACE_ENTRY( "%p %d", conn, mode);
CHECK_PARAMS( conn && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) );
/* Save the mode */
conn->cc_tls_para.mode = mode;
/* Create the master session context */
CHECK_GNUTLS_DO( gnutls_init (&conn->cc_tls_para.session, mode), return ENOMEM );
/* Set the algorithm suite */
CHECK_GNUTLS_DO( gnutls_priority_set( conn->cc_tls_para.session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL );
/* Set the credentials of this side of the connection */
CHECK_GNUTLS_DO( gnutls_credentials_set (conn->cc_tls_para.session, GNUTLS_CRD_CERTIFICATE, fd_g_config->cnf_sec_data.credentials), return EINVAL );
/* Request the remote credentials as well */
if (mode == GNUTLS_SERVER) {
gnutls_certificate_server_set_request (conn->cc_tls_para.session, GNUTLS_CERT_REQUIRE);
}
/* Set the socket info in the session */
gnutls_transport_set_ptr (conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn->cc_socket);
/* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */
if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_sctp_para.pairs > 0)) {
#ifndef DISABLE_SCTP
TODO("Initialize the SCTP TLS wrapper");
TODO("Set the lowat, push and pull functions");
#else /* DISABLE_SCTP */
ASSERT(0);
#endif /* DISABLE_SCTP */
}
/* Handshake master session */
{
int ret;
CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session),
{
if (TRACE_BOOL(INFO)) {
fd_log_debug("TLS Handshake failed on socket %d : %s\n", conn->cc_socket, gnutls_strerror(ret));
}
return EINVAL;
} );
/* Now verify the remote credentials are valid -- only simple test here */
CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (conn->cc_tls_para.session, &ret), return EINVAL );
if (ret) {
if (TRACE_BOOL(INFO)) {
fd_log_debug("TLS: Remote certificate invalid on socket %d :\n", conn->cc_socket);
if (ret & GNUTLS_CERT_INVALID)
fd_log_debug(" - The certificate is not trusted (unknown CA?)\n");
if (ret & GNUTLS_CERT_REVOKED)
fd_log_debug(" - The certificate has been revoked.\n");
if (ret & GNUTLS_CERT_SIGNER_NOT_FOUND)
fd_log_debug(" - The certificate hasn't got a known issuer.\n");
if (ret & GNUTLS_CERT_SIGNER_NOT_CA)
fd_log_debug(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.\n");
if (ret & GNUTLS_CERT_INSECURE_ALGORITHM)
fd_log_debug(" - The certificate signature uses a weak algorithm.\n");
}
return EINVAL;
}
}
/* Other sessions in case of multi-stream SCTP are resumed from the master */
if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_sctp_para.pairs > 0)) {
#ifndef DISABLE_SCTP
TODO("Init and resume all additional sessions from the master one.");
#endif /* DISABLE_SCTP */
}
return 0;
}
......@@ -238,10 +238,12 @@ int fd_conf_parse()
{ TRACE_DEBUG(INFO, "Error in priority string at position : %s", err_pos); return EINVAL; } );
}
if (! fd_g_config->cnf_sec_data.dh_bits) {
TRACE_DEBUG(FULL, "Generating DH parameters...");
CHECK_GNUTLS_DO( gnutls_dh_params_generate2(
fd_g_config->cnf_sec_data.dh_cache,
GNUTLS_DEFAULT_DHBITS),
{ TRACE_DEBUG(INFO, "Error in DH bits value : %d", GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
TRACE_DEBUG(FULL, "DH parameters generated.");
}
......
......@@ -172,6 +172,40 @@ struct sentreq {
struct msg *req; /* A request that was sent and not yet answered. */
};
/* The connection context structure */
struct cnxctx {
int cc_socket; /* The socket object of the connection -- <=0 if no socket is created */
struct fifo **cc_events; /* Location of the events list to send connection events */
int cc_proto; /* IPPROTO_TCP or IPPROTO_SCTP */
int cc_tls; /* Is TLS already started ? */
uint16_t cc_port; /* Remote port of the connection, when we are client */
struct fd_list cc_ep_remote; /* The remote address(es) of the connection */
struct fd_list cc_ep_local; /* The local address(es) of the connection */
/* If cc_proto == SCTP */
struct {
int str_out;/* Out streams */
int str_in; /* In streams */
int pairs; /* max number of pairs ( = min(in, out)) */
int next; /* # of stream the next message will be sent to */
} cc_sctp_para;
/* If cc_tls == true */
struct {
int mode; /* GNUTLS_CLIENT / GNUTLS_SERVER */
gnutls_session_t session; /* Session object (stream #0 in case of SCTP) */
} cc_tls_para;
/* If both conditions */
struct {
gnutls_session_t *res_sessions; /* Sessions of other pairs of streams, resumed from the first */
/* Buffers, threads, ... */
} cc_sctp_tls_para;
};
/* Functions */
int fd_peer_fini();
void fd_peer_dump_list(int details);
......@@ -191,4 +225,22 @@ int fd_psm_begin(struct fd_peer * peer );
int fd_psm_terminate(struct fd_peer * peer );
void fd_psm_abord(struct fd_peer * peer );
/* Server sockets */
void fd_servers_dump();
int fd_servers_start();
void fd_servers_stop();
/* Connection contexts */
struct cnxctx * fd_cnx_init(int sock, int proto);
int fd_cnx_handshake(struct cnxctx * conn, int mode);
/* SCTP */
#ifndef DISABLE_SCTP
int fd_sctp_create_bind_server( int * socket, uint16_t port );
int fd_sctp_get_str_info( int socket, int *in, int *out );
#endif /* DISABLE_SCTP */
#endif /* _FD_H */
......@@ -510,10 +510,12 @@ tls_prio: TLS_PRIO '=' QSTRING ';'
tls_dh: TLS_DH_BITS '=' INTEGER ';'
{
conf->cnf_sec_data.dh_bits = $3;
TRACE_DEBUG(FULL, "Generating DH parameters...");
CHECK_GNUTLS_DO( gnutls_dh_params_generate2(
conf->cnf_sec_data.dh_cache,
conf->cnf_sec_data.dh_bits),
{ yyerror (&yylloc, conf, "Error setting DH Bits parameters.");
YYERROR; } );
TRACE_DEBUG(FULL, "DH parameters generated.");
}
;
......@@ -122,6 +122,10 @@ int main(int argc, char * argv[])
fd_ext_dump();
break;
case FDEV_DUMP_SERV:
fd_servers_dump();
break;
case FDEV_DUMP_QUEUES:
fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk);
fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk);
......@@ -170,6 +174,7 @@ const char * fd_ev_str(int event)
case_str(FDEV_TERMINATE);
case_str(FDEV_DUMP_DICT);
case_str(FDEV_DUMP_EXT);
case_str(FDEV_DUMP_SERV);
case_str(FDEV_DUMP_QUEUES);
case_str(FDEV_DUMP_CONFIG);
case_str(FDEV_DUMP_PEERS);
......
......@@ -43,6 +43,7 @@ const char *peer_state_str[] = {
, "STATE_WAITCNXACK"
, "STATE_WAITCNXACK_ELEC"
, "STATE_WAITCEA"
, "STATE_OPEN_HANDSHAKE"
, "STATE_SUSPECT"
, "STATE_REOPEN"
, "STATE_ZOMBIE"
......
......@@ -343,8 +343,8 @@ void fd_peer_dump(struct fd_peer * peer, int details)
peer->p_hdr.info.pi_flags.sec == PI_SEC_DEFAULT ? "" :
(peer->p_hdr.info.pi_flags.sec == PI_SEC_NONE ? "IPSec." : "InbandTLS."),
peer->p_hdr.info.pi_flags.exp ? "Expire." : "",
peer->p_hdr.info.pi_flags.inband & PI_INB_NONE ? "InbandIPsecOK." : "",
peer->p_hdr.info.pi_flags.inband & PI_INB_TLS ? "InbandTLSOK." : "",
peer->p_hdr.info.pi_flags.inband_none ? "InbandIPsec." : "",
peer->p_hdr.info.pi_flags.inband_tls ? "InbandTLS." : "",
peer->p_hdr.info.pi_flags.relay ? "Relay (0xffffff)" : "No relay"
);
fd_log_debug("\tLifetime : %d sec\n", peer->p_hdr.info.pi_lft);
......
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
#include "fD.h"
int fd_sctp_create_bind_server( int * socket, uint16_t port )
{
TODO("Create sctp server, using fd_g_config: cnf_endpoints, no_ip4, no_ip6, cnf_sctp_str");
return ENOTSUP;
}
int fd_sctp_get_str_info( int socket, int *in, int *out )
{
TODO("Retrieve streams info from the socket");
return ENOTSUP;
}
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
#include "fD.h"
/* This file contains the server (listening) part of the daemon */
struct fd_list FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS); /* The list of all server sockets */
/* We don't need to protect this list, it is only accessed from the main thread. */
/* Server (listening socket) information */
struct server {
struct fd_list chain; /* link in the FD_SERVERS list */
int socket; /* server socket, or <= 0 */
int proto; /* IPPROTO_TCP or IPPROTO_SCTP */
int secur; /* TLS is started immediatly after connection ? */
pthread_t serv_thr; /* The thread listening for new connections */
int serv_status; /* 0 : not created; 1 : running; 2 : terminated */
pthread_mutex_t clients_mtx; /* Mutex to protect the list of clients connected to the thread */
struct fd_list clients; /* The list of clients connecting to this server, which information is not yet known */
char * serv_name; /* A string to identify this server */
};
/* Client (connected remote endpoint, not received CER yet) information */
struct client {
struct fd_list chain; /* link in the server's list of clients */
struct cnxctx *conn; /* Parameters of the connection; sends its events to the ev fifo bellow */
struct timespec ts; /* Delay for receiving CER: INCNX_TIMEOUT */
struct fifo *ev; /* Events of the connection -- allowed: TIMEOUT, ERROR (cnx, tls), MSG_RCV (CER, other=>error) */
pthread_t cli_thr; /* connection state machine (simplified PSM) */
};
/* Parameter for the thread handling the new connected client, to avoid bloking the server thread */
struct cli_fast {
struct server * serv;
int sock;
sSS ss;
socklen_t sslen;
};
/* This thread is called when a new client had just connected */
static void * handle_client_fast(void * arg)
{
struct cli_fast * cf = arg;
struct client * c = NULL;
/* Name the current thread */
ASSERT(arg);
{
char addr[128];
int offset = snprintf(addr, sizeof(addr), "Srv %d/Cli %d : ", cf->serv->socket, cf->sock);
int rc = getnameinfo((sSA *)&cf->ss, sizeof(sSS), addr + offset, sizeof(addr) - offset, NULL, 0, 0);
if (rc)
memcpy(addr + offset, gai_strerror(rc), sizeof(addr) - offset);
if (TRACE_BOOL(INFO)) {
fd_log_debug( "New connection %s, sock %d, from '%s'\n", cf->serv->serv_name, cf->sock, addr + offset);
}
fd_log_threadname ( addr );
}
/* Create a client structure */
CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto early_error );
memset(c, 0, sizeof(struct client));
fd_list_init(&c->chain, c);
c->cli_thr = pthread_self();
/* Create the connection context */
CHECK_MALLOC_DO( c->conn = fd_cnx_init(cf->sock, cf->serv->proto), goto early_error );
/* In case we are a secure server, handshake now */
if (cf->serv->secur) {
TODO("Continue");
}
/* Save the client in the list */
CHECK_POSIX_DO( pthread_mutex_lock( &cf->serv->clients_mtx ), goto early_error );
fd_list_insert_before(&cf->serv->clients, &c->chain);
CHECK_POSIX_DO( pthread_mutex_unlock( &cf->serv->clients_mtx ), goto error );
early_error:
TRACE_DEBUG(INFO, "Thread is detaching to die");
pthread_detach(pthread_self());
shutdown(cf->sock, SHUT_RDWR);
free(cf);
free(c);
error:
TRACE_DEBUG(INFO, "Thread is terminating");
CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
return NULL;
}
/* The thread for the server */
static void * serv_th(void * arg)
{
struct server *sv = (struct server *)arg;
struct cli_fast cf;
CHECK_PARAMS_DO(sv, goto error);
fd_log_threadname ( sv->serv_name );
sv->serv_status = 1;
memset(&cf, 0, sizeof(struct cli_fast));
cf.serv = sv;
/* Accept incoming connections */
CHECK_SYS_DO( listen(sv->socket, 5), goto error );
do {
struct cli_fast * ncf;
pthread_t thr;
/* Re-init socket size */
cf.sslen = sizeof(sSS);
/* Wait for a new client */
CHECK_SYS_DO( cf.sock = accept(sv->socket, (sSA *)&cf.ss, &cf.sslen), goto error );
TRACE_DEBUG(FULL, "New connection accepted");
/* Create the copy for the client thread */
CHECK_MALLOC_DO( ncf = malloc(sizeof(struct cli_fast)), goto error );
memcpy(ncf, &cf, sizeof(struct cli_fast));
/* Create the thread to handle the new incoming connection */
CHECK_POSIX_DO( pthread_create( &thr /* we don't use it, but NULL is not standard */, NULL, handle_client_fast, ncf), goto error );
} while (1);
error:
if (sv)
sv->serv_status = 2;
/* Send error signal to the daemon */
TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating...");
CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), );
return NULL;
}
/* Create a new server structure */
static struct server * new_serv( int proto, int secur, int socket )
{
char buf[32];
char * sn = NULL;
struct server * new;
/* Create the server debug name */
buf[sizeof(buf) - 1] = '\0';
snprintf(buf, sizeof(buf) - 1, "Serv %d (%s%s)", socket, IPPROTO_NAME( proto ), secur ? "s" : "");
CHECK_MALLOC_DO( sn = strdup(buf), return NULL );
/* New server structure */
CHECK_MALLOC_DO( new = malloc(sizeof(struct server)), return NULL );
memset(new, 0, sizeof(struct server));
fd_list_init(&new->chain, new);
new->socket = socket;
new->proto = proto;
new->secur = secur;
CHECK_POSIX_DO( pthread_mutex_init(&new->clients_mtx, NULL), return NULL );
fd_list_init(&new->clients, new);
new->serv_name = sn;
return new;
}
/* Dump all servers information */
void fd_servers_dump()
{
struct fd_list * li;
fd_log_debug("Dumping servers list :\n");
for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
struct server * sv = (struct server *)li;
fd_log_debug(" Serv '%s': %s(%d), %s, %s, %s\n",