static int run_pig_run(const char *signatures, const char *targets, const char *timeout, const char *single_test, const char *gw_addr, const char *nt_mask, const char *loiface) { int timeo = 10000; pigsty_entry_ctx *pigsty = NULL; size_t signatures_count = 0, addr_count = 0; pigsty_entry_ctx *signature = NULL, *sp = NULL; pig_target_addr_ctx *addr = NULL, *addr_p = NULL; pig_hwaddr_ctx *hwaddr = NULL; int sockfd = -1; int retval = 0; unsigned int nt_mask_addr[4] = { 0, 0, 0, 0 }; unsigned char *gw_hwaddr = NULL, *temp = NULL; in_addr_t gw_in_addr = 0; if (timeout != NULL) { timeo = atoi(timeout); } timeo = timeo * 1000; if (!should_be_quiet) { printf("pig INFO: starting up pig engine...\n\n"); } sockfd = init_raw_socket(loiface); if (sockfd == -1) { printf("pig PANIC: unable to create the socket.\npig ERROR: aborted.\n"); return 1; } pigsty = load_signatures(signatures); if (pigsty == NULL) { printf("pig ERROR: aborted.\n"); deinit_raw_socket(sockfd); return 1; } if (targets != NULL) { if (!should_be_quiet) { printf("\npig INFO: parsing the supplied targets...\n"); printf("pig INFO: all targets were parsed.\n"); } addr = parse_targets(targets); } if (is_targets_option_required(pigsty) && addr == NULL) { printf("pig PANIC: --targets option is required by some loaded signatures.\n"); deinit_raw_socket(sockfd); del_pigsty_entry(pigsty); return 1; } signatures_count = get_pigsty_entry_count(pigsty); if (!should_be_quiet) { printf("\npig INFO: done (%d signature(s) read).\n\n", signatures_count); } if (nt_mask == NULL) { printf("\npig PANIC: --net-mask option is required.\n"); deinit_raw_socket(sockfd); del_pigsty_entry(pigsty); return 1; } // WARN(Santiago): by now IPv4 only. if (verify_ipv4_addr(nt_mask) == 0) { printf("pig PANIC: --net-mask has an invalid ip address.\n"); deinit_raw_socket(sockfd); del_pigsty_entry(pigsty); return 1; } nt_mask_addr[0] = htonl(inet_addr(nt_mask)); if (gw_addr != NULL && loiface != NULL) { gw_in_addr = inet_addr(gw_addr); temp = get_mac_by_addr(gw_in_addr, loiface, 2); if (!should_be_quiet && temp != NULL) { gw_hwaddr = mac2byte(temp, strlen(temp)); printf("pig INFO: the gateway's physical address is \"%s\"...\n" "pig INFO: the local interface is \"%s\"...\n" "pig INFO: the network mask is \"%s\"...\n\n", temp, loiface, nt_mask); free(temp); } } if (gw_hwaddr != NULL) { signature = get_pigsty_entry_by_index(rand() % signatures_count, pigsty); if (single_test == NULL) { while (!should_exit) { if (signature == NULL) { continue; // WARN(Santiago): It should never happen. However... Sometimes... The World tends to be a rather weird place. } if (oink(signature, &hwaddr, addr, sockfd, gw_hwaddr, nt_mask_addr, loiface) != -1) { if (!should_be_quiet) { printf("pig INFO: a packet based on signature \"%s\" was sent.\n", signature->signature_name); } usleep(timeo); } signature = get_pigsty_entry_by_index(rand() % signatures_count, pigsty); } } else { retval = (oink(signature, &hwaddr, addr, sockfd, gw_hwaddr, nt_mask_addr, loiface) != -1 ? 0 : 1); if (retval == 0) { if (!should_be_quiet) { printf("pig INFO: a packet based on signature \"%s\" was sent.\n", signature->signature_name); } } } free(gw_hwaddr); } else { printf("\npig PANIC: unable to get the gateway's physical address.\n"); } del_pigsty_entry(pigsty); del_pig_target_addr(addr); del_pig_hwaddr(hwaddr); deinit_raw_socket(sockfd); return retval; }
int main(int argc, char** argv) { s32 opt; u32 loop_cnt = 0, purge_age = 0, seed; u8 sig_loaded = 0, show_once = 0, no_statistics = 0, display_mode = 0, has_fake = 0; s32 oindex = 0; u8 *wordlist = NULL, *output_dir = NULL; u8 *sig_list_strg = NULL; u8 *gtimeout_str = NULL; u32 gtimeout = 0; struct termios term; struct timeval tv; u64 st_time, en_time; signal(SIGINT, ctrlc_handler); signal(SIGWINCH, resize_handler); signal(SIGPIPE, SIG_IGN); SSL_library_init(); /* Options, options, and options */ static struct option long_options[] = { {"auth", required_argument, 0, 'A' }, {"host", required_argument, 0, 'F' }, {"cookie", required_argument, 0, 'C' }, {"reject-cookies", required_argument, 0, 'N' }, {"header", required_argument, 0, 'H' }, {"user-agent", required_argument, 0, 'b' }, #ifdef PROXY_SUPPORT {"proxy", required_argument, 0, 'J' }, #endif /* PROXY_SUPPORT */ {"max-depth", required_argument, 0, 'd' }, {"max-child", required_argument, 0, 'c' }, {"max-descendants", required_argument, 0, 'x' }, {"max-requests", required_argument, 0, 'r' }, {"max-rate", required_argument, 0, 'l'}, {"probability", required_argument, 0, 'p' }, {"seed", required_argument, 0, 'q' }, {"include", required_argument, 0, 'I' }, {"exclude", required_argument, 0, 'X' }, {"skip-param", required_argument, 0, 'K' }, {"skip-forms", no_argument, 0, 'O' }, {"include-domain", required_argument, 0, 'D' }, {"ignore-links", no_argument, 0, 'P' }, {"no-ext-fuzzing", no_argument, 0, 'Y' }, {"log-mixed-content", no_argument, 0, 'M' }, {"skip-error-pages", no_argument, 0, 'Z' }, {"log-external-urls", no_argument, 0, 'U' }, {"log-cache-mismatches", no_argument, 0, 'E' }, {"form-value", no_argument, 0, 'T' }, {"rw-wordlist", required_argument, 0, 'W' }, {"no-keyword-learning", no_argument, 0, 'L' }, {"mode", required_argument, 0, 'J' }, {"wordlist", required_argument, 0, 'S'}, {"trust-domain", required_argument, 0, 'B' }, {"max-connections", required_argument, 0, 'g' }, {"max-host-connections", required_argument, 0, 'm' }, {"max-fail", required_argument, 0, 'f' }, {"request-timeout", required_argument, 0, 't' }, {"network-timeout", required_argument, 0, 'w' }, {"idle-timeout", required_argument, 0, 'i' }, {"response-size", required_argument, 0, 's' }, {"discard-binary", required_argument, 0, 'e' }, {"output", required_argument, 0, 'o' }, {"help", no_argument, 0, 'h' }, {"quiet", no_argument, 0, 'u' }, {"verbose", no_argument, 0, 'v' }, {"scan-timeout", required_argument, 0, 'k'}, {"signatures", required_argument, 0, 'z'}, {"checks", no_argument, 0, 0}, {"checks-toggle", required_argument, 0, 0}, {"no-checks", no_argument, 0, 0}, {"fast", no_argument, 0, 0}, {"auth-form", required_argument, 0, 0}, {"auth-form-target", required_argument, 0, 0}, {"auth-user", required_argument, 0, 0}, {"auth-user-field", required_argument, 0, 0}, {"auth-pass", required_argument, 0, 0}, {"auth-pass-field", required_argument, 0, 0}, {"auth-verify-url", required_argument, 0, 0}, {0, 0, 0, 0 } }; /* Come up with a quasi-decent random seed. */ gettimeofday(&tv, NULL); seed = tv.tv_usec ^ (tv.tv_sec << 16) ^ getpid(); SAY("skipfish version " VERSION " by <*****@*****.**>\n"); while ((opt = getopt_long(argc, argv, "+A:B:C:D:EF:G:H:I:J:K:LMNOPQR:S:T:UW:X:YZ" "b:c:d:ef:g:hi:k:l:m:o:p:q:r:s:t:uvw:x:z:", long_options, &oindex)) >= 0) switch (opt) { case 'A': { u8* x = (u8*)strchr(optarg, ':'); if (!x) FATAL("Credentials must be in 'user:pass' form."); *(x++) = 0; auth_user = (u8*)optarg; auth_pass = x; auth_type = AUTH_BASIC; break; } #ifdef PROXY_SUPPORT case 'J': { u8* x = (u8*)strchr(optarg, ':'); if (!x) FATAL("Proxy data must be in 'host:port' form."); *(x++) = 0; use_proxy = (u8*)optarg; use_proxy_port = atoi((char*)x); if (!use_proxy_port) FATAL("Incorrect proxy port number."); break; } #endif /* PROXY_SUPPORT */ case 'F': { u8* x = (u8*)strchr(optarg, '='); u32 fake_addr; if (!x) FATAL("Fake mappings must be in 'host=IP' form."); *x = 0; fake_addr = inet_addr((char*)x + 1); if (fake_addr == (u32)-1) FATAL("Could not parse IP address '%s'.", x + 1); fake_host((u8*)optarg, fake_addr); has_fake = 1; break; } case 'H': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Extra headers must be in 'name=value' form."); *x = 0; if (!strcasecmp(optarg, "Cookie")) FATAL("Do not use -H to set cookies (try -C instead)."); SET_HDR((u8*)optarg, x + 1, &global_http_par); break; } case 'C': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Cookies must be in 'name=value' form."); if (strchr(optarg, ';')) FATAL("Split multiple cookies into separate -C options."); *x = 0; SET_CK((u8*)optarg, x + 1, &global_http_par); break; } case 'D': if (*optarg == '*') optarg++; APPEND_FILTER(allow_domains, num_allow_domains, optarg); break; case 'K': APPEND_FILTER(skip_params, num_skip_params, optarg); break; case 'B': if (*optarg == '*') optarg++; APPEND_FILTER(trust_domains, num_trust_domains, optarg); break; case 'I': if (*optarg == '*') optarg++; APPEND_FILTER(allow_urls, num_allow_urls, optarg); break; case 'X': if (*optarg == '*') optarg++; APPEND_FILTER(deny_urls, num_deny_urls, optarg); break; case 'T': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Rules must be in 'name=value' form."); *x = 0; add_form_hint((u8*)optarg, x + 1); break; } case 'N': ignore_cookies = 1; break; case 'Y': no_fuzz_ext = 1; break; case 'q': if (sscanf(optarg, "0x%08x", &seed) != 1) FATAL("Invalid seed format."); srandom(seed); break; case 'Q': suppress_dupes = 1; break; case 'P': no_parse = 1; break; case 'M': warn_mixed = 1; break; case 'U': log_ext_urls = 1; break; case 'L': dont_add_words = 1; break; case 'E': pedantic_cache = 1; break; case 'O': no_forms = 1; break; case 'R': purge_age = atoi(optarg); if (purge_age < 3) FATAL("Purge age invalid or too low (min 3)."); break; case 'd': max_depth = atoi(optarg); if (max_depth < 2) FATAL("Invalid value '%s'.", optarg); break; case 'c': max_children = atoi(optarg); if (!max_children) FATAL("Invalid value '%s'.", optarg); break; case 'x': max_descendants = atoi(optarg); if (!max_descendants) FATAL("Invalid value '%s'.", optarg); break; case 'p': crawl_prob = atoi(optarg); if (!crawl_prob) FATAL("Invalid value '%s'.", optarg); break; case 'W': if (wordlist) FATAL("Only one -W parameter permitted (use -S to load supplemental dictionaries)."); if (!strcmp(optarg, "-")) wordlist = (u8*)"/dev/null"; else wordlist = (u8*)optarg; break; case 'S': load_keywords((u8*)optarg, 1, 0); break; case 'z': load_signatures((u8*)optarg); sig_loaded = 1; break; case 'b': if (optarg[0] == 'i') browser_type = BROWSER_MSIE; else if (optarg[0] == 'f') browser_type = BROWSER_FFOX; else if (optarg[0] == 'p') browser_type = BROWSER_PHONE; else usage(argv[0]); break; case 'g': max_connections = atoi(optarg); if (!max_connections) FATAL("Invalid value '%s'.", optarg); break; case 'm': max_conn_host = atoi(optarg); if (!max_conn_host) FATAL("Invalid value '%s'.", optarg); break; case 'G': max_guesses = atoi(optarg); if (!max_guesses) FATAL("Invalid value '%s'.", optarg); break; case 'r': max_requests = atoi(optarg); if (!max_requests) FATAL("Invalid value '%s'.", optarg); break; case 'l': max_requests_sec = atof(optarg); if (!max_requests_sec) FATAL("Invalid value '%s'.", optarg); break; case 'f': max_fail = atoi(optarg); if (!max_fail) FATAL("Invalid value '%s'.", optarg); break; case 't': resp_tmout = atoi(optarg); if (!resp_tmout) FATAL("Invalid value '%s'.", optarg); break; case 'w': rw_tmout = atoi(optarg); if (!rw_tmout) FATAL("Invalid value '%s'.", optarg); break; case 'i': idle_tmout = atoi(optarg); if (!idle_tmout) FATAL("Invalid value '%s'.", optarg); break; case 's': size_limit = atoi(optarg); if (!size_limit) FATAL("Invalid value '%s'.", optarg); break; case 'o': if (output_dir) FATAL("Multiple -o options not allowed."); output_dir = (u8*)optarg; rmdir(optarg); if (mkdir(optarg, 0755)) PFATAL("Unable to create '%s'.", output_dir); break; case 'u': no_statistics = 1; break; case 'v': verbosity++; break; case 'e': delete_bin = 1; break; case 'k': if (gtimeout_str) FATAL("Multiple -k options not allowed."); gtimeout_str = (u8*)optarg; break; case 'Z': no_500_dir = 1; break; case 0: if (!strcmp("checks", long_options[oindex].name )) display_injection_checks(); if (!strcmp("checks-toggle", long_options[oindex].name )) toggle_injection_checks((u8*)optarg, 1, 1); if (!strcmp("no-checks", long_options[oindex].name )) no_checks = 1; if (!strcmp("signatures", long_options[oindex].name )) load_signatures((u8*)optarg); if(!strcmp("fast", long_options[oindex].name )) toggle_injection_checks((u8*)"2,4,5,13,14,15,16", 0, 0); if (!strcmp("auth-form", long_options[oindex].name )) auth_form = (u8*)optarg; if (!strcmp("auth-user", long_options[oindex].name )) auth_user = (u8*)optarg; if (!strcmp("auth-pass", long_options[oindex].name )) auth_pass = (u8*)optarg; if (!strcmp("auth-pass-field", long_options[oindex].name )) auth_pass_field = (u8*)optarg; if (!strcmp("auth-user-field", long_options[oindex].name )) auth_user_field = (u8*)optarg; if (!strcmp("auth-form-target", long_options[oindex].name )) auth_form_target = (u8*)optarg; if (!strcmp("auth-verify-url", long_options[oindex].name )) auth_verify_url = (u8*)optarg; break; default: usage(argv[0]); } #ifdef PROXY_SUPPORT if (has_fake && use_proxy) FATAL("-F and -J should not be used together."); #endif /* PROXY_SUPPORT */ if (access(ASSETS_DIR "/index.html", R_OK)) PFATAL("Unable to access '%s/index.html' - wrong directory?", ASSETS_DIR); srandom(seed); if (optind == argc) FATAL("Scan target not specified (try -h for help)."); if (!output_dir) FATAL("Output directory not specified (try -h for help)."); if(verbosity && !no_statistics && isatty(2)) FATAL("Please use -v in combination with the -u flag or, " "run skipfish while redirecting stderr to a file. "); if (resp_tmout < rw_tmout) resp_tmout = rw_tmout; if (max_connections < max_conn_host) max_connections = max_conn_host; /* Parse the timeout string - format h:m:s */ if (gtimeout_str) { int i = 0; int m[3] = { 1, 60, 3600 }; u8* tok = (u8*)strtok((char*)gtimeout_str, ":"); while(tok && i <= 2) { gtimeout += atoi((char*)tok) * m[i]; tok = (u8*)strtok(NULL, ":"); i++; } if(!gtimeout) FATAL("Wrong timeout format, please use h:m:s (hours, minutes, seconds)"); DEBUG("* Scan timeout is set to %d seconds\n", gtimeout); } if (!wordlist) { wordlist = (u8*)"/dev/null"; DEBUG("* No wordlist specified with -W: defaulting to /dev/null\n"); } /* If no signature files have been specified via command-line: load the default file */ if (!sig_loaded) load_signatures((u8*)SIG_FILE); load_keywords(wordlist, 0, purge_age); /* Load the signatures list for the matching */ if (sig_list_strg) load_signatures(sig_list_strg); /* Try to authenticate when the auth_user and auth_pass fields are set. */ if (auth_user && auth_pass) { authenticate(); while (next_from_queue()) { usleep(1000); } switch (auth_state) { case ASTATE_DONE: DEBUGC(L1, "*- Authentication succeeded!\n"); break; default: DEBUG("Auth state: %d\n", auth_state); FATAL("Authentication failed (use -uv for more info)\n"); break; } } /* Schedule all URLs in the command line for scanning. */ while (optind < argc) { struct http_request *req; /* Support @ notation for reading URL lists from files. */ if (argv[optind][0] == '@') { read_urls((u8*)argv[optind++] + 1); continue; } req = ck_alloc(sizeof(struct http_request)); if (parse_url((u8*)argv[optind], req, NULL)) FATAL("Scan target '%s' is not a valid absolute URL.", argv[optind]); if (!url_allowed_host(req)) APPEND_FILTER(allow_domains, num_allow_domains, __DFL_ck_strdup(req->host)); if (!url_allowed(req)) FATAL("URL '%s' explicitly excluded by -I / -X rules.", argv[optind]); maybe_add_pivot(req, NULL, 2); destroy_request(req); optind++; } /* Char-by char stdin. */ tcgetattr(0, &term); term.c_lflag &= ~ICANON; tcsetattr(0, TCSANOW, &term); fcntl(0, F_SETFL, O_NONBLOCK); gettimeofday(&tv, NULL); st_time = tv.tv_sec * 1000LL + tv.tv_usec / 1000; #ifdef SHOW_SPLASH if (!no_statistics) splash_screen(); #endif /* SHOW_SPLASH */ if (!no_statistics) SAY("\x1b[H\x1b[J"); else SAY(cLGN "[*] " cBRI "Scan in progress, please stay tuned...\n"); u64 refresh_time = 0; /* Enter the crawler loop */ while ((next_from_queue() && !stop_soon) || (!show_once++)) { u8 keybuf[8]; u64 end_time; u64 run_time; struct timeval tv_tmp; gettimeofday(&tv_tmp, NULL); end_time = tv_tmp.tv_sec * 1000LL + tv_tmp.tv_usec / 1000; run_time = end_time - st_time; if (gtimeout > 0 && run_time && run_time/1000 > gtimeout) { DEBUG("* Stopping scan due to timeout\n"); stop_soon = 1; } req_sec = (req_count - queue_cur / 1.15) * 1000 / (run_time + 1); if (no_statistics || ((loop_cnt++ % 100) && !show_once && idle == 0)) continue; if (end_time > refresh_time) { refresh_time = (end_time + 10); if (clear_screen) { SAY("\x1b[H\x1b[2J"); clear_screen = 0; } SAY(cYEL "\x1b[H" "skipfish version " VERSION " by [email protected]\n\n" cBRI " -" cPIN " %s " cBRI "-\n\n" cNOR, allow_domains[0]); if (!display_mode) { http_stats(st_time); SAY("\n"); database_stats(); } else { http_req_list(); } SAY(" \r"); } if (fread(keybuf, 1, sizeof(keybuf), stdin) > 0) { display_mode ^= 1; clear_screen = 1; } } gettimeofday(&tv, NULL); en_time = tv.tv_sec * 1000LL + tv.tv_usec / 1000; SAY("\n"); if (stop_soon) SAY(cYEL "[!] " cBRI "Scan aborted by user, bailing out!" cNOR "\n"); term.c_lflag |= ICANON; tcsetattr(0, TCSANOW, &term); fcntl(0, F_SETFL, O_SYNC); save_keywords((u8*)wordlist); write_report(output_dir, en_time - st_time, seed); #ifdef LOG_STDERR SAY("\n== PIVOT DEBUG ==\n"); dump_pivots(0, 0); SAY("\n== END OF DUMP ==\n\n"); #endif /* LOG_STDERR */ SAY(cLGN "[+] " cBRI "This was a great day for science!" cRST "\n\n"); #ifdef DEBUG_ALLOCATOR if (!stop_soon) { destroy_database(); destroy_signature_lists(); destroy_http(); destroy_signatures(); __TRK_report(); } #endif /* DEBUG_ALLOCATOR */ fflush(0); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); return 0; }
int main(int argc, char **argv) { int arg,ret; char *configfile; char pcapfile[256]; // Load default config init_config(); // Set the signal handlers signal(SIGHUP, sighup_handler); signal(SIGINT, sigquit_handler); signal(SIGQUIT,sigquit_handler); // Parse command-line options while ((arg = getopt(argc, argv, "IP:i:c:f:DqvdTsr:l:u:S:")) != -1){ switch (arg){ case 'f': strncpy(CONFIG_PCAP_FILTER,optarg,CONFIG_MAX_CHAR); break; case 'r': strncpy(pcapfile,optarg,256); mode_offline=1; break; case 'c': configfile = optarg; read_config(configfile); //dump_config(); break; case 'i': // Start the pcap thread strncpy(CONFIG_PCAP_DEV,optarg,CONFIG_MAX_CHAR); break; case 'P': CONFIG_DIVERT_PORT=atoi(optarg); break; case 'I': CONFIG_DIVERT_ENABLE=1; break; case 'q': CONFIG_LOG_STDOUT = 0; break; case 'u': strncpy(CONFIG_USER,optarg,CONFIG_MAX_CHAR); break; case 'l': strncpy(CONFIG_LOGDIR,optarg,CONFIG_MAX_CHAR); if(strlen(CONFIG_LOGDIR) > 64) { fatal_error("Log directory is too long!"); } if (access(CONFIG_LOGDIR, F_OK) == -1){ fatal_error("Log directory does not exist"); } break; case 's': CONFIG_LOG_SYSLOG = 1; break; case 'S': strncpy(CONFIG_SIGFILE,optarg,CONFIG_MAX_CHAR); break; case 'T': CONFIG_TCP_STRICT = 0; break; case 'v': CONFIG_LOG_VERBOSE++; break; case 'd': CONFIG_SHOW_TRAFFIC = 1; break; case 'D': fork_to_background(); break; default: usage(); exit(1); break; } } // Initialize the stats structure and the streams stats_init(); // Create the list, this is to store the IP packets in which can then // be read by another thread. TODO: add maximum list size trafficlist = getRingBuffer(CONFIG_RINGBUFFER_SIZE); // Register the destructor registerListDestructor(destructor_callback,trafficlist); registerListIterator(traffic_analyzer,trafficlist); // Create the control thread first for message logging pthread_create(&t_control,NULL,(void*)control_loop,NULL); //Initialize the detection hooks detect_hook_init(); tcp_stream_init(); //Initialize the timers timer_init(); timer_register_function(CONFIG_TIMER_STATS,"Stats printer",stats_show_cnt_line,NULL); timer_register_function(CONFIG_TIMER_TCP_CLEANER,"TCP session cleaner", tcp_clean_sessions,NULL); timer_register_function(CONFIG_TIMER_IPFRAG_CLEANER,"IP fragment cleaner", ip_frag_cleaner,NULL); //Load the signatures if(load_signatures(CONFIG_SIGFILE) == 1){ usage(); exit(1); } // Make signature index; init_signature_indexes(); log_info("Signatures loaded: %d, not loaded: %d", stat_get(CNT_SIG_LOADED), stat_get(CNT_SIG_NOT_LOADED)); // Check if root privileges are required if(mode_offline == 0 && getuid() != 0) { fprintf(stderr, "Root privileges are required, unless you specify a\n"); fprintf(stderr, "pcap file with the '-r' option..\n"); exit(1); } if(CONFIG_DIVERT_ENABLE) { log_info("Opening DIVERT socket port: %d\n",CONFIG_DIVERT_PORT); divert_open_socket(CONFIG_DIVERT_PORT); // Start the divert_listen loop pthread_create(&t_listener,NULL,(void*)divert_listen_loop,handle); } else if(mode_offline != 1) { // If no device was specified AND not configured then the only // option is to pick one using the cap library (not recommended) if(*CONFIG_PCAP_DEV == '0') { if(pcap_return_device() != NULL) { log_info("Picking random interface (overrule -i)"); strncpy(CONFIG_PCAP_DEV,pcap_return_device(),CONFIG_MAX_CHAR); } else { usage(); exit(1); } } // Start the sniffer thread handle = pcap_open_device(CONFIG_PCAP_DEV,CONFIG_PCAP_FILTER); pthread_create(&t_listener,NULL,(void*)pcap_listen_loop,handle); } else { // Open the file handle = pcap_open_file(pcapfile,CONFIG_PCAP_FILTER); pthread_create(&t_listener,NULL,(void*)pcap_listen_loop,handle); } // Chroot if needed if(CONFIG_CHROOT_ENABLE == 1) { if((ret = chroot(CONFIG_CHROOT_DIR)) != 0) { fatal_error("Chroot to \"%s\" failed: %s !",CONFIG_CHROOT_DIR, strerror(errno)); } else { log_info("Chroot to directory: \"%s\" done",CONFIG_CHROOT_DIR); } } // Drop privileges if needed if(*CONFIG_USER != '0' && drop_privileges(CONFIG_USER) != 0) { fatal_error("Unable to drop privileges, quitting for security reasons",CONFIG_USER); } // Set the time gettimeofday(&startuptime,NULL); pthread_create(&t_analyzer,NULL,(void*)pcap_analyzer,NULL); if(mode_offline == 1) { pthread_join(t_analyzer, NULL); } else { pthread_join(t_listener,NULL); } // Control thread loop_control = 0; pthread_join(t_control, NULL); // And bail out dump_stats(stdout); return 0; }