ip_rcv() -- IP层接收sk_buff

来源:互联网 发布:浩云网络 编辑:程序博客网 时间:2024/06/05 20:34
netif_receive_skb() --> ip_rcv()

    当一个IP包被接收到网卡中时,函数ip_rcv被底层的函数netif_receive_skb()调用。

    First, the function rejects packets not addressed to the local computer. For example, the promiscuous mode allows a network device to accept packets actually addressed to another computer. Such packets are filtered by the packet type (skb->pkt_type == PACKET_OTHERHOST) in the lower layers.

    Subsequently, the basic correctness criteria of a packet are checked: 
    (1) Does the packet have at least the size of an IP header?
    (2) Is this IP Version 4?
    (3) Is the checksum correct?
    (2) Does the packet have a wrong length?

    Now that the packet is correct, the netfilter hook NF_IP_PRE_ROUTING is invoked. Netfilter allows you to extend the procedure of various protocols by specific functions, if desired. Netfilter hooks always reside in strategic points of certain protocols and are used, for example, for firewall, QoS, and address-translation functions. These examples will be discussed in later chapters. A netfilter hook is invoked by a macro, and the function following the handling of the netfilter extension is passed to this macro in the form of a function pointer. If netfilter was not configured, then the macro ensures that there is a direct jump to this follow-up function.



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

int ip_rcv(struct sk_buff     *skb,
           struct net_device -*dev, 
           struct packet_type *pt, 
           struct net_device -*orig_dev)
{
    struct iphdr *iph;
    u32 len;
    if (skb->pkt_type == PACKET_OTHERHOST)         
        goto drop;
    IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); 

    if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
        IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
        goto out;
    }

    if (!pskb_may_pull(skb, sizeof(struct iphdr))) 
        goto inhdr_error;

    iph = skb->nh.iph;
    if (iph->ihl < 5 || iph->version != 4) 
        goto inhdr_error;

    if (!pskb_may_pull(skb, iph->ihl*4))
        goto inhdr_error;

    iph = skb->nh.iph;
    if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
        goto inhdr_error;

    len = ntohs(iph->tot_len);
    if (skb->len < len || len < (iph->ihl*4))
        goto inhdr_error;

    if (pskb_trim_rcsum(skb, len)) {
        IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
        goto drop;
    }

    memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
    return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
               ip_rcv_finish);

inhdr_error:
    IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
drop:
        kfree_skb(skb);
out:
        return NET_RX_DROP;
}
原创粉丝点击