Commit 6a074a55 authored by Sridhar Samudrala's avatar Sridhar Samudrala

Merge us.ibm.com:/home/sridhar/BK/linux-2.5.68

into us.ibm.com:/home/sridhar/BK/lksctp-2.5.68
parents b2520649 e21eb45a
......@@ -182,7 +182,7 @@ typedef struct {
/* Create a new sctp_command_sequence.
* Return NULL if creating a new sequence fails.
*/
sctp_cmd_seq_t *sctp_new_cmd_seq(int priority);
sctp_cmd_seq_t *sctp_new_cmd_seq(int gfp);
/* Initialize a block of memory as a command sequence.
* Return 0 if the initialization fails.
......
......@@ -6,46 +6,42 @@
*
* This file is part of the SCTP kernel reference Implementation
*
* This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation.
*
* The SCTP reference implementation is free software;
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* 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
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* 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 one of the following email
* addresses:
* 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
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@motorola.com>
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@motorola.com>
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@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.
*
* There are still LOTS of bugs in this code... I always run on the motto
* "it is a wonder any code ever works :)"
*
*
*/
#ifndef __sctp_constants_h__
......@@ -220,7 +216,7 @@ typedef enum {
* - A socket in SCTP_SS_LISTENING state indicates that it is willing to
* accept new associations, but cannot initiate the creation of new ones.
* - A socket in SCTP_SS_ESTABLISHED state indicates that it has a single
* association in ESTABLISHED state.
* association.
*/
typedef enum {
SCTP_SS_CLOSED = TCP_CLOSE,
......@@ -336,10 +332,18 @@ typedef enum {
#define SCTP_SIGNATURE_SIZE 20 /* size of a SLA-1 signature */
#define SCTP_COOKIE_MULTIPLE 64 /* Pad out our cookie to make our hash
#define SCTP_COOKIE_MULTIPLE 32 /* Pad out our cookie to make our hash
* functions simpler to write.
*/
#if defined (CONFIG_SCTP_HMAC_MD5)
#define SCTP_COOKIE_HMAC_ALG "md5"
#elif defined (CONFIG_SCTP_HMAC_SHA1)
#define SCTP_COOKIE_HMAC_ALG "sha1"
#else
#define SCTP_COOKIE_HMAC_ALG NULL
#endif
/* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue.
*/
......
......@@ -125,7 +125,7 @@ extern struct sctp_protocol sctp_proto;
extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(struct sctp_protocol *,
struct sctp_bind_addr *,
sctp_scope_t, int priority, int flags);
sctp_scope_t, int gfp, int flags);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
......@@ -141,11 +141,11 @@ extern unsigned int sctp_poll(struct file *file, struct socket *sock,
/*
* sctp/primitive.c
*/
extern int sctp_primitive_ASSOCIATE(sctp_association_t *, void *arg);
extern int sctp_primitive_SHUTDOWN(sctp_association_t *, void *arg);
extern int sctp_primitive_ABORT(sctp_association_t *, void *arg);
extern int sctp_primitive_SEND(sctp_association_t *, void *arg);
extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg);
extern int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg);
extern int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
extern int sctp_primitive_ABORT(struct sctp_association *, void *arg);
extern int sctp_primitive_SEND(struct sctp_association *, void *arg);
extern int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg);
/*
* sctp/crc32c.c
......@@ -153,37 +153,33 @@ extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg);
extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count);
extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
extern __u32 sctp_end_cksum(__u32 cksum);
extern __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
/*
* sctp/input.c
*/
extern int sctp_rcv(struct sk_buff *skb);
extern void sctp_v4_err(struct sk_buff *skb, u32 info);
extern void sctp_hash_established(sctp_association_t *);
extern void __sctp_hash_established(sctp_association_t *);
extern void sctp_unhash_established(sctp_association_t *);
extern void __sctp_unhash_established(sctp_association_t *);
extern void sctp_hash_endpoint(sctp_endpoint_t *);
extern void __sctp_hash_endpoint(sctp_endpoint_t *);
extern void sctp_unhash_endpoint(sctp_endpoint_t *);
extern void __sctp_unhash_endpoint(sctp_endpoint_t *);
extern sctp_association_t *__sctp_lookup_association(const union sctp_addr *,
const union sctp_addr *,
struct sctp_transport **);
extern void sctp_hash_established(struct sctp_association *);
extern void __sctp_hash_established(struct sctp_association *);
extern void sctp_unhash_established(struct sctp_association *);
extern void __sctp_unhash_established(struct sctp_association *);
extern void sctp_hash_endpoint(struct sctp_endpoint *);
extern void __sctp_hash_endpoint(struct sctp_endpoint *);
extern void sctp_unhash_endpoint(struct sctp_endpoint *);
extern void __sctp_unhash_endpoint(struct sctp_endpoint *);
extern struct sctp_association *__sctp_lookup_association(
const union sctp_addr *,
const union sctp_addr *,
struct sctp_transport **);
extern struct sock *sctp_err_lookup(int family, struct sk_buff *,
struct sctphdr *, struct sctp_endpoint **,
struct sctp_association **,
struct sctphdr *, struct sctp_endpoint **,
struct sctp_association **,
struct sctp_transport **);
extern void sctp_err_finish(struct sock *, struct sctp_endpoint *,
extern void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct sctp_association *);
extern void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu);
/*
* sctp/hashdriver.c
*/
extern void sctp_hash_digest(const char *secret, const int secret_len,
const char *text, const int text_len,
__u8 *digest);
/*
* Section: Macros, externs, and inlines
......@@ -334,15 +330,27 @@ static inline void sctp_v6_exit(void) { return; }
#endif /* #if defined(CONFIG_IPV6) */
/* Some wrappers, in case crypto not available. */
#if defined (CONFIG_CRYPTO_HMAC)
#define sctp_crypto_alloc_tfm crypto_alloc_tfm
#define sctp_crypto_free_tfm crypto_free_tfm
#define sctp_crypto_hmac crypto_hmac
#else
#define sctp_crypto_alloc_tfm(x...) NULL
#define sctp_crypto_free_tfm(x...)
#define sctp_crypto_hmac(x...)
#endif
/* Map an association to an assoc_id. */
static inline sctp_assoc_t sctp_assoc2id(const sctp_association_t *asoc)
static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
{
return (sctp_assoc_t) asoc;
}
/* Look up the association by its id. */
sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
/* A macro to walk a list of skbs. */
......@@ -501,10 +509,10 @@ static inline int ipver2af(__u8 ipver)
/* Perform some sanity checks. */
static inline int sctp_sanity_check(void)
{
SCTP_ASSERT(sizeof(struct sctp_ulpevent) <=
SCTP_ASSERT(sizeof(struct sctp_ulpevent) <=
sizeof(((struct sk_buff *)0)->cb),
"SCTP: ulpevent does not fit in skb!\n", return 0);
return 1;
}
......
......@@ -81,8 +81,8 @@ typedef struct {
int action;
} sctp_sm_command_t;
typedef sctp_disposition_t (sctp_state_fn_t) (const sctp_endpoint_t *,
const sctp_association_t *,
typedef sctp_disposition_t (sctp_state_fn_t) (const struct sctp_endpoint *,
const struct sctp_association *,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *);
......@@ -209,67 +209,67 @@ __u32 sctp_generate_verification_tag(void);
void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
/* Prototypes for chunk-building functions. */
sctp_chunk_t *sctp_make_init(const sctp_association_t *,
sctp_chunk_t *sctp_make_init(const struct sctp_association *,
const sctp_bind_addr_t *,
int priority, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *,
int gfp, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *,
const sctp_chunk_t *,
const int priority,
const int gfp,
const int unkparam_len);
sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *,
sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *,
const sctp_chunk_t *);
sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *,
sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *,
const sctp_chunk_t *);
sctp_chunk_t *sctp_make_cwr(const sctp_association_t *,
sctp_chunk_t *sctp_make_cwr(const struct sctp_association *,
const __u32 lowest_tsn,
const sctp_chunk_t *);
sctp_chunk_t *sctp_make_datafrag(sctp_association_t *,
sctp_chunk_t *sctp_make_datafrag(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 *data,
__u8 flags, __u16 ssn);
sctp_chunk_t * sctp_make_datafrag_empty(sctp_association_t *,
sctp_chunk_t * sctp_make_datafrag_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 flags,
__u16 ssn);
sctp_chunk_t *sctp_make_data(sctp_association_t *,
sctp_chunk_t *sctp_make_data(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 *data);
sctp_chunk_t *sctp_make_data_empty(sctp_association_t *,
sctp_chunk_t *sctp_make_data_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *, int len);
sctp_chunk_t *sctp_make_ecne(const sctp_association_t *,
sctp_chunk_t *sctp_make_ecne(const struct sctp_association *,
const __u32);
sctp_chunk_t *sctp_make_sack(const sctp_association_t *);
sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc);
sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc,
sctp_chunk_t *sctp_make_sack(const struct sctp_association *);
sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc);
sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const sctp_chunk_t *);
sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *,
sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *,
const sctp_chunk_t *);
void sctp_init_cause(sctp_chunk_t *, __u16 cause, const void *, size_t);
sctp_chunk_t *sctp_make_abort(const sctp_association_t *,
sctp_chunk_t *sctp_make_abort(const struct sctp_association *,
const sctp_chunk_t *,
const size_t hint);
sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *,
sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *,
const sctp_chunk_t *,
__u32 tsn);
sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *,
sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *,
const sctp_chunk_t *,
const struct msghdr *);
sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *,
sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *,
const void *payload,
const size_t paylen);
sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *,
sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *,
const sctp_chunk_t *,
const void *payload,
const size_t paylen);
sctp_chunk_t *sctp_make_op_error(const sctp_association_t *,
sctp_chunk_t *sctp_make_op_error(const struct sctp_association *,
const sctp_chunk_t *chunk,
__u16 cause_code,
const void *payload,
size_t paylen);
void sctp_chunk_assign_tsn(sctp_chunk_t *);
void sctp_chunk_assign_ssn(sctp_chunk_t *);
int sctp_datachunks_from_user(sctp_association_t *,
int sctp_datachunks_from_user(struct sctp_association *,
const struct sctp_sndrcvinfo *,
struct msghdr *, int len,
struct sk_buff_head *);
......@@ -279,34 +279,34 @@ int sctp_datachunks_from_user(sctp_association_t *,
int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state,
sctp_endpoint_t *,
sctp_association_t *asoc,
struct sctp_endpoint *,
struct sctp_association *asoc,
void *event_arg,
int priority);
int gfp);
int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state,
sctp_endpoint_t *,
sctp_association_t *asoc,
struct sctp_endpoint *,
struct sctp_association *asoc,
void *event_arg,
sctp_disposition_t status,
sctp_cmd_seq_t *commands,
int priority);
int gfp);
/* 2nd level prototypes */
int
sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state,
sctp_endpoint_t *ep,
sctp_association_t *asoc,
struct sctp_endpoint *ep,
struct sctp_association *asoc,
void *event_arg,
sctp_disposition_t status,
sctp_cmd_seq_t *retval,
int priority);
int gfp);
int sctp_gen_sack(sctp_association_t *, int force, sctp_cmd_seq_t *);
void sctp_do_TSNdup(sctp_association_t *, sctp_chunk_t *, long gap);
int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
void sctp_do_TSNdup(struct sctp_association *, sctp_chunk_t *, long gap);
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
......@@ -325,21 +325,21 @@ sctp_cookie_param_t *
sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
const struct sctp_chunk *, int *cookie_len,
const __u8 *, int addrs_len);
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *,
const sctp_association_t *,
sctp_chunk_t *, int priority, int *err,
struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
const struct sctp_association *,
sctp_chunk_t *, int gfp, int *err,
sctp_chunk_t **err_chk_p);
int sctp_addip_addr_config(sctp_association_t *, sctp_param_t,
int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
struct sockaddr_storage*, int);
void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_chunk_t *chunk,
sctp_cmd_seq_t *commands,
sctp_chunk_t *err_chunk);
/* 3rd level prototypes */
__u32 sctp_generate_tag(const sctp_endpoint_t *);
__u32 sctp_generate_tsn(const sctp_endpoint_t *);
__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 *,
......@@ -450,7 +450,7 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a
*/
static inline int
sctp_vtag_verify_either(const sctp_chunk_t *chunk,
const sctp_association_t *asoc)
const struct sctp_association *asoc)
{
/* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
*
......
......@@ -83,14 +83,11 @@ struct sctp_outq;
struct sctp_bind_addr;
struct sctp_ulpq;
struct sctp_opt;
struct sctp_endpoint_common;
struct sctp_ep_common;
struct sctp_ssnmap;
typedef struct sctp_endpoint sctp_endpoint_t;
typedef struct sctp_association sctp_association_t;
typedef struct sctp_chunk sctp_chunk_t;
typedef struct sctp_bind_addr sctp_bind_addr_t;
typedef struct sctp_endpoint_common sctp_endpoint_common_t;
#include <net/sctp/tsnmap.h>
#include <net/sctp/ulpevent.h>
......@@ -114,7 +111,7 @@ typedef struct sctp_bind_hashbucket {
/* Used for hashing all associations. */
typedef struct sctp_hashbucket {
rwlock_t lock;
sctp_endpoint_common_t *chain;
struct sctp_ep_common *chain;
} sctp_hashbucket_t __attribute__((__aligned__(8)));
......@@ -235,7 +232,9 @@ struct sctp_af {
int saddr);
void (*from_sk) (union sctp_addr *,
struct sock *sk);
void (*to_sk) (union sctp_addr *,
void (*to_sk_saddr) (union sctp_addr *,
struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *,
struct sock *sk);
int (*addr_valid) (union sctp_addr *);
sctp_scope_t (*scope) (union sctp_addr *);
......@@ -283,8 +282,11 @@ struct sctp_opt {
/* PF_ family specific functions. */
struct sctp_pf *pf;
/* Access to HMAC transform. */
struct crypto_tfm *hmac;
/* What is our base endpointer? */
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
/* Various Socket Options. */
__u16 default_stream;
......@@ -514,7 +516,7 @@ struct sctp_chunk {
struct sctp_association *asoc;
/* What endpoint received this chunk? */
sctp_endpoint_common_t *rcvr;
struct sctp_ep_common *rcvr;
/* We fill this in if we are calculating RTT. */
unsigned long sent_at;
......@@ -697,7 +699,6 @@ struct sctp_transport {
*/
int rto_pending;
/*
* These are the congestion stats.
*/
......@@ -973,7 +974,7 @@ int sctp_is_any(const union sctp_addr *addr);
int sctp_addr_is_valid(const union sctp_addr *addr);
/* What type of sctp_endpoint_common? */
/* What type of endpoint? */
typedef enum {
SCTP_EP_TYPE_SOCKET,
SCTP_EP_TYPE_ASSOCIATION,
......@@ -995,10 +996,10 @@ typedef enum {
*
*/
struct sctp_endpoint_common {
struct sctp_ep_common {
/* Fields to help us manage our entries in the hash tables. */
sctp_endpoint_common_t *next;
sctp_endpoint_common_t **pprev;
struct sctp_ep_common *next;
struct sctp_ep_common **pprev;
int hashent;
/* Runtime type information. What kind of endpoint is this? */
......@@ -1052,12 +1053,7 @@ struct sctp_endpoint_common {
struct sctp_endpoint {
/* Common substructure for endpoint and association. */
sctp_endpoint_common_t base;
/* These are the system-wide defaults and other stuff which is
* endpoint-independent.
*/
struct sctp_protocol *proto;
struct sctp_ep_common base;
/* Associations: A list of current associations and mappings
* to the data consumers for each association. This
......@@ -1092,28 +1088,29 @@ struct sctp_endpoint {
};
/* Recover the outter endpoint structure. */
static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base)
{
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
ep = container_of(base, sctp_endpoint_t, base);
ep = container_of(base, struct sctp_endpoint, base);
return ep;
}
/* These are function signatures for manipulating endpoints. */
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *, struct sock *, int);
sctp_endpoint_t *sctp_endpoint_init(struct sctp_endpoint *,
struct sctp_protocol *,
struct sock *, int gfp);
void sctp_endpoint_free(sctp_endpoint_t *);
void sctp_endpoint_put(sctp_endpoint_t *);
void sctp_endpoint_hold(sctp_endpoint_t *);
void sctp_endpoint_add_asoc(sctp_endpoint_t *, struct sctp_association *asoc);
struct sctp_association *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
const union sctp_addr *paddr,
struct sctp_transport **);
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *);
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *,
struct sock *, int gfp);
void sctp_endpoint_free(struct sctp_endpoint *);
void sctp_endpoint_put(struct sctp_endpoint *);
void sctp_endpoint_hold(struct sctp_endpoint *);
void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
struct sctp_association *sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **);
int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
const union sctp_addr *);
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr);
......@@ -1126,8 +1123,8 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
sctp_init_chunk_t *init, int gfp);
int sctp_process_param(struct sctp_association *, union sctp_params param,
const union sctp_addr *from, int gfp);
__u32 sctp_generate_tag(const sctp_endpoint_t *);
__u32 sctp_generate_tsn(const sctp_endpoint_t *);
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* RFC2960
......@@ -1150,7 +1147,7 @@ struct sctp_association {
* In this context, it represents the associations's view
* of the local endpoint of the association.
*/
sctp_endpoint_common_t base;
struct sctp_ep_common base;
/* Associations on the same socket. */
struct list_head asocs;
......@@ -1162,7 +1159,7 @@ struct sctp_association {
__u32 eyecatcher;
/* This is our parent endpoint. */
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
/* These are those association elements needed in the cookie. */
sctp_cookie_t c;
......@@ -1548,6 +1545,9 @@ struct sctp_association {
* after reaching 4294967295.
*/
__u32 addip_serial;
/* Is it a temporary association? */
__u8 temp;
};
......@@ -1559,7 +1559,7 @@ enum {
};
/* Recover the outter association structure. */
static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base)
static inline struct sctp_association *sctp_assoc(struct sctp_ep_common *base)
{
struct sctp_association *asoc;
......@@ -1571,10 +1571,10 @@ static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base)
struct sctp_association *
sctp_association_new(const sctp_endpoint_t *, const struct sock *,
sctp_association_new(const struct sctp_endpoint *, const struct sock *,
sctp_scope_t scope, int gfp);
struct sctp_association *
sctp_association_init(struct sctp_association *, const sctp_endpoint_t *,
sctp_association_init(struct sctp_association *, const struct sctp_endpoint *,
const struct sock *, sctp_scope_t scope,
int gfp);
void sctp_association_free(struct sctp_association *);
......
......@@ -114,7 +114,7 @@ struct sctp_tsnmap_iter {
};
/* Create a new tsnmap. */
struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 init_tsn, int priority);
struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 init_tsn, int gfp);
/* Dispose of a tsnmap. */
void sctp_tsnmap_free(struct sctp_tsnmap *);
......
......@@ -10,13 +10,15 @@
* sctp_ulpevent type is used to carry information from the state machine
* upwards to the ULP.
*
* The SCTP reference implementation is free software;
* This file is part of the SCTP kernel 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
* 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.
......@@ -27,12 +29,17 @@
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to one of the
* following email addresses:
* 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
*
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -64,7 +71,7 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
return (struct sctp_ulpevent *)skb->cb;
}
struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int priority);
struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp);
struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
void sctp_ulpevent_free(struct sctp_ulpevent *);
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
......@@ -76,7 +83,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
__u16 error,
__u16 outbound,
__u16 inbound,
int priority);
int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
const struct sctp_association *asoc,
......@@ -84,32 +91,32 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
int flags,
int state,
int error,
int priority);
int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
__u16 flags,
int priority);
int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
__u16 flags,
__u32 error,
int priority);
int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
const struct sctp_association *asoc,
__u16 flags,
int priority);
int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
const struct sctp_association *asoc,
__u32 indication, int priority);
__u32 indication, int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
struct sctp_chunk *chunk,
int priority);
int gfp);
void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
struct msghdr *);
......
......@@ -50,14 +50,15 @@
struct sctp_ulpq {
char malloced;
char pd_mode;
sctp_association_t *asoc;
struct sctp_association *asoc;
struct sk_buff_head reasm;
struct sk_buff_head lobby;
};
/* Prototypes. */
struct sctp_ulpq *sctp_ulpq_new(sctp_association_t *asoc, int priority);
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *, sctp_association_t *);
struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp);
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *,
struct sctp_association *);
void sctp_ulpq_free(struct sctp_ulpq *);
/* Add a new DATA chunk for processing. */
......
......@@ -43,12 +43,12 @@ config SCTP_ADLER32
bool "SCTP: Use old checksum (Adler-32)"
depends on IP_SCTP
help
RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
This has been deprecated and replaced by an algorithm now referred
to as crc32c.
If you say Y, this will use the Adler-32 algorithm, this might be useful
for interoperation with downlevel peers.
If you say Y, this will use the Adler-32 algorithm, this might be
useful for interoperation with downlevel peers.
If unsure, say N.
......@@ -58,19 +58,46 @@ config SCTP_DBG_MSG
help
If you say Y, this will enable verbose debugging messages.
If unsure, say N. However, if you are running into problems, use this
option to gather detailed trace information
If unsure, say N. However, if you are running into problems, use
this option to gather detailed trace information
config SCTP_DBG_OBJCNT
bool "SCTP: Debug object counts"
depends on IP_SCTP
help
If you say Y, this will enable debugging support for counting the types
of objects that are currently allocated. This is useful for identifying
memory leaks. If the /proc filesystem is enabled this debug information
can be viewed by 'cat /proc/net/sctp/sctp_dbg_objcnt'
If you say Y, this will enable debugging support for counting the
type of objects that are currently allocated. This is useful for
identifying memory leaks. If the /proc filesystem is enabled this
debug information can be viewed by
'cat /proc/net/sctp/sctp_dbg_objcnt'
If unsure, say N
endmenu
choice
prompt "SCTP: Cookie HMAC Algorithm"
help
HMAC algorithm to be used during association initialization. It
is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See
configuration for Cryptographic API and enable those algorithms
to make usable by SCTP.
config SCTP_HMAC_NONE
bool "None"
help
Choosing this disables the use of an HMAC during association
establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_SHA1
bool "HMAC-SHA1" if CRYPTO_HMAC=y && CRYPTO_SHA1=y || CRYPTO_SHA1=m
help
Enable the use of HMAC-SHA1 during association establishment. It
is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_MD5
bool "HMAC-MD5" if CRYPTO_HMAC=y && CRYPTO_MD5=y || CRYPTO_MD5=m
help
Enable the use of HMAC-MD5 during association establishment. It is
advised to use either HMAC-MD5 or HMAC-SHA1.
endchoice
endmenu
......@@ -9,8 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
transport.o sm_make_chunk.o ulpevent.o \
inqueue.o outqueue.o ulpqueue.o command.o \
tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o hashdriver.o sla1.o \
debug.o ssnmap.o proc.o
output.o input.o debug.o ssnmap.o proc.o
ifeq ($(CONFIG_SCTP_ADLER32), y)
sctp-y += adler32.o
......
......@@ -2,43 +2,43 @@
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2003 International Business Machines, Corp.
*
*
* This file is part of the SCTP kernel reference Implementation
*
* This file has direct heritage from the SCTP user-level reference
*
* This file has direct heritage from the SCTP user-level reference
* implementation by R. Stewart, et al. These functions implement the
* Adler-32 algorithm as specified by RFC 2960.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* Adler-32 algorithm as specified by RFC 2960.
*
* 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:
* Randall Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
* Sridhar Samudrala <sri@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.
*/
......@@ -65,7 +65,7 @@
* tad, but I have commented the original lines below
*/
#include <linux/types.h>
#include <linux/types.h>
#include <net/sctp/sctp.h>
#define BASE 65521 /* largest prime smaller than 65536 */
......@@ -111,7 +111,7 @@ unsigned long update_adler32(unsigned long adler,
* This would then be (2 * BASE) - 2, which
* will still only do one subtract. On Intel
* this is much better to do this way and
* avoid the divide. Have not -pg'd on
* avoid the divide. Have not -pg'd on
* sparc.
*/
if (s2 >= BASE) {
......@@ -135,7 +135,7 @@ __u32 sctp_start_cksum(__u8 *ptr, __u16 count)
__u32 zero = 0L;
/* Calculate the CRC up to the checksum field. */
adler = update_adler32(adler, ptr,
adler = update_adler32(adler, ptr,
sizeof(struct sctphdr) - sizeof(__u32));
/* Skip over the checksum field. */
adler = update_adler32(adler, (unsigned char *) &zero,
......@@ -156,6 +156,15 @@ __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler)
return adler;
}
__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 count, __u32 adler)
{
/* Its not worth it to try harder. Adler32 is obsolescent. */
adler = update_adler32(adler, from, count);
memcpy(to, from, count);
return adler;
}
__u32 sctp_end_cksum(__u32 adler)
{
return adler;
......
This diff is collapsed.
......@@ -80,6 +80,22 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
goto out;
}
/* If there are no addresses matching the scope and
* this is global scope, try to get a link scope address, with
* the assumption that we must be sitting behind a NAT.
*/
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,
list);
error = sctp_copy_one_addr(dest, &addr->a,
SCTP_SCOPE_LINK, gfp,
flags);
if (error < 0)
goto out;
}
}
out:
if (error)
sctp_bind_addr_clean(dest);
......@@ -214,6 +230,14 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
len += sizeof(sctp_addr_param_t);
}
/* Don't even bother embedding an address if there
* is only one.
*/
if (len == sizeof(sctp_addr_param_t)) {
retval.v = NULL;
goto end_raw;
}
retval.v = kmalloc(len, gfp);
if (!retval.v)
goto end_raw;
......
......@@ -43,9 +43,9 @@
#include <net/sctp/sm.h>
/* Create a new sctp_command_sequence. */
sctp_cmd_seq_t *sctp_new_cmd_seq(int priority)
sctp_cmd_seq_t *sctp_new_cmd_seq(int gfp)
{
sctp_cmd_seq_t *retval = t_new(sctp_cmd_seq_t, priority);
sctp_cmd_seq_t *retval = t_new(sctp_cmd_seq_t, gfp);
if (retval)
sctp_init_cmd_seq(retval);
......
......@@ -170,6 +170,23 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
return crc32;
}
__u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32)
{
__u32 i;
__u32 *_to = (__u32 *)to;
__u32 *_from = (__u32 *)from;
for (i = 0; i < (length/4); i++) {
_to[i] = _from[i];
CRC32C(crc32, from[i*4]);
CRC32C(crc32, from[i*4+1]);
CRC32C(crc32, from[i*4+2]);
CRC32C(crc32, from[i*4+3]);
}
return crc32;
}
__u32 sctp_end_cksum(__u32 crc32)
{
__u32 result;
......
......@@ -54,27 +54,27 @@
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/random.h> /* get_random_bytes() */
#include <linux/crypto.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */
static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep);
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
/* Create a sctp_endpoint_t with all that boring stuff initialized.
/* Create a sctp_endpoint with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
struct sock *sk, int priority)
struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
{
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
/* Build a local endpoint. */
ep = t_new(sctp_endpoint_t, priority);
ep = t_new(struct sctp_endpoint, gfp);
if (!ep)
goto fail;
if (!sctp_endpoint_init(ep, proto, sk, priority))
if (!sctp_endpoint_init(ep, sk, gfp))
goto fail_init;
ep->base.malloced = 1;
SCTP_DBG_OBJCNT_INC(ep);
......@@ -89,12 +89,11 @@ sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
/*
* Initialize the base fields of the endpoint structure.
*/
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
struct sctp_protocol *proto,
struct sock *sk, int priority)
struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
struct sock *sk, int gfp)
{
struct sctp_opt *sp = sctp_sk(sk);
memset(ep, 0, sizeof(sctp_endpoint_t));
memset(ep, 0, sizeof(struct sctp_endpoint));
/* Initialize the base structure. */
/* What type of endpoint are we? */
......@@ -110,8 +109,7 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
/* Set its top-half handler */
sctp_inq_set_th_handler(&ep->base.inqueue,
(void (*)(void *))sctp_endpoint_bh_rcv,
ep);
(void (*)(void *))sctp_endpoint_bh_rcv, ep);
/* Initialize the bind addr area */
sctp_bind_addr_init(&ep->base.bind_addr, 0);
......@@ -121,21 +119,16 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->base.sk = sk;
sock_hold(ep->base.sk);
/* This pointer is useful to access the default protocol parameter
* values.
*/
ep->proto = proto;
/* Create the lists of associations. */
INIT_LIST_HEAD(&ep->asocs);
/* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
......@@ -146,11 +139,11 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
= 5 * sp->rtoinfo.srto_max;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
/* Set up the default send/receive buffer space. */
......@@ -175,7 +168,8 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
}
/* Add an association to an endpoint. */
void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
struct sctp_association *asoc)
{
struct sock *sk = ep->base.sk;
......@@ -191,14 +185,14 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
/* Free the endpoint structure. Delay cleanup until
* all users have released their reference count on this structure.
*/
void sctp_endpoint_free(sctp_endpoint_t *ep)
void sctp_endpoint_free(struct sctp_endpoint *ep)
{
ep->base.dead = 1;
sctp_endpoint_put(ep);
}
/* Final destructor for endpoint. */
void sctp_endpoint_destroy(sctp_endpoint_t *ep)
void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
......@@ -207,9 +201,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
/* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint(ep);
/* Cleanup the inqueue. */
sctp_inq_free(&ep->base.inqueue);
/* Free up the HMAC transform. */
if (sctp_sk(ep->base.sk)->hmac)
sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
/* Cleanup. */
sctp_inq_free(&ep->base.inqueue);
sctp_bind_addr_free(&ep->base.bind_addr);
/* Remove and free the port */
......@@ -228,7 +225,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
}
/* Hold a reference to an endpoint. */
void sctp_endpoint_hold(sctp_endpoint_t *ep)
void sctp_endpoint_hold(struct sctp_endpoint *ep)
{
atomic_inc(&ep->base.refcnt);
}
......@@ -236,17 +233,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep)
/* Release a reference to an endpoint and clean up if there are
* no more references.
*/
void sctp_endpoint_put(sctp_endpoint_t *ep)
void sctp_endpoint_put(struct sctp_endpoint *ep)
{
if (atomic_dec_and_test(&ep->base.refcnt))
sctp_endpoint_destroy(ep);
}
/* Is this the endpoint we are looking for? */
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
const union sctp_addr *laddr)
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
const union sctp_addr *laddr)
{
sctp_endpoint_t *retval;
struct sctp_endpoint *retval;
sctp_read_lock(&ep->base.addr_lock);
if (ep->base.bind_addr.port == laddr->v4.sin_port) {
......@@ -268,19 +265,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
sctp_association_t *__sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *endpoint,
struct sctp_association *__sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
int rport;
sctp_association_t *asoc;
struct sctp_association *asoc;
struct list_head *pos;
rport = paddr->v4.sin_port;
list_for_each(pos, &endpoint->asocs) {
asoc = list_entry(pos, sctp_association_t, asocs);
list_for_each(pos, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
if (rport == asoc->peer.port) {
sctp_read_lock(&asoc->base.addr_lock);
*transport = sctp_assoc_lookup_paddr(asoc, paddr);
......@@ -296,12 +293,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc(
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
sctp_association_t *sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *ep,
struct sctp_association *sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
sctp_local_bh_disable();
asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport);
......@@ -313,7 +310,7 @@ sctp_association_t *sctp_endpoint_lookup_assoc(
/* Look for any peeled off association from the endpoint that matches the
* given peer address.
*/
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
const union sctp_addr *paddr)
{
struct list_head *pos;
......@@ -337,9 +334,9 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
/* Do delayed input processing. This is scheduled by sctp_rcv().
* This may be called on BH or task time.
*/
static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
struct sock *sk;
struct sctp_transport *transport;
sctp_chunk_t *chunk;
......@@ -355,7 +352,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
inqueue = &ep->base.inqueue;
sk = ep->base.sk;
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
subtype.chunk = chunk->chunk_hdr->type;
/* We might have grown an association since last we
......
......@@ -63,11 +63,11 @@
/* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *);
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp);
sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
/* Calculate the SCTP checksum of an SCTP packet. */
......@@ -102,9 +102,9 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
int sctp_rcv(struct sk_buff *skb)
{
struct sock *sk;
sctp_association_t *asoc;
sctp_endpoint_t *ep = NULL;
sctp_endpoint_common_t *rcvr;
struct sctp_association *asoc;
struct sctp_endpoint *ep = NULL;
struct sctp_ep_common *rcvr;
struct sctp_transport *transport = NULL;
sctp_chunk_t *chunk;
struct sctphdr *sh;
......@@ -128,11 +128,11 @@ int sctp_rcv(struct sk_buff *skb)
if (sctp_rcv_checksum(skb) < 0)
goto bad_packet;
skb_pull(skb, sizeof(struct sctphdr));
skb_pull(skb, sizeof(struct sctphdr));
family = ipver2af(skb->nh.iph->version);
af = sctp_get_af_specific(family);
if (unlikely(!af))
if (unlikely(!af))
goto bad_packet;
/* Initialize local addresses for lookups. */
......@@ -224,9 +224,7 @@ int sctp_rcv(struct sk_buff *skb)
return ret;
bad_packet:
#if 0 /* FIXME */
SCTP_INC_STATS(SctpInErrs);
#endif /* FIXME*/
SCTP_INC_STATS(SctpChecksumErrors);
discard_it:
kfree_skb(skb);
......@@ -286,8 +284,8 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
/* Common lookup code for icmp/icmpv6 error handler. */
struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
struct sctphdr *sctphdr,
struct sctp_endpoint **epp,
struct sctp_association **app,
struct sctp_endpoint **epp,
struct sctp_association **app,
struct sctp_transport **tpp)
{
union sctp_addr saddr;
......@@ -309,15 +307,15 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
af->from_skb(&saddr, skb, 1);
af->from_skb(&daddr, skb, 0);
/* Look for an association that matches the incoming ICMP error
/* Look for an association that matches the incoming ICMP error
* packet.
*/
asoc = __sctp_lookup_association(&saddr, &daddr, &transport);
if (!asoc) {
/* If there is no matching association, see if it matches any
* endpoint. This may happen for an ICMP error generated in
* response to an INIT_ACK.
*/
* endpoint. This may happen for an ICMP error generated in
* response to an INIT_ACK.
*/
ep = __sctp_rcv_lookup_endpoint(&daddr);
if (!ep) {
return NULL;
......@@ -345,25 +343,25 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
*app = asoc;
*tpp = transport;
return sk;
out:
sock_put(sk);
if (asoc)
sctp_association_put(asoc);
if (ep)
if (ep)
sctp_endpoint_put(ep);
return NULL;
}
/* Common cleanup code for icmp/icmpv6 error handler. */
void sctp_err_finish(struct sock *sk, struct sctp_endpoint *ep,
void sctp_err_finish(struct sock *sk, struct sctp_endpoint *ep,
struct sctp_association *asoc)
{
sctp_bh_unlock_sock(sk);
sock_put(sk);
if (asoc)
sctp_association_put(asoc);
if (ep)
if (ep)
sctp_endpoint_put(ep);
}
......@@ -389,8 +387,8 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct sock *sk;
sctp_endpoint_t *ep;
sctp_association_t *asoc;
struct sctp_endpoint *ep;
struct sctp_association *asoc;
struct sctp_transport *transport;
struct inet_opt *inet;
char *saveip, *savesctp;
......@@ -414,7 +412,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
ICMP_INC_STATS_BH(IcmpInErrors);
return;
}
/* Warning: The sock lock is held. Remember to call
/* Warning: The sock lock is held. Remember to call
* sctp_err_finish!
*/
......@@ -520,10 +518,10 @@ int sctp_rcv_ootb(struct sk_buff *skb)
}
/* Insert endpoint into the hash table. */
void __sctp_hash_endpoint(sctp_endpoint_t *ep)
void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
sctp_endpoint_common_t **epp;
sctp_endpoint_common_t *epb;
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
sctp_hashbucket_t *head;
epb = &ep->base;
......@@ -542,7 +540,7 @@ void __sctp_hash_endpoint(sctp_endpoint_t *ep)
}
/* Add an endpoint to the hash. Local BH-safe. */
void sctp_hash_endpoint(sctp_endpoint_t *ep)
void sctp_hash_endpoint(struct sctp_endpoint *ep)
{
sctp_local_bh_disable();
__sctp_hash_endpoint(ep);
......@@ -550,10 +548,10 @@ void sctp_hash_endpoint(sctp_endpoint_t *ep)
}
/* Remove endpoint from the hash table. */
void __sctp_unhash_endpoint(sctp_endpoint_t *ep)
void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{
sctp_hashbucket_t *head;
sctp_endpoint_common_t *epb;
struct sctp_ep_common *epb;
epb = &ep->base;
......@@ -574,7 +572,7 @@ void __sctp_unhash_endpoint(sctp_endpoint_t *ep)
}
/* Remove endpoint from the hash. Local BH-safe. */
void sctp_unhash_endpoint(sctp_endpoint_t *ep)
void sctp_unhash_endpoint(struct sctp_endpoint *ep)
{
sctp_local_bh_disable();
__sctp_unhash_endpoint(ep);
......@@ -582,11 +580,11 @@ void sctp_unhash_endpoint(sctp_endpoint_t *ep)
}
/* Look up an endpoint. */
sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
{
sctp_hashbucket_t *head;
sctp_endpoint_common_t *epb;
sctp_endpoint_t *ep;
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
int hash;
hash = sctp_ep_hashfn(laddr->v4.sin_port);
......@@ -609,7 +607,7 @@ sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
}
/* Add an association to the hash. Local BH-safe. */
void sctp_hash_established(sctp_association_t *asoc)
void sctp_hash_established(struct sctp_association *asoc)
{
sctp_local_bh_disable();
__sctp_hash_established(asoc);
......@@ -617,10 +615,10 @@ void sctp_hash_established(sctp_association_t *asoc)
}
/* Insert association into the hash table. */
void __sctp_hash_established(sctp_association_t *asoc)
void __sctp_hash_established(struct sctp_association *asoc)
{
sctp_endpoint_common_t **epp;
sctp_endpoint_common_t *epb;
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
sctp_hashbucket_t *head;
epb = &asoc->base;
......@@ -641,7 +639,7 @@ void __sctp_hash_established(sctp_association_t *asoc)
}
/* Remove association from the hash table. Local BH-safe. */
void sctp_unhash_established(sctp_association_t *asoc)
void sctp_unhash_established(struct sctp_association *asoc)
{
sctp_local_bh_disable();
__sctp_unhash_established(asoc);
......@@ -649,10 +647,10 @@ void sctp_unhash_established(sctp_association_t *asoc)
}
/* Remove association from the hash table. */
void __sctp_unhash_established(sctp_association_t *asoc)
void __sctp_unhash_established(struct sctp_association *asoc)
{
sctp_hashbucket_t *head;
sctp_endpoint_common_t *epb;
struct sctp_ep_common *epb;
epb = &asoc->base;
......@@ -674,13 +672,14 @@ void __sctp_unhash_established(sctp_association_t *asoc)
}
/* Look up an association. */
sctp_association_t *__sctp_lookup_association(const union sctp_addr *local,
const union sctp_addr *peer,
struct sctp_transport **pt)
struct sctp_association *__sctp_lookup_association(
const union sctp_addr *local,
const union sctp_addr *peer,
struct sctp_transport **pt)
{
sctp_hashbucket_t *head;
sctp_endpoint_common_t *epb;
sctp_association_t *asoc;
struct sctp_ep_common *epb;
struct sctp_association *asoc;
struct sctp_transport *transport;
int hash;
......@@ -710,11 +709,11 @@ sctp_association_t *__sctp_lookup_association(const union sctp_addr *local,
}
/* Look up an association. BH-safe. */
sctp_association_t *sctp_lookup_association(const union sctp_addr *laddr,
struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
sctp_local_bh_disable();
asoc = __sctp_lookup_association(laddr, paddr, transportp);
......@@ -727,7 +726,7 @@ sctp_association_t *sctp_lookup_association(const union sctp_addr *laddr,
int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
struct sctp_transport *transport;
if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
......@@ -757,10 +756,10 @@ int sctp_has_association(const union sctp_addr *laddr,
* in certain circumstances.
*
*/
static sctp_association_t *__sctp_rcv_init_lookup(struct sk_buff *skb,
static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
const union sctp_addr *laddr, struct sctp_transport **transportp)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
union sctp_addr addr;
union sctp_addr *paddr = &addr;
struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
......@@ -815,12 +814,12 @@ static sctp_association_t *__sctp_rcv_init_lookup(struct sk_buff *skb,
}
/* Lookup an association for an inbound skb. */
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
asoc = __sctp_lookup_association(laddr, paddr, transportp);
......
......@@ -78,7 +78,7 @@ void sctp_inq_free(struct sctp_inq *queue)
sctp_chunk_t *chunk;
/* Empty the queue. */
while ((chunk = (sctp_chunk_t *) skb_dequeue(&queue->in)) != NULL)
while ((chunk = (sctp_chunk_t *) skb_dequeue(&queue->in)))
sctp_free_chunk(chunk);
/* If there is a packet which is currently being worked on,
......@@ -123,7 +123,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue)
* at this time.
*/
if ((chunk = queue->in_progress) != NULL) {
if ((chunk = queue->in_progress)) {
/* There is a packet that we have been working on.
* Any post processing work to do before we move on?
*/
......
......@@ -95,8 +95,8 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
struct sctphdr *sh = (struct sctphdr *)(skb->data + offset);
struct sock *sk;
sctp_endpoint_t *ep;
sctp_association_t *asoc;
struct sctp_endpoint *ep;
struct sctp_association *asoc;
struct sctp_transport *transport;
struct ipv6_pinfo *np;
char *saveip, *savesctp;
......@@ -116,7 +116,7 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return;
}
/* Warning: The sock lock is held. Remember to call
/* Warning: The sock lock is held. Remember to call
* sctp_err_finish!
*/
......@@ -142,21 +142,19 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
/* Based on tcp_v6_xmit() in tcp_ipv6.c. */
static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
int ipfragok)
{
struct sock *sk = skb->sk;
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl;
struct dst_entry *dst = skb->dst;
struct rt6_info *rt6 = (struct rt6_info *)dst;
fl.proto = sk->protocol;
/* Fill in the dest address from the route entry passed with the skb
* and the source address from the transport.
*/
fl.fl6_dst = &rt6->rt6i_dst.addr;
fl.fl6_dst = &transport->ipaddr.v6.sin6_addr;
fl.fl6_src = &transport->saddr.v6.sin6_addr;
fl.fl6_flowlabel = np->flow_label;
......@@ -187,7 +185,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
struct dst_entry *sctp_v6_get_dst(sctp_association_t *asoc,
struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
union sctp_addr *daddr,
union sctp_addr *saddr)
{
......@@ -245,7 +243,7 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
/* Fills in the source address(saddr) based on the destination address(daddr)
* and asoc's bind address list.
*/
void sctp_v6_get_saddr(sctp_association_t *asoc, struct dst_entry *dst,
void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
union sctp_addr *daddr, union sctp_addr *saddr)
{
sctp_bind_addr_t *bp;
......@@ -370,11 +368,17 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
}
/* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v6_to_sk(union sctp_addr *addr, struct sock *sk)
static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
{
inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
}
/* Initialize sk->daddr from sctp_addr. */
static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
{
inet6_sk(sk)->daddr = addr->v6.sin6_addr;
}
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
unsigned short port)
......@@ -385,7 +389,7 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr);
}
/* Compare addresses exactly.
/* Compare addresses exactly.
* FIXME: v4-mapped-v6.
*/
static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
......@@ -514,6 +518,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newsk->family = PF_INET6;
newsk->protocol = IPPROTO_SCTP;
newsk->backlog_rcv = sk->prot->backlog_rcv;
newsk->shutdown = sk->shutdown;
newsctp6sk = (struct sctp6_sock *)newsk;
newsctp6sk->pinet6 = &newsctp6sk->inet6;
......@@ -523,10 +528,14 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
memcpy(newnp, np, sizeof(struct ipv6_pinfo));
ipv6_addr_copy(&newnp->daddr, &asoc->peer.primary_addr.v6.sin6_addr);
/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
* and getpeername().
*/
newinet->sport = inet->sport;
newinet->dport = asoc->peer.port;
newnp->saddr = np->saddr;
newnp->rcv_saddr = np->rcv_saddr;
newinet->dport = htons(asoc->peer.port);
newnp->daddr = asoc->peer.primary_addr.v6.sin6_addr;
#ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr);
......@@ -562,7 +571,7 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len)
}
/* Initialize a PF_INET msgname from a ulpevent. */
static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
char *msgname, int *addrlen)
{
struct sockaddr_in6 *sin6, *sin6from;
......@@ -589,7 +598,7 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
sin6from = &event->asoc->peer.primary_addr.v6;
ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin6->sin6_scope_id = sin6from->sin6_scope_id;
}
}
......@@ -689,7 +698,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
if (addr->v6.sin6_scope_id)
sk->bound_dev_if = addr->v6.sin6_scope_id;
if (!sk->bound_dev_if)
return 0;
return 0;
}
af = opt->pf->af;
}
......@@ -719,11 +728,11 @@ static int sctp_inet6_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
if (addr->v6.sin6_scope_id)
sk->bound_dev_if = addr->v6.sin6_scope_id;
if (!sk->bound_dev_if)
return 0;
return 0;
}
af = opt->pf->af;
}
return af != NULL;
}
......@@ -799,7 +808,8 @@ static struct sctp_af sctp_ipv6_specific = {
.copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb,
.from_sk = sctp_v6_from_sk,
.to_sk = sctp_v6_to_sk,
.to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr,
.dst_saddr = sctp_v6_dst_saddr,
.cmp_addr = sctp_v6_cmp_addr,
.scope = sctp_v6_scope,
......
......@@ -166,11 +166,11 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
/* If sending DATA and haven't aleady bundled a SACK, try to
* bundle one in to the packet.
*/
if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
if (sctp_chunk_is_data(chunk) && !pkt->has_sack &&
!pkt->has_cookie_echo) {
struct sctp_association *asoc;
asoc = pkt->transport->asoc;
if (asoc->a_rwnd > asoc->rwnd) {
struct sctp_chunk *sack;
asoc->a_rwnd = asoc->rwnd;
......@@ -205,7 +205,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
if (retval != SCTP_XMIT_OK)
goto finish;
pmtu = ((packet->transport->asoc) ?
(packet->transport->asoc->pmtu) :
(packet->transport->pmtu));
......@@ -259,7 +259,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
goto finish;
} else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type)
packet->has_cookie_echo = 1;
else if (SCTP_CID_SACK == chunk->chunk_hdr->type)
else if (SCTP_CID_SACK == chunk->chunk_hdr->type)
packet->has_sack = 1;
/* It is OK to send this chunk. */
......@@ -276,8 +276,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
*/
int sctp_packet_transmit(struct sctp_packet *packet)
{
struct sctp_transport *transport = packet->transport;
struct sctp_association *asoc = transport->asoc;
struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = tp->asoc;
struct sctphdr *sh;
__u32 crc32;
struct sk_buff *nskb;
......@@ -311,6 +311,32 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
skb_set_owner_w(nskb, sk);
/* Build the SCTP header. */
sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
sh->source = htons(packet->source_port);
sh->dest = htons(packet->destination_port);
/* From 6.8 Adler-32 Checksum Calculation:
* After the packet is constructed (containing the SCTP common
* header and one or more control or DATA chunks), the
* transmitter shall:
*
* 1) Fill in the proper Verification Tag in the SCTP common
* header and initialize the checksum field to 0's.
*/
sh->vtag = htonl(packet->vtag);
sh->checksum = 0;
/* 2) Calculate the Adler-32 checksum of the whole packet,
* including the SCTP common header and all the
* chunks.
*
* Note: Adler-32 is no longer applicable, as has been replaced
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
*/
crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
/**
* 6.10 Bundling
*
......@@ -344,16 +370,20 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* for a given destination transport address.
*/
if ((1 == chunk->num_times_sent) &&
(!transport->rto_pending)) {
(!tp->rto_pending)) {
chunk->rtt_in_progress = 1;
transport->rto_pending = 1;
tp->rto_pending = 1;
}
has_data = 1;
}
memcpy(skb_put(nskb, chunk->skb->len),
chunk->skb->data, chunk->skb->len);
padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len;
memset(skb_put(nskb, padding), 0, padding);
if (padding)
memset(skb_put(chunk->skb, padding), 0, padding);
crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
chunk->skb->data,
chunk->skb->len, crc32);
SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, "
"%s %d\n",
"*** Chunk", chunk,
......@@ -376,30 +406,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
sctp_free_chunk(chunk);
}
/* Build the SCTP header. */
sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
sh->source = htons(packet->source_port);
sh->dest = htons(packet->destination_port);
/* From 6.8 Adler-32 Checksum Calculation:
* After the packet is constructed (containing the SCTP common
* header and one or more control or DATA chunks), the
* transmitter shall:
*
* 1) Fill in the proper Verification Tag in the SCTP common
* header and initialize the checksum field to 0's.
*/
sh->vtag = htonl(packet->vtag);
sh->checksum = 0;
/* 2) Calculate the Adler-32 checksum of the whole packet,
* including the SCTP common header and all the
* chunks.
*
* Note: Adler-32 is no longer applicable, as has been replaced
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
*/
crc32 = sctp_start_cksum((__u8 *)sh, nskb->len);
/* Perform final transformation on checksum. */
crc32 = sctp_end_cksum(crc32);
/* 3) Put the resultant value into the checksum field in the
......@@ -431,18 +438,18 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
/* Dump that on IP! */
if (asoc && asoc->peer.last_sent_to != transport) {
if (asoc && asoc->peer.last_sent_to != tp) {
/* Considering the multiple CPU scenario, this is a
* "correcter" place for last_sent_to. --xguo
*/
asoc->peer.last_sent_to = transport;
asoc->peer.last_sent_to = tp;
}
if (has_data) {
struct timer_list *timer;
unsigned long timeout;
transport->last_time_used = jiffies;
tp->last_time_used = jiffies;
/* Restart the AUTOCLOSE timer when sending data. */
if ((SCTP_STATE_ESTABLISHED == asoc->state) &&
......@@ -455,21 +462,21 @@ int sctp_packet_transmit(struct sctp_packet *packet)
}
}
dst = transport->dst;
dst = tp->dst;
/* The 'obsolete' field of dst is set to 2 when a dst is freed. */
if (!dst || (dst->obsolete > 1)) {
dst_release(dst);
sctp_transport_route(transport, NULL, sctp_sk(sk));
sctp_transport_route(tp, NULL, sctp_sk(sk));
sctp_assoc_sync_pmtu(asoc);
}
nskb->dst = dst_clone(transport->dst);
nskb->dst = dst_clone(tp->dst);
if (!nskb->dst)
goto no_route;
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n",
nskb->len);
(*transport->af_specific->sctp_xmit)(nskb, transport, packet->ipfragok);
(*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
out:
packet->size = SCTP_IP_OVERHEAD;
return err;
......@@ -596,7 +603,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
* if any previously transmitted data on the connection remains
* unacknowledged.
*/
if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size &&
if (!sp->nodelay && SCTP_IP_OVERHEAD == packet->size &&
q->outstanding_bytes && SCTP_STATE_ESTABLISHED == asoc->state) {
unsigned len = datasize + q->out_qlen;
......
......@@ -94,13 +94,13 @@ static inline void sctp_outq_insert_data(struct sctp_outq *q,
struct sctp_chunk *ch,
struct sctp_chunk *pos)
{
__skb_insert((struct sk_buff *)ch, (struct sk_buff *)pos->prev,
__skb_insert((struct sk_buff *)ch, (struct sk_buff *)pos->prev,
(struct sk_buff *)pos, pos->list);
q->out_qlen += ch->skb->len;
}
/* Generate a new outqueue. */
struct sctp_outq *sctp_outq_new(sctp_association_t *asoc)
struct sctp_outq *sctp_outq_new(struct sctp_association *asoc)
{
struct sctp_outq *q;
......@@ -116,7 +116,7 @@ struct sctp_outq *sctp_outq_new(sctp_association_t *asoc)
* You still need to define handlers if you really want to DO
* something with this structure...
*/
void sctp_outq_init(sctp_association_t *asoc, struct sctp_outq *q)
void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
{
q->asoc = asoc;
skb_queue_head_init(&q->out);
......@@ -417,7 +417,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
struct sctp_transport *transport = pkt->transport;
sctp_xmit_t status;
sctp_chunk_t *chunk;
sctp_association_t *asoc;
struct sctp_association *asoc;
int error = 0;
asoc = q->asoc;
......@@ -527,7 +527,7 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sctp_chunk *pos,
SCTP_DEBUG_PRINTK("sctp_xmit_frag: q not empty. "
"adding 0x%x to outqueue\n",
ntohl(frag->subh.data_hdr->tsn));
if (pos)
if (pos)
sctp_outq_insert_data(q, frag, pos);
else
sctp_outq_tail_data(q, frag);
......@@ -584,7 +584,7 @@ void sctp_xmit_frag(struct sctp_outq *q, struct sctp_chunk *pos,
void sctp_xmit_fragmented_chunks(struct sctp_outq *q, struct sctp_packet *pkt,
sctp_chunk_t *frag)
{
sctp_association_t *asoc = frag->asoc;
struct sctp_association *asoc = frag->asoc;
struct list_head *lfrag, *frag_list;
__u32 tsn;
int nfrags = 1;
......@@ -618,7 +618,7 @@ void sctp_xmit_fragmented_chunks(struct sctp_outq *q, struct sctp_packet *pkt,
sctp_chunk_t *sctp_fragment_chunk(sctp_chunk_t *chunk,
size_t max_frag_data_len)
{
sctp_association_t *asoc = chunk->asoc;
struct sctp_association *asoc = chunk->asoc;
void *data_ptr = chunk->subh.data_hdr;
struct sctp_sndrcvinfo *sinfo = &chunk->sinfo;
__u16 chunk_data_len = sctp_data_size(chunk);
......@@ -724,7 +724,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
{
struct sctp_packet *packet;
struct sctp_packet singleton;
sctp_association_t *asoc = q->asoc;
struct sctp_association *asoc = q->asoc;
int ecn_capable = asoc->peer.ecn_capable;
__u16 sport = asoc->base.bind_addr.port;
__u16 dport = asoc->peer.port;
......@@ -1077,7 +1077,7 @@ int sctp_outq_set_output_handlers(struct sctp_outq *q,
}
/* Update unack_data based on the incoming SACK chunk */
static void sctp_sack_update_unack_data(sctp_association_t *assoc,
static void sctp_sack_update_unack_data(struct sctp_association *assoc,
sctp_sackhdr_t *sack)
{
sctp_sack_variable_t *frags;
......@@ -1097,7 +1097,7 @@ static void sctp_sack_update_unack_data(sctp_association_t *assoc,
/* Return the highest new tsn that is acknowledged by the given SACK chunk. */
static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack,
sctp_association_t *asoc)
struct sctp_association *asoc)
{
struct list_head *ltransport, *lchunk;
struct sctp_transport *transport;
......@@ -1132,7 +1132,7 @@ static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack,
*/
int sctp_outq_sack(struct sctp_outq *q, sctp_sackhdr_t *sack)
{
sctp_association_t *asoc = q->asoc;
struct sctp_association *asoc = q->asoc;
struct sctp_transport *transport;
sctp_chunk_t *tchunk;
struct list_head *lchunk, *transport_list, *pos;
......
......@@ -55,12 +55,12 @@
#define DECLARE_PRIMITIVE(name) \
/* This is called in the code as sctp_primitive_ ## name. */ \
int sctp_primitive_ ## name(sctp_association_t *asoc, \
int sctp_primitive_ ## name(struct sctp_association *asoc, \
void *arg) { \
int error = 0; \
sctp_event_t event_type; sctp_subtype_t subtype; \
sctp_state_t state; \
sctp_endpoint_t *ep; \
struct sctp_endpoint *ep; \
\
event_type = SCTP_EVENT_T_PRIMITIVE; \
subtype = SCTP_ST_PRIMITIVE(SCTP_PRIMITIVE_ ## name); \
......
......@@ -203,7 +203,7 @@ static void sctp_free_local_addr_list(struct sctp_protocol *proto)
/* Copy the local addresses which are valid for 'scope' into 'bp'. */
int sctp_copy_local_addr_list(struct sctp_protocol *proto,
struct sctp_bind_addr *bp, sctp_scope_t scope,
int priority, int copy_flags)
int gfp, int copy_flags)
{
struct sockaddr_storage_list *addr;
int error = 0;
......@@ -223,8 +223,8 @@ int sctp_copy_local_addr_list(struct sctp_protocol *proto,
(((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp, &addr->a,
priority);
error = sctp_add_bind_addr(bp, &addr->a,
GFP_ATOMIC);
if (error)
goto end_copy;
}
......@@ -267,11 +267,16 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
}
/* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v4_to_sk(union sctp_addr *addr, struct sock *sk)
static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
{
inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr;
}
/* Initialize sk->daddr from sctp_addr. */
static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
{
inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr;
}
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst,
......@@ -471,21 +476,27 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
/* For v4, the source address is cached in the route entry(dst). So no need
* to cache it separately and hence this is an empty routine.
*/
void sctp_v4_get_saddr(sctp_association_t *asoc,
void sctp_v4_get_saddr(struct sctp_association *asoc,
struct dst_entry *dst,
union sctp_addr *daddr,
union sctp_addr *saddr)
{
struct rtable *rt = (struct rtable *)dst;
if (rt) {
saddr->v4.sin_family = AF_INET;
saddr->v4.sin_port = asoc->base.bind_addr.port;
saddr->v4.sin_addr.s_addr = rt->rt_src;
}
}
/* What interface did this skb arrive on? */
int sctp_v4_skb_iif(const struct sk_buff *skb)
int sctp_v4_skb_iif(const struct sk_buff *skb)
{
return ((struct rtable *)skb->dst)->rt_iif;
return ((struct rtable *)skb->dst)->rt_iif;
}
/* Create and initialize a new sk for the socket returned by accept(). */
/* Create and initialize a new sk for the socket returned by accept(). */
struct sock *sctp_v4_create_accept_sk(struct sock *sk,
struct sctp_association *asoc)
{
......@@ -505,22 +516,27 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newsk->prot = sk->prot;
newsk->no_check = sk->no_check;
newsk->reuse = sk->reuse;
newsk->shutdown = sk->shutdown;
newsk->destruct = inet_sock_destruct;
newsk->zapped = 0;
newsk->family = PF_INET;
newsk->protocol = IPPROTO_SCTP;
newsk->backlog_rcv = sk->prot->backlog_rcv;
newinet = inet_sk(newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for
* getsockname() and getpeername()
*/
newinet->sport = inet->sport;
newinet->saddr = inet->saddr;
newinet->rcv_saddr = inet->saddr;
newinet->dport = asoc->peer.port;
newinet->rcv_saddr = inet->rcv_saddr;
newinet->dport = htons(asoc->peer.port);
newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
newinet->pmtudisc = inet->pmtudisc;
newinet->id = 0;
newinet->ttl = sysctl_ip_default_ttl;
newinet->mc_loop = 1;
newinet->mc_ttl = 1;
......@@ -567,7 +583,7 @@ int sctp_ctl_sock_init(void)
if (sctp_get_pf_specific(PF_INET6))
family = PF_INET6;
else
else
family = PF_INET;
err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP,
......@@ -694,7 +710,7 @@ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
return sctp_v4_available(addr);
}
/* Verify that sockaddr looks sendable. Common verification has already
/* Verify that sockaddr looks sendable. Common verification has already
* been taken care of.
*/
static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
......@@ -705,7 +721,7 @@ static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
/* Fill in Supported Address Type information for INIT and INIT-ACK
* chunks. Returns number of addresses supported.
*/
static int sctp_inet_supported_addrs(const struct sctp_opt *opt,
static int sctp_inet_supported_addrs(const struct sctp_opt *opt,
__u16 *types)
{
types[0] = SCTP_PARAM_IPV4_ADDRESS;
......@@ -803,7 +819,8 @@ struct sctp_af sctp_ipv4_specific = {
.copy_addrlist = sctp_v4_copy_addrlist,
.from_skb = sctp_v4_from_skb,
.from_sk = sctp_v4_from_sk,
.to_sk = sctp_v4_to_sk,
.to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr,
.dst_saddr = sctp_v4_dst_saddr,
.cmp_addr = sctp_v4_cmp_addr,
.addr_valid = sctp_v4_addr_valid,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -53,11 +53,11 @@ static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)
/* Create a new sctp_ssnmap.
* Allocate room to store at least 'len' contiguous TSNs.
*/
struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int priority)
struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp)
{
struct sctp_ssnmap *retval;
retval = kmalloc(sctp_ssnmap_size(in, out), priority);
retval = kmalloc(sctp_ssnmap_size(in, out), gfp);
if (!retval)
goto fail;
......
......@@ -54,16 +54,15 @@
/* 1st Level Abstractions. */
/* Allocate and initialize a new transport. */
struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
int priority)
struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int gfp)
{
struct sctp_transport *transport;
transport = t_new(struct sctp_transport, priority);
transport = t_new(struct sctp_transport, gfp);
if (!transport)
goto fail;
if (!sctp_transport_init(transport, addr, priority))
if (!sctp_transport_init(transport, addr, gfp))
goto fail_init;
transport->malloced = 1;
......@@ -81,7 +80,7 @@ struct sctp_transport *sctp_transport_new(const union sctp_addr *addr,
/* Intialize a new transport from provided memory. */
struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
const union sctp_addr *addr,
int priority)
int gfp)
{
struct sctp_protocol *proto = sctp_get_protocol();
......@@ -199,13 +198,13 @@ void sctp_transport_reset_timers(struct sctp_transport *transport)
* Register the reference count in the association.
*/
void sctp_transport_set_owner(struct sctp_transport *transport,
sctp_association_t *asoc)
struct sctp_association *asoc)
{
transport->asoc = asoc;
sctp_association_hold(asoc);
}
/* Initialize the pmtu of a transport. */
/* Initialize the pmtu of a transport. */
void sctp_transport_pmtu(struct sctp_transport *transport)
{
struct dst_entry *dst;
......@@ -225,7 +224,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport)
void sctp_transport_route(struct sctp_transport *transport,
union sctp_addr *saddr, struct sctp_opt *opt)
{
sctp_association_t *asoc = transport->asoc;
struct sctp_association *asoc = transport->asoc;
struct sctp_af *af = transport->af_specific;
union sctp_addr *daddr = &transport->ipaddr;
struct dst_entry *dst;
......@@ -238,9 +237,15 @@ void sctp_transport_route(struct sctp_transport *transport,
af->get_saddr(asoc, dst, daddr, &transport->saddr);
transport->dst = dst;
if (dst)
if (dst) {
transport->pmtu = dst_pmtu(dst);
else
/* Initialize sk->rcv_saddr, if the transport is the
* association's active path for getsockname().
*/
if (asoc && (transport == asoc->peer.active_path))
af->to_sk_saddr(&transport->saddr, asoc->base.sk);
} else
transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;
}
......@@ -359,7 +364,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
* two conditions are met can the cwnd be increased otherwise
* the cwnd MUST not be increased. If these conditions are met
* then cwnd MUST be increased by at most the lesser of
* 1) the total size of the previously outstanding DATA
* 1) the total size of the previously outstanding DATA
* chunk(s) acknowledged, and 2) the destination's path MTU.
*/
if (bytes_acked > pmtu)
......@@ -373,17 +378,17 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
transport, bytes_acked, cwnd,
ssthresh, flight_size, pba);
} else {
/* RFC 2960 7.2.2 Whenever cwnd is greater than ssthresh,
* upon each SACK arrival that advances the Cumulative TSN Ack
* Point, increase partial_bytes_acked by the total number of
* bytes of all new chunks acknowledged in that SACK including
* chunks acknowledged by the new Cumulative TSN Ack and by
/* RFC 2960 7.2.2 Whenever cwnd is greater than ssthresh,
* upon each SACK arrival that advances the Cumulative TSN Ack
* Point, increase partial_bytes_acked by the total number of
* bytes of all new chunks acknowledged in that SACK including
* chunks acknowledged by the new Cumulative TSN Ack and by
* Gap Ack Blocks.
*
* When partial_bytes_acked is equal to or greater than cwnd
* and before the arrival of the SACK the sender had cwnd or
* more bytes of data outstanding (i.e., before arrival of the
* SACK, flightsize was greater than or equal to cwnd),
* When partial_bytes_acked is equal to or greater than cwnd
* and before the arrival of the SACK the sender had cwnd or
* more bytes of data outstanding (i.e., before arrival of the
* SACK, flightsize was greater than or equal to cwnd),
* increase cwnd by MTU, and reset partial_bytes_acked to
* (partial_bytes_acked - cwnd).
*/
......
......@@ -55,13 +55,12 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
/* Create a new sctp_tsnmap.
* Allocate room to store at least 'len' contiguous TSNs.
*/
struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int priority)
struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int gfp)
{
struct sctp_tsnmap *retval;
retval = kmalloc(sizeof(struct sctp_tsnmap) +
sctp_tsnmap_storage_size(len),
priority);
sctp_tsnmap_storage_size(len), gfp);
if (!retval)
goto fail;
......
......@@ -52,12 +52,12 @@ static void sctp_ulpevent_set_owner(struct sk_buff *skb,
const struct sctp_association *asoc);
/* Create a new sctp_ulpevent. */
struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int priority)
struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
{
struct sctp_ulpevent *event;
struct sk_buff *skb;
skb = alloc_skb(size, priority);
skb = alloc_skb(size, gfp);
if (!skb)
goto fail;
......@@ -106,16 +106,16 @@ int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event)
* zero'd out.
*/
struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
const sctp_association_t *asoc,
const struct sctp_association *asoc,
__u16 flags, __u16 state, __u16 error, __u16 outbound,
__u16 inbound, int priority)
__u16 inbound, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_assoc_change *sac;
struct sk_buff *skb;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, priority);
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
skb = sctp_event2skb(event);
......@@ -207,15 +207,16 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
* an interface details event is sent.
*/
struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
const sctp_association_t *asoc, const struct sockaddr_storage *aaddr,
int flags, int state, int error, int priority)
const struct sctp_association *asoc,
const struct sockaddr_storage *aaddr,
int flags, int state, int error, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_paddr_change *spc;
struct sk_buff *skb;
event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change),
MSG_NOTIFICATION, priority);
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
......@@ -315,8 +316,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
* error formats.
*/
struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
const sctp_association_t *asoc, sctp_chunk_t *chunk,
__u16 flags, int priority)
const struct sctp_association *asoc, sctp_chunk_t *chunk,
__u16 flags, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_remote_error *sre;
......@@ -338,7 +339,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
skb = skb_copy_expand(chunk->skb,
sizeof(struct sctp_remote_error), /* headroom */
0, /* tailroom */
priority);
gfp);
/* Pull off the rest of the cause TLV from the chunk. */
skb_pull(chunk->skb, elen);
......@@ -419,8 +420,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
* 5.3.1.4 SCTP_SEND_FAILED
*/
struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
const sctp_association_t *asoc, sctp_chunk_t *chunk,
__u16 flags, __u32 error, int priority)
const struct sctp_association *asoc, sctp_chunk_t *chunk,
__u16 flags, __u32 error, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_send_failed *ssf;
......@@ -430,7 +431,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
skb = skb_copy_expand(chunk->skb,
sizeof(struct sctp_send_failed), /* headroom */
0, /* tailroom */
priority);
gfp);
if (!skb)
goto fail;
......@@ -521,15 +522,15 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
* 5.3.1.5 SCTP_SHUTDOWN_EVENT
*/
struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
const sctp_association_t *asoc,
__u16 flags, int priority)
const struct sctp_association *asoc,
__u16 flags, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_shutdown_event *sse;
struct sk_buff *skb;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, priority);
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
......@@ -586,8 +587,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
* Socket Extensions for SCTP
* 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV)
*/
struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
sctp_chunk_t *chunk, int priority)
struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
sctp_chunk_t *chunk, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_sndrcvinfo *info;
......@@ -595,7 +596,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
size_t padding, len;
/* Clone the original skb, sharing the data. */
skb = skb_clone(chunk->skb, priority);
skb = skb_clone(chunk->skb, gfp);
if (!skb)
goto fail;
......@@ -631,7 +632,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
event->iif = sctp_chunk_iif(chunk);
/* Note: Not clearing the entire event struct as
* this is just a fragment of the real event. However,
* we still need to do rwnd accounting.
* we still need to do rwnd accounting.
*/
for (list = skb_shinfo(skb)->frag_list; list; list = list->next)
sctp_ulpevent_set_owner_r(list, asoc);
......@@ -690,16 +691,16 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
info->sinfo_flags |= MSG_UNORDERED;
/* sinfo_cumtsn: 32 bit (unsigned integer)
*
* This field will hold the current cumulative TSN as
* known by the underlying SCTP layer. Note this field is
* ignored when sending and only valid for a receive
*
* This field will hold the current cumulative TSN as
* known by the underlying SCTP layer. Note this field is
* ignored when sending and only valid for a receive
* operation when sinfo_flags are set to MSG_UNORDERED.
*/
info->sinfo_cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
}
/* Note: For reassembly, we need to have the fragmentation bits.
/* Note: For reassembly, we need to have the fragmentation bits.
* For now, merge these into the msg_flags, since those bit
* possitions are not used.
*/
......@@ -732,7 +733,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
return NULL;
}
/* Create a partial delivery related event.
/* Create a partial delivery related event.
*
* 5.3.1.7 SCTP_PARTIAL_DELIVERY_EVENT
*
......@@ -741,14 +742,14 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
* various events.
*/
struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
const sctp_association_t *asoc, __u32 indication, int priority)
const struct sctp_association *asoc, __u32 indication, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_rcv_pdapi_event *pd;
struct sk_buff *skb;
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, priority);
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
......@@ -780,7 +781,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
pd->pdapi_indication = indication;
/* pdapi_assoc_id: sizeof (sctp_assoc_t)
*
*
* The association id field, holds the identifier for the association.
*/
pd->pdapi_assoc_id = sctp_assoc2id(asoc);
......@@ -817,7 +818,7 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
/* Do accounting for bytes just read by user. */
static void sctp_rcvmsg_rfree(struct sk_buff *skb)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
struct sctp_ulpevent *event;
/* Current stack structures assume that the rcv buffer is
......@@ -834,7 +835,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
/* Charge receive window for bytes received. */
static void sctp_ulpevent_set_owner_r(struct sk_buff *skb,
sctp_association_t *asoc)
struct sctp_association *asoc)
{
struct sctp_ulpevent *event;
......
......@@ -57,11 +57,11 @@ static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *,
/* 1st Level Abstractions */
/* Create a new ULP queue. */
struct sctp_ulpq *sctp_ulpq_new(sctp_association_t *asoc, int priority)
struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp)
{
struct sctp_ulpq *ulpq;
ulpq = kmalloc(sizeof(struct sctp_ulpq), priority);
ulpq = kmalloc(sizeof(struct sctp_ulpq), gfp);
if (!ulpq)
goto fail;
if (!sctp_ulpq_init(ulpq, asoc))
......@@ -77,7 +77,7 @@ struct sctp_ulpq *sctp_ulpq_new(sctp_association_t *asoc, int priority)
/* Initialize a ULP queue from a block of memory. */
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
sctp_association_t *asoc)
struct sctp_association *asoc)
{
memset(ulpq, sizeof(struct sctp_ulpq), 0x00);
......@@ -119,7 +119,7 @@ void sctp_ulpq_free(struct sctp_ulpq *ulpq)
/* Process an incoming DATA chunk. */
int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, sctp_chunk_t *chunk,
int priority)
int gfp)
{
struct sk_buff_head temp;
sctp_data_chunk_t *hdr;
......@@ -128,7 +128,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, sctp_chunk_t *chunk,
hdr = (sctp_data_chunk_t *) chunk->chunk_hdr;
/* Create an event from the incoming chunk. */
event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, priority);
event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp);
if (!event)
return -ENOMEM;
......@@ -253,6 +253,21 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
tsn = event->sndrcvinfo.sinfo_tsn;
/* See if it belongs at the end. */
pos = skb_peek_tail(&ulpq->reasm);
if (!pos) {
__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
return;
}
/* Short circuit just dropping it at the end. */
cevent = sctp_skb2event(pos);
ctsn = cevent->sndrcvinfo.sinfo_tsn;
if (TSN_lt(ctsn, tsn)) {
__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
return;
}
/* Find the right place in this list. We store them by TSN. */
skb_queue_walk(&ulpq->reasm, pos) {
cevent = sctp_skb2event(pos);
......@@ -262,12 +277,9 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
break;
}
/* If the queue is empty, we have a different function to call. */
if (skb_peek(&ulpq->reasm))
__skb_insert(sctp_event2skb(event), pos->prev, pos,
&ulpq->reasm);
else
__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
/* Insert before pos. */
__skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->reasm);
}
/* Helper function to return an event corresponding to the reassembled
......@@ -592,8 +604,27 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
__u16 sid, csid;
__u16 ssn, cssn;
pos = skb_peek_tail(&ulpq->lobby);
if (!pos) {
__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
return;
}
sid = event->sndrcvinfo.sinfo_stream;
ssn = event->sndrcvinfo.sinfo_ssn;
cevent = (struct sctp_ulpevent *) pos->cb;
csid = cevent->sndrcvinfo.sinfo_stream;
cssn = cevent->sndrcvinfo.sinfo_ssn;
if (sid > csid) {
__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
return;
}
if ((sid == csid) && SSN_lt(cssn, ssn)) {
__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
return;
}
/* Find the right place in this list. We store them by
* stream ID and then by SSN.
......@@ -609,12 +640,10 @@ static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
break;
}
/* If the queue is empty, we have a different function to call. */
if (skb_peek(&ulpq->lobby))
__skb_insert(sctp_event2skb(event), pos->prev, pos,
&ulpq->lobby);
else
__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
/* Insert before pos. */
__skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->lobby);
}
static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
......@@ -705,7 +734,7 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)
/* Partial deliver the first message as there is pressure on rwnd. */
void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
struct sctp_chunk *chunk, int priority)
struct sctp_chunk *chunk, int gfp)
{
struct sctp_ulpevent *event;
struct sctp_association *asoc;
......@@ -729,7 +758,7 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
/* Renege some packets to make room for an incoming chunk. */
void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
int priority)
int gfp)
{
struct sctp_association *asoc;
__u16 needed, freed;
......@@ -755,9 +784,9 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
__u32 tsn;
tsn = ntohl(chunk->subh.data_hdr->tsn);
sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn);
sctp_ulpq_tail_data(ulpq, chunk, priority);
sctp_ulpq_tail_data(ulpq, chunk, gfp);
sctp_ulpq_partial_delivery(ulpq, chunk, priority);
sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
}
return;
......@@ -768,7 +797,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
/* Notify the application if an association is aborted and in
* partial delivery mode. Send up any pending received messages.
*/
void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, int priority)
void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, int gfp)
{
struct sctp_ulpevent *ev = NULL;
struct sock *sk;
......@@ -781,7 +810,7 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, int priority)
&sctp_sk(sk)->subscribe))
ev = sctp_ulpevent_make_pdapi(ulpq->asoc,
SCTP_PARTIAL_DELIVERY_ABORTED,
priority);
gfp);
if (ev)
__skb_queue_tail(&sk->receive_queue, sctp_event2skb(ev));
......
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