diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 4 | ||||
-rw-r--r-- | net/sctp/bind_addr.c | 3 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 5 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 5 | ||||
-rw-r--r-- | net/sctp/offload.c | 2 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 2 | ||||
-rw-r--r-- | net/sctp/protocol.c | 40 | ||||
-rw-r--r-- | net/sctp/socket.c | 16 | ||||
-rw-r--r-- | net/sctp/transport.c | 2 |
9 files changed, 47 insertions, 32 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 68428e1f7181..d3cc30c25c41 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1471,7 +1471,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) * threshold. The idea is to recover slowly, but up * to the initial advertised window. */ - if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { + if (asoc->rwnd_press) { int change = min(asoc->pathmtu, asoc->rwnd_press); asoc->rwnd += change; asoc->rwnd_press -= change; @@ -1539,7 +1539,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) asoc->rwnd = 0; } } else { - asoc->rwnd_over = len - asoc->rwnd; + asoc->rwnd_over += len - asoc->rwnd; asoc->rwnd = 0; } diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 401c60750b20..1ebc184a0e23 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -292,6 +292,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, } af->from_addr_param(&addr, rawaddr, htons(port), 0); + if (sctp_bind_addr_state(bp, &addr) != -1) + goto next; retval = sctp_add_bind_addr(bp, &addr, sizeof(addr), SCTP_ADDR_SRC, gfp); if (retval) { @@ -300,6 +302,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, break; } +next: len = ntohs(param->length); addrs_len -= len; raw_addr_list += len; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 1f03065686fe..410ddc1e3443 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -331,7 +331,9 @@ struct sctp_association *sctp_endpoint_lookup_assoc( * on this endpoint. */ if (!ep->base.bind_addr.port) - goto out; + return NULL; + + rcu_read_lock(); t = sctp_epaddr_lookup_transport(ep, paddr); if (!t) goto out; @@ -339,6 +341,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc( *transport = t; asoc = t->asoc; out: + rcu_read_unlock(); return asoc; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 176af3080a2b..64dfd35ccdcc 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -71,7 +71,7 @@ #include <net/inet_ecn.h> #include <net/sctp/sctp.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> static inline int sctp_v6_addr_match_len(union sctp_addr *s1, union sctp_addr *s2); @@ -222,7 +222,8 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); rcu_read_lock(); - res = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), np->tclass); + res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt), + np->tclass); rcu_read_unlock(); return res; } diff --git a/net/sctp/offload.c b/net/sctp/offload.c index 7e869d0cca69..4f5a2b580aa5 100644 --- a/net/sctp/offload.c +++ b/net/sctp/offload.c @@ -68,7 +68,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb, goto out; } - segs = skb_segment(skb, features | NETIF_F_HW_CSUM); + segs = skb_segment(skb, features | NETIF_F_HW_CSUM | NETIF_F_SG); if (IS_ERR(segs)) goto out; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index e54082699520..34efaa4ef2f6 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1048,7 +1048,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp) (new_transport->state == SCTP_PF))) new_transport = asoc->peer.active_path; if (new_transport->state == SCTP_UNCONFIRMED) { - WARN_ONCE(1, "Atempt to send packet on unconfirmed path."); + WARN_ONCE(1, "Attempt to send packet on unconfirmed path."); sctp_chunk_fail(chunk, 0); sctp_chunk_free(chunk); continue; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 7b523e3f551f..616a9428e0c4 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -205,26 +205,30 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { if (!addr->valid) continue; - if (sctp_in_scope(net, &addr->a, scope)) { - /* Now that the address is in scope, check to see if - * the address type is really supported by the local - * sock as well as the remote peer. - */ - if ((((AF_INET == addr->a.sa.sa_family) && - (copy_flags & SCTP_ADDR4_PEERSUPP))) || - (((AF_INET6 == addr->a.sa.sa_family) && - (copy_flags & SCTP_ADDR6_ALLOWED) && - (copy_flags & SCTP_ADDR6_PEERSUPP)))) { - error = sctp_add_bind_addr(bp, &addr->a, - sizeof(addr->a), - SCTP_ADDR_SRC, GFP_ATOMIC); - if (error) - goto end_copy; - } - } + if (!sctp_in_scope(net, &addr->a, scope)) + continue; + + /* Now that the address is in scope, check to see if + * the address type is really supported by the local + * sock as well as the remote peer. + */ + if (addr->a.sa.sa_family == AF_INET && + !(copy_flags & SCTP_ADDR4_PEERSUPP)) + continue; + if (addr->a.sa.sa_family == AF_INET6 && + (!(copy_flags & SCTP_ADDR6_ALLOWED) || + !(copy_flags & SCTP_ADDR6_PEERSUPP))) + continue; + + if (sctp_bind_addr_state(bp, &addr->a) != -1) + continue; + + error = sctp_add_bind_addr(bp, &addr->a, sizeof(addr->a), + SCTP_ADDR_SRC, GFP_ATOMIC); + if (error) + break; } -end_copy: rcu_read_unlock(); return error; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d5f4b4a8369b..1b5d669e3029 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -235,8 +235,12 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, sctp_assoc_t id) { struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; - struct sctp_transport *transport; + struct sctp_af *af = sctp_get_af_specific(addr->ss_family); union sctp_addr *laddr = (union sctp_addr *)addr; + struct sctp_transport *transport; + + if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len)) + return NULL; addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, laddr, @@ -4472,18 +4476,17 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), const union sctp_addr *paddr, void *p) { struct sctp_transport *transport; - int err = -ENOENT; + int err; rcu_read_lock(); transport = sctp_addrs_lookup_transport(net, laddr, paddr); + rcu_read_unlock(); if (!transport) - goto out; + return -ENOENT; - rcu_read_unlock(); err = cb(transport, p); sctp_transport_put(transport); -out: return err; } EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); @@ -7423,7 +7426,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, */ release_sock(sk); current_timeo = schedule_timeout(current_timeo); - BUG_ON(sk != asoc->base.sk); + if (sk != asoc->base.sk) + goto do_error; lock_sock(sk); *timeo_p = current_timeo; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index ce54dce13ddb..a1652ab63918 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -72,7 +72,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net, */ peer->rto = msecs_to_jiffies(net->sctp.rto_initial); - peer->last_time_heard = ktime_set(0, 0); + peer->last_time_heard = 0; peer->last_time_ecne_reduced = jiffies; peer->param_flags = SPP_HB_DISABLE | |