/* Validate options */ int checkConfigOptions(const struct config_options *o) { int minThreshold; /* Check if we have root priviledges. */ if ( getuid() != 0 ) { ERROR("you must have root privilege"); return 0; } /* Warning missed target. */ if (o->ip.daddr == INADDR_ANY) { ERROR("Need target address. Try --help for usage"); return 0; } /* Sanitizing the CIDR. */ if ((o->bits != 0) && ((o->bits < CIDR_MINIMUM) || (o->bits > CIDR_MAXIMUM))) { /* NOTE: Arbitrary array size... 48 is qword aligned on stack, i suppose! */ char errstr[48]; sprintf(errstr, "CIDR must be beewten %d and %d", CIDR_MINIMUM, CIDR_MAXIMUM); ERROR(errstr); return 0; } /* Sanitizing the TCP Options SACK_Permitted and SACK Edges. */ if (TEST_BITS(o->tcp.options, TCP_OPTION_SACK_OK) && TEST_BITS(o->tcp.options, TCP_OPTION_SACK_EDGE)) { ERROR("TCP options SACK-Permitted and SACK Edges are not allowed"); return 0; } /* Sanitizing the TCP Options T/TCP CC and T/TCP CC.ECHO. */ if (TEST_BITS(o->tcp.options, TCP_OPTION_CC) && (o->tcp.cc_echo)) { ERROR("TCP options T/TCP CC and T/TCP CC.ECHO are not allowed"); return 0; } if (!o->flood) { #ifdef __HAVE_TURBO__ /* Sanitizing TURBO mode. */ if (o->turbo) { ERROR("turbo mode is only available in flood mode"); return 0; } #endif /* __HAVE_TURBO__ */ /* Sanitizing the threshold. */ minThreshold = getNumberOfRegisteredModules(); if ((o->ip.protocol == IPPROTO_T50) && (o->threshold < (unsigned)minThreshold)) { fprintf(stderr, "%s: protocol %s cannot have threshold smaller than %d\n", PACKAGE, mod_table[o->ip.protoname].acronym, minThreshold); return 0; } } else /* if (o->flood) isn't 0 */ { /* Warning FLOOD mode. */ puts("entering in flood mode..."); #ifdef __HAVE_TURBO__ if (o->turbo) puts("activating turbo..."); #endif /* __HAVE_TURBO__ */ /* Warning CIDR mode. */ if (o->bits != 0) puts("performing DDoS..."); puts("hit CTRL+C to break."); } /* Returning. */ return 1; }
/* Main function launches all T50 modules */ int main(int argc, char *argv[]) { struct config_options *co; /* Pointer to options. */ struct cidr *cidr_ptr; /* Pointer to cidr host id and 1st ip address. */ modules_table_t *ptbl; /* Pointer to modules table */ uint8_t proto; /* Used on main loop. */ initialize(); /* Configuring command line interface options. */ co = getConfigOptions(argc, argv); /* This is a requirement of t50. User must be root to use it. Previously on checkConfigOptions(). */ if (getuid()) { ERROR("User must have root priviledge to run."); return EXIT_FAILURE; } /* Validating command line interface options. */ if (!checkConfigOptions(co)) return EXIT_FAILURE; /* Setting socket file descriptor. */ /* NOTE: createSocket() handles its own errors before returning. */ createSocket(); /* Setup random seed using current date/time timestamp. */ /* NOTE: Random seed don't need to be so precise! */ srandom(time(NULL)); #ifdef __HAVE_TURBO__ /* Entering in TURBO. */ if (co->turbo) { /* Decides if it's necessary to fork a new process. */ if ((co->ip.protocol == IPPROTO_T50 && co->threshold > (threshold_t)getNumberOfRegisteredModules()) || (co->ip.protocol != IPPROTO_T50 && co->threshold > 1)) { threshold_t new_threshold; if ((pid = fork()) == -1) { perror("Error creating child process. Exiting..."); return EXIT_FAILURE; } /* Setting the priority to both parent and child process to highly favorable scheduling value. */ /* FIXME: Why not setup this value when t50 runs as a single process? */ if (setpriority(PRIO_PROCESS, PRIO_PROCESS, -15) == -1) { perror("Error setting process priority. Exiting..."); return EXIT_FAILURE; } /* Divide the process iterations in main loop between processes. */ new_threshold = co->threshold / 2; /* FIX: Ooops! Parent process get the extra packet, if given threshold is odd. */ if ((co->threshold % 2) && !IS_CHILD_PID(pid)) new_threshold++; co->threshold = new_threshold; } } #endif /* __HAVE_TURBO__ */ /* Calculates CIDR for destination address. */ cidr_ptr = config_cidr(co->bits, co->ip.daddr); /* Show launch info only for parent process. */ if (!IS_CHILD_PID(pid)) { time_t lt; struct tm *tm; /* Getting the local time. */ lt = time(NULL); tm = localtime(<); printf("\b\n%s %s successfully launched at %s %2d%s %d %.02d:%.02d:%.02d\n", PACKAGE, VERSION, getMonth(tm->tm_mon), tm->tm_mday, getOrdinalSuffix(tm->tm_mday), (tm->tm_year + 1900), tm->tm_hour, tm->tm_min, tm->tm_sec); } /* Selects the initial protocol to use. */ proto = co->ip.protocol; ptbl = mod_table; if (proto != IPPROTO_T50) ptbl += co->ip.protoname; co->ip.daddr = htonl(cidr_ptr->__1st_addr); /* Preallocate packet buffer. */ alloc_packet(INITIAL_PACKET_SIZE); /* Execute if flood or while threshold greater than 0. */ while (co->flood || (co->threshold-- > 0)) { /* Holds the actual packet size after module function call. */ size_t size; /* Set the destination IP address to RANDOM IP address. */ if (cidr_ptr->hostid) co->ip.daddr = htonl(cidr_ptr->__1st_addr + (random() % cidr_ptr->hostid)); /* Calls the 'module' function and sends the packet. */ co->ip.protocol = ptbl->protocol_id; ptbl->func(co, &size); sendPacket(packet, size, co); /* If protocol if 'T50', then get the next true protocol. */ if (proto == IPPROTO_T50) if ((++ptbl)->func == NULL) ptbl = mod_table; } /* Show termination message only for parent process. */ if (!IS_CHILD_PID(pid)) { time_t lt; struct tm *tm; /* FIX: We need to wait() for child processes only if we forked one! */ #ifdef __HAVE_TURBO__ int status; /* Wait 5 seconds for child process, then ungracefully closes the program. */ alarm(5); wait(&status); #endif /* FIX: To graciously end the program, only the parent process can close the socket. NOTE: I realize that closing descriptors are reference counted. Kept the logic just in case! */ closeSocket(); /* Getting the local time. */ lt = time(NULL); tm = localtime(<); printf("\b\n%s %s successfully finished at %s %2d%s %d %.02d:%.02d:%.02d\n", PACKAGE, VERSION, getMonth(tm->tm_mon), tm->tm_mday, getOrdinalSuffix(tm->tm_mday), (tm->tm_year + 1900), tm->tm_hour, tm->tm_min, tm->tm_sec); } return 0; }