diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2008-07-19 02:06:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-19 02:06:32 -0400 |
commit | 4e54064e0a13b7a7d4a481123c1783f770538e30 (patch) | |
tree | ccd64b852003e7f3869cd24e78381fbba7bae764 | |
parent | 23b29ed80bd7184398317a111dc488605cb66c7f (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.c | 25 |
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; |