全部博文(140)
分类: LINUX
2014-03-10 23:22:32
/* Returns 1 if okfn() needs to be executed by the caller,* -EPERM for NF_DROP, 0 otherwise. */int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,struct net_device *indev, struct net_device *outdev,int (*okfn)(struct sk_buff *), int hook_thresh){struct list_head *elem;unsigned int verdict; //四个字节,高16位为queue-num,低16位是NF_QUEUE.int ret = 0;
/* We may already have this, but read-locks nest anyway */rcu_read_lock();
elem = &nf_hooks[pf][hook];next_hook:verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,outdev, &elem, okfn, hook_thresh); //verdict是回调函数的返回值,比如返回一个NF_QUEUE.if (verdict == NF_ACCEPT || verdict == NF_STOP) {ret = 1;} else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {kfree_skb(skb);ret = NF_DROP_GETERR(verdict);if (ret == 0)ret = -EPERM;} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {int err = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,verdict >> NF_VERDICT_QBITS); //将数据包传递给上层,并等待消息if (err < 0) {if (err == -ECANCELED)goto next_hook;if (err == -ESRCH &&(verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))goto next_hook;kfree_skb(skb);}}rcu_read_unlock();return ret;}EXPORT_SYMBOL(nf_hook_slow);