Beispiel #1
0
void RunUnittests(int list_unittests, char *regex_arg)
{
#ifdef UNITTESTS
    /* Initializations for global vars, queues, etc (memsets, mutex init..) */
    GlobalInits();
    TimeInit();
    SupportFastPatternForSigMatchTypes();

    default_packet_size = DEFAULT_PACKET_SIZE;
#ifdef __SC_CUDA_SUPPORT__
    /* Init the CUDA environment */
    SCCudaInitCudaEnvironment();
    CudaBufferInit();
#endif
    /* load the pattern matchers */
    MpmTableSetup();
#ifdef __SC_CUDA_SUPPORT__
    MpmCudaEnvironmentSetup();
#endif
    SpmTableSetup();

    AppLayerSetup();

    /* hardcoded initialization code */
    SigTableSetup(); /* load the rule keywords */
    TmqhSetup();

    StorageInit();
    CIDRInit();
    SigParsePrepare();

#ifdef DBG_MEM_ALLOC
    SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem);
#endif
    SCReputationInitCtx();
    SCProtoNameInit();

    TagInitCtx();
    SCReferenceConfInit();
    SCClassConfInit();

    UtInitialize();

    RegisterAllModules();

    HostBitInitCtx();

    StorageFinalize();
   /* test and initialize the unittesting subsystem */
    if(regex_arg == NULL){
        regex_arg = ".*";
        UtRunSelftest(regex_arg); /* inits and cleans up again */
    }

    AppLayerHtpEnableRequestBodyCallback();
    AppLayerHtpNeedFileInspection();

    UTHRegisterTests();
    StreamTcpRegisterTests();
    SigRegisterTests();
    SCReputationRegisterTests();
    TmModuleRegisterTests();
    SigTableRegisterTests();
    HashTableRegisterTests();
    HashListTableRegisterTests();
    BloomFilterRegisterTests();
    BloomFilterCountingRegisterTests();
    PoolRegisterTests();
    ByteRegisterTests();
    MpmRegisterTests();
    FlowBitRegisterTests();
    HostBitRegisterTests();
    IPPairBitRegisterTests();
    StatsRegisterTests();
    DecodePPPRegisterTests();
    DecodeVLANRegisterTests();
    DecodeRawRegisterTests();
    DecodePPPOERegisterTests();
    DecodeICMPV4RegisterTests();
    DecodeICMPV6RegisterTests();
    DecodeIPV4RegisterTests();
    DecodeIPV6RegisterTests();
    DecodeTCPRegisterTests();
    DecodeUDPV4RegisterTests();
    DecodeGRERegisterTests();
    DecodeAsn1RegisterTests();
    DecodeMPLSRegisterTests();
    AppLayerProtoDetectUnittestsRegister();
    ConfRegisterTests();
    ConfYamlRegisterTests();
    TmqhFlowRegisterTests();
    FlowRegisterTests();
    HostRegisterUnittests();
    IPPairRegisterUnittests();
    SCSigRegisterSignatureOrderingTests();
    SCRadixRegisterTests();
    DefragRegisterTests();
    SigGroupHeadRegisterTests();
    SCHInfoRegisterTests();
    SCRuleVarsRegisterTests();
    AppLayerParserRegisterUnittests();
    ThreadMacrosRegisterTests();
    UtilSpmSearchRegistertests();
    UtilActionRegisterTests();
    SCClassConfRegisterTests();
    SCThresholdConfRegisterTests();
    SCRConfRegisterTests();
#ifdef __SC_CUDA_SUPPORT__
    SCCudaRegisterTests();
#endif
    PayloadRegisterTests();
    DcePayloadRegisterTests();
    UriRegisterTests();
#ifdef PROFILING
    SCProfilingRegisterTests();
#endif
    DeStateRegisterTests();
    DetectRingBufferRegisterTests();
    MemcmpRegisterTests();
    DetectEngineHttpClientBodyRegisterTests();
    DetectEngineHttpServerBodyRegisterTests();
    DetectEngineHttpHeaderRegisterTests();
    DetectEngineHttpRawHeaderRegisterTests();
    DetectEngineHttpMethodRegisterTests();
    DetectEngineHttpCookieRegisterTests();
    DetectEngineHttpRawUriRegisterTests();
    DetectEngineHttpStatMsgRegisterTests();
    DetectEngineHttpStatCodeRegisterTests();
    DetectEngineHttpUARegisterTests();
    DetectEngineHttpHHRegisterTests();
    DetectEngineHttpHRHRegisterTests();
    DetectEngineInspectModbusRegisterTests();
    DetectEngineRegisterTests();
    DetectEngineSMTPFiledataRegisterTests();
    SCLogRegisterTests();
    MagicRegisterTests();
    UtilMiscRegisterTests();
    DetectAddressTests();
    DetectProtoTests();
    DetectPortTests();
    SCAtomicRegisterTests();
    MemrchrRegisterTests();
#ifdef __SC_CUDA_SUPPORT__
    CudaBufferRegisterUnittests();
