TCP序列号的简单递增并将其分配给C中发送tcp header确认号
simple incrementing of TCP sequence number and assigning it to sending tcp header acknowledgement number in C
我在模拟TCP,现在卡在确认号处理上
tcph->seq
是收到的序列号,我将它分配给 tcp->ack_seq 这是确认号,如
tcp->ack_seq=htons(ntohs(tcph->seq)+1);
但是鉴于上面的代码,似乎存在一些固有的错误,tcph->seq 和 tcph 是网络字节顺序这应该是因为我 cast-ed 它来自缓冲区并分配给 tcph 指针
这是我的简单线程函数,它读取接收到的缓冲区提取 tcthdr (struct tcph) 并调整值或分配值以发送 tcphdr (struct tcp)
它只是在做它所做的事情,我确实有问题。我一直收到错误的确认号(并没有真正反映出我是如何递增序列号并将其分配给确认号的)。任何人都可以看看这个所以我终于成功地完成了 TCP 握手。问题来了,我发送 SYN+ACK 数据包,我的客户端重新传输 SYN 数据包,这个循环污染了我的 wireshark 视图,没有任何用处,只是大量的 SYN 战利品和来自我的代码的响应 SYN+ACK
void * receiver(void *data)
{
//struct sockaddr_in cliaddr = {0};
int recvlen = -1;
int writelen = -1;
//socklen_t clilen = sizeof(cliaddr);
while (!_do_exit)
{
//recvlen = rrecvfrom(_udp_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
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);
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);
if(recvlen>0)
{
//BUFFER received here
struct iphdr *iph=(struct iphdr *)buf;
struct iphdr *ip=(struct iphdr *)buf_1;
int y=0;
for(int b=0;b<(sizeof(struct iphdr)+sizeof(struct tcphdr));b++)
{
if(y==20)
{
y=0;
//printf("\n");
}
//printf("%x ",buf[b]<<24);
y++;
}
// tcph->check=(tcp_chksum(iph,tcph));
//iph->check = csum(iph, sizeof(*iph));
char str_src[18]={0};
char str_dest_t[18]={0};
//printf("IN %s %s\n",get_ip_str_1(iph->saddr,str_src),get_ip_str_1(iph->daddr,str_dest_t));
memcpy(&ip->daddr,&iph->saddr,sizeof(uint32_t));
memcpy(&ip->saddr,&iph->daddr,sizeof(uint32_t));
//printf("OUT %s %s\n",get_ip_str_1(ip->saddr,str_src),get_ip_str_1(ip->daddr,str_dest_t));
//Create ip
//DOUBLE CHECK FOR BYTE ORDER
//ip->tot_len=iph->tot_len;
populate_ip_some(iph,ip);
ip->tos=0;
ip->tos=iph->tos;
ip->ihl = 5;
ip->version = 4;
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip->protocol = 6;
ip->check=0;
//DOUBLE CHECK FOR BYTE ORDER
ip->id=htons(100);
ip->check = htons(csum(ip, sizeof(*ip)));
//printf("before %d \n",htons(iph->check));
iph->check=0;
//printf("middle %d\n",iph->check);
//DOUBLE CHECK FOR BYTE ORDER
iph->check = htons(csum(iph, sizeof(*iph)));
int i=iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr *)(buf+i);
//printf("tcp before %x\n",htons(tcph->check));
tcph->check=0;
printf("TCP START\n");
tcph->check=(tcp_chksum(iph,tcph));
printf("TCP END\n");
//printf("tcp after %d\n",(tcph->check));
//printf("i == %d\n",i);
//POSSIBLY PRINT IPH for fun
//for(int a=0;a<recvlen;a++)
//printf("%x\n",buf[a]);
//GET ihl SEND -- tcp
int j=(ip->ihl*4);
//printf("j == %d\n",j);
int x=0;
//SEEK filling
struct tcphdr *tcp=(struct tcphdr *)(buf_1+20);
//populate_tcp_some(tcph,tcp);//Do LOOK AT THIS FUNCTION TO [SEE/CORRECT IT] >:)
seq++;
if(tcph->syn==1)
{
printf("WHAT THE HELL THEN WHY\n");
printf("syn\n");
//populate_tcp_some(tcph,tcp);
tcp->seq=htons(seq);
//tcp->ack_seq=htons(ntohs(tcph->seq)+1);
printf("seq = %d | ack_seq = %d\n",ntohs(tcph->seq),ntohs(tcp->ack_seq));
tcp->syn=1;
tcp->ack=1;
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
tcp->dest=tcph->source;
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//htons(ntohs(tcph->seq)+1);
// printf("received tcp syn = %d\n",tcph->syn);
}
else if(tcph->syn==0 && tcph->ack==1){
printf("WHAT THE HELL THEN COOL\n");
printf("syn\n");
// populate_tcp_some(tcph,tcp);
//tcp->seq=htons(1);
tcp->seq=htons(seq);
tcp->ack_seq=tcph->seq;
tcp->syn=0;
tcp->ack=1;
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
tcp->dest=tcph->source;
//tcp->ack_seq=tcph->seq;//htons(ntohs(tcph->seq)+1);
tcp->ack_seq=htons(ntohs(tcph->seq)+1);
}
else
{
populate_tcp_some(tcph,tcp);
tcp->syn=0;
tcp->ack=1;
//tcp->seq=htons(1);
tcp->seq=htons(seq);
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
tcp->dest=tcph->source;
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//tcp->ack_seq=tcph->seq;//htons(ntohs(tcph->seq)+1);
// printf("sending tcp syn = %d ack = %d\n",tcp->syn,tcp->ack);
}
printf("syn=%d | ack = %d | fin = %d | %d seq = %d ack_seq = %d | urg = %d | doff = %d | psh = %d rst = %d | rst2 = %d\n",tcp->syn,tcp->ack,tcp->fin,tcp->seq,tcp->ack_seq,tcp->urg,tcp->doff,tcp->psh,tcp->res1,tcp->res2);
//populate_tcp_some(tcph,tcp);
tcp->dest=tcph->source;
tcp->window=tcph->window;
//
//printf("%d %d SOURCE PORT \n",ntohs(tcph->source),ntohs(tcp->dest));
tcp->source=htons(80);
printf("%d %d PORTS \n",ntohs(tcp->source),ntohs(tcp->dest));
tcp->check=0;
//TCP CHECKSUM ABOUT TRIPPLE WOW
tcp->check=htons(tcp_chksum(ip,tcp));
//printf("tcpH = %d | tcp = %d\n",tcph->check,htons(tcp->check));
//IF needed make payload data
//WRITE
if (recvlen > 0)
{
printf("\n-WOW WOW WOW received seq = %d ack == %d",ntohs(tcph->seq),ntohs(tcp->ack_seq));
writelen = write(_tun_fd, buf_1, sizeof(struct iphdr)+sizeof(struct tcphdr));
//exit(0);
// sleep(2);
//debug("SR:%04d\n", recvlen);
//debug("TW:%04d\n", writelen);
if (writelen < 0)
{
//debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
//break;//NO NEED
}
}
else if (recvlen < 0)
{
//debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
//break;//NO NEED
}
else if (recvlen == 0)
{
//why
}
//FINALLY THEN SEND || DO WIRE SHARK
}
// ...:)__ :) __:) ___:)___ (: __(:__ (;...
}
debug("** Receiver ending.\n");
pthread_exit(NULL);
}
更新
现在我的 ACK+SYN 数据包没有捕获到 TCP 最后一段
这是收到的SYN
0000 45 00 00 3c c5 18 40 00 40 06 e0 2f c0 a8 0a 14
0010 c0 a8 0a 0f bc b2 00 50 f0 32 1f de 00 00 00 00
0020 a0 02 fa f0 c6 93 00 00 02 04 05 b4 04 02 08 0a
0030 95 a6 8e 4d 00 00 00 00 01 03 03 07
这是SYN+ACK
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc b2 86 e8 00 00 f0 32 1f df
0020 50 12 fa f0 cb 70 00 00
这是 SYN AGAIN
0000 45 00 00 3c c5 19 40 00 40 06 e0 2e c0 a8 0a 14
0010 c0 a8 0a 0f bc b2 00 50 f0 32 1f de 00 00 00 00
0020 a0 02 fa f0 c2 9c 00 00 02 04 05 b4 04 02 08 0a
0030 95 a6 92 44 00 00 00 00 01 03 03 07
在此数据包的行中再次进行 SYN 我收到未捕获的最后一段消息
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc b2 86 e9 00 00 f0 32 1f df
0020 50 12 fa f0 cb 6f 00 00
这是我的 更新 2
同步
0000 45 00 00 3c 9f 75 40 00 40 06 05 d3 c0 a8 0a 14
0010 c0 a8 0a 0f bc b8 00 50 55 a8 f4 2c 00 00 00 00
0020 a0 02 fa f0 83 25 00 00 02 04 05 b4 04 02 08 0a
0030 96 60 97 37 00 00 00 00 01 03 03 07
SYN + ACK
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc b8 00 00 00 03 55 a8 f4 2d
0020 50 12 fa f0 18 8c 00 00
这是 SYN agian retramit
0000 45 00 00 3c 9f 76 40 00 40 06 05 d2 c0 a8 0a 14
0010 c0 a8 0a 0f bc b8 00 50 55 a8 f4 2c 00 00 00 00
0020 a0 02 fa f0 7f 38 00 00 02 04 05 b4 04 02 08 0a
0030 96 60 9b 24 00 00 00 00 01 03 03 07
序列号和确认号是 32 位值:
因此这一行:
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//htons(ntohs(tcph->seq)+1);
正在使用 htons/ntohs,这是交换 16 位整数字节的函数。您需要将其更改为使用 htonl
和 ntohl
这可能不是您唯一的错误。
tcph->seq
是收到的序列号,我将它分配给 tcp->ack_seq 这是确认号,如
tcp->ack_seq=htons(ntohs(tcph->seq)+1);
但是鉴于上面的代码,似乎存在一些固有的错误,tcph->seq 和 tcph 是网络字节顺序这应该是因为我 cast-ed 它来自缓冲区并分配给 tcph 指针
这是我的简单线程函数,它读取接收到的缓冲区提取 tcthdr (struct tcph) 并调整值或分配值以发送 tcphdr (struct tcp)
它只是在做它所做的事情,我确实有问题。我一直收到错误的确认号(并没有真正反映出我是如何递增序列号并将其分配给确认号的)。任何人都可以看看这个所以我终于成功地完成了 TCP 握手。问题来了,我发送 SYN+ACK 数据包,我的客户端重新传输 SYN 数据包,这个循环污染了我的 wireshark 视图,没有任何用处,只是大量的 SYN 战利品和来自我的代码的响应 SYN+ACK
void * receiver(void *data)
{
//struct sockaddr_in cliaddr = {0};
int recvlen = -1;
int writelen = -1;
//socklen_t clilen = sizeof(cliaddr);
while (!_do_exit)
{
//recvlen = rrecvfrom(_udp_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
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);
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);
if(recvlen>0)
{
//BUFFER received here
struct iphdr *iph=(struct iphdr *)buf;
struct iphdr *ip=(struct iphdr *)buf_1;
int y=0;
for(int b=0;b<(sizeof(struct iphdr)+sizeof(struct tcphdr));b++)
{
if(y==20)
{
y=0;
//printf("\n");
}
//printf("%x ",buf[b]<<24);
y++;
}
// tcph->check=(tcp_chksum(iph,tcph));
//iph->check = csum(iph, sizeof(*iph));
char str_src[18]={0};
char str_dest_t[18]={0};
//printf("IN %s %s\n",get_ip_str_1(iph->saddr,str_src),get_ip_str_1(iph->daddr,str_dest_t));
memcpy(&ip->daddr,&iph->saddr,sizeof(uint32_t));
memcpy(&ip->saddr,&iph->daddr,sizeof(uint32_t));
//printf("OUT %s %s\n",get_ip_str_1(ip->saddr,str_src),get_ip_str_1(ip->daddr,str_dest_t));
//Create ip
//DOUBLE CHECK FOR BYTE ORDER
//ip->tot_len=iph->tot_len;
populate_ip_some(iph,ip);
ip->tos=0;
ip->tos=iph->tos;
ip->ihl = 5;
ip->version = 4;
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
ip->protocol = 6;
ip->check=0;
//DOUBLE CHECK FOR BYTE ORDER
ip->id=htons(100);
ip->check = htons(csum(ip, sizeof(*ip)));
//printf("before %d \n",htons(iph->check));
iph->check=0;
//printf("middle %d\n",iph->check);
//DOUBLE CHECK FOR BYTE ORDER
iph->check = htons(csum(iph, sizeof(*iph)));
int i=iph->ihl*4;
struct tcphdr *tcph=(struct tcphdr *)(buf+i);
//printf("tcp before %x\n",htons(tcph->check));
tcph->check=0;
printf("TCP START\n");
tcph->check=(tcp_chksum(iph,tcph));
printf("TCP END\n");
//printf("tcp after %d\n",(tcph->check));
//printf("i == %d\n",i);
//POSSIBLY PRINT IPH for fun
//for(int a=0;a<recvlen;a++)
//printf("%x\n",buf[a]);
//GET ihl SEND -- tcp
int j=(ip->ihl*4);
//printf("j == %d\n",j);
int x=0;
//SEEK filling
struct tcphdr *tcp=(struct tcphdr *)(buf_1+20);
//populate_tcp_some(tcph,tcp);//Do LOOK AT THIS FUNCTION TO [SEE/CORRECT IT] >:)
seq++;
if(tcph->syn==1)
{
printf("WHAT THE HELL THEN WHY\n");
printf("syn\n");
//populate_tcp_some(tcph,tcp);
tcp->seq=htons(seq);
//tcp->ack_seq=htons(ntohs(tcph->seq)+1);
printf("seq = %d | ack_seq = %d\n",ntohs(tcph->seq),ntohs(tcp->ack_seq));
tcp->syn=1;
tcp->ack=1;
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
tcp->dest=tcph->source;
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//htons(ntohs(tcph->seq)+1);
// printf("received tcp syn = %d\n",tcph->syn);
}
else if(tcph->syn==0 && tcph->ack==1){
printf("WHAT THE HELL THEN COOL\n");
printf("syn\n");
// populate_tcp_some(tcph,tcp);
//tcp->seq=htons(1);
tcp->seq=htons(seq);
tcp->ack_seq=tcph->seq;
tcp->syn=0;
tcp->ack=1;
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
tcp->dest=tcph->source;
//tcp->ack_seq=tcph->seq;//htons(ntohs(tcph->seq)+1);
tcp->ack_seq=htons(ntohs(tcph->seq)+1);
}
else
{
populate_tcp_some(tcph,tcp);
tcp->syn=0;
tcp->ack=1;
//tcp->seq=htons(1);
tcp->seq=htons(seq);
tcp->res1=0;
tcp->res1=0;
tcp->urg=0;
tcp->psh=0;
tcp->fin=0;
tcp->doff=5;
tcp->source=htons(80);
tcp->dest=tcph->source;
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//tcp->ack_seq=tcph->seq;//htons(ntohs(tcph->seq)+1);
// printf("sending tcp syn = %d ack = %d\n",tcp->syn,tcp->ack);
}
printf("syn=%d | ack = %d | fin = %d | %d seq = %d ack_seq = %d | urg = %d | doff = %d | psh = %d rst = %d | rst2 = %d\n",tcp->syn,tcp->ack,tcp->fin,tcp->seq,tcp->ack_seq,tcp->urg,tcp->doff,tcp->psh,tcp->res1,tcp->res2);
//populate_tcp_some(tcph,tcp);
tcp->dest=tcph->source;
tcp->window=tcph->window;
//
//printf("%d %d SOURCE PORT \n",ntohs(tcph->source),ntohs(tcp->dest));
tcp->source=htons(80);
printf("%d %d PORTS \n",ntohs(tcp->source),ntohs(tcp->dest));
tcp->check=0;
//TCP CHECKSUM ABOUT TRIPPLE WOW
tcp->check=htons(tcp_chksum(ip,tcp));
//printf("tcpH = %d | tcp = %d\n",tcph->check,htons(tcp->check));
//IF needed make payload data
//WRITE
if (recvlen > 0)
{
printf("\n-WOW WOW WOW received seq = %d ack == %d",ntohs(tcph->seq),ntohs(tcp->ack_seq));
writelen = write(_tun_fd, buf_1, sizeof(struct iphdr)+sizeof(struct tcphdr));
//exit(0);
// sleep(2);
//debug("SR:%04d\n", recvlen);
//debug("TW:%04d\n", writelen);
if (writelen < 0)
{
//debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
//break;//NO NEED
}
}
else if (recvlen < 0)
{
//debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
//break;//NO NEED
}
else if (recvlen == 0)
{
//why
}
//FINALLY THEN SEND || DO WIRE SHARK
}
// ...:)__ :) __:) ___:)___ (: __(:__ (;...
}
debug("** Receiver ending.\n");
pthread_exit(NULL);
}
更新
现在我的 ACK+SYN 数据包没有捕获到 TCP 最后一段
这是收到的SYN
0000 45 00 00 3c c5 18 40 00 40 06 e0 2f c0 a8 0a 14
0010 c0 a8 0a 0f bc b2 00 50 f0 32 1f de 00 00 00 00
0020 a0 02 fa f0 c6 93 00 00 02 04 05 b4 04 02 08 0a
0030 95 a6 8e 4d 00 00 00 00 01 03 03 07
这是SYN+ACK
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc b2 86 e8 00 00 f0 32 1f df
0020 50 12 fa f0 cb 70 00 00
这是 SYN AGAIN
0000 45 00 00 3c c5 19 40 00 40 06 e0 2e c0 a8 0a 14
0010 c0 a8 0a 0f bc b2 00 50 f0 32 1f de 00 00 00 00
0020 a0 02 fa f0 c2 9c 00 00 02 04 05 b4 04 02 08 0a
0030 95 a6 92 44 00 00 00 00 01 03 03 07
在此数据包的行中再次进行 SYN 我收到未捕获的最后一段消息
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc b2 86 e9 00 00 f0 32 1f df
0020 50 12 fa f0 cb 6f 00 00
这是我的 更新 2
同步
0000 45 00 00 3c 9f 75 40 00 40 06 05 d3 c0 a8 0a 14
0010 c0 a8 0a 0f bc b8 00 50 55 a8 f4 2c 00 00 00 00
0020 a0 02 fa f0 83 25 00 00 02 04 05 b4 04 02 08 0a
0030 96 60 97 37 00 00 00 00 01 03 03 07
SYN + ACK
0000 45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010 c0 a8 0a 14 00 50 bc b8 00 00 00 03 55 a8 f4 2d
0020 50 12 fa f0 18 8c 00 00
这是 SYN agian retramit
0000 45 00 00 3c 9f 76 40 00 40 06 05 d2 c0 a8 0a 14
0010 c0 a8 0a 0f bc b8 00 50 55 a8 f4 2c 00 00 00 00
0020 a0 02 fa f0 7f 38 00 00 02 04 05 b4 04 02 08 0a
0030 96 60 9b 24 00 00 00 00 01 03 03 07
序列号和确认号是 32 位值:
因此这一行:
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//htons(ntohs(tcph->seq)+1);
正在使用 htons/ntohs,这是交换 16 位整数字节的函数。您需要将其更改为使用 htonl
和 ntohl
这可能不是您唯一的错误。