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 }