#endif
    AppLayerUnittestsRegister();
    MimeDecRegisterTests();
    StreamingBufferRegisterTests();

    if (list_unittests) {
        UtListTests(regex_arg);
    } else {
        /* global packet pool */
        extern intmax_t max_pending_packets;
        max_pending_packets = 128;
        PacketPoolInit();

        uint32_t failed = UtRunTests(regex_arg);
        PacketPoolDestroy();
        UtCleanup();
#ifdef BUILD_HYPERSCAN
        MpmHSGlobalCleanup();
#endif
#ifdef __SC_CUDA_SUPPORT__
        if (PatternMatchDefaultMatcher() == MPM_AC_CUDA)
            MpmCudaBufferDeSetup();
        CudaHandlerFreeProfiles();
#endif
        if (failed) {
            exit(EXIT_FAILURE);
        }
    }

#ifdef DBG_MEM_ALLOC
    SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem);
#endif

    exit(EXIT_SUCCESS);
#else
    SCLogError(SC_ERR_NOT_SUPPORTED, "Unittests are not build-in");
    exit(EXIT_FAILURE);
#endif /* UNITTESTS */
}
Beispiel #2
0
int main(int argc, char **argv)
{
    int opt;
    char *pcap_file = NULL;
    char pcap_dev[128];
#ifdef HAVE_PFRING
    char *pfring_dev = NULL;
#endif
    char *sig_file = NULL;
    char *nfq_id = NULL;
    char *conf_filename = NULL;
    char *pid_filename = NULL;
#ifdef UNITTESTS
    char *regex_arg = NULL;
#endif
    int dump_config = 0;
    int list_unittests = 0;
    int list_cuda_cards = 0;
    int daemon = 0;
    char *user_name = NULL;
    char *group_name = NULL;
    uint8_t do_setuid = FALSE;
    uint8_t do_setgid = FALSE;
    uint32_t userid = 0;
    uint32_t groupid = 0;
    char *erf_file = NULL;
    char *dag_input = NULL;

    char *log_dir;
    struct stat buf;

    sc_set_caps = FALSE;

    SC_ATOMIC_INIT(engine_stage);

    /* initialize the logging subsys */
    SCLogInitLogModule(NULL);

    /* By default use IDS mode, but if nfq or ipfw
     * are specified, IPS mode will overwrite this */
    SET_ENGINE_MODE_IDS(engine_mode);

#ifdef OS_WIN32
	/* service initialization */
	if (SCRunningAsService()) {
		char path[MAX_PATH];
		char *p = NULL;
		strlcpy(path, argv[0], MAX_PATH);
		if ((p = strrchr(path, '\\'))) {
			*p = '\0';
		}
		if (!SetCurrentDirectory(path)) {
			SCLogError(SC_ERR_FATAL, "Can't set current directory to: %s", path);
			return -1;
		}
		SCLogInfo("Current directory is set to: %s", path);
		daemon = 1;
		SCServiceInit(argc, argv);
	}

	/* Windows socket subsystem initialization */
	WSADATA wsaData;
	if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) {
		SCLogError(SC_ERR_FATAL, "Can't initialize Windows sockets: %d", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
#endif /* OS_WIN32 */

#ifdef REVISION
    SCLogInfo("This is %s version %s (rev %s)", PROG_NAME, PROG_VER, xstr(REVISION));
#else
    SCLogInfo("This is %s version %s", PROG_NAME, PROG_VER);
#endif

    /* Initialize the configuration module. */
    ConfInit();

    struct option long_opts[] = {
        {"dump-config", 0, &dump_config, 1},
        {"pfring-int",  required_argument, 0, 0},
        {"pfring-cluster-id",  required_argument, 0, 0},
        {"pfring-cluster-type",  required_argument, 0, 0},
        {"pcap-buffer-size", required_argument, 0, 0},
        {"unittest-filter", required_argument, 0, 'U'},
        {"list-unittests", 0, &list_unittests, 1},
        {"list-cuda-cards", 0, &list_cuda_cards, 1},
        {"engine-analysis", 0, &engine_analysis, 1},
#ifdef OS_WIN32
		{"service-install", 0, 0, 0},
		{"service-remove", 0, 0, 0},
		{"service-change-params", 0, 0, 0},
#endif /* OS_WIN32 */
        {"pidfile", required_argument, 0, 0},
        {"init-errors-fatal", 0, 0, 0},
        {"fatal-unittests", 0, 0, 0},
        {"user", required_argument, 0, 0},
        {"group", required_argument, 0, 0},
        {"erf-in", required_argument, 0, 0},
        {"dag", required_argument, 0, 0},
        {NULL, 0, NULL, 0}
    };

    /* getopt_long stores the option index here. */
    int option_index = 0;

    char short_opts[] = "c:Dhi:l:q:d:r:us:U:V";

    while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) {
        switch (opt) {
        case 0:
            if(strcmp((long_opts[option_index]).name , "pfring-int") == 0){
#ifdef HAVE_PFRING
                run_mode = MODE_PFRING;
                if (ConfSet("pfring.interface", optarg, 0) != 1) {
                    fprintf(stderr, "ERROR: Failed to set pfring interface.\n");
                    exit(EXIT_FAILURE);
                }
#else
                SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure to pass --enable-pfring to configure when building.");
                exit(EXIT_FAILURE);
#endif /* HAVE_PFRING */
            }
            else if(strcmp((long_opts[option_index]).name , "pfring-cluster-id") == 0){
#ifdef HAVE_PFRING
                if (ConfSet("pfring.cluster-id", optarg, 0) != 1) {
                    fprintf(stderr, "ERROR: Failed to set pfring cluster-id.\n");
                    exit(EXIT_FAILURE);
                }
#else
                SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure to pass --enable-pfring to configure when building.");
                exit(EXIT_FAILURE);
#endif /* HAVE_PFRING */
            }
            else if(strcmp((long_opts[option_index]).name , "pfring-cluster-type") == 0){
#ifdef HAVE_PFRING
                if (ConfSet("pfring.cluster-type", optarg, 0) != 1) {
                    fprintf(stderr, "ERROR: Failed to set pfring cluster-type.\n");
                    exit(EXIT_FAILURE);
                }
#else
                SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure to pass --enable-pfring to configure when building.");
                exit(EXIT_FAILURE);
#endif /* HAVE_PFRING */
            }
            else if(strcmp((long_opts[option_index]).name, "init-errors-fatal") == 0) {
                if (ConfSet("engine.init_failure_fatal", "1", 0) != 1) {
                    fprintf(stderr, "ERROR: Failed to set engine init_failure_fatal.\n");
                    exit(EXIT_FAILURE);
                }
            }
            else if(strcmp((long_opts[option_index]).name, "list-unittests") == 0) {
#ifdef UNITTESTS
                /* Set run_mode to unit tests. */
                run_mode = MODE_UNITTEST;
#else
                fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
                exit(EXIT_FAILURE);
#endif /* UNITTESTS */
            } else if(strcmp((long_opts[option_index]).name, "list-cuda-cards") == 0) {
#ifndef __SC_CUDA_SUPPORT__
                fprintf(stderr, "ERROR: Cuda not enabled. Make sure to pass "
                        "--enable-cuda to configure when building.\n");
                exit(EXIT_FAILURE);
#endif /* UNITTESTS */
            } else if(strcmp((long_opts[option_index]).name, "engine-analysis") == 0) {
                // do nothing for now
            }
#ifdef OS_WIN32
            else if(strcmp((long_opts[option_index]).name, "service-install") == 0) {
				if (SCServiceInstall(argc, argv)) {
					exit(EXIT_FAILURE);
				}
				SCLogInfo("Suricata service has been successfuly installed.");
				exit(EXIT_SUCCESS);
            }
            else if(strcmp((long_opts[option_index]).name, "service-remove") == 0) {
				if (SCServiceRemove(argc, argv)) {
					exit(EXIT_FAILURE);
				}
				SCLogInfo("Suricata service has been successfuly removed.");
				exit(EXIT_SUCCESS);
            }
            else if(strcmp((long_opts[option_index]).name, "service-change-params") == 0) {
				if (SCServiceChangeParams(argc, argv)) {
					exit(EXIT_FAILURE);
				}
				SCLogInfo("Suricata service startup parameters has been successfuly changed.");
				exit(EXIT_SUCCESS);
            }
#endif /* OS_WIN32 */
            else if(strcmp((long_opts[option_index]).name, "pidfile") == 0) {
                pid_filename = optarg;
            }
            else if(strcmp((long_opts[option_index]).name, "fatal-unittests") == 0) {
#ifdef UNITTESTS
                if (ConfSet("unittests.failure_fatal", "1", 0) != 1) {
                    fprintf(stderr, "ERROR: Failed to set unittests failure_fatal.\n");
                    exit(EXIT_FAILURE);
                }
#else
                fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
                exit(EXIT_FAILURE);
#endif /* UNITTESTS */
            }
            else if(strcmp((long_opts[option_index]).name, "user") == 0) {
#ifndef HAVE_LIBCAP_NG
                SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to"
                        " drop privileges, but it was not compiled into Suricata.");
                exit(EXIT_FAILURE);
#else
                user_name = optarg;
                do_setuid = TRUE;
#endif /* HAVE_LIBCAP_NG */
            }
            else if(strcmp((long_opts[option_index]).name, "group") == 0) {
#ifndef HAVE_LIBCAP_NG
                SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to"
                        " drop privileges, but it was not compiled into Suricata.");
                exit(EXIT_FAILURE);
#else
                group_name = optarg;
                do_setgid = TRUE;
#endif /* HAVE_LIBCAP_NG */
            }
            else if (strcmp((long_opts[option_index]).name, "erf-in") == 0) {
                run_mode = MODE_ERF_FILE;
                erf_file = optarg;
            }
			else if (strcmp((long_opts[option_index]).name, "dag") == 0) {
#ifdef HAVE_DAG
				run_mode = MODE_DAG;
				dag_input = optarg;
#else
				SCLogError(SC_ERR_DAG_REQUIRED, "libdag and a DAG card are required"
						" to receieve packets using --dag.");
				exit(EXIT_FAILURE);
#endif /* HAVE_DAG */
			}
            else if(strcmp((long_opts[option_index]).name, "pcap-buffer-size") == 0) {
#ifdef HAVE_PCAP_SET_BUFF
                if (ConfSet("pcap.buffer-size", optarg, 0) != 1) {
                    fprintf(stderr, "ERROR: Failed to set pcap-buffer-size.\n");
                    exit(EXIT_FAILURE);
                }
#else
                SCLogError(SC_ERR_NO_PCAP_SET_BUFFER_SIZE, "The version of libpcap you have"
                        " doesn't support setting buffer size.");
#endif /* HAVE_PCAP_SET_BUFF */
            }
            break;
        case 'c':
            conf_filename = optarg;
            break;
#ifndef OS_WIN32
        case 'D':
            daemon = 1;
            break;
#endif /* OS_WIN32 */
        case 'h':
            usage(argv[0]);
            exit(EXIT_SUCCESS);
            break;
        case 'i':
            if (run_mode == MODE_UNKNOWN) {
                run_mode = MODE_PCAP_DEV;
                PcapLiveRegisterDevice(optarg);
            } else if (run_mode == MODE_PCAP_DEV) {
#ifdef OS_WIN32
                SCLogError(SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT, "pcap multi dev "
                        "support is not (yet) supported on Windows.");
                exit(EXIT_FAILURE);
#else
                SCLogWarning(SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL, "using "
                        "multiple pcap devices to get packets is experimental.");
                PcapLiveRegisterDevice(optarg);
#endif
            } else {
                SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
                                                     "has been specified");
                usage(argv[0]);
                exit(EXIT_FAILURE);
            }
			memset(pcap_dev, 0, sizeof(pcap_dev));
            strlcpy(pcap_dev, optarg, ((strlen(optarg) < sizeof(pcap_dev)) ? (strlen(optarg)+1) : (sizeof(pcap_dev))));
            break;
        case 'l':
            if (ConfSet("default-log-dir", optarg, 0) != 1) {
                fprintf(stderr, "ERROR: Failed to set log directory.\n");
                exit(EXIT_FAILURE);
            }
            if (stat(optarg, &buf) != 0) {
                SCLogError(SC_ERR_LOGDIR_CMDLINE, "The logging directory \"%s\" "
                        "supplied at the commandline (-l %s) doesn't "
                        "exist. Shutting down the engine.", optarg, optarg);
                exit(EXIT_FAILURE);
            }
            break;
        case 'q':
