Пример #1
0
Файл: main.c Проект: huap/pig
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;
}
Пример #2
0
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;

}
Пример #3
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;
}