aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-07-19 02:06:32 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-19 02:06:32 -0400
commit4e54064e0a13b7a7d4a481123c1783f770538e30 (patch)
treeccd64b852003e7f3869cd24e78381fbba7bae764
parent23b29ed80bd7184398317a111dc488605cb66c7f (diff)
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>
-rw-r--r--net/sctp/socket.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index fd7ed9d46a48..79bece16aede 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -377,18 +377,19 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
377 if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) 377 if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
378 return -EACCES; 378 return -EACCES;
379 379
380 /* See if the address matches any of the addresses we may have
381 * already bound before checking against other endpoints.
382 */
383 if (sctp_bind_addr_match(bp, addr, sp))
384 return -EINVAL;
385
380 /* Make sure we are allowed to bind here. 386 /* Make sure we are allowed to bind here.
381 * The function sctp_get_port_local() does duplicate address 387 * The function sctp_get_port_local() does duplicate address
382 * detection. 388 * detection.
383 */ 389 */
384 addr->v4.sin_port = htons(snum); 390 addr->v4.sin_port = htons(snum);
385 if ((ret = sctp_get_port_local(sk, addr))) { 391 if ((ret = sctp_get_port_local(sk, addr))) {
386 if (ret == (long) sk) { 392 return -EADDRINUSE;
387 /* This endpoint has a conflicting address. */
388 return -EINVAL;
389 } else {
390 return -EADDRINUSE;
391 }
392 } 393 }
393 394
394 /* Refresh ephemeral port. */ 395 /* Refresh ephemeral port. */
@@ -5584,8 +5585,9 @@ pp_found:
5584 struct sctp_endpoint *ep2; 5585 struct sctp_endpoint *ep2;
5585 ep2 = sctp_sk(sk2)->ep; 5586 ep2 = sctp_sk(sk2)->ep;
5586 5587
5587 if (reuse && sk2->sk_reuse && 5588 if (sk == sk2 ||
5588 sk2->sk_state != SCTP_SS_LISTENING) 5589 (reuse && sk2->sk_reuse &&
5590 sk2->sk_state != SCTP_SS_LISTENING))
5589 continue; 5591 continue;
5590 5592
5591 if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr, 5593 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 if (!ep->base.bind_addr.port) { 5704 if (!ep->base.bind_addr.port) {
5703 if (sctp_autobind(sk)) 5705 if (sctp_autobind(sk))
5704 return -EAGAIN; 5706 return -EAGAIN;
5705 } else 5707 } else {
5708 if (sctp_get_port(sk, inet_sk(sk)->num)) {
5709 sk->sk_state = SCTP_SS_CLOSED;
5710 return -EADDRINUSE;
5711 }
5706 sctp_sk(sk)->bind_hash->fastreuse = 0; 5712 sctp_sk(sk)->bind_hash->fastreuse = 0;
5713 }
5707 5714
5708 sctp_hash_endpoint(ep); 5715 sctp_hash_endpoint(ep);
5709 return 0; 5716 return 0;