Commit efcf40ab authored by David S. Miller's avatar David S. Miller

Merge http://linux-lksctp.bkbits.net/lksctp-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 702ab28f 87611822
......@@ -267,7 +267,8 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 };
* nearest power of 2.
*/
enum { SCTP_MIN_PMTU = 576 };
enum { SCTP_MAX_DUP_TSNS = 128 };
enum { SCTP_MAX_DUP_TSNS = 16 };
enum { SCTP_MAX_GABS = 16 };
typedef enum {
SCTP_COUNTER_INIT_ERROR,
......
......@@ -39,6 +39,7 @@
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -311,6 +312,11 @@ void sctp_sysctl_unregister(void);
#else
static inline void sctp_sysctl_register(void) { return; }
static inline void sctp_sysctl_unregister(void) { return; }
static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen, void **context) {
return -ENOSYS;
}
#endif
/* Size of Supported Address Parameter for 'x' address types. */
......@@ -470,7 +476,7 @@ for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
WORD_ROUND(ntohs(err->length));\
err = (sctp_errhdr_t *)((void *)err + \
WORD_ROUND(ntohs(err->length))))
/* Round an int up to the next multiple of 4. */
#define WORD_ROUND(s) (((s)+3)&~3)
......@@ -592,7 +598,7 @@ int static inline __sctp_style(const struct sock *sk, sctp_socket_type_t style)
/* Is the association in this state? */
#define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state))
int static inline __sctp_state(const struct sctp_association *asoc,
int static inline __sctp_state(const struct sctp_association *asoc,
sctp_state_t state)
{
return asoc->state == state;
......
/* SCTP reference Implementation
* Copyright (C) 1999 Cisco, Inc.
* Copyright (C) 1999 Motorola, Inc.
*
* This file originates from Randy Stewart's SCTP reference Implementation.
*
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Randy Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
*/
#ifndef __SLA1_h__
#define __SLA1_h__
struct SLA_1_Context {
unsigned int A;
unsigned int B;
unsigned int C;
unsigned int D;
unsigned int E;
unsigned int H0;
unsigned int H1;
unsigned int H2;
unsigned int H3;
unsigned int H4;
unsigned int words[80];
unsigned int TEMP;
/* block I am collecting to process */
char SLAblock[64];
/* collected so far */
int howManyInBlock;
unsigned int runningTotal;
};
#define F1(B,C,D) (((B & C) | ((~B) & D))) /* 0 <= t <= 19 */
#define F2(B,C,D) (B ^ C ^ D) /* 20 <= t <= 39 */
#define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */
#define F4(B,C,D) (B ^ C ^ D) /*600 <= t <= 79 */
/* circular shift */
#define CSHIFT(A,B) ((B << A) | (B >> (32-A)))
#define K1 0x5a827999 /* 0 <= t <= 19 */
#define K2 0x6ed9eba1 /* 20 <= t <= 39 */
#define K3 0x8f1bbcdc /* 40 <= t <= 59 */
#define K4 0xca62c1d6 /* 60 <= t <= 79 */
#define H0INIT 0x67452301
#define H1INIT 0xefcdab89
#define H2INIT 0x98badcfe
#define H3INIT 0x10325476
#define H4INIT 0xc3d2e1f0
extern void SLA1_Init(struct SLA_1_Context *);
extern void SLA1_Process(struct SLA_1_Context *, const unsigned char *, int);
extern void SLA1_Final(struct SLA_1_Context *, unsigned char *);
#endif
......@@ -84,7 +84,7 @@ typedef sctp_disposition_t (sctp_state_fn_t) (const struct sctp_endpoint *,
typedef void (sctp_timer_event_t) (unsigned long);
typedef struct {
sctp_state_fn_t *fn;
char *name;
const char *name;
} sctp_sm_table_entry_t;
/* A naming convention of "sctp_sf_xxx" applies to all the state functions
......@@ -176,9 +176,6 @@ 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;
sctp_state_fn_t lucky;
sctp_state_fn_t other_stupid;
/* Prototypes for timeout event state functions. Not in use. */
sctp_state_fn_t sctp_do_4_2_reinit;
sctp_state_fn_t sctp_do_4_3_reecho;
......@@ -193,9 +190,9 @@ sctp_state_fn_t sctp_addip_do_asconf_ack;
/* Prototypes for utility support functions. */
__u8 sctp_get_chunk_type(struct sctp_chunk *chunk);
sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
sctp_state_t state,
sctp_subtype_t event_subtype);
const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t,
sctp_state_t,
sctp_subtype_t);
int sctp_chunk_iif(const struct sctp_chunk *);
struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *,
struct sctp_chunk *,
......@@ -284,20 +281,13 @@ int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
int gfp);
/* 2nd level prototypes */
int
sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state,
struct sctp_endpoint *ep,
struct sctp_association *asoc,
void *event_arg,
sctp_disposition_t status,
sctp_cmd_seq_t *retval,
int gfp);
int sctp_cmd_interpreter(sctp_event_t, sctp_subtype_t, sctp_state_t,
struct sctp_endpoint *, struct sctp_association *,
void *event_arg, sctp_disposition_t,
sctp_cmd_seq_t *retval, int gfp);
int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
void sctp_do_TSNdup(struct sctp_association *, struct sctp_chunk *, long gap);
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
......@@ -311,7 +301,7 @@ struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *,
const struct sctp_chunk *);
void sctp_ootb_pkt_free(struct sctp_packet *);
sctp_cookie_param_t *
struct sctp_cookie_param *
sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
const struct sctp_chunk *, int *cookie_len,
const __u8 *, int addrs_len);
......@@ -332,18 +322,18 @@ __u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* 4th level prototypes */
void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *,
void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *,
__u16 port, int iif);
int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *);
int sockaddr2sctp_addr(const union sctp_addr *, sctp_addr_param_t *);
int sockaddr2sctp_addr(const union sctp_addr *, union sctp_addr_param *);
/* Extern declarations for major data structures. */
sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
extern sctp_sm_table_entry_t
const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
extern const sctp_sm_table_entry_t
primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_sm_table_entry_t
extern const sctp_sm_table_entry_t
other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_sm_table_entry_t
extern const sctp_sm_table_entry_t
timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
......
This diff is collapsed.
/* SCTP kernel reference Implementation Copyright (C) 1999-2001
* Cisco, Motorola, Intel, and International Business Machines Corp.
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
......@@ -97,13 +100,16 @@ struct sctp_tsnmap {
/* Data chunks pending receipt. used by SCTP_STATUS sockopt */
__u16 pending_data;
/* We record duplicate TSNs here. We clear this after
/* Record duplicate TSNs here. We clear this after
* every SACK. Store up to SCTP_MAX_DUP_TSNS worth of
* information.
*/
__u32 dup_tsns[SCTP_MAX_DUP_TSNS];
__u16 num_dup_tsns;
/* Record gap ack block information here. */
struct sctp_gap_ack_block gabs[SCTP_MAX_GABS];
int malloced;
__u8 raw_map[0];
......@@ -140,12 +146,18 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn);
void sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn);
/* Retrieve the Cumulative TSN ACK Point. */
__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *);
static inline __u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map)
{
return map->cumulative_tsn_ack_point;
}
/* Retrieve the highest TSN we've seen. */
__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *);
static inline __u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map)
{
return map->max_tsn_seen;
}
/* How many Duplicate TSNs are stored? */
/* How many duplicate TSNs are stored? */
static inline __u16 sctp_tsnmap_num_dups(struct sctp_tsnmap *map)
{
return map->num_dup_tsns;
......@@ -158,6 +170,27 @@ static inline __u32 *sctp_tsnmap_get_dups(struct sctp_tsnmap *map)
return map->dup_tsns;
}
/* How many gap ack blocks do we have recorded? */
__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map);
/* Refresh the count on pending data. */
__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map);
/* Return pointer to gap ack blocks as needed by SACK. */
static inline struct sctp_gap_ack_block *sctp_tsnmap_get_gabs(struct sctp_tsnmap *map)
{
return map->gabs;
}
/* Is there a gap in the TSN map? */
static inline int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
{
int has_gap;
has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen);
return has_gap;
}
/* Mark a duplicate TSN. Note: limit the storage of duplicate TSN
* information.
*/
......
......@@ -40,6 +40,7 @@
* Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ryan Layer <rmlayer@us.ibm.com>
*
*
* Any bugs reported given to us we will try to fix... any fixes shared will
......@@ -517,11 +518,14 @@ struct sctp_rtoinfo {
*/
struct sctp_assocparams {
__u16 sasoc_asocmaxrxt;
sctp_assoc_t sasoc_assoc_id;
__u16 sasoc_asocmaxrxt;
__u16 sasoc_number_peer_destinations;
__u32 sasoc_peer_rwnd;
__u32 sasoc_local_rwnd;
__u32 sasoc_cookie_life;
};
/*
* 7.1.9 Set Primary Address (SCTP_SET_PRIMARY_ADDR)
*
......
......@@ -41,6 +41,7 @@
* Hui Huang <hui.huang@nokia.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ryan Layer <rmlayer@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -125,23 +126,24 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc->base.addr_lock = RW_LOCK_UNLOCKED;
asoc->state = SCTP_STATE_CLOSED;
asoc->state_timestamp = jiffies;
/* Set things that have constant value. */
asoc->cookie_life.tv_sec = sctp_valid_cookie_life / HZ;
asoc->cookie_life.tv_usec = (sctp_valid_cookie_life % HZ) *
1000000L / HZ;
/* Set these values from the socket values, a conversion between
* millsecons to seconds/microseconds must also be done.
*/
asoc->cookie_life.tv_sec = sp->assocparams.sasoc_cookie_life / 1000;
asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
* 1000;
asoc->pmtu = 0;
asoc->frag_point = 0;
/* Initialize the default association max_retrans and RTO values. */
asoc->max_retrans = sctp_max_retrans_association;
asoc->rto_initial = sctp_rto_initial;
asoc->rto_max = sctp_rto_max;
asoc->rto_min = sctp_rto_min;
/* Set the association max_retrans and RTO values from the
* socket values.
*/
asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
asoc->rto_initial = sp->rtoinfo.srto_initial * HZ / 1000;
asoc->rto_max = sp->rtoinfo.srto_max * HZ / 1000;
asoc->rto_min = sp->rtoinfo.srto_min * HZ / 1000;
asoc->overall_error_threshold = asoc->max_retrans;
asoc->overall_error_count = 0;
/* Initialize the maximum mumber of new data packets that can be sent
......@@ -164,7 +166,8 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc->c.sinit_max_instreams = sp->initmsg.sinit_max_instreams;
asoc->c.sinit_num_ostreams = sp->initmsg.sinit_num_ostreams;
asoc->max_init_attempts = sp->initmsg.sinit_max_attempts;
asoc->max_init_timeo = sp->initmsg.sinit_max_init_timeo * HZ;
asoc->max_init_timeo = sp->initmsg.sinit_max_init_timeo * HZ / 1000;
/* Allocate storage for the ssnmap after the inbound and outbound
* streams have been negotiated during Init.
......@@ -281,7 +284,7 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc->default_flags = sp->default_flags;
asoc->default_context = sp->default_context;
asoc->default_timetolive = sp->default_timetolive;
return asoc;
fail_init:
......@@ -384,7 +387,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
if (transport->active)
asoc->peer.active_path = transport;
/*
/*
* SFR-CACC algorithm:
* Upon the receipt of a request to change the primary
* destination address, on the data structure for the new
......@@ -491,9 +494,14 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Initialize the peer's heartbeat interval based on the
* sock configured value.
*/
peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ;
/* Set the path max_retrans. */
peer->max_retrans = asoc->max_retrans;
/* Set the transport's RTO.initial value */
peer->rto = asoc->rto_initial;
/* Attach the remote transport to our asoc. */
list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
......@@ -793,6 +801,26 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
return transport;
}
/* Is this a live association structure. */
int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc)
{
/* First, verify that this is a kernel address. */
if (!sctp_is_valid_kaddr((unsigned long) asoc))
return 0;
/* Verify that this _is_ an sctp_association
* data structure and if so, that the socket matches.
*/
if (SCTP_ASSOC_EYECATCHER != asoc->eyecatcher)
return 0;
if (asoc->base.sk != sk)
return 0;
/* The association is valid. */
return 1;
}
/* Do delayed input processing. This is scheduled by sctp_rcv(). */
static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
{
......@@ -801,7 +829,6 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
struct sock *sk;
struct sctp_inq *inqueue;
int state, subtype;
sctp_assoc_t associd = sctp_assoc2id(asoc);
int error = 0;
/* The association should be held so we should be safe. */
......@@ -831,7 +858,7 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
/* Check to see if the association is freed in response to
* the incoming chunk. If so, get out of the while loop.
*/
if (!sctp_id2assoc(sk, associd))
if (!sctp_assoc_valid(sk, asoc))
break;
/* If there is an error on chunk, discard this packet. */
......@@ -1033,7 +1060,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
}
/* Increase asoc's rwnd by len and send any window update SACK if needed. */
void sctp_assoc_rwnd_increase(struct sctp_association *asoc, int len)
void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
{
struct sctp_chunk *sack;
struct timer_list *timer;
......@@ -1079,7 +1106,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, int len)
}
/* Decrease asoc's rwnd by len. */
void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, int len)
void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
{
SCTP_ASSERT(asoc->rwnd, "rwnd zero", return);
SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return);
......@@ -1119,11 +1146,11 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, int gfp)
/* Build the association's bind address list from the cookie. */
int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
sctp_cookie_t *cookie, int gfp)
struct sctp_cookie *cookie, int gfp)
{
int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length);
int var_size3 = cookie->raw_addr_list_len;
__u8 *raw = (__u8 *)cookie + sizeof(sctp_cookie_t) + var_size2;
__u8 *raw = (__u8 *)cookie + sizeof(struct sctp_cookie) + var_size2;
return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3,
asoc->ep->base.bind_addr.port, gfp);
......
......@@ -65,7 +65,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, int gfp, int flags)
{
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
struct list_head *pos;
int error = 0;
......@@ -74,7 +74,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
/* Extract the addresses which are relevant for this scope. */
list_for_each(pos, &src->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
error = sctp_copy_one_addr(dest, &addr->a, scope,
gfp, flags);
if (error < 0)
......@@ -87,7 +87,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
*/
if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
list_for_each(pos, &src->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list,
addr = list_entry(pos, struct sctp_sockaddr_entry,
list);
error = sctp_copy_one_addr(dest, &addr->a,
SCTP_SCOPE_LINK, gfp,
......@@ -135,12 +135,12 @@ void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
/* Dispose of the address list. */
static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
{
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
struct list_head *pos, *temp;
/* Empty the bind address list. */
list_for_each_safe(pos, temp, &bp->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
list_del(pos);
kfree(addr);
SCTP_DBG_OBJCNT_DEC(addr);
......@@ -163,14 +163,14 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp)
int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
int gfp)
{
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
/* Add the address to the bind address list. */
addr = t_new(struct sockaddr_storage_list, gfp);
addr = t_new(struct sctp_sockaddr_entry, gfp);
if (!addr)
return -ENOMEM;
addr->a = *new;
memcpy(&addr->a, new, sizeof(*new));
/* Fix up the port if it has not yet been set.
* Both v4 and v6 have the port at the same offset.
......@@ -191,10 +191,10 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
{
struct list_head *pos, *temp;
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
list_for_each_safe(pos, temp, &bp->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
/* Found the exact match. */
list_del(pos);
......@@ -219,22 +219,22 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
union sctp_params addrparms;
union sctp_params retval;
int addrparms_len;
sctp_addr_param_t rawaddr;
union sctp_addr_param rawaddr;
int len;
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
struct list_head *pos;
addrparms_len = 0;
len = 0;
/* Allocate enough memory at once. */
list_for_each(pos, &bp->address_list) {
len += sizeof(sctp_addr_param_t);
len += sizeof(union sctp_addr_param);
}
/* Don't even bother embedding an address if there
* is only one.
*/
if (len == sizeof(sctp_addr_param_t)) {
if (len == sizeof(union sctp_addr_param)) {
retval.v = NULL;
goto end_raw;
}
......@@ -246,7 +246,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
addrparms = retval;
list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
len = sockaddr2sctp_addr(&addr->a, &rawaddr);
memcpy(addrparms.v, &rawaddr, len);
addrparms.v += len;
......@@ -265,16 +265,16 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
int addrs_len, __u16 port, int gfp)
{
sctp_addr_param_t *rawaddr;
sctp_paramhdr_t *param;
union sctp_addr_param *rawaddr;
struct sctp_paramhdr *param;
union sctp_addr addr;
int retval = 0;
int len;
/* Convert the raw address to standard address format */
while (addrs_len) {
param = (sctp_paramhdr_t *)raw_addr_list;
rawaddr = (sctp_addr_param_t *)raw_addr_list;
param = (struct sctp_paramhdr *)raw_addr_list;
rawaddr = (union sctp_addr_param *)raw_addr_list;
switch (param->type) {
case SCTP_PARAM_IPV4_ADDRESS:
......@@ -312,11 +312,11 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp,
const union sctp_addr *addr,
struct sctp_opt *opt)
{
struct sockaddr_storage_list *laddr;
struct sctp_sockaddr_entry *laddr;
struct list_head *pos;
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sockaddr_storage_list, list);
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
if (opt->pf->cmp_addr(&laddr->a, addr, opt))
return 1;
}
......
......@@ -129,7 +129,7 @@ struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
sp->rtoinfo.srto_initial;
sp->rtoinfo.srto_initial * HZ / 1000;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
/* sctpimpguide-05 Section 2.12.2
......@@ -137,7 +137,7 @@ struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
* recommended value of 5 times 'RTO.Max'.
*/
ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
= 5 * sp->rtoinfo.srto_max;
= 5 * (sp->rtoinfo.srto_max * HZ / 1000);
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
......@@ -313,13 +313,13 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
const union sctp_addr *paddr)
{
struct list_head *pos;
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
struct sctp_bind_addr *bp;
sctp_read_lock(&ep->base.addr_lock);
bp = &ep->base.bind_addr;
list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if (sctp_has_association(&addr->a, paddr)) {
sctp_read_unlock(&ep->base.addr_lock);
return 1;
......
/* SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
*
* This file origiantes from Randy Stewart's SCTP reference Implementation.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Randy Stewart rstewar1@email.mot.com
* Ken Morneau kmorneau@cisco.com
* Qiaobing Xie qxie1@email.mot.com
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorperated into the next SCTP release.
*
* There are still LOTS of bugs in this code... I always run on the motto
* "it is a wonder any code ever works :)"
*/
#include <linux/types.h>
#include <asm/string.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sla1.h>
/* SCTP Main driver.
* passing a two pointers and two lengths,
* returning a digest pointer filled. The md5 code
* was taken directly from the RFC (2104) so to understand it
* you may want to go look at the RFC referenced in the
* SCTP spec. We did modify this code to either user OUR
* implementation of SLA1 or the MD5 that comes from its
* RFC. SLA1 may have IPR issues so you need to check in
* to this if you wish to use it... Or at least that is
* what the FIP-180.1 web page says.
*/
void sctp_hash_digest(const char *key, const int in_key_len,
const char *text, const int text_len,
__u8 *digest)
{
int key_len = in_key_len;
struct SLA_1_Context context;
__u8 k_ipad[65]; /* inner padding -
* key XORd with ipad
*/
__u8 k_opad[65]; /* outer padding -
* key XORd with opad
*/
__u8 tk[20];
int i;
/* if key is longer than 64 bytes reset it to key=MD5(key) */
if (key_len > 64) {
struct SLA_1_Context tctx;
SLA1_Init(&tctx);
SLA1_Process(&tctx, key, key_len);
SLA1_Final(&tctx,tk);
key = tk;
key_len = 20;
}
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < 64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner hash */
SLA1_Init(&context); /* init context for 1st
* pass
*/
SLA1_Process(&context, k_ipad, 64); /* start with inner pad */
SLA1_Process(&context, text, text_len); /* then text of datagram */
SLA1_Final(&context,digest); /* finish up 1st pass */
/*
* perform outer hash
*/
SLA1_Init(&context); /* init context for 2nd
* pass
*/
SLA1_Process(&context, k_opad, 64); /* start with outer pad */
SLA1_Process(&context, digest, 20); /* then results of 1st
* hash
*/
SLA1_Final(&context, digest); /* finish up 2nd pass */
}
......@@ -248,7 +248,7 @@ void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
{
struct sctp_bind_addr *bp;
rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr;
struct sctp_sockaddr_entry *laddr;
struct list_head *pos;
sctp_scope_t scope;
union sctp_addr *baddr = NULL;
......@@ -277,7 +277,7 @@ void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
*/
sctp_read_lock(addr_lock);
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sockaddr_storage_list, list);
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
if ((laddr->a.sa.sa_family == AF_INET6) &&
(scope <= sctp_scope(&laddr->a))) {
bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
......@@ -309,7 +309,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
{
struct inet6_dev *in6_dev;
struct inet6_ifaddr *ifp;
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
read_lock(&addrconf_lock);
if ((in6_dev = __in6_dev_get(dev)) == NULL) {
......@@ -320,7 +320,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
read_lock(&in6_dev->lock);
for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) {
/* Add the address to the local list. */
addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC);
addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
if (addr) {
addr->a.v6.sin6_family = AF_INET6;
addr->a.v6.sin6_port = 0;
......
......@@ -1012,7 +1012,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
__u32 sack_ctsn, ctsn, tsn;
__u32 highest_tsn, highest_new_tsn;
__u32 sack_a_rwnd;
int outstanding;
unsigned outstanding;
struct sctp_transport *primary = asoc->peer.primary_path;
int count_of_newacks = 0;
......
......@@ -133,12 +133,12 @@ void sctp_snmp_proc_exit(void)
static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
{
struct list_head *pos;
struct sockaddr_storage_list *laddr;
struct sctp_sockaddr_entry *laddr;
union sctp_addr *addr;
struct sctp_af *af;
list_for_each(pos, &epb->bind_addr.address_list) {
laddr = list_entry(pos, struct sockaddr_storage_list, list);
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
addr = (union sctp_addr *)&laddr->a;
af = sctp_get_af_specific(addr->sa.sa_family);
af->seq_dump_addr(seq, addr);
......
......@@ -143,7 +143,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
read_lock(&inetdev_lock);
if ((in_dev = __in_dev_get(dev)) == NULL) {
......@@ -154,7 +154,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
read_lock(&in_dev->lock);
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
/* Add the address to the local list. */
addr = t_new(struct sockaddr_storage_list, GFP_ATOMIC);
addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
if (addr) {
addr->a.v4.sin_family = AF_INET;
addr->a.v4.sin_port = 0;
......@@ -198,11 +198,11 @@ static void sctp_get_local_addr_list(void)
/* Free the existing local addresses. */
static void __sctp_free_local_addr_list(void)
{
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
struct list_head *pos, *temp;
list_for_each_safe(pos, temp, &sctp_local_addr_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
list_del(pos);
kfree(addr);
}
......@@ -222,14 +222,14 @@ static void sctp_free_local_addr_list(void)
int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
int gfp, int copy_flags)
{
struct sockaddr_storage_list *addr;
struct sctp_sockaddr_entry *addr;
int error = 0;
struct list_head *pos;
unsigned long flags;
sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
list_for_each(pos, &sctp_local_addr_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list);
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if (sctp_in_scope(&addr->a, scope)) {
/* Now that the address is in scope, check to see if
* the address type is really supported by the local
......@@ -412,7 +412,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
struct flowi fl;
struct sctp_bind_addr *bp;
rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr;
struct sctp_sockaddr_entry *laddr;
struct list_head *pos;
struct dst_entry *dst = NULL;
union sctp_addr dst_saddr;
......@@ -447,7 +447,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
*/
sctp_read_lock(addr_lock);
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sockaddr_storage_list,
laddr = list_entry(pos, struct sctp_sockaddr_entry,
list);
sctp_v4_dst_saddr(&dst_saddr, dst, bp->port);
if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
......@@ -467,7 +467,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
*/
sctp_read_lock(addr_lock);
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sockaddr_storage_list, list);
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
if (AF_INET == laddr->a.sa.sa_family) {
fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
......
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
*
* This file is part of the SCTP kernel reference Implementation
*
* (It's really SHA-1 but Hey I was tired when I created this
* file, and on a plane to France :-)
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Randall Stewart <rstewar1@email.mot.com>
* kmorneau@cisco.com
* qxie1@email.mot.com
*
* Based on:
* Randy Stewart, et al. SCTP Reference Implementation which is licenced
* under the GPL.
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fcntl.h>
#include <asm/string.h> /* for memcpy */
#include <linux/sched.h> /* dead chicken for in.h */
#include <linux/in.h> /* for htonl and ntohl */
#include <net/sctp/sla1.h>
void SLA1_Init(struct SLA_1_Context *ctx)
{
/* Init the SLA-1 context structure. */
ctx->A = 0;
ctx->B = 0;
ctx->C = 0;
ctx->D = 0;
ctx->E = 0;
ctx->H0 = H0INIT;
ctx->H1 = H1INIT;
ctx->H2 = H2INIT;
ctx->H3 = H3INIT;
ctx->H4 = H4INIT;
ctx->TEMP = 0;
memset(ctx->words, 0, sizeof(ctx->words));
ctx->howManyInBlock = 0;
ctx->runningTotal = 0;
}
void SLA1processABlock(struct SLA_1_Context *ctx,unsigned int *block)
{
int i;
/* init the W0-W15 to the block of words being
* hashed.
*/
/* step a) */
for (i = 0; i < 16; i++)
ctx->words[i] = ntohl(block[i]);
/* now init the rest based on the SLA-1 formula, step b) */
for (i = 16; i < 80; i++)
ctx->words[i] =
CSHIFT(1, ((ctx->words[(i-3)]) ^
(ctx->words[(i-8)]) ^
(ctx->words[(i-14)]) ^
(ctx->words[(i-16)])));
/* step c) */
ctx->A = ctx->H0;
ctx->B = ctx->H1;
ctx->C = ctx->H2;
ctx->D = ctx->H3;
ctx->E = ctx->H4;
/* step d) */
for (i = 0; i < 80; i++) {
if (i < 20) {
ctx->TEMP = ((CSHIFT(5, ctx->A)) +
(F1(ctx->B, ctx->C, ctx->D)) +
(ctx->E) +
ctx->words[i] +
K1
);
} else if (i < 40) {
ctx->TEMP = ((CSHIFT(5, ctx->A)) +
(F2(ctx->B, ctx->C, ctx->D)) +
(ctx->E) +
(ctx->words[i]) +
K2
);
} else if (i < 60) {
ctx->TEMP = ((CSHIFT(5, ctx->A)) +
(F3(ctx->B, ctx->C, ctx->D)) +
(ctx->E) +
(ctx->words[i]) +
K3
);
} else {
ctx->TEMP = ((CSHIFT(5, ctx->A)) +
(F4(ctx->B, ctx->C, ctx->D)) +
(ctx->E) +
(ctx->words[i]) +
K4
);
}
ctx->E = ctx->D;
ctx->D = ctx->C;
ctx->C = CSHIFT(30, ctx->B);
ctx->B = ctx->A;
ctx->A = ctx->TEMP;
}
/* step e) */
ctx->H0 = (ctx->H0) + (ctx->A);
ctx->H1 = (ctx->H1) + (ctx->B);
ctx->H2 = (ctx->H2) + (ctx->C);
ctx->H3 = (ctx->H3) + (ctx->D);
ctx->H4 = (ctx->H4) + (ctx->E);
}
void SLA1_Process(struct SLA_1_Context *ctx, const unsigned char *ptr, int siz)
{
int numberLeft, leftToFill;
numberLeft = siz;
while (numberLeft > 0) {
leftToFill = sizeof(ctx->SLAblock) - ctx->howManyInBlock;
if (leftToFill > numberLeft) {
/* can only partially fill up this one */
memcpy(&ctx->SLAblock[ctx->howManyInBlock],
ptr, numberLeft);
ctx->howManyInBlock += siz;
ctx->runningTotal += siz;
break;
} else {
/* block is now full, process it */
memcpy(&ctx->SLAblock[ctx->howManyInBlock],
ptr, leftToFill);
SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
numberLeft -= leftToFill;
ctx->runningTotal += leftToFill;
ctx->howManyInBlock = 0;
}
}
}
void SLA1_Final(struct SLA_1_Context *ctx, unsigned char *digestBuf)
{
/* if any left in block fill with padding
* and process. Then transfer the digest to
* the pointer. At the last block some special
* rules need to apply. We must add a 1 bit
* following the message, then we pad with
* 0's. The total size is encoded as a 64 bit
* number at the end. Now if the last buffer has
* more than 55 octets in it we cannot fit
* the 64 bit number + 10000000 pad on the end
* and must add the 10000000 pad, pad the rest
* of the message with 0's and then create a
* all 0 message with just the 64 bit size
* at the end and run this block through by itself.
* Also the 64 bit int must be in network byte
* order.
*/
int i, leftToFill;
unsigned int *ptr;
if (ctx->howManyInBlock > 55) {
/* special case, we need to process two
* blocks here. One for the current stuff
* plus possibly the pad. The other for
* the size.
*/
leftToFill = sizeof(ctx->SLAblock) - ctx->howManyInBlock;
if (leftToFill == 0) {
/* Should not really happen but I am paranoid */
/* Not paranoid enough! It is possible for leftToFill
* to become negative! AAA!!!! This is another reason
* to pick MD5 :-)...
*/
SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
/* init last block, a bit different then the rest :-) */
ctx->SLAblock[0] = 0x80;
for (i = 1; i < sizeof(ctx->SLAblock); i++) {
ctx->SLAblock[i] = 0x0;
}
} else if (leftToFill == 1) {
ctx->SLAblock[ctx->howManyInBlock] = 0x80;
SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
/* init last block */
memset(ctx->SLAblock, 0, sizeof(ctx->SLAblock));
} else {
ctx->SLAblock[ctx->howManyInBlock] = 0x80;
for (i = (ctx->howManyInBlock + 1);
i < sizeof(ctx->SLAblock);
i++) {
ctx->SLAblock[i] = 0x0;
}
SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
/* init last block */
memset(ctx->SLAblock, 0, sizeof(ctx->SLAblock));
}
/* This is in bits so multiply by 8 */
ctx->runningTotal *= 8;
ptr = (unsigned int *) &ctx->SLAblock[60];
*ptr = htonl(ctx->runningTotal);
SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
} else {
/* easy case, we just pad this
* message to size - end with 0
* add the magic 0x80 to the next
* word and then put the network byte
* order size in the last spot and
* process the block.
*/
ctx->SLAblock[ctx->howManyInBlock] = 0x80;
for (i = (ctx->howManyInBlock + 1);
i < sizeof(ctx->SLAblock);
i++) {
ctx->SLAblock[i] = 0x0;
}
/* get last int spot */
ctx->runningTotal *= 8;
ptr = (unsigned int *) &ctx->SLAblock[60];
*ptr = htonl(ctx->runningTotal);
SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
}
/* Now at this point all we need do is transfer the
* digest back to the user
*/
digestBuf[3] = (ctx->H0 & 0xff);
digestBuf[2] = ((ctx->H0 >> 8) & 0xff);
digestBuf[1] = ((ctx->H0 >> 16) & 0xff);
digestBuf[0] = ((ctx->H0 >> 24) & 0xff);
digestBuf[7] = (ctx->H1 & 0xff);
digestBuf[6] = ((ctx->H1 >> 8) & 0xff);
digestBuf[5] = ((ctx->H1 >> 16) & 0xff);
digestBuf[4] = ((ctx->H1 >> 24) & 0xff);
digestBuf[11] = (ctx->H2 & 0xff);
digestBuf[10] = ((ctx->H2 >> 8) & 0xff);
digestBuf[9] = ((ctx->H2 >> 16) & 0xff);
digestBuf[8] = ((ctx->H2 >> 24) & 0xff);
digestBuf[15] = (ctx->H3 & 0xff);
digestBuf[14] = ((ctx->H3 >> 8) & 0xff);
digestBuf[13] = ((ctx->H3 >> 16) & 0xff);
digestBuf[12] = ((ctx->H3 >> 24) & 0xff);
digestBuf[19] = (ctx->H4 & 0xff);
digestBuf[18] = ((ctx->H4 >> 8) & 0xff);
digestBuf[17] = ((ctx->H4 >> 16) & 0xff);
digestBuf[16] = ((ctx->H4 >> 24) & 0xff);
}
......@@ -589,27 +589,17 @@ struct sctp_chunk *sctp_make_data_empty(struct sctp_association *asoc,
struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
{
struct sctp_chunk *retval;
sctp_sackhdr_t sack;
sctp_gap_ack_block_t gab;
int length;
struct sctp_sackhdr sack;
int len;
__u32 ctsn;
struct sctp_tsnmap_iter iter;
__u16 num_gabs, num_dup_tsns;
struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
ctsn = sctp_tsnmap_get_ctsn(map);
SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn);
/* Count the number of Gap Ack Blocks. */
num_gabs = 0;
if (sctp_tsnmap_has_gap(map)) {
sctp_tsnmap_iter_init(map, &iter);
while (sctp_tsnmap_next_gap_ack(map, &iter,
&gab.start, &gab.end))
num_gabs++;
}
SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn);
/* How much room is needed in the chunk? */
num_gabs = sctp_tsnmap_num_gabs(map);
num_dup_tsns = sctp_tsnmap_num_dups(map);
/* Initialize the SACK header. */
......@@ -618,12 +608,12 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
sack.num_gap_ack_blocks = htons(num_gabs);
sack.num_dup_tsns = htons(num_dup_tsns);
length = sizeof(sack)
+ sizeof(sctp_gap_ack_block_t) * num_gabs
len = sizeof(sack)
+ sizeof(struct sctp_gap_ack_block) * num_gabs
+ sizeof(__u32) * num_dup_tsns;
/* Create the chunk. */
retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, length);
retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len);
if (!retval)
goto nodata;
......@@ -662,21 +652,15 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
retval->subh.sack_hdr =
sctp_addto_chunk(retval, sizeof(sack), &sack);
/* Put the Gap Ack Blocks into the chunk. */
if (num_gabs) {
sctp_tsnmap_iter_init(map, &iter);
while(sctp_tsnmap_next_gap_ack(map, &iter,
&gab.start, &gab.end)) {
gab.start = htons(gab.start);
gab.end = htons(gab.end);
sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t),
&gab);
}
}
/* Add the gap ack block information. */
if (num_gabs)
sctp_addto_chunk(retval, sizeof(__u32) * num_gabs,
sctp_tsnmap_get_gabs(map));
/* Register the duplicates. */
sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
sctp_tsnmap_get_dups(map));
/* Add the duplicate TSN information. */
if (num_dup_tsns)
sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
sctp_tsnmap_get_dups(map));
nodata:
return retval;
......@@ -1275,14 +1259,14 @@ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
const __u8 *raw_addrs, int addrs_len)
{
sctp_cookie_param_t *retval;
sctp_signed_cookie_t *cookie;
struct sctp_signed_cookie *cookie;
struct scatterlist sg;
int headersize, bodysize;
unsigned int keylen;
char *key;
headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
bodysize = sizeof(sctp_cookie_t)
bodysize = sizeof(struct sctp_cookie)
+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
/* Pad out the cookie to a multiple to make the signature
......@@ -1304,7 +1288,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
* out on the network.
*/
memset(retval, 0x00, *cookie_len);
cookie = (sctp_signed_cookie_t *) retval->body;
cookie = (struct sctp_signed_cookie *) retval->body;
/* Set up the parameter header. */
retval->p.type = SCTP_PARAM_STATE_COOKIE;
......@@ -1351,26 +1335,26 @@ struct sctp_association *sctp_unpack_cookie(
int *error, struct sctp_chunk **errp)
{
struct sctp_association *retval = NULL;
sctp_signed_cookie_t *cookie;
sctp_cookie_t *bear_cookie;
struct sctp_signed_cookie *cookie;
struct sctp_cookie *bear_cookie;
int headersize, bodysize, fixed_size;
__u8 digest[SCTP_SIGNATURE_SIZE];
struct scatterlist sg;
unsigned int keylen;
unsigned int keylen, len;
char *key;
sctp_scope_t scope;
struct sk_buff *skb = chunk->skb;
headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
fixed_size = headersize + sizeof(sctp_cookie_t);
fixed_size = headersize + sizeof(struct sctp_cookie);
/* Verify that the chunk looks like it even has a cookie.
* There must be enough room for our cookie and our peer's
* INIT chunk.
*/
if (ntohs(chunk->chunk_hdr->length) <
(fixed_size + sizeof(sctp_chunkhdr_t)))
len = ntohs(chunk->chunk_hdr->length);
if (len < fixed_size + sizeof(struct sctp_chunkhdr))
goto malformed;
/* Verify that the cookie has been padded out. */
......@@ -1454,7 +1438,7 @@ struct sctp_association *sctp_unpack_cookie(
retval->peer.port = ntohs(chunk->sctp_hdr->source);
/* Populate the association from the cookie. */
retval->c = *bear_cookie;
memcpy(&retval->c, bear_cookie, sizeof(*bear_cookie));
if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie,
GFP_ATOMIC) < 0) {
......@@ -2022,7 +2006,7 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
********************************************************************/
/* Convert from an SCTP IP parameter to a union sctp_addr. */
void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *param,
void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *param,
__u16 port, int iif)
{
switch(param->v4.param_hdr.type) {
......@@ -2073,7 +2057,7 @@ int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa)
/* Convert a sockaddr_in to an IP address in an SCTP param.
* Returns len if a valid conversion was possible.
*/
int sockaddr2sctp_addr(const union sctp_addr *sa, sctp_addr_param_t *p)
int sockaddr2sctp_addr(const union sctp_addr *sa, union sctp_addr_param *p)
{
int len = 0;
......
......@@ -608,13 +608,13 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds,
}
/* Helper function to change the state of an association. */
static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *asoc,
static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
struct sctp_association *asoc,
sctp_state_t state)
{
struct sock *sk = asoc->base.sk;
asoc->state = state;
asoc->state_timestamp = jiffies;
if (sctp_style(sk, TCP)) {
/* Change the sk->sk_state of a TCP-style socket that has
......@@ -702,7 +702,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
int gfp)
{
sctp_cmd_seq_t commands;
sctp_sm_table_entry_t *state_fn;
const sctp_sm_table_entry_t *state_fn;
sctp_disposition_t status;
int error = 0;
typedef const char *(printfn_t)(sctp_subtype_t);
......
......@@ -45,6 +45,7 @@
* Dajiang Zhang <dajiang.zhang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -537,7 +538,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
* are in good shape.
*/
chunk->subh.cookie_hdr =
(sctp_signed_cookie_t *)chunk->skb->data;
(struct sctp_signed_cookie *)chunk->skb->data;
skb_pull(chunk->skb,
ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
......@@ -738,7 +739,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
{
struct sctp_transport *transport = (struct sctp_transport *) arg;
if (asoc->overall_error_count > asoc->overall_error_threshold) {
if (asoc->overall_error_count > asoc->max_retrans) {
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
......@@ -924,16 +925,16 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
{
int len;
struct sctp_packet *pkt;
sctp_addr_param_t *addrparm;
sctp_errhdr_t *errhdr;
union sctp_addr_param *addrparm;
struct sctp_errhdr *errhdr;
struct sctp_endpoint *ep;
char buffer[sizeof(sctp_errhdr_t) + sizeof(sctp_addr_param_t)];
char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)];
/* Build the error on the stack. We are way to malloc crazy
* throughout the code today.
*/
errhdr = (sctp_errhdr_t *)buffer;
addrparm = (sctp_addr_param_t *)errhdr->variable;
errhdr = (struct sctp_errhdr *)buffer;
addrparm = (union sctp_addr_param *)errhdr->variable;
/* Copy into a parm format. */
len = sockaddr2sctp_addr(ssa, addrparm);
......@@ -1618,7 +1619,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
chunk->subh.cookie_hdr = (sctp_signed_cookie_t *)chunk->skb->data;
chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
sizeof(sctp_chunkhdr_t));
......@@ -1866,7 +1867,7 @@ sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
* yield a higher probability of success on the reattempt.
*/
stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t)));
stale = stale << 1 / 1000;
stale = (stale * 2) / 1000;
bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE;
bht.param_hdr.length = htons(sizeof(bht));
......@@ -1947,22 +1948,23 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
unsigned len;
__u16 error = SCTP_ERROR_NO_ERROR;
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
if (chunk && (ntohs(chunk->chunk_hdr->length) >=
(sizeof(struct sctp_chunkhdr) +
sizeof(struct sctp_errhdr))))
/* Check that chunk header looks valid. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
SCTP_INC_STATS(SctpAborteds);
SCTP_DEC_STATS(SctpCurrEstab);
/* BUG? This does not look complete... */
return SCTP_DISPOSITION_ABORT;
}
......@@ -1978,6 +1980,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
unsigned len;
__u16 error = SCTP_ERROR_NO_ERROR;
if (!sctp_vtag_verify_either(chunk, asoc))
......@@ -1989,9 +1992,9 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
if (chunk && (ntohs(chunk->chunk_hdr->length) >=
(sizeof(struct sctp_chunkhdr) +
sizeof(struct sctp_errhdr))))
/* Check that chunk header looks valid. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
/* CMD_INIT_FAILED will DELETE_TCB. */
......@@ -3201,82 +3204,6 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_CONSUME;
}
#if 0
/*
* We did something stupid but got lucky. Namely, we sent a HEARTBEAT
* before the association was all the way up and we did NOT get an
* ABORT.
*
* Log the fact and then process normally.
*
* Section: Not specified
* Verification Tag: 8.5 Verification Tag [Normal verification]
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t lucky(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
/* 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 (chunk->sctp_hdr->vtag != asoc->c.my_vtag)
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
return SCTP_DISPOSITION_CONSUME;
nomem:
return SCTP_DISPOSITION_NOMEM;
}
#endif /* 0 */
#if 0
/*
* The other end is doing something very stupid. We'll ignore them
* after logging their idiocy. :-)
*
* Section: Not specified
* Verification Tag: 8.5 Verification Tag [Normal verification]
* Inputs
* (endpoint, asoc, chunk)
*
* Outputs
* (asoc, reply_msg, msg_up, timers, counters)
*
* The return value is the disposition of the chunk.
*/
sctp_disposition_t other_stupid(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
/* 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 (chunk->sctp_hdr->vtag != asoc->c.my_vtag)
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
return SCTP_DISPOSITION_CONSUME;
nomem:
return SCTP_DISPOSITION_NOMEM;
}
#endif /* 0 */
/*
* The other end is violating protocol.
......@@ -4070,7 +3997,7 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
{
struct sctp_transport *transport = arg;
if (asoc->overall_error_count >= asoc->overall_error_threshold) {
if (asoc->overall_error_count >= asoc->max_retrans) {
/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
......@@ -4241,7 +4168,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
struct sctp_chunk *reply = NULL;
SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
if (asoc->overall_error_count >= asoc->overall_error_threshold) {
if (asoc->overall_error_count >= asoc->max_retrans) {
/* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
......@@ -4500,13 +4427,21 @@ struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
if (asoc) {
vtag = asoc->peer.i.init_tag;
} else {
/* Special case the INIT as there is no vtag yet. */
if (SCTP_CID_INIT == chunk->chunk_hdr->type) {
/* Special case the INIT and stale COOKIE_ECHO as there is no
* vtag yet.
*/
switch(chunk->chunk_hdr->type) {
case SCTP_CID_INIT:
{
sctp_init_chunk_t *init;
init = (sctp_init_chunk_t *)chunk->chunk_hdr;
vtag = ntohl(init->init_hdr.init_tag);
} else {
break;
}
default:
vtag = ntohl(chunk->sctp_hdr->vtag);
break;
}
}
......@@ -4557,6 +4492,12 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
if (err_chunk) {
packet = sctp_ootb_pkt_new(asoc, chunk);
if (packet) {
struct sctp_signed_cookie *cookie;
/* Override the OOTB vtag from the cookie. */
cookie = chunk->subh.cookie_hdr;
packet->vtag = cookie->c.peer_vtag;
/* Set the skb to the belonging sock for accounting. */
err_chunk->skb->sk = ep->base.sk;
sctp_packet_append_chunk(packet, err_chunk);
......
......@@ -49,7 +49,7 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
static sctp_sm_table_entry_t bug = {
static const sctp_sm_table_entry_t bug = {
.fn = sctp_sf_bug,
.name = "sctp_sf_bug"
};
......@@ -64,9 +64,9 @@ static sctp_sm_table_entry_t bug = {
} \
return &_table[event_subtype._type][(int)state];
sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
sctp_state_t state,
sctp_subtype_t event_subtype)
const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
sctp_state_t state,
sctp_subtype_t event_subtype)
{
switch (event_type) {
case SCTP_EVENT_T_CHUNK:
......@@ -418,7 +418,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
*
* For base protocol (RFC 2960).
*/
sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_DATA,
TYPE_SCTP_INIT,
TYPE_SCTP_INIT_ACK,
......@@ -437,7 +437,7 @@ sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NU
}; /* state_fn_t chunk_event_table[][] */
static sctp_sm_table_entry_t
static const sctp_sm_table_entry_t
chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"},
......@@ -586,7 +586,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* The primary index for this table is the primitive type.
* The secondary index for this table is the state.
*/
sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_PRIMITIVE_ASSOCIATE,
TYPE_SCTP_PRIMITIVE_SHUTDOWN,
TYPE_SCTP_PRIMITIVE_ABORT,
......@@ -617,7 +617,7 @@ sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
}
sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_OTHER_NO_PENDING_TSN,
};
......@@ -811,7 +811,7 @@ sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STA
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_EVENT_TIMEOUT_NONE,
TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE,
TYPE_SCTP_EVENT_TIMEOUT_T1_INIT,
......@@ -823,7 +823,8 @@ sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
};
sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, sctp_state_t state)
const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
sctp_state_t state)
{
if (state > SCTP_STATE_MAX)
return &bug;
......
This diff is collapsed.
/* SCTP kernel reference Implementation
/* 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
*
* Sysctl related interfaces for SCTP.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
*
* Sysctl related interfaces for SCTP.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* 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
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* 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
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Written or modified by:
* Mingqin Liu <liuming@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -42,42 +43,54 @@
#include <net/sctp/structs.h>
#include <linux/sysctl.h>
static ctl_handler sctp_sysctl_jiffies_ms;
static long rto_timer_min = 0;
static long rto_timer_max = 86400000; /* One day */
static ctl_table sctp_table[] = {
{
.ctl_name = NET_SCTP_RTO_INITIAL,
.procname = "rto_initial",
.data = &sctp_rto_initial,
.maxlen = sizeof(int),
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sctp_sysctl_jiffies_ms,
.extra1 = &rto_timer_min,
.extra2 = &rto_timer_max
},
{
.ctl_name = NET_SCTP_RTO_MIN,
.procname = "rto_min",
.data = &sctp_rto_min,
.maxlen = sizeof(int),
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sctp_sysctl_jiffies_ms,
.extra1 = &rto_timer_min,
.extra2 = &rto_timer_max
},
{
.ctl_name = NET_SCTP_RTO_MAX,
.procname = "rto_max",
.data = &sctp_rto_max,
.maxlen = sizeof(int),
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sctp_sysctl_jiffies_ms,
.extra1 = &rto_timer_min,
.extra2 = &rto_timer_max
},
{
.ctl_name = NET_SCTP_VALID_COOKIE_LIFE,
.procname = "valid_cookie_life",
.data = &sctp_valid_cookie_life,
.maxlen = sizeof(int),
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sctp_sysctl_jiffies_ms,
.extra1 = &rto_timer_min,
.extra2 = &rto_timer_max
},
{
.ctl_name = NET_SCTP_MAX_BURST,
......@@ -115,19 +128,23 @@ static ctl_table sctp_table[] = {
.ctl_name = NET_SCTP_HB_INTERVAL,
.procname = "hb_interval",
.data = &sctp_hb_interval,
.maxlen = sizeof(int),
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sctp_sysctl_jiffies_ms,
.extra1 = &rto_timer_min,
.extra2 = &rto_timer_max
},
{
.ctl_name = NET_SCTP_PRESERVE_ENABLE,
.procname = "cookie_preserve_enable",
.data = &sctp_cookie_preserve_enable,
.maxlen = sizeof(int),
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.strategy = &sctp_sysctl_jiffies_ms,
.extra1 = &rto_timer_min,
.extra2 = &rto_timer_max
},
{
.ctl_name = NET_SCTP_RTO_ALPHA,
......@@ -181,3 +198,37 @@ void sctp_sysctl_unregister(void)
{
unregister_sysctl_table(sctp_sysctl_header);
}
/* Strategy function to convert jiffies to milliseconds. */
static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen, void **context) {
if (oldval) {
size_t olen;
if (oldlenp) {
if (get_user(olen, oldlenp))
return -EFAULT;
if (olen != sizeof (int))
return -EINVAL;
}
if (put_user((*(int *)(table->data) / HZ) * 1000,
(int *)oldval) ||
(oldlenp && put_user(sizeof (int), oldlenp)))
return -EFAULT;
}
if (newval && newlen) {
int new;
if (newlen != sizeof (int))
return -EINVAL;
if (get_user(new, (int *)newval))
return -EFAULT;
*(int *)(table->data) = (new * HZ) * 1000;
}
return 1;
}
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
......@@ -46,7 +46,6 @@
#include <net/sctp/sm.h>
static void sctp_tsnmap_update(struct sctp_tsnmap *map);
static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map);
static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
__u16 len, __u16 base,
int *started, __u16 *start,
......@@ -92,7 +91,6 @@ struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len,
map->cumulative_tsn_ack_point = initial_tsn - 1;
map->max_tsn_seen = map->cumulative_tsn_ack_point;
map->malloced = 0;
map->pending_data = 0;
map->num_dup_tsns = 0;
return map;
......@@ -135,14 +133,6 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
return dup;
}
/* Is there a gap in the TSN map? */
int sctp_tsnmap_has_gap(const struct sctp_tsnmap *map)
{
int has_gap;
has_gap = (map->cumulative_tsn_ack_point != map->max_tsn_seen);
return has_gap;
}
/* Mark this TSN as seen. */
void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
......@@ -176,21 +166,6 @@ void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
sctp_tsnmap_update(map);
}
void sctp_tsnmap_report_dup(struct sctp_tsnmap *map, __u32 tsn)
{
}
/* Retrieve the Cumulative TSN Ack Point. */
__u32 sctp_tsnmap_get_ctsn(const struct sctp_tsnmap *map)
{
return map->cumulative_tsn_ack_point;
}
/* Retrieve the highest TSN we've seen. */
__u32 sctp_tsnmap_get_max_tsn_seen(const struct sctp_tsnmap *map)
{
return map->max_tsn_seen;
}
/* Dispose of a tsnmap. */
void sctp_tsnmap_free(struct sctp_tsnmap *map)
......@@ -219,6 +194,10 @@ int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
/* We haven't found a gap yet. */
started = ended = 0;
/* If there are no more gap acks possible, get out fast. */
if (TSN_lte(map->max_tsn_seen, iter->start))
return 0;
/* Search the first mapping array. */
if (iter->start - map->base_tsn < map->len) {
......@@ -304,10 +283,11 @@ static void sctp_tsnmap_update(struct sctp_tsnmap *map)
} while (map->tsn_map[ctsn - map->base_tsn]);
map->cumulative_tsn_ack_point = ctsn - 1; /* Back up one. */
sctp_tsnmap_update_pending_data(map);
}
static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map)
/* How many data chunks are we missing from our peer?
*/
__u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
{
__u32 cum_tsn = map->cumulative_tsn_ack_point;
__u32 max_tsn = map->max_tsn_seen;
......@@ -339,7 +319,7 @@ static void sctp_tsnmap_update_pending_data(struct sctp_tsnmap *map)
}
out:
map->pending_data = pending_data;
return pending_data;
}
/* This is a private helper for finding Gap Ack Blocks. It searches a
......@@ -359,6 +339,8 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
* early if we have found the end of the Gap Ack Block.
*/
/* Also, stop looking past the maximum TSN seen. */
/* Look for the start. */
if (!(*started)) {
for (; i < len; i++) {
......@@ -404,3 +386,26 @@ void sctp_tsnmap_renege(struct sctp_tsnmap *map, __u32 tsn)
else
map->overflow_map[gap - map->len] = 0;
}
/* How many gap ack blocks do we have recorded? */
__u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map)
{
struct sctp_tsnmap_iter iter;
int gabs = 0;
/* Refresh the gap ack information. */
if (sctp_tsnmap_has_gap(map)) {
sctp_tsnmap_iter_init(map, &iter);
while (sctp_tsnmap_next_gap_ack(map, &iter,
&map->gabs[gabs].start,
&map->gabs[gabs].end)) {
map->gabs[gabs].start = htons(map->gabs[gabs].start);
map->gabs[gabs].end = htons(map->gabs[gabs].end);
gabs++;
if (gabs >= SCTP_MAX_GABS)
break;
}
}
return gabs;
}
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