【发布时间】:2022-01-26 06:41:09
【问题描述】:
这是我几乎完整的代码,我认为它为 TCP 数据包发送有效的 IP 标头。但是我的代码未能通过 Wireshark 测试,即它不被识别为 TCP 数据包;相反,Wireshark 只是将其标记为可怕的原始数据包,没有任何源和目标 IP。这确实是一个简单的 IP 数据包,我确信它可以完成通过 Wireshark 测试的工作,但它没有。
我做错了什么?目前没有线索可以进一步了解如何调试它,我还可以在我的 tcp 或 ip 标头中设置什么。在它在Wireshark Fragmented TCP数据包中给我消息之前这意味着什么,然后开始说它只是格式错误的数据包现在它给我的消息是这些响应数据包响应只是从我的这个代码发送的原始数据包,没有源或目标ips,考虑到因为 TCP 甚至没有显示该窗格
void * receiver(void *data)
{
int recvlen = -1;
int writelen = -1;
while (!_do_exit) {
char buf[VPN_MAX_MTU] = {0};
char buf_1[VPN_MAX_MTU] = {0};
memset(buf,0,VPN_MAX_MTU);
memset(buf_1,0,VPN_MAX_MTU);
char *str_source=malloc(18);
char *str_dest=malloc(18);
memset(str_source,0,18);
memset(str_dest,0,18);
recvlen=read(_tun_fd,buf,VPN_MAX_MTU);
debug("SR:%04d\n", recvlen);
struct iphdr *iph=(struct iphdr *)buf;
struct iphdr *ip=(struct iphdr *)buf_1;
char str_src[18]={0};
char str_dest_t[18]={0};
memcpy(&ip->saddr,&iph->daddr,sizeof(uint32_t));
memcpy(&ip->daddr,&iph->saddr,sizeof(uint32_t));
printf("IN %s %s\n",get_ip_str_1(iph->saddr,str_src),get_ip_str_1(iph->daddr,str_dest_t));
//clear the str_str and str_dest_t with memset(,0)
printf("OUT %s %s\n",get_ip_str_1(ip->saddr,str_src),get_ip_str_1(ip->daddr,str_dest_t));
ip->ihl = 5;
ip->version = 4;
ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
ip->protocol = IPPROTO_TCP;
ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));
uint16_t k=csum(ip,sizeof(*ip));
ip->check=k;
printf("checksum %d | %d\n",iph->check,ip->check);
int i=iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr *)(buf+i);
int j=(struct iphdr *)(ip->ihl*4);
struct tcphdr *tcp=(struct tcphdr *)(buf_1+j);
populate_tcp_some(tcph,tcp);
printf("received syn = %d\n",tcph->syn);
if(tcph->syn==1)
{
populate_tcp_some(tcph,tcp);
tcp->syn=1;
tcp->ack=1;
tcp->dest=tcph->source;
tcp->source=htons(80);
printf("received tcp syn = %d\n",tcph->syn);
}
else{
populate_tcp_some(tcph,tcp);
tcp->syn=0;
tcp->ack=1;
tcp->dest=tcph->source;
tcp->source=htons(80);
printf("sending tcp syn = %d ack = %d\n",tcp->syn,tcp->ack);
}
tcp->check=0;
tcp->check=tcp_chksum(ip,tcp);
printf("checksums %d | %d\n",tcph->check,tcp->check);
if (recvlen > 0) {
writelen = write(_tun_fd, buf_1, sizeof(*ip));
debug("TW:%04d\n", writelen);
if (writelen < 0) {
debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
}
} else if (recvlen < 0) {
debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
} else if (recvlen == 0) {
}
}
debug("** Receiver ending.\n");
pthread_exit(NULL);
}
【问题讨论】:
-
常量 IPPROTO_TCP 是主机还是网络字节序? wireshark 会看到你应该输入的相同常量吗?
-
@Effie 这个答案没有 htons stackoverflow.com/a/13620771/4808760
-
或者至少告诉我们wireshark看到了什么。没有错误消息很难调试。
-
您是否在捕获全部数据?因为它捕获了 16 个字节,而您应该有最少 40 个字节的 IP 和 TCP 标头。
-
不,我的意思是“for (i from 0 to total lengh) pritnf (%x)”每个。我们需要检查数据包是否以字节为单位正确。我的意思是两个数据包。