免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: davhuang
打印 上一主题 下一主题

请教2.6中分片重组后的怪现象 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2011-01-01 11:01 |只看该作者
本帖最后由 tuibo 于 2011-01-01 11:17 编辑

Linux 2.6.36 内核

static struct nf_hook_ops ipv4_defrag_ops[] = {
        {
                .hook                = ipv4_conntrack_defrag,
                .owner                = THIS_MODULE,
                .pf                = PF_INET,
                .hooknum        = NF_INET_PRE_ROUTING,
                .priority        = NF_IP_PRI_CONNTRACK_DEFRAG,
        },
这里的conntrack组片,只是把他们链在一起,当然也把除第一片分片报文的ip header 去掉了,但不会拼到一块连续的内存区,没必要做拼到一块。
当然 nat 模块由于可能解析报文内容,可能会需要把报文姘接到一块skb_linearize,不过我觉得做内容分析,很多情况下也没必要拼接在一块。
下面搜索了一下,sip模块还是有可能的。     
    ” 發現重組後的pkt最後的內容與frag3毫不相關“, 你是如果判断的,如何抓取的pkt如何抓取的最后的内容? 怀疑你的判断有问题





---- skb_linearize Matches (34 in 22 files) ----
Aoenet.c (linux-2.6.36\drivers\block\aoe):        if (skb_linearize(skb))
Bnx2x_cmn.c (linux-2.6.36\drivers\net\bnx2x):                if (skb_linearize(skb) != 0) {
Capi.c (linux-2.6.36\drivers\isdn\gigaset):        if (skb_linearize(skb) < 0) {
Capi.c (linux-2.6.36\drivers\isdn\gigaset):                dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__);
Cfpkt_skbuff.c (linux-2.6.36\net\caif):                if (unlikely(skb_linearize(skb) != 0)) {
Cfpkt_skbuff.c (linux-2.6.36\net\caif):        if (unlikely(skb_linearize(skb) != 0)) {
Cfpkt_skbuff.c (linux-2.6.36\net\caif):        if (unlikely(skb_linearize(&pkt->skb) != 0)) {
Cfpkt_skbuff.c (linux-2.6.36\net\caif):        if (unlikely(skb_linearize(skb) != 0)) {
Cfpkt_skbuff.c (linux-2.6.36\net\caif):                if (unlikely(skb_linearize(skb) != 0)) {
Core.h (linux-2.6.36\net\tipc):        return skb_linearize(skb);
Dn_nsp_in.c (linux-2.6.36\net\decnet):                        if (unlikely(skb_linearize(skb)))
Dn_route.c (linux-2.6.36\net\decnet):                if (unlikely(skb_linearize(skb)))
Enic_main.c (linux-2.6.36\drivers\net\enic):            skb_linearize(skb)) {
Fcoe.c (linux-2.6.36\drivers\scsi\fcoe):                skb_linearize(skb);        /* not ideal */
I4l.c (linux-2.6.36\drivers\isdn\gigaset):        if (skb_linearize(skb) < 0) {
I4l.c (linux-2.6.36\drivers\isdn\gigaset):                dev_err(cs->dev, "%s: skb_linearize failed\n", __func__);
Input.c (linux-2.6.36\net\sctp):        if (skb_linearize(skb))
Libfcoe.c (linux-2.6.36\drivers\scsi\fcoe):        if (skb_linearize(skb))
Myri10ge.c (linux-2.6.36\drivers\net\myri10ge):        if (skb_linearize(skb))
Nes_nic.c (linux-2.6.36\drivers\infiniband\hw\nes):                        skb_linearize(skb);
Nf_conntrack_sip.c (linux-2.6.36\net\netfilter):        if (unlikely(skb_linearize(skb)))
Nf_conntrack_sip.c (linux-2.6.36\net\netfilter):        if (unlikely(skb_linearize(skb)))

Qeth_l3_main.c (linux-2.6.36\drivers\s390\net):                        if (skb_linearize(new_skb))
Rx.c (linux-2.6.36\net\mac80211):        if (skb_linearize(rx->skb))
Rx.c (linux-2.6.36\net\mac80211):        if (skb_linearize(rx->skb))
Rx.c (linux-2.6.36\net\mac80211):         *  skb_linearize() might change the skb->data and
Rx.c (linux-2.6.36\net\mac80211):        if (skb_linearize(skb))
Rx.c (linux-2.6.36\net\mac80211):                err = skb_linearize(skb);
Skbuff.c (linux-2.6.36\net\core):        err = skb_linearize(skb);
Skbuff.h (linux-2.6.36\include\linux): *        skb_linearize - convert paged skb to linear one
Skbuff.h (linux-2.6.36\include\linux):static inline int skb_linearize(struct sk_buff *skb)
Smsc75xx.c (linux-2.6.36\drivers\net\usb):        skb_linearize(skb);
Tag_trailer.c (linux-2.6.36\net\dsa):        if (skb_linearize(skb))
Vmxnet3_drv.c (linux-2.6.36\drivers\net\vmxnet3):                        if (skb_linearize(skb) != 0) {

论坛徽章:
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
12 [报告]
发表于 2011-01-01 11:33 |只看该作者
这里的conntrack组片,只是把他们链在一起,当然也把除第一片分片报文的ip header 去掉了,但不会拼到一块连续的内存区,没必要做拼到一块。

会把除第一个分片报文之外的分片,去除 ip header 吗。没有注意到代码中有这样的处理

当然 nat 模块由于可能解析报文内容,可能会需要把报文姘接到一块skb_linearize,不过我觉得做内容分析,很多情况下也没必要拼接在一块。

通常是需要检查应用层内容的时候,可能会考虑线性化一下。

论坛徽章:
0
13 [报告]
发表于 2011-01-01 12:12 |只看该作者
必须要去ip头,不然怎么算是一个报文呢?


static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{
        struct sk_buff *prev, *next;
        struct net_device *dev;
        int flags, offset;
        int ihl, end;
        int err = -ENOENT;

        if (qp->q.last_in & INET_FRAG_COMPLETE)
                goto err;

        if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
            unlikely(ip_frag_too_far(qp)) &&
            unlikely(err = ip_frag_reinit(qp))) {
                ipq_kill(qp);
                goto err;
        }

        offset = ntohs(ip_hdr(skb)->frag_off);
        flags = offset & ~IP_OFFSET;
        offset &= IP_OFFSET;
        offset <<= 3;                /* offset is in 8-byte chunks */
        ihl = ip_hdrlen(skb);

        /* Determine the position of this fragment. */
        end = offset + skb->len - ihl;
        err = -EINVAL;

        /* Is this the final fragment? */
        if ((flags & IP_MF) == 0) {
                /* If we already have some bits beyond end
                 * or have different end, the segment is corrrupted.
                 */
                if (end < qp->q.len ||
                    ((qp->q.last_in & INET_FRAG_LAST_IN) && end != qp->q.len))
                        goto err;
                qp->q.last_in |= INET_FRAG_LAST_IN;
                qp->q.len = end;
        } else {
                if (end&7) {
                        end &= ~7;
                        if (skb->ip_summed != CHECKSUM_UNNECESSARY)
                                skb->ip_summed = CHECKSUM_NONE;
                }
                if (end > qp->q.len) {
                        /* Some bits beyond end -> corruption. */
                        if (qp->q.last_in & INET_FRAG_LAST_IN)
                                goto err;
                        qp->q.len = end;
                }
        }
        if (end == offset)
                goto err;

        err = -ENOMEM;
        if (pskb_pull(skb, ihl) == NULL)
                goto err;


        err = pskb_trim_rcsum(skb, end - offset);
        if (err)
                goto err;

        /* Find out which fragments are in front and at the back of us
         * in the chain of fragments so far.  We must know where to put
         * this fragment, right?
         */
        prev = qp->q.fragments_tail;
        if (!prev || FRAG_CB(prev)->offset < offset) {
                next = NULL;
                goto found;
        }
        prev = NULL;
        for (next = qp->q.fragments; next != NULL; next = next->next) {
                if (FRAG_CB(next)->offset >= offset)
                        break;        /* bingo! */
                prev = next;
        }

found:
        /* We found where to put this one.  Check for overlap with
         * preceding fragment, and, if needed, align things so that
         * any overlaps are eliminated.
         */
        if (prev) {
                int i = (FRAG_CB(prev)->offset + prev->len) - offset;

                if (i > 0) {
                        offset += i;
                        err = -EINVAL;
                        if (end <= offset)
                                goto err;
                        err = -ENOMEM;
                        if (!pskb_pull(skb, i))
                                goto err;
                        if (skb->ip_summed != CHECKSUM_UNNECESSARY)
                                skb->ip_summed = CHECKSUM_NONE;
                }
        }

        err = -ENOMEM;

        while (next && FRAG_CB(next)->offset < end) {
                int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */

                if (i < next->len) {
                        /* Eat head of the next overlapped fragment
                         * and leave the loop. The next ones cannot overlap.
                         */
                        if (!pskb_pull(next, i))
                                goto err;
                        FRAG_CB(next)->offset += i;
                        qp->q.meat -= i;
                        if (next->ip_summed != CHECKSUM_UNNECESSARY)
                                next->ip_summed = CHECKSUM_NONE;
                        break;
                } else {
                        struct sk_buff *free_it = next;

                        /* Old fragment is completely overridden with
                         * new one drop it.
                         */
                        next = next->next;

                        if (prev)
                                prev->next = next;
                        else
                                qp->q.fragments = next;

                        qp->q.meat -= free_it->len;
                        frag_kfree_skb(qp->q.net, free_it);
                }
        }

        FRAG_CB(skb)->offset = offset;

        /* Insert this fragment in the chain of fragments. */
        skb->next = next;
        if (!next)
                qp->q.fragments_tail = skb;
        if (prev)
                prev->next = skb;
        else
                qp->q.fragments = skb;

        dev = skb->dev;
        if (dev) {
                qp->iif = dev->ifindex;
                skb->dev = NULL;
        }
        qp->q.stamp = skb->tstamp;
        qp->q.meat += skb->len;
        atomic_add(skb->truesize, &qp->q.net->mem);
        if (offset == 0)
                qp->q.last_in |= INET_FRAG_FIRST_IN;

        if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
            qp->q.meat == qp->q.len)
                return ip_frag_reasm(qp, prev, dev);

        write_lock(&ip4_frags.lock);
        list_move_tail(&qp->q.lru_list, &qp->q.net->lru_list);
        write_unlock(&ip4_frags.lock);
        return -EINPROGRESS;

err:
        kfree_skb(skb);
        return err;
}

论坛徽章:
0
14 [报告]
发表于 2011-01-01 12:44 |只看该作者
下面这个函数把 head 的头再恢复一下,后续分片不能恢复

/* Build a new IP datagram from all its fragments. */

static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
                         struct net_device *dev)
{
        struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
        struct iphdr *iph;
        struct sk_buff *fp, *head = qp->q.fragments;
        int len;
        int ihlen;
        int err;

        ipq_kill(qp);

        /* Make the one we just received the head. */
        if (prev) {
                head = prev->next;
                fp = skb_clone(head, GFP_ATOMIC);
                if (!fp)
                        goto out_nomem;

                fp->next = head->next;
                if (!fp->next)
                        qp->q.fragments_tail = fp;
                prev->next = fp;

                skb_morph(head, qp->q.fragments);
                head->next = qp->q.fragments->next;

                kfree_skb(qp->q.fragments);
                qp->q.fragments = head;
        }

        WARN_ON(head == NULL);
        WARN_ON(FRAG_CB(head)->offset != 0);

        /* Allocate a new buffer for the datagram. */
        ihlen = ip_hdrlen(head);
        len = ihlen + qp->q.len;

        err = -E2BIG;
        if (len > 65535)
                goto out_oversize;

        /* Head of list must not be cloned. */
        if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC))
                goto out_nomem;

        /* If the first fragment is fragmented itself, we split
         * it to two chunks: the first with data and paged part
         * and the second, holding only fragments. */
        if (skb_has_frags(head)) {
                struct sk_buff *clone;
                int i, plen = 0;

                if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL)
                        goto out_nomem;
                clone->next = head->next;
                head->next = clone;
                skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
                skb_frag_list_init(head);
                for (i=0; i<skb_shinfo(head)->nr_frags; i++)
                        plen += skb_shinfo(head)->frags.size;
                clone->len = clone->data_len = head->data_len - plen;
                head->data_len -= clone->len;
                head->len -= clone->len;
                clone->csum = 0;
                clone->ip_summed = head->ip_summed;
                atomic_add(clone->truesize, &qp->q.net->mem);
        }

        skb_shinfo(head)->frag_list = head->next;
        skb_push(head, head->data - skb_network_header(head));

        for (fp=head->next; fp; fp = fp->next) {
                head->data_len += fp->len;
                head->len += fp->len;
                if (head->ip_summed != fp->ip_summed)
                        head->ip_summed = CHECKSUM_NONE;
                else if (head->ip_summed == CHECKSUM_COMPLETE)
                        head->csum = csum_add(head->csum, fp->csum);
                head->truesize += fp->truesize;
        }
        atomic_sub(head->truesize, &qp->q.net->mem);

        head->next = NULL;
        head->dev = dev;
        head->tstamp = qp->q.stamp;

        iph = ip_hdr(head);
        iph->frag_off = 0;
        iph->tot_len = htons(len);
        IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
        qp->q.fragments = NULL;
        qp->q.fragments_tail = NULL;
        return 0;

out_nomem:
        LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
                              "queue %p\n", qp);
        err = -ENOMEM;
        goto out_fail;
out_oversize:
        if (net_ratelimit())
                printk(KERN_INFO "Oversized IP packet from %pI4.\n",
                        &qp->saddr);
out_fail:
        IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
        return err;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP