分类: LINUX
2007-03-19 15:33:42
nf_iterate()函数遍历由i给定的链表,并且对于给定的分组调用链表结点中注册函数进行处理。
335 static unsigned int nf_iterate(struct list_head *head,
336 struct sk_buff **skb,
337 int hook,
338 const struct net_device *indev,
339 const struct net_device *outdev,
340 struct list_head **i,
341 int (*okfn)(struct sk_buff *))
342 {
for循环完成遍历操作。当调用结点中的hook函数后,根据返回值进行相应处理。如果hook函数的返回值是NF_QUEUE,NF_STOLEN,NF_DROP时,函数返回该值;如果返回值是NF_REPEAT时,则跳到前一个结点继续处理;如果是其他值,由下一个结点继续处理。如果整条链表处理完毕,返回值不是上面四个值,则返回NF_ACCEPT。
343 for (*i = (*i)->next; *i != head; *i = (*i)->next) {
344 struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
345 switch (elem->hook(hook, skb, indev, outdev, okfn)) {
346 case NF_QUEUE:
347 return NF_QUEUE;
348
349 case NF_STOLEN:
350 return NF_STOLEN;
351
352 case NF_DROP:
353 return NF_DROP;
354
355 case NF_REPEAT:
356 *i = (*i)->prev;
357 break;
358
359 #ifdef CONFIG_NETFILTER_DEBUG
360 case NF_ACCEPT:
361 break;
362
363 default:
364 NFDEBUG("Evil return from %p(%u).\n",
365 elem->hook, hook);
366 #endif
367 }
368 }
369 return NF_ACCEPT;
370 }
371
为队列注册处理函数。注册的时候是每一个协议族只注册一个处理函数,如果给定的协议族已经注册了处理函数,则返回出错信息。由于queue_handler是全局结构变量,所以注册时和删除时,要进行加锁保护。
372 int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
373 {
374 int ret;
375
376 br_write_lock_bh(BR_NETPROTO_LOCK);
377 if (queue_handler[pf].outfn)
378 ret = -EBUSY;
379 else {
380 queue_handler[pf].outfn = outfn;
381 queue_handler[pf].data = data;
382 ret = 0;
383 }
384 br_write_unlock_bh(BR_NETPROTO_LOCK);
385
386 return ret;
387 }
388
389 /* The caller must flush their queue before this */
删除给定协议族的队列处理函数。
390 int nf_unregister_queue_handler(int pf)
391 {
392 br_write_lock_bh(BR_NETPROTO_LOCK);
393 queue_handler[pf].outfn = NULL;
394 queue_handler[pf].data = NULL;
395 br_write_unlock_bh(BR_NETPROTO_LOCK);
396 return 0;
397 }
398
399 /*
400 * Any packet that leaves via this function must come back
401 * through nf_reinject().
402 */
nf_queue首先检查给定协议族是否有队列处理函数,如果没有,则无法处理分组,只能丢弃之,然后返回。接着给由skb指定的分组 分配并且附加一个netfilter信息头。如果没有空间,则打印出错信息。这两项工作完成后,调用队列的处理函数处理本分组。如果处理过程中出错,则丢弃分组,并且归还已分配的netfilter信息头空间。
403 static void nf_queue(struct sk_buff *skb,
404 struct list_head *elem,
405 int pf, unsigned int hook,
406 struct net_device *indev,
407 struct net_device *outdev,
408 int (*okfn)(struct sk_buff *))
409 {
410 int status;
411 struct nf_info *info;
412
413 if (!queue_handler[pf].outfn) {
414 kfree_skb(skb);
415 return;
416 }
417
418 info = kmalloc(sizeof(*info), GFP_ATOMIC);
419 if (!info) {
420 if (net_ratelimit())
421 printk(KERN_ERR "OOM queueing packet %p\n",
422 skb);
423 kfree_skb(skb);
424 return;
425 }
426
427 *info = (struct nf_info) {
428 (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
429
430 /* Bump dev refs so they don't vanish while packet is out */
431 if (indev) dev_hold(indev);
432 if (outdev) dev_hold(outdev);
433
434 status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);
435 if (status < 0) { <