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
92fdb242
Commit
92fdb242
authored
Oct 26, 2009
by
Sebastien Decugis
Browse files
Completed connection context files
parent
146fe937
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
extensions/dbg_monitor/monitor.c
View file @
92fdb242
...
...
@@ -48,9 +48,9 @@ EXTENSION_ENTRY("monitor", monitor_main);
/* Function called on receipt of SIGUSR1 */
static
void
got_sig
(
int
signal
)
{
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_DICT
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_CONFIG
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_EXT
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_DICT
,
0
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_CONFIG
,
0
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_EXT
,
0
,
NULL
),
/* continue */
);
}
/* Thread to display periodical debug information */
static
pthread_t
thr
;
...
...
@@ -76,8 +76,9 @@ static void * mn_thr(void * arg)
sleep
(
3600
);
/* 1 hour */
#endif
/* DEBUG */
TRACE_DEBUG
(
NONE
,
"Monitor information"
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_QUEUES
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_PEERS
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_QUEUES
,
0
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_SERV
,
0
,
NULL
),
/* continue */
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_DUMP_PEERS
,
0
,
NULL
),
/* continue */
);
pthread_testcancel
();
}
...
...
freeDiameter/CMakeLists.txt
View file @
92fdb242
...
...
@@ -9,6 +9,7 @@ SET_SOURCE_FILES_PROPERTIES(lex.fdd.c fdd.tab.c PROPERTIES COMPILE_FLAGS "-I ${C
# List of source files
SET
(
FD_COMMON_SRC
fD.h
cnxctx.h
config.c
cnxctx.c
dispatch.c
...
...
@@ -25,7 +26,7 @@ SET(FD_COMMON_SRC
)
IF
(
NOT DISABLE_SCTP
)
SET
(
FD_COMMON_SRC
${
FD_COMMON_SRC
}
sctp.c
)
SET
(
FD_COMMON_SRC
${
FD_COMMON_SRC
}
sctp.c
sctps.c
)
ENDIF
(
NOT DISABLE_SCTP
)
SET
(
FD_COMMON_GEN_SRC
...
...
freeDiameter/cnxctx.c
View file @
92fdb242
This diff is collapsed.
Click to expand it.
freeDiameter/cnxctx.h
0 → 100644
View file @
92fdb242
/*********************************************************************************************************
* 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. *
*********************************************************************************************************/
/* This file contains the definitions for internal use in the connection context files */
#ifndef _CNXCTX_H
#define _CNXCTX_H
/* The connection context structure */
struct
cnxctx
{
char
cc_id
[
60
];
/* The name of this connection */
char
cc_remid
[
60
];
/* Id of remote peer */
int
cc_socket
;
/* The socket object of the connection -- <=0 if no socket is created */
int
cc_proto
;
/* IPPROTO_TCP or IPPROTO_SCTP */
int
cc_tls
;
/* Is TLS already started ? */
pthread_t
cc_rcvthr
;
/* thread for receiving messages on the connection */
int
cc_loop
;
/* tell the thread if it loops or stops after the first message is received */
struct
fifo
*
cc_incoming
;
/* FIFO queue of events received on the connection, FDEVP_CNX_* */
struct
fifo
*
cc_alt
;
/* alternate fifo to send FDEVP_CNX_* events to. */
#define Target_Queue(cnx) ((cnx)->cc_alt ?: (cnx)->cc_incoming)
/* 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 cc_proto == SCTP */
struct
{
uint16_t
str_out
;
/* Out streams */
uint16_t
str_in
;
/* In streams */
uint16_t
pairs
;
/* max number of pairs ( = min(in, out)) */
uint16_t
next
;
/* # of stream the next message will be sent to */
}
cc_sctp_para
;
/* If both conditions */
struct
{
struct
sctps_ctx
*
array
;
/* an array of cc_sctp_para.pairs elements -- the #0 is special (session is outside)*/
struct
sr_store
*
sess_store
;
/* Session data of the master session, to resume the children sessions */
}
cc_sctps_data
;
};
/* TLS */
int
fd_tls_rcvthr_core
(
struct
cnxctx
*
conn
,
gnutls_session_t
session
);
int
fd_tls_prepare
(
gnutls_session_t
*
session
,
int
mode
,
char
*
priority
);
/* TCP */
int
fd_tcp_create_bind_server
(
int
*
sock
,
sSA
*
sa
,
socklen_t
salen
);
int
fd_tcp_listen
(
int
sock
);
int
fd_tcp_client
(
int
*
sock
,
sSA
*
sa
,
socklen_t
salen
);
int
fd_tcp_get_local_ep
(
int
sock
,
sSS
*
ss
,
socklen_t
*
sl
);
int
fd_tcp_get_remote_ep
(
int
sock
,
sSS
*
ss
,
socklen_t
*
sl
);
#ifndef DISABLE_SCTP
/* SCTP */
int
fd_sctp_create_bind_server
(
int
*
sock
,
struct
fd_list
*
list
,
uint16_t
port
);
int
fd_sctp_listen
(
int
sock
);
int
fd_sctp_client
(
int
*
sock
,
int
no_ip6
,
uint16_t
port
,
struct
fd_list
*
list
);
int
fd_sctp_get_local_ep
(
int
sock
,
struct
fd_list
*
list
);
int
fd_sctp_get_remote_ep
(
int
sock
,
struct
fd_list
*
list
);
int
fd_sctp_get_str_info
(
int
sock
,
uint16_t
*
in
,
uint16_t
*
out
,
sSS
*
primary
);
int
fd_sctp_sendstr
(
int
sock
,
uint16_t
strid
,
uint8_t
*
buf
,
size_t
len
);
int
fd_sctp_recvmeta
(
int
sock
,
uint16_t
*
strid
,
uint8_t
**
buf
,
size_t
*
len
,
int
*
event
);
/* TLS over SCTP (multi-stream) */
struct
sctps_ctx
{
struct
cnxctx
*
parent
;
/* for info such as socket, conn name, event list */
uint16_t
strid
;
/* Stream # of this session */
struct
fifo
*
raw_recv
;
/* Raw data received on this stream, for demux */
struct
{
uint8_t
*
buf
;
size_t
bufsz
;
size_t
offset
;
}
partial
;
/* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */
pthread_t
thr
;
/* Thread to decrypt raw data in this pair of streams */
gnutls_session_t
session
;
/* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */
};
int
fd_sctps_init
(
struct
cnxctx
*
conn
);
int
fd_sctps_handshake_others
(
struct
cnxctx
*
conn
,
char
*
priority
);
int
fd_sctps_startthreads
(
struct
cnxctx
*
conn
);
void
fd_sctps_stopthreads
(
struct
cnxctx
*
conn
);
void
fd_sctps_destroy
(
struct
cnxctx
*
conn
);
#endif
/* DISABLE_SCTP */
#endif
/* _CNXCTX_H */
freeDiameter/fD.h
View file @
92fdb242
...
...
@@ -151,13 +151,19 @@ struct fd_peer { /* The "real" definition of the peer structure */
/* Events codespace for struct fd_peer->p_events */
enum
{
/* Dump all info about this peer in the debug log */
FDEVP_DUMP_ALL
=
20
00
FDEVP_DUMP_ALL
=
15
00
/* request to terminate this peer : disconnect, requeue all messages */
,
FDEVP_TERMINATE
/* A connection object has received a message
-- stored in event->data
*/
/* A connection object has received a message
.
*/
,
FDEVP_CNX_MSG_RECV
/* A connection object has encountered an error (disconnected). */
,
FDEVP_CNX_ERROR
/* Endpoints of a connection have been changed (multihomed SCTP). */
,
FDEVP_CNX_EP_CHANGE
/* A message was received in the peer */
,
FDEVP_MSG_INCOMING
...
...
@@ -209,7 +215,7 @@ struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv);
struct
cnxctx
*
fd_cnx_cli_connect_tcp
(
sSA
*
sa
,
socklen_t
addrlen
);
struct
cnxctx
*
fd_cnx_cli_connect_sctp
(
int
no_ip6
,
uint16_t
port
,
struct
fd_list
*
list
);
char
*
fd_cnx_getid
(
struct
cnxctx
*
conn
);
int
fd_cnx_start_clear
(
struct
cnxctx
*
conn
);
int
fd_cnx_start_clear
(
struct
cnxctx
*
conn
,
int
loop
);
int
fd_cnx_handshake
(
struct
cnxctx
*
conn
,
int
mode
,
char
*
priority
);
int
fd_cnx_getcred
(
struct
cnxctx
*
conn
,
const
gnutls_datum_t
**
cert_list
,
unsigned
int
*
cert_list_size
);
int
fd_cnx_getendpoints
(
struct
cnxctx
*
conn
,
struct
fd_list
*
local
,
struct
fd_list
*
remote
);
...
...
@@ -219,24 +225,5 @@ int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo); /* sen
int
fd_cnx_send
(
struct
cnxctx
*
conn
,
unsigned
char
*
buf
,
size_t
len
);
void
fd_cnx_destroy
(
struct
cnxctx
*
conn
);
/* TCP */
int
fd_tcp_create_bind_server
(
int
*
sock
,
sSA
*
sa
,
socklen_t
salen
);
int
fd_tcp_listen
(
int
sock
);
int
fd_tcp_client
(
int
*
sock
,
sSA
*
sa
,
socklen_t
salen
);
int
fd_tcp_get_local_ep
(
int
sock
,
sSS
*
ss
,
socklen_t
*
sl
);
int
fd_tcp_get_remote_ep
(
int
sock
,
sSS
*
ss
,
socklen_t
*
sl
);
/* SCTP */
#ifndef DISABLE_SCTP
int
fd_sctp_create_bind_server
(
int
*
sock
,
struct
fd_list
*
list
,
uint16_t
port
);
int
fd_sctp_listen
(
int
sock
);
int
fd_sctp_client
(
int
*
sock
,
int
no_ip6
,
uint16_t
port
,
struct
fd_list
*
list
);
int
fd_sctp_get_local_ep
(
int
sock
,
struct
fd_list
*
list
);
int
fd_sctp_get_remote_ep
(
int
sock
,
struct
fd_list
*
list
);
int
fd_sctp_get_str_info
(
int
sock
,
int
*
in
,
int
*
out
,
sSS
*
primary
);
#endif
/* DISABLE_SCTP */
#endif
/* _FD_H */
freeDiameter/main.c
View file @
92fdb242
...
...
@@ -116,8 +116,8 @@ int main(int argc, char * argv[])
/* Now, just wait for events */
TRACE_DEBUG
(
INFO
,
FD_PROJECT_BINARY
" daemon initialized."
);
while
(
1
)
{
int
code
;
CHECK_FCT_DO
(
fd_event_get
(
fd_g_config
->
cnf_main_ev
,
&
code
,
NULL
),
break
);
int
code
;
size_t
sz
;
void
*
data
;
CHECK_FCT_DO
(
fd_event_get
(
fd_g_config
->
cnf_main_ev
,
&
code
,
&
sz
,
&
data
),
break
);
switch
(
code
)
{
case
FDEV_DUMP_DICT
:
fd_dict_dump
(
fd_g_config
->
cnf_dict
);
...
...
@@ -338,7 +338,7 @@ static void * sig_hdl(void * arg)
CHECK_SYS_DO
(
sigwait
(
&
sig_main
,
&
sig
),
TRACE_DEBUG
(
INFO
,
"Error in sigwait function"
)
);
TRACE_DEBUG
(
INFO
,
"Received signal %s (%d), exiting"
,
SIGNALSTR
(
sig
),
sig
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
NULL
),
exit
(
2
)
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
0
,
NULL
),
exit
(
2
)
);
return
NULL
;
}
freeDiameter/p_expiry.c
View file @
92fdb242
...
...
@@ -86,7 +86,7 @@ static void * gc_th_fct(void * arg)
error:
TRACE_DEBUG
(
INFO
,
"An error occurred in peers module! GC thread is terminating..."
);
ASSERT
(
0
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
NULL
),
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
0
,
NULL
),
);
return
NULL
;
}
...
...
@@ -131,7 +131,7 @@ static void * exp_th_fct(void * arg)
/* Now, the first peer in the list is expired; signal it */
fd_list_unlink
(
&
first
->
p_expiry
);
CHECK_FCT_DO
(
fd_event_send
(
first
->
p_events
,
FDEVP_TERMINATE
,
NULL
),
goto
error
);
CHECK_FCT_DO
(
fd_event_send
(
first
->
p_events
,
FDEVP_TERMINATE
,
0
,
NULL
),
goto
error
);
}
while
(
1
);
...
...
@@ -139,7 +139,7 @@ static void * exp_th_fct(void * arg)
error:
TRACE_DEBUG
(
INFO
,
"An error occurred in peers module! Expiry thread is terminating..."
);
ASSERT
(
0
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
NULL
),
);
CHECK_FCT_DO
(
fd_event_send
(
fd_g_config
->
cnf_main_ev
,
FDEV_TERMINATE
,
0
,
NULL
),
);
return
NULL
;
}
...
...
freeDiameter/p_psm.c
View file @
92fdb242
...
...
@@ -57,6 +57,8 @@ const char * fd_pev_str(int event)
case_str
(
FDEVP_DUMP_ALL
);
case_str
(
FDEVP_TERMINATE
);
case_str
(
FDEVP_CNX_MSG_RECV
);
case_str
(
FDEVP_CNX_ERROR
);
case_str
(
FDEVP_CNX_EP_CHANGE
);
case_str
(
FDEVP_MSG_INCOMING
);
case_str
(
FDEVP_PSM_TIMEOUT
);
...
...
@@ -125,34 +127,13 @@ static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
#endif
}
/* Wait for the next event in the PSM, or timeout */
static
int
psm_ev_timedget
(
struct
fd_peer
*
peer
,
int
*
code
,
void
**
data
)
{
struct
fd_event
*
ev
;
int
ret
=
0
;
TRACE_ENTRY
(
"%p %p %p"
,
peer
,
code
,
data
);
ret
=
fd_fifo_timedget
(
peer
->
p_events
,
&
ev
,
&
peer
->
p_psm_timer
);
if
(
ret
==
ETIMEDOUT
)
{
*
code
=
FDEVP_PSM_TIMEOUT
;
*
data
=
NULL
;
}
else
{
CHECK_FCT
(
ret
);
*
code
=
ev
->
code
;
*
data
=
ev
->
data
;
free
(
ev
);
}
return
0
;
}
/* The state machine thread (controler) */
static
void
*
p_psm_th
(
void
*
arg
)
{
struct
fd_peer
*
peer
=
(
struct
fd_peer
*
)
arg
;
int
created_started
=
started
;
int
event
;
size_t
ev_sz
;
void
*
ev_data
;
CHECK_PARAMS_DO
(
CHECK_PEER
(
peer
),
ASSERT
(
0
)
);
...
...
@@ -181,10 +162,10 @@ static void * p_psm_th( void * arg )
psm_loop:
/* Get next event */
CHECK_FCT_DO
(
psm_ev
_timedget
(
peer
,
&
event
,
&
ev_data
),
goto
psm_end
);
TRACE_DEBUG
(
FULL
,
"'%s'
\t
<-- '%s'
\t
(%p)
\t
'%s'"
,
CHECK_FCT_DO
(
fd_event
_timedget
(
peer
->
p_events
,
&
peer
->
p_psm_timer
,
FDEVP_PSM_TIMEOUT
,
&
event
,
&
ev_sz
,
&
ev_data
),
goto
psm_end
);
TRACE_DEBUG
(
FULL
,
"'%s'
\t
<-- '%s'
\t
(%p
,%g
)
\t
'%s'"
,
STATE_STR
(
peer
->
p_hdr
.
info
.
pi_state
),
fd_pev_str
(
event
),
ev_data
,
fd_pev_str
(
event
),
ev_data
,
ev_sz
,
peer
->
p_hdr
.
info
.
pi_diamid
);
/* Now, the action depends on the current state and the incoming event */
...
...
@@ -271,7 +252,7 @@ int fd_psm_terminate(struct fd_peer * peer )
CHECK_PARAMS
(
CHECK_PEER
(
peer
)
);
if
(
peer
->
p_hdr
.
info
.
pi_state
!=
STATE_ZOMBIE
)
{
CHECK_FCT
(
fd_event_send
(
peer
->
p_events
,
FDEVP_TERMINATE
,
NULL
)
);
CHECK_FCT
(
fd_event_send
(
peer
->
p_events
,
FDEVP_TERMINATE
,
0
,
NULL
)
);
}
else
{
TRACE_DEBUG
(
FULL
,
"Peer '%s' was already terminated"
,
peer
->
p_hdr
.
info
.
pi_diamid
);
}
...
...
freeDiameter/sctp.c
View file @
92fdb242
...
...
@@ -34,9 +34,16 @@
*********************************************************************************************************/
#include "fD.h"
#include "cnxctx.h"
#include <netinet/sctp.h>
#include <sys/uio.h>
/* Size of buffer to receive ancilliary data. May need to be enlarged if more sockopt are set... */
#ifndef CMSG_BUF_LEN
#define CMSG_BUF_LEN 1024
#endif
/* CMSG_BUF_LEN */
/* Pre-binding socket options -- # streams read in config */
static
int
fd_setsockopt_prebind
(
int
sk
)
{
...
...
@@ -743,7 +750,7 @@ fail:
}
/* Retrieve streams information from a connected association -- optionaly provide the primary address */
int
fd_sctp_get_str_info
(
int
sock
,
int
*
in
,
int
*
out
,
sSS
*
primary
)
int
fd_sctp_get_str_info
(
int
sock
,
u
int
16_t
*
in
,
u
int
16_t
*
out
,
sSS
*
primary
)
{
struct
sctp_status
status
;
socklen_t
sz
=
sizeof
(
status
);
...
...
@@ -775,8 +782,8 @@ int fd_sctp_get_str_info( int sock, int *in, int *out, sSS *primary )
TRACE_DEBUG
(
FULL
,
" sstat_primary.spinfo_mtu : %u"
,
status
.
sstat_primary
.
spinfo_mtu
);
#endif
/* DEBUG_SCTP */
*
in
=
(
int
)
status
.
sstat_instrms
;
*
out
=
(
int
)
status
.
sstat_outstrms
;
*
in
=
status
.
sstat_instrms
;
*
out
=
status
.
sstat_outstrms
;
if
(
primary
)
memcpy
(
primary
,
&
status
.
sstat_primary
.
spinfo_address
,
sizeof
(
sSS
));
...
...
@@ -892,3 +899,218 @@ int fd_sctp_get_remote_ep(int sock, struct fd_list * list)
return
0
;
}
/* Send a buffer over a specified stream */
int
fd_sctp_sendstr
(
int
sock
,
uint16_t
strid
,
uint8_t
*
buf
,
size_t
len
)
{
struct
msghdr
mhdr
;
struct
iovec
iov
;
struct
{
struct
cmsghdr
hdr
;
struct
sctp_sndrcvinfo
sndrcv
;
}
anci
;
ssize_t
ret
;
TRACE_ENTRY
(
"%d %hu %p %g"
,
sock
,
strid
,
buf
,
len
);
memset
(
&
mhdr
,
0
,
sizeof
(
mhdr
));
memset
(
&
iov
,
0
,
sizeof
(
iov
));
memset
(
&
anci
,
0
,
sizeof
(
anci
));
/* IO Vector: message data */
iov
.
iov_base
=
buf
;
iov
.
iov_len
=
len
;
/* Anciliary data: specify SCTP stream */
anci
.
hdr
.
cmsg_len
=
sizeof
(
anci
);
anci
.
hdr
.
cmsg_level
=
IPPROTO_SCTP
;
anci
.
hdr
.
cmsg_type
=
SCTP_SNDRCV
;
anci
.
sndrcv
.
sinfo_stream
=
strid
;
/* note : we could store other data also, for example in .sinfo_ppid for remote peer or in .sinfo_context for errors. */
/* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */
mhdr
.
msg_iov
=
&
iov
;
mhdr
.
msg_iovlen
=
1
;
mhdr
.
msg_control
=
&
anci
;
mhdr
.
msg_controllen
=
sizeof
(
anci
);
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Sending %db data on stream %hu of socket %d"
,
len
,
strid
,
sock
);
#endif
/* DEBUG_SCTP */
CHECK_SYS
(
ret
=
sendmsg
(
sock
,
&
mhdr
,
0
)
);
ASSERT
(
ret
==
len
);
/* There should not be partial delivery with sendmsg... */
return
0
;
}
/* Receive the next data from the socket, or next notification */
int
fd_sctp_recvmeta
(
int
sock
,
uint16_t
*
strid
,
uint8_t
**
buf
,
size_t
*
len
,
int
*
event
)
{
ssize_t
ret
=
0
;
struct
msghdr
mhdr
;
char
ancidata
[
CMSG_BUF_LEN
];
struct
iovec
iov
;
uint8_t
*
data
=
NULL
;
size_t
bufsz
=
0
,
datasize
=
0
;
size_t
mempagesz
=
sysconf
(
_SC_PAGESIZE
);
/* We alloc buffer by memory pages for efficiency */
TRACE_ENTRY
(
"%d %p %p %p %p"
,
sock
,
strid
,
buf
,
len
,
event
);
CHECK_PARAMS
(
(
sock
>
0
)
&&
buf
&&
len
&&
event
);
/* Cleanup out parameters */
*
buf
=
NULL
;
*
len
=
0
;
*
event
=
0
;
/* Prepare header for receiving message */
memset
(
&
mhdr
,
0
,
sizeof
(
mhdr
));
mhdr
.
msg_iov
=
&
iov
;
mhdr
.
msg_iovlen
=
1
;
mhdr
.
msg_control
=
&
ancidata
;
mhdr
.
msg_controllen
=
sizeof
(
ancidata
);
/* We will loop while all data is not received. */
incomplete:
if
(
datasize
==
bufsz
)
{
/* The buffer is full, enlarge it */
bufsz
+=
mempagesz
;
CHECK_MALLOC
(
data
=
realloc
(
data
,
bufsz
)
);
}
/* the new data will be received following the preceding */
memset
(
&
iov
,
0
,
sizeof
(
iov
));
iov
.
iov_base
=
data
+
datasize
;
iov
.
iov_len
=
bufsz
-
datasize
;
/* Receive data from the socket */
pthread_cleanup_push
(
free
,
data
);
ret
=
recvmsg
(
sock
,
&
mhdr
,
0
);
pthread_cleanup_pop
(
0
);
/* Handle errors */
if
(
ret
<=
0
)
{
/* Socket is closed, or an error occurred */
CHECK_SYS_DO
(
ret
,
/* to log in case of error */
);
free
(
data
);
*
event
=
FDEVP_CNX_ERROR
;
return
0
;
}
/* Update the size of data we received */
datasize
+=
ret
;
/* SCTP provides an indication when we received a full record; loop if it is not the case */
if
(
!
(
mhdr
.
msg_flags
&
MSG_EOR
)
)
{
goto
incomplete
;
}
/* Handle the case where the data received is a notification */
if
(
mhdr
.
msg_flags
&
MSG_NOTIFICATION
)
{
union
sctp_notification
*
notif
=
(
union
sctp_notification
*
)
data
;
switch
(
notif
->
sn_header
.
sn_type
)
{
case
SCTP_ASSOC_CHANGE
:
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Received SCTP_ASSOC_CHANGE notification"
);
TRACE_DEBUG
(
FULL
,
" state : %hu"
,
notif
->
sn_assoc_change
.
sac_state
);
TRACE_DEBUG
(
FULL
,
" error : %hu"
,
notif
->
sn_assoc_change
.
sac_error
);
TRACE_DEBUG
(
FULL
,
" instr : %hu"
,
notif
->
sn_assoc_change
.
sac_inbound_streams
);
TRACE_DEBUG
(
FULL
,
" outstr : %hu"
,
notif
->
sn_assoc_change
.
sac_outbound_streams
);
#endif
/* DEBUG_SCTP */
*
event
=
FDEVP_CNX_EP_CHANGE
;
break
;
case
SCTP_PEER_ADDR_CHANGE
:
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Received SCTP_PEER_ADDR_CHANGE notification"
);
TRACE_DEBUG_sSA
(
FULL
,
" intf_change : "
,
&
(
notif
->
sn_paddr_change
.
spc_aaddr
),
NI_NUMERICHOST
|
NI_NUMERICSERV
,
""
);
TRACE_DEBUG
(
FULL
,
" state : %d"
,
notif
->
sn_paddr_change
.
spc_state
);
TRACE_DEBUG
(
FULL
,
" error : %d"
,
notif
->
sn_paddr_change
.
spc_error
);
#endif
/* DEBUG_SCTP */
*
event
=
FDEVP_CNX_EP_CHANGE
;
break
;
case
SCTP_SEND_FAILED
:
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Received SCTP_SEND_FAILED notification"
);
TRACE_DEBUG
(
FULL
,
" len : %hu"
,
notif
->
sn_send_failed
.
ssf_length
);
TRACE_DEBUG
(
FULL
,
" err : %d"
,
notif
->
sn_send_failed
.
ssf_error
);
#endif
/* DEBUG_SCTP */
*
event
=
FDEVP_CNX_ERROR
;
break
;
case
SCTP_REMOTE_ERROR
:
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Received SCTP_REMOTE_ERROR notification"
);
TRACE_DEBUG
(
FULL
,
" err : %hu"
,
ntohs
(
notif
->
sn_remote_error
.
sre_error
));
TRACE_DEBUG
(
FULL
,
" len : %hu"
,
ntohs
(
notif
->
sn_remote_error
.
sre_length
));
#endif
/* DEBUG_SCTP */
*
event
=
FDEVP_CNX_ERROR
;
break
;
case
SCTP_SHUTDOWN_EVENT
:
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Received SCTP_SHUTDOWN_EVENT notification"
);
#endif
/* DEBUG_SCTP */
*
event
=
FDEVP_CNX_ERROR
;
break
;
default:
TRACE_DEBUG
(
FULL
,
"Received unknown notification %d, assume error"
,
notif
->
sn_header
.
sn_type
);
*
event
=
FDEVP_CNX_ERROR
;
}
free
(
data
);
return
0
;
}
/* From this point, we have received a message */
*
event
=
FDEVP_CNX_MSG_RECV
;
*
buf
=
data
;
*
len
=
datasize
;
if
(
strid
)
{
struct
cmsghdr
*
hdr
;
struct
sctp_sndrcvinfo
*
sndrcv
;
/* Handle the anciliary data */
for
(
hdr
=
CMSG_FIRSTHDR
(
&
mhdr
);
hdr
;
hdr
=
CMSG_NXTHDR
(
&
mhdr
,
hdr
))
{
/* We deal only with anciliary data at SCTP level */
if
(
hdr
->
cmsg_level
!=
IPPROTO_SCTP
)
{
TRACE_DEBUG
(
FULL
,
"Received some anciliary data at level %d, skipped"
,
hdr
->
cmsg_level
);
continue
;
}
/* Also only interested in SCTP_SNDRCV message for the moment */
if
(
hdr
->
cmsg_type
!=
SCTP_SNDRCV
)
{
TRACE_DEBUG
(
FULL
,
"Anciliary block IPPROTO_SCTP / %d, skipped"
,
hdr
->
cmsg_type
);
continue
;
}
sndrcv
=
(
struct
sctp_sndrcvinfo
*
)
CMSG_DATA
(
hdr
);
#ifdef DEBUG_SCTP
TRACE_DEBUG
(
FULL
,
"Anciliary block IPPROTO_SCTP / SCTP_SNDRCV"
);
TRACE_DEBUG
(
FULL
,
" sinfo_stream : %hu"
,
sndrcv
->
sinfo_stream
);
TRACE_DEBUG
(
FULL
,
" sinfo_ssn : %hu"
,
sndrcv
->
sinfo_ssn
);
TRACE_DEBUG
(
FULL
,
" sinfo_flags : %hu"
,
sndrcv
->
sinfo_flags
);
/* TRACE_DEBUG(FULL, " sinfo_pr_policy : %hu", sndrcv->sinfo_pr_policy); */
TRACE_DEBUG
(
FULL
,
" sinfo_ppid : %u"
,
sndrcv
->
sinfo_ppid
);
TRACE_DEBUG
(
FULL
,
" sinfo_context : %u"
,
sndrcv
->
sinfo_context
);
/* TRACE_DEBUG(FULL, " sinfo_pr_value : %u" , sndrcv->sinfo_pr_value); */
TRACE_DEBUG
(
FULL
,
" sinfo_tsn : %u"
,
sndrcv
->
sinfo_tsn
);
TRACE_DEBUG
(
FULL
,
" sinfo_cumtsn : %u"
,
sndrcv
->
sinfo_cumtsn
);
#endif
/* DEBUG_SCTP */
*
strid
=
sndrcv
->
sinfo_stream
;
}
}
return
0
;
}
freeDiameter/sctps.c
0 → 100644
View file @
92fdb242
/*********************************************************************************************************
* 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. *