aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c1
-rw-r--r--net/ipv6/af_inet6.c71
-rw-r--r--net/ipv6/exthdrs.c42
-rw-r--r--net/ipv6/icmp.c8
-rw-r--r--net/ipv6/ip6_input.c27
-rw-r--r--net/ipv6/ip6_output.c144
-rw-r--r--net/ipv6/ip6_tunnel.c4
-rw-r--r--net/ipv6/ip6mr.c3
-rw-r--r--net/ipv6/mcast.c22
-rw-r--r--net/ipv6/ndisc.c25
-rw-r--r--net/ipv6/netfilter.c5
-rw-r--r--net/ipv6/netfilter/Kconfig77
-rw-r--r--net/ipv6/netfilter/ip6_tables.c173
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c15
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c22
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c39
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c21
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c11
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c21
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c33
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c9
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c16
-rw-r--r--net/ipv6/netfilter/ip6t_mh.c25
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c21
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c6
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c31
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c20
-rw-r--r--net/ipv6/netfilter/ip6table_security.c6
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c24
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c19
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c32
-rw-r--r--net/ipv6/proc.c121
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/reassembly.c65
-rw-r--r--net/ipv6/route.c57
-rw-r--r--net/ipv6/tcp_ipv6.c167
-rw-r--r--net/ipv6/udp.c18
-rw-r--r--net/ipv6/udplite.c2
38 files changed, 679 insertions, 728 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7b6a584b62dd..eea9542728ca 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3982,7 +3982,6 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
3982} 3982}
3983 3983
3984static int addrconf_sysctl_forward_strategy(ctl_table *table, 3984static int addrconf_sysctl_forward_strategy(ctl_table *table,
3985 int __user *name, int nlen,
3986 void __user *oldval, 3985 void __user *oldval,
3987 size_t __user *oldlenp, 3986 size_t __user *oldlenp,
3988 void __user *newval, size_t newlen) 3987 void __user *newval, size_t newlen)
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 95055f8c3f35..01edac888510 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -50,6 +50,7 @@
50#include <net/ipip.h> 50#include <net/ipip.h>
51#include <net/protocol.h> 51#include <net/protocol.h>
52#include <net/inet_common.h> 52#include <net/inet_common.h>
53#include <net/route.h>
53#include <net/transp_v6.h> 54#include <net/transp_v6.h>
54#include <net/ip6_route.h> 55#include <net/ip6_route.h>
55#include <net/addrconf.h> 56#include <net/addrconf.h>
@@ -794,61 +795,55 @@ static void ipv6_packet_cleanup(void)
794 dev_remove_pack(&ipv6_packet_type); 795 dev_remove_pack(&ipv6_packet_type);
795} 796}
796 797
797static int __init init_ipv6_mibs(void) 798static int __net_init ipv6_init_mibs(struct net *net)
798{ 799{
799 if (snmp_mib_init((void **)ipv6_statistics, 800 if (snmp_mib_init((void **)net->mib.udp_stats_in6,
801 sizeof (struct udp_mib)) < 0)
802 return -ENOMEM;
803 if (snmp_mib_init((void **)net->mib.udplite_stats_in6,
804 sizeof (struct udp_mib)) < 0)
805 goto err_udplite_mib;
806 if (snmp_mib_init((void **)net->mib.ipv6_statistics,
800 sizeof(struct ipstats_mib)) < 0) 807 sizeof(struct ipstats_mib)) < 0)
801 goto err_ip_mib; 808 goto err_ip_mib;
802 if (snmp_mib_init((void **)icmpv6_statistics, 809 if (snmp_mib_init((void **)net->mib.icmpv6_statistics,
803 sizeof(struct icmpv6_mib)) < 0) 810 sizeof(struct icmpv6_mib)) < 0)
804 goto err_icmp_mib; 811 goto err_icmp_mib;
805 if (snmp_mib_init((void **)icmpv6msg_statistics, 812 if (snmp_mib_init((void **)net->mib.icmpv6msg_statistics,
806 sizeof(struct icmpv6msg_mib)) < 0) 813 sizeof(struct icmpv6msg_mib)) < 0)
807 goto err_icmpmsg_mib; 814 goto err_icmpmsg_mib;
808 if (snmp_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib)) < 0)
809 goto err_udp_mib;
810 if (snmp_mib_init((void **)udplite_stats_in6,
811 sizeof (struct udp_mib)) < 0)
812 goto err_udplite_mib;
813 return 0; 815 return 0;
814 816
815err_udplite_mib:
816 snmp_mib_free((void **)udp_stats_in6);
817err_udp_mib:
818 snmp_mib_free((void **)icmpv6msg_statistics);
819err_icmpmsg_mib: 817err_icmpmsg_mib:
820 snmp_mib_free((void **)icmpv6_statistics); 818 snmp_mib_free((void **)net->mib.icmpv6_statistics);
821err_icmp_mib: 819err_icmp_mib:
822 snmp_mib_free((void **)ipv6_statistics); 820 snmp_mib_free((void **)net->mib.ipv6_statistics);
823err_ip_mib: 821err_ip_mib:
822 snmp_mib_free((void **)net->mib.udplite_stats_in6);
823err_udplite_mib:
824 snmp_mib_free((void **)net->mib.udp_stats_in6);
824 return -ENOMEM; 825 return -ENOMEM;
825
826} 826}
827 827
828static void cleanup_ipv6_mibs(void) 828static void __net_exit ipv6_cleanup_mibs(struct net *net)
829{ 829{
830 snmp_mib_free((void **)ipv6_statistics); 830 snmp_mib_free((void **)net->mib.udp_stats_in6);
831 snmp_mib_free((void **)icmpv6_statistics); 831 snmp_mib_free((void **)net->mib.udplite_stats_in6);
832 snmp_mib_free((void **)icmpv6msg_statistics); 832 snmp_mib_free((void **)net->mib.ipv6_statistics);
833 snmp_mib_free((void **)udp_stats_in6); 833 snmp_mib_free((void **)net->mib.icmpv6_statistics);
834 snmp_mib_free((void **)udplite_stats_in6); 834 snmp_mib_free((void **)net->mib.icmpv6msg_statistics);
835} 835}
836 836
837static int inet6_net_init(struct net *net) 837static int __net_init inet6_net_init(struct net *net)
838{ 838{
839 int err = 0; 839 int err = 0;
840 840
841 net->ipv6.sysctl.bindv6only = 0; 841 net->ipv6.sysctl.bindv6only = 0;
842 net->ipv6.sysctl.flush_delay = 0;
843 net->ipv6.sysctl.ip6_rt_max_size = 4096;
844 net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;
845 net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ;
846 net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ;
847 net->ipv6.sysctl.ip6_rt_gc_elasticity = 9;
848 net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
849 net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
850 net->ipv6.sysctl.icmpv6_time = 1*HZ; 842 net->ipv6.sysctl.icmpv6_time = 1*HZ;
851 843
844 err = ipv6_init_mibs(net);
845 if (err)
846 return err;
852#ifdef CONFIG_PROC_FS 847#ifdef CONFIG_PROC_FS
853 err = udp6_proc_init(net); 848 err = udp6_proc_init(net);
854 if (err) 849 if (err)
@@ -859,7 +854,6 @@ static int inet6_net_init(struct net *net)
859 err = ac6_proc_init(net); 854 err = ac6_proc_init(net);
860 if (err) 855 if (err)
861 goto proc_ac6_fail; 856 goto proc_ac6_fail;
862out:
863#endif 857#endif
864 return err; 858 return err;
865 859
@@ -868,7 +862,9 @@ proc_ac6_fail:
868 tcp6_proc_exit(net); 862 tcp6_proc_exit(net);
869proc_tcp6_fail: 863proc_tcp6_fail:
870 udp6_proc_exit(net); 864 udp6_proc_exit(net);
871 goto out; 865out:
866 ipv6_cleanup_mibs(net);
867 return err;
872#endif 868#endif
873} 869}
874 870
@@ -879,6 +875,7 @@ static void inet6_net_exit(struct net *net)
879 tcp6_proc_exit(net); 875 tcp6_proc_exit(net);
880 ac6_proc_exit(net); 876 ac6_proc_exit(net);
881#endif 877#endif
878 ipv6_cleanup_mibs(net);
882} 879}
883 880
884static struct pernet_operations inet6_net_ops = { 881static struct pernet_operations inet6_net_ops = {
@@ -929,11 +926,6 @@ static int __init inet6_init(void)
929 if (err) 926 if (err)
930 goto out_sock_register_fail; 927 goto out_sock_register_fail;
931 928
932 /* Initialise ipv6 mibs */
933 err = init_ipv6_mibs();
934 if (err)
935 goto out_unregister_sock;
936
937#ifdef CONFIG_SYSCTL 929#ifdef CONFIG_SYSCTL
938 err = ipv6_static_sysctl_register(); 930 err = ipv6_static_sysctl_register();
939 if (err) 931 if (err)
@@ -1067,8 +1059,6 @@ register_pernet_fail:
1067 ipv6_static_sysctl_unregister(); 1059 ipv6_static_sysctl_unregister();
1068static_sysctl_fail: 1060static_sysctl_fail:
1069#endif 1061#endif
1070 cleanup_ipv6_mibs();
1071out_unregister_sock:
1072 sock_unregister(PF_INET6); 1062 sock_unregister(PF_INET6);
1073 rtnl_unregister_all(PF_INET6); 1063 rtnl_unregister_all(PF_INET6);
1074out_sock_register_fail: 1064out_sock_register_fail:
@@ -1125,7 +1115,6 @@ static void __exit inet6_exit(void)
1125#ifdef CONFIG_SYSCTL 1115#ifdef CONFIG_SYSCTL
1126 ipv6_static_sysctl_unregister(); 1116 ipv6_static_sysctl_unregister();
1127#endif 1117#endif
1128 cleanup_ipv6_mibs();
1129 proto_unregister(&rawv6_prot); 1118 proto_unregister(&rawv6_prot);
1130 proto_unregister(&udplitev6_prot); 1119 proto_unregister(&udplitev6_prot);
1131 proto_unregister(&udpv6_prot); 1120 proto_unregister(&udpv6_prot);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 837c830d6d8e..6bfffec2371c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -277,7 +277,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
277 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || 277 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
278 !pskb_may_pull(skb, (skb_transport_offset(skb) + 278 !pskb_may_pull(skb, (skb_transport_offset(skb) +
279 ((skb_transport_header(skb)[1] + 1) << 3)))) { 279 ((skb_transport_header(skb)[1] + 1) << 3)))) {
280 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 280 IP6_INC_STATS_BH(dev_net(skb->dst->dev), ip6_dst_idev(skb->dst),
281 IPSTATS_MIB_INHDRERRORS); 281 IPSTATS_MIB_INHDRERRORS);
282 kfree_skb(skb); 282 kfree_skb(skb);
283 return -1; 283 return -1;
@@ -301,7 +301,8 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
301 return 1; 301 return 1;
302 } 302 }
303 303
304 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); 304 IP6_INC_STATS_BH(dev_net(dst->dev),
305 ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
305 dst_release(dst); 306 dst_release(dst);
306 return -1; 307 return -1;
307} 308}
@@ -319,7 +320,8 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
319 int n, i; 320 int n, i;
320 struct ipv6_rt_hdr *hdr; 321 struct ipv6_rt_hdr *hdr;
321 struct rt0_hdr *rthdr; 322 struct rt0_hdr *rthdr;
322 int accept_source_route = dev_net(skb->dev)->ipv6.devconf_all->accept_source_route; 323 struct net *net = dev_net(skb->dev);
324 int accept_source_route = net->ipv6.devconf_all->accept_source_route;
323 325
324 idev = in6_dev_get(skb->dev); 326 idev = in6_dev_get(skb->dev);
325 if (idev) { 327 if (idev) {
@@ -331,7 +333,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
331 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || 333 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
332 !pskb_may_pull(skb, (skb_transport_offset(skb) + 334 !pskb_may_pull(skb, (skb_transport_offset(skb) +
333 ((skb_transport_header(skb)[1] + 1) << 3)))) { 335 ((skb_transport_header(skb)[1] + 1) << 3)))) {
334 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 336 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
335 IPSTATS_MIB_INHDRERRORS); 337 IPSTATS_MIB_INHDRERRORS);
336 kfree_skb(skb); 338 kfree_skb(skb);
337 return -1; 339 return -1;
@@ -341,7 +343,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
341 343
342 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || 344 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
343 skb->pkt_type != PACKET_HOST) { 345 skb->pkt_type != PACKET_HOST) {
344 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 346 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
345 IPSTATS_MIB_INADDRERRORS); 347 IPSTATS_MIB_INADDRERRORS);
346 kfree_skb(skb); 348 kfree_skb(skb);
347 return -1; 349 return -1;
@@ -356,7 +358,7 @@ looped_back:
356 * processed by own 358 * processed by own
357 */ 359 */
358 if (!addr) { 360 if (!addr) {
359 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 361 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
360 IPSTATS_MIB_INADDRERRORS); 362 IPSTATS_MIB_INADDRERRORS);
361 kfree_skb(skb); 363 kfree_skb(skb);
362 return -1; 364 return -1;
@@ -382,7 +384,7 @@ looped_back:
382 goto unknown_rh; 384 goto unknown_rh;
383 /* Silently discard invalid RTH type 2 */ 385 /* Silently discard invalid RTH type 2 */
384 if (hdr->hdrlen != 2 || hdr->segments_left != 1) { 386 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
385 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 387 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
386 IPSTATS_MIB_INHDRERRORS); 388 IPSTATS_MIB_INHDRERRORS);
387 kfree_skb(skb); 389 kfree_skb(skb);
388 return -1; 390 return -1;
@@ -401,7 +403,7 @@ looped_back:
401 n = hdr->hdrlen >> 1; 403 n = hdr->hdrlen >> 1;
402 404
403 if (hdr->segments_left > n) { 405 if (hdr->segments_left > n) {
404 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 406 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
405 IPSTATS_MIB_INHDRERRORS); 407 IPSTATS_MIB_INHDRERRORS);
406 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 408 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
407 ((&hdr->segments_left) - 409 ((&hdr->segments_left) -
@@ -415,7 +417,7 @@ looped_back:
415 if (skb_cloned(skb)) { 417 if (skb_cloned(skb)) {
416 /* the copy is a forwarded packet */ 418 /* the copy is a forwarded packet */
417 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { 419 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
418 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 420 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
419 IPSTATS_MIB_OUTDISCARDS); 421 IPSTATS_MIB_OUTDISCARDS);
420 kfree_skb(skb); 422 kfree_skb(skb);
421 return -1; 423 return -1;
@@ -438,13 +440,13 @@ looped_back:
438 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, 440 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
439 (xfrm_address_t *)&ipv6_hdr(skb)->saddr, 441 (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
440 IPPROTO_ROUTING) < 0) { 442 IPPROTO_ROUTING) < 0) {
441 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 443 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
442 IPSTATS_MIB_INADDRERRORS); 444 IPSTATS_MIB_INADDRERRORS);
443 kfree_skb(skb); 445 kfree_skb(skb);
444 return -1; 446 return -1;
445 } 447 }
446 if (!ipv6_chk_home_addr(dev_net(skb->dst->dev), addr)) { 448 if (!ipv6_chk_home_addr(dev_net(skb->dst->dev), addr)) {
447 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 449 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
448 IPSTATS_MIB_INADDRERRORS); 450 IPSTATS_MIB_INADDRERRORS);
449 kfree_skb(skb); 451 kfree_skb(skb);
450 return -1; 452 return -1;
@@ -456,7 +458,7 @@ looped_back:
456 } 458 }
457 459
458 if (ipv6_addr_is_multicast(addr)) { 460 if (ipv6_addr_is_multicast(addr)) {
459 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 461 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
460 IPSTATS_MIB_INADDRERRORS); 462 IPSTATS_MIB_INADDRERRORS);
461 kfree_skb(skb); 463 kfree_skb(skb);
462 return -1; 464 return -1;
@@ -476,7 +478,7 @@ looped_back:
476 478
477 if (skb->dst->dev->flags&IFF_LOOPBACK) { 479 if (skb->dst->dev->flags&IFF_LOOPBACK) {
478 if (ipv6_hdr(skb)->hop_limit <= 1) { 480 if (ipv6_hdr(skb)->hop_limit <= 1) {
479 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 481 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
480 IPSTATS_MIB_INHDRERRORS); 482 IPSTATS_MIB_INHDRERRORS);
481 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 483 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
482 0, skb->dev); 484 0, skb->dev);
@@ -492,7 +494,7 @@ looped_back:
492 return -1; 494 return -1;
493 495
494unknown_rh: 496unknown_rh:
495 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 497 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
496 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 498 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
497 (&hdr->type) - skb_network_header(skb)); 499 (&hdr->type) - skb_network_header(skb));
498 return -1; 500 return -1;
@@ -579,29 +581,33 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
579{ 581{
580 const unsigned char *nh = skb_network_header(skb); 582 const unsigned char *nh = skb_network_header(skb);
581 u32 pkt_len; 583 u32 pkt_len;
584 struct net *net = dev_net(skb->dst->dev);
582 585
583 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { 586 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
584 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", 587 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
585 nh[optoff+1]); 588 nh[optoff+1]);
586 IP6_INC_STATS_BH(ipv6_skb_idev(skb), 589 IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
587 IPSTATS_MIB_INHDRERRORS); 590 IPSTATS_MIB_INHDRERRORS);
588 goto drop; 591 goto drop;
589 } 592 }
590 593
591 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); 594 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
592 if (pkt_len <= IPV6_MAXPLEN) { 595 if (pkt_len <= IPV6_MAXPLEN) {
593 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); 596 IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
597 IPSTATS_MIB_INHDRERRORS);
594 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); 598 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
595 return 0; 599 return 0;
596 } 600 }
597 if (ipv6_hdr(skb)->payload_len) { 601 if (ipv6_hdr(skb)->payload_len) {
598 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); 602 IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
603 IPSTATS_MIB_INHDRERRORS);
599 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); 604 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
600 return 0; 605 return 0;
601 } 606 }
602 607
603 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { 608 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
604 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS); 609 IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
610 IPSTATS_MIB_INTRUNCATEDPKTS);
605 goto drop; 611 goto drop;
606 } 612 }
607 613
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index b3157a0cc15d..9b7d19ae5ced 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -183,7 +183,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
183 */ 183 */
184 dst = ip6_route_output(net, sk, fl); 184 dst = ip6_route_output(net, sk, fl);
185 if (dst->error) { 185 if (dst->error) {
186 IP6_INC_STATS(ip6_dst_idev(dst), 186 IP6_INC_STATS(net, ip6_dst_idev(dst),
187 IPSTATS_MIB_OUTNOROUTES); 187 IPSTATS_MIB_OUTNOROUTES);
188 } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { 188 } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
189 res = 1; 189 res = 1;
@@ -664,7 +664,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
664 skb_set_network_header(skb, nh); 664 skb_set_network_header(skb, nh);
665 } 665 }
666 666
667 ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS); 667 ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INMSGS);
668 668
669 saddr = &ipv6_hdr(skb)->saddr; 669 saddr = &ipv6_hdr(skb)->saddr;
670 daddr = &ipv6_hdr(skb)->daddr; 670 daddr = &ipv6_hdr(skb)->daddr;
@@ -693,7 +693,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
693 693
694 type = hdr->icmp6_type; 694 type = hdr->icmp6_type;
695 695
696 ICMP6MSGIN_INC_STATS_BH(idev, type); 696 ICMP6MSGIN_INC_STATS_BH(dev_net(dev), idev, type);
697 697
698 switch (type) { 698 switch (type) {
699 case ICMPV6_ECHO_REQUEST: 699 case ICMPV6_ECHO_REQUEST:
@@ -772,7 +772,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
772 return 0; 772 return 0;
773 773
774discard_it: 774discard_it:
775 ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS); 775 ICMP6_INC_STATS_BH(dev_net(dev), idev, ICMP6_MIB_INERRORS);
776drop_no_count: 776drop_no_count:
777 kfree_skb(skb); 777 kfree_skb(skb);
778 return 0; 778 return 0;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 7e14cccd0561..936f48946e20 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -59,6 +59,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
59 struct ipv6hdr *hdr; 59 struct ipv6hdr *hdr;
60 u32 pkt_len; 60 u32 pkt_len;
61 struct inet6_dev *idev; 61 struct inet6_dev *idev;
62 struct net *net = dev_net(skb->dev);
62 63
63 if (skb->pkt_type == PACKET_OTHERHOST) { 64 if (skb->pkt_type == PACKET_OTHERHOST) {
64 kfree_skb(skb); 65 kfree_skb(skb);
@@ -69,11 +70,11 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
69 70
70 idev = __in6_dev_get(skb->dev); 71 idev = __in6_dev_get(skb->dev);
71 72
72 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); 73 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
73 74
74 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || 75 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
75 !idev || unlikely(idev->cnf.disable_ipv6)) { 76 !idev || unlikely(idev->cnf.disable_ipv6)) {
76 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); 77 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
77 rcu_read_unlock(); 78 rcu_read_unlock();
78 goto out; 79 goto out;
79 } 80 }
@@ -118,11 +119,12 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
118 /* pkt_len may be zero if Jumbo payload option is present */ 119 /* pkt_len may be zero if Jumbo payload option is present */
119 if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { 120 if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
120 if (pkt_len + sizeof(struct ipv6hdr) > skb->len) { 121 if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
121 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); 122 IP6_INC_STATS_BH(net,
123 idev, IPSTATS_MIB_INTRUNCATEDPKTS);
122 goto drop; 124 goto drop;
123 } 125 }
124 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { 126 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
125 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); 127 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
126 goto drop; 128 goto drop;
127 } 129 }
128 hdr = ipv6_hdr(skb); 130 hdr = ipv6_hdr(skb);
@@ -130,7 +132,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
130 132
131 if (hdr->nexthdr == NEXTHDR_HOP) { 133 if (hdr->nexthdr == NEXTHDR_HOP) {
132 if (ipv6_parse_hopopts(skb) < 0) { 134 if (ipv6_parse_hopopts(skb) < 0) {
133 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); 135 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
134 rcu_read_unlock(); 136 rcu_read_unlock();
135 return 0; 137 return 0;
136 } 138 }
@@ -141,7 +143,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
141 return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, 143 return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL,
142 ip6_rcv_finish); 144 ip6_rcv_finish);
143err: 145err:
144 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); 146 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
145drop: 147drop:
146 rcu_read_unlock(); 148 rcu_read_unlock();
147 kfree_skb(skb); 149 kfree_skb(skb);
@@ -161,6 +163,7 @@ static int ip6_input_finish(struct sk_buff *skb)
161 int nexthdr, raw; 163 int nexthdr, raw;
162 u8 hash; 164 u8 hash;
163 struct inet6_dev *idev; 165 struct inet6_dev *idev;
166 struct net *net = dev_net(skb->dst->dev);
164 167
165 /* 168 /*
166 * Parse extension headers 169 * Parse extension headers
@@ -205,24 +208,25 @@ resubmit:
205 if (ret > 0) 208 if (ret > 0)
206 goto resubmit; 209 goto resubmit;
207 else if (ret == 0) 210 else if (ret == 0)
208 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); 211 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
209 } else { 212 } else {
210 if (!raw) { 213 if (!raw) {
211 if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { 214 if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
212 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); 215 IP6_INC_STATS_BH(net, idev,
216 IPSTATS_MIB_INUNKNOWNPROTOS);
213 icmpv6_send(skb, ICMPV6_PARAMPROB, 217 icmpv6_send(skb, ICMPV6_PARAMPROB,
214 ICMPV6_UNK_NEXTHDR, nhoff, 218 ICMPV6_UNK_NEXTHDR, nhoff,
215 skb->dev); 219 skb->dev);
216 } 220 }
217 } else 221 } else
218 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); 222 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
219 kfree_skb(skb); 223 kfree_skb(skb);
220 } 224 }
221 rcu_read_unlock(); 225 rcu_read_unlock();
222 return 0; 226 return 0;
223 227
224discard: 228discard:
225 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); 229 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
226 rcu_read_unlock(); 230 rcu_read_unlock();
227 kfree_skb(skb); 231 kfree_skb(skb);
228 return 0; 232 return 0;
@@ -240,7 +244,8 @@ int ip6_mc_input(struct sk_buff *skb)
240 struct ipv6hdr *hdr; 244 struct ipv6hdr *hdr;
241 int deliver; 245 int deliver;
242 246
243 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); 247 IP6_INC_STATS_BH(dev_net(skb->dst->dev),
248 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
244 249
245 hdr = ipv6_hdr(skb); 250 hdr = ipv6_hdr(skb);
246 deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); 251 deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 0e844c2736a7..c77db0b95e26 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -103,7 +103,8 @@ static int ip6_output_finish(struct sk_buff *skb)
103 else if (dst->neighbour) 103 else if (dst->neighbour)
104 return dst->neighbour->output(skb); 104 return dst->neighbour->output(skb);
105 105
106 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 106 IP6_INC_STATS_BH(dev_net(dst->dev),
107 ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
107 kfree_skb(skb); 108 kfree_skb(skb);
108 return -EINVAL; 109 return -EINVAL;
109 110
@@ -150,13 +151,14 @@ static int ip6_output2(struct sk_buff *skb)
150 ip6_dev_loopback_xmit); 151 ip6_dev_loopback_xmit);
151 152
152 if (ipv6_hdr(skb)->hop_limit == 0) { 153 if (ipv6_hdr(skb)->hop_limit == 0) {
153 IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); 154 IP6_INC_STATS(dev_net(dev), idev,
155 IPSTATS_MIB_OUTDISCARDS);
154 kfree_skb(skb); 156 kfree_skb(skb);
155 return 0; 157 return 0;
156 } 158 }
157 } 159 }
158 160
159 IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); 161 IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
160 } 162 }
161 163
162 return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, 164 return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
@@ -175,7 +177,8 @@ int ip6_output(struct sk_buff *skb)
175{ 177{
176 struct inet6_dev *idev = ip6_dst_idev(skb->dst); 178 struct inet6_dev *idev = ip6_dst_idev(skb->dst);
177 if (unlikely(idev->cnf.disable_ipv6)) { 179 if (unlikely(idev->cnf.disable_ipv6)) {
178 IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); 180 IP6_INC_STATS(dev_net(skb->dst->dev), idev,
181 IPSTATS_MIB_OUTDISCARDS);
179 kfree_skb(skb); 182 kfree_skb(skb);
180 return 0; 183 return 0;
181 } 184 }
@@ -194,6 +197,7 @@ int ip6_output(struct sk_buff *skb)
194int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, 197int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
195 struct ipv6_txoptions *opt, int ipfragok) 198 struct ipv6_txoptions *opt, int ipfragok)
196{ 199{
200 struct net *net = sock_net(sk);
197 struct ipv6_pinfo *np = inet6_sk(sk); 201 struct ipv6_pinfo *np = inet6_sk(sk);
198 struct in6_addr *first_hop = &fl->fl6_dst; 202 struct in6_addr *first_hop = &fl->fl6_dst;
199 struct dst_entry *dst = skb->dst; 203 struct dst_entry *dst = skb->dst;
@@ -216,7 +220,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
216 if (skb_headroom(skb) < head_room) { 220 if (skb_headroom(skb) < head_room) {
217 struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); 221 struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
218 if (skb2 == NULL) { 222 if (skb2 == NULL) {
219 IP6_INC_STATS(ip6_dst_idev(skb->dst), 223 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
220 IPSTATS_MIB_OUTDISCARDS); 224 IPSTATS_MIB_OUTDISCARDS);
221 kfree_skb(skb); 225 kfree_skb(skb);
222 return -ENOBUFS; 226 return -ENOBUFS;
@@ -270,7 +274,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
270 274
271 mtu = dst_mtu(dst); 275 mtu = dst_mtu(dst);
272 if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { 276 if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
273 IP6_INC_STATS(ip6_dst_idev(skb->dst), 277 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
274 IPSTATS_MIB_OUTREQUESTS); 278 IPSTATS_MIB_OUTREQUESTS);
275 return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, 279 return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
276 dst_output); 280 dst_output);
@@ -280,7 +284,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
280 printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); 284 printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
281 skb->dev = dst->dev; 285 skb->dev = dst->dev;
282 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); 286 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
283 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); 287 IP6_INC_STATS(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
284 kfree_skb(skb); 288 kfree_skb(skb);
285 return -EMSGSIZE; 289 return -EMSGSIZE;
286} 290}
@@ -422,7 +426,7 @@ int ip6_forward(struct sk_buff *skb)
422 goto drop; 426 goto drop;
423 427
424 if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { 428 if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
425 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); 429 IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
426 goto drop; 430 goto drop;
427 } 431 }
428 432
@@ -455,7 +459,8 @@ int ip6_forward(struct sk_buff *skb)
455 skb->dev = dst->dev; 459 skb->dev = dst->dev;
456 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 460 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
457 0, skb->dev); 461 0, skb->dev);
458 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); 462 IP6_INC_STATS_BH(net,
463 ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
459 464
460 kfree_skb(skb); 465 kfree_skb(skb);
461 return -ETIMEDOUT; 466 return -ETIMEDOUT;
@@ -468,13 +473,14 @@ int ip6_forward(struct sk_buff *skb)
468 if (proxied > 0) 473 if (proxied > 0)
469 return ip6_input(skb); 474 return ip6_input(skb);
470 else if (proxied < 0) { 475 else if (proxied < 0) {
471 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); 476 IP6_INC_STATS(net, ip6_dst_idev(dst),
477 IPSTATS_MIB_INDISCARDS);
472 goto drop; 478 goto drop;
473 } 479 }
474 } 480 }
475 481
476 if (!xfrm6_route_forward(skb)) { 482 if (!xfrm6_route_forward(skb)) {
477 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); 483 IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
478 goto drop; 484 goto drop;
479 } 485 }
480 dst = skb->dst; 486 dst = skb->dst;
@@ -523,14 +529,16 @@ int ip6_forward(struct sk_buff *skb)
523 /* Again, force OUTPUT device used as source address */ 529 /* Again, force OUTPUT device used as source address */
524 skb->dev = dst->dev; 530 skb->dev = dst->dev;
525 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); 531 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev);
526 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); 532 IP6_INC_STATS_BH(net,
527 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS); 533 ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS);
534 IP6_INC_STATS_BH(net,
535 ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS);
528 kfree_skb(skb); 536 kfree_skb(skb);
529 return -EMSGSIZE; 537 return -EMSGSIZE;
530 } 538 }
531 539
532 if (skb_cow(skb, dst->dev->hard_header_len)) { 540 if (skb_cow(skb, dst->dev->hard_header_len)) {
533 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS); 541 IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
534 goto drop; 542 goto drop;
535 } 543 }
536 544
@@ -540,12 +548,12 @@ int ip6_forward(struct sk_buff *skb)
540 548
541 hdr->hop_limit--; 549 hdr->hop_limit--;
542 550
543 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); 551 IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
544 return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev, 552 return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev,
545 ip6_forward_finish); 553 ip6_forward_finish);
546 554
547error: 555error:
548 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); 556 IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
549drop: 557drop:
550 kfree_skb(skb); 558 kfree_skb(skb);
551 return -EINVAL; 559 return -EINVAL;
@@ -613,7 +621,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
613 621
614static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) 622static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
615{ 623{
616 struct net_device *dev;
617 struct sk_buff *frag; 624 struct sk_buff *frag;
618 struct rt6_info *rt = (struct rt6_info*)skb->dst; 625 struct rt6_info *rt = (struct rt6_info*)skb->dst;
619 struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; 626 struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
@@ -623,8 +630,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
623 __be32 frag_id = 0; 630 __be32 frag_id = 0;
624 int ptr, offset = 0, err=0; 631 int ptr, offset = 0, err=0;
625 u8 *prevhdr, nexthdr = 0; 632 u8 *prevhdr, nexthdr = 0;
633 struct net *net = dev_net(skb->dst->dev);
626 634
627 dev = rt->u.dst.dev;
628 hlen = ip6_find_1stfragopt(skb, &prevhdr); 635 hlen = ip6_find_1stfragopt(skb, &prevhdr);
629 nexthdr = *prevhdr; 636 nexthdr = *prevhdr;
630 637
@@ -637,7 +644,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
637 if (!skb->local_df) { 644 if (!skb->local_df) {
638 skb->dev = skb->dst->dev; 645 skb->dev = skb->dst->dev;
639 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); 646 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
640 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); 647 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
648 IPSTATS_MIB_FRAGFAILS);
641 kfree_skb(skb); 649 kfree_skb(skb);
642 return -EMSGSIZE; 650 return -EMSGSIZE;
643 } 651 }
@@ -686,7 +694,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
686 *prevhdr = NEXTHDR_FRAGMENT; 694 *prevhdr = NEXTHDR_FRAGMENT;
687 tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); 695 tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC);
688 if (!tmp_hdr) { 696 if (!tmp_hdr) {
689 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); 697 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
698 IPSTATS_MIB_FRAGFAILS);
690 return -ENOMEM; 699 return -ENOMEM;
691 } 700 }
692 701
@@ -737,7 +746,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
737 746
738 err = output(skb); 747 err = output(skb);
739 if(!err) 748 if(!err)
740 IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES); 749 IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
750 IPSTATS_MIB_FRAGCREATES);
741 751
742 if (err || !frag) 752 if (err || !frag)
743 break; 753 break;
@@ -750,7 +760,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
750 kfree(tmp_hdr); 760 kfree(tmp_hdr);
751 761
752 if (err == 0) { 762 if (err == 0) {
753 IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS); 763 IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
764 IPSTATS_MIB_FRAGOKS);
754 dst_release(&rt->u.dst); 765 dst_release(&rt->u.dst);
755 return 0; 766 return 0;
756 } 767 }
@@ -761,7 +772,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
761 frag = skb; 772 frag = skb;
762 } 773 }
763 774
764 IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS); 775 IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
776 IPSTATS_MIB_FRAGFAILS);
765 dst_release(&rt->u.dst); 777 dst_release(&rt->u.dst);
766 return err; 778 return err;
767 } 779 }
@@ -795,7 +807,7 @@ slow_path:
795 807
796 if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { 808 if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
797 NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); 809 NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
798 IP6_INC_STATS(ip6_dst_idev(skb->dst), 810 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
799 IPSTATS_MIB_FRAGFAILS); 811 IPSTATS_MIB_FRAGFAILS);
800 err = -ENOMEM; 812 err = -ENOMEM;
801 goto fail; 813 goto fail;
@@ -859,15 +871,16 @@ slow_path:
859 if (err) 871 if (err)
860 goto fail; 872 goto fail;
861 873
862 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES); 874 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
875 IPSTATS_MIB_FRAGCREATES);
863 } 876 }
864 IP6_INC_STATS(ip6_dst_idev(skb->dst), 877 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
865 IPSTATS_MIB_FRAGOKS); 878 IPSTATS_MIB_FRAGOKS);
866 kfree_skb(skb); 879 kfree_skb(skb);
867 return err; 880 return err;
868 881
869fail: 882fail:
870 IP6_INC_STATS(ip6_dst_idev(skb->dst), 883 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
871 IPSTATS_MIB_FRAGFAILS); 884 IPSTATS_MIB_FRAGFAILS);
872 kfree_skb(skb); 885 kfree_skb(skb);
873 return err; 886 return err;
@@ -943,46 +956,46 @@ static int ip6_dst_lookup_tail(struct sock *sk,
943 } 956 }
944 957
945#ifdef CONFIG_IPV6_OPTIMISTIC_DAD 958#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
946 /* 959 /*
947 * Here if the dst entry we've looked up 960 * Here if the dst entry we've looked up
948 * has a neighbour entry that is in the INCOMPLETE 961 * has a neighbour entry that is in the INCOMPLETE
949 * state and the src address from the flow is 962 * state and the src address from the flow is
950 * marked as OPTIMISTIC, we release the found 963 * marked as OPTIMISTIC, we release the found
951 * dst entry and replace it instead with the 964 * dst entry and replace it instead with the
952 * dst entry of the nexthop router 965 * dst entry of the nexthop router
953 */ 966 */
954 if (!((*dst)->neighbour->nud_state & NUD_VALID)) { 967 if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
955 struct inet6_ifaddr *ifp; 968 struct inet6_ifaddr *ifp;
956 struct flowi fl_gw; 969 struct flowi fl_gw;
957 int redirect; 970 int redirect;
958 971
959 ifp = ipv6_get_ifaddr(net, &fl->fl6_src, 972 ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
960 (*dst)->dev, 1); 973 (*dst)->dev, 1);
961 974
962 redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); 975 redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
963 if (ifp) 976 if (ifp)
964 in6_ifa_put(ifp); 977 in6_ifa_put(ifp);
965 978
966 if (redirect) { 979 if (redirect) {
967 /* 980 /*
968 * We need to get the dst entry for the 981 * We need to get the dst entry for the
969 * default router instead 982 * default router instead
970 */ 983 */
971 dst_release(*dst); 984 dst_release(*dst);
972 memcpy(&fl_gw, fl, sizeof(struct flowi)); 985 memcpy(&fl_gw, fl, sizeof(struct flowi));
973 memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); 986 memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
974 *dst = ip6_route_output(net, sk, &fl_gw); 987 *dst = ip6_route_output(net, sk, &fl_gw);
975 if ((err = (*dst)->error)) 988 if ((err = (*dst)->error))
976 goto out_err_release; 989 goto out_err_release;
977 }
978 } 990 }
991 }
979#endif 992#endif
980 993
981 return 0; 994 return 0;
982 995
983out_err_release: 996out_err_release:
984 if (err == -ENETUNREACH) 997 if (err == -ENETUNREACH)
985 IP6_INC_STATS_BH(NULL, IPSTATS_MIB_OUTNOROUTES); 998 IP6_INC_STATS_BH(net, NULL, IPSTATS_MIB_OUTNOROUTES);
986 dst_release(*dst); 999 dst_release(*dst);
987 *dst = NULL; 1000 *dst = NULL;
988 return err; 1001 return err;
@@ -1387,7 +1400,7 @@ alloc_new_skb:
1387 return 0; 1400 return 0;
1388error: 1401error:
1389 inet->cork.length -= length; 1402 inet->cork.length -= length;
1390 IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 1403 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
1391 return err; 1404 return err;
1392} 1405}
1393 1406
@@ -1411,6 +1424,7 @@ int ip6_push_pending_frames(struct sock *sk)
1411 struct in6_addr final_dst_buf, *final_dst = &final_dst_buf; 1424 struct in6_addr final_dst_buf, *final_dst = &final_dst_buf;
1412 struct inet_sock *inet = inet_sk(sk); 1425 struct inet_sock *inet = inet_sk(sk);
1413 struct ipv6_pinfo *np = inet6_sk(sk); 1426 struct ipv6_pinfo *np = inet6_sk(sk);
1427 struct net *net = sock_net(sk);
1414 struct ipv6hdr *hdr; 1428 struct ipv6hdr *hdr;
1415 struct ipv6_txoptions *opt = np->cork.opt; 1429 struct ipv6_txoptions *opt = np->cork.opt;
1416 struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; 1430 struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
@@ -1464,12 +1478,12 @@ int ip6_push_pending_frames(struct sock *sk)
1464 skb->mark = sk->sk_mark; 1478 skb->mark = sk->sk_mark;
1465 1479
1466 skb->dst = dst_clone(&rt->u.dst); 1480 skb->dst = dst_clone(&rt->u.dst);
1467 IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); 1481 IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
1468 if (proto == IPPROTO_ICMPV6) { 1482 if (proto == IPPROTO_ICMPV6) {
1469 struct inet6_dev *idev = ip6_dst_idev(skb->dst); 1483 struct inet6_dev *idev = ip6_dst_idev(skb->dst);
1470 1484
1471 ICMP6MSGOUT_INC_STATS_BH(idev, icmp6_hdr(skb)->icmp6_type); 1485 ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type);
1472 ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); 1486 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
1473 } 1487 }
1474 1488
1475 err = ip6_local_out(skb); 1489 err = ip6_local_out(skb);
@@ -1493,7 +1507,7 @@ void ip6_flush_pending_frames(struct sock *sk)
1493 1507
1494 while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { 1508 while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
1495 if (skb->dst) 1509 if (skb->dst)
1496 IP6_INC_STATS(ip6_dst_idev(skb->dst), 1510 IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb->dst),
1497 IPSTATS_MIB_OUTDISCARDS); 1511 IPSTATS_MIB_OUTDISCARDS);
1498 kfree_skb(skb); 1512 kfree_skb(skb);
1499 } 1513 }
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 17c7b098cdb0..64ce3d33d9c6 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1050,10 +1050,10 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1050 } 1050 }
1051 1051
1052 switch (skb->protocol) { 1052 switch (skb->protocol) {
1053 case __constant_htons(ETH_P_IP): 1053 case htons(ETH_P_IP):
1054 ret = ip4ip6_tnl_xmit(skb, dev); 1054 ret = ip4ip6_tnl_xmit(skb, dev);
1055 break; 1055 break;
1056 case __constant_htons(ETH_P_IPV6): 1056 case htons(ETH_P_IPV6):
1057 ret = ip6ip6_tnl_xmit(skb, dev); 1057 ret = ip6ip6_tnl_xmit(skb, dev);
1058 break; 1058 break;
1059 default: 1059 default:
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 095bc453ff4c..182f8a177e7f 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1383,7 +1383,8 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1383 1383
1384static inline int ip6mr_forward2_finish(struct sk_buff *skb) 1384static inline int ip6mr_forward2_finish(struct sk_buff *skb)
1385{ 1385{
1386 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTFORWDATAGRAMS); 1386 IP6_INC_STATS_BH(dev_net(skb->dst->dev), ip6_dst_idev(skb->dst),
1387 IPSTATS_MIB_OUTFORWDATAGRAMS);
1387 return dst_output(skb); 1388 return dst_output(skb);
1388} 1389}
1389 1390
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index e7c03bcc2788..d7b3c6d398ae 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1446,7 +1446,7 @@ static void mld_sendpack(struct sk_buff *skb)
1446 int err; 1446 int err;
1447 struct flowi fl; 1447 struct flowi fl;
1448 1448
1449 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 1449 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
1450 payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); 1450 payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
1451 mldlen = skb->tail - skb->transport_header; 1451 mldlen = skb->tail - skb->transport_header;
1452 pip6->payload_len = htons(payload_len); 1452 pip6->payload_len = htons(payload_len);
@@ -1474,11 +1474,11 @@ static void mld_sendpack(struct sk_buff *skb)
1474 dst_output); 1474 dst_output);
1475out: 1475out:
1476 if (!err) { 1476 if (!err) {
1477 ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); 1477 ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
1478 ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); 1478 ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
1479 IP6_INC_STATS_BH(idev, IPSTATS_MIB_OUTMCASTPKTS); 1479 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
1480 } else 1480 } else
1481 IP6_INC_STATS_BH(idev, IPSTATS_MIB_OUTDISCARDS); 1481 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
1482 1482
1483 if (likely(idev != NULL)) 1483 if (likely(idev != NULL))
1484 in6_dev_put(idev); 1484 in6_dev_put(idev);
@@ -1771,7 +1771,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1771 struct flowi fl; 1771 struct flowi fl;
1772 1772
1773 rcu_read_lock(); 1773 rcu_read_lock();
1774 IP6_INC_STATS(__in6_dev_get(dev), 1774 IP6_INC_STATS(net, __in6_dev_get(dev),
1775 IPSTATS_MIB_OUTREQUESTS); 1775 IPSTATS_MIB_OUTREQUESTS);
1776 rcu_read_unlock(); 1776 rcu_read_unlock();
1777 if (type == ICMPV6_MGM_REDUCTION) 1777 if (type == ICMPV6_MGM_REDUCTION)
@@ -1787,7 +1787,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1787 1787
1788 if (skb == NULL) { 1788 if (skb == NULL) {
1789 rcu_read_lock(); 1789 rcu_read_lock();
1790 IP6_INC_STATS(__in6_dev_get(dev), 1790 IP6_INC_STATS(net, __in6_dev_get(dev),
1791 IPSTATS_MIB_OUTDISCARDS); 1791 IPSTATS_MIB_OUTDISCARDS);
1792 rcu_read_unlock(); 1792 rcu_read_unlock();
1793 return; 1793 return;
@@ -1839,11 +1839,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1839 dst_output); 1839 dst_output);
1840out: 1840out:
1841 if (!err) { 1841 if (!err) {
1842 ICMP6MSGOUT_INC_STATS(idev, type); 1842 ICMP6MSGOUT_INC_STATS(net, idev, type);
1843 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 1843 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
1844 IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); 1844 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
1845 } else 1845 } else
1846 IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); 1846 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
1847 1847
1848 if (likely(idev != NULL)) 1848 if (likely(idev != NULL))
1849 in6_dev_put(idev); 1849 in6_dev_put(idev);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index f1c62ba0f56b..172438320eec 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -516,13 +516,13 @@ static void __ndisc_send(struct net_device *dev,
516 skb->dst = dst; 516 skb->dst = dst;
517 517
518 idev = in6_dev_get(dst->dev); 518 idev = in6_dev_get(dst->dev);
519 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 519 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
520 520
521 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, 521 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
522 dst_output); 522 dst_output);
523 if (!err) { 523 if (!err) {
524 ICMP6MSGOUT_INC_STATS(idev, type); 524 ICMP6MSGOUT_INC_STATS(net, idev, type);
525 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 525 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
526 } 526 }
527 527
528 if (likely(idev != NULL)) 528 if (likely(idev != NULL))
@@ -1199,7 +1199,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1199 } 1199 }
1200 neigh->flags |= NTF_ROUTER; 1200 neigh->flags |= NTF_ROUTER;
1201 } else if (rt) { 1201 } else if (rt) {
1202 rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); 1202 rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
1203 } 1203 }
1204 1204
1205 if (rt) 1205 if (rt)
@@ -1581,12 +1581,12 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1581 1581
1582 buff->dst = dst; 1582 buff->dst = dst;
1583 idev = in6_dev_get(dst->dev); 1583 idev = in6_dev_get(dst->dev);
1584 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 1584 IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
1585 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, 1585 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
1586 dst_output); 1586 dst_output);
1587 if (!err) { 1587 if (!err) {
1588 ICMP6MSGOUT_INC_STATS(idev, NDISC_REDIRECT); 1588 ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT);
1589 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 1589 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
1590 } 1590 }
1591 1591
1592 if (likely(idev != NULL)) 1592 if (likely(idev != NULL))
@@ -1730,9 +1730,8 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f
1730 return ret; 1730 return ret;
1731} 1731}
1732 1732
1733int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, 1733int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
1734 int nlen, void __user *oldval, 1734 void __user *oldval, size_t __user *oldlenp,
1735 size_t __user *oldlenp,
1736 void __user *newval, size_t newlen) 1735 void __user *newval, size_t newlen)
1737{ 1736{
1738 struct net_device *dev = ctl->extra1; 1737 struct net_device *dev = ctl->extra1;
@@ -1745,13 +1744,11 @@ int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
1745 1744
1746 switch (ctl->ctl_name) { 1745 switch (ctl->ctl_name) {
1747 case NET_NEIGH_REACHABLE_TIME: 1746 case NET_NEIGH_REACHABLE_TIME:
1748 ret = sysctl_jiffies(ctl, name, nlen, 1747 ret = sysctl_jiffies(ctl, oldval, oldlenp, newval, newlen);
1749 oldval, oldlenp, newval, newlen);
1750 break; 1748 break;
1751 case NET_NEIGH_RETRANS_TIME_MS: 1749 case NET_NEIGH_RETRANS_TIME_MS:
1752 case NET_NEIGH_REACHABLE_TIME_MS: 1750 case NET_NEIGH_REACHABLE_TIME_MS:
1753 ret = sysctl_ms_jiffies(ctl, name, nlen, 1751 ret = sysctl_ms_jiffies(ctl, oldval, oldlenp, newval, newlen);
1754 oldval, oldlenp, newval, newlen);
1755 break; 1752 break;
1756 default: 1753 default:
1757 ret = 0; 1754 ret = 0;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 8c6c5e71f210..fd5b3a4e3329 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -12,6 +12,7 @@
12 12
13int ip6_route_me_harder(struct sk_buff *skb) 13int ip6_route_me_harder(struct sk_buff *skb)
14{ 14{
15 struct net *net = dev_net(skb->dst->dev);
15 struct ipv6hdr *iph = ipv6_hdr(skb); 16 struct ipv6hdr *iph = ipv6_hdr(skb);
16 struct dst_entry *dst; 17 struct dst_entry *dst;
17 struct flowi fl = { 18 struct flowi fl = {
@@ -23,7 +24,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
23 .saddr = iph->saddr, } }, 24 .saddr = iph->saddr, } },
24 }; 25 };
25 26
26 dst = ip6_route_output(&init_net, skb->sk, &fl); 27 dst = ip6_route_output(net, skb->sk, &fl);
27 28
28#ifdef CONFIG_XFRM 29#ifdef CONFIG_XFRM
29 if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 30 if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
@@ -33,7 +34,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
33#endif 34#endif
34 35
35 if (dst->error) { 36 if (dst->error) {
36 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); 37 IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
37 LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); 38 LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
38 dst_release(dst); 39 dst_release(dst);
39 return -EINVAL; 40 return -EINVAL;
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 0cfcce7b18d8..53ea512c4608 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -55,30 +55,29 @@ config IP6_NF_IPTABLES
55 55
56 To compile it as a module, choose M here. If unsure, say N. 56 To compile it as a module, choose M here. If unsure, say N.
57 57
58if IP6_NF_IPTABLES
59
58# The simple matches. 60# The simple matches.
59config IP6_NF_MATCH_RT 61config IP6_NF_MATCH_AH
60 tristate '"rt" Routing header match support' 62 tristate '"ah" match support'
61 depends on IP6_NF_IPTABLES
62 depends on NETFILTER_ADVANCED 63 depends on NETFILTER_ADVANCED
63 help 64 help
64 rt matching allows you to match packets based on the routing 65 This module allows one to match AH packets.
65 header of the packet.
66 66
67 To compile it as a module, choose M here. If unsure, say N. 67 To compile it as a module, choose M here. If unsure, say N.
68 68
69config IP6_NF_MATCH_OPTS 69config IP6_NF_MATCH_EUI64
70 tristate '"hopbyhop" and "dst" opts header match support' 70 tristate '"eui64" address check'
71 depends on IP6_NF_IPTABLES
72 depends on NETFILTER_ADVANCED 71 depends on NETFILTER_ADVANCED
73 help 72 help
74 This allows one to match packets based on the hop-by-hop 73 This module performs checking on the IPv6 source address
75 and destination options headers of a packet. 74 Compares the last 64 bits with the EUI64 (delivered
75 from the MAC address) address
76 76
77 To compile it as a module, choose M here. If unsure, say N. 77 To compile it as a module, choose M here. If unsure, say N.
78 78
79config IP6_NF_MATCH_FRAG 79config IP6_NF_MATCH_FRAG
80 tristate '"frag" Fragmentation header match support' 80 tristate '"frag" Fragmentation header match support'
81 depends on IP6_NF_IPTABLES
82 depends on NETFILTER_ADVANCED 81 depends on NETFILTER_ADVANCED
83 help 82 help
84 frag matching allows you to match packets based on the fragmentation 83 frag matching allows you to match packets based on the fragmentation
@@ -86,9 +85,17 @@ config IP6_NF_MATCH_FRAG
86 85
87 To compile it as a module, choose M here. If unsure, say N. 86 To compile it as a module, choose M here. If unsure, say N.
88 87
88config IP6_NF_MATCH_OPTS
89 tristate '"hbh" hop-by-hop and "dst" opts header match support'
90 depends on NETFILTER_ADVANCED
91 help
92 This allows one to match packets based on the hop-by-hop
93 and destination options headers of a packet.
94
95 To compile it as a module, choose M here. If unsure, say N.
96
89config IP6_NF_MATCH_HL 97config IP6_NF_MATCH_HL
90 tristate '"hl" match support' 98 tristate '"hl" match support'
91 depends on IP6_NF_IPTABLES
92 depends on NETFILTER_ADVANCED 99 depends on NETFILTER_ADVANCED
93 help 100 help
94 HL matching allows you to match packets based on the hop 101 HL matching allows you to match packets based on the hop
@@ -98,7 +105,6 @@ config IP6_NF_MATCH_HL
98 105
99config IP6_NF_MATCH_IPV6HEADER 106config IP6_NF_MATCH_IPV6HEADER
100 tristate '"ipv6header" IPv6 Extension Headers Match' 107 tristate '"ipv6header" IPv6 Extension Headers Match'
101 depends on IP6_NF_IPTABLES
102 default m if NETFILTER_ADVANCED=n 108 default m if NETFILTER_ADVANCED=n
103 help 109 help
104 This module allows one to match packets based upon 110 This module allows one to match packets based upon
@@ -106,54 +112,40 @@ config IP6_NF_MATCH_IPV6HEADER
106 112
107 To compile it as a module, choose M here. If unsure, say N. 113 To compile it as a module, choose M here. If unsure, say N.
108 114
109config IP6_NF_MATCH_AH
110 tristate '"ah" match support'
111 depends on IP6_NF_IPTABLES
112 depends on NETFILTER_ADVANCED
113 help
114 This module allows one to match AH packets.
115
116 To compile it as a module, choose M here. If unsure, say N.
117
118config IP6_NF_MATCH_MH 115config IP6_NF_MATCH_MH
119 tristate '"mh" match support' 116 tristate '"mh" match support'
120 depends on IP6_NF_IPTABLES
121 depends on NETFILTER_ADVANCED 117 depends on NETFILTER_ADVANCED
122 help 118 help
123 This module allows one to match MH packets. 119 This module allows one to match MH packets.
124 120
125 To compile it as a module, choose M here. If unsure, say N. 121 To compile it as a module, choose M here. If unsure, say N.
126 122
127config IP6_NF_MATCH_EUI64 123config IP6_NF_MATCH_RT
128 tristate '"eui64" address check' 124 tristate '"rt" Routing header match support'
129 depends on IP6_NF_IPTABLES
130 depends on NETFILTER_ADVANCED 125 depends on NETFILTER_ADVANCED
131 help 126 help
132 This module performs checking on the IPv6 source address 127 rt matching allows you to match packets based on the routing
133 Compares the last 64 bits with the EUI64 (delivered 128 header of the packet.
134 from the MAC address) address
135 129
136 To compile it as a module, choose M here. If unsure, say N. 130 To compile it as a module, choose M here. If unsure, say N.
137 131
138# The targets 132# The targets
139config IP6_NF_FILTER 133config IP6_NF_TARGET_LOG
140 tristate "Packet filtering" 134 tristate "LOG target support"
141 depends on IP6_NF_IPTABLES
142 default m if NETFILTER_ADVANCED=n 135 default m if NETFILTER_ADVANCED=n
143 help 136 help
144 Packet filtering defines a table `filter', which has a series of 137 This option adds a `LOG' target, which allows you to create rules in
145 rules for simple packet filtering at local input, forwarding and 138 any iptables table which records the packet header to the syslog.
146 local output. See the man page for iptables(8).
147 139
148 To compile it as a module, choose M here. If unsure, say N. 140 To compile it as a module, choose M here. If unsure, say N.
149 141
150config IP6_NF_TARGET_LOG 142config IP6_NF_FILTER
151 tristate "LOG target support" 143 tristate "Packet filtering"
152 depends on IP6_NF_FILTER
153 default m if NETFILTER_ADVANCED=n 144 default m if NETFILTER_ADVANCED=n
154 help 145 help
155 This option adds a `LOG' target, which allows you to create rules in 146 Packet filtering defines a table `filter', which has a series of
156 any iptables table which records the packet header to the syslog. 147 rules for simple packet filtering at local input, forwarding and
148 local output. See the man page for iptables(8).
157 149
158 To compile it as a module, choose M here. If unsure, say N. 150 To compile it as a module, choose M here. If unsure, say N.
159 151
@@ -170,7 +162,6 @@ config IP6_NF_TARGET_REJECT
170 162
171config IP6_NF_MANGLE 163config IP6_NF_MANGLE
172 tristate "Packet mangling" 164 tristate "Packet mangling"
173 depends on IP6_NF_IPTABLES
174 default m if NETFILTER_ADVANCED=n 165 default m if NETFILTER_ADVANCED=n
175 help 166 help
176 This option adds a `mangle' table to iptables: see the man page for 167 This option adds a `mangle' table to iptables: see the man page for
@@ -198,7 +189,6 @@ config IP6_NF_TARGET_HL
198 189
199config IP6_NF_RAW 190config IP6_NF_RAW
200 tristate 'raw table support (required for TRACE)' 191 tristate 'raw table support (required for TRACE)'
201 depends on IP6_NF_IPTABLES
202 depends on NETFILTER_ADVANCED 192 depends on NETFILTER_ADVANCED
203 help 193 help
204 This option adds a `raw' table to ip6tables. This table is the very 194 This option adds a `raw' table to ip6tables. This table is the very
@@ -211,7 +201,6 @@ config IP6_NF_RAW
211# security table for MAC policy 201# security table for MAC policy
212config IP6_NF_SECURITY 202config IP6_NF_SECURITY
213 tristate "Security table" 203 tristate "Security table"
214 depends on IP6_NF_IPTABLES
215 depends on SECURITY 204 depends on SECURITY
216 depends on NETFILTER_ADVANCED 205 depends on NETFILTER_ADVANCED
217 help 206 help
@@ -220,5 +209,7 @@ config IP6_NF_SECURITY
220 209
221 If unsure, say N. 210 If unsure, say N.
222 211
212endif # IP6_NF_IPTABLES
213
223endmenu 214endmenu
224 215
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 0b4557e03431..a33485dc81cb 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -200,32 +200,25 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6)
200} 200}
201 201
202static unsigned int 202static unsigned int
203ip6t_error(struct sk_buff *skb, 203ip6t_error(struct sk_buff *skb, const struct xt_target_param *par)
204 const struct net_device *in,
205 const struct net_device *out,
206 unsigned int hooknum,
207 const struct xt_target *target,
208 const void *targinfo)
209{ 204{
210 if (net_ratelimit()) 205 if (net_ratelimit())
211 printk("ip6_tables: error: `%s'\n", (char *)targinfo); 206 printk("ip6_tables: error: `%s'\n",
207 (const char *)par->targinfo);
212 208
213 return NF_DROP; 209 return NF_DROP;
214} 210}
215 211
216/* Performance critical - called for every packet */ 212/* Performance critical - called for every packet */
217static inline bool 213static inline bool
218do_match(struct ip6t_entry_match *m, 214do_match(struct ip6t_entry_match *m, const struct sk_buff *skb,
219 const struct sk_buff *skb, 215 struct xt_match_param *par)
220 const struct net_device *in,
221 const struct net_device *out,
222 int offset,
223 unsigned int protoff,
224 bool *hotdrop)
225{ 216{
217 par->match = m->u.kernel.match;
218 par->matchinfo = m->data;
219
226 /* Stop iteration if it doesn't match */ 220 /* Stop iteration if it doesn't match */
227 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data, 221 if (!m->u.kernel.match->match(skb, par))
228 offset, protoff, hotdrop))
229 return true; 222 return true;
230 else 223 else
231 return false; 224 return false;
@@ -355,8 +348,6 @@ ip6t_do_table(struct sk_buff *skb,
355 struct xt_table *table) 348 struct xt_table *table)
356{ 349{
357 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 350 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
358 int offset = 0;
359 unsigned int protoff = 0;
360 bool hotdrop = false; 351 bool hotdrop = false;
361 /* Initializing verdict to NF_DROP keeps gcc happy. */ 352 /* Initializing verdict to NF_DROP keeps gcc happy. */
362 unsigned int verdict = NF_DROP; 353 unsigned int verdict = NF_DROP;
@@ -364,6 +355,8 @@ ip6t_do_table(struct sk_buff *skb,
364 void *table_base; 355 void *table_base;
365 struct ip6t_entry *e, *back; 356 struct ip6t_entry *e, *back;
366 struct xt_table_info *private; 357 struct xt_table_info *private;
358 struct xt_match_param mtpar;
359 struct xt_target_param tgpar;
367 360
368 /* Initialization */ 361 /* Initialization */
369 indev = in ? in->name : nulldevname; 362 indev = in ? in->name : nulldevname;
@@ -374,6 +367,11 @@ ip6t_do_table(struct sk_buff *skb,
374 * things we don't know, ie. tcp syn flag or ports). If the 367 * things we don't know, ie. tcp syn flag or ports). If the
375 * rule is also a fragment-specific rule, non-fragments won't 368 * rule is also a fragment-specific rule, non-fragments won't
376 * match it. */ 369 * match it. */
370 mtpar.hotdrop = &hotdrop;
371 mtpar.in = tgpar.in = in;
372 mtpar.out = tgpar.out = out;
373 mtpar.family = tgpar.family = NFPROTO_IPV6;
374 tgpar.hooknum = hook;
377 375
378 read_lock_bh(&table->lock); 376 read_lock_bh(&table->lock);
379 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 377 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
@@ -388,12 +386,10 @@ ip6t_do_table(struct sk_buff *skb,
388 IP_NF_ASSERT(e); 386 IP_NF_ASSERT(e);
389 IP_NF_ASSERT(back); 387 IP_NF_ASSERT(back);
390 if (ip6_packet_match(skb, indev, outdev, &e->ipv6, 388 if (ip6_packet_match(skb, indev, outdev, &e->ipv6,
391 &protoff, &offset, &hotdrop)) { 389 &mtpar.thoff, &mtpar.fragoff, &hotdrop)) {
392 struct ip6t_entry_target *t; 390 struct ip6t_entry_target *t;
393 391
394 if (IP6T_MATCH_ITERATE(e, do_match, 392 if (IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
395 skb, in, out,
396 offset, protoff, &hotdrop) != 0)
397 goto no_match; 393 goto no_match;
398 394
399 ADD_COUNTER(e->counters, 395 ADD_COUNTER(e->counters,
@@ -441,15 +437,15 @@ ip6t_do_table(struct sk_buff *skb,
441 } else { 437 } else {
442 /* Targets which reenter must return 438 /* Targets which reenter must return
443 abs. verdicts */ 439 abs. verdicts */
440 tgpar.target = t->u.kernel.target;
441 tgpar.targinfo = t->data;
442
444#ifdef CONFIG_NETFILTER_DEBUG 443#ifdef CONFIG_NETFILTER_DEBUG
445 ((struct ip6t_entry *)table_base)->comefrom 444 ((struct ip6t_entry *)table_base)->comefrom
446 = 0xeeeeeeec; 445 = 0xeeeeeeec;
447#endif 446#endif
448 verdict = t->u.kernel.target->target(skb, 447 verdict = t->u.kernel.target->target(skb,
449 in, out, 448 &tgpar);
450 hook,
451 t->u.kernel.target,
452 t->data);
453 449
454#ifdef CONFIG_NETFILTER_DEBUG 450#ifdef CONFIG_NETFILTER_DEBUG
455 if (((struct ip6t_entry *)table_base)->comefrom 451 if (((struct ip6t_entry *)table_base)->comefrom
@@ -602,12 +598,17 @@ mark_source_chains(struct xt_table_info *newinfo,
602static int 598static int
603cleanup_match(struct ip6t_entry_match *m, unsigned int *i) 599cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
604{ 600{
601 struct xt_mtdtor_param par;
602
605 if (i && (*i)-- == 0) 603 if (i && (*i)-- == 0)
606 return 1; 604 return 1;
607 605
608 if (m->u.kernel.match->destroy) 606 par.match = m->u.kernel.match;
609 m->u.kernel.match->destroy(m->u.kernel.match, m->data); 607 par.matchinfo = m->data;
610 module_put(m->u.kernel.match->me); 608 par.family = NFPROTO_IPV6;
609 if (par.match->destroy != NULL)
610 par.match->destroy(&par);
611 module_put(par.match->me);
611 return 0; 612 return 0;
612} 613}
613 614
@@ -632,34 +633,28 @@ check_entry(struct ip6t_entry *e, const char *name)
632 return 0; 633 return 0;
633} 634}
634 635
635static int check_match(struct ip6t_entry_match *m, const char *name, 636static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
636 const struct ip6t_ip6 *ipv6, 637 unsigned int *i)
637 unsigned int hookmask, unsigned int *i)
638{ 638{
639 struct xt_match *match; 639 const struct ip6t_ip6 *ipv6 = par->entryinfo;
640 int ret; 640 int ret;
641 641
642 match = m->u.kernel.match; 642 par->match = m->u.kernel.match;
643 ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m), 643 par->matchinfo = m->data;
644 name, hookmask, ipv6->proto, 644
645 ipv6->invflags & IP6T_INV_PROTO); 645 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
646 if (!ret && m->u.kernel.match->checkentry 646 ipv6->proto, ipv6->invflags & IP6T_INV_PROTO);
647 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data, 647 if (ret < 0) {
648 hookmask)) {
649 duprintf("ip_tables: check failed for `%s'.\n", 648 duprintf("ip_tables: check failed for `%s'.\n",
650 m->u.kernel.match->name); 649 par.match->name);
651 ret = -EINVAL; 650 return ret;
652 } 651 }
653 if (!ret) 652 ++*i;
654 (*i)++; 653 return 0;
655 return ret;
656} 654}
657 655
658static int 656static int
659find_check_match(struct ip6t_entry_match *m, 657find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
660 const char *name,
661 const struct ip6t_ip6 *ipv6,
662 unsigned int hookmask,
663 unsigned int *i) 658 unsigned int *i)
664{ 659{
665 struct xt_match *match; 660 struct xt_match *match;
@@ -674,7 +669,7 @@ find_check_match(struct ip6t_entry_match *m,
674 } 669 }
675 m->u.kernel.match = match; 670 m->u.kernel.match = match;
676 671
677 ret = check_match(m, name, ipv6, hookmask, i); 672 ret = check_match(m, par, i);
678 if (ret) 673 if (ret)
679 goto err; 674 goto err;
680 675
@@ -686,23 +681,26 @@ err:
686 681
687static int check_target(struct ip6t_entry *e, const char *name) 682static int check_target(struct ip6t_entry *e, const char *name)
688{ 683{
689 struct ip6t_entry_target *t; 684 struct ip6t_entry_target *t = ip6t_get_target(e);
690 struct xt_target *target; 685 struct xt_tgchk_param par = {
686 .table = name,
687 .entryinfo = e,
688 .target = t->u.kernel.target,
689 .targinfo = t->data,
690 .hook_mask = e->comefrom,
691 .family = NFPROTO_IPV6,
692 };
691 int ret; 693 int ret;
692 694
693 t = ip6t_get_target(e); 695 t = ip6t_get_target(e);
694 target = t->u.kernel.target; 696 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
695 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), 697 e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
696 name, e->comefrom, e->ipv6.proto, 698 if (ret < 0) {
697 e->ipv6.invflags & IP6T_INV_PROTO);
698 if (!ret && t->u.kernel.target->checkentry
699 && !t->u.kernel.target->checkentry(name, e, target, t->data,
700 e->comefrom)) {
701 duprintf("ip_tables: check failed for `%s'.\n", 699 duprintf("ip_tables: check failed for `%s'.\n",
702 t->u.kernel.target->name); 700 t->u.kernel.target->name);
703 ret = -EINVAL; 701 return ret;
704 } 702 }
705 return ret; 703 return 0;
706} 704}
707 705
708static int 706static int
@@ -713,14 +711,18 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
713 struct xt_target *target; 711 struct xt_target *target;
714 int ret; 712 int ret;
715 unsigned int j; 713 unsigned int j;
714 struct xt_mtchk_param mtpar;
716 715
717 ret = check_entry(e, name); 716 ret = check_entry(e, name);
718 if (ret) 717 if (ret)
719 return ret; 718 return ret;
720 719
721 j = 0; 720 j = 0;
722 ret = IP6T_MATCH_ITERATE(e, find_check_match, name, &e->ipv6, 721 mtpar.table = name;
723 e->comefrom, &j); 722 mtpar.entryinfo = &e->ipv6;
723 mtpar.hook_mask = e->comefrom;
724 mtpar.family = NFPROTO_IPV6;
725 ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
724 if (ret != 0) 726 if (ret != 0)
725 goto cleanup_matches; 727 goto cleanup_matches;
726 728
@@ -795,6 +797,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
795static int 797static int
796cleanup_entry(struct ip6t_entry *e, unsigned int *i) 798cleanup_entry(struct ip6t_entry *e, unsigned int *i)
797{ 799{
800 struct xt_tgdtor_param par;
798 struct ip6t_entry_target *t; 801 struct ip6t_entry_target *t;
799 802
800 if (i && (*i)-- == 0) 803 if (i && (*i)-- == 0)
@@ -803,9 +806,13 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
803 /* Cleanup all matches */ 806 /* Cleanup all matches */
804 IP6T_MATCH_ITERATE(e, cleanup_match, NULL); 807 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
805 t = ip6t_get_target(e); 808 t = ip6t_get_target(e);
806 if (t->u.kernel.target->destroy) 809
807 t->u.kernel.target->destroy(t->u.kernel.target, t->data); 810 par.target = t->u.kernel.target;
808 module_put(t->u.kernel.target->me); 811 par.targinfo = t->data;
812 par.family = NFPROTO_IPV6;
813 if (par.target->destroy != NULL)
814 par.target->destroy(&par);
815 module_put(par.target->me);
809 return 0; 816 return 0;
810} 817}
811 818
@@ -1677,10 +1684,14 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name,
1677{ 1684{
1678 unsigned int j; 1685 unsigned int j;
1679 int ret; 1686 int ret;
1687 struct xt_mtchk_param mtpar;
1680 1688
1681 j = 0; 1689 j = 0;
1682 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, 1690 mtpar.table = name;
1683 e->comefrom, &j); 1691 mtpar.entryinfo = &e->ipv6;
1692 mtpar.hook_mask = e->comefrom;
1693 mtpar.family = NFPROTO_IPV6;
1694 ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j);
1684 if (ret) 1695 if (ret)
1685 goto cleanup_matches; 1696 goto cleanup_matches;
1686 1697
@@ -2146,30 +2157,23 @@ icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2146} 2157}
2147 2158
2148static bool 2159static bool
2149icmp6_match(const struct sk_buff *skb, 2160icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par)
2150 const struct net_device *in,
2151 const struct net_device *out,
2152 const struct xt_match *match,
2153 const void *matchinfo,
2154 int offset,
2155 unsigned int protoff,
2156 bool *hotdrop)
2157{ 2161{
2158 const struct icmp6hdr *ic; 2162 const struct icmp6hdr *ic;
2159 struct icmp6hdr _icmph; 2163 struct icmp6hdr _icmph;
2160 const struct ip6t_icmp *icmpinfo = matchinfo; 2164 const struct ip6t_icmp *icmpinfo = par->matchinfo;
2161 2165
2162 /* Must not be a fragment. */ 2166 /* Must not be a fragment. */
2163 if (offset) 2167 if (par->fragoff != 0)
2164 return false; 2168 return false;
2165 2169
2166 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); 2170 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2167 if (ic == NULL) { 2171 if (ic == NULL) {
2168 /* We've been asked to examine this packet, and we 2172 /* We've been asked to examine this packet, and we
2169 * can't. Hence, no choice but to drop. 2173 * can't. Hence, no choice but to drop.
2170 */ 2174 */
2171 duprintf("Dropping evil ICMP tinygram.\n"); 2175 duprintf("Dropping evil ICMP tinygram.\n");
2172 *hotdrop = true; 2176 *par->hotdrop = true;
2173 return false; 2177 return false;
2174 } 2178 }
2175 2179
@@ -2181,14 +2185,9 @@ icmp6_match(const struct sk_buff *skb,
2181} 2185}
2182 2186
2183/* Called when user tries to insert an entry of this type. */ 2187/* Called when user tries to insert an entry of this type. */
2184static bool 2188static bool icmp6_checkentry(const struct xt_mtchk_param *par)
2185icmp6_checkentry(const char *tablename,
2186 const void *entry,
2187 const struct xt_match *match,
2188 void *matchinfo,
2189 unsigned int hook_mask)
2190{ 2189{
2191 const struct ip6t_icmp *icmpinfo = matchinfo; 2190 const struct ip6t_icmp *icmpinfo = par->matchinfo;
2192 2191
2193 /* Must specify no unknown invflags */ 2192 /* Must specify no unknown invflags */
2194 return !(icmpinfo->invflags & ~IP6T_ICMP_INV); 2193 return !(icmpinfo->invflags & ~IP6T_ICMP_INV);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index d5f8fd5f29d3..27b5adf670a2 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -19,12 +19,10 @@ MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field modification target");
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20 20
21static unsigned int 21static unsigned int
22hl_tg6(struct sk_buff *skb, const struct net_device *in, 22hl_tg6(struct sk_buff *skb, const struct xt_target_param *par)
23 const struct net_device *out, unsigned int hooknum,
24 const struct xt_target *target, const void *targinfo)
25{ 23{
26 struct ipv6hdr *ip6h; 24 struct ipv6hdr *ip6h;
27 const struct ip6t_HL_info *info = targinfo; 25 const struct ip6t_HL_info *info = par->targinfo;
28 int new_hl; 26 int new_hl;
29 27
30 if (!skb_make_writable(skb, skb->len)) 28 if (!skb_make_writable(skb, skb->len))
@@ -56,12 +54,9 @@ hl_tg6(struct sk_buff *skb, const struct net_device *in,
56 return XT_CONTINUE; 54 return XT_CONTINUE;
57} 55}
58 56
59static bool 57static bool hl_tg6_check(const struct xt_tgchk_param *par)
60hl_tg6_check(const char *tablename, const void *entry,
61 const struct xt_target *target, void *targinfo,
62 unsigned int hook_mask)
63{ 58{
64 const struct ip6t_HL_info *info = targinfo; 59 const struct ip6t_HL_info *info = par->targinfo;
65 60
66 if (info->mode > IP6T_HL_MAXMODE) { 61 if (info->mode > IP6T_HL_MAXMODE) {
67 printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", 62 printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
@@ -78,7 +73,7 @@ hl_tg6_check(const char *tablename, const void *entry,
78 73
79static struct xt_target hl_tg6_reg __read_mostly = { 74static struct xt_target hl_tg6_reg __read_mostly = {
80 .name = "HL", 75 .name = "HL",
81 .family = AF_INET6, 76 .family = NFPROTO_IPV6,
82 .target = hl_tg6, 77 .target = hl_tg6,
83 .targetsize = sizeof(struct ip6t_HL_info), 78 .targetsize = sizeof(struct ip6t_HL_info),
84 .table = "mangle", 79 .table = "mangle",
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 3a2316974f83..caa441d09567 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -385,7 +385,7 @@ static struct nf_loginfo default_loginfo = {
385}; 385};
386 386
387static void 387static void
388ip6t_log_packet(unsigned int pf, 388ip6t_log_packet(u_int8_t pf,
389 unsigned int hooknum, 389 unsigned int hooknum,
390 const struct sk_buff *skb, 390 const struct sk_buff *skb,
391 const struct net_device *in, 391 const struct net_device *in,
@@ -438,28 +438,24 @@ ip6t_log_packet(unsigned int pf,
438} 438}
439 439
440static unsigned int 440static unsigned int
441log_tg6(struct sk_buff *skb, const struct net_device *in, 441log_tg6(struct sk_buff *skb, const struct xt_target_param *par)
442 const struct net_device *out, unsigned int hooknum,
443 const struct xt_target *target, const void *targinfo)
444{ 442{
445 const struct ip6t_log_info *loginfo = targinfo; 443 const struct ip6t_log_info *loginfo = par->targinfo;
446 struct nf_loginfo li; 444 struct nf_loginfo li;
447 445
448 li.type = NF_LOG_TYPE_LOG; 446 li.type = NF_LOG_TYPE_LOG;
449 li.u.log.level = loginfo->level; 447 li.u.log.level = loginfo->level;
450 li.u.log.logflags = loginfo->logflags; 448 li.u.log.logflags = loginfo->logflags;
451 449
452 ip6t_log_packet(PF_INET6, hooknum, skb, in, out, &li, loginfo->prefix); 450 ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, par->out,
451 &li, loginfo->prefix);
453 return XT_CONTINUE; 452 return XT_CONTINUE;
454} 453}
455 454
456 455
457static bool 456static bool log_tg6_check(const struct xt_tgchk_param *par)
458log_tg6_check(const char *tablename, const void *entry,
459 const struct xt_target *target, void *targinfo,
460 unsigned int hook_mask)
461{ 457{
462 const struct ip6t_log_info *loginfo = targinfo; 458 const struct ip6t_log_info *loginfo = par->targinfo;
463 459
464 if (loginfo->level >= 8) { 460 if (loginfo->level >= 8) {
465 pr_debug("LOG: level %u >= 8\n", loginfo->level); 461 pr_debug("LOG: level %u >= 8\n", loginfo->level);
@@ -475,7 +471,7 @@ log_tg6_check(const char *tablename, const void *entry,
475 471
476static struct xt_target log_tg6_reg __read_mostly = { 472static struct xt_target log_tg6_reg __read_mostly = {
477 .name = "LOG", 473 .name = "LOG",
478 .family = AF_INET6, 474 .family = NFPROTO_IPV6,
479 .target = log_tg6, 475 .target = log_tg6,
480 .targetsize = sizeof(struct ip6t_log_info), 476 .targetsize = sizeof(struct ip6t_log_info),
481 .checkentry = log_tg6_check, 477 .checkentry = log_tg6_check,
@@ -495,7 +491,7 @@ static int __init log_tg6_init(void)
495 ret = xt_register_target(&log_tg6_reg); 491 ret = xt_register_target(&log_tg6_reg);
496 if (ret < 0) 492 if (ret < 0)
497 return ret; 493 return ret;
498 nf_log_register(PF_INET6, &ip6t_logger); 494 nf_log_register(NFPROTO_IPV6, &ip6t_logger);
499 return 0; 495 return 0;
500} 496}
501 497
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 44c8d65a2431..0981b4ccb8b1 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6");
35MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
36 36
37/* Send RST reply */ 37/* Send RST reply */
38static void send_reset(struct sk_buff *oldskb) 38static void send_reset(struct net *net, struct sk_buff *oldskb)
39{ 39{
40 struct sk_buff *nskb; 40 struct sk_buff *nskb;
41 struct tcphdr otcph, *tcph; 41 struct tcphdr otcph, *tcph;
@@ -94,7 +94,7 @@ static void send_reset(struct sk_buff *oldskb)
94 fl.fl_ip_sport = otcph.dest; 94 fl.fl_ip_sport = otcph.dest;
95 fl.fl_ip_dport = otcph.source; 95 fl.fl_ip_dport = otcph.source;
96 security_skb_classify_flow(oldskb, &fl); 96 security_skb_classify_flow(oldskb, &fl);
97 dst = ip6_route_output(&init_net, NULL, &fl); 97 dst = ip6_route_output(net, NULL, &fl);
98 if (dst == NULL) 98 if (dst == NULL)
99 return; 99 return;
100 if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) 100 if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0))
@@ -163,20 +163,20 @@ static void send_reset(struct sk_buff *oldskb)
163} 163}
164 164
165static inline void 165static inline void
166send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum) 166send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code,
167 unsigned int hooknum)
167{ 168{
168 if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) 169 if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
169 skb_in->dev = init_net.loopback_dev; 170 skb_in->dev = net->loopback_dev;
170 171
171 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); 172 icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL);
172} 173}
173 174
174static unsigned int 175static unsigned int
175reject_tg6(struct sk_buff *skb, const struct net_device *in, 176reject_tg6(struct sk_buff *skb, const struct xt_target_param *par)
176 const struct net_device *out, unsigned int hooknum,
177 const struct xt_target *target, const void *targinfo)
178{ 177{
179 const struct ip6t_reject_info *reject = targinfo; 178 const struct ip6t_reject_info *reject = par->targinfo;
179 struct net *net = dev_net((par->in != NULL) ? par->in : par->out);
180 180
181 pr_debug("%s: medium point\n", __func__); 181 pr_debug("%s: medium point\n", __func__);
182 /* WARNING: This code causes reentry within ip6tables. 182 /* WARNING: This code causes reentry within ip6tables.
@@ -184,25 +184,25 @@ reject_tg6(struct sk_buff *skb, const struct net_device *in,
184 must return an absolute verdict. --RR */ 184 must return an absolute verdict. --RR */
185 switch (reject->with) { 185 switch (reject->with) {
186 case IP6T_ICMP6_NO_ROUTE: 186 case IP6T_ICMP6_NO_ROUTE:
187 send_unreach(skb, ICMPV6_NOROUTE, hooknum); 187 send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum);
188 break; 188 break;
189 case IP6T_ICMP6_ADM_PROHIBITED: 189 case IP6T_ICMP6_ADM_PROHIBITED:
190 send_unreach(skb, ICMPV6_ADM_PROHIBITED, hooknum); 190 send_unreach(net, skb, ICMPV6_ADM_PROHIBITED, par->hooknum);
191 break; 191 break;
192 case IP6T_ICMP6_NOT_NEIGHBOUR: 192 case IP6T_ICMP6_NOT_NEIGHBOUR:
193 send_unreach(skb, ICMPV6_NOT_NEIGHBOUR, hooknum); 193 send_unreach(net, skb, ICMPV6_NOT_NEIGHBOUR, par->hooknum);
194 break; 194 break;
195 case IP6T_ICMP6_ADDR_UNREACH: 195 case IP6T_ICMP6_ADDR_UNREACH:
196 send_unreach(skb, ICMPV6_ADDR_UNREACH, hooknum); 196 send_unreach(net, skb, ICMPV6_ADDR_UNREACH, par->hooknum);
197 break; 197 break;
198 case IP6T_ICMP6_PORT_UNREACH: 198 case IP6T_ICMP6_PORT_UNREACH:
199 send_unreach(skb, ICMPV6_PORT_UNREACH, hooknum); 199 send_unreach(net, skb, ICMPV6_PORT_UNREACH, par->hooknum);
200 break; 200 break;
201 case IP6T_ICMP6_ECHOREPLY: 201 case IP6T_ICMP6_ECHOREPLY:
202 /* Do nothing */ 202 /* Do nothing */
203 break; 203 break;
204 case IP6T_TCP_RESET: 204 case IP6T_TCP_RESET:
205 send_reset(skb); 205 send_reset(net, skb);
206 break; 206 break;
207 default: 207 default:
208 if (net_ratelimit()) 208 if (net_ratelimit())
@@ -213,13 +213,10 @@ reject_tg6(struct sk_buff *skb, const struct net_device *in,
213 return NF_DROP; 213 return NF_DROP;
214} 214}
215 215
216static bool 216static bool reject_tg6_check(const struct xt_tgchk_param *par)
217reject_tg6_check(const char *tablename, const void *entry,
218 const struct xt_target *target, void *targinfo,
219 unsigned int hook_mask)
220{ 217{
221 const struct ip6t_reject_info *rejinfo = targinfo; 218 const struct ip6t_reject_info *rejinfo = par->targinfo;
222 const struct ip6t_entry *e = entry; 219 const struct ip6t_entry *e = par->entryinfo;
223 220
224 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { 221 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
225 printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); 222 printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
@@ -237,7 +234,7 @@ reject_tg6_check(const char *tablename, const void *entry,
237 234
238static struct xt_target reject_tg6_reg __read_mostly = { 235static struct xt_target reject_tg6_reg __read_mostly = {
239 .name = "REJECT", 236 .name = "REJECT",
240 .family = AF_INET6, 237 .family = NFPROTO_IPV6,
241 .target = reject_tg6, 238 .target = reject_tg6,
242 .targetsize = sizeof(struct ip6t_reject_info), 239 .targetsize = sizeof(struct ip6t_reject_info),
243 .table = "filter", 240 .table = "filter",
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 429629fd63b6..3a82f24746b9 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -36,14 +36,11 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
36 return r; 36 return r;
37} 37}
38 38
39static bool 39static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
40ah_mt6(const struct sk_buff *skb, const struct net_device *in,
41 const struct net_device *out, const struct xt_match *match,
42 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
43{ 40{
44 struct ip_auth_hdr _ah; 41 struct ip_auth_hdr _ah;
45 const struct ip_auth_hdr *ah; 42 const struct ip_auth_hdr *ah;
46 const struct ip6t_ah *ahinfo = matchinfo; 43 const struct ip6t_ah *ahinfo = par->matchinfo;
47 unsigned int ptr; 44 unsigned int ptr;
48 unsigned int hdrlen = 0; 45 unsigned int hdrlen = 0;
49 int err; 46 int err;
@@ -51,13 +48,13 @@ ah_mt6(const struct sk_buff *skb, const struct net_device *in,
51 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); 48 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
52 if (err < 0) { 49 if (err < 0) {
53 if (err != -ENOENT) 50 if (err != -ENOENT)
54 *hotdrop = true; 51 *par->hotdrop = true;
55 return false; 52 return false;
56 } 53 }
57 54
58 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); 55 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
59 if (ah == NULL) { 56 if (ah == NULL) {
60 *hotdrop = true; 57 *par->hotdrop = true;
61 return false; 58 return false;
62 } 59 }
63 60
@@ -93,13 +90,9 @@ ah_mt6(const struct sk_buff *skb, const struct net_device *in,
93 !(ahinfo->hdrres && ah->reserved); 90 !(ahinfo->hdrres && ah->reserved);
94} 91}
95 92
96/* Called when user tries to insert an entry of this type. */ 93static bool ah_mt6_check(const struct xt_mtchk_param *par)
97static bool
98ah_mt6_check(const char *tablename, const void *entry,
99 const struct xt_match *match, void *matchinfo,
100 unsigned int hook_mask)
101{ 94{
102 const struct ip6t_ah *ahinfo = matchinfo; 95 const struct ip6t_ah *ahinfo = par->matchinfo;
103 96
104 if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { 97 if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
105 pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags); 98 pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
@@ -110,7 +103,7 @@ ah_mt6_check(const char *tablename, const void *entry,
110 103
111static struct xt_match ah_mt6_reg __read_mostly = { 104static struct xt_match ah_mt6_reg __read_mostly = {
112 .name = "ah", 105 .name = "ah",
113 .family = AF_INET6, 106 .family = NFPROTO_IPV6,
114 .match = ah_mt6, 107 .match = ah_mt6,
115 .matchsize = sizeof(struct ip6t_ah), 108 .matchsize = sizeof(struct ip6t_ah),
116 .checkentry = ah_mt6_check, 109 .checkentry = ah_mt6_check,
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 8f331f12b2ec..db610bacbcce 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -20,18 +20,15 @@ MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); 20MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
21 21
22static bool 22static bool
23eui64_mt6(const struct sk_buff *skb, const struct net_device *in, 23eui64_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
24 const struct net_device *out, const struct xt_match *match,
25 const void *matchinfo, int offset, unsigned int protoff,
26 bool *hotdrop)
27{ 24{
28 unsigned char eui64[8]; 25 unsigned char eui64[8];
29 int i = 0; 26 int i = 0;
30 27
31 if (!(skb_mac_header(skb) >= skb->head && 28 if (!(skb_mac_header(skb) >= skb->head &&
32 skb_mac_header(skb) + ETH_HLEN <= skb->data) && 29 skb_mac_header(skb) + ETH_HLEN <= skb->data) &&
33 offset != 0) { 30 par->fragoff != 0) {
34 *hotdrop = true; 31 *par->hotdrop = true;
35 return false; 32 return false;
36 } 33 }
37 34
@@ -60,7 +57,7 @@ eui64_mt6(const struct sk_buff *skb, const struct net_device *in,
60 57
61static struct xt_match eui64_mt6_reg __read_mostly = { 58static struct xt_match eui64_mt6_reg __read_mostly = {
62 .name = "eui64", 59 .name = "eui64",
63 .family = AF_INET6, 60 .family = NFPROTO_IPV6,
64 .match = eui64_mt6, 61 .match = eui64_mt6,
65 .matchsize = sizeof(int), 62 .matchsize = sizeof(int),
66 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) | 63 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index e2bbc63dba5b..673aa0a5084e 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -35,27 +35,24 @@ id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
35} 35}
36 36
37static bool 37static bool
38frag_mt6(const struct sk_buff *skb, const struct net_device *in, 38frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
39 const struct net_device *out, const struct xt_match *match,
40 const void *matchinfo, int offset, unsigned int protoff,
41 bool *hotdrop)
42{ 39{
43 struct frag_hdr _frag; 40 struct frag_hdr _frag;
44 const struct frag_hdr *fh; 41 const struct frag_hdr *fh;
45 const struct ip6t_frag *fraginfo = matchinfo; 42 const struct ip6t_frag *fraginfo = par->matchinfo;
46 unsigned int ptr; 43 unsigned int ptr;
47 int err; 44 int err;
48 45
49 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); 46 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
50 if (err < 0) { 47 if (err < 0) {
51 if (err != -ENOENT) 48 if (err != -ENOENT)
52 *hotdrop = true; 49 *par->hotdrop = true;
53 return false; 50 return false;
54 } 51 }
55 52
56 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); 53 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
57 if (fh == NULL) { 54 if (fh == NULL) {
58 *hotdrop = true; 55 *par->hotdrop = true;
59 return false; 56 return false;
60 } 57 }
61 58
@@ -110,13 +107,9 @@ frag_mt6(const struct sk_buff *skb, const struct net_device *in,
110 && (ntohs(fh->frag_off) & IP6_MF)); 107 && (ntohs(fh->frag_off) & IP6_MF));
111} 108}
112 109
113/* Called when user tries to insert an entry of this type. */ 110static bool frag_mt6_check(const struct xt_mtchk_param *par)
114static bool
115frag_mt6_check(const char *tablename, const void *ip,
116 const struct xt_match *match, void *matchinfo,
117 unsigned int hook_mask)
118{ 111{
119 const struct ip6t_frag *fraginfo = matchinfo; 112 const struct ip6t_frag *fraginfo = par->matchinfo;
120 113
121 if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { 114 if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
122 pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags); 115 pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
@@ -127,7 +120,7 @@ frag_mt6_check(const char *tablename, const void *ip,
127 120
128static struct xt_match frag_mt6_reg __read_mostly = { 121static struct xt_match frag_mt6_reg __read_mostly = {
129 .name = "frag", 122 .name = "frag",
130 .family = AF_INET6, 123 .family = NFPROTO_IPV6,
131 .match = frag_mt6, 124 .match = frag_mt6,
132 .matchsize = sizeof(struct ip6t_frag), 125 .matchsize = sizeof(struct ip6t_frag),
133 .checkentry = frag_mt6_check, 126 .checkentry = frag_mt6_check,
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 62e39ace0588..cbe8dec9744b 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -42,14 +42,11 @@ MODULE_ALIAS("ip6t_dst");
42 */ 42 */
43 43
44static bool 44static bool
45hbh_mt6(const struct sk_buff *skb, const struct net_device *in, 45hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
46 const struct net_device *out, const struct xt_match *match,
47 const void *matchinfo, int offset, unsigned int protoff,
48 bool *hotdrop)
49{ 46{
50 struct ipv6_opt_hdr _optsh; 47 struct ipv6_opt_hdr _optsh;
51 const struct ipv6_opt_hdr *oh; 48 const struct ipv6_opt_hdr *oh;
52 const struct ip6t_opts *optinfo = matchinfo; 49 const struct ip6t_opts *optinfo = par->matchinfo;
53 unsigned int temp; 50 unsigned int temp;
54 unsigned int ptr; 51 unsigned int ptr;
55 unsigned int hdrlen = 0; 52 unsigned int hdrlen = 0;
@@ -61,16 +58,16 @@ hbh_mt6(const struct sk_buff *skb, const struct net_device *in,
61 unsigned int optlen; 58 unsigned int optlen;
62 int err; 59 int err;
63 60
64 err = ipv6_find_hdr(skb, &ptr, match->data, NULL); 61 err = ipv6_find_hdr(skb, &ptr, par->match->data, NULL);
65 if (err < 0) { 62 if (err < 0) {
66 if (err != -ENOENT) 63 if (err != -ENOENT)
67 *hotdrop = true; 64 *par->hotdrop = true;
68 return false; 65 return false;
69 } 66 }
70 67
71 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); 68 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
72 if (oh == NULL) { 69 if (oh == NULL) {
73 *hotdrop = true; 70 *par->hotdrop = true;
74 return false; 71 return false;
75 } 72 }
76 73
@@ -97,8 +94,6 @@ hbh_mt6(const struct sk_buff *skb, const struct net_device *in,
97 hdrlen -= 2; 94 hdrlen -= 2;
98 if (!(optinfo->flags & IP6T_OPTS_OPTS)) { 95 if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
99 return ret; 96 return ret;
100 } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
101 pr_debug("Not strict - not implemented");
102 } else { 97 } else {
103 pr_debug("Strict "); 98 pr_debug("Strict ");
104 pr_debug("#%d ", optinfo->optsnr); 99 pr_debug("#%d ", optinfo->optsnr);
@@ -165,25 +160,27 @@ hbh_mt6(const struct sk_buff *skb, const struct net_device *in,
165 return false; 160 return false;
166} 161}
167 162
168/* Called when user tries to insert an entry of this type. */ 163static bool hbh_mt6_check(const struct xt_mtchk_param *par)
169static bool
170hbh_mt6_check(const char *tablename, const void *entry,
171 const struct xt_match *match, void *matchinfo,
172 unsigned int hook_mask)
173{ 164{
174 const struct ip6t_opts *optsinfo = matchinfo; 165 const struct ip6t_opts *optsinfo = par->matchinfo;
175 166
176 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { 167 if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
177 pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); 168 pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
178 return false; 169 return false;
179 } 170 }
171
172 if (optsinfo->flags & IP6T_OPTS_NSTRICT) {
173 pr_debug("ip6t_opts: Not strict - not implemented");
174 return false;
175 }
176
180 return true; 177 return true;
181} 178}
182 179
183static struct xt_match hbh_mt6_reg[] __read_mostly = { 180static struct xt_match hbh_mt6_reg[] __read_mostly = {
184 { 181 {
185 .name = "hbh", 182 .name = "hbh",
186 .family = AF_INET6, 183 .family = NFPROTO_IPV6,
187 .match = hbh_mt6, 184 .match = hbh_mt6,
188 .matchsize = sizeof(struct ip6t_opts), 185 .matchsize = sizeof(struct ip6t_opts),
189 .checkentry = hbh_mt6_check, 186 .checkentry = hbh_mt6_check,
@@ -192,7 +189,7 @@ static struct xt_match hbh_mt6_reg[] __read_mostly = {
192 }, 189 },
193 { 190 {
194 .name = "dst", 191 .name = "dst",
195 .family = AF_INET6, 192 .family = NFPROTO_IPV6,
196 .match = hbh_mt6, 193 .match = hbh_mt6,
197 .matchsize = sizeof(struct ip6t_opts), 194 .matchsize = sizeof(struct ip6t_opts),
198 .checkentry = hbh_mt6_check, 195 .checkentry = hbh_mt6_check,
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 345671673845..c964dca1132d 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -19,12 +19,9 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
19MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field match"); 19MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field match");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static bool 22static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
23hl_mt6(const struct sk_buff *skb, const struct net_device *in,
24 const struct net_device *out, const struct xt_match *match,
25 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
26{ 23{
27 const struct ip6t_hl_info *info = matchinfo; 24 const struct ip6t_hl_info *info = par->matchinfo;
28 const struct ipv6hdr *ip6h = ipv6_hdr(skb); 25 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
29 26
30 switch (info->mode) { 27 switch (info->mode) {
@@ -51,7 +48,7 @@ hl_mt6(const struct sk_buff *skb, const struct net_device *in,
51 48
52static struct xt_match hl_mt6_reg __read_mostly = { 49static struct xt_match hl_mt6_reg __read_mostly = {
53 .name = "hl", 50 .name = "hl",
54 .family = AF_INET6, 51 .family = NFPROTO_IPV6,
55 .match = hl_mt6, 52 .match = hl_mt6,
56 .matchsize = sizeof(struct ip6t_hl_info), 53 .matchsize = sizeof(struct ip6t_hl_info),
57 .me = THIS_MODULE, 54 .me = THIS_MODULE,
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 317a8960a757..14e6724d5672 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -27,12 +27,9 @@ MODULE_DESCRIPTION("Xtables: IPv6 header types match");
27MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); 27MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28 28
29static bool 29static bool
30ipv6header_mt6(const struct sk_buff *skb, const struct net_device *in, 30ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
31 const struct net_device *out, const struct xt_match *match,
32 const void *matchinfo, int offset, unsigned int protoff,
33 bool *hotdrop)
34{ 31{
35 const struct ip6t_ipv6header_info *info = matchinfo; 32 const struct ip6t_ipv6header_info *info = par->matchinfo;
36 unsigned int temp; 33 unsigned int temp;
37 int len; 34 int len;
38 u8 nexthdr; 35 u8 nexthdr;
@@ -121,12 +118,9 @@ ipv6header_mt6(const struct sk_buff *skb, const struct net_device *in,
121 } 118 }
122} 119}
123 120
124static bool 121static bool ipv6header_mt6_check(const struct xt_mtchk_param *par)
125ipv6header_mt6_check(const char *tablename, const void *ip,
126 const struct xt_match *match, void *matchinfo,
127 unsigned int hook_mask)
128{ 122{
129 const struct ip6t_ipv6header_info *info = matchinfo; 123 const struct ip6t_ipv6header_info *info = par->matchinfo;
130 124
131 /* invflags is 0 or 0xff in hard mode */ 125 /* invflags is 0 or 0xff in hard mode */
132 if ((!info->modeflag) && info->invflags != 0x00 && 126 if ((!info->modeflag) && info->invflags != 0x00 &&
@@ -138,7 +132,7 @@ ipv6header_mt6_check(const char *tablename, const void *ip,
138 132
139static struct xt_match ipv6header_mt6_reg __read_mostly = { 133static struct xt_match ipv6header_mt6_reg __read_mostly = {
140 .name = "ipv6header", 134 .name = "ipv6header",
141 .family = AF_INET6, 135 .family = NFPROTO_IPV6,
142 .match = ipv6header_mt6, 136 .match = ipv6header_mt6,
143 .matchsize = sizeof(struct ip6t_ipv6header_info), 137 .matchsize = sizeof(struct ip6t_ipv6header_info),
144 .checkentry = ipv6header_mt6_check, 138 .checkentry = ipv6header_mt6_check,
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
index e06678d07ec8..aafe4e66577b 100644
--- a/net/ipv6/netfilter/ip6t_mh.c
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -37,32 +37,29 @@ type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert)
37 return (type >= min && type <= max) ^ invert; 37 return (type >= min && type <= max) ^ invert;
38} 38}
39 39
40static bool 40static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
41mh_mt6(const struct sk_buff *skb, const struct net_device *in,
42 const struct net_device *out, const struct xt_match *match,
43 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
44{ 41{
45 struct ip6_mh _mh; 42 struct ip6_mh _mh;
46 const struct ip6_mh *mh; 43 const struct ip6_mh *mh;
47 const struct ip6t_mh *mhinfo = matchinfo; 44 const struct ip6t_mh *mhinfo = par->matchinfo;
48 45
49 /* Must not be a fragment. */ 46 /* Must not be a fragment. */
50 if (offset) 47 if (par->fragoff != 0)
51 return false; 48 return false;
52 49
53 mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh); 50 mh = skb_header_pointer(skb, par->thoff, sizeof(_mh), &_mh);
54 if (mh == NULL) { 51 if (mh == NULL) {
55 /* We've been asked to examine this packet, and we 52 /* We've been asked to examine this packet, and we
56 can't. Hence, no choice but to drop. */ 53 can't. Hence, no choice but to drop. */
57 duprintf("Dropping evil MH tinygram.\n"); 54 duprintf("Dropping evil MH tinygram.\n");
58 *hotdrop = true; 55 *par->hotdrop = true;
59 return false; 56 return false;
60 } 57 }
61 58
62 if (mh->ip6mh_proto != IPPROTO_NONE) { 59 if (mh->ip6mh_proto != IPPROTO_NONE) {
63 duprintf("Dropping invalid MH Payload Proto: %u\n", 60 duprintf("Dropping invalid MH Payload Proto: %u\n",
64 mh->ip6mh_proto); 61 mh->ip6mh_proto);
65 *hotdrop = true; 62 *par->hotdrop = true;
66 return false; 63 return false;
67 } 64 }
68 65
@@ -70,13 +67,9 @@ mh_mt6(const struct sk_buff *skb, const struct net_device *in,
70 !!(mhinfo->invflags & IP6T_MH_INV_TYPE)); 67 !!(mhinfo->invflags & IP6T_MH_INV_TYPE));
71} 68}
72 69
73/* Called when user tries to insert an entry of this type. */ 70static bool mh_mt6_check(const struct xt_mtchk_param *par)
74static bool
75mh_mt6_check(const char *tablename, const void *entry,
76 const struct xt_match *match, void *matchinfo,
77 unsigned int hook_mask)
78{ 71{
79 const struct ip6t_mh *mhinfo = matchinfo; 72 const struct ip6t_mh *mhinfo = par->matchinfo;
80 73
81 /* Must specify no unknown invflags */ 74 /* Must specify no unknown invflags */
82 return !(mhinfo->invflags & ~IP6T_MH_INV_MASK); 75 return !(mhinfo->invflags & ~IP6T_MH_INV_MASK);
@@ -84,7 +77,7 @@ mh_mt6_check(const char *tablename, const void *entry,
84 77
85static struct xt_match mh_mt6_reg __read_mostly = { 78static struct xt_match mh_mt6_reg __read_mostly = {
86 .name = "mh", 79 .name = "mh",
87 .family = AF_INET6, 80 .family = NFPROTO_IPV6,
88 .checkentry = mh_mt6_check, 81 .checkentry = mh_mt6_check,
89 .match = mh_mt6, 82 .match = mh_mt6,
90 .matchsize = sizeof(struct ip6t_mh), 83 .matchsize = sizeof(struct ip6t_mh),
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 81aaf7aaaabf..356b8d6f6baa 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -36,14 +36,11 @@ segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
36 return r; 36 return r;
37} 37}
38 38
39static bool 39static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
40rt_mt6(const struct sk_buff *skb, const struct net_device *in,
41 const struct net_device *out, const struct xt_match *match,
42 const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
43{ 40{
44 struct ipv6_rt_hdr _route; 41 struct ipv6_rt_hdr _route;
45 const struct ipv6_rt_hdr *rh; 42 const struct ipv6_rt_hdr *rh;
46 const struct ip6t_rt *rtinfo = matchinfo; 43 const struct ip6t_rt *rtinfo = par->matchinfo;
47 unsigned int temp; 44 unsigned int temp;
48 unsigned int ptr; 45 unsigned int ptr;
49 unsigned int hdrlen = 0; 46 unsigned int hdrlen = 0;
@@ -55,13 +52,13 @@ rt_mt6(const struct sk_buff *skb, const struct net_device *in,
55 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); 52 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
56 if (err < 0) { 53 if (err < 0) {
57 if (err != -ENOENT) 54 if (err != -ENOENT)
58 *hotdrop = true; 55 *par->hotdrop = true;
59 return false; 56 return false;
60 } 57 }
61 58
62 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); 59 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
63 if (rh == NULL) { 60 if (rh == NULL) {
64 *hotdrop = true; 61 *par->hotdrop = true;
65 return false; 62 return false;
66 } 63 }
67 64
@@ -189,13 +186,9 @@ rt_mt6(const struct sk_buff *skb, const struct net_device *in,
189 return false; 186 return false;
190} 187}
191 188
192/* Called when user tries to insert an entry of this type. */ 189static bool rt_mt6_check(const struct xt_mtchk_param *par)
193static bool
194rt_mt6_check(const char *tablename, const void *entry,
195 const struct xt_match *match, void *matchinfo,
196 unsigned int hook_mask)
197{ 190{
198 const struct ip6t_rt *rtinfo = matchinfo; 191 const struct ip6t_rt *rtinfo = par->matchinfo;
199 192
200 if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { 193 if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
201 pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags); 194 pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
@@ -214,7 +207,7 @@ rt_mt6_check(const char *tablename, const void *entry,
214 207
215static struct xt_match rt_mt6_reg __read_mostly = { 208static struct xt_match rt_mt6_reg __read_mostly = {
216 .name = "rt", 209 .name = "rt",
217 .family = AF_INET6, 210 .family = NFPROTO_IPV6,
218 .match = rt_mt6, 211 .match = rt_mt6,
219 .matchsize = sizeof(struct ip6t_rt), 212 .matchsize = sizeof(struct ip6t_rt),
220 .checkentry = rt_mt6_check, 213 .checkentry = rt_mt6_check,
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 55a2c290bad4..b110a8a85a14 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -68,7 +68,7 @@ ip6t_local_in_hook(unsigned int hook,
68 int (*okfn)(struct sk_buff *)) 68 int (*okfn)(struct sk_buff *))
69{ 69{
70 return ip6t_do_table(skb, hook, in, out, 70 return ip6t_do_table(skb, hook, in, out,
71 nf_local_in_net(in, out)->ipv6.ip6table_filter); 71 dev_net(in)->ipv6.ip6table_filter);
72} 72}
73 73
74static unsigned int 74static unsigned int
@@ -79,7 +79,7 @@ ip6t_forward_hook(unsigned int hook,
79 int (*okfn)(struct sk_buff *)) 79 int (*okfn)(struct sk_buff *))
80{ 80{
81 return ip6t_do_table(skb, hook, in, out, 81 return ip6t_do_table(skb, hook, in, out,
82 nf_forward_net(in, out)->ipv6.ip6table_filter); 82 dev_net(in)->ipv6.ip6table_filter);
83} 83}
84 84
85static unsigned int 85static unsigned int
@@ -100,7 +100,7 @@ ip6t_local_out_hook(unsigned int hook,
100#endif 100#endif
101 101
102 return ip6t_do_table(skb, hook, in, out, 102 return ip6t_do_table(skb, hook, in, out,
103 nf_local_out_net(in, out)->ipv6.ip6table_filter); 103 dev_net(out)->ipv6.ip6table_filter);
104} 104}
105 105
106static struct nf_hook_ops ip6t_ops[] __read_mostly = { 106static struct nf_hook_ops ip6t_ops[] __read_mostly = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index f405cea21a8b..d0b31b259d4d 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -67,17 +67,29 @@ static struct xt_table packet_mangler = {
67 67
68/* The work comes in here from netfilter.c. */ 68/* The work comes in here from netfilter.c. */
69static unsigned int 69static unsigned int
70ip6t_route_hook(unsigned int hook, 70ip6t_in_hook(unsigned int hook,
71 struct sk_buff *skb, 71 struct sk_buff *skb,
72 const struct net_device *in, 72 const struct net_device *in,
73 const struct net_device *out, 73 const struct net_device *out,
74 int (*okfn)(struct sk_buff *)) 74 int (*okfn)(struct sk_buff *))
75{ 75{
76 return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_mangle); 76 return ip6t_do_table(skb, hook, in, out,
77 dev_net(in)->ipv6.ip6table_mangle);
77} 78}
78 79
79static unsigned int 80static unsigned int
80ip6t_local_hook(unsigned int hook, 81ip6t_post_routing_hook(unsigned int hook,
82 struct sk_buff *skb,
83 const struct net_device *in,
84 const struct net_device *out,
85 int (*okfn)(struct sk_buff *))
86{
87 return ip6t_do_table(skb, hook, in, out,
88 dev_net(out)->ipv6.ip6table_mangle);
89}
90
91static unsigned int
92ip6t_local_out_hook(unsigned int hook,
81 struct sk_buff *skb, 93 struct sk_buff *skb,
82 const struct net_device *in, 94 const struct net_device *in,
83 const struct net_device *out, 95 const struct net_device *out,
@@ -108,7 +120,8 @@ ip6t_local_hook(unsigned int hook,
108 /* flowlabel and prio (includes version, which shouldn't change either */ 120 /* flowlabel and prio (includes version, which shouldn't change either */
109 flowlabel = *((u_int32_t *)ipv6_hdr(skb)); 121 flowlabel = *((u_int32_t *)ipv6_hdr(skb));
110 122
111 ret = ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_mangle); 123 ret = ip6t_do_table(skb, hook, in, out,
124 dev_net(out)->ipv6.ip6table_mangle);
112 125
113 if (ret != NF_DROP && ret != NF_STOLEN 126 if (ret != NF_DROP && ret != NF_STOLEN
114 && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) 127 && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr))
@@ -122,35 +135,35 @@ ip6t_local_hook(unsigned int hook,
122 135
123static struct nf_hook_ops ip6t_ops[] __read_mostly = { 136static struct nf_hook_ops ip6t_ops[] __read_mostly = {
124 { 137 {
125 .hook = ip6t_route_hook, 138 .hook = ip6t_in_hook,
126 .owner = THIS_MODULE, 139 .owner = THIS_MODULE,
127 .pf = PF_INET6, 140 .pf = PF_INET6,
128 .hooknum = NF_INET_PRE_ROUTING, 141 .hooknum = NF_INET_PRE_ROUTING,
129 .priority = NF_IP6_PRI_MANGLE, 142 .priority = NF_IP6_PRI_MANGLE,
130 }, 143 },
131 { 144 {
132 .hook = ip6t_route_hook, 145 .hook = ip6t_in_hook,
133 .owner = THIS_MODULE, 146 .owner = THIS_MODULE,
134 .pf = PF_INET6, 147 .pf = PF_INET6,
135 .hooknum = NF_INET_LOCAL_IN, 148 .hooknum = NF_INET_LOCAL_IN,
136 .priority = NF_IP6_PRI_MANGLE, 149 .priority = NF_IP6_PRI_MANGLE,
137 }, 150 },
138 { 151 {
139 .hook = ip6t_route_hook, 152 .hook = ip6t_in_hook,
140 .owner = THIS_MODULE, 153 .owner = THIS_MODULE,
141 .pf = PF_INET6, 154 .pf = PF_INET6,
142 .hooknum = NF_INET_FORWARD, 155 .hooknum = NF_INET_FORWARD,
143 .priority = NF_IP6_PRI_MANGLE, 156 .priority = NF_IP6_PRI_MANGLE,
144 }, 157 },
145 { 158 {
146 .hook = ip6t_local_hook, 159 .hook = ip6t_local_out_hook,
147 .owner = THIS_MODULE, 160 .owner = THIS_MODULE,
148 .pf = PF_INET6, 161 .pf = PF_INET6,
149 .hooknum = NF_INET_LOCAL_OUT, 162 .hooknum = NF_INET_LOCAL_OUT,
150 .priority = NF_IP6_PRI_MANGLE, 163 .priority = NF_IP6_PRI_MANGLE,
151 }, 164 },
152 { 165 {
153 .hook = ip6t_route_hook, 166 .hook = ip6t_post_routing_hook,
154 .owner = THIS_MODULE, 167 .owner = THIS_MODULE,
155 .pf = PF_INET6, 168 .pf = PF_INET6,
156 .hooknum = NF_INET_POST_ROUTING, 169 .hooknum = NF_INET_POST_ROUTING,
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 92b91077ac29..109fab6f831a 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -45,25 +45,37 @@ static struct xt_table packet_raw = {
45 45
46/* The work comes in here from netfilter.c. */ 46/* The work comes in here from netfilter.c. */
47static unsigned int 47static unsigned int
48ip6t_hook(unsigned int hook, 48ip6t_pre_routing_hook(unsigned int hook,
49 struct sk_buff *skb, 49 struct sk_buff *skb,
50 const struct net_device *in, 50 const struct net_device *in,
51 const struct net_device *out, 51 const struct net_device *out,
52 int (*okfn)(struct sk_buff *)) 52 int (*okfn)(struct sk_buff *))
53{ 53{
54 return ip6t_do_table(skb, hook, in, out, init_net.ipv6.ip6table_raw); 54 return ip6t_do_table(skb, hook, in, out,
55 dev_net(in)->ipv6.ip6table_raw);
56}
57
58static unsigned int
59ip6t_local_out_hook(unsigned int hook,
60 struct sk_buff *skb,
61 const struct net_device *in,
62 const struct net_device *out,
63 int (*okfn)(struct sk_buff *))
64{
65 return ip6t_do_table(skb, hook, in, out,
66 dev_net(out)->ipv6.ip6table_raw);
55} 67}
56 68
57static struct nf_hook_ops ip6t_ops[] __read_mostly = { 69static struct nf_hook_ops ip6t_ops[] __read_mostly = {
58 { 70 {
59 .hook = ip6t_hook, 71 .hook = ip6t_pre_routing_hook,
60 .pf = PF_INET6, 72 .pf = PF_INET6,
61 .hooknum = NF_INET_PRE_ROUTING, 73 .hooknum = NF_INET_PRE_ROUTING,
62 .priority = NF_IP6_PRI_FIRST, 74 .priority = NF_IP6_PRI_FIRST,
63 .owner = THIS_MODULE, 75 .owner = THIS_MODULE,
64 }, 76 },
65 { 77 {
66 .hook = ip6t_hook, 78 .hook = ip6t_local_out_hook,
67 .pf = PF_INET6, 79 .pf = PF_INET6,
68 .hooknum = NF_INET_LOCAL_OUT, 80 .hooknum = NF_INET_LOCAL_OUT,
69 .priority = NF_IP6_PRI_FIRST, 81 .priority = NF_IP6_PRI_FIRST,
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index 6e7131036bc6..20bc52f13e43 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -72,7 +72,7 @@ ip6t_local_in_hook(unsigned int hook,
72 int (*okfn)(struct sk_buff *)) 72 int (*okfn)(struct sk_buff *))
73{ 73{
74 return ip6t_do_table(skb, hook, in, out, 74 return ip6t_do_table(skb, hook, in, out,
75 nf_local_in_net(in, out)->ipv6.ip6table_security); 75 dev_net(in)->ipv6.ip6table_security);
76} 76}
77 77
78static unsigned int 78static unsigned int
@@ -83,7 +83,7 @@ ip6t_forward_hook(unsigned int hook,
83 int (*okfn)(struct sk_buff *)) 83 int (*okfn)(struct sk_buff *))
84{ 84{
85 return ip6t_do_table(skb, hook, in, out, 85 return ip6t_do_table(skb, hook, in, out,
86 nf_forward_net(in, out)->ipv6.ip6table_security); 86 dev_net(in)->ipv6.ip6table_security);
87} 87}
88 88
89static unsigned int 89static unsigned int
@@ -95,7 +95,7 @@ ip6t_local_out_hook(unsigned int hook,
95{ 95{
96 /* TBD: handle short packets via raw socket */ 96 /* TBD: handle short packets via raw socket */
97 return ip6t_do_table(skb, hook, in, out, 97 return ip6t_do_table(skb, hook, in, out,
98 nf_local_out_net(in, out)->ipv6.ip6table_security); 98 dev_net(out)->ipv6.ip6table_security);
99} 99}
100 100
101static struct nf_hook_ops ip6t_ops[] __read_mostly = { 101static struct nf_hook_ops ip6t_ops[] __read_mostly = {
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 85050c072abd..e91db16611d9 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -211,11 +211,10 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
211 return NF_STOLEN; 211 return NF_STOLEN;
212} 212}
213 213
214static unsigned int ipv6_conntrack_in(unsigned int hooknum, 214static unsigned int __ipv6_conntrack_in(struct net *net,
215 struct sk_buff *skb, 215 unsigned int hooknum,
216 const struct net_device *in, 216 struct sk_buff *skb,
217 const struct net_device *out, 217 int (*okfn)(struct sk_buff *))
218 int (*okfn)(struct sk_buff *))
219{ 218{
220 struct sk_buff *reasm = skb->nfct_reasm; 219 struct sk_buff *reasm = skb->nfct_reasm;
221 220
@@ -225,7 +224,7 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum,
225 if (!reasm->nfct) { 224 if (!reasm->nfct) {
226 unsigned int ret; 225 unsigned int ret;
227 226
228 ret = nf_conntrack_in(PF_INET6, hooknum, reasm); 227 ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm);
229 if (ret != NF_ACCEPT) 228 if (ret != NF_ACCEPT)
230 return ret; 229 return ret;
231 } 230 }
@@ -235,7 +234,16 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum,
235 return NF_ACCEPT; 234 return NF_ACCEPT;
236 } 235 }
237 236
238 return nf_conntrack_in(PF_INET6, hooknum, skb); 237 return nf_conntrack_in(net, PF_INET6, hooknum, skb);
238}
239
240static unsigned int ipv6_conntrack_in(unsigned int hooknum,
241 struct sk_buff *skb,
242 const struct net_device *in,
243 const struct net_device *out,
244 int (*okfn)(struct sk_buff *))
245{
246 return __ipv6_conntrack_in(dev_net(in), hooknum, skb, okfn);
239} 247}
240 248
241static unsigned int ipv6_conntrack_local(unsigned int hooknum, 249static unsigned int ipv6_conntrack_local(unsigned int hooknum,
@@ -250,7 +258,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
250 printk("ipv6_conntrack_local: packet too short\n"); 258 printk("ipv6_conntrack_local: packet too short\n");
251 return NF_ACCEPT; 259 return NF_ACCEPT;
252 } 260 }
253 return ipv6_conntrack_in(hooknum, skb, in, out, okfn); 261 return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn);
254} 262}
255 263
256static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { 264static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 14d47d833545..05726177903f 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -81,7 +81,7 @@ static int icmpv6_packet(struct nf_conn *ct,
81 const struct sk_buff *skb, 81 const struct sk_buff *skb,
82 unsigned int dataoff, 82 unsigned int dataoff,
83 enum ip_conntrack_info ctinfo, 83 enum ip_conntrack_info ctinfo,
84 int pf, 84 u_int8_t pf,
85 unsigned int hooknum) 85 unsigned int hooknum)
86{ 86{
87 /* Try to delete connection immediately after all replies: 87 /* Try to delete connection immediately after all replies:
@@ -93,7 +93,7 @@ static int icmpv6_packet(struct nf_conn *ct,
93 nf_ct_kill_acct(ct, ctinfo, skb); 93 nf_ct_kill_acct(ct, ctinfo, skb);
94 } else { 94 } else {
95 atomic_inc(&ct->proto.icmp.count); 95 atomic_inc(&ct->proto.icmp.count);
96 nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); 96 nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
97 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); 97 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout);
98 } 98 }
99 99
@@ -122,7 +122,8 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
122} 122}
123 123
124static int 124static int
125icmpv6_error_message(struct sk_buff *skb, 125icmpv6_error_message(struct net *net,
126 struct sk_buff *skb,
126 unsigned int icmp6off, 127 unsigned int icmp6off,
127 enum ip_conntrack_info *ctinfo, 128 enum ip_conntrack_info *ctinfo,
128 unsigned int hooknum) 129 unsigned int hooknum)
@@ -156,7 +157,7 @@ icmpv6_error_message(struct sk_buff *skb,
156 157
157 *ctinfo = IP_CT_RELATED; 158 *ctinfo = IP_CT_RELATED;
158 159
159 h = nf_conntrack_find_get(&intuple); 160 h = nf_conntrack_find_get(net, &intuple);
160 if (!h) { 161 if (!h) {
161 pr_debug("icmpv6_error: no match\n"); 162 pr_debug("icmpv6_error: no match\n");
162 return -NF_ACCEPT; 163 return -NF_ACCEPT;
@@ -172,21 +173,21 @@ icmpv6_error_message(struct sk_buff *skb,
172} 173}
173 174
174static int 175static int
175icmpv6_error(struct sk_buff *skb, unsigned int dataoff, 176icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
176 enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum) 177 enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
177{ 178{
178 const struct icmp6hdr *icmp6h; 179 const struct icmp6hdr *icmp6h;
179 struct icmp6hdr _ih; 180 struct icmp6hdr _ih;
180 181
181 icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); 182 icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
182 if (icmp6h == NULL) { 183 if (icmp6h == NULL) {
183 if (LOG_INVALID(IPPROTO_ICMPV6)) 184 if (LOG_INVALID(net, IPPROTO_ICMPV6))
184 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, 185 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
185 "nf_ct_icmpv6: short packet "); 186 "nf_ct_icmpv6: short packet ");
186 return -NF_ACCEPT; 187 return -NF_ACCEPT;
187 } 188 }
188 189
189 if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING && 190 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
190 nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { 191 nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
191 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, 192 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
192 "nf_ct_icmpv6: ICMPv6 checksum failed\n"); 193 "nf_ct_icmpv6: ICMPv6 checksum failed\n");
@@ -197,7 +198,7 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
197 if (icmp6h->icmp6_type >= 128) 198 if (icmp6h->icmp6_type >= 128)
198 return NF_ACCEPT; 199 return NF_ACCEPT;
199 200
200 return icmpv6_error_message(skb, dataoff, ctinfo, hooknum); 201 return icmpv6_error_message(net, skb, dataoff, ctinfo, hooknum);
201} 202}
202 203
203#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 204#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 52d06dd4b817..9967ac7a01a8 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -27,7 +27,6 @@
27#include <linux/ipv6.h> 27#include <linux/ipv6.h>
28#include <linux/icmpv6.h> 28#include <linux/icmpv6.h>
29#include <linux/random.h> 29#include <linux/random.h>
30#include <linux/jhash.h>
31 30
32#include <net/sock.h> 31#include <net/sock.h>
33#include <net/snmp.h> 32#include <net/snmp.h>
@@ -103,39 +102,12 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
103}; 102};
104#endif 103#endif
105 104
106static unsigned int ip6qhashfn(__be32 id, const struct in6_addr *saddr,
107 const struct in6_addr *daddr)
108{
109 u32 a, b, c;
110
111 a = (__force u32)saddr->s6_addr32[0];
112 b = (__force u32)saddr->s6_addr32[1];
113 c = (__force u32)saddr->s6_addr32[2];
114
115 a += JHASH_GOLDEN_RATIO;
116 b += JHASH_GOLDEN_RATIO;
117 c += nf_frags.rnd;
118 __jhash_mix(a, b, c);
119
120 a += (__force u32)saddr->s6_addr32[3];
121 b += (__force u32)daddr->s6_addr32[0];
122 c += (__force u32)daddr->s6_addr32[1];
123 __jhash_mix(a, b, c);
124
125 a += (__force u32)daddr->s6_addr32[2];
126 b += (__force u32)daddr->s6_addr32[3];
127 c += (__force u32)id;
128 __jhash_mix(a, b, c);
129
130 return c & (INETFRAGS_HASHSZ - 1);
131}
132
133static unsigned int nf_hashfn(struct inet_frag_queue *q) 105static unsigned int nf_hashfn(struct inet_frag_queue *q)
134{ 106{
135 const struct nf_ct_frag6_queue *nq; 107 const struct nf_ct_frag6_queue *nq;
136 108
137 nq = container_of(q, struct nf_ct_frag6_queue, q); 109 nq = container_of(q, struct nf_ct_frag6_queue, q);
138 return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr); 110 return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd);
139} 111}
140 112
141static void nf_skb_free(struct sk_buff *skb) 113static void nf_skb_free(struct sk_buff *skb)
@@ -209,7 +181,7 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
209 arg.dst = dst; 181 arg.dst = dst;
210 182
211 read_lock_bh(&nf_frags.lock); 183 read_lock_bh(&nf_frags.lock);
212 hash = ip6qhashfn(id, src, dst); 184 hash = inet6_hash_frag(id, src, dst, nf_frags.rnd);
213 185
214 q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); 186 q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash);
215 local_bh_enable(); 187 local_bh_enable();
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 0179b66864f1..07f0b76e7427 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -29,8 +29,6 @@
29#include <net/transp_v6.h> 29#include <net/transp_v6.h>
30#include <net/ipv6.h> 30#include <net/ipv6.h>
31 31
32static struct proc_dir_entry *proc_net_devsnmp6;
33
34static int sockstat6_seq_show(struct seq_file *seq, void *v) 32static int sockstat6_seq_show(struct seq_file *seq, void *v)
35{ 33{
36 struct net *net = seq->private; 34 struct net *net = seq->private;
@@ -48,6 +46,19 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
48 return 0; 46 return 0;
49} 47}
50 48
49static int sockstat6_seq_open(struct inode *inode, struct file *file)
50{
51 return single_open_net(inode, file, sockstat6_seq_show);
52}
53
54static const struct file_operations sockstat6_seq_fops = {
55 .owner = THIS_MODULE,
56 .open = sockstat6_seq_open,
57 .read = seq_read,
58 .llseek = seq_lseek,
59 .release = single_release_net,
60};
61
51static struct snmp_mib snmp6_ipstats_list[] = { 62static struct snmp_mib snmp6_ipstats_list[] = {
52/* ipv6 mib according to RFC 2465 */ 63/* ipv6 mib according to RFC 2465 */
53 SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES), 64 SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
@@ -164,44 +175,52 @@ snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist)
164 175
165static int snmp6_seq_show(struct seq_file *seq, void *v) 176static int snmp6_seq_show(struct seq_file *seq, void *v)
166{ 177{
167 struct inet6_dev *idev = (struct inet6_dev *)seq->private; 178 struct net *net = (struct net *)seq->private;
168 179
169 if (idev) { 180 snmp6_seq_show_item(seq, (void **)net->mib.ipv6_statistics,
170 seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); 181 snmp6_ipstats_list);
171 snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); 182 snmp6_seq_show_item(seq, (void **)net->mib.icmpv6_statistics,
172 snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); 183 snmp6_icmp6_list);
173 snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg); 184 snmp6_seq_show_icmpv6msg(seq, (void **)net->mib.icmpv6msg_statistics);
174 } else { 185 snmp6_seq_show_item(seq, (void **)net->mib.udp_stats_in6,
175 snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); 186 snmp6_udp6_list);
176 snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); 187 snmp6_seq_show_item(seq, (void **)net->mib.udplite_stats_in6,
177 snmp6_seq_show_icmpv6msg(seq, (void **)icmpv6msg_statistics); 188 snmp6_udplite6_list);
178 snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
179 snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list);
180 }
181 return 0; 189 return 0;
182} 190}
183 191
184static int sockstat6_seq_open(struct inode *inode, struct file *file) 192static int snmp6_seq_open(struct inode *inode, struct file *file)
185{ 193{
186 return single_open_net(inode, file, sockstat6_seq_show); 194 return single_open_net(inode, file, snmp6_seq_show);
187} 195}
188 196
189static const struct file_operations sockstat6_seq_fops = { 197static const struct file_operations snmp6_seq_fops = {
190 .owner = THIS_MODULE, 198 .owner = THIS_MODULE,
191 .open = sockstat6_seq_open, 199 .open = snmp6_seq_open,
192 .read = seq_read, 200 .read = seq_read,
193 .llseek = seq_lseek, 201 .llseek = seq_lseek,
194 .release = single_release_net, 202 .release = single_release_net,
195}; 203};
196 204
197static int snmp6_seq_open(struct inode *inode, struct file *file) 205static int snmp6_dev_seq_show(struct seq_file *seq, void *v)
198{ 206{
199 return single_open(file, snmp6_seq_show, PDE(inode)->data); 207 struct inet6_dev *idev = (struct inet6_dev *)seq->private;
208
209 seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
210 snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list);
211 snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list);
212 snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg);
213 return 0;
200} 214}
201 215
202static const struct file_operations snmp6_seq_fops = { 216static int snmp6_dev_seq_open(struct inode *inode, struct file *file)
217{
218 return single_open(file, snmp6_dev_seq_show, PDE(inode)->data);
219}
220
221static const struct file_operations snmp6_dev_seq_fops = {
203 .owner = THIS_MODULE, 222 .owner = THIS_MODULE,
204 .open = snmp6_seq_open, 223 .open = snmp6_dev_seq_open,
205 .read = seq_read, 224 .read = seq_read,
206 .llseek = seq_lseek, 225 .llseek = seq_lseek,
207 .release = single_release, 226 .release = single_release,
@@ -210,18 +229,18 @@ static const struct file_operations snmp6_seq_fops = {
210int snmp6_register_dev(struct inet6_dev *idev) 229int snmp6_register_dev(struct inet6_dev *idev)
211{ 230{
212 struct proc_dir_entry *p; 231 struct proc_dir_entry *p;
232 struct net *net;
213 233
214 if (!idev || !idev->dev) 234 if (!idev || !idev->dev)
215 return -EINVAL; 235 return -EINVAL;
216 236
217 if (!net_eq(dev_net(idev->dev), &init_net)) 237 net = dev_net(idev->dev);
218 return 0; 238 if (!net->mib.proc_net_devsnmp6)
219
220 if (!proc_net_devsnmp6)
221 return -ENOENT; 239 return -ENOENT;
222 240
223 p = proc_create_data(idev->dev->name, S_IRUGO, 241 p = proc_create_data(idev->dev->name, S_IRUGO,
224 proc_net_devsnmp6, &snmp6_seq_fops, idev); 242 net->mib.proc_net_devsnmp6,
243 &snmp6_dev_seq_fops, idev);
225 if (!p) 244 if (!p)
226 return -ENOMEM; 245 return -ENOMEM;
227 246
@@ -231,12 +250,13 @@ int snmp6_register_dev(struct inet6_dev *idev)
231 250
232int snmp6_unregister_dev(struct inet6_dev *idev) 251int snmp6_unregister_dev(struct inet6_dev *idev)
233{ 252{
234 if (!proc_net_devsnmp6) 253 struct net *net = dev_net(idev->dev);
254 if (!net->mib.proc_net_devsnmp6)
235 return -ENOENT; 255 return -ENOENT;
236 if (!idev || !idev->stats.proc_dir_entry) 256 if (!idev || !idev->stats.proc_dir_entry)
237 return -EINVAL; 257 return -EINVAL;
238 remove_proc_entry(idev->stats.proc_dir_entry->name, 258 remove_proc_entry(idev->stats.proc_dir_entry->name,
239 proc_net_devsnmp6); 259 net->mib.proc_net_devsnmp6);
240 idev->stats.proc_dir_entry = NULL; 260 idev->stats.proc_dir_entry = NULL;
241 return 0; 261 return 0;
242} 262}
@@ -246,12 +266,27 @@ static int ipv6_proc_init_net(struct net *net)
246 if (!proc_net_fops_create(net, "sockstat6", S_IRUGO, 266 if (!proc_net_fops_create(net, "sockstat6", S_IRUGO,
247 &sockstat6_seq_fops)) 267 &sockstat6_seq_fops))
248 return -ENOMEM; 268 return -ENOMEM;
269
270 if (!proc_net_fops_create(net, "snmp6", S_IRUGO, &snmp6_seq_fops))
271 goto proc_snmp6_fail;
272
273 net->mib.proc_net_devsnmp6 = proc_mkdir("dev_snmp6", net->proc_net);
274 if (!net->mib.proc_net_devsnmp6)
275 goto proc_dev_snmp6_fail;
249 return 0; 276 return 0;
277
278proc_snmp6_fail:
279 proc_net_remove(net, "sockstat6");
280proc_dev_snmp6_fail:
281 proc_net_remove(net, "dev_snmp6");
282 return -ENOMEM;
250} 283}
251 284
252static void ipv6_proc_exit_net(struct net *net) 285static void ipv6_proc_exit_net(struct net *net)
253{ 286{
254 proc_net_remove(net, "sockstat6"); 287 proc_net_remove(net, "sockstat6");
288 proc_net_remove(net, "dev_snmp6");
289 proc_net_remove(net, "snmp6");
255} 290}
256 291
257static struct pernet_operations ipv6_proc_ops = { 292static struct pernet_operations ipv6_proc_ops = {
@@ -261,33 +296,11 @@ static struct pernet_operations ipv6_proc_ops = {
261 296
262int __init ipv6_misc_proc_init(void) 297int __init ipv6_misc_proc_init(void)
263{ 298{
264 int rc = 0; 299 return register_pernet_subsys(&ipv6_proc_ops);
265
266 if (register_pernet_subsys(&ipv6_proc_ops))
267 goto proc_net_fail;
268
269 if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops))
270 goto proc_snmp6_fail;
271
272 proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net);
273 if (!proc_net_devsnmp6)
274 goto proc_dev_snmp6_fail;
275out:
276 return rc;
277
278proc_dev_snmp6_fail:
279 proc_net_remove(&init_net, "snmp6");
280proc_snmp6_fail:
281 unregister_pernet_subsys(&ipv6_proc_ops);
282proc_net_fail:
283 rc = -ENOMEM;
284 goto out;
285} 300}
286 301
287void ipv6_misc_proc_exit(void) 302void ipv6_misc_proc_exit(void)
288{ 303{
289 proc_net_remove(&init_net, "dev_snmp6");
290 proc_net_remove(&init_net, "snmp6");
291 unregister_pernet_subsys(&ipv6_proc_ops); 304 unregister_pernet_subsys(&ipv6_proc_ops);
292} 305}
293 306
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index e53e493606c5..2ba04d41dc25 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
638 if (err) 638 if (err)
639 goto error_fault; 639 goto error_fault;
640 640
641 IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); 641 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
642 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, 642 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
643 dst_output); 643 dst_output);
644 if (err > 0) 644 if (err > 0)
@@ -652,7 +652,7 @@ error_fault:
652 err = -EFAULT; 652 err = -EFAULT;
653 kfree_skb(skb); 653 kfree_skb(skb);
654error: 654error:
655 IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 655 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
656 return err; 656 return err;
657} 657}
658 658
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 89184b576e23..af12de071f4c 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -99,8 +99,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
99 * callers should be careful not to use the hash value outside the ipfrag_lock 99 * callers should be careful not to use the hash value outside the ipfrag_lock
100 * as doing so could race with ipfrag_hash_rnd being recalculated. 100 * as doing so could race with ipfrag_hash_rnd being recalculated.
101 */ 101 */
102static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, 102unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
103 struct in6_addr *daddr) 103 const struct in6_addr *daddr, u32 rnd)
104{ 104{
105 u32 a, b, c; 105 u32 a, b, c;
106 106
@@ -110,7 +110,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
110 110
111 a += JHASH_GOLDEN_RATIO; 111 a += JHASH_GOLDEN_RATIO;
112 b += JHASH_GOLDEN_RATIO; 112 b += JHASH_GOLDEN_RATIO;
113 c += ip6_frags.rnd; 113 c += rnd;
114 __jhash_mix(a, b, c); 114 __jhash_mix(a, b, c);
115 115
116 a += (__force u32)saddr->s6_addr32[3]; 116 a += (__force u32)saddr->s6_addr32[3];
@@ -125,13 +125,14 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
125 125
126 return c & (INETFRAGS_HASHSZ - 1); 126 return c & (INETFRAGS_HASHSZ - 1);
127} 127}
128EXPORT_SYMBOL_GPL(inet6_hash_frag);
128 129
129static unsigned int ip6_hashfn(struct inet_frag_queue *q) 130static unsigned int ip6_hashfn(struct inet_frag_queue *q)
130{ 131{
131 struct frag_queue *fq; 132 struct frag_queue *fq;
132 133
133 fq = container_of(q, struct frag_queue, q); 134 fq = container_of(q, struct frag_queue, q);
134 return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr); 135 return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr, ip6_frags.rnd);
135} 136}
136 137
137int ip6_frag_match(struct inet_frag_queue *q, void *a) 138int ip6_frag_match(struct inet_frag_queue *q, void *a)
@@ -188,7 +189,7 @@ static void ip6_evictor(struct net *net, struct inet6_dev *idev)
188 189
189 evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags); 190 evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags);
190 if (evicted) 191 if (evicted)
191 IP6_ADD_STATS_BH(idev, IPSTATS_MIB_REASMFAILS, evicted); 192 IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS, evicted);
192} 193}
193 194
194static void ip6_frag_expire(unsigned long data) 195static void ip6_frag_expire(unsigned long data)
@@ -212,8 +213,8 @@ static void ip6_frag_expire(unsigned long data)
212 goto out; 213 goto out;
213 214
214 rcu_read_lock(); 215 rcu_read_lock();
215 IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); 216 IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
216 IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); 217 IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
217 rcu_read_unlock(); 218 rcu_read_unlock();
218 219
219 /* Don't send error if the first segment did not arrive. */ 220 /* Don't send error if the first segment did not arrive. */
@@ -247,7 +248,7 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst,
247 arg.dst = dst; 248 arg.dst = dst;
248 249
249 read_lock(&ip6_frags.lock); 250 read_lock(&ip6_frags.lock);
250 hash = ip6qhashfn(id, src, dst); 251 hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);
251 252
252 q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); 253 q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
253 if (q == NULL) 254 if (q == NULL)
@@ -256,7 +257,7 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst,
256 return container_of(q, struct frag_queue, q); 257 return container_of(q, struct frag_queue, q);
257 258
258oom: 259oom:
259 IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); 260 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS);
260 return NULL; 261 return NULL;
261} 262}
262 263
@@ -266,6 +267,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
266 struct sk_buff *prev, *next; 267 struct sk_buff *prev, *next;
267 struct net_device *dev; 268 struct net_device *dev;
268 int offset, end; 269 int offset, end;
270 struct net *net = dev_net(skb->dst->dev);
269 271
270 if (fq->q.last_in & INET_FRAG_COMPLETE) 272 if (fq->q.last_in & INET_FRAG_COMPLETE)
271 goto err; 273 goto err;
@@ -275,7 +277,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
275 ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); 277 ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1)));
276 278
277 if ((unsigned int)end > IPV6_MAXPLEN) { 279 if ((unsigned int)end > IPV6_MAXPLEN) {
278 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 280 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
279 IPSTATS_MIB_INHDRERRORS); 281 IPSTATS_MIB_INHDRERRORS);
280 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 282 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
281 ((u8 *)&fhdr->frag_off - 283 ((u8 *)&fhdr->frag_off -
@@ -308,7 +310,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
308 /* RFC2460 says always send parameter problem in 310 /* RFC2460 says always send parameter problem in
309 * this case. -DaveM 311 * this case. -DaveM
310 */ 312 */
311 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 313 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst),
312 IPSTATS_MIB_INHDRERRORS); 314 IPSTATS_MIB_INHDRERRORS);
313 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 315 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
314 offsetof(struct ipv6hdr, payload_len)); 316 offsetof(struct ipv6hdr, payload_len));
@@ -432,7 +434,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
432 return -1; 434 return -1;
433 435
434err: 436err:
435 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); 437 IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
438 IPSTATS_MIB_REASMFAILS);
436 kfree_skb(skb); 439 kfree_skb(skb);
437 return -1; 440 return -1;
438} 441}
@@ -548,7 +551,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
548 head->csum); 551 head->csum);
549 552
550 rcu_read_lock(); 553 rcu_read_lock();
551 IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); 554 IP6_INC_STATS_BH(dev_net(dev),
555 __in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
552 rcu_read_unlock(); 556 rcu_read_unlock();
553 fq->q.fragments = NULL; 557 fq->q.fragments = NULL;
554 return 1; 558 return 1;
@@ -562,7 +566,8 @@ out_oom:
562 printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); 566 printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
563out_fail: 567out_fail:
564 rcu_read_lock(); 568 rcu_read_lock();
565 IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); 569 IP6_INC_STATS_BH(dev_net(dev),
570 __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
566 rcu_read_unlock(); 571 rcu_read_unlock();
567 return -1; 572 return -1;
568} 573}
@@ -572,24 +577,17 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
572 struct frag_hdr *fhdr; 577 struct frag_hdr *fhdr;
573 struct frag_queue *fq; 578 struct frag_queue *fq;
574 struct ipv6hdr *hdr = ipv6_hdr(skb); 579 struct ipv6hdr *hdr = ipv6_hdr(skb);
575 struct net *net; 580 struct net *net = dev_net(skb->dst->dev);
576 581
577 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); 582 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS);
578 583
579 /* Jumbo payload inhibits frag. header */ 584 /* Jumbo payload inhibits frag. header */
580 if (hdr->payload_len==0) { 585 if (hdr->payload_len==0)
581 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 586 goto fail_hdr;
582 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 587
583 skb_network_header_len(skb));
584 return -1;
585 }
586 if (!pskb_may_pull(skb, (skb_transport_offset(skb) + 588 if (!pskb_may_pull(skb, (skb_transport_offset(skb) +
587 sizeof(struct frag_hdr)))) { 589 sizeof(struct frag_hdr))))
588 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 590 goto fail_hdr;
589 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
590 skb_network_header_len(skb));
591 return -1;
592 }
593 591
594 hdr = ipv6_hdr(skb); 592 hdr = ipv6_hdr(skb);
595 fhdr = (struct frag_hdr *)skb_transport_header(skb); 593 fhdr = (struct frag_hdr *)skb_transport_header(skb);
@@ -597,13 +595,13 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
597 if (!(fhdr->frag_off & htons(0xFFF9))) { 595 if (!(fhdr->frag_off & htons(0xFFF9))) {
598 /* It is not a fragmented frame */ 596 /* It is not a fragmented frame */
599 skb->transport_header += sizeof(struct frag_hdr); 597 skb->transport_header += sizeof(struct frag_hdr);
600 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); 598 IP6_INC_STATS_BH(net,
599 ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS);
601 600
602 IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb); 601 IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb);
603 return 1; 602 return 1;
604 } 603 }
605 604
606 net = dev_net(skb->dev);
607 if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) 605 if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh)
608 ip6_evictor(net, ip6_dst_idev(skb->dst)); 606 ip6_evictor(net, ip6_dst_idev(skb->dst));
609 607
@@ -620,9 +618,14 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
620 return ret; 618 return ret;
621 } 619 }
622 620
623 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); 621 IP6_INC_STATS_BH(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS);
624 kfree_skb(skb); 622 kfree_skb(skb);
625 return -1; 623 return -1;
624
625fail_hdr:
626 IP6_INC_STATS(net, ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
627 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb));
628 return -1;
626} 629}
627 630
628static struct inet6_protocol frag_protocol = 631static struct inet6_protocol frag_protocol =
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 9af6115f0f50..89dc69924340 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1003,6 +1003,25 @@ int icmp6_dst_gc(void)
1003 return more; 1003 return more;
1004} 1004}
1005 1005
1006static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
1007 void *arg)
1008{
1009 struct dst_entry *dst, **pprev;
1010
1011 spin_lock_bh(&icmp6_dst_lock);
1012 pprev = &icmp6_dst_gc_list;
1013 while ((dst = *pprev) != NULL) {
1014 struct rt6_info *rt = (struct rt6_info *) dst;
1015 if (func(rt, arg)) {
1016 *pprev = dst->next;
1017 dst_free(dst);
1018 } else {
1019 pprev = &dst->next;
1020 }
1021 }
1022 spin_unlock_bh(&icmp6_dst_lock);
1023}
1024
1006static int ip6_dst_gc(struct dst_ops *ops) 1025static int ip6_dst_gc(struct dst_ops *ops)
1007{ 1026{
1008 unsigned long now = jiffies; 1027 unsigned long now = jiffies;
@@ -1814,16 +1833,19 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1814static int ip6_pkt_drop(struct sk_buff *skb, int code, int ipstats_mib_noroutes) 1833static int ip6_pkt_drop(struct sk_buff *skb, int code, int ipstats_mib_noroutes)
1815{ 1834{
1816 int type; 1835 int type;
1836 struct dst_entry *dst = skb->dst;
1817 switch (ipstats_mib_noroutes) { 1837 switch (ipstats_mib_noroutes) {
1818 case IPSTATS_MIB_INNOROUTES: 1838 case IPSTATS_MIB_INNOROUTES:
1819 type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); 1839 type = ipv6_addr_type(&ipv6_hdr(skb)->daddr);
1820 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { 1840 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) {
1821 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); 1841 IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
1842 IPSTATS_MIB_INADDRERRORS);
1822 break; 1843 break;
1823 } 1844 }
1824 /* FALLTHROUGH */ 1845 /* FALLTHROUGH */
1825 case IPSTATS_MIB_OUTNOROUTES: 1846 case IPSTATS_MIB_OUTNOROUTES:
1826 IP6_INC_STATS(ip6_dst_idev(skb->dst), ipstats_mib_noroutes); 1847 IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
1848 ipstats_mib_noroutes);
1827 break; 1849 break;
1828 } 1850 }
1829 icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); 1851 icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
@@ -1930,6 +1952,7 @@ void rt6_ifdown(struct net *net, struct net_device *dev)
1930 }; 1952 };
1931 1953
1932 fib6_clean_all(net, fib6_ifdown, 0, &adn); 1954 fib6_clean_all(net, fib6_ifdown, 0, &adn);
1955 icmp6_clean_all(fib6_ifdown, &adn);
1933} 1956}
1934 1957
1935struct rt6_mtu_change_arg 1958struct rt6_mtu_change_arg
@@ -2611,10 +2634,8 @@ static int ip6_route_net_init(struct net *net)
2611 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, 2634 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
2612 sizeof(*net->ipv6.ip6_prohibit_entry), 2635 sizeof(*net->ipv6.ip6_prohibit_entry),
2613 GFP_KERNEL); 2636 GFP_KERNEL);
2614 if (!net->ipv6.ip6_prohibit_entry) { 2637 if (!net->ipv6.ip6_prohibit_entry)
2615 kfree(net->ipv6.ip6_null_entry); 2638 goto out_ip6_null_entry;
2616 goto out;
2617 }
2618 net->ipv6.ip6_prohibit_entry->u.dst.path = 2639 net->ipv6.ip6_prohibit_entry->u.dst.path =
2619 (struct dst_entry *)net->ipv6.ip6_prohibit_entry; 2640 (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
2620 net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops; 2641 net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
@@ -2622,16 +2643,22 @@ static int ip6_route_net_init(struct net *net)
2622 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, 2643 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
2623 sizeof(*net->ipv6.ip6_blk_hole_entry), 2644 sizeof(*net->ipv6.ip6_blk_hole_entry),
2624 GFP_KERNEL); 2645 GFP_KERNEL);
2625 if (!net->ipv6.ip6_blk_hole_entry) { 2646 if (!net->ipv6.ip6_blk_hole_entry)
2626 kfree(net->ipv6.ip6_null_entry); 2647 goto out_ip6_prohibit_entry;
2627 kfree(net->ipv6.ip6_prohibit_entry);
2628 goto out;
2629 }
2630 net->ipv6.ip6_blk_hole_entry->u.dst.path = 2648 net->ipv6.ip6_blk_hole_entry->u.dst.path =
2631 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; 2649 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
2632 net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops; 2650 net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
2633#endif 2651#endif
2634 2652
2653 net->ipv6.sysctl.flush_delay = 0;
2654 net->ipv6.sysctl.ip6_rt_max_size = 4096;
2655 net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;
2656 net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ;
2657 net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ;
2658 net->ipv6.sysctl.ip6_rt_gc_elasticity = 9;
2659 net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
2660 net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
2661
2635#ifdef CONFIG_PROC_FS 2662#ifdef CONFIG_PROC_FS
2636 proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); 2663 proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
2637 proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); 2664 proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
@@ -2642,6 +2669,12 @@ static int ip6_route_net_init(struct net *net)
2642out: 2669out:
2643 return ret; 2670 return ret;
2644 2671
2672#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2673out_ip6_prohibit_entry:
2674 kfree(net->ipv6.ip6_prohibit_entry);
2675out_ip6_null_entry:
2676 kfree(net->ipv6.ip6_null_entry);
2677#endif
2645out_ip6_dst_ops: 2678out_ip6_dst_ops:
2646 release_net(net->ipv6.ip6_dst_ops->dst_net); 2679 release_net(net->ipv6.ip6_dst_ops->dst_net);
2647 kfree(net->ipv6.ip6_dst_ops); 2680 kfree(net->ipv6.ip6_dst_ops);
@@ -2688,6 +2721,8 @@ int __init ip6_route_init(void)
2688 if (ret) 2721 if (ret)
2689 goto out_kmem_cache; 2722 goto out_kmem_cache;
2690 2723
2724 ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
2725
2691 /* Registering of the loopback is done before this portion of code, 2726 /* Registering of the loopback is done before this portion of code,
2692 * the loopback reference in rt6_info will not be taken, do it 2727 * the loopback reference in rt6_info will not be taken, do it
2693 * manually for init_net */ 2728 * manually for init_net */
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5b90b369ccb2..e5310c9b84dc 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -330,7 +330,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
330 th->dest, &hdr->saddr, th->source, skb->dev->ifindex); 330 th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
331 331
332 if (sk == NULL) { 332 if (sk == NULL) {
333 ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); 333 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
334 ICMP6_MIB_INERRORS);
334 return; 335 return;
335 } 336 }
336 337
@@ -941,117 +942,14 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
941 return 0; 942 return 0;
942} 943}
943 944
944static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) 945static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
946 u32 ts, struct tcp_md5sig_key *key, int rst)
945{ 947{
946 struct tcphdr *th = tcp_hdr(skb), *t1; 948 struct tcphdr *th = tcp_hdr(skb), *t1;
947 struct sk_buff *buff; 949 struct sk_buff *buff;
948 struct flowi fl; 950 struct flowi fl;
949 struct net *net = dev_net(skb->dst->dev); 951 struct net *net = dev_net(skb->dst->dev);
950 struct sock *ctl_sk = net->ipv6.tcp_sk; 952 struct sock *ctl_sk = net->ipv6.tcp_sk;
951 unsigned int tot_len = sizeof(*th);
952#ifdef CONFIG_TCP_MD5SIG
953 struct tcp_md5sig_key *key;
954#endif
955
956 if (th->rst)
957 return;
958
959 if (!ipv6_unicast_destination(skb))
960 return;
961
962#ifdef CONFIG_TCP_MD5SIG
963 if (sk)
964 key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
965 else
966 key = NULL;
967
968 if (key)
969 tot_len += TCPOLEN_MD5SIG_ALIGNED;
970#endif
971
972 /*
973 * We need to grab some memory, and put together an RST,
974 * and then put it into the queue to be sent.
975 */
976
977 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
978 GFP_ATOMIC);
979 if (buff == NULL)
980 return;
981
982 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
983
984 t1 = (struct tcphdr *) skb_push(buff, tot_len);
985
986 /* Swap the send and the receive. */
987 memset(t1, 0, sizeof(*t1));
988 t1->dest = th->source;
989 t1->source = th->dest;
990 t1->doff = tot_len / 4;
991 t1->rst = 1;
992
993 if(th->ack) {
994 t1->seq = th->ack_seq;
995 } else {
996 t1->ack = 1;
997 t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin
998 + skb->len - (th->doff<<2));
999 }
1000
1001#ifdef CONFIG_TCP_MD5SIG
1002 if (key) {
1003 __be32 *opt = (__be32*)(t1 + 1);
1004 opt[0] = htonl((TCPOPT_NOP << 24) |
1005 (TCPOPT_NOP << 16) |
1006 (TCPOPT_MD5SIG << 8) |
1007 TCPOLEN_MD5SIG);
1008 tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key,
1009 &ipv6_hdr(skb)->daddr,
1010 &ipv6_hdr(skb)->saddr, t1);
1011 }
1012#endif
1013
1014 buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
1015
1016 memset(&fl, 0, sizeof(fl));
1017 ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
1018 ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
1019
1020 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
1021 sizeof(*t1), IPPROTO_TCP,
1022 buff->csum);
1023
1024 fl.proto = IPPROTO_TCP;
1025 fl.oif = inet6_iif(skb);
1026 fl.fl_ip_dport = t1->dest;
1027 fl.fl_ip_sport = t1->source;
1028 security_skb_classify_flow(skb, &fl);
1029
1030 /* Pass a socket to ip6_dst_lookup either it is for RST
1031 * Underlying function will use this to retrieve the network
1032 * namespace
1033 */
1034 if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
1035
1036 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
1037 ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
1038 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
1039 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
1040 return;
1041 }
1042 }
1043
1044 kfree_skb(buff);
1045}
1046
1047static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
1048 struct tcp_md5sig_key *key)
1049{
1050 struct tcphdr *th = tcp_hdr(skb), *t1;
1051 struct sk_buff *buff;
1052 struct flowi fl;
1053 struct net *net = dev_net(skb->dev);
1054 struct sock *ctl_sk = net->ipv6.tcp_sk;
1055 unsigned int tot_len = sizeof(struct tcphdr); 953 unsigned int tot_len = sizeof(struct tcphdr);
1056 __be32 *topt; 954 __be32 *topt;
1057 955
@@ -1069,16 +967,17 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
1069 967
1070 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); 968 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
1071 969
1072 t1 = (struct tcphdr *) skb_push(buff,tot_len); 970 t1 = (struct tcphdr *) skb_push(buff, tot_len);
1073 971
1074 /* Swap the send and the receive. */ 972 /* Swap the send and the receive. */
1075 memset(t1, 0, sizeof(*t1)); 973 memset(t1, 0, sizeof(*t1));
1076 t1->dest = th->source; 974 t1->dest = th->source;
1077 t1->source = th->dest; 975 t1->source = th->dest;
1078 t1->doff = tot_len/4; 976 t1->doff = tot_len / 4;
1079 t1->seq = htonl(seq); 977 t1->seq = htonl(seq);
1080 t1->ack_seq = htonl(ack); 978 t1->ack_seq = htonl(ack);
1081 t1->ack = 1; 979 t1->ack = !rst || !th->ack;
980 t1->rst = rst;
1082 t1->window = htons(win); 981 t1->window = htons(win);
1083 982
1084 topt = (__be32 *)(t1 + 1); 983 topt = (__be32 *)(t1 + 1);
@@ -1087,7 +986,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
1087 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | 986 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
1088 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); 987 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
1089 *topt++ = htonl(tcp_time_stamp); 988 *topt++ = htonl(tcp_time_stamp);
1090 *topt = htonl(ts); 989 *topt++ = htonl(ts);
1091 } 990 }
1092 991
1093#ifdef CONFIG_TCP_MD5SIG 992#ifdef CONFIG_TCP_MD5SIG
@@ -1116,10 +1015,16 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
1116 fl.fl_ip_sport = t1->source; 1015 fl.fl_ip_sport = t1->source;
1117 security_skb_classify_flow(skb, &fl); 1016 security_skb_classify_flow(skb, &fl);
1118 1017
1018 /* Pass a socket to ip6_dst_lookup either it is for RST
1019 * Underlying function will use this to retrieve the network
1020 * namespace
1021 */
1119 if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { 1022 if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
1120 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { 1023 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
1121 ip6_xmit(ctl_sk, buff, &fl, NULL, 0); 1024 ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
1122 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); 1025 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
1026 if (rst)
1027 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
1123 return; 1028 return;
1124 } 1029 }
1125 } 1030 }
@@ -1127,6 +1032,38 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
1127 kfree_skb(buff); 1032 kfree_skb(buff);
1128} 1033}
1129 1034
1035static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
1036{
1037 struct tcphdr *th = tcp_hdr(skb);
1038 u32 seq = 0, ack_seq = 0;
1039 struct tcp_md5sig_key *key = NULL;
1040
1041 if (th->rst)
1042 return;
1043
1044 if (!ipv6_unicast_destination(skb))
1045 return;
1046
1047#ifdef CONFIG_TCP_MD5SIG
1048 if (sk)
1049 key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
1050#endif
1051
1052 if (th->ack)
1053 seq = ntohl(th->ack_seq);
1054 else
1055 ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
1056 (th->doff << 2);
1057
1058 tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1);
1059}
1060
1061static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
1062 struct tcp_md5sig_key *key)
1063{
1064 tcp_v6_send_response(skb, seq, ack, win, ts, key, 0);
1065}
1066
1130static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) 1067static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
1131{ 1068{
1132 struct inet_timewait_sock *tw = inet_twsk(sk); 1069 struct inet_timewait_sock *tw = inet_twsk(sk);
@@ -1286,7 +1223,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1286 struct request_sock *req, 1223 struct request_sock *req,
1287 struct dst_entry *dst) 1224 struct dst_entry *dst)
1288{ 1225{
1289 struct inet6_request_sock *treq = inet6_rsk(req); 1226 struct inet6_request_sock *treq;
1290 struct ipv6_pinfo *newnp, *np = inet6_sk(sk); 1227 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
1291 struct tcp6_sock *newtcp6sk; 1228 struct tcp6_sock *newtcp6sk;
1292 struct inet_sock *newinet; 1229 struct inet_sock *newinet;
@@ -1350,6 +1287,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1350 return newsk; 1287 return newsk;
1351 } 1288 }
1352 1289
1290 treq = inet6_rsk(req);
1353 opt = np->opt; 1291 opt = np->opt;
1354 1292
1355 if (sk_acceptq_is_full(sk)) 1293 if (sk_acceptq_is_full(sk))
@@ -1680,11 +1618,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
1680 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); 1618 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
1681 TCP_SKB_CB(skb)->sacked = 0; 1619 TCP_SKB_CB(skb)->sacked = 0;
1682 1620
1683 sk = __inet6_lookup(net, &tcp_hashinfo, 1621 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
1684 &ipv6_hdr(skb)->saddr, th->source,
1685 &ipv6_hdr(skb)->daddr, ntohs(th->dest),
1686 inet6_iif(skb));
1687
1688 if (!sk) 1622 if (!sk)
1689 goto no_tcp_socket; 1623 goto no_tcp_socket;
1690 1624
@@ -2148,6 +2082,7 @@ static int tcpv6_net_init(struct net *net)
2148static void tcpv6_net_exit(struct net *net) 2082static void tcpv6_net_exit(struct net *net)
2149{ 2083{
2150 inet_ctl_sock_destroy(net->ipv6.tcp_sk); 2084 inet_ctl_sock_destroy(net->ipv6.tcp_sk);
2085 inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6);
2151} 2086}
2152 2087
2153static struct pernet_operations tcpv6_net_ops = { 2088static struct pernet_operations tcpv6_net_ops = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index a6aecf76a71b..e51da8c092fa 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -107,6 +107,21 @@ static struct sock *__udp6_lib_lookup(struct net *net,
107 return result; 107 return result;
108} 108}
109 109
110static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
111 __be16 sport, __be16 dport,
112 struct hlist_head udptable[])
113{
114 struct sock *sk;
115 struct ipv6hdr *iph = ipv6_hdr(skb);
116
117 if (unlikely(sk = skb_steal_sock(skb)))
118 return sk;
119 else
120 return __udp6_lib_lookup(dev_net(skb->dst->dev), &iph->saddr, sport,
121 &iph->daddr, dport, inet6_iif(skb),
122 udptable);
123}
124
110/* 125/*
111 * This should be easy, if there is something there we 126 * This should be easy, if there is something there we
112 * return it, otherwise we block. 127 * return it, otherwise we block.
@@ -488,8 +503,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
488 * check socket cache ... must talk to Alan about his plans 503 * check socket cache ... must talk to Alan about his plans
489 * for sock caches... i'll skip this for now. 504 * for sock caches... i'll skip this for now.
490 */ 505 */
491 sk = __udp6_lib_lookup(net, saddr, uh->source, 506 sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
492 daddr, uh->dest, inet6_iif(skb), udptable);
493 507
494 if (sk == NULL) { 508 if (sk == NULL) {
495 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 509 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index f6cdcb348e05..3cd1a1ac3d6c 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -13,8 +13,6 @@
13 */ 13 */
14#include "udp_impl.h" 14#include "udp_impl.h"
15 15
16DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly;
17
18static int udplitev6_rcv(struct sk_buff *skb) 16static int udplitev6_rcv(struct sk_buff *skb)
19{ 17{
20 return __udp6_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE); 18 return __udp6_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);