/*
 *
 *                                  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
 * 
 *  surplus.c - helper functions
 * 
 */

#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>

#define HELPFILE    "./ClothLikeGauze/.help"
#define FBUFSIZE     80
#define MINIBUF      10
#define DEVICE      "eth0"

extern int verbosity;    


/*
 *  IP address into network byte order
 */
                 
unsigned long nameResolve(hostname)
char *hostname;
{
        
    struct in_addr addr;
    struct hostent *hostEnt; 
   
    if((addr.s_addr=inet_addr(hostname))==-1){
        if(!(hostEnt=gethostbyname(hostname)))return(0);
        bcopy(hostEnt->h_addr,(char *)&addr.s_addr,hostEnt->h_length);
    }
    return addr.s_addr;
}

#ifdef FASTCHECK
 
/*
 *  Fast IP checksum routine.
 */

unsigned short in_cksum(buff,len)
unsigned char *buff;
int len;
{
    unsigned long sum = 0;
    if (len>3){
        __asm__("clc\n"
        "1:\t"
        "lodsl\n\t"
        "adcl %%eax, %%ebx\n\t"
        "loop 1b\n\t"
        "adcl $0, %%ebx\n\t"
        "movl %%ebx, %%eax\n\t"
        "shrl $16, %%eax\n\t"
        "addw %%ax, %%bx\n\t"
        "adcw $0, %%bx"
        : "=b" (sum) , "=S" (buff)
        : "0" (sum), "c" (len >> 2) ,"1" (buff)
        : "ax", "cx", "si", "bx" );
    }
    if(len&2){
        __asm__("lodsw\n\t"
        "addw %%ax, %%bx\n\t"      
        "adcw $0, %%bx"
        : "=b" (sum), "=S" (buff)
        : "0" (sum), "1" (buff)
        : "bx", "ax", "si");
    }
    if(len&1){
        __asm__("lodsb\n\t"
        "movb $0, %%ah\n\t"
        "addw %%ax, %%bx\n\t"
        "adcw $0, %%bx"
        : "=b" (sum), "=S" (buff)
        : "0" (sum), "1" (buff)
        : "bx", "ax", "si");
    }                     
    sum =~sum;
    return(sum&0xffff);
}

#else
 
/*
 *  IP Family checksum routine
 */

unsigned short in_cksum(ptr,nbytes)
unsigned short *ptr;
int nbytes;
{
                        
    register long sum=0;        /* assumes long == 32 bits */
    u_short oddbyte;
    register u_short answer;    /* assumes u_short == 16 bits */
        
    while(nbytes>1){
        sum+=*ptr++;
        nbytes-=2;    
    }
    if(nbytes==1){              /* mop up an odd byte, if necessary */
        oddbyte=0;              /* make sure top half is zero */
        *((u_char *)&oddbyte)=*(u_char *)ptr;   /* one byte only */
        sum+=oddbyte;
    }               
    sum+=(sum>>16);             /* add carry */
    answer=~sum;                /* ones-complement, then truncate to 16 bits */
    return(answer);
}

#endif 

/*
 *  Network byte order into IP address
 */

char *hostLookup(in)
unsigned long in;
{

    #define BUFSIZE         256
 
    char hostname[BUFSIZE]={0};
    struct in_addr addr;
#ifdef USENAME
    struct hostent *hostEnt;
#endif
   
    addr.s_addr=in;
    
#ifdef USENAME
    hostEnt=gethostbyaddr((char *)&addr,sizeof(struct in_addr),AF_INET);
    if(!hostEnt)
#endif

        strcpy(hostname,inet_ntoa(addr));           /* KLUDGEY. */

#ifdef USENAME
    else strcpy(hostname,hostEnt->h_name);
#endif
    return(strdup(hostname));
}
 
/*
 *  Simple daemonizing procedure.
 */   

int shadow(void){

    int fd,pid;
    extern int errno;

    signal(SIGTTOU,SIG_IGN);    /* Ignore these signals */
    signal(SIGTTIN,SIG_IGN);
    signal(SIGTSTP,SIG_IGN);

    switch((pid=fork())){
        case 0:                 /* Child */
            break;
        default:        
            exit(0);            /* Parent */
        case -1:
            fprintf(stderr,"Forking Error\n");
            exit(1);
    }
    setpgrp();
    if((fd=open("/dev/tty",O_RDWR))>=0){
        ioctl(fd,TIOCNOTTY,(char *)NULL);
        close(fd);
    }
    errno=0;
    chdir("/");
    umask(0);
    return(pid);
}


