Commit 372f525b authored by Jon Grimm's avatar Jon Grimm

SCTP: Resync with LKSCTP tree.

sctp: one more list_t removal.
sctp: more whitespace cleanup (jgrimm)
sctp: merge with linux bk tree
sctp: Minor ABORT updates (ardelle.fan)  
sctp: Fix misc. COOKIE-ECHO bundling bugs.  (jgrimm)

  There were small windows where the following could occur.
  -Two DATA chunks bundled with COOKIE-ECHO (only 1 allowed.)
  -DATA bundled with lost COOKIE-ECHO needs resent too.
  -DATA sent while in COOKIE-ECHOED if there had not been control data already bundled.

sctp:  more updates for abort (jgrimm and ardelle.fan)
  
  Cleanup T5 upon abort.   Send COMM_LOST notification to ULP upon abort.

sctp: updates to T5 shutdown timer.  (samudrala)
  
  I missed a couple changes from Sridhar's last patch.

sctp: more ABORT, cleanup shutdown timers (ardelle.fan)
  
  When we send or receive an ABORT, there may be a variety of timers running. 
  Turn these timers off when we abort.

sctp: Fix bug in COOKIE-ECHO retransmission.  (jgrimm)
    
  We had saved away the pointer directly to the INIT-ACK state cookie param, but upon COOKIE ECHO retransmission, this skb has already been thrown away.   The fix is to save away the cookie.

sctp:  Unknown chunk processing. (daisyc)
  
  Each chunkheader contains the chunk type.  
  For forward compatiblity, 'action' bits in the type describe what action 
  the peer requests if one does not understand that chunk type.  This patch is to
  implement the handling of those 'unrecognized chunk' actions.

sctp: Add T5 shutdown guard handling. (samudrala)
  
  The T5-shutdown-guard timer is used to bound the time we are willing to try gracefully shutting down.   This protects against certain pathological peers.

