Vous êtes sur la page 1sur 32

1

Module 10
References:
Stevens, Fenner, Rudoff, Chapters 2, 9, 10, 23

Objectives:
 Introduce SCTP protocol
 Describe the differences between SCTP vs. TCP
 Discuss SCTP association establishment and
termination
 Describe some SCTP functions and socket options
 Discuss SCTP program example
2
Introduction
 Stream Control Transmission Protocol (SCTP) is a new transport protocol
standardized by IETF in 2000 (described in RFC 2960 (2000) and updated in
RFC 3309 (2002) ).
– It was designed to meet the demand for transporting telephony signal across
Internet
 SCTP is not as popular as TCP or UDP, but provides some new features that
may simplify certain application designs.
 SCTP provides applications with reliability, sequencing, flow control, and full
duplex data transfer; like in TCP.
 SCTP provides associations between client and server.
– An association is different from a connection.
– Connection: a communication between two IP addresses.
– Association: a communication between two end systems; may involve more than
two IP addresses due to multihoming.
3
SCTP vs TCP
 SCTP is message oriented; it provides sequenced delivery of individual
records.
– The length of the record written by a sender is passed to the receiving application and the
application layer message boundaries is preserved; like in UDP.
– Good for applications that do not send data in streams of bytes.
– Do not need to mark message boundaries within a stream of bytes.
 SCTP provides multiple streams between the association end points.
– A loss in one of the streams does not block the delivery of messages in any of other
streams; unlike in TCP.
 SCTP provides multihoming; a single SCTP endpoint support multiple
addresses.
 SCTP avoids head-of-line blocking for transmitting semantically independent
messages.
– Head of line blocking in TCP occurs when a TCP segment is lost, and the
subsequent TCP segments arrives out of order. The subsequent segments are held
until the first TCP segment is retransmitted and arrives at the receiver.
– A stream in SCTP is a sequence of messages that is ordered within the association.
 It uses a multistream feature; each stream is used for the transmission of a semantically
independent message.
 There is no head of line blocking among segments from different streams.
4
SCTP vs TCP (cont.)
Sending 3 pictures over one TCP Sending 3 pictures over one SCTP
connection streams

server client server client

Picture-1 (1)
Picture-1 (1) Stream 1
lost lost
Picture-2 (1)
Picture-2 (1) Stream 2

queued delivered
Picture-3 (1) Picture-3 (1)
Stream 3

queued Picture-1 (2) delivered


Picture-1 (2) Stream 1

queued Picture-1 (1) queued


Picture-1 (1) Stream 1

Delivered delivered
retransmission All held segments are retransmission one held segment is
delivered delivered

5
SCTP vs TCP(cont.)
 SCTP provides an unordered message service.
– Good for applications that do not need message ordering.
– In TCP, the unordered message needs to be ordered even though it is not needed.
 Some SCTP implementations provide a partially reliable service.
– TCP does not have this option.
 Easy migration from TCP to one-to-one SCTP.
 SCTP adopts almost all TCP features:
– positive acknowledgement, retransmission of lost data, re-sequencing of data,
windowed flow control, slow-start and congestion avoidance, and selective
acknowledgement.
 SCTP does not provide two of TCP features:
– Half closed state
 When one end closes an association, the other end must stop sending new data.
 However, that end can send data that was queued, if any, and complete the shutdown.
– Urgent data.
 SCTP is not recommended for use in a true byte-stream oriented application
like: telnet, rlogin, rsh, and ssh.
6
SCTP Association Establishment
Four-way handshake:  INIT tells the server the client’s list of IP
addresses, sequence number J, tag Ta, number
client server of outbound streams the client is requesting,
and number of inbound stream the client can
socket socket, bind, listen support.
connect (blocks) accept (blocks)  INIT-ACK tells the client the server’s list of IP
(active open) INIT(Ta, J) addresses, sequence number K, tag Tz, number
of outbound streams the server is requesting,
and number of inbound stream the server can
support, and a state cookie.
Ta:INIT-ACK(Tz,K,cookie C) – The use of cookies in the SCTP association
establishment provides protection against denial
of service attack.
Tz:COOKIE-ECHO C  The COOKIE-ECHO may contain user data.
 The server acknowledges the correctness of the
accept returns cookie and establish the association with
Ta:COOKIE-ACK COOKIE-ACK. User data may also be included
read blocks
in the message.
connect returns  The minimum number of packets required is
four.

 The tags Ta and Tz must be used in every packet sent from each side to the peer for the life of the association.
 The cookie is digitally signed to ensure its validity.
– It contains all the state needed to keep information about the association to ensure the server that the
association is valid.
 At the conclusion of the handshake, each side chooses a primary destination address as the default destination.

7
SCTP Association Termination

client server

close
(active close)
SHUTDOWN

(passive close) read returns 0

close
SHUTDOWN-ACK

SHUTDOWN-COMPLETE

8
SCTP States

 CLOSED
 COOKIE-WAIT
 COOKIE-ECHOED
 ESTABLISHED
 SHUTDOWN-PENDING: for active-close end
 SHUTDOWN-SENT
 SHUTDOWN-RECEIVED: for passive-close end
 SHUTDOWN-ACK-SENT

9
client server

socket()
connect() (blocks) socket(), bind(), listen()
(active open) COOKIE-WAIT INIT(Ta, J)
(passive open)
accept() (blocks)
CLOSED
Ta:INIT-ACK(Tz,K,cookie C)

Tz:COOKIE-ECHO C, DATA
COOKIE-ECHOED
accept() returns
Ta:COOKIE-ACK,SACK, DATA ESTABLISHED
connect() returns
ESTABLISHED Tz:SACK, DATA

Ta:SACK

close() Tz:SHUTDOWN
(active close) SHUTDOWN-SENT

(passive close)
read returns 0
Ta:SHUTDOWN-ACK close()
SHUTDOWN-ACK-SENT

Tz:SHUTDOWN-COMPLETE
CLOSED
10
CLOSED
 The unit of information within an SCTP packet is a chunk, which
is self-descriptive containing:
– Chunk type
– Chunk flags
– Chunk length

 SCTP does not need a TIME_WAIT state like that in TCP.


– Each chunk of message is tagged with a verification tag; any chunk from
an old connection will arrive with an incorrect tag.
– SCTP does not allow half-closed association  there is no need for the
FIN segment from the passive close end as in TCP.

11
SCTP Output
application application buffer (any size)

write() user process


kernel

SCTP socket send buffer (SO_SNDBUF)

IP

MTU-sized IPv4 packets

output queue
datalink

 SCTP keeps a fragmentation point based on the smallest path MTU found to all the peer’s
addresses; use SCTP_MAXSEG socket option to request for a smaller fragmentation point.
 This smallest MTU is used to split large user messages into smaller pieces that can be sent in one
IP datagram. 12
SCTP socket types
 Two socket types:
– One-to-one interface.
– One-to-many: several SCTP associations can be active on a given socket
simultaneously.

One-to-one interface
 It corresponds to exactly one SCTP association.
 This type is similar to TCP; was termed as TCP-style.
 It is trivial to convert between TCP and SCTP applications.
– IP socket (AF_INET or AF_INET6), type: SOCK_STREAM, protocol:
IPPROTO_SCTP.

 Differences from TCP:


– All TCP socket options must be converted into SCTP options, e.g.,
TCP_NODELAY to SCTP_NODELAY, TCP_MAXSEG to SCTP_MAXSEG.
– SCTP does not support half-close as in TCP (i.e., to signal the end of input to its
peer).

13
Socket function for SCTP one-to-one style
STCP Server
socket ( )

well-known port
bind ( )
STCP Client
listen ( )
socket ( )

accept ( )

blocks until association is requested


from client
connection establishment
connect ( )
STCP four-way handshake

write ( ) data (request)


read ( )

process request

write ( )
data (reply)

read ( )

close ( ) EOF notification

read ( )

close ( ) 14
One-to-many interface
 Similar to UDP socket that can receive interleaved datagram from several remote UDP
endpoints that are all simultaneously sending data.
– Its original term was UDP-style.
 It provides full support for the new features.
– This style is recommended for new applications developed for SCTP.
– It allows an application programmer to write a server without managing a large number of
socket descriptors.
– However, porting from TCP is not easy.
 An association identifier (type sctp_assoc_t) is used to identify an association.
– When a client closes the association, server will automatically closes.
 The server is commonly an iterative server. To combine iterative with concurrent
servers:
– Use sctp_peeloff() to return a new socket descriptor with that association.
– This new socket then can be handed off to either a thread or a process to execute 
concurrent model.
– The main thread continues to handle messages from any remaining associations 
iterative.
 IP socket (AF_INET or AF_INET6), type: SOCK_SEQPACKET, protocol:
IPPROTO_SCTP.

15
Socket Functions for SCTP one-to-many style
STCP Server

socket ( )

well-known port
bind ( )
STCP Client
listen ( )
socket ( )

sctp_recvmsg ( )

blocks until message arrives from


