diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2008-07-18 23:06:32 -0700 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2008-09-06 16:29:58 +0200 |
commit | ac5d8f8f46918e950a42c347a8695c2a16aedec4 (patch) | |
tree | ae9e9118eb73449f6ab6d3d37bcc27390b335e8e | |
parent | 21c9f4f0f8147a8125db7284f65e85c2cd9893b6 (diff) | |
download | linux-2.4-ac5d8f8f46918e950a42c347a8695c2a16aedec4.tar.gz |
sctp: Allow only 1 listening socket with SO_REUSEADDR
[backport of 2.6 commit 4e54064e0a13b7a7d4a481123c1783f770538e30]
When multiple socket bind to the same port with SO_REUSEADDR,
only 1 can be listining.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Willy Tarreau <w@1wt.eu>
-rw-r--r-- | net/sctp/socket.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6e9c195295a63..05afb7b342fdd 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -324,17 +324,18 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) return -EACCES; + /* See if the address matches any of the addresses we may have + * already bound before checking against other endpoints. + */ + if (sctp_bind_addr_match(bp, addr, sp)) + return -EINVAL; + /* Make sure we are allowed to bind here. * The function sctp_get_port_local() does duplicate address * detection. */ if ((ret = sctp_get_port_local(sk, addr))) { - if (ret == (long) sk) { - /* This endpoint has a conflicting address. */ - return -EINVAL; - } else { - return -EADDRINUSE; - } + return -EADDRINUSE; } /* Refresh ephemeral port. */ @@ -3797,7 +3798,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) struct sctp_endpoint *ep2; ep2 = sctp_sk(sk2)->ep; - if (reuse && sk2->reuse) + if (sk == sk2 || + (reuse && sk2->reuse && + sk2->state != SCTP_SS_LISTENING)) continue; if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, @@ -3918,6 +3921,11 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) if (!ep->base.bind_addr.port) { if (sctp_autobind(sk)) return -EAGAIN; + } else { + if (sctp_get_port(sk, sk->num)) { + sk->state = SCTP_SS_CLOSED; + return -EADDRINUSE; + } } sk->state = SCTP_SS_LISTENING; sctp_hash_endpoint(ep); |