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: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
23b29ed80b
commit
4e54064e0a
1 changed files with 16 additions and 9 deletions
|
@ -377,18 +377,19 @@ 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) {
|
return -EADDRINUSE;
|
||||||
/* This endpoint has a conflicting address. */
|
|
||||||
return -EINVAL;
|
|
||||||
} else {
|
|
||||||
return -EADDRINUSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Refresh ephemeral port. */
|
/* Refresh ephemeral port. */
|
||||||
|
@ -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)
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue