2.4.36-stable kernel tree
リビジョン | 098a93b6ce9b6779e238c91e75175642ccd19e89 (tree) |
---|---|
日時 | 2008-09-06 20:35:25 |
作者 | Vlad Yasevich <vladislav.yasevich@hp.c...> |
コミッター | Willy Tarreau |
sctp: Allow only 1 listening socket with SO_REUSEADDR
[backport of 2.6 commit 4e54064e0a13b7a7d4a481123c1783f770538e30]
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>
Signed-off-by: Willy Tarreau <w@1wt.eu>
@@ -324,17 +324,18 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | ||
324 | 324 | if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) |
325 | 325 | return -EACCES; |
326 | 326 | |
327 | + /* See if the address matches any of the addresses we may have | |
328 | + * already bound before checking against other endpoints. | |
329 | + */ | |
330 | + if (sctp_bind_addr_match(bp, addr, sp)) | |
331 | + return -EINVAL; | |
332 | + | |
327 | 333 | /* Make sure we are allowed to bind here. |
328 | 334 | * The function sctp_get_port_local() does duplicate address |
329 | 335 | * detection. |
330 | 336 | */ |
331 | 337 | if ((ret = sctp_get_port_local(sk, addr))) { |
332 | - if (ret == (long) sk) { | |
333 | - /* This endpoint has a conflicting address. */ | |
334 | - return -EINVAL; | |
335 | - } else { | |
336 | - return -EADDRINUSE; | |
337 | - } | |
338 | + return -EADDRINUSE; | |
338 | 339 | } |
339 | 340 | |
340 | 341 | /* Refresh ephemeral port. */ |
@@ -3797,7 +3798,9 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | ||
3797 | 3798 | struct sctp_endpoint *ep2; |
3798 | 3799 | ep2 = sctp_sk(sk2)->ep; |
3799 | 3800 | |
3800 | - if (reuse && sk2->reuse) | |
3801 | + if (sk == sk2 || | |
3802 | + (reuse && sk2->reuse && | |
3803 | + sk2->state != SCTP_SS_LISTENING)) | |
3801 | 3804 | continue; |
3802 | 3805 | |
3803 | 3806 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, |
@@ -3918,6 +3921,11 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | ||
3918 | 3921 | if (!ep->base.bind_addr.port) { |
3919 | 3922 | if (sctp_autobind(sk)) |
3920 | 3923 | return -EAGAIN; |
3924 | + } else { | |
3925 | + if (sctp_get_port(sk, sk->num)) { | |
3926 | + sk->state = SCTP_SS_CLOSED; | |
3927 | + return -EADDRINUSE; | |
3928 | + } | |
3921 | 3929 | } |
3922 | 3930 | sk->state = SCTP_SS_LISTENING; |
3923 | 3931 | sctp_hash_endpoint(ep); |