aboutsummaryrefslogtreecommitdiff
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/Kconfig6
-rw-r--r--net/sctp/associola.c5
-rw-r--r--net/sctp/auth.c31
-rw-r--r--net/sctp/endpointola.c6
-rw-r--r--net/sctp/input.c3
-rw-r--r--net/sctp/ipv6.c5
-rw-r--r--net/sctp/outqueue.c16
-rw-r--r--net/sctp/probe.c27
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/sm_make_chunk.c33
-rw-r--r--net/sctp/sm_sideeffect.c6
-rw-r--r--net/sctp/sm_statefuns.c4
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/sctp/sysctl.c4
-rw-r--r--net/sctp/transport.c20
15 files changed, 82 insertions, 88 deletions
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig
index c26210618e1..cf4852814e0 100644
--- a/net/sctp/Kconfig
+++ b/net/sctp/Kconfig
@@ -3,8 +3,8 @@
#
menuconfig IP_SCTP
- tristate "The SCTP Protocol (EXPERIMENTAL)"
- depends on INET && EXPERIMENTAL
+ tristate "The SCTP Protocol"
+ depends on INET
depends on IPV6 || IPV6=n
select CRYPTO
select CRYPTO_HMAC
@@ -68,7 +68,7 @@ config SCTP_DBG_OBJCNT
If unsure, say N
choice
prompt "Default SCTP cookie HMAC encoding"
- default SCTP_COOKIE_HMAC_MD5
+ default SCTP_DEFAULT_COOKIE_HMAC_MD5
help
This option sets the default sctp cookie hmac algorithm
when in doubt select 'md5'
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index b45ed1f9692..2f95f5a5145 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -434,8 +434,7 @@ void sctp_association_free(struct sctp_association *asoc)
* on our state.
*/
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
- if (timer_pending(&asoc->timers[i]) &&
- del_timer(&asoc->timers[i]))
+ if (del_timer(&asoc->timers[i]))
sctp_association_put(asoc);
}
@@ -1497,7 +1496,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
/* Stop the SACK timer. */
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_SACK];
- if (timer_pending(timer) && del_timer(timer))
+ if (del_timer(timer))
sctp_association_put(asoc);
}
}
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 159b9bc5d63..ba1dfc3f8de 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -71,7 +71,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)
return;
if (atomic_dec_and_test(&key->refcnt)) {
- kfree(key);
+ kzfree(key);
SCTP_DBG_OBJCNT_DEC(keys);
}
}
@@ -200,27 +200,28 @@ static struct sctp_auth_bytes *sctp_auth_make_key_vector(
struct sctp_auth_bytes *new;
__u32 len;
__u32 offset = 0;
+ __u16 random_len, hmacs_len, chunks_len = 0;
- len = ntohs(random->param_hdr.length) + ntohs(hmacs->param_hdr.length);
- if (chunks)
- len += ntohs(chunks->param_hdr.length);
+ random_len = ntohs(random->param_hdr.length);
+ hmacs_len = ntohs(hmacs->param_hdr.length);
+ if (chunks)
+ chunks_len = ntohs(chunks->param_hdr.length);
- new = kmalloc(sizeof(struct sctp_auth_bytes) + len, gfp);
+ len = random_len + hmacs_len + chunks_len;
+
+ new = sctp_auth_create_key(len, gfp);
if (!new)
return NULL;
- new->len = len;
-
- memcpy(new->data, random, ntohs(random->param_hdr.length));
- offset += ntohs(random->param_hdr.length);
+ memcpy(new->data, random, random_len);
+ offset += random_len;
if (chunks) {
- memcpy(new->data + offset, chunks,
- ntohs(chunks->param_hdr.length));
- offset += ntohs(chunks->param_hdr.length);
+ memcpy(new->data + offset, chunks, chunks_len);
+ offset += chunks_len;
}
- memcpy(new->data + offset, hmacs, ntohs(hmacs->param_hdr.length));
+ memcpy(new->data + offset, hmacs, hmacs_len);
return new;
}
@@ -350,8 +351,8 @@ static struct sctp_auth_bytes *sctp_auth_asoc_create_secret(
secret = sctp_auth_asoc_set_secret(ep_key, first_vector, last_vector,
gfp);
out:
- kfree(local_key_vector);
- kfree(peer_key_vector);
+ sctp_auth_key_put(local_key_vector);
+ sctp_auth_key_put(peer_key_vector);
return secret;
}
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 17a001bac2c..73aad3d16a4 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -151,9 +151,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep->rcvbuf_policy = net->sctp.rcvbuf_policy;
/* Initialize the secret key used with cookie. */
- get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
- ep->last_key = ep->current_key = 0;
- ep->key_changed_at = jiffies;
+ get_random_bytes(ep->secret_key, sizeof(ep->secret_key));
/* SCTP-AUTH extensions*/
INIT_LIST_HEAD(&ep->endpoint_shared_keys);
@@ -271,6 +269,8 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
sctp_inq_free(&ep->base.inqueue);
sctp_bind_addr_free(&ep->base.bind_addr);
+ memset(ep->secret_key, 0, sizeof(ep->secret_key));
+
/* Remove and free the port */
if (sctp_sk(ep->base.sk)->bind_hash)
sctp_put_port(ep->base.sk);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 8bd3c279427..965bbbbe48d 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -468,8 +468,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
} else {
struct net *net = sock_net(sk);
- if (timer_pending(&t->proto_unreach_timer) &&
- del_timer(&t->proto_unreach_timer))
+ if (del_timer(&t->proto_unreach_timer))
sctp_association_put(asoc);
sctp_do_sm(net, SCTP_EVENT_T_OTHER,
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index f3f0f4dc31d..391a245d520 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -326,9 +326,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
*/
rcu_read_lock();
list_for_each_entry_rcu(laddr, &bp->address_list, list) {
- if (!laddr->valid && laddr->state != SCTP_ADDR_SRC)
+ if (!laddr->valid)
continue;
- if ((laddr->a.sa.sa_family == AF_INET6) &&
+ if ((laddr->state == SCTP_ADDR_SRC) &&
+ (laddr->a.sa.sa_family == AF_INET6) &&
(scope <= sctp_scope(&laddr->a))) {
bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
if (!baddr || (matchlen < bmatchlen)) {
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 379c81dee9d..01dca753db1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -224,7 +224,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
/* Free the outqueue structure and any related pending chunks.
*/
-void sctp_outq_teardown(struct sctp_outq *q)
+static void __sctp_outq_teardown(struct sctp_outq *q)
{
struct sctp_transport *transport;
struct list_head *lchunk, *temp;
@@ -277,8 +277,6 @@ void sctp_outq_teardown(struct sctp_outq *q)
sctp_chunk_free(chunk);
}
- q->error = 0;
-
/* Throw away any leftover control chunks. */
list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
list_del_init(&chunk->list);
@@ -286,11 +284,17 @@ void sctp_outq_teardown(struct sctp_outq *q)
}
}
+void sctp_outq_teardown(struct sctp_outq *q)
+{
+ __sctp_outq_teardown(q);
+ sctp_outq_init(q->asoc, q);
+}
+
/* Free the outqueue structure and any related pending chunks. */
void sctp_outq_free(struct sctp_outq *q)
{
/* Throw away leftover chunks. */
- sctp_outq_teardown(q);
+ __sctp_outq_teardown(q);
/* If we were kmalloc()'d, free the memory. */
if (q->malloced)
@@ -1696,10 +1700,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
* address.
*/
if (!transport->flight_size) {
- if (timer_pending(&transport->T3_rtx_timer) &&
- del_timer(&transport->T3_rtx_timer)) {
+ if (del_timer(&transport->T3_rtx_timer))
sctp_transport_put(transport);
- }
} else if (restart_timer) {
if (!mod_timer(&transport->T3_rtx_timer,
jiffies + transport->rto))
diff --git a/net/sctp/probe.c b/net/sctp/probe.c
index 5f7518de2fd..ad0dba87034 100644
--- a/net/sctp/probe.c
+++ b/net/sctp/probe.c
@@ -122,12 +122,12 @@ static const struct file_operations sctpprobe_fops = {
.llseek = noop_llseek,
};
-sctp_disposition_t jsctp_sf_eat_sack(struct net *net,
- const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t jsctp_sf_eat_sack(struct net *net,
+ const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
struct sctp_transport *sp;
static __u32 lcwnd = 0;
@@ -183,13 +183,20 @@ static __init int sctpprobe_init(void)
{
int ret = -ENOMEM;
+ /* Warning: if the function signature of sctp_sf_eat_sack_6_2,
+ * has been changed, you also have to change the signature of
+ * jsctp_sf_eat_sack, otherwise you end up right here!
+ */
+ BUILD_BUG_ON(__same_type(sctp_sf_eat_sack_6_2,
+ jsctp_sf_eat_sack) == 0);
+
init_waitqueue_head(&sctpw.wait);
spin_lock_init(&sctpw.lock);
if (kfifo_alloc(&sctpw.fifo, bufsize, GFP_KERNEL))
return ret;
- if (!proc_net_fops_create(&init_net, procname, S_IRUSR,
- &sctpprobe_fops))
+ if (!proc_create(procname, S_IRUSR, init_net.proc_net,
+ &sctpprobe_fops))
goto free_kfifo;
ret = register_jprobe(&sctp_recv_probe);
@@ -201,7 +208,7 @@ static __init int sctpprobe_init(void)
return 0;
remove_proc:
- proc_net_remove(&init_net, procname);
+ remove_proc_entry(procname, init_net.proc_net);
free_kfifo:
kfifo_free(&sctpw.fifo);
return ret;
@@ -210,7 +217,7 @@ free_kfifo:
static __exit void sctpprobe_exit(void)
{
kfifo_free(&sctpw.fifo);
- proc_net_remove(&init_net, procname);
+ remove_proc_entry(procname, init_net.proc_net);
unregister_jprobe(&sctp_recv_probe);
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index f898b1c58bd..1c2e46cb919 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -595,7 +595,7 @@ static void sctp_v4_ecn_capable(struct sock *sk)
INET_ECN_xmit(sk);
}
-void sctp_addr_wq_timeout_handler(unsigned long arg)
+static void sctp_addr_wq_timeout_handler(unsigned long arg)
{
struct net *net = (struct net *)arg;
struct sctp_sockaddr_entry *addrw, *temp;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index e1c5fc2be6b..cf579e71cff 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1201,7 +1201,7 @@ nodata:
* specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT)
* This is a helper function to allocate an error chunk for
* for those invalid parameter codes in which we may not want
- * to report all the errors, if the incomming chunk is large
+ * to report all the errors, if the incoming chunk is large
*/
static inline struct sctp_chunk *sctp_make_op_error_fixed(
const struct sctp_association *asoc,
@@ -1589,8 +1589,6 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
struct sctp_signed_cookie *cookie;
struct scatterlist sg;
int headersize, bodysize;
- unsigned int keylen;
- char *key;
/* Header size is static data prior to the actual cookie, including
* any padding.
@@ -1650,12 +1648,11 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
/* Sign the message. */
sg_init_one(&sg, &cookie->c, bodysize);
- keylen = SCTP_SECRET_SIZE;
- key = (char *)ep->secret_key[ep->current_key];
desc.tfm = sctp_sk(ep->base.sk)->hmac;
desc.flags = 0;
- if (crypto_hash_setkey(desc.tfm, key, keylen) ||
+ if (crypto_hash_setkey(desc.tfm, ep->secret_key,
+ sizeof(ep->secret_key)) ||
crypto_hash_digest(&desc, &sg, bodysize, cookie->signature))
goto free_cookie;
}
@@ -1682,8 +1679,7 @@ struct sctp_association *sctp_unpack_cookie(
int headersize, bodysize, fixed_size;
__u8 *digest = ep->digest;
struct scatterlist sg;
- unsigned int keylen, len;
- char *key;
+ unsigned int len;
sctp_scope_t scope;
struct sk_buff *skb = chunk->skb;
struct timeval tv;
@@ -1718,34 +1714,21 @@ struct sctp_association *sctp_unpack_cookie(
goto no_hmac;
/* Check the signature. */
- keylen = SCTP_SECRET_SIZE;
sg_init_one(&sg, bear_cookie, bodysize);
- key = (char *)ep->secret_key[ep->current_key];
desc.tfm = sctp_sk(ep->base.sk)->hmac;
desc.flags = 0;
memset(digest, 0x00, SCTP_SIGNATURE_SIZE);
- if (crypto_hash_setkey(desc.tfm, key, keylen) ||
+ if (crypto_hash_setkey(desc.tfm, ep->secret_key,
+ sizeof(ep->secret_key)) ||
crypto_hash_digest(&desc, &sg, bodysize, digest)) {
*error = -SCTP_IERROR_NOMEM;
goto fail;
}
if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
- /* Try the previous key. */
- key = (char *)ep->secret_key[ep->last_key];
- memset(digest, 0x00, SCTP_SIGNATURE_SIZE);
- if (crypto_hash_setkey(desc.tfm, key, keylen) ||
- crypto_hash_digest(&desc, &sg, bodysize, digest)) {
- *error = -SCTP_IERROR_NOMEM;
- goto fail;
- }
-
- if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
- /* Yikes! Still bad signature! */
- *error = -SCTP_IERROR_BAD_SIG;
- goto fail;
- }
+ *error = -SCTP_IERROR_BAD_SIG;
+ goto fail;
}
no_hmac:
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index c9577754a70..8aab894aeab 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -674,10 +674,8 @@ static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
list_for_each_entry(t, &asoc->peer.transport_addr_list,
transports) {
- if (timer_pending(&t->T3_rtx_timer) &&
- del_timer(&t->T3_rtx_timer)) {
+ if (del_timer(&t->T3_rtx_timer))
sctp_transport_put(t);
- }
}
}
@@ -1517,7 +1515,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_TIMER_STOP:
timer = &asoc->timers[cmd->obj.to];
- if (timer_pending(timer) && del_timer(timer))
+ if (del_timer(timer))
sctp_association_put(asoc);
break;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 618ec7e216c..5131fcfedb0 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1779,8 +1779,10 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
/* Update the content of current association. */
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+ SCTP_STATE(SCTP_STATE_ESTABLISHED));
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
return SCTP_DISPOSITION_CONSUME;
nomem_ev:
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9e65758cb03..cedd9bf67b8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3390,7 +3390,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey);
out:
- kfree(authkey);
+ kzfree(authkey);
return ret;
}
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 043889ac86c..bf3c6e8fc40 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -366,7 +366,11 @@ int sctp_sysctl_net_register(struct net *net)
void sctp_sysctl_net_unregister(struct net *net)
{
+ struct ctl_table *table;
+
+ table = net->sctp.sysctl_header->ctl_table_arg;
unregister_net_sysctl_table(net->sctp.sysctl_header);
+ kfree(table);
}
static struct ctl_table_header * sctp_sysctl_header;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 4e45bb68aef..fafd2a461ba 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -151,13 +151,11 @@ void sctp_transport_free(struct sctp_transport *transport)
* structure hang around in memory since we know
* the tranport is going away.
*/
- if (timer_pending(&transport->T3_rtx_timer) &&
- del_timer(&transport->T3_rtx_timer))
+ if (del_timer(&transport->T3_rtx_timer))
sctp_transport_put(transport);
/* Delete the ICMP proto unreachable timer if it's active. */
- if (timer_pending(&transport->proto_unreach_timer) &&
- del_timer(&transport->proto_unreach_timer))
+ if (del_timer(&transport->proto_unreach_timer))
sctp_association_put(transport->asoc);
sctp_transport_put(transport);
@@ -168,10 +166,6 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head)
struct sctp_transport *transport;
transport = container_of(head, struct sctp_transport, rcu);
- if (transport->asoc)
- sctp_association_put(transport->asoc);
-
- sctp_packet_free(&transport->packet);
dst_release(transport->dst);
kfree(transport);
@@ -186,6 +180,11 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
SCTP_ASSERT(transport->dead, "Transport is not dead", return);
call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
+
+ sctp_packet_free(&transport->packet);
+
+ if (transport->asoc)
+ sctp_association_put(transport->asoc);
}
/* Start T3_rtx timer if it is not already running and update the heartbeat
@@ -654,10 +653,9 @@ void sctp_transport_reset(struct sctp_transport *t)
void sctp_transport_immediate_rtx(struct sctp_transport *t)
{
/* Stop pending T3_rtx_timer */
- if (timer_pending(&t->T3_rtx_timer)) {
- (void)del_timer(&t->T3_rtx_timer);
+ if (del_timer(&t->T3_rtx_timer))
sctp_transport_put(t);
- }
+
sctp_retransmit(&t->asoc->outqueue, t, SCTP_RTXR_T3_RTX);
if (!timer_pending(&t->T3_rtx_timer)) {
if (!mod_timer(&t->T3_rtx_timer, jiffies + t->rto))