|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 | // include/linux/netfilter.h
static inline int
NF_HOOK(...)
{
	int ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn);
	if (ret == 1)
		ret = okfn(net, sk, skb);
	return ret;
}
/**
 *	nf_hook - 调用 netfilter 钩子
 */
static inline int nf_hook(...)
{
	struct nf_hook_entries *hook_head = NULL;
	int ret = 1;
	...
	switch (pf) { // 在此处区分 ipv4, ipv6, arp, bridge, decnet,并获取指定钩子序号的钩子列表
	case NFPROTO_IPV4:
		hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]);
		break;
	case NFPROTO_IPV6:
		hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]);
		break;
	case NFPROTO_ARP:
		hook_head = rcu_dereference(net->nf.hooks_arp[hook]);
		break;
	case NFPROTO_BRIDGE:
		hook_head = rcu_dereference(net->nf.hooks_bridge[hook]);
		break;
	case NFPROTO_DECNET:
		hook_head = rcu_dereference(net->nf.hooks_decnet[hook]);
		break;
	default:
		WARN_ON_ONCE(1);
		break;
	}
	if (hook_head) {
		struct nf_hook_state state;
		nf_hook_state_init(&state, hook, pf, indev, outdev,
				   sk, net, okfn);
		ret = nf_hook_slow(skb, &state, hook_head, 0); // 执行列表里的钩子
	}
	return ret;
}
// net/netfilter/core.c
int nf_hook_slow(...)
{
	unsigned int verdict;
	int ret;
	for (; s < e->num_hook_entries; s++) { // 遍历钩子列表
		verdict = nf_hook_entry_hookfn(&e->hooks[s], skb, state); // 执行钩子函数
		switch (verdict & NF_VERDICT_MASK) {
		case NF_ACCEPT:    // -j ACCEPT
			break;
		case NF_DROP:      // -j DROP
			kfree_skb(skb);
			...
			return ret;
		case NF_QUEUE:     // -j NFQUEUE
			ret = nf_queue(skb, state, s, verdict); // NFQUEUE 的处理入口
			if (ret == 1)
				continue;
			return ret;
		default:
			/* Implicit handling for NF_STOLEN, as well as any other
			 * non conventional verdicts.
			 */
			return 0;
		}
	}
	return 1;
}
// include/linux/netfilter.h
static inline int
nf_hook_entry_hookfn(const struct nf_hook_entry *entry, struct sk_buff *skb,
			 struct nf_hook_state *state)
{
	return entry->hook(entry->priv, skb, state);
}
 |