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;
}
当一个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;
}
- ip_rcv() -- IP层接收sk_buff
- Linux网络层 ip_rcv()函数代码分析
- Linux网络层 ip_rcv()函数代码分析
- tcp-ip : sk_buff Structure
- IP层实现3-接收数据
- Linux网络层 ip_rcv()函数代码分析(__pskb_pull_tail)
- Linux网络层 ip_rcv()函数代码分析(__pskb_pull_tail)
- Linux网络层 ip_rcv()函数代码分析(__pskb_pull_tail)
- IP层实现4-raw socket 接收数据
- sk_buff
- sk_buff
- sk_buff
- sk_buff
- sk_buff
- sk_buff
- sk_buff
- struct--iphdr sk_buff->tcphdr -- IP头部
- ip_rcv 分析
- ip_rcv_finish
- eclipse调试postgre遇到的问题以及解决方法
- 中断与时钟
- linux上ln命令详细说明
- php的serialize序列化和json性能测试
- ip_rcv() -- IP层接收sk_buff
- 网络资源
- 问 题三十九: 编程序输出各种星号图 (五)
- ubuntu 12.10 安装maven
- Cacti的优化
- 用sublime text 2 build python 遇到中文的问题
- netif_receive_skb()
- [Matlab]基础教程学习笔记(六):NoteBook的使用
- oracle忘记用户名密码怎样办?