summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/constants.h54
-rw-r--r--include/net/sctp/sctp.h6
-rw-r--r--include/net/sctp/structs.h53
-rw-r--r--net/sctp/Kconfig47
-rw-r--r--net/sctp/Makefile3
-rw-r--r--net/sctp/associola.c11
-rw-r--r--net/sctp/endpointola.c89
-rw-r--r--net/sctp/sm_make_chunk.c248
-rw-r--r--net/sctp/socket.c186
9 files changed, 381 insertions, 316 deletions
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 0d6a20a7390e..60fe2147486f 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -6,46 +6,42 @@
*
* This file is part of the SCTP kernel reference Implementation
*
- * This file is part of the implementation of the add-IP extension,
- * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
- * for the SCTP kernel reference Implementation.
- *
- * The SCTP reference implementation is free software;
+ * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
- * the SCTP reference implementation is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * The SCTP reference implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Please send any bug reports or fixes you make to one of the following email
- * addresses:
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
*
- * La Monte H.P. Yarroll <piggy@acm.org>
- * Karl Knutson <karl@athena.chicago.il.us>
- * Randall Stewart <randall@stewart.chicago.il.us>
- * Ken Morneau <kmorneau@cisco.com>
- * Qiaobing Xie <qxie1@motorola.com>
- * Xingang Guo <xingang.guo@intel.com>
- * Sridhar Samudrala <samudrala@us.ibm.com>
- * Daisy Chang <daisyc@us.ibm.com>
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Randall Stewart <randall@stewart.chicago.il.us>
+ * Ken Morneau <kmorneau@cisco.com>
+ * Qiaobing Xie <qxie1@motorola.com>
+ * Xingang Guo <xingang.guo@intel.com>
+ * Sridhar Samudrala <samudrala@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
- *
- * There are still LOTS of bugs in this code... I always run on the motto
- * "it is a wonder any code ever works :)"
- *
- *
*/
#ifndef __sctp_constants_h__
@@ -336,10 +332,18 @@ typedef enum {
#define SCTP_SIGNATURE_SIZE 20 /* size of a SLA-1 signature */
-#define SCTP_COOKIE_MULTIPLE 64 /* Pad out our cookie to make our hash
+#define SCTP_COOKIE_MULTIPLE 32 /* Pad out our cookie to make our hash
* functions simpler to write.
*/
+#if defined (CONFIG_SCTP_HMAC_MD5)
+#define SCTP_COOKIE_HMAC_ALG "md5"
+#elif defined (CONFIG_SCTP_HMAC_SHA1)
+#define SCTP_COOKIE_HMAC_ALG "sha1"
+#else
+#define SCTP_COOKIE_HMAC_ALG NULL
+#endif
+
/* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue.
*/
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f964badf7062..5743ea6ace44 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -178,12 +178,6 @@ extern void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct sctp_association *);
extern void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu);
-/*
- * sctp/hashdriver.c
- */
-extern void sctp_hash_digest(const char *secret, const int secret_len,
- const char *text, const int text_len,
- __u8 *digest);
/*
* Section: Macros, externs, and inlines
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 5cf74d3c2882..5e7d728b2130 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -283,8 +283,11 @@ struct sctp_opt {
/* PF_ family specific functions. */
struct sctp_pf *pf;
+ /* Access to HMAC transform. */
+ struct crypto_tfm *hmac;
+
/* What is our base endpointer? */
- sctp_endpoint_t *ep;
+ struct sctp_endpoint *ep;
/* Various Socket Options. */
__u16 default_stream;
@@ -1054,11 +1057,6 @@ struct sctp_endpoint {
/* Common substructure for endpoint and association. */
sctp_endpoint_common_t base;
- /* These are the system-wide defaults and other stuff which is
- * endpoint-independent.
- */
- struct sctp_protocol *proto;
-
/* Associations: A list of current associations and mappings
* to the data consumers for each association. This
* may be in the form of a hash table or other
@@ -1092,28 +1090,29 @@ struct sctp_endpoint {
};
/* Recover the outter endpoint structure. */
-static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
+static inline struct sctp_endpoint *sctp_ep(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;
}
/* These are function signatures for manipulating endpoints. */
-sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *, struct sock *, int);
-sctp_endpoint_t *sctp_endpoint_init(struct sctp_endpoint *,
- struct sctp_protocol *,
- struct sock *, int gfp);
-void sctp_endpoint_free(sctp_endpoint_t *);
-void sctp_endpoint_put(sctp_endpoint_t *);
-void sctp_endpoint_hold(sctp_endpoint_t *);
-void sctp_endpoint_add_asoc(sctp_endpoint_t *, struct sctp_association *asoc);
-struct sctp_association *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
- const union sctp_addr *paddr,
- struct sctp_transport **);
-int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *);
-sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
+struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
+struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *,
+ struct sock *, int gfp);
+void sctp_endpoint_free(struct sctp_endpoint *);
+void sctp_endpoint_put(struct sctp_endpoint *);
+void sctp_endpoint_hold(struct sctp_endpoint *);
+void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
+struct sctp_association *sctp_endpoint_lookup_assoc(
+ const struct sctp_endpoint *ep,
+ const union sctp_addr *paddr,
+ struct sctp_transport **);
+int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
+ const union sctp_addr *);
+struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr);
@@ -1126,8 +1125,8 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
sctp_init_chunk_t *init, int gfp);
int sctp_process_param(struct sctp_association *, union sctp_params param,
const union sctp_addr *from, int gfp);
-__u32 sctp_generate_tag(const sctp_endpoint_t *);
-__u32 sctp_generate_tsn(const sctp_endpoint_t *);
+__u32 sctp_generate_tag(const struct sctp_endpoint *);
+__u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* RFC2960
@@ -1162,7 +1161,7 @@ struct sctp_association {
__u32 eyecatcher;
/* This is our parent endpoint. */
- sctp_endpoint_t *ep;
+ struct sctp_endpoint *ep;
/* These are those association elements needed in the cookie. */
sctp_cookie_t c;
@@ -1571,10 +1570,10 @@ static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base)
struct sctp_association *
-sctp_association_new(const sctp_endpoint_t *, const struct sock *,
+sctp_association_new(const struct sctp_endpoint *, const struct sock *,
sctp_scope_t scope, int gfp);
struct sctp_association *
-sctp_association_init(struct sctp_association *, const sctp_endpoint_t *,
+sctp_association_init(struct sctp_association *, const struct sctp_endpoint *,
const struct sock *, sctp_scope_t scope,
int gfp);
void sctp_association_free(struct sctp_association *);
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig
index 500d0e988b47..4df681dde7e5 100644
--- a/net/sctp/Kconfig
+++ b/net/sctp/Kconfig
@@ -43,12 +43,12 @@ config SCTP_ADLER32
bool "SCTP: Use old checksum (Adler-32)"
depends on IP_SCTP
help
- RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
+ RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
This has been deprecated and replaced by an algorithm now referred
to as crc32c.
- If you say Y, this will use the Adler-32 algorithm, this might be useful
- for interoperation with downlevel peers.
+ If you say Y, this will use the Adler-32 algorithm, this might be
+ useful for interoperation with downlevel peers.
If unsure, say N.
@@ -58,19 +58,46 @@ config SCTP_DBG_MSG
help
If you say Y, this will enable verbose debugging messages.
- If unsure, say N. However, if you are running into problems, use this
- option to gather detailed trace information
+ If unsure, say N. However, if you are running into problems, use
+ this option to gather detailed trace information
config SCTP_DBG_OBJCNT
bool "SCTP: Debug object counts"
depends on IP_SCTP
help
- If you say Y, this will enable debugging support for counting the types
- of objects that are currently allocated. This is useful for identifying
- memory leaks. If the /proc filesystem is enabled this debug information
- can be viewed by 'cat /proc/net/sctp/sctp_dbg_objcnt'
+ If you say Y, this will enable debugging support for counting the
+ type of objects that are currently allocated. This is useful for
+ identifying memory leaks. If the /proc filesystem is enabled this
+ debug information can be viewed by
+ 'cat /proc/net/sctp/sctp_dbg_objcnt'
If unsure, say N
-endmenu
+choice
+ prompt "SCTP: Cookie HMAC Algorithm"
+ help
+ HMAC algorithm to be used during association initialization. It
+ is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See
+ configuration for Cryptographic API and enable those algorithms
+ to make usable by SCTP.
+
+config SCTP_HMAC_NONE
+ bool "None"
+ help
+ Choosing this disables the use of an HMAC during association
+ establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1.
+
+config SCTP_HMAC_SHA1
+ bool "HMAC-SHA1" if CRYPTO_HMAC=y && CRYPTO_SHA1=y || CRYPTO_SHA1=m
+ help
+ Enable the use of HMAC-SHA1 during association establishment. It
+ is advised to use either HMAC-MD5 or HMAC-SHA1.
+
+config SCTP_HMAC_MD5
+ bool "HMAC-MD5" if CRYPTO_HMAC=y && CRYPTO_MD5=y || CRYPTO_MD5=m
+ help
+ Enable the use of HMAC-MD5 during association establishment. It is
+ advised to use either HMAC-MD5 or HMAC-SHA1.
+endchoice
+endmenu
diff --git a/net/sctp/Makefile b/net/sctp/Makefile
index 545fad836084..96f3a421379f 100644
--- a/net/sctp/Makefile
+++ b/net/sctp/Makefile
@@ -9,8 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
transport.o sm_make_chunk.o ulpevent.o \
inqueue.o outqueue.o ulpqueue.o command.o \
tsnmap.o bind_addr.o socket.o primitive.o \
- output.o input.o hashdriver.o sla1.o \
- debug.o ssnmap.o proc.o
+ output.o input.o debug.o ssnmap.o proc.o
ifeq ($(CONFIG_SCTP_ADLER32), y)
sctp-y += adler32.o
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 6ffeb79ba851..6264095aabe9 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -96,6 +96,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
int priority)
{
struct sctp_opt *sp;
+ struct sctp_protocol *proto = sctp_get_protocol();
int i;
/* Retrieve the SCTP per socket area. */
@@ -136,10 +137,10 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->frag_point = 0;
/* Initialize the default association max_retrans and RTO values. */
- asoc->max_retrans = ep->proto->max_retrans_association;
- asoc->rto_initial = ep->proto->rto_initial;
- asoc->rto_max = ep->proto->rto_max;
- asoc->rto_min = ep->proto->rto_min;
+ asoc->max_retrans = proto->max_retrans_association;
+ asoc->rto_initial = proto->rto_initial;
+ asoc->rto_max = proto->rto_max;
+ asoc->rto_min = proto->rto_min;
asoc->overall_error_threshold = 0;
asoc->overall_error_count = 0;
@@ -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
* in a burst.
*/
- asoc->max_burst = ep->proto->max_burst;
+ asoc->max_burst = proto->max_burst;
/* Copy things from the endpoint. */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 5a1d749da57c..f4bdabee9b05 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -54,27 +54,27 @@
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/random.h> /* get_random_bytes() */
+#include <linux/crypto.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */
-static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep);
+static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
-/* Create a sctp_endpoint_t with all that boring stuff initialized.
+/* Create a sctp_endpoint with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
-sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
- struct sock *sk, int priority)
+struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
{
- sctp_endpoint_t *ep;
+ struct sctp_endpoint *ep;
/* Build a local endpoint. */
- ep = t_new(sctp_endpoint_t, priority);
+ ep = t_new(struct sctp_endpoint, gfp);
if (!ep)
goto fail;
- if (!sctp_endpoint_init(ep, proto, sk, priority))
+ if (!sctp_endpoint_init(ep, sk, gfp))
goto fail_init;
ep->base.malloced = 1;
SCTP_DBG_OBJCNT_INC(ep);
@@ -89,12 +89,11 @@ fail:
/*
* Initialize the base fields of the endpoint structure.
*/
-sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
- struct sctp_protocol *proto,
- struct sock *sk, int priority)
+struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
+ struct sock *sk, int gfp)
{
struct sctp_opt *sp = sctp_sk(sk);
- memset(ep, 0, sizeof(sctp_endpoint_t));
+ memset(ep, 0, sizeof(struct sctp_endpoint));
/* Initialize the base structure. */
/* What type of endpoint are we? */
@@ -110,8 +109,7 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
/* Set its top-half handler */
sctp_inq_set_th_handler(&ep->base.inqueue,
- (void (*)(void *))sctp_endpoint_bh_rcv,
- ep);
+ (void (*)(void *))sctp_endpoint_bh_rcv, ep);
/* Initialize the bind addr area */
sctp_bind_addr_init(&ep->base.bind_addr, 0);
@@ -121,21 +119,16 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->base.sk = sk;
sock_hold(ep->base.sk);
- /* This pointer is useful to access the default protocol parameter
- * values.
- */
- ep->proto = proto;
-
/* Create the lists of associations. */
INIT_LIST_HEAD(&ep->asocs);
/* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
- ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
- ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
SCTP_DEFAULT_TIMEOUT_T1_INIT;
- ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
@@ -146,11 +139,11 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
= 5 * sp->rtoinfo.srto_max;
- ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
+ ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
- ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
+ ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
SCTP_DEFAULT_TIMEOUT_SACK;
- ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
+ ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
/* Set up the default send/receive buffer space. */
@@ -175,7 +168,8 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
}
/* Add an association to an endpoint. */
-void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
+void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
+ struct sctp_association *asoc)
{
struct sock *sk = ep->base.sk;
@@ -191,14 +185,14 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
/* Free the endpoint structure. Delay cleanup until
* all users have released their reference count on this structure.
*/
-void sctp_endpoint_free(sctp_endpoint_t *ep)
+void sctp_endpoint_free(struct sctp_endpoint *ep)
{
ep->base.dead = 1;
sctp_endpoint_put(ep);
}
/* Final destructor for endpoint. */
-void sctp_endpoint_destroy(sctp_endpoint_t *ep)
+void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
@@ -207,9 +201,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
/* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint(ep);
- /* Cleanup the inqueue. */
- sctp_inq_free(&ep->base.inqueue);
+ /* Free up the HMAC transform. */
+ if (sctp_sk(ep->base.sk)->hmac)
+ crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
+ /* Cleanup. */
+ sctp_inq_free(&ep->base.inqueue);
sctp_bind_addr_free(&ep->base.bind_addr);
/* Remove and free the port */
@@ -228,7 +225,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
}
/* Hold a reference to an endpoint. */
-void sctp_endpoint_hold(sctp_endpoint_t *ep)
+void sctp_endpoint_hold(struct sctp_endpoint *ep)
{
atomic_inc(&ep->base.refcnt);
}
@@ -236,17 +233,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep)
/* Release a reference to an endpoint and clean up if there are
* no more references.
*/
-void sctp_endpoint_put(sctp_endpoint_t *ep)
+void sctp_endpoint_put(struct sctp_endpoint *ep)
{
if (atomic_dec_and_test(&ep->base.refcnt))
sctp_endpoint_destroy(ep);
}
/* Is this the endpoint we are looking for? */
-sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
- const union sctp_addr *laddr)
+struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
+ const union sctp_addr *laddr)
{
- sctp_endpoint_t *retval;
+ struct sctp_endpoint *retval;
sctp_read_lock(&ep->base.addr_lock);
if (ep->base.bind_addr.port == laddr->v4.sin_port) {
@@ -268,19 +265,19 @@ out:
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
-sctp_association_t *__sctp_endpoint_lookup_assoc(
- const sctp_endpoint_t *endpoint,
+struct sctp_association *__sctp_endpoint_lookup_assoc(
+ const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
int rport;
- sctp_association_t *asoc;
+ struct sctp_association *asoc;
struct list_head *pos;
rport = paddr->v4.sin_port;
- list_for_each(pos, &endpoint->asocs) {
- asoc = list_entry(pos, sctp_association_t, asocs);
+ list_for_each(pos, &ep->asocs) {
+ asoc = list_entry(pos, struct sctp_association, asocs);
if (rport == asoc->peer.port) {
sctp_read_lock(&asoc->base.addr_lock);
*transport = sctp_assoc_lookup_paddr(asoc, paddr);
@@ -296,12 +293,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc(
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
-sctp_association_t *sctp_endpoint_lookup_assoc(
- const sctp_endpoint_t *ep,
+struct sctp_association *sctp_endpoint_lookup_assoc(
+ const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
- sctp_association_t *asoc;
+ struct sctp_association *asoc;
sctp_local_bh_disable();
asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport);
@@ -313,7 +310,7 @@ sctp_association_t *sctp_endpoint_lookup_assoc(
/* Look for any peeled off association from the endpoint that matches the
* given peer address.
*/
-int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
+int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
const union sctp_addr *paddr)
{
struct list_head *pos;
@@ -337,9 +334,9 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
/* Do delayed input processing. This is scheduled by sctp_rcv().
* This may be called on BH or task time.
*/
-static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
+static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
{
- sctp_association_t *asoc;
+ struct sctp_association *asoc;
struct sock *sk;
struct sctp_transport *transport;
sctp_chunk_t *chunk;
@@ -355,7 +352,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
inqueue = &ep->base.inqueue;
sk = ep->base.sk;
- while (NULL != (chunk = sctp_inq_pop(inqueue))) {
+ while (NULL != (chunk = sctp_inq_pop(inqueue))) {
subtype.chunk = chunk->chunk_hdr->type;
/* We might have grown an association since last we
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index fb373acf5eb4..87dc7ad07583 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -59,6 +59,8 @@
#include <linux/ipv6.h>
#include <linux/net.h>
#include <linux/inet.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
#include <net/sock.h>
#include <linux/skbuff.h>
@@ -156,7 +158,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
* Host Name Address (Note 3) Optional 11
* 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,
int gfp, int vparam_len)
{
@@ -236,7 +238,7 @@ nodata:
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,
int gfp, int unkparam_len)
{
@@ -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);
/* 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
*
@@ -350,7 +352,7 @@ nomem_rawaddr:
* An implementation SHOULD make the cookie as small as possible
* 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)
{
sctp_chunk_t *retval;
@@ -401,7 +403,7 @@ nodata:
*
* 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)
{
sctp_chunk_t *retval;
@@ -446,7 +448,7 @@ sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *asoc,
*
* 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 sctp_chunk_t *chunk)
{
@@ -481,7 +483,7 @@ nodata:
}
/* 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)
{
sctp_chunk_t *retval;
@@ -502,7 +504,7 @@ nodata:
/* Make a DATA chunk for the given association from the provided
* 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,
int data_len, __u8 flags, __u16 ssn)
{
@@ -537,7 +539,7 @@ nodata:
/* Make a DATA chunk for the given association. Populate the data
* 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,
int data_len, const __u8 *data,
__u8 flags, __u16 ssn)
@@ -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
* '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,
int data_len, const __u8 *data)
{
@@ -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
* 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,
int data_len)
{
@@ -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,
* 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_sackhdr_t sack;
@@ -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);
/* Count the number of Gap Ack Blocks. */
- sctp_tsnmap_iter_init(map, &iter);
- for (num_gabs = 0;
- sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end);
- num_gabs++) {
- /* Do nothing. */
+ num_gabs = 0;
+
+ if (sctp_tsnmap_has_gap(map)) {
+ sctp_tsnmap_iter_init(map, &iter);
+ while (sctp_tsnmap_next_gap_ack(map, &iter,
+ &gab.start, &gab.end))
+ num_gabs++;
}
num_dup_tsns = sctp_tsnmap_num_dups(map);
@@ -659,11 +663,15 @@ sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
sctp_addto_chunk(retval, sizeof(sack), &sack);
/* Put the Gap Ack Blocks into the chunk. */
- sctp_tsnmap_iter_init(map, &iter);
- while(sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end)) {
- gab.start = htons(gab.start);
- gab.end = htons(gab.end);
- sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t), &gab);
+ if (num_gabs) {
+ sctp_tsnmap_iter_init(map, &iter);
+ while(sctp_tsnmap_next_gap_ack(map, &iter,
+ &gab.start, &gab.end)) {
+ gab.start = htons(gab.start);
+ gab.end = htons(gab.end);
+ sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t),
+ &gab);
+ }
}
/* Register the duplicates. */
@@ -675,7 +683,7 @@ nodata:
}
/* 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_shutdownhdr_t shut;
@@ -695,7 +703,7 @@ nodata:
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)
{
sctp_chunk_t *retval;
@@ -717,7 +725,7 @@ sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc,
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)
{
sctp_chunk_t *retval;
@@ -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
* 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 size_t hint)
{
@@ -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. */
-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)
{
sctp_chunk_t *retval;
@@ -809,7 +817,7 @@ no_mem:
}
/* 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 struct msghdr *msg)
{
@@ -856,7 +864,7 @@ err_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 void *payload, const size_t paylen)
{
@@ -876,7 +884,7 @@ nodata:
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 void *payload, const size_t paylen)
{
@@ -906,7 +914,7 @@ nodata:
/* Create an Operation Error chunk with the specified space reserved.
* 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,
size_t size)
{
@@ -933,7 +941,7 @@ nodata:
}
/* 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,
__u16 cause_code, const void *payload,
size_t paylen)
@@ -956,7 +964,8 @@ nodata:
/* Turn an skb into a chunk.
* 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)
{
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,
}
retval->skb = skb;
- retval->asoc = (sctp_association_t *) asoc;
+ retval->asoc = (struct sctp_association *)asoc;
retval->num_times_sent = 0;
retval->has_tsn = 0;
retval->has_ssn = 0;
@@ -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
* 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)
{
sctp_chunk_t *retval;
@@ -1032,7 +1041,7 @@ sctp_chunk_t *sctp_make_chunk(const sctp_association_t *asoc,
struct sock *sk;
/* 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);
if (!skb)
goto nodata;
@@ -1135,7 +1144,7 @@ out:
*/
-int sctp_datachunks_from_user(sctp_association_t *asoc,
+int sctp_datachunks_from_user(struct sctp_association *asoc,
const struct sctp_sndrcvinfo *sinfo,
struct msghdr *msg, int msg_len,
struct sk_buff_head *chunks)
@@ -1291,10 +1300,10 @@ void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
}
/* 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)
{
- sctp_association_t *asoc;
+ struct sctp_association *asoc;
struct sk_buff *skb;
sctp_scope_t scope;
@@ -1339,15 +1348,18 @@ fail:
/* Build a cookie representing asoc.
* 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,
- const sctp_association_t *asoc,
+sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
const sctp_chunk_t *init_chunk,
int *cookie_len,
const __u8 *raw_addrs, int addrs_len)
{
sctp_cookie_param_t *retval;
sctp_signed_cookie_t *cookie;
+ struct scatterlist sg;
int headersize, bodysize;
+ unsigned int keylen = SCTP_SECRET_SIZE;
+ char *key;
headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
bodysize = sizeof(sctp_cookie_t)
@@ -1361,8 +1373,8 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
- (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize;
- retval = (sctp_cookie_param_t *)
- kmalloc(*cookie_len, GFP_ATOMIC);
+ retval = (sctp_cookie_param_t *)kmalloc(*cookie_len, GFP_ATOMIC);
+
if (!retval) {
*cookie_len = 0;
goto nodata;
@@ -1392,31 +1404,39 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
ntohs(init_chunk->chunk_hdr->length));
/* Copy the raw local address list of the association. */
- memcpy((__u8 *)&cookie->c.peer_init[0] +
- ntohs(init_chunk->chunk_hdr->length), raw_addrs,
- addrs_len);
-
- /* Sign the message. */
- sctp_hash_digest(ep->secret_key[ep->current_key], SCTP_SECRET_SIZE,
- (__u8 *) &cookie->c, bodysize, cookie->signature);
+ memcpy((__u8 *)&cookie->c.peer_init[0] +
+ ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
+
+ if (sctp_sk(ep->base.sk)->hmac) {
+ /* Sign the message. */
+ sg.page = virt_to_page(&cookie->c);
+ 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:
return retval;
}
/* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */
-sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
- const sctp_association_t *asoc,
- sctp_chunk_t *chunk, int gfp,
- int *error, sctp_chunk_t **err_chk_p)
+struct sctp_association *sctp_unpack_cookie(
+ const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ 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_cookie_t *bear_cookie;
- int headersize, bodysize;
- int fixed_size;
- __u8 digest_buf[SCTP_SIGNATURE_SIZE];
- int secret;
+ int headersize, bodysize, fixed_size;
+ __u8 digest[SCTP_SIGNATURE_SIZE];
+ struct scatterlist sg;
+ unsigned int keylen;
+ char *key;
sctp_scope_t scope;
struct sk_buff *skb = chunk->skb;
@@ -1440,23 +1460,34 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
cookie = chunk->subh.cookie_hdr;
bear_cookie = &cookie->c;
+ if (!sctp_sk(ep->base.sk)->hmac)
+ goto no_hmac;
+
/* Check the signature. */
- secret = ep->current_key;
- sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE,
- (__u8 *) bear_cookie, bodysize,
- digest_buf);
- if (memcmp(digest_buf, cookie->signature, SCTP_SIGNATURE_SIZE)) {
- /* Try the previous key. */
- secret = ep->last_key;
- sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE,
- (__u8 *) bear_cookie, bodysize, digest_buf);
- if (memcmp(digest_buf, cookie->signature, SCTP_SIGNATURE_SIZE)) {
+ keylen = SCTP_SECRET_SIZE;
+ sg.page = virt_to_page(bear_cookie);
+ sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE;
+ sg.length = bodysize;
+ key = (char *)ep->secret_key[ep->current_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)) {
+ /* 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! */
*error = -SCTP_IERROR_BAD_SIG;
goto fail;
}
}
+no_hmac:
/* Check to see if the cookie is stale. If there is already
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
@@ -1472,15 +1503,15 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* Cookie that has expired.
*/
len = ntohs(chunk->chunk_hdr->length);
- *err_chk_p = sctp_make_op_error_space(asoc, chunk, len);
- if (*err_chk_p) {
+ *errp = sctp_make_op_error_space(asoc, chunk, len);
+ if (*errp) {
suseconds_t usecs = (skb->stamp.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L +
skb->stamp.tv_usec -
bear_cookie->expiration.tv_usec;
usecs = htonl(usecs);
- sctp_init_cause(*err_chk_p, SCTP_ERROR_STALE_COOKIE,
+ sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
&usecs, sizeof(usecs));
*error = -SCTP_IERROR_STALE_COOKIE;
} else
@@ -1541,10 +1572,10 @@ struct __sctp_missing {
/*
* 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_chunk_t *chunk,
- sctp_chunk_t **err_chk_p)
+ sctp_chunk_t **errp)
{
struct __sctp_missing report;
__u16 len;
@@ -1554,13 +1585,13 @@ static int sctp_process_missing_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
- if (!*err_chk_p)
- *err_chk_p = sctp_make_op_error_space(asoc, chunk, len);
+ if (!*errp)
+ *errp = sctp_make_op_error_space(asoc, chunk, len);
- if (*err_chk_p) {
+ if (*errp) {
report.num_missing = htonl(1);
report.type = paramtype;
- sctp_init_cause(*err_chk_p, SCTP_ERROR_INV_PARAM,
+ sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM,
&report, sizeof(report));
}
@@ -1569,17 +1600,17 @@ static int sctp_process_missing_param(const sctp_association_t *asoc,
}
/* 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 **err_chk_p)
+ sctp_chunk_t **errp)
{
/* Invalid Mandatory Parameter Error has no payload. */
- if (!*err_chk_p)
- *err_chk_p = sctp_make_op_error_space(asoc, chunk, 0);
+ if (!*errp)
+ *errp = sctp_make_op_error_space(asoc, chunk, 0);
- if (*err_chk_p)
- sctp_init_cause(*err_chk_p, SCTP_ERROR_INV_PARAM, NULL, 0);
+ if (*errp)
+ sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0);
/* Stop processing this chunk. */
return 0;
@@ -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
* 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,
sctp_chunk_t *chunk,
- sctp_chunk_t **err_chk_p)
+ sctp_chunk_t **errp)
{
__u16 len = ntohs(param.p->length);
/* Make an ERROR chunk. */
- if (!*err_chk_p)
- *err_chk_p = sctp_make_op_error_space(asoc, chunk, len);
+ if (!*errp)
+ *errp = sctp_make_op_error_space(asoc, chunk, len);
- if (*err_chk_p)
- sctp_init_cause(*err_chk_p, SCTP_ERROR_DNS_FAILED,
+ if (*errp)
+ sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED,
param.v, len);
/* Stop processing this chunk. */
@@ -1633,10 +1664,10 @@ static int sctp_process_hn_param(const sctp_association_t *asoc,
* 0 - discard 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,
sctp_chunk_t *chunk,
- sctp_chunk_t **err_chk_p)
+ sctp_chunk_t **errp)
{
int retval = 1;
@@ -1649,12 +1680,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
- if (NULL == *err_chk_p)
- *err_chk_p = sctp_make_op_error_space(asoc, chunk,
+ if (NULL == *errp)
+ *errp = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length));
- if (*err_chk_p)
- sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM,
+ if (*errp)
+ sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
param.v,
WORD_ROUND(ntohs(param.p->length)));
@@ -1665,12 +1696,12 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
- if (NULL == *err_chk_p)
- *err_chk_p = sctp_make_op_error_space(asoc, chunk,
+ if (NULL == *errp)
+ *errp = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length));
- if (*err_chk_p) {
- sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM,
+ if (*errp) {
+ sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
param.v,
WORD_ROUND(ntohs(param.p->length)));
} else {
@@ -1695,7 +1726,7 @@ static int sctp_process_unk_param(const sctp_association_t *asoc,
* 0 - discard 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,
sctp_cid_t cid,
sctp_chunk_t *chunk,
@@ -1733,11 +1764,11 @@ static int sctp_verify_param(const sctp_association_t *asoc,
}
/* 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_init_chunk_t *peer_init,
sctp_chunk_t *chunk,
- sctp_chunk_t **err_chk_p)
+ sctp_chunk_t **errp)
{
union sctp_params param;
int has_cookie = 0;
@@ -1746,7 +1777,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
if ((0 == peer_init->init_hdr.num_outbound_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;
}
@@ -1762,9 +1793,8 @@ int sctp_verify_init(const sctp_association_t *asoc,
* the state cookie for an INIT-ACK chunk.
*/
if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {
-
sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
- chunk, err_chk_p);
+ chunk, errp);
return 0;
}
@@ -1772,7 +1802,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
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;
} /* for (loop through all parameters) */
@@ -1784,7 +1814,7 @@ int sctp_verify_init(const sctp_association_t *asoc,
* Returns 0 on failure, else success.
* 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,
sctp_init_chunk_t *peer_init, int gfp)
{
@@ -1923,7 +1953,7 @@ nomem:
* work we do. In particular, we should not build transport
* 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)
{
union sctp_addr addr;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index ab54b2b63ed6..de5e9ddfd9b4 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -55,7 +55,6 @@
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/time.h>
@@ -63,6 +62,7 @@
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/crypto.h>
#include <net/ip.h>
#include <net/icmp.h>
@@ -96,15 +96,16 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
static int sctp_autobind(struct sock *sk);
static void sctp_sock_migrate(struct sock *, struct sock *,
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
* 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.
*/
if (SCTP_SOCKET_UDP != sctp_sk(sk)->type) {
@@ -116,9 +117,9 @@ sctp_association_t *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
/* First, verify that this is a kernel address. */
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.
*/
if ((SCTP_ASSOC_EYECATCHER == temp->eyecatcher) &&
@@ -188,7 +189,6 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt,
return af;
}
-
/* 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)
{
@@ -637,7 +637,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
/* Alloc space for the address array in kernel memory. */
kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL);
- if (unlikely(NULL == kaddrs))
+ if (unlikely(!kaddrs))
return -ENOMEM;
if (copy_from_user(kaddrs, addrs, addrssize)) {
@@ -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 *);
-SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
- int len, int noblock, int flags, int *addr_len)
+SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, int len, int noblock,
+ int flags, int *addr_len)
{
struct sctp_ulpevent *event = NULL;
struct sctp_opt *sp = sctp_sk(sk);
@@ -1156,7 +1157,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr
err = -ENOTCONN;
goto out;
}
-
+
skb = sctp_skb_recv_datagram(sk, flags, noblock, &err);
if (!skb)
goto out;
@@ -1271,7 +1272,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval,
}
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
- char *optval, int optlen)
+ char *optval, int optlen)
{
struct sctp_paddrparams params;
sctp_association_t *asoc;
@@ -1329,8 +1330,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
return 0;
}
-static int sctp_setsockopt_initmsg(struct sock *sk, char *optval,
- int optlen)
+static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen)
{
if (optlen != sizeof(struct sctp_initmsg))
return -EINVAL;
@@ -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)
*
* 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,
if (optlen < sizeof(__u8))
return -EINVAL;
-
if (get_user(val, (__u8 *)optval))
return -EFAULT;
sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1;
-
return 0;
}
@@ -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
* 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.
*/
if ((SCTP_SS_ESTABLISHED == sk->state) ||
@@ -1690,10 +1687,10 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
struct sctp_opt *sp;
struct sctp_endpoint *ep;
struct sock *newsk = NULL;
- struct sctp_association *assoc;
+ struct sctp_association *asoc;
long timeo;
int error = 0;
-
+
sctp_lock_sock(sk);
sp = sctp_sk(sk);
@@ -1715,21 +1712,21 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
if (error)
goto out;
- /* We treat the list of associations on the endpoint as the accept
- * queue and pick the first association on the list.
+ /* We treat the list of associations on the endpoint as the accept
+ * 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) {
error = -ENOMEM;
goto out;
}
/* Populate the fields of the newsk from the oldsk and migrate the
- * assoc to the newsk.
- */
- sctp_sock_migrate(sk, newsk, assoc, SCTP_SOCKET_TCP);
+ * asoc to the newsk.
+ */
+ sctp_sock_migrate(sk, newsk, asoc, SCTP_SOCKET_TCP);
out:
sctp_release_sock(sk);
@@ -1737,10 +1734,10 @@ out:
return newsk;
}
-/* FIXME: Write Comments. */
+/* The SCTP ioctl handler. */
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
@@ -1835,11 +1832,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
* change the data structure relationships, this may still
* be useful for storing pre-connect address information.
*/
- ep = sctp_endpoint_new(proto, sk, GFP_KERNEL);
- if (NULL == ep)
+ ep = sctp_endpoint_new(sk, GFP_KERNEL);
+ if (!ep)
return -ENOMEM;
sp->ep = ep;
+ sp->hmac = NULL;
SCTP_DBG_OBJCNT_INC(sock);
return 0;
@@ -1848,7 +1846,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Cleanup any SCTP per socket resources. */
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);
@@ -1877,7 +1875,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
int *optlen)
{
struct sctp_status status;
- sctp_association_t *assoc = NULL;
+ struct sctp_association *asoc = NULL;
struct sctp_transport *transport;
sctp_assoc_t associd;
int retval = 0;
@@ -1893,22 +1891,22 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
}
associd = status.sstat_assoc_id;
- assoc = sctp_id2assoc(sk, associd);
- if (!assoc) {
+ asoc = sctp_id2assoc(sk, associd);
+ if (!asoc) {
retval = -EINVAL;
goto out;
}
- transport = assoc->peer.primary_path;
+ transport = asoc->peer.primary_path;
- status.sstat_assoc_id = sctp_assoc2id(assoc);
- status.sstat_state = assoc->state;
- status.sstat_rwnd = assoc->peer.rwnd;
- status.sstat_unackdata = assoc->unack_data;
- status.sstat_penddata = assoc->peer.tsn_map.pending_data;
- status.sstat_instrms = assoc->c.sinit_max_instreams;
- status.sstat_outstrms = assoc->c.sinit_num_ostreams;
- status.sstat_fragmentation_point = assoc->frag_point;
+ status.sstat_assoc_id = sctp_assoc2id(asoc);
+ status.sstat_state = asoc->state;
+ status.sstat_rwnd = asoc->peer.rwnd;
+ status.sstat_unackdata = asoc->unack_data;
+ status.sstat_penddata = asoc->peer.tsn_map.pending_data;
+ status.sstat_instrms = asoc->c.sinit_max_instreams;
+ status.sstat_outstrms = asoc->c.sinit_num_ostreams;
+ status.sstat_fragmentation_point = asoc->frag_point;
status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
memcpy(&status.sstat_primary.spinfo_address,
&(transport->ipaddr), sizeof(union sctp_addr));
@@ -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. */
-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 *newsk;
- struct socket *tmpsock;
+ struct sock *sk = asoc->base.sk;
+ struct socket *sock;
int err = 0;
/* An association cannot be branched off from an already peeled-off
* socket, nor is this supported for tcp style sockets.
*/
- if (SCTP_SOCKET_UDP != sctp_sk(oldsk)->type)
- return -EOPNOTSUPP;
+ if (SCTP_SOCKET_UDP != sctp_sk(sk)->type)
+ return -EINVAL;
/* Create a new socket. */
- err = sock_create(oldsk->family, SOCK_SEQPACKET, IPPROTO_SCTP,
- &tmpsock);
+ err = sock_create(sk->family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
if (err < 0)
return err;
- newsk = tmpsock->sk;
-
/* Populate the fields of the newsk from the oldsk and migrate the
* assoc to the newsk.
- */
- sctp_sock_migrate(oldsk, newsk, assoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
-
- *newsock = tmpsock;
+ */
+ sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
+ *sockp = sock;
return err;
}
@@ -2019,7 +2013,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char *optval, int *
return -EFAULT;
assoc = sctp_id2assoc(sk, peeloff.associd);
- if (NULL == assoc) {
+ if (!assoc) {
retval = -EINVAL;
goto out;
}
@@ -2049,7 +2043,7 @@ out:
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)
{
struct sctp_paddrparams params;
@@ -2102,7 +2096,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *
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)
{
sctp_assoc_t id;
@@ -2350,7 +2344,7 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
* 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)
{
__u8 val;
@@ -2418,7 +2412,7 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
break;
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);
break;
case SCTP_GET_LOCAL_ADDRS_NUM:
@@ -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
* available port (pp != NULL) and it is being
* 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)
/* If there was a hash table miss, create a new port. */
ret = 1;
- if (pp == NULL && (pp = sctp_bucket_create(head, snum)) == NULL)
+ if (!pp && !(pp = sctp_bucket_create(head, snum)))
goto fail_unlock;
/* In either case (hit or miss), make sure fastreuse is 1 only
* if sk->reuse is too (that is, if the caller requested
* SO_REUSEADDR on this socket -sk-).
*/
- if (pp->sk == NULL) {
+ if (!pp->sk)
pp->fastreuse = sk->reuse ? 1 : 0;
- } else if (pp->fastreuse && sk->reuse == 0) {
+ else if (pp->fastreuse && sk->reuse == 0)
pp->fastreuse = 0;
- }
/* We are set, so fill up all the data in the hash table
* 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)
/*
* 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.
*/
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)
{
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);
- err = -EINVAL;
if (sock->state != SS_UNCONNECTED)
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) {
case SOCK_SEQPACKET:
@@ -2756,14 +2759,21 @@ int sctp_inet_listen(struct socket *sock, int backlog)
case SOCK_STREAM:
err = sctp_stream_listen(sk, backlog);
break;
-
default:
- goto out;
+ break;
};
+ if (err)
+ goto cleanup;
+ /* Store away the transform reference. */
+ sctp_sk(sk)->hmac = tfm;
out:
sctp_release_sock(sk);
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,
/* Strictly check lengths following example in SCM code. */
switch (cmsg->cmsg_type) {
case SCTP_INIT:
- /* SCTP Socket API Extension (draft 1)
+ /* SCTP Socket API Extension
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
*
* This cmsghdr structure provides information for
@@ -2987,7 +2997,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
break;
case SCTP_SNDRCV:
- /* SCTP Socket API Extension (draft 1)
+ /* SCTP Socket API Extension
* 5.2.2 SCTP Header Information Structure(SCTP_SNDRCV)
*
* This cmsghdr structure specifies SCTP options for
@@ -3002,7 +3012,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
return -EINVAL;
- cmsgs->info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+ cmsgs->info =
+ (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
/* Minimally, validate the sinfo_flags. */
if (cmsgs->info->sinfo_flags &
@@ -3085,13 +3096,14 @@ out:
* Note: This is pretty much the same routine as in core/datagram.c
* 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;
struct sk_buff *skb;
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);
if (error)
goto no_packet;
@@ -3140,7 +3152,7 @@ no_packet:
}
/* 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)
{
struct sctp_af *af;
@@ -3443,11 +3455,12 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo)
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.
- */
-void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
- struct sctp_association *assoc, sctp_socket_type_t type)
+ */
+static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
+ struct sctp_association *assoc,
+ sctp_socket_type_t type)
{
struct sctp_opt *oldsp = sctp_sk(oldsk);
struct sctp_opt *newsp = sctp_sk(newsk);
@@ -3466,6 +3479,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
* copy.
*/
newsp->ep = newep;
+ newsp->hmac = NULL;
/* Move any messages in the old socket's receive queue that are for the
* peeled off association to the new socket's receive queue.
@@ -3526,7 +3540,7 @@ void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsk->state = SCTP_SS_ESTABLISHED;
}
-
+
/* This proto struct describes the ULP interface for SCTP. */
struct proto sctp_prot = {
.name = "SCTP",