aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-08-09 22:43:44 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:36:49 -0400
commit0ab43f84995f2c2fcc5cc58a9accaa1095e1317f (patch)
treef58711648f91bbd880fcada7718a2462f0249a78 /net
parent2cc7d5730957c4a3f3659d17d2ba5e06d5581c1f (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.c40
-rw-r--r--net/ipv4/netfilter/ip_queue.c3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c3
-rw-r--r--net/netfilter/nfnetlink.c28
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 */
256int nf_unregister_queue_handler(int pf) 260int 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
296void 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 }
405unlock: 429unlock:
@@ -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);
613EXPORT_SYMBOL(nf_setsockopt); 638EXPORT_SYMBOL(nf_setsockopt);
614EXPORT_SYMBOL(nf_unregister_hook); 639EXPORT_SYMBOL(nf_unregister_hook);
615EXPORT_SYMBOL(nf_unregister_queue_handler); 640EXPORT_SYMBOL(nf_unregister_queue_handler);
641EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
616EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); 642EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
617EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); 643EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
618EXPORT_SYMBOL(nf_unregister_sockopt); 644EXPORT_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
282static int 282static int
283ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) 283ipq_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
280static int 280static int
281ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) 281ipq_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);
44static char __initdata nfversion[] = "0.30"; 44static 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
260err_inval: 273err_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}