aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-07-18 23:06:32 -0700
committerWilly Tarreau <w@1wt.eu>2008-09-06 16:29:58 +0200
commitac5d8f8f46918e950a42c347a8695c2a16aedec4 (patch)
treeae9e9118eb73449f6ab6d3d37bcc27390b335e8e
parent21c9f4f0f8147a8125db7284f65e85c2cd9893b6 (diff)
downloadlinux-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.c22
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);