#ifdef NFQ
            if (run_mode == MODE_UNKNOWN) {
                run_mode = MODE_NFQ;
                SET_ENGINE_MODE_IPS(engine_mode);
                if (NFQRegisterQueue(optarg) == -1)
                    exit(EXIT_FAILURE);
            } else if (run_mode == MODE_NFQ) {
                if (NFQRegisterQueue(optarg) == -1)
                    exit(EXIT_FAILURE);
            } else {
                SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
                                                     "has been specified");
                usage(argv[0]);
                exit(EXIT_FAILURE);
            }
            nfq_id = optarg;
#else
            SCLogError(SC_ERR_NFQ_NOSUPPORT,"NFQUEUE not enabled. Make sure to pass --enable-nfqueue to configure when building.");
            exit(EXIT_FAILURE);
#endif /* NFQ */
            break;
        case 'd':
#ifdef IPFW
            if (run_mode == MODE_UNKNOWN) {
                run_mode = MODE_IPFW;
                SET_ENGINE_MODE_IPS(engine_mode);
            } else {
                SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
                                                     "has been specified");
                usage(argv[0]);
                exit(EXIT_SUCCESS);
            }
            if (ConfSet("ipfw-divert-port", optarg, 0) != 1) {
                fprintf(stderr, "ERROR: Failed to set ipfw_divert_port\n");
                exit(EXIT_FAILURE);
            }
#else
            SCLogError(SC_ERR_IPFW_NOSUPPORT,"IPFW not enabled. Make sure to pass --enable-ipfw to configure when building.");
            exit(EXIT_FAILURE);
#endif /* IPFW */
            break;
        case 'r':
            if (run_mode == MODE_UNKNOWN) {
                run_mode = MODE_PCAP_FILE;
            } else {
                SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
                                                     "has been specified");
                usage(argv[0]);
                exit(EXIT_SUCCESS);
            }
            pcap_file = optarg;
            break;
        case 's':
            sig_file = optarg;
            break;
        case 'u':
#ifdef UNITTESTS
            if (run_mode == MODE_UNKNOWN) {
                run_mode = MODE_UNITTEST;
            } else {
                SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode has"
                                                     " been specified");
                usage(argv[0]);
                exit(EXIT_SUCCESS);
            }
#else
            fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
            exit(EXIT_FAILURE);
#endif /* UNITTESTS */
            break;
        case 'U':
#ifdef UNITTESTS
            regex_arg = optarg;

            if(strlen(regex_arg) == 0)
            regex_arg = NULL;
#endif
            break;
        case 'V':
#ifdef REVISION
            printf("\nThis is %s version %s (rev %s)\n\n", PROG_NAME, PROG_VER, xstr(REVISION));
#else
            printf("\nThis is %s version %s\n\n", PROG_NAME, PROG_VER);
#endif
            exit(EXIT_SUCCESS);
        default:
            usage(argv[0]);
            exit(EXIT_FAILURE);
        }
    }
    SetBpfString(optind, argv);

    UtilCpuPrintSummary();

#ifdef __SC_CUDA_SUPPORT__
    /* Init the CUDA environment */
    SCCudaInitCudaEnvironment();
    if (list_cuda_cards) {
        SCCudaListCards();
        exit(EXIT_SUCCESS);
    }
