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];
......
......@@ -14,7 +14,7 @@
*
* 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.
*
......@@ -31,18 +31,20 @@
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Randall Stewart <randall@sctp.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
* Randall Stewart <randall@sctp.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com>
* Xingang Guo <xingang.guo@intel.com>
* Hui Huang <hui.huang@nokia.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com>
* Xingang Guo <xingang.guo@intel.com>
* Hui Huang <hui.huang@nokia.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Dajiang Zhang <dajiang.zhang@nokia.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Dajiang Zhang <dajiang.zhang@nokia.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
* Anup Pemmaiah <pemmaiah@cc.usu.edu>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -54,12 +56,12 @@
#include <linux/time.h> /* We get struct timespec. */
#include <linux/socket.h> /* linux/in.h needs this!! */
#include <linux/in.h> /* We get struct sockaddr_in. */
#include <linux/in6.h> /* We get struct in6_addr */
#include <linux/in6.h> /* We get struct in6_addr */
#include <asm/param.h> /* We get MAXHOSTNAMELEN. */
#include <asm/atomic.h> /* This gets us atomic counters. */
#include <linux/skbuff.h> /* We need sk_buff_head. */
#include <linux/workqueue.h> /* We need tq_struct. */
#include <linux/sctp.h> /* We need sctp* header structs. */
#include <linux/workqueue.h> /* We need tq_struct. */
#include <linux/sctp.h> /* We need sctp* header structs. */
/* A convenience structure for handling sockaddr structures.
* We should wean ourselves off this.
......@@ -93,11 +95,11 @@ struct sctp_ssnmap;
/* Structures useful for managing bind/connect. */
struct sctp_bind_bucket {
unsigned short port;
unsigned short port;
unsigned short fastreuse;
struct sctp_bind_bucket *next;
struct sctp_bind_bucket **pprev;
struct hlist_head sk_list;
struct hlist_head owner;
};
struct sctp_bind_hashbucket {
......@@ -118,11 +120,11 @@ extern struct sctp_globals {
*
* The following protocol parameters are RECOMMENDED:
*
* RTO.Initial - 3 seconds
* RTO.Min - 1 second
* RTO.Max - 60 seconds
* RTO.Alpha - 1/8 (3 when converted to right shifts.)
* RTO.Beta - 1/4 (2 when converted to right shifts.)
* RTO.Initial - 3 seconds
* RTO.Min - 1 second
* RTO.Max - 60 seconds
* RTO.Alpha - 1/8 (3 when converted to right shifts.)
* RTO.Beta - 1/4 (2 when converted to right shifts.)
*/
__u32 rto_initial;
__u32 rto_min;
......@@ -137,24 +139,24 @@ extern struct sctp_globals {
/* Max.Burst - 4 */
int max_burst;
/* Valid.Cookie.Life - 60 seconds */
/* 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)
* Max.Init.Retransmits - 8 attempts
* Path.Max.Retrans - 5 attempts (per destination address)
* Max.Init.Retransmits - 8 attempts
*/
int max_retrans_association;
int max_retrans_path;
int max_retrans_init;
/* HB.interval - 30 seconds */
/* HB.interval - 30 seconds */
int hb_interval;
/* The following variables are implementation specific. */
/* The following variables are implementation specific. */
/* Default initialization values to be applied to new associations. */
__u16 max_instreams;
......@@ -173,7 +175,7 @@ extern struct sctp_globals {
int assoc_hashsize;
struct sctp_hashbucket *assoc_hashbucket;
/* This is the sctp port control hash. */
/* This is the sctp port control hash. */
int port_hashsize;
int port_rover;
spinlock_t port_alloc_lock; /* Protects port_rover. */
......@@ -183,7 +185,7 @@ extern struct sctp_globals {
* We actively maintain this complete list of interfaces on
* the system by catching routing events.
*
* It is a list of struct sockaddr_storage_list.
* It is a list of sctp_sockaddr_entry.
*/
struct list_head local_addr_list;
spinlock_t local_addr_lock;
......@@ -223,12 +225,12 @@ struct sctp_af {
int (*sctp_xmit) (struct sk_buff *skb,
struct sctp_transport *,
int ipfragok);
int (*setsockopt) (struct sock *sk,
int (*setsockopt) (struct sock *sk,
int level,
int optname,
char *optval,
int optlen);
int (*getsockopt) (struct sock *sk,
int (*getsockopt) (struct sock *sk,
int level,
int optname,
char *optval,
......@@ -236,37 +238,37 @@ struct sctp_af {
struct dst_entry *(*get_dst) (struct sctp_association *asoc,
union sctp_addr *daddr,
union sctp_addr *saddr);
void (*get_saddr) (struct sctp_association *asoc,
void (*get_saddr) (struct sctp_association *asoc,
struct dst_entry *dst,
union sctp_addr *daddr,
union sctp_addr *saddr);
void (*copy_addrlist) (struct list_head *,
union sctp_addr *saddr);
void (*copy_addrlist) (struct list_head *,
struct net_device *);
void (*dst_saddr) (union sctp_addr *saddr,
void (*dst_saddr) (union sctp_addr *saddr,
struct dst_entry *dst,
unsigned short port);
int (*cmp_addr) (const union sctp_addr *addr1,
int (*cmp_addr) (const union sctp_addr *addr1,
const union sctp_addr *addr2);
void (*addr_copy) (union sctp_addr *dst,
void (*addr_copy) (union sctp_addr *dst,
union sctp_addr *src);
void (*from_skb) (union sctp_addr *,
void (*from_skb) (union sctp_addr *,
struct sk_buff *skb,
int saddr);
void (*from_sk) (union sctp_addr *,
void (*from_sk) (union sctp_addr *,
struct sock *sk);
void (*to_sk_saddr) (union sctp_addr *,
void (*to_sk_saddr) (union sctp_addr *,
struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *,
void (*to_sk_daddr) (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 *);
int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *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 *);
int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk);
void (*seq_dump_addr)(struct seq_file *seq,
union sctp_addr *addr);
union sctp_addr *addr);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
......@@ -325,6 +327,7 @@ struct sctp_opt {
struct sctp_rtoinfo rtoinfo;
struct sctp_paddrparams paddrparam;
struct sctp_event_subscribe subscribe;
struct sctp_assocparams assocparams;
int user_frag;
__u32 autoclose;
__u8 nodelay;
......@@ -347,23 +350,23 @@ struct sctp_opt {
*
*/
typedef struct sctp_cookie {
struct sctp_cookie {
/* My : Tag expected in every inbound packet and sent
* Verification: in the INIT or INIT ACK chunk.
* Tag :
*/
__u32 my_vtag;
/* My : Tag expected in every inbound packet and sent
* Verification: in the INIT or INIT ACK chunk.
* Tag :
*/
__u32 my_vtag;
/* Peer's : Tag expected in every outbound packet except
* Verification: in the INIT chunk.
* Tag :
*/
__u32 peer_vtag;
/* Peer's : Tag expected in every outbound packet except
* Verification: in the INIT chunk.
* Tag :
*/
__u32 peer_vtag;
/* The rest of these are not from the spec, but really need to
* be in the cookie.
*/
/* The rest of these are not from the spec, but really need to
* be in the cookie.
*/
/* My Tie Tag : Assist in discovering a restarting association. */
__u32 my_ttag;
......@@ -371,8 +374,8 @@ typedef struct sctp_cookie {
/* Peer's Tie Tag: Assist in discovering a restarting association. */
__u32 peer_ttag;
/* When does this cookie expire? */
struct timeval expiration;
/* When does this cookie expire? */
struct timeval expiration;
/* Number of inbound/outbound streams which are set
* and negotiated during the INIT process.
......@@ -380,7 +383,7 @@ typedef struct sctp_cookie {
__u16 sinit_num_ostreams;
__u16 sinit_max_instreams;
/* This is the first sequence number I used. */
/* This is the first sequence number I used. */
__u32 initial_tsn;
/* This holds the originating address of the INIT packet. */
......@@ -393,38 +396,38 @@ typedef struct sctp_cookie {
* the association TCB is re-constructed from the cookie.
*/
__u32 raw_addr_list_len;
sctp_init_chunk_t peer_init[0];
} sctp_cookie_t;
struct sctp_init_chunk peer_init[0];
};
/* The format of our cookie that we send to our peer. */
typedef struct sctp_signed_cookie {
struct sctp_signed_cookie {
__u8 signature[SCTP_SECRET_SIZE];
sctp_cookie_t c;
} sctp_signed_cookie_t;
struct sctp_cookie c;
};
/* This is another convenience type to allocate memory for address
* params for the maximum size and pass such structures around
* internally.
*/
typedef union {
sctp_ipv4addr_param_t v4;
sctp_ipv6addr_param_t v6;
} sctp_addr_param_t;
union sctp_addr_param {
struct sctp_ipv4addr_param v4;
struct sctp_ipv6addr_param v6;
};
/* A convenience type to allow walking through the various
* parameters and avoid casting all over the place.
*/
union sctp_params {
void *v;
sctp_paramhdr_t *p;
sctp_cookie_preserve_param_t *life;
sctp_hostname_param_t *dns;
sctp_cookie_param_t *cookie;
sctp_supported_addrs_param_t *sat;
sctp_ipv4addr_param_t *v4;
sctp_ipv6addr_param_t *v6;
sctp_addr_param_t *addr;
struct sctp_paramhdr *p;
struct sctp_cookie_preserve_param *life;
struct sctp_hostname_param *dns;
struct sctp_cookie_param *cookie;
struct sctp_supported_addrs_param *sat;
struct sctp_ipv4addr_param *v4;
struct sctp_ipv6addr_param *v6;
union sctp_addr_param *addr;
};
/* RFC 2960. Section 3.3.5 Heartbeat.
......@@ -435,7 +438,7 @@ union sctp_params {
* HEARTBEAT is sent (see Section 8.3).
*/
typedef struct sctp_sender_hb_info {
sctp_paramhdr_t param_hdr;
struct sctp_paramhdr param_hdr;
union sctp_addr daddr;
unsigned long sent_at;
} sctp_sender_hb_info_t __attribute__((packed));
......@@ -476,7 +479,7 @@ static inline __u16 sctp_ssn_peek(struct sctp_stream *stream, __u16 id)
return stream->ssn[id];
}
/* Return the next SSN number for this stream. */
/* Return the next SSN number for this stream. */
static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
{
return stream->ssn[id]++;
......@@ -555,23 +558,22 @@ struct sctp_chunk {
union sctp_params param_hdr;
union {
__u8 *v;
sctp_datahdr_t *data_hdr;
sctp_inithdr_t *init_hdr;
sctp_sackhdr_t *sack_hdr;
sctp_heartbeathdr_t *hb_hdr;
sctp_sender_hb_info_t *hbs_hdr;
sctp_shutdownhdr_t *shutdown_hdr;
sctp_signed_cookie_t *cookie_hdr;
sctp_ecnehdr_t *ecne_hdr;
sctp_cwrhdr_t *ecn_cwr_hdr;
sctp_errhdr_t *err_hdr;
struct sctp_datahdr *data_hdr;
struct sctp_inithdr *init_hdr;
struct sctp_sackhdr *sack_hdr;
struct sctp_heartbeathdr *hb_hdr;
struct sctp_sender_hb_info *hbs_hdr;
struct sctp_shutdownhdr *shutdown_hdr;
struct sctp_signed_cookie *cookie_hdr;
struct sctp_ecnehdr *ecne_hdr;
struct sctp_cwrhdr *ecn_cwr_hdr;
struct sctp_errhdr *err_hdr;
} subh;
__u8 *chunk_end;
sctp_chunkhdr_t *chunk_hdr;
sctp_sctphdr_t *sctp_hdr;
struct sctp_chunkhdr *chunk_hdr;
struct sctphdr *sctp_hdr;
/* This needs to be recoverable for SCTP_SEND_FAILED events. */
struct sctp_sndrcvinfo sinfo;
......@@ -595,7 +597,7 @@ struct sctp_chunk {
/* For an inbound chunk, this tells us where it came from.
* For an outbound chunk, it tells us where we'd like it to
* go. It is NULL if we have no preference.
* go. It is NULL if we have no preference.
*/
struct sctp_transport *transport;
......@@ -632,7 +634,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
* sin_port -- ordinary port number
* sin_addr -- cast to either (struct in_addr) or (struct in6_addr)
*/
struct sockaddr_storage_list {
struct sctp_sockaddr_entry {
struct list_head list;
union sctp_addr a;
};
......@@ -685,22 +687,22 @@ typedef int (sctp_outq_thandler_t)(struct sctp_outq *, void *);
typedef int (sctp_outq_ehandler_t)(struct sctp_outq *);
typedef struct sctp_packet *(sctp_outq_ohandler_init_t)
(struct sctp_packet *,
struct sctp_transport *,
__u16 sport,
__u16 dport);
struct sctp_transport *,
__u16 sport,
__u16 dport);
typedef struct sctp_packet *(sctp_outq_ohandler_config_t)
(struct sctp_packet *,
(struct sctp_packet *,
__u32 vtag,
int ecn_capable,
sctp_packet_phandler_t *get_prepend_chunk);
typedef sctp_xmit_t (sctp_outq_ohandler_t)(struct sctp_packet *,
struct sctp_chunk *);
struct sctp_chunk *);
typedef int (sctp_outq_ohandler_force_t)(struct sctp_packet *);
sctp_outq_ohandler_init_t sctp_packet_init;
sctp_outq_ohandler_config_t sctp_packet_config;
sctp_outq_ohandler_t sctp_packet_append_chunk;
sctp_outq_ohandler_t sctp_packet_transmit_chunk;
sctp_outq_ohandler_t sctp_packet_append_chunk;
sctp_outq_ohandler_t sctp_packet_transmit_chunk;
sctp_outq_ohandler_force_t sctp_packet_transmit;
void sctp_packet_free(struct sctp_packet *);
......@@ -710,19 +712,19 @@ void sctp_packet_free(struct sctp_packet *);
*
* RFC2960 Section 1.4 Key Terms
*
* o Transport address: A Transport Address is traditionally defined
* by Network Layer address, Transport Layer protocol and Transport
* Layer port number. In the case of SCTP running over IP, a
* transport address is defined by the combination of an IP address
* and an SCTP port number (where SCTP is the Transport protocol).
* o Transport address: A Transport Address is traditionally defined
* by Network Layer address, Transport Layer protocol and Transport
* Layer port number. In the case of SCTP running over IP, a
* transport address is defined by the combination of an IP address
* and an SCTP port number (where SCTP is the Transport protocol).
*
* RFC2960 Section 7.1 SCTP Differences from TCP Congestion control
*
* o The sender keeps a separate congestion control parameter set for
* each of the destination addresses it can send to (not each
* source-destination pair but for each destination). The parameters
* should decay if the address is not used for a long enough time
* period.
* o The sender keeps a separate congestion control parameter set for
* each of the destination addresses it can send to (not each
* source-destination pair but for each destination). The parameters
* should decay if the address is not used for a long enough time
* period.
*
*/
struct sctp_transport {
......@@ -731,12 +733,12 @@ struct sctp_transport {
/* Reference counting. */
atomic_t refcnt;
int dead;
int dead;
/* This is the peer's IP address and port. */
union sctp_addr ipaddr;
/* These are the functions we call to handle LLP stuff. */
/* These are the functions we call to handle LLP stuff. */
struct sctp_af *af_specific;
/* Which association do we belong to? */
......@@ -750,33 +752,33 @@ struct sctp_transport {
* address list derived from the INIT or INIT ACK chunk, a
* number of data elements needs to be maintained including:
*/
__u32 rtt; /* This is the most recent RTT. */
__u32 rtt; /* This is the most recent RTT. */
/* RTO : The current retransmission timeout value. */
/* RTO : The current retransmission timeout value. */
__u32 rto;
/* RTTVAR : The current RTT variation. */
__u32 rttvar;
/* SRTT : The current smoothed round trip time. */
/* SRTT : The current smoothed round trip time. */
__u32 srtt;
/* RTO-Pending : A flag used to track if one of the DATA
* chunks sent to this address is currently being
* used to compute a RTT. If this flag is 0,
* the next DATA chunk sent to this destination
* should be used to compute a RTT and this flag
* should be set. Every time the RTT
* calculation completes (i.e. the DATA chunk
* is SACK'd) clear this flag.
*/
* chunks sent to this address is currently being
* used to compute a RTT. If this flag is 0,
* the next DATA chunk sent to this destination
* should be used to compute a RTT and this flag
* should be set. Every time the RTT
* calculation completes (i.e. the DATA chunk
* is SACK'd) clear this flag.
*/
int rto_pending;
/*
* These are the congestion stats.
*/
/* cwnd : The current congestion window. */
__u32 cwnd; /* This is the actual cwnd. */
/* cwnd : The current congestion window. */
__u32 cwnd; /* This is the actual cwnd. */
/* ssthresh : The current slow start threshold value. */
__u32 ssthresh;
......@@ -789,7 +791,7 @@ struct sctp_transport {
/* Data that has been sent, but not acknowledged. */
__u32 flight_size;
/* PMTU : The current known path MTU. */
/* PMTU : The current known path MTU. */
__u32 pmtu;
/* Destination */
......@@ -819,23 +821,23 @@ struct sctp_transport {
unsigned long last_time_ecne_reduced;
/* active : The current active state of this destination,
* : i.e. DOWN, UP, etc.
* : i.e. DOWN, UP, etc.
*/
int active;
/* hb_allowed : The current heartbeat state of this destination,
* : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
* : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
*/
int hb_allowed;
/* These are the error stats for this destination. */
/* Error count : The current error count for this destination. */
/* Error count : The current error count for this destination. */
unsigned short error_count;
/* Error : Current error threshold for this destination
* Threshold : i.e. what value marks the destination down if
* : errorCount reaches this value.
* : errorCount reaches this value.
*/
unsigned short error_threshold;
......@@ -845,7 +847,7 @@ struct sctp_transport {
*/
int max_retrans;
/* Per : A timer used by each destination.
/* Per : A timer used by each destination.
* Destination :
* Timer :
*
......@@ -874,10 +876,10 @@ struct sctp_transport {
/* State information saved for SFR_CACC algorithm. The key
* idea in SFR_CACC is to maintain state at the sender on a
* per-destination basis when a changeover happens.
* char changeover_active;
* char cycling_changeover;
* __u32 next_tsn_at_change;
* char cacc_saw_newack;
* char changeover_active;
* char cycling_changeover;
* __u32 next_tsn_at_change;
* char cacc_saw_newack;
*/
struct {
/* An unsigned integer, which stores the next TSN to be
......@@ -938,7 +940,7 @@ struct sctp_inq {
*/
struct work_struct immediate;
int malloced; /* Is this structure kfree()able? */
int malloced; /* Is this structure kfree()able? */
};
struct sctp_inq *sctp_inq_new(void);
......@@ -955,7 +957,7 @@ void sctp_inq_set_th_handler(struct sctp_inq *, void (*)(void *), void *);
* This structure covers sections 6.3, 6.4, 6.7, 6.8, 6.10, 7., 8.1,
* and 8.2 of the v13 draft.
*
* It handles retransmissions. The connection to the timeout portion
* It handles retransmissions. The connection to the timeout portion
* of the state machine is through sctp_..._timeout() and timeout_handler.
*
* If you feed it SACKs, it will eat them.
......@@ -1001,7 +1003,7 @@ struct sctp_outq {
sctp_outq_ohandler_t *build_output;
sctp_outq_ohandler_force_t *force_output;
/* How many unackd bytes do we have in-flight? */
/* How many unackd bytes do we have in-flight? */
__u32 outstanding_bytes;
/* Corked? */
......@@ -1020,7 +1022,7 @@ void sctp_outq_teardown(struct sctp_outq *);
void sctp_outq_free(struct sctp_outq*);
int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
int sctp_outq_flush(struct sctp_outq *, int);
int sctp_outq_sack(struct sctp_outq *, sctp_sackhdr_t *);
int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
int sctp_outq_is_empty(const struct sctp_outq *);
int sctp_outq_set_output_handlers(struct sctp_outq *,
sctp_outq_ohandler_init_t init,
......@@ -1045,8 +1047,8 @@ struct sctp_bind_addr {
/* RFC 2960 12.1 Parameters necessary for the SCTP instance
*
* SCTP Port: The local SCTP port number the endpoint is
* bound to.
* SCTP Port: The local SCTP port number the endpoint is
* bound to.
*/
__u16 port;
......@@ -1058,7 +1060,7 @@ struct sctp_bind_addr {
*/
struct list_head address_list;
int malloced; /* Are we kfree()able? */
int malloced; /* Are we kfree()able? */
};
struct sctp_bind_addr *sctp_bind_addr_new(int gfp_mask);
......@@ -1095,13 +1097,13 @@ typedef enum {
* local endpoint.
* This common structure is useful for several purposes:
* 1) Common interface for lookup routines.
* a) Subfunctions work for either endpoint or association
* b) Single interface to lookup allows hiding the lookup lock rather
* than acquiring it externally.
* a) Subfunctions work for either endpoint or association
* b) Single interface to lookup allows hiding the lookup lock rather
* than acquiring it externally.
* 2) Common interface for the inbound chunk handling/state machine.
* 3) Common object handling routines for reference counting, etc.
* 4) Disentangle association lookup from endpoint lookup, where we
* do not have to find our endpoint to find our association.
* do not have to find our endpoint to find our association.
*
*/
......@@ -1120,14 +1122,14 @@ struct sctp_ep_common {
* malloced - Do we need to kfree this object?
*/
atomic_t refcnt;
char dead;
char malloced;
char dead;
char malloced;
/* What socket does this endpoint belong to? */
struct sock *sk;
/* This is where we receive inbound chunks. */
struct sctp_inq inqueue;
struct sctp_inq inqueue;
/* This substructure includes the defining parameters of the
* endpoint:
......@@ -1165,22 +1167,22 @@ struct sctp_endpoint {
struct sctp_ep_common base;
/* Associations: A list of current associations and mappings
* to the data consumers for each association. This
* may be in the form of a hash table or other
* implementation dependent structure. The data
* consumers may be process identification
* information such as file descriptors, named pipe
* pointer, or table pointers dependent on how SCTP
* is implemented.
* to the data consumers for each association. This
* may be in the form of a hash table or other
* implementation dependent structure. The data
* consumers may be process identification
* information such as file descriptors, named pipe
* pointer, or table pointers dependent on how SCTP
* is implemented.
*/
/* This is really a list of struct sctp_association entries. */
struct list_head asocs;
/* Secret Key: A secret key used by this endpoint to compute
* the MAC. This SHOULD be a cryptographic quality
* random number with a sufficient length.
* the MAC. This SHOULD be a cryptographic quality
* random number with a sufficient length.
* Discussion in [RFC1750] can be helpful in
* selection of the key.
* selection of the key.
*/
__u8 secret_key[SCTP_HOW_MANY_SECRETS][SCTP_SECRET_SIZE];
int current_key;
......@@ -1190,7 +1192,7 @@ struct sctp_endpoint {
/* Default timeouts. */
int timeouts[SCTP_NUM_TIMEOUT_TYPES];
/* Various thresholds. */
/* Various thresholds. */
/* Name for debugging output... */
char *debug_name;
......@@ -1267,11 +1269,11 @@ struct sctp_association {
*/
__u32 eyecatcher;
/* This is our parent endpoint. */
/* This is our parent endpoint. */
struct sctp_endpoint *ep;
/* These are those association elements needed in the cookie. */
sctp_cookie_t c;
struct sctp_cookie c;
/* This is all information about our peer. */
struct {
......@@ -1283,11 +1285,11 @@ struct sctp_association {
/* transport_addr_list
*
* Peer : A list of SCTP transport addresses that the
* Peer : A list of SCTP transport addresses that the
* Transport : peer is bound to. This information is derived
* Address : from the INIT or INIT ACK and is used to
* List : associate an inbound packet with a given
* : association. Normally this information is
* List : associate an inbound packet with a given
* : association. Normally this information is
* : hashed or keyed for quick lookup and access
* : of the TCB.
*
......@@ -1303,8 +1305,8 @@ struct sctp_association {
/* primary_path
*
* Primary : This is the current primary destination
* Path : transport address of the peer endpoint. It
* : may also specify a source transport address
* Path : transport address of the peer endpoint. It
* : may also specify a source transport address
* : on this endpoint.
*
* All of these paths live on transport_addr_list.
......@@ -1343,25 +1345,25 @@ struct sctp_association {
/* Pointer to last transport I have sent on. */
struct sctp_transport *last_sent_to;
/* This is the last transport I have received DATA on. */
/* This is the last transport I have received DATA on. */
struct sctp_transport *last_data_from;
/*
* Mapping An array of bits or bytes indicating which out of
* Array order TSN's have been received (relative to the
* Last Rcvd TSN). If no gaps exist, i.e. no out of
* order packets have been received, this array
* will be set to all zero. This structure may be
* in the form of a circular buffer or bit array.
* Last Rcvd TSN). If no gaps exist, i.e. no out of
* order packets have been received, this array
* will be set to all zero. This structure may be
* in the form of a circular buffer or bit array.
*
* Last Rcvd : This is the last TSN received in
* TSN : sequence. This value is set initially by
* : taking the peer's Initial TSN, received in
* : the INIT or INIT ACK chunk, and subtracting
* : one from it.
* : taking the peer's Initial TSN, received in
* : the INIT or INIT ACK chunk, and subtracting
* : one from it.
*
* Throughout most of the specification this is called the
* "Cumulative TSN ACK Point". In this case, we
* "Cumulative TSN ACK Point". In this case, we
* ignore the advice in 12.2 in favour of the term
* used in the bulk of the text. This value is hidden
* in tsn_map--we get it by calling sctp_tsnmap_get_ctsn().
......@@ -1370,13 +1372,13 @@ struct sctp_association {
__u8 _map[sctp_tsnmap_storage_size(SCTP_TSN_MAP_SIZE)];
/* Do we need to sack the peer? */
__u8 sack_needed;
__u8 sack_needed;
/* These are capabilities which our peer advertised. */
__u8 ecn_capable; /* Can peer do ECN? */
__u8 ipv4_address; /* Peer understands IPv4 addresses? */
__u8 ipv6_address; /* Peer understands IPv6 addresses? */
__u8 ecn_capable; /* Can peer do ECN? */
__u8 ipv4_address; /* Peer understands IPv4 addresses? */
__u8 ipv6_address; /* Peer understands IPv6 addresses? */
__u8 hostname_address;/* Peer understands DNS addresses? */
sctp_inithdr_t i;
struct sctp_inithdr i;
int cookie_len;
void *cookie;
......@@ -1387,22 +1389,19 @@ struct sctp_association {
/* State : A state variable indicating what state the
* : association is in, i.e. COOKIE-WAIT,
* : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING,
* : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT.
* : COOKIE-ECHOED, ESTABLISHED, SHUTDOWN-PENDING,
* : SHUTDOWN-SENT, SHUTDOWN-RECEIVED, SHUTDOWN-ACK-SENT.
*
* Note: No "CLOSED" state is illustrated since if a
* association is "CLOSED" its TCB SHOULD be removed.
* Note: No "CLOSED" state is illustrated since if a
* association is "CLOSED" its TCB SHOULD be removed.
*
* In this implementation we DO have a CLOSED
* In this implementation we DO have a CLOSED
* state which is used during initiation and shutdown.
*
* State takes values from SCTP_STATE_*.
* State takes values from SCTP_STATE_*.
*/
sctp_state_t state;
/* When did we enter this state? */
int state_timestamp;
/* The cookie life I award for any cookie. */
struct timeval cookie_life;
......@@ -1411,12 +1410,6 @@ struct sctp_association {
*/
int overall_error_count;
/* Overall : The threshold for this association that if
* Error : the Overall Error Count reaches will cause
* Threshold : this association to be torn down.
*/
int overall_error_threshold;
/* These are the association's initial, max, and min RTO values.
* These values will be initialized by system defaults, but can
* be modified via the SCTP_RTOINFO socket option.
......@@ -1450,19 +1443,19 @@ struct sctp_association {
struct sctp_transport *shutdown_last_sent_to;
/* Next TSN : The next TSN number to be assigned to a new
* : DATA chunk. This is sent in the INIT or INIT
* : ACK chunk to the peer and incremented each
* : time a DATA chunk is assigned a TSN
* : (normally just prior to transmit or during
* : DATA chunk. This is sent in the INIT or INIT
* : ACK chunk to the peer and incremented each
* : time a DATA chunk is assigned a TSN
* : (normally just prior to transmit or during
* : fragmentation).
*/
__u32 next_tsn;
/*
* Last Rcvd : This is the last TSN received in sequence. This value
* TSN : is set initially by taking the peer's Initial TSN,
* : received in the INIT or INIT ACK chunk, and
* : subtracting one from it.
* TSN : is set initially by taking the peer's Initial TSN,
* : received in the INIT or INIT ACK chunk, and
* : subtracting one from it.
*
* Most of RFC 2960 refers to this as the Cumulative TSN Ack Point.
*/
......@@ -1502,7 +1495,7 @@ struct sctp_association {
wait_queue_head_t wait;
/* Association : The smallest PMTU discovered for all of the
* PMTU : peer's transport addresses.
* PMTU : peer's transport addresses.
*/
__u32 pmtu;
......@@ -1510,14 +1503,14 @@ struct sctp_association {
__u32 frag_point;
/* Ack State : This flag indicates if the next received
* : packet is to be responded to with a
* : SACK. This is initializedto 0. When a packet
* : is received it is incremented. If this value
* : reaches 2 or more, a SACK is sent and the
* : value is reset to 0. Note: This is used only
* : when no DATA chunks are received out of
* : order. When DATA chunks are out of order,
* : SACK's are not delayed (see Section 6).
* : packet is to be responded to with a
* : SACK. This is initializedto 0. When a packet
* : is received it is incremented. If this value
* : reaches 2 or more, a SACK is sent and the
* : value is reset to 0. Note: This is used only
* : when no DATA chunks are received out of
* : order. When DATA chunks are out of order,
* : SACK's are not delayed (see Section 6).
*/
/* Do we need to send an ack?
* When counters[SctpCounterAckState] is above 1 we do!
......@@ -1531,7 +1524,7 @@ struct sctp_association {
__u32 default_context;
__u32 default_timetolive;
/* This tracks outbound ssn for a given stream. */
/* This tracks outbound ssn for a given stream. */
struct sctp_ssnmap *ssnmap;
/* All outbound chunks go through this structure. */
......@@ -1545,7 +1538,7 @@ struct sctp_association {
/* Last TSN that caused an ECNE Chunk to be sent. */
__u32 last_ecne_tsn;
/* Last TSN that caused a CWR Chunk to be sent. */
/* Last TSN that caused a CWR Chunk to be sent. */
__u32 last_cwr_tsn;
/* How many duplicated TSNs have we seen? */
......@@ -1605,7 +1598,7 @@ struct sctp_association {
*
* In defining the ASCONF Chunk transfer procedures, it is
* essential that these transfers MUST NOT cause congestion
* within the network. To achieve this, we place these
* within the network. To achieve this, we place these
* restrictions on the transfer of ASCONF Chunks:
*
* R1) One and only one ASCONF Chunk MAY be in transit and
......@@ -1619,8 +1612,8 @@ struct sctp_association {
*
*
* [I really think this is EXACTLY the sort of intelligence
* which already resides in sctp_outq. Please move this
* queue and its supporting logic down there. --piggy]
* which already resides in sctp_outq. Please move this
* queue and its supporting logic down there. --piggy]
*/
struct sk_buff_head addip_chunks;
......@@ -1673,7 +1666,7 @@ static inline struct sctp_association *sctp_assoc(struct sctp_ep_common *base)
return asoc;
}
/* These are function signatures for manipulating associations. */
/* These are function signatures for manipulating associations. */
struct sctp_association *
......@@ -1710,16 +1703,16 @@ __u32 sctp_association_get_next_tsn(struct sctp_association *);
__u32 sctp_association_get_tsn_block(struct sctp_association *, int);
void sctp_assoc_sync_pmtu(struct sctp_association *);
void sctp_assoc_rwnd_increase(struct sctp_association *, int);
void sctp_assoc_rwnd_decrease(struct sctp_association *, int);
void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned);
void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned);
void sctp_assoc_set_primary(struct sctp_association *,
struct sctp_transport *);
int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, int);
int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
sctp_cookie_t *, int gfp);
struct sctp_cookie*, int gfp);
int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2);
const union sctp_addr *ss2);
struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc);
......
/* 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;
......
......@@ -48,6 +48,8 @@
* Sridhar Samudrala <samudrala@us.ibm.com>
* Inaky Perez-Gonzalez <inaky.gonzalez@intel.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Ryan Layer <rmlayer@us.ibm.com>
* Anup Pemmaiah <pemmaiah@cc.usu.edu>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -100,6 +102,7 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
extern kmem_cache_t *sctp_bucket_cachep;
extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc);
/* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored.
......@@ -110,32 +113,24 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
/* If this is not a UDP-style socket, assoc id should be ignored. */
if (!sctp_style(sk, UDP)) {
/* Return NULL if the socket state is not ESTABLISHED. It
/* Return NULL if the socket state is not ESTABLISHED. It
* could be a TCP-style listening socket or a socket which
* hasn't yet called connect() to establish an association.
*/
if (!sctp_sstate(sk, ESTABLISHED))
return NULL;
/* Get the first and the only association from the list. */
/* Get the first and the only association from the list. */
if (!list_empty(&sctp_sk(sk)->ep->asocs))
asoc = list_entry(sctp_sk(sk)->ep->asocs.next,
struct sctp_association, asocs);
return asoc;
}
/* First, verify that this is a kernel address. */
if (sctp_is_valid_kaddr((unsigned long) id)) {
struct sctp_association *temp;
/* Verify that this _is_ an sctp_association
* data structure and if so, that the socket matches.
*/
temp = (struct sctp_association *)id;
if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) &&
(temp->base.sk == sk))
asoc = temp;
}
/* Otherwise this is a UDP-style socket. */
asoc = (struct sctp_association *)id;
if (!sctp_assoc_valid(sk, asoc))
return NULL;
return asoc;
}
......@@ -1456,7 +1451,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
* spp_pathmaxrxt - This contains the maximum number of
* retransmissions before this address shall be
* considered unreachable.
*/
*/
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
char *optval, int optlen)
{
......@@ -1624,6 +1619,110 @@ static int sctp_setsockopt_nodelay(struct sock *sk, char *optval,
return 0;
}
/*
*
* 7.1.1 SCTP_RTOINFO
*
* The protocol parameters used to initialize and bound retransmission
* timeout (RTO) are tunable. sctp_rtoinfo structure is used to access
* and modify these parameters.
* All parameters are time values, in milliseconds. A value of 0, when
* modifying the parameters, indicates that the current value should not
* be changed.
*
*/
static int sctp_setsockopt_rtoinfo(struct sock *sk, char *optval, int optlen) {
struct sctp_rtoinfo rtoinfo;
struct sctp_association *asoc;
if (optlen != sizeof (struct sctp_rtoinfo))
return -EINVAL;
if (copy_from_user(&rtoinfo, optval, optlen))
return -EFAULT;
asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
/* Set the values to the specific association */
if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
if (asoc) {
if (rtoinfo.srto_initial != 0)
asoc->rto_initial = rtoinfo.srto_initial * HZ / 1000;
if (rtoinfo.srto_max != 0)
asoc->rto_max = rtoinfo.srto_max * HZ / 1000;
if (rtoinfo.srto_min != 0)
asoc->rto_min = rtoinfo.srto_min * HZ / 1000;
} else {
/* If there is no association or the association-id = 0
* set the values to the endpoint.
*/
struct sctp_opt *sp = sctp_sk(sk);
if (rtoinfo.srto_initial != 0)
sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
if (rtoinfo.srto_max != 0)
sp->rtoinfo.srto_max = rtoinfo.srto_max;
if (rtoinfo.srto_min != 0)
sp->rtoinfo.srto_min = rtoinfo.srto_min;
}
return 0;
}
/*
*
* 7.1.2 SCTP_ASSOCINFO
*
* This option is used to tune the the maximum retransmission attempts
* of the association.
* Returns an error if the new association retransmission value is
* greater than the sum of the retransmission value of the peer.
* See [SCTP] for more information.
*
*/
static int sctp_setsockopt_assocrtx(struct sock *sk, char *optval,
int optlen) {
struct sctp_assocparams assocparams;
struct sctp_association *asoc;
if (optlen != sizeof(struct sctp_assocparams))
return -EINVAL;
if (copy_from_user(&assocparams, optval, optlen))
return -EFAULT;
asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
/* Set the values to the specific association */
if (asoc) {
if (assocparams.sasoc_asocmaxrxt != 0)
asoc->max_retrans = assocparams.sasoc_asocmaxrxt;
if (assocparams.sasoc_cookie_life != 0) {
asoc->cookie_life.tv_sec =
assocparams.sasoc_cookie_life / 1000;
asoc->cookie_life.tv_usec =
(assocparams.sasoc_cookie_life % 1000)
* 1000;
}
} else {
/* Set the values to the endpoint */
struct sctp_opt *sp = sctp_sk(sk);
if (assocparams.sasoc_asocmaxrxt != 0)
sp->assocparams.sasoc_asocmaxrxt =
assocparams.sasoc_asocmaxrxt;
if (assocparams.sasoc_cookie_life != 0)
sp->assocparams.sasoc_cookie_life =
assocparams.sasoc_cookie_life;
}
return 0;
}
/*
* 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR)
*
......@@ -1771,6 +1870,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_NODELAY:
retval = sctp_setsockopt_nodelay(sk, optval, optlen);
break;
case SCTP_RTOINFO:
retval = sctp_setsockopt_rtoinfo(sk, optval, optlen);
break;
case SCTP_ASSOCRTXINFO:
retval = sctp_setsockopt_assocrtx(sk, optval, optlen);
break;
case SCTP_I_WANT_MAPPED_V4_ADDR:
retval = sctp_setsockopt_mappedv4(sk, optval, optlen);
break;
......@@ -2027,15 +2132,25 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp->initmsg.sinit_num_ostreams = sctp_max_outstreams;
sp->initmsg.sinit_max_instreams = sctp_max_instreams;
sp->initmsg.sinit_max_attempts = sctp_max_retrans_init;
sp->initmsg.sinit_max_init_timeo = sctp_rto_max / HZ;
sp->initmsg.sinit_max_init_timeo = (sctp_rto_max / HZ) * 1000;
/* Initialize default RTO related parameters. These parameters can
* be modified for with the SCTP_RTOINFO socket option.
* FIXME: These are not used yet.
*/
sp->rtoinfo.srto_initial = sctp_rto_initial;
sp->rtoinfo.srto_max = sctp_rto_max;
sp->rtoinfo.srto_min = sctp_rto_min;
sp->rtoinfo.srto_initial = (sctp_rto_initial / HZ) * 1000;
sp->rtoinfo.srto_max = (sctp_rto_max / HZ) * 1000;
sp->rtoinfo.srto_min = (sctp_rto_min / HZ) * 1000;
/* Initialize default association related parameters. These parameters
* can be modified with the SCTP_ASSOCINFO socket option.
*/
sp->assocparams.sasoc_asocmaxrxt = sctp_max_retrans_association;
sp->assocparams.sasoc_number_peer_destinations = 0;
sp->assocparams.sasoc_peer_rwnd = 0;
sp->assocparams.sasoc_local_rwnd = 0;
sp->assocparams.sasoc_cookie_life = (sctp_valid_cookie_life / HZ)
* 1000;
/* Initialize default event subscriptions.
* the struct sock is initialized to zero, so only
......@@ -2050,7 +2165,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Default Peer Address Parameters. These defaults can
* be modified via SCTP_SET_PEER_ADDR_PARAMS
*/
sp->paddrparam.spp_hbinterval = sctp_hb_interval / HZ;
sp->paddrparam.spp_hbinterval = (sctp_hb_interval / HZ) * 1000;
sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
/* If enabled no SCTP message fragmentation will be performed.
......@@ -2182,7 +2297,8 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
status.sstat_state = asoc->state;
status.sstat_rwnd = asoc->peer.rwnd;
status.sstat_unackdata = asoc->unack_data;
status.sstat_penddata = asoc->peer.tsn_map.pending_data;
status.sstat_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map);
status.sstat_instrms = asoc->c.sinit_max_instreams;
status.sstat_outstrms = asoc->c.sinit_num_ostreams;
/* Just in time frag_point update. */
......@@ -2196,7 +2312,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
status.sstat_primary.spinfo_state = transport->active;
status.sstat_primary.spinfo_cwnd = transport->cwnd;
status.sstat_primary.spinfo_srtt = transport->srtt;
status.sstat_primary.spinfo_rto = transport->rto;
status.sstat_primary.spinfo_rto = (transport->rto / HZ) * 1000;
status.sstat_primary.spinfo_mtu = transport->pmtu;
if (put_user(len, optlen)) {
......@@ -2251,7 +2367,7 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
pinfo.spinfo_state = transport->active;
pinfo.spinfo_cwnd = transport->cwnd;
pinfo.spinfo_srtt = transport->srtt;
pinfo.spinfo_rto = transport->rto;
pinfo.spinfo_rto = (transport->rto / HZ) * 1000;
pinfo.spinfo_mtu = transport->pmtu;
if (put_user(len, optlen)) {
......@@ -2430,7 +2546,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
* spp_pathmaxrxt - This contains the maximum number of
* retransmissions before this address shall be
* considered unreachable.
*/
*/
static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
char *optval, int *optlen)
{
......@@ -2607,7 +2723,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
struct list_head *pos;
int cnt = 0;
struct sctp_getaddrs getaddrs;
struct sockaddr_storage_list *from;
struct sctp_sockaddr_entry *from;
struct sockaddr_storage *to;
if (len != sizeof(struct sctp_getaddrs))
......@@ -2635,7 +2751,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
to = getaddrs.addrs;
list_for_each(pos, &bp->address_list) {
from = list_entry(pos,
struct sockaddr_storage_list,
struct sctp_sockaddr_entry,
list);
if (copy_to_user(to, &from->a, sizeof(from->a)))
return -EFAULT;
......@@ -2763,6 +2879,127 @@ static int sctp_getsockopt_nodelay(struct sock *sk, int len,
return -EFAULT;
return 0;
}
/*
*
* 7.1.1 SCTP_RTOINFO
*
* The protocol parameters used to initialize and bound retransmission
* timeout (RTO) are tunable. sctp_rtoinfo structure is used to access
* and modify these parameters.
* All parameters are time values, in milliseconds. A value of 0, when
* modifying the parameters, indicates that the current value should not
* be changed.
*
*/
static int sctp_getsockopt_rtoinfo(struct sock *sk, int len, char *optval,
int *optlen) {
struct sctp_rtoinfo rtoinfo;
struct sctp_association *asoc;
if (len != sizeof (struct sctp_rtoinfo))
return -EINVAL;
if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo)))
return -EFAULT;
asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
/* Values corresponding to the specific association. */
if (asoc) {
rtoinfo.srto_initial = (asoc->rto_initial / HZ) * 1000;
rtoinfo.srto_max = (asoc->rto_max / HZ) * 1000;
rtoinfo.srto_min = (asoc->rto_min / HZ) * 1000;
} else {
/* Values corresponding to the endpoint. */
struct sctp_opt *sp = sctp_sk(sk);
rtoinfo.srto_initial = sp->rtoinfo.srto_initial;
rtoinfo.srto_max = sp->rtoinfo.srto_max;
rtoinfo.srto_min = sp->rtoinfo.srto_min;
}
if (put_user(len, optlen))
return -EFAULT;
if (copy_to_user(optval, &rtoinfo, len))
return -EFAULT;
return 0;
}
/*
*
* 7.1.2 SCTP_ASSOCINFO
*
* This option is used to tune the the maximum retransmission attempts
* of the association.
* Returns an error if the new association retransmission value is
* greater than the sum of the retransmission value of the peer.
* See [SCTP] for more information.
*
*/
static int sctp_getsockopt_assocrtx(struct sock *sk, int len, char *optval,
int *optlen) {
struct sctp_assocparams assocparams;
struct sctp_association *asoc;
struct list_head *pos;
int cnt = 0;
if (len != sizeof (struct sctp_assocparams))
return -EINVAL;
if (copy_from_user(&assocparams, optval,
sizeof (struct sctp_assocparams)))
return -EFAULT;
asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
/* Values correspoinding to the specific association */
if (assocparams.sasoc_assoc_id != 0) {
assocparams.sasoc_asocmaxrxt = asoc->max_retrans;
assocparams.sasoc_peer_rwnd = asoc->peer.rwnd;
assocparams.sasoc_local_rwnd = asoc->a_rwnd;
assocparams.sasoc_cookie_life = (asoc->cookie_life.tv_sec
* 1000) +
(asoc->cookie_life.tv_usec
/ 1000);
list_for_each(pos, &asoc->peer.transport_addr_list) {
cnt ++;
}
assocparams.sasoc_number_peer_destinations = cnt;
} else {
/* Values corresponding to the endpoint */
struct sctp_opt *sp = sctp_sk(sk);
assocparams.sasoc_asocmaxrxt = sp->assocparams.sasoc_asocmaxrxt;
assocparams.sasoc_peer_rwnd = sp->assocparams.sasoc_peer_rwnd;
assocparams.sasoc_local_rwnd = sp->assocparams.sasoc_local_rwnd;
assocparams.sasoc_cookie_life =
sp->assocparams.sasoc_cookie_life;
assocparams.sasoc_number_peer_destinations =
sp->assocparams.
sasoc_number_peer_destinations;
}
if (put_user(len, optlen))
return -EFAULT;
if (copy_to_user(optval, &assocparams, len))
return -EFAULT;
return 0;
}
/*
* 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR)
*
......@@ -2896,6 +3133,12 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case SCTP_NODELAY:
retval = sctp_getsockopt_nodelay(sk, len, optval, optlen);
break;
case SCTP_RTOINFO:
retval = sctp_getsockopt_rtoinfo(sk, len, optval, optlen);
break;
case SCTP_ASSOCRTXINFO:
retval = sctp_getsockopt_assocrtx(sk, len, optval, optlen);
break;
case SCTP_I_WANT_MAPPED_V4_ADDR:
retval = sctp_getsockopt_mappedv4(sk, len, optval, optlen);
break;
......@@ -2952,7 +3195,6 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
snum = addr->v4.sin_port;
SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum);
sctp_local_bh_disable();
if (snum == 0) {
......@@ -2999,7 +3241,6 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
* mutex.
*/
snum = rover;
pp = NULL;
} else {
/* We are given an specific port number; we verify
* that it is not being used. If it is used, we will
......@@ -3011,23 +3252,23 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
sctp_spin_lock(&head->lock);
for (pp = head->chain; pp; pp = pp->next) {
if (pp->port == snum)
break;
goto pp_found;
}
}
if (pp && !hlist_empty(&pp->sk_list)) {
pp = NULL;
goto pp_not_found;
pp_found:
if (!hlist_empty(&pp->owner)) {
/* We had a port hash table hit - there is an
* available port (pp != NULL) and it is being
* used by other socket (pp->sk_list not empty); that other
* used by other socket (pp->owner not empty); that other
* socket is going to be sk2.
*/
int reuse = sk->sk_reuse;
struct sock *sk2;
struct hlist_node *node;
SCTP_DEBUG_PRINTK("sctp_get_port() found a "
"possible match\n");
SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n");
if (pp->fastreuse && sk->sk_reuse)
goto success;
......@@ -3041,7 +3282,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
* that this port/socket (sk) combination are already
* in an endpoint.
*/
sk_for_each_bound(sk2, node, &pp->sk_list) {
sk_for_each_bound(sk2, node, &pp->owner) {
struct sctp_endpoint *ep2;
ep2 = sctp_sk(sk2)->ep;
......@@ -3056,10 +3297,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
}
SCTP_DEBUG_PRINTK("sctp_get_port(): Found a match\n");
}
pp_not_found:
/* If there was a hash table miss, create a new port. */
ret = 1;
if (!pp && !(pp = sctp_bucket_create(head, snum)))
goto fail_unlock;
......@@ -3067,7 +3307,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
* if sk->sk_reuse is too (that is, if the caller requested
* SO_REUSEADDR on this socket -sk-).
*/
if (hlist_empty(&pp->sk_list))
if (hlist_empty(&pp->owner))
pp->fastreuse = sk->sk_reuse ? 1 : 0;
else if (pp->fastreuse && !sk->sk_reuse)
pp->fastreuse = 0;
......@@ -3079,7 +3319,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
success:
inet_sk(sk)->num = snum;
if (!sctp_sk(sk)->bind_hash) {
sk_add_bind_node(sk, &pp->sk_list);
sk_add_bind_node(sk, &pp->owner);
sctp_sk(sk)->bind_hash = pp;
}
ret = 0;
......@@ -3089,8 +3329,6 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
fail:
sctp_local_bh_enable();
SCTP_DEBUG_PRINTK("sctp_get_port() ends, ret=%d\n", ret);
addr->v4.sin_port = htons(addr->v4.sin_port);
return ret;
}
......@@ -3316,7 +3554,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
if (pp) {
pp->port = snum;
pp->fastreuse = 0;
INIT_HLIST_HEAD(&pp->sk_list);
INIT_HLIST_HEAD(&pp->owner);
if ((pp->next = head->chain) != NULL)
pp->next->pprev = &pp->next;
head->chain = pp;
......@@ -3328,7 +3566,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
/* Caller must hold hashbucket lock for this tb with local BH disabled */
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
if (hlist_empty(&pp->sk_list)) {
if (hlist_empty(&pp->owner)) {
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
......@@ -3337,8 +3575,8 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
}
}
/* FIXME: Comments! */
static __inline__ void __sctp_put_port(struct sock *sk)
/* Release this socket's reference to a local port. */
static inline void __sctp_put_port(struct sock *sk)
{
struct sctp_bind_hashbucket *head =
&sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
......@@ -3942,6 +4180,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
{
struct sctp_opt *oldsp = sctp_sk(oldsk);
struct sctp_opt *newsp = sctp_sk(newsk);
struct sctp_bind_bucket *pp; /* hash list port iterator */
struct sctp_endpoint *newep = newsp->ep;
struct sk_buff *skb, *tmp;
struct sctp_ulpevent *event;
......@@ -3951,7 +4190,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
*/
newsk->sk_sndbuf = oldsk->sk_sndbuf;
newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
*newsp = *oldsp;
/* Brute force copy old sctp opt. */
memcpy(newsp, oldsp, sizeof(struct sctp_opt));
/* Restore the ep value that was overwritten with the above structure
* copy.
......@@ -3959,6 +4199,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsp->ep = newep;
newsp->hmac = NULL;
/* Hook this new socket in to the bind_hash list. */
pp = sctp_sk(oldsk)->bind_hash;
sk_add_bind_node(newsk, &pp->owner);
sctp_sk(newsk)->bind_hash = pp;
inet_sk(newsk)->num = inet_sk(oldsk)->num;
/* Move any messages in the old socket's receive queue that are for the
* peeled off association to the new socket's receive queue.
*/
......
/* 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