Esempio n. 1
0
void MpmCudaEnvironmentSetup()
{
    if (PatternMatchDefaultMatcher() != MPM_AC_CUDA)
        return;

    CudaHandlerAddCudaProfileFromConf("mpm", MpmCudaConfParse, MpmCudaConfFree);

    MpmCudaConf *conf = CudaHandlerGetCudaProfile("mpm");
    if (conf == NULL) {
        SCLogError(SC_ERR_AC_CUDA_ERROR, "Error obtaining cuda mpm "
                       "profile.");
        exit(EXIT_FAILURE);
    }

    if (MpmCudaBufferSetup() < 0) {
        SCLogError(SC_ERR_AC_CUDA_ERROR, "Error setting up env for ac "
                   "cuda");
        exit(EXIT_FAILURE);
    }

    return;
}
Esempio n. 2
0
int RunModeSetLiveCaptureAuto(DetectEngineCtx *de_ctx,
                              ConfigIfaceParserFunc ConfigParser,
                              ConfigIfaceThreadsCountFunc ModThreadsCount,
                              char *recv_mod_name,
                              char *decode_mod_name, char *thread_name,
                              const char *live_dev)
{
    /* Available cpus */
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
    int nlive = LiveGetDeviceCount();
    TmModule *tm_module;
    char tname[16];
    int thread;

    if ((nlive <= 1) && (live_dev != NULL)) {
        void *aconf;
        SCLogDebug("live_dev %s", live_dev);

        aconf = ConfigParser(live_dev);
        if (aconf == NULL) {
            SCLogError(SC_ERR_MEM_ALLOC, "Single dev: Failed to allocate config");
            exit(EXIT_FAILURE);
        }

        if (ModThreadsCount(aconf) > 1) {
            SCLogWarning(SC_ERR_UNIMPLEMENTED, "'Auto' running mode does not honor 'threads'"
                         " variable (set on '%s'). Please use another mode as"
                         " 'autofp' or 'worker'",
                         live_dev);
        }

        /* create the threads */
        ThreadVars *tv_receive =
            TmThreadCreatePacketHandler(recv_mod_name,
                    "packetpool", "packetpool",
                    "pickup-queue", "simple",
                    "pktacqloop");
        if (tv_receive == NULL) {
            SCLogError(SC_ERR_THREAD_CREATE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName(recv_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_INVALID_VALUE, "TmModuleGetByName failed for %s", recv_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receive, tm_module, aconf);

        TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET);

        if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) {
            SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    } else {
        SCLogInfo("Using %d live device(s).", nlive);

        for (thread = 0; thread < nlive; thread++) {
            char *live_dev = LiveGetDeviceName(thread);
            char *tnamec = NULL;
            void *aconf;

            if (live_dev == NULL) {
                SCLogError(SC_ERR_INVALID_VALUE, "Multidev: Failed to lookup live dev %d", thread);
                exit(EXIT_FAILURE);
            }
            SCLogDebug("live_dev %s", live_dev);

            aconf = ConfigParser(live_dev);
            if (aconf == NULL) {
                SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate config for %s (%d)",
                       live_dev, thread);
                exit(EXIT_FAILURE);
            }

            if (ModThreadsCount(aconf) > 1) {
                SCLogWarning(SC_ERR_UNIMPLEMENTED, "'Auto' running mode does not honor 'threads'"
                         " variable (set on '%s'). Please use another mode as"
                         " 'autofp' or 'worker'",
                         live_dev);
            }

            snprintf(tname, sizeof(tname),"%s-%s", thread_name, live_dev);
            tnamec = SCStrdup(tname);
            if (tnamec == NULL) {
                SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name");
                exit(EXIT_FAILURE);
            }

            /* create the threads */
            ThreadVars *tv_receive =
                TmThreadCreatePacketHandler(tnamec,
                        "packetpool", "packetpool",
                        "pickup-queue", "simple",
                        "pktacqloop");
            if (tv_receive == NULL) {
                SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
                exit(EXIT_FAILURE);
            }
            tm_module = TmModuleGetByName(recv_mod_name);
            if (tm_module == NULL) {
                SCLogError(SC_ERR_INVALID_VALUE, "TmModuleGetByName failed for %s", recv_mod_name);
                exit(EXIT_FAILURE);
            }
            TmSlotSetFuncAppend(tv_receive, tm_module, (void *)aconf);

            TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET);

            if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) {
                SCLogError(SC_ERR_INVALID_VALUE, "TmThreadSpawn failed");
                exit(EXIT_FAILURE);
            }
        }
    }

