From d570ee490fb18220262cfe41284d7aede797ed4f Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 15 May 2007 16:32:39 -0400 Subject: [SCTP]: Correctly set daddr for IPv6 sockets during peeloff During peeloff of AF_INET6 socket, the inet6_sk(sk)->daddr wasn't set correctly since the code was assuming IPv4 only. Now we use a correct call to set the destination address. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala --- net/sctp/socket.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4dcdabf56473..d370c945a757 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3550,6 +3550,7 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, struct sock *sk = asoc->base.sk; struct socket *sock; struct inet_sock *inetsk; + struct sctp_af *af; int err = 0; /* An association cannot be branched off from an already peeled-off @@ -3571,8 +3572,9 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, /* Make peeled-off sockets more like 1-1 accepted sockets. * Set the daddr and initialize id to something more random */ + af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); + af->to_sk_daddr(&asoc->peer.primary_addr, sk); inetsk = inet_sk(sock->sk); - inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; inetsk->id = asoc->next_tsn ^ jiffies; *sockp = sock; -- cgit v1.2.2 From 8b35805693e1915829355723537f99f1b8bc9cc0 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 15 May 2007 17:14:58 -0400 Subject: [SCTP]: Allow unspecified port in sctp_bindx() Allow sctp_bindx() to accept multiple address with unspecified port. In this case, all addresses inherit the first bound port. We still catch full mis-matches. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala --- net/sctp/socket.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d370c945a757..a5b6e559451e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -333,12 +333,19 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) if (!sp->pf->bind_verify(sp, addr)) return -EADDRNOTAVAIL; - /* We must either be unbound, or bind to the same port. */ - if (bp->port && (snum != bp->port)) { - SCTP_DEBUG_PRINTK("sctp_do_bind:" + /* We must either be unbound, or bind to the same port. + * It's OK to allow 0 ports if we are already bound. + * We'll just inhert an already bound port in this case + */ + if (bp->port) { + if (!snum) + snum = bp->port; + else if (snum != bp->port) { + SCTP_DEBUG_PRINTK("sctp_do_bind:" " New port %d does not match existing port " "%d.\n", snum, bp->port); - return -EINVAL; + return -EINVAL; + } } if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) -- cgit v1.2.2 From fe979ac169970b3d12facd6565766735862395c5 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 23 May 2007 11:11:37 -0400 Subject: [SCTP] Fix leak in sctp_getsockopt_local_addrs when copy_to_user fails If the copy_to_user or copy_user calls fail in sctp_getsockopt_local_addrs(), the function should free locally allocated storage before returning error. Spotted by Coverity. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala --- net/sctp/socket.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a5b6e559451e..45510c46c223 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4352,11 +4352,12 @@ copy_getaddrs: err = -EFAULT; goto error; } - if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) - return -EFAULT; + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) { + err = -EFAULT; + goto error; + } if (put_user(bytes_copied, optlen)) - return -EFAULT; - + err = -EFAULT; error: kfree(addrs); return err; -- cgit v1.2.2 From c910b47e1811b3f8b184108c48de3d7af3e2999b Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 7 Jun 2007 13:47:03 -0400 Subject: [SCTP] Update pmtu handling to be similar to tcp Introduce new function sctp_transport_update_pmtu that updates the transports and destination caches view of the path mtu. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala --- net/sctp/input.c | 16 ++-------------- net/sctp/transport.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) (limited to 'net') diff --git a/net/sctp/input.c b/net/sctp/input.c index 885109fb3dda..45d6a644cf06 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -371,20 +371,8 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, return; if (t->param_flags & SPP_PMTUD_ENABLE) { - if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) { - printk(KERN_WARNING "%s: Reported pmtu %d too low, " - "using default minimum of %d\n", - __FUNCTION__, pmtu, - SCTP_DEFAULT_MINSEGMENT); - /* Use default minimum segment size and disable - * pmtu discovery on this transport. - */ - t->pathmtu = SCTP_DEFAULT_MINSEGMENT; - t->param_flags = (t->param_flags & ~SPP_PMTUD) | - SPP_PMTUD_DISABLE; - } else { - t->pathmtu = pmtu; - } + /* Update transports view of the MTU */ + sctp_transport_update_pmtu(t, pmtu); /* Update association pmtu. */ sctp_assoc_sync_pmtu(asoc); diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 961df275d5b9..e14c271cf28b 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -241,6 +241,47 @@ void sctp_transport_pmtu(struct sctp_transport *transport) transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; } +/* this is a complete rip-off from __sk_dst_check + * the cookie is always 0 since this is how it's used in the + * pmtu code + */ +static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t) +{ + struct dst_entry *dst = t->dst; + + if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) { + dst_release(t->dst); + t->dst = NULL; + return NULL; + } + + return dst; +} + +void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) +{ + struct dst_entry *dst; + + if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) { + printk(KERN_WARNING "%s: Reported pmtu %d too low, " + "using default minimum of %d\n", + __FUNCTION__, pmtu, + SCTP_DEFAULT_MINSEGMENT); + /* Use default minimum segment size and disable + * pmtu discovery on this transport. + */ + t->pathmtu = SCTP_DEFAULT_MINSEGMENT; + t->param_flags = (t->param_flags & ~SPP_PMTUD) | + SPP_PMTUD_DISABLE; + } else { + t->pathmtu = pmtu; + } + + dst = sctp_transport_dst_check(t); + if (dst) + dst->ops->update_pmtu(dst, pmtu); +} + /* Caches the dst entry and source address for a transport's destination * address. */ -- cgit v1.2.2 From 8a4794914f9cf2681235ec2311e189fe307c28c7 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 7 Jun 2007 14:21:05 -0400 Subject: [SCTP] Flag a pmtu change request Currently, if the socket is owned by the user, we drop the ICMP message. As a result SCTP forgets that path MTU changed and never adjusting it's estimate. This causes all subsequent packets to be fragmented. With this patch, we'll flag the association that it needs to udpate it's estimate based on the already updated routing information. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala --- net/sctp/associola.c | 4 ++++ net/sctp/input.c | 8 +++++++- net/sctp/socket.c | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sctp/associola.c b/net/sctp/associola.c index df94e3cdfba3..498edb0cd4e5 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1231,6 +1231,10 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc) /* Get the lowest pmtu of all the transports. */ list_for_each(pos, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); + if (t->pmtu_pending && t->dst) { + sctp_transport_update_pmtu(t, dst_mtu(t->dst)); + t->pmtu_pending = 0; + } if (!pmtu || (t->pathmtu < pmtu)) pmtu = t->pathmtu; } diff --git a/net/sctp/input.c b/net/sctp/input.c index 45d6a644cf06..d57ff7f3c576 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -367,9 +367,15 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, struct sctp_transport *t, __u32 pmtu) { - if (sock_owned_by_user(sk) || !t || (t->pathmtu == pmtu)) + if (!t || (t->pathmtu == pmtu)) return; + if (sock_owned_by_user(sk)) { + asoc->pmtu_pending = 1; + t->pmtu_pending = 1; + return; + } + if (t->param_flags & SPP_PMTUD_ENABLE) { /* Update transports view of the MTU */ sctp_transport_update_pmtu(t, pmtu); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 45510c46c223..6edaaa009d62 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1662,6 +1662,9 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_free; } + if (asoc->pmtu_pending) + sctp_assoc_pending_pmtu(asoc); + /* If fragmentation is disabled and the message length exceeds the * association fragmentation point, return EMSGSIZE. The I-D * does not specify what this error is, but this looks like -- cgit v1.2.2 From 06ad391919b2078ec2e012f0593014b88e7a6c4e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 12 Jun 2007 15:26:22 -0400 Subject: [SCTP] Don't disable PMTU discovery when mtu is small Right now, when we receive a mtu estimate smaller then minim threshold in the ICMP message, we disable the path mtu discovery on the transport. This leads to the never increasing sctp fragmentation point even when the real path mtu has increased. Signed-off-by: Vlad Yasevich --- net/sctp/transport.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net') diff --git a/net/sctp/transport.c b/net/sctp/transport.c index e14c271cf28b..5f467c914f80 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -271,8 +271,6 @@ void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) * pmtu discovery on this transport. */ t->pathmtu = SCTP_DEFAULT_MINSEGMENT; - t->param_flags = (t->param_flags & ~SPP_PMTUD) | - SPP_PMTUD_DISABLE; } else { t->pathmtu = pmtu; } -- cgit v1.2.2