aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@medozas.de>2009-06-17 07:57:48 -0400
committerJan Engelhardt <jengelh@medozas.de>2010-02-10 11:13:33 -0500
commit2b95efe7f6bb750256a702cc32d33b0cb2cd8223 (patch)
tree49ab6f0eb13fe524211f94db29c19827529f49a5
parent2b21e051472fdb4680076278b2ccf63ebc1cc3bc (diff)
netfilter: xtables: use xt_table for hook instantiation
The respective xt_table structures already have most of the metadata needed for hook setup. Add a 'priority' field to struct xt_table so that xt_hook_link() can be called with a reduced number of arguments. So should we be having more tables in the future, it comes at no static cost (only runtime, as before) - space saved: 6807373->6806555. Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
-rw-r--r--include/linux/netfilter/x_tables.h4
-rw-r--r--net/ipv4/netfilter/arptable_filter.c33
-rw-r--r--net/ipv4/netfilter/iptable_filter.c33
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c47
-rw-r--r--net/ipv4/netfilter/iptable_raw.c27
-rw-r--r--net/ipv4/netfilter/iptable_security.c33
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c33
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c48
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c26
-rw-r--r--net/ipv6/netfilter/ip6table_security.c33
-rw-r--r--net/netfilter/x_tables.c54
11 files changed, 121 insertions, 250 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 365fabe1b16e..fdd3342c1235 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -361,6 +361,7 @@ struct xt_table {
361 struct module *me; 361 struct module *me;
362 362
363 u_int8_t af; /* address/protocol family */ 363 u_int8_t af; /* address/protocol family */
364 int priority; /* hook order */
364 365
365 /* A unique name... */ 366 /* A unique name... */
366 const char name[XT_TABLE_MAXNAMELEN]; 367 const char name[XT_TABLE_MAXNAMELEN];
@@ -522,6 +523,9 @@ static inline unsigned long ifname_compare_aligned(const char *_a,
522 return ret; 523 return ret;
523} 524}
524 525
526extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *);
527extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *);
528
525#ifdef CONFIG_COMPAT 529#ifdef CONFIG_COMPAT
526#include <net/compat.h> 530#include <net/compat.h>
527 531
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index deeda9b2cf05..b361de0dac4c 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -50,6 +50,7 @@ static const struct xt_table packet_filter = {
50 .valid_hooks = FILTER_VALID_HOOKS, 50 .valid_hooks = FILTER_VALID_HOOKS,
51 .me = THIS_MODULE, 51 .me = THIS_MODULE,
52 .af = NFPROTO_ARP, 52 .af = NFPROTO_ARP,
53 .priority = NF_IP_PRI_FILTER,
53}; 54};
54 55
55/* The work comes in here from netfilter.c */ 56/* The work comes in here from netfilter.c */
@@ -63,29 +64,7 @@ arptable_filter_hook(unsigned int hook, struct sk_buff *skb,
63 return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); 64 return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter);
64} 65}
65 66
66static struct nf_hook_ops arpt_ops[] __read_mostly = { 67static struct nf_hook_ops *arpfilter_ops __read_mostly;
67 {
68 .hook = arptable_filter_hook,
69 .owner = THIS_MODULE,
70 .pf = NFPROTO_ARP,
71 .hooknum = NF_ARP_IN,
72 .priority = NF_IP_PRI_FILTER,
73 },
74 {
75 .hook = arptable_filter_hook,
76 .owner = THIS_MODULE,
77 .pf = NFPROTO_ARP,
78 .hooknum = NF_ARP_OUT,
79 .priority = NF_IP_PRI_FILTER,
80 },
81 {
82 .hook = arptable_filter_hook,
83 .owner = THIS_MODULE,
84 .pf = NFPROTO_ARP,
85 .hooknum = NF_ARP_FORWARD,
86 .priority = NF_IP_PRI_FILTER,
87 },
88};
89 68
90static int __net_init arptable_filter_net_init(struct net *net) 69static int __net_init arptable_filter_net_init(struct net *net)
91{ 70{
@@ -115,9 +94,11 @@ static int __init arptable_filter_init(void)
115 if (ret < 0) 94 if (ret < 0)
116 return ret; 95 return ret;
117 96
118 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 97 arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
119 if (ret < 0) 98 if (IS_ERR(arpfilter_ops)) {
99 ret = PTR_ERR(arpfilter_ops);
120 goto cleanup_table; 100 goto cleanup_table;
101 }
121 return ret; 102 return ret;
122 103
123cleanup_table: 104cleanup_table:
@@ -127,7 +108,7 @@ cleanup_table:
127 108
128static void __exit arptable_filter_fini(void) 109static void __exit arptable_filter_fini(void)
129{ 110{
130 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 111 xt_hook_unlink(&packet_filter, arpfilter_ops);
131 unregister_pernet_subsys(&arptable_filter_net_ops); 112 unregister_pernet_subsys(&arptable_filter_net_ops);
132} 113}
133 114
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 1bfeaae6f624..c14bb85db1d9 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -58,6 +58,7 @@ static const struct xt_table packet_filter = {
58 .valid_hooks = FILTER_VALID_HOOKS, 58 .valid_hooks = FILTER_VALID_HOOKS,
59 .me = THIS_MODULE, 59 .me = THIS_MODULE,
60 .af = NFPROTO_IPV4, 60 .af = NFPROTO_IPV4,
61 .priority = NF_IP_PRI_FILTER,
61}; 62};
62 63
63static unsigned int 64static unsigned int
@@ -77,29 +78,7 @@ iptable_filter_hook(unsigned int hook, struct sk_buff *skb,
77 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); 78 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter);
78} 79}
79 80
80static struct nf_hook_ops ipt_ops[] __read_mostly = { 81static struct nf_hook_ops *filter_ops __read_mostly;
81 {
82 .hook = iptable_filter_hook,
83 .owner = THIS_MODULE,
84 .pf = NFPROTO_IPV4,
85 .hooknum = NF_INET_LOCAL_IN,
86 .priority = NF_IP_PRI_FILTER,
87 },
88 {
89 .hook = iptable_filter_hook,
90 .owner = THIS_MODULE,
91 .pf = NFPROTO_IPV4,
92 .hooknum = NF_INET_FORWARD,
93 .priority = NF_IP_PRI_FILTER,
94 },
95 {
96 .hook = iptable_filter_hook,
97 .owner = THIS_MODULE,
98 .pf = NFPROTO_IPV4,
99 .hooknum = NF_INET_LOCAL_OUT,
100 .priority = NF_IP_PRI_FILTER,
101 },
102};
103 82
104/* Default to forward because I got too much mail already. */ 83/* Default to forward because I got too much mail already. */
105static int forward = NF_ACCEPT; 84static int forward = NF_ACCEPT;
@@ -142,9 +121,11 @@ static int __init iptable_filter_init(void)
142 return ret; 121 return ret;
143 122
144 /* Register hooks */ 123 /* Register hooks */
145 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 124 filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
146 if (ret < 0) 125 if (IS_ERR(filter_ops)) {
126 ret = PTR_ERR(filter_ops);
147 goto cleanup_table; 127 goto cleanup_table;
128 }
148 129
149 return ret; 130 return ret;
150 131
@@ -155,7 +136,7 @@ static int __init iptable_filter_init(void)
155 136
156static void __exit iptable_filter_fini(void) 137static void __exit iptable_filter_fini(void)
157{ 138{
158 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 139 xt_hook_unlink(&packet_filter, filter_ops);
159 unregister_pernet_subsys(&iptable_filter_net_ops); 140 unregister_pernet_subsys(&iptable_filter_net_ops);
160} 141}
161 142
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 4e699cd275c6..2355a229f8ee 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -69,6 +69,7 @@ static const struct xt_table packet_mangler = {
69 .valid_hooks = MANGLE_VALID_HOOKS, 69 .valid_hooks = MANGLE_VALID_HOOKS,
70 .me = THIS_MODULE, 70 .me = THIS_MODULE,
71 .af = NFPROTO_IPV4, 71 .af = NFPROTO_IPV4,
72 .priority = NF_IP_PRI_MANGLE,
72}; 73};
73 74
74static unsigned int 75static unsigned int
@@ -129,43 +130,7 @@ iptable_mangle_hook(unsigned int hook,
129 dev_net(in)->ipv4.iptable_mangle); 130 dev_net(in)->ipv4.iptable_mangle);
130} 131}
131 132
132static struct nf_hook_ops ipt_ops[] __read_mostly = { 133static struct nf_hook_ops *mangle_ops __read_mostly;
133 {
134 .hook = iptable_mangle_hook,
135 .owner = THIS_MODULE,
136 .pf = NFPROTO_IPV4,
137 .hooknum = NF_INET_PRE_ROUTING,
138 .priority = NF_IP_PRI_MANGLE,
139 },
140 {
141 .hook = iptable_mangle_hook,
142 .owner = THIS_MODULE,
143 .pf = NFPROTO_IPV4,
144 .hooknum = NF_INET_LOCAL_IN,
145 .priority = NF_IP_PRI_MANGLE,
146 },
147 {
148 .hook = iptable_mangle_hook,
149 .owner = THIS_MODULE,
150 .pf = NFPROTO_IPV4,
151 .hooknum = NF_INET_FORWARD,
152 .priority = NF_IP_PRI_MANGLE,
153 },
154 {
155 .hook = iptable_mangle_hook,
156 .owner = THIS_MODULE,
157 .pf = NFPROTO_IPV4,
158 .hooknum = NF_INET_LOCAL_OUT,
159 .priority = NF_IP_PRI_MANGLE,
160 },
161 {
162 .hook = iptable_mangle_hook,
163 .owner = THIS_MODULE,
164 .pf = NFPROTO_IPV4,
165 .hooknum = NF_INET_POST_ROUTING,
166 .priority = NF_IP_PRI_MANGLE,
167 },
168};
169 134
170static int __net_init iptable_mangle_net_init(struct net *net) 135static int __net_init iptable_mangle_net_init(struct net *net)
171{ 136{
@@ -196,9 +161,11 @@ static int __init iptable_mangle_init(void)
196 return ret; 161 return ret;
197 162
198 /* Register hooks */ 163 /* Register hooks */
199 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 164 mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
200 if (ret < 0) 165 if (IS_ERR(mangle_ops)) {
166 ret = PTR_ERR(mangle_ops);
201 goto cleanup_table; 167 goto cleanup_table;
168 }
202 169
203 return ret; 170 return ret;
204 171
@@ -209,7 +176,7 @@ static int __init iptable_mangle_init(void)
209 176
210static void __exit iptable_mangle_fini(void) 177static void __exit iptable_mangle_fini(void)
211{ 178{
212 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 179 xt_hook_unlink(&packet_mangler, mangle_ops);
213 unregister_pernet_subsys(&iptable_mangle_net_ops); 180 unregister_pernet_subsys(&iptable_mangle_net_ops);
214} 181}
215 182
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index d16e43777c31..62a99154f14c 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -41,6 +41,7 @@ static const struct xt_table packet_raw = {
41 .valid_hooks = RAW_VALID_HOOKS, 41 .valid_hooks = RAW_VALID_HOOKS,
42 .me = THIS_MODULE, 42 .me = THIS_MODULE,
43 .af = NFPROTO_IPV4, 43 .af = NFPROTO_IPV4,
44 .priority = NF_IP_PRI_RAW,
44}; 45};
45 46
46/* The work comes in here from netfilter.c. */ 47/* The work comes in here from netfilter.c. */
@@ -61,23 +62,7 @@ iptable_raw_hook(unsigned int hook, struct sk_buff *skb,
61 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); 62 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw);
62} 63}
63 64
64/* 'raw' is the very first table. */ 65static struct nf_hook_ops *rawtable_ops __read_mostly;
65static struct nf_hook_ops ipt_ops[] __read_mostly = {
66 {
67 .hook = iptable_raw_hook,
68 .pf = NFPROTO_IPV4,
69 .hooknum = NF_INET_PRE_ROUTING,
70 .priority = NF_IP_PRI_RAW,
71 .owner = THIS_MODULE,
72 },
73 {
74 .hook = iptable_raw_hook,
75 .pf = NFPROTO_IPV4,
76 .hooknum = NF_INET_LOCAL_OUT,
77 .priority = NF_IP_PRI_RAW,
78 .owner = THIS_MODULE,
79 },
80};
81 66
82static int __net_init iptable_raw_net_init(struct net *net) 67static int __net_init iptable_raw_net_init(struct net *net)
83{ 68{
@@ -108,9 +93,11 @@ static int __init iptable_raw_init(void)
108 return ret; 93 return ret;
109 94
110 /* Register hooks */ 95 /* Register hooks */
111 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 96 rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
112 if (ret < 0) 97 if (IS_ERR(rawtable_ops)) {
98 ret = PTR_ERR(rawtable_ops);
113 goto cleanup_table; 99 goto cleanup_table;
100 }
114 101
115 return ret; 102 return ret;
116 103
@@ -121,7 +108,7 @@ static int __init iptable_raw_init(void)
121 108
122static void __exit iptable_raw_fini(void) 109static void __exit iptable_raw_fini(void)
123{ 110{
124 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 111 xt_hook_unlink(&packet_raw, rawtable_ops);
125 unregister_pernet_subsys(&iptable_raw_net_ops); 112 unregister_pernet_subsys(&iptable_raw_net_ops);
126} 113}
127 114
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index 324505aaaa73..b1bf3ca2c6c7 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -62,6 +62,7 @@ static const struct xt_table security_table = {
62 .valid_hooks = SECURITY_VALID_HOOKS, 62 .valid_hooks = SECURITY_VALID_HOOKS,
63 .me = THIS_MODULE, 63 .me = THIS_MODULE,
64 .af = NFPROTO_IPV4, 64 .af = NFPROTO_IPV4,
65 .priority = NF_IP_PRI_SECURITY,
65}; 66};
66 67
67static unsigned int 68static unsigned int
@@ -82,29 +83,7 @@ iptable_security_hook(unsigned int hook, struct sk_buff *skb,
82 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); 83 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security);
83} 84}
84 85
85static struct nf_hook_ops ipt_ops[] __read_mostly = { 86static struct nf_hook_ops *sectbl_ops __read_mostly;
86 {
87 .hook = iptable_security_hook,
88 .owner = THIS_MODULE,
89 .pf = NFPROTO_IPV4,
90 .hooknum = NF_INET_LOCAL_IN,
91 .priority = NF_IP_PRI_SECURITY,
92 },
93 {
94 .hook = iptable_security_hook,
95 .owner = THIS_MODULE,
96 .pf = NFPROTO_IPV4,
97 .hooknum = NF_INET_FORWARD,
98 .priority = NF_IP_PRI_SECURITY,
99 },
100 {
101 .hook = iptable_security_hook,
102 .owner = THIS_MODULE,
103 .pf = NFPROTO_IPV4,
104 .hooknum = NF_INET_LOCAL_OUT,
105 .priority = NF_IP_PRI_SECURITY,
106 },
107};
108 87
109static int __net_init iptable_security_net_init(struct net *net) 88static int __net_init iptable_security_net_init(struct net *net)
110{ 89{
@@ -135,9 +114,11 @@ static int __init iptable_security_init(void)
135 if (ret < 0) 114 if (ret < 0)
136 return ret; 115 return ret;
137 116
138 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 117 sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
139 if (ret < 0) 118 if (IS_ERR(sectbl_ops)) {
119 ret = PTR_ERR(sectbl_ops);
140 goto cleanup_table; 120 goto cleanup_table;
121 }
141 122
142 return ret; 123 return ret;
143 124
@@ -148,7 +129,7 @@ cleanup_table:
148 129
149static void __exit iptable_security_fini(void) 130static void __exit iptable_security_fini(void)
150{ 131{
151 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 132 xt_hook_unlink(&security_table, sectbl_ops);
152 unregister_pernet_subsys(&iptable_security_net_ops); 133 unregister_pernet_subsys(&iptable_security_net_ops);
153} 134}
154 135
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 866f34ae236b..6e95d0614ca9 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -56,6 +56,7 @@ static const struct xt_table packet_filter = {
56 .valid_hooks = FILTER_VALID_HOOKS, 56 .valid_hooks = FILTER_VALID_HOOKS,
57 .me = THIS_MODULE, 57 .me = THIS_MODULE,
58 .af = NFPROTO_IPV6, 58 .af = NFPROTO_IPV6,
59 .priority = NF_IP6_PRI_FILTER,
59}; 60};
60 61
61/* The work comes in here from netfilter.c. */ 62/* The work comes in here from netfilter.c. */
@@ -69,29 +70,7 @@ ip6table_filter_hook(unsigned int hook, struct sk_buff *skb,
69 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); 70 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter);
70} 71}
71 72
72static struct nf_hook_ops ip6t_ops[] __read_mostly = { 73static struct nf_hook_ops *filter_ops __read_mostly;
73 {
74 .hook = ip6table_filter_hook,
75 .owner = THIS_MODULE,
76 .pf = NFPROTO_IPV6,
77 .hooknum = NF_INET_LOCAL_IN,
78 .priority = NF_IP6_PRI_FILTER,
79 },
80 {
81 .hook = ip6table_filter_hook,
82 .owner = THIS_MODULE,
83 .pf = NFPROTO_IPV6,
84 .hooknum = NF_INET_FORWARD,
85 .priority = NF_IP6_PRI_FILTER,
86 },
87 {
88 .hook = ip6table_filter_hook,
89 .owner = THIS_MODULE,
90 .pf = NFPROTO_IPV6,
91 .hooknum = NF_INET_LOCAL_OUT,
92 .priority = NF_IP6_PRI_FILTER,
93 },
94};
95 74
96/* Default to forward because I got too much mail already. */ 75/* Default to forward because I got too much mail already. */
97static int forward = NF_ACCEPT; 76static int forward = NF_ACCEPT;
@@ -134,9 +113,11 @@ static int __init ip6table_filter_init(void)
134 return ret; 113 return ret;
135 114
136 /* Register hooks */ 115 /* Register hooks */
137 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 116 filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
138 if (ret < 0) 117 if (IS_ERR(filter_ops)) {
118 ret = PTR_ERR(filter_ops);
139 goto cleanup_table; 119 goto cleanup_table;
120 }
140 121
141 return ret; 122 return ret;
142 123
@@ -147,7 +128,7 @@ static int __init ip6table_filter_init(void)
147 128
148static void __exit ip6table_filter_fini(void) 129static void __exit ip6table_filter_fini(void)
149{ 130{
150 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 131 xt_hook_unlink(&packet_filter, filter_ops);
151 unregister_pernet_subsys(&ip6table_filter_net_ops); 132 unregister_pernet_subsys(&ip6table_filter_net_ops);
152} 133}
153 134
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 405ac1f76390..5023ac52ffec 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -62,6 +62,7 @@ static const struct xt_table packet_mangler = {
62 .valid_hooks = MANGLE_VALID_HOOKS, 62 .valid_hooks = MANGLE_VALID_HOOKS,
63 .me = THIS_MODULE, 63 .me = THIS_MODULE,
64 .af = NFPROTO_IPV6, 64 .af = NFPROTO_IPV6,
65 .priority = NF_IP6_PRI_MANGLE,
65}; 66};
66 67
67static unsigned int 68static unsigned int
@@ -122,44 +123,7 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb,
122 dev_net(in)->ipv6.ip6table_mangle); 123 dev_net(in)->ipv6.ip6table_mangle);
123} 124}
124 125
125static struct nf_hook_ops ip6t_ops[] __read_mostly = { 126static struct nf_hook_ops *mangle_ops __read_mostly;
126 {
127 .hook = ip6table_mangle_hook,
128 .owner = THIS_MODULE,
129 .pf = NFPROTO_IPV6,
130 .hooknum = NF_INET_PRE_ROUTING,
131 .priority = NF_IP6_PRI_MANGLE,
132 },
133 {
134 .hook = ip6table_mangle_hook,
135 .owner = THIS_MODULE,
136 .pf = NFPROTO_IPV6,
137 .hooknum = NF_INET_LOCAL_IN,
138 .priority = NF_IP6_PRI_MANGLE,
139 },
140 {
141 .hook = ip6table_mangle_hook,
142 .owner = THIS_MODULE,
143 .pf = NFPROTO_IPV6,
144 .hooknum = NF_INET_FORWARD,
145 .priority = NF_IP6_PRI_MANGLE,
146 },
147 {
148 .hook = ip6table_mangle_hook,
149 .owner = THIS_MODULE,
150 .pf = NFPROTO_IPV6,
151 .hooknum = NF_INET_LOCAL_OUT,
152 .priority = NF_IP6_PRI_MANGLE,
153 },
154 {
155 .hook = ip6table_mangle_hook,
156 .owner = THIS_MODULE,
157 .pf = NFPROTO_IPV6,
158 .hooknum = NF_INET_POST_ROUTING,
159 .priority = NF_IP6_PRI_MANGLE,
160 },
161};
162
163static int __net_init ip6table_mangle_net_init(struct net *net) 127static int __net_init ip6table_mangle_net_init(struct net *net)
164{ 128{
165 /* Register table */ 129 /* Register table */
@@ -189,9 +153,11 @@ static int __init ip6table_mangle_init(void)
189 return ret; 153 return ret;
190 154
191 /* Register hooks */ 155 /* Register hooks */
192 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 156 mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
193 if (ret < 0) 157 if (IS_ERR(mangle_ops)) {
158 ret = PTR_ERR(mangle_ops);
194 goto cleanup_table; 159 goto cleanup_table;
160 }
195 161
196 return ret; 162 return ret;
197 163
@@ -202,7 +168,7 @@ static int __init ip6table_mangle_init(void)
202 168
203static void __exit ip6table_mangle_fini(void) 169static void __exit ip6table_mangle_fini(void)
204{ 170{
205 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 171 xt_hook_unlink(&packet_mangler, mangle_ops);
206 unregister_pernet_subsys(&ip6table_mangle_net_ops); 172 unregister_pernet_subsys(&ip6table_mangle_net_ops);
207} 173}
208 174
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 5451a36fbc21..3bfa69511641 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -40,6 +40,7 @@ static const struct xt_table packet_raw = {
40 .valid_hooks = RAW_VALID_HOOKS, 40 .valid_hooks = RAW_VALID_HOOKS,
41 .me = THIS_MODULE, 41 .me = THIS_MODULE,
42 .af = NFPROTO_IPV6, 42 .af = NFPROTO_IPV6,
43 .priority = NF_IP6_PRI_FIRST,
43}; 44};
44 45
45/* The work comes in here from netfilter.c. */ 46/* The work comes in here from netfilter.c. */
@@ -53,22 +54,7 @@ ip6table_raw_hook(unsigned int hook, struct sk_buff *skb,
53 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); 54 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw);
54} 55}
55 56
56static struct nf_hook_ops ip6t_ops[] __read_mostly = { 57static struct nf_hook_ops *rawtable_ops __read_mostly;
57 {
58 .hook = ip6table_raw_hook,
59 .pf = NFPROTO_IPV6,
60 .hooknum = NF_INET_PRE_ROUTING,
61 .priority = NF_IP6_PRI_FIRST,
62 .owner = THIS_MODULE,
63 },
64 {
65 .hook = ip6table_raw_hook,
66 .pf = NFPROTO_IPV6,
67 .hooknum = NF_INET_LOCAL_OUT,
68 .priority = NF_IP6_PRI_FIRST,
69 .owner = THIS_MODULE,
70 },
71};
72 58
73static int __net_init ip6table_raw_net_init(struct net *net) 59static int __net_init ip6table_raw_net_init(struct net *net)
74{ 60{
@@ -99,9 +85,11 @@ static int __init ip6table_raw_init(void)
99 return ret; 85 return ret;
100 86
101 /* Register hooks */ 87 /* Register hooks */
102 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 88 rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
103 if (ret < 0) 89 if (IS_ERR(rawtable_ops)) {
90 ret = PTR_ERR(rawtable_ops);
104 goto cleanup_table; 91 goto cleanup_table;
92 }
105 93
106 return ret; 94 return ret;
107 95
@@ -112,7 +100,7 @@ static int __init ip6table_raw_init(void)
112 100
113static void __exit ip6table_raw_fini(void) 101static void __exit ip6table_raw_fini(void)
114{ 102{
115 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 103 xt_hook_unlink(&packet_raw, rawtable_ops);
116 unregister_pernet_subsys(&ip6table_raw_net_ops); 104 unregister_pernet_subsys(&ip6table_raw_net_ops);
117} 105}
118 106
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index 841ea77f5218..dd2200f17a6c 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -61,6 +61,7 @@ static const struct xt_table security_table = {
61 .valid_hooks = SECURITY_VALID_HOOKS, 61 .valid_hooks = SECURITY_VALID_HOOKS,
62 .me = THIS_MODULE, 62 .me = THIS_MODULE,
63 .af = NFPROTO_IPV6, 63 .af = NFPROTO_IPV6,
64 .priority = NF_IP6_PRI_SECURITY,
64}; 65};
65 66
66static unsigned int 67static unsigned int
@@ -74,29 +75,7 @@ ip6table_security_hook(unsigned int hook, struct sk_buff *skb,
74 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); 75 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security);
75} 76}
76 77
77static struct nf_hook_ops ip6t_ops[] __read_mostly = { 78static struct nf_hook_ops *sectbl_ops __read_mostly;
78 {
79 .hook = ip6table_security_hook,
80 .owner = THIS_MODULE,
81 .pf = NFPROTO_IPV6,
82 .hooknum = NF_INET_LOCAL_IN,
83 .priority = NF_IP6_PRI_SECURITY,
84 },
85 {
86 .hook = ip6table_security_hook,
87 .owner = THIS_MODULE,
88 .pf = NFPROTO_IPV6,
89 .hooknum = NF_INET_FORWARD,
90 .priority = NF_IP6_PRI_SECURITY,
91 },
92 {
93 .hook = ip6table_security_hook,
94 .owner = THIS_MODULE,
95 .pf = NFPROTO_IPV6,
96 .hooknum = NF_INET_LOCAL_OUT,
97 .priority = NF_IP6_PRI_SECURITY,
98 },
99};
100 79
101static int __net_init ip6table_security_net_init(struct net *net) 80static int __net_init ip6table_security_net_init(struct net *net)
102{ 81{
@@ -127,9 +106,11 @@ static int __init ip6table_security_init(void)
127 if (ret < 0) 106 if (ret < 0)
128 return ret; 107 return ret;
129 108
130 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 109 sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
131 if (ret < 0) 110 if (IS_ERR(sectbl_ops)) {
111 ret = PTR_ERR(sectbl_ops);
132 goto cleanup_table; 112 goto cleanup_table;
113 }
133 114
134 return ret; 115 return ret;
135 116
@@ -140,7 +121,7 @@ cleanup_table:
140 121
141static void __exit ip6table_security_fini(void) 122static void __exit ip6table_security_fini(void)
142{ 123{
143 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 124 xt_hook_unlink(&security_table, sectbl_ops);
144 unregister_pernet_subsys(&ip6table_security_net_ops); 125 unregister_pernet_subsys(&ip6table_security_net_ops);
145} 126}
146 127
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index f01955cce314..b51cb0d7234a 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1091,6 +1091,60 @@ static const struct file_operations xt_target_ops = {
1091 1091
1092#endif /* CONFIG_PROC_FS */ 1092#endif /* CONFIG_PROC_FS */
1093 1093
1094/**
1095 * xt_hook_link - set up hooks for a new table
1096 * @table: table with metadata needed to set up hooks
1097 * @fn: Hook function
1098 *
1099 * This function will take care of creating and registering the necessary
1100 * Netfilter hooks for XT tables.
1101 */
1102struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
1103{
1104 unsigned int hook_mask = table->valid_hooks;
1105 uint8_t i, num_hooks = hweight32(hook_mask);
1106 uint8_t hooknum;
1107 struct nf_hook_ops *ops;
1108 int ret;
1109
1110 ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
1111 if (ops == NULL)
1112 return ERR_PTR(-ENOMEM);
1113
1114 for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
1115 hook_mask >>= 1, ++hooknum) {
1116 if (!(hook_mask & 1))
1117 continue;
1118 ops[i].hook = fn;
1119 ops[i].owner = table->me;
1120 ops[i].pf = table->af;
1121 ops[i].hooknum = hooknum;
1122 ops[i].priority = table->priority;
1123 ++i;
1124 }
1125
1126 ret = nf_register_hooks(ops, num_hooks);
1127 if (ret < 0) {
1128 kfree(ops);
1129 return ERR_PTR(ret);
1130 }
1131
1132 return ops;
1133}
1134EXPORT_SYMBOL_GPL(xt_hook_link);
1135
1136/**
1137 * xt_hook_unlink - remove hooks for a table
1138 * @ops: nf_hook_ops array as returned by nf_hook_link
1139 * @hook_mask: the very same mask that was passed to nf_hook_link
1140 */
1141void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
1142{
1143 nf_unregister_hooks(ops, hweight32(table->valid_hooks));
1144 kfree(ops);
1145}
1146EXPORT_SYMBOL_GPL(xt_hook_unlink);
1147
1094int xt_proto_init(struct net *net, u_int8_t af) 1148int xt_proto_init(struct net *net, u_int8_t af)
1095{ 1149{
1096#ifdef CONFIG_PROC_FS 1150#ifdef CONFIG_PROC_FS