/** * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. * \return A LogFileCtx pointer on success, NULL on failure. */ OutputCtx *OutputJsonInitCtx(ConfNode *conf) { OutputJsonCtx *json_ctx = SCCalloc(1, sizeof(OutputJsonCtx));; /* First lookup a sensor-name value in this outputs configuration * node (deprecated). If that fails, lookup the global one. */ const char *sensor_name = ConfNodeLookupChildValue(conf, "sensor-name"); if (sensor_name != NULL) { SCLogWarning(SC_ERR_DEPRECATED_CONF, "Found deprecated eve-log setting \"sensor-name\". " "Please set sensor-name globally."); } else { (void)ConfGet("sensor-name", (char **)&sensor_name); } if (unlikely(json_ctx == NULL)) { SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx"); return NULL; } json_ctx->file_ctx = LogFileNewCtx(); if (unlikely(json_ctx->file_ctx == NULL)) { SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx"); SCFree(json_ctx); return NULL; } if (sensor_name) { json_ctx->file_ctx->sensor_name = SCStrdup(sensor_name); if (json_ctx->file_ctx->sensor_name == NULL) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); return NULL; } } else { json_ctx->file_ctx->sensor_name = NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); return NULL; } output_ctx->data = json_ctx; output_ctx->DeInit = OutputJsonDeInitCtx; if (conf) { const char *output_s = ConfNodeLookupChildValue(conf, "filetype"); // Backwards compatibility if (output_s == NULL) { output_s = ConfNodeLookupChildValue(conf, "type"); } if (output_s != NULL) { if (strcmp(output_s, "file") == 0 || strcmp(output_s, "regular") == 0) { json_ctx->json_out = LOGFILE_TYPE_FILE; } else if (strcmp(output_s, "syslog") == 0) { json_ctx->json_out = LOGFILE_TYPE_SYSLOG; } else if (strcmp(output_s, "unix_dgram") == 0) { json_ctx->json_out = LOGFILE_TYPE_UNIX_DGRAM; } else if (strcmp(output_s, "unix_stream") == 0) { json_ctx->json_out = LOGFILE_TYPE_UNIX_STREAM; } else if (strcmp(output_s, "redis") == 0) { #ifdef HAVE_LIBHIREDIS json_ctx->json_out = LOGFILE_TYPE_REDIS; #else SCLogError(SC_ERR_INVALID_ARGUMENT, "redis JSON output option is not compiled"); exit(EXIT_FAILURE); #endif } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON output option: %s", output_s); exit(EXIT_FAILURE); } } const char *prefix = ConfNodeLookupChildValue(conf, "prefix"); if (prefix != NULL) { SCLogInfo("Using prefix '%s' for JSON messages", prefix); json_ctx->file_ctx->prefix = SCStrdup(prefix); if (json_ctx->file_ctx->prefix == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for eve-log.prefix setting."); exit(EXIT_FAILURE); } json_ctx->file_ctx->prefix_len = strlen(prefix); } if (json_ctx->json_out == LOGFILE_TYPE_FILE || json_ctx->json_out == LOGFILE_TYPE_UNIX_DGRAM || json_ctx->json_out == LOGFILE_TYPE_UNIX_STREAM) { if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return NULL; } OutputRegisterFileRotationFlag(&json_ctx->file_ctx->rotation_flag); const char *format_s = ConfNodeLookupChildValue(conf, "format"); if (format_s != NULL) { if (strcmp(format_s, "indent") == 0) { json_ctx->format = INDENT; } else if (strcmp(format_s, "compact") == 0) { json_ctx->format = COMPACT; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON format option: %s", format_s); exit(EXIT_FAILURE); } } } else if (json_ctx->json_out == LOGFILE_TYPE_SYSLOG) { const char *facility_s = ConfNodeLookupChildValue(conf, "facility"); if (facility_s == NULL) { facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR; } int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap()); if (facility == -1) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\"," " now using \"%s\" as syslog facility", facility_s, DEFAULT_ALERT_SYSLOG_FACILITY_STR); facility = DEFAULT_ALERT_SYSLOG_FACILITY; } const char *level_s = ConfNodeLookupChildValue(conf, "level"); if (level_s != NULL) { int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap()); if (level != -1) { json_ctx->file_ctx->syslog_setup.alert_syslog_level = level; } } const char *ident = ConfNodeLookupChildValue(conf, "identity"); /* if null we just pass that to openlog, which will then * figure it out by itself. */ openlog(ident, LOG_PID|LOG_NDELAY, facility); } #ifdef HAVE_LIBHIREDIS else if (json_ctx->json_out == LOGFILE_TYPE_REDIS) { ConfNode *redis_node = ConfNodeLookupChild(conf, "redis"); if (!json_ctx->file_ctx->sensor_name) { char hostname[1024]; gethostname(hostname, 1023); json_ctx->file_ctx->sensor_name = SCStrdup(hostname); } if (json_ctx->file_ctx->sensor_name == NULL) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return NULL; } if (SCConfLogOpenRedis(redis_node, json_ctx->file_ctx) < 0) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return NULL; } } #endif const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id"); if (sensor_id_s != NULL) { if (ByteExtractStringUint64((uint64_t *)&sensor_id, 10, 0, sensor_id_s) == -1) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize JSON output, " "invalid sensor-is: %s", sensor_id_s); exit(EXIT_FAILURE); } } json_ctx->file_ctx->type = json_ctx->json_out; } SCLogDebug("returning output_ctx %p", output_ctx); return output_ctx; }
static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, char *depthstr) { char *str = depthstr; char dubbed = 0; SigMatch *pm = NULL; int ret = -1; /* strip "'s */ if (depthstr[0] == '\"' && depthstr[strlen(depthstr) - 1] == '\"') { str = SCStrdup(depthstr + 1); if (unlikely(str == NULL)) goto end; str[strlen(depthstr) - 2] = '\0'; dubbed = 1; } /* retrive the sm to apply the depth against */ if (s->list != DETECT_SM_LIST_NOTSET) { pm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[s->list]); } else { pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); } if (pm == NULL) { SCLogError(SC_ERR_DEPTH_MISSING_CONTENT, "depth needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, http_user_agent, " "http_host, http_raw_host or " "file_data/dce_stub_data sticky buffer options"); goto end; } /* verify other conditions. */ DetectContentData *cd = (DetectContentData *)pm->ctx; if (cd->flags & DETECT_CONTENT_DEPTH) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple depths for the same content."); goto end; } if ((cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_DISTANCE)) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use a relative " "keyword like within/distance with a absolute " "relative keyword like depth/offset for the same " "content." ); goto end; } if (cd->flags & DETECT_CONTENT_NEGATED && cd->flags & DETECT_CONTENT_FAST_PATTERN) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a fast_pattern"); goto end; } if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "keyword set along with a fast_pattern:only;"); goto end; } if (str[0] != '-' && isalpha((unsigned char)str[0])) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(str, s); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "unknown byte_extract var " "seen in depth - %s\n", str); goto end; } cd->depth = ((DetectByteExtractData *)bed_sm->ctx)->local_id; cd->flags |= DETECT_CONTENT_DEPTH_BE; } else { cd->depth = (uint32_t)atoi(str); if (cd->depth < cd->content_len) { SCLogError(SC_ERR_INVALID_SIGNATURE, "depth - %"PRIu16 " smaller than content length - %"PRIu32, cd->depth, cd->content_len); goto end; } /* Now update the real limit, as depth is relative to the offset */ cd->depth += cd->offset; } cd->flags |= DETECT_CONTENT_DEPTH; ret = 0; end: if (dubbed) SCFree(str); return ret; }
/** * \brief Init function for RecievePfring. * * This is a setup function for recieving packets * via libpfring. * * \param tv pointer to ThreadVars * \param initdata pointer to the interface passed from the user * \param data pointer gets populated with PfringThreadVars * \todo add a config option for setting cluster id * \todo Create a general pfring setup function. * \retval TM_ECODE_OK on success * \retval TM_ECODE_FAILED on error */ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { int rc; u_int32_t version = 0; PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata; unsigned int opflag; if (pfconf == NULL) return TM_ECODE_FAILED; PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars)); if (unlikely(ptv == NULL)) { pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } memset(ptv, 0, sizeof(PfringThreadVars)); ptv->tv = tv; ptv->threads = 1; ptv->interface = SCStrdup(pfconf->iface); if (unlikely(ptv->interface == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate device string"); SCReturnInt(TM_ECODE_FAILED); } ptv->livedev = LiveGetDevice(pfconf->iface); if (ptv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); SCReturnInt(TM_ECODE_FAILED); } ptv->checksum_mode = pfconf->checksum_mode; opflag = PF_RING_REENTRANT | PF_RING_PROMISC; /* if suri uses VLAN and if we have a recent kernel, we need * to use parsed_pkt to get VLAN info */ if ((! ptv->vlan_disabled) && SCKernelVersionIsAtLeast(3, 0)) { opflag |= PF_RING_LONG_HEADER; } if (ptv->checksum_mode == CHECKSUM_VALIDATION_RXONLY) { if (strncmp(ptv->interface, "dna", 3) == 0) { SCLogWarning(SC_ERR_INVALID_VALUE, "Can't use rxonly checksum-checks on DNA interface," " resetting to auto"); ptv->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else { opflag |= PF_RING_LONG_HEADER; } } #ifdef HAVE_PFRING_OPEN_NEW ptv->pd = pfring_open(ptv->interface, (uint32_t)default_packet_size, opflag); #else ptv->pd = pfring_open(ptv->interface, LIBPFRING_PROMISC, (uint32_t)default_packet_size, LIBPFRING_REENTRANT); #endif if (ptv->pd == NULL) { SCLogError(SC_ERR_PF_RING_OPEN,"Failed to open %s: pfring_open error." " Check if %s exists and pf_ring module is loaded.", ptv->interface, ptv->interface); pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } else { pfring_set_application_name(ptv->pd, PROG_NAME); pfring_version(ptv->pd, &version); } /* We only set cluster info if the number of pfring threads is greater than 1 */ ptv->threads = pfconf->threads; ptv->cluster_id = pfconf->cluster_id; if ((ptv->threads == 1) && (strncmp(ptv->interface, "dna", 3) == 0)) { SCLogInfo("DNA interface detected, not adding thread to cluster"); } else if (strncmp(ptv->interface, "zc", 2) == 0) { SCLogInfo("ZC interface detected, not adding thread to cluster"); } else { #ifdef HAVE_PFRING_CLUSTER_TYPE ptv->ctype = pfconf->ctype; rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); #else rc = pfring_set_cluster(ptv->pd, ptv->cluster_id); #endif /* HAVE_PFRING_CLUSTER_TYPE */ if (rc != 0) { SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster " "returned %d for cluster-id: %d", rc, ptv->cluster_id); pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } } if (ptv->threads > 1) { SCLogInfo("(%s) Using PF_RING v.%d.%d.%d, interface %s, cluster-id %d", tv->name, (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF, ptv->interface, ptv->cluster_id); } else {
/** * \internal * \brief This function is used to parse threshold options passed via threshold: keyword * * \param rawstr Pointer to the user provided threshold options * * \retval de pointer to DetectThresholdData on success * \retval NULL on failure */ static DetectThresholdData *DetectThresholdParse(char *rawstr) { DetectThresholdData *de = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; const char *str_ptr = NULL; char *args[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char *copy_str = NULL, *threshold_opt = NULL; int second_found = 0, count_found = 0; int type_found = 0, track_found = 0; int second_pos = 0, count_pos = 0; uint16_t pos = 0; int i = 0; copy_str = SCStrdup(rawstr); if (unlikely(copy_str == NULL)) { goto error; } for(pos = 0, threshold_opt = strtok(copy_str,","); pos < strlen(copy_str) && threshold_opt != NULL; pos++, threshold_opt = strtok(NULL,",")) { if(strstr(threshold_opt,"count")) count_found++; if(strstr(threshold_opt,"second")) second_found++; if(strstr(threshold_opt,"type")) type_found++; if(strstr(threshold_opt,"track")) track_found++; } SCFree(copy_str); copy_str = NULL; if(count_found != 1 || second_found != 1 || type_found != 1 || track_found != 1) goto error; ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 5) { SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); goto error; } de = SCMalloc(sizeof(DetectThresholdData)); if (unlikely(de == NULL)) goto error; memset(de,0,sizeof(DetectThresholdData)); for (i = 0; i < (ret - 1); i++) { res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS,i + 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } args[i] = (char *)str_ptr; if (strncasecmp(args[i],"limit",strlen("limit")) == 0) de->type = TYPE_LIMIT; if (strncasecmp(args[i],"both",strlen("both")) == 0) de->type = TYPE_BOTH; if (strncasecmp(args[i],"threshold",strlen("threshold")) == 0) de->type = TYPE_THRESHOLD; if (strncasecmp(args[i],"by_dst",strlen("by_dst")) == 0) de->track = TRACK_DST; if (strncasecmp(args[i],"by_src",strlen("by_src")) == 0) de->track = TRACK_SRC; if (strncasecmp(args[i],"count",strlen("count")) == 0) count_pos = i+1; if (strncasecmp(args[i],"seconds",strlen("seconds")) == 0) second_pos = i+1; } if (args[count_pos] == NULL || args[second_pos] == NULL) { goto error; } if (ByteExtractStringUint32(&de->count, 10, strlen(args[count_pos]), args[count_pos]) <= 0) { goto error; } if (ByteExtractStringUint32(&de->seconds, 10, strlen(args[second_pos]), args[second_pos]) <= 0) { goto error; } for (i = 0; i < (ret - 1); i++) { if (args[i] != NULL) SCFree(args[i]); } return de; error: for (i = 0; i < (ret - 1); i++) { if (args[i] != NULL) SCFree(args[i]); } if (de != NULL) SCFree(de); return NULL; }
int RunModeSetLiveCaptureAutoFp(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, char *recv_mod_name, char *decode_mod_name, char *thread_name, const char *live_dev) { char tname[TM_THREAD_NAME_MAX]; char qname[TM_QUEUE_NAME_MAX]; char *queues = NULL; int thread = 0; /* Available cpus */ uint16_t ncpus = UtilCpuGetNumProcessorsOnline(); int nlive = LiveGetDeviceCount(); int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET); /* always create at least one thread */ if (thread_max == 0) thread_max = ncpus * threading_detect_ratio; if (thread_max < 1) thread_max = 1; RunmodeSetFlowStreamAsync(); queues = RunmodeAutoFpCreatePickupQueuesString(thread_max); if (queues == NULL) { SCLogError(SC_ERR_RUNMODE, "RunmodeAutoFpCreatePickupQueuesString failed"); exit(EXIT_FAILURE); } if ((nlive <= 1) && (live_dev != NULL)) { void *aconf; int threads_count; SCLogDebug("live_dev %s", live_dev); aconf = ConfigParser(live_dev); if (aconf == NULL) { SCLogError(SC_ERR_RUNMODE, "Failed to allocate config for %s (%d)", live_dev, thread); exit(EXIT_FAILURE); } threads_count = ModThreadsCount(aconf); SCLogInfo("Going to use %" PRId32 " %s receive thread(s)", threads_count, recv_mod_name); /* create the threads */ for (thread = 0; thread < threads_count; thread++) { snprintf(tname, sizeof(tname), "%s%d", thread_name, thread+1); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name"); exit(EXIT_FAILURE); } ThreadVars *tv_receive = TmThreadCreatePacketHandler(thread_name, "packetpool", "packetpool", queues, "flow", "pktacqloop"); if (tv_receive == NULL) { SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName(recv_mod_name); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName failed for %s", recv_mod_name); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_receive, tm_module, aconf); 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_receive, tm_module, NULL); TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET); if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } } else { /* Multiple input device */ SCLogInfo("Using %d live device(s).", nlive); int lthread; for (lthread = 0; lthread < nlive; lthread++) { char *live_dev = LiveGetDeviceName(lthread); void *aconf; int threads_count; if (live_dev == NULL) { SCLogError(SC_ERR_RUNMODE, "Failed to lookup live dev %d", lthread); exit(EXIT_FAILURE); } SCLogDebug("live_dev %s", live_dev); aconf = ConfigParser(live_dev); if (aconf == NULL) { SCLogError(SC_ERR_RUNMODE, "Multidev: Failed to allocate config for %s (%d)", live_dev, lthread); exit(EXIT_FAILURE); } threads_count = ModThreadsCount(aconf); for (thread = 0; thread < threads_count; thread++) { snprintf(tname, sizeof(tname), "%s%s%d", thread_name, live_dev, thread+1); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name"); exit(EXIT_FAILURE); } ThreadVars *tv_receive = TmThreadCreatePacketHandler(thread_name, "packetpool", "packetpool", queues, "flow", "pktacqloop"); if (tv_receive == NULL) { SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName(recv_mod_name); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName failed for %s", recv_mod_name); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_receive, tm_module, aconf); 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_receive, tm_module, NULL); TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET); if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } } } for (thread = 0; thread < thread_max; thread++) { snprintf(tname, sizeof(tname), "Detect%d", thread+1); snprintf(qname, sizeof(qname), "pickup%d", thread+1); SCLogDebug("tname %s, qname %s", tname, qname); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name"); exit(EXIT_FAILURE); } ThreadVars *tv_detect_ncpu = TmThreadCreatePacketHandler(thread_name, qname, "flow", "packetpool", "packetpool", "varslot"); if (tv_detect_ncpu == NULL) { SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName("StreamTcp"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL); if (DetectEngineEnabled()) { tm_module = TmModuleGetByName("Detect"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName Detect failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL); } TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET); char *thread_group_name = SCStrdup("Detect"); if (unlikely(thread_group_name == NULL)) { SCLogError(SC_ERR_RUNMODE, "Error allocating memory"); exit(EXIT_FAILURE); } tv_detect_ncpu->thread_group_name = thread_group_name; tm_module = TmModuleGetByName("RespondReject"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName RespondReject failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL); /* add outputs as well */ SetupOutputs(tv_detect_ncpu); if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } SCFree(queues); return 0; }
int RunModeSetIPSAutoFp(ConfigIPSParserFunc ConfigParser, char *recv_mod_name, char *verdict_mod_name, char *decode_mod_name) { SCEnter(); char tname[TM_THREAD_NAME_MAX]; char qname[TM_QUEUE_NAME_MAX]; TmModule *tm_module ; char *cur_queue = NULL; char *queues = NULL; int thread; /* Available cpus */ uint16_t ncpus = UtilCpuGetNumProcessorsOnline(); int nqueue = LiveGetDeviceCount(); int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET); /* always create at least one thread */ if (thread_max == 0) thread_max = ncpus * threading_detect_ratio; if (thread_max < 1) thread_max = 1; RunmodeSetFlowStreamAsync(); queues = RunmodeAutoFpCreatePickupQueuesString(thread_max); if (queues == NULL) { SCLogError(SC_ERR_RUNMODE, "RunmodeAutoFpCreatePickupQueuesString failed"); exit(EXIT_FAILURE); } for (int i = 0; i < nqueue; i++) { /* create the threads */ cur_queue = LiveGetDeviceName(i); if (cur_queue == NULL) { SCLogError(SC_ERR_RUNMODE, "invalid queue number"); exit(EXIT_FAILURE); } memset(tname, 0, sizeof(tname)); snprintf(tname, sizeof(tname), "Recv-Q%s", cur_queue); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_RUNMODE, "thread name creation failed"); exit(EXIT_FAILURE); } ThreadVars *tv_receive = TmThreadCreatePacketHandler(thread_name, "packetpool", "packetpool", queues, "flow", "pktacqloop"); if (tv_receive == NULL) { SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName(recv_mod_name); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName failed for %s", recv_mod_name); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_receive, tm_module, (void *) ConfigParser(i)); 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_receive, tm_module, NULL); TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET); if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } for (thread = 0; thread < thread_max; thread++) { snprintf(tname, sizeof(tname), "Detect%d", thread+1); snprintf(qname, sizeof(qname), "pickup%d", thread+1); SCLogDebug("tname %s, qname %s", tname, qname); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name"); exit(EXIT_FAILURE); } ThreadVars *tv_detect_ncpu = TmThreadCreatePacketHandler(thread_name, qname, "flow", "verdict-queue", "simple", "varslot"); if (tv_detect_ncpu == NULL) { SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } TmModule *tm_module = TmModuleGetByName("StreamTcp"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL); if (DetectEngineEnabled()) { tm_module = TmModuleGetByName("Detect"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName Detect failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL); } TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET); SetupOutputs(tv_detect_ncpu); char *thread_group_name = SCStrdup("Detect"); if (unlikely(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_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } /* create the threads */ for (int i = 0; i < nqueue; i++) { memset(tname, 0, sizeof(tname)); snprintf(tname, sizeof(tname), "Verdict%d", i); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_RUNMODE, "Error allocating memory"); exit(EXIT_FAILURE); } ThreadVars *tv_verdict = TmThreadCreatePacketHandler(thread_name, "verdict-queue", "simple", "packetpool", "packetpool", "varslot"); if (tv_verdict == NULL) { SCLogError(SC_ERR_RUNMODE, "TmThreadsCreate failed"); exit(EXIT_FAILURE); } tm_module = TmModuleGetByName(verdict_mod_name); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", verdict_mod_name); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_verdict, tm_module, (void *)ConfigParser(i)); tm_module = TmModuleGetByName("RespondReject"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for RespondReject failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_verdict, tm_module, NULL); TmThreadSetCPU(tv_verdict, VERDICT_CPU_SET); if (TmThreadSpawn(tv_verdict) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } SCFree(queues); return 0; }
/** * \brief This function is used to parse a flowint option * * \param de_ctx pointer to the engine context * \param rawstr pointer to the string holding the options * * \retval NULL if invalid option * \retval DetectFlowintData pointer with the flowint parsed */ DetectFlowintData *DetectFlowintParse(DetectEngineCtx *de_ctx, char *rawstr) { DetectFlowintData *sfd = NULL; char *varname = NULL; char *varval = NULL; char *modstr = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; uint8_t modifier = FLOWINT_MODIFIER_UNKNOWN; unsigned long long value_long = 0; const char *str_ptr; ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 3 || ret > 4) { SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowint(ret = %d).", rawstr, ret); return NULL; } /* Get our flowint varname */ res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0 || str_ptr == NULL) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } varname = (char *)str_ptr; res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); if (res < 0 || str_ptr == NULL) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } modstr = (char *)str_ptr; /* Get the modifier */ if (strcmp("=", modstr) == 0) modifier = FLOWINT_MODIFIER_SET; if (strcmp("+", modstr) == 0) modifier = FLOWINT_MODIFIER_ADD; if (strcmp("-", modstr) == 0) modifier = FLOWINT_MODIFIER_SUB; if (strcmp("<", modstr) == 0) modifier = FLOWINT_MODIFIER_LT; if (strcmp("<=", modstr) == 0) modifier = FLOWINT_MODIFIER_LE; if (strcmp("!=", modstr) == 0) modifier = FLOWINT_MODIFIER_NE; if (strcmp("==", modstr) == 0) modifier = FLOWINT_MODIFIER_EQ; if (strcmp(">=", modstr) == 0) modifier = FLOWINT_MODIFIER_GE; if (strcmp(">", modstr) == 0) modifier = FLOWINT_MODIFIER_GT; if (strcmp("isset", modstr) == 0) modifier = FLOWINT_MODIFIER_ISSET; if (strcmp("notset", modstr) == 0) modifier = FLOWINT_MODIFIER_NOTSET; if (modifier == FLOWINT_MODIFIER_UNKNOWN) { SCLogError(SC_ERR_UNKNOWN_VALUE, "Unknown modifier"); goto error; } sfd = SCMalloc(sizeof(DetectFlowintData)); if (unlikely(sfd == NULL)) goto error; /* If we need another arg, check it out(isset doesn't need another arg) */ if (modifier != FLOWINT_MODIFIER_ISSET && modifier != FLOWINT_MODIFIER_NOTSET) { if (ret < 4) goto error; res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 3, &str_ptr); varval = (char *)str_ptr; if (res < 0 || varval == NULL || strcmp(varval, "") == 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } if (varval[0] >= '0' && varval[0] <= '9') { /* is digit, look at the regexp */ sfd->targettype = FLOWINT_TARGET_VAL; value_long = atoll(varval); if (value_long > UINT32_MAX) { SCLogDebug("DetectFlowintParse: Cannot load this value." " Values should be between 0 and %"PRIu32, UINT32_MAX); goto error; } sfd->target.value = (uint32_t) value_long; } else { sfd->targettype = FLOWINT_TARGET_VAR; sfd->target.tvar.name = SCStrdup(varval); if (unlikely(sfd->target.tvar.name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed"); goto error; } } } else { sfd->targettype = FLOWINT_TARGET_SELF; } /* Set the name of the origin var to modify/compared with the target */ sfd->name = SCStrdup(varname); if (unlikely(sfd->name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed"); goto error; } if (de_ctx != NULL) sfd->idx = VariableNameGetIdx(de_ctx, varname, VAR_TYPE_FLOW_INT); sfd->modifier = modifier; pcre_free_substring(varname); pcre_free_substring(modstr); if (varval) pcre_free_substring(varval); return sfd; error: if (varname) pcre_free_substring(varname); if (varval) pcre_free_substring(varval); if (modstr) pcre_free_substring(modstr); if (sfd != NULL) SCFree(sfd); return NULL; }
/** \brief Create a new LogFileCtx from the provided ConfNode. * \param conf The configuration node for this output. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ OutputCtx *Unified2AlertInitCtx(ConfNode *conf) { int ret = 0; LogFileCtx* file_ctx = NULL; file_ctx = LogFileNewCtx(); if (file_ctx == NULL) { SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Couldn't create new file_ctx"); goto error; } const char *filename = NULL; if (conf != NULL) { /* To faciliate unit tests. */ filename = ConfNodeLookupChildValue(conf, "filename"); } if (filename == NULL) filename = DEFAULT_LOG_FILENAME; file_ctx->prefix = SCStrdup(filename); const char *s_limit = NULL; file_ctx->size_limit = DEFAULT_LIMIT; if (conf != NULL) { s_limit = ConfNodeLookupChildValue(conf, "limit"); if (s_limit != NULL) { if (ParseSizeStringU64(s_limit, &file_ctx->size_limit) < 0) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid limit: %s", s_limit); exit(EXIT_FAILURE); } if (file_ctx->size_limit < 4096) { SCLogInfo("unified2-alert \"limit\" value of %"PRIu64" assumed to be pre-1.2 " "style: setting limit to %"PRIu64"mb", file_ctx->size_limit, file_ctx->size_limit); uint64_t size = file_ctx->size_limit * 1024 * 1024; file_ctx->size_limit = size; } else if (file_ctx->size_limit < MIN_LIMIT) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, limit less than " "allowed minimum: %d.", MIN_LIMIT); exit(EXIT_FAILURE); } } } if (conf != NULL) { const char *sensor_id_s = NULL; sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id"); if (sensor_id_s != NULL) { if (ByteExtractStringUint32(&sensor_id, 10, 0, sensor_id_s) == -1) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid sensor-id: %s", sensor_id_s); exit(EXIT_FAILURE); } } } ret = Unified2AlertOpenFileCtx(file_ctx, filename); if (ret < 0) goto error; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) goto error; output_ctx->data = file_ctx; output_ctx->DeInit = Unified2AlertDeInitCtx; SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu64" MB", filename, file_ctx->size_limit / (1024*1024)); SC_ATOMIC_INIT(unified2_event_id); return output_ctx; error: if (file_ctx != NULL) { LogFileFreeCtx(file_ctx); } return NULL; }
/** * \brief RunModeTileMpipeWorkers set up to process all modules in each thread. * * \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(void) { 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); } } } /* Get affinity for worker */ cpu_set_t cpus; //int result = tmc_cpus_get_my_affinity(&cpus); int result = tmc_cpus_get_dataplane_cpus(&cpus); if (result < 0) { SCLogError(SC_ERR_INVALID_ARGUMENT, "tmc_cpus_get_my_affinity() returned=%d", result); SCReturnInt(TM_ECODE_FAILED); } 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); /* create the threads */ ThreadVars *tv_worker = TmThreadCreatePacketHandler(tname, "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); /* Bind to a single cpu. */ int pipe_cpu = tmc_cpus_find_nth_cpu(&cpus, pipe); tv_worker->rank = pipe; 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); if (DetectEngineEnabled()) { tm_module = TmModuleGetByName("Detect"); if (tm_module == NULL) { printf("ERROR: TmModuleGetByName Detect failed\n"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv_worker, tm_module, NULL); } 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 This function is used to parse IPV4 ip_id passed via keyword: "id" * * \param idstr Pointer to the user provided id option * * \retval id_d pointer to DetectTlsVersionData on success * \retval NULL on failure */ DetectTlsVersionData *DetectTlsVersionParse (char *str) { uint16_t temp; DetectTlsVersionData *tls = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 1 || ret > 3) { SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.version option"); goto error; } if (ret > 1) { const char *str_ptr; char *orig; char *tmp_str; res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } /* We have a correct id option */ tls = SCMalloc(sizeof(DetectTlsVersionData)); if (tls == NULL) goto error; orig = SCStrdup((char*)str_ptr); tmp_str=orig; if (tmp_str == NULL) { goto error; } /* Let's see if we need to scape "'s */ if (tmp_str[0] == '"') { tmp_str[strlen(tmp_str) - 1] = '\0'; tmp_str += 1; } if (strcmp("1.0", tmp_str) == 0) { temp = TLS_VERSION_10; } else if (strcmp("1.1", tmp_str) == 0) { temp = TLS_VERSION_11; } else if (strcmp("1.2", tmp_str) == 0) { temp = TLS_VERSION_12; } else { SCLogError(SC_ERR_INVALID_VALUE, "Invalid value"); goto error; } tls->ver = temp; SCFree(orig); SCLogDebug("will look for tls %"PRIu8"", tls->ver); } return tls; error: if (tls != NULL) DetectTlsVersionFree(tls); return NULL; }
/** * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. * \return A LogFileCtx pointer on success, NULL on failure. */ OutputInitResult OutputJsonInitCtx(ConfNode *conf) { OutputInitResult result = { NULL, false }; OutputJsonCtx *json_ctx = SCCalloc(1, sizeof(OutputJsonCtx)); if (unlikely(json_ctx == NULL)) { SCLogDebug("could not create new OutputJsonCtx"); return result; } /* First lookup a sensor-name value in this outputs configuration * node (deprecated). If that fails, lookup the global one. */ const char *sensor_name = ConfNodeLookupChildValue(conf, "sensor-name"); if (sensor_name != NULL) { SCLogWarning(SC_ERR_DEPRECATED_CONF, "Found deprecated eve-log setting \"sensor-name\". " "Please set sensor-name globally."); } else { (void)ConfGet("sensor-name", &sensor_name); } json_ctx->file_ctx = LogFileNewCtx(); if (unlikely(json_ctx->file_ctx == NULL)) { SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx"); SCFree(json_ctx); return result; } if (sensor_name) { json_ctx->file_ctx->sensor_name = SCStrdup(sensor_name); if (json_ctx->file_ctx->sensor_name == NULL) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); return result; } } else { json_ctx->file_ctx->sensor_name = NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); return result; } output_ctx->data = json_ctx; output_ctx->DeInit = OutputJsonDeInitCtx; if (conf) { const char *output_s = ConfNodeLookupChildValue(conf, "filetype"); // Backwards compatibility if (output_s == NULL) { output_s = ConfNodeLookupChildValue(conf, "type"); } if (output_s != NULL) { if (strcmp(output_s, "file") == 0 || strcmp(output_s, "regular") == 0) { json_ctx->json_out = LOGFILE_TYPE_FILE; } else if (strcmp(output_s, "syslog") == 0) { json_ctx->json_out = LOGFILE_TYPE_SYSLOG; } else if (strcmp(output_s, "unix_dgram") == 0) { json_ctx->json_out = LOGFILE_TYPE_UNIX_DGRAM; } else if (strcmp(output_s, "unix_stream") == 0) { json_ctx->json_out = LOGFILE_TYPE_UNIX_STREAM; } else if (strcmp(output_s, "redis") == 0) { #ifdef HAVE_LIBHIREDIS SCLogRedisInit(); json_ctx->json_out = LOGFILE_TYPE_REDIS; #else SCLogError(SC_ERR_INVALID_ARGUMENT, "redis JSON output option is not compiled"); exit(EXIT_FAILURE); #endif } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON output option: %s", output_s); exit(EXIT_FAILURE); } } const char *prefix = ConfNodeLookupChildValue(conf, "prefix"); if (prefix != NULL) { SCLogInfo("Using prefix '%s' for JSON messages", prefix); json_ctx->file_ctx->prefix = SCStrdup(prefix); if (json_ctx->file_ctx->prefix == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for eve-log.prefix setting."); exit(EXIT_FAILURE); } json_ctx->file_ctx->prefix_len = strlen(prefix); } if (json_ctx->json_out == LOGFILE_TYPE_FILE || json_ctx->json_out == LOGFILE_TYPE_UNIX_DGRAM || json_ctx->json_out == LOGFILE_TYPE_UNIX_STREAM) { if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return result; } OutputRegisterFileRotationFlag(&json_ctx->file_ctx->rotation_flag); } #ifndef OS_WIN32 else if (json_ctx->json_out == LOGFILE_TYPE_SYSLOG) { const char *facility_s = ConfNodeLookupChildValue(conf, "facility"); if (facility_s == NULL) { facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR; } int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap()); if (facility == -1) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\"," " now using \"%s\" as syslog facility", facility_s, DEFAULT_ALERT_SYSLOG_FACILITY_STR); facility = DEFAULT_ALERT_SYSLOG_FACILITY; } const char *level_s = ConfNodeLookupChildValue(conf, "level"); if (level_s != NULL) { int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap()); if (level != -1) { json_ctx->file_ctx->syslog_setup.alert_syslog_level = level; } } const char *ident = ConfNodeLookupChildValue(conf, "identity"); /* if null we just pass that to openlog, which will then * figure it out by itself. */ openlog(ident, LOG_PID|LOG_NDELAY, facility); } #endif #ifdef HAVE_LIBHIREDIS else if (json_ctx->json_out == LOGFILE_TYPE_REDIS) { ConfNode *redis_node = ConfNodeLookupChild(conf, "redis"); if (!json_ctx->file_ctx->sensor_name) { char hostname[1024]; gethostname(hostname, 1023); json_ctx->file_ctx->sensor_name = SCStrdup(hostname); } if (json_ctx->file_ctx->sensor_name == NULL) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return result; } if (SCConfLogOpenRedis(redis_node, json_ctx->file_ctx) < 0) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return result; } } #endif const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id"); if (sensor_id_s != NULL) { if (ByteExtractStringUint64((uint64_t *)&sensor_id, 10, 0, sensor_id_s) == -1) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize JSON output, " "invalid sensor-id: %s", sensor_id_s); exit(EXIT_FAILURE); } } /* Check if top-level metadata should be logged. */ const ConfNode *metadata = ConfNodeLookupChild(conf, "metadata"); if (metadata && metadata->val && ConfValIsFalse(metadata->val)) { SCLogConfig("Disabling eve metadata logging."); json_ctx->cfg.include_metadata = false; } else { json_ctx->cfg.include_metadata = true; } /* See if we want to enable the community id */ const ConfNode *community_id = ConfNodeLookupChild(conf, "community-id"); if (community_id && community_id->val && ConfValIsTrue(community_id->val)) { SCLogConfig("Enabling eve community_id logging."); json_ctx->cfg.include_community_id = true; } else { json_ctx->cfg.include_community_id = false; } const char *cid_seed = ConfNodeLookupChildValue(conf, "community-id-seed"); if (cid_seed != NULL) { if (ByteExtractStringUint16(&json_ctx->cfg.community_id_seed, 10, 0, cid_seed) == -1) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize JSON output, " "invalid community-id-seed: %s", cid_seed); exit(EXIT_FAILURE); } } /* Do we have a global eve xff configuration? */ const ConfNode *xff = ConfNodeLookupChild(conf, "xff"); if (xff != NULL) { json_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg)); if (likely(json_ctx->xff_cfg != NULL)) { HttpXFFGetCfg(conf, json_ctx->xff_cfg); } } const char *pcapfile_s = ConfNodeLookupChildValue(conf, "pcap-file"); if (pcapfile_s != NULL && ConfValIsTrue(pcapfile_s)) { json_ctx->file_ctx->is_pcap_offline = (RunmodeGetCurrent() == RUNMODE_PCAP_FILE); } json_ctx->file_ctx->type = json_ctx->json_out; } SCLogDebug("returning output_ctx %p", output_ctx); result.ctx = output_ctx; result.ok = true; return result; }
/** * \brief This function is used to parse ssl_version data passed via * keyword: "ssl_version" * * \param str Pointer to the user provided options * * \retval ssl pointer to DetectSslVersionData on success * \retval NULL on failure */ DetectSslVersionData *DetectSslVersionParse(char *str) { DetectSslVersionData *ssl = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 1 || ret > 5) { SCLogError(SC_ERR_PCRE_MATCH, "invalid ssl_version option"); goto error; } if (ret > 1) { const char *str_ptr; char *orig; uint8_t found = 0, neg = 0; char *tmp_str; /* We have a correct ssl_version options */ ssl = SCCalloc(1, sizeof (DetectSslVersionData)); if (unlikely(ssl == NULL)) goto error; int i; for (i = 1; i < ret; i++) { res = pcre_get_substring((char *) str, ov, MAX_SUBSTRINGS, i, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); if (found == 0) goto error; break; } orig = SCStrdup((char*) str_ptr); if (unlikely(orig == NULL)) { goto error; } tmp_str = orig; /* Let's see if we need to scape "'s */ if (tmp_str[0] == '"') { tmp_str[strlen(tmp_str) - 1] = '\0'; tmp_str += 1; } if (tmp_str[0] == '!') { neg = 1; tmp_str++; } if (strncasecmp("sslv2", tmp_str, 5) == 0) { ssl->data[SSLv2].ver = SSL_VERSION_2; if (neg == 1) ssl->data[SSLv2].flags |= DETECT_SSL_VERSION_NEGATED; } else if (strncasecmp("sslv3", tmp_str, 5) == 0) { ssl->data[SSLv3].ver = SSL_VERSION_3; if (neg == 1) ssl->data[SSLv3].flags |= DETECT_SSL_VERSION_NEGATED; } else if (strncasecmp("tls1.0", tmp_str, 6) == 0) { ssl->data[TLS10].ver = TLS_VERSION_10; if (neg == 1) ssl->data[TLS10].flags |= DETECT_SSL_VERSION_NEGATED; } else if (strncasecmp("tls1.1", tmp_str, 6) == 0) { ssl->data[TLS11].ver = TLS_VERSION_11; if (neg == 1) ssl->data[TLS11].flags |= DETECT_SSL_VERSION_NEGATED; } else if (strncasecmp("tls1.2", tmp_str, 6) == 0) { ssl->data[TLS12].ver = TLS_VERSION_12; if (neg == 1) ssl->data[TLS12].flags |= DETECT_SSL_VERSION_NEGATED; } else if (strcmp(tmp_str, "") == 0) { SCFree(orig); if (found == 0) goto error; break; } else { SCLogError(SC_ERR_INVALID_VALUE, "Invalid value"); SCFree(orig); goto error; } found = 1; neg = 0; SCFree(orig); pcre_free_substring(str_ptr); } } return ssl; error: if (ssl != NULL) DetectSslVersionFree(ssl); return NULL; }
/** * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. * \return A LogFileCtx pointer on success, NULL on failure. */ OutputCtx *OutputJsonInitCtx(ConfNode *conf) { OutputJsonCtx *json_ctx = SCCalloc(1, sizeof(OutputJsonCtx));; if (unlikely(json_ctx == NULL)) { SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx"); return NULL; } json_ctx->file_ctx = LogFileNewCtx(); if (unlikely(json_ctx->file_ctx == NULL)) { SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx"); SCFree(json_ctx); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); return NULL; } output_ctx->data = json_ctx; output_ctx->DeInit = OutputJsonDeInitCtx; if (conf) { const char *output_s = ConfNodeLookupChildValue(conf, "filetype"); // Backwards compatibility if (output_s == NULL) { output_s = ConfNodeLookupChildValue(conf, "type"); } if (output_s != NULL) { if (strcmp(output_s, "file") == 0 || strcmp(output_s, "regular") == 0) { json_ctx->json_out = LOGFILE_TYPE_FILE; } else if (strcmp(output_s, "syslog") == 0) { json_ctx->json_out = LOGFILE_TYPE_SYSLOG; } else if (strcmp(output_s, "unix_dgram") == 0) { json_ctx->json_out = LOGFILE_TYPE_UNIX_DGRAM; } else if (strcmp(output_s, "unix_stream") == 0) { json_ctx->json_out = LOGFILE_TYPE_UNIX_STREAM; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON output option: %s", output_s); exit(EXIT_FAILURE); } } const char *prefix = ConfNodeLookupChildValue(conf, "prefix"); if (prefix != NULL) { json_ctx->file_ctx->prefix = SCStrdup(prefix); if (json_ctx->file_ctx->prefix == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for eve-log.prefix setting."); exit(EXIT_FAILURE); } } if (json_ctx->json_out == LOGFILE_TYPE_FILE || json_ctx->json_out == LOGFILE_TYPE_UNIX_DGRAM || json_ctx->json_out == LOGFILE_TYPE_UNIX_STREAM) { if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return NULL; } OutputRegisterFileRotationFlag(&json_ctx->file_ctx->rotation_flag); const char *format_s = ConfNodeLookupChildValue(conf, "format"); if (format_s != NULL) { if (strcmp(format_s, "indent") == 0) { json_ctx->format = INDENT; } else if (strcmp(format_s, "compact") == 0) { json_ctx->format = COMPACT; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON format option: %s", format_s); exit(EXIT_FAILURE); } } } else if (json_ctx->json_out == LOGFILE_TYPE_SYSLOG) { const char *facility_s = ConfNodeLookupChildValue(conf, "facility"); if (facility_s == NULL) { facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR; } int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap()); if (facility == -1) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\"," " now using \"%s\" as syslog facility", facility_s, DEFAULT_ALERT_SYSLOG_FACILITY_STR); facility = DEFAULT_ALERT_SYSLOG_FACILITY; } const char *level_s = ConfNodeLookupChildValue(conf, "level"); if (level_s != NULL) { int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap()); if (level != -1) { alert_syslog_level = level; } } const char *ident = ConfNodeLookupChildValue(conf, "identity"); /* if null we just pass that to openlog, which will then * figure it out by itself. */ openlog(ident, LOG_PID|LOG_NDELAY, facility); } const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id"); if (sensor_id_s != NULL) { if (ByteExtractStringUint64((uint64_t *)&sensor_id, 10, 0, sensor_id_s) == -1) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize JSON output, " "invalid sensor-is: %s", sensor_id_s); exit(EXIT_FAILURE); } } json_ctx->file_ctx->type = json_ctx->json_out; } SCLogDebug("returning output_ctx %p", output_ctx); return output_ctx; }
/** \brief open a generic output "log file", which may be a regular file or a socket * \param conf ConfNode structure for the output section in question * \param log_ctx Log file context allocated by caller * \param default_filename Default name of file to open, if not specified in ConfNode * \param rotate Register the file for rotation in HUP. * \retval 0 on success * \retval -1 on error */ int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate) { char log_path[PATH_MAX]; char *log_dir; const char *filename, *filetype; // Arg check if (conf == NULL || log_ctx == NULL || default_filename == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "SCConfLogOpenGeneric(conf %p, ctx %p, default %p) " "missing an argument", conf, log_ctx, default_filename); return -1; } if (log_ctx->fp != NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "SCConfLogOpenGeneric: previously initialized Log CTX " "encountered"); return -1; } // Resolve the given config filename = ConfNodeLookupChildValue(conf, "filename"); if (filename == NULL) filename = default_filename; log_dir = ConfigGetLogDirectory(); if (PathIsAbsolute(filename)) { snprintf(log_path, PATH_MAX, "%s", filename); } else { snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); } filetype = ConfNodeLookupChildValue(conf, "filetype"); if (filetype == NULL) filetype = DEFAULT_LOG_FILETYPE; const char *append = ConfNodeLookupChildValue(conf, "append"); if (append == NULL) append = DEFAULT_LOG_MODE_APPEND; // Now, what have we been asked to open? if (strcasecmp(filetype, "unix_stream") == 0) { /* Don't bail. May be able to connect later. */ log_ctx->is_sock = 1; log_ctx->sock_type = SOCK_STREAM; log_ctx->fp = SCLogOpenUnixSocketFp(log_path, SOCK_STREAM, 1); } else if (strcasecmp(filetype, "unix_dgram") == 0) { /* Don't bail. May be able to connect later. */ log_ctx->is_sock = 1; log_ctx->sock_type = SOCK_DGRAM; log_ctx->fp = SCLogOpenUnixSocketFp(log_path, SOCK_DGRAM, 1); } else if (strcasecmp(filetype, DEFAULT_LOG_FILETYPE) == 0 || strcasecmp(filetype, "file") == 0) { log_ctx->fp = SCLogOpenFileFp(log_path, append); if (log_ctx->fp == NULL) return -1; // Error already logged by Open...Fp routine log_ctx->is_regular = 1; if (rotate) { OutputRegisterFileRotationFlag(&log_ctx->rotation_flag); } } else if (strcasecmp(filetype, "pcie") == 0) { log_ctx->pcie_fp = SCLogOpenPcieFp(log_ctx, log_path, append); if (log_ctx->pcie_fp == NULL) return -1; // Error already logged by Open...Fp routine } else { SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid entry for " "%s.filetype. Expected \"regular\" (default), \"unix_stream\", " "\"pcie\" " "or \"unix_dgram\"", conf->name); } log_ctx->filename = SCStrdup(log_path); if (unlikely(log_ctx->filename == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for filename"); return -1; } SCLogInfo("%s output device (%s) initialized: %s", conf->name, filetype, filename); return 0; }
static int DetectDistanceSetup (DetectEngineCtx *de_ctx, Signature *s, char *distancestr) { char *str = distancestr; char dubbed = 0; SigMatch *pm = NULL; int ret = -1; /* Strip leading and trailing "s. */ if (distancestr[0] == '\"') { str = SCStrdup(distancestr + 1); if (unlikely(str == NULL)) goto end; if (strlen(str) && str[strlen(str) - 1] == '\"') { str[strlen(str) - 1] = '\0'; } dubbed = 1; } /* retrive the sm to apply the depth against */ if (s->list != DETECT_SM_LIST_NOTSET) { pm = SigMatchGetLastSMFromLists(s, 2, DETECT_CONTENT, s->sm_lists_tail[s->list]); } else { pm = SigMatchGetLastSMFromLists(s, 28, DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_FILEDATA], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH], DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]); } if (pm == NULL) { SCLogError(SC_ERR_OFFSET_MISSING_CONTENT, "distance needs " "preceding content, uricontent option, http_client_body, " "http_server_body, http_header option, http_raw_header option, " "http_method option, http_cookie, http_raw_uri, " "http_stat_msg, http_stat_code, http_user_agent or " "file_data/dce_stub_data sticky buffer option"); goto end; } /* verify other conditions */ DetectContentData *cd = (DetectContentData *)pm->ctx; if (cd->flags & DETECT_CONTENT_DISTANCE) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple distances for the same content."); goto end; } if ((cd->flags & DETECT_CONTENT_DEPTH) || (cd->flags & DETECT_CONTENT_OFFSET)) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use a relative " "keyword like within/distance with a absolute " "relative keyword like depth/offset for the same " "content." ); goto end; } if (cd->flags & DETECT_CONTENT_NEGATED && cd->flags & DETECT_CONTENT_FAST_PATTERN) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "negated keyword set along with a fast_pattern"); goto end; } if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative " "keyword set along with a fast_pattern:only;"); goto end; } if (str[0] != '-' && isalpha((unsigned char)str[0])) { SigMatch *bed_sm = DetectByteExtractRetrieveSMVar(str, s); if (bed_sm == NULL) { SCLogError(SC_ERR_INVALID_SIGNATURE, "unknown byte_extract var " "seen in distance - %s\n", str); goto end; } cd->distance = ((DetectByteExtractData *)bed_sm->ctx)->local_id; cd->flags |= DETECT_CONTENT_DISTANCE_BE; } else { cd->distance = strtol(str, NULL, 10); } cd->flags |= DETECT_CONTENT_DISTANCE; SigMatch *prev_pm = SigMatchGetLastSMFromLists(s, 4, DETECT_CONTENT, pm->prev, DETECT_PCRE, pm->prev); if (prev_pm == NULL) { ret = 0; goto end; } if (prev_pm->type == DETECT_CONTENT) { DetectContentData *prev_cd = (DetectContentData *)prev_pm->ctx; if (prev_cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { SCLogError(SC_ERR_INVALID_SIGNATURE, "previous keyword " "has a fast_pattern:only; set. Can't " "have relative keywords around a fast_pattern " "only content"); goto end; } prev_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT; } else if (prev_pm->type == DETECT_PCRE) { DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx; pd->flags |= DETECT_PCRE_RELATIVE_NEXT; } ret = 0; end: if (dubbed) SCFree(str); return ret; }
int SCConfLogOpenRedis(ConfNode *redis_node, LogFileCtx *log_ctx) { const char *redis_server = NULL; const char *redis_port = NULL; const char *redis_mode = NULL; const char *redis_key = NULL; if (redis_node) { redis_server = ConfNodeLookupChildValue(redis_node, "server"); redis_port = ConfNodeLookupChildValue(redis_node, "port"); redis_mode = ConfNodeLookupChildValue(redis_node, "mode"); redis_key = ConfNodeLookupChildValue(redis_node, "key"); } if (!redis_server) { redis_server = "127.0.0.1"; SCLogInfo("Using default redis server (127.0.0.1)"); } if (!redis_port) redis_port = "6379"; if (!redis_mode) redis_mode = "list"; if (!redis_key) redis_key = "suricata"; log_ctx->redis_setup.key = SCStrdup(redis_key); if (!log_ctx->redis_setup.key) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key name"); exit(EXIT_FAILURE); } log_ctx->redis_setup.batch_size = 0; ConfNode *pipelining = ConfNodeLookupChild(redis_node, "pipelining"); if (pipelining) { int enabled = 0; int ret; intmax_t val; ret = ConfGetChildValueBool(pipelining, "enabled", &enabled); if (ret && enabled) { ret = ConfGetChildValueInt(pipelining, "batch-size", &val); if (ret) { log_ctx->redis_setup.batch_size = val; } else { log_ctx->redis_setup.batch_size = 10; } } } if (!strcmp(redis_mode, "list")) { log_ctx->redis_setup.command = redis_push_cmd; if (!log_ctx->redis_setup.command) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key command"); exit(EXIT_FAILURE); } } else { log_ctx->redis_setup.command = redis_publish_cmd; if (!log_ctx->redis_setup.command) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate redis key command"); exit(EXIT_FAILURE); } } redisContext *c = redisConnect(redis_server, atoi(redis_port)); if (c != NULL && c->err) { SCLogError(SC_ERR_SOCKET, "Error connecting to redis server: %s", c->errstr); exit(EXIT_FAILURE); } /* store server params for reconnection */ log_ctx->redis_setup.server = SCStrdup(redis_server); if (!log_ctx->redis_setup.server) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocating redis server string"); exit(EXIT_FAILURE); } log_ctx->redis_setup.port = atoi(redis_port); log_ctx->redis_setup.tried = 0; log_ctx->redis = c; log_ctx->Close = SCLogFileCloseRedis; return 0; }
static DetectBytetestData *DetectBytetestParse(const char *optstr, char **value, char **offset) { DetectBytetestData *data = NULL; char *args[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; int i; uint32_t nbytes; const char *str_ptr = NULL; /* Execute the regex and populate args with captures. */ ret = pcre_exec(parse_regex, parse_regex_study, optstr, strlen(optstr), 0, 0, ov, MAX_SUBSTRINGS); if (ret < 6 || ret > 10) { SCLogError(SC_ERR_PCRE_PARSE, "parse error, ret %" PRId32 ", string %s", ret, optstr); goto error; } for (i = 0; i < (ret - 1); i++) { res = pcre_get_substring((char *)optstr, ov, MAX_SUBSTRINGS, i + 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed " "for arg %d", i + 1); goto error; } args[i] = (char *)str_ptr; } /* Initialize the data */ data = SCMalloc(sizeof(DetectBytetestData)); if (unlikely(data == NULL)) goto error; data->base = DETECT_BYTETEST_BASE_UNSET; data->flags = 0; /* * The first four options are required and positional. The * remaining arguments are flags and are not positional. */ /* Number of bytes */ if (ByteExtractStringUint32(&nbytes, 10, 0, args[0]) <= 0) { SCLogError(SC_ERR_INVALID_VALUE, "Malformed number of bytes: %s", str_ptr); goto error; } /* Operator is next two args: neg + op */ data->op = 0; if (args[1] != NULL && *args[1] == '!') { data->flags |= DETECT_BYTETEST_NEGOP; } if (args[2] != NULL) { if ((strcmp("=", args[2]) == 0) || ((data->flags & DETECT_BYTETEST_NEGOP) && strcmp("", args[2]) == 0)) { data->op |= DETECT_BYTETEST_OP_EQ; } else if (strcmp("<", args[2]) == 0) { data->op |= DETECT_BYTETEST_OP_LT; } else if (strcmp(">", args[2]) == 0) { data->op |= DETECT_BYTETEST_OP_GT; } else if (strcmp("&", args[2]) == 0) { data->op |= DETECT_BYTETEST_OP_AND; } else if (strcmp("^", args[2]) == 0) { data->op |= DETECT_BYTETEST_OP_OR; } else if (strcmp(">=", args[2]) == 0) { data->op |= DETECT_BYTETEST_OP_GE; } else if (strcmp("<=", args[2]) == 0) { data->op |= DETECT_BYTETEST_OP_LE; } else { SCLogError(SC_ERR_INVALID_OPERATOR, "Invalid operator"); goto error; } } /* Value */ if (args[3][0] != '-' && isalpha((unsigned char)args[3][0])) { if (value == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "byte_test supplied with " "var name for value. \"value\" argument supplied to " "this function has to be non-NULL"); goto error; } *value = SCStrdup(args[3]); if (*value == NULL) goto error; } else { if (ByteExtractStringUint64(&data->value, 0, 0, args[3]) <= 0) { SCLogError(SC_ERR_INVALID_VALUE, "Malformed value: %s", str_ptr); goto error; } } /* Offset */ if (args[4][0] != '-' && isalpha((unsigned char)args[4][0])) { if (offset == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "byte_test supplied with " "var name for offset. \"offset\" argument supplied to " "this function has to be non-NULL"); goto error; } *offset = SCStrdup(args[4]); if (*offset == NULL) goto error; } else { if (ByteExtractStringInt32(&data->offset, 0, 0, args[4]) <= 0) { SCLogError(SC_ERR_INVALID_VALUE, " Malformed offset: %s", str_ptr); goto error; } } /* The remaining options are flags. */ /** \todo Error on dups? */ for (i = 5; i < (ret - 1); i++) { if (args[i] != NULL) { if (strcmp("relative", args[i]) == 0) { data->flags |= DETECT_BYTETEST_RELATIVE; } else if (strcasecmp("string", args[i]) == 0) { data->flags |= DETECT_BYTETEST_STRING; } else if (strcasecmp("dec", args[i]) == 0) { data->base |= DETECT_BYTETEST_BASE_DEC; } else if (strcasecmp("hex", args[i]) == 0) { data->base |= DETECT_BYTETEST_BASE_HEX; } else if (strcasecmp("oct", args[i]) == 0) { data->base |= DETECT_BYTETEST_BASE_OCT; } else if (strcasecmp("big", args[i]) == 0) { if (data->flags & DETECT_BYTETEST_LITTLE) { data->flags ^= DETECT_BYTETEST_LITTLE; } data->flags |= DETECT_BYTETEST_BIG; } else if (strcasecmp("little", args[i]) == 0) { data->flags |= DETECT_BYTETEST_LITTLE; } else if (strcasecmp("dce", args[i]) == 0) { data->flags |= DETECT_BYTETEST_DCE; } else { SCLogError(SC_ERR_UNKNOWN_VALUE, "Unknown value: \"%s\"", args[i]); goto error; } } } if (data->flags & DETECT_BYTETEST_STRING) { /* 23 - This is the largest string (octal, with a zero prefix) that * will not overflow uint64_t. The only way this length * could be over 23 and still not overflow is if it were zero * prefixed and we only support 1 byte of zero prefix for octal. * * "01777777777777777777777" = 0xffffffffffffffff */ if (nbytes > 23) { SCLogError(SC_ERR_INVALID_VALUE, "Cannot test more than 23 bytes with \"string\": %s", optstr); goto error; } } else { if (nbytes > 8) { SCLogError(SC_ERR_INVALID_VALUE, "Cannot test more than 8 bytes without \"string\": %s", optstr); goto error; } if (data->base != DETECT_BYTETEST_BASE_UNSET) { SCLogError(SC_ERR_INVALID_VALUE, "Cannot use a base without \"string\": %s", optstr); goto error; } } /* This is max 23 so it will fit in a byte (see above) */ data->nbytes = (uint8_t)nbytes; for (i = 0; i < (ret - 1); i++){ if (args[i] != NULL) SCFree(args[i]); } return data; error: for (i = 0; i < (ret - 1); i++){ if (args[i] != NULL) SCFree(args[i]); } if (data != NULL) DetectBytetestFree(data); return NULL; }
/** * \brief extract information from config file * * The returned structure will be freed by the thread init function. * This is thus necessary to or copy the structure before giving it * to thread or to reparse the file for each thread (and thus have * new structure. * * If old config system is used, then return the smae parameters * value for each interface. * * \return a PfringIfaceConfig corresponding to the interface name */ void *ParsePfringConfig(const char *iface) { char *threadsstr = NULL; ConfNode *if_root; ConfNode *if_default = NULL; ConfNode *pf_ring_node; PfringIfaceConfig *pfconf = SCMalloc(sizeof(*pfconf)); char *tmpclusterid; char *tmpctype = NULL; #ifdef HAVE_PFRING_CLUSTER_TYPE cluster_type default_ctype = CLUSTER_ROUND_ROBIN; int getctype = 0; #endif #ifdef HAVE_PFRING_SET_BPF_FILTER char *bpf_filter = NULL; #endif /* HAVE_PFRING_SET_BPF_FILTER */ if (unlikely(pfconf == NULL)) { return NULL; } if (iface == NULL) { SCFree(pfconf); return NULL; } memset(pfconf, 0, sizeof(PfringIfaceConfig)); strlcpy(pfconf->iface, iface, sizeof(pfconf->iface)); pfconf->threads = 1; pfconf->cluster_id = 1; #ifdef HAVE_PFRING_CLUSTER_TYPE pfconf->ctype = (cluster_type)default_ctype; #endif pfconf->DerefFunc = PfringDerefConfig; SC_ATOMIC_INIT(pfconf->ref); (void) SC_ATOMIC_ADD(pfconf->ref, 1); /* Find initial node */ pf_ring_node = ConfGetNode("pfring"); if (pf_ring_node == NULL) { SCLogInfo("Unable to find pfring config using default value"); return pfconf; } if_root = ConfNodeLookupKeyValue(pf_ring_node, "interface", iface); if_default = ConfNodeLookupKeyValue(pf_ring_node, "interface", "default"); if (if_root == NULL && if_default == NULL) { /* Switch to old mode */ if_root = pf_ring_node; SCLogInfo("Unable to find pfring config for " "interface %s, using default value or 1.0 " "configuration system. ", iface); return pfconf; } /* If there is no setting for current interface use default one as main iface */ if (if_root == NULL) { if_root = if_default; if_default = NULL; } if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) { pfconf->threads = 1; } else { if (threadsstr != NULL) { pfconf->threads = (uint8_t)atoi(threadsstr); } } if (pfconf->threads == 0) { pfconf->threads = 1; } SC_ATOMIC_RESET(pfconf->ref); (void) SC_ATOMIC_ADD(pfconf->ref, pfconf->threads); /* command line value has precedence */ if (ConfGet("pfring.cluster-id", &tmpclusterid) == 1) { pfconf->cluster_id = (uint16_t)atoi(tmpclusterid); SCLogDebug("Going to use command-line provided cluster-id %" PRId32, pfconf->cluster_id); } else { if (ConfGetChildValueWithDefault(if_root, if_default, "cluster-id", &tmpclusterid) != 1) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Could not get cluster-id from config"); } else { pfconf->cluster_id = (uint16_t)atoi(tmpclusterid); SCLogDebug("Going to use cluster-id %" PRId32, pfconf->cluster_id); } } #ifdef HAVE_PFRING_SET_BPF_FILTER /*load pfring bpf filter*/ /* command line value has precedence */ if (ConfGet("bpf-filter", &bpf_filter) == 1) { if (strlen(bpf_filter) > 0) { pfconf->bpf_filter = SCStrdup(bpf_filter); SCLogDebug("Going to use command-line provided bpf filter %s", pfconf->bpf_filter); } } else { if (ConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &bpf_filter) == 1) { if (strlen(bpf_filter) > 0) { pfconf->bpf_filter = SCStrdup(bpf_filter); SCLogDebug("Going to use bpf filter %s", pfconf->bpf_filter); } } } #endif /* HAVE_PFRING_SET_BPF_FILTER */ #ifdef HAVE_PFRING_CLUSTER_TYPE if (ConfGet("pfring.cluster-type", &tmpctype) == 1) { SCLogDebug("Going to use command-line provided cluster-type"); getctype = 1; } else { if (ConfGetChildValueWithDefault(if_root, if_default, "cluster-type", &tmpctype) != 1) { SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED, "Could not get cluster-type fron config"); } else { getctype = 1; } } if (getctype) { if (strcmp(tmpctype, "cluster_round_robin") == 0) { SCLogInfo("Using round-robin cluster mode for PF_RING (iface %s)", pfconf->iface); pfconf->ctype = CLUSTER_ROUND_ROBIN; } else if (strcmp(tmpctype, "cluster_flow") == 0) { SCLogInfo("Using flow cluster mode for PF_RING (iface %s)", pfconf->iface); pfconf->ctype = CLUSTER_FLOW; } else { SCLogError(SC_ERR_INVALID_CLUSTER_TYPE, "invalid cluster-type %s", tmpctype); SCFree(pfconf); return NULL; } } #endif /* HAVE_PFRING_CLUSTER_TYPE */ if (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) { if (strcmp(tmpctype, "auto") == 0) { pfconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else if (strcmp(tmpctype, "yes") == 0) { pfconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE; } else if (strcmp(tmpctype, "no") == 0) { pfconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE; } else if (strcmp(tmpctype, "rx-only") == 0) { pfconf->checksum_mode = CHECKSUM_VALIDATION_RXONLY; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", pfconf->iface); } } return pfconf; }
/** * \brief This function is used to parse fingerprint passed via keyword: "fingerprint" * * \param idstr Pointer to the user provided fingerprint option * * \retval pointer to DetectTlsData on success * \retval NULL on failure */ static DetectTlsData *DetectTlsFingerprintParse (const char *str, bool negate) { DetectTlsData *tls = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; const char *str_ptr; char *orig; char *tmp_str; uint32_t flag = 0; ret = pcre_exec(fingerprint_parse_regex, fingerprint_parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS); if (ret != 2) { SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.fingerprint option"); goto error; } if (negate) flag = DETECT_CONTENT_NEGATED; res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } /* We have a correct id option */ tls = SCMalloc(sizeof(DetectTlsData)); if (unlikely(tls == NULL)) goto error; tls->fingerprint = NULL; tls->flags = flag; orig = SCStrdup((char*)str_ptr); if (unlikely(orig == NULL)) { goto error; } pcre_free_substring(str_ptr); tmp_str=orig; /* Let's see if we need to escape "'s */ if (tmp_str[0] == '"') { tmp_str[strlen(tmp_str) - 1] = '\0'; tmp_str += 1; } tls->fingerprint = SCStrdup(tmp_str); if (tls->fingerprint == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate fingerprint"); } SCFree(orig); SCLogDebug("will look for TLS fingerprint %s", tls->fingerprint); return tls; error: if (tls != NULL) DetectTlsFingerprintFree(tls); return NULL; }
static int RunModeSetLiveCaptureWorkersForDevice(ConfigIfaceThreadsCountFunc ModThreadsCount, char *recv_mod_name, char *decode_mod_name, char *thread_name, const char *live_dev, void *aconf, unsigned char single_mode) { int thread; int threads_count; if (single_mode) { threads_count = 1; } else { threads_count = ModThreadsCount(aconf); SCLogInfo("Going to use %" PRId32 " thread(s)", threads_count); } /* create the threads */ for (thread = 0; thread < threads_count; thread++) { char tname[TM_THREAD_NAME_MAX]; char *n_thread_name = NULL; ThreadVars *tv = NULL; TmModule *tm_module = NULL; if (single_mode) { snprintf(tname, sizeof(tname), "%s", thread_name); } else { snprintf(tname, sizeof(tname), "%s%s%d", thread_name, live_dev, thread+1); } n_thread_name = SCStrdup(tname); if (unlikely(n_thread_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate thread name"); exit(EXIT_FAILURE); } tv = TmThreadCreatePacketHandler(n_thread_name, "packetpool", "packetpool", "packetpool", "packetpool", "pktacqloop"); if (tv == 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, tm_module, aconf); 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, tm_module, NULL); tm_module = TmModuleGetByName("StreamTcp"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); if (DetectEngineEnabled()) { tm_module = TmModuleGetByName("Detect"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName Detect failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); } tm_module = TmModuleGetByName("RespondReject"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName RespondReject failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); SetupOutputs(tv); TmThreadSetCPU(tv, DETECT_CPU_SET); if (TmThreadSpawn(tv) != TM_ECODE_OK) { SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } return 0; }
static int DetectLuaSetupPrime(DetectLuajitData *ld) { lua_State *luastate = luaL_newstate(); if (luastate == NULL) goto error; luaL_openlibs(luastate); int status = luaL_loadfile(luastate, ld->filename); if (status) { SCLogError(SC_ERR_LUAJIT_ERROR, "couldn't load file: %s", lua_tostring(luastate, -1)); goto error; } /* prime the script (or something) */ if (lua_pcall(luastate, 0, 0, 0) != 0) { SCLogError(SC_ERR_LUAJIT_ERROR, "couldn't prime file: %s", lua_tostring(luastate, -1)); goto error; } lua_getglobal(luastate, "init"); if (lua_type(luastate, -1) != LUA_TFUNCTION) { SCLogError(SC_ERR_LUAJIT_ERROR, "no init function in script"); goto error; } lua_newtable(luastate); /* stack at -1 */ if (lua_gettop(luastate) == 0 || lua_type(luastate, 2) != LUA_TTABLE) { SCLogError(SC_ERR_LUAJIT_ERROR, "no table setup"); goto error; } lua_pushliteral(luastate, "script_api_ver"); /* stack at -2 */ lua_pushnumber (luastate, 1); /* stack at -3 */ lua_settable(luastate, -3); if (lua_pcall(luastate, 1, 1, 0) != 0) { SCLogError(SC_ERR_LUAJIT_ERROR, "couldn't run script 'init' function: %s", lua_tostring(luastate, -1)); goto error; } /* process returns from script */ if (lua_gettop(luastate) == 0) { SCLogError(SC_ERR_LUAJIT_ERROR, "init function in script should return table, nothing returned"); goto error; } if (lua_type(luastate, 1) != LUA_TTABLE) { SCLogError(SC_ERR_LUAJIT_ERROR, "init function in script should return table, returned is not table"); goto error; } lua_pushnil(luastate); const char *k, *v; while (lua_next(luastate, -2)) { v = lua_tostring(luastate, -1); lua_pop(luastate, 1); k = lua_tostring(luastate, -1); if (!k || !v) continue; SCLogDebug("k='%s', v='%s'", k, v); if (strcmp(k, "packet") == 0 && strcmp(v, "true") == 0) { ld->flags |= DATATYPE_PACKET; } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) { ld->flags |= DATATYPE_PAYLOAD; } else if (strncmp(k, "http", 4) == 0 && strcmp(v, "true") == 0) { if (ld->alproto != ALPROTO_UNKNOWN && ld->alproto != ALPROTO_HTTP) { SCLogError(SC_ERR_LUAJIT_ERROR, "can just inspect script against one app layer proto like HTTP at a time"); goto error; } if (ld->flags != 0) { SCLogError(SC_ERR_LUAJIT_ERROR, "when inspecting HTTP buffers only a single buffer can be inspected"); goto error; } /* http types */ ld->alproto = ALPROTO_HTTP; if (strcmp(k, "http.uri") == 0) ld->flags |= DATATYPE_HTTP_URI; else if (strcmp(k, "http.uri.raw") == 0) ld->flags |= DATATYPE_HTTP_URI_RAW; else if (strcmp(k, "http.request_line") == 0) ld->flags |= DATATYPE_HTTP_REQUEST_LINE; else if (strcmp(k, "http.request_headers") == 0) ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS; else if (strcmp(k, "http.request_headers.raw") == 0) ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS_RAW; else if (strcmp(k, "http.request_cookie") == 0) ld->flags |= DATATYPE_HTTP_REQUEST_COOKIE; else if (strcmp(k, "http.request_user_agent") == 0) ld->flags |= DATATYPE_HTTP_REQUEST_UA; else if (strcmp(k, "http.request_body") == 0) ld->flags |= DATATYPE_HTTP_REQUEST_BODY; else if (strcmp(k, "http.response_body") == 0) ld->flags |= DATATYPE_HTTP_RESPONSE_BODY; else if (strcmp(k, "http.response_cookie") == 0) ld->flags |= DATATYPE_HTTP_RESPONSE_COOKIE; else if (strcmp(k, "http.response_headers") == 0) ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS; else if (strcmp(k, "http.response_headers.raw") == 0) ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS_RAW; else { SCLogError(SC_ERR_LUAJIT_ERROR, "unsupported http data type %s", k); goto error; } ld->buffername = SCStrdup(k); if (ld->buffername == NULL) { SCLogError(SC_ERR_LUAJIT_ERROR, "alloc error"); goto error; } } else { SCLogError(SC_ERR_LUAJIT_ERROR, "unsupported data type %s", k); goto error; } } /* pop the table */ lua_pop(luastate, 1); lua_close(luastate); return 0; error: lua_close(luastate); return -1; }
int RunModeSetIPSWorker(ConfigIPSParserFunc ConfigParser, char *recv_mod_name, char *verdict_mod_name, char *decode_mod_name) { char tname[TM_THREAD_NAME_MAX]; ThreadVars *tv = NULL; TmModule *tm_module = NULL; char *cur_queue = NULL; int nqueue = LiveGetDeviceCount(); for (int i = 0; i < nqueue; i++) { /* create the threads */ cur_queue = LiveGetDeviceName(i); if (cur_queue == NULL) { SCLogError(SC_ERR_RUNMODE, "invalid queue number"); exit(EXIT_FAILURE); } memset(tname, 0, sizeof(tname)); snprintf(tname, sizeof(tname), "Worker-Q%s", cur_queue); char *thread_name = SCStrdup(tname); if (unlikely(thread_name == NULL)) { SCLogError(SC_ERR_RUNMODE, "Error allocating memory"); exit(EXIT_FAILURE); } tv = TmThreadCreatePacketHandler(thread_name, "packetpool", "packetpool", "packetpool", "packetpool", "pktacqloop"); if (tv == 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, tm_module, (void *) ConfigParser(i)); 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, tm_module, NULL); tm_module = TmModuleGetByName("StreamTcp"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName StreamTcp failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); if (DetectEngineEnabled()) { tm_module = TmModuleGetByName("Detect"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName Detect failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); } tm_module = TmModuleGetByName(verdict_mod_name); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName %s failed", verdict_mod_name); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); tm_module = TmModuleGetByName("RespondReject"); if (tm_module == NULL) { SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for RespondReject failed"); exit(EXIT_FAILURE); } TmSlotSetFuncAppend(tv, tm_module, NULL); SetupOutputs(tv); TmThreadSetCPU(tv, DETECT_CPU_SET); if (TmThreadSpawn(tv) != TM_ECODE_OK) { SCLogError(SC_ERR_RUNMODE, "TmThreadSpawn failed"); exit(EXIT_FAILURE); } } return 0; }
/** * \brief This function is used to parse IPV4 ip_id passed via keyword: "id" * * \param idstr Pointer to the user provided id option * * \retval id_d pointer to DetectTlsData on success * \retval NULL on failure */ static DetectTlsData *DetectTlsIssuerDNParse(char *str) { DetectTlsData *tls = NULL; #define MAX_SUBSTRINGS 30 int ret = 0, res = 0; int ov[MAX_SUBSTRINGS]; const char *str_ptr; char *orig = NULL; char *tmp_str; uint32_t flag = 0; ret = pcre_exec(issuerdn_parse_regex, issuerdn_parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS); if (ret != 3) { SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.issuerdn option"); goto error; } res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } if (str_ptr[0] == '!') flag = DETECT_CONTENT_NEGATED; pcre_free_substring(str_ptr); res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 2, &str_ptr); if (res < 0) { SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); goto error; } /* We have a correct id option */ tls = SCMalloc(sizeof(DetectTlsData)); if (unlikely(tls == NULL)) goto error; tls->issuerdn = NULL; tls->flags = flag; orig = SCStrdup((char*)str_ptr); if (unlikely(orig == NULL)) { goto error; } pcre_free_substring(str_ptr); tmp_str=orig; /* Let's see if we need to escape "'s */ if (tmp_str[0] == '"') { tmp_str[strlen(tmp_str) - 1] = '\0'; tmp_str += 1; } tls->issuerdn = SCStrdup(tmp_str); if (unlikely(tls->issuerdn == NULL)) { goto error; } SCFree(orig); SCLogDebug("Will look for TLS issuerdn %s", tls->issuerdn); return tls; error: if (orig != NULL) SCFree(orig); if (tls != NULL) DetectTlsIssuerDNFree(tls); return NULL; }