diff options
author | Harald Welte <laforge@netfilter.org> | 2005-08-09 22:43:44 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:36:49 -0400 |
commit | 0ab43f84995f2c2fcc5cc58a9accaa1095e1317f (patch) | |
tree | f58711648f91bbd880fcada7718a2462f0249a78 /net | |
parent | 2cc7d5730957c4a3f3659d17d2ba5e06d5581c1f (diff) |
[NETFILTER]: Core changes required by upcoming nfnetlink_queue code
- split netfiler verdict in 16bit verdict and 16bit queue number
- add 'queuenum' argument to nf_queue_outfn_t and its users ip[6]_queue
- move NFNL_SUBSYS_ definitions from enum to #define
- introduce autoloading for nfnetlink subsystem modules
- add MODULE_ALIAS_NFNL_SUBSYS macro
- add nf_unregister_queue_handlers() to register all handlers for a given
nf_queue_outfn_t
- add more verbose DEBUGP macro definition to nfnetlink.c
- make nfnetlink_subsys_register fail if subsys already exists
- add some more comments and debug statements to nfnetlink.c
Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/netfilter.c | 40 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 3 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 28 |
4 files changed, 59 insertions, 15 deletions
diff --git a/net/core/netfilter.c b/net/core/netfilter.c index 1ed4f3110421..3e38084ac2bd 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c | |||
@@ -221,7 +221,8 @@ static unsigned int nf_iterate(struct list_head *head, | |||
221 | verdict = elem->hook(hook, skb, indev, outdev, okfn); | 221 | verdict = elem->hook(hook, skb, indev, outdev, okfn); |
222 | if (verdict != NF_ACCEPT) { | 222 | if (verdict != NF_ACCEPT) { |
223 | #ifdef CONFIG_NETFILTER_DEBUG | 223 | #ifdef CONFIG_NETFILTER_DEBUG |
224 | if (unlikely(verdict > NF_MAX_VERDICT)) { | 224 | if (unlikely((verdict & NF_VERDICT_MASK) |
225 | > NF_MAX_VERDICT)) { | ||
225 | NFDEBUG("Evil return from %p(%u).\n", | 226 | NFDEBUG("Evil return from %p(%u).\n", |
226 | elem->hook, hook); | 227 | elem->hook, hook); |
227 | continue; | 228 | continue; |
@@ -239,6 +240,9 @@ int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data) | |||
239 | { | 240 | { |
240 | int ret; | 241 | int ret; |
241 | 242 | ||
243 | if (pf >= NPROTO) | ||
244 | return -EINVAL; | ||
245 | |||
242 | write_lock_bh(&queue_handler_lock); | 246 | write_lock_bh(&queue_handler_lock); |
243 | if (queue_handler[pf].outfn) | 247 | if (queue_handler[pf].outfn) |
244 | ret = -EBUSY; | 248 | ret = -EBUSY; |
@@ -255,6 +259,9 @@ int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data) | |||
255 | /* The caller must flush their queue before this */ | 259 | /* The caller must flush their queue before this */ |
256 | int nf_unregister_queue_handler(int pf) | 260 | int nf_unregister_queue_handler(int pf) |
257 | { | 261 | { |
262 | if (pf >= NPROTO) | ||
263 | return -EINVAL; | ||
264 | |||
258 | write_lock_bh(&queue_handler_lock); | 265 | write_lock_bh(&queue_handler_lock); |
259 | queue_handler[pf].outfn = NULL; | 266 | queue_handler[pf].outfn = NULL; |
260 | queue_handler[pf].data = NULL; | 267 | queue_handler[pf].data = NULL; |
@@ -286,6 +293,20 @@ int nf_unregister_queue_rerouter(int pf) | |||
286 | return 0; | 293 | return 0; |
287 | } | 294 | } |
288 | 295 | ||
296 | void nf_unregister_queue_handlers(nf_queue_outfn_t outfn) | ||
297 | { | ||
298 | int pf; | ||
299 | |||
300 | write_lock_bh(&queue_handler_lock); | ||
301 | for (pf = 0; pf < NPROTO; pf++) { | ||
302 | if (queue_handler[pf].outfn == outfn) { | ||
303 | queue_handler[pf].outfn = NULL; | ||
304 | queue_handler[pf].data = NULL; | ||
305 | } | ||
306 | } | ||
307 | write_unlock_bh(&queue_handler_lock); | ||
308 | } | ||
309 | |||
289 | /* | 310 | /* |
290 | * Any packet that leaves via this function must come back | 311 | * Any packet that leaves via this function must come back |
291 | * through nf_reinject(). | 312 | * through nf_reinject(). |
@@ -295,7 +316,8 @@ static int nf_queue(struct sk_buff **skb, | |||
295 | int pf, unsigned int hook, | 316 | int pf, unsigned int hook, |
296 | struct net_device *indev, | 317 | struct net_device *indev, |
297 | struct net_device *outdev, | 318 | struct net_device *outdev, |
298 | int (*okfn)(struct sk_buff *)) | 319 | int (*okfn)(struct sk_buff *), |
320 | unsigned int queuenum) | ||
299 | { | 321 | { |
300 | int status; | 322 | int status; |
301 | struct nf_info *info; | 323 | struct nf_info *info; |
@@ -347,7 +369,8 @@ static int nf_queue(struct sk_buff **skb, | |||
347 | if (queue_rerouter[pf].save) | 369 | if (queue_rerouter[pf].save) |
348 | queue_rerouter[pf].save(*skb, info); | 370 | queue_rerouter[pf].save(*skb, info); |
349 | 371 | ||
350 | status = queue_handler[pf].outfn(*skb, info, queue_handler[pf].data); | 372 | status = queue_handler[pf].outfn(*skb, info, queuenum, |
373 | queue_handler[pf].data); | ||
351 | 374 | ||
352 | if (status >= 0 && queue_rerouter[pf].reroute) | 375 | if (status >= 0 && queue_rerouter[pf].reroute) |
353 | status = queue_rerouter[pf].reroute(skb, info); | 376 | status = queue_rerouter[pf].reroute(skb, info); |
@@ -397,9 +420,10 @@ next_hook: | |||
397 | } else if (verdict == NF_DROP) { | 420 | } else if (verdict == NF_DROP) { |
398 | kfree_skb(*pskb); | 421 | kfree_skb(*pskb); |
399 | ret = -EPERM; | 422 | ret = -EPERM; |
400 | } else if (verdict == NF_QUEUE) { | 423 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { |
401 | NFDEBUG("nf_hook: Verdict = QUEUE.\n"); | 424 | NFDEBUG("nf_hook: Verdict = QUEUE.\n"); |
402 | if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn)) | 425 | if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn, |
426 | verdict >> NF_VERDICT_BITS)) | ||
403 | goto next_hook; | 427 | goto next_hook; |
404 | } | 428 | } |
405 | unlock: | 429 | unlock: |
@@ -456,14 +480,15 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, | |||
456 | info->okfn, INT_MIN); | 480 | info->okfn, INT_MIN); |
457 | } | 481 | } |
458 | 482 | ||
459 | switch (verdict) { | 483 | switch (verdict & NF_VERDICT_MASK) { |
460 | case NF_ACCEPT: | 484 | case NF_ACCEPT: |
461 | info->okfn(skb); | 485 | info->okfn(skb); |
462 | break; | 486 | break; |
463 | 487 | ||
464 | case NF_QUEUE: | 488 | case NF_QUEUE: |
465 | if (!nf_queue(&skb, elem, info->pf, info->hook, | 489 | if (!nf_queue(&skb, elem, info->pf, info->hook, |
466 | info->indev, info->outdev, info->okfn)) | 490 | info->indev, info->outdev, info->okfn, |
491 | verdict >> NF_VERDICT_BITS)) | ||
467 | goto next_hook; | 492 | goto next_hook; |
468 | break; | 493 | break; |
469 | } | 494 | } |
@@ -613,6 +638,7 @@ EXPORT_SYMBOL(nf_reinject); | |||
613 | EXPORT_SYMBOL(nf_setsockopt); | 638 | EXPORT_SYMBOL(nf_setsockopt); |
614 | EXPORT_SYMBOL(nf_unregister_hook); | 639 | EXPORT_SYMBOL(nf_unregister_hook); |
615 | EXPORT_SYMBOL(nf_unregister_queue_handler); | 640 | EXPORT_SYMBOL(nf_unregister_queue_handler); |
641 | EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); | ||
616 | EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); | 642 | EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); |
617 | EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); | 643 | EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); |
618 | EXPORT_SYMBOL(nf_unregister_sockopt); | 644 | EXPORT_SYMBOL(nf_unregister_sockopt); |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 78892980f42c..cfc886f382ac 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -280,7 +280,8 @@ nlmsg_failure: | |||
280 | } | 280 | } |
281 | 281 | ||
282 | static int | 282 | static int |
283 | ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) | 283 | ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, |
284 | unsigned int queuenum, void *data) | ||
284 | { | 285 | { |
285 | int status = -EINVAL; | 286 | int status = -EINVAL; |
286 | struct sk_buff *nskb; | 287 | struct sk_buff *nskb; |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index c45d8f8815de..5af4cee93d9b 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -278,7 +278,8 @@ nlmsg_failure: | |||
278 | } | 278 | } |
279 | 279 | ||
280 | static int | 280 | static int |
281 | ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) | 281 | ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, |
282 | unsigned int queuenum, void *data) | ||
282 | { | 283 | { |
283 | int status = -EINVAL; | 284 | int status = -EINVAL; |
284 | struct sk_buff *nskb; | 285 | struct sk_buff *nskb; |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 6210ca42166c..30b25f47f7cc 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -44,7 +44,9 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); | |||
44 | static char __initdata nfversion[] = "0.30"; | 44 | static char __initdata nfversion[] = "0.30"; |
45 | 45 | ||
46 | #if 0 | 46 | #if 0 |
47 | #define DEBUGP printk | 47 | #define DEBUGP(format, args...) \ |
48 | printk(KERN_DEBUG "%s(%d):%s(): " format, __FILE__, \ | ||
49 | __LINE__, __FUNCTION__, ## args) | ||
48 | #else | 50 | #else |
49 | #define DEBUGP(format, args...) | 51 | #define DEBUGP(format, args...) |
50 | #endif | 52 | #endif |
@@ -67,11 +69,11 @@ int nfnetlink_subsys_register(struct nfnetlink_subsystem *n) | |||
67 | { | 69 | { |
68 | DEBUGP("registering subsystem ID %u\n", n->subsys_id); | 70 | DEBUGP("registering subsystem ID %u\n", n->subsys_id); |
69 | 71 | ||
70 | /* If the netlink socket wasn't created, then fail */ | ||
71 | if (!nfnl) | ||
72 | return -1; | ||
73 | |||
74 | nfnl_lock(); | 72 | nfnl_lock(); |
73 | if (subsys_table[n->subsys_id]) { | ||
74 | nfnl_unlock(); | ||
75 | return -EBUSY; | ||
76 | } | ||
75 | subsys_table[n->subsys_id] = n; | 77 | subsys_table[n->subsys_id] = n; |
76 | nfnl_unlock(); | 78 | nfnl_unlock(); |
77 | 79 | ||
@@ -227,8 +229,18 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
227 | 229 | ||
228 | type = nlh->nlmsg_type; | 230 | type = nlh->nlmsg_type; |
229 | ss = nfnetlink_get_subsys(type); | 231 | ss = nfnetlink_get_subsys(type); |
230 | if (!ss) | 232 | if (!ss) { |
233 | #ifdef CONFIG_KMOD | ||
234 | /* don't call nfnl_shunlock, since it would reenter | ||
235 | * with further packet processing */ | ||
236 | up(&nfnl_sem); | ||
237 | request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); | ||
238 | nfnl_shlock(); | ||
239 | ss = nfnetlink_get_subsys(type); | ||
240 | if (!ss) | ||
241 | #endif | ||
231 | goto err_inval; | 242 | goto err_inval; |
243 | } | ||
232 | 244 | ||
233 | nc = nfnetlink_find_client(type, ss); | 245 | nc = nfnetlink_find_client(type, ss); |
234 | if (!nc) { | 246 | if (!nc) { |
@@ -252,12 +264,14 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
252 | if (err < 0) | 264 | if (err < 0) |
253 | goto err_inval; | 265 | goto err_inval; |
254 | 266 | ||
267 | DEBUGP("calling handler\n"); | ||
255 | err = nc->call(nfnl, skb, nlh, cda, errp); | 268 | err = nc->call(nfnl, skb, nlh, cda, errp); |
256 | *errp = err; | 269 | *errp = err; |
257 | return err; | 270 | return err; |
258 | } | 271 | } |
259 | 272 | ||
260 | err_inval: | 273 | err_inval: |
274 | DEBUGP("returning -EINVAL\n"); | ||
261 | *errp = -EINVAL; | 275 | *errp = -EINVAL; |
262 | return -1; | 276 | return -1; |
263 | } | 277 | } |
@@ -311,6 +325,8 @@ static void nfnetlink_rcv(struct sock *sk, int len) | |||
311 | kfree_skb(skb); | 325 | kfree_skb(skb); |
312 | } | 326 | } |
313 | 327 | ||
328 | /* don't call nfnl_shunlock, since it would reenter | ||
329 | * with further packet processing */ | ||
314 | up(&nfnl_sem); | 330 | up(&nfnl_sem); |
315 | } while(nfnl && nfnl->sk_receive_queue.qlen); | 331 | } while(nfnl && nfnl->sk_receive_queue.qlen); |
316 | } | 332 | } |