aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-10 11:56:46 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-10 11:56:46 -0500
commita8c28d05150f758625c5da38199b247887735e65 (patch)
treecf1f40f49bc0b1049b7d0f63ba5622028f07b924 /net
parentd0b0268fddea3235a8df35e52167c3b206bf2f5a (diff)
parente3eaa9910b380530cfd2c0670fcd3f627674da8a (diff)
Merge branch 'master' of git://dev.medozas.de/linux
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/arp_tables.c7
-rw-r--r--net/ipv4/netfilter/arptable_filter.c95
-rw-r--r--net/ipv4/netfilter/ip_tables.c7
-rw-r--r--net/ipv4/netfilter/iptable_filter.c122
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c154
-rw-r--r--net/ipv4/netfilter/iptable_raw.c94
-rw-r--r--net/ipv4/netfilter/iptable_security.c115
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c39
-rw-r--r--net/ipv6/netfilter/ip6_tables.c7
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c111
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c131
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c84
-rw-r--r--net/ipv6/netfilter/ip6table_security.c107
-rw-r--r--net/netfilter/x_tables.c58
-rw-r--r--net/netfilter/xt_repldata.h35
15 files changed, 341 insertions, 825 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 90203e1b9187..72723ea1054b 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -27,6 +27,7 @@
27 27
28#include <linux/netfilter/x_tables.h> 28#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter_arp/arp_tables.h> 29#include <linux/netfilter_arp/arp_tables.h>
30#include "../../netfilter/xt_repldata.h"
30 31
31MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
32MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 33MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
@@ -58,6 +59,12 @@ do { \
58#define ARP_NF_ASSERT(x) 59#define ARP_NF_ASSERT(x)
59#endif 60#endif
60 61
62void *arpt_alloc_initial_table(const struct xt_table *info)
63{
64 return xt_alloc_initial_table(arpt, ARPT);
65}
66EXPORT_SYMBOL_GPL(arpt_alloc_initial_table);
67
61static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 68static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
62 const char *hdr_addr, int len) 69 const char *hdr_addr, int len)
63{ 70{
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 97337601827a..bfe26f32b930 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/netfilter/x_tables.h>
9#include <linux/netfilter_arp/arp_tables.h> 10#include <linux/netfilter_arp/arp_tables.h>
10 11
11MODULE_LICENSE("GPL"); 12MODULE_LICENSE("GPL");
@@ -15,93 +16,37 @@ MODULE_DESCRIPTION("arptables filter table");
15#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ 16#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
16 (1 << NF_ARP_FORWARD)) 17 (1 << NF_ARP_FORWARD))
17 18
18static const struct
19{
20 struct arpt_replace repl;
21 struct arpt_standard entries[3];
22 struct arpt_error term;
23} initial_table __net_initdata = {
24 .repl = {
25 .name = "filter",
26 .valid_hooks = FILTER_VALID_HOOKS,
27 .num_entries = 4,
28 .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
29 .hook_entry = {
30 [NF_ARP_IN] = 0,
31 [NF_ARP_OUT] = sizeof(struct arpt_standard),
32 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
33 },
34 .underflow = {
35 [NF_ARP_IN] = 0,
36 [NF_ARP_OUT] = sizeof(struct arpt_standard),
37 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
38 },
39 },
40 .entries = {
41 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
42 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
43 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
44 },
45 .term = ARPT_ERROR_INIT,
46};
47
48static const struct xt_table packet_filter = { 19static const struct xt_table packet_filter = {
49 .name = "filter", 20 .name = "filter",
50 .valid_hooks = FILTER_VALID_HOOKS, 21 .valid_hooks = FILTER_VALID_HOOKS,
51 .me = THIS_MODULE, 22 .me = THIS_MODULE,
52 .af = NFPROTO_ARP, 23 .af = NFPROTO_ARP,
24 .priority = NF_IP_PRI_FILTER,
53}; 25};
54 26
55/* The work comes in here from netfilter.c */ 27/* The work comes in here from netfilter.c */
56static unsigned int arpt_in_hook(unsigned int hook, 28static unsigned int
57 struct sk_buff *skb, 29arptable_filter_hook(unsigned int hook, struct sk_buff *skb,
58 const struct net_device *in, 30 const struct net_device *in, const struct net_device *out,
59 const struct net_device *out, 31 int (*okfn)(struct sk_buff *))
60 int (*okfn)(struct sk_buff *))
61{ 32{
62 return arpt_do_table(skb, hook, in, out, 33 const struct net *net = dev_net((in != NULL) ? in : out);
63 dev_net(in)->ipv4.arptable_filter);
64}
65 34
66static unsigned int arpt_out_hook(unsigned int hook, 35 return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter);
67 struct sk_buff *skb,
68 const struct net_device *in,
69 const struct net_device *out,
70 int (*okfn)(struct sk_buff *))
71{
72 return arpt_do_table(skb, hook, in, out,
73 dev_net(out)->ipv4.arptable_filter);
74} 36}
75 37
76static struct nf_hook_ops arpt_ops[] __read_mostly = { 38static struct nf_hook_ops *arpfilter_ops __read_mostly;
77 {
78 .hook = arpt_in_hook,
79 .owner = THIS_MODULE,
80 .pf = NFPROTO_ARP,
81 .hooknum = NF_ARP_IN,
82 .priority = NF_IP_PRI_FILTER,
83 },
84 {
85 .hook = arpt_out_hook,
86 .owner = THIS_MODULE,
87 .pf = NFPROTO_ARP,
88 .hooknum = NF_ARP_OUT,
89 .priority = NF_IP_PRI_FILTER,
90 },
91 {
92 .hook = arpt_in_hook,
93 .owner = THIS_MODULE,
94 .pf = NFPROTO_ARP,
95 .hooknum = NF_ARP_FORWARD,
96 .priority = NF_IP_PRI_FILTER,
97 },
98};
99 39
100static int __net_init arptable_filter_net_init(struct net *net) 40static int __net_init arptable_filter_net_init(struct net *net)
101{ 41{
102 /* Register table */ 42 struct arpt_replace *repl;
43
44 repl = arpt_alloc_initial_table(&packet_filter);
45 if (repl == NULL)
46 return -ENOMEM;
103 net->ipv4.arptable_filter = 47 net->ipv4.arptable_filter =
104 arpt_register_table(net, &packet_filter, &initial_table.repl); 48 arpt_register_table(net, &packet_filter, repl);
49 kfree(repl);
105 if (IS_ERR(net->ipv4.arptable_filter)) 50 if (IS_ERR(net->ipv4.arptable_filter))
106 return PTR_ERR(net->ipv4.arptable_filter); 51 return PTR_ERR(net->ipv4.arptable_filter);
107 return 0; 52 return 0;
@@ -125,9 +70,11 @@ static int __init arptable_filter_init(void)
125 if (ret < 0) 70 if (ret < 0)
126 return ret; 71 return ret;
127 72
128 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 73 arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
129 if (ret < 0) 74 if (IS_ERR(arpfilter_ops)) {
75 ret = PTR_ERR(arpfilter_ops);
130 goto cleanup_table; 76 goto cleanup_table;
77 }
131 return ret; 78 return ret;
132 79
133cleanup_table: 80cleanup_table:
@@ -137,7 +84,7 @@ cleanup_table:
137 84
138static void __exit arptable_filter_fini(void) 85static void __exit arptable_filter_fini(void)
139{ 86{
140 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 87 xt_hook_unlink(&packet_filter, arpfilter_ops);
141 unregister_pernet_subsys(&arptable_filter_net_ops); 88 unregister_pernet_subsys(&arptable_filter_net_ops);
142} 89}
143 90
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 5bf7de1527a5..2057b1bb6178 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -28,6 +28,7 @@
28#include <linux/netfilter/x_tables.h> 28#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter_ipv4/ip_tables.h> 29#include <linux/netfilter_ipv4/ip_tables.h>
30#include <net/netfilter/nf_log.h> 30#include <net/netfilter/nf_log.h>
31#include "../../netfilter/xt_repldata.h"
31 32
32MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 34MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -66,6 +67,12 @@ do { \
66#define inline 67#define inline
67#endif 68#endif
68 69
70void *ipt_alloc_initial_table(const struct xt_table *info)
71{
72 return xt_alloc_initial_table(ipt, IPT);
73}
74EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
75
69/* 76/*
70 We keep a set of rules for each CPU, so we can avoid write-locking 77 We keep a set of rules for each CPU, so we can avoid write-locking
71 them in the softirq when updating the counters and therefore 78 them in the softirq when updating the counters and therefore
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index dee90eb8aa47..c8dc9800d620 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -23,104 +23,32 @@ MODULE_DESCRIPTION("iptables filter table");
23 (1 << NF_INET_FORWARD) | \ 23 (1 << NF_INET_FORWARD) | \
24 (1 << NF_INET_LOCAL_OUT)) 24 (1 << NF_INET_LOCAL_OUT))
25 25
26static struct
27{
28 struct ipt_replace repl;
29 struct ipt_standard entries[3];
30 struct ipt_error term;
31} initial_table __net_initdata = {
32 .repl = {
33 .name = "filter",
34 .valid_hooks = FILTER_VALID_HOOKS,
35 .num_entries = 4,
36 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
37 .hook_entry = {
38 [NF_INET_LOCAL_IN] = 0,
39 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
40 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
41 },
42 .underflow = {
43 [NF_INET_LOCAL_IN] = 0,
44 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
45 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
46 },
47 },
48 .entries = {
49 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
50 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
51 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
52 },
53 .term = IPT_ERROR_INIT, /* ERROR */
54};
55
56static const struct xt_table packet_filter = { 26static const struct xt_table packet_filter = {
57 .name = "filter", 27 .name = "filter",
58 .valid_hooks = FILTER_VALID_HOOKS, 28 .valid_hooks = FILTER_VALID_HOOKS,
59 .me = THIS_MODULE, 29 .me = THIS_MODULE,
60 .af = NFPROTO_IPV4, 30 .af = NFPROTO_IPV4,
31 .priority = NF_IP_PRI_FILTER,
61}; 32};
62 33
63/* The work comes in here from netfilter.c. */
64static unsigned int
65ipt_local_in_hook(unsigned int hook,
66 struct sk_buff *skb,
67 const struct net_device *in,
68 const struct net_device *out,
69 int (*okfn)(struct sk_buff *))
70{
71 return ipt_do_table(skb, hook, in, out,
72 dev_net(in)->ipv4.iptable_filter);
73}
74
75static unsigned int 34static unsigned int
76ipt_hook(unsigned int hook, 35iptable_filter_hook(unsigned int hook, struct sk_buff *skb,
77 struct sk_buff *skb, 36 const struct net_device *in, const struct net_device *out,
78 const struct net_device *in, 37 int (*okfn)(struct sk_buff *))
79 const struct net_device *out,
80 int (*okfn)(struct sk_buff *))
81{ 38{
82 return ipt_do_table(skb, hook, in, out, 39 const struct net *net;
83 dev_net(in)->ipv4.iptable_filter);
84}
85 40
86static unsigned int 41 if (hook == NF_INET_LOCAL_OUT &&
87ipt_local_out_hook(unsigned int hook, 42 (skb->len < sizeof(struct iphdr) ||
88 struct sk_buff *skb, 43 ip_hdrlen(skb) < sizeof(struct iphdr)))
89 const struct net_device *in, 44 /* root is playing with raw sockets. */
90 const struct net_device *out,
91 int (*okfn)(struct sk_buff *))
92{
93 /* root is playing with raw sockets. */
94 if (skb->len < sizeof(struct iphdr) ||
95 ip_hdrlen(skb) < sizeof(struct iphdr))
96 return NF_ACCEPT; 45 return NF_ACCEPT;
97 return ipt_do_table(skb, hook, in, out, 46
98 dev_net(out)->ipv4.iptable_filter); 47 net = dev_net((in != NULL) ? in : out);
48 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter);
99} 49}
100 50
101static struct nf_hook_ops ipt_ops[] __read_mostly = { 51static struct nf_hook_ops *filter_ops __read_mostly;
102 {
103 .hook = ipt_local_in_hook,
104 .owner = THIS_MODULE,
105 .pf = NFPROTO_IPV4,
106 .hooknum = NF_INET_LOCAL_IN,
107 .priority = NF_IP_PRI_FILTER,
108 },
109 {
110 .hook = ipt_hook,
111 .owner = THIS_MODULE,
112 .pf = NFPROTO_IPV4,
113 .hooknum = NF_INET_FORWARD,
114 .priority = NF_IP_PRI_FILTER,
115 },
116 {
117 .hook = ipt_local_out_hook,
118 .owner = THIS_MODULE,
119 .pf = NFPROTO_IPV4,
120 .hooknum = NF_INET_LOCAL_OUT,
121 .priority = NF_IP_PRI_FILTER,
122 },
123};
124 52
125/* Default to forward because I got too much mail already. */ 53/* Default to forward because I got too much mail already. */
126static int forward = NF_ACCEPT; 54static int forward = NF_ACCEPT;
@@ -128,9 +56,18 @@ module_param(forward, bool, 0000);
128 56
129static int __net_init iptable_filter_net_init(struct net *net) 57static int __net_init iptable_filter_net_init(struct net *net)
130{ 58{
131 /* Register table */ 59 struct ipt_replace *repl;
60
61 repl = ipt_alloc_initial_table(&packet_filter);
62 if (repl == NULL)
63 return -ENOMEM;
64 /* Entry 1 is the FORWARD hook */
65 ((struct ipt_standard *)repl->entries)[1].target.verdict =
66 -forward - 1;
67
132 net->ipv4.iptable_filter = 68 net->ipv4.iptable_filter =
133 ipt_register_table(net, &packet_filter, &initial_table.repl); 69 ipt_register_table(net, &packet_filter, repl);
70 kfree(repl);
134 if (IS_ERR(net->ipv4.iptable_filter)) 71 if (IS_ERR(net->ipv4.iptable_filter))
135 return PTR_ERR(net->ipv4.iptable_filter); 72 return PTR_ERR(net->ipv4.iptable_filter);
136 return 0; 73 return 0;
@@ -155,17 +92,16 @@ static int __init iptable_filter_init(void)
155 return -EINVAL; 92 return -EINVAL;
156 } 93 }
157 94
158 /* Entry 1 is the FORWARD hook */
159 initial_table.entries[1].target.verdict = -forward - 1;
160
161 ret = register_pernet_subsys(&iptable_filter_net_ops); 95 ret = register_pernet_subsys(&iptable_filter_net_ops);
162 if (ret < 0) 96 if (ret < 0)
163 return ret; 97 return ret;
164 98
165 /* Register hooks */ 99 /* Register hooks */
166 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 100 filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
167 if (ret < 0) 101 if (IS_ERR(filter_ops)) {
102 ret = PTR_ERR(filter_ops);
168 goto cleanup_table; 103 goto cleanup_table;
104 }
169 105
170 return ret; 106 return ret;
171 107
@@ -176,7 +112,7 @@ static int __init iptable_filter_init(void)
176 112
177static void __exit iptable_filter_fini(void) 113static void __exit iptable_filter_fini(void)
178{ 114{
179 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 115 xt_hook_unlink(&packet_filter, filter_ops);
180 unregister_pernet_subsys(&iptable_filter_net_ops); 116 unregister_pernet_subsys(&iptable_filter_net_ops);
181} 117}
182 118
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index e07bf242343a..58d7097baa3d 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -27,95 +27,14 @@ MODULE_DESCRIPTION("iptables mangle table");
27 (1 << NF_INET_LOCAL_OUT) | \ 27 (1 << NF_INET_LOCAL_OUT) | \
28 (1 << NF_INET_POST_ROUTING)) 28 (1 << NF_INET_POST_ROUTING))
29 29
30/* Ouch - five different hooks? Maybe this should be a config option..... -- BC */
31static const struct
32{
33 struct ipt_replace repl;
34 struct ipt_standard entries[5];
35 struct ipt_error term;
36} initial_table __net_initdata = {
37 .repl = {
38 .name = "mangle",
39 .valid_hooks = MANGLE_VALID_HOOKS,
40 .num_entries = 6,
41 .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
42 .hook_entry = {
43 [NF_INET_PRE_ROUTING] = 0,
44 [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
45 [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
46 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
47 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
48 },
49 .underflow = {
50 [NF_INET_PRE_ROUTING] = 0,
51 [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
52 [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
53 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
54 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
55 },
56 },
57 .entries = {
58 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
59 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
60 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
61 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
62 IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
63 },
64 .term = IPT_ERROR_INIT, /* ERROR */
65};
66
67static const struct xt_table packet_mangler = { 30static const struct xt_table packet_mangler = {
68 .name = "mangle", 31 .name = "mangle",
69 .valid_hooks = MANGLE_VALID_HOOKS, 32 .valid_hooks = MANGLE_VALID_HOOKS,
70 .me = THIS_MODULE, 33 .me = THIS_MODULE,
71 .af = NFPROTO_IPV4, 34 .af = NFPROTO_IPV4,
35 .priority = NF_IP_PRI_MANGLE,
72}; 36};
73 37
74/* The work comes in here from netfilter.c. */
75static unsigned int
76ipt_pre_routing_hook(unsigned int hook,
77 struct sk_buff *skb,
78 const struct net_device *in,
79 const struct net_device *out,
80 int (*okfn)(struct sk_buff *))
81{
82 return ipt_do_table(skb, hook, in, out,
83 dev_net(in)->ipv4.iptable_mangle);
84}
85
86static unsigned int
87ipt_post_routing_hook(unsigned int hook,
88 struct sk_buff *skb,
89 const struct net_device *in,
90 const struct net_device *out,
91 int (*okfn)(struct sk_buff *))
92{
93 return ipt_do_table(skb, hook, in, out,
94 dev_net(out)->ipv4.iptable_mangle);
95}
96
97static unsigned int
98ipt_local_in_hook(unsigned int hook,
99 struct sk_buff *skb,
100 const struct net_device *in,
101 const struct net_device *out,
102 int (*okfn)(struct sk_buff *))
103{
104 return ipt_do_table(skb, hook, in, out,
105 dev_net(in)->ipv4.iptable_mangle);
106}
107
108static unsigned int
109ipt_forward_hook(unsigned int hook,
110 struct sk_buff *skb,
111 const struct net_device *in,
112 const struct net_device *out,
113 int (*okfn)(struct sk_buff *))
114{
115 return ipt_do_table(skb, hook, in, out,
116 dev_net(in)->ipv4.iptable_mangle);
117}
118
119static unsigned int 38static unsigned int
120ipt_local_hook(unsigned int hook, 39ipt_local_hook(unsigned int hook,
121 struct sk_buff *skb, 40 struct sk_buff *skb,
@@ -158,49 +77,34 @@ ipt_local_hook(unsigned int hook,
158 return ret; 77 return ret;
159} 78}
160 79
161static struct nf_hook_ops ipt_ops[] __read_mostly = { 80/* The work comes in here from netfilter.c. */
162 { 81static unsigned int
163 .hook = ipt_pre_routing_hook, 82iptable_mangle_hook(unsigned int hook,
164 .owner = THIS_MODULE, 83 struct sk_buff *skb,
165 .pf = NFPROTO_IPV4, 84 const struct net_device *in,
166 .hooknum = NF_INET_PRE_ROUTING, 85 const struct net_device *out,
167 .priority = NF_IP_PRI_MANGLE, 86 int (*okfn)(struct sk_buff *))
168 }, 87{
169 { 88 if (hook == NF_INET_LOCAL_OUT)
170 .hook = ipt_local_in_hook, 89 return ipt_local_hook(hook, skb, in, out, okfn);
171 .owner = THIS_MODULE, 90
172 .pf = NFPROTO_IPV4, 91 /* PREROUTING/INPUT/FORWARD: */
173 .hooknum = NF_INET_LOCAL_IN, 92 return ipt_do_table(skb, hook, in, out,
174 .priority = NF_IP_PRI_MANGLE, 93 dev_net(in)->ipv4.iptable_mangle);
175 }, 94}
176 { 95
177 .hook = ipt_forward_hook, 96static struct nf_hook_ops *mangle_ops __read_mostly;
178 .owner = THIS_MODULE,
179 .pf = NFPROTO_IPV4,
180 .hooknum = NF_INET_FORWARD,
181 .priority = NF_IP_PRI_MANGLE,
182 },
183 {
184 .hook = ipt_local_hook,
185 .owner = THIS_MODULE,
186 .pf = NFPROTO_IPV4,
187 .hooknum = NF_INET_LOCAL_OUT,
188 .priority = NF_IP_PRI_MANGLE,
189 },
190 {
191 .hook = ipt_post_routing_hook,
192 .owner = THIS_MODULE,
193 .pf = NFPROTO_IPV4,
194 .hooknum = NF_INET_POST_ROUTING,
195 .priority = NF_IP_PRI_MANGLE,
196 },
197};
198 97
199static int __net_init iptable_mangle_net_init(struct net *net) 98static int __net_init iptable_mangle_net_init(struct net *net)
200{ 99{
201 /* Register table */ 100 struct ipt_replace *repl;
101
102 repl = ipt_alloc_initial_table(&packet_mangler);
103 if (repl == NULL)
104 return -ENOMEM;
202 net->ipv4.iptable_mangle = 105 net->ipv4.iptable_mangle =
203 ipt_register_table(net, &packet_mangler, &initial_table.repl); 106 ipt_register_table(net, &packet_mangler, repl);
107 kfree(repl);
204 if (IS_ERR(net->ipv4.iptable_mangle)) 108 if (IS_ERR(net->ipv4.iptable_mangle))
205 return PTR_ERR(net->ipv4.iptable_mangle); 109 return PTR_ERR(net->ipv4.iptable_mangle);
206 return 0; 110 return 0;
@@ -225,9 +129,11 @@ static int __init iptable_mangle_init(void)
225 return ret; 129 return ret;
226 130
227 /* Register hooks */ 131 /* Register hooks */
228 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 132 mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
229 if (ret < 0) 133 if (IS_ERR(mangle_ops)) {
134 ret = PTR_ERR(mangle_ops);
230 goto cleanup_table; 135 goto cleanup_table;
136 }
231 137
232 return ret; 138 return ret;
233 139
@@ -238,7 +144,7 @@ static int __init iptable_mangle_init(void)
238 144
239static void __exit iptable_mangle_fini(void) 145static void __exit iptable_mangle_fini(void)
240{ 146{
241 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 147 xt_hook_unlink(&packet_mangler, mangle_ops);
242 unregister_pernet_subsys(&iptable_mangle_net_ops); 148 unregister_pernet_subsys(&iptable_mangle_net_ops);
243} 149}
244 150
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 40f2b9f611a2..06fb9d11953c 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -9,90 +9,44 @@
9 9
10#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 10#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
11 11
12static const struct
13{
14 struct ipt_replace repl;
15 struct ipt_standard entries[2];
16 struct ipt_error term;
17} initial_table __net_initdata = {
18 .repl = {
19 .name = "raw",
20 .valid_hooks = RAW_VALID_HOOKS,
21 .num_entries = 3,
22 .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
23 .hook_entry = {
24 [NF_INET_PRE_ROUTING] = 0,
25 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
26 },
27 .underflow = {
28 [NF_INET_PRE_ROUTING] = 0,
29 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
30 },
31 },
32 .entries = {
33 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
34 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
35 },
36 .term = IPT_ERROR_INIT, /* ERROR */
37};
38
39static const struct xt_table packet_raw = { 12static const struct xt_table packet_raw = {
40 .name = "raw", 13 .name = "raw",
41 .valid_hooks = RAW_VALID_HOOKS, 14 .valid_hooks = RAW_VALID_HOOKS,
42 .me = THIS_MODULE, 15 .me = THIS_MODULE,
43 .af = NFPROTO_IPV4, 16 .af = NFPROTO_IPV4,
17 .priority = NF_IP_PRI_RAW,
44}; 18};
45 19
46/* The work comes in here from netfilter.c. */ 20/* The work comes in here from netfilter.c. */
47static unsigned int 21static unsigned int
48ipt_hook(unsigned int hook, 22iptable_raw_hook(unsigned int hook, struct sk_buff *skb,
49 struct sk_buff *skb, 23 const struct net_device *in, const struct net_device *out,
50 const struct net_device *in, 24 int (*okfn)(struct sk_buff *))
51 const struct net_device *out,
52 int (*okfn)(struct sk_buff *))
53{ 25{
54 return ipt_do_table(skb, hook, in, out, 26 const struct net *net;
55 dev_net(in)->ipv4.iptable_raw);
56}
57 27
58static unsigned int 28 if (hook == NF_INET_LOCAL_OUT &&
59ipt_local_hook(unsigned int hook, 29 (skb->len < sizeof(struct iphdr) ||
60 struct sk_buff *skb, 30 ip_hdrlen(skb) < sizeof(struct iphdr)))
61 const struct net_device *in, 31 /* root is playing with raw sockets. */
62 const struct net_device *out,
63 int (*okfn)(struct sk_buff *))
64{
65 /* root is playing with raw sockets. */
66 if (skb->len < sizeof(struct iphdr) ||
67 ip_hdrlen(skb) < sizeof(struct iphdr))
68 return NF_ACCEPT; 32 return NF_ACCEPT;
69 return ipt_do_table(skb, hook, in, out, 33
70 dev_net(out)->ipv4.iptable_raw); 34 net = dev_net((in != NULL) ? in : out);
35 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw);
71} 36}
72 37
73/* 'raw' is the very first table. */ 38static struct nf_hook_ops *rawtable_ops __read_mostly;
74static struct nf_hook_ops ipt_ops[] __read_mostly = {
75 {
76 .hook = ipt_hook,
77 .pf = NFPROTO_IPV4,
78 .hooknum = NF_INET_PRE_ROUTING,
79 .priority = NF_IP_PRI_RAW,
80 .owner = THIS_MODULE,
81 },
82 {
83 .hook = ipt_local_hook,
84 .pf = NFPROTO_IPV4,
85 .hooknum = NF_INET_LOCAL_OUT,
86 .priority = NF_IP_PRI_RAW,
87 .owner = THIS_MODULE,
88 },
89};
90 39
91static int __net_init iptable_raw_net_init(struct net *net) 40static int __net_init iptable_raw_net_init(struct net *net)
92{ 41{
93 /* Register table */ 42 struct ipt_replace *repl;
43
44 repl = ipt_alloc_initial_table(&packet_raw);
45 if (repl == NULL)
46 return -ENOMEM;
94 net->ipv4.iptable_raw = 47 net->ipv4.iptable_raw =
95 ipt_register_table(net, &packet_raw, &initial_table.repl); 48 ipt_register_table(net, &packet_raw, repl);
49 kfree(repl);
96 if (IS_ERR(net->ipv4.iptable_raw)) 50 if (IS_ERR(net->ipv4.iptable_raw))
97 return PTR_ERR(net->ipv4.iptable_raw); 51 return PTR_ERR(net->ipv4.iptable_raw);
98 return 0; 52 return 0;
@@ -117,9 +71,11 @@ static int __init iptable_raw_init(void)
117 return ret; 71 return ret;
118 72
119 /* Register hooks */ 73 /* Register hooks */
120 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 74 rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
121 if (ret < 0) 75 if (IS_ERR(rawtable_ops)) {
76 ret = PTR_ERR(rawtable_ops);
122 goto cleanup_table; 77 goto cleanup_table;
78 }
123 79
124 return ret; 80 return ret;
125 81
@@ -130,7 +86,7 @@ static int __init iptable_raw_init(void)
130 86
131static void __exit iptable_raw_fini(void) 87static void __exit iptable_raw_fini(void)
132{ 88{
133 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 89 xt_hook_unlink(&packet_raw, rawtable_ops);
134 unregister_pernet_subsys(&iptable_raw_net_ops); 90 unregister_pernet_subsys(&iptable_raw_net_ops);
135} 91}
136 92
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index 7ce2366e4305..cce2f64e6f21 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -27,109 +27,44 @@ MODULE_DESCRIPTION("iptables security table, for MAC rules");
27 (1 << NF_INET_FORWARD) | \ 27 (1 << NF_INET_FORWARD) | \
28 (1 << NF_INET_LOCAL_OUT) 28 (1 << NF_INET_LOCAL_OUT)
29 29
30static const struct
31{
32 struct ipt_replace repl;
33 struct ipt_standard entries[3];
34 struct ipt_error term;
35} initial_table __net_initdata = {
36 .repl = {
37 .name = "security",
38 .valid_hooks = SECURITY_VALID_HOOKS,
39 .num_entries = 4,
40 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
41 .hook_entry = {
42 [NF_INET_LOCAL_IN] = 0,
43 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
44 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
45 },
46 .underflow = {
47 [NF_INET_LOCAL_IN] = 0,
48 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
49 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
50 },
51 },
52 .entries = {
53 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
54 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
55 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
56 },
57 .term = IPT_ERROR_INIT, /* ERROR */
58};
59
60static const struct xt_table security_table = { 30static const struct xt_table security_table = {
61 .name = "security", 31 .name = "security",
62 .valid_hooks = SECURITY_VALID_HOOKS, 32 .valid_hooks = SECURITY_VALID_HOOKS,
63 .me = THIS_MODULE, 33 .me = THIS_MODULE,
64 .af = NFPROTO_IPV4, 34 .af = NFPROTO_IPV4,
35 .priority = NF_IP_PRI_SECURITY,
65}; 36};
66 37
67static unsigned int 38static unsigned int
68ipt_local_in_hook(unsigned int hook, 39iptable_security_hook(unsigned int hook, struct sk_buff *skb,
69 struct sk_buff *skb, 40 const struct net_device *in,
70 const struct net_device *in, 41 const struct net_device *out,
71 const struct net_device *out, 42 int (*okfn)(struct sk_buff *))
72 int (*okfn)(struct sk_buff *))
73{
74 return ipt_do_table(skb, hook, in, out,
75 dev_net(in)->ipv4.iptable_security);
76}
77
78static unsigned int
79ipt_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{ 43{
85 return ipt_do_table(skb, hook, in, out, 44 const struct net *net;
86 dev_net(in)->ipv4.iptable_security);
87}
88 45
89static unsigned int 46 if (hook == NF_INET_LOCAL_OUT &&
90ipt_local_out_hook(unsigned int hook, 47 (skb->len < sizeof(struct iphdr) ||
91 struct sk_buff *skb, 48 ip_hdrlen(skb) < sizeof(struct iphdr)))
92 const struct net_device *in, 49 /* Somebody is playing with raw sockets. */
93 const struct net_device *out,
94 int (*okfn)(struct sk_buff *))
95{
96 /* Somebody is playing with raw sockets. */
97 if (skb->len < sizeof(struct iphdr) ||
98 ip_hdrlen(skb) < sizeof(struct iphdr))
99 return NF_ACCEPT; 50 return NF_ACCEPT;
100 return ipt_do_table(skb, hook, in, out, 51
101 dev_net(out)->ipv4.iptable_security); 52 net = dev_net((in != NULL) ? in : out);
53 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security);
102} 54}
103 55
104static struct nf_hook_ops ipt_ops[] __read_mostly = { 56static struct nf_hook_ops *sectbl_ops __read_mostly;
105 {
106 .hook = ipt_local_in_hook,
107 .owner = THIS_MODULE,
108 .pf = NFPROTO_IPV4,
109 .hooknum = NF_INET_LOCAL_IN,
110 .priority = NF_IP_PRI_SECURITY,
111 },
112 {
113 .hook = ipt_forward_hook,
114 .owner = THIS_MODULE,
115 .pf = NFPROTO_IPV4,
116 .hooknum = NF_INET_FORWARD,
117 .priority = NF_IP_PRI_SECURITY,
118 },
119 {
120 .hook = ipt_local_out_hook,
121 .owner = THIS_MODULE,
122 .pf = NFPROTO_IPV4,
123 .hooknum = NF_INET_LOCAL_OUT,
124 .priority = NF_IP_PRI_SECURITY,
125 },
126};
127 57
128static int __net_init iptable_security_net_init(struct net *net) 58static int __net_init iptable_security_net_init(struct net *net)
129{ 59{
130 net->ipv4.iptable_security = 60 struct ipt_replace *repl;
131 ipt_register_table(net, &security_table, &initial_table.repl);
132 61
62 repl = ipt_alloc_initial_table(&security_table);
63 if (repl == NULL)
64 return -ENOMEM;
65 net->ipv4.iptable_security =
66 ipt_register_table(net, &security_table, repl);
67 kfree(repl);
133 if (IS_ERR(net->ipv4.iptable_security)) 68 if (IS_ERR(net->ipv4.iptable_security))
134 return PTR_ERR(net->ipv4.iptable_security); 69 return PTR_ERR(net->ipv4.iptable_security);
135 70
@@ -154,9 +89,11 @@ static int __init iptable_security_init(void)
154 if (ret < 0) 89 if (ret < 0)
155 return ret; 90 return ret;
156 91
157 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 92 sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
158 if (ret < 0) 93 if (IS_ERR(sectbl_ops)) {
94 ret = PTR_ERR(sectbl_ops);
159 goto cleanup_table; 95 goto cleanup_table;
96 }
160 97
161 return ret; 98 return ret;
162 99
@@ -167,7 +104,7 @@ cleanup_table:
167 104
168static void __exit iptable_security_fini(void) 105static void __exit iptable_security_fini(void)
169{ 106{
170 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 107 xt_hook_unlink(&security_table, sectbl_ops);
171 unregister_pernet_subsys(&iptable_security_net_ops); 108 unregister_pernet_subsys(&iptable_security_net_ops);
172} 109}
173 110
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 85da34fdc755..ab74cc0535e2 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -28,36 +28,6 @@
28 (1 << NF_INET_POST_ROUTING) | \ 28 (1 << NF_INET_POST_ROUTING) | \
29 (1 << NF_INET_LOCAL_OUT)) 29 (1 << NF_INET_LOCAL_OUT))
30 30
31static const struct
32{
33 struct ipt_replace repl;
34 struct ipt_standard entries[3];
35 struct ipt_error term;
36} nat_initial_table __net_initdata = {
37 .repl = {
38 .name = "nat",
39 .valid_hooks = NAT_VALID_HOOKS,
40 .num_entries = 4,
41 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
42 .hook_entry = {
43 [NF_INET_PRE_ROUTING] = 0,
44 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard),
45 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
46 },
47 .underflow = {
48 [NF_INET_PRE_ROUTING] = 0,
49 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard),
50 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
51 },
52 },
53 .entries = {
54 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
55 IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
56 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
57 },
58 .term = IPT_ERROR_INIT, /* ERROR */
59};
60
61static const struct xt_table nat_table = { 31static const struct xt_table nat_table = {
62 .name = "nat", 32 .name = "nat",
63 .valid_hooks = NAT_VALID_HOOKS, 33 .valid_hooks = NAT_VALID_HOOKS,
@@ -186,8 +156,13 @@ static struct xt_target ipt_dnat_reg __read_mostly = {
186 156
187static int __net_init nf_nat_rule_net_init(struct net *net) 157static int __net_init nf_nat_rule_net_init(struct net *net)
188{ 158{
189 net->ipv4.nat_table = ipt_register_table(net, &nat_table, 159 struct ipt_replace *repl;
190 &nat_initial_table.repl); 160
161 repl = ipt_alloc_initial_table(&nat_table);
162 if (repl == NULL)
163 return -ENOMEM;
164 net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl);
165 kfree(repl);
191 if (IS_ERR(net->ipv4.nat_table)) 166 if (IS_ERR(net->ipv4.nat_table))
192 return PTR_ERR(net->ipv4.nat_table); 167 return PTR_ERR(net->ipv4.nat_table);
193 return 0; 168 return 0;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4332f4591482..dcd7825fe7b6 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -29,6 +29,7 @@
29#include <linux/netfilter_ipv6/ip6_tables.h> 29#include <linux/netfilter_ipv6/ip6_tables.h>
30#include <linux/netfilter/x_tables.h> 30#include <linux/netfilter/x_tables.h>
31#include <net/netfilter/nf_log.h> 31#include <net/netfilter/nf_log.h>
32#include "../../netfilter/xt_repldata.h"
32 33
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 35MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -67,6 +68,12 @@ do { \
67#define inline 68#define inline
68#endif 69#endif
69 70
71void *ip6t_alloc_initial_table(const struct xt_table *info)
72{
73 return xt_alloc_initial_table(ip6t, IP6T);
74}
75EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
76
70/* 77/*
71 We keep a set of rules for each CPU, so we can avoid write-locking 78 We keep a set of rules for each CPU, so we can avoid write-locking
72 them in the softirq when updating the counters and therefore 79 them in the softirq when updating the counters and therefore
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 33ddfe53e18d..36b72cafc227 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -21,99 +21,26 @@ MODULE_DESCRIPTION("ip6tables filter table");
21 (1 << NF_INET_FORWARD) | \ 21 (1 << NF_INET_FORWARD) | \
22 (1 << NF_INET_LOCAL_OUT)) 22 (1 << NF_INET_LOCAL_OUT))
23 23
24static struct
25{
26 struct ip6t_replace repl;
27 struct ip6t_standard entries[3];
28 struct ip6t_error term;
29} initial_table __net_initdata = {
30 .repl = {
31 .name = "filter",
32 .valid_hooks = FILTER_VALID_HOOKS,
33 .num_entries = 4,
34 .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
35 .hook_entry = {
36 [NF_INET_LOCAL_IN] = 0,
37 [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
38 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
39 },
40 .underflow = {
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 },
46 .entries = {
47 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
48 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
49 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
50 },
51 .term = IP6T_ERROR_INIT, /* ERROR */
52};
53
54static const struct xt_table packet_filter = { 24static const struct xt_table packet_filter = {
55 .name = "filter", 25 .name = "filter",
56 .valid_hooks = FILTER_VALID_HOOKS, 26 .valid_hooks = FILTER_VALID_HOOKS,
57 .me = THIS_MODULE, 27 .me = THIS_MODULE,
58 .af = NFPROTO_IPV6, 28 .af = NFPROTO_IPV6,
29 .priority = NF_IP6_PRI_FILTER,
59}; 30};
60 31
61/* The work comes in here from netfilter.c. */ 32/* The work comes in here from netfilter.c. */
62static unsigned int 33static unsigned int
63ip6t_in_hook(unsigned int hook, 34ip6table_filter_hook(unsigned int hook, struct sk_buff *skb,
64 struct sk_buff *skb, 35 const struct net_device *in, const struct net_device *out,
65 const struct net_device *in, 36 int (*okfn)(struct sk_buff *))
66 const struct net_device *out,
67 int (*okfn)(struct sk_buff *))
68{
69 return ip6t_do_table(skb, hook, in, out,
70 dev_net(in)->ipv6.ip6table_filter);
71}
72
73static unsigned int
74ip6t_local_out_hook(unsigned int hook,
75 struct sk_buff *skb,
76 const struct net_device *in,
77 const struct net_device *out,
78 int (*okfn)(struct sk_buff *))
79{ 37{
80#if 0 38 const struct net *net = dev_net((in != NULL) ? in : out);
81 /* root is playing with raw sockets. */
82 if (skb->len < sizeof(struct iphdr) ||
83 ip_hdrlen(skb) < sizeof(struct iphdr)) {
84 if (net_ratelimit())
85 printk("ip6t_hook: happy cracking.\n");
86 return NF_ACCEPT;
87 }
88#endif
89 39
90 return ip6t_do_table(skb, hook, in, out, 40 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter);
91 dev_net(out)->ipv6.ip6table_filter);
92} 41}
93 42
94static struct nf_hook_ops ip6t_ops[] __read_mostly = { 43static struct nf_hook_ops *filter_ops __read_mostly;
95 {
96 .hook = ip6t_in_hook,
97 .owner = THIS_MODULE,
98 .pf = NFPROTO_IPV6,
99 .hooknum = NF_INET_LOCAL_IN,
100 .priority = NF_IP6_PRI_FILTER,
101 },
102 {
103 .hook = ip6t_in_hook,
104 .owner = THIS_MODULE,
105 .pf = NFPROTO_IPV6,
106 .hooknum = NF_INET_FORWARD,
107 .priority = NF_IP6_PRI_FILTER,
108 },
109 {
110 .hook = ip6t_local_out_hook,
111 .owner = THIS_MODULE,
112 .pf = NFPROTO_IPV6,
113 .hooknum = NF_INET_LOCAL_OUT,
114 .priority = NF_IP6_PRI_FILTER,
115 },
116};
117 44
118/* Default to forward because I got too much mail already. */ 45/* Default to forward because I got too much mail already. */
119static int forward = NF_ACCEPT; 46static int forward = NF_ACCEPT;
@@ -121,9 +48,18 @@ module_param(forward, bool, 0000);
121 48
122static int __net_init ip6table_filter_net_init(struct net *net) 49static int __net_init ip6table_filter_net_init(struct net *net)
123{ 50{
124 /* Register table */ 51 struct ip6t_replace *repl;
52
53 repl = ip6t_alloc_initial_table(&packet_filter);
54 if (repl == NULL)
55 return -ENOMEM;
56 /* Entry 1 is the FORWARD hook */
57 ((struct ip6t_standard *)repl->entries)[1].target.verdict =
58 -forward - 1;
59
125 net->ipv6.ip6table_filter = 60 net->ipv6.ip6table_filter =
126 ip6t_register_table(net, &packet_filter, &initial_table.repl); 61 ip6t_register_table(net, &packet_filter, repl);
62 kfree(repl);
127 if (IS_ERR(net->ipv6.ip6table_filter)) 63 if (IS_ERR(net->ipv6.ip6table_filter))
128 return PTR_ERR(net->ipv6.ip6table_filter); 64 return PTR_ERR(net->ipv6.ip6table_filter);
129 return 0; 65 return 0;
@@ -148,17 +84,16 @@ static int __init ip6table_filter_init(void)
148 return -EINVAL; 84 return -EINVAL;
149 } 85 }
150 86
151 /* Entry 1 is the FORWARD hook */
152 initial_table.entries[1].target.verdict = -forward - 1;
153
154 ret = register_pernet_subsys(&ip6table_filter_net_ops); 87 ret = register_pernet_subsys(&ip6table_filter_net_ops);
155 if (ret < 0) 88 if (ret < 0)
156 return ret; 89 return ret;
157 90
158 /* Register hooks */ 91 /* Register hooks */
159 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 92 filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
160 if (ret < 0) 93 if (IS_ERR(filter_ops)) {
94 ret = PTR_ERR(filter_ops);
161 goto cleanup_table; 95 goto cleanup_table;
96 }
162 97
163 return ret; 98 return ret;
164 99
@@ -169,7 +104,7 @@ static int __init ip6table_filter_init(void)
169 104
170static void __exit ip6table_filter_fini(void) 105static void __exit ip6table_filter_fini(void)
171{ 106{
172 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 107 xt_hook_unlink(&packet_filter, filter_ops);
173 unregister_pernet_subsys(&ip6table_filter_net_ops); 108 unregister_pernet_subsys(&ip6table_filter_net_ops);
174} 109}
175 110
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 9bc483f000e5..dc803b7e8e54 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -21,76 +21,17 @@ MODULE_DESCRIPTION("ip6tables mangle table");
21 (1 << NF_INET_LOCAL_OUT) | \ 21 (1 << NF_INET_LOCAL_OUT) | \
22 (1 << NF_INET_POST_ROUTING)) 22 (1 << NF_INET_POST_ROUTING))
23 23
24static const struct
25{
26 struct ip6t_replace repl;
27 struct ip6t_standard entries[5];
28 struct ip6t_error term;
29} initial_table __net_initdata = {
30 .repl = {
31 .name = "mangle",
32 .valid_hooks = MANGLE_VALID_HOOKS,
33 .num_entries = 6,
34 .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
35 .hook_entry = {
36 [NF_INET_PRE_ROUTING] = 0,
37 [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard),
38 [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2,
39 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
40 [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
41 },
42 .underflow = {
43 [NF_INET_PRE_ROUTING] = 0,
44 [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard),
45 [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2,
46 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
47 [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
48 },
49 },
50 .entries = {
51 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
52 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
53 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
54 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
55 IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
56 },
57 .term = IP6T_ERROR_INIT, /* ERROR */
58};
59
60static const struct xt_table packet_mangler = { 24static const struct xt_table packet_mangler = {
61 .name = "mangle", 25 .name = "mangle",
62 .valid_hooks = MANGLE_VALID_HOOKS, 26 .valid_hooks = MANGLE_VALID_HOOKS,
63 .me = THIS_MODULE, 27 .me = THIS_MODULE,
64 .af = NFPROTO_IPV6, 28 .af = NFPROTO_IPV6,
29 .priority = NF_IP6_PRI_MANGLE,
65}; 30};
66 31
67/* The work comes in here from netfilter.c. */
68static unsigned int
69ip6t_in_hook(unsigned int hook,
70 struct sk_buff *skb,
71 const struct net_device *in,
72 const struct net_device *out,
73 int (*okfn)(struct sk_buff *))
74{
75 return ip6t_do_table(skb, hook, in, out,
76 dev_net(in)->ipv6.ip6table_mangle);
77}
78
79static unsigned int
80ip6t_post_routing_hook(unsigned int hook,
81 struct sk_buff *skb,
82 const struct net_device *in,
83 const struct net_device *out,
84 int (*okfn)(struct sk_buff *))
85{
86 return ip6t_do_table(skb, hook, in, out,
87 dev_net(out)->ipv6.ip6table_mangle);
88}
89
90static unsigned int 32static unsigned int
91ip6t_local_out_hook(unsigned int hook, 33ip6t_local_out_hook(unsigned int hook,
92 struct sk_buff *skb, 34 struct sk_buff *skb,
93 const struct net_device *in,
94 const struct net_device *out, 35 const struct net_device *out,
95 int (*okfn)(struct sk_buff *)) 36 int (*okfn)(struct sk_buff *))
96{ 37{
@@ -119,7 +60,7 @@ ip6t_local_out_hook(unsigned int hook,
119 /* flowlabel and prio (includes version, which shouldn't change either */ 60 /* flowlabel and prio (includes version, which shouldn't change either */
120 flowlabel = *((u_int32_t *)ipv6_hdr(skb)); 61 flowlabel = *((u_int32_t *)ipv6_hdr(skb));
121 62
122 ret = ip6t_do_table(skb, hook, in, out, 63 ret = ip6t_do_table(skb, hook, NULL, out,
123 dev_net(out)->ipv6.ip6table_mangle); 64 dev_net(out)->ipv6.ip6table_mangle);
124 65
125 if (ret != NF_DROP && ret != NF_STOLEN && 66 if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -132,49 +73,31 @@ ip6t_local_out_hook(unsigned int hook,
132 return ret; 73 return ret;
133} 74}
134 75
135static struct nf_hook_ops ip6t_ops[] __read_mostly = { 76/* The work comes in here from netfilter.c. */
136 { 77static unsigned int
137 .hook = ip6t_in_hook, 78ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb,
138 .owner = THIS_MODULE, 79 const struct net_device *in, const struct net_device *out,
139 .pf = NFPROTO_IPV6, 80 int (*okfn)(struct sk_buff *))
140 .hooknum = NF_INET_PRE_ROUTING, 81{
141 .priority = NF_IP6_PRI_MANGLE, 82 if (hook == NF_INET_LOCAL_OUT)
142 }, 83 return ip6t_local_out_hook(hook, skb, out, okfn);
143 {
144 .hook = ip6t_in_hook,
145 .owner = THIS_MODULE,
146 .pf = NFPROTO_IPV6,
147 .hooknum = NF_INET_LOCAL_IN,
148 .priority = NF_IP6_PRI_MANGLE,
149 },
150 {
151 .hook = ip6t_in_hook,
152 .owner = THIS_MODULE,
153 .pf = NFPROTO_IPV6,
154 .hooknum = NF_INET_FORWARD,
155 .priority = NF_IP6_PRI_MANGLE,
156 },
157 {
158 .hook = ip6t_local_out_hook,
159 .owner = THIS_MODULE,
160 .pf = NFPROTO_IPV6,
161 .hooknum = NF_INET_LOCAL_OUT,
162 .priority = NF_IP6_PRI_MANGLE,
163 },
164 {
165 .hook = ip6t_post_routing_hook,
166 .owner = THIS_MODULE,
167 .pf = NFPROTO_IPV6,
168 .hooknum = NF_INET_POST_ROUTING,
169 .priority = NF_IP6_PRI_MANGLE,
170 },
171};
172 84
85 /* INPUT/FORWARD */
86 return ip6t_do_table(skb, hook, in, out,
87 dev_net(in)->ipv6.ip6table_mangle);
88}
89
90static struct nf_hook_ops *mangle_ops __read_mostly;
173static int __net_init ip6table_mangle_net_init(struct net *net) 91static int __net_init ip6table_mangle_net_init(struct net *net)
174{ 92{
175 /* Register table */ 93 struct ip6t_replace *repl;
94
95 repl = ip6t_alloc_initial_table(&packet_mangler);
96 if (repl == NULL)
97 return -ENOMEM;
176 net->ipv6.ip6table_mangle = 98 net->ipv6.ip6table_mangle =
177 ip6t_register_table(net, &packet_mangler, &initial_table.repl); 99 ip6t_register_table(net, &packet_mangler, repl);
100 kfree(repl);
178 if (IS_ERR(net->ipv6.ip6table_mangle)) 101 if (IS_ERR(net->ipv6.ip6table_mangle))
179 return PTR_ERR(net->ipv6.ip6table_mangle); 102 return PTR_ERR(net->ipv6.ip6table_mangle);
180 return 0; 103 return 0;
@@ -199,9 +122,11 @@ static int __init ip6table_mangle_init(void)
199 return ret; 122 return ret;
200 123
201 /* Register hooks */ 124 /* Register hooks */
202 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 125 mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
203 if (ret < 0) 126 if (IS_ERR(mangle_ops)) {
127 ret = PTR_ERR(mangle_ops);
204 goto cleanup_table; 128 goto cleanup_table;
129 }
205 130
206 return ret; 131 return ret;
207 132
@@ -212,7 +137,7 @@ static int __init ip6table_mangle_init(void)
212 137
213static void __exit ip6table_mangle_fini(void) 138static void __exit ip6table_mangle_fini(void)
214{ 139{
215 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 140 xt_hook_unlink(&packet_mangler, mangle_ops);
216 unregister_pernet_subsys(&ip6table_mangle_net_ops); 141 unregister_pernet_subsys(&ip6table_mangle_net_ops);
217} 142}
218 143
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 4c90b552e433..aef31a29de9e 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -8,85 +8,37 @@
8 8
9#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 9#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
10 10
11static const struct
12{
13 struct ip6t_replace repl;
14 struct ip6t_standard entries[2];
15 struct ip6t_error term;
16} initial_table __net_initdata = {
17 .repl = {
18 .name = "raw",
19 .valid_hooks = RAW_VALID_HOOKS,
20 .num_entries = 3,
21 .size = sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
22 .hook_entry = {
23 [NF_INET_PRE_ROUTING] = 0,
24 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard)
25 },
26 .underflow = {
27 [NF_INET_PRE_ROUTING] = 0,
28 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard)
29 },
30 },
31 .entries = {
32 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
33 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
34 },
35 .term = IP6T_ERROR_INIT, /* ERROR */
36};
37
38static const struct xt_table packet_raw = { 11static const struct xt_table packet_raw = {
39 .name = "raw", 12 .name = "raw",
40 .valid_hooks = RAW_VALID_HOOKS, 13 .valid_hooks = RAW_VALID_HOOKS,
41 .me = THIS_MODULE, 14 .me = THIS_MODULE,
42 .af = NFPROTO_IPV6, 15 .af = NFPROTO_IPV6,
16 .priority = NF_IP6_PRI_FIRST,
43}; 17};
44 18
45/* The work comes in here from netfilter.c. */ 19/* The work comes in here from netfilter.c. */
46static unsigned int 20static unsigned int
47ip6t_pre_routing_hook(unsigned int hook, 21ip6table_raw_hook(unsigned int hook, struct sk_buff *skb,
48 struct sk_buff *skb, 22 const struct net_device *in, const struct net_device *out,
49 const struct net_device *in, 23 int (*okfn)(struct sk_buff *))
50 const struct net_device *out,
51 int (*okfn)(struct sk_buff *))
52{ 24{
53 return ip6t_do_table(skb, hook, in, out, 25 const struct net *net = dev_net((in != NULL) ? in : out);
54 dev_net(in)->ipv6.ip6table_raw);
55}
56 26
57static unsigned int 27 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw);
58ip6t_local_out_hook(unsigned int hook,
59 struct sk_buff *skb,
60 const struct net_device *in,
61 const struct net_device *out,
62 int (*okfn)(struct sk_buff *))
63{
64 return ip6t_do_table(skb, hook, in, out,
65 dev_net(out)->ipv6.ip6table_raw);
66} 28}
67 29
68static struct nf_hook_ops ip6t_ops[] __read_mostly = { 30static struct nf_hook_ops *rawtable_ops __read_mostly;
69 {
70 .hook = ip6t_pre_routing_hook,
71 .pf = NFPROTO_IPV6,
72 .hooknum = NF_INET_PRE_ROUTING,
73 .priority = NF_IP6_PRI_FIRST,
74 .owner = THIS_MODULE,
75 },
76 {
77 .hook = ip6t_local_out_hook,
78 .pf = NFPROTO_IPV6,
79 .hooknum = NF_INET_LOCAL_OUT,
80 .priority = NF_IP6_PRI_FIRST,
81 .owner = THIS_MODULE,
82 },
83};
84 31
85static int __net_init ip6table_raw_net_init(struct net *net) 32static int __net_init ip6table_raw_net_init(struct net *net)
86{ 33{
87 /* Register table */ 34 struct ip6t_replace *repl;
35
36 repl = ip6t_alloc_initial_table(&packet_raw);
37 if (repl == NULL)
38 return -ENOMEM;
88 net->ipv6.ip6table_raw = 39 net->ipv6.ip6table_raw =
89 ip6t_register_table(net, &packet_raw, &initial_table.repl); 40 ip6t_register_table(net, &packet_raw, repl);
41 kfree(repl);
90 if (IS_ERR(net->ipv6.ip6table_raw)) 42 if (IS_ERR(net->ipv6.ip6table_raw))
91 return PTR_ERR(net->ipv6.ip6table_raw); 43 return PTR_ERR(net->ipv6.ip6table_raw);
92 return 0; 44 return 0;
@@ -111,9 +63,11 @@ static int __init ip6table_raw_init(void)
111 return ret; 63 return ret;
112 64
113 /* Register hooks */ 65 /* Register hooks */
114 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 66 rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
115 if (ret < 0) 67 if (IS_ERR(rawtable_ops)) {
68 ret = PTR_ERR(rawtable_ops);
116 goto cleanup_table; 69 goto cleanup_table;
70 }
117 71
118 return ret; 72 return ret;
119 73
@@ -124,7 +78,7 @@ static int __init ip6table_raw_init(void)
124 78
125static void __exit ip6table_raw_fini(void) 79static void __exit ip6table_raw_fini(void)
126{ 80{
127 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 81 xt_hook_unlink(&packet_raw, rawtable_ops);
128 unregister_pernet_subsys(&ip6table_raw_net_ops); 82 unregister_pernet_subsys(&ip6table_raw_net_ops);
129} 83}
130 84
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index baa8d4ef3b0a..0824d865aa9b 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -26,106 +26,37 @@ MODULE_DESCRIPTION("ip6tables security table, for MAC rules");
26 (1 << NF_INET_FORWARD) | \ 26 (1 << NF_INET_FORWARD) | \
27 (1 << NF_INET_LOCAL_OUT) 27 (1 << NF_INET_LOCAL_OUT)
28 28
29static const struct
30{
31 struct ip6t_replace repl;
32 struct ip6t_standard entries[3];
33 struct ip6t_error term;
34} initial_table __net_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
59static const struct xt_table security_table = { 29static const struct xt_table security_table = {
60 .name = "security", 30 .name = "security",
61 .valid_hooks = SECURITY_VALID_HOOKS, 31 .valid_hooks = SECURITY_VALID_HOOKS,
62 .me = THIS_MODULE, 32 .me = THIS_MODULE,
63 .af = NFPROTO_IPV6, 33 .af = NFPROTO_IPV6,
34 .priority = NF_IP6_PRI_SECURITY,
64}; 35};
65 36
66static unsigned int 37static unsigned int
67ip6t_local_in_hook(unsigned int hook, 38ip6table_security_hook(unsigned int hook, struct sk_buff *skb,
68 struct sk_buff *skb, 39 const struct net_device *in,
69 const struct net_device *in, 40 const struct net_device *out,
70 const struct net_device *out, 41 int (*okfn)(struct sk_buff *))
71 int (*okfn)(struct sk_buff *))
72{
73 return ip6t_do_table(skb, hook, in, out,
74 dev_net(in)->ipv6.ip6table_security);
75}
76
77static unsigned int
78ip6t_forward_hook(unsigned int hook,
79 struct sk_buff *skb,
80 const struct net_device *in,
81 const struct net_device *out,
82 int (*okfn)(struct sk_buff *))
83{ 42{
84 return ip6t_do_table(skb, hook, in, out, 43 const struct net *net = dev_net((in != NULL) ? in : out);
85 dev_net(in)->ipv6.ip6table_security);
86}
87 44
88static unsigned int 45 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security);
89ip6t_local_out_hook(unsigned int hook,
90 struct sk_buff *skb,
91 const struct net_device *in,
92 const struct net_device *out,
93 int (*okfn)(struct sk_buff *))
94{
95 /* TBD: handle short packets via raw socket */
96 return ip6t_do_table(skb, hook, in, out,
97 dev_net(out)->ipv6.ip6table_security);
98} 46}
99 47
100static struct nf_hook_ops ip6t_ops[] __read_mostly = { 48static struct nf_hook_ops *sectbl_ops __read_mostly;
101 {
102 .hook = ip6t_local_in_hook,
103 .owner = THIS_MODULE,
104 .pf = NFPROTO_IPV6,
105 .hooknum = NF_INET_LOCAL_IN,
106 .priority = NF_IP6_PRI_SECURITY,
107 },
108 {
109 .hook = ip6t_forward_hook,
110 .owner = THIS_MODULE,
111 .pf = NFPROTO_IPV6,
112 .hooknum = NF_INET_FORWARD,
113 .priority = NF_IP6_PRI_SECURITY,
114 },
115 {
116 .hook = ip6t_local_out_hook,
117 .owner = THIS_MODULE,
118 .pf = NFPROTO_IPV6,
119 .hooknum = NF_INET_LOCAL_OUT,
120 .priority = NF_IP6_PRI_SECURITY,
121 },
122};
123 49
124static int __net_init ip6table_security_net_init(struct net *net) 50static int __net_init ip6table_security_net_init(struct net *net)
125{ 51{
126 net->ipv6.ip6table_security = 52 struct ip6t_replace *repl;
127 ip6t_register_table(net, &security_table, &initial_table.repl);
128 53
54 repl = ip6t_alloc_initial_table(&security_table);
55 if (repl == NULL)
56 return -ENOMEM;
57 net->ipv6.ip6table_security =
58 ip6t_register_table(net, &security_table, repl);
59 kfree(repl);
129 if (IS_ERR(net->ipv6.ip6table_security)) 60 if (IS_ERR(net->ipv6.ip6table_security))
130 return PTR_ERR(net->ipv6.ip6table_security); 61 return PTR_ERR(net->ipv6.ip6table_security);
131 62
@@ -150,9 +81,11 @@ static int __init ip6table_security_init(void)
150 if (ret < 0) 81 if (ret < 0)
151 return ret; 82 return ret;
152 83
153 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 84 sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
154 if (ret < 0) 85 if (IS_ERR(sectbl_ops)) {
86 ret = PTR_ERR(sectbl_ops);
155 goto cleanup_table; 87 goto cleanup_table;
88 }
156 89
157 return ret; 90 return ret;
158 91
@@ -163,7 +96,7 @@ cleanup_table:
163 96
164static void __exit ip6table_security_fini(void) 97static void __exit ip6table_security_fini(void)
165{ 98{
166 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 99 xt_hook_unlink(&security_table, sectbl_ops);
167 unregister_pernet_subsys(&ip6table_security_net_ops); 100 unregister_pernet_subsys(&ip6table_security_net_ops);
168} 101}
169 102
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 5c564ff10a3b..255ab0657ce8 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -26,7 +26,9 @@
26 26
27#include <linux/netfilter/x_tables.h> 27#include <linux/netfilter/x_tables.h>
28#include <linux/netfilter_arp.h> 28#include <linux/netfilter_arp.h>
29 29#include <linux/netfilter_ipv4/ip_tables.h>
30#include <linux/netfilter_ipv6/ip6_tables.h>
31#include <linux/netfilter_arp/arp_tables.h>
30 32
31MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 34MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -1091,6 +1093,60 @@ static const struct file_operations xt_target_ops = {
1091 1093
1092#endif /* CONFIG_PROC_FS */ 1094#endif /* CONFIG_PROC_FS */
1093 1095
1096/**
1097 * xt_hook_link - set up hooks for a new table
1098 * @table: table with metadata needed to set up hooks
1099 * @fn: Hook function
1100 *
1101 * This function will take care of creating and registering the necessary
1102 * Netfilter hooks for XT tables.
1103 */
1104struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
1105{
1106 unsigned int hook_mask = table->valid_hooks;
1107 uint8_t i, num_hooks = hweight32(hook_mask);
1108 uint8_t hooknum;
1109 struct nf_hook_ops *ops;
1110 int ret;
1111
1112 ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
1113 if (ops == NULL)
1114 return ERR_PTR(-ENOMEM);
1115
1116 for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
1117 hook_mask >>= 1, ++hooknum) {
1118 if (!(hook_mask & 1))
1119 continue;
1120 ops[i].hook = fn;
1121 ops[i].owner = table->me;
1122 ops[i].pf = table->af;
1123 ops[i].hooknum = hooknum;
1124 ops[i].priority = table->priority;
1125 ++i;
1126 }
1127
1128 ret = nf_register_hooks(ops, num_hooks);
1129 if (ret < 0) {
1130 kfree(ops);
1131 return ERR_PTR(ret);
1132 }
1133
1134 return ops;
1135}
1136EXPORT_SYMBOL_GPL(xt_hook_link);
1137
1138/**
1139 * xt_hook_unlink - remove hooks for a table
1140 * @ops: nf_hook_ops array as returned by nf_hook_link
1141 * @hook_mask: the very same mask that was passed to nf_hook_link
1142 */
1143void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
1144{
1145 nf_unregister_hooks(ops, hweight32(table->valid_hooks));
1146 kfree(ops);
1147}
1148EXPORT_SYMBOL_GPL(xt_hook_unlink);
1149
1094int xt_proto_init(struct net *net, u_int8_t af) 1150int xt_proto_init(struct net *net, u_int8_t af)
1095{ 1151{
1096#ifdef CONFIG_PROC_FS 1152#ifdef CONFIG_PROC_FS
diff --git a/net/netfilter/xt_repldata.h b/net/netfilter/xt_repldata.h
new file mode 100644
index 000000000000..6efe4e5a81c6
--- /dev/null
+++ b/net/netfilter/xt_repldata.h
@@ -0,0 +1,35 @@
1/*
2 * Today's hack: quantum tunneling in structs
3 *
4 * 'entries' and 'term' are never anywhere referenced by word in code. In fact,
5 * they serve as the hanging-off data accessed through repl.data[].
6 */
7
8#define xt_alloc_initial_table(type, typ2) ({ \
9 unsigned int hook_mask = info->valid_hooks; \
10 unsigned int nhooks = hweight32(hook_mask); \
11 unsigned int bytes = 0, hooknum = 0, i = 0; \
12 struct { \
13 struct type##_replace repl; \
14 struct type##_standard entries[nhooks]; \
15 struct type##_error term; \
16 } *tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); \
17 if (tbl == NULL) \
18 return NULL; \
19 strncpy(tbl->repl.name, info->name, sizeof(tbl->repl.name)); \
20 tbl->term = (struct type##_error)typ2##_ERROR_INIT; \
21 tbl->repl.valid_hooks = hook_mask; \
22 tbl->repl.num_entries = nhooks + 1; \
23 tbl->repl.size = nhooks * sizeof(struct type##_standard) + \
24 sizeof(struct type##_error); \
25 for (; hook_mask != 0; hook_mask >>= 1, ++hooknum) { \
26 if (!(hook_mask & 1)) \
27 continue; \
28 tbl->repl.hook_entry[hooknum] = bytes; \
29 tbl->repl.underflow[hooknum] = bytes; \
30 tbl->entries[i++] = (struct type##_standard) \
31 typ2##_STANDARD_INIT(NF_ACCEPT); \
32 bytes += sizeof(struct type##_standard); \
33 } \
34 tbl; \
35})