#endif

    if (!CheckValidDaemonModes(daemon, run_mode)) {
        exit(EXIT_FAILURE);
    }

    /* Initializations for global vars, queues, etc (memsets, mutex init..) */
    GlobalInits();
    TimeInit();
    SupportFastPatternForSigMatchTypes();

    /* Load yaml configuration file if provided. */
    if (conf_filename != NULL) {
        if (ConfYamlLoadFile(conf_filename) != 0) {
            /* Error already displayed. */
            exit(EXIT_FAILURE);
        }
    } else if (run_mode != MODE_UNITTEST){
        SCLogError(SC_ERR_OPENING_FILE, "Configuration file has not been provided");
        usage(argv[0]);
        exit(EXIT_FAILURE);
    }

    if (dump_config) {
        ConfDump();
        exit(EXIT_SUCCESS);
    }

    /* Check for the existance of the default logging directory which we pick
     * from suricata.yaml.  If not found, shut the engine down */
    if (ConfGet("default-log-dir", &log_dir) != 1)
        log_dir = DEFAULT_LOG_DIR;
    if (stat(log_dir, &buf) != 0) {
        SCLogError(SC_ERR_LOGDIR_CONFIG, "The logging directory \"%s\" "
                    "supplied by %s (default-log-dir) doesn't exist. "
                    "Shutting down the engine", log_dir, conf_filename);
        exit(EXIT_FAILURE);
    }

    /* Pull the max pending packets from the config, if not found fall
     * back on a sane default. */
    if (ConfGetInt("max-pending-packets", &max_pending_packets) != 1)
        max_pending_packets = DEFAULT_MAX_PENDING_PACKETS;
    SCLogDebug("Max pending packets set to %"PRIiMAX, max_pending_packets);

    /* Pull the default packet size from the config, if not found fall
     * back on a sane default. */
    if (ConfGetInt("default-packet-size", &default_packet_size) != 1) {
        switch (run_mode) {
            case MODE_PCAP_DEV:
            case MODE_PFRING:
                /* find payload for interface and use it */
                default_packet_size = GetIfaceMaxPayloadSize(pcap_dev);
                if (default_packet_size)
                    break;
            default:
                default_packet_size = DEFAULT_PACKET_SIZE;
        }
    }
    SCLogDebug("Default packet size set to %"PRIiMAX, default_packet_size);

#ifdef NFQ
    if (run_mode == MODE_NFQ)
        NFQInitConfig(FALSE);
#endif

    /* Since our config is now loaded we can finish configurating the
     * logging module. */
    SCLogLoadConfig();

#ifdef __SC_CUDA_SUPPORT__
    /* load the cuda configuration */
    SCCudaHlGetYamlConf();