client
STCP four-way handshake
sctp_sendto()
Data(request) on COOKIE-ECHO

process request

sctp_sendmsg()
data (reply)

sctp_recvmsg ( )

close ( ) Shutdown of association

Server need not 16


care
SCTP Functions

int sctp_bindx (int sockfd, const struct sockaddr *addrs, int addrcnt, int flags);

Description
sockfd: socket descriptor.
addrs: a pointer to a list of addresses.
addrcnt: the number of addresses passed in.
flags: SCTP_BINDX_ADD_ADDR  add the address(es) to the socket.
SCTP_BINDX_REM_ADDR  remove the address(es) from the socket.

 The function is used when a server wants to bind a subset of IP addresses


associated with the host system.
– bind() can be used to bind only one address or all addresses.
 It can be used on a bound or unbound socket.
– On an unbound socket: to bind the given set of addresses to the socket descriptor.
– On a bound socket: can be used with SCTP_BINDX_ADD_ADDR or with
SCTP_BINDX_REM_ADDR.

17
SCTP Functions (cont.)
int sctp_connectx (int sockfd, const struct sockaddr *addrs, int addrcnt);

Description
sockfd: socket descriptor.
addrs: a pointer to a list of addresses.
addrcnt: the number of addresses passed in.
 The function is used to connect to a multihomed peer.

int sctp_getpaddrs (int sockfd, sctp_assoc_t id, struct sockaddr **addrs);


 It returns the number of peer addresses stored in addrs.
 It is used to retrieve all the peer’s addresses  similar to getpeername()
– getpeername() in SCTP returns only the primary address.

int sctp_freepaddrs (struct sockaddr *addrs);


 This function is to free resources allocated by sctp_getpaddrs () function.

18
SCTP Functions (cont.)
int sctp_getladdrs (int sockfd, sctp_assoc_t id, struct sockaddr **addrs);
 It returns the number of local addresses stored in addrs.
 It is used to retrieve all the local addresses that are part of an association.

int sctp_freeladdrs (struct sockaddr *addrs);


 To free resources allocated by sctp_getladdrs () function.

19
SCTP Functions (cont.)
ssize_t sctp_sendmsg (int sockfd, const void *msg, size_t msgsz, const struct
sockaddr *to, socklen_t tolen, uint32_t ppid, uint32_t flags, uint16_t stream,
uint32_t timetolive, uint32_t context)

Description
sockfd: socket descriptor.
msg: pointer to a buffer of msgsz bytes to be sent.
to: the address of the receiver with length tolen.
ppid: payload protocol identifier that will be passed with the data chunk
flags: for options, see Figure 7.16 (textbook).
stream: Specifies the stream number.
timetolive: Specifies the lifetime of the message (milliseconds); 0  infinite.

 The function is used to control advanced SCTP features.

Example:
ret = sctp_sendmsg (sockfd, data, datasz, &dest, sizeof(dest), 24, MSG_PR_SCTP_TTL, 1,
1000, 52)
This sends a message to stream #1, send flag= MSG_PR_SCTP_TTL, lifetime= 1000
millisecond, ppid=24, context=52.
20
SCTP Functions (cont.)

ssize_t sctp_recvmsg (int sockfd, const void *msg, size_t msgsz, const struct
sockaddr *from, socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo, int
*msg_flags);

Description
sockfd: socket descriptor.
msg: pointer to a buffer of msgsz bytes received.
from: the address of the peer with length fromlen.
msg_flags: for options, see Figure 7.16 (textbook).
sinfo: retrieves sctp_sndrcvinfo structure for the message.
Must subscribe sctp_data_io_event using SCTP_EVENTS socket option.

 The function is used to control advanced SCTP features.

21
SCTP Functions (cont.)
int sctp_opt_info (int sockfd, sctp_assoc_t assoc_id, int opt, void *arg, socklen_t
*siz)

 It is used for implementations that cannot use getsockopt() functions for


SCTP.
– For portability, use this function for all options that require in-out variables.

int sctp_peeloff (int sockfd, sctp_assoc_t id)

 It is used to extract an association contained by one-to-many socket into an


individual one-to-one-style socket.
 It returns a new socket descriptor on success which can be used for the one-to-
one-style socket.

22
shutdown() function
 Shutdown() can be used for one-to-one-style interface.

 Similarities and differences from its use in TCP:

– With shutdown() both endpoints must complete transmission of any data currently
in the queue and close the association.

– SCTP uses shutdown() so that the end point can reuse the socket to connect to a
new peer  not possible with close() function.

– SHUT_RD: Same as in TCP. No application read. All data in the receive buffer
will be discarded. No SCTP protocol action is taken.

– SHUT_WR: Disable application write. Initiates SCTP shutdown procedure. Allow


the local endpoint to read data that the peer has sent prior to receiving the
SHUTDOWN message.

– SHUT_RDWR: No more application read or write. Initiates SCTP shutdown


procedure. Any queued data will be ACK, and silently discarded.

23
SCTP Socket Options
SCTP_ASSOCINFO Socket option
Can be used for:
 Retrieving information about an existing association
 Changing the parameters for an existing association
 Setting defaults for future associations.

SCTP_EVENTS Socket option


 Allows a caller to fetch, enable, or disable various SCTP notifications.
– An SCTP notification is a message that the SCTP stack will send to the application.
– The message is read as a normal data using either recvmsg () or sctp_recvmsg ()
functions with msg_flags set to MSG_NOTIFICATION.
 Eight different events can be subscribed (See Figure 7.17).

SCTP_STATUS Socket option


 To retrieve the current state of an SCTP association.
 Use sctp_op_info() function for portability.

24
Notifications
 User can track the association states via these notifications.
 Notifications communicate transport-level events, including network status
change, association startups, remote operational errors, and undeliverable
messages.
 Eight events can be subscribed using SCTP_EVENTS socket option by passing
sctp_event_subscribe structure to setsockopt() function.
struct sctp_event_subscribe {
u_int8_t sctp_data_io_event;
u_int8_t sctp_association_event;
u_int8_t sctp_address_event;
u_int8_t sctp_send_failure_event;
u_int8_t sctp_peer_error_event;
u_int8_t sctp_shutdown_event;
u_int8_t sctp_partial_delivery_event;
u_int8_t sctp_adaption_layer_event;
};

 Set sctp_data_io_event to enable sctp_sndrcvinfo to be sent with each


sctp_recvmsg().
25
SCTP Client/Server Example
fgets()
stdin sctp_recvmsg()
STCP sctp_sendmsg() STCP
client server

stdout
sctp_sendmsg()
sctp_recvmsg()
fputs()

Performs the following steps:


 A client reads a line of text from stdin, and sends it to the server.
– The line follows the form: [#] text, where the number in the bracket is the SCTP
stream number.
 The server receives the text, increases the stream number (from which it
received the text) by one and sends the text back to the client with the updated
stream number.
 The client receives the reply and displays it in stdout including the stream
number, stream sequence number and text string.

26
Figure 10.2 SCTP streaming echo server
#include "unp.h"
Int main(int argc, char **argv)
{
int sock_fd,msg_flags; char readbuf[BUFFSIZE]; struct sockaddr_in servaddr, cliaddr;
struct sctp_sndrcvinfo sri; struct sctp_event_subscribe evnts; int stream_increment=1; socklen_t len; size_t rd_sz;

if (argc == 2)
stream_increment = atoi(argv[1]);

sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);


bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT);
Bind (sock_fd, (SA *) &servaddr, sizeof(servaddr));

bzero(&evnts, sizeof(evnts)); evnts.sctp_data_io_event = 1;


Setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));

Listen(sock_fd, LISTENQ);
for ( ; ; ) {
len = sizeof(struct sockaddr_in);
rd_sz = Sctp_recvmsg (sock_fd, readbuf, sizeof(readbuf), (SA *)&cliaddr, &len, &sri,&msg_flags);
if (stream_increment) {
sri.sinfo_stream++;
if (sri.sinfo_stream >= sctp_get_no_strms(sock_fd,(SA *)&cliaddr, len))
sri.sinfo_stream = 0;
}
Sctp_sendmsg(sock_fd, readbuf, rd_sz, (SA *)&cliaddr, len, sri.sinfo_ppid, sri.sinfo_flags, sri.sinfo_stream, 0, 0);
}
}

27
Figure 10.3 SCTP streaming echo client
#include "unp.h"
int
main(int argc, char **argv)
{
int sock_fd;
struct sockaddr_in servaddr;
struct sctp_event_subscribe evnts;
int echo_to_all=0;
if(argc < 2)
err_quit("Missing host argument - use '%s host [echo]'\n",
argv[0]);
if(argc > 2) {
printf("Echoing messages to all streams\n");
echo_to_all = 1;
}

sock_fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);


bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT); Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

bzero(&evnts, sizeof(evnts)); evnts.sctp_data_io_event = 1;


Setsockopt(sock_fd,IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts));

