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; |
