/*
 *
 *                                  Juggernaut
 *                                  Version 1.2
 *
 *                            1996/7 Guild productions
 *                           daemon9[guild|phrack|r00t]
 *
 *                         comments to route@infonexus.com
 *
 *  This coding project made possible by a grant from the Guild corporation
 * 
 *  prometheus.c - the packet assemby workshop module.  Each of the main 
 *  packet assembly subfunctions will end up calling the ip assembler to build
 *  the IP portion and send it (them) out.
 *
 *  Too many dependencies in menu.c 
 *
 *  Shout out to Nirva for some suggestions/help.  Nirva rules, BTW.  I love 
 *  Nirva.  You should too.
 *
 */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <linux/if_ether.h>
#include <linux/if.h>
 
#define MINIBUF     10  
#define BUFSIZE     512
#define ETHHDR      14
#define PHDR        12
#define TCPHDR      20
#define UDPHDR      8
#define IPHDR       20

#define NOTRANSPORT     0x00
#define TCPTRANSPORT    0x01
#define UDPTRANSPORT    0x02
#define ICMPTRANSPORT   0x04

struct tpak{			/* TCP packet */
    struct tcphdr tcp;
    char payload[BUFSIZE];
}tpack;

struct upak{			/* UDP packet */
    struct udphdr udp;
    char payload[BUFSIZE];
}upack;

struct ipak{			/* ICMP packet */
    struct icmphdr icmp;
    char payload[BUFSIZE];
}ipack;

struct rippak{     		/* IP packet */
    struct iphdr ip;
    char payload[BUFSIZE+20];   /* Payload + transport header */
}rippack;

int woe;                        /* Global var to let us know where to return 
                                   to... */
extern int verbosity;

				/* This will change when IP/TCP options are 
                                   implemented... */
#define RIPPACKETSIZE 552	/* IP header + transport header of up to 20 
                                   bytes + 512 byte payload */

int prometheus(type)
int type;
{
    void tcpa();
    void udpa();
    void icmpa();
    void igmpa();
    void ripa(int);

    bzero(&rippack,sizeof(rippack));
    woe=0;

    switch(type){
        case 1:
	    tcpa();		/* TCP */
	    break;
	case 2:
	    udpa();		/* UDP */
	    break;
	case 3:				
	    icmpa();		/* ICMP */
	    break;
	case 4:
	    ripa(NOTRANSPORT);	/* RAW IP with no transport and no payload */	
	    break;
	case 5:
	    return(woe=1);      /* Done assembling packets */
	default:
	    break;              /* bad input -- not done */			
    }
    return(woe);
}


/* 
 *  TCP assembler
 */

