Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
oai
freediameter
Commits
dd9351e9
Commit
dd9351e9
authored
Oct 07, 2009
by
Sebastien Decugis
Browse files
Backup before typhoon... Progress on server side
parent
d95897c7
Changes
14
Hide whitespace changes
Inline
Side-by-side
INSTALL
View file @
dd9351e9
...
...
@@ -8,7 +8,7 @@ cmake ../
make
You can enable the unary tests by doing:
cmake -D
NO
_TESTS:BOOL=OFF ../
cmake -D
SKIP
_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
doc/freediameter.conf.sample
View file @
dd9351e9
# 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";
freeDiameter/CMakeLists.txt
View file @
dd9351e9
...
...
@@ -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
...
...
freeDiameter/cnxctx.c
0 → 100644
View file @
dd9351e9
/*********************************************************************************************************
* 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
;
}
freeDiameter/config.c
View file @
dd9351e9
...
...
@@ -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."
);
}
...
...
freeDiameter/fD.h
View file @
dd9351e9
...
...
@@ -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 */
freeDiameter/fdd.y
View file @
dd9351e9
...
...
@@ -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.");
}
;
freeDiameter/main.c
View file @
dd9351e9
...
...
@@ -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
);
...
...
freeDiameter/p_psm.c
View file @
dd9351e9
...
...
@@ -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"
...
...
freeDiameter/peers.c
View file @
dd9351e9
...
...
@@ -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
?
"InbandIPsec
OK
."
:
""
,
peer
->
p_hdr
.
info
.
pi_flags
.
inband
&
PI_INB_TLS
?
"InbandTLS
OK
."
:
""
,
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
(
"
\t
Lifetime : %d sec
\n
"
,
peer
->
p_hdr
.
info
.
pi_lft
);
...
...
freeDiameter/sctp.c
0 → 100644
View file @
dd9351e9
/*********************************************************************************************************
* 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
;
}
freeDiameter/server.c
0 → 100644
View file @
dd9351e9
/*********************************************************************************************************
* 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
"
,