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 { ...@@ -112,6 +112,7 @@ typedef enum {
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
SCTP_EVENT_TIMEOUT_T3_RTX, SCTP_EVENT_TIMEOUT_T3_RTX,
SCTP_EVENT_TIMEOUT_T4_RTO, SCTP_EVENT_TIMEOUT_T4_RTO,
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
SCTP_EVENT_TIMEOUT_HEARTBEAT, SCTP_EVENT_TIMEOUT_HEARTBEAT,
SCTP_EVENT_TIMEOUT_SACK, SCTP_EVENT_TIMEOUT_SACK,
SCTP_EVENT_TIMEOUT_AUTOCLOSE, SCTP_EVENT_TIMEOUT_AUTOCLOSE,
......
...@@ -114,7 +114,8 @@ extern sctp_protocol_t sctp_proto; ...@@ -114,7 +114,8 @@ extern sctp_protocol_t sctp_proto;
extern struct sock *sctp_get_ctl_sock(void); extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *, extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *,
sctp_scope_t, int priority, int flags); 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 * sctp_socket.c
......
...@@ -107,6 +107,9 @@ sctp_state_fn_t sctp_sf_timer_ignore; ...@@ -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_do_9_1_abort;
sctp_state_fn_t sctp_sf_cookie_wait_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_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_1B_init;
sctp_state_fn_t sctp_sf_do_5_1C_ack; sctp_state_fn_t sctp_sf_do_5_1C_ack;
sctp_state_fn_t sctp_sf_do_5_1D_ce; sctp_state_fn_t sctp_sf_do_5_1D_ce;
...@@ -119,6 +122,7 @@ sctp_state_fn_t sctp_sf_tabort_8_4_8; ...@@ -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_operr_notify;
sctp_state_fn_t sctp_sf_t1_timer_expire; sctp_state_fn_t sctp_sf_t1_timer_expire;
sctp_state_fn_t sctp_sf_t2_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_sendbeat_8_3;
sctp_state_fn_t sctp_sf_beat_8_3; sctp_state_fn_t sctp_sf_beat_8_3;
sctp_state_fn_t sctp_sf_backbeat_8_3; sctp_state_fn_t sctp_sf_backbeat_8_3;
...@@ -134,6 +138,7 @@ sctp_state_fn_t sctp_sf_discard_chunk; ...@@ -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_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit; 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_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
/* Prototypes for primitive event state functions. */ /* Prototypes for primitive event state functions. */
sctp_state_fn_t sctp_sf_do_prm_asoc; sctp_state_fn_t sctp_sf_do_prm_asoc;
...@@ -144,6 +149,9 @@ sctp_state_fn_t sctp_sf_cookie_echoed_prm_shutdown; ...@@ -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_do_9_1_prm_abort;
sctp_state_fn_t sctp_sf_cookie_wait_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_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_closed;
sctp_state_fn_t sctp_sf_error_shutdown; sctp_state_fn_t sctp_sf_error_shutdown;
sctp_state_fn_t sctp_sf_ignore_primitive; sctp_state_fn_t sctp_sf_ignore_primitive;
......
...@@ -255,6 +255,12 @@ typedef struct sctp_func { ...@@ -255,6 +255,12 @@ typedef struct sctp_func {
sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address); 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. */ /* SCTP Socket type: UDP or TCP style. */
typedef enum { typedef enum {
SCTP_SOCKET_UDP = 0, SCTP_SOCKET_UDP = 0,
...@@ -280,6 +286,7 @@ struct sctp_opt { ...@@ -280,6 +286,7 @@ struct sctp_opt {
__u32 autoclose; __u32 autoclose;
__u8 nodelay; __u8 nodelay;
__u8 disable_fragments; __u8 disable_fragments;
sctp_pf_t *pf;
}; };
...@@ -845,6 +852,7 @@ int sctp_outqueue_set_output_handlers(sctp_outqueue_t *, ...@@ -845,6 +852,7 @@ int sctp_outqueue_set_output_handlers(sctp_outqueue_t *,
sctp_outqueue_ohandler_force_t force); sctp_outqueue_ohandler_force_t force);
void sctp_outqueue_restart(sctp_outqueue_t *); void sctp_outqueue_restart(sctp_outqueue_t *);
void sctp_retransmit(sctp_outqueue_t *, sctp_transport_t *, __u8); 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 */ /* These bind address data fields common between endpoints and associations */
...@@ -1128,6 +1136,11 @@ struct SCTP_association { ...@@ -1128,6 +1136,11 @@ struct SCTP_association {
*/ */
sctp_transport_t *primary_path; 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 /* active_path
* The path that we are currently using to * The path that we are currently using to
* transmit new data and most control chunks. * transmit new data and most control chunks.
...@@ -1183,7 +1196,7 @@ struct SCTP_association { ...@@ -1183,7 +1196,7 @@ struct SCTP_association {
int next_dup_tsn; int next_dup_tsn;
/* Do we need to sack the peer? */ /* Do we need to sack the peer? */
int sack_needed; uint8_t sack_needed;
/* These are capabilities which our peer advertised. */ /* These are capabilities which our peer advertised. */
__u8 ecn_capable; /* Can peer do ECN? */ __u8 ecn_capable; /* Can peer do ECN? */
......
...@@ -96,7 +96,7 @@ unsigned long update_adler32(unsigned long adler, ...@@ -96,7 +96,7 @@ unsigned long update_adler32(unsigned long adler,
* one subtract at the MOST, since buf[n] * one subtract at the MOST, since buf[n]
* is a max of 255. * is a max of 255.
*/ */
if(s1 >= BASE) if (s1 >= BASE)
s1 -= BASE; s1 -= BASE;
/* s2 = (s2 + s1) % BASE */ /* s2 = (s2 + s1) % BASE */
......
...@@ -66,7 +66,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc); ...@@ -66,7 +66,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc);
/* Allocate and initialize a new association */ /* Allocate and initialize a new association */
sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep, sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep,
const struct sock *sk, const struct sock *sk,
sctp_scope_t scope, int priority) sctp_scope_t scope, int priority)
{ {
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -91,7 +91,7 @@ sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep, ...@@ -91,7 +91,7 @@ sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep,
/* Intialize a new association from provided memory. */ /* Intialize a new association from provided memory. */
sctp_association_t *sctp_association_init(sctp_association_t *asoc, sctp_association_t *sctp_association_init(sctp_association_t *asoc,
const sctp_endpoint_t *ep, const sctp_endpoint_t *ep,
const struct sock *sk, const struct sock *sk,
sctp_scope_t scope, sctp_scope_t scope,
int priority) int priority)
...@@ -109,19 +109,19 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -109,19 +109,19 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->ep = (sctp_endpoint_t *)ep; asoc->ep = (sctp_endpoint_t *)ep;
sctp_endpoint_hold(asoc->ep); sctp_endpoint_hold(asoc->ep);
/* Hold the sock. */ /* Hold the sock. */
asoc->base.sk = (struct sock *)sk; asoc->base.sk = (struct sock *)sk;
sock_hold(asoc->base.sk); sock_hold(asoc->base.sk);
/* Initialize the common base substructure. */ /* Initialize the common base substructure. */
asoc->base.type = SCTP_EP_TYPE_ASSOCIATION; asoc->base.type = SCTP_EP_TYPE_ASSOCIATION;
/* Initialize the object handling fields. */ /* Initialize the object handling fields. */
atomic_set(&asoc->base.refcnt, 1); atomic_set(&asoc->base.refcnt, 1);
asoc->base.dead = 0; asoc->base.dead = 0;
asoc->base.malloced = 0; asoc->base.malloced = 0;
/* Initialize the bind addr area. */ /* Initialize the bind addr area. */
sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port); sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
asoc->base.addr_lock = RW_LOCK_UNLOCKED; asoc->base.addr_lock = RW_LOCK_UNLOCKED;
...@@ -135,7 +135,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -135,7 +135,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->pmtu = 0; asoc->pmtu = 0;
asoc->frag_point = 0; asoc->frag_point = 0;
/* Initialize the default association max_retrans and RTO values. */ /* Initialize the default association max_retrans and RTO values. */
asoc->max_retrans = ep->proto->max_retrans_association; asoc->max_retrans = ep->proto->max_retrans_association;
asoc->rto_initial = ep->proto->rto_initial; asoc->rto_initial = ep->proto->rto_initial;
asoc->rto_max = ep->proto->rto_max; asoc->rto_max = ep->proto->rto_max;
...@@ -288,7 +288,6 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -288,7 +288,6 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
return NULL; return NULL;
} }
/* Free this association if possible. There may still be users, so /* Free this association if possible. There may still be users, so
* the actual deallocation may be delayed. * the actual deallocation may be delayed.
*/ */
...@@ -330,6 +329,11 @@ void sctp_association_free(sctp_association_t *asoc) ...@@ -330,6 +329,11 @@ void sctp_association_free(sctp_association_t *asoc)
sctp_association_put(asoc); sctp_association_put(asoc);
} }
/* Free peer's cached cookie. */
if (asoc->peer.cookie) {
kfree(asoc->peer.cookie);
}
/* Release the transport structures. */ /* Release the transport structures. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, sctp_transport_t, transports); transport = list_entry(pos, sctp_transport_t, transports);
...@@ -342,7 +346,6 @@ void sctp_association_free(sctp_association_t *asoc) ...@@ -342,7 +346,6 @@ void sctp_association_free(sctp_association_t *asoc)
sctp_association_put(asoc); sctp_association_put(asoc);
} }
/* Cleanup and free up an association. */ /* Cleanup and free up an association. */
static void sctp_association_destroy(sctp_association_t *asoc) static void sctp_association_destroy(sctp_association_t *asoc)
{ {
...@@ -383,12 +386,11 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc, ...@@ -383,12 +386,11 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
}; };
/* Set the port if it has not been set yet. */ /* Set the port if it has not been set yet. */
if (0 == asoc->peer.port) { if (0 == asoc->peer.port) {
asoc->peer.port = *port; asoc->peer.port = *port;
} }
SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n", SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n", return NULL);
return NULL);
/* Check to see if this is a duplicate. */ /* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr); peer = sctp_assoc_lookup_paddr(asoc, addr);
...@@ -461,11 +463,21 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc, ...@@ -461,11 +463,21 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
sp = sctp_sk(asoc->base.sk); sp = sctp_sk(asoc->base.sk);
peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ; peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ;
/* Attach the remote transport to our asoc. */ /* Attach the remote transport to our asoc. */
list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
/* If we do not yet have a primary path, set one. */ /* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) { 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; asoc->peer.primary_path = peer;
asoc->peer.active_path = peer; asoc->peer.active_path = peer;
asoc->peer.retran_path = peer; asoc->peer.retran_path = peer;
...@@ -617,7 +629,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc) ...@@ -617,7 +629,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc)
asoc->next_tsn++; asoc->next_tsn++;
asoc->unack_data++; asoc->unack_data++;
return retval; return retval;
} }
/* Allocate 'num' TSNs by incrementing the association's TSN by num. */ /* Allocate 'num' TSNs by incrementing the association's TSN by num. */
...@@ -739,7 +751,7 @@ int sctp_cmp_addr_exact(const sockaddr_storage_t *ss1, ...@@ -739,7 +751,7 @@ int sctp_cmp_addr_exact(const sockaddr_storage_t *ss1,
* Note: We are sly and return a shared, prealloced chunk. * Note: We are sly and return a shared, prealloced chunk.
*/ */
sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc) sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc)
{ {
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
int need_ecne; int need_ecne;
__u32 lowest_tsn; __u32 lowest_tsn;
...@@ -892,7 +904,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc) ...@@ -892,7 +904,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc)
/* Check to see if the association is freed in response to /* Check to see if the association is freed in response to
* the incoming chunk. If so, get out of the while loop. * the incoming chunk. If so, get out of the while loop.
*/ */
if (!sctp_id2assoc(sk, associd)) if (!sctp_id2assoc(sk, associd))
goto out; goto out;
...@@ -967,7 +979,7 @@ void sctp_assoc_update(sctp_association_t *asoc, sctp_association_t *new) ...@@ -967,7 +979,7 @@ void sctp_assoc_update(sctp_association_t *asoc, sctp_association_t *new)
* and peer's streams. * and peer's streams.
*/ */
for (i = 0; i < SCTP_MAX_STREAM; i++) { for (i = 0; i < SCTP_MAX_STREAM; i++) {
asoc->ssn[i] = 0; asoc->ssn[i] = 0;
asoc->ulpq.ssn[i] = 0; asoc->ulpq.ssn[i] = 0;
} }
} else { } else {
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) Cisco 1999,2000 * Copyright (c) Cisco 1999,2000
* Copyright (c) Motorola 1999,2000,2001 * Copyright (c) Motorola 1999,2000,2001
* Copyright (c) International Business Machines Corp., 2001 * Copyright (c) International Business Machines Corp., 2001
* Copyright (c) La Monte H.P. Yarroll 2001 * Copyright (c) La Monte H.P. Yarroll 2001
* *
* This file is part of the SCTP kernel reference implementation. * This file is part of the SCTP kernel reference implementation.
* *
* A collection class to handle the storage of transport addresses. * A collection class to handle the storage of transport addresses.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -83,7 +83,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, ...@@ -83,7 +83,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
out: out:
if (error) if (error)
sctp_bind_addr_clean(dest); sctp_bind_addr_clean(dest);
return error; return error;
} }
...@@ -356,7 +356,7 @@ int sctp_in_scope(const sockaddr_storage_t *addr, sctp_scope_t scope) ...@@ -356,7 +356,7 @@ int sctp_in_scope(const sockaddr_storage_t *addr, sctp_scope_t scope)
case AF_INET: case AF_INET:
/* According to the SCTP IPv4 address scoping document - /* According to the SCTP IPv4 address scoping document -
* <draft-stewart-tsvwg-sctp-ipv4-00.txt>, the scope has * <draft-stewart-tsvwg-sctp-ipv4-00.txt>, the scope has
* a heirarchy of 5 levels: * a heirarchy of 5 levels:
* Level 0 - unusable SCTP addresses * Level 0 - unusable SCTP addresses
* Level 1 - loopback address * Level 1 - loopback address
* Level 2 - link-local addresses * Level 2 - link-local addresses
......
/* SCTP kernel reference Implementation Copyright (C) 1999-2001 /* SCTP kernel reference Implementation Copyright (C) 1999-2001
* Cisco, Motorola, and IBM * Cisco, Motorola, and IBM
* Copyright 2001 La Monte H.P. Yarroll * Copyright 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions manipulate sctp command sequences. * These functions manipulate sctp command sequences.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
......
...@@ -198,6 +198,7 @@ static const char *sctp_timer_tbl[] = { ...@@ -198,6 +198,7 @@ static const char *sctp_timer_tbl[] = {
"TIMEOUT_T2_SHUTDOWN", "TIMEOUT_T2_SHUTDOWN",
"TIMEOUT_T3_RTX", "TIMEOUT_T3_RTX",
"TIMEOUT_T4_RTO", "TIMEOUT_T4_RTO",
"TIMEOUT_T5_SHUTDOWN_GUARD",
"TIMEOUT_HEARTBEAT", "TIMEOUT_HEARTBEAT",
"TIMEOUT_SACK", "TIMEOUT_SACK",
"TIMEOUT_AUTOCLOSE", "TIMEOUT_AUTOCLOSE",
......
...@@ -5,46 +5,46 @@ ...@@ -5,46 +5,46 @@
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This abstraction represents an SCTP endpoint. * This abstraction represents an SCTP endpoint.
* *
* This file is part of the implementation of the add-IP extension, * This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001, * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation. * for the SCTP kernel reference Implementation.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@austin.ibm.com> * Jon Grimm <jgrimm@austin.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Dajiang Zhang <dajiang.zhang@nokia.com> * Dajiang Zhang <dajiang.zhang@nokia.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -92,15 +92,16 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto, ...@@ -92,15 +92,16 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto,
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto, sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
struct sock *sk, int priority) struct sock *sk, int priority)
{ {
sctp_opt_t *sp = sctp_sk(sk);
memset(ep, 0, sizeof(sctp_endpoint_t)); memset(ep, 0, sizeof(sctp_endpoint_t));
/* Initialize the base structure. */ /* Initialize the base structure. */
/* What type of endpoint are we? */ /* What type of endpoint are we? */
ep->base.type = SCTP_EP_TYPE_SOCKET; ep->base.type = SCTP_EP_TYPE_SOCKET;
/* Initialize the basic object fields. */ /* Initialize the basic object fields. */
atomic_set(&ep->base.refcnt, 1); atomic_set(&ep->base.refcnt, 1);
ep->base.dead = 0; ep->base.dead = 0;
ep->base.malloced = 1; ep->base.malloced = 1;
/* Create an input queue. */ /* Create an input queue. */
...@@ -129,22 +130,30 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto, ...@@ -129,22 +130,30 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
/* Set up the base timeout information. */ /* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
= SCTP_DEFAULT_TIMEOUT_T1_COOKIE; SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
= SCTP_DEFAULT_TIMEOUT_T1_INIT; SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
= sctp_sk(sk)->rtoinfo.srto_initial; sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT]
= SCTP_DEFAULT_TIMEOUT_HEARTBEAT; /* sctpimpguide-05 Section 2.12.2
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
= SCTP_DEFAULT_TIMEOUT_SACK; * recommended value of 5 times 'RTO.Max'.
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] */
= sctp_sk(sk)->autoclose * HZ; ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
ep->timeouts[SCTP_EVENT_TIMEOUT_PMTU_RAISE] = 5 * sp->rtoinfo.srto_max;
= SCTP_DEFAULT_TIMEOUT_PMTU_RAISE;
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. */ /* Set up the default send/receive buffer space. */
...@@ -251,9 +260,10 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep, ...@@ -251,9 +260,10 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint. * We do a linear search of the associations for this endpoint.
* We return the matching transport address too. * 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 sockaddr_storage_t *paddr, const sctp_endpoint_t *endpoint,
sctp_transport_t **transport) const sockaddr_storage_t *paddr,
sctp_transport_t **transport)
{ {
int rport; int rport;
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -310,7 +320,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -310,7 +320,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
asoc = NULL; asoc = NULL;
inqueue = &ep->base.inqueue; inqueue = &ep->base.inqueue;
sk = ep->base.sk; sk = ep->base.sk;
while (NULL != (chunk = sctp_pop_inqueue(inqueue))) { while (NULL != (chunk = sctp_pop_inqueue(inqueue))) {
subtype.chunk = chunk->chunk_hdr->type; subtype.chunk = chunk->chunk_hdr->type;
...@@ -343,15 +353,15 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -343,15 +353,15 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
/* FIX ME We really would rather NOT have to use /* FIX ME We really would rather NOT have to use
* GFP_ATOMIC. * GFP_ATOMIC.
*/ */
error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state, error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state,
ep, asoc, chunk, GFP_ATOMIC); ep, asoc, chunk, GFP_ATOMIC);
if (error != 0) if (error != 0)
goto err_out; goto err_out;
/* Check to see if the endpoint is freed in response to /* Check to see if the endpoint is freed in response to
* the incoming chunk. If so, get out of the while loop. * the incoming chunk. If so, get out of the while loop.
*/ */
if (!sctp_sk(sk)->ep) if (!sctp_sk(sk)->ep)
goto out; goto out;
} }
...@@ -360,10 +370,5 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -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? */ /* Is this the right way to pass errors up to the ULP? */
if (error) if (error)
ep->base.sk->err = -error; ep->base.sk->err = -error;
out: out:
} }
...@@ -5,43 +5,43 @@ ...@@ -5,43 +5,43 @@
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions handle all input from the IP layer into SCTP. * These functions handle all input from the IP layer into SCTP.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Xingang Guo <xingang.guo@intel.com> * Xingang Guo <xingang.guo@intel.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */ /* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *); static int sctp_rcv_ootb(struct sk_buff *);
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb, sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
const sockaddr_storage_t *laddr, const sockaddr_storage_t *laddr,
const sockaddr_storage_t *paddr, const sockaddr_storage_t *paddr,
...@@ -639,7 +639,7 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb, ...@@ -639,7 +639,7 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb,
/* Lookup an association for an inbound skb. */ /* Lookup an association for an inbound skb. */
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb, sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
const sockaddr_storage_t *paddr, const sockaddr_storage_t *paddr,
const sockaddr_storage_t *laddr, const sockaddr_storage_t *laddr,
sctp_transport_t **transportp) sctp_transport_t **transportp)
{ {
sctp_association_t *asoc; sctp_association_t *asoc;
......
...@@ -2,36 +2,36 @@ ...@@ -2,36 +2,36 @@
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* Copyright (c) 2002 International Business Machines, Corp. * Copyright (c) 2002 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* SCTP over IPv6. * SCTP over IPv6.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* Le Yanqun <yanqun.le@nokia.com> * Le Yanqun <yanqun.le@nokia.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
* *
* Based on: * Based on:
* linux/net/ipv6/tcp_ipv6.c * linux/net/ipv6/tcp_ipv6.c
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -145,7 +145,7 @@ static inline int sctp_v6_xmit(struct sk_buff *skb) ...@@ -145,7 +145,7 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
IPV6_ADDR_LOOPBACK)) { IPV6_ADDR_LOOPBACK)) {
ipv6_addr_copy(&saddr, &np->daddr); ipv6_addr_copy(&saddr, &np->daddr);
} }
} }
fl.fl6_src = &saddr; fl.fl6_src = &saddr;
} else { } else {
fl.fl6_src = &np->saddr; fl.fl6_src = &np->saddr;
...@@ -177,7 +177,7 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -177,7 +177,7 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address)
if (dst) { if (dst) {
dst_mtu = dst->pmtu; dst_mtu = dst->pmtu;
SCTP_DEBUG_PRINTK("sctp_v6_get_dst_mtu: " SCTP_DEBUG_PRINTK("sctp_v6_get_dst_mtu: "
"ip6_route_output: dev:%s pmtu:%d\n", "ip6_route_output: dev:%s pmtu:%d\n",
dst->dev->name, dst_mtu); dst->dev->name, dst_mtu);
dst_release(dst); dst_release(dst);
} else { } else {
...@@ -189,11 +189,85 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -189,11 +189,85 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address)
return dst_mtu; 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 = { static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6, .family = PF_INET6,
.release = inet6_release, .release = inet6_release,
.bind = inet6_bind, .bind = inet6_bind,
.connect = inet_dgram_connect, .connect = inet_dgram_connect,
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
.accept = inet_accept, .accept = inet_accept,
.getname = inet6_getname, .getname = inet6_getname,
...@@ -238,15 +312,22 @@ static sctp_func_t sctp_ipv6_specific = { ...@@ -238,15 +312,22 @@ static sctp_func_t sctp_ipv6_specific = {
.sa_family = AF_INET6, .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. */ /* Initialize IPv6 support and register with inet6 stack. */
int sctp_v6_init(void) int sctp_v6_init(void)
{ {
/* Add SCTPv6 to inetsw6 linked list. */ /* Add SCTPv6 to inetsw6 linked list. */
inet6_register_protosw(&sctpv6_protosw); inet6_register_protosw(&sctpv6_protosw);
/* Register inet6 protocol. */ /* Register inet6 protocol. */
inet6_add_protocol(&sctpv6_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. */ /* Fill in address family info. */
INIT_LIST_HEAD(&sctp_ipv6_specific.list); INIT_LIST_HEAD(&sctp_ipv6_specific.list);
list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families); list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families);
......
...@@ -2,41 +2,41 @@ ...@@ -2,41 +2,41 @@
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions handle output processing. * These functions handle output processing.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@austin.ibm.com> * Jon Grimm <jgrimm@austin.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/init.h> #include <linux/init.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/icmp.h> #include <net/icmp.h>
#ifndef TEST_FRAME #ifndef TEST_FRAME
...@@ -113,7 +113,7 @@ void sctp_packet_free(sctp_packet_t *packet) ...@@ -113,7 +113,7 @@ void sctp_packet_free(sctp_packet_t *packet)
{ {
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
while (NULL != while (NULL !=
(chunk = (sctp_chunk_t *)skb_dequeue(&packet->chunks))) { (chunk = (sctp_chunk_t *)skb_dequeue(&packet->chunks))) {
sctp_free_chunk(chunk); sctp_free_chunk(chunk);
} }
...@@ -129,7 +129,8 @@ void sctp_packet_free(sctp_packet_t *packet) ...@@ -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 * 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. * 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; sctp_xmit_t retval;
int error = 0; int error = 0;
...@@ -181,8 +182,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk) ...@@ -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 /* Both control chunks and data chunks with TSNs are
* non-fragmentable. * non-fragmentable.
*/ */
int fragmentable = sctp_chunk_is_data(chunk) int fragmentable = sctp_chunk_is_data(chunk) &&
&& (!chunk->has_tsn); (!chunk->has_tsn);
if (packet_empty) { if (packet_empty) {
if (fragmentable) { if (fragmentable) {
retval = SCTP_XMIT_MUST_FRAG; retval = SCTP_XMIT_MUST_FRAG;
...@@ -221,10 +222,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk) ...@@ -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. */ /* It is OK to send this chunk. */
skb_queue_tail(&packet->chunks, skb_queue_tail(&packet->chunks, (struct sk_buff *)chunk);
(struct sk_buff *)chunk);
packet->size += chunk_len; packet->size += chunk_len;
finish: finish:
return retval; return retval;
} }
...@@ -305,7 +304,7 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -305,7 +304,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
*/ */
if ((1 == chunk->num_times_sent) && if ((1 == chunk->num_times_sent) &&
(!transport->rto_pending)) { (!transport->rto_pending)) {
chunk->rtt_in_progress = 1; chunk->rtt_in_progress = 1;
transport->rto_pending = 1; transport->rto_pending = 1;
} }
packet_has_data = 1; packet_has_data = 1;
...@@ -337,9 +336,9 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -337,9 +336,9 @@ int sctp_packet_transmit(sctp_packet_t *packet)
} }
/* Build the SCTP header. */ /* 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->source = htons(packet->source_port);
sh->dest = htons(packet->destination_port); sh->dest = htons(packet->destination_port);
/* From 6.8 Adler-32 Checksum Calculation: /* From 6.8 Adler-32 Checksum Calculation:
* After the packet is constructed (containing the SCTP common * After the packet is constructed (containing the SCTP common
...@@ -349,8 +348,8 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -349,8 +348,8 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* 1) Fill in the proper Verification Tag in the SCTP common * 1) Fill in the proper Verification Tag in the SCTP common
* header and initialize the checksum field to 0's. * header and initialize the checksum field to 0's.
*/ */
sh->vtag = htonl(packet->vtag); sh->vtag = htonl(packet->vtag);
sh->checksum = 0; sh->checksum = 0;
/* 2) Calculate the Adler-32 checksum of the whole packet, /* 2) Calculate the Adler-32 checksum of the whole packet,
* including the SCTP common header and all the * including the SCTP common header and all the
...@@ -467,7 +466,8 @@ static void sctp_packet_reset(sctp_packet_t *packet) ...@@ -467,7 +466,8 @@ static void sctp_packet_reset(sctp_packet_t *packet)
} }
/* This private function handles the specifics of appending DATA chunks. */ /* 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; sctp_xmit_t retval = SCTP_XMIT_OK;
size_t datasize, rwnd, inflight; size_t datasize, rwnd, inflight;
...@@ -502,12 +502,13 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t * ...@@ -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 * transmit new DATA chunks, the protocol parameter Max.Burst MUST
* first be applied to limit how many new DATA chunks may be sent. * first be applied to limit how many new DATA chunks may be sent.
* The limit is applied by adjusting cwnd as follows: * The limit is applied by adjusting cwnd as follows:
* if((flightsize + Max.Burst*MTU) < cwnd) * if ((flightsize + Max.Burst * MTU) < cwnd)
* cwnd = flightsize + Max.Burst*MTU * cwnd = flightsize + Max.Burst * MTU
*/ */
max_burst_bytes = transport->asoc->max_burst * transport->asoc->pmtu; max_burst_bytes = transport->asoc->max_burst * transport->asoc->pmtu;
if ((transport->flight_size + max_burst_bytes) < transport->cwnd) { if ((transport->flight_size + max_burst_bytes) < transport->cwnd) {
...@@ -516,11 +517,11 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t * ...@@ -516,11 +517,11 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
"transport: %p, cwnd: %d, " "transport: %p, cwnd: %d, "
"ssthresh: %d, flight_size: %d, " "ssthresh: %d, flight_size: %d, "
"pba: %d\n", "pba: %d\n",
__FUNCTION__, transport, __FUNCTION__, transport,
transport->cwnd, transport->cwnd,
transport->ssthresh, transport->ssthresh,
transport->flight_size, transport->flight_size,
transport->partial_bytes_acked); transport->partial_bytes_acked);
} }
/* RFC 2960 6.1 Transmission of DATA Chunks /* RFC 2960 6.1 Transmission of DATA Chunks
...@@ -552,7 +553,3 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t * ...@@ -552,7 +553,3 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
finish: finish:
return retval; return retval;
} }
...@@ -196,23 +196,14 @@ int sctp_push_outqueue(sctp_outqueue_t *q, sctp_chunk_t *chunk) ...@@ -196,23 +196,14 @@ int sctp_push_outqueue(sctp_outqueue_t *q, sctp_chunk_t *chunk)
return error; return error;
} }
/* Mark all the eligible packets on a transport for retransmission and force /* Mark all the eligible packets on a transport for retransmission. */
* one packet out. void sctp_retransmit_mark(sctp_outqueue_t *q, sctp_transport_t *transport,
*/ __u8 fast_retransmit)
void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
__u8 fast_retransmit)
{ {
struct list_head *lchunk; struct list_head *lchunk;
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
int error = 0;
struct list_head tlist; 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); INIT_LIST_HEAD(&tlist);
while (!list_empty(&transport->transmitted)) { while (!list_empty(&transport->transmitted)) {
...@@ -224,7 +215,7 @@ void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport, ...@@ -224,7 +215,7 @@ void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
* should be added to the retransmit queue. If we are doing * should be added to the retransmit queue. If we are doing
* retransmission due to a timeout, only the chunks that are * retransmission due to a timeout, only the chunks that are
* not yet acked should be added to the retransmit queue. * not yet acked should be added to the retransmit queue.
*/ */
if ((fast_retransmit && !chunk->fast_retransmit) || if ((fast_retransmit && !chunk->fast_retransmit) ||
(!fast_retransmit && chunk->tsn_gap_acked)) { (!fast_retransmit && chunk->tsn_gap_acked)) {
list_add_tail(lchunk, &tlist); list_add_tail(lchunk, &tlist);
...@@ -276,7 +267,26 @@ void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport, ...@@ -276,7 +267,26 @@ void sctp_retransmit(sctp_outqueue_t *q, sctp_transport_t *transport,
transport->flight_size, transport->flight_size,
transport->partial_bytes_acked); 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); error = sctp_flush_outqueue(q, /* rtx_timeout */ 1);
if (error) if (error)
q->asoc->base.sk->err = -error; q->asoc->base.sk->err = -error;
} }
...@@ -327,7 +337,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt, ...@@ -327,7 +337,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt,
/* If a chunk has been tried for more than SCTP_DEF_MAX_SEND /* If a chunk has been tried for more than SCTP_DEF_MAX_SEND
* times, discard it, and check the empty flag of the outqueue. * times, discard it, and check the empty flag of the outqueue.
* *
* --xguo * --xguo
*/ */
if (chunk->snd_count > SCTP_DEF_MAX_SEND) { if (chunk->snd_count > SCTP_DEF_MAX_SEND) {
sctp_free_chunk(chunk); sctp_free_chunk(chunk);
...@@ -339,7 +349,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt, ...@@ -339,7 +349,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt,
switch (status) { switch (status) {
case SCTP_XMIT_PMTU_FULL: case SCTP_XMIT_PMTU_FULL:
/* Send this packet. */ /* Send this packet. */
if ((error = (*q->force_output)(pkt)) == 0) if ((error = (*q->force_output)(pkt)) == 0)
*start_timer = 1; *start_timer = 1;
...@@ -370,8 +380,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt, ...@@ -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 append was successful, so add this chunk to
* the transmitted list. * the transmitted list.
*/ */
list_add_tail(lchunk, list_add_tail(lchunk, &transport->transmitted);
&transport->transmitted);
*start_timer = 1; *start_timer = 1;
q->empty = 0; q->empty = 0;
...@@ -389,8 +398,7 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt, ...@@ -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. * chunk that is currently in the process of fragmentation.
*/ */
void sctp_xmit_frag(sctp_outqueue_t *q, struct sk_buff *pos, void sctp_xmit_frag(sctp_outqueue_t *q, struct sk_buff *pos,
sctp_packet_t *packet, sctp_packet_t *packet, sctp_chunk_t *frag, __u32 tsn)
sctp_chunk_t *frag, __u32 tsn)
{ {
sctp_transport_t *transport = packet->transport; sctp_transport_t *transport = packet->transport;
struct sk_buff_head *queue = &q->out; struct sk_buff_head *queue = &q->out;
...@@ -407,7 +415,7 @@ void sctp_xmit_frag(sctp_outqueue_t *q, struct sk_buff *pos, ...@@ -407,7 +415,7 @@ void sctp_xmit_frag(sctp_outqueue_t *q, struct sk_buff *pos,
if (!skb_queue_empty(queue)) { if (!skb_queue_empty(queue)) {
SCTP_DEBUG_PRINTK("sctp_xmit_frag: q not empty. " SCTP_DEBUG_PRINTK("sctp_xmit_frag: q not empty. "
"adding 0x%x to outqueue\n", "adding 0x%x to outqueue\n",
ntohl(frag->subh.data_hdr->tsn)); ntohl(frag->subh.data_hdr->tsn));
if (pos) { if (pos) {
skb_insert(pos, (struct sk_buff *) frag); skb_insert(pos, (struct sk_buff *) frag);
} else { } else {
...@@ -499,7 +507,8 @@ void sctp_xmit_fragmented_chunks(sctp_outqueue_t *q, sctp_packet_t *packet, ...@@ -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 * fragments. It returns the first fragment with the frag_list field holding
* the remaining fragments. * 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; sctp_association_t *asoc = chunk->asoc;
void *data_ptr = chunk->subh.data_hdr; void *data_ptr = chunk->subh.data_hdr;
...@@ -519,7 +528,7 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, size_t max_frag_data_len) ...@@ -519,7 +528,7 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, size_t max_frag_data_len)
/* Make the first fragment. */ /* Make the first fragment. */
first_frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len, first_frag = sctp_make_datafrag(asoc, sinfo, max_frag_data_len,
data_ptr, SCTP_DATA_FIRST_FRAG, ssn); data_ptr, SCTP_DATA_FIRST_FRAG, ssn);
if (!first_frag) if (!first_frag)
goto err; goto err;
...@@ -533,11 +542,14 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, size_t max_frag_data_len) ...@@ -533,11 +542,14 @@ sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk, size_t max_frag_data_len)
/* Make the middle fragments. */ /* Make the middle fragments. */
while (chunk_data_len > max_frag_data_len) { while (chunk_data_len > max_frag_data_len) {
frag = sctp_make_datafrag(asoc, sinfo, 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) if (!frag)
goto err; 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); list_add_tail(&frag->frag_list, frag_list);
chunk_data_len -= max_frag_data_len; chunk_data_len -= max_frag_data_len;
...@@ -641,7 +653,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -641,7 +653,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
* chunk->transport, even it's inactive. * chunk->transport, even it's inactive.
*/ */
if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT) if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT)
new_transport = asoc->peer.active_path; new_transport = asoc->peer.active_path;
} }
/* Are we switching transports? /* Are we switching transports?
...@@ -674,7 +686,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -674,7 +686,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
(void) (*q->build_output)(&singleton, chunk); (void) (*q->build_output)(&singleton, chunk);
error = (*q->force_output)(&singleton); error = (*q->force_output)(&singleton);
if (error < 0) if (error < 0)
return(error); return error;
break; break;
case SCTP_CID_ABORT: case SCTP_CID_ABORT:
...@@ -698,17 +710,17 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -698,17 +710,17 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
default: default:
/* We built a chunk with an illegal type! */ /* We built a chunk with an illegal type! */
BUG(); BUG();
}; };
} }
/* Is it OK to send data chunks? */ /* Is it OK to send data chunks? */
switch (asoc->state) { switch (asoc->state) {
case SCTP_STATE_COOKIE_ECHOED: 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. * chunk.
*/ */
if (packet && !packet->has_cookie_echo) if (!packet || !packet->has_cookie_echo)
break; break;
/* fallthru */ /* fallthru */
...@@ -748,6 +760,12 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -748,6 +760,12 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
if (start_timer) if (start_timer)
sctp_transport_reset_timers(transport); 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. */ /* Finally, transmit new packets. */
...@@ -809,12 +827,11 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -809,12 +827,11 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
: "Illegal Chunk"); : "Illegal Chunk");
SCTP_DEBUG_PRINTK("TX TSN 0x%x skb->head " SCTP_DEBUG_PRINTK("TX TSN 0x%x skb->head "
"%p skb->users %d.\n", "%p skb->users %d.\n",
ntohl(chunk->subh.data_hdr->tsn), ntohl(chunk->subh.data_hdr->tsn),
chunk->skb ?chunk->skb->head : 0, chunk->skb ?chunk->skb->head : 0,
chunk->skb ? chunk->skb ?
atomic_read(&chunk->skb->users) : atomic_read(&chunk->skb->users) : -1);
-1);
/* Add the chunk to the packet. */ /* Add the chunk to the packet. */
status = (*q->build_output)(packet, chunk); status = (*q->build_output)(packet, chunk);
...@@ -826,8 +843,9 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -826,8 +843,9 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
* the chunk back on the output queue. * the chunk back on the output queue.
*/ */
SCTP_DEBUG_PRINTK("sctp_flush_outqueue: could" SCTP_DEBUG_PRINTK("sctp_flush_outqueue: could"
"not transmit TSN: 0x%x, status: %d\n", "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); skb_queue_head(queue, (struct sk_buff *)chunk);
goto sctp_flush_out; goto sctp_flush_out;
break; break;
...@@ -836,7 +854,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -836,7 +854,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
sctp_chunk_t *frag; sctp_chunk_t *frag;
frag = sctp_fragment_chunk(chunk, frag = sctp_fragment_chunk(chunk,
packet->transport->asoc->frag_point); packet->transport->asoc->frag_point);
if (!frag) { if (!frag) {
/* We could not fragment due to out of /* We could not fragment due to out of
* memory condition. Free the original * memory condition. Free the original
...@@ -857,7 +875,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -857,7 +875,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
default: default:
BUG(); BUG();
}; }
/* BUG: We assume that the (*q->force_output()) /* BUG: We assume that the (*q->force_output())
* call below will succeed all the time and add the * 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) ...@@ -875,13 +893,19 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
sctp_transport_reset_timers(transport); sctp_transport_reset_timers(transport);
q->empty = 0; 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; break;
default: default:
/* Do nothing. */ /* Do nothing. */
break; break;
}; }
sctp_flush_out: sctp_flush_out:
/* Before returning, examine all the transports touched in /* Before returning, examine all the transports touched in
...@@ -901,7 +925,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout) ...@@ -901,7 +925,7 @@ int sctp_flush_outqueue(sctp_outqueue_t *q, int rtx_timeout)
if (packet->size != SCTP_IP_OVERHEAD) if (packet->size != SCTP_IP_OVERHEAD)
error = (*q->force_output)(packet); error = (*q->force_output)(packet);
} }
return error; return error;
} }
...@@ -986,8 +1010,7 @@ int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack) ...@@ -986,8 +1010,7 @@ int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack)
ctsn = q->asoc->ctsn_ack_point; ctsn = q->asoc->ctsn_ack_point;
SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n", SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n",
__FUNCTION__, __FUNCTION__, sack_ctsn);
sack_ctsn);
SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association " SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association "
"%p is 0x%x.\n", __FUNCTION__, q->asoc, ctsn); "%p is 0x%x.\n", __FUNCTION__, q->asoc, ctsn);
...@@ -1114,8 +1137,9 @@ static void sctp_check_transmitted(sctp_outqueue_t *q, ...@@ -1114,8 +1137,9 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
* 6.3.1 C5) Karn's algorithm: RTT measurements * 6.3.1 C5) Karn's algorithm: RTT measurements
* MUST NOT be made using packets that were * MUST NOT be made using packets that were
* retransmitted (and thus for which it is * retransmitted (and thus for which it is
* ambiguous whether the reply was for the first * ambiguous whether the reply was for the
* instance of the packet or a later instance). * first instance of the packet or a later
* instance).
*/ */
if ((!tchunk->tsn_gap_acked) && if ((!tchunk->tsn_gap_acked) &&
(1 == tchunk->num_times_sent) && (1 == tchunk->num_times_sent) &&
...@@ -1150,15 +1174,15 @@ static void sctp_check_transmitted(sctp_outqueue_t *q, ...@@ -1150,15 +1174,15 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
* 'Stray DATA chunk(s)' record the highest TSN * 'Stray DATA chunk(s)' record the highest TSN
* reported as newly acknowledged, call this * reported as newly acknowledged, call this
* value 'HighestTSNinSack'. A newly * value 'HighestTSNinSack'. A newly
* acknowledged DATA chunk is one not previously * acknowledged DATA chunk is one not
* acknowledged in a SACK. * previously acknowledged in a SACK.
* *
* When the SCTP sender of data receives a SACK * When the SCTP sender of data receives a SACK
* chunk that acknowledges, for the first time, * chunk that acknowledges, for the first time,
* the receipt of a DATA chunk, all the still * the receipt of a DATA chunk, all the still
* unacknowledged DATA chunks whose TSN is older * unacknowledged DATA chunks whose TSN is
* than that newly acknowledged DATA chunk, are * older than that newly acknowledged DATA
* qualified as 'Stray DATA chunks'. * chunk, are qualified as 'Stray DATA chunks'.
*/ */
if (!tchunk->tsn_gap_acked) { if (!tchunk->tsn_gap_acked) {
tchunk->tsn_gap_acked = 1; tchunk->tsn_gap_acked = 1;
...@@ -1217,8 +1241,8 @@ static void sctp_check_transmitted(sctp_outqueue_t *q, ...@@ -1217,8 +1241,8 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
} else { } else {
if (tchunk->tsn_gap_acked) { if (tchunk->tsn_gap_acked) {
SCTP_DEBUG_PRINTK("%s: Receiver reneged on data " SCTP_DEBUG_PRINTK("%s: Receiver reneged on "
"TSN: 0x%x\n", "data TSN: 0x%x\n",
__FUNCTION__, __FUNCTION__,
tsn); tsn);
tchunk->tsn_gap_acked = 0; tchunk->tsn_gap_acked = 0;
...@@ -1227,10 +1251,11 @@ static void sctp_check_transmitted(sctp_outqueue_t *q, ...@@ -1227,10 +1251,11 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
/* RFC 2960 6.3.2 Retransmission Timer Rules /* RFC 2960 6.3.2 Retransmission Timer Rules
* *
* R4) Whenever a SACK is received missing a TSN * R4) Whenever a SACK is received missing a
* that was previously acknowledged via a Gap Ack * TSN that was previously acknowledged via a
* Block, start T3-rtx for the destination * Gap Ack Block, start T3-rtx for the
* address to which the DATA chunk was originally * destination address to which the DATA
* chunk was originally
* transmitted if it is not already running. * transmitted if it is not already running.
*/ */
restart_timer = 1; restart_timer = 1;
...@@ -1306,10 +1331,11 @@ static void sctp_check_transmitted(sctp_outqueue_t *q, ...@@ -1306,10 +1331,11 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
* active if it is not so marked. * active if it is not so marked.
*/ */
if (!transport->state.active) { if (!transport->state.active) {
sctp_assoc_control_transport(transport->asoc, sctp_assoc_control_transport(
transport, transport->asoc,
SCTP_TRANSPORT_UP, transport,
SCTP_RECEIVED_SACK); SCTP_TRANSPORT_UP,
SCTP_RECEIVED_SACK);
} }
sctp_transport_raise_cwnd(transport, sack_ctsn, sctp_transport_raise_cwnd(transport, sack_ctsn,
...@@ -1398,8 +1424,7 @@ static void sctp_check_transmitted(sctp_outqueue_t *q, ...@@ -1398,8 +1424,7 @@ static void sctp_check_transmitted(sctp_outqueue_t *q,
SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, " SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, "
"ssthresh: %d, flight_size: %d, pba: %d\n", "ssthresh: %d, flight_size: %d, pba: %d\n",
__FUNCTION__, __FUNCTION__, transport, transport->cwnd,
transport, transport->cwnd,
transport->ssthresh, transport->flight_size, transport->ssthresh, transport->flight_size,
transport->partial_bytes_acked); transport->partial_bytes_acked);
} }
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions implement the SCTP primitive functions from Section 10. * These functions implement the SCTP primitive functions from Section 10.
* *
* Note that the descriptions from the specification are USER level * Note that the descriptions from the specification are USER level
* functions--this file is the functions which populate the struct proto * functions--this file is the functions which populate the struct proto
* for SCTP which is the BOTTOM of the sockets interface. * for SCTP which is the BOTTOM of the sockets interface.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Narasimha Budihal <narasimha@refcode.org> * Narasimha Budihal <narasimha@refcode.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
......
...@@ -66,6 +66,9 @@ struct proc_dir_entry *proc_net_sctp; ...@@ -66,6 +66,9 @@ struct proc_dir_entry *proc_net_sctp;
*/ */
static struct socket *sctp_ctl_socket; 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; extern struct net_proto_family inet_family_ops;
/* Return the address of the control sock. */ /* Return the address of the control sock. */
...@@ -91,7 +94,7 @@ void sctp_proc_init(void) ...@@ -91,7 +94,7 @@ void sctp_proc_init(void)
void sctp_proc_exit(void) void sctp_proc_exit(void)
{ {
if (proc_net_sctp) { if (proc_net_sctp) {
proc_net_sctp= NULL; proc_net_sctp = NULL;
remove_proc_entry("net/sctp", 0); remove_proc_entry("net/sctp", 0);
} }
} }
...@@ -135,7 +138,8 @@ static inline void sctp_v4_get_local_addr_list(sctp_protocol_t *proto, ...@@ -135,7 +138,8 @@ static inline void sctp_v4_get_local_addr_list(sctp_protocol_t *proto,
* the protocol structure. * the protocol structure.
* FIXME: Make this an address family function. * 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 #ifdef SCTP_V6_SUPPORT
/* FIXME: The testframe doesn't support this function. */ /* FIXME: The testframe doesn't support this function. */
...@@ -227,8 +231,8 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp, ...@@ -227,8 +231,8 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp,
long flags __attribute__ ((unused)); long flags __attribute__ ((unused));
sctp_spin_lock_irqsave(&proto->local_addr_lock, flags); sctp_spin_lock_irqsave(&proto->local_addr_lock, flags);
list_for_each(pos, &proto->local_addr_list) { list_for_each(pos, &proto->local_addr_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list); addr = list_entry(pos, struct sockaddr_storage_list, list);
if (sctp_in_scope(&addr->a, scope)) { if (sctp_in_scope(&addr->a, scope)) {
/* Now that the address is in scope, check to see if /* Now that the address is in scope, check to see if
* the address type is really supported by the local * the address type is really supported by the local
...@@ -239,8 +243,7 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp, ...@@ -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) && (((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) { (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp, error = sctp_add_bind_addr(bp, &addr->a,
&addr->a,
priority); priority);
if (error) if (error)
goto end_copy; goto end_copy;
...@@ -286,7 +289,8 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -286,7 +289,8 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address)
/* Event handler for inet device events. /* Event handler for inet device events.
* Basically, whenever there is an event, we re-build our local address list. * 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)); long flags __attribute__ ((unused));
...@@ -312,8 +316,8 @@ int sctp_ctl_sock_init(void) ...@@ -312,8 +316,8 @@ int sctp_ctl_sock_init(void)
err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP, err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP,
&sctp_ctl_socket); &sctp_ctl_socket);
if (err < 0) { if (err < 0) {
printk(KERN_ERR printk(KERN_ERR
"SCTP: Failed to create the SCTP control socket.\n"); "SCTP: Failed to create the SCTP control socket.\n");
return err; return err;
} }
sctp_ctl_socket->sk->allocation = GFP_ATOMIC; sctp_ctl_socket->sk->allocation = GFP_ATOMIC;
...@@ -347,6 +351,52 @@ sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address) ...@@ -347,6 +351,52 @@ sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address)
return retval; 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. */ /* Registration for netdev events. */
struct notifier_block sctp_netdev_notifier = { struct notifier_block sctp_netdev_notifier = {
.notifier_call = sctp_netdev_event, .notifier_call = sctp_netdev_event,
...@@ -403,6 +453,34 @@ sctp_func_t sctp_ipv4_specific = { ...@@ -403,6 +453,34 @@ sctp_func_t sctp_ipv4_specific = {
.sa_family = AF_INET, .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. */ /* Initialize the universe into something sensible. */
int sctp_init(void) int sctp_init(void)
{ {
...@@ -421,9 +499,11 @@ int sctp_init(void) ...@@ -421,9 +499,11 @@ int sctp_init(void)
/* Initialize object count debugging. */ /* Initialize object count debugging. */
sctp_dbg_objcnt_init(); 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 * 14. Suggested SCTP Protocol Parameter Values
*/ */
/* The following protocol parameters are RECOMMENDED: */ /* The following protocol parameters are RECOMMENDED: */
/* RTO.Initial - 3 seconds */ /* RTO.Initial - 3 seconds */
sctp_proto.rto_initial = SCTP_RTO_INITIAL; sctp_proto.rto_initial = SCTP_RTO_INITIAL;
...@@ -468,7 +548,7 @@ int sctp_init(void) ...@@ -468,7 +548,7 @@ int sctp_init(void)
sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *) sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.assoc_hashbucket) { 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; status = -ENOMEM;
goto err_ahash_alloc; goto err_ahash_alloc;
} }
...@@ -482,7 +562,7 @@ int sctp_init(void) ...@@ -482,7 +562,7 @@ int sctp_init(void)
sctp_proto.ep_hashbucket = (sctp_hashbucket_t *) sctp_proto.ep_hashbucket = (sctp_hashbucket_t *)
kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.ep_hashbucket) { 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; status = -ENOMEM;
goto err_ehash_alloc; goto err_ehash_alloc;
} }
...@@ -497,7 +577,7 @@ int sctp_init(void) ...@@ -497,7 +577,7 @@ int sctp_init(void)
sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *) sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.port_hashtable) { if (!sctp_proto.port_hashtable) {
printk (KERN_ERR "SCTP: Failed bind hash alloc."); printk(KERN_ERR "SCTP: Failed bind hash alloc.");
status = -ENOMEM; status = -ENOMEM;
goto err_bhash_alloc; goto err_bhash_alloc;
} }
......
...@@ -9,36 +9,36 @@ ...@@ -9,36 +9,36 @@
* This file includes part of the implementation of the add-IP extension, * This file includes part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001, * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation. * for the SCTP kernel reference Implementation.
* *
* These functions work with the state functions in sctp_sm_statefuns.c * These functions work with the state functions in sctp_sm_statefuns.c
* to implement the state operations. These functions implement the * to implement the state operations. These functions implement the
* steps which require modifying existing data structures. * steps which require modifying existing data structures.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* C. Robin <chris@hundredacre.ac.uk> * C. Robin <chris@hundredacre.ac.uk>
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
* support any address type. * support any address type.
*/ */
static const sctp_supported_addrs_param_t sat_param = { static const sctp_supported_addrs_param_t sat_param = {
{ {
SCTP_PARAM_SUPPORTED_ADDRESS_TYPES, SCTP_PARAM_SUPPORTED_ADDRESS_TYPES,
__constant_htons(SCTP_SAT_LEN), __constant_htons(SCTP_SAT_LEN),
}, },
...@@ -204,7 +204,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc, ...@@ -204,7 +204,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
* PLEASE DO NOT FIXME [This version does not support Host Name.] * PLEASE DO NOT FIXME [This version does not support Host Name.]
*/ */
retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize); retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize);
if (!retval) if (!retval)
goto nodata; goto nodata;
...@@ -1204,7 +1204,7 @@ sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *ep, ...@@ -1204,7 +1204,7 @@ sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *ep,
case 6: case 6:
asoc->c.peer_addr.v6.sin6_family = AF_INET6; asoc->c.peer_addr.v6.sin6_family = AF_INET6;
asoc->c.peer_addr.v6.sin6_port asoc->c.peer_addr.v6.sin6_port
= ntohs(chunk->sctp_hdr->source); = ntohs(chunk->sctp_hdr->source);
asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */ asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */
asoc->c.peer_addr.v6.sin6_addr = chunk->skb->nh.ipv6h->saddr; asoc->c.peer_addr.v6.sin6_addr = chunk->skb->nh.ipv6h->saddr;
...@@ -1245,7 +1245,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep, ...@@ -1245,7 +1245,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
* functions simpler to write. * functions simpler to write.
*/ */
if (bodysize % SCTP_COOKIE_MULTIPLE) if (bodysize % SCTP_COOKIE_MULTIPLE)
bodysize += SCTP_COOKIE_MULTIPLE bodysize += SCTP_COOKIE_MULTIPLE
- (bodysize % SCTP_COOKIE_MULTIPLE); - (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize; *cookie_len = headersize + bodysize;
...@@ -1418,6 +1418,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1418,6 +1418,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
__u8 *end; __u8 *end;
sctp_transport_t *transport; sctp_transport_t *transport;
struct list_head *pos, *temp; struct list_head *pos, *temp;
char *cookie;
/* We must include the address that the INIT packet came from. /* We must include the address that the INIT packet came from.
* This is the only address that matters for an INIT packet. * This is the only address that matters for an INIT packet.
...@@ -1437,7 +1438,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1437,7 +1438,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
for (param.v = peer_init->init_hdr.params; for (param.v = peer_init->init_hdr.params;
param.v < end; param.v < end;
param.v += WORD_ROUND(ntohs(param.p->length))) { param.v += WORD_ROUND(ntohs(param.p->length))) {
if (!sctp_process_param(asoc, param, peer_addr, cid, if (!sctp_process_param(asoc, param, peer_addr, cid,
priority)) priority))
goto clean_up; goto clean_up;
} }
...@@ -1461,7 +1462,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1461,7 +1462,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
*/ */
if (asoc->c.sinit_num_ostreams > if (asoc->c.sinit_num_ostreams >
ntohs(peer_init->init_hdr.num_inbound_streams)) { ntohs(peer_init->init_hdr.num_inbound_streams)) {
asoc->c.sinit_num_ostreams = asoc->c.sinit_num_ostreams =
ntohs(peer_init->init_hdr.num_inbound_streams); ntohs(peer_init->init_hdr.num_inbound_streams);
} }
...@@ -1471,6 +1472,15 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -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. */ /* Peer Rwnd : Current calculated value of the peer's rwnd. */
asoc->peer.rwnd = asoc->peer.i.a_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 /* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
* high (for example, implementations MAY use the size of the receiver * high (for example, implementations MAY use the size of the receiver
* advertised window). * advertised window).
...@@ -1560,7 +1570,7 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param, ...@@ -1560,7 +1570,7 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param,
break; break;
case SCTP_PARAM_HOST_NAME_ADDRESS: 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; break;
case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES: case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
...@@ -1595,13 +1605,12 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param, ...@@ -1595,13 +1605,12 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param,
case SCTP_PARAM_STATE_COOKIE: case SCTP_PARAM_STATE_COOKIE:
asoc->peer.cookie_len = asoc->peer.cookie_len =
ntohs(param.p->length) - ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
sizeof(sctp_paramhdr_t);
asoc->peer.cookie = param.cookie->body; asoc->peer.cookie = param.cookie->body;
break; break;
case SCTP_PARAM_HEATBEAT_INFO: case SCTP_PARAM_HEATBEAT_INFO:
SCTP_DEBUG_PRINTK("unimplmented " SCTP_DEBUG_PRINTK("unimplemented "
"SCTP_PARAM_HEATBEAT_INFO\n"); "SCTP_PARAM_HEATBEAT_INFO\n");
break; break;
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999 Cisco, Inc. * Copyright (c) 1999 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines Corp. * Copyright (c) 2001-2002 International Business Machines Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions work with the state functions in sctp_sm_statefuns.c * These functions work with the state functions in sctp_sm_statefuns.c
* to implement that state operations. These functions implement the * to implement that state operations. These functions implement the
* steps which require modifying existing data structures. * steps which require modifying existing data structures.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@austin.ibm.com> * Jon Grimm <jgrimm@austin.ibm.com>
...@@ -119,7 +119,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -119,7 +119,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
int priority) int priority)
{ {
sctp_cmd_seq_t commands; sctp_cmd_seq_t commands;
sctp_sm_table_entry_t *state_fn; sctp_sm_table_entry_t *state_fn;
sctp_disposition_t status; sctp_disposition_t status;
int error = 0; int error = 0;
typedef const char *(printfn_t)(sctp_subtype_t); typedef const char *(printfn_t)(sctp_subtype_t);
...@@ -253,6 +253,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -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 *new_obj;
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
sctp_packet_t *packet; sctp_packet_t *packet;
struct list_head *pos;
struct timer_list *timer; struct timer_list *timer;
unsigned long timeout; unsigned long timeout;
sctp_transport_t *t; sctp_transport_t *t;
...@@ -336,9 +337,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -336,9 +337,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case SCTP_CMD_PEER_INIT: case SCTP_CMD_PEER_INIT:
/* Process a unified INIT from the peer. */ /* Process a unified INIT from the peer. */
sctp_cmd_process_init(commands, sctp_cmd_process_init(commands, asoc, chunk,
asoc, chunk, command->obj.ptr, command->obj.ptr, priority);
priority);
break; break;
case SCTP_CMD_GEN_COOKIE_ECHO: case SCTP_CMD_GEN_COOKIE_ECHO:
...@@ -462,6 +462,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -462,6 +462,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break; break;
case SCTP_CMD_INIT_RESTART: case SCTP_CMD_INIT_RESTART:
/* Do the needed accounting and updates /* Do the needed accounting and updates
* associated with restarting an initialization * associated with restarting an initialization
* timer. * timer.
...@@ -474,6 +475,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -474,6 +475,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
asoc->max_init_timeo; 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_add_cmd_sf(commands,
SCTP_CMD_TIMER_RESTART, SCTP_CMD_TIMER_RESTART,
SCTP_TO(command->obj.to)); SCTP_TO(command->obj.to));
...@@ -602,7 +612,7 @@ static sctp_chunk_t *sctp_do_ecn_ecne_work(sctp_association_t *asoc, ...@@ -602,7 +612,7 @@ static sctp_chunk_t *sctp_do_ecn_ecne_work(sctp_association_t *asoc,
{ {
sctp_chunk_t *repl; sctp_chunk_t *repl;
sctp_transport_t *transport; sctp_transport_t *transport;
/* Our previously transmitted packet ran into some congestion /* Our previously transmitted packet ran into some congestion
* so we should take action by reducing cwnd and ssthresh * so we should take action by reducing cwnd and ssthresh
* and then ACK our peer that we we've done so by * and then ACK our peer that we we've done so by
...@@ -716,7 +726,7 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands) ...@@ -716,7 +726,7 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands)
error = sctp_push_outqueue(&asoc->outqueue, sack); error = sctp_push_outqueue(&asoc->outqueue, sack);
/* Stop the SACK timer. */ /* Stop the SACK timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
} }
...@@ -785,7 +795,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) ...@@ -785,7 +795,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20))) if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20)))
sctp_transport_hold(transport); sctp_transport_hold(transport);
goto out_unlock; goto out_unlock;
} }
/* Is this transport really dead and just waiting around for /* Is this transport really dead and just waiting around for
* the timer to let go of the reference? * the timer to let go of the reference?
...@@ -867,6 +877,14 @@ void sctp_generate_t2_shutdown_event(unsigned long data) ...@@ -867,6 +877,14 @@ void sctp_generate_t2_shutdown_event(unsigned long data)
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN); 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) void sctp_generate_autoclose_event(unsigned long data)
{ {
sctp_association_t *asoc = (sctp_association_t *) data; sctp_association_t *asoc = (sctp_association_t *) data;
...@@ -890,7 +908,7 @@ void sctp_generate_heartbeat_event(unsigned long data) ...@@ -890,7 +908,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20))) if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20)))
sctp_transport_hold(transport); sctp_transport_hold(transport);
goto out_unlock; goto out_unlock;
} }
/* Is this structure just waiting around for us to actually /* Is this structure just waiting around for us to actually
* get destroyed? * get destroyed?
...@@ -932,6 +950,7 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = { ...@@ -932,6 +950,7 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = {
sctp_generate_t2_shutdown_event, sctp_generate_t2_shutdown_event,
NULL, NULL,
NULL, NULL,
sctp_generate_t5_shutdown_guard_event,
sctp_generate_heartbeat_event, sctp_generate_heartbeat_event,
sctp_generate_sack_event, sctp_generate_sack_event,
sctp_generate_autoclose_event, sctp_generate_autoclose_event,
...@@ -1023,6 +1042,9 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, ...@@ -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_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
SCTP_ULPEVENT(event)); 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 /* FIXME: We need to handle data that could not be sent or was not
* acked, if the user has enabled SEND_FAILED notifications. * acked, if the user has enabled SEND_FAILED notifications.
*/ */
......
...@@ -5,36 +5,36 @@ ...@@ -5,36 +5,36 @@
* Copyright (c) 2002 Nokia Corp. * Copyright (c) 2002 Nokia Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This is part of the SCTP Linux Kernel Reference Implementation. * This is part of the SCTP Linux Kernel Reference Implementation.
* *
* These are the state functions for the state machine. * These are the state functions for the state machine.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Mathew Kotowsky <kotowsky@sctp.org> * Mathew Kotowsky <kotowsky@sctp.org>
...@@ -149,6 +149,9 @@ sctp_disposition_t sctp_sf_do_4_C(const sctp_endpoint_t *ep, ...@@ -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_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 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_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED)); SCTP_STATE(SCTP_STATE_CLOSED));
...@@ -160,35 +163,6 @@ sctp_disposition_t sctp_sf_do_4_C(const sctp_endpoint_t *ep, ...@@ -160,35 +163,6 @@ sctp_disposition_t sctp_sf_do_4_C(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_NOMEM; 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. * Respond to a normal INIT chunk.
* We are the side that is being asked for an association. * We are the side that is being asked for an association.
...@@ -263,7 +237,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep, ...@@ -263,7 +237,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
/* /*
* Note: After sending out INIT ACK with the State Cookie parameter, * Note: After sending out INIT ACK with the State Cookie parameter,
* "Z" MUST NOT allocate any resources, nor keep any states for the * "Z" MUST NOT allocate any resources, nor keep any states for the
* new association. Otherwise, "Z" will be vulnerable to resource * new association. Otherwise, "Z" will be vulnerable to resource
* attacks. * attacks.
...@@ -324,7 +298,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep, ...@@ -324,7 +298,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_VIOLATION; return SCTP_DISPOSITION_VIOLATION;
/* Grab the INIT header. */ /* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data; chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
init_tag = ntohl(chunk->subh.init_hdr->init_tag); init_tag = ntohl(chunk->subh.init_hdr->init_tag);
...@@ -338,20 +312,17 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep, ...@@ -338,20 +312,17 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const sctp_endpoint_t *ep,
if (!reply) if (!reply)
goto nomem; goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
SCTP_CHUNK(reply));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED)); SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB; return SCTP_DISPOSITION_DELETE_TCB;
} }
/* Tag the variable length paramters. Note that we never /* Tag the variable length paramters. Note that we never
* convert the parameters in an INIT chunk. * convert the parameters in an INIT chunk.
*/ */
chunk->param_hdr.v = chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
initchunk = (sctp_init_chunk_t *) chunk->chunk_hdr; initchunk = (sctp_init_chunk_t *) chunk->chunk_hdr;
...@@ -428,7 +399,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep, ...@@ -428,7 +399,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep,
* control endpoint, responding with an ABORT. * control endpoint, responding with an ABORT.
*/ */
if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
return sctp_sf_ootb(ep, asoc, type, arg, commands); return sctp_sf_ootb(ep, asoc, type, arg, commands);
/* "Decode" the chunk. We have no optional parameters so we /* "Decode" the chunk. We have no optional parameters so we
* are in good shape. * are in good shape.
...@@ -460,8 +431,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep, ...@@ -460,8 +431,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep,
case -SCTP_IERROR_BAD_SIG: case -SCTP_IERROR_BAD_SIG:
default: default:
return sctp_sf_pdiscard(ep, asoc, type, return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
arg, commands);
}; };
} }
...@@ -560,7 +530,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const sctp_endpoint_t *ep, ...@@ -560,7 +530,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const sctp_endpoint_t *ep,
SCTP_STATE(SCTP_STATE_ESTABLISHED)); SCTP_STATE(SCTP_STATE_ESTABLISHED));
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
if (asoc->autoclose) if (asoc->autoclose)
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
...@@ -625,8 +595,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep, ...@@ -625,8 +595,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const sctp_endpoint_t *ep,
if (!reply) if (!reply)
goto nomem; goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
SCTP_CHUNK(reply));
/* Set transport error counter and association error counter /* Set transport error counter and association error counter
* when sending heartbeat. * when sending heartbeat.
...@@ -751,7 +720,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const sctp_endpoint_t *ep, ...@@ -751,7 +720,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const sctp_endpoint_t *ep,
return sctp_sf_pdiscard(ep, asoc, type, arg, commands); return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
from_addr = hbinfo->daddr; from_addr = hbinfo->daddr;
link = sctp_assoc_lookup_paddr(asoc, &from_addr); link = sctp_assoc_lookup_paddr(asoc, &from_addr);
/* This should never happen, but lets log it if so. */ /* This should never happen, but lets log it if so. */
...@@ -779,8 +748,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const sctp_endpoint_t *ep, ...@@ -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 * sent and mark the destination transport address as active if
* it is not so marked. * it is not so marked.
*/ */
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON, sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON, SCTP_TRANSPORT(link));
SCTP_TRANSPORT(link));
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
...@@ -810,7 +778,7 @@ static void sctp_tietags_populate(sctp_association_t *new_asoc, ...@@ -810,7 +778,7 @@ static void sctp_tietags_populate(sctp_association_t *new_asoc,
break; break;
/* 5.2.2 Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED, /* 5.2.2 Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED,
* COOKIE-WAIT and SHUTDOWN-ACK-SENT * COOKIE-WAIT and SHUTDOWN-ACK-SENT
*/ */
default: default:
new_asoc->c.my_ttag = asoc->c.my_vtag; new_asoc->c.my_ttag = asoc->c.my_vtag;
...@@ -843,10 +811,10 @@ static char sctp_tietags_compare(sctp_association_t *new_asoc, ...@@ -843,10 +811,10 @@ static char sctp_tietags_compare(sctp_association_t *new_asoc,
/* In this case, the peer may have restarted. */ /* In this case, the peer may have restarted. */
if ((asoc->c.my_vtag != new_asoc->c.my_vtag) && if ((asoc->c.my_vtag != new_asoc->c.my_vtag) &&
(asoc->c.peer_vtag != new_asoc->c.peer_vtag) && (asoc->c.peer_vtag != new_asoc->c.peer_vtag) &&
(asoc->c.my_vtag == new_asoc->c.my_ttag) && (asoc->c.my_vtag == new_asoc->c.my_ttag) &&
(asoc->c.peer_vtag == new_asoc->c.peer_ttag)) (asoc->c.peer_vtag == new_asoc->c.peer_ttag))
return 'A'; return 'A';
/* Collision case D. /* Collision case D.
* Note: Test case D first, otherwise it may be incorrectly * Note: Test case D first, otherwise it may be incorrectly
* identified as second case of B if the value of the Tie_tag is * identified as second case of B if the value of the Tie_tag is
...@@ -875,8 +843,10 @@ static char sctp_tietags_compare(sctp_association_t *new_asoc, ...@@ -875,8 +843,10 @@ static char sctp_tietags_compare(sctp_association_t *new_asoc,
/* Common helper routine for both duplicate and simulataneous INIT /* Common helper routine for both duplicate and simulataneous INIT
* chunk handling. * chunk handling.
*/ */
static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep, static sctp_disposition_t sctp_sf_do_unexpected_init(
const sctp_association_t *asoc, const sctp_subtype_t type, const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_subtype_t type,
void *arg, sctp_cmd_seq_t *commands) void *arg, sctp_cmd_seq_t *commands)
{ {
sctp_chunk_t *chunk = arg; sctp_chunk_t *chunk = arg;
...@@ -894,8 +864,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep, ...@@ -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; chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
/* Tag the variable length parameters. */ /* Tag the variable length parameters. */
chunk->param_hdr.v = chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
skb_pull(chunk->skb, sizeof(sctp_inithdr_t));
/* /*
* Other parameters for the endpoint SHOULD be copied from the * 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, ...@@ -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 * Verification Tag and Peers Verification tag into a reserved
* place (local tie-tag and per tie-tag) within the state cookie. * place (local tie-tag and per tie-tag) within the state cookie.
*/ */
sctp_process_init(new_asoc, chunk->chunk_hdr->type, sctp_process_init(new_asoc, chunk->chunk_hdr->type, sctp_source(chunk),
sctp_source(chunk), (sctp_init_chunk_t *)chunk->chunk_hdr, GFP_ATOMIC);
(sctp_init_chunk_t *)chunk->chunk_hdr,
GFP_ATOMIC);
sctp_tietags_populate(new_asoc, asoc); sctp_tietags_populate(new_asoc, asoc);
/* B) "Z" shall respond immediately with an INIT ACK chunk. */ /* B) "Z" shall respond immediately with an INIT ACK chunk. */
...@@ -927,7 +895,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep, ...@@ -927,7 +895,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
/* /*
* Note: After sending out INIT ACK with the State Cookie parameter, * Note: After sending out INIT ACK with the State Cookie parameter,
* "Z" MUST NOT allocate any resources for this new association. * "Z" MUST NOT allocate any resources for this new association.
* Otherwise, "Z" will be vulnerable to resource attacks. * Otherwise, "Z" will be vulnerable to resource attacks.
*/ */
...@@ -1072,7 +1040,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const sctp_endpoint_t *ep, ...@@ -1072,7 +1040,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const sctp_endpoint_t *ep,
list_for_each(pos, &new_asoc->peer.transport_addr_list) { list_for_each(pos, &new_asoc->peer.transport_addr_list) {
new_addr = list_entry(pos, sctp_transport_t, transports); new_addr = list_entry(pos, sctp_transport_t, transports);
found = 1; found = 1;
list_for_each_safe(pos2, temp, list_for_each_safe(pos2, temp,
&asoc->peer.transport_addr_list) { &asoc->peer.transport_addr_list) {
addr = list_entry(pos2, sctp_transport_t, transports); addr = list_entry(pos2, sctp_transport_t, transports);
if (!sctp_cmp_addr_exact(&new_addr->ipaddr, if (!sctp_cmp_addr_exact(&new_addr->ipaddr,
...@@ -1256,7 +1224,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const sctp_endpoint_t *ep, ...@@ -1256,7 +1224,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const sctp_endpoint_t *ep,
if (SCTP_STATE_ESTABLISHED != asoc->state) { if (SCTP_STATE_ESTABLISHED != asoc->state) {
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_ESTABLISHED)); SCTP_STATE(SCTP_STATE_ESTABLISHED));
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START,
SCTP_NULL()); SCTP_NULL());
/* RFC 2960 5.1 Normal Establishment of an Association /* RFC 2960 5.1 Normal Establishment of an Association
...@@ -1323,10 +1291,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep, ...@@ -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 /* "Decode" the chunk. We have no optional parameters so we
* are in good shape. * are in good shape.
*/ */
chunk->subh.cookie_hdr = chunk->subh.cookie_hdr = (sctp_signed_cookie_t *)chunk->skb->data;
(sctp_signed_cookie_t *) chunk->skb->data; skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie /* 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 * of a duplicate COOKIE ECHO match the Verification Tags of the
...@@ -1335,25 +1302,24 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep, ...@@ -1335,25 +1302,24 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
*/ */
new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error); new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error);
/* FIXME: /* FIXME:
* If the re-build failed, what is the proper error path * If the re-build failed, what is the proper error path
* from here? * from here?
* *
* [We should abort the association. --piggy] * [We should abort the association. --piggy]
*/ */
if (!new_asoc) { if (!new_asoc) {
/* FIXME: Several errors are possible. A bad cookie should /* FIXME: Several errors are possible. A bad cookie should
* be silently discarded, but think about logging it too. * be silently discarded, but think about logging it too.
*/ */
switch (error) { switch (error) {
case -SCTP_IERROR_NOMEM: case -SCTP_IERROR_NOMEM:
goto nomem; goto nomem;
case -SCTP_IERROR_BAD_SIG: case -SCTP_IERROR_BAD_SIG:
default: default:
return sctp_sf_pdiscard(ep, asoc, type, return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
arg, commands); };
};
} }
/* Compare the tie_tag in cookie with the verification tag of /* Compare the tie_tag in cookie with the verification tag of
...@@ -1398,6 +1364,65 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep, ...@@ -1398,6 +1364,65 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_NOMEM; 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 #if 0
/* /*
* Handle a Stale COOKIE Error * Handle a Stale COOKIE Error
...@@ -1442,7 +1467,7 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep, ...@@ -1442,7 +1467,7 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep,
__u8 *addrs; __u8 *addrs;
int addrs_len; int addrs_len;
time_t rtt; time_t rtt;
struct sctpCookiePreserve bht; struct sctpCookiePreserve bht;
/* If we have gotten too many failures, give up. */ /* If we have gotten too many failures, give up. */
if (1 + asoc->counters[SctpCounterInits] > asoc->max_init_attempts) { if (1 + asoc->counters[SctpCounterInits] > asoc->max_init_attempts) {
...@@ -1540,11 +1565,8 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const sctp_endpoint_t *ep, ...@@ -1540,11 +1565,8 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const sctp_endpoint_t *ep,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
/* Check the verification tag. */ /* ASSOC_FAILED will DELETE_TCB. */
/* BUG: WRITE ME. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 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());
/* BUG? This does not look complete... */ /* BUG? This does not look complete... */
return SCTP_DISPOSITION_ABORT; return SCTP_DISPOSITION_ABORT;
...@@ -1561,15 +1583,19 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const sctp_endpoint_t *ep, ...@@ -1561,15 +1583,19 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const sctp_endpoint_t *ep,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
/* Check the verification tag. */
/* BUG: WRITE ME. */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED)); SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
/* CMD_INIT_FAILED will DELETE_TCB. */ /* 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;
} }
/* /*
...@@ -1585,70 +1611,9 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const sctp_endpoint_t *ep, ...@@ -1585,70 +1611,9 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const sctp_endpoint_t *ep,
{ {
/* There is a single T1 timer, so we should be able to use /* There is a single T1 timer, so we should be able to use
* common function with the COOKIE-WAIT state. * common function with the COOKIE-WAIT state.
*/
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) { return sctp_sf_cookie_wait_abort(ep, asoc, type, arg, commands);
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 * sctp_sf_do_9_2_shut
...@@ -1694,7 +1659,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep, ...@@ -1694,7 +1659,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep,
sctp_disposition_t disposition; sctp_disposition_t disposition;
/* Convert the elaborate header. */ /* 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)); skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
chunk->subh.shutdown_hdr = sdh; chunk->subh.shutdown_hdr = sdh;
...@@ -1718,9 +1683,8 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep, ...@@ -1718,9 +1683,8 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep,
disposition = SCTP_DISPOSITION_CONSUME; disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outqueue_is_empty(&asoc->outqueue)) { if (sctp_outqueue_is_empty(&asoc->outqueue)) {
disposition = disposition = sctp_sf_do_9_2_shutdown_ack(ep, asoc, type,
sctp_sf_do_9_2_shutdown_ack(ep, asoc, type, arg, commands);
arg, commands);
} }
/* - verify, by checking the Cumulative TSN Ack field of the /* - verify, by checking the Cumulative TSN Ack field of the
...@@ -1732,6 +1696,42 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep, ...@@ -1732,6 +1696,42 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const sctp_endpoint_t *ep,
return disposition; 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 * sctp_sf_do_ecn_cwr
* *
...@@ -1780,7 +1780,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const sctp_endpoint_t *ep, ...@@ -1780,7 +1780,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const sctp_endpoint_t *ep,
cwr->lowest_tsn = ntohl(cwr->lowest_tsn); cwr->lowest_tsn = ntohl(cwr->lowest_tsn);
/* Does this CWR ack the last sent congestion notification? */ /* Does this CWR ack the last sent congestion notification? */
if (TSN_lte(asoc->last_ecne_tsn, cwr->lowest_tsn)) { if (TSN_lte(asoc->last_ecne_tsn, cwr->lowest_tsn)) {
/* Stop sending ECNE. */ /* Stop sending ECNE. */
sctp_add_cmd_sf(commands, sctp_add_cmd_sf(commands,
...@@ -1844,7 +1844,7 @@ sctp_disposition_t sctp_sf_do_ecne(const sctp_endpoint_t *ep, ...@@ -1844,7 +1844,7 @@ sctp_disposition_t sctp_sf_do_ecne(const sctp_endpoint_t *ep,
if (TSN_lt(asoc->last_cwr_tsn, ecne->lowest_tsn)) { if (TSN_lt(asoc->last_cwr_tsn, ecne->lowest_tsn)) {
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_ECNE, sctp_add_cmd_sf(commands, SCTP_CMD_ECN_ECNE,
SCTP_U32(ecne->lowest_tsn)); SCTP_U32(ecne->lowest_tsn));
} }
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
...@@ -1979,13 +1979,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep, ...@@ -1979,13 +1979,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
* processing the rest of the chunks in the packet. * 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_DISCARD_PACKET,SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
/* We are accepting this DATA chunk. */ /* We are accepting this DATA chunk. */
/* Record the fact that we have received this TSN. */ /* Record the fact that we have received this TSN. */
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
...@@ -2029,7 +2027,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep, ...@@ -2029,7 +2027,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const sctp_endpoint_t *ep,
* *
* The SCTP endpoint MUST always acknowledge the reception of * The SCTP endpoint MUST always acknowledge the reception of
* each valid DATA chunk. * each valid DATA chunk.
* *
* The guidelines on delayed acknowledgement algorithm * The guidelines on delayed acknowledgement algorithm
* specified in Section 4.2 of [RFC2581] SHOULD be followed. * specified in Section 4.2 of [RFC2581] SHOULD be followed.
* Specifically, an acknowledgement SHOULD be generated for at * Specifically, an acknowledgement SHOULD be generated for at
...@@ -2142,7 +2140,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep, ...@@ -2142,7 +2140,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep,
*/ */
if (!chunk->ecn_ce_done) { if (!chunk->ecn_ce_done) {
chunk->ecn_ce_done = 1; chunk->ecn_ce_done = 1;
if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) && if (INET_ECN_is_ce(chunk->skb->nh.iph->tos) &&
asoc->peer.ecn_capable) { asoc->peer.ecn_capable) {
/* Do real work as sideffect. */ /* Do real work as sideffect. */
sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
...@@ -2185,9 +2183,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const sctp_endpoint_t *ep, ...@@ -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. * 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_DISCARD_PACKET,SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
SCTP_STATE(SCTP_STATE_CLOSED));
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
...@@ -2296,14 +2292,12 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const sctp_endpoint_t *ep, ...@@ -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)) { if (TSN_lt(ctsn, asoc->ctsn_ack_point)) {
SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn); SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn);
SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point);
asoc->ctsn_ack_point);
return SCTP_DISPOSITION_DISCARD; return SCTP_DISPOSITION_DISCARD;
} }
/* Return this SACK for further processing. */ /* Return this SACK for further processing. */
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh));
SCTP_SACKH(sackh));
/* Note: We do the rest of the work on the PROCESS_SACK /* Note: We do the rest of the work on the PROCESS_SACK
* sideeffect. * sideeffect.
...@@ -2410,7 +2404,8 @@ sctp_disposition_t sctp_sf_operr_notify(const sctp_endpoint_t *ep, ...@@ -2410,7 +2404,8 @@ sctp_disposition_t sctp_sf_operr_notify(const sctp_endpoint_t *ep,
sctp_ulpevent_t *ev; sctp_ulpevent_t *ev;
while (chunk->chunk_end > chunk->skb->data) { 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) if (!ev)
goto nomem; goto nomem;
...@@ -2464,6 +2459,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const sctp_endpoint_t *ep, ...@@ -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_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 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, */ /* ...send a SHUTDOWN COMPLETE chunk to its peer, */
reply = sctp_make_shutdown_complete(asoc, chunk); reply = sctp_make_shutdown_complete(asoc, chunk);
if (!reply) if (!reply)
...@@ -2524,7 +2522,7 @@ sctp_disposition_t sctp_sf_ootb(const sctp_endpoint_t *ep, ...@@ -2524,7 +2522,7 @@ sctp_disposition_t sctp_sf_ootb(const sctp_endpoint_t *ep,
if (ootb_shut_ack) if (ootb_shut_ack)
sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands);
else else
sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
return sctp_sf_pdiscard(ep, asoc, type, arg, commands); return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
} }
...@@ -2616,6 +2614,148 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const sctp_endpoint_t *ep, ...@@ -2616,6 +2614,148 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const sctp_endpoint_t *ep,
nomem: nomem:
return SCTP_DISPOSITION_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 #if 0
/* /*
...@@ -2821,7 +2961,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep, ...@@ -2821,7 +2961,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep,
* or else move the association allocation/init into this function. * or else move the association allocation/init into this function.
* The association structure is brand new before calling this * The association structure is brand new before calling this
* function, so would not be a sideeffect if the allocation * function, so would not be a sideeffect if the allocation
* moved into this function. --jgrimm * moved into this function. --jgrimm
*/ */
sctp_add_cmd_sf(commands, SCTP_CMD_SET_BIND_ADDR, (sctp_arg_t) bp); sctp_add_cmd_sf(commands, SCTP_CMD_SET_BIND_ADDR, (sctp_arg_t) bp);
...@@ -2974,13 +3114,19 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown(const sctp_endpoint_t *ep, ...@@ -2974,13 +3114,19 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown(const sctp_endpoint_t *ep,
* if necessary to fill gaps. * if necessary to fill gaps.
*/ */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); 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; disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outqueue_is_empty(&asoc->outqueue)) { if (sctp_outqueue_is_empty(&asoc->outqueue)) {
disposition = disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
sctp_sf_do_9_2_start_shutdown(ep, asoc, type, arg, commands);
arg, commands);
} }
return disposition; return disposition;
} }
...@@ -3034,7 +3180,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(const sctp_endpoint_t *ep, ...@@ -3034,7 +3180,7 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(const sctp_endpoint_t *ep,
/* Generate ABORT chunk to send the peer. */ /* Generate ABORT chunk to send the peer. */
abort = sctp_make_abort(asoc, NULL, 0); abort = sctp_make_abort(asoc, NULL, 0);
if (!abort) if (!abort)
retval = SCTP_DISPOSITION_NOMEM; retval = SCTP_DISPOSITION_NOMEM;
else else
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
...@@ -3042,12 +3188,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(const sctp_endpoint_t *ep, ...@@ -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. * TCB. This is a departure from our typical NOMEM handling.
*/ */
/* Change to CLOSED state. */ /* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_NULL());
SCTP_STATE(SCTP_STATE_CLOSED));
/* Delete the established association. */
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
return retval; return retval;
} }
...@@ -3090,11 +3232,12 @@ sctp_disposition_t sctp_sf_error_shutdown(const sctp_endpoint_t *ep, ...@@ -3090,11 +3232,12 @@ sctp_disposition_t sctp_sf_error_shutdown(const sctp_endpoint_t *ep,
* Outputs * Outputs
* (timers) * (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_association_t *asoc, const sctp_endpoint_t *ep,
const sctp_subtype_t type, const sctp_association_t *asoc,
void *arg, const sctp_subtype_t type,
sctp_cmd_seq_t *commands) void *arg,
sctp_cmd_seq_t *commands)
{ {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
...@@ -3134,7 +3277,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown( ...@@ -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 * Section: 4 Note: 2
* Verification Tag: * Verification Tag:
...@@ -3148,19 +3291,41 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown( ...@@ -3148,19 +3291,41 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown(
* (timers) * (timers)
*/ */
sctp_disposition_t sctp_sf_cookie_wait_prm_abort(const sctp_endpoint_t *ep, sctp_disposition_t sctp_sf_cookie_wait_prm_abort(const sctp_endpoint_t *ep,
const sctp_association_t *asoc, const sctp_association_t *asoc,
const sctp_subtype_t type, const sctp_subtype_t type,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
sctp_chunk_t *abort;
sctp_disposition_t retval;
/* Stop T1-init timer */ /* Stop T1-init timer */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 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 * Section: 4 Note: 3
* Verification Tag: * Verification Tag:
...@@ -3174,10 +3339,10 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(const sctp_endpoint_t *ep, ...@@ -3174,10 +3339,10 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(const sctp_endpoint_t *ep,
* (timers) * (timers)
*/ */
sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(const sctp_endpoint_t *ep, sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(const sctp_endpoint_t *ep,
const sctp_association_t *asoc, const sctp_association_t *asoc,
const sctp_subtype_t type, const sctp_subtype_t type,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
/* There is a single T1 timer, so we should be able to use /* There is a single T1 timer, so we should be able to use
* common function with the COOKIE-WAIT state. * common function with the COOKIE-WAIT state.
...@@ -3185,6 +3350,87 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_abort(const sctp_endpoint_t *ep, ...@@ -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); 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 * Ignore the primitive event
* *
...@@ -3218,10 +3464,10 @@ sctp_disposition_t sctp_sf_ignore_primitive(const sctp_endpoint_t *ep, ...@@ -3218,10 +3464,10 @@ sctp_disposition_t sctp_sf_ignore_primitive(const sctp_endpoint_t *ep,
* The return value is the disposition. * The return value is the disposition.
*/ */
sctp_disposition_t sctp_sf_do_9_2_start_shutdown(const sctp_endpoint_t *ep, sctp_disposition_t sctp_sf_do_9_2_start_shutdown(const sctp_endpoint_t *ep,
const sctp_association_t *asoc, const sctp_association_t *asoc,
const sctp_subtype_t type, const sctp_subtype_t type,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
sctp_chunk_t *reply; sctp_chunk_t *reply;
...@@ -3236,7 +3482,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(const sctp_endpoint_t *ep, ...@@ -3236,7 +3482,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(const sctp_endpoint_t *ep,
/* Set the transport for the SHUTDOWN chunk and the timeout for the /* Set the transport for the SHUTDOWN chunk and the timeout for the
* T2-shutdown timer. * T2-shutdown timer.
*/ */
sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply));
/* It shall then start the T2-shutdown timer */ /* It shall then start the T2-shutdown timer */
...@@ -3322,8 +3568,7 @@ sctp_disposition_t sctp_sf_ignore_other(const sctp_endpoint_t *ep, ...@@ -3322,8 +3568,7 @@ sctp_disposition_t sctp_sf_ignore_other(const sctp_endpoint_t *ep,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
SCTP_DEBUG_PRINTK("The event other type %d is ignored\n", SCTP_DEBUG_PRINTK("The event other type %d is ignored\n", type.other);
type.other);
return SCTP_DISPOSITION_DISCARD; return SCTP_DISPOSITION_DISCARD;
} }
...@@ -3413,7 +3658,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const sctp_endpoint_t *ep, ...@@ -3413,7 +3658,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const sctp_endpoint_t *ep,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
...@@ -3479,11 +3724,11 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep, ...@@ -3479,11 +3724,11 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep,
if (!repl) if (!repl)
goto nomem; goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
/* Issue a sideeffect to do the needed accounting. */ /* Issue a sideeffect to do the needed accounting. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
SCTP_TO(timer)); SCTP_TO(timer));
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
} else { } else {
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; return SCTP_DISPOSITION_DELETE_TCB;
...@@ -3559,16 +3804,44 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const sctp_endpoint_t *ep, ...@@ -3559,16 +3804,44 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_NOMEM; 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, /* Handle expiration of AUTOCLOSE timer. When the autoclose timer expires,
* the association is automatically closed by starting the shutdown process. * 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 * The work that needs to be done is same as when SHUTDOWN is initiated by
* the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown(). * the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown().
*/ */
sctp_disposition_t sctp_sf_autoclose_timer_expire(const sctp_endpoint_t *ep, sctp_disposition_t sctp_sf_autoclose_timer_expire(const sctp_endpoint_t *ep,
const sctp_association_t *asoc, const sctp_association_t *asoc,
const sctp_subtype_t type, const sctp_subtype_t type,
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
int disposition; int disposition;
...@@ -3583,11 +3856,16 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(const sctp_endpoint_t *ep, ...@@ -3583,11 +3856,16 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); 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; disposition = SCTP_DISPOSITION_CONSUME;
if (sctp_outqueue_is_empty(&asoc->outqueue)) { if (sctp_outqueue_is_empty(&asoc->outqueue)) {
disposition = disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type,
sctp_sf_do_9_2_start_shutdown(ep, asoc, type, arg, commands);
arg, commands);
} }
return disposition; return disposition;
} }
...@@ -3651,30 +3929,6 @@ sctp_disposition_t sctp_sf_timer_ignore(const sctp_endpoint_t *ep, ...@@ -3651,30 +3929,6 @@ sctp_disposition_t sctp_sf_timer_ignore(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_CONSUME; 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 * 2nd Level Abstractions
********************************************************************/ ********************************************************************/
......
...@@ -4,36 +4,36 @@ ...@@ -4,36 +4,36 @@
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These are the state tables for the SCTP state machine. * These are the state tables for the SCTP state machine.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
...@@ -48,9 +48,10 @@ ...@@ -48,9 +48,10 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
sctp_sm_table_entry_t nop = {fn: sctp_sf_discard_chunk, sctp_sm_table_entry_t bug = {
name: "sctp_sf_discard_chunk"}; .fn = sctp_sf_bug,
sctp_sm_table_entry_t bug = {fn: sctp_sf_bug, name: "sctp_sf_bug"}; .name = "sctp_sf_bug"
};
#define DO_LOOKUP(_max, _type, _table) \ #define DO_LOOKUP(_max, _type, _table) \
if ((event_subtype._type > (_max))) { \ if ((event_subtype._type > (_max))) { \
...@@ -58,9 +59,9 @@ sctp_sm_table_entry_t bug = {fn: sctp_sf_bug, name: "sctp_sf_bug"}; ...@@ -58,9 +59,9 @@ sctp_sm_table_entry_t bug = {fn: sctp_sf_bug, name: "sctp_sf_bug"};
"sctp table %p possible attack:" \ "sctp table %p possible attack:" \
" event %d exceeds max %d\n", \ " event %d exceeds max %d\n", \
_table, event_subtype._type, _max); \ _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_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
sctp_state_t state, sctp_state_t state,
...@@ -71,7 +72,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, ...@@ -71,7 +72,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
return sctp_chunk_event_lookup(event_subtype.chunk, state); return sctp_chunk_event_lookup(event_subtype.chunk, state);
break; break;
case SCTP_EVENT_T_TIMEOUT: case SCTP_EVENT_T_TIMEOUT:
DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout, DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout,
timeout_event_table); timeout_event_table);
break; break;
...@@ -92,320 +93,323 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, ...@@ -92,320 +93,323 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
#define TYPE_SCTP_DATA { \ #define TYPE_SCTP_DATA { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_DATA */
#define TYPE_SCTP_INIT { \ #define TYPE_SCTP_INIT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_INIT */
#define TYPE_SCTP_INIT_ACK { \ #define TYPE_SCTP_INIT_ACK { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_INIT_ACK */
#define TYPE_SCTP_SACK { \ #define TYPE_SCTP_SACK { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_SACK */
#define TYPE_SCTP_HEARTBEAT { \ #define TYPE_SCTP_HEARTBEAT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
/* This should not happen, but we are nice. */ \ /* 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 */ } /* TYPE_SCTP_HEARTBEAT */
#define TYPE_SCTP_HEARTBEAT_ACK { \ #define TYPE_SCTP_HEARTBEAT_ACK { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \ {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_HEARTBEAT_ACK */
#define TYPE_SCTP_ABORT { \ #define TYPE_SCTP_ABORT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_pdiscard, name: "sctp_sf_pdiscard"}, \ {.fn = sctp_sf_pdiscard, .name = "sctp_sf_pdiscard"}, \
/* SCTP_STATE_COOKIE_WAIT */ \ /* 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 */ \ /* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_cookie_echoed_abort, \ {.fn = sctp_sf_cookie_echoed_abort, \
name: "sctp_sf_cookie_echoed_abort"}, \ .name = "sctp_sf_cookie_echoed_abort"}, \
/* SCTP_STATE_ESTABLISHED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_ABORT */
#define TYPE_SCTP_SHUTDOWN { \ #define TYPE_SCTP_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_9_2_shutdown_ack, \ {.fn = sctp_sf_do_9_2_shutdown_ack, \
name: "sctp_sf_do_9_2_shutdown_ack"}, \ .name = "sctp_sf_do_9_2_shutdown_ack"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_SHUTDOWN */
#define TYPE_SCTP_SHUTDOWN_ACK { \ #define TYPE_SCTP_SHUTDOWN_ACK { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \ {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \ /* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_violation, name: "sctp_sf_violation"}, \ {.fn = sctp_sf_violation, .name = "sctp_sf_violation"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_SHUTDOWN_ACK */
#define TYPE_SCTP_ERROR { \ #define TYPE_SCTP_ERROR { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_ERROR */
#define TYPE_SCTP_COOKIE_ECHO { \ #define TYPE_SCTP_COOKIE_ECHO { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_COOKIE_ECHO */
#define TYPE_SCTP_COOKIE_ACK { \ #define TYPE_SCTP_COOKIE_ACK { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_COOKIE_ACK */
#define TYPE_SCTP_ECN_ECNE { \ #define TYPE_SCTP_ECN_ECNE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_WAIT */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_ECN_ECNE */
#define TYPE_SCTP_ECN_CWR { \ #define TYPE_SCTP_ECN_CWR { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_ECN_CWR */
#define TYPE_SCTP_SHUTDOWN_COMPLETE { \ #define TYPE_SCTP_SHUTDOWN_COMPLETE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_ootb, name: "sctp_sf_ootb"}, \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_SHUTDOWN_COMPLETE */
/* The primary index for this table is the chunk type. /* 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 ...@@ -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 static sctp_sm_table_entry_t
chunk_event_table_asconf[SCTP_STATE_NUM_STATES] = { chunk_event_table_asconf[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* SCTP_STATE_ESTABLISHED */
{fn: sctp_sf_discard_chunk, {.fn = sctp_sf_discard_chunk,
name: "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"}, .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"},
/* SCTP_STATE_SHUTDOWN_PENDING */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ }; /* chunk asconf */
static sctp_sm_table_entry_t static sctp_sm_table_entry_t
chunk_event_table_asconf_ack[SCTP_STATE_NUM_STATES] = { chunk_event_table_asconf_ack[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* SCTP_STATE_ESTABLISHED */
{fn: sctp_sf_discard_chunk, {.fn = sctp_sf_discard_chunk,
name: "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"}, .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"},
/* SCTP_STATE_SHUTDOWN_PENDING */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ }; /* 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 { \ #define TYPE_SCTP_PRIMITIVE_INITIALIZE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_INITIALIZE */
#define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \ #define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */
#define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \ #define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_cookie_wait_prm_shutdown, \ {.fn = sctp_sf_cookie_wait_prm_shutdown, \
name: "sctp_sf_cookie_wait_prm_shutdown"}, \ .name = "sctp_sf_cookie_wait_prm_shutdown"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* 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"},\ name:"sctp_sf_cookie_echoed_prm_shutdown"},\
/* SCTP_STATE_ESTABLISHED */ \ /* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_9_2_prm_shutdown, \ {.fn = sctp_sf_do_9_2_prm_shutdown, \
name: "sctp_sf_do_9_2_prm_shutdown"}, \ .name = "sctp_sf_do_9_2_prm_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */
#define TYPE_SCTP_PRIMITIVE_ABORT { \ #define TYPE_SCTP_PRIMITIVE_ABORT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_cookie_wait_prm_abort, \ {.fn = sctp_sf_cookie_wait_prm_abort, \
name: "sctp_sf_cookie_wait_prm_abort"}, \ .name = "sctp_sf_cookie_wait_prm_abort"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_cookie_echoed_prm_abort, \ {.fn = sctp_sf_cookie_echoed_prm_abort, \
name: "sctp_sf_cookie_echoed_prm_abort"}, \ .name = "sctp_sf_cookie_echoed_prm_abort"}, \
/* SCTP_STATE_ESTABLISHED */ \ /* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_do_9_1_prm_abort, \ {.fn = sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \ .name = "sctp_sf_do_9_1_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \ /* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_9_1_prm_abort, \ {.fn = sctp_sf_shutdown_pending_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \ .name = "sctp_sf_shutdown_pending_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \ /* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_do_9_1_prm_abort, \ {.fn = sctp_sf_shutdown_sent_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \ .name = "sctp_sf_shutdown_sent_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_9_1_prm_abort, \ {.fn = sctp_sf_do_9_1_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \ .name = "sctp_sf_do_9_1_prm_abort"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_do_9_1_prm_abort, \ {.fn = sctp_sf_shutdown_ack_sent_prm_abort, \
name: "sctp_sf_do_9_1_prm_abort"}, \ .name = "sctp_sf_shutdown_ack_sent_prm_abort"}, \
} /* TYPE_SCTP_PRIMITIVE_ABORT */ } /* TYPE_SCTP_PRIMITIVE_ABORT */
#define TYPE_SCTP_PRIMITIVE_SEND { \ #define TYPE_SCTP_PRIMITIVE_SEND { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_SEND */
#define TYPE_SCTP_PRIMITIVE_SETPRIMARY { \ #define TYPE_SCTP_PRIMITIVE_SETPRIMARY { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_SETPRIMARY */
#define TYPE_SCTP_PRIMITIVE_RECEIVE { \ #define TYPE_SCTP_PRIMITIVE_RECEIVE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_RECEIVE */
#define TYPE_SCTP_PRIMITIVE_STATUS { \ #define TYPE_SCTP_PRIMITIVE_STATUS { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_STATUS */
#define TYPE_SCTP_PRIMITIVE_CHANGEHEARTBEAT { \ #define TYPE_SCTP_PRIMITIVE_CHANGEHEARTBEAT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_CHANGEHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \ #define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */
#define TYPE_SCTP_PRIMITIVE_GETSRTTREPORT { \ #define TYPE_SCTP_PRIMITIVE_GETSRTTREPORT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_GETSRTTREPORT */
#define TYPE_SCTP_PRIMITIVE_SETFAILURETHRESHOLD { \ #define TYPE_SCTP_PRIMITIVE_SETFAILURETHRESHOLD { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_SETFAILURETHRESHOLD */
#define TYPE_SCTP_PRIMITIVE_SETPROTOPARAMETERS { \ #define TYPE_SCTP_PRIMITIVE_SETPROTOPARAMETERS { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_SETPROTOPARAMETERS */
#define TYPE_SCTP_PRIMITIVE_RECEIVE_UNSENT { \ #define TYPE_SCTP_PRIMITIVE_RECEIVE_UNSENT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_RECEIVE_UNSENT */
#define TYPE_SCTP_PRIMITIVE_RECEIVE_UNACKED { \ #define TYPE_SCTP_PRIMITIVE_RECEIVE_UNACKED { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_RECEIVE_UNACKED */
#define TYPE_SCTP_PRIMITIVE_DESTROY { \ #define TYPE_SCTP_PRIMITIVE_DESTROY { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ } /* TYPE_SCTP_PRIMITIVE_DESTROY */
/* The primary index for this table is the primitive type. /* 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 ...@@ -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 { \ #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_do_9_2_start_shutdown, \ {.fn = sctp_sf_do_9_2_start_shutdown, \
name: "sctp_do_9_2_start_shutdown"}, \ .name = "sctp_do_9_2_start_shutdown"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \ /* 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 */ \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_do_9_2_shutdown_ack, \ {.fn = sctp_sf_do_9_2_shutdown_ack, \
name: "sctp_sf_do_9_2_shutdown_ack"}, \ .name = "sctp_sf_do_9_2_shutdown_ack"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ /* 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 { \ #define TYPE_SCTP_OTHER_ICMP_UNREACHFRAG { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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] = { 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 ...@@ -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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_NONE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_WAIT */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_ESTABLISHED */ \ /* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \ /* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \ /* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \
/* SCTP_STATE_EMPTY */ \ /* 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"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_ESTABLISHED */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{.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"}, \
}
#define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \
/* SCTP_STATE_EMPTY */ \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* SCTP_STATE_CLOSED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \ /* SCTP_STATE_COOKIE_WAIT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \ /* SCTP_STATE_COOKIE_ECHOED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \ /* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \ /* SCTP_STATE_SHUTDOWN_PENDING */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_SENT */ \ /* SCTP_STATE_SHUTDOWN_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
{fn: sctp_sf_not_impl, name: "sctp_sf_not_impl"}, \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
} }
#define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \ #define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_SACK { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \
/* SCTP_STATE_EMPTY */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* SCTP_STATE_ESTABLISHED */ \
{fn: sctp_sf_autoclose_timer_expire, \ {.fn = sctp_sf_autoclose_timer_expire, \
name: "sctp_sf_autoclose_timer_expire"}, \ .name = "sctp_sf_autoclose_timer_expire"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 { \ #define TYPE_SCTP_EVENT_TIMEOUT_PMTU_RAISE { \
/* SCTP_STATE_EMPTY */ \ /* SCTP_STATE_EMPTY */ \
{fn: sctp_sf_bug, name: "sctp_sf_bug"}, \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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 */ \ /* 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] = { 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 ...@@ -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_T2_SHUTDOWN,
TYPE_SCTP_EVENT_TIMEOUT_T3_RTX, TYPE_SCTP_EVENT_TIMEOUT_T3_RTX,
TYPE_SCTP_EVENT_TIMEOUT_T4_RTO, TYPE_SCTP_EVENT_TIMEOUT_T4_RTO,
TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT, TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT,
TYPE_SCTP_EVENT_TIMEOUT_SACK, TYPE_SCTP_EVENT_TIMEOUT_SACK,
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE, TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
...@@ -1125,12 +1169,11 @@ sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM ...@@ -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) sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, sctp_state_t state)
{ {
if (state > SCTP_STATE_MAX) if (state > SCTP_STATE_MAX)
BUG(); return &bug;
if (cid < 0)
return &nop;
if (cid <= SCTP_CID_BASE_MAX) if (cid >= 0 && cid <= SCTP_CID_BASE_MAX) {
return &chunk_event_table[cid][state]; return &chunk_event_table[cid][state];
}
switch (cid) { switch (cid) {
case SCTP_CID_ASCONF: 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 ...@@ -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: case SCTP_CID_ASCONF_ACK:
return &chunk_event_table_asconf_ack[state]; return &chunk_event_table_asconf_ack[state];
default: default:
return &nop; return &chunk_event_table_unknown[state];
}; }
return &nop;
} }
/* Copyright (c) 1999-2000 Cisco, Inc. /* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001-2002 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001-2002 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001-2002 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
...@@ -82,8 +82,6 @@ static void sctp_wfree(struct sk_buff *skb); ...@@ -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, static int sctp_wait_for_sndbuf(sctp_association_t *asoc, long *timeo_p,
int msg_len); int msg_len);
static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p); 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 *, static inline void sctp_sk_addr_set(struct sock *,
const sockaddr_storage_t *newaddr, const sockaddr_storage_t *newaddr,
sockaddr_storage_t *saveaddr); sockaddr_storage_t *saveaddr);
...@@ -121,7 +119,7 @@ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -121,7 +119,7 @@ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
/* Disallow binding twice. */ /* Disallow binding twice. */
if (!sctp_sk(sk)->ep->base.bind_addr.port) if (!sctp_sk(sk)->ep->base.bind_addr.port)
retval = sctp_do_bind(sk, (sockaddr_storage_t *)uaddr, retval = sctp_do_bind(sk, (sockaddr_storage_t *)uaddr,
addr_len); addr_len);
else else
retval = -EINVAL; retval = -EINVAL;
...@@ -317,7 +315,7 @@ static int sctp_do_bind(struct sock *sk, sockaddr_storage_t *newaddr, int addr_l ...@@ -317,7 +315,7 @@ static int sctp_do_bind(struct sock *sk, sockaddr_storage_t *newaddr, int addr_l
/* Unprotected by locks. Call only with socket lock sk->lock held! See /* Unprotected by locks. Call only with socket lock sk->lock held! See
* sctp_bindx() for a lock-protected call. * sctp_bindx() for a lock-protected call.
*/ */
static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs,
int addrcnt, int flags) int addrcnt, int flags)
...@@ -326,11 +324,11 @@ static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, ...@@ -326,11 +324,11 @@ static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs,
SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, " SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, "
"flags: %s)\n", sk, addrs, addrcnt, "flags: %s)\n", sk, addrs, addrcnt,
(BINDX_ADD_ADDR == flags)?"ADD": (BINDX_ADD_ADDR == flags) ? "ADD" :
((BINDX_REM_ADDR == flags)?"REM":"BOGUS")); ((BINDX_REM_ADDR == flags) ? "REM" : "BOGUS"));
switch (flags) { switch (flags) {
case BINDX_ADD_ADDR: case BINDX_ADD_ADDR:
retval = sctp_bindx_add(sk, addrs, addrcnt); retval = sctp_bindx_add(sk, addrs, addrcnt);
break; break;
...@@ -411,7 +409,7 @@ int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) ...@@ -411,7 +409,7 @@ int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
sctp_bindx_rem(sk, addrs, cnt); sctp_bindx_rem(sk, addrs, cnt);
return retval; return retval;
} }
} }
/* Notify the peer(s), assuming we have (an) association(s). /* Notify the peer(s), assuming we have (an) association(s).
* FIXME: for UDP, we have a 1-1-many mapping amongst sk, ep and asoc, * FIXME: for UDP, we have a 1-1-many mapping amongst sk, ep and asoc,
...@@ -500,9 +498,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) ...@@ -500,9 +498,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt)
case AF_INET: case AF_INET:
saveaddr = *((sockaddr_storage_t *) saveaddr = *((sockaddr_storage_t *)
&addrs[cnt]); &addrs[cnt]);
saveaddr.v4.sin_port = saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
ntohs(saveaddr.v4.sin_port); /* Verify the port. */
/* verify the port */
if (saveaddr.v4.sin_port != bp->port) { if (saveaddr.v4.sin_port != bp->port) {
retval = -EINVAL; retval = -EINVAL;
goto err_bindx_rem; goto err_bindx_rem;
...@@ -606,7 +603,8 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) ...@@ -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. * 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) int addrssize, int op)
{ {
struct sockaddr_storage *kaddrs; struct sockaddr_storage *kaddrs;
...@@ -614,8 +612,7 @@ static int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr_storage *addrs ...@@ -614,8 +612,7 @@ static int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr_storage *addrs
size_t addrcnt; size_t addrcnt;
SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p" SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p"
" addrssize %d opt %d\n", sk, addrs, " addrssize %d opt %d\n", sk, addrs, addrssize, op);
addrssize, op);
/* Do we have an integer number of structs sockaddr_storage? */ /* Do we have an integer number of structs sockaddr_storage? */
if (unlikely(addrssize <= 0 || if (unlikely(addrssize <= 0 ||
...@@ -781,7 +778,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -781,7 +778,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
memcpy(&to, msg->msg_name, msg->msg_namelen); memcpy(&to, msg->msg_name, msg->msg_namelen);
SCTP_DEBUG_PRINTK("Just memcpy'd. msg_name is " SCTP_DEBUG_PRINTK("Just memcpy'd. msg_name is "
"0x%x:%u.\n", "0x%x:%u.\n",
to.v4.sin_addr.s_addr, to.v4.sin_port); to.v4.sin_addr.s_addr, to.v4.sin_port);
to.v4.sin_port = ntohs(to.v4.sin_port); to.v4.sin_port = ntohs(to.v4.sin_port);
...@@ -823,14 +820,14 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -823,14 +820,14 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
} else { } else {
/* For a peeled-off socket, ignore any associd specified by /* For a peeled-off socket, ignore any associd specified by
* the user with SNDRCVINFO. * the user with SNDRCVINFO.
*/ */
if (SCTP_SOCKET_UDP_HIGH_BANDWIDTH == sp->type) { if (SCTP_SOCKET_UDP_HIGH_BANDWIDTH == sp->type) {
if (list_empty(&ep->asocs)) { if (list_empty(&ep->asocs)) {
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_unlock;
} }
asoc = list_entry(ep->asocs.next, sctp_association_t, asoc = list_entry(ep->asocs.next, sctp_association_t,
asocs); asocs);
} else if (associd) { } else if (associd) {
asoc = sctp_id2assoc(sk, associd); asoc = sctp_id2assoc(sk, associd);
} }
...@@ -851,7 +848,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -851,7 +848,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
goto out_unlock; goto out_unlock;
} }
if (sinfo_flags & MSG_ABORT) { 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); sctp_primitive_ABORT(asoc, NULL);
err = 0; err = 0;
goto out_unlock; goto out_unlock;
...@@ -866,8 +863,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -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. * either the default or the user specified stream counts.
*/ */
if (sinfo) { if (sinfo) {
if (!sinit || if (!sinit || (sinit && !sinit->sinit_num_ostreams)) {
(sinit && !sinit->sinit_num_ostreams)) {
/* Check against the defaults. */ /* Check against the defaults. */
if (sinfo->sinfo_stream >= if (sinfo->sinfo_stream >=
sp->initmsg.sinit_num_ostreams) { sp->initmsg.sinit_num_ostreams) {
...@@ -988,7 +984,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -988,7 +984,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
/* If the user didn't specify SNDRCVINFO, make up one with /* If the user didn't specify SNDRCVINFO, make up one with
* some defaults. * some defaults.
*/ */
default_sinfo.sinfo_stream = asoc->defaults.stream; default_sinfo.sinfo_stream = asoc->defaults.stream;
default_sinfo.sinfo_ppid = asoc->defaults.ppid; default_sinfo.sinfo_ppid = asoc->defaults.ppid;
sinfo = &default_sinfo; sinfo = &default_sinfo;
} }
...@@ -1011,7 +1007,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -1011,7 +1007,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
/* FIXME: This looks wrong so I'll comment out. /* FIXME: This looks wrong so I'll comment out.
* We should be able to use this same technique for * We should be able to use this same technique for
* primary address override! --jgrimm * primary address override! --jgrimm
*/ */
/* If the user gave us an address, copy it in. */ /* If the user gave us an address, copy it in. */
if (msg->msg_name) { if (msg->msg_name) {
chunk->transport = sctp_assoc_lookup_paddr(asoc, &to); chunk->transport = sctp_assoc_lookup_paddr(asoc, &to);
...@@ -1025,7 +1021,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -1025,7 +1021,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
/* Copy the message from the user. */ /* Copy the message from the user. */
err = sctp_user_addto_chunk(chunk, msg_len, msg->msg_iov); err = sctp_user_addto_chunk(chunk, msg_len, msg->msg_iov);
if (err < 0) if (err < 0)
goto out_free; goto out_free;
SCTP_DEBUG_PRINTK("Copied message to chunk: %p.\n", chunk); SCTP_DEBUG_PRINTK("Copied message to chunk: %p.\n", chunk);
...@@ -1096,12 +1092,13 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -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 * flags - flags sent or received with the user message, see Section
* 5 for complete description of the flags. * 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, static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
int noblock, int flags, int *addr_len) int noblock, int flags, int *addr_len)
{ {
sctp_ulpevent_t *event = NULL; sctp_ulpevent_t *event = NULL;
sctp_opt_t *sp = sctp_sk(sk);
struct sk_buff *skb; struct sk_buff *skb;
int copied; int copied;
int err = 0; int err = 0;
...@@ -1147,19 +1144,16 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len, ...@@ -1147,19 +1144,16 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
sock_recv_timestamp(msg, sk, skb); sock_recv_timestamp(msg, sk, skb);
if (sctp_ulpevent_is_notification(event)) { if (sctp_ulpevent_is_notification(event)) {
msg->msg_flags |= MSG_NOTIFICATION; msg->msg_flags |= MSG_NOTIFICATION;
sp->pf->event_msgname(event, msg->msg_name, addr_len);
} else { } else {
/* Copy the address. */ sp->pf->skb_msgname(skb, msg->msg_name, addr_len);
if (addr_len && msg->msg_name)
sctp_sk_memcpy_msgname(sk, msg->msg_name,
addr_len, skb);
} }
/* Check if we allow SCTP_SNDRCVINFO. */ /* 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); sctp_ulpevent_read_sndrcvinfo(event, msg);
#if 0 #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) if (sk->protinfo.af_inet.cmsg_flags)
ip_cmsg_recv(msg, skb); ip_cmsg_recv(msg, skb);
#endif #endif
...@@ -1176,7 +1170,8 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len, ...@@ -1176,7 +1170,8 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
return err; 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; int val;
...@@ -1191,7 +1186,8 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk, char *optva ...@@ -1191,7 +1186,8 @@ static inline int sctp_setsockopt_disable_fragments(struct sock *sk, char *optva
return 0; 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)) if (optlen != sizeof(struct sctp_event_subscribe))
return -EINVAL; return -EINVAL;
...@@ -1200,7 +1196,8 @@ static inline int sctp_setsockopt_set_events(struct sock *sk, char *optval, int ...@@ -1200,7 +1196,8 @@ static inline int sctp_setsockopt_set_events(struct sock *sk, char *optval, int
return 0; 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); sctp_opt_t *sp = sctp_sk(sk);
...@@ -1236,7 +1233,7 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, ...@@ -1236,7 +1233,7 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
char *optval, int optlen) char *optval, int optlen)
{ {
int retval = 0; int retval = 0;
char * tmp; char *tmp;
sctp_protocol_t *proto = sctp_get_protocol(); sctp_protocol_t *proto = sctp_get_protocol();
struct list_head *pos; struct list_head *pos;
sctp_func_t *af; sctp_func_t *af;
...@@ -1332,7 +1329,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err) ...@@ -1332,7 +1329,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err)
{ {
int error = -EOPNOTSUPP; int error = -EOPNOTSUPP;
*err = error; *err = error;
return NULL; return NULL;
} }
...@@ -1356,19 +1353,9 @@ static int sctp_init_sock(struct sock *sk) ...@@ -1356,19 +1353,9 @@ static int sctp_init_sock(struct sock *sk)
proto = sctp_get_protocol(); 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); sp = sctp_sk(sk);
/* Initialize the SCTP per socket area. */ /* Initialize the SCTP per socket area. */
sp->ep = ep;
sp->type = SCTP_SOCKET_UDP; sp->type = SCTP_SOCKET_UDP;
/* FIXME: The next draft (04) of the SCTP Sockets Extensions /* FIXME: The next draft (04) of the SCTP Sockets Extensions
...@@ -1425,6 +1412,16 @@ static int sctp_init_sock(struct sock *sk) ...@@ -1425,6 +1412,16 @@ static int sctp_init_sock(struct sock *sk)
* for UDP-style sockets only. * for UDP-style sockets only.
*/ */
sp->autoclose = 0; 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); SCTP_DBG_OBJCNT_INC(sock);
return 0; return 0;
...@@ -1836,8 +1833,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum) ...@@ -1836,8 +1833,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum)
case PF_INET6: case PF_INET6:
SCTP_V6(tmpaddr.v6.sin6_family = AF_INET6; SCTP_V6(tmpaddr.v6.sin6_family = AF_INET6;
tmpaddr.v6.sin6_port = snum; tmpaddr.v6.sin6_port = snum;
tmpaddr.v6.sin6_addr = tmpaddr.v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
inet6_sk(sk)->rcv_saddr;
) )
break; break;
...@@ -1855,7 +1851,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum) ...@@ -1855,7 +1851,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum)
* that this port/socket (sk) combination are already * that this port/socket (sk) combination are already
* in an endpoint. * in an endpoint.
*/ */
for( ; sk2 != NULL; sk2 = sk2->bind_next) { for ( ; sk2 != NULL; sk2 = sk2->bind_next) {
sctp_endpoint_t *ep2; sctp_endpoint_t *ep2;
ep2 = sctp_sk(sk2)->ep; ep2 = sctp_sk(sk2)->ep;
...@@ -1887,7 +1883,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum) ...@@ -1887,7 +1883,7 @@ static long sctp_get_port_local(struct sock *sk, unsigned short snum)
* SO_REUSEADDR on this socket -sk-). * SO_REUSEADDR on this socket -sk-).
*/ */
if (pp->sk == NULL) { if (pp->sk == NULL) {
pp->fastreuse = sk->reuse? 1 : 0; pp->fastreuse = sk->reuse ? 1 : 0;
} else if (pp->fastreuse && sk->reuse == 0) { } else if (pp->fastreuse && sk->reuse == 0) {
pp->fastreuse = 0; pp->fastreuse = 0;
} }
...@@ -1974,7 +1970,7 @@ int sctp_inet_listen(struct socket *sock, int backlog) ...@@ -1974,7 +1970,7 @@ int sctp_inet_listen(struct socket *sock, int backlog)
err = -EINVAL; err = -EINVAL;
if (sock->state != SS_UNCONNECTED) if (sock->state != SS_UNCONNECTED)
goto out; goto out;
switch (sock->type) { switch (sock->type) {
case SOCK_SEQPACKET: case SOCK_SEQPACKET:
err = sctp_seqpacket_listen(sk, backlog); err = sctp_seqpacket_listen(sk, backlog);
break; break;
...@@ -2073,7 +2069,7 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi ...@@ -2073,7 +2069,7 @@ static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsi
pp->sk = NULL; pp->sk = NULL;
if ((pp->next = head->chain) != NULL) if ((pp->next = head->chain) != NULL)
pp->next->pprev = &pp->next; pp->next->pprev = &pp->next;
head->chain= pp; head->chain = pp;
pp->pprev = &head->chain; pp->pprev = &head->chain;
} }
SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp); SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp);
...@@ -2127,7 +2123,7 @@ static int sctp_autobind(struct sock *sk) ...@@ -2127,7 +2123,7 @@ static int sctp_autobind(struct sock *sk)
switch (sk->family) { switch (sk->family) {
case PF_INET: case PF_INET:
autoaddr.v4.sin_family = AF_INET; autoaddr.v4.sin_family = AF_INET;
autoaddr.v4.sin_addr.s_addr = INADDR_ANY; autoaddr.v4.sin_addr.s_addr = INADDR_ANY;
autoaddr.v4.sin_port = htons(inet_sk(sk)->num); autoaddr.v4.sin_port = htons(inet_sk(sk)->num);
addr_len = sizeof(struct sockaddr_in); addr_len = sizeof(struct sockaddr_in);
break; break;
...@@ -2202,7 +2198,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) ...@@ -2202,7 +2198,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
return -EINVAL; return -EINVAL;
} }
/* Should we parse this header or ignore? */ /* Should we parse this header or ignore? */
if (cmsg->cmsg_level != IPPROTO_SCTP) if (cmsg->cmsg_level != IPPROTO_SCTP)
continue; continue;
...@@ -2433,41 +2429,6 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no ...@@ -2433,41 +2429,6 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
return NULL; 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) static inline int sctp_sendmsg_verify_name(struct sock *sk, struct msghdr *msg)
{ {
sockaddr_storage_t *sa; sockaddr_storage_t *sa;
...@@ -2590,7 +2551,7 @@ static int sctp_wait_for_sndbuf(sctp_association_t *asoc, long *timeo_p, int msg ...@@ -2590,7 +2551,7 @@ static int sctp_wait_for_sndbuf(sctp_association_t *asoc, long *timeo_p, int msg
/* Let another process have a go. Since we are going /* Let another process have a go. Since we are going
* to sleep anyway. * to sleep anyway.
*/ */
sctp_release_sock(sk); sctp_release_sock(sk);
current_timeo = schedule_timeout(current_timeo); current_timeo = schedule_timeout(current_timeo);
sctp_lock_sock(sk); sctp_lock_sock(sk);
......
...@@ -4,45 +4,45 @@ ...@@ -4,45 +4,45 @@
* Copyright (c) 2001 International Business Machines Corp. * Copyright (c) 2001 International Business Machines Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This module provides the abstraction for an SCTP tranport representing * This module provides the abstraction for an SCTP tranport representing
* a remote transport address. For local transport addresses, we just use * a remote transport address. For local transport addresses, we just use
* sockaddr_storage_t. * sockaddr_storage_t.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Xingang Guo <xingang.guo@intel.com> * Xingang Guo <xingang.guo@intel.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -215,7 +215,7 @@ void sctp_transport_put(sctp_transport_t *transport) ...@@ -215,7 +215,7 @@ void sctp_transport_put(sctp_transport_t *transport)
sctp_transport_destroy(transport); sctp_transport_destroy(transport);
} }
/* Update transport's RTO based on the newly calculated RTT. */ /* Update transport's RTO based on the newly calculated RTT. */
void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt) void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt)
{ {
sctp_protocol_t *proto = sctp_get_protocol(); sctp_protocol_t *proto = sctp_get_protocol();
...@@ -263,7 +263,7 @@ void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt) ...@@ -263,7 +263,7 @@ void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt)
* seconds then it is rounded up to RTO.Min seconds. * seconds then it is rounded up to RTO.Min seconds.
*/ */
if (tp->rto < tp->asoc->rto_min) if (tp->rto < tp->asoc->rto_min)
tp->rto = tp->asoc->rto_min; tp->rto = tp->asoc->rto_min;
/* 6.3.1 C7) A maximum value may be placed on RTO provided it is /* 6.3.1 C7) A maximum value may be placed on RTO provided it is
* at least RTO.max seconds. * at least RTO.max seconds.
...@@ -381,13 +381,13 @@ void sctp_transport_lower_cwnd(sctp_transport_t *transport, ...@@ -381,13 +381,13 @@ void sctp_transport_lower_cwnd(sctp_transport_t *transport,
break; break;
case SCTP_LOWER_CWND_FAST_RTX: case SCTP_LOWER_CWND_FAST_RTX:
/* RFC 2960 7.2.4 Adjust the ssthresh and cwnd of the /* RFC 2960 7.2.4 Adjust the ssthresh and cwnd of the
* destination address(es) to which the missing DATA chunks * destination address(es) to which the missing DATA chunks
* were last sent, according to the formula described in * were last sent, according to the formula described in
* Section 7.2.3. * Section 7.2.3.
* *
* RFC 2960 7.2.3, sctpimpguide-05 2.9.2 Upon detection of * RFC 2960 7.2.3, sctpimpguide-05 2.9.2 Upon detection of
* packet losses from SACK (see Section 7.2.4), An endpoint * packet losses from SACK (see Section 7.2.4), An endpoint
* should do the following: * should do the following:
* ssthresh = max(cwnd/2, 2*MTU) * ssthresh = max(cwnd/2, 2*MTU)
* cwnd = ssthresh * cwnd = ssthresh
......
...@@ -46,9 +46,10 @@ ...@@ -46,9 +46,10 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/sctp/sm.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, static void sctp_ulpevent_set_owner_r(struct sk_buff *skb,
sctp_association_t *asoc); sctp_association_t *asoc);
static void
sctp_ulpevent_set_owner(struct sk_buff *skb, const sctp_association_t *asoc);
/* Create a new sctp_ulpevent. */ /* Create a new sctp_ulpevent. */
sctp_ulpevent_t *sctp_ulpevent_new(int size, int msg_flags, int priority) 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, ...@@ -123,14 +124,12 @@ sctp_ulpevent_t *sctp_ulpevent_make_assoc_change(const sctp_association_t *asoc,
struct sctp_assoc_change *sac; struct sctp_assoc_change *sac;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, MSG_NOTIFICATION, priority);
priority);
if (!event) if (!event)
goto fail; goto fail;
sac = (struct sctp_assoc_change *) sac = (struct sctp_assoc_change *)
skb_put(event->parent, skb_put(event->parent, sizeof(struct sctp_assoc_change));
sizeof(struct sctp_assoc_change));
/* Socket Extensions for SCTP /* Socket Extensions for SCTP
* 5.3.1.1 SCTP_ASSOC_CHANGE * 5.3.1.1 SCTP_ASSOC_CHANGE
...@@ -199,6 +198,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_assoc_change(const sctp_association_t *asoc, ...@@ -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 * All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored. * identifier. For TCP style socket, this field is ignored.
*/ */
sctp_ulpevent_set_owner(event->parent, asoc);
sac->sac_assoc_id = sctp_assoc2id(asoc); sac->sac_assoc_id = sctp_assoc2id(asoc);
return event; return event;
...@@ -227,14 +227,12 @@ sctp_ulpevent_t *sctp_ulpevent_make_peer_addr_change( ...@@ -227,14 +227,12 @@ sctp_ulpevent_t *sctp_ulpevent_make_peer_addr_change(
struct sctp_paddr_change *spc; struct sctp_paddr_change *spc;
event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change), event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change),
MSG_NOTIFICATION, MSG_NOTIFICATION, priority);
priority);
if (!event) if (!event)
goto fail; goto fail;
spc = (struct sctp_paddr_change *) spc = (struct sctp_paddr_change *)
skb_put(event->parent, skb_put(event->parent, sizeof(struct sctp_paddr_change));
sizeof(struct sctp_paddr_change));
/* Sockets API Extensions for SCTP /* Sockets API Extensions for SCTP
* Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE
...@@ -287,12 +285,13 @@ sctp_ulpevent_t *sctp_ulpevent_make_peer_addr_change( ...@@ -287,12 +285,13 @@ sctp_ulpevent_t *sctp_ulpevent_make_peer_addr_change(
/* Socket Extensions for SCTP /* Socket Extensions for SCTP
* 5.3.1.1 SCTP_ASSOC_CHANGE * 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. * The association id field, holds the identifier for the association.
* All notifications for a given association have the same association * All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored. * identifier. For TCP style socket, this field is ignored.
*/ */
sctp_ulpevent_set_owner(event->parent, asoc);
spc->spc_assoc_id = sctp_assoc2id(asoc); spc->spc_assoc_id = sctp_assoc2id(asoc);
/* Sockets API Extensions for SCTP /* Sockets API Extensions for SCTP
...@@ -360,9 +359,8 @@ sctp_ulpevent_t *sctp_ulpevent_make_remote_error(const sctp_association_t *asoc, ...@@ -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. */ /* Embed the event fields inside the cloned skb. */
event = (sctp_ulpevent_t *) skb->cb; event = (sctp_ulpevent_t *) skb->cb;
event = sctp_ulpevent_init(event, event = sctp_ulpevent_init(event, skb, MSG_NOTIFICATION);
skb,
MSG_NOTIFICATION);
if (!event) if (!event)
goto fail; goto fail;
...@@ -418,6 +416,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_remote_error(const sctp_association_t *asoc, ...@@ -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 * All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored. * identifier. For TCP style socket, this field is ignored.
*/ */
sctp_ulpevent_set_owner(event->parent, asoc);
sre->sre_assoc_id = sctp_assoc2id(asoc); sre->sre_assoc_id = sctp_assoc2id(asoc);
return event; return event;
...@@ -515,9 +514,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc, ...@@ -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 * The original send information associated with the undelivered
* message. * message.
*/ */
memcpy(&ssf->ssf_info, memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo));
&chunk->sinfo,
sizeof(struct sctp_sndrcvinfo));
/* Socket Extensions for SCTP /* Socket Extensions for SCTP
* 5.3.1.4 SCTP_SEND_FAILED * 5.3.1.4 SCTP_SEND_FAILED
...@@ -528,8 +525,8 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc, ...@@ -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 * same association identifier. For TCP style socket, this field is
* ignored. * ignored.
*/ */
sctp_ulpevent_set_owner(event->parent, asoc);
ssf->ssf_assoc_id = sctp_assoc2id(asoc); ssf->ssf_assoc_id = sctp_assoc2id(asoc);
return event; return event;
fail: fail:
...@@ -541,22 +538,21 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc, ...@@ -541,22 +538,21 @@ sctp_ulpevent_t *sctp_ulpevent_make_send_failed(const sctp_association_t *asoc,
* Socket Extensions for SCTP - draft-01 * Socket Extensions for SCTP - draft-01
* 5.3.1.5 SCTP_SHUTDOWN_EVENT * 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(
__u16 flags, const sctp_association_t *asoc,
int priority) __u16 flags,
int priority)
{ {
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
struct sctp_shutdown_event *sse; struct sctp_shutdown_event *sse;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, MSG_NOTIFICATION, priority);
priority);
if (!event) if (!event)
goto fail; goto fail;
sse = (struct sctp_shutdown_event *) sse = (struct sctp_shutdown_event *)
skb_put(event->parent, skb_put(event->parent, sizeof(struct sctp_shutdown_event));
sizeof(struct sctp_shutdown_event));
/* Socket Extensions for SCTP /* Socket Extensions for SCTP
* 5.3.1.5 SCTP_SHUTDOWN_EVENT * 5.3.1.5 SCTP_SHUTDOWN_EVENT
...@@ -591,6 +587,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(const sctp_association_t *aso ...@@ -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 * All notifications for a given association have the same association
* identifier. For TCP style socket, this field is ignored. * identifier. For TCP style socket, this field is ignored.
*/ */
sctp_ulpevent_set_owner(event->parent, asoc);
sse->sse_assoc_id = sctp_assoc2id(asoc); sse->sse_assoc_id = sctp_assoc2id(asoc);
return event; return event;
...@@ -607,8 +604,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(const sctp_association_t *aso ...@@ -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) * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
*/ */
sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc, sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
sctp_chunk_t *chunk, sctp_chunk_t *chunk, int priority)
int priority)
{ {
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
struct sctp_sndrcvinfo *info; struct sctp_sndrcvinfo *info;
...@@ -619,7 +615,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc, ...@@ -619,7 +615,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
skb = skb_clone(chunk->skb, priority); skb = skb_clone(chunk->skb, priority);
if (!skb) if (!skb)
goto fail; goto fail;
/* First calculate the padding, so we don't inadvertently /* First calculate the padding, so we don't inadvertently
* pass up the wrong length to the user. * pass up the wrong length to the user.
* *
...@@ -645,7 +641,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc, ...@@ -645,7 +641,7 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
event = (sctp_ulpevent_t *) skb->cb; event = (sctp_ulpevent_t *) skb->cb;
/* Initialize event with flags 0. */ /* Initialize event with flags 0. */
event = sctp_ulpevent_init(event, skb, 0); event = sctp_ulpevent_init(event, skb, 0);
if (!event) if (!event)
goto fail_init; goto fail_init;
...@@ -818,23 +814,33 @@ static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *a ...@@ -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_over = skb->len - asoc->rwnd;
asoc->rwnd = 0; asoc->rwnd = 0;
} }
SCTP_DEBUG_PRINTK("rwnd decreased by %d to (%u, %u)\n", SCTP_DEBUG_PRINTK("rwnd decreased by %d to (%u, %u)\n",
skb->len, asoc->rwnd, asoc->rwnd_over); 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;
}
...@@ -5,38 +5,38 @@ ...@@ -5,38 +5,38 @@
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This abstraction carries sctp events to the ULP (sockets). * This abstraction carries sctp events to the ULP (sockets).
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -131,7 +131,7 @@ int sctp_ulpqueue_tail_data(sctp_ulpqueue_t *ulpq, sctp_chunk_t *chunk, ...@@ -131,7 +131,7 @@ int sctp_ulpqueue_tail_data(sctp_ulpqueue_t *ulpq, sctp_chunk_t *chunk,
int priority) int priority)
{ {
struct sk_buff_head temp; struct sk_buff_head temp;
sctp_data_chunk_t *hdr; sctp_data_chunk_t *hdr;
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
hdr = (sctp_data_chunk_t *) chunk->chunk_hdr; hdr = (sctp_data_chunk_t *) chunk->chunk_hdr;
...@@ -157,7 +157,7 @@ int sctp_ulpqueue_tail_data(sctp_ulpqueue_t *ulpq, sctp_chunk_t *chunk, ...@@ -157,7 +157,7 @@ int sctp_ulpqueue_tail_data(sctp_ulpqueue_t *ulpq, sctp_chunk_t *chunk,
event = sctp_ulpqueue_order(ulpq, event); event = sctp_ulpqueue_order(ulpq, event);
} }
/* Send event to the ULP. */ /* Send event to the ULP. */
if (event) if (event)
sctp_ulpqueue_tail_event(ulpq, event); sctp_ulpqueue_tail_event(ulpq, event);
...@@ -449,7 +449,7 @@ static inline sctp_ulpevent_t *sctp_ulpqueue_order(sctp_ulpqueue_t *ulpq, ...@@ -449,7 +449,7 @@ static inline sctp_ulpevent_t *sctp_ulpqueue_order(sctp_ulpqueue_t *ulpq,
/* Check if this message needs ordering. */ /* Check if this message needs ordering. */
if (SCTP_DATA_UNORDERED & event->chunk_flags) if (SCTP_DATA_UNORDERED & event->chunk_flags)
return event; return event;
/* Note: The stream ID must be verified before this routine. */ /* Note: The stream ID must be verified before this routine. */
sid = event->sndrcvinfo.sinfo_stream; sid = event->sndrcvinfo.sinfo_stream;
......
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