深入理解TCP/IP协议的实现之ip分片重组(基于linux1.2.13)

本文详细探讨了TCP/IP协议在遇到数据链路层MTU限制时的分片与重组过程,主要关注Linux 1.2.13版本中的实现。文章介绍了ipq和ipfrag结构体在分片重组中的作用,分析了ip报文格式,并讲解了分片重组的基本操作函数,包括创建ipq队列、查找对应队列、创建ipfrag结构体等。通过对ip_defrag函数的分段分析,阐述了整个组包流程,包括判断、排序、处理重叠分片等问题,最终实现分片的完整重组。
摘要由CSDN通过智能技术生成

我们都知道数据链路层有mtu的限制,如果我们上层发的包太大,那就要分片,那么对端就需要重组分片,组装好再通知上层。我们看一下分片重组的过程。我们看一下分片重组中用到的数据结构。ipq结构体是代表一个完整的传输层包,他被ip层分成了多个分片。ipfrag结构体是代表一个ip分片。他是传输层包的一个部分。

再看一下ip报文的格式。

我们开始分析组片之前,先看一下一些基础函数。 1 创建一个用于重组传输层数据包的结构体ipq。这个是第一个ip分配到达时调用的。他维护了属于同一个分片组(同一个传输层数据包)的多个分片。

// 创建一个队列用于重组分片,iphdr 即ip报文头
static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev)
{
    struct ipq *qp;
    int maclen;
    int ihlen;
    // 申请一个新ipq的表示分片队列
    qp = (struct ipq *) kmalloc(sizeof(struct ipq), GFP_ATOMIC);
    // 初始化内存
    memset(qp, 0, sizeof(struct ipq));

    // skb->data指向mac头首地址,mac头长度等于ip头减去mac头首地址
    maclen = ((unsigned long) iph) - ((unsigned long) skb->data);
    // 分配内存保存mac头
    qp->mac = (unsigned char *) kmalloc(maclen, GFP_ATOMIC);

    // ip头长度由ip头字段*4得出,多分配8个字节给icmp
    ihlen = (iph->ihl * sizeof(unsigned long));
    qp->iph = (struct iphdr *) kmalloc(ihlen + 8, GFP_ATOMIC);

    // 把mac头内容复制到mac字段
    memcpy(qp->mac, skb->data, maclen);
    // 把ip头和传输层的8个字节复制到iph字段,8个字段的内容用于发送icmp报文时
    memcpy(qp->iph, iph, ihlen + 8);

    // 未分片的ip报文的总长度,未知,收到所有分片后重新赋值
    qp->len = 0;
    // 当前分片的ip头和mac头长度
    qp->ihlen = ihlen;
    qp->maclen = maclen;
    qp->fragments = NULL;
    // 关联的设备
    qp->dev = dev;
    // 开始计时,一定时间内还没收到所有分片则重组失败,发送icmp报文
    qp->timer.expires = IP_FRAG_TIME;       
    qp->timer.data = (unsigned long) qp;        
    qp->timer.function = ip_expire;     
    // 开始计时,如果超时没有收到新的ip分片,则重组失败,如果收到一个新的,重置计时器
    add_timer(&qp->timer);

    qp->prev = NULL;
    cli();
    // 头插法插入分片重组的队列
    qp->next = ipqueue;
    /*
        如果当前新增的节点不是第一个节点则把当前第一个
        节点的prev指针指向新增的节点
    */
    if (qp->next != NULL)
        qp->next->prev = qp;
    //更新ipqueue指向新增的节点,新增节点是首节点 
    ipqueue = qp;

    sti();
    return(qp);
}

根据一开始的结构体,上面的代码不难理解。主要是申请一个ipq结构体。然后初始化各个字段,最后插入ipq队列。并且开始计算分片重组的超时时间和超时回调。

2 通过ip头查找对应的ipq队列。

// 根据ip头找到分片队列的头指针
static struct ipq *ip_find
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值