#if defined(__SC_CUDA_SUPPORT__)
    if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) {
        ThreadVars *tv_decode1 =
            TmThreadCreatePacketHandler("Decode",
                    "pickup-queue", "simple",
                    "decode-queue1", "simple",
                    "1slot");
        if (tv_decode1 == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed for Decode1");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName(decode_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", decode_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);

        TmThreadSetCPU(tv_decode1, DECODE_CPU_SET);

        if (TmThreadSpawn(tv_decode1) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }

        ThreadVars *tv_cuda_PB =
            TmThreadCreate("CUDA_PB",
                    "decode-queue1", "simple",
                    "cuda-pb-queue1", "simple",
                    "custom", SCCudaPBTmThreadsSlot1, 0);
        if (tv_cuda_PB == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed for CUDA_PB");
            exit(EXIT_FAILURE);
        }
        tv_cuda_PB->type = TVT_PPT;

        tm_module = TmModuleGetByName("CudaPacketBatcher");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName CudaPacketBatcher failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_cuda_PB, tm_module, (void *)de_ctx);

        TmThreadSetCPU(tv_cuda_PB, DETECT_CPU_SET);

        if (TmThreadSpawn(tv_cuda_PB) != TM_ECODE_OK) {
            SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }

        ThreadVars *tv_stream1 =
            TmThreadCreatePacketHandler("Stream1",
                    "cuda-pb-queue1", "simple",
                    "stream-queue1", "simple",
                    "1slot");
        if (tv_stream1 == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed for Stream1");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_stream1, tm_module, NULL);

        TmThreadSetCPU(tv_stream1, STREAM_CPU_SET);

        if (TmThreadSpawn(tv_stream1) != TM_ECODE_OK) {
            SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    } else {
        ThreadVars *tv_decode1 =
            TmThreadCreatePacketHandler("Decode & Stream",
                    "pickup-queue", "simple",
                    "stream-queue1", "simple",
                    "varslot");
        if (tv_decode1 == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed for Decode1");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName(decode_mod_name);
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", decode_mod_name);
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);

        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);

        TmThreadSetCPU(tv_decode1, DECODE_CPU_SET);

        if (TmThreadSpawn(tv_decode1) != TM_ECODE_OK) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    }

#else
    ThreadVars *tv_decode1 =
        TmThreadCreatePacketHandler("Decode & Stream",
                "pickup-queue", "simple",
                "stream-queue1", "simple",
                "varslot");
    if (tv_decode1 == NULL) {
        SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed for Decode1");
        exit(EXIT_FAILURE);
    }
    tm_module = TmModuleGetByName(decode_mod_name);
    if (tm_module == NULL) {
        SCLogError(SC_ERR_INVALID_VALUE, "TmModuleGetByName %s failed", decode_mod_name);
        exit(EXIT_FAILURE);
    }
    TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);

    tm_module = TmModuleGetByName("StreamTcp");
    if (tm_module == NULL) {
        SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed");
        exit(EXIT_FAILURE);
    }
    TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);

    TmThreadSetCPU(tv_decode1, DECODE_CPU_SET);

    if (TmThreadSpawn(tv_decode1) != TM_ECODE_OK) {
        SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
        exit(EXIT_FAILURE);
    }
