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>
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index fd7ed9d..79bece1 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -377,18 +377,19 @@
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.
*/
addr->v4.sin_port = htons(snum);
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. */
@@ -5584,8 +5585,9 @@
struct sctp_endpoint *ep2;
ep2 = sctp_sk(sk2)->ep;
- if (reuse && sk2->sk_reuse &&
- sk2->sk_state != SCTP_SS_LISTENING)
+ if (sk == sk2 ||
+ (reuse && sk2->sk_reuse &&
+ sk2->sk_state != SCTP_SS_LISTENING))
continue;
if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr,
@@ -5702,8 +5704,13 @@
if (!ep->base.bind_addr.port) {
if (sctp_autobind(sk))
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_hash_endpoint(ep);
return 0;