#endif /* __SC_CUDA_SUPPORT__ */

    /* Load the Host-OS lookup. */
    SCHInfoLoadFromConfig();

    if (run_mode == MODE_UNKNOWN) {
        if (!engine_analysis) {
            usage(argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    if (engine_analysis) {
        SCLogInfo("== Carrying out Engine Analysis ==");
        char *temp = NULL;
        if (ConfGet("engine-analysis", &temp) == 0) {
            SCLogInfo("no engine-analysis parameter(s) defined in conf file.  "
                      "Please define/enable them in the conf to use this "
                      "feature.");
            exit(EXIT_FAILURE);
        }
    }

    /* create table for O(1) lowercase conversion lookup.  It was removed, but
     * we still need it for cuda.  So resintalling it back into the codebase */
    uint8_t c = 0;
    memset(g_u8_lowercasetable, 0x00, sizeof(g_u8_lowercasetable));
    for ( ; c < 255; c++) {
        if (c >= 'A' && c <= 'Z')
            g_u8_lowercasetable[c] = (c + ('a' - 'A'));
        else
            g_u8_lowercasetable[c] = c;
    }

    /* hardcoded initialization code */
    MpmTableSetup(); /* load the pattern matchers */
    SigTableSetup(); /* load the rule keywords */
    TmqhSetup();

    CIDRInit();
    SigParsePrepare();
    //PatternMatchPrepare(mpm_ctx, MPM_B2G);
    SCPerfInitCounterApi();
#ifdef PROFILING
    SCProfilingInit();
#endif /* PROFILING */
    SCReputationInitCtx();
    SCProtoNameInit();

    TagInitCtx();

    TmModuleReceiveNFQRegister();
    TmModuleVerdictNFQRegister();
    TmModuleDecodeNFQRegister();
    TmModuleReceiveIPFWRegister();
    TmModuleVerdictIPFWRegister();
    TmModuleDecodeIPFWRegister();
    TmModuleReceivePcapRegister();
    TmModuleDecodePcapRegister();
    TmModuleReceivePfringRegister();
    TmModuleDecodePfringRegister();
    TmModuleReceivePcapFileRegister();
    TmModuleDecodePcapFileRegister();
    TmModuleDetectRegister();
    TmModuleAlertFastLogRegister();
    TmModuleAlertDebugLogRegister();
    TmModuleAlertPreludeRegister();
    TmModuleRespondRejectRegister();
    TmModuleAlertFastLogIPv4Register();
    TmModuleAlertFastLogIPv6Register();
    TmModuleAlertSyslogIPv4Register();
    TmModuleAlertSyslogIPv6Register();
    TmModuleAlertUnifiedLogRegister();
    TmModuleAlertUnifiedAlertRegister();
    TmModuleUnified2AlertRegister();
    TmModuleAlertSyslogRegister();
    TmModuleLogDropLogRegister();
    TmModuleStreamTcpRegister();
    TmModuleLogHttpLogRegister();
    TmModuleLogHttpLogIPv4Register();
    TmModuleLogHttpLogIPv6Register();
#ifdef __SC_CUDA_SUPPORT__
    TmModuleCudaMpmB2gRegister();
    TmModuleCudaPacketBatcherRegister();
#endif
    TmModuleReceiveErfFileRegister();
    TmModuleDecodeErfFileRegister();
    TmModuleReceiveErfDagRegister();
    TmModuleDecodeErfDagRegister();
    TmModuleDebugList();

    /** \todo we need an api for these */
    AppLayerDetectProtoThreadInit();
    RegisterAppLayerParsers();
    RegisterHTPParsers();
    RegisterTLSParsers();
    RegisterSMBParsers();
    RegisterDCERPCParsers();
    RegisterDCERPCUDPParsers();
    RegisterFTPParsers();
    RegisterSSHParsers();
    AppLayerParsersInitPostProcess();

#ifdef UNITTESTS

    if (run_mode == MODE_UNITTEST) {
#ifdef DBG_MEM_ALLOC
    SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem);
#endif
        /* test and initialize the unittesting subsystem */
        if(regex_arg == NULL){
            regex_arg = ".*";
            UtRunSelftest(regex_arg); /* inits and cleans up again */
        }

        AppLayerHtpEnableRequestBodyCallback();
        AppLayerHtpRegisterExtraCallbacks();

        UtInitialize();
        UTHRegisterTests();
        SCReputationRegisterTests();
        TmModuleRegisterTests();
        SigTableRegisterTests();
        HashTableRegisterTests();
        HashListTableRegisterTests();
        BloomFilterRegisterTests();
        BloomFilterCountingRegisterTests();
        PoolRegisterTests();
        ByteRegisterTests();
        MpmRegisterTests();
        FlowBitRegisterTests();
        FlowAlertSidRegisterTests();
        SCPerfRegisterTests();
        DecodePPPRegisterTests();
        DecodeVLANRegisterTests();
        HTPParserRegisterTests();
        TLSParserRegisterTests();
        SSHParserRegisterTests();
        SMBParserRegisterTests();
        DCERPCParserRegisterTests();
        DCERPCUDPParserRegisterTests();
        FTPParserRegisterTests();
        DecodeRawRegisterTests();
        DecodePPPOERegisterTests();
        DecodeICMPV4RegisterTests();
        DecodeICMPV6RegisterTests();
        DecodeIPV4RegisterTests();
        DecodeTCPRegisterTests();
        DecodeUDPV4RegisterTests();
        DecodeGRERegisterTests();
        DecodeAsn1RegisterTests();
        AlpDetectRegisterTests();
        ConfRegisterTests();
        ConfYamlRegisterTests();
        TmqhFlowRegisterTests();
        FlowRegisterTests();
        SCSigRegisterSignatureOrderingTests();
        SCRadixRegisterTests();
        DefragRegisterTests();
        SigGroupHeadRegisterTests();
        SCHInfoRegisterTests();
        SCRuleVarsRegisterTests();
        AppLayerParserRegisterTests();
        ThreadMacrosRegisterTests();
        UtilSpmSearchRegistertests();
        UtilActionRegisterTests();
        SCClassConfRegisterTests();
        SCThresholdConfRegisterTests();
        SCRConfRegisterTests();
#ifdef __SC_CUDA_SUPPORT__
        SCCudaRegisterTests();
#endif
        PayloadRegisterTests();
        DcePayloadRegisterTests();
        UriRegisterTests();
#ifdef PROFILING
        SCProfilingRegisterTests();
#endif
        DeStateRegisterTests();
        DetectRingBufferRegisterTests();
        MemcmpRegisterTests();
        DetectEngineHttpClientBodyRegisterTests();
        DetectEngineHttpHeaderRegisterTests();
        DetectEngineHttpRawHeaderRegisterTests();
        DetectEngineHttpMethodRegisterTests();
        DetectEngineHttpCookieRegisterTests();
        DetectEngineRegisterTests();
        SCLogRegisterTests();
        if (list_unittests) {
            UtListTests(regex_arg);
        }
        else {
            uint32_t failed = UtRunTests(regex_arg);
            UtCleanup();
#ifdef __SC_CUDA_SUPPORT__
            /* need this in case any of the cuda dispatcher threads are still
             * running, kill them, so that we can free the cuda contexts.  We
             * need to free those cuda contexts so that next when we call
             * deregister functions, we will need to attach to those contexts
             * the contexts and its associated data */
            TmThreadKillThreads();
            SCCudaHlDeRegisterAllRegisteredModules();
#endif
            if (failed) {
                exit(EXIT_FAILURE);
            }
        }

#ifdef DBG_MEM_ALLOC
        SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem);
#endif

        exit(EXIT_SUCCESS);
    }
#endif /* UNITTESTS */

    if (daemon == 1) {
        Daemonize();
        if (pid_filename != NULL) {
            if (SCPidfileCreate(pid_filename) != 0) {
                pid_filename = NULL;
                exit(EXIT_FAILURE);
            }
        }
    } else {
        if (pid_filename != NULL) {
            SCLogError(SC_ERR_PIDFILE_DAEMON, "The pidfile file option applies "
                    "only to the daemon modes");
            pid_filename = NULL;
            exit(EXIT_FAILURE);
        }
    }

    /* registering signals we use */
    SignalHandlerSetup(SIGINT, SignalHandlerSigint);
    SignalHandlerSetup(SIGTERM, SignalHandlerSigterm);

#ifndef OS_WIN32
	/* SIGHUP is not implemnetd on WIN32 */
    //SignalHandlerSetup(SIGHUP, SignalHandlerSighup);

    /* Get the suricata user ID to given user ID */
    if (do_setuid == TRUE) {
        if (SCGetUserID(user_name, group_name, &userid, &groupid) != 0) {
            SCLogError(SC_ERR_UID_FAILED, "failed in getting user ID");
            exit(EXIT_FAILURE);
        }

        sc_set_caps = TRUE;
    /* Get the suricata group ID to given group ID */
    } else if (do_setgid == TRUE) {
        if (SCGetGroupID(group_name, &groupid) != 0) {
            SCLogError(SC_ERR_GID_FAILED, "failed in getting group ID");
            exit(EXIT_FAILURE);
        }

        sc_set_caps = TRUE;
    }
#endif /* OS_WIN32 */

    /* pre allocate packets */
    SCLogDebug("preallocating packets... packet size %" PRIuMAX "", (uintmax_t)SIZE_OF_PACKET);
    int i = 0;
    for (i = 0; i < max_pending_packets; i++) {
        /* XXX pkt alloc function */
        Packet *p = SCMalloc(SIZE_OF_PACKET);
        if (p == NULL) {
            SCLogError(SC_ERR_FATAL, "Fatal error encountered while allocating a packet. Exiting...");
            exit(EXIT_FAILURE);
        }
        PACKET_INITIALIZE(p);

        PacketPoolStorePacket(p);
    }
    SCLogInfo("preallocated %"PRIiMAX" packets. Total memory %"PRIuMAX"",
        max_pending_packets, (uintmax_t)(max_pending_packets*SIZE_OF_PACKET));

    FlowInitConfig(FLOW_VERBOSE);

    DetectEngineCtx *de_ctx = DetectEngineCtxInit();

    SCClassConfLoadClassficationConfigFile(de_ctx);
    SCRConfLoadReferenceConfigFile(de_ctx);

    ActionInitConfig();

    if (SigLoadSignatures(de_ctx, sig_file) < 0) {
        if (sig_file == NULL) {
            SCLogError(SC_ERR_OPENING_FILE, "Signature file has not been provided");
        } else {
            SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
        }
        if (de_ctx->failure_fatal)
            exit(EXIT_FAILURE);
    }

    if (engine_analysis) {
        exit(EXIT_SUCCESS);
    }

#ifdef PROFILING
    SCProfilingInitRuleCounters(de_ctx);
#endif /* PROFILING */

#ifdef __SC_CUDA_SUPPORT__
    SCCudaPBSetUpQueuesAndBuffers();
#endif /* __SC_CUDA_SUPPORT__ */

    AppLayerHtpRegisterExtraCallbacks();
    SCThresholdConfInitContext(de_ctx,NULL);
    SCAsn1LoadConfig();

    struct timeval start_time;
    memset(&start_time, 0, sizeof(start_time));
    gettimeofday(&start_time, NULL);

    SCDropMainThreadCaps(userid, groupid);

    RunModeInitializeOutputs();

    /* run the selected runmode */
    if (run_mode == MODE_PCAP_DEV) {
        //RunModeIdsPcap3(de_ctx, pcap_dev);
        //RunModeIdsPcap2(de_ctx, pcap_dev);
        //RunModeIdsPcap(de_ctx, pcap_dev);
        PcapTranslateIPToDevice(pcap_dev, sizeof(pcap_dev));
        RunModeIdsPcapAuto(de_ctx, pcap_dev);
    }
    else if (run_mode == MODE_PCAP_FILE) {
        //RunModeFilePcap(de_ctx, pcap_file);
        //RunModeFilePcap2(de_ctx, pcap_file);
        RunModeFilePcapAuto(de_ctx, pcap_file);
        //RunModeFilePcapAutoFp(de_ctx, pcap_file);
        //RunModeFilePcapAuto2(de_ctx, pcap_file);
    }
#ifdef HAVE_PFRING
    else if (run_mode == MODE_PFRING) {
        PfringLoadConfig();
        //RunModeIdsPfring3(de_ctx, pfring_dev);
        //RunModeIdsPfring2(de_ctx, pfring_dev);
        //RunModeIdsPfring(de_ctx, pfring_dev);
        //RunModeIdsPfring4(de_ctx, pfring_dev);
        if (PfringConfGetThreads() == 1) {
            RunModeIdsPfringAuto(de_ctx, pfring_dev);
        } else {
            RunModeIdsPfringAutoFp(de_ctx, pfring_dev);
        }
    }
#endif /* HAVE_PFRING */
    else if (run_mode == MODE_NFQ) {
        //RunModeIpsNFQ(de_ctx, nfq_id);
        RunModeIpsNFQAuto(de_ctx, nfq_id);
    }
    else if (run_mode == MODE_IPFW) {
        //RunModeIpsIPFW(de_ctx);
        RunModeIpsIPFWAuto(de_ctx);
    }
    else if (run_mode == MODE_ERF_FILE) {
        RunModeErfFileAuto(de_ctx, erf_file);
    }
    else if (run_mode == MODE_DAG) {
        RunModeErfDagAuto(de_ctx, dag_input);
    }
    else {
        SCLogError(SC_ERR_UNKNOWN_RUN_MODE, "Unknown runtime mode. Aborting");
        exit(EXIT_FAILURE);
    }

#ifdef __SC_CUDA_SUPPORT__
    if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) {
        /* start the dispatcher thread for this module */
        if (B2gCudaStartDispatcherThreadRC("SC_RULES_CONTENT_B2G_CUDA") == -1)
            exit(EXIT_FAILURE);
    }