#endif

    /* always create at least one thread */
    int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET);
    if (thread_max == 0)
        thread_max = ncpus * threading_detect_ratio;
    if (thread_max < 1)
        thread_max = 1;

    for (thread = 0; thread < thread_max; thread++) {
        snprintf(tname, sizeof(tname),"Detect%"PRIu16, thread+1);

        char *thread_name = SCStrdup(tname);

        if (thread_name == NULL) {
            SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name");
            exit(EXIT_FAILURE);
        }

        ThreadVars *tv_detect_ncpu =
            TmThreadCreatePacketHandler(thread_name,
                    "stream-queue1", "simple",
                    "verdict-queue", "simple",
                    "1slot");
        if (tv_detect_ncpu == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("Detect");
        if (tm_module == NULL) {
            SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName Detect failed");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppendDelayed(tv_detect_ncpu, tm_module,
                                   (void *)de_ctx, de_ctx->delayed_detect);

        TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET);

        char *thread_group_name = SCStrdup("Detect");
        if (thread_group_name == NULL) {
            SCLogError(SC_ERR_RUNMODE, "Error allocating memory");
            exit(EXIT_FAILURE);
        }
        tv_detect_ncpu->thread_group_name = thread_group_name;

        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
            SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed");
            exit(EXIT_FAILURE);
        }
    }

    ThreadVars *tv_rreject =
        TmThreadCreatePacketHandler("RespondReject",
                "verdict-queue", "simple",
                "alert-queue", "simple",
                "1slot");
    if (tv_rreject == NULL) {
        SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed");
        exit(EXIT_FAILURE);
    }
    tm_module = TmModuleGetByName("RespondReject");
    if (tm_module == NULL) {
        SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for RespondReject failed");
        exit(EXIT_FAILURE);
    }
    TmSlotSetFuncAppend(tv_rreject, tm_module, NULL);

    TmThreadSetCPU(tv_rreject, REJECT_CPU_SET);

    if (TmThreadSpawn(tv_rreject) != TM_ECODE_OK) {
        SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
        exit(EXIT_FAILURE);
    }

    ThreadVars *tv_outputs =
        TmThreadCreatePacketHandler("Outputs",
                "alert-queue", "simple",
                "packetpool", "packetpool",
                "varslot");
    if (tv_outputs == NULL) {
        SCLogError(SC_ERR_RUNMODE, "TmThreadCreatePacketHandler for Outputs failed");
        exit(EXIT_FAILURE);
    }

    SetupOutputs(tv_outputs);

    TmThreadSetCPU(tv_outputs, OUTPUT_CPU_SET);

    if (TmThreadSpawn(tv_outputs) != TM_ECODE_OK) {
        SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed");
        exit(EXIT_FAILURE);
    }

    return 0;
}
Esempio n. 3
0
/*
 * \brief RunModeFilePcapAuto set up the following thread packet handlers:
 *        - Receive thread (from pcap file)
 *        - Decode thread
 *        - Stream thread
 *        - Detect: If we have only 1 cpu, it will setup one Detect thread
 *                  If we have more than one, it will setup num_cpus - 1
 *                  starting from the second cpu available.
 *        - Outputs thread
 *        By default the threads will use the first cpu available
 *        except the Detection threads if we have more than one cpu.
 *
 * \param de_ctx Pointer to the Detection Engine.
 *
 * \retval 0 If all goes well. (If any problem is detected the engine will
 *           exit()).
 */
