To be precise, I have a simple program which crafts a TCP syn packet and send it to a remote host.
Code TCP.c:
//Data part
data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr);
strcpy(data, datagram);
//some address resolution
strcpy(source_ip , sourceip);
sin.sin_family = AF_INET;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = inet_addr (destinationip);
//Fill in the IP Header
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr) + strlen(data);
iph->id = htonl (54321); //Id of this packet
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_TCP;
iph->check = 0; //Set to 0 before calculating checksum
iph->saddr = inet_addr ( source_ip ); //Spoof the source ip address
iph->daddr = sin.sin_addr.s_addr;
//Ip checksum
iph->check = csum ((unsigned short *) datagram, iph->tot_len);
//TCP Header
tcph->source = htons (sourceport);
tcph->dest = htons (destinationport);
tcph->seq = htonl (seqn);
tcph->ack_seq = htonl (ackn);
tcph->doff = 5; //tcp header size
tcph->fin = fin;
tcph->syn = syn;
tcph->rst = rst;
tcph->psh = push;
tcph->ack = ack;
tcph->urg = urg;
tcph->window = htons (win); /* maximum allowed window size */
tcph->check = 0; //leave checksum 0 now, filled later by pseudo header
tcph->urg_ptr = 0;
//Now the TCP checksum
psh.source_address = inet_addr( source_ip );
psh.dest_address = sin.sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_TCP;
psh.tcp_length = htons(sizeof(struct tcphdr) + strlen(data) );
int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + strlen(data);
pseudogram = malloc(psize);
memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + strlen(data));
tcph->check = csum( (unsigned short*) pseudogram , psize);
//IP_HDRINCL to tell the kernel that headers are included in the packet
int one = 1;
const int *val = &one;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
{
perror("Error setting IP_HDRINCL");
exit(0);
}
while (1)
{
//Send the packet
if (sendto (s, datagram, iph->tot_len , 0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror("sendto failed");
}
//Data send successfully
else
{
printf (" Packet Send. Length : %d \n" , iph->tot_len);
}
sleep(2);
}
So far it work just fine, I can see wireshark in my source machine generating a syn packet and sending it to my destination machine.
In my Destination host I have a simple server which listens on port 8000.
What I basically Do is using this TCP packet generator I am sending a syn packet to my server and then the server responds with syn, ack, but then the source machine(above program) sends back rst. which does not complete the 3-way-handshake.
What I want to do is to complete the 3-way-handshake with my TCP.c program.
I would really Appreciate if you could tell me how do I do that? Do I use recv() to receive back the syn/ack and then craft a new packet as ack and responds with it or what?
Regards :)