aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2008-01-31 08:07:57 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:28:21 -0500
commitfa4d3c6210380c55cf7f295d28fd981fbcbb828c (patch)
tree0161c8574349adb4eb93b2996dacf70b472696ac
parentd86e0dac2ce412715181f792aa0749fe3effff11 (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.c25
-rw-r--r--net/ipv6/udp.c10
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);
130atomic_t udp_memory_allocated; 130atomic_t udp_memory_allocated;
131EXPORT_SYMBOL(udp_memory_allocated); 131EXPORT_SYMBOL(udp_memory_allocated);
132 132
133static inline int __udp_lib_lport_inuse(__u16 num, 133static 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 */
264static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, 266static 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
59static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, 59static 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) {