L4协议的注册:
位于IPv4之上的L4协议是由net_protocol数据结构定义的
1: struct net_protocol {
2: int (*handler)(struct sk_buff *skb);
3: void (*err_handler)(struct sk_buff *skb, u32 info);
4: int (*gso_send_check)(struct sk_buff *skb);
5: struct sk_buff *(*gso_segment)(struct sk_buff *skb,
6: int features);
7: struct sk_buff **(*gro_receive)(struct sk_buff **head,
8: struct sk_buff *skb);
9: int (*gro_complete)(struct sk_buff *skb);
10: unsigned int no_policy:1,
11: netns_ok:1;
12: };
handler,由此协议注册的函数,来作为送进来的封包的处理函数。
err_handler,由icmp协议处理函数所用的函数,用于通知l4协议有关接收到icmp unreachable消息的时间。
no_policy,此字段在网络协议中的某些关键点都会被查询,用于使协议免于ipsec策略检查:1是指没有必要针对此协议检查ipsec策略。
1: /*
2: * Add a protocol handler to the hash tables
3: */
4:
5: int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
6: {
7: int hash, ret;
8:
9: hash = protocol & (MAX_INET_PROTOS - 1);
10:
11: spin_lock_bh(&inet_proto_lock);
12: if (inet_protos[hash]) {
13: ret = -1;
14: } else {
15: inet_protos[hash] = prot;
16: ret = 0;
17: }
18: spin_unlock_bh(&inet_proto_lock);
19:
20: return ret;
21: }
22:
23: /*
24: * Remove a protocol from the hash tables.
25: */
26:
27: int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
28: {
29: int hash, ret;
30:
31: hash = protocol & (MAX_INET_PROTOS - 1);
32:
33: spin_lock_bh(&inet_proto_lock);
34: if (inet_protos[hash] == prot) {
35: inet_protos[hash] = NULL;
36: ret = 0;
37: } else {
38: ret = -1;
39: }
40: spin_unlock_bh(&inet_proto_lock);
41:
42: synchronize_net();
43:
44: return ret;
45: }
1: static int ip_local_deliver_finish(struct sk_buff *skb)
2: {
3: struct net *net = dev_net(skb->dev);
4:
5: __skb_pull(skb, ip_hdrlen(skb));
6:
7: /* Point into the IP datagram, just past the header. */
8: skb_reset_transport_header(skb);
9:
10: rcu_read_lock();
11: {
12: int protocol = ip_hdr(skb)->protocol;
13: int hash, raw;
14: const struct net_protocol *ipprot;
15:
16: resubmit:
17: raw = raw_local_deliver(skb, protocol);
18:
19: hash = protocol & (MAX_INET_PROTOS - 1);
20: ipprot = rcu_dereference(inet_protos[hash]);
21: if (ipprot != NULL) {
22: int ret;
23:
24: if (!net_eq(net, &init_net) && !ipprot->netns_ok) {
25: if (net_ratelimit())
26: printk("%s: proto %d isn't netns-ready\n",
27: __func__, protocol);
28: kfree_skb(skb);
29: goto out;
30: }
31:
32: if (!ipprot->no_policy) {
33: if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
34: kfree_skb(skb);
35: goto out;
36: }
37: nf_reset(skb);
38: }
39: ret = ipprot->handler(skb);
40: if (ret < 0) {
41: protocol = -ret;
42: goto resubmit;
43: }
44: IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
45: } else {
46: if (!raw) {
47: if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
48: IP_INC_STATS_BH(net, IPSTATS_MIB_INUNKNOWNPROTOS);
49: icmp_send(skb, ICMP_DEST_UNREACH,
50: ICMP_PROT_UNREACH, 0);
51: }
52: } else
53: IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS);
54: kfree_skb(skb);
55: }
56: }
57: out:
58: rcu_read_unlock();
59:
60: return 0;
61: }