#endif

    /* Spawn the flow manager thread */
    FlowManagerThreadSpawn();

    StreamTcpInitConfig(STREAM_VERBOSE);
    DefragInit();

    /* Spawn the L7 App Detect thread */
    //AppLayerDetectProtoThreadSpawn();

    /* Spawn the perf counter threads.  Let these be the last one spawned */
    SCPerfSpawnThreads();

    /* Check if the alloted queues have at least 1 reader and writer */
    TmValidateQueueState();

    /* Wait till all the threads have been initialized */
    if (TmThreadWaitOnThreadInit() == TM_ECODE_FAILED) {
        SCLogError(SC_ERR_INITIALIZATION, "Engine initialization failed, "
                   "aborting...");
        exit(EXIT_FAILURE);
    }

    SC_ATOMIC_CAS(&engine_stage, SURICATA_INIT, SURICATA_RUNTIME);

    /* Un-pause all the paused threads */
    TmThreadContinueThreads();

#ifdef DBG_MEM_ALLOC
    SCLogInfo("Memory used at startup: %"PRIdMAX, (intmax_t)global_mem);
#ifdef DBG_MEM_ALLOC_SKIP_STARTUP
    print_mem_flag = 1;
#endif
#endif

    while(1) {
        if (suricata_ctl_flags != 0) {
            SCLogInfo("signal received");

            if (suricata_ctl_flags & SURICATA_STOP)  {
                SCLogInfo("EngineStop received");

                /* Stop the engine so it quits after processing the pcap file
                 * but first make sure all packets are processed by all other
                 * threads. */
                char done = 0;
                do {
                    if (suricata_ctl_flags & SURICATA_KILL)
                        break;

                    /* if all packets are returned to the packetpool
                     * we are done */
                    if (PacketPoolSize() == max_pending_packets)
                        done = 1;

                    if (done == 0) {
                        usleep(100);
                    }
                } while (done == 0);

                SCLogInfo("all packets processed by threads, stopping engine");
            }

            struct timeval end_time;
            memset(&end_time, 0, sizeof(end_time));
            gettimeofday(&end_time, NULL);

            SCLogInfo("time elapsed %" PRIuMAX "s", (uintmax_t)(end_time.tv_sec - start_time.tv_sec));

#ifdef __SC_CUDA_SUPPORT__
            SCCudaPBKillBatchingPackets();
#endif

            TmThreadKillThreads();
            SCPerfReleaseResources();
            break;
        }

        TmThreadCheckThreadState();

        usleep(10* 1000);
    }

    /* Update the engine stage/status flag */
    SC_ATOMIC_CAS(&engine_stage, SURICATA_RUNTIME, SURICATA_DEINIT);


    FlowShutdown();
    FlowPrintQueueInfo();
    StreamTcpFreeConfig(STREAM_VERBOSE);
    HTPFreeConfig();
    HTPAtExitPrintStats();

