Commit 2b95efe7f6bb750256a702cc32d33b0cb2cd8223
1 parent
2b21e05147
Exists in
master
and in
39 other branches
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>
Showing 11 changed files with 121 additions and 250 deletions Side-by-side Diff
- include/linux/netfilter/x_tables.h
- net/ipv4/netfilter/arptable_filter.c
- net/ipv4/netfilter/iptable_filter.c
- net/ipv4/netfilter/iptable_mangle.c
- net/ipv4/netfilter/iptable_raw.c
- net/ipv4/netfilter/iptable_security.c
- net/ipv6/netfilter/ip6table_filter.c
- net/ipv6/netfilter/ip6table_mangle.c
- net/ipv6/netfilter/ip6table_raw.c
- net/ipv6/netfilter/ip6table_security.c
- net/netfilter/x_tables.c
include/linux/netfilter/x_tables.h
... | ... | @@ -361,6 +361,7 @@ |
361 | 361 | struct module *me; |
362 | 362 | |
363 | 363 | u_int8_t af; /* address/protocol family */ |
364 | + int priority; /* hook order */ | |
364 | 365 | |
365 | 366 | /* A unique name... */ |
366 | 367 | const char name[XT_TABLE_MAXNAMELEN]; |
... | ... | @@ -521,6 +522,9 @@ |
521 | 522 | BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); |
522 | 523 | return ret; |
523 | 524 | } |
525 | + | |
526 | +extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); | |
527 | +extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); | |
524 | 528 | |
525 | 529 | #ifdef CONFIG_COMPAT |
526 | 530 | #include <net/compat.h> |
net/ipv4/netfilter/arptable_filter.c
... | ... | @@ -50,6 +50,7 @@ |
50 | 50 | .valid_hooks = FILTER_VALID_HOOKS, |
51 | 51 | .me = THIS_MODULE, |
52 | 52 | .af = NFPROTO_ARP, |
53 | + .priority = NF_IP_PRI_FILTER, | |
53 | 54 | }; |
54 | 55 | |
55 | 56 | /* The work comes in here from netfilter.c */ |
... | ... | @@ -63,29 +64,7 @@ |
63 | 64 | return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); |
64 | 65 | } |
65 | 66 | |
66 | -static struct nf_hook_ops arpt_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 | -}; | |
67 | +static struct nf_hook_ops *arpfilter_ops __read_mostly; | |
89 | 68 | |
90 | 69 | static int __net_init arptable_filter_net_init(struct net *net) |
91 | 70 | { |
92 | 71 | |
... | ... | @@ -115,9 +94,11 @@ |
115 | 94 | if (ret < 0) |
116 | 95 | return ret; |
117 | 96 | |
118 | - ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); | |
119 | - if (ret < 0) | |
97 | + arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook); | |
98 | + if (IS_ERR(arpfilter_ops)) { | |
99 | + ret = PTR_ERR(arpfilter_ops); | |
120 | 100 | goto cleanup_table; |
101 | + } | |
121 | 102 | return ret; |
122 | 103 | |
123 | 104 | cleanup_table: |
... | ... | @@ -127,7 +108,7 @@ |
127 | 108 | |
128 | 109 | static 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 | 112 | unregister_pernet_subsys(&arptable_filter_net_ops); |
132 | 113 | } |
133 | 114 |
net/ipv4/netfilter/iptable_filter.c
... | ... | @@ -58,6 +58,7 @@ |
58 | 58 | .valid_hooks = FILTER_VALID_HOOKS, |
59 | 59 | .me = THIS_MODULE, |
60 | 60 | .af = NFPROTO_IPV4, |
61 | + .priority = NF_IP_PRI_FILTER, | |
61 | 62 | }; |
62 | 63 | |
63 | 64 | static unsigned int |
... | ... | @@ -77,29 +78,7 @@ |
77 | 78 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); |
78 | 79 | } |
79 | 80 | |
80 | -static struct nf_hook_ops ipt_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 | -}; | |
81 | +static struct nf_hook_ops *filter_ops __read_mostly; | |
103 | 82 | |
104 | 83 | /* Default to forward because I got too much mail already. */ |
105 | 84 | static int forward = NF_ACCEPT; |
106 | 85 | |
... | ... | @@ -142,9 +121,11 @@ |
142 | 121 | return ret; |
143 | 122 | |
144 | 123 | /* Register hooks */ |
145 | - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | |
146 | - if (ret < 0) | |
124 | + filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); | |
125 | + if (IS_ERR(filter_ops)) { | |
126 | + ret = PTR_ERR(filter_ops); | |
147 | 127 | goto cleanup_table; |
128 | + } | |
148 | 129 | |
149 | 130 | return ret; |
150 | 131 | |
... | ... | @@ -155,7 +136,7 @@ |
155 | 136 | |
156 | 137 | static 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 | 140 | unregister_pernet_subsys(&iptable_filter_net_ops); |
160 | 141 | } |
161 | 142 |
net/ipv4/netfilter/iptable_mangle.c
... | ... | @@ -69,6 +69,7 @@ |
69 | 69 | .valid_hooks = MANGLE_VALID_HOOKS, |
70 | 70 | .me = THIS_MODULE, |
71 | 71 | .af = NFPROTO_IPV4, |
72 | + .priority = NF_IP_PRI_MANGLE, | |
72 | 73 | }; |
73 | 74 | |
74 | 75 | static unsigned int |
... | ... | @@ -129,43 +130,7 @@ |
129 | 130 | dev_net(in)->ipv4.iptable_mangle); |
130 | 131 | } |
131 | 132 | |
132 | -static struct nf_hook_ops ipt_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 | -}; | |
133 | +static struct nf_hook_ops *mangle_ops __read_mostly; | |
169 | 134 | |
170 | 135 | static int __net_init iptable_mangle_net_init(struct net *net) |
171 | 136 | { |
172 | 137 | |
... | ... | @@ -196,9 +161,11 @@ |
196 | 161 | return ret; |
197 | 162 | |
198 | 163 | /* Register hooks */ |
199 | - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | |
200 | - if (ret < 0) | |
164 | + mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); | |
165 | + if (IS_ERR(mangle_ops)) { | |
166 | + ret = PTR_ERR(mangle_ops); | |
201 | 167 | goto cleanup_table; |
168 | + } | |
202 | 169 | |
203 | 170 | return ret; |
204 | 171 | |
... | ... | @@ -209,7 +176,7 @@ |
209 | 176 | |
210 | 177 | static 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 | 180 | unregister_pernet_subsys(&iptable_mangle_net_ops); |
214 | 181 | } |
215 | 182 |
net/ipv4/netfilter/iptable_raw.c
... | ... | @@ -41,6 +41,7 @@ |
41 | 41 | .valid_hooks = RAW_VALID_HOOKS, |
42 | 42 | .me = THIS_MODULE, |
43 | 43 | .af = NFPROTO_IPV4, |
44 | + .priority = NF_IP_PRI_RAW, | |
44 | 45 | }; |
45 | 46 | |
46 | 47 | /* The work comes in here from netfilter.c. */ |
... | ... | @@ -61,23 +62,7 @@ |
61 | 62 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); |
62 | 63 | } |
63 | 64 | |
64 | -/* 'raw' is the very first table. */ | |
65 | -static 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 | -}; | |
65 | +static struct nf_hook_ops *rawtable_ops __read_mostly; | |
81 | 66 | |
82 | 67 | static int __net_init iptable_raw_net_init(struct net *net) |
83 | 68 | { |
84 | 69 | |
... | ... | @@ -108,9 +93,11 @@ |
108 | 93 | return ret; |
109 | 94 | |
110 | 95 | /* Register hooks */ |
111 | - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | |
112 | - if (ret < 0) | |
96 | + rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); | |
97 | + if (IS_ERR(rawtable_ops)) { | |
98 | + ret = PTR_ERR(rawtable_ops); | |
113 | 99 | goto cleanup_table; |
100 | + } | |
114 | 101 | |
115 | 102 | return ret; |
116 | 103 | |
... | ... | @@ -121,7 +108,7 @@ |
121 | 108 | |
122 | 109 | static 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 | 112 | unregister_pernet_subsys(&iptable_raw_net_ops); |
126 | 113 | } |
127 | 114 |
net/ipv4/netfilter/iptable_security.c
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 | .valid_hooks = SECURITY_VALID_HOOKS, |
63 | 63 | .me = THIS_MODULE, |
64 | 64 | .af = NFPROTO_IPV4, |
65 | + .priority = NF_IP_PRI_SECURITY, | |
65 | 66 | }; |
66 | 67 | |
67 | 68 | static unsigned int |
... | ... | @@ -82,29 +83,7 @@ |
82 | 83 | return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); |
83 | 84 | } |
84 | 85 | |
85 | -static struct nf_hook_ops ipt_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 | -}; | |
86 | +static struct nf_hook_ops *sectbl_ops __read_mostly; | |
108 | 87 | |
109 | 88 | static int __net_init iptable_security_net_init(struct net *net) |
110 | 89 | { |
111 | 90 | |
... | ... | @@ -135,9 +114,11 @@ |
135 | 114 | if (ret < 0) |
136 | 115 | return ret; |
137 | 116 | |
138 | - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | |
139 | - if (ret < 0) | |
117 | + sectbl_ops = xt_hook_link(&security_table, iptable_security_hook); | |
118 | + if (IS_ERR(sectbl_ops)) { | |
119 | + ret = PTR_ERR(sectbl_ops); | |
140 | 120 | goto cleanup_table; |
121 | + } | |
141 | 122 | |
142 | 123 | return ret; |
143 | 124 | |
... | ... | @@ -148,7 +129,7 @@ |
148 | 129 | |
149 | 130 | static 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 | 133 | unregister_pernet_subsys(&iptable_security_net_ops); |
153 | 134 | } |
154 | 135 |
net/ipv6/netfilter/ip6table_filter.c
... | ... | @@ -56,6 +56,7 @@ |
56 | 56 | .valid_hooks = FILTER_VALID_HOOKS, |
57 | 57 | .me = THIS_MODULE, |
58 | 58 | .af = NFPROTO_IPV6, |
59 | + .priority = NF_IP6_PRI_FILTER, | |
59 | 60 | }; |
60 | 61 | |
61 | 62 | /* The work comes in here from netfilter.c. */ |
... | ... | @@ -69,29 +70,7 @@ |
69 | 70 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); |
70 | 71 | } |
71 | 72 | |
72 | -static struct nf_hook_ops ip6t_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 | -}; | |
73 | +static struct nf_hook_ops *filter_ops __read_mostly; | |
95 | 74 | |
96 | 75 | /* Default to forward because I got too much mail already. */ |
97 | 76 | static int forward = NF_ACCEPT; |
98 | 77 | |
... | ... | @@ -134,9 +113,11 @@ |
134 | 113 | return ret; |
135 | 114 | |
136 | 115 | /* Register hooks */ |
137 | - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | |
138 | - if (ret < 0) | |
116 | + filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook); | |
117 | + if (IS_ERR(filter_ops)) { | |
118 | + ret = PTR_ERR(filter_ops); | |
139 | 119 | goto cleanup_table; |
120 | + } | |
140 | 121 | |
141 | 122 | return ret; |
142 | 123 | |
... | ... | @@ -147,7 +128,7 @@ |
147 | 128 | |
148 | 129 | static 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 | 132 | unregister_pernet_subsys(&ip6table_filter_net_ops); |
152 | 133 | } |
153 | 134 |
net/ipv6/netfilter/ip6table_mangle.c
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 | .valid_hooks = MANGLE_VALID_HOOKS, |
63 | 63 | .me = THIS_MODULE, |
64 | 64 | .af = NFPROTO_IPV6, |
65 | + .priority = NF_IP6_PRI_MANGLE, | |
65 | 66 | }; |
66 | 67 | |
67 | 68 | static unsigned int |
... | ... | @@ -122,44 +123,7 @@ |
122 | 123 | dev_net(in)->ipv6.ip6table_mangle); |
123 | 124 | } |
124 | 125 | |
125 | -static struct nf_hook_ops ip6t_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 | - | |
126 | +static struct nf_hook_ops *mangle_ops __read_mostly; | |
163 | 127 | static int __net_init ip6table_mangle_net_init(struct net *net) |
164 | 128 | { |
165 | 129 | /* Register table */ |
166 | 130 | |
... | ... | @@ -189,9 +153,11 @@ |
189 | 153 | return ret; |
190 | 154 | |
191 | 155 | /* Register hooks */ |
192 | - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | |
193 | - if (ret < 0) | |
156 | + mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook); | |
157 | + if (IS_ERR(mangle_ops)) { | |
158 | + ret = PTR_ERR(mangle_ops); | |
194 | 159 | goto cleanup_table; |
160 | + } | |
195 | 161 | |
196 | 162 | return ret; |
197 | 163 | |
... | ... | @@ -202,7 +168,7 @@ |
202 | 168 | |
203 | 169 | static 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 | 172 | unregister_pernet_subsys(&ip6table_mangle_net_ops); |
207 | 173 | } |
208 | 174 |
net/ipv6/netfilter/ip6table_raw.c
... | ... | @@ -40,6 +40,7 @@ |
40 | 40 | .valid_hooks = RAW_VALID_HOOKS, |
41 | 41 | .me = THIS_MODULE, |
42 | 42 | .af = NFPROTO_IPV6, |
43 | + .priority = NF_IP6_PRI_FIRST, | |
43 | 44 | }; |
44 | 45 | |
45 | 46 | /* The work comes in here from netfilter.c. */ |
... | ... | @@ -53,22 +54,7 @@ |
53 | 54 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); |
54 | 55 | } |
55 | 56 | |
56 | -static struct nf_hook_ops ip6t_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 | -}; | |
57 | +static struct nf_hook_ops *rawtable_ops __read_mostly; | |
72 | 58 | |
73 | 59 | static int __net_init ip6table_raw_net_init(struct net *net) |
74 | 60 | { |
75 | 61 | |
... | ... | @@ -99,9 +85,11 @@ |
99 | 85 | return ret; |
100 | 86 | |
101 | 87 | /* Register hooks */ |
102 | - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | |
103 | - if (ret < 0) | |
88 | + rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook); | |
89 | + if (IS_ERR(rawtable_ops)) { | |
90 | + ret = PTR_ERR(rawtable_ops); | |
104 | 91 | goto cleanup_table; |
92 | + } | |
105 | 93 | |
106 | 94 | return ret; |
107 | 95 | |
... | ... | @@ -112,7 +100,7 @@ |
112 | 100 | |
113 | 101 | static 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 | 104 | unregister_pernet_subsys(&ip6table_raw_net_ops); |
117 | 105 | } |
118 | 106 |
net/ipv6/netfilter/ip6table_security.c
... | ... | @@ -61,6 +61,7 @@ |
61 | 61 | .valid_hooks = SECURITY_VALID_HOOKS, |
62 | 62 | .me = THIS_MODULE, |
63 | 63 | .af = NFPROTO_IPV6, |
64 | + .priority = NF_IP6_PRI_SECURITY, | |
64 | 65 | }; |
65 | 66 | |
66 | 67 | static unsigned int |
... | ... | @@ -74,29 +75,7 @@ |
74 | 75 | return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); |
75 | 76 | } |
76 | 77 | |
77 | -static struct nf_hook_ops ip6t_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 | -}; | |
78 | +static struct nf_hook_ops *sectbl_ops __read_mostly; | |
100 | 79 | |
101 | 80 | static int __net_init ip6table_security_net_init(struct net *net) |
102 | 81 | { |
103 | 82 | |
... | ... | @@ -127,9 +106,11 @@ |
127 | 106 | if (ret < 0) |
128 | 107 | return ret; |
129 | 108 | |
130 | - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | |
131 | - if (ret < 0) | |
109 | + sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook); | |
110 | + if (IS_ERR(sectbl_ops)) { | |
111 | + ret = PTR_ERR(sectbl_ops); | |
132 | 112 | goto cleanup_table; |
113 | + } | |
133 | 114 | |
134 | 115 | return ret; |
135 | 116 | |
... | ... | @@ -140,7 +121,7 @@ |
140 | 121 | |
141 | 122 | static 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 | 125 | unregister_pernet_subsys(&ip6table_security_net_ops); |
145 | 126 | } |
146 | 127 |
net/netfilter/x_tables.c
... | ... | @@ -1091,6 +1091,60 @@ |
1091 | 1091 | |
1092 | 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 | + */ | |
1102 | +struct 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 | +} | |
1134 | +EXPORT_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 | + */ | |
1141 | +void 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 | +} | |
1146 | +EXPORT_SYMBOL_GPL(xt_hook_unlink); | |
1147 | + | |
1094 | 1148 | int xt_proto_init(struct net *net, u_int8_t af) |
1095 | 1149 | { |
1096 | 1150 | #ifdef CONFIG_PROC_FS |