diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 26 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 22 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 12 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_security.c | 172 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 5 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 61 | ||||
-rw-r--r-- | net/ipv6/sit.c | 24 | ||||
-rw-r--r-- | net/ipv6/sysctl_net_ipv6.c | 29 |
10 files changed, 281 insertions, 74 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 2bda3ba100b1..37814810ac49 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -711,7 +711,7 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
711 | } | 711 | } |
712 | 712 | ||
713 | if (!ip6_tnl_rcv_ctl(t)) { | 713 | if (!ip6_tnl_rcv_ctl(t)) { |
714 | t->stat.rx_dropped++; | 714 | t->dev->stats.rx_dropped++; |
715 | read_unlock(&ip6_tnl_lock); | 715 | read_unlock(&ip6_tnl_lock); |
716 | goto discard; | 716 | goto discard; |
717 | } | 717 | } |
@@ -728,8 +728,8 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
728 | 728 | ||
729 | dscp_ecn_decapsulate(t, ipv6h, skb); | 729 | dscp_ecn_decapsulate(t, ipv6h, skb); |
730 | 730 | ||
731 | t->stat.rx_packets++; | 731 | t->dev->stats.rx_packets++; |
732 | t->stat.rx_bytes += skb->len; | 732 | t->dev->stats.rx_bytes += skb->len; |
733 | netif_rx(skb); | 733 | netif_rx(skb); |
734 | read_unlock(&ip6_tnl_lock); | 734 | read_unlock(&ip6_tnl_lock); |
735 | return 0; | 735 | return 0; |
@@ -849,7 +849,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
849 | __u32 *pmtu) | 849 | __u32 *pmtu) |
850 | { | 850 | { |
851 | struct ip6_tnl *t = netdev_priv(dev); | 851 | struct ip6_tnl *t = netdev_priv(dev); |
852 | struct net_device_stats *stats = &t->stat; | 852 | struct net_device_stats *stats = &t->dev->stats; |
853 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 853 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
854 | struct ipv6_tel_txoption opt; | 854 | struct ipv6_tel_txoption opt; |
855 | struct dst_entry *dst; | 855 | struct dst_entry *dst; |
@@ -1043,11 +1043,11 @@ static int | |||
1043 | ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | 1043 | ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) |
1044 | { | 1044 | { |
1045 | struct ip6_tnl *t = netdev_priv(dev); | 1045 | struct ip6_tnl *t = netdev_priv(dev); |
1046 | struct net_device_stats *stats = &t->stat; | 1046 | struct net_device_stats *stats = &t->dev->stats; |
1047 | int ret; | 1047 | int ret; |
1048 | 1048 | ||
1049 | if (t->recursion++) { | 1049 | if (t->recursion++) { |
1050 | t->stat.collisions++; | 1050 | stats->collisions++; |
1051 | goto tx_err; | 1051 | goto tx_err; |
1052 | } | 1052 | } |
1053 | 1053 | ||
@@ -1289,19 +1289,6 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1289 | } | 1289 | } |
1290 | 1290 | ||
1291 | /** | 1291 | /** |
1292 | * ip6_tnl_get_stats - return the stats for tunnel device | ||
1293 | * @dev: virtual device associated with tunnel | ||
1294 | * | ||
1295 | * Return: stats for device | ||
1296 | **/ | ||
1297 | |||
1298 | static struct net_device_stats * | ||
1299 | ip6_tnl_get_stats(struct net_device *dev) | ||
1300 | { | ||
1301 | return &(((struct ip6_tnl *)netdev_priv(dev))->stat); | ||
1302 | } | ||
1303 | |||
1304 | /** | ||
1305 | * ip6_tnl_change_mtu - change mtu manually for tunnel device | 1292 | * ip6_tnl_change_mtu - change mtu manually for tunnel device |
1306 | * @dev: virtual device associated with tunnel | 1293 | * @dev: virtual device associated with tunnel |
1307 | * @new_mtu: the new mtu | 1294 | * @new_mtu: the new mtu |
@@ -1334,7 +1321,6 @@ static void ip6_tnl_dev_setup(struct net_device *dev) | |||
1334 | dev->uninit = ip6_tnl_dev_uninit; | 1321 | dev->uninit = ip6_tnl_dev_uninit; |
1335 | dev->destructor = free_netdev; | 1322 | dev->destructor = free_netdev; |
1336 | dev->hard_start_xmit = ip6_tnl_xmit; | 1323 | dev->hard_start_xmit = ip6_tnl_xmit; |
1337 | dev->get_stats = ip6_tnl_get_stats; | ||
1338 | dev->do_ioctl = ip6_tnl_ioctl; | 1324 | dev->do_ioctl = ip6_tnl_ioctl; |
1339 | dev->change_mtu = ip6_tnl_change_mtu; | 1325 | dev->change_mtu = ip6_tnl_change_mtu; |
1340 | 1326 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 2de3c464fe75..bf268b386963 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -388,8 +388,8 @@ static int pim6_rcv(struct sk_buff *skb) | |||
388 | skb->ip_summed = 0; | 388 | skb->ip_summed = 0; |
389 | skb->pkt_type = PACKET_HOST; | 389 | skb->pkt_type = PACKET_HOST; |
390 | dst_release(skb->dst); | 390 | dst_release(skb->dst); |
391 | ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len; | 391 | reg_dev->stats.rx_bytes += skb->len; |
392 | ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++; | 392 | reg_dev->stats.rx_packets++; |
393 | skb->dst = NULL; | 393 | skb->dst = NULL; |
394 | nf_reset(skb); | 394 | nf_reset(skb); |
395 | netif_rx(skb); | 395 | netif_rx(skb); |
@@ -409,26 +409,20 @@ static struct inet6_protocol pim6_protocol = { | |||
409 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) | 409 | static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) |
410 | { | 410 | { |
411 | read_lock(&mrt_lock); | 411 | read_lock(&mrt_lock); |
412 | ((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len; | 412 | dev->stats.tx_bytes += skb->len; |
413 | ((struct net_device_stats *)netdev_priv(dev))->tx_packets++; | 413 | dev->stats.tx_packets++; |
414 | ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT); | 414 | ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT); |
415 | read_unlock(&mrt_lock); | 415 | read_unlock(&mrt_lock); |
416 | kfree_skb(skb); | 416 | kfree_skb(skb); |
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) | ||
421 | { | ||
422 | return (struct net_device_stats *)netdev_priv(dev); | ||
423 | } | ||
424 | |||
425 | static void reg_vif_setup(struct net_device *dev) | 420 | static void reg_vif_setup(struct net_device *dev) |
426 | { | 421 | { |
427 | dev->type = ARPHRD_PIMREG; | 422 | dev->type = ARPHRD_PIMREG; |
428 | dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; | 423 | dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; |
429 | dev->flags = IFF_NOARP; | 424 | dev->flags = IFF_NOARP; |
430 | dev->hard_start_xmit = reg_vif_xmit; | 425 | dev->hard_start_xmit = reg_vif_xmit; |
431 | dev->get_stats = reg_vif_get_stats; | ||
432 | dev->destructor = free_netdev; | 426 | dev->destructor = free_netdev; |
433 | } | 427 | } |
434 | 428 | ||
@@ -436,9 +430,7 @@ static struct net_device *ip6mr_reg_vif(void) | |||
436 | { | 430 | { |
437 | struct net_device *dev; | 431 | struct net_device *dev; |
438 | 432 | ||
439 | dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg", | 433 | dev = alloc_netdev(0, "pim6reg", reg_vif_setup); |
440 | reg_vif_setup); | ||
441 | |||
442 | if (dev == NULL) | 434 | if (dev == NULL) |
443 | return NULL; | 435 | return NULL; |
444 | 436 | ||
@@ -1377,8 +1369,8 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | |||
1377 | if (vif->flags & MIFF_REGISTER) { | 1369 | if (vif->flags & MIFF_REGISTER) { |
1378 | vif->pkt_out++; | 1370 | vif->pkt_out++; |
1379 | vif->bytes_out += skb->len; | 1371 | vif->bytes_out += skb->len; |
1380 | ((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len; | 1372 | vif->dev->stats.tx_bytes += skb->len; |
1381 | ((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++; | 1373 | vif->dev->stats.tx_packets++; |
1382 | ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT); | 1374 | ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT); |
1383 | kfree_skb(skb); | 1375 | kfree_skb(skb); |
1384 | return 0; | 1376 | return 0; |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 6cae5475737e..689dec899c57 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -208,5 +208,17 @@ config IP6_NF_RAW | |||
208 | If you want to compile it as a module, say M here and read | 208 | If you want to compile it as a module, say M here and read |
209 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 209 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
210 | 210 | ||
211 | # security table for MAC policy | ||
212 | config IP6_NF_SECURITY | ||
213 | tristate "Security table" | ||
214 | depends on IP6_NF_IPTABLES | ||
215 | depends on SECURITY | ||
216 | default m if NETFILTER_ADVANCED=n | ||
217 | help | ||
218 | This option adds a `security' table to iptables, for use | ||
219 | with Mandatory Access Control (MAC) policy. | ||
220 | |||
221 | If unsure, say N. | ||
222 | |||
211 | endmenu | 223 | endmenu |
212 | 224 | ||
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index fbf2c14ed887..3f17c948eefb 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | |||
8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
9 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 9 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
10 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 10 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
11 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | ||
11 | 12 | ||
12 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
13 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o | 14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 2eff3ae8977d..1b8815f6153d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -159,7 +159,6 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
159 | case IPQ_COPY_META: | 159 | case IPQ_COPY_META: |
160 | case IPQ_COPY_NONE: | 160 | case IPQ_COPY_NONE: |
161 | size = NLMSG_SPACE(sizeof(*pmsg)); | 161 | size = NLMSG_SPACE(sizeof(*pmsg)); |
162 | data_len = 0; | ||
163 | break; | 162 | break; |
164 | 163 | ||
165 | case IPQ_COPY_PACKET: | 164 | case IPQ_COPY_PACKET: |
@@ -226,8 +225,6 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
226 | return skb; | 225 | return skb; |
227 | 226 | ||
228 | nlmsg_failure: | 227 | nlmsg_failure: |
229 | if (skb) | ||
230 | kfree_skb(skb); | ||
231 | *errp = -EINVAL; | 228 | *errp = -EINVAL; |
232 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); | 229 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); |
233 | return NULL; | 230 | return NULL; |
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c new file mode 100644 index 000000000000..063a3d9c3c67 --- /dev/null +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * "security" table for IPv6 | ||
3 | * | ||
4 | * This is for use by Mandatory Access Control (MAC) security models, | ||
5 | * which need to be able to manage security policy in separate context | ||
6 | * to DAC. | ||
7 | * | ||
8 | * Based on iptable_mangle.c | ||
9 | * | ||
10 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | ||
11 | * Copyright (C) 2000-2004 Netfilter Core Team <coreteam <at> netfilter.org> | ||
12 | * Copyright (C) 2008 Red Hat, Inc., James Morris <jmorris <at> redhat.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
20 | |||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_AUTHOR("James Morris <jmorris <at> redhat.com>"); | ||
23 | MODULE_DESCRIPTION("ip6tables security table, for MAC rules"); | ||
24 | |||
25 | #define SECURITY_VALID_HOOKS (1 << NF_INET_LOCAL_IN) | \ | ||
26 | (1 << NF_INET_FORWARD) | \ | ||
27 | (1 << NF_INET_LOCAL_OUT) | ||
28 | |||
29 | static struct | ||
30 | { | ||
31 | struct ip6t_replace repl; | ||
32 | struct ip6t_standard entries[3]; | ||
33 | struct ip6t_error term; | ||
34 | } initial_table __initdata = { | ||
35 | .repl = { | ||
36 | .name = "security", | ||
37 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
38 | .num_entries = 4, | ||
39 | .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), | ||
40 | .hook_entry = { | ||
41 | [NF_INET_LOCAL_IN] = 0, | ||
42 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
43 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, | ||
44 | }, | ||
45 | .underflow = { | ||
46 | [NF_INET_LOCAL_IN] = 0, | ||
47 | [NF_INET_FORWARD] = sizeof(struct ip6t_standard), | ||
48 | [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, | ||
49 | }, | ||
50 | }, | ||
51 | .entries = { | ||
52 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ | ||
53 | IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ | ||
54 | IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ | ||
55 | }, | ||
56 | .term = IP6T_ERROR_INIT, /* ERROR */ | ||
57 | }; | ||
58 | |||
59 | static struct xt_table security_table = { | ||
60 | .name = "security", | ||
61 | .valid_hooks = SECURITY_VALID_HOOKS, | ||
62 | .lock = __RW_LOCK_UNLOCKED(security_table.lock), | ||
63 | .me = THIS_MODULE, | ||
64 | .af = AF_INET6, | ||
65 | }; | ||
66 | |||
67 | static unsigned int | ||
68 | ip6t_local_in_hook(unsigned int hook, | ||
69 | struct sk_buff *skb, | ||
70 | const struct net_device *in, | ||
71 | const struct net_device *out, | ||
72 | int (*okfn)(struct sk_buff *)) | ||
73 | { | ||
74 | return ip6t_do_table(skb, hook, in, out, | ||
75 | init_net.ipv6.ip6table_security); | ||
76 | } | ||
77 | |||
78 | static unsigned int | ||
79 | ip6t_forward_hook(unsigned int hook, | ||
80 | struct sk_buff *skb, | ||
81 | const struct net_device *in, | ||
82 | const struct net_device *out, | ||
83 | int (*okfn)(struct sk_buff *)) | ||
84 | { | ||
85 | return ip6t_do_table(skb, hook, in, out, | ||
86 | init_net.ipv6.ip6table_security); | ||
87 | } | ||
88 | |||
89 | static unsigned int | ||
90 | ip6t_local_out_hook(unsigned int hook, | ||
91 | struct sk_buff *skb, | ||
92 | const struct net_device *in, | ||
93 | const struct net_device *out, | ||
94 | int (*okfn)(struct sk_buff *)) | ||
95 | { | ||
96 | /* TBD: handle short packets via raw socket */ | ||
97 | return ip6t_do_table(skb, hook, in, out, | ||
98 | init_net.ipv6.ip6table_security); | ||
99 | } | ||
100 | |||
101 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | ||
102 | { | ||
103 | .hook = ip6t_local_in_hook, | ||
104 | .owner = THIS_MODULE, | ||
105 | .pf = PF_INET6, | ||
106 | .hooknum = NF_INET_LOCAL_IN, | ||
107 | .priority = NF_IP6_PRI_SECURITY, | ||
108 | }, | ||
109 | { | ||
110 | .hook = ip6t_forward_hook, | ||
111 | .owner = THIS_MODULE, | ||
112 | .pf = PF_INET6, | ||
113 | .hooknum = NF_INET_FORWARD, | ||
114 | .priority = NF_IP6_PRI_SECURITY, | ||
115 | }, | ||
116 | { | ||
117 | .hook = ip6t_local_out_hook, | ||
118 | .owner = THIS_MODULE, | ||
119 | .pf = PF_INET6, | ||
120 | .hooknum = NF_INET_LOCAL_OUT, | ||
121 | .priority = NF_IP6_PRI_SECURITY, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static int __net_init ip6table_security_net_init(struct net *net) | ||
126 | { | ||
127 | net->ipv6.ip6table_security = | ||
128 | ip6t_register_table(net, &security_table, &initial_table.repl); | ||
129 | |||
130 | if (IS_ERR(net->ipv6.ip6table_security)) | ||
131 | return PTR_ERR(net->ipv6.ip6table_security); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void __net_exit ip6table_security_net_exit(struct net *net) | ||
137 | { | ||
138 | ip6t_unregister_table(net->ipv6.ip6table_security); | ||
139 | } | ||
140 | |||
141 | static struct pernet_operations ip6table_security_net_ops = { | ||
142 | .init = ip6table_security_net_init, | ||
143 | .exit = ip6table_security_net_exit, | ||
144 | }; | ||
145 | |||
146 | static int __init ip6table_security_init(void) | ||
147 | { | ||
148 | int ret; | ||
149 | |||
150 | ret = register_pernet_subsys(&ip6table_security_net_ops); | ||
151 | if (ret < 0) | ||
152 | return ret; | ||
153 | |||
154 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | ||
155 | if (ret < 0) | ||
156 | goto cleanup_table; | ||
157 | |||
158 | return ret; | ||
159 | |||
160 | cleanup_table: | ||
161 | unregister_pernet_subsys(&ip6table_security_net_ops); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static void __exit ip6table_security_fini(void) | ||
166 | { | ||
167 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | ||
168 | unregister_pernet_subsys(&ip6table_security_net_ops); | ||
169 | } | ||
170 | |||
171 | module_init(ip6table_security_init); | ||
172 | module_exit(ip6table_security_fini); | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index ee713b03e9ec..14d47d833545 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -89,9 +89,8 @@ static int icmpv6_packet(struct nf_conn *ct, | |||
89 | means this will only run once even if count hits zero twice | 89 | means this will only run once even if count hits zero twice |
90 | (theoretically possible with SMP) */ | 90 | (theoretically possible with SMP) */ |
91 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { | 91 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { |
92 | if (atomic_dec_and_test(&ct->proto.icmp.count) | 92 | if (atomic_dec_and_test(&ct->proto.icmp.count)) |
93 | && del_timer(&ct->timeout)) | 93 | nf_ct_kill_acct(ct, ctinfo, skb); |
94 | ct->timeout.function((unsigned long)ct); | ||
95 | } else { | 94 | } else { |
96 | atomic_inc(&ct->proto.icmp.count); | 95 | atomic_inc(&ct->proto.icmp.count); |
97 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); | 96 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 798cabc7535b..9391a6949b96 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -632,7 +632,7 @@ static struct inet6_protocol frag_protocol = | |||
632 | }; | 632 | }; |
633 | 633 | ||
634 | #ifdef CONFIG_SYSCTL | 634 | #ifdef CONFIG_SYSCTL |
635 | static struct ctl_table ip6_frags_ctl_table[] = { | 635 | static struct ctl_table ip6_frags_ns_ctl_table[] = { |
636 | { | 636 | { |
637 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, | 637 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, |
638 | .procname = "ip6frag_high_thresh", | 638 | .procname = "ip6frag_high_thresh", |
@@ -658,6 +658,10 @@ static struct ctl_table ip6_frags_ctl_table[] = { | |||
658 | .proc_handler = &proc_dointvec_jiffies, | 658 | .proc_handler = &proc_dointvec_jiffies, |
659 | .strategy = &sysctl_jiffies, | 659 | .strategy = &sysctl_jiffies, |
660 | }, | 660 | }, |
661 | { } | ||
662 | }; | ||
663 | |||
664 | static struct ctl_table ip6_frags_ctl_table[] = { | ||
661 | { | 665 | { |
662 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, | 666 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, |
663 | .procname = "ip6frag_secret_interval", | 667 | .procname = "ip6frag_secret_interval", |
@@ -670,21 +674,20 @@ static struct ctl_table ip6_frags_ctl_table[] = { | |||
670 | { } | 674 | { } |
671 | }; | 675 | }; |
672 | 676 | ||
673 | static int ip6_frags_sysctl_register(struct net *net) | 677 | static int ip6_frags_ns_sysctl_register(struct net *net) |
674 | { | 678 | { |
675 | struct ctl_table *table; | 679 | struct ctl_table *table; |
676 | struct ctl_table_header *hdr; | 680 | struct ctl_table_header *hdr; |
677 | 681 | ||
678 | table = ip6_frags_ctl_table; | 682 | table = ip6_frags_ns_ctl_table; |
679 | if (net != &init_net) { | 683 | if (net != &init_net) { |
680 | table = kmemdup(table, sizeof(ip6_frags_ctl_table), GFP_KERNEL); | 684 | table = kmemdup(table, sizeof(ip6_frags_ns_ctl_table), GFP_KERNEL); |
681 | if (table == NULL) | 685 | if (table == NULL) |
682 | goto err_alloc; | 686 | goto err_alloc; |
683 | 687 | ||
684 | table[0].data = &net->ipv6.frags.high_thresh; | 688 | table[0].data = &net->ipv6.frags.high_thresh; |
685 | table[1].data = &net->ipv6.frags.low_thresh; | 689 | table[1].data = &net->ipv6.frags.low_thresh; |
686 | table[2].data = &net->ipv6.frags.timeout; | 690 | table[2].data = &net->ipv6.frags.timeout; |
687 | table[3].mode &= ~0222; | ||
688 | } | 691 | } |
689 | 692 | ||
690 | hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table); | 693 | hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table); |
@@ -701,7 +704,7 @@ err_alloc: | |||
701 | return -ENOMEM; | 704 | return -ENOMEM; |
702 | } | 705 | } |
703 | 706 | ||
704 | static void ip6_frags_sysctl_unregister(struct net *net) | 707 | static void ip6_frags_ns_sysctl_unregister(struct net *net) |
705 | { | 708 | { |
706 | struct ctl_table *table; | 709 | struct ctl_table *table; |
707 | 710 | ||
@@ -709,13 +712,36 @@ static void ip6_frags_sysctl_unregister(struct net *net) | |||
709 | unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); | 712 | unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); |
710 | kfree(table); | 713 | kfree(table); |
711 | } | 714 | } |
715 | |||
716 | static struct ctl_table_header *ip6_ctl_header; | ||
717 | |||
718 | static int ip6_frags_sysctl_register(void) | ||
719 | { | ||
720 | ip6_ctl_header = register_net_sysctl_rotable(net_ipv6_ctl_path, | ||
721 | ip6_frags_ctl_table); | ||
722 | return ip6_ctl_header == NULL ? -ENOMEM : 0; | ||
723 | } | ||
724 | |||
725 | static void ip6_frags_sysctl_unregister(void) | ||
726 | { | ||
727 | unregister_net_sysctl_table(ip6_ctl_header); | ||
728 | } | ||
712 | #else | 729 | #else |
713 | static inline int ip6_frags_sysctl_register(struct net *net) | 730 | static inline int ip6_frags_ns_sysctl_register(struct net *net) |
714 | { | 731 | { |
715 | return 0; | 732 | return 0; |
716 | } | 733 | } |
717 | 734 | ||
718 | static inline void ip6_frags_sysctl_unregister(struct net *net) | 735 | static inline void ip6_frags_ns_sysctl_unregister(struct net *net) |
736 | { | ||
737 | } | ||
738 | |||
739 | static inline int ip6_frags_sysctl_register(void) | ||
740 | { | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static inline void ip6_frags_sysctl_unregister(void) | ||
719 | { | 745 | { |
720 | } | 746 | } |
721 | #endif | 747 | #endif |
@@ -728,12 +754,12 @@ static int ipv6_frags_init_net(struct net *net) | |||
728 | 754 | ||
729 | inet_frags_init_net(&net->ipv6.frags); | 755 | inet_frags_init_net(&net->ipv6.frags); |
730 | 756 | ||
731 | return ip6_frags_sysctl_register(net); | 757 | return ip6_frags_ns_sysctl_register(net); |
732 | } | 758 | } |
733 | 759 | ||
734 | static void ipv6_frags_exit_net(struct net *net) | 760 | static void ipv6_frags_exit_net(struct net *net) |
735 | { | 761 | { |
736 | ip6_frags_sysctl_unregister(net); | 762 | ip6_frags_ns_sysctl_unregister(net); |
737 | inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); | 763 | inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); |
738 | } | 764 | } |
739 | 765 | ||
@@ -750,7 +776,13 @@ int __init ipv6_frag_init(void) | |||
750 | if (ret) | 776 | if (ret) |
751 | goto out; | 777 | goto out; |
752 | 778 | ||
753 | register_pernet_subsys(&ip6_frags_ops); | 779 | ret = ip6_frags_sysctl_register(); |
780 | if (ret) | ||
781 | goto err_sysctl; | ||
782 | |||
783 | ret = register_pernet_subsys(&ip6_frags_ops); | ||
784 | if (ret) | ||
785 | goto err_pernet; | ||
754 | 786 | ||
755 | ip6_frags.hashfn = ip6_hashfn; | 787 | ip6_frags.hashfn = ip6_hashfn; |
756 | ip6_frags.constructor = ip6_frag_init; | 788 | ip6_frags.constructor = ip6_frag_init; |
@@ -763,11 +795,18 @@ int __init ipv6_frag_init(void) | |||
763 | inet_frags_init(&ip6_frags); | 795 | inet_frags_init(&ip6_frags); |
764 | out: | 796 | out: |
765 | return ret; | 797 | return ret; |
798 | |||
799 | err_pernet: | ||
800 | ip6_frags_sysctl_unregister(); | ||
801 | err_sysctl: | ||
802 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); | ||
803 | goto out; | ||
766 | } | 804 | } |
767 | 805 | ||
768 | void ipv6_frag_exit(void) | 806 | void ipv6_frag_exit(void) |
769 | { | 807 | { |
770 | inet_frags_fini(&ip6_frags); | 808 | inet_frags_fini(&ip6_frags); |
809 | ip6_frags_sysctl_unregister(); | ||
771 | unregister_pernet_subsys(&ip6_frags_ops); | 810 | unregister_pernet_subsys(&ip6_frags_ops); |
772 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); | 811 | inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT); |
773 | } | 812 | } |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3de6ffdaedf2..6b8f0583b637 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -491,13 +491,13 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
491 | 491 | ||
492 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && | 492 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && |
493 | !isatap_chksrc(skb, iph, tunnel)) { | 493 | !isatap_chksrc(skb, iph, tunnel)) { |
494 | tunnel->stat.rx_errors++; | 494 | tunnel->dev->stats.rx_errors++; |
495 | read_unlock(&ipip6_lock); | 495 | read_unlock(&ipip6_lock); |
496 | kfree_skb(skb); | 496 | kfree_skb(skb); |
497 | return 0; | 497 | return 0; |
498 | } | 498 | } |
499 | tunnel->stat.rx_packets++; | 499 | tunnel->dev->stats.rx_packets++; |
500 | tunnel->stat.rx_bytes += skb->len; | 500 | tunnel->dev->stats.rx_bytes += skb->len; |
501 | skb->dev = tunnel->dev; | 501 | skb->dev = tunnel->dev; |
502 | dst_release(skb->dst); | 502 | dst_release(skb->dst); |
503 | skb->dst = NULL; | 503 | skb->dst = NULL; |
@@ -537,7 +537,7 @@ static inline __be32 try_6to4(struct in6_addr *v6dst) | |||
537 | static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 537 | static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
538 | { | 538 | { |
539 | struct ip_tunnel *tunnel = netdev_priv(dev); | 539 | struct ip_tunnel *tunnel = netdev_priv(dev); |
540 | struct net_device_stats *stats = &tunnel->stat; | 540 | struct net_device_stats *stats = &tunnel->dev->stats; |
541 | struct iphdr *tiph = &tunnel->parms.iph; | 541 | struct iphdr *tiph = &tunnel->parms.iph; |
542 | struct ipv6hdr *iph6 = ipv6_hdr(skb); | 542 | struct ipv6hdr *iph6 = ipv6_hdr(skb); |
543 | u8 tos = tunnel->parms.iph.tos; | 543 | u8 tos = tunnel->parms.iph.tos; |
@@ -551,7 +551,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
551 | int addr_type; | 551 | int addr_type; |
552 | 552 | ||
553 | if (tunnel->recursion++) { | 553 | if (tunnel->recursion++) { |
554 | tunnel->stat.collisions++; | 554 | stats->collisions++; |
555 | goto tx_error; | 555 | goto tx_error; |
556 | } | 556 | } |
557 | 557 | ||
@@ -618,20 +618,20 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
618 | .oif = tunnel->parms.link, | 618 | .oif = tunnel->parms.link, |
619 | .proto = IPPROTO_IPV6 }; | 619 | .proto = IPPROTO_IPV6 }; |
620 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 620 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { |
621 | tunnel->stat.tx_carrier_errors++; | 621 | stats->tx_carrier_errors++; |
622 | goto tx_error_icmp; | 622 | goto tx_error_icmp; |
623 | } | 623 | } |
624 | } | 624 | } |
625 | if (rt->rt_type != RTN_UNICAST) { | 625 | if (rt->rt_type != RTN_UNICAST) { |
626 | ip_rt_put(rt); | 626 | ip_rt_put(rt); |
627 | tunnel->stat.tx_carrier_errors++; | 627 | stats->tx_carrier_errors++; |
628 | goto tx_error_icmp; | 628 | goto tx_error_icmp; |
629 | } | 629 | } |
630 | tdev = rt->u.dst.dev; | 630 | tdev = rt->u.dst.dev; |
631 | 631 | ||
632 | if (tdev == dev) { | 632 | if (tdev == dev) { |
633 | ip_rt_put(rt); | 633 | ip_rt_put(rt); |
634 | tunnel->stat.collisions++; | 634 | stats->collisions++; |
635 | goto tx_error; | 635 | goto tx_error; |
636 | } | 636 | } |
637 | 637 | ||
@@ -641,7 +641,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
641 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 641 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; |
642 | 642 | ||
643 | if (mtu < 68) { | 643 | if (mtu < 68) { |
644 | tunnel->stat.collisions++; | 644 | stats->collisions++; |
645 | ip_rt_put(rt); | 645 | ip_rt_put(rt); |
646 | goto tx_error; | 646 | goto tx_error; |
647 | } | 647 | } |
@@ -916,11 +916,6 @@ done: | |||
916 | return err; | 916 | return err; |
917 | } | 917 | } |
918 | 918 | ||
919 | static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) | ||
920 | { | ||
921 | return &(((struct ip_tunnel*)netdev_priv(dev))->stat); | ||
922 | } | ||
923 | |||
924 | static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 919 | static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) |
925 | { | 920 | { |
926 | if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) | 921 | if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) |
@@ -934,7 +929,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
934 | dev->uninit = ipip6_tunnel_uninit; | 929 | dev->uninit = ipip6_tunnel_uninit; |
935 | dev->destructor = free_netdev; | 930 | dev->destructor = free_netdev; |
936 | dev->hard_start_xmit = ipip6_tunnel_xmit; | 931 | dev->hard_start_xmit = ipip6_tunnel_xmit; |
937 | dev->get_stats = ipip6_tunnel_get_stats; | ||
938 | dev->do_ioctl = ipip6_tunnel_ioctl; | 932 | dev->do_ioctl = ipip6_tunnel_ioctl; |
939 | dev->change_mtu = ipip6_tunnel_change_mtu; | 933 | dev->change_mtu = ipip6_tunnel_change_mtu; |
940 | 934 | ||
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 3804dcbbfab0..5c99274558bf 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -37,6 +37,10 @@ static ctl_table ipv6_table_template[] = { | |||
37 | .mode = 0644, | 37 | .mode = 0644, |
38 | .proc_handler = &proc_dointvec | 38 | .proc_handler = &proc_dointvec |
39 | }, | 39 | }, |
40 | { .ctl_name = 0 } | ||
41 | }; | ||
42 | |||
43 | static ctl_table ipv6_table[] = { | ||
40 | { | 44 | { |
41 | .ctl_name = NET_IPV6_MLD_MAX_MSF, | 45 | .ctl_name = NET_IPV6_MLD_MAX_MSF, |
42 | .procname = "mld_max_msf", | 46 | .procname = "mld_max_msf", |
@@ -80,12 +84,6 @@ static int ipv6_sysctl_net_init(struct net *net) | |||
80 | 84 | ||
81 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; | 85 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; |
82 | 86 | ||
83 | /* We don't want this value to be per namespace, it should be global | ||
84 | to all namespaces, so make it read-only when we are not in the | ||
85 | init network namespace */ | ||
86 | if (net != &init_net) | ||
87 | ipv6_table[3].mode = 0444; | ||
88 | |||
89 | net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, | 87 | net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, |
90 | ipv6_table); | 88 | ipv6_table); |
91 | if (!net->ipv6.sysctl.table) | 89 | if (!net->ipv6.sysctl.table) |
@@ -126,12 +124,29 @@ static struct pernet_operations ipv6_sysctl_net_ops = { | |||
126 | .exit = ipv6_sysctl_net_exit, | 124 | .exit = ipv6_sysctl_net_exit, |
127 | }; | 125 | }; |
128 | 126 | ||
127 | static struct ctl_table_header *ip6_header; | ||
128 | |||
129 | int ipv6_sysctl_register(void) | 129 | int ipv6_sysctl_register(void) |
130 | { | 130 | { |
131 | return register_pernet_subsys(&ipv6_sysctl_net_ops); | 131 | int err = -ENOMEM;; |
132 | |||
133 | ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_table); | ||
134 | if (ip6_header == NULL) | ||
135 | goto out; | ||
136 | |||
137 | err = register_pernet_subsys(&ipv6_sysctl_net_ops); | ||
138 | if (err) | ||
139 | goto err_pernet; | ||
140 | out: | ||
141 | return err; | ||
142 | |||
143 | err_pernet: | ||
144 | unregister_net_sysctl_table(ip6_header); | ||
145 | goto out; | ||
132 | } | 146 | } |
133 | 147 | ||
134 | void ipv6_sysctl_unregister(void) | 148 | void ipv6_sysctl_unregister(void) |
135 | { | 149 | { |
150 | unregister_net_sysctl_table(ip6_header); | ||
136 | unregister_pernet_subsys(&ipv6_sysctl_net_ops); | 151 | unregister_pernet_subsys(&ipv6_sysctl_net_ops); |
137 | } | 152 | } |