Commit 8d0df569 authored by Sridhar Samudrala's avatar Sridhar Samudrala

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

into us.ibm.com:/home/sridhar/BK/lksctp-2.5.67
parents f01d7733 d77fdda9
...@@ -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__
...@@ -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.
*/ */
......
...@@ -178,12 +178,6 @@ extern void sctp_err_finish(struct sock *, struct sctp_endpoint *, ...@@ -178,12 +178,6 @@ extern 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 *, extern 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
......
...@@ -283,8 +283,11 @@ struct sctp_opt { ...@@ -283,8 +283,11 @@ struct sctp_opt {
/* PF_ family specific functions. */ /* PF_ family specific functions. */
struct sctp_pf *pf; struct sctp_pf *pf;
/* Access to HMAC transform. */
struct crypto_tfm *hmac;
/* What is our base endpointer? */ /* What is our base endpointer? */
sctp_endpoint_t *ep; struct sctp_endpoint *ep;
/* Various Socket Options. */ /* Various Socket Options. */
__u16 default_stream; __u16 default_stream;
...@@ -1054,11 +1057,6 @@ struct sctp_endpoint { ...@@ -1054,11 +1057,6 @@ struct sctp_endpoint {
/* Common substructure for endpoint and association. */ /* Common substructure for endpoint and association. */
sctp_endpoint_common_t base; sctp_endpoint_common_t base;
/* These are the system-wide defaults and other stuff which is
* endpoint-independent.
*/
struct sctp_protocol *proto;
/* Associations: A list of current associations and mappings /* Associations: A list of current associations and mappings
* to the data consumers for each association. This * to the data consumers for each association. This
* may be in the form of a hash table or other * may be in the form of a hash table or other
...@@ -1092,28 +1090,29 @@ struct sctp_endpoint { ...@@ -1092,28 +1090,29 @@ struct sctp_endpoint {
}; };
/* Recover the outter endpoint structure. */ /* Recover the outter endpoint structure. */
static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base) static inline struct sctp_endpoint *sctp_ep(sctp_endpoint_common_t *base)
{ {
sctp_endpoint_t *ep; struct sctp_endpoint *ep;
ep = container_of(base, sctp_endpoint_t, base); ep = container_of(base, struct sctp_endpoint, base);
return ep; return ep;
} }
/* These are function signatures for manipulating endpoints. */ /* These are function signatures for manipulating endpoints. */
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *, struct sock *, int); struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
sctp_endpoint_t *sctp_endpoint_init(struct sctp_endpoint *, struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *,
struct sctp_protocol *, struct sock *, int gfp);
struct sock *, int gfp); void sctp_endpoint_free(struct sctp_endpoint *);
void sctp_endpoint_free(sctp_endpoint_t *); void sctp_endpoint_put(struct sctp_endpoint *);
void sctp_endpoint_put(sctp_endpoint_t *); void sctp_endpoint_hold(struct sctp_endpoint *);
void sctp_endpoint_hold(sctp_endpoint_t *); void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
void sctp_endpoint_add_asoc(sctp_endpoint_t *, struct sctp_association *asoc); struct sctp_association *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 **); struct sctp_transport **);
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *); int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *, const union sctp_addr *);
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
const union sctp_addr *); const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr, int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr); const union sctp_addr *paddr);
...@@ -1126,8 +1125,8 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid, ...@@ -1126,8 +1125,8 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
sctp_init_chunk_t *init, int gfp); sctp_init_chunk_t *init, int gfp);
int sctp_process_param(struct sctp_association *, union sctp_params param, int sctp_process_param(struct sctp_association *, union sctp_params param,
const union sctp_addr *from, int gfp); const union sctp_addr *from, int gfp);
__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 *);
/* RFC2960 /* RFC2960
...@@ -1162,7 +1161,7 @@ struct sctp_association { ...@@ -1162,7 +1161,7 @@ struct sctp_association {
__u32 eyecatcher; __u32 eyecatcher;
/* This is our parent endpoint. */ /* This is our parent endpoint. */
sctp_endpoint_t *ep; struct sctp_endpoint *ep;
/* These are those association elements needed in the cookie. */ /* These are those association elements needed in the cookie. */
sctp_cookie_t c; sctp_cookie_t c;
...@@ -1571,10 +1570,10 @@ static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base) ...@@ -1571,10 +1570,10 @@ static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base)
struct sctp_association * struct sctp_association *
sctp_association_new(const sctp_endpoint_t *, const struct sock *, sctp_association_new(const struct sctp_endpoint *, const struct sock *,
sctp_scope_t scope, int gfp); sctp_scope_t scope, int gfp);
struct sctp_association * struct sctp_association *
sctp_association_init(struct sctp_association *, const sctp_endpoint_t *, sctp_association_init(struct sctp_association *, const struct sctp_endpoint *,
const struct sock *, sctp_scope_t scope, const struct sock *, sctp_scope_t scope,
int gfp); int gfp);
void sctp_association_free(struct sctp_association *); void sctp_association_free(struct sctp_association *);
......
...@@ -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
...@@ -9,8 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ ...@@ -9,8 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
transport.o sm_make_chunk.o ulpevent.o \ transport.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
......
...@@ -96,6 +96,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -96,6 +96,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
int priority) int priority)
{ {
struct sctp_opt *sp; struct sctp_opt *sp;
struct sctp_protocol *proto = sctp_get_protocol();
int i; int i;
/* Retrieve the SCTP per socket area. */ /* Retrieve the SCTP per socket area. */
...@@ -136,10 +137,10 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -136,10 +137,10 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->frag_point = 0; asoc->frag_point = 0;
/* Initialize the default association max_retrans and RTO values. */ /* Initialize the default association max_retrans and RTO values. */
asoc->max_retrans = ep->proto->max_retrans_association; asoc->max_retrans = proto->max_retrans_association;
asoc->rto_initial = ep->proto->rto_initial; asoc->rto_initial = proto->rto_initial;
asoc->rto_max = ep->proto->rto_max; asoc->rto_max = proto->rto_max;
asoc->rto_min = ep->proto->rto_min; asoc->rto_min = proto->rto_min;
asoc->overall_error_threshold = 0; asoc->overall_error_threshold = 0;
asoc->overall_error_count = 0; asoc->overall_error_count = 0;
...@@ -147,7 +148,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -147,7 +148,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
/* Initialize the maximum mumber of new data packets that can be sent /* Initialize the maximum mumber of new data packets that can be sent
* in a burst. * in a burst.
*/ */
asoc->max_burst = ep->proto->max_burst; asoc->max_burst = proto->max_burst;
/* Copy things from the endpoint. */ /* Copy things from the endpoint. */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) { for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
......
...@@ -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;
...@@ -191,14 +185,14 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc) ...@@ -191,14 +185,14 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
/* 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 +201,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep) ...@@ -207,9 +201,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)
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 +225,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep) ...@@ -228,7 +225,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 +233,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep) ...@@ -236,17 +233,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 +265,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep, ...@@ -268,19 +265,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint. * We 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 +293,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc( ...@@ -296,12 +293,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,7 +310,7 @@ sctp_association_t *sctp_endpoint_lookup_assoc( ...@@ -313,7 +310,7 @@ 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;
...@@ -337,9 +334,9 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep, ...@@ -337,9 +334,9 @@ 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; sctp_chunk_t *chunk;
...@@ -355,7 +352,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -355,7 +352,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
......
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/inet.h> #include <linux/inet.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
#include <net/sock.h> #include <net/sock.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -156,7 +158,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code, ...@@ -156,7 +158,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
* Host Name Address (Note 3) Optional 11 * Host Name Address (Note 3) Optional 11
* Supported Address Types (Note 4) Optional 12 * Supported Address Types (Note 4) Optional 12
*/ */
sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_init(const struct sctp_association *asoc,
const sctp_bind_addr_t *bp, const sctp_bind_addr_t *bp,
int gfp, int vparam_len) int gfp, int vparam_len)
{ {
...@@ -236,7 +238,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc, ...@@ -236,7 +238,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
return retval; return retval;
} }
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const sctp_chunk_t *chunk,
int gfp, int unkparam_len) int gfp, int unkparam_len)
{ {
...@@ -294,7 +296,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc, ...@@ -294,7 +296,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param); sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
/* We need to remove the const qualifier at this point. */ /* We need to remove the const qualifier at this point. */
retval->asoc = (sctp_association_t *) asoc; retval->asoc = (struct sctp_association *) asoc;
/* RFC 2960 6.4 Multi-homed SCTP Endpoints /* RFC 2960 6.4 Multi-homed SCTP Endpoints
* *
...@@ -350,7 +352,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc, ...@@ -350,7 +352,7 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
* An implementation SHOULD make the cookie as small as possible * An implementation SHOULD make the cookie as small as possible
* to insure interoperability. * to insure interoperability.
*/ */
sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_cookie_echo(const struct sctp_association *asoc,
const sctp_chunk_t *chunk) const sctp_chunk_t *chunk)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -401,7 +403,7 @@ sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *asoc, ...@@ -401,7 +403,7 @@ sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *asoc,
* *
* Set to zero on transmit and ignored on receipt. * Set to zero on transmit and ignored on receipt.
*/ */
sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_cookie_ack(const struct sctp_association *asoc,
const sctp_chunk_t *chunk) const sctp_chunk_t *chunk)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -446,7 +448,7 @@ sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *asoc, ...@@ -446,7 +448,7 @@ sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *asoc,
* *
* Note: The CWR is considered a Control chunk. * Note: The CWR is considered a Control chunk.
*/ */
sctp_chunk_t *sctp_make_cwr(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_cwr(const struct sctp_association *asoc,
const __u32 lowest_tsn, const __u32 lowest_tsn,
const sctp_chunk_t *chunk) const sctp_chunk_t *chunk)
{ {
...@@ -481,7 +483,7 @@ sctp_chunk_t *sctp_make_cwr(const sctp_association_t *asoc, ...@@ -481,7 +483,7 @@ sctp_chunk_t *sctp_make_cwr(const sctp_association_t *asoc,
} }
/* Make an ECNE chunk. This is a congestion experienced report. */ /* Make an ECNE chunk. This is a congestion experienced report. */
sctp_chunk_t *sctp_make_ecne(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_ecne(const struct sctp_association *asoc,
const __u32 lowest_tsn) const __u32 lowest_tsn)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -502,7 +504,7 @@ sctp_chunk_t *sctp_make_ecne(const sctp_association_t *asoc, ...@@ -502,7 +504,7 @@ sctp_chunk_t *sctp_make_ecne(const sctp_association_t *asoc,
/* Make a DATA chunk for the given association from the provided /* Make a DATA chunk for the given association from the provided
* parameters. However, do not populate the data payload. * parameters. However, do not populate the data payload.
*/ */
sctp_chunk_t *sctp_make_datafrag_empty(sctp_association_t *asoc, sctp_chunk_t *sctp_make_datafrag_empty(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int data_len, __u8 flags, __u16 ssn) int data_len, __u8 flags, __u16 ssn)
{ {
...@@ -537,7 +539,7 @@ sctp_chunk_t *sctp_make_datafrag_empty(sctp_association_t *asoc, ...@@ -537,7 +539,7 @@ sctp_chunk_t *sctp_make_datafrag_empty(sctp_association_t *asoc,
/* Make a DATA chunk for the given association. Populate the data /* Make a DATA chunk for the given association. Populate the data
* payload. * payload.
*/ */
sctp_chunk_t *sctp_make_datafrag(sctp_association_t *asoc, sctp_chunk_t *sctp_make_datafrag(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int data_len, const __u8 *data, int data_len, const __u8 *data,
__u8 flags, __u16 ssn) __u8 flags, __u16 ssn)
...@@ -554,7 +556,7 @@ sctp_chunk_t *sctp_make_datafrag(sctp_association_t *asoc, ...@@ -554,7 +556,7 @@ sctp_chunk_t *sctp_make_datafrag(sctp_association_t *asoc,
/* Make a DATA chunk for the given association to ride on stream id /* Make a DATA chunk for the given association to ride on stream id
* 'stream', with a payload id of 'payload', and a body of 'data'. * 'stream', with a payload id of 'payload', and a body of 'data'.
*/ */
sctp_chunk_t *sctp_make_data(sctp_association_t *asoc, sctp_chunk_t *sctp_make_data(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int data_len, const __u8 *data) int data_len, const __u8 *data)
{ {
...@@ -571,7 +573,7 @@ sctp_chunk_t *sctp_make_data(sctp_association_t *asoc, ...@@ -571,7 +573,7 @@ sctp_chunk_t *sctp_make_data(sctp_association_t *asoc,
* hold 'data_len' octets of data. We use this version when we need * hold 'data_len' octets of data. We use this version when we need
* to build the message AFTER allocating memory. * to build the message AFTER allocating memory.
*/ */
sctp_chunk_t *sctp_make_data_empty(sctp_association_t *asoc, sctp_chunk_t *sctp_make_data_empty(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
int data_len) int data_len)
{ {
...@@ -584,7 +586,7 @@ sctp_chunk_t *sctp_make_data_empty(sctp_association_t *asoc, ...@@ -584,7 +586,7 @@ sctp_chunk_t *sctp_make_data_empty(sctp_association_t *asoc,
* association. This reports on which TSN's we've seen to date, * association. This reports on which TSN's we've seen to date,
* including duplicates and gaps. * including duplicates and gaps.
*/ */
sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc) sctp_chunk_t *sctp_make_sack(const struct sctp_association *asoc)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
sctp_sackhdr_t sack; sctp_sackhdr_t sack;
...@@ -599,11 +601,13 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc) ...@@ -599,11 +601,13 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn); SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn);
/* Count the number of Gap Ack Blocks. */ /* Count the number of Gap Ack Blocks. */
sctp_tsnmap_iter_init(map, &iter); num_gabs = 0;
for (num_gabs = 0;
sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end); if (sctp_tsnmap_has_gap(map)) {
num_gabs++) { sctp_tsnmap_iter_init(map, &iter);
/* Do nothing. */ while (sctp_tsnmap_next_gap_ack(map, &iter,
&gab.start, &gab.end))
num_gabs++;
} }
num_dup_tsns = sctp_tsnmap_num_dups(map); num_dup_tsns = sctp_tsnmap_num_dups(map);
...@@ -659,11 +663,15 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc) ...@@ -659,11 +663,15 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
sctp_addto_chunk(retval, sizeof(sack), &sack); sctp_addto_chunk(retval, sizeof(sack), &sack);
/* Put the Gap Ack Blocks into the chunk. */ /* Put the Gap Ack Blocks into the chunk. */
sctp_tsnmap_iter_init(map, &iter); if (num_gabs) {
while(sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end)) { sctp_tsnmap_iter_init(map, &iter);
gab.start = htons(gab.start); while(sctp_tsnmap_next_gap_ack(map, &iter,
gab.end = htons(gab.end); &gab.start, &gab.end)) {
sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t), &gab); gab.start = htons(gab.start);
gab.end = htons(gab.end);
sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t),
&gab);
}
} }
/* Register the duplicates. */ /* Register the duplicates. */
...@@ -675,7 +683,7 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc) ...@@ -675,7 +683,7 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
} }
/* Make a SHUTDOWN chunk. */ /* Make a SHUTDOWN chunk. */
sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc) sctp_chunk_t *sctp_make_shutdown(const struct sctp_association *asoc)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
sctp_shutdownhdr_t shut; sctp_shutdownhdr_t shut;
...@@ -695,7 +703,7 @@ sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc) ...@@ -695,7 +703,7 @@ sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc)
return retval; return retval;
} }
sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const sctp_chunk_t *chunk) const sctp_chunk_t *chunk)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -717,7 +725,7 @@ sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc, ...@@ -717,7 +725,7 @@ sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc,
return retval; return retval;
} }
sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_shutdown_complete(const struct sctp_association *asoc,
const sctp_chunk_t *chunk) const sctp_chunk_t *chunk)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -747,7 +755,7 @@ sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *asoc, ...@@ -747,7 +755,7 @@ sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *asoc,
/* Create an ABORT. Note that we set the T bit if we have no /* Create an ABORT. Note that we set the T bit if we have no
* association. * association.
*/ */
sctp_chunk_t *sctp_make_abort(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_abort(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const sctp_chunk_t *chunk,
const size_t hint) const size_t hint)
{ {
...@@ -775,7 +783,7 @@ sctp_chunk_t *sctp_make_abort(const sctp_association_t *asoc, ...@@ -775,7 +783,7 @@ sctp_chunk_t *sctp_make_abort(const sctp_association_t *asoc,
} }
/* Helper to create ABORT with a NO_USER_DATA error. */ /* Helper to create ABORT with a NO_USER_DATA error. */
sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_abort_no_data(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, __u32 tsn) const sctp_chunk_t *chunk, __u32 tsn)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -809,7 +817,7 @@ sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *asoc, ...@@ -809,7 +817,7 @@ sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *asoc,
} }
/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */
sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const sctp_chunk_t *chunk,
const struct msghdr *msg) const struct msghdr *msg)
{ {
...@@ -856,7 +864,7 @@ sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *asoc, ...@@ -856,7 +864,7 @@ sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *asoc,
} }
/* Make a HEARTBEAT chunk. */ /* Make a HEARTBEAT chunk. */
sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_heartbeat(const struct sctp_association *asoc,
const struct sctp_transport *transport, const struct sctp_transport *transport,
const void *payload, const size_t paylen) const void *payload, const size_t paylen)
{ {
...@@ -876,7 +884,7 @@ sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *asoc, ...@@ -876,7 +884,7 @@ sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *asoc,
return retval; return retval;
} }
sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_heartbeat_ack(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const sctp_chunk_t *chunk,
const void *payload, const size_t paylen) const void *payload, const size_t paylen)
{ {
...@@ -906,7 +914,7 @@ sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *asoc, ...@@ -906,7 +914,7 @@ sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *asoc,
/* Create an Operation Error chunk with the specified space reserved. /* Create an Operation Error chunk with the specified space reserved.
* This routine can be used for containing multiple causes in the chunk. * This routine can be used for containing multiple causes in the chunk.
*/ */
sctp_chunk_t *sctp_make_op_error_space(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_op_error_space(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const sctp_chunk_t *chunk,
size_t size) size_t size)
{ {
...@@ -933,7 +941,7 @@ sctp_chunk_t *sctp_make_op_error_space(const sctp_association_t *asoc, ...@@ -933,7 +941,7 @@ sctp_chunk_t *sctp_make_op_error_space(const sctp_association_t *asoc,
} }
/* Create an Operation Error chunk. */ /* Create an Operation Error chunk. */
sctp_chunk_t *sctp_make_op_error(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_op_error(const struct sctp_association *asoc,
const sctp_chunk_t *chunk, const sctp_chunk_t *chunk,
__u16 cause_code, const void *payload, __u16 cause_code, const void *payload,
size_t paylen) size_t paylen)
...@@ -956,7 +964,8 @@ sctp_chunk_t *sctp_make_op_error(const sctp_association_t *asoc, ...@@ -956,7 +964,8 @@ sctp_chunk_t *sctp_make_op_error(const sctp_association_t *asoc,
/* Turn an skb into a chunk. /* Turn an skb into a chunk.
* FIXME: Eventually move the structure directly inside the skb->cb[]. * FIXME: Eventually move the structure directly inside the skb->cb[].
*/ */
sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc, sctp_chunk_t *sctp_chunkify(struct sk_buff *skb,
const struct sctp_association *asoc,
struct sock *sk) struct sock *sk)
{ {
sctp_chunk_t *retval = t_new(sctp_chunk_t, GFP_ATOMIC); sctp_chunk_t *retval = t_new(sctp_chunk_t, GFP_ATOMIC);
...@@ -970,7 +979,7 @@ sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc, ...@@ -970,7 +979,7 @@ sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc,
} }
retval->skb = skb; retval->skb = skb;
retval->asoc = (sctp_association_t *) asoc; retval->asoc = (struct sctp_association *)asoc;
retval->num_times_sent = 0; retval->num_times_sent = 0;
retval->has_tsn = 0; retval->has_tsn = 0;
retval->has_ssn = 0; retval->has_ssn = 0;
...@@ -1023,7 +1032,7 @@ const union sctp_addr *sctp_source(const sctp_chunk_t *chunk) ...@@ -1023,7 +1032,7 @@ const union sctp_addr *sctp_source(const sctp_chunk_t *chunk)
/* Create a new chunk, setting the type and flags headers from the /* Create a new chunk, setting the type and flags headers from the
* arguments, reserving enough space for a 'paylen' byte payload. * arguments, reserving enough space for a 'paylen' byte payload.
*/ */
sctp_chunk_t *sctp_make_chunk(const sctp_association_t *asoc, sctp_chunk_t *sctp_make_chunk(const struct sctp_association *asoc,
__u8 type, __u8 flags, int paylen) __u8 type, __u8 flags, int paylen)
{ {
sctp_chunk_t *retval; sctp_chunk_t *retval;
...@@ -1032,7 +1041,7 @@ sctp_chunk_t *sctp_make_chunk(const sctp_association_t *asoc, ...@@ -1032,7 +1041,7 @@ sctp_chunk_t *sctp_make_chunk(const sctp_association_t *asoc,
struct sock *sk; struct sock *sk;
/* No need to allocate LL here, as this is only a chunk. */ /* No need to allocate LL here, as this is only a chunk. */
skb = alloc_skb(WORD_ROUND(sizeof(sctp_chunkhdr_t) + paylen), skb = alloc_skb(WORD_ROUND(sizeof(sctp_chunkhdr_t) + paylen),
GFP_ATOMIC); GFP_ATOMIC);
if (!skb) if (!skb)
goto nodata; goto nodata;
...@@ -1135,7 +1144,7 @@ static int sctp_user_addto_chunk(sctp_chunk_t *chunk, int off, int len, ...@@ -1135,7 +1144,7 @@ static int sctp_user_addto_chunk(sctp_chunk_t *chunk, int off, int len,
*/ */
int sctp_datachunks_from_user(sctp_association_t *asoc, int sctp_datachunks_from_user(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo, const struct sctp_sndrcvinfo *sinfo,
struct msghdr *msg, int msg_len, struct msghdr *msg, int msg_len,
struct sk_buff_head *chunks) struct sk_buff_head *chunks)
...@@ -1291,10 +1300,10 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk) ...@@ -1291,10 +1300,10 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
} }
/* Create a CLOSED association to use with an incoming packet. */ /* Create a CLOSED association to use with an incoming packet. */
sctp_association_t *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk, int gfp) struct sctp_chunk *chunk, int gfp)
{ {
sctp_association_t *asoc; struct sctp_association *asoc;
struct sk_buff *skb; struct sk_buff *skb;
sctp_scope_t scope; sctp_scope_t scope;
...@@ -1339,15 +1348,18 @@ sctp_association_t *sctp_make_temp_asoc(const struct sctp_endpoint *ep, ...@@ -1339,15 +1348,18 @@ sctp_association_t *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
/* Build a cookie representing asoc. /* Build a cookie representing asoc.
* This INCLUDES the param header needed to put the cookie in the INIT ACK. * This INCLUDES the param header needed to put the cookie in the INIT ACK.
*/ */
sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep, sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
const sctp_association_t *asoc, const struct sctp_association *asoc,
const sctp_chunk_t *init_chunk, const sctp_chunk_t *init_chunk,
int *cookie_len, int *cookie_len,
const __u8 *raw_addrs, int addrs_len) const __u8 *raw_addrs, int addrs_len)
{ {
sctp_cookie_param_t *retval; sctp_cookie_param_t *retval;
sctp_signed_cookie_t *cookie; sctp_signed_cookie_t *cookie;
struct scatterlist sg;
int headersize, bodysize; int headersize, bodysize;
unsigned int keylen = SCTP_SECRET_SIZE;
char *key;
headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE; headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
bodysize = sizeof(sctp_cookie_t) bodysize = sizeof(sctp_cookie_t)
...@@ -1361,8 +1373,8 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep, ...@@ -1361,8 +1373,8 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
- (bodysize % SCTP_COOKIE_MULTIPLE); - (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize; *cookie_len = headersize + bodysize;
retval = (sctp_cookie_param_t *) retval = (sctp_cookie_param_t *)kmalloc(*cookie_len, GFP_ATOMIC);
kmalloc(*cookie_len, GFP_ATOMIC);
if (!retval) { if (!retval) {
*cookie_len = 0; *cookie_len = 0;
goto nodata; goto nodata;
...@@ -1392,31 +1404,39 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep, ...@@ -1392,31 +1404,39 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
ntohs(init_chunk->chunk_hdr->length)); ntohs(init_chunk->chunk_hdr->length));
/* Copy the raw local address list of the association. */ /* Copy the raw local address list of the association. */
memcpy((__u8 *)&cookie->c.peer_init[0] + memcpy((__u8 *)&cookie->c.peer_init[0] +
ntohs(init_chunk->chunk_hdr->length), raw_addrs, ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
addrs_len);
if (sctp_sk(ep->base.sk)->hmac) {
/* Sign the message. */ /* Sign the message. */
sctp_hash_digest(ep->secret_key[ep->current_key], SCTP_SECRET_SIZE, sg.page = virt_to_page(&cookie->c);
(__u8 *) &cookie->c, bodysize, cookie->signature); sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE;
sg.length = bodysize;
key = (char *)ep->secret_key[ep->current_key];
crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1,
cookie->signature);
}
nodata: nodata:
return retval; return retval;
} }
/* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */ /* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, struct sctp_association *sctp_unpack_cookie(
const sctp_association_t *asoc, const struct sctp_endpoint *ep,
sctp_chunk_t *chunk, int gfp, const struct sctp_association *asoc,
int *error, sctp_chunk_t **err_chk_p) sctp_chunk_t *chunk, int gfp,
int *error, sctp_chunk_t **errp)
{ {
sctp_association_t *retval = NULL; struct sctp_association *retval = NULL;
sctp_signed_cookie_t *cookie; sctp_signed_cookie_t *cookie;
sctp_cookie_t *bear_cookie; sctp_cookie_t *bear_cookie;
int headersize, bodysize; int headersize, bodysize, fixed_size;
int fixed_size; __u8 digest[SCTP_SIGNATURE_SIZE];
__u8 digest_buf[SCTP_SIGNATURE_SIZE]; struct scatterlist sg;
int secret; unsigned int keylen;
char *key;
sctp_scope_t scope; sctp_scope_t scope;
struct sk_buff *skb = chunk->skb; struct sk_buff *skb = chunk->skb;
...@@ -1440,23 +1460,34 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1440,23 +1460,34 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
cookie = chunk->subh.cookie_hdr; cookie = chunk->subh.cookie_hdr;
bear_cookie = &cookie->c; bear_cookie = &cookie->c;
if (!sctp_sk(ep->base.sk)->hmac)
goto no_hmac;
/* Check the signature. */ /* Check the signature. */
secret = ep->current_key; keylen = SCTP_SECRET_SIZE;
sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE, sg.page = virt_to_page(bear_cookie);
(__u8 *) bear_cookie, bodysize, sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE;
digest_buf); sg.length = bodysize;
if (memcmp(digest_buf, cookie->signature, SCTP_SIGNATURE_SIZE)) { key = (char *)ep->secret_key[ep->current_key];
/* Try the previous key. */
secret = ep->last_key; memset(digest, 0x00, sizeof(digest));
sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE, crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1, digest);
(__u8 *) bear_cookie, bodysize, digest_buf);
if (memcmp(digest_buf, cookie->signature, SCTP_SIGNATURE_SIZE)) { if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
/* Try the previous key. */
key = (char *)ep->secret_key[ep->last_key];
memset(digest, 0x00, sizeof(digest));
crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, 1,
digest);
if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
/* Yikes! Still bad signature! */ /* Yikes! Still bad signature! */
*error = -SCTP_IERROR_BAD_SIG; *error = -SCTP_IERROR_BAD_SIG;
goto fail; goto fail;
} }
} }
no_hmac:
/* Check to see if the cookie is stale. If there is already /* Check to see if the cookie is stale. If there is already
* an association, there is no need to check cookie's expiration * an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK. * for init collision case of lost COOKIE ACK.
...@@ -1472,15 +1503,15 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1472,15 +1503,15 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* Cookie that has expired. * Cookie that has expired.
*/ */
len = ntohs(chunk->chunk_hdr->length); len = ntohs(chunk->chunk_hdr->length);
*err_chk_p = sctp_make_op_error_space(asoc, chunk, len); *errp = sctp_make_op_error_space(asoc, chunk, len);
if (*err_chk_p) { if (*errp) {
suseconds_t usecs = (skb->stamp.tv_sec - suseconds_t usecs = (skb->stamp.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L + bear_cookie->expiration.tv_sec) * 1000000L +
skb->stamp.tv_usec - skb->stamp.tv_usec -
bear_cookie->expiration.tv_usec; bear_cookie->expiration.tv_usec;
usecs = htonl(usecs); usecs = htonl(usecs);
sctp_init_cause(*err_chk_p, SCTP_ERROR_STALE_COOKIE, sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
&usecs, sizeof(usecs)); &usecs, sizeof(usecs));
*error = -SCTP_IERROR_STALE_COOKIE; *error = -SCTP_IERROR_STALE_COOKIE;
} else } else
...@@ -1541,10 +1572,10 @@ struct __sctp_missing { ...@@ -1541,10 +1572,10 @@ struct __sctp_missing {
/* /*
* Report a missing mandatory parameter. * Report a missing mandatory parameter.
*/ */
static int sctp_process_missing_param(const sctp_association_t *asoc, static int sctp_process_missing_param(const struct sctp_association *asoc,
sctp_param_t paramtype, sctp_param_t paramtype,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p) sctp_chunk_t **errp)
{ {
struct __sctp_missing report; struct __sctp_missing report;
__u16 len; __u16 len;
...@@ -1554,13 +1585,13 @@ static int sctp_process_missing_param(const sctp_association_t *asoc, ...@@ -1554,13 +1585,13 @@ static int sctp_process_missing_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for /* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters. * returning multiple unknown parameters.
*/ */
if (!*err_chk_p) if (!*errp)
*err_chk_p = sctp_make_op_error_space(asoc, chunk, len); *errp = sctp_make_op_error_space(asoc, chunk, len);
if (*err_chk_p) { if (*errp) {
report.num_missing = htonl(1); report.num_missing = htonl(1);
report.type = paramtype; report.type = paramtype;
sctp_init_cause(*err_chk_p, SCTP_ERROR_INV_PARAM, sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM,
&report, sizeof(report)); &report, sizeof(report));
} }
...@@ -1569,17 +1600,17 @@ static int sctp_process_missing_param(const sctp_association_t *asoc, ...@@ -1569,17 +1600,17 @@ static int sctp_process_missing_param(const sctp_association_t *asoc,
} }
/* Report an Invalid Mandatory Parameter. */ /* Report an Invalid Mandatory Parameter. */
static int sctp_process_inv_mandatory(const sctp_association_t *asoc, static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p) sctp_chunk_t **errp)
{ {
/* Invalid Mandatory Parameter Error has no payload. */ /* Invalid Mandatory Parameter Error has no payload. */
if (!*err_chk_p) if (!*errp)
*err_chk_p = sctp_make_op_error_space(asoc, chunk, 0); *errp = sctp_make_op_error_space(asoc, chunk, 0);
if (*err_chk_p) if (*errp)
sctp_init_cause(*err_chk_p, SCTP_ERROR_INV_PARAM, NULL, 0); sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0);
/* Stop processing this chunk. */ /* Stop processing this chunk. */
return 0; return 0;
...@@ -1588,19 +1619,19 @@ static int sctp_process_inv_mandatory(const sctp_association_t *asoc, ...@@ -1588,19 +1619,19 @@ static int sctp_process_inv_mandatory(const sctp_association_t *asoc,
/* Do not attempt to handle the HOST_NAME parm. However, do /* Do not attempt to handle the HOST_NAME parm. However, do
* send back an indicator to the peer. * send back an indicator to the peer.
*/ */
static int sctp_process_hn_param(const sctp_association_t *asoc, static int sctp_process_hn_param(const struct sctp_association *asoc,
union sctp_params param, union sctp_params param,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p) sctp_chunk_t **errp)
{ {
__u16 len = ntohs(param.p->length); __u16 len = ntohs(param.p->length);
/* Make an ERROR chunk. */ /* Make an ERROR chunk. */
if (!*err_chk_p) if (!*errp)
*err_chk_p = sctp_make_op_error_space(asoc, chunk, len); *errp = sctp_make_op_error_space(asoc, chunk, len);
if (*err_chk_p) if (*errp)
sctp_init_cause(*err_chk_p, SCTP_ERROR_DNS_FAILED, sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED,
param.v, len); param.v, len);
/* Stop processing this chunk. */ /* Stop processing this chunk. */
...@@ -1633,10 +1664,10 @@ static int sctp_process_hn_param(const sctp_association_t *asoc, ...@@ -1633,10 +1664,10 @@ static int sctp_process_hn_param(const sctp_association_t *asoc,
* 0 - discard the chunk * 0 - discard the chunk
* 1 - continue with the chunk * 1 - continue with the chunk
*/ */
static int sctp_process_unk_param(const sctp_association_t *asoc, static int sctp_process_unk_param(const struct sctp_association *asoc,
union sctp_params param, union sctp_params param,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p) sctp_chunk_t **errp)
{ {
int retval = 1; int retval = 1;
...@@ -1649,12 +1680,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc, ...@@ -1649,12 +1680,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for /* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters. * returning multiple unknown parameters.
*/ */
if (NULL == *err_chk_p) if (NULL == *errp)
*err_chk_p = sctp_make_op_error_space(asoc, chunk, *errp = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length)); ntohs(chunk->chunk_hdr->length));
if (*err_chk_p) if (*errp)
sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM, sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
param.v, param.v,
WORD_ROUND(ntohs(param.p->length))); WORD_ROUND(ntohs(param.p->length)));
...@@ -1665,12 +1696,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc, ...@@ -1665,12 +1696,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for /* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters. * returning multiple unknown parameters.
*/ */
if (NULL == *err_chk_p) if (NULL == *errp)
*err_chk_p = sctp_make_op_error_space(asoc, chunk, *errp = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length)); ntohs(chunk->chunk_hdr->length));
if (*err_chk_p) { if (*errp) {
sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM, sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
param.v, param.v,
WORD_ROUND(ntohs(param.p->length))); WORD_ROUND(ntohs(param.p->length)));
} else { } else {
...@@ -1695,7 +1726,7 @@ static int sctp_process_unk_param(const sctp_association_t *asoc, ...@@ -1695,7 +1726,7 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
* 0 - discard the chunk * 0 - discard the chunk
* 1 - continue with the chunk * 1 - continue with the chunk
*/ */
static int sctp_verify_param(const sctp_association_t *asoc, static int sctp_verify_param(const struct sctp_association *asoc,
union sctp_params param, union sctp_params param,
sctp_cid_t cid, sctp_cid_t cid,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
...@@ -1733,11 +1764,11 @@ static int sctp_verify_param(const sctp_association_t *asoc, ...@@ -1733,11 +1764,11 @@ static int sctp_verify_param(const sctp_association_t *asoc,
} }
/* Verify the INIT packet before we process it. */ /* Verify the INIT packet before we process it. */
int sctp_verify_init(const sctp_association_t *asoc, int sctp_verify_init(const struct sctp_association *asoc,
sctp_cid_t cid, sctp_cid_t cid,
sctp_init_chunk_t *peer_init, sctp_init_chunk_t *peer_init,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p) sctp_chunk_t **errp)
{ {
union sctp_params param; union sctp_params param;
int has_cookie = 0; int has_cookie = 0;
...@@ -1746,7 +1777,7 @@ int sctp_verify_init(const sctp_association_t *asoc, ...@@ -1746,7 +1777,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
if ((0 == peer_init->init_hdr.num_outbound_streams) || if ((0 == peer_init->init_hdr.num_outbound_streams) ||
(0 == peer_init->init_hdr.num_inbound_streams)) { (0 == peer_init->init_hdr.num_inbound_streams)) {
sctp_process_inv_mandatory(asoc, chunk, err_chk_p); sctp_process_inv_mandatory(asoc, chunk, errp);
return 0; return 0;
} }
...@@ -1762,9 +1793,8 @@ int sctp_verify_init(const sctp_association_t *asoc, ...@@ -1762,9 +1793,8 @@ int sctp_verify_init(const sctp_association_t *asoc,
* the state cookie for an INIT-ACK chunk. * the state cookie for an INIT-ACK chunk.
*/ */
if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) { if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {
sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE, sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
chunk, err_chk_p); chunk, errp);
return 0; return 0;
} }
...@@ -1772,7 +1802,7 @@ int sctp_verify_init(const sctp_association_t *asoc, ...@@ -1772,7 +1802,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
sctp_walk_params(param, peer_init, init_hdr.params) { sctp_walk_params(param, peer_init, init_hdr.params) {
if (!sctp_verify_param(asoc, param, cid, chunk, err_chk_p)) if (!sctp_verify_param(asoc, param, cid, chunk, errp))
return 0; return 0;
} /* for (loop through all parameters) */ } /* for (loop through all parameters) */
...@@ -1784,7 +1814,7 @@ int sctp_verify_init(const sctp_association_t *asoc, ...@@ -1784,7 +1814,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
* Returns 0 on failure, else success. * Returns 0 on failure, else success.
* FIXME: This is an association method. * FIXME: This is an association method.
*/ */
int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
const union sctp_addr *peer_addr, const union sctp_addr *peer_addr,
sctp_init_chunk_t *peer_init, int gfp) sctp_init_chunk_t *peer_init, int gfp)
{ {
...@@ -1923,7 +1953,7 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1923,7 +1953,7 @@ int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* work we do. In particular, we should not build transport * work we do. In particular, we should not build transport
* structures for the addresses. * structures for the addresses.
*/ */
int sctp_process_param(sctp_association_t *asoc, union sctp_params param, int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
const union sctp_addr *peer_addr, int gfp) const union sctp_addr *peer_addr, int gfp)
{ {
union sctp_addr addr; union sctp_addr addr;
......
...@@ -55,7 +55,6 @@ ...@@ -55,7 +55,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/compiler.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/time.h> #include <linux/time.h>
...@@ -63,6 +62,7 @@ ...@@ -63,6 +62,7 @@
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/crypto.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/icmp.h> #include <net/icmp.h>
...@@ -96,15 +96,16 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int); ...@@ -96,15 +96,16 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
static int sctp_autobind(struct sock *sk); static int sctp_autobind(struct sock *sk);
static void sctp_sock_migrate(struct sock *, struct sock *, static void sctp_sock_migrate(struct sock *, struct sock *,
struct sctp_association *, sctp_socket_type_t); struct sctp_association *, sctp_socket_type_t);
static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
/* Look up the association by its id. If this is not a UDP-style /* Look up the association by its id. If this is not a UDP-style
* socket, the ID field is always ignored. * socket, the ID field is always ignored.
*/ */
sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id) struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
{ {
sctp_association_t *asoc = NULL; struct sctp_association *asoc = NULL;
/* If this is not a UDP-style socket, assoc id should be /* If this is not a UDP-style socket, assoc id should be
* ignored. * ignored.
*/ */
if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) { if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) {
...@@ -116,9 +117,9 @@ sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id) ...@@ -116,9 +117,9 @@ sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
/* First, verify that this is a kernel address. */ /* First, verify that this is a kernel address. */
if (sctp_is_valid_kaddr((unsigned long) id)) { if (sctp_is_valid_kaddr((unsigned long) id)) {
sctp_association_t *temp = (sctp_association_t *) id; struct sctp_association *temp = (sctp_association_t *) id;
/* Verify that this _is_ an sctp_association_t /* Verify that this _is_ an sctp_association
* data structure and if so, that the socket matches. * data structure and if so, that the socket matches.
*/ */
if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) && if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) &&
...@@ -188,7 +189,6 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt, ...@@ -188,7 +189,6 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt,
return af; return af;
} }
/* Bind a local address either to an endpoint or to an association. */ /* Bind a local address either to an endpoint or to an association. */
SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
{ {
...@@ -637,7 +637,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, ...@@ -637,7 +637,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
/* Alloc space for the address array in kernel memory. */ /* Alloc space for the address array in kernel memory. */
kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL); kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL);
if (unlikely(NULL == kaddrs)) if (unlikely(!kaddrs))
return -ENOMEM; return -ENOMEM;
if (copy_from_user(kaddrs, addrs, addrssize)) { if (copy_from_user(kaddrs, addrs, addrssize)) {
...@@ -1134,8 +1134,9 @@ static int sctp_skb_pull(struct sk_buff *skb, int len) ...@@ -1134,8 +1134,9 @@ static int sctp_skb_pull(struct sk_buff *skb, int len)
*/ */
static struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); static struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
int len, int noblock, int flags, int *addr_len) struct msghdr *msg, int len, int noblock,
int flags, int *addr_len)
{ {
struct sctp_ulpevent *event = NULL; struct sctp_ulpevent *event = NULL;
struct sctp_opt *sp = sctp_sk(sk); struct sctp_opt *sp = sctp_sk(sk);
...@@ -1156,7 +1157,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr ...@@ -1156,7 +1157,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
err = -ENOTCONN; err = -ENOTCONN;
goto out; goto out;
} }
skb = sctp_skb_recv_datagram(sk, flags, noblock, &err); skb = sctp_skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) if (!skb)
goto out; goto out;
...@@ -1271,7 +1272,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval, ...@@ -1271,7 +1272,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
} }
static int sctp_setsockopt_peer_addr_params(struct sock *sk, static int sctp_setsockopt_peer_addr_params(struct sock *sk,
char *optval, int optlen) char *optval, int optlen)
{ {
struct sctp_paddrparams params; struct sctp_paddrparams params;
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -1329,8 +1330,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, ...@@ -1329,8 +1330,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
return 0; return 0;
} }
static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen)
int optlen)
{ {
if (optlen != sizeof(struct sctp_initmsg)) if (optlen != sizeof(struct sctp_initmsg))
return -EINVAL; return -EINVAL;
...@@ -1340,7 +1340,6 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, ...@@ -1340,7 +1340,6 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval,
} }
/* /*
*
* 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM) * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM)
* *
* Applications that wish to use the sendto() system call may wish to * Applications that wish to use the sendto() system call may wish to
...@@ -1428,12 +1427,10 @@ static int sctp_setsockopt_nodelay(struct sock *sk, char *optval, ...@@ -1428,12 +1427,10 @@ static int sctp_setsockopt_nodelay(struct sock *sk, char *optval,
if (optlen < sizeof(__u8)) if (optlen < sizeof(__u8))
return -EINVAL; return -EINVAL;
if (get_user(val, (__u8 *)optval)) if (get_user(val, (__u8 *)optval))
return -EFAULT; return -EFAULT;
sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1; sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1;
return 0; return 0;
} }
...@@ -1590,7 +1587,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -1590,7 +1587,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
/* connect() cannot be done on a socket that is already in ESTABLISHED /* connect() cannot be done on a socket that is already in ESTABLISHED
* state - UDP-style peeled off socket or a TCP-style socket that * state - UDP-style peeled off socket or a TCP-style socket that
* is already connected. * is already connected.
* It cannot be done even on a TCP-style listening socket. * It cannot be done even on a TCP-style listening socket.
*/ */
if ((SCTP_SS_ESTABLISHED == sk->state) || if ((SCTP_SS_ESTABLISHED == sk->state) ||
...@@ -1690,10 +1687,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err) ...@@ -1690,10 +1687,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
struct sctp_opt *sp; struct sctp_opt *sp;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
struct sock *newsk = NULL; struct sock *newsk = NULL;
struct sctp_association *assoc; struct sctp_association *asoc;
long timeo; long timeo;
int error = 0; int error = 0;
sctp_lock_sock(sk); sctp_lock_sock(sk);
sp = sctp_sk(sk); sp = sctp_sk(sk);
...@@ -1715,21 +1712,21 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err) ...@@ -1715,21 +1712,21 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
if (error) if (error)
goto out; goto out;
/* We treat the list of associations on the endpoint as the accept /* We treat the list of associations on the endpoint as the accept
* queue and pick the first association on the list. * queue and pick the first association on the list.
*/ */
assoc = list_entry(ep->asocs.next, struct sctp_association, asocs); asoc = list_entry(ep->asocs.next, struct sctp_association, asocs);
newsk = sp->pf->create_accept_sk(sk, assoc); newsk = sp->pf->create_accept_sk(sk, asoc);
if (!newsk) { if (!newsk) {
error = -ENOMEM; error = -ENOMEM;
goto out; goto out;
} }
/* Populate the fields of the newsk from the oldsk and migrate the /* Populate the fields of the newsk from the oldsk and migrate the
* assoc to the newsk. * asoc to the newsk.
*/ */
sctp_sock_migrate(sk, newsk, assoc, SCTP_SOCKET_TCP); sctp_sock_migrate(sk, newsk, asoc, SCTP_SOCKET_TCP);
out: out:
sctp_release_sock(sk); sctp_release_sock(sk);
...@@ -1737,10 +1734,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err) ...@@ -1737,10 +1734,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
return newsk; return newsk;
} }
/* FIXME: Write Comments. */ /* The SCTP ioctl handler. */
SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{ {
return -EOPNOTSUPP; /* STUB */ return -ENOIOCTLCMD;
} }
/* This is the function which gets called during socket creation to /* This is the function which gets called during socket creation to
...@@ -1835,11 +1832,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) ...@@ -1835,11 +1832,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
* change the data structure relationships, this may still * change the data structure relationships, this may still
* be useful for storing pre-connect address information. * be useful for storing pre-connect address information.
*/ */
ep = sctp_endpoint_new(proto, sk, GFP_KERNEL); ep = sctp_endpoint_new(sk, GFP_KERNEL);
if (NULL == ep) if (!ep)
return -ENOMEM; return -ENOMEM;
sp->ep = ep; sp->ep = ep;
sp->hmac = NULL;
SCTP_DBG_OBJCNT_INC(sock); SCTP_DBG_OBJCNT_INC(sock);
return 0; return 0;
...@@ -1848,7 +1846,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) ...@@ -1848,7 +1846,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Cleanup any SCTP per socket resources. */ /* Cleanup any SCTP per socket resources. */
SCTP_STATIC int sctp_destroy_sock(struct sock *sk) SCTP_STATIC int sctp_destroy_sock(struct sock *sk)
{ {
sctp_endpoint_t *ep; struct sctp_endpoint *ep;
SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk); SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk);
...@@ -1877,7 +1875,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval, ...@@ -1877,7 +1875,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
int *optlen) int *optlen)
{ {
struct sctp_status status; struct sctp_status status;
sctp_association_t *assoc = NULL; struct sctp_association *asoc = NULL;
struct sctp_transport *transport; struct sctp_transport *transport;
sctp_assoc_t associd; sctp_assoc_t associd;
int retval = 0; int retval = 0;
...@@ -1893,22 +1891,22 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval, ...@@ -1893,22 +1891,22 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
} }
associd = status.sstat_assoc_id; associd = status.sstat_assoc_id;
assoc = sctp_id2assoc(sk, associd); asoc = sctp_id2assoc(sk, associd);
if (!assoc) { if (!asoc) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
transport = assoc->peer.primary_path; transport = asoc->peer.primary_path;
status.sstat_assoc_id = sctp_assoc2id(assoc); status.sstat_assoc_id = sctp_assoc2id(asoc);
status.sstat_state = assoc->state; status.sstat_state = asoc->state;
status.sstat_rwnd = assoc->peer.rwnd; status.sstat_rwnd = asoc->peer.rwnd;
status.sstat_unackdata = assoc->unack_data; status.sstat_unackdata = asoc->unack_data;
status.sstat_penddata = assoc->peer.tsn_map.pending_data; status.sstat_penddata = asoc->peer.tsn_map.pending_data;
status.sstat_instrms = assoc->c.sinit_max_instreams; status.sstat_instrms = asoc->c.sinit_max_instreams;
status.sstat_outstrms = assoc->c.sinit_num_ostreams; status.sstat_outstrms = asoc->c.sinit_num_ostreams;
status.sstat_fragmentation_point = assoc->frag_point; status.sstat_fragmentation_point = asoc->frag_point;
status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
memcpy(&status.sstat_primary.spinfo_address, memcpy(&status.sstat_primary.spinfo_address,
&(transport->ipaddr), sizeof(union sctp_addr)); &(transport->ipaddr), sizeof(union sctp_addr));
...@@ -1975,33 +1973,29 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int ...@@ -1975,33 +1973,29 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int
} }
/* Helper routine to branch off an association to a new socket. */ /* Helper routine to branch off an association to a new socket. */
SCTP_STATIC int sctp_do_peeloff(sctp_association_t *assoc, struct socket **newsock) SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
struct socket **sockp)
{ {
struct sock *oldsk = assoc->base.sk; struct sock *sk = asoc->base.sk;
struct sock *newsk; struct socket *sock;
struct socket *tmpsock;
int err = 0; int err = 0;
/* An association cannot be branched off from an already peeled-off /* An association cannot be branched off from an already peeled-off
* socket, nor is this supported for tcp style sockets. * socket, nor is this supported for tcp style sockets.
*/ */
if (SCTP_SOCKET_UDP != sctp_sk(oldsk)->type) if (SCTP_SOCKET_UDP != sctp_sk(sk)->type)
return -EOPNOTSUPP; return -EINVAL;
/* Create a new socket. */ /* Create a new socket. */
err = sock_create(oldsk->family, SOCK_SEQPACKET, IPPROTO_SCTP, err = sock_create(sk->family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
&tmpsock);
if (err < 0) if (err < 0)
return err; return err;
newsk = tmpsock->sk;
/* Populate the fields of the newsk from the oldsk and migrate the /* Populate the fields of the newsk from the oldsk and migrate the
* assoc to the newsk. * assoc to the newsk.
*/ */
sctp_sock_migrate(oldsk, newsk, assoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
*sockp = sock;
*newsock = tmpsock;
return err; return err;
} }
...@@ -2019,7 +2013,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int * ...@@ -2019,7 +2013,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
return -EFAULT; return -EFAULT;
assoc = sctp_id2assoc(sk, peeloff.associd); assoc = sctp_id2assoc(sk, peeloff.associd);
if (NULL == assoc) { if (!assoc) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
...@@ -2049,7 +2043,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int * ...@@ -2049,7 +2043,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
return retval; return retval;
} }
static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
struct sctp_paddrparams params; struct sctp_paddrparams params;
...@@ -2102,7 +2096,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int * ...@@ -2102,7 +2096,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *
return 0; return 0;
} }
static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
sctp_assoc_t id; sctp_assoc_t id;
...@@ -2350,7 +2344,7 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, ...@@ -2350,7 +2344,7 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
* integer boolean flag. * integer boolean flag.
*/ */
static int sctp_getsockopt_nodelay(struct sock *sk, int len, static int sctp_getsockopt_nodelay(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
__u8 val; __u8 val;
...@@ -2418,7 +2412,7 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, ...@@ -2418,7 +2412,7 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
break; break;
case SCTP_GET_PEER_ADDRS_NUM: case SCTP_GET_PEER_ADDRS_NUM:
retval = sctp_getsockopt_peer_addrs_num(sk, len, optval, retval = sctp_getsockopt_peer_addrs_num(sk, len, optval,
optlen); optlen);
break; break;
case SCTP_GET_LOCAL_ADDRS_NUM: case SCTP_GET_LOCAL_ADDRS_NUM:
...@@ -2553,7 +2547,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) ...@@ -2553,7 +2547,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
} }
if (pp != NULL && pp->sk != NULL) { if (pp && pp->sk) {
/* We had a port hash table hit - there is an /* We had a port hash table hit - there is an
* available port (pp != NULL) and it is being * available port (pp != NULL) and it is being
* used by other socket (pp->sk != NULL); that other * used by other socket (pp->sk != NULL); that other
...@@ -2601,18 +2595,17 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) ...@@ -2601,18 +2595,17 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
/* If there was a hash table miss, create a new port. */ /* If there was a hash table miss, create a new port. */
ret = 1; ret = 1;
if (pp == NULL && (pp = sctp_bucket_create(head, snum)) == NULL) if (!pp && !(pp = sctp_bucket_create(head, snum)))
goto fail_unlock; goto fail_unlock;
/* In either case (hit or miss), make sure fastreuse is 1 only /* In either case (hit or miss), make sure fastreuse is 1 only
* if sk->reuse is too (that is, if the caller requested * if sk->reuse is too (that is, if the caller requested
* SO_REUSEADDR on this socket -sk-). * SO_REUSEADDR on this socket -sk-).
*/ */
if (pp->sk == NULL) { if (!pp->sk)
pp->fastreuse = sk->reuse ? 1 : 0; pp->fastreuse = sk->reuse ? 1 : 0;
} else if (pp->fastreuse && sk->reuse == 0) { else if (pp->fastreuse && sk->reuse == 0)
pp->fastreuse = 0; pp->fastreuse = 0;
}
/* We are set, so fill up all the data in the hash table /* We are set, so fill up all the data in the hash table
* entry, tie the socket list information with the rest of the * entry, tie the socket list information with the rest of the
...@@ -2702,7 +2695,7 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) ...@@ -2702,7 +2695,7 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
/* /*
* 4.1.3 listen() - TCP Style Syntax * 4.1.3 listen() - TCP Style Syntax
* *
* Applications uses listen() to ready the SCTP endpoint for accepting * Applications uses listen() to ready the SCTP endpoint for accepting
* inbound associations. * inbound associations.
*/ */
SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
...@@ -2739,15 +2732,25 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) ...@@ -2739,15 +2732,25 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
int sctp_inet_listen(struct socket *sock, int backlog) int sctp_inet_listen(struct socket *sock, int backlog)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err; struct crypto_tfm *tfm=NULL;
int err = -EINVAL;
if (unlikely(backlog < 0))
goto out;
sctp_lock_sock(sk); sctp_lock_sock(sk);
err = -EINVAL;
if (sock->state != SS_UNCONNECTED) if (sock->state != SS_UNCONNECTED)
goto out; goto out;
if (unlikely(backlog < 0))
goto out; /* Allocate HMAC for generating cookie. */
if (sctp_hmac_alg) {
tfm = crypto_alloc_tfm(sctp_hmac_alg, 0);
if (!tfm) {
err = -ENOSYS;
goto out;
}
}
switch (sock->type) { switch (sock->type) {
case SOCK_SEQPACKET: case SOCK_SEQPACKET:
...@@ -2756,14 +2759,21 @@ int sctp_inet_listen(struct socket *sock, int backlog) ...@@ -2756,14 +2759,21 @@ int sctp_inet_listen(struct socket *sock, int backlog)
case SOCK_STREAM: case SOCK_STREAM:
err = sctp_stream_listen(sk, backlog); err = sctp_stream_listen(sk, backlog);
break; break;
default: default:
goto out; break;
}; };
if (err)
goto cleanup;
/* Store away the transform reference. */
sctp_sk(sk)->hmac = tfm;
out: out:
sctp_release_sock(sk); sctp_release_sock(sk);
return err; return err;
cleanup:
if (tfm)
crypto_free_tfm(tfm);
goto out;
} }
/* /*
...@@ -2967,7 +2977,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, ...@@ -2967,7 +2977,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
/* Strictly check lengths following example in SCM code. */ /* Strictly check lengths following example in SCM code. */
switch (cmsg->cmsg_type) { switch (cmsg->cmsg_type) {
case SCTP_INIT: case SCTP_INIT:
/* SCTP Socket API Extension (draft 1) /* SCTP Socket API Extension
* 5.2.1 SCTP Initiation Structure (SCTP_INIT) * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
* *
* This cmsghdr structure provides information for * This cmsghdr structure provides information for
...@@ -2987,7 +2997,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, ...@@ -2987,7 +2997,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
break; break;
case SCTP_SNDRCV: case SCTP_SNDRCV:
/* SCTP Socket API Extension (draft 1) /* SCTP Socket API Extension
* 5.2.2 SCTP Header Information Structure(SCTP_SNDRCV) * 5.2.2 SCTP Header Information Structure(SCTP_SNDRCV)
* *
* This cmsghdr structure specifies SCTP options for * This cmsghdr structure specifies SCTP options for
...@@ -3002,7 +3012,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, ...@@ -3002,7 +3012,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
CMSG_LEN(sizeof(struct sctp_sndrcvinfo))) CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
return -EINVAL; return -EINVAL;
cmsgs->info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); cmsgs->info =
(struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
/* Minimally, validate the sinfo_flags. */ /* Minimally, validate the sinfo_flags. */
if (cmsgs->info->sinfo_flags & if (cmsgs->info->sinfo_flags &
...@@ -3085,13 +3096,14 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p) ...@@ -3085,13 +3096,14 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p)
* Note: This is pretty much the same routine as in core/datagram.c * Note: This is pretty much the same routine as in core/datagram.c
* with a few changes to make lksctp work. * with a few changes to make lksctp work.
*/ */
static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int noblock, int *err) static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
int noblock, int *err)
{ {
int error; int error;
struct sk_buff *skb; struct sk_buff *skb;
long timeo; long timeo;
/* Caller is allowed not to check sk->err before skb_recv_datagram() */ /* Caller is allowed not to check sk->err before calling. */
error = sock_error(sk); error = sock_error(sk);
if (error) if (error)
goto no_packet; goto no_packet;
...@@ -3140,7 +3152,7 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no ...@@ -3140,7 +3152,7 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
} }
/* Verify that this is a valid address. */ /* Verify that this is a valid address. */
static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
int len) int len)
{ {
struct sctp_af *af; struct sctp_af *af;
...@@ -3443,11 +3455,12 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) ...@@ -3443,11 +3455,12 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo)
return err; return err;
} }
/* Populate the fields of the newsk from the oldsk and migrate the assoc /* Populate the fields of the newsk from the oldsk and migrate the assoc
* and its messages to the newsk. * and its messages to the newsk.
*/ */
void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
struct sctp_association *assoc, sctp_socket_type_t type) struct sctp_association *assoc,
sctp_socket_type_t type)
{ {
struct sctp_opt *oldsp = sctp_sk(oldsk); struct sctp_opt *oldsp = sctp_sk(oldsk);
struct sctp_opt *newsp = sctp_sk(newsk); struct sctp_opt *newsp = sctp_sk(newsk);
...@@ -3466,6 +3479,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, ...@@ -3466,6 +3479,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
* copy. * copy.
*/ */
newsp->ep = newep; newsp->ep = newep;
newsp->hmac = NULL;
/* Move any messages in the old socket's receive queue that are for the /* Move any messages in the old socket's receive queue that are for the
* peeled off association to the new socket's receive queue. * peeled off association to the new socket's receive queue.
...@@ -3526,7 +3540,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, ...@@ -3526,7 +3540,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsk->state = SCTP_SS_ESTABLISHED; newsk->state = SCTP_SS_ESTABLISHED;
} }
/* This proto struct describes the ULP interface for SCTP. */ /* This proto struct describes the ULP interface for SCTP. */
struct proto sctp_prot = { struct proto sctp_prot = {
.name = "SCTP", .name = "SCTP",
......
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