#ifdef DBG_MEM_ALLOC
    SCLogInfo("Total memory used (without SCFree()): %"PRIdMAX, (intmax_t)global_mem);
#ifdef DBG_MEM_ALLOC_SKIP_STARTUP
    print_mem_flag = 0;
#endif
#endif

    SCPidfileRemove(pid_filename);

    /** \todo review whats needed here */
#ifdef __SC_CUDA_SUPPORT__
    if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) {
        /* all threadvars related to cuda should be free by now, which means
         * the cuda contexts would be floating */
        if (SCCudaHlPushCudaContextFromModule("SC_RULES_CONTENT_B2G_CUDA") == -1) {
            SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Call to "
                       "SCCudaHlPushCudaContextForModule() failed during the "
                       "shutdown phase just before the call to SigGroupCleanup()");
        }
    }
#endif
    SigGroupCleanup(de_ctx);
#ifdef __SC_CUDA_SUPPORT__
    if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) {
        /* pop the cuda context we just pushed before the call to SigGroupCleanup() */
        if (SCCudaCtxPopCurrent(NULL) == -1) {
            SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Call to SCCudaCtxPopCurrent() "
                       "during the shutdown phase just before the call to "
                       "SigGroupCleanup()");
            return 0;
        }
    }
#endif

    AppLayerHtpPrintStats();

    SigCleanSignatures(de_ctx);
    if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
        MpmFactoryDeRegisterAllMpmCtxProfiles();
    }
    DetectEngineCtxFree(de_ctx);
    AlpProtoDestroy();

    TagDestroyCtx();

    RunModeShutDown();
    OutputDeregisterAll();
    TimeDeinit();
    SCProtoNameDeInit();
    DefragDestroy();
    TmqhPacketpoolDestroy();

#ifdef PROFILING
    if (profiling_rules_enabled)
        SCProfilingDump(stdout);
    SCProfilingDestroy();
#endif

#ifdef __SC_CUDA_SUPPORT__
    /* all cuda contexts attached to any threads should be free by now.
     * if any host_thread is still attached to any cuda_context, they need
     * to pop them by the time we reach here, if they aren't using those
     * cuda contexts in any way */
    SCCudaHlDeRegisterAllRegisteredModules();
#endif
#ifdef OS_WIN32
	if (daemon) {
		return 0;
	}
#endif /* OS_WIN32 */

    SC_ATOMIC_DESTROY(engine_stage);
    exit(EXIT_SUCCESS);
}