diff options
| -rw-r--r-- | net/ipv4/udp.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index db313d964884..113e0c4c8a92 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -203,6 +203,13 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
| 203 | result = sysctl_local_port_range[0] | 203 | result = sysctl_local_port_range[0] |
| 204 | + ((result - sysctl_local_port_range[0]) & | 204 | + ((result - sysctl_local_port_range[0]) & |
| 205 | (UDP_HTABLE_SIZE - 1)); | 205 | (UDP_HTABLE_SIZE - 1)); |
| 206 | hash = hash_port_and_addr(result, 0); | ||
| 207 | if (__udp_lib_port_inuse(hash, result, | ||
| 208 | 0, udptable)) | ||
| 209 | continue; | ||
| 210 | if (!inet_sk(sk)->rcv_saddr) | ||
| 211 | break; | ||
| 212 | |||
| 206 | hash = hash_port_and_addr(result, | 213 | hash = hash_port_and_addr(result, |
| 207 | inet_sk(sk)->rcv_saddr); | 214 | inet_sk(sk)->rcv_saddr); |
| 208 | if (! __udp_lib_port_inuse(hash, result, | 215 | if (! __udp_lib_port_inuse(hash, result, |
| @@ -214,18 +221,36 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
| 214 | gotit: | 221 | gotit: |
| 215 | *port_rover = snum = result; | 222 | *port_rover = snum = result; |
| 216 | } else { | 223 | } else { |
| 217 | hash = hash_port_and_addr(snum, inet_sk(sk)->rcv_saddr); | 224 | hash = hash_port_and_addr(snum, 0); |
| 218 | head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; | 225 | head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; |
| 219 | 226 | ||
| 220 | sk_for_each(sk2, node, head) | 227 | sk_for_each(sk2, node, head) |
| 221 | if (sk2->sk_hash == hash && | 228 | if (sk2->sk_hash == hash && |
| 222 | sk2 != sk && | 229 | sk2 != sk && |
| 223 | inet_sk(sk2)->num == snum && | 230 | inet_sk(sk2)->num == snum && |
| 224 | (!sk2->sk_reuse || !sk->sk_reuse) && | 231 | (!sk2->sk_reuse || !sk->sk_reuse) && |
| 225 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 232 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if || |
| 226 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 233 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
| 227 | (*saddr_comp)(sk, sk2) ) | 234 | (*saddr_comp)(sk, sk2)) |
| 228 | goto fail; | 235 | goto fail; |
| 236 | |||
| 237 | if (inet_sk(sk)->rcv_saddr) { | ||
| 238 | hash = hash_port_and_addr(snum, | ||
| 239 | inet_sk(sk)->rcv_saddr); | ||
| 240 | head = &udptable[hash & (UDP_HTABLE_SIZE - 1)]; | ||
| 241 | |||
| 242 | sk_for_each(sk2, node, head) | ||
| 243 | if (sk2->sk_hash == hash && | ||
| 244 | sk2 != sk && | ||
| 245 | inet_sk(sk2)->num == snum && | ||
| 246 | (!sk2->sk_reuse || !sk->sk_reuse) && | ||
| 247 | (!sk2->sk_bound_dev_if || | ||
| 248 | !sk->sk_bound_dev_if || | ||
| 249 | sk2->sk_bound_dev_if == | ||
| 250 | sk->sk_bound_dev_if) && | ||
| 251 | (*saddr_comp)(sk, sk2)) | ||
| 252 | goto fail; | ||
| 253 | } | ||
| 229 | } | 254 | } |
| 230 | inet_sk(sk)->num = snum; | 255 | inet_sk(sk)->num = snum; |
| 231 | sk->sk_hash = hash; | 256 | sk->sk_hash = hash; |
