diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-01-31 08:07:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:28:21 -0500 |
commit | fa4d3c6210380c55cf7f295d28fd981fbcbb828c (patch) | |
tree | 0161c8574349adb4eb93b2996dacf70b472696ac | |
parent | d86e0dac2ce412715181f792aa0749fe3effff11 (diff) |
[NETNS]: Udp sockets per-net lookup.
Add the net parameter to udp_get_port family of calls and
udp_lookup one and use it to filter sockets.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/udp.c | 25 | ||||
-rw-r--r-- | net/ipv6/udp.c | 10 |
2 files changed, 20 insertions, 15 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; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index bd4b9df8f614..53739de829db 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -56,7 +56,8 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
56 | return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); | 56 | return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, | 59 | static struct sock *__udp6_lib_lookup(struct net *net, |
60 | struct in6_addr *saddr, __be16 sport, | ||
60 | struct in6_addr *daddr, __be16 dport, | 61 | struct in6_addr *daddr, __be16 dport, |
61 | int dif, struct hlist_head udptable[]) | 62 | int dif, struct hlist_head udptable[]) |
62 | { | 63 | { |
@@ -69,7 +70,8 @@ static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, | |||
69 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { | 70 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
70 | struct inet_sock *inet = inet_sk(sk); | 71 | struct inet_sock *inet = inet_sk(sk); |
71 | 72 | ||
72 | if (sk->sk_hash == hnum && sk->sk_family == PF_INET6) { | 73 | if (sk->sk_net == net && sk->sk_hash == hnum && |
74 | sk->sk_family == PF_INET6) { | ||
73 | struct ipv6_pinfo *np = inet6_sk(sk); | 75 | struct ipv6_pinfo *np = inet6_sk(sk); |
74 | int score = 0; | 76 | int score = 0; |
75 | if (inet->dport) { | 77 | if (inet->dport) { |
@@ -233,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
233 | struct sock *sk; | 235 | struct sock *sk; |
234 | int err; | 236 | int err; |
235 | 237 | ||
236 | sk = __udp6_lib_lookup(daddr, uh->dest, | 238 | sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest, |
237 | saddr, uh->source, inet6_iif(skb), udptable); | 239 | saddr, uh->source, inet6_iif(skb), udptable); |
238 | if (sk == NULL) | 240 | if (sk == NULL) |
239 | return; | 241 | return; |
@@ -478,7 +480,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
478 | * check socket cache ... must talk to Alan about his plans | 480 | * check socket cache ... must talk to Alan about his plans |
479 | * for sock caches... i'll skip this for now. | 481 | * for sock caches... i'll skip this for now. |
480 | */ | 482 | */ |
481 | sk = __udp6_lib_lookup(saddr, uh->source, | 483 | sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source, |
482 | daddr, uh->dest, inet6_iif(skb), udptable); | 484 | daddr, uh->dest, inet6_iif(skb), udptable); |
483 | 485 | ||
484 | if (sk == NULL) { | 486 | if (sk == NULL) { |