如何在C语言中嗅探数据包时发现TCP重传

如何在C语言中嗅探数据包时发现TCP重传,c,tcp,pcap,libpcap,retransmit-timeout,C,Tcp,Pcap,Libpcap,Retransmit Timeout,我已经编写了一个简单的源文件,可以使用C语言中的libpcap库读取pcap文件。我可以逐个解析数据包,并对它们进行一定程度的分析。我希望能够推断我解析的TCP数据包是否是TCP重传。在广泛搜索web之后,我得出结论,为了做到这一点,我需要跟踪流量行为,这意味着还要分析以前收到的数据包 我真正想要实现的是,在一个基本的层次上,实现wireshark中的tcp.analysis.retransmissionfilter所做的 这是一个MRE,它读取pcap文件并分析通过IPv4发送的TCP数据包。

我已经编写了一个简单的源文件,可以使用C语言中的libpcap库读取pcap文件。我可以逐个解析数据包,并对它们进行一定程度的分析。我希望能够推断我解析的TCP数据包是否是TCP重传。在广泛搜索web之后,我得出结论,为了做到这一点,我需要跟踪流量行为,这意味着还要分析以前收到的数据包

我真正想要实现的是,在一个基本的层次上,实现wireshark中的
tcp.analysis.retransmission
filter所做的

这是一个MRE,它读取pcap文件并分析通过IPv4发送的TCP数据包。功能
find_retransmissions
用于分析数据包

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效进程数据包(u_char*,常量结构pcap_pkthdr*,常量u_char*);
无效查找重新传输(常量字符*,int);
int main()
{
pcap_t*手柄;
字符errbuff[PCAP_ERRBUF_SIZE];
handle=pcap\u open\u offline(“smallFlows.pcap”,errbuff);
pcap_循环(句柄,-1,进程_数据包,NULL);
}
无效进程\u数据包(u\u字符*参数,
const struct pcap_pkthdr*头,
常量u_char*缓冲区)
{
int size=标题->长度;
结构ethhdr*eth=(结构ethhdr*)缓冲区;
if(eth->h_proto==8)//检查IPv4
{
结构iphdr*iph=(结构iphdr*)(缓冲区+sizeof(结构ethhdr));
if(iph->protocol==6)//检查TCP
{
查找_重传(缓冲区、大小);
}
}
}
void find_重传(const u_char*Buffer,int Size)
{
静态结构iphdr以前的_数据包[20000];
静态结构tcphdr previous_tcp[20000];
静态int指数=0;
静态int重传=0;
int重传=0;
源、目标中的结构sockaddr_;
无符号短iphdrlen;
//IP报头
结构iphdr*iph=(结构iphdr*)(缓冲区+sizeof(结构ethhdr));
以前的_数据包[索引]=*iph;
iphdrlen=iph->ihl*4;
memset(&source,0,sizeof(source));
source.sin\u addr.s\u addr=iph->saddr;
memset(&dest,0,sizeof(dest));
dest.sin_addr.s_addr=iph->daddr;
//TCP报头
结构tcphdr*tcph=(结构tcphdr*)(缓冲区
+伊夫德伦
+sizeof(struct ethhdr));
以前的_tcp[索引]=*tcph;
索引++;
int header_size=sizeof(struct ethhdr)+iphdrlen+tcph->doff*4;
无符号整数段长度;
分段长度=尺寸-标题尺寸;
/*首先检查是否已收到相同的TCP数据包*/
for(int i=0;isaddr)//相同的源IP地址
&&(以前的_数据包[i].daddr==iph->daddr)//相同的目标Ip地址
&&(以前的_数据包[i]。协议==iph->协议)//相同的协议
&&(temphdrlen==iphdrlen))//相同的头长度
{
//然后检查TCP头
if((先前的_tcp[i].source==tcph->source)//相同的源端口
&&(上一个\u tcp[i].dest==tcph->dest)//相同的目标端口
&&(先前的\u-tcp[i].th\u-seq==tcph->th\u-seq)//相同的序列号
&&(先前的\u tcp[i]。th\u ack==tcph->th\u ack)//相同的确认号
&&(上一个\u-tcp[i].th\u-win==tcph->th\u-win)//同一窗口
&&(先前的\u tcp[i].th\u标志==tcph->th\u标志)//相同的标志
&&(tcph->syn==1 | | tcph->fin==1 | | segmentlength>0))//检查syn或fin是否为
{//设置或如果tcp.0段
//此时,数据包几乎相同
//现在检查以前的通信以检查是否重新传输
对于(intz=index-1;z>=0;z--)
{   
//查找反向的数据包
if((以前的_数据包[z].daddr==iph->saddr)//交换的IP源地址
&&(以前的_数据包[z].saddr==iph->daddr)//对于IP dest addreses相同
&&(以前的_数据包[z]。协议==iph->协议))//相同的协议
{
if((先前的_tcp[z].dest==tcph->source)//交换的端口
&&(上一个\u tcp[z]。源==tcph->dest)
&&(上一个\u-tcp[z].th\u-seq-1!=tcph->th\u-ack)//未保留
&&(tcph->syn==1//设置了任一syn
||tcph->fin==1//设置了任一fin
||(segmentlength>0))//任一segmentlength>0
&&(上一个\u-tcp[z]。th_-seq>tcph->th_-seq)//下一个序列号为
//比预期的要大
&&(previous_tcp[z].ack!=1))//设置了最后一次看到的ack
{
重传=1;
重传++;
打破
}
}
}
}
}
}
if(重传==1)
{
printf(“重新传输:True\n”);
printf(“\n\n**************************************************************************\n”);
printf(“|-IP版本:%d\n”,(unsigned int)iph->Version);
printf(“|-源IP:%s\n”,inet_ntoa(Source.sin_addr));
printf(“|-目标IP:%s\n”,inet_ntoa(dest.sin_addr));
printf(“|-源端口:%u\n”,ntohs(tcph->Source));
printf(“|-目标端口:%u\n”,ntohs(tcph->dest));
printf(“|-Protocol:%d\n”,(unsigned int)iph->Protocol);
printf(“|-IP头长度:%d个DWORDS或%d个字节\n”,
(uns)