Commit 4e54064e authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller

sctp: Allow only 1 listening socket with SO_REUSEADDR

When multiple socket bind to the same port with SO_REUSEADDR,
only 1 can be listining.
Signed-off-by: default avatarVlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23b29ed8
...@@ -377,19 +377,20 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) ...@@ -377,19 +377,20 @@ 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)) if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
return -EACCES; 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. /* Make sure we are allowed to bind here.
* The function sctp_get_port_local() does duplicate address * The function sctp_get_port_local() does duplicate address
* detection. * detection.
*/ */
addr->v4.sin_port = htons(snum); addr->v4.sin_port = htons(snum);
if ((ret = sctp_get_port_local(sk, addr))) { 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. */ /* Refresh ephemeral port. */
if (!bp->port) if (!bp->port)
...@@ -5584,8 +5585,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) ...@@ -5584,8 +5585,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
struct sctp_endpoint *ep2; struct sctp_endpoint *ep2;
ep2 = sctp_sk(sk2)->ep; ep2 = sctp_sk(sk2)->ep;
if (reuse && sk2->sk_reuse && if (sk == sk2 ||
sk2->sk_state != SCTP_SS_LISTENING) (reuse && sk2->sk_reuse &&
sk2->sk_state != SCTP_SS_LISTENING))
continue; continue;
if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr, if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr,
...@@ -5702,8 +5704,13 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) ...@@ -5702,8 +5704,13 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
if (!ep->base.bind_addr.port) { if (!ep->base.bind_addr.port) {
if (sctp_autobind(sk)) if (sctp_autobind(sk))
return -EAGAIN; return -EAGAIN;
} else } else {
if (sctp_get_port(sk, inet_sk(sk)->num)) {
sk->sk_state = SCTP_SS_CLOSED;
return -EADDRINUSE;
}
sctp_sk(sk)->bind_hash->fastreuse = 0; sctp_sk(sk)->bind_hash->fastreuse = 0;
}
sctp_hash_endpoint(ep); sctp_hash_endpoint(ep);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment