忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 342 | 回复: 4

[网络子系统] 请教一个ip_rcv的问题 [复制链接]

论坛徽章:
0
发表于 2017-03-17 15:48 |显示全部楼层

/*
*         Main IP Receive routine.
*/
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;

        /* When the interface is in promisc. mode, drop all the crap
         * that it receives, do not try to analyse it.
         */
        if (skb->pkt_type == PACKET_OTHERHOST)
                goto drop;


        IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);

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

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

        iph = ip_hdr(skb);

        /*
         *        RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
         *
         *        Is the datagram acceptable?
         *
         *        1.        Length at least the size of an ip header
         *        2.        Version of 4
         *        3.        Checksums correctly. [Speed optimisation for later, skip loopback checksums]
         *        4.        Doesn't have a bogus length
         */

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

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

        iph = ip_hdr(skb);

        if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
                goto inhdr_error;

        len = ntohs(iph->tot_len);
        if (skb->len < len) {               
                /**
                 * 缓冲区(即已接收的包)长度大于或者等于IP报头中记录的长度。
                 *                这是由于L2协议(如ethernet)会填充有效负载,所以,在IP有效负载之后可能有多余的字节.
                */问题1:,这里的L2协议会填充有效负载,是指NET_IP_ALIGN对齐吗?导致skb->len>=len?
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
                goto drop;
        } else if (len < (iph->ihl*4))
                goto inhdr_error;

        /* Our transport medium may have padded the buffer out. Now we know it
         * is IP we can trim to the true length of the frame.
         * Note this now means skb->len holds ntohs(iph->tot_len).
         */
        if (pskb_trim_rcsum(skb, len)) {
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
                goto drop;
        }

        /* Remove any debris in the socket control block */
        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));

        /* Must drop socket now because of tproxy. */
        skb_orphan(skb);

        return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL,
                       ip_rcv_finish);

inhdr_error:
        IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
drop:
        kfree_skb(skb);
out:
        return NET_RX_DROP;
}


论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2017-03-20 11:44 |显示全部楼层
回复 1# ymc4444


skb->len 指实际收到的 IP 包的长度,len 是从 ip header 中提取的报文长度。skb->len < len 的话,必然是代表有问题了。

论坛徽章:
16
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00黑曼巴
日期:2016-12-26 16:00:32每日论坛发贴之星
日期:2016-07-18 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:51程序设计版块每日发帖之星
日期:2016-06-03 06:20:00程序设计版块每日发帖之星
日期:2016-06-02 06:20:00程序设计版块每日发帖之星
日期:2016-05-30 06:20:00程序设计版块每日发帖之星
日期:2016-03-19 06:20:00程序设计版块每日发帖之星
日期:2016-03-12 06:20:00
发表于 2017-03-20 16:44 |显示全部楼层
l2 header has been stripped by nic driver code.
usually by eth_type_trans(skb)

论坛徽章:
0
发表于 2017-03-21 20:21 |显示全部楼层
在ip_rcv中,skb->len和len(iph->tot_len)之间在没出错的情况下是个什么关系?skb->len == len?还是skb->len >= len?

论坛徽章:
16
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00黑曼巴
日期:2016-12-26 16:00:32每日论坛发贴之星
日期:2016-07-18 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:51程序设计版块每日发帖之星
日期:2016-06-03 06:20:00程序设计版块每日发帖之星
日期:2016-06-02 06:20:00程序设计版块每日发帖之星
日期:2016-05-30 06:20:00程序设计版块每日发帖之星
日期:2016-03-19 06:20:00程序设计版块每日发帖之星
日期:2016-03-12 06:20:00
发表于 2017-03-27 14:49 |显示全部楼层
那注释是别人写的吧?怎么感觉放在else分支里才合理?

排除恶意payload的情况,skb.len > iph.total_len的原因有可能是二层封装的tailer。
比如PPPoE报文(或者其它隧道),或者网卡没有strip CRC的case。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP