任务说明
将收到ip分片重组为完整的ip包。
struct IpPkt* CombinIp(struct IpPktList *ip_list)
注意:参数中给出的分片顺序可能是乱序的,与前一关任务中返回的链表会存在不同。
#include"network_protocol.h"
#include <malloc.h>
//ip分片重组
struct IpPkt* CombinIp(struct IpPktList *ip_list){
struct IpPkt *ip=NULL;
/********* Begin 1 **********/
//如果只有一个分片,直接复制ip
if(ip_list->next == NULL){
return ip_list->ip;
}
//找到最后分片,确定ip的长度,其标志为000,片偏移不为0
struct IpPktList *t = (struct IpPktList*)malloc(sizeof(struct IpPktList));
t = ip_list;
struct IpPkt *tempip;
short len = t->ip->ip_len;
while(t!=NULL){
tempip = t->ip;
short fragoff = ntohs(tempip->ip_fragoff);
if((fragoff & 0xe000) == 0 && (fragoff & 0x1fff) > 0){
// printf("%d\n", fragoff);
len = (fragoff << 3) + ntohs(tempip->ip_len) - 20;
break;
}
t = t->next;
}
// printf("%d\n", len);
//按片偏移进行重组,注意最后的ip长度,偏移标志字段,校验要重新计算
ip = (struct IpPkt*)malloc(20 + len);
*ip = *(t->ip);
ip->ip_len = htons(len + 20);
ip->ip_cksum = 0;
ip->ip_fragoff = 0;
ip->ip_cksum = htons(ipcksum(ip));
t = ip_list;
while(t != NULL){
tempip = t->ip;
short fragoff = ntohs(tempip->ip_fragoff);
short offset = fragoff << 3;
len = ntohs(tempip->ip_len) - 20;
for(int i = 0; i < len; i++){
ip->ip_data[offset + 1] = tempip->ip_data[i];
}
t = t->next;
}
/********* End 1 **********/
return ip;
}