diff options
author | Mahesh Bandewar <maheshb@google.com> | 2016-09-16 15:59:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-09-19 01:25:22 -0400 |
commit | e8bffe0cf964f0330595bb376b74921cccdaac88 (patch) | |
tree | c3361b07773fa3d0900c4a5b10b44c77a3155806 | |
parent | d409b84768037ad03d1d73538d99fb902adf7365 (diff) |
net: Add _nf_(un)register_hooks symbols
Add _nf_register_hooks() and _nf_unregister_hooks() calls which allow
caller to hold RTNL mutex.
Signed-off-by: Mahesh Bandewar <maheshb@google.com>
CC: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter.h | 2 | ||||
-rw-r--r-- | net/netfilter/core.c | 51 |
2 files changed, 48 insertions, 5 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 9230f9aee896..e82b76781bf6 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -133,6 +133,8 @@ int nf_register_hook(struct nf_hook_ops *reg); | |||
133 | void nf_unregister_hook(struct nf_hook_ops *reg); | 133 | void nf_unregister_hook(struct nf_hook_ops *reg); |
134 | int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); | 134 | int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); |
135 | void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n); | 135 | void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n); |
136 | int _nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); | ||
137 | void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n); | ||
136 | 138 | ||
137 | /* Functions to register get/setsockopt ranges (non-inclusive). You | 139 | /* Functions to register get/setsockopt ranges (non-inclusive). You |
138 | need to check permissions yourself! */ | 140 | need to check permissions yourself! */ |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index f39276d1c2d7..2c5327e43a88 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -188,19 +188,17 @@ EXPORT_SYMBOL(nf_unregister_net_hooks); | |||
188 | 188 | ||
189 | static LIST_HEAD(nf_hook_list); | 189 | static LIST_HEAD(nf_hook_list); |
190 | 190 | ||
191 | int nf_register_hook(struct nf_hook_ops *reg) | 191 | static int _nf_register_hook(struct nf_hook_ops *reg) |
192 | { | 192 | { |
193 | struct net *net, *last; | 193 | struct net *net, *last; |
194 | int ret; | 194 | int ret; |
195 | 195 | ||
196 | rtnl_lock(); | ||
197 | for_each_net(net) { | 196 | for_each_net(net) { |
198 | ret = nf_register_net_hook(net, reg); | 197 | ret = nf_register_net_hook(net, reg); |
199 | if (ret && ret != -ENOENT) | 198 | if (ret && ret != -ENOENT) |
200 | goto rollback; | 199 | goto rollback; |
201 | } | 200 | } |
202 | list_add_tail(®->list, &nf_hook_list); | 201 | list_add_tail(®->list, &nf_hook_list); |
203 | rtnl_unlock(); | ||
204 | 202 | ||
205 | return 0; | 203 | return 0; |
206 | rollback: | 204 | rollback: |
@@ -210,19 +208,34 @@ rollback: | |||
210 | break; | 208 | break; |
211 | nf_unregister_net_hook(net, reg); | 209 | nf_unregister_net_hook(net, reg); |
212 | } | 210 | } |
211 | return ret; | ||
212 | } | ||
213 | |||
214 | int nf_register_hook(struct nf_hook_ops *reg) | ||
215 | { | ||
216 | int ret; | ||
217 | |||
218 | rtnl_lock(); | ||
219 | ret = _nf_register_hook(reg); | ||
213 | rtnl_unlock(); | 220 | rtnl_unlock(); |
221 | |||
214 | return ret; | 222 | return ret; |
215 | } | 223 | } |
216 | EXPORT_SYMBOL(nf_register_hook); | 224 | EXPORT_SYMBOL(nf_register_hook); |
217 | 225 | ||
218 | void nf_unregister_hook(struct nf_hook_ops *reg) | 226 | static void _nf_unregister_hook(struct nf_hook_ops *reg) |
219 | { | 227 | { |
220 | struct net *net; | 228 | struct net *net; |
221 | 229 | ||
222 | rtnl_lock(); | ||
223 | list_del(®->list); | 230 | list_del(®->list); |
224 | for_each_net(net) | 231 | for_each_net(net) |
225 | nf_unregister_net_hook(net, reg); | 232 | nf_unregister_net_hook(net, reg); |
233 | } | ||
234 | |||
235 | void nf_unregister_hook(struct nf_hook_ops *reg) | ||
236 | { | ||
237 | rtnl_lock(); | ||
238 | _nf_unregister_hook(reg); | ||
226 | rtnl_unlock(); | 239 | rtnl_unlock(); |
227 | } | 240 | } |
228 | EXPORT_SYMBOL(nf_unregister_hook); | 241 | EXPORT_SYMBOL(nf_unregister_hook); |
@@ -246,6 +259,26 @@ err: | |||
246 | } | 259 | } |
247 | EXPORT_SYMBOL(nf_register_hooks); | 260 | EXPORT_SYMBOL(nf_register_hooks); |
248 | 261 | ||
262 | /* Caller MUST take rtnl_lock() */ | ||
263 | int _nf_register_hooks(struct nf_hook_ops *reg, unsigned int n) | ||
264 | { | ||
265 | unsigned int i; | ||
266 | int err = 0; | ||
267 | |||
268 | for (i = 0; i < n; i++) { | ||
269 | err = _nf_register_hook(®[i]); | ||
270 | if (err) | ||
271 | goto err; | ||
272 | } | ||
273 | return err; | ||
274 | |||
275 | err: | ||
276 | if (i > 0) | ||
277 | _nf_unregister_hooks(reg, i); | ||
278 | return err; | ||
279 | } | ||
280 | EXPORT_SYMBOL(_nf_register_hooks); | ||
281 | |||
249 | void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) | 282 | void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) |
250 | { | 283 | { |
251 | while (n-- > 0) | 284 | while (n-- > 0) |
@@ -253,6 +286,14 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) | |||
253 | } | 286 | } |
254 | EXPORT_SYMBOL(nf_unregister_hooks); | 287 | EXPORT_SYMBOL(nf_unregister_hooks); |
255 | 288 | ||
289 | /* Caller MUST take rtnl_lock */ | ||
290 | void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) | ||
291 | { | ||
292 | while (n-- > 0) | ||
293 | _nf_unregister_hook(®[n]); | ||
294 | } | ||
295 | EXPORT_SYMBOL(_nf_unregister_hooks); | ||
296 | |||
256 | unsigned int nf_iterate(struct list_head *head, | 297 | unsigned int nf_iterate(struct list_head *head, |
257 | struct sk_buff *skb, | 298 | struct sk_buff *skb, |
258 | struct nf_hook_state *state, | 299 | struct nf_hook_state *state, |