// Authors: Rajesh Balla, Wei Cheng, Corinne Rhodes, Saifee Suterwala.

// Date Created: May 2, 2000

// Last Modified: Sept 15, 2000

//

// Description:  This is a program that implements the construction of a TCP packet.  // It takes a source address, source port, destination address, destination port

// number, sequence number, acknowledgement number, the values for the SYN, ACK,

// FIN, and RST flags.

 

 

 

#include <stdio.h>      // for printf() and fprintf()

#include <stdlib.h>     // for atoi()

#include <signal.h>    

#include <string.h>     // for memset()

#include <unistd.h>     // or close()

#include <netdb.h>

#include <netinet/in.h>

#include <sys/socket.h> // for socket(), connect(), send(), and recv()

#include <arpa/inet.h>  // for socketaddr_in and inet_addr()

#include <netinet/ip.h> // for ip struct

#include <netinet/tcp.h>// for tcp struct

 

char myBUFFER[80];

 

void send_packet(unsigned int, unsigned short, unsigned int, unsigned short);

unsigned short in_cksum(unsigned short *, int);

unsigned int host2ip(char *);

void DieWithError (char *errorMessage); /* error handling function*/

 

main(int argc, char **argv)

{

   unsigned int srchost;

   unsigned int dsthost;

   unsigned short dstport;

   unsigned short srcport;

  

//check for the minimum number of arguements

   if(argc < 5 || argc >= 6)

   {

      fprintf(stderr, "Usage: %s  <srchost> <srcport> <dsthost> <dstport>\n", argv[0]);

      exit(0);

   }

   srchost= host2ip(argv[1]);

   srcport = atoi(argv[2]);

   dsthost = host2ip(argv[3]);

   dstport = atoi(argv[4]);

 

   if(dstport == 0) dstport = 80;

   send_packet(srchost, srcport, dsthost, dstport);

}

 

// Creates the IP and TCP packet, opens the socket, calculate IP checksum,

void send_packet(unsigned int source_addr, unsigned short srcport, unsigned int dest_addr, unsigned short dest_port)

