ip_local_deliver_finish()

190 篇文章 1 订阅
ip_local_deliver()  --> ip_local_deliver_finish()

    The packet has now reached the end of the Internet Protocol processing. It is checked to see whether the packet is intended for a RAW-IP socket; otherwise, the transport protocol has to be determined for further processing (demultiplexing). 

    All transport protocols are managed in the ipprot hash table on the IP layer in Linux. At the end of the IP processing, there is now a special data structure, instead of simple query sequences and simple commands. The reason lies mainly in the nature of the Internet Protocol. Unless a packet includes special options, IP processing is very simple, and so IP is efficient and easy to implement. The complexity of IP packet options normally necessitates several more complex programming methods. 

    The protocol ID of the IP header modulo (MAX_INET_PROTOS - 1) is used to calculate the hash value in the ipprot hash table. The hash table is organized so that there are no collisions. If a new transport protocol would ever have to be integrated, then the assignment in the hash table should be checked. If the corresponding transport protocol can be found, then the appropriate handling routine (handler) of the protocol is invoked. The following handling routines are most common: 

     tcp_v4_rcv() : Transmission Control Protocol      (TCP)
    udp_rcv():    User Datagram Protocol             (UDP)
     icmp_rcv() :   Internet Control Message Protocol (ICMP)
    igmp_rcv():   Internet Group Management Protocol (IGMP)

    If no transport protocol can be found, then the packet either is passed to a RAW socket (if there is one) or it is dropped and an ICMP Destination Unreachable message is returned to the sender. 


/usr/src/linux-2.6.19/net/ipv4/ip_input.c

static inline int  ip_local_deliver_finish (struct  sk_buff  *skb)
{
    int ihl = skb->nh.iph->ihl*4;
     __skb_pull (skb, ihl);    //(1) 剥离IP头
    skb->h.raw = skb->data; -//(2) 数据(IP层的有效载荷)交给上层协议(比如TCP)

    rcu_read_lock();
    {
        int protocol = skb->nh.iph->protocol;
        int hash;
        struct sock *raw_sk;
        struct  net_protocol  *ipprot;
    resubmit:
        hash = protocol & (MAX_INET_PROTOS - 1);
        raw_sk = sk_head(&raw_v4_htable[hash]);
        if (raw_sk && !raw_v4_input(skb, skb->nh.iph, hash))
            raw_sk = NULL;
        if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
            int ret;
            if (!ipprot->no_policy) {
                if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
                    kfree_skb(skb);
                    goto out;
                }
                nf_reset(skb);
            }
            ret = ipprot-> handler (skb);
            if (ret < 0) {
                protocol = -ret;
                goto resubmit;
            }
            IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
        } else {
            if (!raw_sk) {
                if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
                    IP_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS);
                    icmp_send(skb, ICMP_DEST_UNREACH,
                          ICMP_PROT_UNREACH, 0);
                }
            } else
                IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
            kfree_skb(skb);
        }
    }

out:
    rcu_read_unlock();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值