int RunModeFilePcapAuto(DetectEngineCtx *de_ctx)
{
    SCEnter();
    char tname[16];
    uint16_t cpu = 0;
    TmModule *tm_module;
    int cuda = 0;
    RunModeInitialize();

    /* Available cpus */
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();

    char *file = NULL;
    if (ConfGet("pcap-file.file", &file) == 0) {
        SCLogError(SC_ERR_RUNMODE, "Failed retrieving pcap-file from Conf");
        exit(EXIT_FAILURE);
    }
    SCLogDebug("file %s", file);

    TimeModeSetOffline();

#if defined(__SC_CUDA_SUPPORT__)
    if (PatternMatchDefaultMatcher() == MPM_B2G_CUDA) {
        cuda = 1;
    }
#endif

    if (cuda == 0) {
        /* create the threads */
        ThreadVars *tv_receivepcap =
            TmThreadCreatePacketHandler("ReceivePcapFile",
                    "packetpool", "packetpool",
                    "detect-queue1", "simple",
                    "pktacqloop");
        if (tv_receivepcap == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("ReceivePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, file);

        TmThreadSetCPU(tv_receivepcap, RECEIVE_CPU_SET);

        tm_module = TmModuleGetByName("DecodePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName DecodePcap failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, NULL);

        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName StreamTcp failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, (void *)de_ctx);

        TmThreadSetCPU(tv_receivepcap, DECODE_CPU_SET);

        if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }
#if defined(__SC_CUDA_SUPPORT__)
    } else {
        /* create the threads */
        ThreadVars *tv_receivepcap =
            TmThreadCreatePacketHandler("ReceivePcapFile",
                                        "packetpool", "packetpool",
                                        "cuda-pb", "simple",
                                        "pktacqloop");
        if (tv_receivepcap == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("ReceivePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, file);

        TmThreadSetCPU(tv_receivepcap, RECEIVE_CPU_SET);

        tm_module = TmModuleGetByName("DecodePcapFile");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName DecodePcap failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_receivepcap, tm_module, NULL);

        TmThreadSetCPU(tv_receivepcap, DECODE_CPU_SET);

        if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

        ThreadVars *tv_cuda_PB =
            TmThreadCreate("CUDA_PB",
                           "cuda-pb", "simple",
                           "detect-queue1", "simple",
                           "custom", SCCudaPBTmThreadsSlot1, 0);
        if (tv_cuda_PB == NULL) {
            printf("ERROR: TmThreadsCreate failed for CUDA_PB\n");
            exit(EXIT_FAILURE);
        }
        tv_cuda_PB->type = TVT_PPT;

        tm_module = TmModuleGetByName("CudaPacketBatcher");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName CudaPacketBatcher failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_cuda_PB, tm_module, de_ctx);

        tm_module = TmModuleGetByName("StreamTcp");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName StreamTcp failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_cuda_PB, tm_module, NULL);

        if (TmThreadSpawn(tv_cuda_PB) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

#endif
    }

    /* start with cpu 1 so that if we're creating an odd number of detect
     * threads we're not creating the most on CPU0. */
    if (ncpus > 0)
        cpu = 1;

    /* always create at least one thread */
    int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET);
    if (thread_max == 0)
        thread_max = ncpus * threading_detect_ratio;
    if (thread_max < 1)
        thread_max = 1;

    int thread;
    for (thread = 0; thread < thread_max; thread++) {
        snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1);

        char *thread_name = SCStrdup(tname);
        if (unlikely(thread_name == NULL)) {
            printf("ERROR: Can not strdup thread name\n");
            exit(EXIT_FAILURE);
        }
        SCLogDebug("Assigning %s affinity to cpu %u", thread_name, cpu);

        ThreadVars *tv_detect_ncpu =
            TmThreadCreatePacketHandler(thread_name,
                                        "detect-queue1", "simple",
                                        "alert-queue1", "simple",
                                        "1slot");
        if (tv_detect_ncpu == NULL) {
            printf("ERROR: TmThreadsCreate failed\n");
            exit(EXIT_FAILURE);
        }
        tm_module = TmModuleGetByName("Detect");
        if (tm_module == NULL) {
            printf("ERROR: TmModuleGetByName Detect failed\n");
            exit(EXIT_FAILURE);
        }
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx);

        TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET);

        char *thread_group_name = SCStrdup("Detect");
        if (unlikely(thread_group_name == NULL)) {
            printf("Error allocating memory\n");
            exit(EXIT_FAILURE);
        }
        tv_detect_ncpu->thread_group_name = thread_group_name;

        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
            printf("ERROR: TmThreadSpawn failed\n");
            exit(EXIT_FAILURE);
        }

        if ((cpu + 1) == ncpus)
            cpu = 0;
        else
            cpu++;
    }

    ThreadVars *tv_outputs =
        TmThreadCreatePacketHandler("Outputs",
                                    "alert-queue1", "simple",
                                    "packetpool", "packetpool",
                                    "varslot");
    if (tv_outputs == NULL) {
        printf("ERROR: TmThreadCreatePacketHandler for Outputs failed\n");
        exit(EXIT_FAILURE);
    }

    SetupOutputs(tv_outputs);

    TmThreadSetCPU(tv_outputs, OUTPUT_CPU_SET);

    if (TmThreadSpawn(tv_outputs) != TM_ECODE_OK) {
        printf("ERROR: TmThreadSpawn failed\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}
Esempio n. 4
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 */
}
Esempio n. 5
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);
}