diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2fb8d731026b..7ea1b67b6de1 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -130,14 +130,14 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min); | |||
130 | atomic_t udp_memory_allocated; | 130 | atomic_t udp_memory_allocated; |
131 | EXPORT_SYMBOL(udp_memory_allocated); | 131 | EXPORT_SYMBOL(udp_memory_allocated); |
132 | 132 | ||
133 | static inline int __udp_lib_lport_inuse(__u16 num, | 133 | static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, |
134 | const struct hlist_head udptable[]) | 134 | const struct hlist_head udptable[]) |
135 | { | 135 | { |
136 | struct sock *sk; | 136 | struct sock *sk; |
137 | struct hlist_node *node; | 137 | struct hlist_node *node; |
138 | 138 | ||
139 | sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) | 139 | sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)]) |
140 | if (sk->sk_hash == num) | 140 | if (sk->sk_net == net && sk->sk_hash == num) |
141 | return 1; | 141 | return 1; |
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
@@ -159,6 +159,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
159 | struct hlist_head *head; | 159 | struct hlist_head *head; |
160 | struct sock *sk2; | 160 | struct sock *sk2; |
161 | int error = 1; | 161 | int error = 1; |
162 | struct net *net = sk->sk_net; | ||
162 | 163 | ||
163 | write_lock_bh(&udp_hash_lock); | 164 | write_lock_bh(&udp_hash_lock); |
164 | 165 | ||
@@ -198,7 +199,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
198 | /* 2nd pass: find hole in shortest hash chain */ | 199 | /* 2nd pass: find hole in shortest hash chain */ |
199 | rover = best; | 200 | rover = best; |
200 | for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) { | 201 | for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) { |
201 | if (! __udp_lib_lport_inuse(rover, udptable)) | 202 | if (! __udp_lib_lport_inuse(net, rover, udptable)) |
202 | goto gotit; | 203 | goto gotit; |
203 | rover += UDP_HTABLE_SIZE; | 204 | rover += UDP_HTABLE_SIZE; |
204 | if (rover > high) | 205 | if (rover > high) |
@@ -218,6 +219,7 @@ gotit: | |||
218 | sk_for_each(sk2, node, head) | 219 | sk_for_each(sk2, node, head) |
219 | if (sk2->sk_hash == snum && | 220 | if (sk2->sk_hash == snum && |
220 | sk2 != sk && | 221 | sk2 != sk && |
222 | sk2->sk_net == net && | ||
221 | (!sk2->sk_reuse || !sk->sk_reuse) && | 223 | (!sk2->sk_reuse || !sk->sk_reuse) && |
222 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 224 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if |
223 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 225 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
@@ -261,9 +263,9 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) | |||
261 | /* UDP is nearly always wildcards out the wazoo, it makes no sense to try | 263 | /* UDP is nearly always wildcards out the wazoo, it makes no sense to try |
262 | * harder than this. -DaveM | 264 | * harder than this. -DaveM |
263 | */ | 265 | */ |
264 | static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, | 266 | static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, |
265 | __be32 daddr, __be16 dport, | 267 | __be16 sport, __be32 daddr, __be16 dport, |
266 | int dif, struct hlist_head udptable[]) | 268 | int dif, struct hlist_head udptable[]) |
267 | { | 269 | { |
268 | struct sock *sk, *result = NULL; | 270 | struct sock *sk, *result = NULL; |
269 | struct hlist_node *node; | 271 | struct hlist_node *node; |
@@ -274,7 +276,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, | |||
274 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 276 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
275 | struct inet_sock *inet = inet_sk(sk); | 277 | struct inet_sock *inet = inet_sk(sk); |
276 | 278 | ||
277 | if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) { | 279 | if (sk->sk_net == net && sk->sk_hash == hnum && |
280 | !ipv6_only_sock(sk)) { | ||
278 | int score = (sk->sk_family == PF_INET ? 1 : 0); | 281 | int score = (sk->sk_family == PF_INET ? 1 : 0); |
279 | if (inet->rcv_saddr) { | 282 | if (inet->rcv_saddr) { |
280 | if (inet->rcv_saddr != daddr) | 283 | if (inet->rcv_saddr != daddr) |
@@ -361,8 +364,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[]) | |||
361 | int harderr; | 364 | int harderr; |
362 | int err; | 365 | int err; |
363 | 366 | ||
364 | sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, | 367 | sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest, |
365 | skb->dev->ifindex, udptable ); | 368 | iph->saddr, uh->source, skb->dev->ifindex, udptable); |
366 | if (sk == NULL) { | 369 | if (sk == NULL) { |
367 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 370 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); |
368 | return; /* No socket for error */ | 371 | return; /* No socket for error */ |
@@ -1185,8 +1188,8 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
1185 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) | 1188 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) |
1186 | return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); | 1189 | return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); |
1187 | 1190 | ||
1188 | sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, | 1191 | sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr, |
1189 | inet_iif(skb), udptable); | 1192 | uh->dest, inet_iif(skb), udptable); |
1190 | 1193 | ||
1191 | if (sk != NULL) { | 1194 | if (sk != NULL) { |
1192 | int ret = 0; | 1195 | int ret = 0; |