suricata
detect-engine-loader.c
Go to the documentation of this file.
1/* Copyright (C) 2021-2023 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 */
23
24#include "suricata-common.h"
25#include "suricata.h"
26#include "conf.h"
27#include "detect.h"
28#include "detect-parse.h"
29
30#include "runmodes.h"
31#include "threads.h"
32#include "threadvars.h"
33#include "tm-threads.h"
34#include "queue.h"
35
36#include "detect-engine.h"
38#include "detect-engine-build.h"
40#include "detect-engine-mpm.h"
42
43#include "util-detect.h"
45#include "util-path.h"
46
47#include "rust.h"
48
49#ifdef HAVE_GLOB_H
50#include <glob.h>
51#endif
52
53extern int rule_reload;
54extern int engine_analysis;
55static bool fp_engine_analysis_set = false;
57
58static char *DetectLoadCompleteSigPathWithKey(
59 const DetectEngineCtx *de_ctx, const char *default_key, const char *sig_file)
60{
61 const char *defaultpath = NULL;
62 char *path = NULL;
63 char varname[128];
64
65 if (sig_file == NULL) {
66 SCLogError("invalid sig_file argument - NULL");
67 return NULL;
68 }
69
70 /* If we have a configuration prefix, only use it if the primary configuration node
71 * is not marked as final, as that means it was provided on the command line with
72 * a --set. */
73 SCConfNode *default_rule_path = SCConfGetNode(default_key);
74 if ((!default_rule_path || !default_rule_path->final) && strlen(de_ctx->config_prefix) > 0) {
75 snprintf(varname, sizeof(varname), "%s.%s", de_ctx->config_prefix, default_key);
76 default_rule_path = SCConfGetNode(varname);
77 }
78 if (default_rule_path) {
79 defaultpath = default_rule_path->val;
80 }
81
82 /* Path not specified */
83 if (PathIsRelative(sig_file)) {
84 if (defaultpath) {
85 path = PathMergeAlloc(defaultpath, sig_file);
86 if (unlikely(path == NULL))
87 return NULL;
88 } else {
89 path = SCStrdup(sig_file);
90 if (unlikely(path == NULL))
91 return NULL;
92 }
93 } else {
94 path = SCStrdup(sig_file);
95 if (unlikely(path == NULL))
96 return NULL;
97 }
98 return path;
99}
100
101/**
102 * \brief Create the path if default-rule-path was specified
103 * \param sig_file The name of the file
104 * \retval str Pointer to the string path + sig_file
105 */
106char *DetectLoadCompleteSigPath(const DetectEngineCtx *de_ctx, const char *sig_file)
107{
108 return DetectLoadCompleteSigPathWithKey(de_ctx, "default-rule-path", sig_file);
109}
110
111/**
112 * \brief Load a file with signatures
113 * \param de_ctx Pointer to the detection engine context
114 * \param sig_file Filename to load signatures from
115 * \param goodsigs_tot Will store number of valid signatures in the file
116 * \param badsigs_tot Will store number of invalid signatures in the file
117 * \retval 0 on success, -1 on error
118 */
119static int DetectLoadSigFile(DetectEngineCtx *de_ctx, const char *sig_file, int *goodsigs,
120 int *badsigs, int *skippedsigs, const bool firewall_rule)
121{
122 int good = 0, bad = 0, skipped = 0;
123 char line[DETECT_MAX_RULE_SIZE] = "";
124 size_t offset = 0;
125 int lineno = 0, multiline = 0;
126
127 (*goodsigs) = 0;
128 (*badsigs) = 0;
129 (*skippedsigs) = 0;
130
131 FILE *fp = fopen(sig_file, "r");
132 if (fp == NULL) {
133 SCLogError("opening rule file %s:"
134 " %s.",
135 sig_file, strerror(errno));
136 return -1;
137 }
138
139 while (1) {
140 /* help clang to understand offset can't get > sizeof(line), so the argument to
141 * fgets can't get negative. */
142 BUG_ON(offset >= sizeof(line));
143 char *res = fgets(line + offset, (int)(sizeof(line) - offset), fp);
144 if (res == NULL)
145 break;
146
147 lineno++;
148 size_t len = strlen(line);
149
150 /* ignore comments and empty lines */
151 if (line[0] == '\n' || line [0] == '\r' || line[0] == ' ' || line[0] == '#' || line[0] == '\t')
152 continue;
153
154 /* Check for multiline rules. */
155 while (len > 0 && isspace((unsigned char)line[--len]));
156 if (line[len] == '\\') {
157 multiline++;
158 offset = len;
159 if (offset < sizeof(line) - 1) {
160 /* We have room for more. */
161 continue;
162 }
163 /* No more room in line buffer, continue, rule will fail
164 * to parse. */
165 }
166
167 /* Check if we have a trailing newline, and remove it */
168 len = strlen(line);
169 if (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
170 line[len - 1] = '\0';
171 }
172
173 /* Reset offset. */
174 offset = 0;
175
176 de_ctx->rule_file = sig_file;
177 de_ctx->rule_line = lineno - multiline;
178
179 Signature *sig = NULL;
180 if (firewall_rule)
182 else
183 sig = DetectEngineAppendSig(de_ctx, line);
184 if (sig != NULL) {
185 if (rule_engine_analysis_set || fp_engine_analysis_set) {
186 if (fp_engine_analysis_set) {
187 EngineAnalysisFP(de_ctx, sig, line);
188 }
190 EngineAnalysisRules(de_ctx, sig, line);
191 }
192 }
193 SCLogDebug("signature %"PRIu32" loaded", sig->id);
194 good++;
195 } else {
196 if (!de_ctx->sigerror_silent) {
197 SCLogError("error parsing signature \"%s\" from "
198 "file %s at line %" PRId32 "",
199 line, sig_file, lineno - multiline);
200
201 if (!SigStringAppend(&de_ctx->sig_stat, sig_file, line, de_ctx->sigerror, (lineno - multiline))) {
202 SCLogError("Error adding sig \"%s\" from "
203 "file %s at line %" PRId32 "",
204 line, sig_file, lineno - multiline);
205 }
206 if (de_ctx->sigerror) {
207 de_ctx->sigerror = NULL;
208 }
209 }
211 EngineAnalysisRulesFailure(de_ctx, line, sig_file, lineno - multiline);
212 }
213 if (!de_ctx->sigerror_ok) {
214 bad++;
215 }
217 SCLogInfo("Skipping signature due to missing requirements: %s from file %s at line "
218 "%" PRId32,
219 line, sig_file, lineno - multiline);
220 skipped++;
221 }
222 }
223 multiline = 0;
224 }
225 fclose(fp);
226
227 *goodsigs = good;
228 *badsigs = bad;
229 *skippedsigs = skipped;
230 return 0;
231}
232
233/**
234 * \brief Expands wildcards and reads signatures from each matching file
235 * \param de_ctx Pointer to the detection engine context
236 * \param sig_file Filename (or pattern) holding signatures
237 * \retval -1 on error
238 */
239static int ProcessSigFiles(DetectEngineCtx *de_ctx, char *pattern, SigFileLoaderStat *st,
240 int *good_sigs, int *bad_sigs, int *skipped_sigs)
241{
242 int r = 0;
243
244 if (pattern == NULL) {
245 SCLogError("opening rule file null");
246 return -1;
247 }
248
249#ifdef HAVE_GLOB_H
250 glob_t files;
251 r = glob(pattern, 0, NULL, &files);
252
253 if (r == GLOB_NOMATCH) {
254 SCLogWarning("No rule files match the pattern %s", pattern);
255 ++(st->bad_files);
256 ++(st->total_files);
257 return -1;
258 } else if (r != 0) {
259 SCLogError("error expanding template %s: %s", pattern, strerror(errno));
260 return -1;
261 }
262
263 for (size_t i = 0; i < (size_t)files.gl_pathc; i++) {
264 char *fname = files.gl_pathv[i];
265 if (strcmp("/dev/null", fname) == 0)
266 continue;
267#else
268 char *fname = pattern;
269 if (strcmp("/dev/null", fname) == 0)
270 return 0;
271#endif
272 if (strlen(de_ctx->config_prefix) > 0) {
273 SCLogConfig("tenant id %d: Loading rule file: %s", de_ctx->tenant_id, fname);
274 } else {
275 SCLogConfig("Loading rule file: %s", fname);
276 }
277 r = DetectLoadSigFile(de_ctx, fname, good_sigs, bad_sigs, skipped_sigs, false);
278 if (r < 0) {
279 ++(st->bad_files);
280 }
281
282 ++(st->total_files);
283
284 st->good_sigs_total += *good_sigs;
285 st->bad_sigs_total += *bad_sigs;
286 st->skipped_sigs_total += *skipped_sigs;
287
288#ifdef HAVE_GLOB_H
289 }
290 globfree(&files);
291#endif
292 return r;
293}
294
295static int LoadFirewallRuleFiles(DetectEngineCtx *de_ctx)
296{
298 int32_t good_sigs = 0;
299 int32_t bad_sigs = 0;
300 int32_t skipped_sigs = 0;
301
302 SCLogNotice("fw: rule file full path \"%s\"", de_ctx->firewall_rule_file_exclusive);
303
304 int ret = DetectLoadSigFile(de_ctx, de_ctx->firewall_rule_file_exclusive, &good_sigs,
305 &bad_sigs, &skipped_sigs, true);
306
307 /* for now be as strict as possible */
308 if (ret != 0 || bad_sigs != 0 || skipped_sigs != 0) {
309 /* Some rules failed to load, just exit as
310 * errors would have already been logged. */
311 exit(EXIT_FAILURE);
312 }
313
314 if (good_sigs == 0) {
315 SCLogNotice("fw: No rules loaded from %s.", de_ctx->firewall_rule_file_exclusive);
316 } else {
317 SCLogNotice("fw: %d rules loaded from %s.", good_sigs,
319 de_ctx->sig_stat.good_sigs_total += good_sigs;
320 }
321
322 return 0;
323 }
324
325 SCConfNode *default_fw_rule_path = SCConfGetNode("firewall.rule-path");
326 if (default_fw_rule_path == NULL) {
327 SCLogNotice("fw: firewall.rule-path not defined, skip loading firewall rules");
328 return 0;
329 }
330 SCConfNode *rule_files = SCConfGetNode("firewall.rule-files");
331 if (rule_files == NULL) {
332 SCLogNotice("fw: firewall.rule-files not defined, skip loading firewall rules");
333 return 0;
334 }
335
336 SCConfNode *file = NULL;
337 TAILQ_FOREACH (file, &rule_files->head, next) {
338 int32_t good_sigs = 0;
339 int32_t bad_sigs = 0;
340 int32_t skipped_sigs = 0;
341
342 char *sfile = DetectLoadCompleteSigPathWithKey(de_ctx, "firewall.rule-path", file->val);
343 SCLogNotice("fw: rule file full path \"%s\"", sfile);
344
345 int ret = DetectLoadSigFile(de_ctx, sfile, &good_sigs, &bad_sigs, &skipped_sigs, true);
346 SCFree(sfile);
347
348 /* for now be as strict as possible */
349 if (ret != 0 || bad_sigs != 0 || skipped_sigs != 0) {
350 /* Some rules failed to load, just exit as
351 * errors would have already been logged. */
352 exit(EXIT_FAILURE);
353 }
354
355 if (good_sigs == 0) {
356 SCLogNotice("fw: No rules loaded from %s.", file->val);
357 } else {
358 SCLogNotice("fw: %d rules loaded from %s.", good_sigs, file->val);
359 de_ctx->sig_stat.good_sigs_total += good_sigs;
360 }
361 }
362 return 0;
363}
364
365/**
366 * \brief Load signatures
367 * \param de_ctx Pointer to the detection engine context
368 * \param sig_file Filename (or pattern) holding signatures
369 * \param sig_file_exclusive File passed in 'sig_file' should be loaded exclusively.
370 * \retval -1 on error
371 */
372int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, bool sig_file_exclusive)
373{
374 SCEnter();
375
376 SCConfNode *rule_files;
377 SCConfNode *file = NULL;
378 SigFileLoaderStat *sig_stat = &de_ctx->sig_stat;
379 int ret = 0;
380 char *sfile = NULL;
381 char varname[128] = "rule-files";
382 int good_sigs = 0;
383 int bad_sigs = 0;
384 int skipped_sigs = 0;
385
386 if (strlen(de_ctx->config_prefix) > 0) {
387 snprintf(varname, sizeof(varname), "%s.rule-files", de_ctx->config_prefix);
388 }
389
391 SetupEngineAnalysis(de_ctx, &fp_engine_analysis_set, &rule_engine_analysis_set);
392 }
393
395 if (LoadFirewallRuleFiles(de_ctx) < 0) {
396 if (de_ctx->failure_fatal) {
397 exit(EXIT_FAILURE);
398 }
399 ret = -1;
400 goto end;
401 }
402
403 /* skip regular rules if we used a exclusive firewall rule file */
404 if (!sig_file_exclusive && de_ctx->firewall_rule_file_exclusive) {
405 ret = 0;
406 goto skip_regular_rules;
407 }
408 }
409
410 /* ok, let's load signature files from the general config */
411 if (!(sig_file != NULL && sig_file_exclusive)) {
412 rule_files = SCConfGetNode(varname);
413 if (rule_files != NULL) {
414 if (!SCConfNodeIsSequence(rule_files)) {
415 SCLogWarning("Invalid rule-files configuration section: "
416 "expected a list of filenames.");
417 } else {
418 TAILQ_FOREACH(file, &rule_files->head, next) {
419 sfile = DetectLoadCompleteSigPath(de_ctx, file->val);
420 good_sigs = bad_sigs = skipped_sigs = 0;
421 ret = ProcessSigFiles(
422 de_ctx, sfile, sig_stat, &good_sigs, &bad_sigs, &skipped_sigs);
423 SCFree(sfile);
424
425 if (de_ctx->failure_fatal && ret != 0) {
426 /* Some rules failed to load, just exit as
427 * errors would have already been logged. */
428 exit(EXIT_FAILURE);
429 }
430
431 if (good_sigs == 0) {
432 SCLogConfig("No rules loaded from %s.", file->val);
433 }
434 }
435 }
436 }
437 }
438
439 /* If a Signature file is specified from command-line, parse it too */
440 if (sig_file != NULL) {
441 ret = ProcessSigFiles(de_ctx, sig_file, sig_stat, &good_sigs, &bad_sigs, &skipped_sigs);
442
443 if (ret != 0) {
444 if (de_ctx->failure_fatal) {
445 exit(EXIT_FAILURE);
446 }
447 }
448
449 if (good_sigs == 0) {
450 SCLogConfig("No rules loaded from %s", sig_file);
451 }
452 }
453
454skip_regular_rules:
455 /* now we should have signatures to work with */
456 if (sig_stat->good_sigs_total <= 0) {
457 if (sig_stat->total_files > 0) {
459 "%d rule files specified, but no rules were loaded!", sig_stat->total_files);
460 } else {
461 SCLogInfo("No signatures supplied.");
462 goto end;
463 }
464 } else {
465 /* we report the total of files and rules successfully loaded and failed */
466 if (strlen(de_ctx->config_prefix) > 0) {
467 SCLogInfo("tenant id %d: %" PRId32 " rule files processed. %" PRId32
468 " rules successfully loaded, %" PRId32 " rules failed, %" PRId32
469 " rules skipped",
470 de_ctx->tenant_id, sig_stat->total_files, sig_stat->good_sigs_total,
471 sig_stat->bad_sigs_total, sig_stat->skipped_sigs_total);
472 } else {
473 SCLogInfo("%" PRId32 " rule files processed. %" PRId32
474 " rules successfully loaded, %" PRId32 " rules failed, %" PRId32
475 " rules skipped",
476 sig_stat->total_files, sig_stat->good_sigs_total, sig_stat->bad_sigs_total,
477 sig_stat->skipped_sigs_total);
478 }
479 if (de_ctx->requirements != NULL && sig_stat->skipped_sigs_total > 0) {
480 SCDetectRequiresStatusLog(de_ctx->requirements, PROG_VER,
481 strlen(de_ctx->config_prefix) > 0 ? de_ctx->tenant_id : 0);
482 }
483 }
484
485 if ((sig_stat->bad_sigs_total || sig_stat->bad_files) && de_ctx->failure_fatal) {
486 ret = -1;
487 goto end;
488 }
489
493
495 ret = -1;
496 goto end;
497 }
498
499 /* Setup the signature group lookup structure and pattern matchers */
500 if (SigGroupBuild(de_ctx) < 0)
501 goto end;
502
503 ret = 0;
504
507 }
508
509 end:
510 gettimeofday(&de_ctx->last_reload, NULL);
513 }
514
516 SCReturnInt(ret);
517}
518
519#define NLOADERS 4
520static DetectLoaderControl *loaders = NULL;
521static int cur_loader = 0;
522static void TmThreadWakeupDetectLoaderThreads(void);
523static int num_loaders = NLOADERS;
524
525/** \param loader -1 for auto select
526 * \retval loader_id or negative in case of error */
527int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx, LoaderFreeFunc FreeFunc)
528{
529 if (loader_id == -1) {
530 loader_id = cur_loader;
531 cur_loader++;
532 if (cur_loader >= num_loaders)
533 cur_loader = 0;
534 }
535 if (loader_id >= num_loaders || loader_id < 0) {
536 return -ERANGE;
537 }
538
539 DetectLoaderControl *loader = &loaders[loader_id];
540
541 DetectLoaderTask *t = SCCalloc(1, sizeof(*t));
542 if (t == NULL)
543 return -ENOMEM;
544
545 t->Func = Func;
546 t->ctx = func_ctx;
547 t->FreeFunc = FreeFunc;
548
549 SCMutexLock(&loader->m);
550 TAILQ_INSERT_TAIL(&loader->task_list, t, next);
551 SCMutexUnlock(&loader->m);
552
553 TmThreadWakeupDetectLoaderThreads();
554
555 SCLogDebug("%d %p %p", loader_id, Func, func_ctx);
556 return loader_id;
557}
558
559/** \brief wait for loader tasks to complete
560 * \retval result 0 for ok, -1 for errors */
562{
563 SCLogDebug("waiting");
564 int errors = 0;
565 for (int i = 0; i < num_loaders; i++) {
566 bool done = false;
567
568 DetectLoaderControl *loader = &loaders[i];
569 while (!done) {
570 SCMutexLock(&loader->m);
571 if (TAILQ_EMPTY(&loader->task_list)) {
572 done = true;
573 }
574 SCMutexUnlock(&loader->m);
575 if (!done) {
576 /* nudge thread in case it's sleeping */
577 SCCtrlMutexLock(loader->tv->ctrl_mutex);
578 pthread_cond_broadcast(loader->tv->ctrl_cond);
580 }
581 }
582 SCMutexLock(&loader->m);
583 if (loader->result != 0) {
584 errors++;
585 loader->result = 0;
586 }
587 SCMutexUnlock(&loader->m);
588 }
589 if (errors) {
590 SCLogError("%d loaders reported errors", errors);
591 return -1;
592 }
593 SCLogDebug("done");
594 return 0;
595}
596
597static void DetectLoaderInit(DetectLoaderControl *loader)
598{
599 memset(loader, 0x00, sizeof(*loader));
600 SCMutexInit(&loader->m, NULL);
601 TAILQ_INIT(&loader->task_list);
602}
603
605{
606 intmax_t setting = NLOADERS;
607 (void)SCConfGetInt("multi-detect.loaders", &setting);
608
609 if (setting < 1 || setting > 1024) {
610 FatalError("invalid multi-detect.loaders setting %" PRIdMAX, setting);
611 }
612
613 num_loaders = (int32_t)setting;
614 SCLogInfo("using %d detect loader threads", num_loaders);
615
616 BUG_ON(loaders != NULL);
617 loaders = SCCalloc(num_loaders, sizeof(DetectLoaderControl));
618 BUG_ON(loaders == NULL);
619
620 for (int i = 0; i < num_loaders; i++) {
621 DetectLoaderInit(&loaders[i]);
622 }
623}
624
625/**
626 * \brief Unpauses all threads present in tv_root
627 */
628static void TmThreadWakeupDetectLoaderThreads(void)
629{
631 for (int i = 0; i < TVT_MAX; i++) {
632 ThreadVars *tv = tv_root[i];
633 while (tv != NULL) {
634 if (strncmp(tv->name,"DL#",3) == 0) {
635 BUG_ON(tv->ctrl_cond == NULL);
637 pthread_cond_broadcast(tv->ctrl_cond);
639 }
640 tv = tv->next;
641 }
642 }
644}
645
646/**
647 * \brief Unpauses all threads present in tv_root
648 */
650{
652 for (int i = 0; i < TVT_MAX; i++) {
653 ThreadVars *tv = tv_root[i];
654 while (tv != NULL) {
655 if (strncmp(tv->name,"DL#",3) == 0)
657
658 tv = tv->next;
659 }
660 }
662}
663
664SC_ATOMIC_DECLARE(int, detect_loader_cnt);
665
669
670static TmEcode DetectLoaderThreadInit(ThreadVars *t, const void *initdata, void **data)
671{
673 if (ftd == NULL)
674 return TM_ECODE_FAILED;
675
676 ftd->instance = SC_ATOMIC_ADD(detect_loader_cnt, 1); /* id's start at 0 */
677 SCLogDebug("detect loader instance %u", ftd->instance);
678
679 /* pass thread data back to caller */
680 *data = ftd;
681
682 DetectLoaderControl *loader = &loaders[ftd->instance];
683 loader->tv = t;
684
685 return TM_ECODE_OK;
686}
687
688static TmEcode DetectLoaderThreadDeinit(ThreadVars *t, void *data)
689{
690 SCFree(data);
691 return TM_ECODE_OK;
692}
693
694
695static TmEcode DetectLoader(ThreadVars *th_v, void *thread_data)
696{
698 BUG_ON(ftd == NULL);
699
701 SCLogDebug("loader thread started");
702 bool run = TmThreadsWaitForUnpause(th_v);
703 while (run) {
704 /* see if we have tasks */
705
706 DetectLoaderControl *loader = &loaders[ftd->instance];
707 SCMutexLock(&loader->m);
708
709 DetectLoaderTask *task = NULL, *tmptask = NULL;
710 TAILQ_FOREACH_SAFE(task, &loader->task_list, next, tmptask) {
711 int r = task->Func(task->ctx, ftd->instance);
712 loader->result |= r;
713 TAILQ_REMOVE(&loader->task_list, task, next);
714 task->FreeFunc(task->ctx);
715 SCFree(task);
716 }
717
718 SCMutexUnlock(&loader->m);
719
720 /* just wait until someone wakes us up */
722 int rc = 0;
723 while (rc == 0) {
724 if (TmThreadsCheckFlag(th_v, THV_KILL)) {
725 run = false;
726 break;
727 }
728 SCMutexLock(&loader->m);
729 bool has_work = loader->task_list.tqh_first != NULL;
730 SCMutexUnlock(&loader->m);
731 if (has_work)
732 break;
733
734 rc = SCCtrlCondWait(th_v->ctrl_cond, th_v->ctrl_mutex);
735 }
737
738 SCLogDebug("woke up...");
739 }
740
744
745 return TM_ECODE_OK;
746}
747
748/** \brief spawn the detect loader manager thread */
750{
751 for (int i = 0; i < num_loaders; i++) {
753 snprintf(name, sizeof(name), "%s#%02d", thread_name_detect_loader, i+1);
754
755 ThreadVars *tv_loader = TmThreadCreateCmdThreadByName(name, "DetectLoader", 1);
756 if (tv_loader == NULL) {
757 FatalError("failed to create thread %s", name);
758 }
759 if (TmThreadSpawn(tv_loader) != TM_ECODE_OK) {
760 FatalError("failed to create spawn %s", name);
761 }
762 }
763}
764
766{
767 tmm_modules[TMM_DETECTLOADER].name = "DetectLoader";
768 tmm_modules[TMM_DETECTLOADER].ThreadInit = DetectLoaderThreadInit;
769 tmm_modules[TMM_DETECTLOADER].ThreadDeinit = DetectLoaderThreadDeinit;
773 SCLogDebug("%s registered", tmm_modules[TMM_DETECTLOADER].name);
774
775 SC_ATOMIC_INIT(detect_loader_cnt);
776}
uint8_t len
struct HtpBodyChunk_ * next
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition conf.c:181
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition conf.c:414
int SCConfNodeIsSequence(const SCConfNode *node)
Check if a node is a sequence or node.
Definition conf.c:925
void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
void EngineAnalysisRulesFailure(const DetectEngineCtx *de_ctx, const char *line, const char *file, int lineno)
void SetupEngineAnalysis(DetectEngineCtx *de_ctx, bool *fp_analysis, bool *rule_analysis)
void CleanupEngineAnalysis(DetectEngineCtx *de_ctx)
void EngineAnalysisRules(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
Prints analysis of loaded rules.
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
int DetectLoadersSync(void)
wait for loader tasks to complete
#define NLOADERS
void TmModuleDetectLoaderRegister(void)
int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, bool sig_file_exclusive)
Load signatures.
void DetectLoaderThreadSpawn(void)
spawn the detect loader manager thread
int engine_analysis
int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx, LoaderFreeFunc FreeFunc)
char * DetectLoadCompleteSigPath(const DetectEngineCtx *de_ctx, const char *sig_file)
Create the path if default-rule-path was specified.
int rule_reload
void DetectLoadersInit(void)
bool rule_engine_analysis_set
void TmThreadContinueDetectLoaderThreads(void)
Unpauses all threads present in tv_root.
struct DetectLoaderThreadData_ DetectLoaderThreadData
int(* LoaderFunc)(void *ctx, int loader_id)
void(* LoaderFreeFunc)(void *ctx)
void SCSigOrderSignatures(DetectEngineCtx *de_ctx)
Orders the signatures.
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
Lets you register the Signature ordering functions. The order in which the functions are registered s...
void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
Frees the hash table that is used to cull duplicate sigs.
Signature * DetectFirewallRuleAppendNew(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
#define DETECT_MAX_RULE_SIZE
Definition detect.h:46
ThreadVars * tv
DetectEngineCtx * de_ctx
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:329
#define TAILQ_INIT(head)
Definition queue.h:262
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition queue.h:294
#define TAILQ_REMOVE(head, elm, field)
Definition queue.h:312
#define TAILQ_EMPTY(head)
Definition queue.h:248
const char * thread_name_detect_loader
Definition runmodes.c:74
@ RUNMODE_ENGINE_ANALYSIS
Definition runmodes.h:56
main detection engine ctx
Definition detect.h:932
bool sigerror_silent
Definition detect.h:1026
const char * rule_file
Definition detect.h:1024
uint8_t mpm_matcher
Definition detect.h:935
const char * firewall_rule_file_exclusive
Definition detect.h:1144
uint32_t tenant_id
Definition detect.h:939
SigFileLoaderStat sig_stat
Definition detect.h:1102
bool sigerror_requires
Definition detect.h:1030
const char * sigerror
Definition detect.h:1025
SCDetectRequiresStatus * requirements
Definition detect.h:1135
MpmConfig * mpm_cfg
Definition detect.h:936
char config_prefix[64]
Definition detect.h:1051
bool failure_fatal
Definition detect.h:933
struct timeval last_reload
Definition detect.h:1099
int(* CacheRuleset)(MpmConfig *)
Definition util-mpm.h:176
int final
Definition conf.h:44
char * val
Definition conf.h:39
Signature loader statistics.
Definition detect.h:876
Signature container.
Definition detect.h:668
uint32_t id
Definition detect.h:713
Per thread variable structure.
Definition threadvars.h:58
char name[16]
Definition threadvars.h:65
SCCtrlMutex * ctrl_mutex
Definition threadvars.h:132
struct ThreadVars_ * next
Definition threadvars.h:125
SCCtrlCondT * ctrl_cond
Definition threadvars.h:133
const char * name
Definition tm-modules.h:48
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition tm-modules.h:53
uint8_t cap_flags
Definition tm-modules.h:77
uint8_t flags
Definition tm-modules.h:80
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition tm-modules.h:51
TmEcode(* Management)(ThreadVars *, void *)
Definition tm-modules.h:69
#define BUG_ON(x)
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition suricata.c:279
#define PROG_VER
Definition suricata.h:76
#define SCCtrlMutexLock(mut)
#define SCMutexUnlock(mut)
#define SCCtrlMutexUnlock(mut)
#define SCMutexInit(mut, mutattrs)
#define SCCtrlCondWait
#define SCMutexLock(mut)
#define THV_RUNNING_DONE
Definition threadvars.h:46
#define THV_CLOSED
Definition threadvars.h:42
#define THV_DEINIT
Definition threadvars.h:45
#define THV_KILL
Definition threadvars.h:40
#define THV_RUNNING
Definition threadvars.h:55
#define THV_INIT_DONE
Definition threadvars.h:37
TmModule tmm_modules[TMM_SIZE]
Definition tm-modules.c:29
#define TM_FLAG_MANAGEMENT_TM
Definition tm-modules.h:36
@ TVT_MAX
@ TMM_DETECTLOADER
@ TM_ECODE_FAILED
@ TM_ECODE_OK
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition tm-threads.c:93
ThreadVars * TmThreadCreateCmdThreadByName(const char *name, const char *module, int mucond)
Creates and returns the TV instance for a Command thread (CMD). This function supports only custom sl...
const char * name
void TmThreadWaitForFlag(ThreadVars *tv, uint32_t flags)
Waits till the specified flag(s) is(are) set. We don't bother if the kill flag has been set or not on...
ThreadVars * tv_root[TVT_MAX]
Definition tm-threads.c:82
void TmThreadContinue(ThreadVars *tv)
Unpauses a thread.
SCMutex tv_root_lock
Definition tm-threads.c:85
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition tm-threads.c:363
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition tm-threads.c:101
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
#define TM_THREAD_NAME_MAX
Definition tm-threads.h:49
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
#define SC_ATOMIC_DECLARE(type, name)
wrapper for declaring atomic variables.
#define SCEnter(...)
Definition util-debug.h:277
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition util-debug.h:243
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCLogConfig(...)
Definition util-debug.h:229
int SigStringAppend(SigFileLoaderStat *sig_stats, const char *sig_file, const char *sig_str, const char *sig_error, int line)
Append a new list member to SigString list.
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define SCStrdup(s)
Definition util-mem.h:56
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition util-mpm.c:47
#define unlikely(expr)
char * PathMergeAlloc(const char *const dir, const char *const fname)
Definition util-path.c:107
int PathIsRelative(const char *path)
Check if a path is relative.
Definition util-path.c:69
uint64_t offset
int SCThresholdConfInitContext(DetectEngineCtx *de_ctx)
Inits the context to be used by the Threshold Config parsing API.