Commit e8120ed0 authored by Sridhar Samudrala's avatar Sridhar Samudrala Committed by Sridhar Samudrala

[SCTP] Stale cookie support. (ardelle.fan)

parent 079b9dc1
...@@ -543,7 +543,8 @@ enum { ...@@ -543,7 +543,8 @@ enum {
NET_SCTP_PATH_MAX_RETRANS = 8, NET_SCTP_PATH_MAX_RETRANS = 8,
NET_SCTP_MAX_INIT_RETRANSMITS = 9, NET_SCTP_MAX_INIT_RETRANSMITS = 9,
NET_SCTP_HB_INTERVAL = 10, NET_SCTP_HB_INTERVAL = 10,
NET_SCTP_MAX_BURST = 11, NET_SCTP_PRESERVE_ENABLE = 11,
NET_SCTP_MAX_BURST = 12,
}; };
/* CTL_PROC names: */ /* CTL_PROC names: */
......
...@@ -140,6 +140,8 @@ sctp_state_fn_t sctp_sf_do_5_2_2_dupinit; ...@@ -140,6 +140,8 @@ 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; sctp_state_fn_t sctp_sf_unk_chunk;
sctp_state_fn_t sctp_sf_do_8_5_1_E_sa; sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
sctp_state_fn_t sctp_sf_cookie_echoed_err;
sctp_state_fn_t sctp_sf_do_5_2_6_stale;
/* 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;
...@@ -175,7 +177,6 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire; ...@@ -175,7 +177,6 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire;
*/ */
/* Prototypes for chunk state functions. Not in use. */ /* Prototypes for chunk state functions. Not in use. */
sctp_state_fn_t sctp_sf_do_5_2_6_stale;
sctp_state_fn_t sctp_sf_do_9_2_reshutack; sctp_state_fn_t sctp_sf_do_9_2_reshutack;
sctp_state_fn_t sctp_sf_do_9_2_reshut; sctp_state_fn_t sctp_sf_do_9_2_reshut;
sctp_state_fn_t sctp_sf_do_9_2_shutack; sctp_state_fn_t sctp_sf_do_9_2_shutack;
...@@ -211,7 +212,7 @@ void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag); ...@@ -211,7 +212,7 @@ void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
/* Prototypes for chunk-building functions. */ /* Prototypes for chunk-building functions. */
sctp_chunk_t *sctp_make_init(const sctp_association_t *, sctp_chunk_t *sctp_make_init(const sctp_association_t *,
const sctp_bind_addr_t *, const sctp_bind_addr_t *,
int priority); int priority, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *, sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *,
const sctp_chunk_t *, const sctp_chunk_t *,
const int priority, const int priority,
...@@ -322,9 +323,15 @@ sctp_pack_cookie(const sctp_endpoint_t *, const sctp_association_t *, ...@@ -322,9 +323,15 @@ sctp_pack_cookie(const sctp_endpoint_t *, const sctp_association_t *,
const __u8 *, int addrs_len); const __u8 *, int addrs_len);
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *, sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *,
const sctp_association_t *, const sctp_association_t *,
sctp_chunk_t *, int priority, int *err); sctp_chunk_t *, int priority, int *err,
sctp_chunk_t **err_chk_p);
int sctp_addip_addr_config(sctp_association_t *, sctp_param_t, int sctp_addip_addr_config(sctp_association_t *, sctp_param_t,
struct sockaddr_storage*, int); struct sockaddr_storage*, int);
void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_chunk_t *chunk,
sctp_cmd_seq_t *commands,
sctp_chunk_t *err_chunk);
/* 3rd level prototypes */ /* 3rd level prototypes */
__u32 sctp_generate_tag(const sctp_endpoint_t *); __u32 sctp_generate_tag(const sctp_endpoint_t *);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.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>
* Ardelle Fan <ardelle.fan@intel.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.
...@@ -183,6 +184,9 @@ struct SCTP_protocol { ...@@ -183,6 +184,9 @@ struct SCTP_protocol {
/* Valid.Cookie.Life - 60 seconds */ /* Valid.Cookie.Life - 60 seconds */
int valid_cookie_life; int valid_cookie_life;
/* Whether Cookie Preservative is enabled(1) or not(0) */
int cookie_preserve_enable;
/* Association.Max.Retrans - 10 attempts /* Association.Max.Retrans - 10 attempts
* Path.Max.Retrans - 5 attempts (per destination address) * Path.Max.Retrans - 5 attempts (per destination address)
* Max.Init.Retransmits - 8 attempts * Max.Init.Retransmits - 8 attempts
...@@ -1278,7 +1282,6 @@ struct SCTP_association { ...@@ -1278,7 +1282,6 @@ struct SCTP_association {
/* The cookie life I award for any cookie. */ /* The cookie life I award for any cookie. */
struct timeval cookie_life; struct timeval cookie_life;
__u32 cookie_preserve;
/* Overall : The overall association error count. /* Overall : The overall association error count.
* Error Count : [Clear this any time I get something.] * Error Count : [Clear this any time I get something.]
......
...@@ -128,8 +128,9 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -128,8 +128,9 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->state_timestamp = jiffies; asoc->state_timestamp = jiffies;
/* Set things that have constant value. */ /* Set things that have constant value. */
asoc->cookie_life.tv_sec = SCTP_DEFAULT_COOKIE_LIFE_SEC; asoc->cookie_life.tv_sec = sctp_proto.valid_cookie_life / HZ;
asoc->cookie_life.tv_usec = SCTP_DEFAULT_COOKIE_LIFE_USEC; asoc->cookie_life.tv_usec = (sctp_proto.valid_cookie_life % HZ) *
1000000L / HZ;
asoc->pmtu = 0; asoc->pmtu = 0;
asoc->frag_point = 0; asoc->frag_point = 0;
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.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.
...@@ -279,6 +280,7 @@ int sctp_rcv_ootb(struct sk_buff *skb) ...@@ -279,6 +280,7 @@ int sctp_rcv_ootb(struct sk_buff *skb)
{ {
sctp_chunkhdr_t *ch; sctp_chunkhdr_t *ch;
__u8 *ch_end; __u8 *ch_end;
sctp_errhdr_t *err;
ch = (sctp_chunkhdr_t *) skb->data; ch = (sctp_chunkhdr_t *) skb->data;
...@@ -308,7 +310,8 @@ int sctp_rcv_ootb(struct sk_buff *skb) ...@@ -308,7 +310,8 @@ int sctp_rcv_ootb(struct sk_buff *skb)
goto discard; goto discard;
if (ch->type == SCTP_CID_ERROR) { if (ch->type == SCTP_CID_ERROR) {
/* FIXME - Need to check the "Stale cookie" ERROR. */ err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t));
if (SCTP_ERROR_STALE_COOKIE == err->cause)
goto discard; goto discard;
} }
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.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.
...@@ -691,6 +692,9 @@ int sctp_init(void) ...@@ -691,6 +692,9 @@ int sctp_init(void)
/* Valid.Cookie.Life - 60 seconds */ /* Valid.Cookie.Life - 60 seconds */
sctp_proto.valid_cookie_life = 60 * HZ; sctp_proto.valid_cookie_life = 60 * HZ;
/* Whether Cookie Preservative is enabled(1) or not(0) */
sctp_proto.cookie_preserve_enable = 1;
/* Max.Burst - 4 */ /* Max.Burst - 4 */
sctp_proto.max_burst = SCTP_MAX_BURST; sctp_proto.max_burst = SCTP_MAX_BURST;
......
...@@ -163,7 +163,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code, ...@@ -163,7 +163,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
*/ */
sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
const sctp_bind_addr_t *bp, const sctp_bind_addr_t *bp,
int priority) int priority, int vparam_len)
{ {
sctp_inithdr_t init; sctp_inithdr_t init;
union sctp_params addrs; union sctp_params addrs;
...@@ -192,6 +192,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc, ...@@ -192,6 +192,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN; chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN;
chunksize += sizeof(ecap_param); chunksize += sizeof(ecap_param);
chunksize += vparam_len;
/* RFC 2960 3.3.2 Initiation (INIT) (1) /* RFC 2960 3.3.2 Initiation (INIT) (1)
* *
...@@ -1337,7 +1338,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep, ...@@ -1337,7 +1338,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
const sctp_association_t *asoc, const sctp_association_t *asoc,
sctp_chunk_t *chunk, int priority, sctp_chunk_t *chunk, int priority,
int *error) int *error, sctp_chunk_t **err_chk_p)
{ {
sctp_association_t *retval = NULL; sctp_association_t *retval = NULL;
sctp_signed_cookie_t *cookie; sctp_signed_cookie_t *cookie;
...@@ -1394,7 +1395,29 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1394,7 +1395,29 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* for init collision case of lost COOKIE ACK. * for init collision case of lost COOKIE ACK.
*/ */
if (!asoc && tv_lt(bear_cookie->expiration, chunk->skb->stamp)) { if (!asoc && tv_lt(bear_cookie->expiration, chunk->skb->stamp)) {
/*
* Section 3.3.10.3 Stale Cookie Error (3)
*
* Cause of error
* ---------------
* Stale Cookie Error: Indicates the receipt of a valid State
* Cookie that has expired.
*/
*err_chk_p = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length));
if (*err_chk_p) {
suseconds_t usecs = (chunk->skb->stamp.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L +
chunk->skb->stamp.tv_usec -
bear_cookie->expiration.tv_usec;
usecs = htonl(usecs);
sctp_init_cause(*err_chk_p, SCTP_ERROR_STALE_COOKIE,
&usecs, sizeof(usecs));
*error = -SCTP_IERROR_STALE_COOKIE; *error = -SCTP_IERROR_STALE_COOKIE;
} else
*error = -SCTP_IERROR_NOMEM;
goto fail; goto fail;
} }
...@@ -1751,6 +1774,7 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param, ...@@ -1751,6 +1774,7 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
__u16 sat; __u16 sat;
int retval = 1; int retval = 1;
sctp_scope_t scope; sctp_scope_t scope;
time_t stale;
/* We maintain all INIT parameters in network byte order all the /* We maintain all INIT parameters in network byte order all the
* time. This allows us to not worry about whether the parameters * time. This allows us to not worry about whether the parameters
...@@ -1770,8 +1794,16 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param, ...@@ -1770,8 +1794,16 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
break; break;
case SCTP_PARAM_COOKIE_PRESERVATIVE: case SCTP_PARAM_COOKIE_PRESERVATIVE:
asoc->cookie_preserve = if (!sctp_proto.cookie_preserve_enable)
ntohl(param.life->lifespan_increment); break;
stale = ntohl(param.life->lifespan_increment);
/* Suggested Cookie Life span increment's unit is msec,
* (1/1000sec).
*/
asoc->cookie_life.tv_sec += stale / 1000;
asoc->cookie_life.tv_usec += (stale % 1000) * 1000;
break; break;
case SCTP_PARAM_HOST_NAME_ADDRESS: case SCTP_PARAM_HOST_NAME_ADDRESS:
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* 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-2002 International Business Machines, Corp. * Copyright (c) 2001-2002 International Business Machines, Corp.
* Copyright (c) 2001-2002 Intel Corp.
* 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
...@@ -502,6 +503,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep, ...@@ -502,6 +503,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep,
sctp_chunk_t *repl; sctp_chunk_t *repl;
sctp_ulpevent_t *ev; sctp_ulpevent_t *ev;
int error = 0; int error = 0;
sctp_chunk_t *err_chk_p;
/* If the packet is an OOTB packet which is temporarily on the /* If the packet is an OOTB packet which is temporarily on the
* control endpoint, responding with an ABORT. * control endpoint, responding with an ABORT.
...@@ -521,7 +523,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep, ...@@ -521,7 +523,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep,
* "Z" will reply with a COOKIE ACK chunk after building a TCB * "Z" will reply with a COOKIE ACK chunk after building a TCB
* and moving to the ESTABLISHED state. * and moving to the ESTABLISHED state.
*/ */
new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error); new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error,
&err_chk_p);
/* FIXME: /* FIXME:
* If the re-build failed, what is the proper error path * If the re-build failed, what is the proper error path
...@@ -537,6 +540,11 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep, ...@@ -537,6 +540,11 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const sctp_endpoint_t *ep,
case -SCTP_IERROR_NOMEM: case -SCTP_IERROR_NOMEM:
goto nomem; goto nomem;
case -SCTP_IERROR_STALE_COOKIE:
sctp_send_stale_cookie_err(ep, asoc, chunk, commands,
err_chk_p);
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
case -SCTP_IERROR_BAD_SIG: case -SCTP_IERROR_BAD_SIG:
default: default:
return sctp_sf_pdiscard(ep, asoc, type, arg, commands); return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
...@@ -1562,6 +1570,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep, ...@@ -1562,6 +1570,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
sctp_association_t *new_asoc; sctp_association_t *new_asoc;
int error = 0; int error = 0;
char action; char action;
sctp_chunk_t *err_chk_p;
/* "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.
...@@ -1575,7 +1584,8 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep, ...@@ -1575,7 +1584,8 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
* current association, consider the State Cookie valid even if * current association, consider the State Cookie valid even if
* the lifespan is exceeded. * the lifespan is exceeded.
*/ */
new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error); new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error,
&err_chk_p);
/* FIXME: /* FIXME:
* If the re-build failed, what is the proper error path * If the re-build failed, what is the proper error path
...@@ -1591,6 +1601,12 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep, ...@@ -1591,6 +1601,12 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const sctp_endpoint_t *ep,
case -SCTP_IERROR_NOMEM: case -SCTP_IERROR_NOMEM:
goto nomem; goto nomem;
case -SCTP_IERROR_STALE_COOKIE:
sctp_send_stale_cookie_err(ep, asoc, chunk, commands,
err_chk_p);
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
break;
case -SCTP_IERROR_BAD_SIG: case -SCTP_IERROR_BAD_SIG:
default: default:
return sctp_sf_pdiscard(ep, asoc, type, arg, commands); return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
...@@ -1706,7 +1722,47 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(const sctp_endpoint_t *ep, ...@@ -1706,7 +1722,47 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(const sctp_endpoint_t *ep,
return sctp_sf_shutdown_sent_abort(ep, asoc, type, arg, commands); return sctp_sf_shutdown_sent_abort(ep, asoc, type, arg, commands);
} }
#if 0 /*
* Handle an Error received in COOKIE_ECHOED state.
*
* Only handle the error type of stale COOKIE Error, the other errors will
* be ignored.
*
* 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_cookie_echoed_err(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;
sctp_errhdr_t *err;
/* If we have gotten too many failures, give up. */
if (1 + asoc->counters[SCTP_COUNTER_INIT_ERROR] >
asoc->max_init_attempts) {
/* INIT_FAILED will issue an ulpevent. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB;
}
err = (sctp_errhdr_t *)(chunk->skb->data);
/* Process the error here */
switch (err->cause) {
case SCTP_ERROR_STALE_COOKIE:
return sctp_sf_do_5_2_6_stale(ep, asoc, type, arg, commands);
default:
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
}
/* /*
* Handle a Stale COOKIE Error * Handle a Stale COOKIE Error
* *
...@@ -1732,47 +1788,30 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(const sctp_endpoint_t *ep, ...@@ -1732,47 +1788,30 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(const sctp_endpoint_t *ep,
* *
* The return value is the disposition of the chunk. * The return value is the disposition of the chunk.
*/ */
sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep, sctp_disposition_t sctp_sf_do_5_2_6_stale(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 *chunk = arg; sctp_chunk_t *chunk = arg;
time_t stale;
sctp_cookie_preserve_param_t bht;
sctp_errhdr_t *err;
struct list_head *pos;
sctp_transport_t *t;
sctp_chunk_t *reply;
sctp_bind_addr_t *bp;
int attempts;
/* This is not a real chunk type. It is a subtype of the attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
* ERROR chunk type. The ERROR chunk processing will bring us
* here.
*/
sctp_chunk_t *in_packet;
stp_chunk_t *reply;
sctp_inithdr_t initack;
__u8 *addrs;
int addrs_len;
time_t rtt;
struct sctpCookiePreserve bht;
/* If we have gotten too many failures, give up. */ if (attempts >= asoc->max_init_attempts) {
if (1 + asoc->counters[SctpCounterInits] > asoc->max_init_attempts) { sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_NULL());
/* FIXME: Move to new ulpevent. */
retval->event_up = sctp_make_ulp_init_timeout(asoc);
if (!retval->event_up)
goto nomem;
sctp_add_cmd_sf(retval->commands, SCTP_CMD_DELETE_TCB,
SCTP_NULL());
return SCTP_DISPOSITION_DELETE_TCB; return SCTP_DISPOSITION_DELETE_TCB;
} }
retval->counters[0] = SCTP_COUNTER_INCR; err = (sctp_errhdr_t *)(chunk->skb->data);
retval->counters[0] = SctpCounterInits;
retval->counters[1] = 0;
retval->counters[1] = 0;
/* Calculate the RTT in ms. */
/* BUG--we should get the send time of the HEARTBEAT REQUEST. */
in_packet = chunk;
rtt = 1000 * timeval_sub(in_packet->skb->stamp,
asoc->c.state_timestamp);
/* When calculating the time extension, an implementation /* When calculating the time extension, an implementation
* SHOULD use the RTT information measured based on the * SHOULD use the RTT information measured based on the
...@@ -1780,28 +1819,48 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep, ...@@ -1780,28 +1819,48 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep,
* more than 1 second beyond the measured RTT, due to long * more than 1 second beyond the measured RTT, due to long
* State Cookie lifetimes making the endpoint more subject to * State Cookie lifetimes making the endpoint more subject to
* a replay attack. * a replay attack.
* Measure of Staleness's unit is usec. (1/1000000 sec)
* Suggested Cookie Life-span Increment's unit is msec.
* (1/1000 sec)
* In general, if you use the suggested cookie life, the value
* found in the field of measure of staleness should be doubled
* to give ample time to retransmit the new cookie and thus
* yield a higher probability of success on the reattempt.
*/ */
bht.p = {SCTP_COOKIE_PRESERVE, 8}; stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t)));
bht.extraTime = htonl(rtt + 1000); stale = stale << 1 / 1000;
initack.init_tag = htonl(asoc->c.my_vtag); bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE;
initack.a_rwnd = htonl(atomic_read(&asoc->rnwd)); bht.param_hdr.length = htons(sizeof(bht));
initack.num_outbound_streams = htons(asoc->streamoutcnt); bht.lifespan_increment = htonl(stale);
initack.num_inbound_streams = htons(asoc->streamincnt);
initack.initial_tsn = htonl(asoc->c.initSeqNumber);
sctp_get_my_addrs(asoc, &addrs, &addrs_len);
/* Build that new INIT chunk. */ /* Build that new INIT chunk. */
reply = sctp_make_chunk(SCTP_INITIATION, 0, bp = (sctp_bind_addr_t *) &asoc->base.bind_addr;
sizeof(initack) reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht));
+ sizeof(bht)
+ addrs_len);
if (!reply) if (!reply)
goto nomem; goto nomem;
sctp_addto_chunk(reply, sizeof(initack), &initack);
sctp_addto_chunk(reply, sizeof(bht), &bht); sctp_addto_chunk(reply, sizeof(bht), &bht);
sctp_addto_chunk(reply, addrs_len, addrs);
/* Cast away the const modifier, as we want to just
* rerun it through as a sideffect.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
/* 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_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(t));
}
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_COOKIE_WAIT));
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
...@@ -1809,7 +1868,6 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep, ...@@ -1809,7 +1868,6 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep,
nomem: nomem:
return SCTP_DISPOSITION_NOMEM; return SCTP_DISPOSITION_NOMEM;
} }
#endif /* 0 */
/* /*
* Process an ABORT. * Process an ABORT.
...@@ -3220,7 +3278,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep, ...@@ -3220,7 +3278,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep,
* 1 to 4294967295 (see 5.3.1 for Tag value selection). ... * 1 to 4294967295 (see 5.3.1 for Tag value selection). ...
*/ */
repl = sctp_make_init(asoc, bp, GFP_ATOMIC); repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
if (!repl) if (!repl)
goto nomem; goto nomem;
...@@ -3992,7 +4050,7 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep, ...@@ -3992,7 +4050,7 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep,
switch (timer) { switch (timer) {
case SCTP_EVENT_TIMEOUT_T1_INIT: case SCTP_EVENT_TIMEOUT_T1_INIT:
bp = (sctp_bind_addr_t *) &asoc->base.bind_addr; bp = (sctp_bind_addr_t *) &asoc->base.bind_addr;
repl = sctp_make_init(asoc, bp, GFP_ATOMIC); repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
break; break;
case SCTP_EVENT_TIMEOUT_T1_COOKIE: case SCTP_EVENT_TIMEOUT_T1_COOKIE:
...@@ -4334,3 +4392,25 @@ void sctp_ootb_pkt_free(sctp_packet_t *packet) ...@@ -4334,3 +4392,25 @@ void sctp_ootb_pkt_free(sctp_packet_t *packet)
sctp_transport_free(packet->transport); sctp_transport_free(packet->transport);
sctp_packet_free(packet); sctp_packet_free(packet);
} }
/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */
void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_chunk_t *chunk,
sctp_cmd_seq_t *commands,
sctp_chunk_t *err_chunk)
{
sctp_packet_t *packet;
if (err_chunk) {
packet = sctp_ootb_pkt_new(asoc, chunk);
if (packet) {
/* Set the skb to the belonging sock for accounting. */
err_chunk->skb->sk = ep->base.sk;
sctp_packet_append_chunk(packet, err_chunk);
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
SCTP_PACKET(packet));
} else
sctp_free_chunk (err_chunk);
}
}
...@@ -295,7 +295,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, ...@@ -295,7 +295,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* 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_cookie_echoed_err, .name = "sctp_sf_cookie_echoed_err"}, \
/* 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 */ \
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 2002 International Business Machines Corp. * Copyright (c) 2002 International Business Machines Corp.
* Copyright (c) 2002 Intel Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
* Written or modified by: * Written or modified by:
* Mingqin Liu <liuming@us.ibm.com> * Mingqin Liu <liuming@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.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.
...@@ -70,6 +72,9 @@ static ctl_table sctp_table[] = { ...@@ -70,6 +72,9 @@ static ctl_table sctp_table[] = {
{ NET_SCTP_HB_INTERVAL, "hb_interval", { NET_SCTP_HB_INTERVAL, "hb_interval",
&sctp_proto.hb_interval, sizeof(int), 0644, NULL, &sctp_proto.hb_interval, sizeof(int), 0644, NULL,
&proc_dointvec_jiffies, &sysctl_jiffies }, &proc_dointvec_jiffies, &sysctl_jiffies },
{ NET_SCTP_PRESERVE_ENABLE, "cookie_preserve_enable",
&sctp_proto.cookie_preserve_enable, sizeof(int), 0644, NULL,
&proc_dointvec_jiffies, &sysctl_jiffies },
{ NET_SCTP_RTO_ALPHA, "rto_alpha_exp_divisor", { NET_SCTP_RTO_ALPHA, "rto_alpha_exp_divisor",
&sctp_proto.rto_alpha, sizeof(int), 0644, NULL, &sctp_proto.rto_alpha, sizeof(int), 0644, NULL,
&proc_dointvec }, &proc_dointvec },
......
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