sctp: Add msg_name support for notifications and PF_INET sockets. (jgrimm)
parent cc8f2609
......@@ -112,6 +112,7 @@ typedef enum {
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
SCTP_EVENT_TIMEOUT_T3_RTX,
SCTP_EVENT_TIMEOUT_T4_RTO,
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
SCTP_EVENT_TIMEOUT_HEARTBEAT,
SCTP_EVENT_TIMEOUT_SACK,
SCTP_EVENT_TIMEOUT_AUTOCLOSE,
......
......@@ -114,7 +114,8 @@ extern sctp_protocol_t sctp_proto;
extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *,
sctp_scope_t, int priority, int flags);
extern sctp_pf_t *sctp_get_pf_specific(int family);
extern void sctp_set_pf_specific(int family, sctp_pf_t *);
/*
* sctp_socket.c
......
......@@ -107,6 +107,9 @@ sctp_state_fn_t sctp_sf_timer_ignore;
sctp_state_fn_t sctp_sf_do_9_1_abort;
sctp_state_fn_t sctp_sf_cookie_wait_abort;
sctp_state_fn_t sctp_sf_cookie_echoed_abort;
sctp_state_fn_t sctp_sf_shutdown_pending_abort;
sctp_state_fn_t sctp_sf_shutdown_sent_abort;
sctp_state_fn_t sctp_sf_shutdown_ack_sent_abort;
sctp_state_fn_t sctp_sf_do_5_1B_init;
sctp_state_fn_t sctp_sf_do_5_1C_ack;
sctp_state_fn_t sctp_sf_do_5_1D_ce;
......@@ -119,6 +122,7 @@ sctp_state_fn_t sctp_sf_tabort_8_4_8;
sctp_state_fn_t sctp_sf_operr_notify;
sctp_state_fn_t sctp_sf_t1_timer_expire;
sctp_state_fn_t sctp_sf_t2_timer_expire;
sctp_state_fn_t sctp_sf_t5_timer_expire;
sctp_state_fn_t sctp_sf_sendbeat_8_3;
sctp_state_fn_t sctp_sf_beat_8_3;
sctp_state_fn_t sctp_sf_backbeat_8_3;
......@@ -134,6 +138,7 @@ sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
/* Prototypes for primitive event state functions. */
sctp_state_fn_t sctp_sf_do_prm_asoc;
......@@ -144,6 +149,9 @@ sctp_state_fn_t sctp_sf_cookie_echoed_prm_shutdown;
sctp_state_fn_t sctp_sf_do_9_1_prm_abort;
sctp_state_fn_t sctp_sf_cookie_wait_prm_abort;
sctp_state_fn_t sctp_sf_cookie_echoed_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_pending_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_sent_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_ack_sent_prm_abort;
sctp_state_fn_t sctp_sf_error_closed;
sctp_state_fn_t sctp_sf_error_shutdown;
sctp_state_fn_t sctp_sf_ignore_primitive;
......
......@@ -255,6 +255,12 @@ typedef struct sctp_func {
sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address);
/* Protocol family functions. */
typedef struct sctp_pf {
void (*event_msgname)(sctp_ulpevent_t *, char *, int *);
void (*skb_msgname)(struct sk_buff *, char *, int *);
} sctp_pf_t;
/* SCTP Socket type: UDP or TCP style. */
typedef enum {
SCTP_SOCKET_UDP = 0,
......@@ -280,6 +286,7 @@ struct sctp_opt {
__u32 autoclose;
__u8 nodelay;
__u8 disable_fragments;
sctp_pf_t *pf;
};
......@@ -845,6 +852,7 @@ int sctp_outqueue_set_output_handlers(sctp_outqueue_t *,
sctp_outqueue_ohandler_force_t force);
void sctp_outqueue_restart(sctp_outqueue_t *);
void sctp_retransmit(sctp_outqueue_t *, sctp_transport_t *, __u8);
void sctp_retransmit_mark(sctp_outqueue_t *, sctp_transport_t *, __u8);
/* These bind address data fields common between endpoints and associations */
......@@ -1128,6 +1136,11 @@ struct SCTP_association {
*/
sctp_transport_t *primary_path;
/* Cache the primary path address here, when we
* need a an address for msg_name.
*/
sockaddr_storage_t primary_addr;
/* active_path
* The path that we are currently using to
* transmit new data and most control chunks.
......@@ -1183,7 +1196,7 @@ struct SCTP_association {
int next_dup_tsn;
/* Do we need to sack the peer? */
int sack_needed;
uint8_t sack_needed;
/* These are capabilities which our peer advertised. */
__u8 ecn_capable; /* Can peer do ECN? */
......
......@@ -96,7 +96,7 @@ unsigned long update_adler32(unsigned long adler,
* one subtract at the MOST, since buf[n]
* is a max of 255.
*/
if(s1 >= BASE)
if (s1 >= BASE)
s1 -= BASE;
/* s2 = (s2 + s1) % BASE */
......
......@@ -288,7 +288,6 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
return NULL;
}
/* Free this association if possible. There may still be users, so
* the actual deallocation may be delayed.
*/
......@@ -330,6 +329,11 @@ void sctp_association_free(sctp_association_t *asoc)
sctp_association_put(asoc);
}
/* Free peer's cached cookie. */
if (asoc->peer.cookie) {
kfree(asoc->peer.cookie);
}
/* Release the transport structures. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, sctp_transport_t, transports);
......@@ -342,7 +346,6 @@ void sctp_association_free(sctp_association_t *asoc)
sctp_association_put(asoc);
}
/* Cleanup and free up an association. */
static void sctp_association_destroy(sctp_association_t *asoc)
{
......@@ -387,8 +390,7 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
asoc->peer.port = *port;
}
SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n",
return NULL);
SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n", return NULL);
/* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr);
......@@ -464,6 +466,16 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
/* Attach the remote transport to our asoc. */
list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
/* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) {
asoc->peer.primary_path = peer;
/* Set a default msg_name for events. */
memcpy(&asoc->peer.primary_addr, &peer->ipaddr,
sizeof(sockaddr_storage_t));
asoc->peer.active_path = peer;
asoc->peer.retran_path = peer;
}
/* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) {
asoc->peer.primary_path = peer;
......
......@@ -198,6 +198,7 @@ static const char *sctp_timer_tbl[] = {
"TIMEOUT_T2_SHUTDOWN",
"TIMEOUT_T3_RTX",
"TIMEOUT_T4_RTO",
"TIMEOUT_T5_SHUTDOWN_GUARD",
"TIMEOUT_HEARTBEAT",
"TIMEOUT_SACK",
"TIMEOUT_AUTOCLOSE",
......
......@@ -92,6 +92,7 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto,
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
struct sock *sk, int priority)
{
sctp_opt_t *sp = sctp_sk(sk);
memset(ep, 0, sizeof(sctp_endpoint_t));
/* Initialize the base structure. */
......@@ -129,22 +130,30 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
/* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]
= SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]
= SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN]
= sctp_sk(sk)->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT]
= SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK]
= SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]
= sctp_sk(sk)->autoclose * HZ;
ep->timeouts[SCTP_EVENT_TIMEOUT_PMTU_RAISE]
= SCTP_DEFAULT_TIMEOUT_PMTU_RAISE;
/* sctpimpguide-05 Section 2.12.2
* If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
* recommended value of 5 times 'RTO.Max'.
*/
ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
= 5 * sp->rtoinfo.srto_max;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
ep->timeouts[SCTP_EVENT_TIMEOUT_PMTU_RAISE] =
SCTP_DEFAULT_TIMEOUT_PMTU_RAISE;
/* Set up the default send/receive buffer space. */
......@@ -251,7 +260,8 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
sctp_association_t *__sctp_endpoint_lookup_assoc(const sctp_endpoint_t *endpoint,
sctp_association_t *__sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *endpoint,
const sockaddr_storage_t *paddr,
sctp_transport_t **transport)
{
......@@ -360,10 +370,5 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
/* Is this the right way to pass errors up to the ULP? */
if (error)
ep->base.sk->err = -error;
out:
}
......@@ -189,6 +189,80 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address)
return dst_mtu;
}
/* Initialize a PF_INET6 socket msg_name. */
static void sctp_inet6_msgname(char *msgname, int *addr_len)
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)msgname;
sin6->sin6_family = AF_INET6;
sin6->sin6_flowinfo = 0;
sin6->sin6_scope_id = 0;
*addr_len = sizeof(struct sockaddr_in6);
}
/* Initialize a PF_INET msgname from a ulpevent. */
static void sctp_inet6_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addrlen)
{
struct sockaddr_in6 *sin6, *sin6from;
if (msgname) {
sockaddr_storage_t *addr;
sctp_inet6_msgname(msgname, addrlen);
sin6 = (struct sockaddr_in6 *)msgname;
sin6->sin6_port = htons(event->asoc->peer.port);
addr = &event->asoc->peer.primary_addr;
/* Note: If we go to a common v6 format, this code
* will change.
*/
/* Map ipv4 address into v4-mapped-on-v6 address. */
if (AF_INET == addr->sa.sa_family) {
/* FIXME: Easy, but there was no way to test this
* yet.
*/
return;
}
sin6from = &event->asoc->peer.primary_addr.v6;
ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr);
}
}
/* Initialize a msg_name from an inbound skb. */
static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
int *addr_len)
{
struct sctphdr *sh;
struct sockaddr_in6 *sin6;
if (msgname) {
sctp_inet6_msgname(msgname, addr_len);
sin6 = (struct sockaddr_in6 *)msgname;
sh = (struct sctphdr *)skb->h.raw;
sin6->sin6_port = sh->source;
/* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */
if (__constant_htons(ETH_P_IP) == skb->protocol) {
/* FIXME: Easy, but there was no way to test this
* yet.
*/
return;
}
/* Otherwise, just copy the v6 address. */
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
struct inet6_skb_parm *opt =
(struct inet6_skb_parm *) skb->cb;
sin6->sin6_scope_id = opt->iif;
}
}
}
static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6,
.release = inet6_release,
......@@ -238,15 +312,22 @@ static sctp_func_t sctp_ipv6_specific = {
.sa_family = AF_INET6,
};
static sctp_pf_t sctp_pf_inet6_specific = {
.event_msgname = sctp_inet6_event_msgname,
.skb_msgname = sctp_inet6_skb_msgname,
};
/* Initialize IPv6 support and register with inet6 stack. */
int sctp_v6_init(void)
{
/* Add SCTPv6 to inetsw6 linked list. */
inet6_register_protosw(&sctpv6_protosw);
/* Register inet6 protocol. */
inet6_add_protocol(&sctpv6_protocol);
/* Register the SCTP specfic PF_INET6 functions. */
sctp_set_pf_specific(PF_INET6, &sctp_pf_inet6_specific);
/* Fill in address family info. */
INIT_LIST_HEAD(&sctp_ipv6_specific.list);
list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families);
......
......@@ -129,7 +129,8 @@ void sctp_packet_free(sctp_packet_t *packet)
* as it can fit in the packet, but any more data that does not fit in this
* packet can be sent only after receiving the COOKIE_ACK.
*/
sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet,
sctp_chunk_t *chunk)
{
sctp_xmit_t retval;
int error = 0;
......@@ -181,8 +182,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
/* Both control chunks and data chunks with TSNs are
* non-fragmentable.
*/
int fragmentable = sctp_chunk_is_data(chunk)
&& (!chunk->has_tsn);
int fragmentable = sctp_chunk_is_data(chunk) &&
(!chunk->has_tsn);
if (packet_empty) {
if (fragmentable) {
retval = SCTP_XMIT_MUST_FRAG;
......@@ -221,10 +222,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
}
/* It is OK to send this chunk. */
skb_queue_tail(&packet->chunks,
(struct sk_buff *)chunk);
skb_queue_tail(&packet->chunks, (struct sk_buff *)chunk);
packet->size += chunk_len;
finish:
return retval;
}
......@@ -337,7 +336,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
}
/* Build the SCTP header. */
sh = (struct sctphdr *) skb_push(nskb, sizeof(struct sctphdr));
sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
sh->source = htons(packet->source_port);
sh->dest = htons(packet->destination_port);
......@@ -467,7 +466,8 @@ static void sctp_packet_reset(sctp_packet_t *packet)
}
/* This private function handles the specifics of appending DATA chunks. */
static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *chunk)
static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
sctp_chunk_t *chunk)
{
sctp_xmit_t retval = SCTP_XMIT_OK;
size_t datasize, rwnd, inflight;
......@@ -502,12 +502,13 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
}
}
/* sctpimpguide-05 2.14.2 D) When the time comes for the sender to
/* sctpimpguide-05 2.14.2
* D) When the time comes for the sender to
* transmit new DATA chunks, the protocol parameter Max.Burst MUST
* first be applied to limit how many new DATA chunks may be sent.
* The limit is applied by adjusting cwnd as follows:
* if((flightsize + Max.Burst*MTU) < cwnd)
* cwnd = flightsize + Max.Burst*MTU
* if ((flightsize + Max.Burst * MTU) < cwnd)
* cwnd = flightsize + Max.Burst * MTU
*/
max_burst_bytes = transport->asoc->max_burst * transport->asoc->pmtu;
if ((transport->flight_size + max_burst_bytes) < transport->cwnd) {
......@@ -552,7 +553,3 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
finish:
return retval;
}
......@@ -196,23 +196,14 @@ int sctp_push_outqueue(sctp_outqueue_t *q, sctp_chunk_t *chunk)
return error;
}
/* Mark all the eligible packets on a transport for retransmission and force
* one packet out.
*/
void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
/* Mark all the eligible packets on a transport for retransmission. */
void sctp_retransmit_mark(sctp_outqueue_t *q, sctp_transport_t *transport,
__u8 fast_retransmit)
{
struct list_head *lchunk;
sctp_chunk_t *chunk;
int error = 0;
struct list_head tlist;
if (fast_retransmit) {
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
} else {
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
}
INIT_LIST_HEAD(&tlist);
while (!list_empty(&transport->transmitted)) {
......@@ -276,7 +267,26 @@ void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
transport->flight_size,
transport->partial_bytes_acked);
}
/* Mark all the eligible packets on a transport for retransmission and force
* one packet out.
*/
void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
__u8 fast_retransmit)
{
int error = 0;
if (fast_retransmit) {
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
} else {
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
}
sctp_retransmit_mark(q, transport, fast_retransmit);
error = sctp_flush_outqueue(q, /* rtx_timeout */ 1);
if (error)
q->asoc->base.sk->err = -error;
}
......@@ -370,8 +380,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt,
/* The append was successful, so add this chunk to
* the transmitted list.
*/
list_add_tail(lchunk,
&transport->transmitted);
list_add_tail(lchunk, &transport->transmitted);
*start_timer = 1;
q->empty = 0;
......@@ -389,8 +398,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt,
* chunk that is currently in the process of fragmentation.
*/
void sctp_xmit_frag(sctp_outqueue_t *q, struct sk_buff *pos,
sctp_packet_t *packet,
sctp_chunk_t *frag, __u32 tsn)
sctp_packet_t *packet, sctp_chunk_t *frag, __u32 tsn)
{
sctp_transport_t *transport = packet->transport;
struct sk_buff_head *queue = &q->out;
......@@ -499,7 +507,8 @@ void sctp_xmit_fragmented_chunks(sctp_outqueue_t *q, sctp_packet_t *packet,
* fragments. It returns the first fragment with the frag_list field holding
* the remaining fragments.
*/
sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, size_t max_frag_data_len)
sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk,
size_t max_frag_data_len)
{
sctp_association_t *asoc = chunk->asoc;
void *data_ptr = chunk->subh.data_hdr;
......@@ -533,11 +542,14 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, size_t max_frag_data_len)
/* Make the middle fragments. */
while (chunk_data_len > max_frag_data_len) {
frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len,
data_ptr, SCTP_DATA_MIDDLE_FRAG, ssn);
data_ptr, SCTP_DATA_MIDDLE_FRAG,
ssn);
if (!frag)
goto err;
/* Add the middle fragment to the first fragment's frag_list. */
/* Add the middle fragment to the first fragment's
* frag_list.
*/
list_add_tail(&frag->frag_list, frag_list);
chunk_data_len -= max_frag_data_len;
......@@ -674,7 +686,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
(void) (*q->build_output)(&singleton, chunk);
error = (*q->force_output)(&singleton);
if (error < 0)
return(error);
return error;
break;
case SCTP_CID_ABORT:
......@@ -705,10 +717,10 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
/* Is it OK to send data chunks? */
switch (asoc->state) {
case SCTP_STATE_COOKIE_ECHOED:
/* Only allow bundling, if this packet has a COOKIE-ECHO
/* Only allow bundling when this packet has a COOKIE-ECHO
* chunk.
*/
if (packet && !packet->has_cookie_echo)
if (!packet || !packet->has_cookie_echo)
break;
/* fallthru */
......@@ -748,6 +760,12 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
if (start_timer)
sctp_transport_reset_timers(transport);
/* This can happen on COOKIE-ECHO resend. Only
* one chunk can get bundled with a COOKIE-ECHO.
*/
if (packet->has_cookie_echo)
goto sctp_flush_out;
}
/* Finally, transmit new packets. */
......@@ -813,8 +831,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
ntohl(chunk->subh.data_hdr->tsn),
chunk->skb ?chunk->skb->head : 0,
chunk->skb ?
atomic_read(&chunk->skb->users) :
-1);
atomic_read(&chunk->skb->users) : -1);
/* Add the chunk to the packet. */
status = (*q->build_output)(packet, chunk);
......@@ -827,7 +844,8 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
*/
SCTP_DEBUG_PRINTK("sctp_flush_outqueue: could"
"not transmit TSN: 0x%x, status: %d\n",
ntohl(chunk->subh.data_hdr->tsn), status);
ntohl(chunk->subh.data_hdr->tsn),
status);
skb_queue_head(queue, (struct sk_buff *)chunk);
goto sctp_flush_out;
break;
......@@ -857,7 +875,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
default:
BUG();
};
}
/* BUG: We assume that the (*q->force_output())
* call below will succeed all the time and add the
......@@ -875,13 +893,19 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
sctp_transport_reset_timers(transport);
q->empty = 0;
/* Only let one DATA chunk get bundled with a
* COOKIE-ECHO chunk.
*/
if (packet->has_cookie_echo)
goto sctp_flush_out;
}
break;
default:
/* Do nothing. */
break;
};
}
sctp_flush_out:
/* Before returning, examine all the transports touched in
......@@ -986,8 +1010,7 @@ int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack)
ctsn = q->asoc->ctsn_ack_point;
SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n",
__FUNCTION__,
sack_ctsn);
__FUNCTION__, sack_ctsn);
SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association "
"%p is 0x%x.\n", __FUNCTION__, q->asoc, ctsn);
......@@ -1114,8 +1137,9 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
* 6.3.1 C5) Karn's algorithm: RTT measurements
* MUST NOT be made using packets that were
* retransmitted (and thus for which it is
* ambiguous whether the reply was for the first
* instance of the packet or a later instance).
* ambiguous whether the reply was for the
* first instance of the packet or a later
* instance).
*/
if ((!tchunk->tsn_gap_acked) &&
(1 == tchunk->num_times_sent) &&
......@@ -1150,15 +1174,15 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
* 'Stray DATA chunk(s)' record the highest TSN
* reported as newly acknowledged, call this
* value 'HighestTSNinSack'. A newly
* acknowledged DATA chunk is one not previously
* acknowledged in a SACK.
* acknowledged DATA chunk is one not
* previously acknowledged in a SACK.
*
* When the SCTP sender of data receives a SACK
* chunk that acknowledges, for the first time,
* the receipt of a DATA chunk, all the still
* unacknowledged DATA chunks whose TSN is older
* than that newly acknowledged DATA chunk, are
* qualified as 'Stray DATA chunks'.
* unacknowledged DATA chunks whose TSN is
* older than that newly acknowledged DATA
* chunk, are qualified as 'Stray DATA chunks'.
*/
if (!tchunk->tsn_gap_acked) {
tchunk->tsn_gap_acked = 1;
......@@ -1217,8 +1241,8 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
} else {
if (tchunk->tsn_gap_acked) {
SCTP_DEBUG_PRINTK("%s: Receiver reneged on data "
"TSN: 0x%x\n",
SCTP_DEBUG_PRINTK("%s: Receiver reneged on "
"data TSN: 0x%x\n",
__FUNCTION__,
tsn);
tchunk->tsn_gap_acked = 0;
......@@ -1227,10 +1251,11 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
/* RFC 2960 6.3.2 Retransmission Timer Rules
*
* R4) Whenever a SACK is received missing a TSN
* that was previously acknowledged via a Gap Ack
* Block, start T3-rtx for the destination
* address to which the DATA chunk was originally
* R4) Whenever a SACK is received missing a
* TSN that was previously acknowledged via a
* Gap Ack Block, start T3-rtx for the
* destination address to which the DATA
* chunk was originally
* transmitted if it is not already running.
*/
restart_timer = 1;
......@@ -1306,7 +1331,8 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
* active if it is not so marked.
*/
if (!transport->state.active) {
sctp_assoc_control_transport(transport->asoc,
sctp_assoc_control_transport(
transport->asoc,
transport,
SCTP_TRANSPORT_UP,
SCTP_RECEIVED_SACK);
......@@ -1398,8 +1424,7 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, "
"ssthresh: %d, flight_size: %d, pba: %d\n",
__FUNCTION__,
transport, transport->cwnd,
__FUNCTION__, transport, transport->cwnd,
transport->ssthresh, transport->flight_size,
transport->partial_bytes_acked);
}
......
......@@ -66,6 +66,9 @@ struct proc_dir_entry *proc_net_sctp;
*/
static struct socket *sctp_ctl_socket;
static sctp_pf_t *sctp_pf_inet6_specific;
static sctp_pf_t *sctp_pf_inet_specific;
extern struct net_proto_family inet_family_ops;
/* Return the address of the control sock. */
......@@ -91,7 +94,7 @@ void sctp_proc_init(void)
void sctp_proc_exit(void)
{
if (proc_net_sctp) {
proc_net_sctp= NULL;
proc_net_sctp = NULL;
remove_proc_entry("net/sctp", 0);
}
}
......@@ -135,7 +138,8 @@ static inline void sctp_v4_get_local_addr_list(sctp_protocol_t *proto,
* the protocol structure.
* FIXME: Make this an address family function.
*/
static inline void sctp_v6_get_local_addr_list(sctp_protocol_t *proto, struct net_device *dev)
static inline void sctp_v6_get_local_addr_list(sctp_protocol_t *proto,
struct net_device *dev)
{
#ifdef SCTP_V6_SUPPORT
/* FIXME: The testframe doesn't support this function. */
......@@ -239,8 +243,7 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp,
(((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp,
&addr->a,
error = sctp_add_bind_addr(bp, &addr->a,
priority);
if (error)
goto end_copy;
......@@ -286,7 +289,8 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address)
/* Event handler for inet device events.
* Basically, whenever there is an event, we re-build our local address list.
*/
static int sctp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
static int sctp_netdev_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
long flags __attribute__ ((unused));
......@@ -347,6 +351,52 @@ sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address)
return retval;
}
/* Common code to initialize a AF_INET msg_name. */
static void sctp_inet_msgname(char *msgname, int *addr_len)
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)msgname;
*addr_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
}
/* Copy the primary address of the peer primary address as the msg_name. */
static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addr_len)
{
struct sockaddr_in *sin, *sinfrom;
if (msgname) {
sctp_inet_msgname(msgname, addr_len);
sin = (struct sockaddr_in *)msgname;
sinfrom = &event->asoc->peer.primary_addr.v4;
sin->sin_port = htons(event->asoc->peer.port);
sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr;
}
}
/* Initialize and copy out a msgname from an inbound skb. */
static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *addr_len)
{
struct sctphdr *sh;
struct sockaddr_in *sin;
if (msgname) {
sctp_inet_msgname(msgname, addr_len);
sin = (struct sockaddr_in *)msgname;
sh = (struct sctphdr *)skb->h.raw;
sin->sin_port = sh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
}
}
static sctp_pf_t sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname,
.skb_msgname = sctp_inet_skb_msgname,
};
/* Registration for netdev events. */
struct notifier_block sctp_netdev_notifier = {
.notifier_call = sctp_netdev_event,
......@@ -403,6 +453,34 @@ sctp_func_t sctp_ipv4_specific = {
.sa_family = AF_INET,
};
sctp_pf_t *sctp_get_pf_specific(int family) {
switch (family) {
case PF_INET:
return sctp_pf_inet_specific;
case PF_INET6:
return sctp_pf_inet6_specific;
default:
return NULL;
}
}
/* Set the PF specific function table. */
void sctp_set_pf_specific(int family, sctp_pf_t *pf)
{
switch (family) {
case PF_INET:
sctp_pf_inet_specific = pf;
break;
case PF_INET6:
sctp_pf_inet6_specific = pf;
break;
default:
BUG();
break;
}
}
/* Initialize the universe into something sensible. */
int sctp_init(void)
{
......@@ -421,6 +499,8 @@ int sctp_init(void)
/* Initialize object count debugging. */
sctp_dbg_objcnt_init();
/* Initialize the SCTP specific PF functions. */
sctp_set_pf_specific(PF_INET, &sctp_pf_inet);
/*
* 14. Suggested SCTP Protocol Parameter Values
*/
......@@ -468,7 +548,7 @@ int sctp_init(void)
sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.assoc_hashbucket) {
printk (KERN_ERR "SCTP: Failed association hash alloc.\n");
printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
status = -ENOMEM;
goto err_ahash_alloc;
}
......@@ -482,7 +562,7 @@ int sctp_init(void)
sctp_proto.ep_hashbucket = (sctp_hashbucket_t *)
kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.ep_hashbucket) {
printk (KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
status = -ENOMEM;
goto err_ehash_alloc;
}
......@@ -497,7 +577,7 @@ int sctp_init(void)
sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.port_hashtable) {
printk (KERN_ERR "SCTP: Failed bind hash alloc.");
printk(KERN_ERR "SCTP: Failed bind hash alloc.");
status = -ENOMEM;
goto err_bhash_alloc;
}
......
......@@ -1418,6 +1418,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
__u8 *end;
sctp_transport_t *transport;
struct list_head *pos, *temp;
char *cookie;
/* We must include the address that the INIT packet came from.
* This is the only address that matters for an INIT packet.
......@@ -1471,6 +1472,15 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
/* Peer Rwnd : Current calculated value of the peer's rwnd. */
asoc->peer.rwnd = asoc->peer.i.a_rwnd;
/* Copy cookie in case we need to resend COOKIE-ECHO. */
cookie = asoc->peer.cookie;
if (cookie) {
asoc->peer.cookie = kmalloc(asoc->peer.cookie_len, priority);
if (!asoc->peer.cookie)
goto clean_up;
memcpy(asoc->peer.cookie, cookie, asoc->peer.cookie_len);
}
/* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
* high (for example, implementations MAY use the size of the receiver
* advertised window).
......@@ -1560,7 +1570,7 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param,
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
SCTP_DEBUG_PRINTK("unimplmented SCTP_HOST_NAME_ADDRESS\n");
SCTP_DEBUG_PRINTK("unimplemented SCTP_HOST_NAME_ADDRESS\n");
break;
case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
......@@ -1595,13 +1605,12 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param,
case SCTP_PARAM_STATE_COOKIE:
asoc->peer.cookie_len =
ntohs(param.p->length) -
sizeof(sctp_paramhdr_t);
ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
asoc->peer.cookie = param.cookie->body;
break;
case SCTP_PARAM_HEATBEAT_INFO:
SCTP_DEBUG_PRINTK("unimplmented "
SCTP_DEBUG_PRINTK("unimplemented "
"SCTP_PARAM_HEATBEAT_INFO\n");
break;
......
......@@ -253,6 +253,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_chunk_t *new_obj;
sctp_chunk_t *chunk;
sctp_packet_t *packet;
struct list_head *pos;
struct timer_list *timer;
unsigned long timeout;
sctp_transport_t *t;
......@@ -336,9 +337,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case SCTP_CMD_PEER_INIT:
/* Process a unified INIT from the peer. */
sctp_cmd_process_init(commands,
asoc, chunk, command->obj.ptr,
priority);
sctp_cmd_process_init(commands, asoc, chunk,
command->obj.ptr, priority);
break;
case SCTP_CMD_GEN_COOKIE_ECHO:
......@@ -462,6 +462,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break;
case SCTP_CMD_INIT_RESTART:
/* Do the needed accounting and updates
* associated with restarting an initialization
* timer.
......@@ -474,6 +475,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
asoc->max_init_timeo;
}
/* If we've sent any data bundled with
* COOKIE-ECHO we need to resend.
*/
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, sctp_transport_t,
transports);
sctp_retransmit_mark(&asoc->outqueue, t, 0);
}
sctp_add_cmd_sf(commands,
SCTP_CMD_TIMER_RESTART,
SCTP_TO(command->obj.to));
......@@ -867,6 +877,14 @@ void sctp_generate_t2_shutdown_event(unsigned long data)
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN);
}
void sctp_generate_t5_shutdown_guard_event(unsigned long data)
{
sctp_association_t *asoc = (sctp_association_t *)data;
sctp_generate_timeout_event(asoc,
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD);
} /* sctp_generate_t5_shutdown_guard_event() */
void sctp_generate_autoclose_event(unsigned long data)
{
sctp_association_t *asoc = (sctp_association_t *) data;
......@@ -932,6 +950,7 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = {
sctp_generate_t2_shutdown_event,
NULL,
NULL,
sctp_generate_t5_shutdown_guard_event,
sctp_generate_heartbeat_event,
sctp_generate_sack_event,
sctp_generate_autoclose_event,
......@@ -1023,6 +1042,9 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
SCTP_ULPEVENT(event));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
/* FIXME: We need to handle data that could not be sent or was not
* acked, if the user has enabled SEND_FAILED notifications.
*/
......
......@@ -149,6 +149,9 @@ sctp_disposition_t sctp_sf_do_4_C(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
......@@ -160,35 +163,6 @@ sctp_disposition_t sctp_sf_do_4_C(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_NOMEM;
}
/*
* Discard the whole packet.
*
* Section: 8.4 2)
*
* 2) If the OOTB packet contains an ABORT chunk, the receiver MUST
* silently discard the OOTB packet and take no further action.
* Otherwise,
*
* Verification Tag: No verification necessary
*
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t sctp_sf_pdiscard(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
}
/*
* Respond to a normal INIT chunk.
* We are the side that is being asked for an association.
......@@ -338,20 +312,17 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep,
if (!reply)
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(reply));
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,
SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB;
}
/* Tag the variable length paramters. Note that we never
* convert the parameters in an INIT chunk.
*/
chunk->param_hdr.v =
skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
initchunk = (sctp_init_chunk_t *) chunk->chunk_hdr;
......@@ -460,8 +431,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep,
case -SCTP_IERROR_BAD_SIG:
default:
return sctp_sf_pdiscard(ep, asoc, type,
arg, commands);
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
};
}
......@@ -625,8 +595,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
if (!reply)
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(reply));
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
/* Set transport error counter and association error counter
* when sending heartbeat.
......@@ -779,8 +748,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const sctp_endpoint_t *ep,
* sent and mark the destination transport address as active if
* it is not so marked.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON,
SCTP_TRANSPORT(link));
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON, SCTP_TRANSPORT(link));
return SCTP_DISPOSITION_CONSUME;
}
......@@ -875,8 +843,10 @@ static char sctp_tietags_compare(sctp_association_t *new_asoc,
/* Common helper routine for both duplicate and simulataneous INIT
* chunk handling.
*/
static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep,
const sctp_association_t *asoc, const sctp_subtype_t type,
static sctp_disposition_t sctp_sf_do_unexpected_init(
const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg, sctp_cmd_seq_t *commands)
{
sctp_chunk_t *chunk = arg;
......@@ -894,8 +864,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep,
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
/* Tag the variable length parameters. */
chunk->param_hdr.v =
skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
/*
* Other parameters for the endpoint SHOULD be copied from the
......@@ -912,10 +881,9 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep,
* Verification Tag and Peers Verification tag into a reserved
* place (local tie-tag and per tie-tag) within the state cookie.
*/
sctp_process_init(new_asoc, chunk->chunk_hdr->type,
sctp_source(chunk),
(sctp_init_chunk_t *)chunk->chunk_hdr,
GFP_ATOMIC);
sctp_process_init(new_asoc, chunk->chunk_hdr->type, sctp_source(chunk),
(sctp_init_chunk_t *)chunk->chunk_hdr, GFP_ATOMIC);
sctp_tietags_populate(new_asoc, asoc);
/* B) "Z" shall respond immediately with an INIT ACK chunk. */
......@@ -1323,10 +1291,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
chunk->subh.cookie_hdr =
(sctp_signed_cookie_t *) chunk->skb->data;
skb_pull(chunk->skb,
ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
chunk->subh.cookie_hdr = (sctp_signed_cookie_t *)chunk->skb->data;
skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
sizeof(sctp_chunkhdr_t));
/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie
* of a duplicate COOKIE ECHO match the Verification Tags of the
......@@ -1351,8 +1318,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
case -SCTP_IERROR_BAD_SIG:
default:
return sctp_sf_pdiscard(ep, asoc, type,
arg, commands);
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
};
}
......@@ -1398,6 +1364,65 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_NOMEM;
}
/*
* Process an ABORT. (SHUTDOWN-PENDING state)
*
* See sctp_sf_do_9_1_abort().
*/
sctp_disposition_t sctp_sf_shutdown_pending_abort(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
return sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);
}
/*
* Process an ABORT. (SHUTDOWN-SENT state)
*
* See sctp_sf_do_9_1_abort().
*/
sctp_disposition_t sctp_sf_shutdown_sent_abort(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
/* Stop the T2-shutdown timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
return sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);
}
/*
* Process an ABORT. (SHUTDOWN-ACK-SENT state)
*
* See sctp_sf_do_9_1_abort().
*/
sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
/* The same T2 timer, so we should be able to use
* common function with the SHUTDOWN-SENT state.
*/
return sctp_sf_shutdown_sent_abort(ep, asoc, type, arg, commands);
}
#if 0
/*
* Handle a Stale COOKIE Error
......@@ -1540,11 +1565,8 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const sctp_endpoint_t *ep,
void *arg,
sctp_cmd_seq_t *commands)
{
/* Check the verification tag. */
/* BUG: WRITE ME. */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
/* BUG? This does not look complete... */
return SCTP_DISPOSITION_ABORT;
......@@ -1561,15 +1583,19 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const sctp_endpoint_t *ep,
void *arg,
sctp_cmd_seq_t *commands)
{
/* Check the verification tag. */
/* BUG: WRITE ME. */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands,SCTP_CMD_INIT_FAILED, SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB;
/* BUG? This does not look complete... */
return SCTP_DISPOSITION_ABORT;
}
/*
......@@ -1589,67 +1615,6 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const sctp_endpoint_t *ep,
return sctp_sf_cookie_wait_abort(ep, asoc, type, arg, commands);
}
#if 0
/*
* Handle a shutdown timeout or INIT during a shutdown phase.
*
* Section: 9.2
* If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk
* (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination
* transport addresses (either in the IP addresses or in the INIT chunk)
* that belong to this association, it should discard the INIT chunk and
* retransmit the SHUTDOWN ACK chunk.
*...
* While in SHUTDOWN-SENT state ... If the timer expires, the endpoint
* must re-send the SHUTDOWN ACK.
*
* Verification Tag: Neither the INIT nor the timeout will have a
* valid verification tag, so it is safe to ignore.
*
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t sctp_do_9_2_reshutack(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_chunk_t *chunk = arg;
/* If this was a timeout (not an INIT), then do the counter
* work. We might need to just dump the association.
*/
if (!chunk) {
if (1 + asoc->counters[SctpCounterRetran] >
asoc->maxRetrans) {
sctp_add_cmd(commands, SCTP_CMD_DELETE_TCB,
SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB;
}
retval->counters[0] = SCTP_COUNTER_INCR;
retval->counters[0] = SctpCounterRetran;
retval->counters[1] = 0;
retval->counters[1] = 0;
}
reply = sctp_make_shutdown_ack(asoc, chunk);
if (!reply)
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
return SCTP_DISPOSITION_CONSUME;
nomem:
return SCTP_DISPOSITION_NOMEM;
}
#endif /* 0 */
/*
* sctp_sf_do_9_2_shut
*
......@@ -1694,7 +1659,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep,
sctp_disposition_t disposition;
/* Convert the elaborate header. */
sdh = (sctp_shutdownhdr_t *) chunk->skb->data;
sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
chunk->subh.shutdown_hdr = sdh;
......@@ -1718,8 +1683,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep,
disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outqueue_is_empty(&asoc->outqueue)) {
disposition =
sctp_sf_do_9_2_shutdown_ack(ep, asoc, type,
disposition = sctp_sf_do_9_2_shutdown_ack(ep, asoc, type,
arg, commands);
}
......@@ -1732,6 +1696,42 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep,
return disposition;
}
/* RFC 2960 9.2
* If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk
* (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination
* transport addresses (either in the IP addresses or in the INIT chunk)
* that belong to this association, it should discard the INIT chunk and
* retransmit the SHUTDOWN ACK chunk.
*/
sctp_disposition_t sctp_sf_do_9_2_reshutack(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_chunk_t *chunk = (sctp_chunk_t *) arg;
sctp_chunk_t *reply;
reply = sctp_make_shutdown_ack(asoc, chunk);
if (NULL == reply)
goto nomem;
/* Set the transport for the SHUTDOWN ACK chunk and the timeout for
* the T2-SHUTDOWN timer.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply));
/* and restart the T2-shutdown timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
return SCTP_DISPOSITION_CONSUME;
nomem:
return SCTP_DISPOSITION_NOMEM;
}
/*
* sctp_sf_do_ecn_cwr
*
......@@ -1979,9 +1979,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
}
......@@ -2185,9 +2183,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep,
* processing the rest of the chunks in the packet.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
}
......@@ -2296,14 +2292,12 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const sctp_endpoint_t *ep,
*/
if (TSN_lt(ctsn, asoc->ctsn_ack_point)) {
SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn);
SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n",
asoc->ctsn_ack_point);
SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point);
return SCTP_DISPOSITION_DISCARD;
}
/* Return this SACK for further processing. */
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,
SCTP_SACKH(sackh));
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh));
/* Note: We do the rest of the work on the PROCESS_SACK
* sideeffect.
......@@ -2410,7 +2404,8 @@ sctp_disposition_t sctp_sf_operr_notify(const sctp_endpoint_t *ep,
sctp_ulpevent_t *ev;
while (chunk->chunk_end > chunk->skb->data) {
ev = sctp_ulpevent_make_remote_error(asoc,chunk,0, GFP_ATOMIC);
ev = sctp_ulpevent_make_remote_error(asoc, chunk, 0,
GFP_ATOMIC);
if (!ev)
goto nomem;
......@@ -2464,6 +2459,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
/* ...send a SHUTDOWN COMPLETE chunk to its peer, */
reply = sctp_make_shutdown_complete(asoc, chunk);
if (!reply)
......@@ -2616,6 +2614,148 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const sctp_endpoint_t *ep,
nomem:
return SCTP_DISPOSITION_NOMEM;
}
/*
* Process an unknown chunk.
*
* Section: 3.2. Also, 2.1 in the implementor's guide.
*
* Chunk Types are encoded such that the highest-order two bits specify
* the action that must be taken if the processing endpoint does not
* recognize the Chunk Type.
*
* 00 - Stop processing this SCTP packet and discard it, do not process
* any further chunks within it.
*
* 01 - Stop processing this SCTP packet and discard it, do not process
* any further chunks within it, and report the unrecognized
* chunk in an 'Unrecognized Chunk Type'.
*
* 10 - Skip this chunk and continue processing.
*
* 11 - Skip this chunk and continue processing, but report in an ERROR
* Chunk using the 'Unrecognized Chunk Type' cause of error.
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t sctp_sf_unk_chunk(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_chunk_t *unk_chunk = arg;
sctp_chunk_t *err_chunk;
sctp_chunkhdr_t *hdr;
SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk);
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet.
*/
if (ntohl(unk_chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
switch (type.chunk & SCTP_CID_ACTION_MASK) {
case SCTP_CID_ACTION_DISCARD:
/* Discard the packet. */
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
break;
case SCTP_CID_ACTION_DISCARD_ERR:
/* Discard the packet. */
sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* Generate an ERROR chunk as response. */
hdr = unk_chunk->chunk_hdr;
err_chunk = sctp_make_op_error(asoc, unk_chunk,
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
WORD_ROUND(ntohs(hdr->length)));
if (err_chunk) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err_chunk));
}
return SCTP_DISPOSITION_CONSUME;
break;
case SCTP_CID_ACTION_SKIP:
/* Skip the chunk. */
return SCTP_DISPOSITION_DISCARD;
break;
case SCTP_CID_ACTION_SKIP_ERR:
/* Generate an ERROR chunk as response. */
hdr = unk_chunk->chunk_hdr;
err_chunk = sctp_make_op_error(asoc, unk_chunk,
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
WORD_ROUND(ntohs(hdr->length)));
if (err_chunk) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err_chunk));
}
/* Skip the chunk. */
return SCTP_DISPOSITION_CONSUME;
break;
default:
break;
}
return SCTP_DISPOSITION_DISCARD;
}
/*
* Discard the chunk.
*
* Section: 0.2, 5.2.3, 5.2.5, 5.2.6, 6.0, 8.4.6, 8.5.1c, 9.2
* [Too numerous to mention...]
* Verification Tag: No verification needed.
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t sctp_sf_discard_chunk(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk);
return SCTP_DISPOSITION_DISCARD;
}
/*
* Discard the whole packet.
*
* Section: 8.4 2)
*
* 2) If the OOTB packet contains an ABORT chunk, the receiver MUST
* silently discard the OOTB packet and take no further action.
* Otherwise,
*
* Verification Tag: No verification necessary
*
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t
sctp_sf_pdiscard(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
}
#if 0
/*
......@@ -2976,10 +3116,16 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING));
/* sctpimpguide-05 Section 2.12.2
* The sender of the SHUTDOWN MAY also start an overall guard timer
* 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outqueue_is_empty(&asoc->outqueue)) {
disposition =
sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
arg, commands);
}
return disposition;
......@@ -3042,12 +3188,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(const sctp_endpoint_t *ep,
* TCB. This is a departure from our typical NOMEM handling.
*/
/* Change to CLOSED state. */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
return retval;
}
......@@ -3090,7 +3232,8 @@ sctp_disposition_t sctp_sf_error_shutdown(const sctp_endpoint_t *ep,
* Outputs
* (timers)
*/
sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(const sctp_endpoint_t *ep,
sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown(
const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
......@@ -3134,7 +3277,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown(
}
/*
* sctp_cookie_wait_prm_abort
* sctp_sf_cookie_wait_prm_abort
*
* Section: 4 Note: 2
* Verification Tag:
......@@ -3153,14 +3296,36 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(const sctp_endpoint_t *ep,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_chunk_t *abort;
sctp_disposition_t retval;
/* Stop T1-init timer */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands);
retval = SCTP_DISPOSITION_CONSUME;
/* Generate ABORT chunk to send the peer */
abort = sctp_make_abort(asoc, NULL, 0);
if (!abort)
retval = SCTP_DISPOSITION_NOMEM;
else
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
/* Even if we can't send the ABORT due to low memory delete the
* TCB. This is a departure from our typical NOMEM handling.
*/
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_NULL());
return retval;
}
/*
* sctp_cookie_echoed_prm_abort
* sctp_sf_cookie_echoed_prm_abort
*
* Section: 4 Note: 3
* Verification Tag:
......@@ -3185,6 +3350,87 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(const sctp_endpoint_t *ep,
return sctp_sf_cookie_wait_prm_abort(ep, asoc, type, arg, commands);
}
/*
* sctp_sf_shutdown_pending_prm_abort
*
* Inputs
* (endpoint, asoc)
*
* The RFC does not explicitly address this issue, but is the route through the
* state table when someone issues an abort while in SHUTDOWN-PENDING state.
*
* Outputs
* (timers)
*/
sctp_disposition_t sctp_sf_shutdown_pending_prm_abort(
const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands);
}
/*
* sctp_sf_shutdown_sent_prm_abort
*
* Inputs
* (endpoint, asoc)
*
* The RFC does not explicitly address this issue, but is the route through the
* state table when someone issues an abort while in SHUTDOWN-SENT state.
*
* Outputs
* (timers)
*/
sctp_disposition_t sctp_sf_shutdown_sent_prm_abort(
const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
/* Stop the T2-shutdown timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands);
}
/*
* sctp_sf_cookie_echoed_prm_abort
*
* Inputs
* (endpoint, asoc)
*
* The RFC does not explcitly address this issue, but is the route through the
* state table when someone issues an abort while in COOKIE_ECHOED state.
*
* Outputs
* (timers)
*/
sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort(
const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
/* The same T2 timer, so we should be able to use
* common function with the SHUTDOWN-SENT state.
*/
return sctp_sf_shutdown_sent_prm_abort(ep, asoc, type, arg, commands);
}
/*
* Ignore the primitive event
*
......@@ -3322,8 +3568,7 @@ sctp_disposition_t sctp_sf_ignore_other(const sctp_endpoint_t *ep,
void *arg,
sctp_cmd_seq_t *commands)
{
SCTP_DEBUG_PRINTK("The event other type %d is ignored\n",
type.other);
SCTP_DEBUG_PRINTK("The event other type %d is ignored\n", type.other);
return SCTP_DISPOSITION_DISCARD;
}
......@@ -3479,11 +3724,11 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep,
if (!repl)
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
/* Issue a sideeffect to do the needed accounting. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
SCTP_TO(timer));
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
} else {
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB;
......@@ -3559,6 +3804,34 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_NOMEM;
}
/* sctpimpguide-05 Section 2.12.2
* The sender of the SHUTDOWN MAY also start an overall guard timer
* 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
* At the expiration of this timer the sender SHOULD abort the association
* by sending an ABORT chunk.
*/
sctp_disposition_t sctp_sf_t5_timer_expire(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
sctp_chunk_t *reply = NULL;
SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
reply = sctp_make_abort(asoc, NULL, 0);
if (!reply)
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB;
nomem:
return SCTP_DISPOSITION_NOMEM;
}
/* Handle expiration of AUTOCLOSE timer. When the autoclose timer expires,
* the association is automatically closed by starting the shutdown process.
* The work that needs to be done is same as when SHUTDOWN is initiated by
......@@ -3583,10 +3856,15 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING));
/* sctpimpguide-05 Section 2.12.2
* The sender of the SHUTDOWN MAY also start an overall guard timer
* 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outqueue_is_empty(&asoc->outqueue)) {
disposition =
sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
arg, commands);
}
return disposition;
......@@ -3651,30 +3929,6 @@ sctp_disposition_t sctp_sf_timer_ignore(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_CONSUME;
}
/*
* Discard the chunk.
*
* Section: 0.2, 5.2.3, 5.2.5, 5.2.6, 6.0, 8.4.6, 8.5.1c, 9.2
* [Too numerous to mention...]
* Verification Tag: No verification needed.
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t sctp_sf_discard_chunk(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk);
return SCTP_DISPOSITION_DISCARD;
}
/********************************************************************
* 2nd Level Abstractions
********************************************************************/
......
......@@ -48,9 +48,10 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
sctp_sm_table_entry_t nop = {fn: sctp_sf_discard_chunk,
name: "sctp_sf_discard_chunk"};
sctp_sm_table_entry_t bug = {fn: sctp_sf_bug, name: "sctp_sf_bug"};
sctp_sm_table_entry_t bug = {
.fn = sctp_sf_bug,
.name = "sctp_sf_bug"
};
#define DO_LOOKUP(_max, _type, _table) \
if ((event_subtype._type > (_max))) { \
......@@ -58,9 +59,9 @@ sctp_sm_table_entry_t bug = {fn: sctp_sf_bug, name: "sctp_sf_bug"};
"sctp table %p possible attack:" \
" event %d exceeds max %d\n", \
_table, event_subtype._type, _max); \
return(&bug); \
return &bug; \
} \
return(&_table[event_subtype._type][(int)state]);
return &_table[event_subtype._type][(int)state];
sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
sctp_state_t state,
......@@ -92,320 +93,323 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
#define TYPE_SCTP_DATA { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_tabort_8_4_8, name: "sctp_sf_tabort_8_4_8"}, \
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_eat_data_6_2, name: "sctp_sf_eat_data_6_2"}, \
{.fn = sctp_sf_eat_data_6_2, .name = "sctp_sf_eat_data_6_2"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_eat_data_6_2, name: "sctp_sf_eat_data_6_2"}, \
{.fn = sctp_sf_eat_data_6_2, .name = "sctp_sf_eat_data_6_2"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_eat_data_fast_4_4, name: "sctp_sf_eat_data_fast_4_4"}, \
{.fn = sctp_sf_eat_data_fast_4_4, .name = "sctp_sf_eat_data_fast_4_4"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_DATA */
#define TYPE_SCTP_INIT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_do_5_1B_init, name: "sctp_sf_do_5_1B_init"}, \
{.fn = sctp_sf_do_5_1B_init, .name = "sctp_sf_do_5_1B_init"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_do_5_2_1_siminit, name: "sctp_sf_do_5_2_1_siminit"}, \
{.fn = sctp_sf_do_5_2_1_siminit, .name = "sctp_sf_do_5_2_1_siminit"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_do_5_2_1_siminit, name: "sctp_sf_do_5_2_1_siminit"}, \
{.fn = sctp_sf_do_5_2_1_siminit, .name = "sctp_sf_do_5_2_1_siminit"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_5_2_2_dupinit, name: "sctp_sf_do_5_2_2_dupinit"}, \
{.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_5_2_2_dupinit, name: "sctp_sf_do_5_2_2_dupinit"}, \
{.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_5_2_2_dupinit, name: "sctp_sf_do_5_2_2_dupinit"}, \
{.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_5_2_2_dupinit, name: "sctp_sf_do_5_2_2_dupinit"}, \
{.fn = sctp_sf_do_5_2_2_dupinit, .name = "sctp_sf_do_5_2_2_dupinit"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_do_9_2_reshutack, .name = "sctp_sf_do_9_2_reshutack"}, \
} /* TYPE_SCTP_INIT */
#define TYPE_SCTP_INIT_ACK { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_do_5_1C_ack, name: "sctp_sf_do_5_1C_ack"}, \
{.fn = sctp_sf_do_5_1C_ack, .name = "sctp_sf_do_5_1C_ack"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_INIT_ACK */
#define TYPE_SCTP_SACK { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_tabort_8_4_8, name: "sctp_sf_tabort_8_4_8"}, \
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_eat_sack_6_2, name: "sctp_sf_eat_sack_6_2"}, \
{.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_eat_sack_6_2, name: "sctp_sf_eat_sack_6_2"}, \
{.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_eat_sack_6_2, name: "sctp_sf_eat_sack_6_2"}, \
{.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_eat_sack_6_2, name: "sctp_sf_eat_sack_6_2"}, \
{.fn = sctp_sf_eat_sack_6_2, .name = "sctp_sf_eat_sack_6_2"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_SACK */
#define TYPE_SCTP_HEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_tabort_8_4_8, name: "sctp_sf_tabort_8_4_8"}, \
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_beat_8_3, name: "sctp_sf_beat_8_3"}, \
{.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_beat_8_3, name: "sctp_sf_beat_8_3"}, \
{.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_beat_8_3, name: "sctp_sf_beat_8_3"}, \
{.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_beat_8_3, name: "sctp_sf_beat_8_3"}, \
{.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_beat_8_3, name: "sctp_sf_beat_8_3"}, \
{.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
/* This should not happen, but we are nice. */ \
{fn: sctp_sf_beat_8_3, name: "sctp_sf_beat_8_3"}, \
{.fn = sctp_sf_beat_8_3, .name = "sctp_sf_beat_8_3"}, \
} /* TYPE_SCTP_HEARTBEAT */
#define TYPE_SCTP_HEARTBEAT_ACK { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_tabort_8_4_8, name: "sctp_sf_tabort_8_4_8"}, \
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \
{.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_backbeat_8_3, name: "sctp_sf_backbeat_8_3"}, \
{.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_backbeat_8_3, name: "sctp_sf_backbeat_8_3"}, \
{.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_backbeat_8_3, name: "sctp_sf_backbeat_8_3"}, \
{.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_backbeat_8_3, name: "sctp_sf_backbeat_8_3"}, \
{.fn = sctp_sf_backbeat_8_3, .name = "sctp_sf_backbeat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_HEARTBEAT_ACK */
#define TYPE_SCTP_ABORT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_pdiscard, name: "sctp_sf_pdiscard"}, \
{.fn = sctp_sf_pdiscard, .name = "sctp_sf_pdiscard"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_cookie_wait_abort, name: "sctp_sf_cookie_wait_abort"}, \
{.fn = sctp_sf_cookie_wait_abort, .name = "sctp_sf_cookie_wait_abort"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_cookie_echoed_abort, \
name: "sctp_sf_cookie_echoed_abort"}, \
{.fn = sctp_sf_cookie_echoed_abort, \
.name = "sctp_sf_cookie_echoed_abort"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_9_1_abort, name: "sctp_sf_do_9_1_abort"}, \
{.fn = sctp_sf_do_9_1_abort, .name = "sctp_sf_do_9_1_abort"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_9_1_abort, name: "sctp_sf_do_9_1_abort"}, \
{.fn = sctp_sf_shutdown_pending_abort, \
.name = "sctp_sf_shutdown_pending_abort"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_9_1_abort, name: "sctp_sf_do_9_1_abort"}, \
{.fn = sctp_sf_shutdown_sent_abort, \
.name = "sctp_sf_shutdown_sent_abort"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_9_1_abort, name: "sctp_sf_do_9_1_abort"}, \
{.fn = sctp_sf_do_9_1_abort, .name = "sctp_sf_do_9_1_abort"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_do_9_1_abort, name: "sctp_sf_do_9_1_abort"}, \
{.fn = sctp_sf_shutdown_ack_sent_abort, \
.name = "sctp_sf_shutdown_ack_sent_abort"}, \
} /* TYPE_SCTP_ABORT */
#define TYPE_SCTP_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_tabort_8_4_8, name: "sctp_sf_tabort_8_4_8"}, \
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_9_2_shutdown, name: "sctp_sf_do_9_2_shutdown"}, \
{.fn = sctp_sf_do_9_2_shutdown, .name = "sctp_sf_do_9_2_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_9_2_shutdown_ack, \
name: "sctp_sf_do_9_2_shutdown_ack"}, \
{.fn = sctp_sf_do_9_2_shutdown_ack, \
.name = "sctp_sf_do_9_2_shutdown_ack"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_SHUTDOWN */
#define TYPE_SCTP_SHUTDOWN_ACK { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \
{.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \
{.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_9_2_final, name: "sctp_sf_do_9_2_final"}, \
{.fn = sctp_sf_do_9_2_final, .name = "sctp_sf_do_9_2_final"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \
{.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_do_9_2_final, name: "sctp_sf_do_9_2_final"}, \
{.fn = sctp_sf_do_9_2_final, .name = "sctp_sf_do_9_2_final"}, \
} /* TYPE_SCTP_SHUTDOWN_ACK */
#define TYPE_SCTP_ERROR { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_tabort_8_4_8, name: "sctp_sf_tabort_8_4_8"}, \
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_operr_notify, name: "sctp_sf_operr_notify"}, \
{.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_ERROR */
#define TYPE_SCTP_COOKIE_ECHO { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_do_5_1D_ce, name: "sctp_sf_do_5_1D_ce"}, \
{.fn = sctp_sf_do_5_1D_ce, .name = "sctp_sf_do_5_1D_ce"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_do_5_2_4_dupcook, name: "sctp_sf_do_5_2_4_dupcook"}, \
{.fn = sctp_sf_do_5_2_4_dupcook, .name = "sctp_sf_do_5_2_4_dupcook"}, \
} /* TYPE_SCTP_COOKIE_ECHO */
#define TYPE_SCTP_COOKIE_ACK { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_do_5_1E_ca, name: "sctp_sf_do_5_1E_ca"}, \
{.fn = sctp_sf_do_5_1E_ca, .name = "sctp_sf_do_5_1E_ca"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_COOKIE_ACK */
#define TYPE_SCTP_ECN_ECNE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_do_ecne, name: "sctp_sf_do_ecne"}, \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_ecne, name: "sctp_sf_do_ecne"}, \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_ecne, name: "sctp_sf_do_ecne"}, \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_ecne, name: "sctp_sf_do_ecne"}, \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_ecne, name: "sctp_sf_do_ecne"}, \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
} /* TYPE_SCTP_ECN_ECNE */
#define TYPE_SCTP_ECN_CWR { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_ecn_cwr, name: "sctp_sf_do_ecn_cwr"}, \
{.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_ecn_cwr, name: "sctp_sf_do_ecn_cwr"}, \
{.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_ecn_cwr, name: "sctp_sf_do_ecn_cwr"}, \
{.fn = sctp_sf_do_ecn_cwr, .name = "sctp_sf_do_ecn_cwr"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
} /* TYPE_SCTP_ECN_CWR */
#define TYPE_SCTP_SHUTDOWN_COMPLETE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"}, \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_do_4_C, name: "sctp_sf_do_4_C"}, \
{.fn = sctp_sf_do_4_C, .name = "sctp_sf_do_4_C"}, \
} /* TYPE_SCTP_SHUTDOWN_COMPLETE */
/* The primary index for this table is the chunk type.
......@@ -434,397 +438,415 @@ sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NU
static sctp_sm_table_entry_t
chunk_event_table_asconf[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_CLOSED */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_COOKIE_WAIT */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_COOKIE_ECHOED */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_ESTABLISHED */
{fn: sctp_sf_discard_chunk,
name: "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"},
{.fn = sctp_sf_discard_chunk,
.name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"},
/* SCTP_STATE_SHUTDOWN_PENDING */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_SHUTDOWN_SENT */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_SHUTDOWN_RECEIVED */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
}; /* chunk asconf */
static sctp_sm_table_entry_t
chunk_event_table_asconf_ack[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_CLOSED */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_COOKIE_WAIT */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_COOKIE_ECHOED */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_ESTABLISHED */
{fn: sctp_sf_discard_chunk,
name: "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"},
{.fn = sctp_sf_discard_chunk,
.name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"},
/* SCTP_STATE_SHUTDOWN_PENDING */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_SHUTDOWN_SENT */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_SHUTDOWN_RECEIVED */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
{fn: sctp_sf_discard_chunk, name: "sctp_sf_discard_chunk"},
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"},
}; /* chunk asconf_ack */
static sctp_sm_table_entry_t
chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"},
/* SCTP_STATE_CLOSED */
{.fn = sctp_sf_tabort_8_4_8, .name = "sctp_sf_tabort_8_4_8"},
/* SCTP_STATE_COOKIE_WAIT */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
/* SCTP_STATE_COOKIE_ECHOED */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
/* SCTP_STATE_ESTABLISHED */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
/* SCTP_STATE_SHUTDOWN_PENDING */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
/* SCTP_STATE_SHUTDOWN_SENT */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
/* SCTP_STATE_SHUTDOWN_RECEIVED */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
/* SCTP_STATE_SHUTDOWN_ACK_SENT */
{.fn = sctp_sf_unk_chunk, .name = "sctp_sf_unk_chunk"},
}; /* chunk unknown */
#define TYPE_SCTP_PRIMITIVE_INITIALIZE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_INITIALIZE */
#define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_do_prm_asoc, name: "sctp_sf_do_prm_asoc"}, \
{.fn = sctp_sf_do_prm_asoc, .name = "sctp_sf_do_prm_asoc"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */
#define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_error_closed, name: "sctp_sf_error_closed"}, \
{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_cookie_wait_prm_shutdown, \
name: "sctp_sf_cookie_wait_prm_shutdown"}, \
{.fn = sctp_sf_cookie_wait_prm_shutdown, \
.name = "sctp_sf_cookie_wait_prm_shutdown"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_cookie_echoed_prm_shutdown, \
{.fn = sctp_sf_cookie_echoed_prm_shutdown, \
name:"sctp_sf_cookie_echoed_prm_shutdown"},\
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_9_2_prm_shutdown, \
name: "sctp_sf_do_9_2_prm_shutdown"}, \
{.fn = sctp_sf_do_9_2_prm_shutdown, \
.name = "sctp_sf_do_9_2_prm_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_ignore_primitive, name: "sctp_sf_ignore_primitive"}, \
{.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_ignore_primitive, name: "sctp_sf_ignore_primitive"}, \
{.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_ignore_primitive, name: "sctp_sf_ignore_primitive"}, \
{.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_ignore_primitive, name: "sctp_sf_ignore_primitive"}, \
{.fn = sctp_sf_ignore_primitive, .name = "sctp_sf_ignore_primitive"}, \
} /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */
#define TYPE_SCTP_PRIMITIVE_ABORT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_error_closed, name: "sctp_sf_error_closed"}, \
{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_cookie_wait_prm_abort, \
name: "sctp_sf_cookie_wait_prm_abort"}, \
{.fn = sctp_sf_cookie_wait_prm_abort, \
.name = "sctp_sf_cookie_wait_prm_abort"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_cookie_echoed_prm_abort, \
name: "sctp_sf_cookie_echoed_prm_abort"}, \
{.fn = sctp_sf_cookie_echoed_prm_abort, \
.name = "sctp_sf_cookie_echoed_prm_abort"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \
{.fn = sctp_sf_do_9_1_prm_abort, \
.name = "sctp_sf_do_9_1_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \
{.fn = sctp_sf_shutdown_pending_prm_abort, \
.name = "sctp_sf_shutdown_pending_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \
{.fn = sctp_sf_shutdown_sent_prm_abort, \
.name = "sctp_sf_shutdown_sent_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \
{.fn = sctp_sf_do_9_1_prm_abort, \
.name = "sctp_sf_do_9_1_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \
{.fn = sctp_sf_shutdown_ack_sent_prm_abort, \
.name = "sctp_sf_shutdown_ack_sent_prm_abort"}, \
} /* TYPE_SCTP_PRIMITIVE_ABORT */
#define TYPE_SCTP_PRIMITIVE_SEND { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_error_closed, name: "sctp_sf_error_closed"}, \
{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_do_prm_send, name: "sctp_sf_do_prm_send"}, \
{.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_do_prm_send, name: "sctp_sf_do_prm_send"}, \
{.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_prm_send, name: "sctp_sf_do_prm_send"}, \
{.fn = sctp_sf_do_prm_send, .name = "sctp_sf_do_prm_send"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_error_shutdown, name: "sctp_sf_error_shutdown"}, \
{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_error_shutdown, name: "sctp_sf_error_shutdown"}, \
{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_error_shutdown, name: "sctp_sf_error_shutdown"}, \
{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_error_shutdown, name: "sctp_sf_error_shutdown"}, \
{.fn = sctp_sf_error_shutdown, .name = "sctp_sf_error_shutdown"}, \
} /* TYPE_SCTP_PRIMITIVE_SEND */
#define TYPE_SCTP_PRIMITIVE_SETPRIMARY { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_SETPRIMARY */
#define TYPE_SCTP_PRIMITIVE_RECEIVE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_RECEIVE */
#define TYPE_SCTP_PRIMITIVE_STATUS { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_STATUS */
#define TYPE_SCTP_PRIMITIVE_CHANGEHEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_CHANGEHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_GETSRTTREPORT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_GETSRTTREPORT */
#define TYPE_SCTP_PRIMITIVE_SETFAILURETHRESHOLD { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_SETFAILURETHRESHOLD */
#define TYPE_SCTP_PRIMITIVE_SETPROTOPARAMETERS { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_SETPROTOPARAMETERS */
#define TYPE_SCTP_PRIMITIVE_RECEIVE_UNSENT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_RECEIVE_UNSENT */
#define TYPE_SCTP_PRIMITIVE_RECEIVE_UNACKED { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_RECEIVE_UNACKED */
#define TYPE_SCTP_PRIMITIVE_DESTROY { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
} /* TYPE_SCTP_PRIMITIVE_DESTROY */
/* The primary index for this table is the primitive type.
......@@ -851,46 +873,46 @@ sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE
#define TYPE_SCTP_OTHER_NO_PENDING_TSN { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_ignore_other, name: "sctp_sf_ignore_other"}, \
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_ignore_other, name: "sctp_sf_ignore_other"}, \
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_ignore_other, name: "sctp_sf_ignore_other"}, \
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_ignore_other, name: "sctp_sf_ignore_other"}, \
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_9_2_start_shutdown, \
name: "sctp_do_9_2_start_shutdown"}, \
{.fn = sctp_sf_do_9_2_start_shutdown, \
.name = "sctp_do_9_2_start_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_ignore_other, name: "sctp_sf_ignore_other"}, \
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_9_2_shutdown_ack, \
name: "sctp_sf_do_9_2_shutdown_ack"}, \
{.fn = sctp_sf_do_9_2_shutdown_ack, \
.name = "sctp_sf_do_9_2_shutdown_ack"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_ignore_other, name: "sctp_sf_ignore_other"}, \
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
}
#define TYPE_SCTP_OTHER_ICMP_UNREACHFRAG { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
}
sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
......@@ -900,213 +922,234 @@ sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STA
#define TYPE_SCTP_EVENT_TIMEOUT_NONE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_t1_timer_expire, name: "sctp_sf_t1_timer_expire"}, \
{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_t1_timer_expire, name: "sctp_sf_t1_timer_expire"}, \
{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_t2_timer_expire, name: "sctp_sf_t2_timer_expire"}, \
{.fn = sctp_sf_t2_timer_expire, .name = "sctp_sf_t2_timer_expire"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_t2_timer_expire, name: "sctp_sf_t2_timer_expire"}, \
{.fn = sctp_sf_t2_timer_expire, .name = "sctp_sf_t2_timer_expire"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_do_6_3_3_rtx, name: "sctp_sf_do_6_3_3_rtx"}, \
{.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_6_3_3_rtx, name: "sctp_sf_do_6_3_3_rtx"}, \
{.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_6_3_3_rtx, name: "sctp_sf_do_6_3_3_rtx"}, \
{.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_6_3_3_rtx, name: "sctp_sf_do_6_3_3_rtx"}, \
{.fn = sctp_sf_do_6_3_3_rtx, .name = "sctp_sf_do_6_3_3_rtx"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \
/* SCTP_STATE_EMPTY */ \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_sendbeat_8_3, name: "sctp_sf_sendbeat_8_3"}, \
{.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_sendbeat_8_3, name: "sctp_sf_sendbeat_8_3"}, \
{.fn = sctp_sf_sendbeat_8_3, .name = "sctp_sf_sendbeat_8_3"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_SACK { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_6_2_sack, name: "sctp_sf_do_6_2_sack"}, \
{.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_6_2_sack, name: "sctp_sf_do_6_2_sack"}, \
{.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_6_2_sack, name: "sctp_sf_do_6_2_sack"}, \
{.fn = sctp_sf_do_6_2_sack, .name = "sctp_sf_do_6_2_sack"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_autoclose_timer_expire, \
name: "sctp_sf_autoclose_timer_expire"}, \
{.fn = sctp_sf_autoclose_timer_expire, \
.name = "sctp_sf_autoclose_timer_expire"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_timer_ignore, name: "sctp_sf_timer_ignore"}, \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_PMTU_RAISE { \
/* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
}
sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
......@@ -1116,6 +1159,7 @@ sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM
TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
TYPE_SCTP_EVENT_TIMEOUT_T3_RTX,
TYPE_SCTP_EVENT_TIMEOUT_T4_RTO,
TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT,
TYPE_SCTP_EVENT_TIMEOUT_SACK,
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
......@@ -1125,12 +1169,11 @@ sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM
sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, sctp_state_t state)
{
if (state > SCTP_STATE_MAX)
BUG();
if (cid < 0)
return &nop;
return &bug;
if (cid <= SCTP_CID_BASE_MAX)
if (cid >= 0 && cid <= SCTP_CID_BASE_MAX) {
return &chunk_event_table[cid][state];
}
switch (cid) {
case SCTP_CID_ASCONF:
......@@ -1139,8 +1182,6 @@ sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, sctp_state_t stat
case SCTP_CID_ASCONF_ACK:
return &chunk_event_table_asconf_ack[state];
default:
return &nop;
};
return &nop;
return &chunk_event_table_unknown[state];
}
}
/* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp.
* Copyright (c) 2001-2002 Intel Corp.
* Copyright (c) 2001-2002 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
*
* This file is part of the SCTP kernel reference Implementation
......@@ -82,8 +82,6 @@ static void sctp_wfree(struct sk_buff *skb);
static int sctp_wait_for_sndbuf(sctp_association_t *asoc, long *timeo_p,
int msg_len);
static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p);
static inline void sctp_sk_memcpy_msgname(struct sock *sk, char * msgname,
int *addr_len, struct sk_buff *skb);
static inline void sctp_sk_addr_set(struct sock *,
const sockaddr_storage_t *newaddr,
sockaddr_storage_t *saveaddr);
......@@ -326,8 +324,8 @@ static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs,
SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, "
"flags: %s)\n", sk, addrs, addrcnt,
(BINDX_ADD_ADDR == flags)?"ADD":
((BINDX_REM_ADDR == flags)?"REM":"BOGUS"));
(BINDX_ADD_ADDR == flags) ? "ADD" :
((BINDX_REM_ADDR == flags) ? "REM" : "BOGUS"));
switch (flags) {
case BINDX_ADD_ADDR:
......@@ -500,9 +498,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
case AF_INET:
saveaddr = *((sockaddr_storage_t *)
&addrs[cnt]);
saveaddr.v4.sin_port =
ntohs(saveaddr.v4.sin_port);
/* verify the port */
saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
/* Verify the port. */
if (saveaddr.v4.sin_port != bp->port) {
retval = -EINVAL;
goto err_bindx_rem;
......@@ -606,7 +603,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
*
* Returns 0 if ok, <0 errno code on error.
*/
static int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr_storage *addrs,
static int sctp_setsockopt_bindx(struct sock* sk,
struct sockaddr_storage *addrs,
int addrssize, int op)
{
struct sockaddr_storage *kaddrs;
......@@ -614,8 +612,7 @@ static int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr_storage *addrs
size_t addrcnt;
SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p"
" addrssize %d opt %d\n", sk, addrs,
addrssize, op);
" addrssize %d opt %d\n", sk, addrs, addrssize, op);
/* Do we have an integer number of structs sockaddr_storage? */
if (unlikely(addrssize <= 0 ||
......@@ -851,7 +848,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
goto out_unlock;
}
if (sinfo_flags & MSG_ABORT) {
SCTP_DEBUG_PRINTK("Aborting association: %p\n",asoc);
SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
sctp_primitive_ABORT(asoc, NULL);
err = 0;
goto out_unlock;
......@@ -866,8 +863,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
* either the default or the user specified stream counts.
*/
if (sinfo) {
if (!sinit ||
(sinit && !sinit->sinit_num_ostreams)) {
if (!sinit || (sinit && !sinit->sinit_num_ostreams)) {
/* Check against the defaults. */
if (sinfo->sinfo_stream >=
sp->initmsg.sinit_num_ostreams) {
......@@ -1096,12 +1092,13 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
* flags - flags sent or received with the user message, see Section
* 5 for complete description of the flags.
*/
static struct sk_buff * sctp_skb_recv_datagram(struct sock *, int, int, int *);
static struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
int noblock, int flags, int *addr_len)
{
sctp_ulpevent_t *event = NULL;
sctp_opt_t *sp = sctp_sk(sk);
struct sk_buff *skb;
int copied;
int err = 0;
......@@ -1147,19 +1144,16 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
sock_recv_timestamp(msg, sk, skb);
if (sctp_ulpevent_is_notification(event)) {
msg->msg_flags |= MSG_NOTIFICATION;
sp->pf->event_msgname(event, msg->msg_name, addr_len);
} else {
/* Copy the address. */
if (addr_len && msg->msg_name)
sctp_sk_memcpy_msgname(sk, msg->msg_name,
addr_len, skb);
sp->pf->skb_msgname(skb, msg->msg_name, addr_len);
}
/* Check if we allow SCTP_SNDRCVINFO. */
if (sctp_sk(sk)->subscribe.sctp_data_io_event)
if (sp->subscribe.sctp_data_io_event)
sctp_ulpevent_read_sndrcvinfo(event, msg);
#if 0
/* FIXME: we should be calling IP layer too. */
/* FIXME: we should be calling IP/IPv6 layers. */
if (sk->protinfo.af_inet.cmsg_flags)
ip_cmsg_recv(msg, skb);
#endif
......@@ -1176,7 +1170,8 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
return err;
}
static inline int sctp_setsockopt_disable_fragments(struct sock *sk, char *optval, int optlen)
static inline int sctp_setsockopt_disable_fragments(struct sock *sk,
char *optval, int optlen)
{
int val;
......@@ -1191,7 +1186,8 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk, char *optva
return 0;
}
static inline int sctp_setsockopt_set_events(struct sock *sk, char *optval, int optlen)
static inline int sctp_setsockopt_set_events(struct sock *sk, char *optval,
int optlen)
{
if (optlen != sizeof(struct sctp_event_subscribe))
return -EINVAL;
......@@ -1200,7 +1196,8 @@ static inline int sctp_setsockopt_set_events(struct sock *sk, char *optval, int
return 0;
}
static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval, int optlen)
static inline int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
int optlen)
{
sctp_opt_t *sp = sctp_sk(sk);
......@@ -1236,7 +1233,7 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
char *optval, int optlen)
{
int retval = 0;
char * tmp;
char *tmp;
sctp_protocol_t *proto = sctp_get_protocol();
struct list_head *pos;
sctp_func_t *af;
......@@ -1356,19 +1353,9 @@ static int sctp_init_sock(struct sock *sk)
proto = sctp_get_protocol();
/* Create a per socket endpoint structure. Even if we
* change the data structure relationships, this may still
* be useful for storing pre-connect address information.
*/
ep = sctp_endpoint_new(proto, sk, GFP_KERNEL);
if (!ep)
return -ENOMEM;
sp = sctp_sk(sk);
/* Initialize the SCTP per socket area. */
sp->ep = ep;
sp->type = SCTP_SOCKET_UDP;
/* FIXME: The next draft (04) of the SCTP Sockets Extensions
......@@ -1425,6 +1412,16 @@ static int sctp_init_sock(struct sock *sk)
* for UDP-style sockets only.
*/
sp->autoclose = 0;
sp->pf = sctp_get_pf_specific(sk->family);
/* Create a per socket endpoint structure. Even if we
* change the data structure relationships, this may still
* be useful for storing pre-connect address information.
*/
ep = sctp_endpoint_new(proto, sk, GFP_KERNEL);
if (NULL == ep)
return -ENOMEM;
sp->ep = ep;
SCTP_DBG_OBJCNT_INC(sock);
return 0;
......@@ -1836,8 +1833,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum)
case PF_INET6:
SCTP_V6(tmpaddr.v6.sin6_family = AF_INET6;
tmpaddr.v6.sin6_port = snum;
tmpaddr.v6.sin6_addr =
inet6_sk(sk)->rcv_saddr;
tmpaddr.v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
)
break;
......@@ -1855,7 +1851,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum)
* that this port/socket (sk) combination are already
* in an endpoint.
*/
for( ; sk2 != NULL; sk2 = sk2->bind_next) {
for ( ; sk2 != NULL; sk2 = sk2->bind_next) {
sctp_endpoint_t *ep2;
ep2 = sctp_sk(sk2)->ep;
......@@ -1887,7 +1883,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum)
* SO_REUSEADDR on this socket -sk-).
*/
if (pp->sk == NULL) {
pp->fastreuse = sk->reuse? 1 : 0;
pp->fastreuse = sk->reuse ? 1 : 0;
} else if (pp->fastreuse && sk->reuse == 0) {
pp->fastreuse = 0;
}
......@@ -2073,7 +2069,7 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
pp->sk = NULL;
if ((pp->next = head->chain) != NULL)
pp->next->pprev = &pp->next;
head->chain= pp;
head->chain = pp;
pp->pprev = &head->chain;
}
SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp);
......@@ -2433,41 +2429,6 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
return NULL;
}
/* Copy an approriately formatted address for msg_name. */
static inline void sctp_sk_memcpy_msgname(struct sock *sk, char * msgname,
int *addr_len, struct sk_buff *skb)
{
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6 __attribute__ ((unused));
struct sctphdr *sh;
/* The sockets layer handles copying this out to user space. */
switch (sk->family) {
case PF_INET:
sin = (struct sockaddr_in *)msgname;
if (addr_len)
*addr_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
sh = (struct sctphdr *) skb->h.raw;
sin->sin_port = sh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
break;
case PF_INET6:
SCTP_V6(
/* FIXME: Need v6 code here. We should convert
* V4 addresses to PF_INET6 format. See ipv6/udp.c
* for an example. --jgrimm
*/
);
break;
default: /* Should not get here. */
break;
};
}
static inline int sctp_sendmsg_verify_name(struct sock *sk, struct msghdr *msg)
{
sockaddr_storage_t *sa;
......
......@@ -46,9 +46,10 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static void sctp_rcvmsg_rfree(struct sk_buff *skb);
static void sctp_ulpevent_set_owner_r(struct sk_buff *skb,
sctp_association_t *asoc);
static void
sctp_ulpevent_set_owner(struct sk_buff *skb, const sctp_association_t *asoc);
/* Create a new sctp_ulpevent. */
sctp_ulpevent_t *sctp_ulpevent_new(int size, int msg_flags, int priority)
......@@ -123,14 +124,12 @@ sctp_ulpevent_t *sctp_ulpevent_make_assoc_change(const sctp_association_t *asoc,
struct sctp_assoc_change *sac;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION,
priority);
MSG_NOTIFICATION, priority);
if (!event)
goto fail;
sac = (struct sctp_assoc_change *)
skb_put(event->parent,
sizeof(struct sctp_assoc_change));
skb_put(event->parent, sizeof(struct sctp_assoc_change));
/* Socket Extensions for SCTP
* 5.3.1.1 SCTP_ASSOC_CHANGE
......@@ -199,6 +198,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_assoc_change(const sctp_association_t *asoc,
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner(event->parent, asoc);
sac->sac_assoc_id = sctp_assoc2id(asoc);
return event;
......@@ -227,14 +227,12 @@ sctp_ulpevent_t *sctp_ulpevent_make_peer_addr_change(
struct sctp_paddr_change *spc;
event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change),
MSG_NOTIFICATION,
priority);
MSG_NOTIFICATION, priority);
if (!event)
goto fail;
spc = (struct sctp_paddr_change *)
skb_put(event->parent,
sizeof(struct sctp_paddr_change));
skb_put(event->parent, sizeof(struct sctp_paddr_change));
/* Sockets API Extensions for SCTP
* Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE
......@@ -287,12 +285,13 @@ sctp_ulpevent_t *sctp_ulpevent_make_peer_addr_change(
/* Socket Extensions for SCTP
* 5.3.1.1 SCTP_ASSOC_CHANGE
*
* sac_assoc_id: sizeof (sctp_assoc_t)
* spc_assoc_id: sizeof (sctp_assoc_t)
*
* The association id field, holds the identifier for the association.
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner(event->parent, asoc);
spc->spc_assoc_id = sctp_assoc2id(asoc);
/* Sockets API Extensions for SCTP
......@@ -360,9 +359,8 @@ sctp_ulpevent_t *sctp_ulpevent_make_remote_error(const sctp_association_t *asoc,
/* Embed the event fields inside the cloned skb. */
event = (sctp_ulpevent_t *) skb->cb;
event = sctp_ulpevent_init(event,
skb,
MSG_NOTIFICATION);
event = sctp_ulpevent_init(event, skb, MSG_NOTIFICATION);
if (!event)
goto fail;
......@@ -418,6 +416,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_remote_error(const sctp_association_t *asoc,
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner(event->parent, asoc);
sre->sre_assoc_id = sctp_assoc2id(asoc);
return event;
......@@ -515,9 +514,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc,
* The original send information associated with the undelivered
* message.
*/
memcpy(&ssf->ssf_info,
&chunk->sinfo,
sizeof(struct sctp_sndrcvinfo));
memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo));
/* Socket Extensions for SCTP
* 5.3.1.4 SCTP_SEND_FAILED
......@@ -528,8 +525,8 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc,
* same association identifier. For TCP style socket, this field is
* ignored.
*/
sctp_ulpevent_set_owner(event->parent, asoc);
ssf->ssf_assoc_id = sctp_assoc2id(asoc);
return event;
fail:
......@@ -541,7 +538,8 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc,
* Socket Extensions for SCTP - draft-01
* 5.3.1.5 SCTP_SHUTDOWN_EVENT
*/
sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(const sctp_association_t *asoc,
sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(
const sctp_association_t *asoc,
__u16 flags,
int priority)
{
......@@ -549,14 +547,12 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(const sctp_association_t *aso
struct sctp_shutdown_event *sse;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION,
priority);
MSG_NOTIFICATION, priority);
if (!event)
goto fail;
sse = (struct sctp_shutdown_event *)
skb_put(event->parent,
sizeof(struct sctp_shutdown_event));
skb_put(event->parent, sizeof(struct sctp_shutdown_event));
/* Socket Extensions for SCTP
* 5.3.1.5 SCTP_SHUTDOWN_EVENT
......@@ -591,6 +587,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(const sctp_association_t *aso
* All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored.
*/
sctp_ulpevent_set_owner(event->parent, asoc);
sse->sse_assoc_id = sctp_assoc2id(asoc);
return event;
......@@ -607,8 +604,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(const sctp_association_t *aso
* 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
*/
sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
sctp_chunk_t *chunk,
int priority)
sctp_chunk_t *chunk, int priority)
{
sctp_ulpevent_t *event;
struct sctp_sndrcvinfo *info;
......@@ -818,23 +814,33 @@ static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *a
asoc->rwnd_over = skb->len - asoc->rwnd;
asoc->rwnd = 0;
}
SCTP_DEBUG_PRINTK("rwnd decreased by %d to (%u, %u)\n",
skb->len, asoc->rwnd, asoc->rwnd_over);
}
/* A simple destructor to give up the reference to the association. */
static void sctp_ulpevent_rfree(struct sk_buff *skb)
{
sctp_ulpevent_t *event;
event = (sctp_ulpevent_t *)skb->cb;
sctp_association_put(event->asoc);
}
/* Hold the association in case the msg_name needs read out of
* the association.
*/
static void sctp_ulpevent_set_owner(struct sk_buff *skb,
const sctp_association_t *asoc)
{
sctp_ulpevent_t *event;
/* Cast away the const, as we are just wanting to
* bump the reference count.
*/
sctp_association_hold((sctp_association_t *)asoc);
skb->sk = asoc->base.sk;
event = (sctp_ulpevent_t *)skb->cb;
event->asoc = (sctp_association_t *)asoc;
skb->destructor = sctp_ulpevent_rfree;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment