diff options
author | Hans Schillstrom <hans.schillstrom@ericsson.com> | 2011-01-03 08:44:43 -0500 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2011-01-12 20:30:26 -0500 |
commit | fc723250c9cb046cc19833a2b1c4309bbf59ac36 (patch) | |
tree | fa8cd33ad9e020549dd8c6389f311d25e495ca7d | |
parent | 61b1ab4583e275af216c8454b9256de680499b19 (diff) |
IPVS: netns to services part 1
Services hash tables got netns ptr a hash arg,
While Real Servers (rs) has been moved to ipvs struct.
Two new inline functions added to get net ptr from skb.
Since ip_vs is called from different contexts there is two
places to dig for the net ptr skb->dev or skb->sk
this is handled in skb_net() and skb_sknet()
Global functions, ip_vs_service_get() ip_vs_lookup_real_service()
etc have got struct net *net as first param.
If possible get net ptr skb etc,
- if not &init_net is used at this early stage of patching.
ip_vs_ctl.c procfs not ready for netns yet.
*v3
Comments by Julian
- __ip_vs_service_find and __ip_vs_svc_fwm_find are fast path,
net_eq(svc->net, net) so the check is at the end now.
- net = skb_net(skb) in ip_vs_out moved after check for skb_dst.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r-- | include/net/ip_vs.h | 64 | ||||
-rw-r--r-- | include/net/netns/ip_vs.h | 8 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_conn.c | 2 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 232 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_sctp.c | 5 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_tcp.c | 7 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto_udp.c | 5 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 2 |
9 files changed, 214 insertions, 115 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index c1c2ece3ed94..d551e0d8fd9a 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -37,6 +37,59 @@ static inline struct netns_ipvs *net_ipvs(struct net* net) | |||
37 | { | 37 | { |
38 | return net->ipvs; | 38 | return net->ipvs; |
39 | } | 39 | } |
40 | /* | ||
41 | * Get net ptr from skb in traffic cases | ||
42 | * use skb_sknet when call is from userland (ioctl or netlink) | ||
43 | */ | ||
44 | static inline struct net *skb_net(struct sk_buff *skb) | ||
45 | { | ||
46 | #ifdef CONFIG_NET_NS | ||
47 | #ifdef CONFIG_IP_VS_DEBUG | ||
48 | /* | ||
49 | * This is used for debug only. | ||
50 | * Start with the most likely hit | ||
51 | * End with BUG | ||
52 | */ | ||
53 | if (likely(skb->dev && skb->dev->nd_net)) | ||
54 | return dev_net(skb->dev); | ||
55 | if (skb_dst(skb)->dev) | ||
56 | return dev_net(skb_dst(skb)->dev); | ||
57 | WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n", | ||
58 | __func__, __LINE__); | ||
59 | if (likely(skb->sk && skb->sk->sk_net)) | ||
60 | return sock_net(skb->sk); | ||
61 | pr_err("There is no net ptr to find in the skb in %s() line:%d\n", | ||
62 | __func__, __LINE__); | ||
63 | BUG(); | ||
64 | #else | ||
65 | return dev_net(skb->dev ? : skb_dst(skb)->dev); | ||
66 | #endif | ||
67 | #else | ||
68 | return &init_net; | ||
69 | #endif | ||
70 | } | ||
71 | |||
72 | static inline struct net *skb_sknet(struct sk_buff *skb) | ||
73 | { | ||
74 | #ifdef CONFIG_NET_NS | ||
75 | #ifdef CONFIG_IP_VS_DEBUG | ||
76 | /* Start with the most likely hit */ | ||
77 | if (likely(skb->sk && skb->sk->sk_net)) | ||
78 | return sock_net(skb->sk); | ||
79 | WARN(skb->dev, "Maybe skb_net should be used instead in %s() line:%d\n", | ||
80 | __func__, __LINE__); | ||
81 | if (likely(skb->dev && skb->dev->nd_net)) | ||
82 | return dev_net(skb->dev); | ||
83 | pr_err("There is no net ptr to find in the skb in %s() line:%d\n", | ||
84 | __func__, __LINE__); | ||
85 | BUG(); | ||
86 | #else | ||
87 | return sock_net(skb->sk); | ||
88 | #endif | ||
89 | #else | ||
90 | return &init_net; | ||
91 | #endif | ||
92 | } | ||
40 | 93 | ||
41 | /* Connections' size value needed by ip_vs_ctl.c */ | 94 | /* Connections' size value needed by ip_vs_ctl.c */ |
42 | extern int ip_vs_conn_tab_size; | 95 | extern int ip_vs_conn_tab_size; |
@@ -496,6 +549,7 @@ struct ip_vs_service { | |||
496 | unsigned flags; /* service status flags */ | 549 | unsigned flags; /* service status flags */ |
497 | unsigned timeout; /* persistent timeout in ticks */ | 550 | unsigned timeout; /* persistent timeout in ticks */ |
498 | __be32 netmask; /* grouping granularity */ | 551 | __be32 netmask; /* grouping granularity */ |
552 | struct net *net; | ||
499 | 553 | ||
500 | struct list_head destinations; /* real server d-linked list */ | 554 | struct list_head destinations; /* real server d-linked list */ |
501 | __u32 num_dests; /* number of servers */ | 555 | __u32 num_dests; /* number of servers */ |
@@ -896,7 +950,7 @@ extern int sysctl_ip_vs_sync_ver; | |||
896 | 950 | ||
897 | extern void ip_vs_sync_switch_mode(int mode); | 951 | extern void ip_vs_sync_switch_mode(int mode); |
898 | extern struct ip_vs_service * | 952 | extern struct ip_vs_service * |
899 | ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, | 953 | ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol, |
900 | const union nf_inet_addr *vaddr, __be16 vport); | 954 | const union nf_inet_addr *vaddr, __be16 vport); |
901 | 955 | ||
902 | static inline void ip_vs_service_put(struct ip_vs_service *svc) | 956 | static inline void ip_vs_service_put(struct ip_vs_service *svc) |
@@ -905,7 +959,7 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc) | |||
905 | } | 959 | } |
906 | 960 | ||
907 | extern struct ip_vs_dest * | 961 | extern struct ip_vs_dest * |
908 | ip_vs_lookup_real_service(int af, __u16 protocol, | 962 | ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol, |
909 | const union nf_inet_addr *daddr, __be16 dport); | 963 | const union nf_inet_addr *daddr, __be16 dport); |
910 | 964 | ||
911 | extern int ip_vs_use_count_inc(void); | 965 | extern int ip_vs_use_count_inc(void); |
@@ -913,9 +967,9 @@ extern void ip_vs_use_count_dec(void); | |||
913 | extern int ip_vs_control_init(void); | 967 | extern int ip_vs_control_init(void); |
914 | extern void ip_vs_control_cleanup(void); | 968 | extern void ip_vs_control_cleanup(void); |
915 | extern struct ip_vs_dest * | 969 | extern struct ip_vs_dest * |
916 | ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, | 970 | ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr, |
917 | const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol, | 971 | __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, |
918 | __u32 fwmark); | 972 | __u16 protocol, __u32 fwmark); |
919 | extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); | 973 | extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); |
920 | 974 | ||
921 | 975 | ||
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h index 12fe84087cec..5b87d22a39fb 100644 --- a/include/net/netns/ip_vs.h +++ b/include/net/netns/ip_vs.h | |||
@@ -20,6 +20,14 @@ struct ctl_table_header; | |||
20 | 20 | ||
21 | struct netns_ipvs { | 21 | struct netns_ipvs { |
22 | int gen; /* Generation */ | 22 | int gen; /* Generation */ |
23 | /* | ||
24 | * Hash table: for real service lookups | ||
25 | */ | ||
26 | #define IP_VS_RTAB_BITS 4 | ||
27 | #define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS) | ||
28 | #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1) | ||
29 | |||
30 | struct list_head rs_table[IP_VS_RTAB_SIZE]; | ||
23 | }; | 31 | }; |
24 | 32 | ||
25 | #endif /* IP_VS_H_ */ | 33 | #endif /* IP_VS_H_ */ |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 7c1b502f8d8d..7a0e79e3ad0f 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
@@ -611,7 +611,7 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) | |||
611 | struct ip_vs_dest *dest; | 611 | struct ip_vs_dest *dest; |
612 | 612 | ||
613 | if ((cp) && (!cp->dest)) { | 613 | if ((cp) && (!cp->dest)) { |
614 | dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport, | 614 | dest = ip_vs_find_dest(&init_net, cp->af, &cp->daddr, cp->dport, |
615 | &cp->vaddr, cp->vport, | 615 | &cp->vaddr, cp->vport, |
616 | cp->protocol, cp->fwmark); | 616 | cp->protocol, cp->fwmark); |
617 | ip_vs_bind_dest(cp, dest); | 617 | ip_vs_bind_dest(cp, dest); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 206f40c548d7..d0616ea1eebf 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1031,6 +1031,7 @@ drop: | |||
1031 | static unsigned int | 1031 | static unsigned int |
1032 | ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | 1032 | ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) |
1033 | { | 1033 | { |
1034 | struct net *net = NULL; | ||
1034 | struct ip_vs_iphdr iph; | 1035 | struct ip_vs_iphdr iph; |
1035 | struct ip_vs_protocol *pp; | 1036 | struct ip_vs_protocol *pp; |
1036 | struct ip_vs_conn *cp; | 1037 | struct ip_vs_conn *cp; |
@@ -1054,6 +1055,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1054 | if (unlikely(!skb_dst(skb))) | 1055 | if (unlikely(!skb_dst(skb))) |
1055 | return NF_ACCEPT; | 1056 | return NF_ACCEPT; |
1056 | 1057 | ||
1058 | net = skb_net(skb); | ||
1057 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1059 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1058 | #ifdef CONFIG_IP_VS_IPV6 | 1060 | #ifdef CONFIG_IP_VS_IPV6 |
1059 | if (af == AF_INET6) { | 1061 | if (af == AF_INET6) { |
@@ -1119,7 +1121,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1119 | sizeof(_ports), _ports); | 1121 | sizeof(_ports), _ports); |
1120 | if (pptr == NULL) | 1122 | if (pptr == NULL) |
1121 | return NF_ACCEPT; /* Not for me */ | 1123 | return NF_ACCEPT; /* Not for me */ |
1122 | if (ip_vs_lookup_real_service(af, iph.protocol, | 1124 | if (ip_vs_lookup_real_service(net, af, iph.protocol, |
1123 | &iph.saddr, | 1125 | &iph.saddr, |
1124 | pptr[0])) { | 1126 | pptr[0])) { |
1125 | /* | 1127 | /* |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index ceeef4352d34..2d7c96bd2114 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -288,15 +288,6 @@ static struct list_head ip_vs_svc_table[IP_VS_SVC_TAB_SIZE]; | |||
288 | static struct list_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE]; | 288 | static struct list_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE]; |
289 | 289 | ||
290 | /* | 290 | /* |
291 | * Hash table: for real service lookups | ||
292 | */ | ||
293 | #define IP_VS_RTAB_BITS 4 | ||
294 | #define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS) | ||
295 | #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1) | ||
296 | |||
297 | static struct list_head ip_vs_rtable[IP_VS_RTAB_SIZE]; | ||
298 | |||
299 | /* | ||
300 | * Trash for destinations | 291 | * Trash for destinations |
301 | */ | 292 | */ |
302 | static LIST_HEAD(ip_vs_dest_trash); | 293 | static LIST_HEAD(ip_vs_dest_trash); |
@@ -311,9 +302,9 @@ static atomic_t ip_vs_nullsvc_counter = ATOMIC_INIT(0); | |||
311 | /* | 302 | /* |
312 | * Returns hash value for virtual service | 303 | * Returns hash value for virtual service |
313 | */ | 304 | */ |
314 | static __inline__ unsigned | 305 | static inline unsigned |
315 | ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr, | 306 | ip_vs_svc_hashkey(struct net *net, int af, unsigned proto, |
316 | __be16 port) | 307 | const union nf_inet_addr *addr, __be16 port) |
317 | { | 308 | { |
318 | register unsigned porth = ntohs(port); | 309 | register unsigned porth = ntohs(port); |
319 | __be32 addr_fold = addr->ip; | 310 | __be32 addr_fold = addr->ip; |
@@ -323,6 +314,7 @@ ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr, | |||
323 | addr_fold = addr->ip6[0]^addr->ip6[1]^ | 314 | addr_fold = addr->ip6[0]^addr->ip6[1]^ |
324 | addr->ip6[2]^addr->ip6[3]; | 315 | addr->ip6[2]^addr->ip6[3]; |
325 | #endif | 316 | #endif |
317 | addr_fold ^= ((size_t)net>>8); | ||
326 | 318 | ||
327 | return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth) | 319 | return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth) |
328 | & IP_VS_SVC_TAB_MASK; | 320 | & IP_VS_SVC_TAB_MASK; |
@@ -331,13 +323,13 @@ ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr, | |||
331 | /* | 323 | /* |
332 | * Returns hash value of fwmark for virtual service lookup | 324 | * Returns hash value of fwmark for virtual service lookup |
333 | */ | 325 | */ |
334 | static __inline__ unsigned ip_vs_svc_fwm_hashkey(__u32 fwmark) | 326 | static inline unsigned ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark) |
335 | { | 327 | { |
336 | return fwmark & IP_VS_SVC_TAB_MASK; | 328 | return (((size_t)net>>8) ^ fwmark) & IP_VS_SVC_TAB_MASK; |
337 | } | 329 | } |
338 | 330 | ||
339 | /* | 331 | /* |
340 | * Hashes a service in the ip_vs_svc_table by <proto,addr,port> | 332 | * Hashes a service in the ip_vs_svc_table by <netns,proto,addr,port> |
341 | * or in the ip_vs_svc_fwm_table by fwmark. | 333 | * or in the ip_vs_svc_fwm_table by fwmark. |
342 | * Should be called with locked tables. | 334 | * Should be called with locked tables. |
343 | */ | 335 | */ |
@@ -353,16 +345,16 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc) | |||
353 | 345 | ||
354 | if (svc->fwmark == 0) { | 346 | if (svc->fwmark == 0) { |
355 | /* | 347 | /* |
356 | * Hash it by <protocol,addr,port> in ip_vs_svc_table | 348 | * Hash it by <netns,protocol,addr,port> in ip_vs_svc_table |
357 | */ | 349 | */ |
358 | hash = ip_vs_svc_hashkey(svc->af, svc->protocol, &svc->addr, | 350 | hash = ip_vs_svc_hashkey(svc->net, svc->af, svc->protocol, |
359 | svc->port); | 351 | &svc->addr, svc->port); |
360 | list_add(&svc->s_list, &ip_vs_svc_table[hash]); | 352 | list_add(&svc->s_list, &ip_vs_svc_table[hash]); |
361 | } else { | 353 | } else { |
362 | /* | 354 | /* |
363 | * Hash it by fwmark in ip_vs_svc_fwm_table | 355 | * Hash it by fwmark in svc_fwm_table |
364 | */ | 356 | */ |
365 | hash = ip_vs_svc_fwm_hashkey(svc->fwmark); | 357 | hash = ip_vs_svc_fwm_hashkey(svc->net, svc->fwmark); |
366 | list_add(&svc->f_list, &ip_vs_svc_fwm_table[hash]); | 358 | list_add(&svc->f_list, &ip_vs_svc_fwm_table[hash]); |
367 | } | 359 | } |
368 | 360 | ||
@@ -374,7 +366,7 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc) | |||
374 | 366 | ||
375 | 367 | ||
376 | /* | 368 | /* |
377 | * Unhashes a service from ip_vs_svc_table/ip_vs_svc_fwm_table. | 369 | * Unhashes a service from svc_table / svc_fwm_table. |
378 | * Should be called with locked tables. | 370 | * Should be called with locked tables. |
379 | */ | 371 | */ |
380 | static int ip_vs_svc_unhash(struct ip_vs_service *svc) | 372 | static int ip_vs_svc_unhash(struct ip_vs_service *svc) |
@@ -386,10 +378,10 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc) | |||
386 | } | 378 | } |
387 | 379 | ||
388 | if (svc->fwmark == 0) { | 380 | if (svc->fwmark == 0) { |
389 | /* Remove it from the ip_vs_svc_table table */ | 381 | /* Remove it from the svc_table table */ |
390 | list_del(&svc->s_list); | 382 | list_del(&svc->s_list); |
391 | } else { | 383 | } else { |
392 | /* Remove it from the ip_vs_svc_fwm_table table */ | 384 | /* Remove it from the svc_fwm_table table */ |
393 | list_del(&svc->f_list); | 385 | list_del(&svc->f_list); |
394 | } | 386 | } |
395 | 387 | ||
@@ -400,23 +392,24 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc) | |||
400 | 392 | ||
401 | 393 | ||
402 | /* | 394 | /* |
403 | * Get service by {proto,addr,port} in the service table. | 395 | * Get service by {netns, proto,addr,port} in the service table. |
404 | */ | 396 | */ |
405 | static inline struct ip_vs_service * | 397 | static inline struct ip_vs_service * |
406 | __ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr, | 398 | __ip_vs_service_find(struct net *net, int af, __u16 protocol, |
407 | __be16 vport) | 399 | const union nf_inet_addr *vaddr, __be16 vport) |
408 | { | 400 | { |
409 | unsigned hash; | 401 | unsigned hash; |
410 | struct ip_vs_service *svc; | 402 | struct ip_vs_service *svc; |
411 | 403 | ||
412 | /* Check for "full" addressed entries */ | 404 | /* Check for "full" addressed entries */ |
413 | hash = ip_vs_svc_hashkey(af, protocol, vaddr, vport); | 405 | hash = ip_vs_svc_hashkey(net, af, protocol, vaddr, vport); |
414 | 406 | ||
415 | list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){ | 407 | list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){ |
416 | if ((svc->af == af) | 408 | if ((svc->af == af) |
417 | && ip_vs_addr_equal(af, &svc->addr, vaddr) | 409 | && ip_vs_addr_equal(af, &svc->addr, vaddr) |
418 | && (svc->port == vport) | 410 | && (svc->port == vport) |
419 | && (svc->protocol == protocol)) { | 411 | && (svc->protocol == protocol) |
412 | && net_eq(svc->net, net)) { | ||
420 | /* HIT */ | 413 | /* HIT */ |
421 | return svc; | 414 | return svc; |
422 | } | 415 | } |
@@ -430,16 +423,17 @@ __ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr, | |||
430 | * Get service by {fwmark} in the service table. | 423 | * Get service by {fwmark} in the service table. |
431 | */ | 424 | */ |
432 | static inline struct ip_vs_service * | 425 | static inline struct ip_vs_service * |
433 | __ip_vs_svc_fwm_find(int af, __u32 fwmark) | 426 | __ip_vs_svc_fwm_find(struct net *net, int af, __u32 fwmark) |
434 | { | 427 | { |
435 | unsigned hash; | 428 | unsigned hash; |
436 | struct ip_vs_service *svc; | 429 | struct ip_vs_service *svc; |
437 | 430 | ||
438 | /* Check for fwmark addressed entries */ | 431 | /* Check for fwmark addressed entries */ |
439 | hash = ip_vs_svc_fwm_hashkey(fwmark); | 432 | hash = ip_vs_svc_fwm_hashkey(net, fwmark); |
440 | 433 | ||
441 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) { | 434 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) { |
442 | if (svc->fwmark == fwmark && svc->af == af) { | 435 | if (svc->fwmark == fwmark && svc->af == af |
436 | && net_eq(svc->net, net)) { | ||
443 | /* HIT */ | 437 | /* HIT */ |
444 | return svc; | 438 | return svc; |
445 | } | 439 | } |
@@ -449,7 +443,7 @@ __ip_vs_svc_fwm_find(int af, __u32 fwmark) | |||
449 | } | 443 | } |
450 | 444 | ||
451 | struct ip_vs_service * | 445 | struct ip_vs_service * |
452 | ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, | 446 | ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol, |
453 | const union nf_inet_addr *vaddr, __be16 vport) | 447 | const union nf_inet_addr *vaddr, __be16 vport) |
454 | { | 448 | { |
455 | struct ip_vs_service *svc; | 449 | struct ip_vs_service *svc; |
@@ -459,14 +453,15 @@ ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, | |||
459 | /* | 453 | /* |
460 | * Check the table hashed by fwmark first | 454 | * Check the table hashed by fwmark first |
461 | */ | 455 | */ |
462 | if (fwmark && (svc = __ip_vs_svc_fwm_find(af, fwmark))) | 456 | svc = __ip_vs_svc_fwm_find(net, af, fwmark); |
457 | if (fwmark && svc) | ||
463 | goto out; | 458 | goto out; |
464 | 459 | ||
465 | /* | 460 | /* |
466 | * Check the table hashed by <protocol,addr,port> | 461 | * Check the table hashed by <protocol,addr,port> |
467 | * for "full" addressed entries | 462 | * for "full" addressed entries |
468 | */ | 463 | */ |
469 | svc = __ip_vs_service_find(af, protocol, vaddr, vport); | 464 | svc = __ip_vs_service_find(net, af, protocol, vaddr, vport); |
470 | 465 | ||
471 | if (svc == NULL | 466 | if (svc == NULL |
472 | && protocol == IPPROTO_TCP | 467 | && protocol == IPPROTO_TCP |
@@ -476,7 +471,7 @@ ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, | |||
476 | * Check if ftp service entry exists, the packet | 471 | * Check if ftp service entry exists, the packet |
477 | * might belong to FTP data connections. | 472 | * might belong to FTP data connections. |
478 | */ | 473 | */ |
479 | svc = __ip_vs_service_find(af, protocol, vaddr, FTPPORT); | 474 | svc = __ip_vs_service_find(net, af, protocol, vaddr, FTPPORT); |
480 | } | 475 | } |
481 | 476 | ||
482 | if (svc == NULL | 477 | if (svc == NULL |
@@ -484,7 +479,7 @@ ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, | |||
484 | /* | 479 | /* |
485 | * Check if the catch-all port (port zero) exists | 480 | * Check if the catch-all port (port zero) exists |
486 | */ | 481 | */ |
487 | svc = __ip_vs_service_find(af, protocol, vaddr, 0); | 482 | svc = __ip_vs_service_find(net, af, protocol, vaddr, 0); |
488 | } | 483 | } |
489 | 484 | ||
490 | out: | 485 | out: |
@@ -545,10 +540,10 @@ static inline unsigned ip_vs_rs_hashkey(int af, | |||
545 | } | 540 | } |
546 | 541 | ||
547 | /* | 542 | /* |
548 | * Hashes ip_vs_dest in ip_vs_rtable by <proto,addr,port>. | 543 | * Hashes ip_vs_dest in rs_table by <proto,addr,port>. |
549 | * should be called with locked tables. | 544 | * should be called with locked tables. |
550 | */ | 545 | */ |
551 | static int ip_vs_rs_hash(struct ip_vs_dest *dest) | 546 | static int ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest) |
552 | { | 547 | { |
553 | unsigned hash; | 548 | unsigned hash; |
554 | 549 | ||
@@ -562,19 +557,19 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest) | |||
562 | */ | 557 | */ |
563 | hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); | 558 | hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); |
564 | 559 | ||
565 | list_add(&dest->d_list, &ip_vs_rtable[hash]); | 560 | list_add(&dest->d_list, &ipvs->rs_table[hash]); |
566 | 561 | ||
567 | return 1; | 562 | return 1; |
568 | } | 563 | } |
569 | 564 | ||
570 | /* | 565 | /* |
571 | * UNhashes ip_vs_dest from ip_vs_rtable. | 566 | * UNhashes ip_vs_dest from rs_table. |
572 | * should be called with locked tables. | 567 | * should be called with locked tables. |
573 | */ | 568 | */ |
574 | static int ip_vs_rs_unhash(struct ip_vs_dest *dest) | 569 | static int ip_vs_rs_unhash(struct ip_vs_dest *dest) |
575 | { | 570 | { |
576 | /* | 571 | /* |
577 | * Remove it from the ip_vs_rtable table. | 572 | * Remove it from the rs_table table. |
578 | */ | 573 | */ |
579 | if (!list_empty(&dest->d_list)) { | 574 | if (!list_empty(&dest->d_list)) { |
580 | list_del(&dest->d_list); | 575 | list_del(&dest->d_list); |
@@ -588,10 +583,11 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest) | |||
588 | * Lookup real service by <proto,addr,port> in the real service table. | 583 | * Lookup real service by <proto,addr,port> in the real service table. |
589 | */ | 584 | */ |
590 | struct ip_vs_dest * | 585 | struct ip_vs_dest * |
591 | ip_vs_lookup_real_service(int af, __u16 protocol, | 586 | ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol, |
592 | const union nf_inet_addr *daddr, | 587 | const union nf_inet_addr *daddr, |
593 | __be16 dport) | 588 | __be16 dport) |
594 | { | 589 | { |
590 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
595 | unsigned hash; | 591 | unsigned hash; |
596 | struct ip_vs_dest *dest; | 592 | struct ip_vs_dest *dest; |
597 | 593 | ||
@@ -602,7 +598,7 @@ ip_vs_lookup_real_service(int af, __u16 protocol, | |||
602 | hash = ip_vs_rs_hashkey(af, daddr, dport); | 598 | hash = ip_vs_rs_hashkey(af, daddr, dport); |
603 | 599 | ||
604 | read_lock(&__ip_vs_rs_lock); | 600 | read_lock(&__ip_vs_rs_lock); |
605 | list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { | 601 | list_for_each_entry(dest, &ipvs->rs_table[hash], d_list) { |
606 | if ((dest->af == af) | 602 | if ((dest->af == af) |
607 | && ip_vs_addr_equal(af, &dest->addr, daddr) | 603 | && ip_vs_addr_equal(af, &dest->addr, daddr) |
608 | && (dest->port == dport) | 604 | && (dest->port == dport) |
@@ -652,7 +648,8 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, | |||
652 | * ip_vs_lookup_real_service() looked promissing, but | 648 | * ip_vs_lookup_real_service() looked promissing, but |
653 | * seems not working as expected. | 649 | * seems not working as expected. |
654 | */ | 650 | */ |
655 | struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr, | 651 | struct ip_vs_dest *ip_vs_find_dest(struct net *net, int af, |
652 | const union nf_inet_addr *daddr, | ||
656 | __be16 dport, | 653 | __be16 dport, |
657 | const union nf_inet_addr *vaddr, | 654 | const union nf_inet_addr *vaddr, |
658 | __be16 vport, __u16 protocol, __u32 fwmark) | 655 | __be16 vport, __u16 protocol, __u32 fwmark) |
@@ -660,7 +657,7 @@ struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr, | |||
660 | struct ip_vs_dest *dest; | 657 | struct ip_vs_dest *dest; |
661 | struct ip_vs_service *svc; | 658 | struct ip_vs_service *svc; |
662 | 659 | ||
663 | svc = ip_vs_service_get(af, fwmark, protocol, vaddr, vport); | 660 | svc = ip_vs_service_get(net, af, fwmark, protocol, vaddr, vport); |
664 | if (!svc) | 661 | if (!svc) |
665 | return NULL; | 662 | return NULL; |
666 | dest = ip_vs_lookup_dest(svc, daddr, dport); | 663 | dest = ip_vs_lookup_dest(svc, daddr, dport); |
@@ -768,6 +765,7 @@ static void | |||
768 | __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, | 765 | __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, |
769 | struct ip_vs_dest_user_kern *udest, int add) | 766 | struct ip_vs_dest_user_kern *udest, int add) |
770 | { | 767 | { |
768 | struct netns_ipvs *ipvs = net_ipvs(svc->net); | ||
771 | int conn_flags; | 769 | int conn_flags; |
772 | 770 | ||
773 | /* set the weight and the flags */ | 771 | /* set the weight and the flags */ |
@@ -780,11 +778,11 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, | |||
780 | conn_flags |= IP_VS_CONN_F_NOOUTPUT; | 778 | conn_flags |= IP_VS_CONN_F_NOOUTPUT; |
781 | } else { | 779 | } else { |
782 | /* | 780 | /* |
783 | * Put the real service in ip_vs_rtable if not present. | 781 | * Put the real service in rs_table if not present. |
784 | * For now only for NAT! | 782 | * For now only for NAT! |
785 | */ | 783 | */ |
786 | write_lock_bh(&__ip_vs_rs_lock); | 784 | write_lock_bh(&__ip_vs_rs_lock); |
787 | ip_vs_rs_hash(dest); | 785 | ip_vs_rs_hash(ipvs, dest); |
788 | write_unlock_bh(&__ip_vs_rs_lock); | 786 | write_unlock_bh(&__ip_vs_rs_lock); |
789 | } | 787 | } |
790 | atomic_set(&dest->conn_flags, conn_flags); | 788 | atomic_set(&dest->conn_flags, conn_flags); |
@@ -1117,7 +1115,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) | |||
1117 | * Add a service into the service hash table | 1115 | * Add a service into the service hash table |
1118 | */ | 1116 | */ |
1119 | static int | 1117 | static int |
1120 | ip_vs_add_service(struct ip_vs_service_user_kern *u, | 1118 | ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, |
1121 | struct ip_vs_service **svc_p) | 1119 | struct ip_vs_service **svc_p) |
1122 | { | 1120 | { |
1123 | int ret = 0; | 1121 | int ret = 0; |
@@ -1172,6 +1170,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u, | |||
1172 | svc->flags = u->flags; | 1170 | svc->flags = u->flags; |
1173 | svc->timeout = u->timeout * HZ; | 1171 | svc->timeout = u->timeout * HZ; |
1174 | svc->netmask = u->netmask; | 1172 | svc->netmask = u->netmask; |
1173 | svc->net = net; | ||
1175 | 1174 | ||
1176 | INIT_LIST_HEAD(&svc->destinations); | 1175 | INIT_LIST_HEAD(&svc->destinations); |
1177 | rwlock_init(&svc->sched_lock); | 1176 | rwlock_init(&svc->sched_lock); |
@@ -1428,17 +1427,19 @@ static int ip_vs_del_service(struct ip_vs_service *svc) | |||
1428 | /* | 1427 | /* |
1429 | * Flush all the virtual services | 1428 | * Flush all the virtual services |
1430 | */ | 1429 | */ |
1431 | static int ip_vs_flush(void) | 1430 | static int ip_vs_flush(struct net *net) |
1432 | { | 1431 | { |
1433 | int idx; | 1432 | int idx; |
1434 | struct ip_vs_service *svc, *nxt; | 1433 | struct ip_vs_service *svc, *nxt; |
1435 | 1434 | ||
1436 | /* | 1435 | /* |
1437 | * Flush the service table hashed by <protocol,addr,port> | 1436 | * Flush the service table hashed by <netns,protocol,addr,port> |
1438 | */ | 1437 | */ |
1439 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 1438 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
1440 | list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx], s_list) { | 1439 | list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx], |
1441 | ip_vs_unlink_service(svc); | 1440 | s_list) { |
1441 | if (net_eq(svc->net, net)) | ||
1442 | ip_vs_unlink_service(svc); | ||
1442 | } | 1443 | } |
1443 | } | 1444 | } |
1444 | 1445 | ||
@@ -1448,7 +1449,8 @@ static int ip_vs_flush(void) | |||
1448 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 1449 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
1449 | list_for_each_entry_safe(svc, nxt, | 1450 | list_for_each_entry_safe(svc, nxt, |
1450 | &ip_vs_svc_fwm_table[idx], f_list) { | 1451 | &ip_vs_svc_fwm_table[idx], f_list) { |
1451 | ip_vs_unlink_service(svc); | 1452 | if (net_eq(svc->net, net)) |
1453 | ip_vs_unlink_service(svc); | ||
1452 | } | 1454 | } |
1453 | } | 1455 | } |
1454 | 1456 | ||
@@ -1472,20 +1474,22 @@ static int ip_vs_zero_service(struct ip_vs_service *svc) | |||
1472 | return 0; | 1474 | return 0; |
1473 | } | 1475 | } |
1474 | 1476 | ||
1475 | static int ip_vs_zero_all(void) | 1477 | static int ip_vs_zero_all(struct net *net) |
1476 | { | 1478 | { |
1477 | int idx; | 1479 | int idx; |
1478 | struct ip_vs_service *svc; | 1480 | struct ip_vs_service *svc; |
1479 | 1481 | ||
1480 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 1482 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
1481 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | 1483 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { |
1482 | ip_vs_zero_service(svc); | 1484 | if (net_eq(svc->net, net)) |
1485 | ip_vs_zero_service(svc); | ||
1483 | } | 1486 | } |
1484 | } | 1487 | } |
1485 | 1488 | ||
1486 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 1489 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
1487 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | 1490 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { |
1488 | ip_vs_zero_service(svc); | 1491 | if (net_eq(svc->net, net)) |
1492 | ip_vs_zero_service(svc); | ||
1489 | } | 1493 | } |
1490 | } | 1494 | } |
1491 | 1495 | ||
@@ -1763,6 +1767,7 @@ static struct ctl_table_header * sysctl_header; | |||
1763 | #ifdef CONFIG_PROC_FS | 1767 | #ifdef CONFIG_PROC_FS |
1764 | 1768 | ||
1765 | struct ip_vs_iter { | 1769 | struct ip_vs_iter { |
1770 | struct seq_net_private p; /* Do not move this, netns depends upon it*/ | ||
1766 | struct list_head *table; | 1771 | struct list_head *table; |
1767 | int bucket; | 1772 | int bucket; |
1768 | }; | 1773 | }; |
@@ -1789,6 +1794,7 @@ static inline const char *ip_vs_fwd_name(unsigned flags) | |||
1789 | /* Get the Nth entry in the two lists */ | 1794 | /* Get the Nth entry in the two lists */ |
1790 | static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos) | 1795 | static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos) |
1791 | { | 1796 | { |
1797 | struct net *net = seq_file_net(seq); | ||
1792 | struct ip_vs_iter *iter = seq->private; | 1798 | struct ip_vs_iter *iter = seq->private; |
1793 | int idx; | 1799 | int idx; |
1794 | struct ip_vs_service *svc; | 1800 | struct ip_vs_service *svc; |
@@ -1796,7 +1802,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos) | |||
1796 | /* look in hash by protocol */ | 1802 | /* look in hash by protocol */ |
1797 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 1803 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
1798 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | 1804 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { |
1799 | if (pos-- == 0){ | 1805 | if (net_eq(svc->net, net) && pos-- == 0) { |
1800 | iter->table = ip_vs_svc_table; | 1806 | iter->table = ip_vs_svc_table; |
1801 | iter->bucket = idx; | 1807 | iter->bucket = idx; |
1802 | return svc; | 1808 | return svc; |
@@ -1807,7 +1813,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos) | |||
1807 | /* keep looking in fwmark */ | 1813 | /* keep looking in fwmark */ |
1808 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 1814 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
1809 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | 1815 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { |
1810 | if (pos-- == 0) { | 1816 | if (net_eq(svc->net, net) && pos-- == 0) { |
1811 | iter->table = ip_vs_svc_fwm_table; | 1817 | iter->table = ip_vs_svc_fwm_table; |
1812 | iter->bucket = idx; | 1818 | iter->bucket = idx; |
1813 | return svc; | 1819 | return svc; |
@@ -1961,7 +1967,7 @@ static const struct seq_operations ip_vs_info_seq_ops = { | |||
1961 | 1967 | ||
1962 | static int ip_vs_info_open(struct inode *inode, struct file *file) | 1968 | static int ip_vs_info_open(struct inode *inode, struct file *file) |
1963 | { | 1969 | { |
1964 | return seq_open_private(file, &ip_vs_info_seq_ops, | 1970 | return seq_open_net(inode, file, &ip_vs_info_seq_ops, |
1965 | sizeof(struct ip_vs_iter)); | 1971 | sizeof(struct ip_vs_iter)); |
1966 | } | 1972 | } |
1967 | 1973 | ||
@@ -2011,7 +2017,7 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v) | |||
2011 | 2017 | ||
2012 | static int ip_vs_stats_seq_open(struct inode *inode, struct file *file) | 2018 | static int ip_vs_stats_seq_open(struct inode *inode, struct file *file) |
2013 | { | 2019 | { |
2014 | return single_open(file, ip_vs_stats_show, NULL); | 2020 | return single_open_net(inode, file, ip_vs_stats_show); |
2015 | } | 2021 | } |
2016 | 2022 | ||
2017 | static const struct file_operations ip_vs_stats_fops = { | 2023 | static const struct file_operations ip_vs_stats_fops = { |
@@ -2113,6 +2119,7 @@ static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest, | |||
2113 | static int | 2119 | static int |
2114 | do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | 2120 | do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) |
2115 | { | 2121 | { |
2122 | struct net *net = sock_net(sk); | ||
2116 | int ret; | 2123 | int ret; |
2117 | unsigned char arg[MAX_ARG_LEN]; | 2124 | unsigned char arg[MAX_ARG_LEN]; |
2118 | struct ip_vs_service_user *usvc_compat; | 2125 | struct ip_vs_service_user *usvc_compat; |
@@ -2147,7 +2154,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2147 | 2154 | ||
2148 | if (cmd == IP_VS_SO_SET_FLUSH) { | 2155 | if (cmd == IP_VS_SO_SET_FLUSH) { |
2149 | /* Flush the virtual service */ | 2156 | /* Flush the virtual service */ |
2150 | ret = ip_vs_flush(); | 2157 | ret = ip_vs_flush(net); |
2151 | goto out_unlock; | 2158 | goto out_unlock; |
2152 | } else if (cmd == IP_VS_SO_SET_TIMEOUT) { | 2159 | } else if (cmd == IP_VS_SO_SET_TIMEOUT) { |
2153 | /* Set timeout values for (tcp tcpfin udp) */ | 2160 | /* Set timeout values for (tcp tcpfin udp) */ |
@@ -2174,7 +2181,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2174 | if (cmd == IP_VS_SO_SET_ZERO) { | 2181 | if (cmd == IP_VS_SO_SET_ZERO) { |
2175 | /* if no service address is set, zero counters in all */ | 2182 | /* if no service address is set, zero counters in all */ |
2176 | if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) { | 2183 | if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) { |
2177 | ret = ip_vs_zero_all(); | 2184 | ret = ip_vs_zero_all(net); |
2178 | goto out_unlock; | 2185 | goto out_unlock; |
2179 | } | 2186 | } |
2180 | } | 2187 | } |
@@ -2191,10 +2198,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2191 | 2198 | ||
2192 | /* Lookup the exact service by <protocol, addr, port> or fwmark */ | 2199 | /* Lookup the exact service by <protocol, addr, port> or fwmark */ |
2193 | if (usvc.fwmark == 0) | 2200 | if (usvc.fwmark == 0) |
2194 | svc = __ip_vs_service_find(usvc.af, usvc.protocol, | 2201 | svc = __ip_vs_service_find(net, usvc.af, usvc.protocol, |
2195 | &usvc.addr, usvc.port); | 2202 | &usvc.addr, usvc.port); |
2196 | else | 2203 | else |
2197 | svc = __ip_vs_svc_fwm_find(usvc.af, usvc.fwmark); | 2204 | svc = __ip_vs_svc_fwm_find(net, usvc.af, usvc.fwmark); |
2198 | 2205 | ||
2199 | if (cmd != IP_VS_SO_SET_ADD | 2206 | if (cmd != IP_VS_SO_SET_ADD |
2200 | && (svc == NULL || svc->protocol != usvc.protocol)) { | 2207 | && (svc == NULL || svc->protocol != usvc.protocol)) { |
@@ -2207,7 +2214,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2207 | if (svc != NULL) | 2214 | if (svc != NULL) |
2208 | ret = -EEXIST; | 2215 | ret = -EEXIST; |
2209 | else | 2216 | else |
2210 | ret = ip_vs_add_service(&usvc, &svc); | 2217 | ret = ip_vs_add_service(net, &usvc, &svc); |
2211 | break; | 2218 | break; |
2212 | case IP_VS_SO_SET_EDIT: | 2219 | case IP_VS_SO_SET_EDIT: |
2213 | ret = ip_vs_edit_service(svc, &usvc); | 2220 | ret = ip_vs_edit_service(svc, &usvc); |
@@ -2267,7 +2274,8 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src) | |||
2267 | } | 2274 | } |
2268 | 2275 | ||
2269 | static inline int | 2276 | static inline int |
2270 | __ip_vs_get_service_entries(const struct ip_vs_get_services *get, | 2277 | __ip_vs_get_service_entries(struct net *net, |
2278 | const struct ip_vs_get_services *get, | ||
2271 | struct ip_vs_get_services __user *uptr) | 2279 | struct ip_vs_get_services __user *uptr) |
2272 | { | 2280 | { |
2273 | int idx, count=0; | 2281 | int idx, count=0; |
@@ -2278,7 +2286,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, | |||
2278 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 2286 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
2279 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | 2287 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { |
2280 | /* Only expose IPv4 entries to old interface */ | 2288 | /* Only expose IPv4 entries to old interface */ |
2281 | if (svc->af != AF_INET) | 2289 | if (svc->af != AF_INET || !net_eq(svc->net, net)) |
2282 | continue; | 2290 | continue; |
2283 | 2291 | ||
2284 | if (count >= get->num_services) | 2292 | if (count >= get->num_services) |
@@ -2297,7 +2305,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, | |||
2297 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 2305 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
2298 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | 2306 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { |
2299 | /* Only expose IPv4 entries to old interface */ | 2307 | /* Only expose IPv4 entries to old interface */ |
2300 | if (svc->af != AF_INET) | 2308 | if (svc->af != AF_INET || !net_eq(svc->net, net)) |
2301 | continue; | 2309 | continue; |
2302 | 2310 | ||
2303 | if (count >= get->num_services) | 2311 | if (count >= get->num_services) |
@@ -2317,7 +2325,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get, | |||
2317 | } | 2325 | } |
2318 | 2326 | ||
2319 | static inline int | 2327 | static inline int |
2320 | __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get, | 2328 | __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, |
2321 | struct ip_vs_get_dests __user *uptr) | 2329 | struct ip_vs_get_dests __user *uptr) |
2322 | { | 2330 | { |
2323 | struct ip_vs_service *svc; | 2331 | struct ip_vs_service *svc; |
@@ -2325,9 +2333,9 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get, | |||
2325 | int ret = 0; | 2333 | int ret = 0; |
2326 | 2334 | ||
2327 | if (get->fwmark) | 2335 | if (get->fwmark) |
2328 | svc = __ip_vs_svc_fwm_find(AF_INET, get->fwmark); | 2336 | svc = __ip_vs_svc_fwm_find(net, AF_INET, get->fwmark); |
2329 | else | 2337 | else |
2330 | svc = __ip_vs_service_find(AF_INET, get->protocol, &addr, | 2338 | svc = __ip_vs_service_find(net, AF_INET, get->protocol, &addr, |
2331 | get->port); | 2339 | get->port); |
2332 | 2340 | ||
2333 | if (svc) { | 2341 | if (svc) { |
@@ -2401,7 +2409,9 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2401 | unsigned char arg[128]; | 2409 | unsigned char arg[128]; |
2402 | int ret = 0; | 2410 | int ret = 0; |
2403 | unsigned int copylen; | 2411 | unsigned int copylen; |
2412 | struct net *net = sock_net(sk); | ||
2404 | 2413 | ||
2414 | BUG_ON(!net); | ||
2405 | if (!capable(CAP_NET_ADMIN)) | 2415 | if (!capable(CAP_NET_ADMIN)) |
2406 | return -EPERM; | 2416 | return -EPERM; |
2407 | 2417 | ||
@@ -2463,7 +2473,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2463 | ret = -EINVAL; | 2473 | ret = -EINVAL; |
2464 | goto out; | 2474 | goto out; |
2465 | } | 2475 | } |
2466 | ret = __ip_vs_get_service_entries(get, user); | 2476 | ret = __ip_vs_get_service_entries(net, get, user); |
2467 | } | 2477 | } |
2468 | break; | 2478 | break; |
2469 | 2479 | ||
@@ -2476,10 +2486,11 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2476 | entry = (struct ip_vs_service_entry *)arg; | 2486 | entry = (struct ip_vs_service_entry *)arg; |
2477 | addr.ip = entry->addr; | 2487 | addr.ip = entry->addr; |
2478 | if (entry->fwmark) | 2488 | if (entry->fwmark) |
2479 | svc = __ip_vs_svc_fwm_find(AF_INET, entry->fwmark); | 2489 | svc = __ip_vs_svc_fwm_find(net, AF_INET, entry->fwmark); |
2480 | else | 2490 | else |
2481 | svc = __ip_vs_service_find(AF_INET, entry->protocol, | 2491 | svc = __ip_vs_service_find(net, AF_INET, |
2482 | &addr, entry->port); | 2492 | entry->protocol, &addr, |
2493 | entry->port); | ||
2483 | if (svc) { | 2494 | if (svc) { |
2484 | ip_vs_copy_service(entry, svc); | 2495 | ip_vs_copy_service(entry, svc); |
2485 | if (copy_to_user(user, entry, sizeof(*entry)) != 0) | 2496 | if (copy_to_user(user, entry, sizeof(*entry)) != 0) |
@@ -2502,7 +2513,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2502 | ret = -EINVAL; | 2513 | ret = -EINVAL; |
2503 | goto out; | 2514 | goto out; |
2504 | } | 2515 | } |
2505 | ret = __ip_vs_get_dest_entries(get, user); | 2516 | ret = __ip_vs_get_dest_entries(net, get, user); |
2506 | } | 2517 | } |
2507 | break; | 2518 | break; |
2508 | 2519 | ||
@@ -2722,11 +2733,12 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb, | |||
2722 | int idx = 0, i; | 2733 | int idx = 0, i; |
2723 | int start = cb->args[0]; | 2734 | int start = cb->args[0]; |
2724 | struct ip_vs_service *svc; | 2735 | struct ip_vs_service *svc; |
2736 | struct net *net = skb_sknet(skb); | ||
2725 | 2737 | ||
2726 | mutex_lock(&__ip_vs_mutex); | 2738 | mutex_lock(&__ip_vs_mutex); |
2727 | for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { | 2739 | for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { |
2728 | list_for_each_entry(svc, &ip_vs_svc_table[i], s_list) { | 2740 | list_for_each_entry(svc, &ip_vs_svc_table[i], s_list) { |
2729 | if (++idx <= start) | 2741 | if (++idx <= start || !net_eq(svc->net, net)) |
2730 | continue; | 2742 | continue; |
2731 | if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { | 2743 | if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { |
2732 | idx--; | 2744 | idx--; |
@@ -2737,7 +2749,7 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb, | |||
2737 | 2749 | ||
2738 | for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { | 2750 | for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) { |
2739 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) { | 2751 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) { |
2740 | if (++idx <= start) | 2752 | if (++idx <= start || !net_eq(svc->net, net)) |
2741 | continue; | 2753 | continue; |
2742 | if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { | 2754 | if (ip_vs_genl_dump_service(skb, svc, cb) < 0) { |
2743 | idx--; | 2755 | idx--; |
@@ -2753,7 +2765,8 @@ nla_put_failure: | |||
2753 | return skb->len; | 2765 | return skb->len; |
2754 | } | 2766 | } |
2755 | 2767 | ||
2756 | static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc, | 2768 | static int ip_vs_genl_parse_service(struct net *net, |
2769 | struct ip_vs_service_user_kern *usvc, | ||
2757 | struct nlattr *nla, int full_entry, | 2770 | struct nlattr *nla, int full_entry, |
2758 | struct ip_vs_service **ret_svc) | 2771 | struct ip_vs_service **ret_svc) |
2759 | { | 2772 | { |
@@ -2796,9 +2809,9 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc, | |||
2796 | } | 2809 | } |
2797 | 2810 | ||
2798 | if (usvc->fwmark) | 2811 | if (usvc->fwmark) |
2799 | svc = __ip_vs_svc_fwm_find(usvc->af, usvc->fwmark); | 2812 | svc = __ip_vs_svc_fwm_find(net, usvc->af, usvc->fwmark); |
2800 | else | 2813 | else |
2801 | svc = __ip_vs_service_find(usvc->af, usvc->protocol, | 2814 | svc = __ip_vs_service_find(net, usvc->af, usvc->protocol, |
2802 | &usvc->addr, usvc->port); | 2815 | &usvc->addr, usvc->port); |
2803 | *ret_svc = svc; | 2816 | *ret_svc = svc; |
2804 | 2817 | ||
@@ -2835,13 +2848,14 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc, | |||
2835 | return 0; | 2848 | return 0; |
2836 | } | 2849 | } |
2837 | 2850 | ||
2838 | static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla) | 2851 | static struct ip_vs_service *ip_vs_genl_find_service(struct net *net, |
2852 | struct nlattr *nla) | ||
2839 | { | 2853 | { |
2840 | struct ip_vs_service_user_kern usvc; | 2854 | struct ip_vs_service_user_kern usvc; |
2841 | struct ip_vs_service *svc; | 2855 | struct ip_vs_service *svc; |
2842 | int ret; | 2856 | int ret; |
2843 | 2857 | ||
2844 | ret = ip_vs_genl_parse_service(&usvc, nla, 0, &svc); | 2858 | ret = ip_vs_genl_parse_service(net, &usvc, nla, 0, &svc); |
2845 | return ret ? ERR_PTR(ret) : svc; | 2859 | return ret ? ERR_PTR(ret) : svc; |
2846 | } | 2860 | } |
2847 | 2861 | ||
@@ -2909,6 +2923,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb, | |||
2909 | struct ip_vs_service *svc; | 2923 | struct ip_vs_service *svc; |
2910 | struct ip_vs_dest *dest; | 2924 | struct ip_vs_dest *dest; |
2911 | struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1]; | 2925 | struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1]; |
2926 | struct net *net; | ||
2912 | 2927 | ||
2913 | mutex_lock(&__ip_vs_mutex); | 2928 | mutex_lock(&__ip_vs_mutex); |
2914 | 2929 | ||
@@ -2917,7 +2932,8 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb, | |||
2917 | IPVS_CMD_ATTR_MAX, ip_vs_cmd_policy)) | 2932 | IPVS_CMD_ATTR_MAX, ip_vs_cmd_policy)) |
2918 | goto out_err; | 2933 | goto out_err; |
2919 | 2934 | ||
2920 | svc = ip_vs_genl_find_service(attrs[IPVS_CMD_ATTR_SERVICE]); | 2935 | net = skb_sknet(skb); |
2936 | svc = ip_vs_genl_find_service(net, attrs[IPVS_CMD_ATTR_SERVICE]); | ||
2921 | if (IS_ERR(svc) || svc == NULL) | 2937 | if (IS_ERR(svc) || svc == NULL) |
2922 | goto out_err; | 2938 | goto out_err; |
2923 | 2939 | ||
@@ -3102,13 +3118,15 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3102 | struct ip_vs_dest_user_kern udest; | 3118 | struct ip_vs_dest_user_kern udest; |
3103 | int ret = 0, cmd; | 3119 | int ret = 0, cmd; |
3104 | int need_full_svc = 0, need_full_dest = 0; | 3120 | int need_full_svc = 0, need_full_dest = 0; |
3121 | struct net *net; | ||
3105 | 3122 | ||
3123 | net = skb_sknet(skb); | ||
3106 | cmd = info->genlhdr->cmd; | 3124 | cmd = info->genlhdr->cmd; |
3107 | 3125 | ||
3108 | mutex_lock(&__ip_vs_mutex); | 3126 | mutex_lock(&__ip_vs_mutex); |
3109 | 3127 | ||
3110 | if (cmd == IPVS_CMD_FLUSH) { | 3128 | if (cmd == IPVS_CMD_FLUSH) { |
3111 | ret = ip_vs_flush(); | 3129 | ret = ip_vs_flush(net); |
3112 | goto out; | 3130 | goto out; |
3113 | } else if (cmd == IPVS_CMD_SET_CONFIG) { | 3131 | } else if (cmd == IPVS_CMD_SET_CONFIG) { |
3114 | ret = ip_vs_genl_set_config(info->attrs); | 3132 | ret = ip_vs_genl_set_config(info->attrs); |
@@ -3133,7 +3151,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3133 | goto out; | 3151 | goto out; |
3134 | } else if (cmd == IPVS_CMD_ZERO && | 3152 | } else if (cmd == IPVS_CMD_ZERO && |
3135 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { | 3153 | !info->attrs[IPVS_CMD_ATTR_SERVICE]) { |
3136 | ret = ip_vs_zero_all(); | 3154 | ret = ip_vs_zero_all(net); |
3137 | goto out; | 3155 | goto out; |
3138 | } | 3156 | } |
3139 | 3157 | ||
@@ -3143,7 +3161,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3143 | if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE) | 3161 | if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE) |
3144 | need_full_svc = 1; | 3162 | need_full_svc = 1; |
3145 | 3163 | ||
3146 | ret = ip_vs_genl_parse_service(&usvc, | 3164 | ret = ip_vs_genl_parse_service(net, &usvc, |
3147 | info->attrs[IPVS_CMD_ATTR_SERVICE], | 3165 | info->attrs[IPVS_CMD_ATTR_SERVICE], |
3148 | need_full_svc, &svc); | 3166 | need_full_svc, &svc); |
3149 | if (ret) | 3167 | if (ret) |
@@ -3173,7 +3191,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3173 | switch (cmd) { | 3191 | switch (cmd) { |
3174 | case IPVS_CMD_NEW_SERVICE: | 3192 | case IPVS_CMD_NEW_SERVICE: |
3175 | if (svc == NULL) | 3193 | if (svc == NULL) |
3176 | ret = ip_vs_add_service(&usvc, &svc); | 3194 | ret = ip_vs_add_service(net, &usvc, &svc); |
3177 | else | 3195 | else |
3178 | ret = -EEXIST; | 3196 | ret = -EEXIST; |
3179 | break; | 3197 | break; |
@@ -3211,7 +3229,9 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3211 | struct sk_buff *msg; | 3229 | struct sk_buff *msg; |
3212 | void *reply; | 3230 | void *reply; |
3213 | int ret, cmd, reply_cmd; | 3231 | int ret, cmd, reply_cmd; |
3232 | struct net *net; | ||
3214 | 3233 | ||
3234 | net = skb_sknet(skb); | ||
3215 | cmd = info->genlhdr->cmd; | 3235 | cmd = info->genlhdr->cmd; |
3216 | 3236 | ||
3217 | if (cmd == IPVS_CMD_GET_SERVICE) | 3237 | if (cmd == IPVS_CMD_GET_SERVICE) |
@@ -3240,7 +3260,8 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info) | |||
3240 | { | 3260 | { |
3241 | struct ip_vs_service *svc; | 3261 | struct ip_vs_service *svc; |
3242 | 3262 | ||
3243 | svc = ip_vs_genl_find_service(info->attrs[IPVS_CMD_ATTR_SERVICE]); | 3263 | svc = ip_vs_genl_find_service(net, |
3264 | info->attrs[IPVS_CMD_ATTR_SERVICE]); | ||
3244 | if (IS_ERR(svc)) { | 3265 | if (IS_ERR(svc)) { |
3245 | ret = PTR_ERR(svc); | 3266 | ret = PTR_ERR(svc); |
3246 | goto out_err; | 3267 | goto out_err; |
@@ -3411,9 +3432,15 @@ static void ip_vs_genl_unregister(void) | |||
3411 | */ | 3432 | */ |
3412 | int __net_init __ip_vs_control_init(struct net *net) | 3433 | int __net_init __ip_vs_control_init(struct net *net) |
3413 | { | 3434 | { |
3435 | int idx; | ||
3436 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
3437 | |||
3414 | if (!net_eq(net, &init_net)) /* netns not enabled yet */ | 3438 | if (!net_eq(net, &init_net)) /* netns not enabled yet */ |
3415 | return -EPERM; | 3439 | return -EPERM; |
3416 | 3440 | ||
3441 | for (idx = 0; idx < IP_VS_RTAB_SIZE; idx++) | ||
3442 | INIT_LIST_HEAD(&ipvs->rs_table[idx]); | ||
3443 | |||
3417 | proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops); | 3444 | proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops); |
3418 | proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops); | 3445 | proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops); |
3419 | sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path, | 3446 | sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path, |
@@ -3445,43 +3472,48 @@ static struct pernet_operations ipvs_control_ops = { | |||
3445 | 3472 | ||
3446 | int __init ip_vs_control_init(void) | 3473 | int __init ip_vs_control_init(void) |
3447 | { | 3474 | { |
3448 | int ret; | ||
3449 | int idx; | 3475 | int idx; |
3476 | int ret; | ||
3450 | 3477 | ||
3451 | EnterFunction(2); | 3478 | EnterFunction(2); |
3452 | 3479 | ||
3453 | /* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */ | 3480 | /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */ |
3454 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | 3481 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { |
3455 | INIT_LIST_HEAD(&ip_vs_svc_table[idx]); | 3482 | INIT_LIST_HEAD(&ip_vs_svc_table[idx]); |
3456 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | 3483 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); |
3457 | } | 3484 | } |
3458 | for(idx = 0; idx < IP_VS_RTAB_SIZE; idx++) { | 3485 | |
3459 | INIT_LIST_HEAD(&ip_vs_rtable[idx]); | 3486 | ret = register_pernet_subsys(&ipvs_control_ops); |
3487 | if (ret) { | ||
3488 | pr_err("cannot register namespace.\n"); | ||
3489 | goto err; | ||
3460 | } | 3490 | } |
3461 | smp_wmb(); | 3491 | |
3492 | smp_wmb(); /* Do we really need it now ? */ | ||
3462 | 3493 | ||
3463 | ret = nf_register_sockopt(&ip_vs_sockopts); | 3494 | ret = nf_register_sockopt(&ip_vs_sockopts); |
3464 | if (ret) { | 3495 | if (ret) { |
3465 | pr_err("cannot register sockopt.\n"); | 3496 | pr_err("cannot register sockopt.\n"); |
3466 | return ret; | 3497 | goto err_net; |
3467 | } | 3498 | } |
3468 | 3499 | ||
3469 | ret = ip_vs_genl_register(); | 3500 | ret = ip_vs_genl_register(); |
3470 | if (ret) { | 3501 | if (ret) { |
3471 | pr_err("cannot register Generic Netlink interface.\n"); | 3502 | pr_err("cannot register Generic Netlink interface.\n"); |
3472 | nf_unregister_sockopt(&ip_vs_sockopts); | 3503 | nf_unregister_sockopt(&ip_vs_sockopts); |
3473 | return ret; | 3504 | goto err_net; |
3474 | } | 3505 | } |
3475 | 3506 | ||
3476 | ret = register_pernet_subsys(&ipvs_control_ops); | ||
3477 | if (ret) | ||
3478 | return ret; | ||
3479 | |||
3480 | /* Hook the defense timer */ | 3507 | /* Hook the defense timer */ |
3481 | schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD); | 3508 | schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD); |
3482 | 3509 | ||
3483 | LeaveFunction(2); | 3510 | LeaveFunction(2); |
3484 | return 0; | 3511 | return 0; |
3512 | |||
3513 | err_net: | ||
3514 | unregister_pernet_subsys(&ipvs_control_ops); | ||
3515 | err: | ||
3516 | return ret; | ||
3485 | } | 3517 | } |
3486 | 3518 | ||
3487 | 3519 | ||
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index a315159983ad..521b827083fe 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c | |||
@@ -12,6 +12,7 @@ static int | |||
12 | sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | 12 | sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
13 | int *verdict, struct ip_vs_conn **cpp) | 13 | int *verdict, struct ip_vs_conn **cpp) |
14 | { | 14 | { |
15 | struct net *net; | ||
15 | struct ip_vs_service *svc; | 16 | struct ip_vs_service *svc; |
16 | sctp_chunkhdr_t _schunkh, *sch; | 17 | sctp_chunkhdr_t _schunkh, *sch; |
17 | sctp_sctphdr_t *sh, _sctph; | 18 | sctp_sctphdr_t *sh, _sctph; |
@@ -27,9 +28,9 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
27 | sizeof(_schunkh), &_schunkh); | 28 | sizeof(_schunkh), &_schunkh); |
28 | if (sch == NULL) | 29 | if (sch == NULL) |
29 | return 0; | 30 | return 0; |
30 | 31 | net = skb_net(skb); | |
31 | if ((sch->type == SCTP_CID_INIT) && | 32 | if ((sch->type == SCTP_CID_INIT) && |
32 | (svc = ip_vs_service_get(af, skb->mark, iph.protocol, | 33 | (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol, |
33 | &iph.daddr, sh->dest))) { | 34 | &iph.daddr, sh->dest))) { |
34 | int ignored; | 35 | int ignored; |
35 | 36 | ||
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 1cdab12abfef..c175d3166263 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c | |||
@@ -31,6 +31,7 @@ static int | |||
31 | tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | 31 | tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
32 | int *verdict, struct ip_vs_conn **cpp) | 32 | int *verdict, struct ip_vs_conn **cpp) |
33 | { | 33 | { |
34 | struct net *net; | ||
34 | struct ip_vs_service *svc; | 35 | struct ip_vs_service *svc; |
35 | struct tcphdr _tcph, *th; | 36 | struct tcphdr _tcph, *th; |
36 | struct ip_vs_iphdr iph; | 37 | struct ip_vs_iphdr iph; |
@@ -42,11 +43,11 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
42 | *verdict = NF_DROP; | 43 | *verdict = NF_DROP; |
43 | return 0; | 44 | return 0; |
44 | } | 45 | } |
45 | 46 | net = skb_net(skb); | |
46 | /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ | 47 | /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ |
47 | if (th->syn && | 48 | if (th->syn && |
48 | (svc = ip_vs_service_get(af, skb->mark, iph.protocol, &iph.daddr, | 49 | (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol, |
49 | th->dest))) { | 50 | &iph.daddr, th->dest))) { |
50 | int ignored; | 51 | int ignored; |
51 | 52 | ||
52 | if (ip_vs_todrop()) { | 53 | if (ip_vs_todrop()) { |
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c index cd398de010cc..5ab54f648654 100644 --- a/net/netfilter/ipvs/ip_vs_proto_udp.c +++ b/net/netfilter/ipvs/ip_vs_proto_udp.c | |||
@@ -31,6 +31,7 @@ static int | |||
31 | udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | 31 | udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
32 | int *verdict, struct ip_vs_conn **cpp) | 32 | int *verdict, struct ip_vs_conn **cpp) |
33 | { | 33 | { |
34 | struct net *net; | ||
34 | struct ip_vs_service *svc; | 35 | struct ip_vs_service *svc; |
35 | struct udphdr _udph, *uh; | 36 | struct udphdr _udph, *uh; |
36 | struct ip_vs_iphdr iph; | 37 | struct ip_vs_iphdr iph; |
@@ -42,8 +43,8 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
42 | *verdict = NF_DROP; | 43 | *verdict = NF_DROP; |
43 | return 0; | 44 | return 0; |
44 | } | 45 | } |
45 | 46 | net = skb_net(skb); | |
46 | svc = ip_vs_service_get(af, skb->mark, iph.protocol, | 47 | svc = ip_vs_service_get(net, af, skb->mark, iph.protocol, |
47 | &iph.daddr, uh->dest); | 48 | &iph.daddr, uh->dest); |
48 | if (svc) { | 49 | if (svc) { |
49 | int ignored; | 50 | int ignored; |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 3668739a6d06..662aa2c22a05 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -749,7 +749,7 @@ static void ip_vs_proc_conn(struct ip_vs_conn_param *param, unsigned flags, | |||
749 | * If it is not found the connection will remain unbound | 749 | * If it is not found the connection will remain unbound |
750 | * but still handled. | 750 | * but still handled. |
751 | */ | 751 | */ |
752 | dest = ip_vs_find_dest(type, daddr, dport, param->vaddr, | 752 | dest = ip_vs_find_dest(&init_net, type, daddr, dport, param->vaddr, |
753 | param->vport, protocol, fwmark); | 753 | param->vport, protocol, fwmark); |
754 | 754 | ||
755 | /* Set the approprite ativity flag */ | 755 | /* Set the approprite ativity flag */ |