static int GetIfaceOffloadingBSD(const char *ifname) { int ret = 0; int if_caps = GetIfaceCaps(ifname); if (if_caps == -1) { return -1; } SCLogDebug("if_caps %X", if_caps); if (if_caps & IFCAP_RXCSUM) { SCLogWarning(SC_ERR_NIC_OFFLOADING, "Using %s with RXCSUM activated can lead to capture " "problems. Run: ifconfig %s -rxcsum", ifname, ifname); ret = 1; } #ifdef IFCAP_TOE if (if_caps & (IFCAP_TSO|IFCAP_TOE|IFCAP_LRO)) { SCLogWarning(SC_ERR_NIC_OFFLOADING, "Using %s with TSO, TOE or LRO activated can lead to " "capture problems. Run: ifconfig %s -tso -toe -lro", ifname, ifname); ret = 1; } #else if (if_caps & (IFCAP_TSO|IFCAP_LRO)) { SCLogWarning(SC_ERR_NIC_OFFLOADING, "Using %s with TSO or LRO activated can lead to " "capture problems. Run: ifconfig %s -tso -lro", ifname, ifname); ret = 1; } #endif return ret; }
/** \brief Run callback for all segments * * \return -1 in case of error, the number of segment in case of success */ int StreamSegmentForEach(Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data) { switch(p->proto) { case IPPROTO_TCP: return StreamTcpSegmentForEach(p, flag, CallbackFunc, data); break; case IPPROTO_UDP: SCLogWarning(SC_ERR_UNKNOWN_PROTOCOL, "UDP is currently unsupported"); break; default: SCLogWarning(SC_ERR_UNKNOWN_PROTOCOL, "This protocol is currently unsupported"); break; } return 0; }
/** * \brief NFQ function to get a packet from the kernel * * \note separate functions for Linux and Win32 for readability. */ static void NFQRecvPkt(NFQQueueVars *t, NFQThreadVars *tv) { int rv, ret; int flag = NFQVerdictCacheLen(t) ? MSG_DONTWAIT : 0; /* XXX what happens on rv == 0? */ rv = recv(t->fd, tv->data, tv->datalen, flag); if (rv < 0) { if (errno == EINTR || errno == EWOULDBLOCK) { /* no error on timeout */ if (flag) NFQVerdictCacheFlush(t); /* inject a fake packet on timeout */ TmThreadsCaptureInjectPacket(tv->tv, tv->slot, NULL); } else { #ifdef COUNTERS NFQMutexLock(t); t->errs++; NFQMutexUnlock(t); #endif /* COUNTERS */ } } else if(rv == 0) { SCLogWarning(SC_ERR_NFQ_RECV, "recv got returncode 0"); } else { #ifdef DBG_PERF if (rv > t->dbg_maxreadsize) t->dbg_maxreadsize = rv; #endif /* DBG_PERF */ //printf("NFQRecvPkt: t %p, rv = %" PRId32 "\n", t, rv); NFQMutexLock(t); if (t->qh != NULL) { ret = nfq_handle_packet(t->h, tv->data, rv); } else { SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "NFQ handle has been destroyed"); ret = -1; } NFQMutexUnlock(t); if (ret != 0) { SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "nfq_handle_packet error %"PRId32" %s", ret, strerror(errno)); } } }
/** \brief register all unittests for the tm modules */ void TmModuleRegisterTests(void) { #ifdef UNITTESTS TmModule *t; uint16_t i; for (i = 0; i < TMM_SIZE; i++) { t = &tmm_modules[i]; if (t->name == NULL) continue; g_ut_modules++; if (t->RegisterTests == NULL) { if (coverage_unittests) SCLogWarning(SC_WARN_NO_UNITTESTS, "threading module %s has no unittest " "registration function.", t->name); } else { t->RegisterTests(); g_ut_covered++; } } #endif /* UNITTESTS */ }
static void NFQVerdictCacheFlush(NFQQueueVars *t) { #ifdef HAVE_NFQ_SET_VERDICT_BATCH int ret; int iter = 0; do { if (t->verdict_cache.mark_valid) ret = nfq_set_verdict_batch2(t->qh, t->verdict_cache.packet_id, t->verdict_cache.verdict, t->verdict_cache.mark); else ret = nfq_set_verdict_batch(t->qh, t->verdict_cache.packet_id, t->verdict_cache.verdict); } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_TIME)); if (ret < 0) { SCLogWarning(SC_ERR_NFQ_SET_VERDICT, "nfq_set_verdict_batch failed: %s", strerror(errno)); } else { t->verdict_cache.len = 0; t->verdict_cache.mark_valid = 0; } #endif }
static int SetEthtoolValue(const char *dev, int cmd, uint32_t value) { struct ifreq ifr; int fd; struct ethtool_value ethv; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) { return -1; } (void)strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); ethv.cmd = cmd; ethv.data = value; ifr.ifr_data = (void *) ðv; if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) { SCLogWarning(SC_ERR_SYSCALL, "Failure when trying to set feature via ioctl for '%s': %s (%d)", dev, strerror(errno), errno); close(fd); return -1; } close(fd); return 0; }
/** \brief connect to the indicated local stream socket, logging any errors * \param path filesystem path to connect to * \param log_err, non-zero if connect failure should be logged. * \retval FILE* on success (fdopen'd wrapper of underlying socket) * \retval NULL on error */ static FILE * SCLogOpenUnixSocketFp(const char *path, int sock_type, int log_err) { struct sockaddr_un saun; int s = -1; FILE * ret = NULL; memset(&saun, 0x00, sizeof(saun)); s = socket(PF_UNIX, sock_type, 0); if (s < 0) goto err; saun.sun_family = AF_UNIX; strlcpy(saun.sun_path, path, sizeof(saun.sun_path)); if (connect(s, (const struct sockaddr *)&saun, sizeof(saun)) < 0) goto err; ret = fdopen(s, "w"); if (ret == NULL) goto err; return ret; err: if (log_err) SCLogWarning(SC_ERR_SOCKET, "Error connecting to socket \"%s\": %s (will keep trying)", path, strerror(errno)); if (s >= 0) close(s); return NULL; }
/** * \brief output the link MTU * * \param Name of link * \retval -1 in case of error, 0 if MTU can not be found */ int GetIfaceMTU(const char *pcap_dev) { #if defined SIOCGIFMTU struct ifreq ifr; int fd; (void)strlcpy(ifr.ifr_name, pcap_dev, sizeof(ifr.ifr_name)); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) { return -1; } if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) { SCLogWarning(SC_ERR_SYSCALL, "Failure when trying to get MTU via ioctl for '%s': %s (%d)", pcap_dev, strerror(errno), errno); close(fd); return -1; } close(fd); SCLogInfo("Found an MTU of %d for '%s'", ifr.ifr_mtu, pcap_dev); return ifr.ifr_mtu; #elif defined OS_WIN32 return GetIfaceMTUWin32(pcap_dev); #else /* ioctl is not defined, let's pretend returning 0 is ok */ return 0; #endif }
/** * \brief Reopen a regular log file with the side-affect of truncating it. * * This is useful to clear the log file and start a new one, or to * re-open the file after its been moved by something external * (eg. logrotate). */ int SCConfLogReopen(LogFileCtx *log_ctx) { if (!log_ctx->is_regular) { /* Not supported and not needed on non-regular files. */ return 0; } if (log_ctx->filename == NULL) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Can't re-open LogFileCtx without a filename."); return -1; } fclose(log_ctx->fp); /* Reopen the file. Append is forced in case the file was not * moved as part of a rotation process. */ SCLogDebug("Reopening log file %s.", log_ctx->filename); log_ctx->fp = SCLogOpenFileFp(log_ctx->filename, "yes"); if (log_ctx->fp == NULL) { return -1; // Already logged by Open..Fp routine. } return 0; }
/** * \brief Initialize the "magic" context. */ int MagicInit(void) { BUG_ON(g_magic_ctx != NULL); SCEnter(); char *filename = NULL; FILE *fd = NULL; SCMutexInit(&g_magic_lock, NULL); SCMutexLock(&g_magic_lock); g_magic_ctx = magic_open(0); if (g_magic_ctx == NULL) { SCLogError(SC_ERR_MAGIC_OPEN, "magic_open failed: %s", magic_error(g_magic_ctx)); goto error; } (void)ConfGet("magic-file", &filename); if (filename != NULL) { if (strlen(filename) == 0) { /* set filename to NULL on *nix systems so magic_load uses system * default path (see man libmagic) */ SCLogConfig("using system default magic-file"); filename = NULL; } else { SCLogConfig("using magic-file %s", filename); if ( (fd = fopen(filename, "r")) == NULL) { SCLogWarning(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno)); goto error; } fclose(fd); } } if (magic_load(g_magic_ctx, filename) != 0) { SCLogError(SC_ERR_MAGIC_LOAD, "magic_load failed: %s", magic_error(g_magic_ctx)); goto error; } SCMutexUnlock(&g_magic_lock); SCReturnInt(0); error: if (g_magic_ctx != NULL) { magic_close(g_magic_ctx); g_magic_ctx = NULL; } SCMutexUnlock(&g_magic_lock); SCReturnInt(-1); }
static OutputInitResult JsonDropLogInitCtx(ConfNode *conf) { OutputInitResult result = { NULL, false }; if (OutputDropLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'drop' logger " "can be enabled"); return result; } JsonDropOutputCtx *drop_ctx = SCCalloc(1, sizeof(*drop_ctx)); if (drop_ctx == NULL) return result; drop_ctx->file_ctx = LogFileNewCtx(); if (drop_ctx->file_ctx == NULL) { JsonDropOutputCtxFree(drop_ctx); return result; } if (SCConfLogOpenGeneric(conf, drop_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { JsonDropOutputCtxFree(drop_ctx); return result; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { JsonDropOutputCtxFree(drop_ctx); return result; } if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "alerts"); if (extended != NULL) { if (ConfValIsTrue(extended)) { drop_ctx->flags = LOG_DROP_ALERTS; } } extended = ConfNodeLookupChildValue(conf, "flows"); if (extended != NULL) { if (strcasecmp(extended, "start") == 0) { g_droplog_flows_start = 1; } else if (strcasecmp(extended, "all") == 0) { g_droplog_flows_start = 0; } else { SCLogWarning(SC_ERR_CONF_YAML_ERROR, "valid options for " "'flow' are 'start' and 'all'"); } } } output_ctx->data = drop_ctx; output_ctx->DeInit = JsonDropLogDeInitCtx; result.ctx = output_ctx; result.ok = true; return result; }
void NFQRecvPkt(NFQQueueVars *t, NFQThreadVars *tv) { int rv, ret; /* XXX what happens on rv == 0? */ rv = recv(t->fd, tv->data, tv->datalen, 0); if (rv < 0) { if (errno == EINTR || errno == EWOULDBLOCK) { /* no error on timeout */ } else { #ifdef COUNTERS NFQMutexLock(t); t->errs++; NFQMutexUnlock(t); #endif /* COUNTERS */ } } else if(rv == 0) { SCLogWarning(SC_ERR_NFQ_RECV, "recv got returncode 0"); } else { #ifdef DBG_PERF if (rv > t->dbg_maxreadsize) t->dbg_maxreadsize = rv; #endif /* DBG_PERF */ //printf("NFQRecvPkt: t %p, rv = %" PRId32 "\n", t, rv); NFQMutexLock(t); if (t->qh != NULL) { ret = nfq_handle_packet(t->h, tv->data, rv); } else { SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "NFQ handle has been destroyed"); ret = -1; } NFQMutexUnlock(t); if (ret != 0) { SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "nfq_handle_packet error %" PRId32 "", ret); } } }
static void *DetectFilemagicThreadInit(void *data) { char *filename = NULL; FILE *fd = NULL; DetectFilemagicData *filemagic = (DetectFilemagicData *)data; BUG_ON(filemagic == NULL); DetectFilemagicThreadData *t = SCMalloc(sizeof(DetectFilemagicThreadData)); if (unlikely(t == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "couldn't alloc ctx memory"); return NULL; } memset(t, 0x00, sizeof(DetectFilemagicThreadData)); t->ctx = magic_open(0); if (t->ctx == NULL) { SCLogError(SC_ERR_MAGIC_OPEN, "magic_open failed: %s", magic_error(t->ctx)); goto error; } (void)ConfGet("magic-file", &filename); if (filename != NULL) { if (strlen(filename) == 0) { /* set filename to NULL on *nix systems so magic_load uses system default path (see man libmagic) */ SCLogInfo("using system default magic-file"); filename = NULL; } else { SCLogInfo("using magic-file %s", filename); if ( (fd = fopen(filename, "r")) == NULL) { SCLogWarning(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno)); goto error; } fclose(fd); } } if (magic_load(t->ctx, filename) != 0) { SCLogError(SC_ERR_MAGIC_LOAD, "magic_load failed: %s", magic_error(t->ctx)); goto error; } return (void *)t; error: if (t->ctx) magic_close(t->ctx); SCFree(t); return NULL; }
/** * \brief Add a single Netfilter queue * * \param string with the queue number * * \retval 0 on success. * \retval -1 on failure. */ int NFQRegisterQueue(const uint16_t number) { NFQThreadVars *ntv = NULL; NFQQueueVars *nq = NULL; char queue[10] = { 0 }; static bool many_queues_warned = false; uint16_t num_cpus = UtilCpuGetNumProcessorsOnline(); if (g_nfq_t == NULL || g_nfq_q == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "NFQ context is not initialized"); return -1; } SCMutexLock(&nfq_init_lock); if (!many_queues_warned && (receive_queue_num >= num_cpus)) { SCLogWarning(SC_WARN_UNCOMMON, "using more Netfilter queues than %hu available CPU core(s) " "may degrade performance", num_cpus); many_queues_warned = true; } if (receive_queue_num >= NFQ_MAX_QUEUE) { SCLogError(SC_ERR_INVALID_ARGUMENT, "can not register more than %d Netfilter queues", NFQ_MAX_QUEUE); SCMutexUnlock(&nfq_init_lock); return -1; } ntv = &g_nfq_t[receive_queue_num]; ntv->nfq_index = receive_queue_num; nq = &g_nfq_q[receive_queue_num]; nq->queue_num = number; receive_queue_num++; SCMutexUnlock(&nfq_init_lock); snprintf(queue, sizeof(queue) - 1, "NFQ#%hu", number); LiveRegisterDevice(queue); ntv->livedev = LiveGetDevice(queue); if (ntv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); return -1; } SCLogDebug("Queue %d registered.", number); return 0; }
/** * \brief Create a new LogFileCtx for "syslog" output style. * * \param conf The configuration node for this output. * \return A OutputCtx pointer on success, NULL on failure. */ OutputCtx *AlertSyslogInitCtx(ConfNode *conf) { const char *facility_s = ConfNodeLookupChildValue(conf, "facility"); if (facility_s == NULL) { facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR; } LogFileCtx *logfile_ctx = LogFileNewCtx(); if (logfile_ctx == NULL) { SCLogDebug("AlertSyslogInitCtx: Could not create new LogFileCtx"); return NULL; } 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); OutputCtx *output_ctx = SCMalloc(sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCLogDebug("AlertSyslogInitCtx: Could not create new OutputCtx"); return NULL; } memset(output_ctx, 0x00, sizeof(OutputCtx)); output_ctx->data = logfile_ctx; output_ctx->DeInit = AlertSyslogDeInitCtx; SCLogInfo("Syslog output initialized"); return output_ctx; }
int GetIfaceRSSQueuesNum(const char *pcap_dev) { #if defined HAVE_LINUX_ETHTOOL_H && defined ETHTOOL_GRXRINGS struct ifreq ifr; struct ethtool_rxnfc nfccmd; int fd; (void)strlcpy(ifr.ifr_name, pcap_dev, sizeof(ifr.ifr_name)); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) { SCLogWarning(SC_ERR_SYSCALL, "Failure when opening socket for ioctl: %s (%d)", strerror(errno), errno); return -1; } nfccmd.cmd = ETHTOOL_GRXRINGS; ifr.ifr_data = (void*) &nfccmd; if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) { if (errno != ENOTSUP) { SCLogWarning(SC_ERR_SYSCALL, "Failure when trying to get number of RSS queue ioctl for '%s': %s (%d)", pcap_dev, strerror(errno), errno); } close(fd); return 0; } close(fd); SCLogInfo("Found %d RX RSS queues for '%s'", (int)nfccmd.data, pcap_dev); return (int)nfccmd.data; #else return 0; #endif }
static void LogFilestoreFinalizeFiles(const File *ff) { char pid_expression[PATH_MAX] = ""; if (FileIncludePid()) snprintf(pid_expression, sizeof(pid_expression), ".%d", getpid()); char final_filename[PATH_MAX] = ""; if (snprintf(final_filename, sizeof(final_filename), "%s/file%s.%u", g_logfile_base_dir, pid_expression, ff->file_store_id) == sizeof(final_filename)) return; char working_filename[PATH_MAX] = ""; if (snprintf(working_filename, sizeof(working_filename), "%s%s", final_filename, g_working_file_suffix) == sizeof(working_filename)) return; if (rename(working_filename, final_filename) != 0) { SCLogWarning(SC_WARN_RENAMING_FILE, "renaming file %s to %s failed", working_filename, final_filename); return; } if (FileWriteMeta()) { LogFilestoreLogCloseMetaFile(ff); char final_metafilename[PATH_MAX] = ""; if (snprintf(final_metafilename, sizeof(final_metafilename), "%s.meta", final_filename) == sizeof(final_metafilename)) return; char working_metafilename[PATH_MAX] = ""; if (snprintf(working_metafilename, sizeof(working_metafilename), "%s%s", final_metafilename, g_working_file_suffix) == sizeof(working_metafilename)) return; if (rename(working_metafilename, final_metafilename) != 0) { SCLogWarning(SC_WARN_RENAMING_FILE, "renaming metafile %s to %s failed", working_metafilename, final_metafilename); } } }
/** * \brief DeInit function closes divert socket at exit. * \todo Unit tests are needed for this module. * \param tv pointer to ThreadVars * \param data pointer that gets cast into IPFWThreadVars for ptv */ TmEcode ReceiveIPFWThreadDeinit(ThreadVars *tv, void *data) { IPFWThreadVars *ptv = (IPFWThreadVars *)data; IPFWQueueVars *nq = IPFWGetQueue(ptv->ipfw_index); SCEnter(); /* Attempt to shut the socket down...close instead? */ if (shutdown(nq->fd, SHUT_RD) < 0) { SCLogWarning(SC_WARN_IPFW_UNBIND,"Unable to disable ipfw socket: %s",strerror(errno)); SCReturnInt(TM_ECODE_FAILED); } SCReturnInt(TM_ECODE_OK); }
/** * \brief Attempt to reconnect a disconnected (or never-connected) Unix domain socket. * \retval 1 if it is now connected; otherwise 0 */ static int SCLogUnixSocketReconnect(LogFileCtx *log_ctx) { int disconnected = 0; if (log_ctx->fp) { SCLogWarning(SC_ERR_SOCKET, "Write error on Unix socket \"%s\": %s; reconnecting...", log_ctx->filename, strerror(errno)); fclose(log_ctx->fp); log_ctx->fp = NULL; log_ctx->reconn_timer = 0; disconnected = 1; } struct timeval tv; uint64_t now; gettimeofday(&tv, NULL); now = (uint64_t)tv.tv_sec * 1000; now += tv.tv_usec / 1000; /* msec resolution */ if (log_ctx->reconn_timer != 0 && (now - log_ctx->reconn_timer) < LOGFILE_RECONN_MIN_TIME) { /* Don't bother to try reconnecting too often. */ return 0; } log_ctx->reconn_timer = now; log_ctx->fp = SCLogOpenUnixSocketFp(log_ctx->filename, log_ctx->sock_type, 0); if (log_ctx->fp) { /* Connected at last (or reconnected) */ SCLogNotice("Reconnected socket \"%s\"", log_ctx->filename); } else if (disconnected) { SCLogWarning(SC_ERR_SOCKET, "Reconnect failed: %s (will keep trying)", strerror(errno)); } return log_ctx->fp ? 1 : 0; }
void CudaHandlerModuleStoreData(const char *module_name, const char *data_name, void *data_ptr) { SCMutexLock(&mutex); CudaHandlerModule *module = cudahl_modules; while (module != NULL && strcasecmp(module->name, module_name) != 0) module = module->next; if (module == NULL) { SCLogError(SC_ERR_CUDA_HANDLER_ERROR, "Trying to retrieve data " "\"%s\" from module \"%s\" that hasn't been registered " "yet.", module_name, data_name); exit(EXIT_FAILURE); } CudaHandlerModuleData *data = module->module_data; while (data != NULL && (strcasecmp(data_name, data->name) != 0)) { data = data->next; } if (data != NULL) { SCLogWarning(SC_ERR_CUDA_HANDLER_ERROR, "Data \"%s\" already " "registered for this module \"%s\".", data_name, module_name); SCMutexUnlock(&mutex); goto end; } CudaHandlerModuleData *new_data = SCMalloc(sizeof(CudaHandlerModuleData)); if (new_data == NULL) exit(EXIT_FAILURE); memset(new_data, 0, sizeof(CudaHandlerModuleData)); new_data->name = SCStrdup(data_name); if (new_data->name == NULL) exit(EXIT_FAILURE); new_data->data = data_ptr; if (module->module_data == NULL) { module->module_data = new_data; } else { new_data->next = module->module_data; module->module_data = new_data; } SCMutexUnlock(&mutex); end: return; }
static void OutputJsonDeInitCtx(OutputCtx *output_ctx) { OutputJsonCtx *json_ctx = (OutputJsonCtx *)output_ctx->data; LogFileCtx *logfile_ctx = json_ctx->file_ctx; if (logfile_ctx->dropped) { SCLogWarning(SC_WARN_EVENT_DROPPED, "%"PRIu64" events were dropped due to slow or " "disconnected socket", logfile_ctx->dropped); } if (json_ctx->xff_cfg != NULL) { SCFree(json_ctx->xff_cfg); } LogFileFreeCtx(logfile_ctx); SCFree(json_ctx); SCFree(output_ctx); }
/** * \brief Initialize the "magic" context. */ int MagicInit(void) { BUG_ON(g_magic_ctx != NULL); SCEnter(); char *filename = NULL; FILE *fd = NULL; SCMutexInit(&g_magic_lock, NULL); SCMutexLock(&g_magic_lock); g_magic_ctx = magic_open(0); if (g_magic_ctx == NULL) { SCLogError(SC_ERR_MAGIC_OPEN, "magic_open failed: %s", magic_error(g_magic_ctx)); goto error; } (void)ConfGet("magic-file", &filename); if (filename != NULL) { SCLogInfo("using magic-file %s", filename); if ( (fd = fopen(filename, "r")) == NULL) { SCLogWarning(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno)); goto error; } fclose(fd); } if (magic_load(g_magic_ctx, filename) != 0) { SCLogError(SC_ERR_MAGIC_LOAD, "magic_load failed: %s", magic_error(g_magic_ctx)); goto error; } SCMutexUnlock(&g_magic_lock); SCReturnInt(0); error: if (g_magic_ctx != NULL) { magic_close(g_magic_ctx); g_magic_ctx = NULL; } SCMutexUnlock(&g_magic_lock); SCReturnInt(-1); }
/** \brief SCRedisAsyncEchoCommandCallback() Callback for an ECHO command reply * This is used to check if redis is connected. * \param ac redis async context * \param r redis reply * \param privvata opaque datq with pointer to LogFileCtx */ static void SCRedisAsyncEchoCommandCallback(redisAsyncContext *ac, void *r, void *privdata) { redisReply *reply = r; SCLogRedisContext * ctx = privdata; if (reply) { if (ctx->connected == 0) { SCLogNotice("Connected to Redis."); ctx->connected = 1; ctx->tried = 0; } } else { ctx->connected = 0; if (ctx->tried == 0) { SCLogWarning(SC_ERR_SOCKET, "Failed to connect to Redis... (will keep trying)"); } ctx->tried = time(NULL); } event_base_loopbreak(ctx->ev_base); }
void ReceivePcapFileThreadExitStats(ThreadVars *tv, void *data) { SCEnter(); PcapFileThreadVars *ptv = (PcapFileThreadVars *)data; if (pcap_g.conf_checksum_mode == CHECKSUM_VALIDATION_AUTO && pcap_g.cnt < CHECKSUM_SAMPLE_COUNT && SC_ATOMIC_GET(pcap_g.invalid_checksums)) { uint64_t chrate = pcap_g.cnt / SC_ATOMIC_GET(pcap_g.invalid_checksums); if (chrate < CHECKSUM_INVALID_RATIO) SCLogWarning(SC_ERR_INVALID_CHECKSUM, "1/%" PRIu64 "th of packets have an invalid checksum," " consider setting pcap-file.checksum-checks variable to no" " or use '-k none' option on command line.", chrate); else SCLogInfo("1/%" PRIu64 "th of packets have an invalid checksum", chrate); } SCLogNotice("Pcap-file module read %" PRIu32 " packets, %" PRIu64 " bytes", ptv->pkts, ptv->bytes); return; }
/** * \brief NFQ receive module main entry function: receive a packet from NFQ */ TmEcode ReceiveNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { NFQThreadVars *ntv = (NFQThreadVars *)data; NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index); if (nq == NULL) { SCLogWarning(SC_ERR_INVALID_ARGUMENT, "can't get queue for %" PRId16 "", ntv->nfq_index); return TM_ECODE_FAILED; } /* make sure we have at least one packet in the packet pool, to prevent * us from 1) alloc'ing packets at line rate, 2) have a race condition * for the nfq mutex lock with the verdict thread. */ while (PacketPoolSize() == 0) { PacketPoolWait(); } /* do our nfq magic */ NFQRecvPkt(nq, ntv); return TM_ECODE_OK; }
static const char *PrintInetIPv6(const void *src, char *dst, socklen_t size) { int i; char s_part[6]; uint16_t x[8]; memcpy(&x, src, 16); /* current IPv6 format is fixed size */ if (size < 8 * 5) { SCLogWarning(SC_ERR_ARG_LEN_LONG, "Too small buffer to write IPv6 address"); return NULL; } memset(dst, 0, size); for(i = 0; i < 8; i++) { snprintf(s_part, sizeof(s_part), "%04x:", htons(x[i])); strlcat(dst, s_part, size); } /* suppress last ':' */ dst[strlen(dst) - 1] = 0; return dst; }
void CleanupPcapFileFileVars(PcapFileFileVars *pfv) { if (pfv != NULL) { if (pfv->pcap_handle != NULL) { pcap_close(pfv->pcap_handle); pfv->pcap_handle = NULL; } if (pfv->filename != NULL) { if (pfv->shared != NULL && pfv->shared->should_delete) { SCLogDebug("Deleting pcap file %s", pfv->filename); if (unlink(pfv->filename) != 0) { SCLogWarning(SC_ERR_PCAP_FILE_DELETE_FAILED, "Failed to delete %s", pfv->filename); } } SCFree(pfv->filename); pfv->filename = NULL; } pfv->shared = NULL; SCFree(pfv); } }
void MpmRegisterTests(void) { #ifdef UNITTESTS uint16_t i; for (i = 0; i < MPM_TABLE_SIZE; i++) { if (i == MPM_NOTSET) continue; g_ut_modules++; if (mpm_table[i].RegisterUnittests != NULL) { g_ut_covered++; mpm_table[i].RegisterUnittests(); } else { if (coverage_unittests) SCLogWarning(SC_WARN_NO_UNITTESTS, "mpm module %s has no " "unittest registration function.", mpm_table[i].name); } } #endif }
/** \brief open the indicated file, logging any errors * \param path filesystem path to open * \param append_setting open file with O_APPEND: "yes" or "no" * \param mode permissions to set on file * \retval FILE* on success * \retval NULL on error */ static FILE * SCLogOpenFileFp(const char *path, const char *append_setting, uint32_t mode) { FILE *ret = NULL; char *filename = SCLogFilenameFromPattern(path); if (filename == NULL) { return NULL; } int rc = SCLogCreateDirectoryTree(filename); if (rc < 0) { SCFree(filename); return NULL; } if (ConfValIsTrue(append_setting)) { ret = fopen(filename, "a"); } else { ret = fopen(filename, "w"); } if (ret == NULL) { SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno)); } else { if (mode != 0) { int r = chmod(filename, mode); if (r < 0) { SCLogWarning(SC_WARN_CHMOD, "Could not chmod %s to %u: %s", filename, mode, strerror(errno)); } } } SCFree(filename); return ret; }
/** * \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, "type"); if (output_s != NULL) { if (strcmp(output_s, "file") == 0) { json_ctx->json_out = ALERT_FILE; } else if (strcmp(output_s, "syslog") == 0) { json_ctx->json_out = ALERT_SYSLOG; } else if (strcmp(output_s, "unix_dgram") == 0) { json_ctx->json_out = ALERT_UNIX_DGRAM; } else if (strcmp(output_s, "unix_stream") == 0) { json_ctx->json_out = ALERT_UNIX_STREAM; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid JSON output option: %s", output_s); exit(EXIT_FAILURE); } } if (json_ctx->json_out == ALERT_FILE) { if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME) < 0) { LogFileFreeCtx(json_ctx->file_ctx); SCFree(json_ctx); SCFree(output_ctx); return NULL; } 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_out == ALERT_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); } } format = json_ctx->format; json_out = json_ctx->json_out; } return output_ctx; }