if(echo_to_all == 0)
sctpstr_cli (stdin,sock_fd,(SA *)&servaddr,sizeof(servaddr));
else
sctpstr_cli_echoall (stdin,sock_fd,(SA *)&servaddr,sizeof(servaddr));
Close(sock_fd);
return(0);
}
28
Figure 10.4 SCTP sctpstr_cli() function
#include "unp.h"
void
sctpstr_cli (FILE *fp, int sock_fd, struct sockaddr *to, socklen_t tolen)
{
struct sockaddr_in peeraddr;
struct sctp_sndrcvinfo sri;
char sendline[MAXLINE], recvline[MAXLINE];
socklen_t len;
int out_sz,rd_sz;
int msg_flags;

bzero(&sri,sizeof(sri));
while (fgets(sendline, MAXLINE, fp) != NULL) {
if(sendline[0] != '[') {
printf("Error, line must be of the form '[streamnum]text'\n");
continue;
}

sri.sinfo_stream = strtol(&sendline[1],NULL,0);
out_sz = strlen(sendline);
Sctp_sendmsg(sock_fd, sendline, out_sz, to, tolen, 0, 0, sri.sinfo_stream, 0, 0);
len = sizeof(peeraddr);
rd_sz = Sctp_recvmsg(sock_fd, recvline, sizeof(recvline), (SA *)&peeraddr, &len, &sri,&msg_flags);
printf("From str:%d seq:%d (assoc:0x%x):", sri.sinfo_stream,sri.sinfo_ssn, (u_int)sri.sinfo_assoc_id);
printf("%.*s",rd_sz,recvline);
}
}

29
SCTP sctpstr_cli_echoall() function
#include "unp.h"
#define SCTP_MAXLINE 800
void
sctpstr_cli_echoall(FILE *fp, int sock_fd, struct sockaddr *to, socklen_t tolen)
{
struct sockaddr_in peeraddr;
struct sctp_sndrcvinfo sri;
char sendline[SCTP_MAXLINE], recvline[SCTP_MAXLINE];
socklen_t len;
int rd_sz,i,strsz;
int msg_flags;

bzero (sendline, sizeof(sendline)); bzero (&sri, sizeof(sri));


while ( fgets (sendline, SCTP_MAXLINE - 9, fp) != NULL) {
strsz = strlen (sendline);
if (sendline[strsz-1] == '\n') {
sendline[strsz-1] = '\0';
strsz--;
}
for(i=0;i<SERV_MAX_SCTP_STRM;i++) {
snprintf (sendline + strsz, sizeof(sendline) - strsz, ".msg.%d", i);
Sctp_sendmsg (sock_fd, sendline, sizeof(sendline), to, tolen, 0, 0, i, 0, 0);
}
for(i=0;i<SERV_MAX_SCTP_STRM;i++) {
len = sizeof(peeraddr);
rd_sz = Sctp_recvmsg (sock_fd, recvline, sizeof(recvline), (SA *)&peeraddr, &len, &sri,&msg_flags);
printf ("From str:%d seq:%d (assoc:0x%x):", sri.sinfo_stream,sri.sinfo_ssn, (u_int)sri.sinfo_assoc_id);
printf ("%.*s\n",rd_sz,recvline);
}
}
} 30
// return the number of streams negotiated
int
sctp_get_no_strms (int sock_fd,struct sockaddr *to, socklen_t tolen)
{
int retsz;
struct sctp_status status;
retsz = sizeof(status);
bzero(&status,sizeof(status));
status.sstat_assoc_id = sctp_address_to_associd (sock_fd, to, tolen);
Getsockopt (sock_fd, IPPROTO_SCTP, SCTP_STATUS, &status, &retsz);
return (status.sstat_outstrms);
}

//Translate an address to an association ID - Fig. 23.13 Steven’s book.


sctp_assoc_t
sctp_address_to_associd (int sock_fd, struct sockaddr *sa, socklen_t salen)
{
struct sctp_paddrparams sp;
int siz;
siz = sizeof (struct sctp_paddrparams);
bzero(&sp,siz);
memcpy (&sp.spp_address, sa, salen);
sctp_opt_info (sock_fd,0, SCTP_PEER_ADDR_PARAMS, &sp, &siz);
return (sp.spp_assoc_id);
}

31
Notifications (cont.)

struct sctp_sndrcvinfo {
u_int16_t sinfo_stream;
u_int16_t sinfo_ssn;
u_int16_t sinfo_flags;
u_int32_t sinfo_ppid;
u_int32_t sinfo_context;
u_int32_t sinfo_timetolive;
u_int32_t sinfo_tsn;
u_int32_t sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
};

32

Vous aimerez peut-être aussi