char *RunModeTileGetPipelineConfig(const char *custom_mode) { intmax_t pipelines; intmax_t detect_per_pipe; intmax_t value = 0; char *s; if (custom_mode != NULL) { return custom_mode; } char *runmode = NULL; if (ConfGet("runmode", &runmode) == 1) { if (strcmp(runmode, "workers") == 0) { /* Available cpus */ cpu_set_t cpus; tmc_cpus_get_dataplane_cpus(&cpus); uint16_t ncpus = tmc_cpus_count(&cpus); TileNumPipelines = ncpus - 1; return runmode; } } if (ConfGetInt("tile.pipelines", &pipelines) == 1) { TileNumPipelines = pipelines; } else { TileNumPipelines = DFLT_TILERA_PIPELINES; } SCLogInfo("%d Tilera pipelines", TileNumPipelines); if (ConfGetInt("tile.detect-per-pipeline", &detect_per_pipe) == 1) { TileDetectThreadPerPipeline = detect_per_pipe; } else { TileDetectThreadPerPipeline = DFLT_DETECT_THREADS_PER_PIPELINE; } if ((ConfGetInt("mpipe.poll", &value)) == 1) { /* only 1 and 2 are permitted */ if ((value >= 1) && (value <= 2)) { TileNumPipelinesPerRx = (unsigned int) value; } else { SCLogError(SC_ERR_FATAL, "Illegal mpipe.poll value."); } } if (ConfGet("tile.queue", &s) == 1) { if (strcmp(s, "simple") == 0) { queue_type = simple; } else if (strcmp(s, "tmc") == 0) { queue_type = tmc; } } SCLogInfo("%d detect threads per pipeline", TileDetectThreadPerPipeline); SCLogInfo("%d utilized dataplane tiles", (TILES_PER_PIPELINE * TileNumPipelines) + (TileNumPipelines / 2)); SCLogInfo("%s queueing between tiles", (queue_type == simple) ? "simple" : "tmc"); return NULL; }
void SCAsn1LoadConfig() { intmax_t value = 0; /** set config defaults */ if ((ConfGetInt("asn1-max-frames", &value)) == 1) { asn1_max_frames_config = (uint16_t)value; SCLogDebug("Max stack frame set to %"PRIu16, asn1_max_frames_config); } }
/** * \brief RunModeTileMpipeWorkers set up to process all modules in each thread. * * \param de_ctx pointer to the Detection Engine * \param iface pointer to the name of the interface from which we will * fetch the packets * \retval 0 if all goes well. (If any problem is detected the engine will * exit()) */ int RunModeTileMpipeWorkers(DetectEngineCtx *de_ctx) { SCEnter(); char tname[TM_THREAD_NAME_MAX]; char *thread_name; TmModule *tm_module; int pipe; RunModeInitialize(); /* Available cpus */ uint16_t ncpus = UtilCpuGetNumProcessorsOnline(); TimeModeSetLive(); unsigned int pipe_max = 1; if (ncpus > 1) pipe_max = ncpus - 1; intmax_t threads; if (ConfGetInt("mpipe.threads", &threads) == 1) { tile_num_pipelines = threads; } else { tile_num_pipelines = pipe_max; } SCLogInfo("%d Tilera worker threads", tile_num_pipelines); ReceiveMpipeInit(); char *mpipe_dev = NULL; int nlive = LiveGetDeviceCount(); if (nlive > 0) { SCLogInfo("Using %d live device(s).", nlive); /*mpipe_dev = LiveGetDevice(0);*/ } else { /* * Attempt to get interface from config file * overrides -i from command line. */ if (ConfGet("mpipe.interface", &mpipe_dev) == 0) { if (ConfGet("mpipe.single_mpipe_dev", &mpipe_dev) == 0) { SCLogError(SC_ERR_RUNMODE, "Failed retrieving " "mpipe.single_mpipe_dev from Conf"); exit(EXIT_FAILURE); } } } for (pipe = 0; pipe < tile_num_pipelines; pipe++) { char *mpipe_devc; if (nlive > 0) { mpipe_devc = SCStrdup("multi"); } else { mpipe_devc = SCStrdup(mpipe_dev); } if (unlikely(mpipe_devc == NULL)) { printf("ERROR: SCStrdup failed for ReceiveMpipe\n"); exit(EXIT_FAILURE); } snprintf(tname, sizeof(tname), "Worker%d", pipe+1); thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { printf("ERROR: SCStrdup failed for ReceiveMpipe\n"); exit(EXIT_FAILURE); } /* create the threads */ ThreadVars *tv_worker = TmThreadCreatePacketHandler(thread_name, "packetpool", "packetpool", "packetpool", "packetpool", "pktacqloop"); if (tv_worker == NULL) { printf("ERROR: TmThreadsCreate failed\n"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName("ReceiveMpipe"); if (tm_module == NULL) { printf("ERROR: TmModuleGetByName failed for ReceiveMpipe\n"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_worker, tm_module, (void *)mpipe_devc); /* set affinity for worker */ int pipe_cpu = pipe + 1; TmThreadSetCPUAffinity(tv_worker, pipe_cpu); tm_module = TmModuleGetByName("DecodeMpipe"); if (tm_module == NULL) { printf("ERROR: TmModuleGetByName DecodeMpipe failed\n"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_worker, tm_module, NULL); tm_module = TmModuleGetByName("StreamTcp"); if (tm_module == NULL) { printf("ERROR: TmModuleGetByName StreamTcp failed\n"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_worker, tm_module, NULL); tm_module = TmModuleGetByName("Detect"); if (tm_module == NULL) { printf("ERROR: TmModuleGetByName Detect failed\n"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_worker, tm_module, (void *)de_ctx); tm_module = TmModuleGetByName("RespondReject"); if (tm_module == NULL) { printf("ERROR: TmModuleGetByName for RespondReject failed\n"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_worker, tm_module, NULL); SetupOutputs(tv_worker); if (TmThreadSpawn(tv_worker) != TM_ECODE_OK) { printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } } return 0; }
/** \brief To initialize the NFQ global configuration data * * \param quiet It tells the mode of operation, if it is TRUE nothing will * be get printed. */ void NFQInitConfig(char quiet) { intmax_t value = 0; char* nfq_mode = NULL; int boolval; SCLogDebug("Initializing NFQ"); memset(&nfq_config, 0, sizeof(nfq_config)); if ((ConfGet("nfq.mode", &nfq_mode)) == 0) { nfq_config.mode = NFQ_ACCEPT_MODE; } else { if (!strcmp("accept", nfq_mode)) { nfq_config.mode = NFQ_ACCEPT_MODE; } else if (!strcmp("repeat", nfq_mode)) { nfq_config.mode = NFQ_REPEAT_MODE; } else if (!strcmp("route", nfq_mode)) { nfq_config.mode = NFQ_ROUTE_MODE; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Unknown nfq.mode"); exit(EXIT_FAILURE); } } (void)ConfGetBool("nfq.fail-open", (int *)&boolval); if (boolval) { #ifdef HAVE_NFQ_SET_QUEUE_FLAGS SCLogInfo("Enabling fail-open on queue"); nfq_config.flags |= NFQ_FLAG_FAIL_OPEN; #else SCLogError(SC_ERR_NFQ_NOSUPPORT, "nfq.fail-open set but NFQ library has no support for it."); #endif } if ((ConfGetInt("nfq.repeat-mark", &value)) == 1) { nfq_config.mark = (uint32_t)value; } if ((ConfGetInt("nfq.repeat-mask", &value)) == 1) { nfq_config.mask = (uint32_t)value; } if ((ConfGetInt("nfq.route-queue", &value)) == 1) { nfq_config.next_queue = ((uint32_t)value) << 16; } if (!quiet) { switch (nfq_config.mode) { case NFQ_ACCEPT_MODE: SCLogInfo("NFQ running in standard ACCEPT/DROP mode"); break; case NFQ_REPEAT_MODE: SCLogInfo("NFQ running in REPEAT mode with mark %"PRIu32"/%"PRIu32, nfq_config.mark, nfq_config.mask); break; case NFQ_ROUTE_MODE: SCLogInfo("NFQ running in route mode with next queue %"PRIu32, nfq_config.next_queue); break; } } }
/** * \brief Initialize profiling. */ void SCProfilingInit(void) { ConfNode *conf; SC_ATOMIC_INIT(samples); intmax_t rate_v = 0; (void)ConfGetInt("profiling.sample-rate", &rate_v); if (rate_v > 0 && rate_v < INT_MAX) { rate = (int)rate_v; if (rate != 1) SCLogInfo("profiling runs for every %dth packet", rate); else SCLogInfo("profiling runs for every packet"); } conf = ConfGetNode("profiling.packets"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { profiling_packets_enabled = 1; if (pthread_mutex_init(&packet_profile_lock, NULL) != 0) { SCLogError(SC_ERR_MUTEX, "Failed to initialize packet profiling mutex."); exit(EXIT_FAILURE); } memset(&packet_profile_data4, 0, sizeof(packet_profile_data4)); memset(&packet_profile_data6, 0, sizeof(packet_profile_data6)); memset(&packet_profile_tmm_data4, 0, sizeof(packet_profile_tmm_data4)); memset(&packet_profile_tmm_data6, 0, sizeof(packet_profile_tmm_data6)); memset(&packet_profile_app_data4, 0, sizeof(packet_profile_app_data4)); memset(&packet_profile_app_data6, 0, sizeof(packet_profile_app_data6)); memset(&packet_profile_app_pd_data4, 0, sizeof(packet_profile_app_pd_data4)); memset(&packet_profile_app_pd_data6, 0, sizeof(packet_profile_app_pd_data6)); memset(&packet_profile_detect_data4, 0, sizeof(packet_profile_detect_data4)); memset(&packet_profile_detect_data6, 0, sizeof(packet_profile_detect_data6)); memset(&packet_profile_log_data4, 0, sizeof(packet_profile_log_data4)); memset(&packet_profile_log_data6, 0, sizeof(packet_profile_log_data6)); memset(&packet_profile_flowworker_data, 0, sizeof(packet_profile_flowworker_data)); const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename != NULL) { char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_packets_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_packets_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name"); exit(EXIT_FAILURE); } snprintf(profiling_packets_file_name, PATH_MAX, "%s/%s", log_dir, filename); const char *v = ConfNodeLookupChildValue(conf, "append"); if (v == NULL || ConfValIsTrue(v)) { profiling_packets_file_mode = "a"; } else { profiling_packets_file_mode = "w"; } profiling_packets_output_to_file = 1; } } conf = ConfGetNode("profiling.packets.csv"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename == NULL) { filename = "packet_profile.csv"; } char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_csv_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_csv_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "out of memory"); exit(EXIT_FAILURE); } snprintf(profiling_csv_file_name, PATH_MAX, "%s/%s", log_dir, filename); packet_profile_csv_fp = fopen(profiling_csv_file_name, "w"); if (packet_profile_csv_fp == NULL) { return; } fprintf(packet_profile_csv_fp, "pcap_cnt,ipver,ipproto,total,"); int i; for (i = 0; i < TMM_SIZE; i++) { fprintf(packet_profile_csv_fp, "%s,", TmModuleTmmIdToString(i)); } fprintf(packet_profile_csv_fp, "threading,"); for (i = 0; i < ALPROTO_MAX; i++) { fprintf(packet_profile_csv_fp, "%s,", AppProtoToString(i)); } fprintf(packet_profile_csv_fp, "proto detect,"); for (i = 0; i < PROF_DETECT_SIZE; i++) { fprintf(packet_profile_csv_fp, "%s,", PacketProfileDetectIdToString(i)); } fprintf(packet_profile_csv_fp, "\n"); profiling_packets_csv_enabled = 1; } } } conf = ConfGetNode("profiling.locks"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { #ifndef PROFILE_LOCKING SCLogWarning(SC_WARN_PROFILE, "lock profiling not compiled in. Add --enable-profiling-locks to configure."); #else profiling_locks_enabled = 1; LockRecordInitHash(); const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename != NULL) { char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_locks_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_locks_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name"); exit(EXIT_FAILURE); } snprintf(profiling_locks_file_name, PATH_MAX, "%s/%s", log_dir, filename); const char *v = ConfNodeLookupChildValue(conf, "append"); if (v == NULL || ConfValIsTrue(v)) { profiling_locks_file_mode = "a"; } else { profiling_locks_file_mode = "w"; } profiling_locks_output_to_file = 1; } #endif } } }
TmEcode ReceivePcapFileThreadInit(ThreadVars *tv, void *initdata, void **data) { SCEnter(); char *tmpbpfstring = NULL; char *tmpstring = NULL; if (initdata == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "error: initdata == NULL"); SCReturnInt(TM_ECODE_FAILED); } SCLogInfo("reading pcap file %s", (char *)initdata); PcapFileThreadVars *ptv = SCMalloc(sizeof(PcapFileThreadVars)); if (unlikely(ptv == NULL)) SCReturnInt(TM_ECODE_FAILED); memset(ptv, 0, sizeof(PcapFileThreadVars)); intmax_t tenant = 0; if (ConfGetInt("pcap-file.tenant-id", &tenant) == 1) { if (tenant > 0 && tenant < UINT_MAX) { ptv->tenant_id = (uint32_t)tenant; SCLogInfo("tenant %u", ptv->tenant_id); } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant out of range"); } } char errbuf[PCAP_ERRBUF_SIZE] = ""; pcap_g.pcap_handle = pcap_open_offline((char *)initdata, errbuf); if (pcap_g.pcap_handle == NULL) { SCLogError(SC_ERR_FOPEN, "%s\n", errbuf); SCFree(ptv); if (! RunModeUnixSocketIsActive()) { return TM_ECODE_FAILED; } else { UnixSocketPcapFile(TM_ECODE_FAILED); SCReturnInt(TM_ECODE_DONE); } } if (ConfGet("bpf-filter", &tmpbpfstring) != 1) { SCLogDebug("could not get bpf or none specified"); } else { SCLogInfo("using bpf-filter \"%s\"", tmpbpfstring); if (pcap_compile(pcap_g.pcap_handle, &pcap_g.filter, tmpbpfstring, 1, 0) < 0) { SCLogError(SC_ERR_BPF,"bpf compilation error %s", pcap_geterr(pcap_g.pcap_handle)); SCFree(ptv); return TM_ECODE_FAILED; } if (pcap_setfilter(pcap_g.pcap_handle, &pcap_g.filter) < 0) { SCLogError(SC_ERR_BPF,"could not set bpf filter %s", pcap_geterr(pcap_g.pcap_handle)); SCFree(ptv); return TM_ECODE_FAILED; } } pcap_g.datalink = pcap_datalink(pcap_g.pcap_handle); SCLogDebug("datalink %" PRId32 "", pcap_g.datalink); switch (pcap_g.datalink) { case LINKTYPE_LINUX_SLL: pcap_g.Decoder = DecodeSll; break; case LINKTYPE_ETHERNET: pcap_g.Decoder = DecodeEthernet; break; case LINKTYPE_PPP: pcap_g.Decoder = DecodePPP; break; case LINKTYPE_RAW: pcap_g.Decoder = DecodeRaw; break; case LINKTYPE_NULL: pcap_g.Decoder = DecodeNull; break; default: SCLogError(SC_ERR_UNIMPLEMENTED, "datalink type %" PRId32 " not " "(yet) supported in module PcapFile.\n", pcap_g.datalink); SCFree(ptv); if (! RunModeUnixSocketIsActive()) { SCReturnInt(TM_ECODE_FAILED); } else { pcap_close(pcap_g.pcap_handle); pcap_g.pcap_handle = NULL; UnixSocketPcapFile(TM_ECODE_DONE); SCReturnInt(TM_ECODE_DONE); } } if (ConfGet("pcap-file.checksum-checks", &tmpstring) != 1) { pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO; } else { if (strcmp(tmpstring, "auto") == 0) { pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_AUTO; } else if (strcmp(tmpstring, "yes") == 0) { pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_ENABLE; } else if (strcmp(tmpstring, "no") == 0) { pcap_g.conf_checksum_mode = CHECKSUM_VALIDATION_DISABLE; } } pcap_g.checksum_mode = pcap_g.conf_checksum_mode; ptv->tv = tv; *data = (void *)ptv; SCReturnInt(TM_ECODE_OK); }
void *ParsePcapConfig(const char *iface) { char *threadsstr = NULL; ConfNode *if_root; ConfNode *pcap_node; PcapIfaceConfig *aconf = SCMalloc(sizeof(*aconf)); char *tmpbpf; char *tmpctype; intmax_t value; if (unlikely(aconf == NULL)) { return NULL; } if (iface == NULL) { SCFree(aconf); return NULL; } memset(aconf, 0x00, sizeof(*aconf)); strlcpy(aconf->iface, iface, sizeof(aconf->iface)); aconf->buffer_size = 0; /* If set command line option has precedence over config */ if ((ConfGetInt("pcap.buffer-size", &value)) == 1) { SCLogInfo("Pcap will use %d buffer size", (int)value); aconf->buffer_size = value; } aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; aconf->bpf_filter = NULL; if ((ConfGet("bpf-filter", &tmpbpf)) == 1) { aconf->bpf_filter = tmpbpf; } SC_ATOMIC_INIT(aconf->ref); aconf->DerefFunc = PcapDerefConfig; aconf->threads = 1; /* Find initial node */ pcap_node = ConfGetNode("pcap"); if (pcap_node == NULL) { SCLogInfo("Unable to find pcap config using default value"); return aconf; } if_root = ConfNodeLookupKeyValue(pcap_node, "interface", iface); if (if_root == NULL) { SCLogInfo("Unable to find pcap config for " "interface %s, using default value", iface); return aconf; } if (ConfGetChildValue(if_root, "threads", &threadsstr) != 1) { aconf->threads = 1; } else { if (threadsstr != NULL) { aconf->threads = (uint8_t)atoi(threadsstr); } } if (aconf->threads == 0) { aconf->threads = 1; } (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads); if (aconf->buffer_size == 0) { const char *s_limit = ConfNodeLookupChildValue(if_root, "buffer-size"); if (s_limit != NULL) { uint64_t bsize = 0; if (ParseSizeStringU64(s_limit, &bsize) < 0) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to parse pcap buffer size: %s", s_limit); } else { /* the string 2gb returns 2147483648 which is 1 to high * for a int. */ if (bsize == (uint64_t)((uint64_t)INT_MAX + (uint64_t)1)) bsize = (uint64_t)INT_MAX; if (bsize > INT_MAX) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to set pcap buffer size: 2gb max. %"PRIu64" > %d", bsize, INT_MAX); } else { aconf->buffer_size = (int)bsize; } } } } if (aconf->bpf_filter == NULL) { /* set bpf filter if we have one */ if (ConfGetChildValue(if_root, "bpf-filter", &tmpbpf) != 1) { SCLogDebug("could not get bpf or none specified"); } else { aconf->bpf_filter = tmpbpf; } } else { SCLogInfo("BPF filter set from command line or via old 'bpf-filter' option."); } if (ConfGetChildValue(if_root, "checksum-checks", &tmpctype) == 1) { if (strcmp(tmpctype, "auto") == 0) { aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else if (strcmp(tmpctype, "yes") == 0) { aconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE; } else if (strcmp(tmpctype, "no") == 0) { aconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface); } } return aconf; }
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); }