diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-05-04 16:34:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-05-04 16:34:49 -0400 |
commit | ce5325c1338acf965f4300f4976eac2129aeb439 (patch) | |
tree | bd1da5c37d92568113c79ba47668a1c2a756811a | |
parent | 16d00fb7765a43a1b05989062e985d283b3a1f2d (diff) |
[SCTP]: Fix the SO_REUSEADDR handling to be similar to TCP.
Update the SO_REUSEADDR handling to also check for listen state. This
was muliple listening server sockets can't be created and they will
not steal packets from each other.
Reported by Paolo Galtieri <pgaltieri@mvista.com>
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 | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b2ffab62a229..9f1a908776de 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5020,7 +5020,8 @@ pp_found: | |||
5020 | struct hlist_node *node; | 5020 | struct hlist_node *node; |
5021 | 5021 | ||
5022 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); | 5022 | SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); |
5023 | if (pp->fastreuse && sk->sk_reuse) | 5023 | if (pp->fastreuse && sk->sk_reuse && |
5024 | sk->sk_state != SCTP_SS_LISTENING) | ||
5024 | goto success; | 5025 | goto success; |
5025 | 5026 | ||
5026 | /* Run through the list of sockets bound to the port | 5027 | /* Run through the list of sockets bound to the port |
@@ -5037,7 +5038,8 @@ pp_found: | |||
5037 | struct sctp_endpoint *ep2; | 5038 | struct sctp_endpoint *ep2; |
5038 | ep2 = sctp_sk(sk2)->ep; | 5039 | ep2 = sctp_sk(sk2)->ep; |
5039 | 5040 | ||
5040 | if (reuse && sk2->sk_reuse) | 5041 | if (reuse && sk2->sk_reuse && |
5042 | sk2->sk_state != SCTP_SS_LISTENING) | ||
5041 | continue; | 5043 | continue; |
5042 | 5044 | ||
5043 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, | 5045 | if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, |
@@ -5058,9 +5060,13 @@ pp_not_found: | |||
5058 | * if sk->sk_reuse is too (that is, if the caller requested | 5060 | * if sk->sk_reuse is too (that is, if the caller requested |
5059 | * SO_REUSEADDR on this socket -sk-). | 5061 | * SO_REUSEADDR on this socket -sk-). |
5060 | */ | 5062 | */ |
5061 | if (hlist_empty(&pp->owner)) | 5063 | if (hlist_empty(&pp->owner)) { |
5062 | pp->fastreuse = sk->sk_reuse ? 1 : 0; | 5064 | if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING) |
5063 | else if (pp->fastreuse && !sk->sk_reuse) | 5065 | pp->fastreuse = 1; |
5066 | else | ||
5067 | pp->fastreuse = 0; | ||
5068 | } else if (pp->fastreuse && | ||
5069 | (!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING)) | ||
5064 | pp->fastreuse = 0; | 5070 | pp->fastreuse = 0; |
5065 | 5071 | ||
5066 | /* We are set, so fill up all the data in the hash table | 5072 | /* We are set, so fill up all the data in the hash table |
@@ -5068,8 +5074,8 @@ pp_not_found: | |||
5068 | * sockets FIXME: Blurry, NPI (ipg). | 5074 | * sockets FIXME: Blurry, NPI (ipg). |
5069 | */ | 5075 | */ |
5070 | success: | 5076 | success: |
5071 | inet_sk(sk)->num = snum; | ||
5072 | if (!sctp_sk(sk)->bind_hash) { | 5077 | if (!sctp_sk(sk)->bind_hash) { |
5078 | inet_sk(sk)->num = snum; | ||
5073 | sk_add_bind_node(sk, &pp->owner); | 5079 | sk_add_bind_node(sk, &pp->owner); |
5074 | sctp_sk(sk)->bind_hash = pp; | 5080 | sctp_sk(sk)->bind_hash = pp; |
5075 | } | 5081 | } |
@@ -5142,12 +5148,16 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5142 | * This is not currently spelled out in the SCTP sockets | 5148 | * This is not currently spelled out in the SCTP sockets |
5143 | * extensions draft, but follows the practice as seen in TCP | 5149 | * extensions draft, but follows the practice as seen in TCP |
5144 | * sockets. | 5150 | * sockets. |
5151 | * | ||
5152 | * Additionally, turn off fastreuse flag since we are not listening | ||
5145 | */ | 5153 | */ |
5154 | sk->sk_state = SCTP_SS_LISTENING; | ||
5146 | if (!ep->base.bind_addr.port) { | 5155 | if (!ep->base.bind_addr.port) { |
5147 | if (sctp_autobind(sk)) | 5156 | if (sctp_autobind(sk)) |
5148 | return -EAGAIN; | 5157 | return -EAGAIN; |
5149 | } | 5158 | } else |
5150 | sk->sk_state = SCTP_SS_LISTENING; | 5159 | sctp_sk(sk)->bind_hash->fastreuse = 0; |
5160 | |||
5151 | sctp_hash_endpoint(ep); | 5161 | sctp_hash_endpoint(ep); |
5152 | return 0; | 5162 | return 0; |
5153 | } | 5163 | } |
@@ -5185,11 +5195,13 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) | |||
5185 | * extensions draft, but follows the practice as seen in TCP | 5195 | * extensions draft, but follows the practice as seen in TCP |
5186 | * sockets. | 5196 | * sockets. |
5187 | */ | 5197 | */ |
5198 | sk->sk_state = SCTP_SS_LISTENING; | ||
5188 | if (!ep->base.bind_addr.port) { | 5199 | if (!ep->base.bind_addr.port) { |
5189 | if (sctp_autobind(sk)) | 5200 | if (sctp_autobind(sk)) |
5190 | return -EAGAIN; | 5201 | return -EAGAIN; |
5191 | } | 5202 | } else |
5192 | sk->sk_state = SCTP_SS_LISTENING; | 5203 | sctp_sk(sk)->bind_hash->fastreuse = 0; |
5204 | |||
5193 | sk->sk_max_ack_backlog = backlog; | 5205 | sk->sk_max_ack_backlog = backlog; |
5194 | sctp_hash_endpoint(ep); | 5206 | sctp_hash_endpoint(ep); |
5195 | return 0; | 5207 | return 0; |