赞
踩
我们都知道数据链路层有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);
- }
根据一开始的结构体,上面的代码不难理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。