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

Merge nuts.ninka.net:/home/davem/src/BK/sctp-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents af3d7b0a ce1de957
...@@ -182,7 +182,7 @@ typedef struct { ...@@ -182,7 +182,7 @@ typedef struct {
/* Create a new sctp_command_sequence. /* Create a new sctp_command_sequence.
* Return NULL if creating a new sequence fails. * 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. /* Initialize a block of memory as a command sequence.
* Return 0 if the initialization fails. * Return 0 if the initialization fails.
......
...@@ -6,46 +6,42 @@ ...@@ -6,46 +6,42 @@
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This file is part of the implementation of the add-IP extension, * The SCTP reference implementation is free software;
* 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;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * 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 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * 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 one of the following email * Please send any bug reports or fixes you make to the
* addresses: * 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> * Written or modified by:
* Karl Knutson <karl@athena.chicago.il.us> * La Monte H.P. Yarroll <piggy@acm.org>
* Randall Stewart <randall@stewart.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com> * Randall Stewart <randall@stewart.chicago.il.us>
* Qiaobing Xie <qxie1@motorola.com> * Ken Morneau <kmorneau@cisco.com>
* Xingang Guo <xingang.guo@intel.com> * Qiaobing Xie <qxie1@motorola.com>
* Sridhar Samudrala <samudrala@us.ibm.com> * Xingang Guo <xingang.guo@intel.com>
* Daisy Chang <daisyc@us.ibm.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 * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*
* 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__ #ifndef __sctp_constants_h__
...@@ -220,7 +216,7 @@ typedef enum { ...@@ -220,7 +216,7 @@ typedef enum {
* - A socket in SCTP_SS_LISTENING state indicates that it is willing to * - A socket in SCTP_SS_LISTENING state indicates that it is willing to
* accept new associations, but cannot initiate the creation of new ones. * accept new associations, but cannot initiate the creation of new ones.
* - A socket in SCTP_SS_ESTABLISHED state indicates that it has a single * - A socket in SCTP_SS_ESTABLISHED state indicates that it has a single
* association in ESTABLISHED state. * association.
*/ */
typedef enum { typedef enum {
SCTP_SS_CLOSED = TCP_CLOSE, SCTP_SS_CLOSED = TCP_CLOSE,
...@@ -336,10 +332,18 @@ typedef enum { ...@@ -336,10 +332,18 @@ typedef enum {
#define SCTP_SIGNATURE_SIZE 20 /* size of a SLA-1 signature */ #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. * 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 /* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue. * routines which form the lower interface to SCTP_outqueue.
*/ */
......
...@@ -125,65 +125,61 @@ extern struct sctp_protocol sctp_proto; ...@@ -125,65 +125,61 @@ extern struct sctp_protocol sctp_proto;
extern struct sock *sctp_get_ctl_sock(void); extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(struct sctp_protocol *, extern int sctp_copy_local_addr_list(struct sctp_protocol *,
struct sctp_bind_addr *, 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 struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t); extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
/* /*
* sctp/socket.c * sctp/socket.c
*/ */
extern int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb); int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
extern int sctp_inet_listen(struct socket *sock, int backlog); int sctp_inet_listen(struct socket *sock, int backlog);
extern void sctp_write_space(struct sock *sk); void sctp_write_space(struct sock *sk);
extern unsigned int sctp_poll(struct file *file, struct socket *sock, unsigned int sctp_poll(struct file *file, struct socket *sock,
poll_table *wait); poll_table *wait);
/* /*
* sctp/primitive.c * sctp/primitive.c
*/ */
extern int sctp_primitive_ASSOCIATE(sctp_association_t *, void *arg); int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg);
extern int sctp_primitive_SHUTDOWN(sctp_association_t *, void *arg); int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg);
extern int sctp_primitive_ABORT(sctp_association_t *, void *arg); int sctp_primitive_ABORT(struct sctp_association *, void *arg);
extern int sctp_primitive_SEND(sctp_association_t *, void *arg); int sctp_primitive_SEND(struct sctp_association *, void *arg);
extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg); int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg);
/* /*
* sctp/crc32c.c * sctp/crc32c.c
*/ */
extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count); __u32 sctp_start_cksum(__u8 *ptr, __u16 count);
extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum); __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
extern __u32 sctp_end_cksum(__u32 cksum); __u32 sctp_end_cksum(__u32 cksum);
__u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
/* /*
* sctp/input.c * sctp/input.c
*/ */
extern int sctp_rcv(struct sk_buff *skb); int sctp_rcv(struct sk_buff *skb);
extern void sctp_v4_err(struct sk_buff *skb, u32 info); void sctp_v4_err(struct sk_buff *skb, u32 info);
extern void sctp_hash_established(sctp_association_t *); void sctp_hash_established(struct sctp_association *);
extern void __sctp_hash_established(sctp_association_t *); void __sctp_hash_established(struct sctp_association *);
extern void sctp_unhash_established(sctp_association_t *); void sctp_unhash_established(struct sctp_association *);
extern void __sctp_unhash_established(sctp_association_t *); void __sctp_unhash_established(struct sctp_association *);
extern void sctp_hash_endpoint(sctp_endpoint_t *); void sctp_hash_endpoint(struct sctp_endpoint *);
extern void __sctp_hash_endpoint(sctp_endpoint_t *); void __sctp_hash_endpoint(struct sctp_endpoint *);
extern void sctp_unhash_endpoint(sctp_endpoint_t *); void sctp_unhash_endpoint(struct sctp_endpoint *);
extern void __sctp_unhash_endpoint(sctp_endpoint_t *); void __sctp_unhash_endpoint(struct sctp_endpoint *);
extern sctp_association_t *__sctp_lookup_association(const union sctp_addr *, struct sctp_association *__sctp_lookup_association(
const union sctp_addr *, const union sctp_addr *,
struct sctp_transport **); const union sctp_addr *,
extern struct sock *sctp_err_lookup(int family, struct sk_buff *, struct sctp_transport **);
struct sctphdr *, struct sctp_endpoint **, struct sock *sctp_err_lookup(int family, struct sk_buff *,
struct sctp_association **, struct sctphdr *, struct sctp_endpoint **,
struct sctp_transport **); struct sctp_association **,
extern void sctp_err_finish(struct sock *, struct sctp_endpoint *, struct sctp_transport **);
void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct sctp_association *); struct sctp_association *);
extern void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu); 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 * Section: Macros, externs, and inlines
...@@ -281,6 +277,7 @@ extern atomic_t sctp_dbg_objcnt_chunk; ...@@ -281,6 +277,7 @@ extern atomic_t sctp_dbg_objcnt_chunk;
extern atomic_t sctp_dbg_objcnt_bind_addr; extern atomic_t sctp_dbg_objcnt_bind_addr;
extern atomic_t sctp_dbg_objcnt_addr; extern atomic_t sctp_dbg_objcnt_addr;
extern atomic_t sctp_dbg_objcnt_ssnmap; extern atomic_t sctp_dbg_objcnt_ssnmap;
extern atomic_t sctp_dbg_objcnt_datamsg;
/* Macros to atomically increment/decrement objcnt counters. */ /* Macros to atomically increment/decrement objcnt counters. */
#define SCTP_DBG_OBJCNT_INC(name) \ #define SCTP_DBG_OBJCNT_INC(name) \
...@@ -296,8 +293,8 @@ atomic_t sctp_dbg_objcnt_## name = ATOMIC_INIT(0) ...@@ -296,8 +293,8 @@ atomic_t sctp_dbg_objcnt_## name = ATOMIC_INIT(0)
#define SCTP_DBG_OBJCNT_ENTRY(name) \ #define SCTP_DBG_OBJCNT_ENTRY(name) \
{.label= #name, .counter= &sctp_dbg_objcnt_## name} {.label= #name, .counter= &sctp_dbg_objcnt_## name}
extern void sctp_dbg_objcnt_init(void); void sctp_dbg_objcnt_init(void);
extern void sctp_dbg_objcnt_exit(void); void sctp_dbg_objcnt_exit(void);
#else #else
...@@ -310,8 +307,8 @@ static inline void sctp_dbg_objcnt_exit(void) { return; } ...@@ -310,8 +307,8 @@ static inline void sctp_dbg_objcnt_exit(void) { return; }
#endif /* CONFIG_SCTP_DBG_OBJCOUNT */ #endif /* CONFIG_SCTP_DBG_OBJCOUNT */
#if defined CONFIG_SYSCTL #if defined CONFIG_SYSCTL
extern void sctp_sysctl_register(void); void sctp_sysctl_register(void);
extern void sctp_sysctl_unregister(void); void sctp_sysctl_unregister(void);
#else #else
static inline void sctp_sysctl_register(void) { return; } static inline void sctp_sysctl_register(void) { return; }
static inline void sctp_sysctl_unregister(void) { return; } static inline void sctp_sysctl_unregister(void) { return; }
...@@ -322,9 +319,9 @@ static inline void sctp_sysctl_unregister(void) { return; } ...@@ -322,9 +319,9 @@ static inline void sctp_sysctl_unregister(void) { return; }
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
extern int sctp_v6_init(void); int sctp_v6_init(void);
extern void sctp_v6_exit(void); void sctp_v6_exit(void);
extern void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info); int type, int code, int offset, __u32 info);
#else /* #ifdef defined(CONFIG_IPV6) */ #else /* #ifdef defined(CONFIG_IPV6) */
...@@ -334,15 +331,26 @@ static inline void sctp_v6_exit(void) { return; } ...@@ -334,15 +331,26 @@ static inline void sctp_v6_exit(void) { return; }
#endif /* #if defined(CONFIG_IPV6) */ #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. */ /* 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; return (sctp_assoc_t) asoc;
} }
/* Look up the association by its id. */ /* 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. */ /* A macro to walk a list of skbs. */
...@@ -422,12 +430,16 @@ static inline __s32 sctp_jitter(__u32 rto) ...@@ -422,12 +430,16 @@ static inline __s32 sctp_jitter(__u32 rto)
} }
/* Break down data chunks at this point. */ /* Break down data chunks at this point. */
static inline int sctp_frag_point(int pmtu) static inline int sctp_frag_point(const struct sctp_opt *sp, int pmtu)
{ {
pmtu -= SCTP_IP_OVERHEAD + sizeof(struct sctp_data_chunk); int frag = pmtu;
pmtu -= sizeof(struct sctp_sack_chunk); frag -= SCTP_IP_OVERHEAD + sizeof(struct sctp_data_chunk);
frag -= sizeof(struct sctp_sack_chunk);
return pmtu; if (sp->user_frag)
frag = min_t(int, frag, sp->user_frag);
return frag;
} }
/* Walk through a list of TLV parameters. Don't trust the /* Walk through a list of TLV parameters. Don't trust the
...@@ -475,7 +487,7 @@ static inline void tv_add(const struct timeval *entered, struct timeval *leaved) ...@@ -475,7 +487,7 @@ static inline void tv_add(const struct timeval *entered, struct timeval *leaved)
extern struct proto sctp_prot; extern struct proto sctp_prot;
extern struct proc_dir_entry *proc_net_sctp; extern struct proc_dir_entry *proc_net_sctp;
extern void sctp_put_port(struct sock *sk); void sctp_put_port(struct sock *sk);
/* Static inline functions. */ /* Static inline functions. */
...@@ -501,10 +513,10 @@ static inline int ipver2af(__u8 ipver) ...@@ -501,10 +513,10 @@ static inline int ipver2af(__u8 ipver)
/* Perform some sanity checks. */ /* Perform some sanity checks. */
static inline int sctp_sanity_check(void) 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), sizeof(((struct sk_buff *)0)->cb),
"SCTP: ulpevent does not fit in skb!\n", return 0); "SCTP: ulpevent does not fit in skb!\n", return 0);
return 1; return 1;
} }
...@@ -566,4 +578,26 @@ struct sctp6_sock { ...@@ -566,4 +578,26 @@ struct sctp6_sock {
#define sctp_sk(__sk) (&((struct sctp_sock *)__sk)->sctp) #define sctp_sk(__sk) (&((struct sctp_sock *)__sk)->sctp)
/* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
int static inline __sctp_style(const struct sock *sk, sctp_socket_type_t style)
{
return sctp_sk(sk)->type == 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,
sctp_state_t state)
{
return asoc->state == state;
}
/* Is the socket in this state? */
#define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state))
int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
{
return sk->state == state;
}
#endif /* __net_sctp_h__ */ #endif /* __net_sctp_h__ */
...@@ -6,10 +6,6 @@ ...@@ -6,10 +6,6 @@
* *
* This file is part of the SCTP kernel reference Implementation * 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.
*
* These are definitions needed by the state machine. * These are definitions needed by the state machine.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
...@@ -50,7 +46,6 @@ ...@@ -50,7 +46,6 @@
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -81,8 +76,8 @@ typedef struct { ...@@ -81,8 +76,8 @@ typedef struct {
int action; int action;
} sctp_sm_command_t; } sctp_sm_command_t;
typedef sctp_disposition_t (sctp_state_fn_t) (const sctp_endpoint_t *, typedef sctp_disposition_t (sctp_state_fn_t) (const struct sctp_endpoint *,
const sctp_association_t *, const struct sctp_association *,
const sctp_subtype_t type, const sctp_subtype_t type,
void *arg, void *arg,
sctp_cmd_seq_t *); sctp_cmd_seq_t *);
...@@ -209,109 +204,104 @@ __u32 sctp_generate_verification_tag(void); ...@@ -209,109 +204,104 @@ __u32 sctp_generate_verification_tag(void);
void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag); void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
/* Prototypes for chunk-building functions. */ /* Prototypes for chunk-building functions. */
sctp_chunk_t *sctp_make_init(const sctp_association_t *, struct sctp_chunk *sctp_make_init(const struct sctp_association *,
const sctp_bind_addr_t *, const struct sctp_bind_addr *,
int priority, int vparam_len); int gfp, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *, struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const int priority, const int gfp,
const int unkparam_len); const int unkparam_len);
sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *, struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *, struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_cwr(const sctp_association_t *, struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
const __u32 lowest_tsn, const __u32 lowest_tsn,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_datafrag(sctp_association_t *, struct sctp_chunk *sctp_make_datafrag(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 *data, int len, const __u8 *data,
__u8 flags, __u16 ssn); __u8 flags, __u16 ssn);
sctp_chunk_t * sctp_make_datafrag_empty(sctp_association_t *, struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 flags, int len, const __u8 flags,
__u16 ssn); __u16 ssn);
sctp_chunk_t *sctp_make_data(sctp_association_t *, struct sctp_chunk *sctp_make_data(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 *data); int len, const __u8 *data);
sctp_chunk_t *sctp_make_data_empty(sctp_association_t *, struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *, int len); const struct sctp_sndrcvinfo *, int len);
sctp_chunk_t *sctp_make_ecne(const sctp_association_t *, struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
const __u32); const __u32);
sctp_chunk_t *sctp_make_sack(const sctp_association_t *); struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc); struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc);
sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc, struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const sctp_chunk_t *); const struct sctp_chunk *);
sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *, struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
const sctp_chunk_t *); const struct sctp_chunk *);
void sctp_init_cause(sctp_chunk_t *, __u16 cause, const void *, size_t); void sctp_init_cause(struct sctp_chunk *, __u16 cause, const void *, size_t);
sctp_chunk_t *sctp_make_abort(const sctp_association_t *, struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const size_t hint); const size_t hint);
sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *, struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
__u32 tsn); __u32 tsn);
sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *, struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const struct msghdr *); const struct msghdr *);
sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *, struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *, const struct sctp_transport *,
const void *payload, const void *payload,
const size_t paylen); const size_t paylen);
sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *, struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
const sctp_chunk_t *, const struct sctp_chunk *,
const void *payload, const void *payload,
const size_t paylen); const size_t paylen);
sctp_chunk_t *sctp_make_op_error(const sctp_association_t *, struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
const sctp_chunk_t *chunk, const struct sctp_chunk *chunk,
__u16 cause_code, __u16 cause_code,
const void *payload, const void *payload,
size_t paylen); size_t paylen);
void sctp_chunk_assign_tsn(sctp_chunk_t *); void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(sctp_chunk_t *); void sctp_chunk_assign_ssn(struct sctp_chunk *);
int sctp_datachunks_from_user(sctp_association_t *,
const struct sctp_sndrcvinfo *,
struct msghdr *, int len,
struct sk_buff_head *);
/* Prototypes for statetable processing. */ /* Prototypes for statetable processing. */
int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state, sctp_state_t state,
sctp_endpoint_t *, struct sctp_endpoint *,
sctp_association_t *asoc, struct sctp_association *asoc,
void *event_arg, void *event_arg,
int priority); int gfp);
int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state, sctp_state_t state,
sctp_endpoint_t *, struct sctp_endpoint *,
sctp_association_t *asoc, struct sctp_association *asoc,
void *event_arg, void *event_arg,
sctp_disposition_t status, sctp_disposition_t status,
sctp_cmd_seq_t *commands, sctp_cmd_seq_t *commands,
int priority); int gfp);
/* 2nd level prototypes */ /* 2nd level prototypes */
int int
sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_state_t state, sctp_state_t state,
sctp_endpoint_t *ep, struct sctp_endpoint *ep,
sctp_association_t *asoc, struct sctp_association *asoc,
void *event_arg, void *event_arg,
sctp_disposition_t status, sctp_disposition_t status,
sctp_cmd_seq_t *retval, sctp_cmd_seq_t *retval,
int priority); int gfp);
int sctp_gen_sack(sctp_association_t *, int force, sctp_cmd_seq_t *); int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
void sctp_do_TSNdup(sctp_association_t *, sctp_chunk_t *, long gap); void sctp_do_TSNdup(struct sctp_association *, struct sctp_chunk *, long gap);
void sctp_generate_t3_rtx_event(unsigned long peer); void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer); void sctp_generate_heartbeat_event(unsigned long peer);
sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *); sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *);
struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *, struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *,
const struct sctp_association *, const struct sctp_association *,
struct sctp_chunk *chunk, struct sctp_chunk *chunk,
...@@ -325,21 +315,21 @@ sctp_cookie_param_t * ...@@ -325,21 +315,21 @@ sctp_cookie_param_t *
sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *, sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
const struct sctp_chunk *, int *cookie_len, const struct sctp_chunk *, int *cookie_len,
const __u8 *, int addrs_len); const __u8 *, int addrs_len);
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *, struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
const sctp_association_t *, const struct sctp_association *,
sctp_chunk_t *, int priority, int *err, struct sctp_chunk *, int gfp, int *err,
sctp_chunk_t **err_chk_p); struct sctp_chunk **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); struct sockaddr_storage*, int);
void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep, void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
const sctp_association_t *asoc, const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const struct sctp_chunk *chunk,
sctp_cmd_seq_t *commands, sctp_cmd_seq_t *commands,
sctp_chunk_t *err_chunk); struct sctp_chunk *err_chunk);
/* 3rd level prototypes */ /* 3rd level prototypes */
__u32 sctp_generate_tag(const sctp_endpoint_t *); __u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const sctp_endpoint_t *); __u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* 4th level prototypes */ /* 4th level prototypes */
void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *, void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *,
...@@ -361,7 +351,7 @@ extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES]; ...@@ -361,7 +351,7 @@ extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
/* Get the size of a DATA chunk payload. */ /* Get the size of a DATA chunk payload. */
static inline __u16 sctp_data_size(sctp_chunk_t *chunk) static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
{ {
__u16 size; __u16 size;
...@@ -449,8 +439,8 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a ...@@ -449,8 +439,8 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a
* tag and the T bit is set in the Chunk Flags. * tag and the T bit is set in the Chunk Flags.
*/ */
static inline int static inline int
sctp_vtag_verify_either(const sctp_chunk_t *chunk, sctp_vtag_verify_either(const struct sctp_chunk *chunk,
const sctp_association_t *asoc) const struct sctp_association *asoc)
{ {
/* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2 /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
* *
......
This diff is collapsed.
...@@ -114,7 +114,7 @@ struct sctp_tsnmap_iter { ...@@ -114,7 +114,7 @@ struct sctp_tsnmap_iter {
}; };
/* Create a new tsnmap. */ /* 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. */ /* Dispose of a tsnmap. */
void sctp_tsnmap_free(struct sctp_tsnmap *); void sctp_tsnmap_free(struct sctp_tsnmap *);
......
...@@ -10,13 +10,15 @@ ...@@ -10,13 +10,15 @@
* sctp_ulpevent type is used to carry information from the state machine * sctp_ulpevent type is used to carry information from the state machine
* upwards to the ULP. * 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 * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * 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 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
...@@ -27,12 +29,17 @@ ...@@ -27,12 +29,17 @@
* the Free Software Foundation, 59 Temple Place - Suite 330, * 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 one of the * Please send any bug reports or fixes you make to the
* following email addresses: * 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> * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * Jon Grimm <jgrimm@us.ibm.com>
* Karl Knutson <karl@athena.chicago.il.us> * 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 * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -64,7 +71,7 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb) ...@@ -64,7 +71,7 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
return (struct sctp_ulpevent *)skb->cb; 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); struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
void sctp_ulpevent_free(struct sctp_ulpevent *); void sctp_ulpevent_free(struct sctp_ulpevent *);
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *); int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
...@@ -76,7 +83,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( ...@@ -76,7 +83,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change(
__u16 error, __u16 error,
__u16 outbound, __u16 outbound,
__u16 inbound, __u16 inbound,
int priority); int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
const struct sctp_association *asoc, const struct sctp_association *asoc,
...@@ -84,32 +91,32 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( ...@@ -84,32 +91,32 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
int flags, int flags,
int state, int state,
int error, int error,
int priority); int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_remote_error( struct sctp_ulpevent *sctp_ulpevent_make_remote_error(
const struct sctp_association *asoc, const struct sctp_association *asoc,
struct sctp_chunk *chunk, struct sctp_chunk *chunk,
__u16 flags, __u16 flags,
int priority); int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_send_failed( struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
const struct sctp_association *asoc, const struct sctp_association *asoc,
struct sctp_chunk *chunk, struct sctp_chunk *chunk,
__u16 flags, __u16 flags,
__u32 error, __u32 error,
int priority); int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event( struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
const struct sctp_association *asoc, const struct sctp_association *asoc,
__u16 flags, __u16 flags,
int priority); int gfp);
struct sctp_ulpevent *sctp_ulpevent_make_pdapi( struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
const struct sctp_association *asoc, 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_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
struct sctp_chunk *chunk, struct sctp_chunk *chunk,
int priority); int gfp);
void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
struct msghdr *); struct msghdr *);
......
...@@ -50,14 +50,15 @@ ...@@ -50,14 +50,15 @@
struct sctp_ulpq { struct sctp_ulpq {
char malloced; char malloced;
char pd_mode; char pd_mode;
sctp_association_t *asoc; struct sctp_association *asoc;
struct sk_buff_head reasm; struct sk_buff_head reasm;
struct sk_buff_head lobby; struct sk_buff_head lobby;
}; };
/* Prototypes. */ /* Prototypes. */
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 *sctp_ulpq_init(struct sctp_ulpq *, sctp_association_t *); struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *,
struct sctp_association *);
void sctp_ulpq_free(struct sctp_ulpq *); void sctp_ulpq_free(struct sctp_ulpq *);
/* Add a new DATA chunk for processing. */ /* Add a new DATA chunk for processing. */
......
...@@ -110,6 +110,10 @@ enum sctp_optname { ...@@ -110,6 +110,10 @@ enum sctp_optname {
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
SCTP_NODELAY, /* Get/set nodelay option. */ SCTP_NODELAY, /* Get/set nodelay option. */
#define SCTP_NODELAY SCTP_NODELAY #define SCTP_NODELAY SCTP_NODELAY
SCTP_I_WANT_MAPPED_V4_ADDR, /* Turn on/off mapped v4 addresses */
#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR
SCTP_MAXSEG, /* Get/set maximum fragment. */
#define SCTP_MAXSEG SCTP_MAXSEG
}; };
......
...@@ -43,12 +43,12 @@ config SCTP_ADLER32 ...@@ -43,12 +43,12 @@ config SCTP_ADLER32
bool "SCTP: Use old checksum (Adler-32)" bool "SCTP: Use old checksum (Adler-32)"
depends on IP_SCTP depends on IP_SCTP
help 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 This has been deprecated and replaced by an algorithm now referred
to as crc32c. to as crc32c.
If you say Y, this will use the Adler-32 algorithm, this might be useful If you say Y, this will use the Adler-32 algorithm, this might be
for interoperation with downlevel peers. useful for interoperation with downlevel peers.
If unsure, say N. If unsure, say N.
...@@ -58,19 +58,46 @@ config SCTP_DBG_MSG ...@@ -58,19 +58,46 @@ config SCTP_DBG_MSG
help help
If you say Y, this will enable verbose debugging messages. If you say Y, this will enable verbose debugging messages.
If unsure, say N. However, if you are running into problems, use this If unsure, say N. However, if you are running into problems, use
option to gather detailed trace information this option to gather detailed trace information
config SCTP_DBG_OBJCNT config SCTP_DBG_OBJCNT
bool "SCTP: Debug object counts" bool "SCTP: Debug object counts"
depends on IP_SCTP depends on IP_SCTP
help help
If you say Y, this will enable debugging support for counting the types If you say Y, this will enable debugging support for counting the
of objects that are currently allocated. This is useful for identifying type of objects that are currently allocated. This is useful for
memory leaks. If the /proc filesystem is enabled this debug information identifying memory leaks. If the /proc filesystem is enabled this
can be viewed by 'cat /proc/net/sctp/sctp_dbg_objcnt' debug information can be viewed by
'cat /proc/net/sctp/sctp_dbg_objcnt'
If unsure, say N 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
...@@ -6,11 +6,10 @@ obj-$(CONFIG_IP_SCTP) += sctp.o ...@@ -6,11 +6,10 @@ obj-$(CONFIG_IP_SCTP) += sctp.o
sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
protocol.o endpointola.o associola.o \ protocol.o endpointola.o associola.o \
transport.o sm_make_chunk.o ulpevent.o \ transport.o chunk.o sm_make_chunk.o ulpevent.o \
inqueue.o outqueue.o ulpqueue.o command.o \ inqueue.o outqueue.o ulpqueue.o command.o \
tsnmap.o bind_addr.o socket.o primitive.o \ tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o hashdriver.o sla1.o \ output.o input.o debug.o ssnmap.o proc.o
debug.o ssnmap.o proc.o
ifeq ($(CONFIG_SCTP_ADLER32), y) ifeq ($(CONFIG_SCTP_ADLER32), y)
sctp-y += adler32.o sctp-y += adler32.o
......
...@@ -2,43 +2,43 @@ ...@@ -2,43 +2,43 @@
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2003 International Business Machines, Corp. * Copyright (c) 2003 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * 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 * implementation by R. Stewart, et al. These functions implement the
* Adler-32 algorithm as specified by RFC 2960. * Adler-32 algorithm as specified by RFC 2960.
* *
* 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 * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * 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 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * 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 * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* Randall Stewart <rstewar1@email.mot.com> * Randall Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com> * Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com> * Qiaobing Xie <qxie1@email.mot.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
* tad, but I have commented the original lines below * tad, but I have commented the original lines below
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#define BASE 65521 /* largest prime smaller than 65536 */ #define BASE 65521 /* largest prime smaller than 65536 */
...@@ -111,7 +111,7 @@ unsigned long update_adler32(unsigned long adler, ...@@ -111,7 +111,7 @@ unsigned long update_adler32(unsigned long adler,
* This would then be (2 * BASE) - 2, which * This would then be (2 * BASE) - 2, which
* will still only do one subtract. On Intel * will still only do one subtract. On Intel
* this is much better to do this way and * 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. * sparc.
*/ */
if (s2 >= BASE) { if (s2 >= BASE) {
...@@ -135,7 +135,7 @@ __u32 sctp_start_cksum(__u8 *ptr, __u16 count) ...@@ -135,7 +135,7 @@ __u32 sctp_start_cksum(__u8 *ptr, __u16 count)
__u32 zero = 0L; __u32 zero = 0L;
/* Calculate the CRC up to the checksum field. */ /* Calculate the CRC up to the checksum field. */
adler = update_adler32(adler, ptr, adler = update_adler32(adler, ptr,
sizeof(struct sctphdr) - sizeof(__u32)); sizeof(struct sctphdr) - sizeof(__u32));
/* Skip over the checksum field. */ /* Skip over the checksum field. */
adler = update_adler32(adler, (unsigned char *) &zero, adler = update_adler32(adler, (unsigned char *) &zero,
...@@ -156,6 +156,15 @@ __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler) ...@@ -156,6 +156,15 @@ __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler)
return 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) __u32 sctp_end_cksum(__u32 adler)
{ {
return adler; return adler;
......
This diff is collapsed.
...@@ -52,16 +52,17 @@ ...@@ -52,16 +52,17 @@
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */ /* Forward declarations for internal helpers. */
static int sctp_copy_one_addr(sctp_bind_addr_t *, union sctp_addr *, static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
sctp_scope_t scope, int gfp, int flags); sctp_scope_t scope, int gfp, int flags);
static void sctp_bind_addr_clean(sctp_bind_addr_t *); static void sctp_bind_addr_clean(struct sctp_bind_addr *);
/* First Level Abstractions. */ /* First Level Abstractions. */
/* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses
* in 'src' which have a broader scope than 'scope'. * in 'src' which have a broader scope than 'scope'.
*/ */
int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, int gfp, int flags) sctp_scope_t scope, int gfp, int flags)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
...@@ -80,6 +81,22 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, ...@@ -80,6 +81,22 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
goto out; 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: out:
if (error) if (error)
sctp_bind_addr_clean(dest); sctp_bind_addr_clean(dest);
...@@ -88,11 +105,11 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, ...@@ -88,11 +105,11 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
} }
/* Create a new SCTP_bind_addr from nothing. */ /* Create a new SCTP_bind_addr from nothing. */
sctp_bind_addr_t *sctp_bind_addr_new(int gfp) struct sctp_bind_addr *sctp_bind_addr_new(int gfp)
{ {
sctp_bind_addr_t *retval; struct sctp_bind_addr *retval;
retval = t_new(sctp_bind_addr_t, gfp); retval = t_new(struct sctp_bind_addr, gfp);
if (!retval) if (!retval)
goto nomem; goto nomem;
...@@ -107,7 +124,7 @@ sctp_bind_addr_t *sctp_bind_addr_new(int gfp) ...@@ -107,7 +124,7 @@ sctp_bind_addr_t *sctp_bind_addr_new(int gfp)
/* Initialize the SCTP_bind_addr structure for either an endpoint or /* Initialize the SCTP_bind_addr structure for either an endpoint or
* an association. * an association.
*/ */
void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port) void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
{ {
bp->malloced = 0; bp->malloced = 0;
...@@ -116,7 +133,7 @@ void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port) ...@@ -116,7 +133,7 @@ void sctp_bind_addr_init(sctp_bind_addr_t *bp, __u16 port)
} }
/* Dispose of the address list. */ /* Dispose of the address list. */
static void sctp_bind_addr_clean(sctp_bind_addr_t *bp) static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
struct list_head *pos, *temp; struct list_head *pos, *temp;
...@@ -131,7 +148,7 @@ static void sctp_bind_addr_clean(sctp_bind_addr_t *bp) ...@@ -131,7 +148,7 @@ static void sctp_bind_addr_clean(sctp_bind_addr_t *bp)
} }
/* Dispose of an SCTP_bind_addr structure */ /* Dispose of an SCTP_bind_addr structure */
void sctp_bind_addr_free(sctp_bind_addr_t *bp) void sctp_bind_addr_free(struct sctp_bind_addr *bp)
{ {
/* Empty the bind address list. */ /* Empty the bind address list. */
sctp_bind_addr_clean(bp); sctp_bind_addr_clean(bp);
...@@ -143,7 +160,7 @@ void sctp_bind_addr_free(sctp_bind_addr_t *bp) ...@@ -143,7 +160,7 @@ void sctp_bind_addr_free(sctp_bind_addr_t *bp)
} }
/* Add an address to the bind address list in the SCTP_bind_addr structure. */ /* Add an address to the bind address list in the SCTP_bind_addr structure. */
int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new, int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
int gfp) int gfp)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
...@@ -171,7 +188,7 @@ int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new, ...@@ -171,7 +188,7 @@ int sctp_add_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *new,
/* Delete an address from the bind address list in the SCTP_bind_addr /* Delete an address from the bind address list in the SCTP_bind_addr
* structure. * structure.
*/ */
int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
{ {
struct list_head *pos, *temp; struct list_head *pos, *temp;
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
...@@ -196,7 +213,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) ...@@ -196,7 +213,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr)
* *
* The second argument is the return value for the length. * The second argument is the return value for the length.
*/ */
union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
int *addrs_len, int gfp) int *addrs_len, int gfp)
{ {
union sctp_params addrparms; union sctp_params addrparms;
...@@ -214,6 +231,14 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, ...@@ -214,6 +231,14 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
len += sizeof(sctp_addr_param_t); 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); retval.v = kmalloc(len, gfp);
if (!retval.v) if (!retval.v)
goto end_raw; goto end_raw;
...@@ -237,7 +262,7 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, ...@@ -237,7 +262,7 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
* Create an address list out of the raw address list format (IPv4 and IPv6 * Create an address list out of the raw address list format (IPv4 and IPv6
* address parameters). * address parameters).
*/ */
int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
int addrs_len, __u16 port, int gfp) int addrs_len, __u16 port, int gfp)
{ {
sctp_addr_param_t *rawaddr; sctp_addr_param_t *rawaddr;
...@@ -283,7 +308,8 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, ...@@ -283,7 +308,8 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
********************************************************************/ ********************************************************************/
/* Does this contain a specified address? Allow wildcarding. */ /* Does this contain a specified address? Allow wildcarding. */
int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, int sctp_bind_addr_match(struct sctp_bind_addr *bp,
const union sctp_addr *addr,
struct sctp_opt *opt) struct sctp_opt *opt)
{ {
struct sockaddr_storage_list *laddr; struct sockaddr_storage_list *laddr;
...@@ -299,7 +325,8 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr, ...@@ -299,7 +325,8 @@ int sctp_bind_addr_match(sctp_bind_addr_t *bp, const union sctp_addr *addr,
} }
/* Copy out addresses from the global local address list. */ /* Copy out addresses from the global local address list. */
static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr, static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
union sctp_addr *addr,
sctp_scope_t scope, int gfp, int flags) sctp_scope_t scope, int gfp, int flags)
{ {
struct sctp_protocol *proto = sctp_get_protocol(); struct sctp_protocol *proto = sctp_get_protocol();
......
/* SCTP kernel reference Implementation
* Copyright (c) 2003 International Business Machines Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
* This file contains the code relating the the chunk abstraction.
*
* 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:
* Jon Grimm <jgrimm@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.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* This file is mostly in anticipation of future work, but initially
* populate with fragment tracking for an outbound message.
*/
/* Initialize datamsg from memory. */
void sctp_datamsg_init(struct sctp_datamsg *msg)
{
atomic_set(&msg->refcnt, 1);
msg->send_failed = 0;
msg->send_error = 0;
msg->can_expire = 0;
INIT_LIST_HEAD(&msg->chunks);
}
/* Allocate and initialize datamsg. */
struct sctp_datamsg *sctp_datamsg_new(int gfp)
{
struct sctp_datamsg *msg;
msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
if (msg)
sctp_datamsg_init(msg);
SCTP_DBG_OBJCNT_INC(datamsg);
return msg;
}
/* Final destructruction of datamsg memory. */
static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
{
struct list_head *pos, *temp;
struct sctp_chunk *chunk;
struct sctp_opt *sp;
struct sctp_ulpevent *ev;
struct sctp_association *asoc = NULL;
int error = 0, notify;
/* If we failed, we may need to notify. */
notify = msg->send_failed ? -1 : 0;
/* Release all references. */
list_for_each_safe(pos, temp, &msg->chunks) {
list_del(pos);
chunk = list_entry(pos, struct sctp_chunk, frag_list);
/* Check whether we _really_ need to notify. */
if (notify < 0) {
asoc = chunk->asoc;
if (msg->send_error)
error = msg->send_error;
else
error = asoc->outqueue.error;
sp = sctp_sk(asoc->base.sk);
notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED,
&sp->subscribe);
}
/* Generate a SEND FAILED event only if enabled. */
if (notify > 0) {
int sent;
if (chunk->has_tsn)
sent = SCTP_DATA_SENT;
else
sent = SCTP_DATA_UNSENT;
ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent,
error, GFP_ATOMIC);
if (ev)
sctp_ulpq_tail_event(&asoc->ulpq, ev);
}
sctp_chunk_put(chunk);
}
SCTP_DBG_OBJCNT_DEC(datamsg);
kfree(msg);
}
/* Hold a reference. */
void sctp_datamsg_hold(struct sctp_datamsg *msg)
{
atomic_inc(&msg->refcnt);
}
/* Release a reference. */
void sctp_datamsg_put(struct sctp_datamsg *msg)
{
if (atomic_dec_and_test(&msg->refcnt))
sctp_datamsg_destroy(msg);
}
/* Free a message. Really just give up a reference, the
* really free happens in sctp_datamsg_destroy().
*/
void sctp_datamsg_free(struct sctp_datamsg *msg)
{
sctp_datamsg_put(msg);
}
/* Hold on to all the fragments until all chunks have been sent. */
void sctp_datamsg_track(struct sctp_chunk *chunk)
{
sctp_chunk_hold(chunk);
}
/* Assign a chunk to this datamsg. */
void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
{
sctp_datamsg_hold(msg);
chunk->msg = msg;
}
/* A data chunk can have a maximum payload of (2^16 - 20). Break
* down any such message into smaller chunks. Opportunistically, fragment
* the chunks down to the current MTU constraints. We may get refragmented
* later if the PMTU changes, but it is _much better_ to fragment immediately
* with a reasonable guess than always doing our fragmentation on the
* soft-interrupt.
*/
struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct sctp_sndrcvinfo *sinfo,
struct msghdr *msgh, int msg_len)
{
int max, whole, i, offset, over, err;
int len, first_len;
struct sctp_chunk *chunk;
struct sctp_datamsg *msg;
struct list_head *pos, *temp;
__u8 frag;
msg = sctp_datamsg_new(GFP_KERNEL);
if (!msg)
return NULL;
/* Note: Calculate this outside of the loop, so that all fragments
* have the same expiration.
*/
if (sinfo->sinfo_timetolive) {
struct timeval tv;
__u32 ttl = sinfo->sinfo_timetolive;
/* sinfo_timetolive is in milliseconds */
tv.tv_sec = ttl / 1000;
tv.tv_usec = ttl % 1000 * 1000;
msg->expires_at = jiffies + timeval_to_jiffies(&tv);
msg->can_expire = 1;
}
/* What is a reasonable fragmentation point right now? */
max = asoc->pmtu;
if (max < SCTP_MIN_PMTU)
max = SCTP_MIN_PMTU;
max -= SCTP_IP_OVERHEAD;
/* Make sure not beyond maximum chunk size. */
if (max > SCTP_MAX_CHUNK_LEN)
max = SCTP_MAX_CHUNK_LEN;
/* Subtract out the overhead of a data chunk header. */
max -= sizeof(struct sctp_data_chunk);
whole = 0;
/* If user has specified smaller fragmentation, make it so. */
if (sctp_sk(asoc->base.sk)->user_frag)
max = min_t(int, max, sctp_sk(asoc->base.sk)->user_frag);
first_len = max;
/* Encourage Cookie-ECHO bundling. */
if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);
/* Account for the DATA to be bundled with the COOKIE-ECHO. */
if (whole) {
first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
msg_len -= first_len;
whole = 1;
}
}
/* How many full sized? How many bytes leftover? */
whole += msg_len / max;
over = msg_len % max;
offset = 0;
if ((whole > 1) || (whole && over))
SCTP_INC_STATS_USER(SctpFragUsrMsgs);
/* Create chunks for all the full sized DATA chunks. */
for (i=0, len=first_len; i < whole; i++) {
frag = SCTP_DATA_MIDDLE_FRAG;
if (0 == i)
frag |= SCTP_DATA_FIRST_FRAG;
if ((i == (whole - 1)) && !over)
frag |= SCTP_DATA_LAST_FRAG;
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
if (!chunk)
goto errout;
err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
if (err < 0)
goto errout;
offset += len;
/* Put the chunk->skb back into the form expected by send. */
__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
- (__u8 *)chunk->skb->data);
sctp_datamsg_assign(msg, chunk);
list_add_tail(&chunk->frag_list, &msg->chunks);
/* The first chunk, the first chunk was likely short
* to allow bundling, so reset to full size.
*/
if (0 == i)
len = max;
}
/* .. now the leftover bytes. */
if (over) {
if (!whole)
frag = SCTP_DATA_NOT_FRAG;
else
frag = SCTP_DATA_LAST_FRAG;
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
if (!chunk)
goto errout;
err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
/* Put the chunk->skb back into the form expected by send. */
__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
- (__u8 *)chunk->skb->data);
if (err < 0)
goto errout;
sctp_datamsg_assign(msg, chunk);
list_add_tail(&chunk->frag_list, &msg->chunks);
}
return msg;
errout:
list_for_each_safe(pos, temp, &msg->chunks) {
list_del(pos);
chunk = list_entry(pos, struct sctp_chunk, frag_list);
sctp_chunk_free(chunk);
}
sctp_datamsg_free(msg);
return NULL;
}
/* Check whether this message has expired. */
int sctp_datamsg_expires(struct sctp_chunk *chunk)
{
struct sctp_datamsg *msg = chunk->msg;
/* FIXME: When PR-SCTP is supported we can make this
* check more lenient.
*/
if (!msg->can_expire)
return 0;
if (time_after(jiffies, msg->expires_at))
return 1;
return 0;
}
/* This chunk (and consequently entire message) has failed in its sending. */
void sctp_datamsg_fail(struct sctp_chunk *chunk, int error)
{
chunk->msg->send_failed = 1;
chunk->msg->send_error = error;
}
...@@ -43,9 +43,9 @@ ...@@ -43,9 +43,9 @@
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Create a new sctp_command_sequence. */ /* 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) if (retval)
sctp_init_cmd_seq(retval); sctp_init_cmd_seq(retval);
......
...@@ -170,6 +170,23 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32) ...@@ -170,6 +170,23 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
return 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 sctp_end_cksum(__u32 crc32)
{ {
__u32 result; __u32 result;
......
...@@ -54,27 +54,27 @@ ...@@ -54,27 +54,27 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/random.h> /* get_random_bytes() */ #include <linux/random.h> /* get_random_bytes() */
#include <linux/crypto.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */ /* 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. * Returns NULL if there isn't enough memory.
*/ */
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto, struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
struct sock *sk, int priority)
{ {
sctp_endpoint_t *ep; struct sctp_endpoint *ep;
/* Build a local endpoint. */ /* Build a local endpoint. */
ep = t_new(sctp_endpoint_t, priority); ep = t_new(struct sctp_endpoint, gfp);
if (!ep) if (!ep)
goto fail; goto fail;
if (!sctp_endpoint_init(ep, proto, sk, priority)) if (!sctp_endpoint_init(ep, sk, gfp))
goto fail_init; goto fail_init;
ep->base.malloced = 1; ep->base.malloced = 1;
SCTP_DBG_OBJCNT_INC(ep); SCTP_DBG_OBJCNT_INC(ep);
...@@ -89,12 +89,11 @@ sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto, ...@@ -89,12 +89,11 @@ sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
/* /*
* Initialize the base fields of the endpoint structure. * Initialize the base fields of the endpoint structure.
*/ */
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
struct sctp_protocol *proto, struct sock *sk, int gfp)
struct sock *sk, int priority)
{ {
struct sctp_opt *sp = sctp_sk(sk); 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. */ /* Initialize the base structure. */
/* What type of endpoint are we? */ /* What type of endpoint are we? */
...@@ -110,8 +109,7 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, ...@@ -110,8 +109,7 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
/* Set its top-half handler */ /* Set its top-half handler */
sctp_inq_set_th_handler(&ep->base.inqueue, sctp_inq_set_th_handler(&ep->base.inqueue,
(void (*)(void *))sctp_endpoint_bh_rcv, (void (*)(void *))sctp_endpoint_bh_rcv, ep);
ep);
/* Initialize the bind addr area */ /* Initialize the bind addr area */
sctp_bind_addr_init(&ep->base.bind_addr, 0); sctp_bind_addr_init(&ep->base.bind_addr, 0);
...@@ -121,21 +119,16 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, ...@@ -121,21 +119,16 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->base.sk = sk; ep->base.sk = sk;
sock_hold(ep->base.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. */ /* Create the lists of associations. */
INIT_LIST_HEAD(&ep->asocs); INIT_LIST_HEAD(&ep->asocs);
/* Set up the base timeout information. */ /* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0; 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; SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
SCTP_DEFAULT_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; sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
...@@ -146,11 +139,11 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, ...@@ -146,11 +139,11 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD] ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
= 5 * sp->rtoinfo.srto_max; = 5 * sp->rtoinfo.srto_max;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT; SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] = ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
SCTP_DEFAULT_TIMEOUT_SACK; SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ; sp->autoclose * HZ;
/* Set up the default send/receive buffer space. */ /* Set up the default send/receive buffer space. */
...@@ -175,7 +168,8 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, ...@@ -175,7 +168,8 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
} }
/* Add an association to an endpoint. */ /* 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; struct sock *sk = ep->base.sk;
...@@ -183,22 +177,21 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc) ...@@ -183,22 +177,21 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
list_add_tail(&asoc->asocs, &ep->asocs); list_add_tail(&asoc->asocs, &ep->asocs);
/* Increment the backlog value for a TCP-style listening socket. */ /* Increment the backlog value for a TCP-style listening socket. */
if ((SCTP_SOCKET_TCP == sctp_sk(sk)->type) && if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
(SCTP_SS_LISTENING == sk->state))
sk->ack_backlog++; sk->ack_backlog++;
} }
/* Free the endpoint structure. Delay cleanup until /* Free the endpoint structure. Delay cleanup until
* all users have released their reference count on this structure. * 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; ep->base.dead = 1;
sctp_endpoint_put(ep); sctp_endpoint_put(ep);
} }
/* Final destructor for endpoint. */ /* 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); SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
...@@ -207,9 +200,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep) ...@@ -207,9 +200,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
/* Unlink this endpoint, so we can't find it again! */ /* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint(ep); sctp_unhash_endpoint(ep);
/* Cleanup the inqueue. */ /* Free up the HMAC transform. */
sctp_inq_free(&ep->base.inqueue); 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); sctp_bind_addr_free(&ep->base.bind_addr);
/* Remove and free the port */ /* Remove and free the port */
...@@ -228,7 +224,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep) ...@@ -228,7 +224,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
} }
/* Hold a reference to an endpoint. */ /* 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); atomic_inc(&ep->base.refcnt);
} }
...@@ -236,17 +232,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep) ...@@ -236,17 +232,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep)
/* Release a reference to an endpoint and clean up if there are /* Release a reference to an endpoint and clean up if there are
* no more references. * 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)) if (atomic_dec_and_test(&ep->base.refcnt))
sctp_endpoint_destroy(ep); sctp_endpoint_destroy(ep);
} }
/* Is this the endpoint we are looking for? */ /* Is this the endpoint we are looking for? */
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep, struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
const union sctp_addr *laddr) const union sctp_addr *laddr)
{ {
sctp_endpoint_t *retval; struct sctp_endpoint *retval;
sctp_read_lock(&ep->base.addr_lock); sctp_read_lock(&ep->base.addr_lock);
if (ep->base.bind_addr.port == laddr->v4.sin_port) { if (ep->base.bind_addr.port == laddr->v4.sin_port) {
...@@ -268,19 +264,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep, ...@@ -268,19 +264,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint. * We do a linear search of the associations for this endpoint.
* We return the matching transport address too. * We return the matching transport address too.
*/ */
sctp_association_t *__sctp_endpoint_lookup_assoc( struct sctp_association *__sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *endpoint, const struct sctp_endpoint *ep,
const union sctp_addr *paddr, const union sctp_addr *paddr,
struct sctp_transport **transport) struct sctp_transport **transport)
{ {
int rport; int rport;
sctp_association_t *asoc; struct sctp_association *asoc;
struct list_head *pos; struct list_head *pos;
rport = paddr->v4.sin_port; rport = paddr->v4.sin_port;
list_for_each(pos, &endpoint->asocs) { list_for_each(pos, &ep->asocs) {
asoc = list_entry(pos, sctp_association_t, asocs); asoc = list_entry(pos, struct sctp_association, asocs);
if (rport == asoc->peer.port) { if (rport == asoc->peer.port) {
sctp_read_lock(&asoc->base.addr_lock); sctp_read_lock(&asoc->base.addr_lock);
*transport = sctp_assoc_lookup_paddr(asoc, paddr); *transport = sctp_assoc_lookup_paddr(asoc, paddr);
...@@ -296,12 +292,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc( ...@@ -296,12 +292,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc(
} }
/* Lookup association on an endpoint based on a peer address. BH-safe. */ /* Lookup association on an endpoint based on a peer address. BH-safe. */
sctp_association_t *sctp_endpoint_lookup_assoc( struct sctp_association *sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *ep, const struct sctp_endpoint *ep,
const union sctp_addr *paddr, const union sctp_addr *paddr,
struct sctp_transport **transport) struct sctp_transport **transport)
{ {
sctp_association_t *asoc; struct sctp_association *asoc;
sctp_local_bh_disable(); sctp_local_bh_disable();
asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport); asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport);
...@@ -313,12 +309,12 @@ sctp_association_t *sctp_endpoint_lookup_assoc( ...@@ -313,12 +309,12 @@ sctp_association_t *sctp_endpoint_lookup_assoc(
/* Look for any peeled off association from the endpoint that matches the /* Look for any peeled off association from the endpoint that matches the
* given peer address. * 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) const union sctp_addr *paddr)
{ {
struct list_head *pos; struct list_head *pos;
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
sctp_read_lock(&ep->base.addr_lock); sctp_read_lock(&ep->base.addr_lock);
bp = &ep->base.bind_addr; bp = &ep->base.bind_addr;
...@@ -337,12 +333,12 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep, ...@@ -337,12 +333,12 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
/* Do delayed input processing. This is scheduled by sctp_rcv(). /* Do delayed input processing. This is scheduled by sctp_rcv().
* This may be called on BH or task time. * 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 sock *sk;
struct sctp_transport *transport; struct sctp_transport *transport;
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
struct sctp_inq *inqueue; struct sctp_inq *inqueue;
sctp_subtype_t subtype; sctp_subtype_t subtype;
sctp_state_t state; sctp_state_t state;
...@@ -355,7 +351,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -355,7 +351,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
inqueue = &ep->base.inqueue; inqueue = &ep->base.inqueue;
sk = ep->base.sk; sk = ep->base.sk;
while (NULL != (chunk = sctp_inq_pop(inqueue))) { while (NULL != (chunk = sctp_inq_pop(inqueue))) {
subtype.chunk = chunk->chunk_hdr->type; subtype.chunk = chunk->chunk_hdr->type;
/* We might have grown an association since last we /* We might have grown an association since last we
......
This diff is collapsed.
...@@ -75,17 +75,17 @@ struct sctp_inq *sctp_inq_new(void) ...@@ -75,17 +75,17 @@ struct sctp_inq *sctp_inq_new(void)
/* Release the memory associated with an SCTP inqueue. */ /* Release the memory associated with an SCTP inqueue. */
void sctp_inq_free(struct sctp_inq *queue) void sctp_inq_free(struct sctp_inq *queue)
{ {
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
/* Empty the queue. */ /* Empty the queue. */
while ((chunk = (sctp_chunk_t *) skb_dequeue(&queue->in)) != NULL) while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)))
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
/* If there is a packet which is currently being worked on, /* If there is a packet which is currently being worked on,
* free it as well. * free it as well.
*/ */
if (queue->in_progress) if (queue->in_progress)
sctp_free_chunk(queue->in_progress); sctp_chunk_free(queue->in_progress);
if (queue->malloced) { if (queue->malloced) {
/* Dump the master memory segment. */ /* Dump the master memory segment. */
...@@ -96,7 +96,7 @@ void sctp_inq_free(struct sctp_inq *queue) ...@@ -96,7 +96,7 @@ void sctp_inq_free(struct sctp_inq *queue)
/* Put a new packet in an SCTP inqueue. /* Put a new packet in an SCTP inqueue.
* We assume that packet->sctp_hdr is set and in host byte order. * We assume that packet->sctp_hdr is set and in host byte order.
*/ */
void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet) void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet)
{ {
/* Directly call the packet handling routine. */ /* Directly call the packet handling routine. */
...@@ -114,23 +114,23 @@ void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet) ...@@ -114,23 +114,23 @@ void sctp_inq_push(struct sctp_inq *q, sctp_chunk_t *packet)
* WARNING: If you need to put the chunk on another queue, you need to * WARNING: If you need to put the chunk on another queue, you need to
* make a shallow copy (clone) of it. * make a shallow copy (clone) of it.
*/ */
sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue) struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
{ {
sctp_chunk_t *chunk; struct sctp_chunk *chunk;
sctp_chunkhdr_t *ch = NULL; sctp_chunkhdr_t *ch = NULL;
/* The assumption is that we are safe to process the chunks /* The assumption is that we are safe to process the chunks
* at this time. * at this time.
*/ */
if ((chunk = queue->in_progress) != NULL) { if ((chunk = queue->in_progress)) {
/* There is a packet that we have been working on. /* There is a packet that we have been working on.
* Any post processing work to do before we move on? * Any post processing work to do before we move on?
*/ */
if (chunk->singleton || if (chunk->singleton ||
chunk->end_of_packet || chunk->end_of_packet ||
chunk->pdiscard) { chunk->pdiscard) {
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
chunk = queue->in_progress = NULL; chunk = queue->in_progress = NULL;
} else { } else {
/* Nothing to do. Next chunk in the packet, please. */ /* Nothing to do. Next chunk in the packet, please. */
...@@ -149,7 +149,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue) ...@@ -149,7 +149,7 @@ sctp_chunk_t *sctp_inq_pop(struct sctp_inq *queue)
return NULL; return NULL;
chunk = queue->in_progress = chunk = queue->in_progress =
(sctp_chunk_t *) skb_dequeue(&queue->in); (struct sctp_chunk *) skb_dequeue(&queue->in);
/* This is the first chunk in the packet. */ /* This is the first chunk in the packet. */
chunk->singleton = 1; chunk->singleton = 1;
......
...@@ -96,8 +96,8 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -96,8 +96,8 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
struct sctphdr *sh = (struct sctphdr *)(skb->data + offset); struct sctphdr *sh = (struct sctphdr *)(skb->data + offset);
struct sock *sk; struct sock *sk;
sctp_endpoint_t *ep; struct sctp_endpoint *ep;
sctp_association_t *asoc; struct sctp_association *asoc;
struct sctp_transport *transport; struct sctp_transport *transport;
struct ipv6_pinfo *np; struct ipv6_pinfo *np;
char *saveip, *savesctp; char *saveip, *savesctp;
...@@ -119,7 +119,7 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -119,7 +119,7 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
goto out; goto out;
} }
/* Warning: The sock lock is held. Remember to call /* Warning: The sock lock is held. Remember to call
* sctp_err_finish! * sctp_err_finish!
*/ */
...@@ -148,21 +148,19 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -148,21 +148,19 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
} }
/* Based on tcp_v6_xmit() in tcp_ipv6.c. */ /* 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) int ipfragok)
{ {
struct sock *sk = skb->sk; struct sock *sk = skb->sk;
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl; struct flowi fl;
struct dst_entry *dst = skb->dst;
struct rt6_info *rt6 = (struct rt6_info *)dst;
fl.proto = sk->protocol; fl.proto = sk->protocol;
/* Fill in the dest address from the route entry passed with the skb /* Fill in the dest address from the route entry passed with the skb
* and the source address from the transport. * 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_src = &transport->saddr.v6.sin6_addr;
fl.fl6_flowlabel = np->flow_label; fl.fl6_flowlabel = np->flow_label;
...@@ -193,7 +191,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, ...@@ -193,7 +191,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 /* Returns the dst cache entry for the given source and destination ip
* addresses. * 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 *daddr,
union sctp_addr *saddr) union sctp_addr *saddr)
{ {
...@@ -251,10 +249,10 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, ...@@ -251,10 +249,10 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
/* Fills in the source address(saddr) based on the destination address(daddr) /* Fills in the source address(saddr) based on the destination address(daddr)
* and asoc's bind address list. * 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) union sctp_addr *daddr, union sctp_addr *saddr)
{ {
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
rwlock_t *addr_lock; rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr; struct sockaddr_storage_list *laddr;
struct list_head *pos; struct list_head *pos;
...@@ -376,11 +374,17 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) ...@@ -376,11 +374,17 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
} }
/* Initialize sk->rcv_saddr from sctp_addr. */ /* 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; 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. */ /* Initialize a sctp_addr from a dst_entry. */
static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
unsigned short port) unsigned short port)
...@@ -391,7 +395,7 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, ...@@ -391,7 +395,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); ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr);
} }
/* Compare addresses exactly. /* Compare addresses exactly.
* FIXME: v4-mapped-v6. * FIXME: v4-mapped-v6.
*/ */
static int sctp_v6_cmp_addr(const union sctp_addr *addr1, static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
...@@ -521,6 +525,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -521,6 +525,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newsk->family = PF_INET6; newsk->family = PF_INET6;
newsk->protocol = IPPROTO_SCTP; newsk->protocol = IPPROTO_SCTP;
newsk->backlog_rcv = sk->prot->backlog_rcv; newsk->backlog_rcv = sk->prot->backlog_rcv;
newsk->shutdown = sk->shutdown;
newsctp6sk = (struct sctp6_sock *)newsk; newsctp6sk = (struct sctp6_sock *)newsk;
newsctp6sk->pinet6 = &newsctp6sk->inet6; newsctp6sk->pinet6 = &newsctp6sk->inet6;
...@@ -530,10 +535,28 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -530,10 +535,28 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
memcpy(newnp, np, sizeof(struct ipv6_pinfo)); 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->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;
/* Init the ipv4 part of the socket since we can have sockets
* using v6 API for ipv4.
*/
newinet->ttl = sysctl_ip_default_ttl;
newinet->mc_loop = 1;
newinet->mc_ttl = 1;
newinet->mc_index = 0;
newinet->mc_list = NULL;
if (ipv4_config.no_pmtu_disc)
newinet->pmtudisc = IP_PMTUDISC_DONT;
else
newinet->pmtudisc = IP_PMTUDISC_WANT;
#ifdef INET_REFCNT_DEBUG #ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr); atomic_inc(&inet6_sock_nr);
...@@ -556,6 +579,12 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb) ...@@ -556,6 +579,12 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb)
return opt->iif; return opt->iif;
} }
/* Was this packet marked by Explicit Congestion Notification? */
static int sctp_v6_is_ce(const struct sk_buff *skb)
{
return *((__u32 *)(skb->nh.ipv6h)) & htonl(1<<20);
}
/* Initialize a PF_INET6 socket msg_name. */ /* Initialize a PF_INET6 socket msg_name. */
static void sctp_inet6_msgname(char *msgname, int *addr_len) static void sctp_inet6_msgname(char *msgname, int *addr_len)
{ {
...@@ -569,7 +598,7 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len) ...@@ -569,7 +598,7 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len)
} }
/* Initialize a PF_INET msgname from a ulpevent. */ /* 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) char *msgname, int *addrlen)
{ {
struct sockaddr_in6 *sin6, *sin6from; struct sockaddr_in6 *sin6, *sin6from;
...@@ -596,7 +625,7 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, ...@@ -596,7 +625,7 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
sin6from = &event->asoc->peer.primary_addr.v6; sin6from = &event->asoc->peer.primary_addr.v6;
ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr); 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; sin6->sin6_scope_id = sin6from->sin6_scope_id;
} }
} }
...@@ -696,7 +725,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -696,7 +725,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
if (addr->v6.sin6_scope_id) if (addr->v6.sin6_scope_id)
sk->bound_dev_if = addr->v6.sin6_scope_id; sk->bound_dev_if = addr->v6.sin6_scope_id;
if (!sk->bound_dev_if) if (!sk->bound_dev_if)
return 0; return 0;
} }
af = opt->pf->af; af = opt->pf->af;
} }
...@@ -726,11 +755,11 @@ static int sctp_inet6_send_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -726,11 +755,11 @@ static int sctp_inet6_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
if (addr->v6.sin6_scope_id) if (addr->v6.sin6_scope_id)
sk->bound_dev_if = addr->v6.sin6_scope_id; sk->bound_dev_if = addr->v6.sin6_scope_id;
if (!sk->bound_dev_if) if (!sk->bound_dev_if)
return 0; return 0;
} }
af = opt->pf->af; af = opt->pf->af;
} }
return af != NULL; return af != NULL;
} }
...@@ -807,7 +836,8 @@ static struct sctp_af sctp_ipv6_specific = { ...@@ -807,7 +836,8 @@ static struct sctp_af sctp_ipv6_specific = {
.copy_addrlist = sctp_v6_copy_addrlist, .copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb, .from_skb = sctp_v6_from_skb,
.from_sk = sctp_v6_from_sk, .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, .dst_saddr = sctp_v6_dst_saddr,
.cmp_addr = sctp_v6_cmp_addr, .cmp_addr = sctp_v6_cmp_addr,
.scope = sctp_v6_scope, .scope = sctp_v6_scope,
...@@ -816,6 +846,7 @@ static struct sctp_af sctp_ipv6_specific = { ...@@ -816,6 +846,7 @@ static struct sctp_af sctp_ipv6_specific = {
.is_any = sctp_v6_is_any, .is_any = sctp_v6_is_any,
.available = sctp_v6_available, .available = sctp_v6_available,
.skb_iif = sctp_v6_skb_iif, .skb_iif = sctp_v6_skb_iif,
.is_ce = sctp_v6_is_ce,
.net_header_len = sizeof(struct ipv6hdr), .net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6), .sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6, .sa_family = AF_INET6,
......
...@@ -55,6 +55,7 @@ SCTP_DBG_OBJCNT(bind_addr); ...@@ -55,6 +55,7 @@ SCTP_DBG_OBJCNT(bind_addr);
SCTP_DBG_OBJCNT(chunk); SCTP_DBG_OBJCNT(chunk);
SCTP_DBG_OBJCNT(addr); SCTP_DBG_OBJCNT(addr);
SCTP_DBG_OBJCNT(ssnmap); SCTP_DBG_OBJCNT(ssnmap);
SCTP_DBG_OBJCNT(datamsg);
/* An array to make it easy to pretty print the debug information /* An array to make it easy to pretty print the debug information
* to the proc fs. * to the proc fs.
...@@ -68,6 +69,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = { ...@@ -68,6 +69,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
SCTP_DBG_OBJCNT_ENTRY(bind_addr), SCTP_DBG_OBJCNT_ENTRY(bind_addr),
SCTP_DBG_OBJCNT_ENTRY(addr), SCTP_DBG_OBJCNT_ENTRY(addr),
SCTP_DBG_OBJCNT_ENTRY(ssnmap), SCTP_DBG_OBJCNT_ENTRY(ssnmap),
SCTP_DBG_OBJCNT_ENTRY(datamsg),
}; };
/* Callback from procfs to read out objcount information. /* Callback from procfs to read out objcount information.
......
...@@ -114,7 +114,7 @@ void sctp_packet_free(struct sctp_packet *packet) ...@@ -114,7 +114,7 @@ void sctp_packet_free(struct sctp_packet *packet)
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)))
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
if (packet->malloced) if (packet->malloced)
kfree(packet); kfree(packet);
...@@ -166,11 +166,11 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, ...@@ -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 /* If sending DATA and haven't aleady bundled a SACK, try to
* bundle one in to the packet. * 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) { !pkt->has_cookie_echo) {
struct sctp_association *asoc; struct sctp_association *asoc;
asoc = pkt->transport->asoc; asoc = pkt->transport->asoc;
if (asoc->a_rwnd > asoc->rwnd) { if (asoc->a_rwnd > asoc->rwnd) {
struct sctp_chunk *sack; struct sctp_chunk *sack;
asoc->a_rwnd = asoc->rwnd; asoc->a_rwnd = asoc->rwnd;
...@@ -205,7 +205,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -205,7 +205,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
if (retval != SCTP_XMIT_OK) if (retval != SCTP_XMIT_OK)
goto finish; goto finish;
pmtu = ((packet->transport->asoc) ? pmtu = ((packet->transport->asoc) ?
(packet->transport->asoc->pmtu) : (packet->transport->asoc->pmtu) :
(packet->transport->pmtu)); (packet->transport->pmtu));
...@@ -219,21 +219,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -219,21 +219,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
/* Both control chunks and data chunks with TSNs are /* Both control chunks and data chunks with TSNs are
* non-fragmentable. * non-fragmentable.
*/ */
int fragmentable = sctp_chunk_is_data(chunk) &&
(!chunk->has_tsn);
if (packet_empty) { if (packet_empty) {
if (fragmentable) {
retval = SCTP_XMIT_MUST_FRAG; /* We no longer do refragmentation at all.
goto finish; * Just fragment at the IP layer, if we
} else { * actually hit this condition
/* The packet is too big but we can */
* not fragment it--we have to just
* transmit and rely on IP packet->ipfragok = 1;
* fragmentation. goto append;
*/
packet->ipfragok = 1;
goto append;
}
} else { /* !packet_empty */ } else { /* !packet_empty */
retval = SCTP_XMIT_PMTU_FULL; retval = SCTP_XMIT_PMTU_FULL;
goto finish; goto finish;
...@@ -259,7 +254,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -259,7 +254,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
goto finish; goto finish;
} else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type) } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type)
packet->has_cookie_echo = 1; 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; packet->has_sack = 1;
/* It is OK to send this chunk. */ /* It is OK to send this chunk. */
...@@ -276,8 +271,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, ...@@ -276,8 +271,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
*/ */
int sctp_packet_transmit(struct sctp_packet *packet) int sctp_packet_transmit(struct sctp_packet *packet)
{ {
struct sctp_transport *transport = packet->transport; struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = transport->asoc; struct sctp_association *asoc = tp->asoc;
struct sctphdr *sh; struct sctphdr *sh;
__u32 crc32; __u32 crc32;
struct sk_buff *nskb; struct sk_buff *nskb;
...@@ -311,6 +306,31 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -311,6 +306,31 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/ */
skb_set_owner_w(nskb, sk); 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 * 6.10 Bundling
* *
...@@ -332,10 +352,12 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -332,10 +352,12 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/ */
SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
chunk->num_times_sent++;
chunk->sent_at = jiffies;
if (sctp_chunk_is_data(chunk)) { if (sctp_chunk_is_data(chunk)) {
sctp_chunk_assign_tsn(chunk);
if (!chunk->has_tsn) {
sctp_chunk_assign_ssn(chunk);
sctp_chunk_assign_tsn(chunk);
/* 6.3.1 C4) When data is in flight and when allowed /* 6.3.1 C4) When data is in flight and when allowed
* by rule C5, a new RTT measurement MUST be made each * by rule C5, a new RTT measurement MUST be made each
...@@ -343,19 +365,27 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -343,19 +365,27 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* SHOULD be made no more than once per round-trip * SHOULD be made no more than once per round-trip
* for a given destination transport address. * for a given destination transport address.
*/ */
if ((1 == chunk->num_times_sent) &&
(!transport->rto_pending)) { if (!tp->rto_pending) {
chunk->rtt_in_progress = 1; chunk->rtt_in_progress = 1;
transport->rto_pending = 1; tp->rto_pending = 1;
} }
} else
chunk->resent = 1;
chunk->sent_at = jiffies;
has_data = 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; padding = WORD_ROUND(chunk->skb->len) - chunk->skb->len;
memset(skb_put(nskb, padding), 0, padding); if (padding)
SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d, " memset(skb_put(chunk->skb, padding), 0, padding);
"%s %d\n",
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\n",
"*** Chunk", chunk, "*** Chunk", chunk,
sctp_cname(SCTP_ST_CHUNK( sctp_cname(SCTP_ST_CHUNK(
chunk->chunk_hdr->type)), chunk->chunk_hdr->type)),
...@@ -364,7 +394,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -364,7 +394,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
ntohl(chunk->subh.data_hdr->tsn) : 0, ntohl(chunk->subh.data_hdr->tsn) : 0,
"length", ntohs(chunk->chunk_hdr->length), "length", ntohs(chunk->chunk_hdr->length),
"chunk->skb->len", chunk->skb->len, "chunk->skb->len", chunk->skb->len,
"num_times_sent", chunk->num_times_sent,
"rtt_in_progress", chunk->rtt_in_progress); "rtt_in_progress", chunk->rtt_in_progress);
/* /*
...@@ -373,33 +402,10 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -373,33 +402,10 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* acknowledged or have failed. * acknowledged or have failed.
*/ */
if (!sctp_chunk_is_data(chunk)) if (!sctp_chunk_is_data(chunk))
sctp_free_chunk(chunk); sctp_chunk_free(chunk);
} }
/* Build the SCTP header. */ /* Perform final transformation on checksum. */
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);
crc32 = sctp_end_cksum(crc32); crc32 = sctp_end_cksum(crc32);
/* 3) Put the resultant value into the checksum field in the /* 3) Put the resultant value into the checksum field in the
...@@ -413,17 +419,13 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -413,17 +419,13 @@ int sctp_packet_transmit(struct sctp_packet *packet)
* data sender to indicate that the end-points of the * data sender to indicate that the end-points of the
* transport protocol are ECN-capable." * transport protocol are ECN-capable."
* *
* If ECN capable && negotiated && it makes sense for * Now setting the ECT bit all the time, as it should not cause
* this packet to support it (e.g. post ECN negotiation) * any problems protocol-wise even if our peer ignores it.
* then lets set the ECT bit
* *
* FIXME: Need to do something else for IPv6 * Note: The works for IPv6 layer checks this bit too later
* in transmission. See IP6_ECN_flow_xmit().
*/ */
if (packet->ecn_capable) { INET_ECN_xmit(nskb->sk);
INET_ECN_xmit(nskb->sk);
} else {
INET_ECN_dontxmit(nskb->sk);
}
/* Set up the IP options. */ /* Set up the IP options. */
/* BUG: not implemented /* BUG: not implemented
...@@ -431,22 +433,21 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -431,22 +433,21 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/ */
/* Dump that on IP! */ /* 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 /* Considering the multiple CPU scenario, this is a
* "correcter" place for last_sent_to. --xguo * "correcter" place for last_sent_to. --xguo
*/ */
asoc->peer.last_sent_to = transport; asoc->peer.last_sent_to = tp;
} }
if (has_data) { if (has_data) {
struct timer_list *timer; struct timer_list *timer;
unsigned long timeout; unsigned long timeout;
transport->last_time_used = jiffies; tp->last_time_used = jiffies;
/* Restart the AUTOCLOSE timer when sending data. */ /* Restart the AUTOCLOSE timer when sending data. */
if ((SCTP_STATE_ESTABLISHED == asoc->state) && if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
(asoc->autoclose)) {
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
...@@ -455,21 +456,21 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -455,21 +456,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. */ /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
if (!dst || (dst->obsolete > 1)) { if (!dst || (dst->obsolete > 1)) {
dst_release(dst); dst_release(dst);
sctp_transport_route(transport, NULL, sctp_sk(sk)); sctp_transport_route(tp, NULL, sctp_sk(sk));
sctp_assoc_sync_pmtu(asoc); sctp_assoc_sync_pmtu(asoc);
} }
nskb->dst = dst_clone(transport->dst); nskb->dst = dst_clone(tp->dst);
if (!nskb->dst) if (!nskb->dst)
goto no_route; goto no_route;
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n", SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n",
nskb->len); nskb->len);
(*transport->af_specific->sctp_xmit)(nskb, transport, packet->ipfragok); (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
out: out:
packet->size = SCTP_IP_OVERHEAD; packet->size = SCTP_IP_OVERHEAD;
return err; return err;
...@@ -596,8 +597,8 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, ...@@ -596,8 +597,8 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
* if any previously transmitted data on the connection remains * if any previously transmitted data on the connection remains
* unacknowledged. * 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) { q->outstanding_bytes && sctp_state(asoc, ESTABLISHED)) {
unsigned len = datasize + q->out_qlen; unsigned len = datasize + q->out_qlen;
/* Check whether this chunk and all the rest of pending /* Check whether this chunk and all the rest of pending
...@@ -623,6 +624,8 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, ...@@ -623,6 +624,8 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
rwnd = 0; rwnd = 0;
asoc->peer.rwnd = rwnd; asoc->peer.rwnd = rwnd;
/* Has been accepted for transmission. */
chunk->msg->can_expire = 0;
finish: finish:
return retval; return retval;
......
This diff is collapsed.
...@@ -55,12 +55,12 @@ ...@@ -55,12 +55,12 @@
#define DECLARE_PRIMITIVE(name) \ #define DECLARE_PRIMITIVE(name) \
/* This is called in the code as sctp_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) { \ void *arg) { \
int error = 0; \ int error = 0; \
sctp_event_t event_type; sctp_subtype_t subtype; \ sctp_event_t event_type; sctp_subtype_t subtype; \
sctp_state_t state; \ sctp_state_t state; \
sctp_endpoint_t *ep; \ struct sctp_endpoint *ep; \
\ \
event_type = SCTP_EVENT_T_PRIMITIVE; \ event_type = SCTP_EVENT_T_PRIMITIVE; \
subtype = SCTP_ST_PRIMITIVE(SCTP_PRIMITIVE_ ## name); \ subtype = SCTP_ST_PRIMITIVE(SCTP_PRIMITIVE_ ## name); \
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/inet_common.h> #include <net/inet_common.h>
#include <net/inet_ecn.h>
/* Global data structures. */ /* Global data structures. */
struct sctp_protocol sctp_proto; struct sctp_protocol sctp_proto;
...@@ -203,7 +204,7 @@ static void sctp_free_local_addr_list(struct sctp_protocol *proto) ...@@ -203,7 +204,7 @@ static void sctp_free_local_addr_list(struct sctp_protocol *proto)
/* Copy the local addresses which are valid for 'scope' into 'bp'. */ /* Copy the local addresses which are valid for 'scope' into 'bp'. */
int sctp_copy_local_addr_list(struct sctp_protocol *proto, int sctp_copy_local_addr_list(struct sctp_protocol *proto,
struct sctp_bind_addr *bp, sctp_scope_t scope, struct sctp_bind_addr *bp, sctp_scope_t scope,
int priority, int copy_flags) int gfp, int copy_flags)
{ {
struct sockaddr_storage_list *addr; struct sockaddr_storage_list *addr;
int error = 0; int error = 0;
...@@ -223,8 +224,8 @@ int sctp_copy_local_addr_list(struct sctp_protocol *proto, ...@@ -223,8 +224,8 @@ int sctp_copy_local_addr_list(struct sctp_protocol *proto,
(((AF_INET6 == addr->a.sa.sa_family) && (((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) { (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp, &addr->a, error = sctp_add_bind_addr(bp, &addr->a,
priority); GFP_ATOMIC);
if (error) if (error)
goto end_copy; goto end_copy;
} }
...@@ -267,11 +268,16 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) ...@@ -267,11 +268,16 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
} }
/* Initialize sk->rcv_saddr from sctp_addr. */ /* 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; 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. */ /* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst,
...@@ -388,7 +394,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, ...@@ -388,7 +394,7 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
{ {
struct rtable *rt; struct rtable *rt;
struct flowi fl; struct flowi fl;
sctp_bind_addr_t *bp; struct sctp_bind_addr *bp;
rwlock_t *addr_lock; rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr; struct sockaddr_storage_list *laddr;
struct list_head *pos; struct list_head *pos;
...@@ -471,21 +477,33 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, ...@@ -471,21 +477,33 @@ 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 /* 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. * 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, struct dst_entry *dst,
union sctp_addr *daddr, union sctp_addr *daddr,
union sctp_addr *saddr) 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? */ /* What interface did this skb arrive on? */
int sctp_v4_skb_iif(const struct sk_buff *skb) static int sctp_v4_skb_iif(const struct sk_buff *skb)
{
return ((struct rtable *)skb->dst)->rt_iif;
}
/* Was this packet marked by Explicit Congestion Notification? */
static int sctp_v4_is_ce(const struct sk_buff *skb)
{ {
return ((struct rtable *)skb->dst)->rt_iif; return INET_ECN_is_ce(skb->nh.iph->tos);
} }
/* 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 sock *sctp_v4_create_accept_sk(struct sock *sk,
struct sctp_association *asoc) struct sctp_association *asoc)
{ {
...@@ -506,22 +524,27 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -506,22 +524,27 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newsk->prot = sk->prot; newsk->prot = sk->prot;
newsk->no_check = sk->no_check; newsk->no_check = sk->no_check;
newsk->reuse = sk->reuse; newsk->reuse = sk->reuse;
newsk->shutdown = sk->shutdown;
newsk->destruct = inet_sock_destruct; newsk->destruct = inet_sock_destruct;
newsk->zapped = 0; newsk->zapped = 0;
newsk->family = PF_INET; newsk->family = PF_INET;
newsk->protocol = IPPROTO_SCTP; newsk->protocol = IPPROTO_SCTP;
newsk->backlog_rcv = sk->prot->backlog_rcv; newsk->backlog_rcv = sk->prot->backlog_rcv;
newinet = inet_sk(newsk); newinet = inet_sk(newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for
* getsockname() and getpeername()
*/
newinet->sport = inet->sport; newinet->sport = inet->sport;
newinet->saddr = inet->saddr; newinet->saddr = inet->saddr;
newinet->rcv_saddr = inet->saddr; newinet->rcv_saddr = inet->rcv_saddr;
newinet->dport = asoc->peer.port; newinet->dport = htons(asoc->peer.port);
newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
newinet->pmtudisc = inet->pmtudisc; newinet->pmtudisc = inet->pmtudisc;
newinet->id = 0; newinet->id = 0;
newinet->ttl = sysctl_ip_default_ttl; newinet->ttl = sysctl_ip_default_ttl;
newinet->mc_loop = 1; newinet->mc_loop = 1;
newinet->mc_ttl = 1; newinet->mc_ttl = 1;
...@@ -568,7 +591,7 @@ int sctp_ctl_sock_init(void) ...@@ -568,7 +591,7 @@ int sctp_ctl_sock_init(void)
if (sctp_get_pf_specific(PF_INET6)) if (sctp_get_pf_specific(PF_INET6))
family = PF_INET6; family = PF_INET6;
else else
family = PF_INET; family = PF_INET;
err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP, err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP,
...@@ -695,7 +718,7 @@ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -695,7 +718,7 @@ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
return sctp_v4_available(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. * been taken care of.
*/ */
static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr) static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr)
...@@ -706,7 +729,7 @@ static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -706,7 +729,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 /* Fill in Supported Address Type information for INIT and INIT-ACK
* chunks. Returns number of addresses supported. * 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) __u16 *types)
{ {
types[0] = SCTP_PARAM_IPV4_ADDRESS; types[0] = SCTP_PARAM_IPV4_ADDRESS;
...@@ -805,7 +828,8 @@ struct sctp_af sctp_ipv4_specific = { ...@@ -805,7 +828,8 @@ struct sctp_af sctp_ipv4_specific = {
.copy_addrlist = sctp_v4_copy_addrlist, .copy_addrlist = sctp_v4_copy_addrlist,
.from_skb = sctp_v4_from_skb, .from_skb = sctp_v4_from_skb,
.from_sk = sctp_v4_from_sk, .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, .dst_saddr = sctp_v4_dst_saddr,
.cmp_addr = sctp_v4_cmp_addr, .cmp_addr = sctp_v4_cmp_addr,
.addr_valid = sctp_v4_addr_valid, .addr_valid = sctp_v4_addr_valid,
...@@ -814,6 +838,7 @@ struct sctp_af sctp_ipv4_specific = { ...@@ -814,6 +838,7 @@ struct sctp_af sctp_ipv4_specific = {
.available = sctp_v4_available, .available = sctp_v4_available,
.scope = sctp_v4_scope, .scope = sctp_v4_scope,
.skb_iif = sctp_v4_skb_iif, .skb_iif = sctp_v4_skb_iif,
.is_ce = sctp_v4_is_ce,
.net_header_len = sizeof(struct iphdr), .net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in), .sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET, .sa_family = AF_INET,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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