{

   struct send_tcp   /* structure for the TCP/IP packet to send */

   {

      struct iphdr ip;

      struct tcphdr tcp;

   } send_tcp;

   struct pseudo_header   /* for calculating the checksum */

   {

      unsigned int source_address;

      unsigned int dest_address;

      unsigned char placeholder;

      unsigned char protocol;

      unsigned short tcp_length;

      struct tcphdr tcp;

   } pseudo_header;

   int i;

   int tcp_socket;  /* raw socket to send our TCP packet through */

   struct sockaddr_in sin;

   int sinlen;

   char ans = 'n';

   char temp;

  

  

   memset (&send_tcp, 0, sizeof(send_tcp));  

 

   printf("\n Do you want to enter the sequence number (y/n)?:");

   fflush(stdin);

   ans = getchar();

   if(ans =='y' || ans == 'Y')

     {

        printf("\n Enter the sequence number: ");

     scanf("%u",& send_tcp.tcp.seq);

     }

   else

     {

     printf("\n Using default sequence number = %d \n", getpid());

      send_tcp.tcp.seq = getpid(); 

     }

      ans ='n';  

 

   printf("\n Do you want to enter the Acknowledge Number (y/n)?:");

   getchar();

   ans = getchar();

   if(ans =='y' || ans == 'Y')

     {

     printf("\n Enter the Acknowledge Number: ");

     scanf("%u", & send_tcp.tcp.ack_seq);

     }

   else

     {

      printf("\n Using default Acknowledge number = %d\n", 0);

      send_tcp.tcp.ack_seq = 0;

     }

   ans ='n';         

  

   printf("\n Do you want to set the SYN Flag (y/n)?:");

   getchar();

   ans = getchar();

   if(ans =='y' || ans == 'Y')

     {

     printf("\n Setting the SYN flag\n");

     send_tcp.tcp.syn = 1;      

     }

   else

     {

     printf("\n Resetting the SYN flag\n");

     send_tcp.tcp.syn = 0;

     }

   ans ='n';

 

   printf("\n Do you want to set the ACK Flag (y/n)?:");

   getchar();

   ans = getchar();

   if(ans =='y' || ans == 'Y')

     {

      printf("\n Setting the ACK flag\n");

     send_tcp.tcp.ack = 1;      

     }

   else

     {

        printf("\n Resetting the ACK flag\n");

     send_tcp.tcp.ack = 0;

     }

   ans ='n';

 

   printf("\n Do you want to set the FIN Flag (y/n)?:");

   getchar();

   ans = getchar();

   if(ans =='y' || ans == 'Y')

     {

      printf("\n Setting the FIN flag\n");

     send_tcp.tcp.fin = 1;      

     }

   else

     {

      printf("\n Resetting the FIN flag\n");

     send_tcp.tcp.fin = 0;

     }

   ans ='n';

 

   printf("\n Do you want to set the RESET Flag (y/n)?:");

   getchar();

   ans = getchar();

   if(ans =='y' || ans == 'Y')

     {

     printf("\n Setting the RESET flag\n");

      send_tcp.tcp.rst = 1;      

     }

   else

     {

        printf("\n Resetting the RESET flag\n\n");

     send_tcp.tcp.rst = 0;

     }

   ans ='n';

 

   /* form ip packet */

   send_tcp.ip.ihl = 5;

   send_tcp.ip.version = 4;

   send_tcp.ip.tos = 0;

   send_tcp.ip.tot_len = htons(40);

   send_tcp.ip.id = getpid();

   send_tcp.ip.frag_off = 0;

   send_tcp.ip.ttl = 255;

   send_tcp.ip.protocol = IPPROTO_TCP;

   send_tcp.ip.check = 0;

   send_tcp.ip.saddr = source_addr;

   send_tcp.ip.daddr = dest_addr;

  

   /* form tcp packet */

   send_tcp.tcp.source = htons(srcport);

   send_tcp.tcp.dest = htons(dest_port); 

   send_tcp.tcp.seq = htonl(send_tcp.tcp.seq);

   send_tcp.tcp.ack_seq = htonl(send_tcp.tcp.ack_seq);

   send_tcp.tcp.res1 = 0;

   send_tcp.tcp.doff = 5;

   send_tcp.tcp.psh = 0;

   send_tcp.tcp.urg = 0;

   send_tcp.tcp.res2 = 0;

   send_tcp.tcp.window = htons(1024);

   send_tcp.tcp.check = 0;

   send_tcp.tcp.urg_ptr = 0;

  

   /* setup the sin struct */

   sin.sin_family = AF_INET;

   sin.sin_port = send_tcp.tcp.source;

   sin.sin_addr.s_addr = send_tcp.ip.daddr;  

  

   /* (try to) open the socket */

   tcp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

   if(tcp_socket < 0)

   {

      perror("socket");

      exit(1);

   }

   /* calculate the ip checksum */

   send_tcp.ip.check = in_cksum((unsigned short *)&send_tcp.ip, 20);

 

   /* set the pseudo header fields */

   pseudo_header.source_address = send_tcp.ip.saddr;

   pseudo_header.dest_address = send_tcp.ip.daddr;

   pseudo_header.placeholder = 0;

   pseudo_header.protocol = IPPROTO_TCP;

   pseudo_header.tcp_length = htons(20);

   bcopy((char *)&send_tcp.tcp, (char *)&pseudo_header.tcp, 20);

   send_tcp.tcp.check = in_cksum((unsigned short *)&pseudo_header, 32);

   sinlen = sizeof(sin);

   printf("\n Hit a key to continue");

   getchar();

   getchar();

   sendto(tcp_socket, &send_tcp, sizeof(send_tcp), 0, (struct sockaddr *)&sin, sinlen);

   printf("\n***** Sent TCP packet *****\n");

 

   getchar();

   printf("\n Hit any key to terminate!\n");

 

   getchar();

 

   close(tcp_socket);      

}

 

//  finds the TCP checksum

unsigned short in_cksum(unsigned short *ptr, int nbytes)

{

        register long           sum;            /* assumes long == 32 bits */

        u_short                 oddbyte;

        register u_short        answer;         /* assumes u_short == 16 bits */

 

        /*

         * Our algorithm is simple, using a 32-bit accumulator (sum),

         * we add sequential 16-bit words to it, and at the end, fold back

         * all the carry bits from the top 16 bits into the lower 16 bits.

         */

 

        sum = 0;

        while (nbytes > 1)  {

                sum += *ptr++;

                nbytes -= 2;

        }

 

                                /* mop up an odd byte, if necessary */

        if (nbytes == 1) {

                oddbyte = 0;            /* make sure top half is zero */

                *((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */

                sum += oddbyte;

        }

 

        /*

         * Add back carry outs from top 16 bits to low 16 bits.

         */

 

        sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */

        sum += (sum >> 16);                     /* add carry */

        answer = ~sum;          /* ones-complement, then truncate to 16 bits */

        return(answer);

}

 

// converts the char string IP address to valid internet address

unsigned int host2ip(char *hostname)

{

   static struct in_addr i;

   struct hostent *h;

   i.s_addr = inet_addr(hostname);

   if(i.s_addr == -1)

   {

      h = gethostbyname(hostname);

      if(h == NULL)

      {

         fprintf(stderr, "cant find %s!\n", hostname);

         exit(0);

      }

      bcopy(h->h_addr, (char *)&i.s_addr, h->h_length);

   }

   return i.s_addr;

}