From d8367696c51189c05d28c279da3aa769e077c105 Mon Sep 17 00:00:00 2001 From: Jon Grimm Date: Thu, 21 Nov 2002 02:43:28 -0600 Subject: [SCTP] Last of the v4/v6 partioning (for now) Mostly code on the bind path, splitting out to pf and af family specific functions. Minor code cleanups/fixes mixed in. --- include/net/sctp/sctp.h | 4 ++-- include/net/sctp/structs.h | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 73c948813e72..f12e54cd4919 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -123,8 +123,8 @@ extern sctp_protocol_t sctp_proto; extern struct sock *sctp_get_ctl_sock(void); extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *, sctp_scope_t, int priority, int flags); -extern sctp_pf_t *sctp_get_pf_specific(int family); -extern void sctp_set_pf_specific(int family, sctp_pf_t *); +extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); +extern int sctp_register_pf(struct sctp_pf *, sa_family_t); /* * sctp_socket.c diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d7b5674bdbdc..4b7f0e451449 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -234,7 +234,7 @@ struct SCTP_protocol { * Pointers to address related SCTP functions. * (i.e. things that depend on the address family.) */ -typedef struct sctp_func { +struct sctp_af { int (*queue_xmit) (struct sk_buff *skb); int (*setsockopt) (struct sock *sk, int level, @@ -259,27 +259,34 @@ typedef struct sctp_func { void (*from_skb) (union sctp_addr *, struct sk_buff *skb, int saddr); + void (*from_sk) (union sctp_addr *, + struct sock *sk); + void (*to_sk) (union sctp_addr *, + struct sock *sk); int (*addr_valid) (union sctp_addr *); sctp_scope_t (*scope) (union sctp_addr *); void (*inaddr_any) (union sctp_addr *, unsigned short); int (*is_any) (const union sctp_addr *); + int (*available) (const union sctp_addr *); __u16 net_header_len; int sockaddr_len; sa_family_t sa_family; struct list_head list; -} sctp_func_t; +}; -sctp_func_t *sctp_get_af_specific(sa_family_t); +struct sctp_af *sctp_get_af_specific(sa_family_t); +int sctp_register_af(struct sctp_af *); /* Protocol family functions. */ typedef struct sctp_pf { void (*event_msgname)(sctp_ulpevent_t *, char *, int *); - void (*skb_msgname)(struct sk_buff *, char *, int *); - int (*af_supported)(sa_family_t); + void (*skb_msgname) (struct sk_buff *, char *, int *); + int (*af_supported) (sa_family_t); int (*cmp_addr) (const union sctp_addr *, const union sctp_addr *, struct sctp_opt *); - struct sctp_func *af; + int (*bind_verify) (struct sctp_opt *, union sctp_addr *); + struct sctp_af *af; } sctp_pf_t; /* SCTP Socket type: UDP or TCP style. */ @@ -623,7 +630,7 @@ struct SCTP_transport { union sctp_addr ipaddr; /* These are the functions we call to handle LLP stuff. */ - sctp_func_t *af_specific; + struct sctp_af *af_specific; /* Which association do we belong to? */ sctp_association_t *asoc; -- cgit v1.2.3 From e8120ed074ce4408f5218c327fd41bc45b1cb999 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Thu, 5 Dec 2002 01:33:24 -0800 Subject: [SCTP] Stale cookie support. (ardelle.fan) --- include/linux/sysctl.h | 3 +- include/net/sctp/sm.h | 13 +++- include/net/sctp/structs.h | 5 +- net/sctp/associola.c | 5 +- net/sctp/input.c | 7 +- net/sctp/protocol.c | 4 + net/sctp/sm_make_chunk.c | 42 ++++++++-- net/sctp/sm_statefuns.c | 190 ++++++++++++++++++++++++++++++++------------- net/sctp/sm_statetable.c | 2 +- net/sctp/sysctl.c | 5 ++ 10 files changed, 206 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index e70fc2ef0856..47d74c442191 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -543,7 +543,8 @@ enum { NET_SCTP_PATH_MAX_RETRANS = 8, NET_SCTP_MAX_INIT_RETRANSMITS = 9, NET_SCTP_HB_INTERVAL = 10, - NET_SCTP_MAX_BURST = 11, + NET_SCTP_PRESERVE_ENABLE = 11, + NET_SCTP_MAX_BURST = 12, }; /* CTL_PROC names: */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index e811bf37e4ca..68af144ef56c 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -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_unk_chunk; 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. */ sctp_state_fn_t sctp_sf_do_prm_asoc; @@ -175,7 +177,6 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire; */ /* 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_reshut; 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); /* Prototypes for chunk-building functions. */ sctp_chunk_t *sctp_make_init(const sctp_association_t *, const sctp_bind_addr_t *, - int priority); + int priority, int vparam_len); sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *, const sctp_chunk_t *, const int priority, @@ -322,9 +323,15 @@ sctp_pack_cookie(const sctp_endpoint_t *, const sctp_association_t *, const __u8 *, int addrs_len); sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_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, 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 */ __u32 sctp_generate_tag(const sctp_endpoint_t *); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 4b7f0e451449..fc4a3f1a3b4c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -42,6 +42,7 @@ * Sridhar Samudrala * Daisy Chang * Dajiang Zhang + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -182,6 +183,9 @@ struct SCTP_protocol { /* Valid.Cookie.Life - 60 seconds */ int valid_cookie_life; + + /* Whether Cookie Preservative is enabled(1) or not(0) */ + int cookie_preserve_enable; /* Association.Max.Retrans - 10 attempts * Path.Max.Retrans - 5 attempts (per destination address) @@ -1278,7 +1282,6 @@ struct SCTP_association { /* The cookie life I award for any cookie. */ struct timeval cookie_life; - __u32 cookie_preserve; /* Overall : The overall association error count. * Error Count : [Clear this any time I get something.] diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 17a45a7f6932..e61cf97204f3 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -128,8 +128,9 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, asoc->state_timestamp = jiffies; /* Set things that have constant value. */ - asoc->cookie_life.tv_sec = SCTP_DEFAULT_COOKIE_LIFE_SEC; - asoc->cookie_life.tv_usec = SCTP_DEFAULT_COOKIE_LIFE_USEC; + asoc->cookie_life.tv_sec = sctp_proto.valid_cookie_life / HZ; + asoc->cookie_life.tv_usec = (sctp_proto.valid_cookie_life % HZ) * + 1000000L / HZ; asoc->pmtu = 0; asoc->frag_point = 0; diff --git a/net/sctp/input.c b/net/sctp/input.c index dfec562150ef..d6e64da75733 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -42,6 +42,7 @@ * Hui Huang * Daisy Chang * Sridhar Samudrala + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -279,6 +280,7 @@ int sctp_rcv_ootb(struct sk_buff *skb) { sctp_chunkhdr_t *ch; __u8 *ch_end; + sctp_errhdr_t *err; ch = (sctp_chunkhdr_t *) skb->data; @@ -308,8 +310,9 @@ int sctp_rcv_ootb(struct sk_buff *skb) goto discard; if (ch->type == SCTP_CID_ERROR) { - /* FIXME - Need to check the "Stale cookie" ERROR. */ - goto discard; + err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t)); + if (SCTP_ERROR_STALE_COOKIE == err->cause) + goto discard; } ch = (sctp_chunkhdr_t *) ch_end; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 417d1d9eab07..ff0e0cf471d8 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -40,6 +40,7 @@ * Jon Grimm * Sridhar Samudrala * Daisy Chang + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -691,6 +692,9 @@ int sctp_init(void) /* Valid.Cookie.Life - 60 seconds */ 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 */ sctp_proto.max_burst = SCTP_MAX_BURST; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 288f4ec6edb4..b6f33256b3e5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -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, const sctp_bind_addr_t *bp, - int priority) + int priority, int vparam_len) { sctp_inithdr_t init; union sctp_params addrs; @@ -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(ecap_param); + chunksize += vparam_len; /* RFC 2960 3.3.2 Initiation (INIT) (1) * @@ -1337,7 +1338,7 @@ nodata: sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, const sctp_association_t *asoc, sctp_chunk_t *chunk, int priority, - int *error) + int *error, sctp_chunk_t **err_chk_p) { sctp_association_t *retval = NULL; sctp_signed_cookie_t *cookie; @@ -1394,7 +1395,29 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, * for init collision case of lost COOKIE ACK. */ if (!asoc && tv_lt(bear_cookie->expiration, chunk->skb->stamp)) { - *error = -SCTP_IERROR_STALE_COOKIE; + /* + * 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; + } else + *error = -SCTP_IERROR_NOMEM; + goto fail; } @@ -1751,6 +1774,7 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param, __u16 sat; int retval = 1; sctp_scope_t scope; + time_t stale; /* We maintain all INIT parameters in network byte order all the * 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, break; case SCTP_PARAM_COOKIE_PRESERVATIVE: - asoc->cookie_preserve = - ntohl(param.life->lifespan_increment); + if (!sctp_proto.cookie_preserve_enable) + 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; case SCTP_PARAM_HOST_NAME_ADDRESS: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 6825e088ed7e..84f2ea0fb301 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2,6 +2,7 @@ * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 International Business Machines, Corp. + * Copyright (c) 2001-2002 Intel Corp. * Copyright (c) 2002 Nokia Corp. * * 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, sctp_chunk_t *repl; sctp_ulpevent_t *ev; int error = 0; + sctp_chunk_t *err_chk_p; /* If the packet is an OOTB packet which is temporarily on the * control endpoint, responding with an ABORT. @@ -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 * 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: * 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, case -SCTP_IERROR_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: default: 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, sctp_association_t *new_asoc; int error = 0; char action; + sctp_chunk_t *err_chk_p; /* "Decode" the chunk. We have no optional parameters so we * are in good shape. @@ -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 * 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: * 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, case -SCTP_IERROR_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: default: 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, 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 * @@ -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. */ -sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep, - const sctp_association_t *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands) +sctp_disposition_t sctp_sf_do_5_2_6_stale(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; + 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 - * 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; + attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; - /* If we have gotten too many failures, give up. */ - if (1 + asoc->counters[SctpCounterInits] > asoc->max_init_attempts) { - /* 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()); + if (attempts >= asoc->max_init_attempts) { + sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_NULL()); return SCTP_DISPOSITION_DELETE_TCB; } - retval->counters[0] = SCTP_COUNTER_INCR; - 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); + err = (sctp_errhdr_t *)(chunk->skb->data); /* When calculating the time extension, an implementation * 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, * more than 1 second beyond the measured RTT, due to long * State Cookie lifetimes making the endpoint more subject to * 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}; - bht.extraTime = htonl(rtt + 1000); + stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t))); + stale = stale << 1 / 1000; - initack.init_tag = htonl(asoc->c.my_vtag); - initack.a_rwnd = htonl(atomic_read(&asoc->rnwd)); - initack.num_outbound_streams = htons(asoc->streamoutcnt); - initack.num_inbound_streams = htons(asoc->streamincnt); - initack.initial_tsn = htonl(asoc->c.initSeqNumber); - - sctp_get_my_addrs(asoc, &addrs, &addrs_len); + bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE; + bht.param_hdr.length = htons(sizeof(bht)); + bht.lifespan_increment = htonl(stale); /* Build that new INIT chunk. */ - reply = sctp_make_chunk(SCTP_INITIATION, 0, - sizeof(initack) - + sizeof(bht) - + addrs_len); + bp = (sctp_bind_addr_t *) &asoc->base.bind_addr; + reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht)); if (!reply) goto nomem; - sctp_addto_chunk(reply, sizeof(initack), &initack); + 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)); return SCTP_DISPOSITION_CONSUME; @@ -1809,7 +1868,6 @@ sctp_disposition_t do_5_2_6_stale(const sctp_endpoint_t *ep, nomem: return SCTP_DISPOSITION_NOMEM; } -#endif /* 0 */ /* * Process an ABORT. @@ -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). ... */ - repl = sctp_make_init(asoc, bp, GFP_ATOMIC); + repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); if (!repl) goto nomem; @@ -3992,7 +4050,7 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const sctp_endpoint_t *ep, switch (timer) { case SCTP_EVENT_TIMEOUT_T1_INIT: 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; case SCTP_EVENT_TIMEOUT_T1_COOKIE: @@ -4334,3 +4392,25 @@ void sctp_ootb_pkt_free(sctp_packet_t *packet) sctp_transport_free(packet->transport); 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); + } +} diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index e0744f1f463a..fc603bba8cda 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -295,7 +295,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* 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"}, \ + {.fn = sctp_sf_cookie_echoed_err, .name = "sctp_sf_cookie_echoed_err"}, \ /* SCTP_STATE_ESTABLISHED */ \ {.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 11b3bb63d241..75eee265cbfc 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -1,5 +1,6 @@ /* SCTP kernel reference Implementation * Copyright (c) 2002 International Business Machines Corp. + * Copyright (c) 2002 Intel Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -32,6 +33,7 @@ * Written or modified by: * Mingqin Liu * Jon Grimm + * Ardelle Fan * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -70,6 +72,9 @@ static ctl_table sctp_table[] = { { NET_SCTP_HB_INTERVAL, "hb_interval", &sctp_proto.hb_interval, sizeof(int), 0644, NULL, &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", &sctp_proto.rto_alpha, sizeof(int), 0644, NULL, &proc_dointvec }, -- cgit v1.2.3 From 0e0059c155390fbc430a3a0e9567f0e371b03a11 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Sun, 15 Dec 2002 23:08:03 -0800 Subject: [SCTP] Window update SACK support. --- include/net/sctp/structs.h | 3 +++ net/sctp/associola.c | 2 ++ net/sctp/sm_sideeffect.c | 3 +++ net/sctp/ulpevent.c | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 42 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index fc4a3f1a3b4c..db3a3041bfe8 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1360,6 +1360,9 @@ struct SCTP_association { */ __u32 rwnd; + /* This is the last advertised value of rwnd over a SACK chunk. */ + __u32 a_rwnd; + /* Number of bytes by which the rwnd has slopped. The rwnd is allowed * to slop over a maximum of the association's frag_point. */ diff --git a/net/sctp/associola.c b/net/sctp/associola.c index e61cf97204f3..0bb00779df4f 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -186,6 +186,8 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, else asoc->rwnd = sk->rcvbuf; + asoc->a_rwnd = 0; + asoc->rwnd_over = 0; /* Use my own max window until I learn something better. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index a979d06c4825..6745e28b0bb7 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -737,6 +737,9 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands) if (!sack) goto nomem; + /* Update the last advertised rwnd value. */ + asoc->a_rwnd = asoc->rwnd; + asoc->peer.sack_needed = 0; asoc->peer.next_dup_tsn = 0; diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 7cb59736935a..78d88d00956b 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -762,6 +762,8 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) { sctp_association_t *asoc; sctp_ulpevent_t *event; + sctp_chunk_t *sack; + struct timer_list *timer; /* Current stack structures assume that the rcv buffer is * per socket. For UDP style sockets this is not true as @@ -782,9 +784,39 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) asoc->rwnd += skb->len; } - SCTP_DEBUG_PRINTK("rwnd increased by %d to (%u, %u)\n", - skb->len, asoc->rwnd, asoc->rwnd_over); + SCTP_DEBUG_PRINTK("rwnd increased by %d to (%u, %u) - %u\n", + skb->len, asoc->rwnd, asoc->rwnd_over, asoc->a_rwnd); + + /* Send a window update SACK if the rwnd has increased by at least the + * minimum of the association's PMTU and half of the receive buffer. + * The algorithm used is similar to the one described in Section 4.2.3.3 + * of RFC 1122. + */ + if ((asoc->state == SCTP_STATE_ESTABLISHED) && + (asoc->rwnd > asoc->a_rwnd) && + ((asoc->rwnd - asoc->a_rwnd) >= + min_t(__u32, (asoc->base.sk->rcvbuf >> 1), asoc->pmtu))) { + SCTP_DEBUG_PRINTK("Sending window update SACK- rwnd: %u " + "a_rwnd: %u\n", asoc->rwnd, asoc->a_rwnd); + sack = sctp_make_sack(asoc); + if (!sack) + goto out; + + /* Update the last advertised rwnd value. */ + asoc->a_rwnd = asoc->rwnd; + + asoc->peer.sack_needed = 0; + asoc->peer.next_dup_tsn = 0; + + sctp_push_outqueue(&asoc->outqueue, sack); + + /* Stop the SACK timer. */ + timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK]; + if (timer_pending(timer) && del_timer(timer)) + sctp_association_put(asoc); + } +out: sctp_association_put(asoc); } -- cgit v1.2.3