/*
 *  Keeps processes from zombiing on us...
 */
        
static void reaper(signo)
int signo;
{
    pid_t pid;
    int sys;

    pid=wait(&sys); 
    signal(SIGCHLD,reaper);
    return;
}


/*
 *  Dump usage and exit.
 */

void usage(nomenclature)
char *nomenclature;
{
    fprintf(stderr,"\n\nUsage:\t%s [-h] [-s TOKEN [-e xx] ] [-v] [-t xx]\n\n
    -h terse help
    -H expanded help for those 'specially challanged' people...
    -s dedicated sniffing (bloodhound) mode, in which TOKEN is found enticing
    -e enticement factor (defaults to 16)
    -v decrease verbosity (don't do this)
    -V version information
    -t xx network read timeout in seconds (defaults to 10)
    Invoked without arguments, Juggernaut starts in `normal` mode.\n\n",nomenclature);
    exit(0);
}


/*
 *  Simple file pager.
 */

void bookworm(){

    FILE *fp;
    char tempBuf[FBUFSIZE],buf[MINIBUF];
    int i=0;

    if(!(fp=fopen(HELPFILE,"r"))){
        if(verbosity){
            fprintf(stderr,"Cannot open help file.\n");
            fprintf(stderr,"[cr]");
            getchar();
            return;
        }
    }
    while(fgets(tempBuf,FBUFSIZE-1,fp)){
        fprintf(stderr,tempBuf);
        if(i==24){
            fprintf(stderr,"\n[cr,q] >");
            bzero(&buf,sizeof(buf));
            fgets(buf,sizeof(buf-1),stdin);
            if(buf[0]=='q')break;
            i=0;
        }
        else i++;
    }
}


/*
 *  Main signal handler to facilitate clean exits.
 */

void twitch(){

    void cleanexit();

    if(verbosity)fprintf(stderr,"\nCaught signal, exiting cleanly.\n");
    signal(SIGINT,SIG_DFL);
    signal(SIGQUIT,SIG_DFL);
    cleanexit();
}


/*
 *  Used as a catchall to cleanly exit proccesses
 */

void spasm(){

    extern int linksock;

    if(linksock)close(linksock);        /* Hunter should have this... */
    exit(0);
}


/*
 *  Spy signal handler.
 */ 
                    
void convulsion(){

    void twitch();
    
    extern int sigsentry;

    if(verbosity)fprintf(stderr,"\nCaught signal.\n");
    fprintf(stderr,"[cr]");
    getchar();
    signal(SIGINT,twitch);
    sigsentry=0;
}


/*
 *  Pre-hijacking signal handler.
 */

void sputter(){

    void twitch();

    extern int sigsentry;

    if(verbosity)fprintf(stderr,"\nCaught prehijack signal.\n");
    signal(SIGINT,twitch);
    sigsentry=0;
}      


/*
 *  Post-hijacking signal handler.
 */

void seizure(){

    void twitch();

    extern int sigsentry;

    if(verbosity)fprintf(stderr,"\nCaught posthijack signal.\n");
    sigsentry=0;
    signal(SIGINT,twitch);
}      

/*
 *  Exit Cleanly.
 */

void cleanexit(){

    void powerdown();
    int tap(char *,int);

    extern int ripsock;
    extern int hpid;
    extern int acrstpid;

    close(ripsock);
    powerdown();
    tap(DEVICE,0);                          /* Unset promisc mode on the interface */
    if(kill(hpid,SIGUSR1))if(verbosity){    /* Send signal to the hunter */
        perror("(cleanexit) Could not signal hunter");
        fprintf(stderr,"[cr]");
        getchar();
    }
    if(acrstpid)    /* Send signal to the automated connection reset daemon. 
                       XXX - This only signals one daemon!  If more exist, 
                       they will be left stranded! */
        if(kill(acrstpid,SIGUSR1))if(verbosity){ 
        perror("(cleanexit) Could not signal ACRSTD"); 
        fprintf(stderr,"[cr]");    
        getchar();                     
        }                                  
    fprintf(stderr,"Juggernaut is a Guild Corporation production, (c) 1996/7.\n\n");
    exit(0);
}
  