void tcpa(){

    void ripa(int);
    void mwipe();
    void mpktatcp(int,unsigned short,unsigned short,unsigned long,unsigned long,char *,unsigned short,char *);

    char buf[2*MINIBUF];
    unsigned long val;
    int packetready=0;		/* flag bits */
    char data[4*MINIBUF]={0},flags[MINIBUF]={0},filename[4*MINIBUF]={0};
    int i,j,fd,loopsentry=1;

    bzero(&tpack,sizeof(tpack));

    srandom((unsigned)time(0)); /* seed psuedo random number generator */ 

    while(loopsentry){
        mwipe();	
	mpktatcp(packetready,ntohs(tpack.tcp.source),ntohs(tpack.tcp.dest),ntohl(tpack.tcp.seq),ntohl(tpack.tcp.ack_seq),flags,ntohs(tpack.tcp.window),data);
                    
        fgets(buf,sizeof(buf),stdin);
        if(!(val=atoi(buf)))continue;
        switch(val){
            case 1:         /* Source Port */
 	        fprintf(stderr,"\nSource Port (0 - 65535) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='r'){
		    tpack.tcp.source=htons(random()&0xffff);
		    packetready|=0x01;
		    break;
		}
                if(buf[0]=='q'||(val=atoi(buf))<0||val>65535){
		    if(packetready&0x01)packetready^=0x01;	/* Clear flag 
                                                                   if set */
		    tpack.tcp.source=0;
		    break;
		}
		tpack.tcp.source=htons(val);
		packetready|=0x01;
		break;
            case 2:         /* Destination Port */
	        fprintf(stderr,"\nDestination Port (0 - 65535) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='r'){
		    tpack.tcp.dest=htons(random()&0xffff);
		    packetready|=0x02;
		    break;
		}
                if(buf[0]=='q'||(val=atoi(buf))<0||val>65535){
		    if(packetready&0x02)packetready^=0x02;
		    tpack.tcp.dest=0;
		    break;
		}
		tpack.tcp.dest=htons(val);
		packetready|=0x02;
		break;
            case 3: 	    /* Sequence Number */
	        fprintf(stderr,"\nSequence Number (0 - 4294967295) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='r'){
		    tpack.tcp.seq=htonl(random());
		    packetready|=0x04;
		    break;
		}
                if(buf[0]=='q'||buf[0]=='-'){                           
		    if(packetready&0x04)packetready^=0x04;		
		    tpack.tcp.seq=0;
		    break;
		}
		tpack.tcp.seq=htonl(strtoul(buf,0,10));
		packetready|=0x04;
		break;
            case 4:         /* Acknowledgement Number */
	        fprintf(stderr,"\nAcknowledgement Number (0 - 4294967295) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='r'){
		    tpack.tcp.ack_seq=htonl(random());
		    packetready|=0x08;
		    break;
		}
                if(buf[0]=='q'||buf[0]=='-'){
		    if(packetready&0x08)packetready^=0x08;
		    tpack.tcp.ack_seq=0;
		    break;
		}
		tpack.tcp.ack_seq=htonl(strtoul(buf,0,10));
		packetready|=0x08;
		break;
	    case 5:         /* Control Flags */
	        i=0;
		bzero(flags,sizeof(flags));
	        fprintf(stderr,"\nURG? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;
		    tpack.tcp.urg=0;
		    break;
		}
	        if(buf[0]=='y'){
		    tpack.tcp.urg=1;
		    flags[i++]='U';
		}
		fprintf(stderr,"\nACK? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;		
		    tpack.tcp.ack=0;
		    break;
		}
		if(buf[0]=='y'){
		    tpack.tcp.ack=1;
		    flags[i++]='A';
		}
		fprintf(stderr,"\nPSH? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;
		    tpack.tcp.psh=0;
		    break;
		}
		if(buf[0]=='y'){
		    tpack.tcp.psh=1;
		    flags[i++]='P';
		}
		fprintf(stderr,"\nRST? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;	
		    tpack.tcp.rst=0;
		    break;
		}
		if(buf[0]=='y'){
		    tpack.tcp.rst=1;
		    flags[i++]='R';
		}
		fprintf(stderr,"\nSYN? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;
		    tpack.tcp.syn=0;
		    break;
		}
		if(buf[0]=='y'){
		    tpack.tcp.syn=1;
		    flags[i++]='S';
		}
		fprintf(stderr,"\nFIN? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
	        if(buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;		
		    tpack.tcp.fin=0;
		    break;
		}
		if(buf[0]=='y'){
		    tpack.tcp.fin=1;
		    flags[i++]='F';
	        }
		if(!flags[0])strcpy(flags,"none set");
		packetready|=0x10;
		break;
            case 6:     /* Window Size */
	        fprintf(stderr,"\nWindow Size (0 - 65535) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='r'){
		    tpack.tcp.window=htons(random()&0xffff);
		    packetready|=0x20;
		    break;
		}
                if(buf[0]=='q'||(val=atoi(buf))<0||val>65535){
		    if(packetready&0x20)packetready^=0x20;
		    tpack.tcp.window=0;
		    break;
		}
		tpack.tcp.window=htons(val);
		packetready|=0x20;
		break;
            case 7:     /* Data payload */
	        bzero(data,sizeof(data));
		bzero(tpack.payload,sizeof(tpack.payload));
		bzero(filename,sizeof(filename));
		fprintf(stderr,"\nData Payload Source (512 Bytes Maximum) [qfc] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='c'){	/* Input from command line */
		    fprintf(stderr,"\nEnter Payload [q] >");
		    fgets(tpack.payload,sizeof(tpack.payload),stdin);
		    strncpy(data,tpack.payload,sizeof(data));
		    packetready|=0x40;
		    break;
		}
		if(buf[0]=='f'){	/* Input from file */
		    fprintf(stderr,"\nFilename [q] >");
		    if(buf[0]==0x0a||buf[0]=='q')break;
		    fgets(filename,sizeof(filename),stdin);
		    for(i=0;i<4*MINIBUF;i++)if(!filename[i])break;
		    filename[--i]=0;	/* Pesky Newline */
		    if((fd=open(filename,O_RDONLY))<0){
                        if(verbosity){
                            fprintf(stderr,"Cannot open file for reading.\n");
                            fprintf(stderr,"[cr]");
                            getchar();
                        }
			continue;
                    }
                    i=0;
                    j=0;
		    while(i<512){
                        j=read(fd,tpack.payload,sizeof(tpack.payload));
                        if(!j)break;    /* No more bytes ta read */
                        i+=j;
                    }
		    strncpy(data,filename,sizeof(filename));
		    close(fd);
		    packetready|=0x40;
		    break;
       	        }   
		if(packetready&0x40)packetready^=0x40;
		bzero(data,sizeof(data));
		bzero(tpack.payload,sizeof(tpack.payload));
		break;
	    case 8:         /* Return to previous menu */
	        loopsentry=0;
                bzero(&tpack,sizeof(tpack));
		break;
            case 9:         /* Return to Main */
	        loopsentry=0;
                woe=1;
                break;
	    case 10:        /* RIP assembler */
	        if(packetready==0x07f){	    /* AND mask of all the options */
                    tpack.tcp.doff=5;       /* Data offset */
		    ripa(TCPTRANSPORT);	    /* Checksum will be computed in 
                                               ripa */
		    break;
		}
                continue;
	    default:        /* Bad input */
	        continue;
        }
    }
}

/* 
 *  UDP assembler
 */

void udpa(){

    void ripa(int);
    void mwipe();
    void mpktaudp(int,unsigned short,unsigned short,char *);

    char buf[2*MINIBUF];
    unsigned long val;
    int packetready=0;		/* flag bits */
    char data[4*MINIBUF]={0},filename[4*MINIBUF]={0};
    int i=0,j,fd=0,loopsentry=1;

    bzero(&upack,sizeof(upack));

    srandom((unsigned)time(0));

    while(loopsentry){
        mwipe();	

	mpktaudp(packetready,ntohs(upack.udp.source),ntohs(upack.udp.dest),data);
                
	fgets(buf,sizeof(buf),stdin);
        if(!(val=atoi(buf)))continue;
        switch(val){
            case 1:         /* Source Port */
	        fprintf(stderr,"\nSource Port (0 - 65535) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]==0x0a||buf[0]=='q'){
		    if(packetready&0x01)packetready^=0x01;	
		    upack.udp.source=0;
		    break;
		}
		if(buf[0]=='r'){
		    upack.udp.source=htons(random()&0xffff);
		    packetready|=0x01;
		    break;
		}
		if(!(int)(val=atoi(buf)))break;
	        upack.udp.source=htons(val);
		packetready|=0x01;
		break;
            case 2:	    /* Destination Port */
	        fprintf(stderr,"\nDestination Port (0 - 65535) [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]==0x0a||buf[0]=='q'){
		    if(packetready&0x02)packetready^=0x02;
		    upack.udp.dest=0;
		    break;
		}
		if(buf[0]=='r'){
		    upack.udp.dest=htons(random()&0xffff);
		    packetready|=0x02;
		    break;
                }
		if(!(int)(val=atoi(buf)))break;
		upack.udp.dest=htons(val);
		packetready|=0x02;
		break;
	    case 3:	    /* Data payload */
	        bzero(data,sizeof(data));
	        bzero(upack.payload,sizeof(upack.payload));
		bzero(filename,sizeof(filename));
		fprintf(stderr,"\nData Payload Source (512 Bytes Maximum) [qfc] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='c'){	/* Input from command line */
		    fprintf(stderr,"\nEnter Payload [q] >");
		    fgets(upack.payload,sizeof(upack.payload),stdin);
		    strncpy(data,upack.payload,sizeof(data));
		    packetready|=0x04;
		    break;
		}
	        if(buf[0]=='f'){	/* Input from file */
		    fprintf(stderr,"\nFilename [q] >");
		    if(buf[0]==0x0a||buf[0]=='q')break;
		    fgets(filename,sizeof(filename),stdin);
		    for(i=0;i<4*MINIBUF;i++)if(!filename[i])break;
		    filename[--i]=0;
		    if((fd=open(filename,O_RDONLY))<0){
                        if(verbosity){
                            fprintf(stderr,"Cannot open file for reading.\n");
                            fprintf(stderr,"[cr]");
                            getchar();
                        }
			continue;
                    }
                    i=0;
                    j=0;
		    while(i<512){
                        j=read(fd,upack.payload,sizeof(upack.payload));
                        if(!j)break;  
                        i+=j;
                    }
		    strncpy(data,filename,sizeof(filename));
		    close(fd);
		    packetready|=0x04;
		    break;
       	 	}
		if(packetready&0x04)packetready^=0x04;
		bzero(data,sizeof(data));
		bzero(upack.payload,sizeof(upack.payload));
		break;
	    case 4:     /* Return to previous menu */
	        loopsentry=0;
                bzero(&upack,sizeof(upack));
		break;
            case 5:     /* Retuen to Main */
                loopsentry=0;
                woe=1;
                break;
	    case 6:     /* RIP assembler */
	        if(packetready==0x07){		
                    upack.udp.len=htons(UDPHDR+BUFSIZE);
		    ripa(UDPTRANSPORT);		
		    break;
		}
	        continue;
	    default:    /* bad input */
	        continue;   
        }
    }
}

/* 
 *  ICMP assembler
 *  This is no where as robust as it should be.  In fact, it doesn't really 
 *  create legal ICMP packets.  Oh well.  Next version.  I am tired of
 *  packet assembly duldrums...
 */

void icmpa(){

    void ripa(int);
    void mwipe();
    void mpktaicmp(int,unsigned short,unsigned short,char *);

    char buf[2*MINIBUF];
    unsigned long val;
    int packetready=0;		/* flag bits */
    char data[4*MINIBUF]={0},filename[4*MINIBUF]={0};
    int i=0,j,fd=0,loopsentry=1;

    bzero(&ipack,sizeof(ipack));

    while(loopsentry){
        mwipe();	

        mpktaicmp(packetready,ipack.icmp.type,ipack.icmp.code,data);
                
	fgets(buf,sizeof(buf),stdin);
        if(!(val=atoi(buf)))continue;
        switch(val){
            case 1:				/* Type */
	        fprintf(stderr,"\nType (0,3,4,5,8,9,10,11,12,13,14,15,16,17,18) [q] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]==0x0a||buf[0]=='q'){
		    if(packetready&0x01)packetready^=0x01;
		    ipack.icmp.type=0;
		    break;
		}
	        if(!(int)(val=atoi(buf)))break;
		ipack.icmp.type=val;
		packetready|=0x01;
		break;
            case 2:				/* Code */
	        fprintf(stderr,"\nCode (0,1 {2,3}) [q] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]==0x0a||buf[0]=='q'){
		if(packetready&0x02)packetready^=0x02;
		    ipack.icmp.code=0;
		    break;
		}
		if(!(int)(val=atoi(buf)))break;
		ipack.icmp.code=val;
		packetready|=0x02;
		break;
	    case 3:				/* Data payload */
	        bzero(data,sizeof(data));
		bzero(ipack.payload,sizeof(ipack.payload));
		bzero(filename,sizeof(filename));
		fprintf(stderr,"\nData Payload Source (512 Bytes Maximum) [qfc] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='c'){	/* Input from command line */
		    fprintf(stderr,"\nEnter Payload [q] >");
		    fgets(ipack.payload,sizeof(ipack.payload),stdin);
		    strncpy(data,ipack.payload,sizeof(data));
		    packetready|=0x04;
		    break;
		}
		if(buf[0]=='f'){	/* Input from file */
		    fprintf(stderr,"\nFilename [q] >");
		    if(buf[0]==0x0a||buf[0]=='q')break;
		    fgets(filename,sizeof(filename),stdin);
		    for(i=0;i<4*MINIBUF;i++)if(!filename[i])break;
		    filename[--i]=0;	
		    if((fd=open(filename,O_RDONLY))<0){
                        if(verbosity){
                            fprintf(stderr,"Cannot open file for reading.\n");
                            fprintf(stderr,"[cr]");
                            getchar();
                        }
		        continue;
                    }
                    i=0;
                    j=0;
                    while(i<512){
                        j=read(fd,upack.payload,sizeof(upack.payload));
                        if(!j)break; 
                        i+=j;
                    }
                    strncpy(data,filename,sizeof(filename));
		    close(fd);
		    packetready|=0x04;
		    break;
       	 	}
		if(packetready&0x04)packetready^=0x04;	
		bzero(data,sizeof(data));
		bzero(ipack.payload,sizeof(ipack.payload));
		break;
	    case 4:	
                loopsentry=0;
	        bzero(&ipack,sizeof(ipack));
		break;
            case 5:
                loopsentry=0;
                woe=1;
                break;
	    case 6: 
	        if(packetready==0x07){	
		    ripa(ICMPTRANSPORT);		
		    break;
		}
		continue;
	    default: 
	        continue;
        }
    }
}


/* 
 *  IP assembler and xmitter.  Transport layer checksum routines thanks to 
 *  Myth (Red, actually).
 */

void ripa(transport)
int transport;
{

    void mwipe();
    void mpktaip(int,char *,char *,unsigned short,unsigned short,char *,char *,int,char *);
    char *hostLookup(unsigned long);
    unsigned long nameResolve(char *);
    unsigned short in_cksum(unsigned short *,int);
    

    char buf[2*MINIBUF];
    unsigned long val;
    char tosflags[MINIBUF]={0},fflags[MINIBUF]={0},packettype[MINIBUF]={0};
    char sip[2*MINIBUF]={0},dip[2*MINIBUF]={0},*tempBuf;
    int packetready=0;              /* flag bits */
    int i=0,j=0,k=0;                /* Counters */
    int loopsentry=1,number=0;

    struct sockaddr_in sin;	 

    struct psuedoHeader{                        
        unsigned long saddr;
        unsigned long daddr;
        unsigned char null;
        unsigned char prot;
        unsigned short tlen;
    }*ppheader;

    extern int ripsock;

    bzero(&rippack,sizeof(rippack));
    bzero((char *)&sin,sizeof(sin));
	
    srandom((unsigned)time(0));   

    while(loopsentry){
        i=0;
        mwipe();
        mpktaip(packetready,tosflags,fflags,ntohs(rippack.ip.frag_off),rippack.ip.ttl,sip,dip,number,packettype);
        
        fgets(buf,sizeof(buf),stdin);
        if(!(val=atoi(buf)))continue;
        switch(val){
            case 1:     /* TOS */
	        bzero(tosflags,sizeof(tosflags));
		fprintf(stderr,"\nMinimize Delay? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x01)packetready^=0x01; 
		    rippack.ip.tos=0;
		    break;
		}
		if(buf[0]=='y'){
		    rippack.ip.tos|=0x10;
		    tosflags[i++]='D';
		}
		fprintf(stderr,"\nMaximize Throughput? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x01)packetready^=0x01; 
		    rippack.ip.tos=0;
		    break;
		}
		if(buf[0]=='y'){
		    rippack.ip.tos|=0x08;
		    tosflags[i++]='T';
		}
		fprintf(stderr,"\nMaximize Reliability? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x01)packetready^=0x01; 
		    rippack.ip.tos=0;
		    break;
		}
		if(buf[0]=='y'){
		    rippack.ip.tos|=0x04;
		    tosflags[i++]='R';
		}
		fprintf(stderr,"\nMinimize Monetary Cost? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x01)packetready^=0x01; 
		    rippack.ip.tos=0;
		    break;
		}
		if(buf[0]=='y'){
		    rippack.ip.tos|=0x02;
		    tosflags[i++]='C';
		}
		if(!tosflags[0])strcpy(tosflags,"none set");
		packetready|=0x01;
		break;
            case 2:			/* Frag Flags */
	        bzero(fflags,sizeof(fflags));
		fprintf(stderr,"\nMore Fragments? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x02)packetready^=0x02; 
		    rippack.ip.frag_off=0;
		    break;
		}
		if(buf[0]=='y'){
		    rippack.ip.frag_off|=htons(0x4000);
		    fflags[i++]='M';
		}
		fprintf(stderr,"\nDon't Fragment? [yNq] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]=='q'){
		    if(packetready&0x02)packetready^=0x02; 
		    rippack.ip.frag_off=0;
		    break;
		}
	        if(buf[0]=='y'){
		    rippack.ip.frag_off|=htons(0x2000);
		    fflags[i++]='D';
		}
                if(!fflags[0])strcpy(fflags,"none set");
		packetready|=0x02;
		break;
            case 3: 		/* Frag Offset */
	        fprintf(stderr,"\nFragment Offset [qr] >");
                fgets(buf,sizeof(buf),stdin);
	        if(buf[0]=='r'){
		    rippack.ip.frag_off|=htons(random()&0x1fff);
		    packetready|=0x04;
		    break;
	        }
                if(buf[0]=='q'||(val=atoi(buf))<0||val>8191){
		    if(packetready&0x04)packetready^=0x04;
		    rippack.ip.frag_off&=~0x3fff;
		    break;
	        }
                rippack.ip.frag_off|=htons(val&0x1fff);
	        packetready|=0x04;
                break;
            case 4:			/* TTL */
                fprintf(stderr,"\nTTL (0 - 255) [qr] >");
                fgets(buf,sizeof(buf),stdin);
	        if(buf[0]=='r'){			
		    rippack.ip.ttl=random()&0xff;
		    packetready|=0x08;
	            break;
	        }
	        if(buf[0]=='q'||(val=atoi(buf))<0||val>255){
		    if(packetready&0x08)packetready^=0x08;
		    rippack.ip.ttl=0;
		    break;
                }
	        rippack.ip.ttl=val;
	        packetready|=0x08;
	        break;
	    case 5:			/* Source Address */
                bzero(sip,sizeof(sip));
	        fprintf(stderr,"\nSource Address [qr] >");
                fgets(buf,sizeof(buf),stdin);
		if(buf[0]==0x0a||buf[0]=='q'){
		    if(packetready&0x10)packetready^=0x10;
		    rippack.ip.saddr=0;
		    break;
                }
                if(buf[0]=='r'){
                    rippack.ip.saddr=htonl(random());
                    strncpy(sip,hostLookup(rippack.ip.saddr),sizeof(sip));
                    packetready|=0x10;
                    break;
                }
                strncpy(sip,buf,sizeof(sip));
                for(i=0;i<2*MINIBUF;i++)if(!sip[i])break;
                sip[--i]=0;                 	
       	        if(!(rippack.ip.saddr=nameResolve(buf))){
		    fprintf(stderr,"Cannot resolve IP address.\n");
	            fprintf(stderr,"[cr]");
                    getchar();
		    bzero(sip,sizeof(sip));			
		    if(packetready&0x10)packetready^=0x10;
		    break;
	        }
                packetready|=0x10;
	        break;
	    case 6:			/* Destination Address */
                bzero(dip,sizeof(dip));
	        fprintf(stderr,"\nDestination Address [qr] >");
                fgets(buf,sizeof(buf),stdin);
	        if(buf[0]==0x0a||buf[0]=='q'){
	            if(packetready&0x20)packetready^=0x20;
	            rippack.ip.daddr=0;
	            break;
                }
                if(buf[0]=='r'){
                    strncpy(dip,hostLookup(rippack.ip.daddr),sizeof(dip));
                    rippack.ip.daddr=htonl(random());
                    packetready|=0x20;
                    break;
                }
                strncpy(dip,buf,sizeof(dip));
                for(i=0;i<2*MINIBUF;i++)if(!dip[i])break;
                dip[--i]=0;
	        if(!(rippack.ip.daddr=nameResolve(buf))){
	            fprintf(stderr,"Cannot resolve IP address.\n");
	            fprintf(stderr,"[cr]");
                    getchar();
	            bzero(dip,sizeof(dip));
	            if(packetready&0x20)packetready^=0x20;
	            break;
	        }
	        packetready|=0x20;
	        break;
	    case 7:                     /* Number of packets to send */
                fprintf(stderr,"\nAmount (1 - 65536) [qr] >");
                fgets(buf,sizeof(buf),stdin);
                if(buf[0]=='r'){
                    number=(random()&0xffff);
                    packetready|=0x40;
                    break;
                }
                if(buf[0]=='q'||(val=atoi(buf))<0||val>65536){
                    if(packetready&0x40)packetready^=0x40;
                    number=0;
                    break;
                }
                number=val;
                packetready|=0x40;
                break;
            case 8:			    /* Return */
                loopsentry=0;
                bzero(&rippack,sizeof(rippack));
	        break;
            case 9:
                loopsentry=0;
                woe=1;
                break;
            case 10:			
                if(packetready==0x7f){
		    sin.sin_family=AF_INET;         
                    sin.sin_port=0;

                    rippack.ip.version=4;	        /* IPv4 */
                    rippack.ip.ihl=5;		        /* This will change 
                                                           if options are
                                                           present */
		    switch(transport){              
		        case NOTRANSPORT:		/* IP packet only */
                            sin.sin_addr.s_addr=rippack.ip.daddr;

                            rippack.ip.protocol=IPPROTO_IP;

		            break;
		        case TCPTRANSPORT:		/* TCP */
                            sin.sin_port=tpack.tcp.source;
                            sin.sin_addr.s_addr=rippack.ip.daddr;
                        
                            rippack.ip.protocol=IPPROTO_TCP;

                            tempBuf=(char *)malloc(PHDR+TCPHDR+BUFSIZE);
                            ppheader=(struct psuedoHeader *)tempBuf;

                            ppheader->saddr=rippack.ip.saddr;
                            ppheader->daddr=rippack.ip.daddr;
                            ppheader->prot=IPPROTO_TCP;
                            ppheader->null=0;
                            ppheader->tlen=htons(TCPHDR+BUFSIZE);

                            bcopy(&tpack,tempBuf+PHDR,PHDR+TCPHDR+BUFSIZE);
                            tpack.tcp.check=in_cksum((unsigned short *)tempBuf,PHDR+TCPHDR+BUFSIZE);
                            free(tempBuf);
                            bcopy((char *)&tpack,(char *)&rippack.payload,TCPHDR+BUFSIZE);

                            break;
		        case UDPTRANSPORT:		/* UDP */
                            sin.sin_port=upack.udp.source;
                            sin.sin_addr.s_addr=rippack.ip.daddr;

			    rippack.ip.protocol=IPPROTO_UDP;

                            tempBuf=(char *)malloc(PHDR+UDPHDR+BUFSIZE);
                            ppheader=(struct psuedoHeader *)tempBuf;

                            ppheader->saddr=rippack.ip.saddr;
                            ppheader->daddr=rippack.ip.daddr;
                            ppheader->prot=IPPROTO_UDP;
                            ppheader->null=0;
                            ppheader->tlen=htons(UDPHDR+BUFSIZE);

                            bcopy(&upack,tempBuf+PHDR,PHDR+UDPHDR+BUFSIZE);
                            upack.udp.check=in_cksum((unsigned short *)tempBuf,PHDR+UDPHDR+BUFSIZE);
                            free(tempBuf);
                            bcopy((char *)&upack,(char *)&rippack.payload,UDPHDR+BUFSIZE);

                            break;
		        case ICMPTRANSPORT:		/* ICMP */
                            sin.sin_addr.s_addr=rippack.ip.daddr;

			    rippack.ip.protocol=IPPROTO_ICMP;
			
                            break;
		        default:	    /* Control should never fall here */
			    if(verbosity)perror("RIP Assembler [unknown transport]");
			    exit(1);
		    }
                    for(k=number,i=0;i<number;i++){
    	                if((j=sendto(ripsock,&rippack,RIPPACKETSIZE,0,(struct sockaddr *)&sin,sizeof(sin)))<RIPPACKETSIZE){
		            fprintf(stderr,"Packet # %d: Wrote only %d bytes to raw socket\n",i,j);
                            k--;
			    if(verbosity)perror("RIP module sendto");
		        }
                    }
		    fprintf(stderr,"%d Packet(s) injected.\n",k);
		    getchar();
		    break;
	        }
	        continue;
	    default: 
                continue;
        }
    }
	                            /* NOTREACHED */
}
