IP输入 之 ip_local_deliver && ip_local_deliver_finish

概述:

当ip包收上来,查路由,发现是发往本地的数据包时,会调用ip_local_deliver函数;

ip_local_deliver中对ip分片进行重组,经过LOCAL_IN钩子点,然后调用ip_local_deliver_finish;

ip_local_deliver_finish函数处理原始套接字的数据接收,并调用上层协议的包接收函数,将数据包传递到传输层;

以下为源码分析:

 1 /*
 2  *     Deliver IP Packets to the higher protocol layers.
 3  */
 4 int ip_local_deliver(struct sk_buff *skb)
 5 {
 6     /*
 7      *    Reassemble IP fragments.
 8      */
 9     struct net *net = dev_net(skb->dev);
10 
11     /* 分片重组 */
12     if (ip_is_fragment(ip_hdr(skb))) {
13         if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER))
14             return 0;
15     }
16 
17     /* 经过LOCAL_IN钩子点 */
18     return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,
19                net, NULL, skb, skb->dev, NULL,
20                ip_local_deliver_finish);
21 }

 

 1 static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 2 {
 3     /* 去掉ip头 */
 4     __skb_pull(skb, skb_network_header_len(skb));
 5 
 6     rcu_read_lock();
 7     {
 8         /* 获取协议 */
 9         int protocol = ip_hdr(skb)->protocol;
10         const struct net_protocol *ipprot;
11         int raw;
12 
13     resubmit:
14         /* 原始套接口,复制一个副本,输出到该套接口 */
15         raw = raw_local_deliver(skb, protocol);
16 
17         /* 获取协议处理结构 */
18         ipprot = rcu_dereference(inet_protos[protocol]);
19         if (ipprot) {
20             int ret;
21 
22             if (!ipprot->no_policy) {
23                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
24                     kfree_skb(skb);
25                     goto out;
26                 }
27                 nf_reset(skb);
28             }
29 
30             /* 协议上层收包处理函数 */
31             ret = ipprot->handler(skb);
32             if (ret < 0) {
33                 protocol = -ret;
34                 goto resubmit;
35             }
36             __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
37         } 
38         /* 没有协议接收该数据包 */
39         else {
40             /* 原始套接口未接收或接收异常 */
41             if (!raw) {
42                 if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
43                     __IP_INC_STATS(net, IPSTATS_MIB_INUNKNOWNPROTOS);
44                     /* 发送icmp */
45                     icmp_send(skb, ICMP_DEST_UNREACH,
46                           ICMP_PROT_UNREACH, 0);
47                 }
48                 /* 丢包 */
49                 kfree_skb(skb);
50             } 
51             /* 原始套接口接收 */
52             else {
53                 __IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
54                 /* 释放包 */
55                 consume_skb(skb);
56             }
57         }
58     }
59  out:
60     rcu_read_unlock();
61 
62     return 0;
63 }

 

posted @ 2017-09-27 20:30  AlexAlex  阅读(1249)  评论(0编辑  收藏  举报