I am simulating TCP and now I am stuck to acknowledgement number handling.
tcph->seq
is received sequence number and I am assigning it to tcp->ack_seq which is acknowledgement number like
tcp->ack_seq=htons(ntohs(tcph->seq)+1);
But given the above code it seems like there is something inherently wrong, tcph->seq and tcph is in network byte order which It should be because I cast-ed it from buffer and assign to tcph pointer
This is my simple thread function that reads received buffer extract tcthdr (struct tcph) and tweak values or assign values to send tcphdr (struct tcp)
Its simply does what it does I there is really something wrong with this. I am keeping getting wrong acknowlegdemnet numbers (not really reflecting as to how I am incrementing sequence number and assign it to acknowledgement number). Can any one please take a look at this so I finally have TCP handshake successful. Problem comes I send SYN+ACK packet and my client retransmit SYN packet and this cycle is polluting my wireshark view nothing useful just awefull loots of SYN and reponse SYN+ACK from my code
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);
}
Update
Now I am get TCP last segment not captured for my ACK+SYN packet
This is received 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
This is 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
And this is 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
ANd SYN again in row of this packet I get message last segment not captured
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
This is my Update 2 to this
SYN
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
And this is 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
sequence and ack numbers are 32-bit values:
Hence this line:
tcp->ack_seq=htons(ntohs(tcph->seq)+1);//htons(ntohs(tcph->seq)+1);
Is using htons/ntohs which are functions that swap the bytes of 16-bit integers. You need to change it to use htonl
and ntohl
That might not be your only bug.