suricata
detect-engine.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2019 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 "debug.h"
27 #include "detect.h"
28 #include "flow.h"
29 #include "flow-private.h"
30 #include "flow-util.h"
31 #include "flow-worker.h"
32 #include "conf.h"
33 #include "conf-yaml-loader.h"
34 
35 #include "app-layer-parser.h"
36 #include "app-layer-htp.h"
37 
38 #include "detect-parse.h"
39 #include "detect-engine-sigorder.h"
40 
41 #include "detect-engine-siggroup.h"
42 #include "detect-engine-address.h"
43 #include "detect-engine-port.h"
45 #include "detect-engine-mpm.h"
46 #include "detect-engine-iponly.h"
47 #include "detect-engine-tag.h"
48 
49 #include "detect-engine-file.h"
50 
51 #include "detect-engine.h"
52 #include "detect-engine-state.h"
53 #include "detect-engine-payload.h"
54 #include "detect-byte-extract.h"
55 #include "detect-content.h"
56 #include "detect-uricontent.h"
57 #include "detect-tcphdr.h"
60 
61 #include "detect-engine-loader.h"
62 
64 #include "util-reference-config.h"
65 #include "util-threshold-config.h"
66 #include "util-error.h"
67 #include "util-hash.h"
68 #include "util-byte.h"
69 #include "util-debug.h"
70 #include "util-unittest.h"
71 #include "util-action.h"
72 #include "util-magic.h"
73 #include "util-signal.h"
74 #include "util-spm.h"
75 #include "util-device.h"
76 #include "util-var-name.h"
77 #include "util-profiling.h"
78 
79 #include "tm-threads.h"
80 #include "runmodes.h"
81 
82 #include "reputation.h"
83 
84 #define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000
85 
86 static DetectEngineThreadCtx *DetectEngineThreadCtxInitForReload(
87  ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt);
88 
89 static int DetectEngineCtxLoadConf(DetectEngineCtx *);
90 
91 static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER,
92  0, 99, NULL, NULL, TENANT_SELECTOR_UNKNOWN, NULL, NULL, 0};
93 
94 static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len);
95 static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len);
96 static void TenantIdFree(void *d);
97 static uint32_t DetectEngineTentantGetIdFromLivedev(const void *ctx, const Packet *p);
98 static uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet *p);
99 static uint32_t DetectEngineTentantGetIdFromPcap(const void *ctx, const Packet *p);
100 
101 static DetectEngineAppInspectionEngine *g_app_inspect_engines = NULL;
102 static DetectEnginePktInspectionEngine *g_pkt_inspect_engines = NULL;
103 
105 #ifdef UNITTESTS
106  { "TEST", DET_CTX_EVENT_TEST },
107 #endif
108  { "NO_MEMORY", FILE_DECODER_EVENT_NO_MEM },
109  { "INVALID_SWF_LENGTH", FILE_DECODER_EVENT_INVALID_SWF_LENGTH },
110  { "INVALID_SWF_VERSION", FILE_DECODER_EVENT_INVALID_SWF_VERSION },
111  { "Z_DATA_ERROR", FILE_DECODER_EVENT_Z_DATA_ERROR },
112  { "Z_STREAM_ERROR", FILE_DECODER_EVENT_Z_STREAM_ERROR },
113  { "Z_BUF_ERROR", FILE_DECODER_EVENT_Z_BUF_ERROR },
114  { "Z_UNKNOWN_ERROR", FILE_DECODER_EVENT_Z_UNKNOWN_ERROR },
115  { "LZMA_DECODER_ERROR", FILE_DECODER_EVENT_LZMA_DECODER_ERROR },
116  { "LZMA_MEMLIMIT_ERROR", FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR },
117  { "LZMA_OPTIONS_ERROR", FILE_DECODER_EVENT_LZMA_OPTIONS_ERROR },
118  { "LZMA_FORMAT_ERROR", FILE_DECODER_EVENT_LZMA_FORMAT_ERROR },
119  { "LZMA_DATA_ERROR", FILE_DECODER_EVENT_LZMA_DATA_ERROR },
120  { "LZMA_BUF_ERROR", FILE_DECODER_EVENT_LZMA_BUF_ERROR },
121  { "LZMA_UNKNOWN_ERROR", FILE_DECODER_EVENT_LZMA_UNKNOWN_ERROR },
122  { NULL, -1 },
123 };
124 
125 /** \brief register inspect engine at start up time
126  *
127  * \note errors are fatal */
128 void DetectPktInspectEngineRegister(const char *name,
131 {
133  const int sm_list = DetectBufferTypeGetByName(name);
134  if (sm_list == -1) {
136  "failed to register inspect engine %s", name);
137  }
138 
139  if ((sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) ||
140  (Callback == NULL))
141  {
142  SCLogError(SC_ERR_INVALID_ARGUMENTS, "Invalid arguments");
143  BUG_ON(1);
144  }
145 
146  DetectEnginePktInspectionEngine *new_engine = SCCalloc(1, sizeof(*new_engine));
147  if (unlikely(new_engine == NULL)) {
149  "failed to register inspect engine %s: %s", name, strerror(errno));
150  }
151  new_engine->sm_list = sm_list;
152  new_engine->v1.Callback = Callback;
153  new_engine->v1.GetData = GetPktData;
154 
155  if (g_pkt_inspect_engines == NULL) {
156  g_pkt_inspect_engines = new_engine;
157  } else {
158  DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
159  while (t->next != NULL) {
160  t = t->next;
161  }
162 
163  t->next = new_engine;
164  }
165 }
166 
167 /** \brief register inspect engine at start up time
168  *
169  * \note errors are fatal */
171  AppProto alproto, uint32_t dir,
172  int progress, InspectEngineFuncPtr Callback)
173 {
174  if (AppLayerParserIsEnabled(alproto)) {
175  if (!AppLayerParserSupportsTxDetectFlags(alproto)) {
177  "Inspect engine registered for app-layer protocol without "
178  "TX detect flag support: %s", AppProtoToString(alproto));
179  }
180  }
182  const int sm_list = DetectBufferTypeGetByName(name);
183  if (sm_list == -1) {
185  "failed to register inspect engine %s", name);
186  }
187 
188  if ((alproto >= ALPROTO_FAILED) ||
189  (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) ||
190  (sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) ||
191  (progress < 0 || progress >= SHRT_MAX) ||
192  (Callback == NULL))
193  {
194  SCLogError(SC_ERR_INVALID_ARGUMENTS, "Invalid arguments");
195  BUG_ON(1);
196  }
197 
198  int direction;
199  if (dir == SIG_FLAG_TOSERVER) {
200  direction = 0;
201  } else {
202  direction = 1;
203  }
204 
206  if (unlikely(new_engine == NULL)) {
207  exit(EXIT_FAILURE);
208  }
209  memset(new_engine, 0, sizeof(*new_engine));
210  new_engine->alproto = alproto;
211  new_engine->dir = direction;
212  new_engine->sm_list = sm_list;
213  new_engine->progress = progress;
214  new_engine->Callback = Callback;
215 
216  if (g_app_inspect_engines == NULL) {
217  g_app_inspect_engines = new_engine;
218  } else {
219  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
220  while (t->next != NULL) {
221  t = t->next;
222  }
223 
224  t->next = new_engine;
225  }
226 }
227 
228 /** \brief register inspect engine at start up time
229  *
230  * \note errors are fatal */
232  AppProto alproto, uint32_t dir, int progress,
233  InspectEngineFuncPtr2 Callback2,
235 {
237  const int sm_list = DetectBufferTypeGetByName(name);
238  if (sm_list == -1) {
240  "failed to register inspect engine %s", name);
241  }
242 
243  if ((alproto >= ALPROTO_FAILED) ||
244  (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) ||
245  (sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) ||
246  (progress < 0 || progress >= SHRT_MAX) ||
247  (Callback2 == NULL))
248  {
249  SCLogError(SC_ERR_INVALID_ARGUMENTS, "Invalid arguments");
250  BUG_ON(1);
251  } else if (Callback2 == DetectEngineInspectBufferGeneric && GetData == NULL) {
252  SCLogError(SC_ERR_INVALID_ARGUMENTS, "Invalid arguments: must register "
253  "GetData with DetectEngineInspectBufferGeneric");
254  BUG_ON(1);
255  }
256 
257  int direction;
258  if (dir == SIG_FLAG_TOSERVER) {
259  direction = 0;
260  } else {
261  direction = 1;
262  }
263 
265  if (unlikely(new_engine == NULL)) {
266  exit(EXIT_FAILURE);
267  }
268  memset(new_engine, 0, sizeof(*new_engine));
269  new_engine->alproto = alproto;
270  new_engine->dir = direction;
271  new_engine->sm_list = sm_list;
272  new_engine->progress = progress;
273  new_engine->v2.Callback = Callback2;
274  new_engine->v2.GetData = GetData;
275 
276  if (g_app_inspect_engines == NULL) {
277  g_app_inspect_engines = new_engine;
278  } else {
279  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
280  while (t->next != NULL) {
281  t = t->next;
282  }
283 
284  t->next = new_engine;
285  }
286 }
287 
288 /* copy an inspect engine with transforms to a new list id. */
289 static void DetectAppLayerInspectEngineCopy(
291  int sm_list, int new_list,
292  const DetectEngineTransforms *transforms)
293 {
294  const DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
295  while (t) {
296  if (t->sm_list == sm_list) {
298  if (unlikely(new_engine == NULL)) {
299  exit(EXIT_FAILURE);
300  }
301  new_engine->alproto = t->alproto;
302  new_engine->dir = t->dir;
303  new_engine->sm_list = new_list; /* use new list id */
304  new_engine->progress = t->progress;
305  new_engine->Callback = t->Callback;
306  new_engine->v2 = t->v2;
307  new_engine->v2.transforms = transforms; /* assign transforms */
308 
309  if (de_ctx->app_inspect_engines == NULL) {
310  de_ctx->app_inspect_engines = new_engine;
311  } else {
313  while (list->next != NULL) {
314  list = list->next;
315  }
316 
317  list->next = new_engine;
318  }
319  }
320  t = t->next;
321  }
322 }
323 
324 /* copy inspect engines from global registrations to de_ctx list */
325 static void DetectAppLayerInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
326 {
327  const DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
328  while (t) {
330  if (unlikely(new_engine == NULL)) {
331  exit(EXIT_FAILURE);
332  }
333  new_engine->alproto = t->alproto;
334  new_engine->dir = t->dir;
335  new_engine->sm_list = t->sm_list;
336  new_engine->progress = t->progress;
337  new_engine->Callback = t->Callback;
338  new_engine->v2 = t->v2;
339 
340  if (de_ctx->app_inspect_engines == NULL) {
341  de_ctx->app_inspect_engines = new_engine;
342  } else {
344  while (list->next != NULL) {
345  list = list->next;
346  }
347 
348  list->next = new_engine;
349  }
350 
351  t = t->next;
352  }
353 }
354 
355 /* copy an inspect engine with transforms to a new list id. */
356 static void DetectPktInspectEngineCopy(
358  int sm_list, int new_list,
359  const DetectEngineTransforms *transforms)
360 {
361  const DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
362  while (t) {
363  if (t->sm_list == sm_list) {
365  if (unlikely(new_engine == NULL)) {
366  exit(EXIT_FAILURE);
367  }
368  new_engine->sm_list = new_list; /* use new list id */
369  new_engine->v1 = t->v1;
370  new_engine->v1.transforms = transforms; /* assign transforms */
371 
372  if (de_ctx->pkt_inspect_engines == NULL) {
373  de_ctx->pkt_inspect_engines = new_engine;
374  } else {
376  while (list->next != NULL) {
377  list = list->next;
378  }
379 
380  list->next = new_engine;
381  }
382  }
383  t = t->next;
384  }
385 }
386 
387 /* copy inspect engines from global registrations to de_ctx list */
388 static void DetectPktInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
389 {
390  const DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
391  while (t) {
392  SCLogDebug("engine %p", t);
394  if (unlikely(new_engine == NULL)) {
395  exit(EXIT_FAILURE);
396  }
397  new_engine->sm_list = t->sm_list;
398  new_engine->v1 = t->v1;
399 
400  if (de_ctx->pkt_inspect_engines == NULL) {
401  de_ctx->pkt_inspect_engines = new_engine;
402  } else {
404  while (list->next != NULL) {
405  list = list->next;
406  }
407 
408  list->next = new_engine;
409  }
410 
411  t = t->next;
412  }
413 }
414 
415 /** \internal
416  * \brief append the stream inspection
417  *
418  * If stream inspection is MPM, then prepend it.
419  */
420 static void AppendStreamInspectEngine(Signature *s, SigMatchData *stream, int direction, uint32_t id)
421 {
422  bool prepend = false;
423 
425  if (unlikely(new_engine == NULL)) {
426  exit(EXIT_FAILURE);
427  }
429  SCLogDebug("stream is mpm");
430  prepend = true;
431  new_engine->mpm = true;
432  }
433  new_engine->alproto = ALPROTO_UNKNOWN; /* all */
434  new_engine->dir = direction;
435  new_engine->stream = true;
436  new_engine->sm_list = DETECT_SM_LIST_PMATCH;
437  new_engine->smd = stream;
438  new_engine->Callback = DetectEngineInspectStream;
439  new_engine->progress = 0;
440 
441  /* append */
442  if (s->app_inspect == NULL) {
443  s->app_inspect = new_engine;
444  new_engine->id = DE_STATE_FLAG_BASE; /* id is used as flag in stateful detect */
445  } else if (prepend) {
446  new_engine->next = s->app_inspect;
447  s->app_inspect = new_engine;
448  new_engine->id = id;
449 
450  } else {
452  while (a->next != NULL) {
453  a = a->next;
454  }
455 
456  a->next = new_engine;
457  new_engine->id = id;
458  }
459  SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
460 }
461 
462 /**
463  * \note for the file inspect engine, the id DE_STATE_ID_FILE_INSPECT
464  * is assigned.
465  */
467 {
468  const int nlists = s->init_data->smlists_array_size;
469  SigMatchData *ptrs[nlists];
470  memset(&ptrs, 0, (nlists * sizeof(SigMatchData *)));
471 
472  const int mpm_list = s->init_data->mpm_sm ?
474  -1;
475 
476  const int files_id = DetectBufferTypeGetByName("files");
477 
478  /* convert lists to SigMatchData arrays */
479  int i = 0;
480  for (i = DETECT_SM_LIST_DYNAMIC_START; i < nlists; i++) {
481  if (s->init_data->smlists[i] == NULL)
482  continue;
483 
484  ptrs[i] = SigMatchList2DataArray(s->init_data->smlists[i]);
485  SCLogDebug("ptrs[%d] is set", i);
486  }
487 
488  /* set up pkt inspect engines */
490  while (e != NULL) {
491  SCLogDebug("e %p sm_list %u nlists %u ptrs[] %p", e, e->sm_list, nlists, e->sm_list < nlists ? ptrs[e->sm_list] : NULL);
492  if (e->sm_list < nlists && ptrs[e->sm_list] != NULL) {
493  bool prepend = false;
494 
496  if (unlikely(new_engine == NULL)) {
497  exit(EXIT_FAILURE);
498  }
499  if (mpm_list == e->sm_list) {
501  prepend = true;
502  new_engine->mpm = true;
503  }
504 
505  new_engine->sm_list = e->sm_list;
506  new_engine->smd = ptrs[new_engine->sm_list];
507  new_engine->v1 = e->v1;
508  SCLogDebug("sm_list %d new_engine->v1 %p/%p/%p",
509  new_engine->sm_list, new_engine->v1.Callback,
510  new_engine->v1.GetData, new_engine->v1.transforms);
511 
512  if (s->pkt_inspect == NULL) {
513  s->pkt_inspect = new_engine;
514  } else if (prepend) {
515  new_engine->next = s->pkt_inspect;
516  s->pkt_inspect = new_engine;
517  } else {
519  while (a->next != NULL) {
520  a = a->next;
521  }
522  new_engine->next = a->next;
523  a->next = new_engine;
524  }
525  }
526  e = e->next;
527  }
528 
529  bool head_is_mpm = false;
530  uint32_t last_id = DE_STATE_FLAG_BASE;
532  while (t != NULL) {
533  bool prepend = false;
534 
535  if (t->sm_list >= nlists)
536  goto next;
537 
538  if (ptrs[t->sm_list] == NULL)
539  goto next;
540 
541  SCLogDebug("ptrs[%d] is set", t->sm_list);
542 
543  if (t->alproto == ALPROTO_UNKNOWN) {
544  /* special case, inspect engine applies to all protocols */
545  } else if (s->alproto != ALPROTO_UNKNOWN && s->alproto != t->alproto)
546  goto next;
547 
548  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
549  if (t->dir == 1)
550  goto next;
551  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
552  if (t->dir == 0)
553  goto next;
554  }
556  if (unlikely(new_engine == NULL)) {
557  exit(EXIT_FAILURE);
558  }
559  if (mpm_list == t->sm_list) {
561  prepend = true;
562  head_is_mpm = true;
563  new_engine->mpm = true;
564  }
565 
566  new_engine->alproto = t->alproto;
567  new_engine->dir = t->dir;
568  new_engine->sm_list = t->sm_list;
569  new_engine->smd = ptrs[new_engine->sm_list];
570  new_engine->Callback = t->Callback;
571  new_engine->progress = t->progress;
572  new_engine->v2 = t->v2;
573  SCLogDebug("sm_list %d new_engine->v2 %p/%p/%p",
574  new_engine->sm_list, new_engine->v2.Callback,
575  new_engine->v2.GetData, new_engine->v2.transforms);
576 
577  if (s->app_inspect == NULL) {
578  s->app_inspect = new_engine;
579  if (new_engine->sm_list == files_id) {
580  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
581  new_engine->id = DE_STATE_ID_FILE_INSPECT;
582  } else {
583  new_engine->id = DE_STATE_FLAG_BASE; /* id is used as flag in stateful detect */
584  }
585 
586  /* prepend engine if forced or if our engine has a lower progress. */
587  } else if (prepend || (!head_is_mpm && s->app_inspect->progress > new_engine->progress)) {
588  new_engine->next = s->app_inspect;
589  s->app_inspect = new_engine;
590  if (new_engine->sm_list == files_id) {
591  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
592  new_engine->id = DE_STATE_ID_FILE_INSPECT;
593  } else {
594  new_engine->id = ++last_id;
595  }
596 
597  } else {
599  while (a->next != NULL) {
600  if (a->next && a->next->progress > new_engine->progress) {
601  break;
602  }
603 
604  a = a->next;
605  }
606 
607  new_engine->next = a->next;
608  a->next = new_engine;
609  if (new_engine->sm_list == files_id) {
610  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
611  new_engine->id = DE_STATE_ID_FILE_INSPECT;
612  } else {
613  new_engine->id = ++last_id;
614  }
615  }
616 
617  SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
618 
620 next:
621  t = t->next;
622  }
623 
626  {
627  /* if engine is added multiple times, we pass it the same list */
629  BUG_ON(stream == NULL);
630  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
631  AppendStreamInspectEngine(s, stream, 0, last_id + 1);
632  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
633  AppendStreamInspectEngine(s, stream, 1, last_id + 1);
634  } else {
635  AppendStreamInspectEngine(s, stream, 0, last_id + 1);
636  AppendStreamInspectEngine(s, stream, 1, last_id + 1);
637  }
638 
640  SCLogDebug("set SIG_FLAG_FLUSH on %u", s->id);
641  s->flags |= SIG_FLAG_FLUSH;
642  }
643  }
644 
645 #ifdef DEBUG
647  while (iter) {
648  SCLogDebug("%u: engine %s id %u progress %d %s", s->id,
650  iter->progress,
651  iter->sm_list == mpm_list ? "MPM":"");
652  iter = iter->next;
653  }
654 #endif
655  return 0;
656 }
657 
658 /** \brief free app inspect engines for a signature
659  *
660  * For lists that are registered multiple times, like http_header and
661  * http_cookie, making the engines owner of the lists is complicated.
662  * Multiple engines in a sig may be pointing to the same list. To
663  * address this the 'free' code needs to be extra careful about not
664  * double freeing, so it takes an approach to first fill an array
665  * of the to-free pointers before freeing them.
666  */
668 {
669  int nlists = 0;
670 
672  while (ie) {
673  nlists = MAX(ie->sm_list + 1, nlists);
674  ie = ie->next;
675  }
677  while (e) {
678  nlists = MAX(e->sm_list + 1, nlists);
679  e = e->next;
680  }
681  if (nlists == 0) {
682  BUG_ON(s->pkt_inspect);
683  return;
684  }
685 
686  SigMatchData *ptrs[nlists];
687  memset(&ptrs, 0, (nlists * sizeof(SigMatchData *)));
688 
689  /* free engines and put smd in the array */
690  ie = s->app_inspect;
691  while (ie) {
693  BUG_ON(ptrs[ie->sm_list] != NULL && ptrs[ie->sm_list] != ie->smd);
694  ptrs[ie->sm_list] = ie->smd;
695  SCFree(ie);
696  ie = next;
697  }
698  e = s->pkt_inspect;
699  while (e) {
701  ptrs[e->sm_list] = e->smd;
702  SCFree(e);
703  e = next;
704  }
705 
706  /* free the smds */
707  for (int i = 0; i < nlists; i++)
708  {
709  if (ptrs[i] == NULL)
710  continue;
711 
712  SigMatchData *smd = ptrs[i];
713  while(1) {
714  if (sigmatch_table[smd->type].Free != NULL) {
715  sigmatch_table[smd->type].Free(smd->ctx);
716  }
717  if (smd->is_last)
718  break;
719  smd++;
720  }
721  SCFree(ptrs[i]);
722  }
723 }
724 
725 /* code for registering buffers */
726 
727 #include "util-hash-lookup3.h"
728 
729 static HashListTable *g_buffer_type_hash = NULL;
730 static int g_buffer_type_id = DETECT_SM_LIST_DYNAMIC_START;
731 static int g_buffer_type_reg_closed = 0;
732 
733 static DetectEngineTransforms no_transforms = { .transforms = { 0 }, .cnt = 0, };
734 
736 {
737  return g_buffer_type_id;
738 }
739 
740 static uint32_t DetectBufferTypeHashFunc(HashListTable *ht, void *data, uint16_t datalen)
741 {
742  const DetectBufferType *map = (DetectBufferType *)data;
743  uint32_t hash = 0;
744 
745  hash = hashlittle_safe(map->string, strlen(map->string), 0);
746  hash += hashlittle_safe((uint8_t *)&map->transforms, sizeof(map->transforms), 0);
747  hash %= ht->array_size;
748 
749  return hash;
750 }
751 
752 static char DetectBufferTypeCompareFunc(void *data1, uint16_t len1, void *data2,
753  uint16_t len2)
754 {
755  DetectBufferType *map1 = (DetectBufferType *)data1;
756  DetectBufferType *map2 = (DetectBufferType *)data2;
757 
758  int r = (strcmp(map1->string, map2->string) == 0);
759  r &= (memcmp((uint8_t *)&map1->transforms, (uint8_t *)&map2->transforms, sizeof(map2->transforms)) == 0);
760  return r;
761 }
762 
763 static void DetectBufferTypeFreeFunc(void *data)
764 {
765  DetectBufferType *map = (DetectBufferType *)data;
766  if (map != NULL) {
767  SCFree(map);
768  }
769 }
770 
771 static int DetectBufferTypeInit(void)
772 {
773  BUG_ON(g_buffer_type_hash);
774  g_buffer_type_hash = HashListTableInit(256,
775  DetectBufferTypeHashFunc,
776  DetectBufferTypeCompareFunc,
777  DetectBufferTypeFreeFunc);
778  if (g_buffer_type_hash == NULL)
779  return -1;
780 
781  return 0;
782 }
783 #if 0
784 static void DetectBufferTypeFree(void)
785 {
786  if (g_buffer_type_hash == NULL)
787  return;
788 
789  HashListTableFree(g_buffer_type_hash);
790  g_buffer_type_hash = NULL;
791  return;
792 }
793 #endif
794 static int DetectBufferTypeAdd(const char *string)
795 {
796  DetectBufferType *map = SCCalloc(1, sizeof(*map));
797  if (map == NULL)
798  return -1;
799 
800  map->string = string;
801  map->id = g_buffer_type_id++;
802 
803  BUG_ON(HashListTableAdd(g_buffer_type_hash, (void *)map, 0) != 0);
804  SCLogDebug("buffer %s registered with id %d", map->string, map->id);
805  return map->id;
806 }
807 
808 static DetectBufferType *DetectBufferTypeLookupByName(const char *string)
809 {
810  DetectBufferType map = { (char *)string, NULL, 0, 0, 0, 0, false, NULL, NULL, no_transforms };
811 
812  DetectBufferType *res = HashListTableLookup(g_buffer_type_hash, &map, 0);
813  return res;
814 }
815 
816 int DetectBufferTypeRegister(const char *name)
817 {
818  BUG_ON(g_buffer_type_reg_closed);
819  if (g_buffer_type_hash == NULL)
820  DetectBufferTypeInit();
821 
822  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
823  if (!exists) {
824  return DetectBufferTypeAdd(name);
825  } else {
826  return exists->id;
827  }
828 }
829 
830 void DetectBufferTypeSupportsPacket(const char *name)
831 {
832  BUG_ON(g_buffer_type_reg_closed);
834  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
835  BUG_ON(!exists);
836  exists->packet = TRUE;
837  SCLogDebug("%p %s -- %d supports packet inspection", exists, name, exists->id);
838 }
839 
840 void DetectBufferTypeSupportsMpm(const char *name)
841 {
842  BUG_ON(g_buffer_type_reg_closed);
844  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
845  BUG_ON(!exists);
846  exists->mpm = TRUE;
847  SCLogDebug("%p %s -- %d supports mpm", exists, name, exists->id);
848 }
849 
851 {
852  BUG_ON(g_buffer_type_reg_closed);
854  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
855  BUG_ON(!exists);
856  exists->supports_transforms = true;
857  SCLogDebug("%p %s -- %d supports transformations", exists, name, exists->id);
858 }
859 
860 int DetectBufferTypeGetByName(const char *name)
861 {
862  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
863  if (!exists) {
864  return -1;
865  }
866  return exists->id;
867 }
868 
869 const char *DetectBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
870 {
871  BUG_ON(id < 0 || (uint32_t)id >= de_ctx->buffer_type_map_elements);
872  BUG_ON(de_ctx->buffer_type_map == NULL);
873 
874  if (de_ctx->buffer_type_map[id] == NULL)
875  return NULL;
876 
877  return de_ctx->buffer_type_map[id]->string;
878 }
879 
880 static const DetectBufferType *DetectBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
881 {
882  BUG_ON(id < 0 || (uint32_t)id >= de_ctx->buffer_type_map_elements);
883  BUG_ON(de_ctx->buffer_type_map == NULL);
884 
885  return de_ctx->buffer_type_map[id];
886 }
887 
888 void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
889 {
890  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
891  if (!exists) {
892  return;
893  }
894  exists->description = desc;
895 }
896 
898 {
899  const DetectBufferType *exists = DetectBufferTypeGetById(de_ctx, id);
900  if (!exists) {
901  return NULL;
902  }
903  return exists->description;
904 }
905 
906 const char *DetectBufferTypeGetDescriptionByName(const char *name)
907 {
908  const DetectBufferType *exists = DetectBufferTypeLookupByName(name);
909  if (!exists) {
910  return NULL;
911  }
912  return exists->description;
913 }
914 
916 {
917  const DetectBufferType *map = DetectBufferTypeGetById(de_ctx, id);
918  if (map == NULL)
919  return FALSE;
920  SCLogDebug("map %p id %d packet? %d", map, id, map->packet);
921  return map->packet;
922 }
923 
925 {
926  const DetectBufferType *map = DetectBufferTypeGetById(de_ctx, id);
927  if (map == NULL)
928  return FALSE;
929  SCLogDebug("map %p id %d mpm? %d", map, id, map->mpm);
930  return map->mpm;
931 }
932 
934  void (*SetupCallback)(const DetectEngineCtx *, Signature *))
935 {
936  BUG_ON(g_buffer_type_reg_closed);
938  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
939  BUG_ON(!exists);
940  exists->SetupCallback = SetupCallback;
941 }
942 
944  const int id, Signature *s)
945 {
946  const DetectBufferType *map = DetectBufferTypeGetById(de_ctx, id);
947  if (map && map->SetupCallback) {
948  map->SetupCallback(de_ctx, s);
949  }
950 }
951 
953  bool (*ValidateCallback)(const Signature *, const char **sigerror))
954 {
955  BUG_ON(g_buffer_type_reg_closed);
957  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
958  BUG_ON(!exists);
959  exists->ValidateCallback = ValidateCallback;
960 }
961 
963  const int id, const Signature *s, const char **sigerror)
964 {
965  const DetectBufferType *map = DetectBufferTypeGetById(de_ctx, id);
966  if (map && map->ValidateCallback) {
967  return map->ValidateCallback(s, sigerror);
968  }
969  return TRUE;
970 }
971 
972 int DetectBufferSetActiveList(Signature *s, const int list)
973 {
974  BUG_ON(s->init_data == NULL);
975 
976  if (s->init_data->list && s->init_data->transform_cnt) {
977  return -1;
978  }
979  s->init_data->list = list;
980  s->init_data->list_set = true;
981 
982  return 0;
983 }
984 
986 {
987  BUG_ON(s->init_data == NULL);
988 
989  if (s->init_data->transform_cnt) {
990  if (s->init_data->list == DETECT_SM_LIST_NOTSET ||
992  SCLogError(SC_ERR_INVALID_SIGNATURE, "previous transforms not consumed "
993  "(list: %u, transform_cnt %u)", s->init_data->list,
995  SCReturnInt(-1);
996  }
997 
998  SCLogDebug("buffer %d has transform(s) registered: %d",
999  s->init_data->list, s->init_data->transforms[0]);
1002  if (new_list == -1) {
1003  SCReturnInt(-1);
1004  }
1005  SCLogDebug("new_list %d", new_list);
1006  s->init_data->list = new_list;
1007  s->init_data->list_set = false;
1008  // reset transforms now that we've set up the list
1009  s->init_data->transform_cnt = 0;
1010  }
1011 
1012  SCReturnInt(0);
1013 }
1014 
1016 {
1017  /* single buffers */
1018  for (uint32_t i = 0; i < det_ctx->inspect.to_clear_idx; i++)
1019  {
1020  const uint32_t idx = det_ctx->inspect.to_clear_queue[i];
1021  InspectionBuffer *buffer = &det_ctx->inspect.buffers[idx];
1022  buffer->inspect = NULL;
1023  }
1024  det_ctx->inspect.to_clear_idx = 0;
1025 
1026  /* multi buffers */
1027  for (uint32_t i = 0; i < det_ctx->multi_inspect.to_clear_idx; i++)
1028  {
1029  const uint32_t idx = det_ctx->multi_inspect.to_clear_queue[i];
1030  InspectionBufferMultipleForList *mbuffer = &det_ctx->multi_inspect.buffers[idx];
1031  for (uint32_t x = 0; x <= mbuffer->max; x++) {
1032  InspectionBuffer *buffer = &mbuffer->inspection_buffers[x];
1033  buffer->inspect = NULL;
1034  }
1035  mbuffer->init = 0;
1036  mbuffer->max = 0;
1037  }
1038  det_ctx->multi_inspect.to_clear_idx = 0;
1039 }
1040 
1042 {
1043  InspectionBuffer *buffer = &det_ctx->inspect.buffers[list_id];
1044  if (buffer->inspect == NULL) {
1045  det_ctx->inspect.to_clear_queue[det_ctx->inspect.to_clear_idx++] = list_id;
1046  }
1047  return buffer;
1048 }
1049 
1050 /** \brief for a InspectionBufferMultipleForList get a InspectionBuffer
1051  * \param fb the multiple buffer array
1052  * \param local_id the index to get a buffer
1053  * \param buffer the inspect buffer or NULL in case of error */
1055 {
1056  if (local_id >= fb->size) {
1057  uint32_t old_size = fb->size;
1058  uint32_t new_size = local_id + 1;
1059  uint32_t grow_by = new_size - old_size;
1060  SCLogDebug("size is %u, need %u, so growing by %u", old_size, new_size, grow_by);
1061 
1062  SCLogDebug("fb->inspection_buffers %p", fb->inspection_buffers);
1063  void *ptr = SCRealloc(fb->inspection_buffers, (local_id + 1) * sizeof(InspectionBuffer));
1064  if (ptr == NULL)
1065  return NULL;
1066 
1067  InspectionBuffer *to_zero = (InspectionBuffer *)ptr + old_size;
1068  SCLogDebug("ptr %p to_zero %p", ptr, to_zero);
1069  memset((uint8_t *)to_zero, 0, (grow_by * sizeof(InspectionBuffer)));
1070  fb->inspection_buffers = ptr;
1071  fb->size = new_size;
1072  }
1073 
1074  fb->max = MAX(fb->max, local_id);
1075  InspectionBuffer *buffer = &fb->inspection_buffers[local_id];
1076  SCLogDebug("using file_data buffer %p", buffer);
1077  return buffer;
1078 }
1079 
1081 {
1082  InspectionBufferMultipleForList *buffer = &det_ctx->multi_inspect.buffers[list_id];
1083  if (!buffer->init) {
1084  det_ctx->multi_inspect.to_clear_queue[det_ctx->multi_inspect.to_clear_idx++] = list_id;
1085  buffer->init = 1;
1086  }
1087  return buffer;
1088 }
1089 
1090 void InspectionBufferInit(InspectionBuffer *buffer, uint32_t initial_size)
1091 {
1092  memset(buffer, 0, sizeof(*buffer));
1093  buffer->buf = SCCalloc(initial_size, sizeof(uint8_t));
1094  if (buffer->buf != NULL) {
1095  buffer->size = initial_size;
1096  }
1097 }
1098 
1099 /** \brief setup the buffer with our initial data */
1100 void InspectionBufferSetup(InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
1101 {
1102  buffer->inspect = buffer->orig = data;
1103  buffer->inspect_len = buffer->orig_len = data_len;
1104  buffer->len = 0;
1105 }
1106 
1108 {
1109  if (buffer->buf != NULL) {
1110  SCFree(buffer->buf);
1111  }
1112  memset(buffer, 0, sizeof(*buffer));
1113 }
1114 
1115 /**
1116  * \brief make sure that the buffer has at least 'min_size' bytes
1117  * Expand the buffer if necessary
1118  */
1119 void InspectionBufferCheckAndExpand(InspectionBuffer *buffer, uint32_t min_size)
1120 {
1121  if (likely(buffer->size >= min_size))
1122  return;
1123 
1124  uint32_t new_size = (buffer->size == 0) ? 4096 : buffer->size;
1125  while (new_size < min_size) {
1126  new_size *= 2;
1127  }
1128 
1129  void *ptr = SCRealloc(buffer->buf, new_size);
1130  if (ptr != NULL) {
1131  buffer->buf = ptr;
1132  buffer->size = new_size;
1133  }
1134 }
1135 
1136 void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
1137 {
1138  InspectionBufferCheckAndExpand(buffer, buf_len);
1139 
1140  if (buffer->size) {
1141  uint32_t copy_size = MIN(buf_len, buffer->size);
1142  memcpy(buffer->buf, buf, copy_size);
1143  buffer->inspect = buffer->buf;
1144  buffer->inspect_len = copy_size;
1145  }
1146 }
1147 
1149  const DetectEngineTransforms *transforms)
1150 {
1151  if (transforms) {
1152  for (int i = 0; i < DETECT_TRANSFORMS_MAX; i++) {
1153  const int id = transforms->transforms[i];
1154  if (id == 0)
1155  break;
1156  BUG_ON(sigmatch_table[id].Transform == NULL);
1157  sigmatch_table[id].Transform(buffer);
1158  SCLogDebug("applied transform %s", sigmatch_table[id].name);
1159  }
1160  }
1161 }
1162 
1163 static void DetectBufferTypeSetupDetectEngine(DetectEngineCtx *de_ctx)
1164 {
1165  const int size = g_buffer_type_id;
1166  BUG_ON(!(size > 0));
1167 
1168  de_ctx->buffer_type_map = SCCalloc(size, sizeof(DetectBufferType *));
1171  SCLogDebug("de_ctx->buffer_type_map %p with %u members", de_ctx->buffer_type_map, size);
1172 
1173  SCLogDebug("DETECT_SM_LIST_DYNAMIC_START %u", DETECT_SM_LIST_DYNAMIC_START);
1174  HashListTableBucket *b = HashListTableGetListHead(g_buffer_type_hash);
1175  while (b) {
1177  de_ctx->buffer_type_map[map->id] = map;
1178  SCLogDebug("name %s id %d mpm %s packet %s -- %s. "
1179  "Callbacks: Setup %p Validate %p", map->string, map->id,
1180  map->mpm ? "true" : "false", map->packet ? "true" : "false",
1181  map->description, map->SetupCallback, map->ValidateCallback);
1182  b = HashListTableGetListNext(b);
1183  }
1184 
1186  DetectBufferTypeHashFunc,
1187  DetectBufferTypeCompareFunc,
1188  DetectBufferTypeFreeFunc);
1189  if (de_ctx->buffer_type_hash == NULL) {
1190  BUG_ON(1);
1191  }
1192  de_ctx->buffer_type_id = g_buffer_type_id;
1193 
1196  DetectAppLayerInspectEngineCopyListToDetectCtx(de_ctx);
1198  DetectPktInspectEngineCopyListToDetectCtx(de_ctx);
1199 }
1200 
1201 static void DetectBufferTypeFreeDetectEngine(DetectEngineCtx *de_ctx)
1202 {
1203  if (de_ctx) {
1204  if (de_ctx->buffer_type_map)
1206  if (de_ctx->buffer_type_hash)
1208 
1210  while (ilist) {
1212  SCFree(ilist);
1213  ilist = next;
1214  }
1216  while (mlist) {
1218  SCFree(mlist);
1219  mlist = next;
1220  }
1222  while (plist) {
1224  SCFree(plist);
1225  plist = next;
1226  }
1228  while (pmlist) {
1229  DetectBufferMpmRegistery *next = pmlist->next;
1230  SCFree(pmlist);
1231  pmlist = next;
1232  }
1234  }
1235 }
1236 
1238 {
1239  BUG_ON(g_buffer_type_hash == NULL);
1240 
1241  g_buffer_type_reg_closed = 1;
1242 }
1243 
1245  int *transforms, int transform_cnt)
1246 {
1247  const DetectBufferType *base_map = DetectBufferTypeGetById(de_ctx, id);
1248  if (!base_map) {
1249  return -1;
1250  }
1251  if (!base_map->supports_transforms) {
1252  SCLogError(SC_ERR_INVALID_SIGNATURE, "buffer '%s' does not support transformations",
1253  base_map->string);
1254  return -1;
1255  }
1256 
1257  SCLogDebug("base_map %s", base_map->string);
1258 
1260  memset(&t, 0, sizeof(t));
1261  for (int i = 0; i < transform_cnt; i++) {
1262  t.transforms[i] = transforms[i];
1263  }
1264  t.cnt = transform_cnt;
1265 
1266  DetectBufferType lookup_map = { (char *)base_map->string, NULL, 0, 0, 0, 0, false, NULL, NULL, t };
1268 
1269  SCLogDebug("res %p", res);
1270  if (res != NULL) {
1271  return res->id;
1272  }
1273 
1274  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1275  if (map == NULL)
1276  return -1;
1277 
1278  map->string = base_map->string;
1279  map->id = de_ctx->buffer_type_id++;
1280  map->parent_id = base_map->id;
1281  map->transforms = t;
1282  map->mpm = base_map->mpm;
1283  map->packet = base_map->packet;
1284  map->SetupCallback = base_map->SetupCallback;
1285  map->ValidateCallback = base_map->ValidateCallback;
1286  if (map->packet) {
1288  map->id, map->parent_id, &map->transforms);
1289  } else {
1291  map->id, map->parent_id, &map->transforms);
1292  }
1293 
1294  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash, (void *)map, 0) != 0);
1295  SCLogDebug("buffer %s registered with id %d, parent %d", map->string, map->id, map->parent_id);
1296 
1297  if (map->id >= 0 && (uint32_t)map->id >= de_ctx->buffer_type_map_elements) {
1298  void *ptr = SCRealloc(de_ctx->buffer_type_map, (map->id + 1) * sizeof(DetectBufferType *));
1299  BUG_ON(ptr == NULL);
1300  SCLogDebug("de_ctx->buffer_type_map resized to %u (was %u)", (map->id + 1), de_ctx->buffer_type_map_elements);
1301  de_ctx->buffer_type_map = ptr;
1302  de_ctx->buffer_type_map[map->id] = map;
1303  de_ctx->buffer_type_map_elements = map->id + 1;
1304 
1305  if (map->packet) {
1306  DetectPktInspectEngineCopy(de_ctx, map->parent_id, map->id,
1307  &map->transforms);
1308  } else {
1309  DetectAppLayerInspectEngineCopy(de_ctx, map->parent_id, map->id,
1310  &map->transforms);
1311  }
1312  }
1313  return map->id;
1314 }
1315 
1316 /* returns false if no match, true if match */
1317 static int DetectEngineInspectRulePacketMatches(
1318  DetectEngineThreadCtx *det_ctx,
1319  const DetectEnginePktInspectionEngine *engine,
1320  const Signature *s,
1321  Packet *p, uint8_t *_alert_flags)
1322 {
1323  SCEnter();
1324 
1325  /* run the packet match functions */
1327  const SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
1328 
1329  SCLogDebug("running match functions, sm %p", smd);
1330  while (1) {
1332  if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) <= 0) {
1333  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
1334  SCLogDebug("no match");
1335  return false;
1336  }
1337  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1338  if (smd->is_last) {
1339  SCLogDebug("match and is_last");
1340  break;
1341  }
1342  smd++;
1343  }
1344  return true;
1345 }
1346 
1347 static int DetectEngineInspectRulePayloadMatches(
1348  DetectEngineThreadCtx *det_ctx,
1349  const DetectEnginePktInspectionEngine *engine,
1350  const Signature *s, Packet *p, uint8_t *alert_flags)
1351 {
1352  SCEnter();
1353 
1354  DetectEngineCtx *de_ctx = det_ctx->de_ctx;
1355 
1357  /* if we have stream msgs, inspect against those first,
1358  * but not for a "dsize" signature */
1359  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1360  int pmatch = 0;
1361  if (p->flags & PKT_DETECT_HAS_STREAMDATA) {
1362  pmatch = DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, p->flow, p);
1363  if (pmatch) {
1365  /* Tell the engine that this reassembled stream can drop the
1366  * rest of the pkts with no further inspection */
1367  if (s->action & ACTION_DROP)
1368  *alert_flags |= PACKET_ALERT_FLAG_DROP_FLOW;
1369 
1370  *alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH;
1371  }
1372  }
1373  /* no match? then inspect packet payload */
1374  if (pmatch == 0) {
1375  SCLogDebug("no match in stream, fall back to packet payload");
1376 
1377  /* skip if we don't have to inspect the packet and segment was
1378  * added to stream */
1379  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET) && (p->flags & PKT_STREAM_ADD)) {
1380  return false;
1381  }
1382  if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, p->flow, p) != 1) {
1383  return false;
1384  }
1385  }
1386  } else {
1387  if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, p->flow, p) != 1) {
1388  return false;
1389  }
1390  }
1391  return true;
1392 }
1393 
1395  DetectEngineThreadCtx *det_ctx, const Signature *s,
1396  Flow *f, Packet *p,
1397  uint8_t *alert_flags)
1398 {
1399  SCEnter();
1400 
1401  for (DetectEnginePktInspectionEngine *e = s->pkt_inspect; e != NULL; e = e->next) {
1402  if (e->v1.Callback(det_ctx, e, s, p, alert_flags) == false) {
1403  SCLogDebug("sid %u: e %p Callback returned false", s->id, e);
1404  return false;
1405  }
1406  SCLogDebug("sid %u: e %p Callback returned true", s->id, e);
1407  }
1408 
1409  SCLogDebug("sid %u: returning true", s->id);
1410  return true;
1411 }
1412 
1413 /**
1414  * \param data pointer to SigMatchData. Allowed to be NULL.
1415  */
1416 static int DetectEnginePktInspectionAppend(Signature *s,
1418  SigMatchData *data)
1419 {
1420  DetectEnginePktInspectionEngine *e = SCCalloc(1, sizeof(*e));
1421  if (e == NULL)
1422  return -1;
1423 
1424  e->v1.Callback = Callback;
1425  e->smd = data;
1426 
1427  if (s->pkt_inspect == NULL) {
1428  s->pkt_inspect = e;
1429  } else {
1431  while (a->next != NULL) {
1432  a = a->next;
1433  }
1434  a->next = e;
1435  }
1436  return 0;
1437 }
1438 
1440 {
1441  /* only handle PMATCH here if we're not an app inspect rule */
1443  if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRulePayloadMatches,
1444  NULL) < 0)
1445  return -1;
1446  SCLogDebug("sid %u: DetectEngineInspectRulePayloadMatches appended", s->id);
1447  }
1448 
1449  if (s->sm_arrays[DETECT_SM_LIST_MATCH]) {
1450  if (DetectEnginePktInspectionAppend(s, DetectEngineInspectRulePacketMatches,
1451  NULL) < 0)
1452  return -1;
1453  SCLogDebug("sid %u: DetectEngineInspectRulePacketMatches appended", s->id);
1454  }
1455 
1456  return 0;
1457 }
1458 
1459 /* code to control the main thread to do a reload */
1460 
1462  IDLE, /**< ready to start a reload */
1463  RELOAD, /**< command main thread to do the reload */
1464 };
1465 
1466 
1467 typedef struct DetectEngineSyncer_ {
1471 
1472 static DetectEngineSyncer detect_sync = { SCMUTEX_INITIALIZER, IDLE };
1473 
1474 /* tell main to start reloading */
1476 {
1477  int r = 0;
1478  SCMutexLock(&detect_sync.m);
1479  if (detect_sync.state == IDLE) {
1480  detect_sync.state = RELOAD;
1481  } else {
1482  r = -1;
1483  }
1484  SCMutexUnlock(&detect_sync.m);
1485  return r;
1486 }
1487 
1488 /* main thread checks this to see if it should start */
1490 {
1491  int r = 0;
1492  SCMutexLock(&detect_sync.m);
1493  if (detect_sync.state == RELOAD) {
1494  r = 1;
1495  }
1496  SCMutexUnlock(&detect_sync.m);
1497  return r;
1498 }
1499 
1500 /* main thread sets done when it's done */
1502 {
1503  SCMutexLock(&detect_sync.m);
1504  detect_sync.state = IDLE;
1505  SCMutexUnlock(&detect_sync.m);
1506 }
1507 
1508 /* caller loops this until it returns 1 */
1510 {
1511  int r = 0;
1512  SCMutexLock(&detect_sync.m);
1513  if (detect_sync.state == IDLE) {
1514  r = 1;
1515  }
1516  SCMutexUnlock(&detect_sync.m);
1517  return r;
1518 }
1519 
1520 /** \brief Do the content inspection & validation for a signature
1521  *
1522  * \param de_ctx Detection engine context
1523  * \param det_ctx Detection engine thread context
1524  * \param s Signature to inspect
1525  * \param sm SigMatch to inspect
1526  * \param f Flow
1527  * \param flags app layer flags
1528  * \param state App layer state
1529  *
1530  * \retval 0 no match
1531  * \retval 1 match
1532  */
1534  const DetectEngineCtx *de_ctx,
1535  DetectEngineThreadCtx *det_ctx,
1536  const Signature *s, const SigMatchData *smd,
1537  Flow *f, const uint8_t flags,
1538  void *alstate, void *txv, uint64_t tx_id)
1539 {
1540  SCLogDebug("running match functions, sm %p", smd);
1541  if (smd != NULL) {
1542  while (1) {
1543  int match = 0;
1545  match = sigmatch_table[smd->type].
1546  AppLayerTxMatch(det_ctx, f, flags, alstate, txv, s, smd->ctx);
1547  KEYWORD_PROFILING_END(det_ctx, smd->type, (match == 1));
1548  if (match == 0)
1550  if (match == 2) {
1552  }
1553 
1554  if (smd->is_last)
1555  break;
1556  smd++;
1557  }
1558  }
1559 
1561 }
1562 
1563 
1564 /**
1565  * \brief Do the content inspection & validation for a signature
1566  *
1567  * \param de_ctx Detection engine context
1568  * \param det_ctx Detection engine thread context
1569  * \param s Signature to inspect
1570  * \param f Flow
1571  * \param flags app layer flags
1572  * \param state App layer state
1573  *
1574  * \retval 0 no match.
1575  * \retval 1 match.
1576  * \retval 2 Sig can't match.
1577  */
1580  const DetectEngineAppInspectionEngine *engine,
1581  const Signature *s,
1582  Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
1583 {
1584  const int list_id = engine->sm_list;
1585  SCLogDebug("running inspect on %d", list_id);
1586 
1587  const bool eof = (AppLayerParserGetStateProgress(f->proto, f->alproto, txv, flags) > engine->progress);
1588 
1589  SCLogDebug("list %d mpm? %s transforms %p",
1590  engine->sm_list, engine->mpm ? "true" : "false", engine->v2.transforms);
1591 
1592  /* if prefilter didn't already run, we need to consider transformations */
1593  const DetectEngineTransforms *transforms = NULL;
1594  if (!engine->mpm) {
1595  transforms = engine->v2.transforms;
1596  }
1597 
1598  const InspectionBuffer *buffer = engine->v2.GetData(det_ctx, transforms,
1599  f, flags, txv, list_id);
1600  if (unlikely(buffer == NULL)) {
1603  }
1604 
1605  const uint32_t data_len = buffer->inspect_len;
1606  const uint8_t *data = buffer->inspect;
1607  const uint64_t offset = buffer->inspect_offset;
1608 
1609  uint8_t ci_flags = eof ? DETECT_CI_FLAGS_END : 0;
1610  ci_flags |= (offset == 0 ? DETECT_CI_FLAGS_START : 0);
1611  ci_flags |= buffer->flags;
1612 
1613  det_ctx->discontinue_matching = 0;
1614  det_ctx->buffer_offset = 0;
1615  det_ctx->inspection_recursion_counter = 0;
1616 
1617  /* Inspect all the uricontents fetched on each
1618  * transaction at the app layer */
1619  int r = DetectEngineContentInspection(de_ctx, det_ctx,
1620  s, engine->smd,
1621  NULL, f,
1622  (uint8_t *)data, data_len, offset, ci_flags,
1624  if (r == 1) {
1626  } else {
1629  }
1630 }
1631 
1632 /**
1633  * \brief Do the content inspection & validation for a signature
1634  *
1635  * \param de_ctx Detection engine context
1636  * \param det_ctx Detection engine thread context
1637  * \param s Signature to inspect
1638  * \param p Packet
1639  *
1640  * \retval 0 no match.
1641  * \retval 1 match.
1642  */
1644  DetectEngineThreadCtx *det_ctx,
1645  const DetectEnginePktInspectionEngine *engine,
1646  const Signature *s, Packet *p, uint8_t *_alert_flags)
1647 {
1648  const int list_id = engine->sm_list;
1649  SCLogDebug("running inspect on %d", list_id);
1650 
1651  SCLogDebug("list %d transforms %p",
1652  engine->sm_list, engine->v1.transforms);
1653 
1654  /* if prefilter didn't already run, we need to consider transformations */
1655  const DetectEngineTransforms *transforms = NULL;
1656  if (!engine->mpm) {
1657  transforms = engine->v1.transforms;
1658  }
1659 
1660  const InspectionBuffer *buffer = engine->v1.GetData(det_ctx, transforms, p,
1661  list_id);
1662  if (unlikely(buffer == NULL)) {
1664  }
1665 
1666  const uint32_t data_len = buffer->inspect_len;
1667  const uint8_t *data = buffer->inspect;
1668  const uint64_t offset = 0;
1669 
1670  uint8_t ci_flags = DETECT_CI_FLAGS_START|DETECT_CI_FLAGS_END;
1671  ci_flags |= buffer->flags;
1672 
1673  det_ctx->discontinue_matching = 0;
1674  det_ctx->buffer_offset = 0;
1675  det_ctx->inspection_recursion_counter = 0;
1676 
1677  /* Inspect all the uricontents fetched on each
1678  * transaction at the app layer */
1679  int r = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx,
1680  s, engine->smd,
1681  p, p->flow,
1682  (uint8_t *)data, data_len, offset, ci_flags,
1684  if (r == 1) {
1686  } else {
1688  }
1689 }
1690 
1691 
1692 /* nudge capture loops to wake up */
1693 static void BreakCapture(void)
1694 {
1696  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
1697  if ((tv->tmm_flags & TM_FLAG_RECEIVE_TM) == 0) {
1698  continue;
1699  }
1700  /* find the correct slot */
1701  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
1702  if (suricata_ctl_flags != 0) {
1704  return;
1705  }
1706 
1707  TmModule *tm = TmModuleGetById(s->tm_id);
1708  if (!(tm->flags & TM_FLAG_RECEIVE_TM)) {
1709  continue;
1710  }
1711 
1712  /* signal capture method that we need a packet. */
1714  /* if the method supports it, BreakLoop. Otherwise we rely on
1715  * the capture method's recv timeout */
1716  if (tm->PktAcqLoop && tm->PktAcqBreakLoop) {
1717  tm->PktAcqBreakLoop(tv, SC_ATOMIC_GET(s->slot_data));
1718  }
1719  break;
1720  }
1721  }
1723 }
1724 
1725 /** \internal
1726  * \brief inject a pseudo packet into each detect thread that doesn't use the
1727  * new det_ctx yet
1728  */
1729 static void InjectPackets(ThreadVars **detect_tvs,
1730  DetectEngineThreadCtx **new_det_ctx,
1731  int no_of_detect_tvs)
1732 {
1733  /* inject a fake packet if the detect thread isn't using the new ctx yet,
1734  * this speeds up the process */
1735  for (int i = 0; i < no_of_detect_tvs; i++) {
1736  if (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
1737  if (detect_tvs[i]->inq != NULL) {
1738  Packet *p = PacketGetFromAlloc();
1739  if (p != NULL) {
1742  PacketQueue *q = detect_tvs[i]->inq->pq;
1743  SCMutexLock(&q->mutex_q);
1744  PacketEnqueue(q, p);
1745  SCCondSignal(&q->cond_q);
1746  SCMutexUnlock(&q->mutex_q);
1747  }
1748  }
1749  }
1750  }
1751 }
1752 
1753 /** \internal
1754  * \brief Update detect threads with new detect engine
1755  *
1756  * Atomically update each detect thread with a new thread context
1757  * that is associated to the new detection engine(s).
1758  *
1759  * If called in unix socket mode, it's possible that we don't have
1760  * detect threads yet.
1761  *
1762  * \retval -1 error
1763  * \retval 0 no detection threads
1764  * \retval 1 successful reload
1765  */
1766 static int DetectEngineReloadThreads(DetectEngineCtx *new_de_ctx)
1767 {
1768  SCEnter();
1769  uint32_t i = 0;
1770 
1771  /* count detect threads in use */
1772  uint32_t no_of_detect_tvs = TmThreadCountThreadsByTmmFlags(TM_FLAG_DETECT_TM);
1773  /* can be zero in unix socket mode */
1774  if (no_of_detect_tvs == 0) {
1775  return 0;
1776  }
1777 
1778  /* prepare swap structures */
1779  DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs];
1780  DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs];
1781  ThreadVars *detect_tvs[no_of_detect_tvs];
1782  memset(old_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
1783  memset(new_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
1784  memset(detect_tvs, 0x00, (no_of_detect_tvs * sizeof(ThreadVars *)));
1785 
1786  /* start the process of swapping detect threads ctxs */
1787 
1788  /* get reference to tv's and setup new_det_ctx array */
1790  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
1791  if ((tv->tmm_flags & TM_FLAG_DETECT_TM) == 0) {
1792  continue;
1793  }
1794  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
1795  TmModule *tm = TmModuleGetById(s->tm_id);
1796  if (!(tm->flags & TM_FLAG_DETECT_TM)) {
1797  continue;
1798  }
1799 
1800  if (suricata_ctl_flags != 0) {
1802  goto error;
1803  }
1804 
1805  old_det_ctx[i] = FlowWorkerGetDetectCtxPtr(SC_ATOMIC_GET(s->slot_data));
1806  detect_tvs[i] = tv;
1807 
1808  new_det_ctx[i] = DetectEngineThreadCtxInitForReload(tv, new_de_ctx, 1);
1809  if (new_det_ctx[i] == NULL) {
1810  SCLogError(SC_ERR_LIVE_RULE_SWAP, "Detect engine thread init "
1811  "failure in live rule swap. Let's get out of here");
1813  goto error;
1814  }
1815  SCLogDebug("live rule swap created new det_ctx - %p and de_ctx "
1816  "- %p\n", new_det_ctx[i], new_de_ctx);
1817  i++;
1818  break;
1819  }
1820  }
1821  BUG_ON(i != no_of_detect_tvs);
1822 
1823  /* atomically replace the det_ctx data */
1824  i = 0;
1825  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
1826  if ((tv->tmm_flags & TM_FLAG_DETECT_TM) == 0) {
1827  continue;
1828  }
1829  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
1830  TmModule *tm = TmModuleGetById(s->tm_id);
1831  if (!(tm->flags & TM_FLAG_DETECT_TM)) {
1832  continue;
1833  }
1834  SCLogDebug("swapping new det_ctx - %p with older one - %p",
1835  new_det_ctx[i], SC_ATOMIC_GET(s->slot_data));
1836  FlowWorkerReplaceDetectCtx(SC_ATOMIC_GET(s->slot_data), new_det_ctx[i++]);
1837  break;
1838  }
1839  }
1841 
1842  /* threads now all have new data, however they may not have started using
1843  * it and may still use the old data */
1844 
1845  SCLogDebug("Live rule swap has swapped %d old det_ctx's with new ones, "
1846  "along with the new de_ctx", no_of_detect_tvs);
1847 
1848  InjectPackets(detect_tvs, new_det_ctx, no_of_detect_tvs);
1849 
1850  for (i = 0; i < no_of_detect_tvs; i++) {
1851  int break_out = 0;
1852  usleep(1000);
1853  while (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
1854  if (suricata_ctl_flags != 0) {
1855  break_out = 1;
1856  break;
1857  }
1858 
1859  BreakCapture();
1860  usleep(1000);
1861  }
1862  if (break_out)
1863  break;
1864  SCLogDebug("new_det_ctx - %p used by detect engine", new_det_ctx[i]);
1865  }
1866 
1867  /* this is to make sure that if someone initiated shutdown during a live
1868  * rule swap, the live rule swap won't clean up the old det_ctx and
1869  * de_ctx, till all detect threads have stopped working and sitting
1870  * silently after setting RUNNING_DONE flag and while waiting for
1871  * THV_DEINIT flag */
1872  if (i != no_of_detect_tvs) { // not all threads we swapped
1873  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
1874  if ((tv->tmm_flags & TM_FLAG_DETECT_TM) == 0) {
1875  continue;
1876  }
1877 
1879  usleep(100);
1880  }
1881  }
1882  }
1883 
1884  /* free all the ctxs */
1885  for (i = 0; i < no_of_detect_tvs; i++) {
1886  SCLogDebug("Freeing old_det_ctx - %p used by detect",
1887  old_det_ctx[i]);
1888  DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]);
1889  }
1890 
1892 
1893  return 1;
1894 
1895  error:
1896  for (i = 0; i < no_of_detect_tvs; i++) {
1897  if (new_det_ctx[i] != NULL)
1898  DetectEngineThreadCtxDeinit(NULL, new_det_ctx[i]);
1899  }
1900  return -1;
1901 }
1902 
1903 static DetectEngineCtx *DetectEngineCtxInitReal(enum DetectEngineType type, const char *prefix)
1904 {
1906  if (unlikely(de_ctx == NULL))
1907  goto error;
1908 
1909  memset(de_ctx,0,sizeof(DetectEngineCtx));
1910  memset(&de_ctx->sig_stat, 0, sizeof(SigFileLoaderStat));
1911  TAILQ_INIT(&de_ctx->sig_stat.failed_sigs);
1912  de_ctx->sigerror = NULL;
1913  de_ctx->type = type;
1914 
1917  SCLogDebug("stub %u with version %u", type, de_ctx->version);
1918  return de_ctx;
1919  }
1920 
1921  if (prefix != NULL) {
1922  strlcpy(de_ctx->config_prefix, prefix, sizeof(de_ctx->config_prefix));
1923  }
1924 
1925  if (ConfGetBool("engine.init-failure-fatal", (int *)&(de_ctx->failure_fatal)) != 1) {
1926  SCLogDebug("ConfGetBool could not load the value.");
1927  }
1928 
1931  SCLogConfig("pattern matchers: MPM: %s, SPM: %s",
1934 
1936  if (de_ctx->spm_global_thread_ctx == NULL) {
1937  SCLogDebug("Unable to alloc SpmGlobalThreadCtx.");
1938  goto error;
1939  }
1940 
1941  if (DetectEngineCtxLoadConf(de_ctx) == -1) {
1942  goto error;
1943  }
1944 
1951  DetectBufferTypeSetupDetectEngine(de_ctx);
1952 
1953  /* init iprep... ignore errors for now */
1954  (void)SRepInit(de_ctx);
1955 
1958 
1959  if (ActionInitConfig() < 0) {
1960  goto error;
1961  }
1962 
1965  SCLogDebug("dectx with version %u", de_ctx->version);
1966  return de_ctx;
1967 error:
1968  if (de_ctx != NULL) {
1970  }
1971  return NULL;
1972 
1973 }
1974 
1976 {
1977  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_MT_STUB, NULL);
1978 }
1979 
1981 {
1982  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_DD_STUB, NULL);
1983 }
1984 
1986 {
1987  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_NORMAL, NULL);
1988 }
1989 
1991 {
1992  if (prefix == NULL || strlen(prefix) == 0)
1993  return DetectEngineCtxInit();
1994  else
1995  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_NORMAL, prefix);
1996 }
1997 
1998 static void DetectEngineCtxFreeThreadKeywordData(DetectEngineCtx *de_ctx)
1999 {
2001  while (item) {
2003  SCFree(item);
2004  item = next;
2005  }
2006  de_ctx->keyword_list = NULL;
2007 }
2008 
2009 static void DetectEngineCtxFreeFailedSigs(DetectEngineCtx *de_ctx)
2010 {
2011  SigString *item = NULL;
2012  SigString *sitem;
2013 
2014  TAILQ_FOREACH_SAFE(item, &de_ctx->sig_stat.failed_sigs, next, sitem) {
2015  SCFree(item->filename);
2016  SCFree(item->sig_str);
2017  if (item->sig_error) {
2018  SCFree(item->sig_error);
2019  }
2020  TAILQ_REMOVE(&de_ctx->sig_stat.failed_sigs, item, next);
2021  SCFree(item);
2022  }
2023 }
2024 
2025 /**
2026  * \brief Free a DetectEngineCtx::
2027  *
2028  * \param de_ctx DetectEngineCtx:: to be freed
2029  */
2031 {
2032 
2033  if (de_ctx == NULL)
2034  return;
2035 
2036 #ifdef PROFILING
2037  if (de_ctx->profile_ctx != NULL) {
2039  de_ctx->profile_ctx = NULL;
2040  }
2041  if (de_ctx->profile_keyword_ctx != NULL) {
2042  SCProfilingKeywordDestroyCtx(de_ctx);//->profile_keyword_ctx);
2043 // de_ctx->profile_keyword_ctx = NULL;
2044  }
2045  if (de_ctx->profile_sgh_ctx != NULL) {
2047  }
2049 #endif
2050 
2051  /* Normally the hashes are freed elsewhere, but
2052  * to be sure look at them again here.
2053  */
2060  if (de_ctx->sig_array)
2062 
2065 
2067 
2069 
2071 
2072  DetectEngineCtxFreeThreadKeywordData(de_ctx);
2074  DetectEngineCtxFreeFailedSigs(de_ctx);
2075 
2078 
2079  /* if we have a config prefix, remove the config from the tree */
2080  if (strlen(de_ctx->config_prefix) > 0) {
2081  /* remove config */
2083  if (node != NULL) {
2084  ConfNodeRemove(node); /* frees node */
2085  }
2086 #if 0
2087  ConfDump();
2088 #endif
2089  }
2090 
2093 
2094  DetectBufferTypeFreeDetectEngine(de_ctx);
2095  /* freed our var name hash */
2097 
2098  SCFree(de_ctx);
2099  //DetectAddressGroupPrintMemory();
2100  //DetectSigGroupPrintMemory();
2101  //DetectPortPrintMemory();
2102 }
2103 
2104 /** \brief Function that load DetectEngineCtx config for grouping sigs
2105  * used by the engine
2106  * \retval 0 if no config provided, 1 if config was provided
2107  * and loaded successfully
2108  */
2109 static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
2110 {
2111  uint8_t profile = ENGINE_PROFILE_MEDIUM;
2112  const char *max_uniq_toclient_groups_str = NULL;
2113  const char *max_uniq_toserver_groups_str = NULL;
2114  const char *sgh_mpm_context = NULL;
2115  const char *de_ctx_profile = NULL;
2116 
2117  (void)ConfGet("detect.profile", &de_ctx_profile);
2118  (void)ConfGet("detect.sgh-mpm-context", &sgh_mpm_context);
2119 
2120  ConfNode *de_ctx_custom = ConfGetNode("detect-engine");
2121  ConfNode *opt = NULL;
2122 
2123  if (de_ctx_custom != NULL) {
2124  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
2125  if (de_ctx_profile == NULL) {
2126  if (opt->val && strcmp(opt->val, "profile") == 0) {
2127  de_ctx_profile = opt->head.tqh_first->val;
2128  }
2129  }
2130 
2131  if (sgh_mpm_context == NULL) {
2132  if (opt->val && strcmp(opt->val, "sgh-mpm-context") == 0) {
2133  sgh_mpm_context = opt->head.tqh_first->val;
2134  }
2135  }
2136  }
2137  }
2138 
2139  if (de_ctx_profile != NULL) {
2140  if (strcmp(de_ctx_profile, "low") == 0 ||
2141  strcmp(de_ctx_profile, "lowest") == 0) { // legacy
2142  profile = ENGINE_PROFILE_LOW;
2143  } else if (strcmp(de_ctx_profile, "medium") == 0) {
2144  profile = ENGINE_PROFILE_MEDIUM;
2145  } else if (strcmp(de_ctx_profile, "high") == 0 ||
2146  strcmp(de_ctx_profile, "highest") == 0) { // legacy
2147  profile = ENGINE_PROFILE_HIGH;
2148  } else if (strcmp(de_ctx_profile, "custom") == 0) {
2149  profile = ENGINE_PROFILE_CUSTOM;
2150  } else {
2152  "invalid value for detect.profile: '%s'. "
2153  "Valid options: low, medium, high and custom.",
2154  de_ctx_profile);
2155  return -1;
2156  }
2157 
2158  SCLogDebug("Profile for detection engine groups is \"%s\"", de_ctx_profile);
2159  } else {
2160  SCLogDebug("Profile for detection engine groups not provided "
2161  "at suricata.yaml. Using default (\"medium\").");
2162  }
2163 
2164  /* detect-engine.sgh-mpm-context option parsing */
2165  if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context, "auto") == 0) {
2166  /* for now, since we still haven't implemented any intelligence into
2167  * understanding the patterns and distributing mpm_ctx across sgh */
2169 #ifdef BUILD_HYPERSCAN
2170  de_ctx->mpm_matcher == MPM_HS ||
2171 #endif
2174  } else {
2176  }
2177  } else {
2178  if (strcmp(sgh_mpm_context, "single") == 0) {
2180  } else if (strcmp(sgh_mpm_context, "full") == 0) {
2182  } else {
2183  SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "You have supplied an "
2184  "invalid conf value for detect-engine.sgh-mpm-context-"
2185  "%s", sgh_mpm_context);
2186  exit(EXIT_FAILURE);
2187  }
2188  }
2189 
2190  if (run_mode == RUNMODE_UNITTEST) {
2192  }
2193 
2194  /* parse profile custom-values */
2195  opt = NULL;
2196  switch (profile) {
2197  case ENGINE_PROFILE_LOW:
2200  break;
2201 
2202  case ENGINE_PROFILE_HIGH:
2205  break;
2206 
2207  case ENGINE_PROFILE_CUSTOM:
2208  (void)ConfGet("detect.custom-values.toclient-groups",
2209  &max_uniq_toclient_groups_str);
2210  (void)ConfGet("detect.custom-values.toserver-groups",
2211  &max_uniq_toserver_groups_str);
2212 
2213  if (de_ctx_custom != NULL) {
2214  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
2215  if (opt->val && strcmp(opt->val, "custom-values") == 0) {
2216  if (max_uniq_toclient_groups_str == NULL) {
2217  max_uniq_toclient_groups_str = (char *)ConfNodeLookupChildValue
2218  (opt->head.tqh_first, "toclient-sp-groups");
2219  }
2220  if (max_uniq_toclient_groups_str == NULL) {
2221  max_uniq_toclient_groups_str = (char *)ConfNodeLookupChildValue
2222  (opt->head.tqh_first, "toclient-groups");
2223  }
2224  if (max_uniq_toserver_groups_str == NULL) {
2225  max_uniq_toserver_groups_str = (char *)ConfNodeLookupChildValue
2226  (opt->head.tqh_first, "toserver-dp-groups");
2227  }
2228  if (max_uniq_toserver_groups_str == NULL) {
2229  max_uniq_toserver_groups_str = (char *)ConfNodeLookupChildValue
2230  (opt->head.tqh_first, "toserver-groups");
2231  }
2232  }
2233  }
2234  }
2235  if (max_uniq_toclient_groups_str != NULL) {
2237  strlen(max_uniq_toclient_groups_str),
2238  (const char *)max_uniq_toclient_groups_str) <= 0)
2239  {
2241 
2242  SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
2243  "toclient-groups failed, using %u",
2244  max_uniq_toclient_groups_str,
2246  }
2247  } else {
2249  }
2250  SCLogConfig("toclient-groups %u", de_ctx->max_uniq_toclient_groups);
2251 
2252  if (max_uniq_toserver_groups_str != NULL) {
2254  strlen(max_uniq_toserver_groups_str),
2255  (const char *)max_uniq_toserver_groups_str) <= 0)
2256  {
2258 
2259  SCLogWarning(SC_ERR_SIZE_PARSE, "parsing '%s' for "
2260  "toserver-groups failed, using %u",
2261  max_uniq_toserver_groups_str,
2263  }
2264  } else {
2266  }
2267  SCLogConfig("toserver-groups %u", de_ctx->max_uniq_toserver_groups);
2268  break;
2269 
2270  /* Default (or no config provided) is profile medium */
2271  case ENGINE_PROFILE_MEDIUM:
2273  default:
2276  break;
2277  }
2278 
2279  intmax_t value = 0;
2280  if (ConfGetInt("detect.inspection-recursion-limit", &value) == 1)
2281  {
2282  if (value >= 0 && value <= INT_MAX) {
2283  de_ctx->inspection_recursion_limit = (int)value;
2284  }
2285 
2286  /* fall back to old config parsing */
2287  } else {
2288  ConfNode *insp_recursion_limit_node = NULL;
2289  char *insp_recursion_limit = NULL;
2290 
2291  if (de_ctx_custom != NULL) {
2292  opt = NULL;
2293  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
2294  if (opt->val && strcmp(opt->val, "inspection-recursion-limit") != 0)
2295  continue;
2296 
2297  insp_recursion_limit_node = ConfNodeLookupChild(opt, opt->val);
2298  if (insp_recursion_limit_node == NULL) {
2299  SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Error retrieving conf "
2300  "entry for detect-engine:inspection-recursion-limit");
2301  break;
2302  }
2303  insp_recursion_limit = insp_recursion_limit_node->val;
2304  SCLogDebug("Found detect-engine.inspection-recursion-limit - %s:%s",
2305  insp_recursion_limit_node->name, insp_recursion_limit_node->val);
2306  break;
2307  }
2308 
2309  if (insp_recursion_limit != NULL) {
2310  de_ctx->inspection_recursion_limit = atoi(insp_recursion_limit);
2311  } else {
2314  }
2315  }
2316  }
2317 
2320 
2321  SCLogDebug("de_ctx->inspection_recursion_limit: %d",
2323 
2324  /* parse port grouping whitelisting settings */
2325 
2326  const char *ports = NULL;
2327  (void)ConfGet("detect.grouping.tcp-whitelist", &ports);
2328  if (ports) {
2329  SCLogConfig("grouping: tcp-whitelist %s", ports);
2330  } else {
2331  ports = "53, 80, 139, 443, 445, 1433, 3306, 3389, 6666, 6667, 8080";
2332  SCLogConfig("grouping: tcp-whitelist (default) %s", ports);
2333 
2334  }
2335  if (DetectPortParse(de_ctx, &de_ctx->tcp_whitelist, ports) != 0) {
2336  SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, "'%s' is not a valid value "
2337  "for detect.grouping.tcp-whitelist", ports);
2338  }
2340  for ( ; x != NULL; x = x->next) {
2341  if (x->port != x->port2) {
2342  SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, "'%s' is not a valid value "
2343  "for detect.grouping.tcp-whitelist: only single ports allowed", ports);
2345  de_ctx->tcp_whitelist = NULL;
2346  break;
2347  }
2348  }
2349 
2350  ports = NULL;
2351  (void)ConfGet("detect.grouping.udp-whitelist", &ports);
2352  if (ports) {
2353  SCLogConfig("grouping: udp-whitelist %s", ports);
2354  } else {
2355  ports = "53, 135, 5060";
2356  SCLogConfig("grouping: udp-whitelist (default) %s", ports);
2357 
2358  }
2359  if (DetectPortParse(de_ctx, &de_ctx->udp_whitelist, ports) != 0) {
2360  SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, "'%s' is not a valid value "
2361  "forr detect.grouping.udp-whitelist", ports);
2362  }
2363  for (x = de_ctx->udp_whitelist; x != NULL; x = x->next) {
2364  if (x->port != x->port2) {
2365  SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, "'%s' is not a valid value "
2366  "for detect.grouping.udp-whitelist: only single ports allowed", ports);
2368  de_ctx->udp_whitelist = NULL;
2369  break;
2370  }
2371  }
2372 
2374  const char *pf_setting = NULL;
2375  if (ConfGet("detect.prefilter.default", &pf_setting) == 1 && pf_setting) {
2376  if (strcasecmp(pf_setting, "mpm") == 0) {
2378  } else if (strcasecmp(pf_setting, "auto") == 0) {
2380  }
2381  }
2382  switch (de_ctx->prefilter_setting) {
2383  case DETECT_PREFILTER_MPM:
2384  SCLogConfig("prefilter engines: MPM");
2385  break;
2386  case DETECT_PREFILTER_AUTO:
2387  SCLogConfig("prefilter engines: MPM and keywords");
2388  break;
2389  }
2390 
2391  return 0;
2392 }
2393 
2394 /*
2395  * getting & (re)setting the internal sig i
2396  */
2397 
2398 //inline uint32_t DetectEngineGetMaxSigId(DetectEngineCtx *de_ctx)
2399 //{
2400 // return de_ctx->signum;
2401 //}
2402 
2404 {
2405  de_ctx->signum = 0;
2406 }
2407 
2408 static int DetectEngineThreadCtxInitGlobalKeywords(DetectEngineThreadCtx *det_ctx)
2409 {
2410  const DetectEngineMasterCtx *master = &g_master_de_ctx;
2411 
2412  if (master->keyword_id > 0) {
2413  // coverity[suspicious_sizeof : FALSE]
2414  det_ctx->global_keyword_ctxs_array = (void **)SCCalloc(master->keyword_id, sizeof(void *));
2415  if (det_ctx->global_keyword_ctxs_array == NULL) {
2416  SCLogError(SC_ERR_DETECT_PREPARE, "setting up thread local detect ctx");
2417  return TM_ECODE_FAILED;
2418  }
2419  det_ctx->global_keyword_ctxs_size = master->keyword_id;
2420 
2421  const DetectEngineThreadKeywordCtxItem *item = master->keyword_list;
2422  while (item) {
2423  det_ctx->global_keyword_ctxs_array[item->id] = item->InitFunc(item->data);
2424  if (det_ctx->global_keyword_ctxs_array[item->id] == NULL) {
2425  SCLogError(SC_ERR_DETECT_PREPARE, "setting up thread local detect ctx "
2426  "for keyword \"%s\" failed", item->name);
2427  return TM_ECODE_FAILED;
2428  }
2429  item = item->next;
2430  }
2431  }
2432  return TM_ECODE_OK;
2433 }
2434 
2435 static void DetectEngineThreadCtxDeinitGlobalKeywords(DetectEngineThreadCtx *det_ctx)
2436 {
2437  if (det_ctx->global_keyword_ctxs_array == NULL ||
2438  det_ctx->global_keyword_ctxs_size == 0) {
2439  return;
2440  }
2441 
2442  const DetectEngineMasterCtx *master = &g_master_de_ctx;
2443  if (master->keyword_id > 0) {
2444  const DetectEngineThreadKeywordCtxItem *item = master->keyword_list;
2445  while (item) {
2446  if (det_ctx->global_keyword_ctxs_array[item->id] != NULL)
2447  item->FreeFunc(det_ctx->global_keyword_ctxs_array[item->id]);
2448 
2449  item = item->next;
2450  }
2451  det_ctx->global_keyword_ctxs_size = 0;
2453  det_ctx->global_keyword_ctxs_array = NULL;
2454  }
2455 }
2456 
2457 static int DetectEngineThreadCtxInitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
2458 {
2459  if (de_ctx->keyword_id > 0) {
2460  // coverity[suspicious_sizeof : FALSE]
2461  det_ctx->keyword_ctxs_array = SCMalloc(de_ctx->keyword_id * sizeof(void *));
2462  if (det_ctx->keyword_ctxs_array == NULL) {
2463  SCLogError(SC_ERR_DETECT_PREPARE, "setting up thread local detect ctx");
2464  return TM_ECODE_FAILED;
2465  }
2466 
2467  memset(det_ctx->keyword_ctxs_array, 0x00, de_ctx->keyword_id * sizeof(void *));
2468 
2469  det_ctx->keyword_ctxs_size = de_ctx->keyword_id;
2470 
2472  while (item) {
2473  det_ctx->keyword_ctxs_array[item->id] = item->InitFunc(item->data);
2474  if (det_ctx->keyword_ctxs_array[item->id] == NULL) {
2475  SCLogError(SC_ERR_DETECT_PREPARE, "setting up thread local detect ctx "
2476  "for keyword \"%s\" failed", item->name);
2477  return TM_ECODE_FAILED;
2478  }
2479  item = item->next;
2480  }
2481  }
2482  return TM_ECODE_OK;
2483 }
2484 
2485 static void DetectEngineThreadCtxDeinitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
2486 {
2487  if (de_ctx->keyword_id > 0) {
2489  while (item) {
2490  if (det_ctx->keyword_ctxs_array[item->id] != NULL)
2491  item->FreeFunc(det_ctx->keyword_ctxs_array[item->id]);
2492 
2493  item = item->next;
2494  }
2495  det_ctx->keyword_ctxs_size = 0;
2496  SCFree(det_ctx->keyword_ctxs_array);
2497  det_ctx->keyword_ctxs_array = NULL;
2498  }
2499 }
2500 
2501 /** NOTE: master MUST be locked before calling this */
2502 static TmEcode DetectEngineThreadCtxInitForMT(ThreadVars *tv, DetectEngineThreadCtx *det_ctx)
2503 {
2504  DetectEngineMasterCtx *master = &g_master_de_ctx;
2505  DetectEngineTenantMapping *map_array = NULL;
2506  uint32_t map_array_size = 0;
2507  uint32_t map_cnt = 0;
2508  int max_tenant_id = 0;
2509  DetectEngineCtx *list = master->list;
2510  HashTable *mt_det_ctxs_hash = NULL;
2511 
2512  if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
2513  SCLogError(SC_ERR_MT_NO_SELECTOR, "no tenant selector set: "
2514  "set using multi-detect.selector");
2515  return TM_ECODE_FAILED;
2516  }
2517 
2518  uint32_t tcnt = 0;
2519  while (list) {
2520  if (list->tenant_id > max_tenant_id)
2521  max_tenant_id = list->tenant_id;
2522 
2523  list = list->next;
2524  tcnt++;
2525  }
2526 
2527  mt_det_ctxs_hash = HashTableInit(tcnt * 2, TenantIdHash, TenantIdCompare, TenantIdFree);
2528  if (mt_det_ctxs_hash == NULL) {
2529  goto error;
2530  }
2531 
2532  if (tcnt == 0) {
2533  SCLogInfo("no tenants left, or none registered yet");
2534  } else {
2535  max_tenant_id++;
2536 
2538  while (map) {
2539  map_cnt++;
2540  map = map->next;
2541  }
2542 
2543  if (map_cnt > 0) {
2544  map_array_size = map_cnt + 1;
2545 
2546  map_array = SCCalloc(map_array_size, sizeof(*map_array));
2547  if (map_array == NULL)
2548  goto error;
2549 
2550  /* fill the array */
2551  map_cnt = 0;
2552  map = master->tenant_mapping_list;
2553  while (map) {
2554  if (map_cnt >= map_array_size) {
2555  goto error;
2556  }
2557  map_array[map_cnt].traffic_id = map->traffic_id;
2558  map_array[map_cnt].tenant_id = map->tenant_id;
2559  map_cnt++;
2560  map = map->next;
2561  }
2562 
2563  }
2564 
2565  /* set up hash for tenant lookup */
2566  list = master->list;
2567  while (list) {
2568  SCLogDebug("tenant-id %u", list->tenant_id);
2569  if (list->tenant_id != 0) {
2570  DetectEngineThreadCtx *mt_det_ctx = DetectEngineThreadCtxInitForReload(tv, list, 0);
2571  if (mt_det_ctx == NULL)
2572  goto error;
2573  if (HashTableAdd(mt_det_ctxs_hash, mt_det_ctx, 0) != 0) {
2574  goto error;
2575  }
2576  }
2577  list = list->next;
2578  }
2579  }
2580 
2581  det_ctx->mt_det_ctxs_hash = mt_det_ctxs_hash;
2582  mt_det_ctxs_hash = NULL;
2583 
2584  det_ctx->mt_det_ctxs_cnt = max_tenant_id;
2585 
2586  det_ctx->tenant_array = map_array;
2587  det_ctx->tenant_array_size = map_array_size;
2588 
2589  switch (master->tenant_selector) {
2591  SCLogDebug("TENANT_SELECTOR_UNKNOWN");
2592  break;
2593  case TENANT_SELECTOR_VLAN:
2594  det_ctx->TenantGetId = DetectEngineTentantGetIdFromVlanId;
2595  SCLogDebug("TENANT_SELECTOR_VLAN");
2596  break;
2598  det_ctx->TenantGetId = DetectEngineTentantGetIdFromLivedev;
2599  SCLogDebug("TENANT_SELECTOR_LIVEDEV");
2600  break;
2602  det_ctx->TenantGetId = DetectEngineTentantGetIdFromPcap;
2603  SCLogDebug("TENANT_SELECTOR_DIRECT");
2604  break;
2605  }
2606 
2607  return TM_ECODE_OK;
2608 error:
2609  if (map_array != NULL)
2610  SCFree(map_array);
2611  if (mt_det_ctxs_hash != NULL)
2612  HashTableFree(mt_det_ctxs_hash);
2613 
2614  return TM_ECODE_FAILED;
2615 }
2616 
2617 /** \internal
2618  * \brief Helper for DetectThread setup functions
2619  */
2620 static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
2621 {
2625 
2626  PmqSetup(&det_ctx->pmq);
2627 
2629  if (det_ctx->spm_thread_ctx == NULL) {
2630  return TM_ECODE_FAILED;
2631  }
2632 
2633  /* sized to the max of our sgh settings. A max setting of 0 implies that all
2634  * sgh's have: sgh->non_pf_store_cnt == 0 */
2635  if (de_ctx->non_pf_store_cnt_max > 0) {
2637  BUG_ON(det_ctx->non_pf_id_array == NULL);
2638  }
2639 
2640  /* IP-ONLY */
2642 
2643  /* DeState */
2644  if (de_ctx->sig_array_len > 0) {
2645  det_ctx->match_array_len = de_ctx->sig_array_len;
2646  det_ctx->match_array = SCMalloc(det_ctx->match_array_len * sizeof(Signature *));
2647  if (det_ctx->match_array == NULL) {
2648  return TM_ECODE_FAILED;
2649  }
2650  memset(det_ctx->match_array, 0,
2651  det_ctx->match_array_len * sizeof(Signature *));
2652 
2654  }
2655 
2656  /* byte_extract storage */
2657  det_ctx->bj_values = SCMalloc(sizeof(*det_ctx->bj_values) *
2659  if (det_ctx->bj_values == NULL) {
2660  return TM_ECODE_FAILED;
2661  }
2662 
2663  /* Allocate space for base64 decoded data. */
2666  if (det_ctx->base64_decoded == NULL) {
2667  return TM_ECODE_FAILED;
2668  }
2670  det_ctx->base64_decoded_len = 0;
2671  }
2672 
2674  det_ctx->inspect.buffers = SCCalloc(det_ctx->inspect.buffers_size, sizeof(InspectionBuffer));
2675  if (det_ctx->inspect.buffers == NULL) {
2676  return TM_ECODE_FAILED;
2677  }
2678  det_ctx->inspect.to_clear_queue = SCCalloc(det_ctx->inspect.buffers_size, sizeof(uint32_t));
2679  if (det_ctx->inspect.to_clear_queue == NULL) {
2680  return TM_ECODE_FAILED;
2681  }
2682  det_ctx->inspect.to_clear_idx = 0;
2683 
2686  if (det_ctx->multi_inspect.buffers == NULL) {
2687  return TM_ECODE_FAILED;
2688  }
2689  det_ctx->multi_inspect.to_clear_queue = SCCalloc(det_ctx->multi_inspect.buffers_size, sizeof(uint32_t));
2690  if (det_ctx->multi_inspect.to_clear_queue == NULL) {
2691  return TM_ECODE_FAILED;
2692  }
2693  det_ctx->multi_inspect.to_clear_idx = 0;
2694 
2695 
2696  DetectEngineThreadCtxInitKeywords(de_ctx, det_ctx);
2697  DetectEngineThreadCtxInitGlobalKeywords(det_ctx);
2698 #ifdef PROFILING
2703 #endif
2704  SC_ATOMIC_INIT(det_ctx->so_far_used_by_detect);
2705 
2706  return TM_ECODE_OK;
2707 }
2708 
2709 /** \brief initialize thread specific detection engine context
2710  *
2711  * \note there is a special case when using delayed detect. In this case the
2712  * function is called twice per thread. The first time the rules are not
2713  * yet loaded. de_ctx->delayed_detect_initialized will be 0. The 2nd
2714  * time they will be loaded. de_ctx->delayed_detect_initialized will be 1.
2715  * This is needed to do the per thread counter registration before the
2716  * packet runtime starts. In delayed detect mode, the first call will
2717  * return a NULL ptr through the data ptr.
2718  *
2719  * \param tv ThreadVars for this thread
2720  * \param initdata pointer to de_ctx
2721  * \param data[out] pointer to store our thread detection ctx
2722  *
2723  * \retval TM_ECODE_OK if all went well
2724  * \retval TM_ECODE_FAILED on serious errors
2725  */
2726 TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
2727 {
2729  if (unlikely(det_ctx == NULL))
2730  return TM_ECODE_FAILED;
2731  memset(det_ctx, 0, sizeof(DetectEngineThreadCtx));
2732 
2733  det_ctx->tv = tv;
2734  det_ctx->de_ctx = DetectEngineGetCurrent();
2735  if (det_ctx->de_ctx == NULL) {
2736 #ifdef UNITTESTS
2737  if (RunmodeIsUnittests()) {
2738  det_ctx->de_ctx = (DetectEngineCtx *)initdata;
2739  } else {
2740  DetectEngineThreadCtxDeinit(tv, det_ctx);
2741  return TM_ECODE_FAILED;
2742  }
2743 #else
2744  DetectEngineThreadCtxDeinit(tv, det_ctx);
2745  return TM_ECODE_FAILED;
2746 #endif
2747  }
2748 
2749  if (det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
2750  det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_TENANT)
2751  {
2752  if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
2753  DetectEngineThreadCtxDeinit(tv, det_ctx);
2754  return TM_ECODE_FAILED;
2755  }
2756  }
2757 
2758  /** alert counter setup */
2759  det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", tv);
2760 #ifdef PROFILING
2761  det_ctx->counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
2762  det_ctx->counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
2763  det_ctx->counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
2764  det_ctx->counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
2765 #endif
2766 
2768  if (DetectEngineThreadCtxInitForMT(tv, det_ctx) != TM_ECODE_OK) {
2769  DetectEngineThreadCtxDeinit(tv, det_ctx);
2770  return TM_ECODE_FAILED;
2771  }
2772  }
2773 
2774  /* pass thread data back to caller */
2775  *data = (void *)det_ctx;
2776 
2777  return TM_ECODE_OK;
2778 }
2779 
2780 /**
2781  * \internal
2782  * \brief initialize a det_ctx for reload cases
2783  * \param new_de_ctx the new detection engine
2784  * \param mt flag to indicate if MT should be set up for this det_ctx
2785  * this should only be done for the 'root' det_ctx
2786  *
2787  * \retval det_ctx detection engine thread ctx or NULL in case of error
2788  */
2789 static DetectEngineThreadCtx *DetectEngineThreadCtxInitForReload(
2790  ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
2791 {
2793  if (unlikely(det_ctx == NULL))
2794  return NULL;
2795  memset(det_ctx, 0, sizeof(DetectEngineThreadCtx));
2796 
2797  det_ctx->tenant_id = new_de_ctx->tenant_id;
2798  det_ctx->tv = tv;
2799  det_ctx->de_ctx = DetectEngineReference(new_de_ctx);
2800  if (det_ctx->de_ctx == NULL) {
2801  SCFree(det_ctx);
2802  return NULL;
2803  }
2804 
2805  /* most of the init happens here */
2806  if (det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
2807  det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_TENANT)
2808  {
2809  if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
2810  DetectEngineDeReference(&det_ctx->de_ctx);
2811  SCFree(det_ctx);
2812  return NULL;
2813  }
2814  }
2815 
2816  /** alert counter setup */
2817  det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", tv);
2818 #ifdef PROFILING
2819  uint16_t counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
2820  uint16_t counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
2821  uint16_t counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
2822  uint16_t counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
2823  det_ctx->counter_mpm_list = counter_mpm_list;
2824  det_ctx->counter_nonmpm_list = counter_nonmpm_list;
2825  det_ctx->counter_fnonmpm_list = counter_fnonmpm_list;
2826  det_ctx->counter_match_list = counter_match_list;
2827 #endif
2828 
2829  if (mt && DetectEngineMultiTenantEnabled()) {
2830  if (DetectEngineThreadCtxInitForMT(tv, det_ctx) != TM_ECODE_OK) {
2831  DetectEngineDeReference(&det_ctx->de_ctx);
2832  SCFree(det_ctx);
2833  return NULL;
2834  }
2835  }
2836 
2837  return det_ctx;
2838 }
2839 
2840 static void DetectEngineThreadCtxFree(DetectEngineThreadCtx *det_ctx)
2841 {
2842 #if DEBUG
2843  SCLogDebug("PACKET PKT_STREAM_ADD: %"PRIu64, det_ctx->pkt_stream_add_cnt);
2844 
2845  SCLogDebug("PAYLOAD MPM %"PRIu64"/%"PRIu64, det_ctx->payload_mpm_cnt, det_ctx->payload_mpm_size);
2846  SCLogDebug("STREAM MPM %"PRIu64"/%"PRIu64, det_ctx->stream_mpm_cnt, det_ctx->stream_mpm_size);
2847 
2848  SCLogDebug("PAYLOAD SIG %"PRIu64"/%"PRIu64, det_ctx->payload_persig_cnt, det_ctx->payload_persig_size);
2849  SCLogDebug("STREAM SIG %"PRIu64"/%"PRIu64, det_ctx->stream_persig_cnt, det_ctx->stream_persig_size);
2850 #endif
2851 
2852  if (det_ctx->tenant_array != NULL) {
2853  SCFree(det_ctx->tenant_array);
2854  det_ctx->tenant_array = NULL;
2855  }
2856 
2857 #ifdef PROFILING
2861  SCProfilingSghThreadCleanup(det_ctx);
2862 #endif
2863 
2865 
2866  /** \todo get rid of this static */
2867  if (det_ctx->de_ctx != NULL) {
2868  PatternMatchThreadDestroy(&det_ctx->mtc, det_ctx->de_ctx->mpm_matcher);
2869  PatternMatchThreadDestroy(&det_ctx->mtcs, det_ctx->de_ctx->mpm_matcher);
2870  PatternMatchThreadDestroy(&det_ctx->mtcu, det_ctx->de_ctx->mpm_matcher);
2871  }
2872 
2873  PmqFree(&det_ctx->pmq);
2874 
2875  if (det_ctx->spm_thread_ctx != NULL) {
2877  }
2878 
2879  if (det_ctx->non_pf_id_array != NULL)
2880  SCFree(det_ctx->non_pf_id_array);
2881 
2882  if (det_ctx->match_array != NULL)
2883  SCFree(det_ctx->match_array);
2884 
2886 
2887  if (det_ctx->bj_values != NULL)
2888  SCFree(det_ctx->bj_values);
2889 
2890  /* Decoded base64 data. */
2891  if (det_ctx->base64_decoded != NULL) {
2892  SCFree(det_ctx->base64_decoded);
2893  }
2894 
2895  if (det_ctx->inspect.buffers) {
2896  for (uint32_t i = 0; i < det_ctx->inspect.buffers_size; i++) {
2897  InspectionBufferFree(&det_ctx->inspect.buffers[i]);
2898  }
2899  SCFree(det_ctx->inspect.buffers);
2900  }
2901  if (det_ctx->inspect.to_clear_queue) {
2902  SCFree(det_ctx->inspect.to_clear_queue);
2903  }
2904  if (det_ctx->multi_inspect.buffers) {
2905  for (uint32_t i = 0; i < det_ctx->multi_inspect.buffers_size; i++) {
2907  for (uint32_t x = 0; x < fb->size; x++) {
2909  }
2911  }
2912  SCFree(det_ctx->multi_inspect.buffers);
2913  }
2914  if (det_ctx->multi_inspect.to_clear_queue) {
2916  }
2917 
2918  DetectEngineThreadCtxDeinitGlobalKeywords(det_ctx);
2919  if (det_ctx->de_ctx != NULL) {
2920  DetectEngineThreadCtxDeinitKeywords(det_ctx->de_ctx, det_ctx);
2921 #ifdef UNITTESTS
2922  if (!RunmodeIsUnittests() || det_ctx->de_ctx->ref_cnt > 0)
2923  DetectEngineDeReference(&det_ctx->de_ctx);
2924 #else
2925  DetectEngineDeReference(&det_ctx->de_ctx);
2926 #endif
2927  }
2928 
2930 
2931  SCFree(det_ctx);
2932 }
2933 
2935 {
2936  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
2937 
2938  if (det_ctx == NULL) {
2939  SCLogWarning(SC_ERR_INVALID_ARGUMENTS, "argument \"data\" NULL");
2940  return TM_ECODE_OK;
2941  }
2942 
2943  if (det_ctx->mt_det_ctxs_hash != NULL) {
2944  HashTableFree(det_ctx->mt_det_ctxs_hash);
2945  det_ctx->mt_det_ctxs_hash = NULL;
2946  }
2947  DetectEngineThreadCtxFree(det_ctx);
2948 
2949  return TM_ECODE_OK;
2950 }
2951 
2953 {
2954  /* XXX */
2955  PatternMatchThreadPrint(&det_ctx->mtc, det_ctx->de_ctx->mpm_matcher);
2956  PatternMatchThreadPrint(&det_ctx->mtcu, det_ctx->de_ctx->mpm_matcher);
2957 }
2958 
2959 /** \brief Register Thread keyword context Funcs
2960  *
2961  * \param de_ctx detection engine to register in
2962  * \param name keyword name for error printing
2963  * \param InitFunc function ptr
2964  * \param data keyword init data to pass to Func. Can be NULL.
2965  * \param FreeFunc function ptr
2966  * \param mode 0 normal (ctx per keyword instance) 1 shared (one ctx per det_ct)
2967  *
2968  * \retval id for retrieval of ctx at runtime
2969  * \retval -1 on error
2970  *
2971  * \note make sure "data" remains valid and it free'd elsewhere. It's
2972  * recommended to store it in the keywords global ctx so that
2973  * it's freed when the de_ctx is freed.
2974  */
2975 int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *), int mode)
2976 {
2977  BUG_ON(de_ctx == NULL || InitFunc == NULL || FreeFunc == NULL);
2978 
2979  if (mode) {
2981  while (item != NULL) {
2982  if (strcmp(name, item->name) == 0) {
2983  return item->id;
2984  }
2985 
2986  item = item->next;
2987  }
2988  }
2989 
2991  if (unlikely(item == NULL))
2992  return -1;
2993  memset(item, 0x00, sizeof(DetectEngineThreadKeywordCtxItem));
2994 
2995  item->InitFunc = InitFunc;
2996  item->FreeFunc = FreeFunc;
2997  item->data = data;
2998  item->name = name;
2999 
3000  item->next = de_ctx->keyword_list;
3001  de_ctx->keyword_list = item;
3002  item->id = de_ctx->keyword_id++;
3003 
3004  return item->id;
3005 }
3006 
3007 /** \brief Retrieve thread local keyword ctx by id
3008  *
3009  * \param det_ctx detection engine thread ctx to retrieve the ctx from
3010  * \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
3011  * keyword init.
3012  *
3013  * \retval ctx or NULL on error
3014  */
3016 {
3017  if (id < 0 || id > det_ctx->keyword_ctxs_size || det_ctx->keyword_ctxs_array == NULL)
3018  return NULL;
3019 
3020  return det_ctx->keyword_ctxs_array[id];
3021 }
3022 
3023 
3024 /** \brief Register Thread keyword context Funcs (Global)
3025  *
3026  * IDs stay static over reloads and between tenants
3027  *
3028  * \param name keyword name for error printing
3029  * \param InitFunc function ptr
3030  * \param FreeFunc function ptr
3031  *
3032  * \retval id for retrieval of ctx at runtime
3033  * \retval -1 on error
3034  */
3036  void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *))
3037 {
3038  int id;
3039  BUG_ON(InitFunc == NULL || FreeFunc == NULL);
3040 
3041  DetectEngineMasterCtx *master = &g_master_de_ctx;
3042 
3043  /* if already registered, return existing id */
3045  while (item != NULL) {
3046  if (strcmp(name, item->name) == 0) {
3047  id = item->id;
3048  return id;
3049  }
3050 
3051  item = item->next;
3052  }
3053 
3054  item = SCCalloc(1, sizeof(*item));
3055  if (unlikely(item == NULL)) {
3056  return -1;
3057  }
3058  item->InitFunc = InitFunc;
3059  item->FreeFunc = FreeFunc;
3060  item->name = name;
3061  item->data = data;
3062 
3063  item->next = master->keyword_list;
3064  master->keyword_list = item;
3065  item->id = master->keyword_id++;
3066 
3067  id = item->id;
3068  return id;
3069 }
3070 
3071 /** \brief Retrieve thread local keyword ctx by id
3072  *
3073  * \param det_ctx detection engine thread ctx to retrieve the ctx from
3074  * \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
3075  * keyword init.
3076  *
3077  * \retval ctx or NULL on error
3078  */
3080 {
3081  if (id < 0 || id > det_ctx->global_keyword_ctxs_size ||
3082  det_ctx->global_keyword_ctxs_array == NULL) {
3083  return NULL;
3084  }
3085 
3086  return det_ctx->global_keyword_ctxs_array[id];
3087 }
3088 
3089 /** \brief Check if detection is enabled
3090  * \retval bool true or false */
3092 {
3093  DetectEngineMasterCtx *master = &g_master_de_ctx;
3094  SCMutexLock(&master->lock);
3095 
3096  if (master->list == NULL) {
3097  SCMutexUnlock(&master->lock);
3098  return 0;
3099  }
3100 
3101  SCMutexUnlock(&master->lock);
3102  return 1;
3103 }
3104 
3106 {
3107  uint32_t version;
3108  DetectEngineMasterCtx *master = &g_master_de_ctx;
3109  SCMutexLock(&master->lock);
3110  version = master->version;
3111  SCMutexUnlock(&master->lock);
3112  return version;
3113 }
3114 
3116 {
3117  DetectEngineMasterCtx *master = &g_master_de_ctx;
3118  SCMutexLock(&master->lock);
3119  master->version++;
3120  SCLogDebug("master version now %u", master->version);
3121  SCMutexUnlock(&master->lock);
3122 }
3123 
3125 {
3126  DetectEngineMasterCtx *master = &g_master_de_ctx;
3127  SCMutexLock(&master->lock);
3128 
3129  DetectEngineCtx *de_ctx = master->list;
3130  while (de_ctx) {
3134  {
3135  de_ctx->ref_cnt++;
3136  SCLogDebug("de_ctx %p ref_cnt %u", de_ctx, de_ctx->ref_cnt);
3137  SCMutexUnlock(&master->lock);
3138  return de_ctx;
3139  }
3140  de_ctx = de_ctx->next;
3141  }
3142 
3143  SCMutexUnlock(&master->lock);
3144  return NULL;
3145 }
3146 
3148 {
3149  if (de_ctx == NULL)
3150  return NULL;
3151  de_ctx->ref_cnt++;
3152  return de_ctx;
3153 }
3154 
3155 /** TODO locking? Not needed if this is a one time setting at startup */
3157 {
3158  DetectEngineMasterCtx *master = &g_master_de_ctx;
3159  return (master->multi_tenant_enabled);
3160 }
3161 
3162 /** \internal
3163  * \brief load a tenant from a yaml file
3164  *
3165  * \param tenant_id the tenant id by which the config is known
3166  * \param filename full path of a yaml file
3167  * \param loader_id id of loader thread or -1
3168  *
3169  * \retval 0 ok
3170  * \retval -1 failed
3171  */
3172 static int DetectEngineMultiTenantLoadTenant(uint32_t tenant_id, const char *filename, int loader_id)
3173 {
3174  DetectEngineCtx *de_ctx = NULL;
3175  char prefix[64];
3176 
3177  snprintf(prefix, sizeof(prefix), "multi-detect.%d", tenant_id);
3178 
3179 #ifdef OS_WIN32
3180  struct _stat st;
3181  if(_stat(filename, &st) != 0) {
3182 #else
3183  struct stat st;
3184  if(stat(filename, &st) != 0) {
3185 #endif /* OS_WIN32 */
3186  SCLogError(SC_ERR_FOPEN, "failed to stat file %s", filename);
3187  goto error;
3188  }
3189 
3190  de_ctx = DetectEngineGetByTenantId(tenant_id);
3191  if (de_ctx != NULL) {
3192  SCLogError(SC_ERR_MT_DUPLICATE_TENANT, "tenant %u already registered",
3193  tenant_id);
3195  goto error;
3196  }
3197 
3198  ConfNode *node = ConfGetNode(prefix);
3199  if (node == NULL) {
3200  SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to properly setup yaml %s", filename);
3201  goto error;
3202  }
3203 
3205  if (de_ctx == NULL) {
3206  SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
3207  "context failed.");
3208  goto error;
3209  }
3210  SCLogDebug("de_ctx %p with prefix %s", de_ctx, de_ctx->config_prefix);
3211 
3213  de_ctx->tenant_id = tenant_id;
3214  de_ctx->loader_id = loader_id;
3215 
3216  if (SigLoadSignatures(de_ctx, NULL, 0) < 0) {
3217  SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
3218  goto error;
3219  }
3220 
3222 
3223  return 0;
3224 
3225 error:
3226  if (de_ctx != NULL) {
3228  }
3229  return -1;
3230 }
3231 
3232 static int DetectEngineMultiTenantReloadTenant(uint32_t tenant_id, const char *filename, int reload_cnt)
3233 {
3234  DetectEngineCtx *old_de_ctx = DetectEngineGetByTenantId(tenant_id);
3235  if (old_de_ctx == NULL) {
3236  SCLogError(SC_ERR_INITIALIZATION, "tenant detect engine not found");
3237  return -1;
3238  }
3239 
3240  char prefix[64];
3241  snprintf(prefix, sizeof(prefix), "multi-detect.%d.reload.%d", tenant_id, reload_cnt);
3242  reload_cnt++;
3243  SCLogDebug("prefix %s", prefix);
3244 
3245  if (ConfYamlLoadFileWithPrefix(filename, prefix) != 0) {
3246  SCLogError(SC_ERR_INITIALIZATION,"failed to load yaml");
3247  goto error;
3248  }
3249 
3250  ConfNode *node = ConfGetNode(prefix);
3251  if (node == NULL) {
3252  SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to properly setup yaml %s", filename);
3253  goto error;
3254  }
3255 
3256  DetectEngineCtx *new_de_ctx = DetectEngineCtxInitWithPrefix(prefix);
3257  if (new_de_ctx == NULL) {
3258  SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
3259  "context failed.");
3260  goto error;
3261  }
3262  SCLogDebug("de_ctx %p with prefix %s", new_de_ctx, new_de_ctx->config_prefix);
3263 
3264  new_de_ctx->type = DETECT_ENGINE_TYPE_TENANT;
3265  new_de_ctx->tenant_id = tenant_id;
3266  new_de_ctx->loader_id = old_de_ctx->loader_id;
3267 
3268  if (SigLoadSignatures(new_de_ctx, NULL, 0) < 0) {
3269  SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
3270  goto error;
3271  }
3272 
3273  DetectEngineAddToMaster(new_de_ctx);
3274 
3275  /* move to free list */
3276  DetectEngineMoveToFreeList(old_de_ctx);
3277  DetectEngineDeReference(&old_de_ctx);
3278  return 0;
3279 
3280 error:
3281  DetectEngineDeReference(&old_de_ctx);
3282  return -1;
3283 }
3284 
3285 
3286 typedef struct TenantLoaderCtx_ {
3287  uint32_t tenant_id;
3288  int reload_cnt; /**< used by reload */
3289  const char *yaml;
3290 } TenantLoaderCtx;
3291 
3292 static int DetectLoaderFuncLoadTenant(void *vctx, int loader_id)
3293 {
3294  TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx;
3295 
3296  SCLogDebug("loader %d", loader_id);
3297  if (DetectEngineMultiTenantLoadTenant(ctx->tenant_id, ctx->yaml, loader_id) != 0) {
3298  return -1;
3299  }
3300  return 0;
3301 }
3302 
3303 static int DetectLoaderSetupLoadTenant(uint32_t tenant_id, const char *yaml)
3304 {
3305  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
3306  if (t == NULL)
3307  return -ENOMEM;
3308 
3309  t->tenant_id = tenant_id;
3310  t->yaml = yaml;
3311 
3312  return DetectLoaderQueueTask(-1, DetectLoaderFuncLoadTenant, t);
3313 }
3314 
3315 static int DetectLoaderFuncReloadTenant(void *vctx, int loader_id)
3316 {
3317  TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx;
3318 
3319  SCLogDebug("loader_id %d", loader_id);
3320 
3321  if (DetectEngineMultiTenantReloadTenant(ctx->tenant_id, ctx->yaml, ctx->reload_cnt) != 0) {
3322  return -1;
3323  }
3324  return 0;
3325 }
3326 
3327 static int DetectLoaderSetupReloadTenant(uint32_t tenant_id, const char *yaml, int reload_cnt)
3328 {
3329  DetectEngineCtx *old_de_ctx = DetectEngineGetByTenantId(tenant_id);
3330  if (old_de_ctx == NULL)
3331  return -ENOENT;
3332  int loader_id = old_de_ctx->loader_id;
3333  DetectEngineDeReference(&old_de_ctx);
3334 
3335  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
3336  if (t == NULL)
3337  return -ENOMEM;
3338 
3339  t->tenant_id = tenant_id;
3340  t->yaml = yaml;
3341  t->reload_cnt = reload_cnt;
3342 
3343  SCLogDebug("loader_id %d", loader_id);
3344 
3345  return DetectLoaderQueueTask(loader_id, DetectLoaderFuncReloadTenant, t);
3346 }
3347 
3348 /** \brief Load a tenant and wait for loading to complete
3349  */
3350 int DetectEngineLoadTenantBlocking(uint32_t tenant_id, const char *yaml)
3351 {
3352  int r = DetectLoaderSetupLoadTenant(tenant_id, yaml);
3353  if (r < 0)
3354  return r;
3355 
3356  if (DetectLoadersSync() != 0)
3357  return -1;
3358 
3359  return 0;
3360 }
3361 
3362 /** \brief Reload a tenant and wait for loading to complete
3363  */
3364 int DetectEngineReloadTenantBlocking(uint32_t tenant_id, const char *yaml, int reload_cnt)
3365 {
3366  int r = DetectLoaderSetupReloadTenant(tenant_id, yaml, reload_cnt);
3367  if (r < 0)
3368  return r;
3369 
3370  if (DetectLoadersSync() != 0)
3371  return -1;
3372 
3373  return 0;
3374 }
3375 
3376 static int DetectEngineMultiTenantSetupLoadLivedevMappings(const ConfNode *mappings_root_node,
3377  bool failure_fatal)
3378 {
3379  ConfNode *mapping_node = NULL;
3380 
3381  int mapping_cnt = 0;
3382  if (mappings_root_node != NULL) {
3383  TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
3384  ConfNode *tenant_id_node = ConfNodeLookupChild(mapping_node, "tenant-id");
3385  if (tenant_id_node == NULL)
3386  goto bad_mapping;
3387  ConfNode *device_node = ConfNodeLookupChild(mapping_node, "device");
3388  if (device_node == NULL)
3389  goto bad_mapping;
3390 
3391  uint32_t tenant_id = 0;
3392  if (StringParseUint32(&tenant_id, 10, strlen(tenant_id_node->val),
3393  tenant_id_node->val) < 0)
3394  {
3395  SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant-id "
3396  "of %s is invalid", tenant_id_node->val);
3397  goto bad_mapping;
3398  }
3399 
3400  const char *dev = device_node->val;
3401  LiveDevice *ld = LiveGetDevice(dev);
3402  if (ld == NULL) {
3403  SCLogWarning(SC_ERR_MT_NO_MAPPING, "device %s not found", dev);
3404  goto bad_mapping;
3405  }
3406 
3407  if (ld->tenant_id_set) {
3408  SCLogWarning(SC_ERR_MT_NO_MAPPING, "device %s already mapped to tenant-id %u",
3409  dev, ld->tenant_id);
3410  goto bad_mapping;
3411  }
3412 
3413  ld->tenant_id = tenant_id;
3414  ld->tenant_id_set = true;
3415 
3416  if (DetectEngineTentantRegisterLivedev(tenant_id, ld->id) != 0) {
3417  goto error;
3418  }
3419 
3420  SCLogConfig("device %s connected to tenant-id %u", dev, tenant_id);
3421  mapping_cnt++;
3422  continue;
3423 
3424  bad_mapping:
3425  if (failure_fatal)
3426  goto error;
3427  }
3428  }
3429  SCLogConfig("%d device - tenant-id mappings defined", mapping_cnt);
3430  return mapping_cnt;
3431 
3432 error:
3433  return 0;
3434 }
3435 
3436 static int DetectEngineMultiTenantSetupLoadVlanMappings(const ConfNode *mappings_root_node,
3437  bool failure_fatal)
3438 {
3439  ConfNode *mapping_node = NULL;
3440 
3441  int mapping_cnt = 0;
3442  if (mappings_root_node != NULL) {
3443  TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
3444  ConfNode *tenant_id_node = ConfNodeLookupChild(mapping_node, "tenant-id");
3445  if (tenant_id_node == NULL)
3446  goto bad_mapping;
3447  ConfNode *vlan_id_node = ConfNodeLookupChild(mapping_node, "vlan-id");
3448  if (vlan_id_node == NULL)
3449  goto bad_mapping;
3450 
3451  uint32_t tenant_id = 0;
3452  if (StringParseUint32(&tenant_id, 10, strlen(tenant_id_node->val),
3453  tenant_id_node->val) < 0)
3454  {
3455  SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant-id "
3456  "of %s is invalid", tenant_id_node->val);
3457  goto bad_mapping;
3458  }
3459 
3460  uint16_t vlan_id = 0;
3461  if (StringParseUint16(&vlan_id, 10, strlen(vlan_id_node->val),
3462  vlan_id_node->val) < 0)
3463  {
3465  "of %s is invalid", vlan_id_node->val);
3466  goto bad_mapping;
3467  }
3468  if (vlan_id == 0 || vlan_id >= 4095) {
3470  "of %s is invalid. Valid range 1-4094.", vlan_id_node->val);
3471  goto bad_mapping;
3472  }
3473 
3474  if (DetectEngineTentantRegisterVlanId(tenant_id, (uint32_t)vlan_id) != 0) {
3475  goto error;
3476  }
3477  SCLogConfig("vlan %u connected to tenant-id %u", vlan_id, tenant_id);
3478  mapping_cnt++;
3479  continue;
3480 
3481  bad_mapping:
3482  if (failure_fatal)
3483  goto error;
3484  }
3485  }
3486  return mapping_cnt;
3487 
3488 error:
3489  return 0;
3490 }
3491 
3492 /**
3493  * \brief setup multi-detect / multi-tenancy
3494  *
3495  * See if MT is enabled. If so, setup the selector, tenants and mappings.
3496  * Tenants and mappings are optional, and can also dynamically be added
3497  * and removed from the unix socket.
3498  */
3500 {
3502  DetectEngineMasterCtx *master = &g_master_de_ctx;
3503 
3504  int unix_socket = ConfUnixSocketIsEnable();
3505 
3506  int failure_fatal = 0;
3507  (void)ConfGetBool("engine.init-failure-fatal", &failure_fatal);
3508 
3509  int enabled = 0;
3510  (void)ConfGetBool("multi-detect.enabled", &enabled);
3511  if (enabled == 1) {
3516 
3517  SCMutexLock(&master->lock);
3518  master->multi_tenant_enabled = 1;
3519 
3520  const char *handler = NULL;
3521  if (ConfGet("multi-detect.selector", &handler) == 1) {
3522  SCLogConfig("multi-tenant selector type %s", handler);
3523 
3524  if (strcmp(handler, "vlan") == 0) {
3525  tenant_selector = master->tenant_selector = TENANT_SELECTOR_VLAN;
3526 
3527  int vlanbool = 0;
3528  if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
3529  SCLogError(SC_ERR_INVALID_VALUE, "vlan tracking is disabled, "
3530  "can't use multi-detect selector 'vlan'");
3531  SCMutexUnlock(&master->lock);
3532  goto error;
3533  }
3534 
3535  } else if (strcmp(handler, "direct") == 0) {
3536  tenant_selector = master->tenant_selector = TENANT_SELECTOR_DIRECT;
3537  } else if (strcmp(handler, "device") == 0) {
3538  tenant_selector = master->tenant_selector = TENANT_SELECTOR_LIVEDEV;
3539  if (EngineModeIsIPS()) {
3541  "multi-tenant 'device' mode not supported for IPS");
3542  SCMutexUnlock(&master->lock);
3543  goto error;
3544  }
3545 
3546  } else {
3547  SCLogError(SC_ERR_INVALID_VALUE, "unknown value %s "
3548  "multi-detect.selector", handler);
3549  SCMutexUnlock(&master->lock);
3550  goto error;
3551  }
3552  }
3553  SCMutexUnlock(&master->lock);
3554  SCLogConfig("multi-detect is enabled (multi tenancy). Selector: %s", handler);
3555 
3556  /* traffic -- tenant mappings */
3557  ConfNode *mappings_root_node = ConfGetNode("multi-detect.mappings");
3558 
3559  if (tenant_selector == TENANT_SELECTOR_VLAN) {
3560  int mapping_cnt = DetectEngineMultiTenantSetupLoadVlanMappings(mappings_root_node,
3561  failure_fatal);
3562  if (mapping_cnt == 0) {
3563  /* no mappings are valid when we're in unix socket mode,
3564  * they can be added on the fly. Otherwise warn/error
3565  * depending on failure_fatal */
3566 
3567  if (unix_socket) {
3568  SCLogNotice("no tenant traffic mappings defined, "
3569  "tenants won't be used until mappings are added");
3570  } else {
3571  if (failure_fatal) {
3572  SCLogError(SC_ERR_MT_NO_MAPPING, "no multi-detect mappings defined");
3573  goto error;
3574  } else {
3575  SCLogWarning(SC_ERR_MT_NO_MAPPING, "no multi-detect mappings defined");
3576  }
3577  }
3578  }
3579  } else if (tenant_selector == TENANT_SELECTOR_LIVEDEV) {
3580  int mapping_cnt = DetectEngineMultiTenantSetupLoadLivedevMappings(mappings_root_node,
3581  failure_fatal);
3582  if (mapping_cnt == 0) {
3583  if (failure_fatal) {
3584  SCLogError(SC_ERR_MT_NO_MAPPING, "no multi-detect mappings defined");
3585  goto error;
3586  } else {
3587  SCLogWarning(SC_ERR_MT_NO_MAPPING, "no multi-detect mappings defined");
3588  }
3589  }
3590  }
3591 
3592  /* tenants */
3593  ConfNode *tenants_root_node = ConfGetNode("multi-detect.tenants");
3594  ConfNode *tenant_node = NULL;
3595 
3596  if (tenants_root_node != NULL) {
3597  TAILQ_FOREACH(tenant_node, &tenants_root_node->head, next) {
3598  ConfNode *id_node = ConfNodeLookupChild(tenant_node, "id");
3599  if (id_node == NULL) {
3600  goto bad_tenant;
3601  }
3602  ConfNode *yaml_node = ConfNodeLookupChild(tenant_node, "yaml");
3603  if (yaml_node == NULL) {
3604  goto bad_tenant;
3605  }
3606 
3607  uint32_t tenant_id = 0;
3608  if (StringParseUint32(&tenant_id, 10, strlen(id_node->val),
3609  id_node->val) < 0)
3610  {
3611  SCLogError(SC_ERR_INVALID_ARGUMENT, "tenant_id "
3612  "of %s is invalid", id_node->val);
3613  goto bad_tenant;
3614  }
3615  SCLogDebug("tenant id: %u, %s", tenant_id, yaml_node->val);
3616 
3617  /* setup the yaml in this loop so that it's not done by the loader
3618  * threads. ConfYamlLoadFileWithPrefix is not thread safe. */
3619  char prefix[64];
3620  snprintf(prefix, sizeof(prefix), "multi-detect.%d", tenant_id);
3621  if (ConfYamlLoadFileWithPrefix(yaml_node->val, prefix) != 0) {
3622  SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to load yaml %s", yaml_node->val);
3623  goto bad_tenant;
3624  }
3625 
3626  int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_node->val);
3627  if (r < 0) {
3628  /* error logged already */
3629  goto bad_tenant;
3630  }
3631  continue;
3632 
3633  bad_tenant:
3634  if (failure_fatal)
3635  goto error;
3636  }
3637  }
3638 
3639  /* wait for our loaders to complete their tasks */
3640  if (DetectLoadersSync() != 0) {
3641  goto error;
3642  }
3643 
3645 
3646  } else {
3647  SCLogDebug("multi-detect not enabled (multi tenancy)");
3648  }
3649  return 0;
3650 error:
3651  return -1;
3652 }
3653 
3654 static uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet *p)
3655 {
3656  const DetectEngineThreadCtx *det_ctx = ctx;
3657  uint32_t x = 0;
3658  uint32_t vlan_id = 0;
3659 
3660  if (p->vlan_idx == 0)
3661  return 0;
3662 
3663  vlan_id = p->vlan_id[0];
3664 
3665  if (det_ctx == NULL || det_ctx->tenant_array == NULL || det_ctx->tenant_array_size == 0)
3666  return 0;
3667 
3668  /* not very efficient, but for now we're targeting only limited amounts.
3669  * Can use hash/tree approach later. */
3670  for (x = 0; x < det_ctx->tenant_array_size; x++) {
3671  if (det_ctx->tenant_array[x].traffic_id == vlan_id)
3672  return det_ctx->tenant_array[x].tenant_id;
3673  }
3674 
3675  return 0;
3676 }
3677 
3678 static uint32_t DetectEngineTentantGetIdFromLivedev(const void *ctx, const Packet *p)
3679 {
3680  const DetectEngineThreadCtx *det_ctx = ctx;
3681  const LiveDevice *ld = p->livedev;
3682 
3683  if (ld == NULL || det_ctx == NULL)
3684  return 0;
3685 
3686  SCLogDebug("using tenant-id %u for packet on device %s", ld->tenant_id, ld->dev);
3687  return ld->tenant_id;
3688 }
3689 
3690 static int DetectEngineTentantRegisterSelector(enum DetectEngineTenantSelectors selector,
3691  uint32_t tenant_id, uint32_t traffic_id)
3692 {
3693  DetectEngineMasterCtx *master = &g_master_de_ctx;
3694  SCMutexLock(&master->lock);
3695 
3696  if (!(master->tenant_selector == TENANT_SELECTOR_UNKNOWN || master->tenant_selector == selector)) {
3697  SCLogInfo("conflicting selector already set");
3698  SCMutexUnlock(&master->lock);
3699  return -1;
3700  }
3701 
3703  while (m) {
3704  if (m->traffic_id == traffic_id) {
3705  SCLogInfo("traffic id already registered");
3706  SCMutexUnlock(&master->lock);
3707  return -1;
3708  }
3709  m = m->next;
3710  }
3711 
3712  DetectEngineTenantMapping *map = SCCalloc(1, sizeof(*map));
3713  if (map == NULL) {
3714  SCLogInfo("memory fail");
3715  SCMutexUnlock(&master->lock);
3716  return -1;
3717  }
3718  map->traffic_id = traffic_id;
3719  map->tenant_id = tenant_id;
3720 
3721  map->next = master->tenant_mapping_list;
3722  master->tenant_mapping_list = map;
3723 
3724  master->tenant_selector = selector;
3725 
3726  SCLogDebug("tenant handler %u %u %u registered", selector, tenant_id, traffic_id);
3727  SCMutexUnlock(&master->lock);
3728  return 0;
3729 }
3730 
3731 static int DetectEngineTentantUnregisterSelector(enum DetectEngineTenantSelectors selector,
3732  uint32_t tenant_id, uint32_t traffic_id)
3733 {
3734  DetectEngineMasterCtx *master = &g_master_de_ctx;
3735  SCMutexLock(&master->lock);
3736 
3737  if (master->tenant_mapping_list == NULL) {
3738  SCMutexUnlock(&master->lock);
3739  return -1;
3740  }
3741 
3742  DetectEngineTenantMapping *prev = NULL;
3744  while (map) {
3745  if (map->traffic_id == traffic_id &&
3746  map->tenant_id == tenant_id)
3747  {
3748  if (prev != NULL)
3749  prev->next = map->next;
3750  else
3751  master->tenant_mapping_list = map->next;
3752 
3753  map->next = NULL;
3754  SCFree(map);
3755  SCLogInfo("tenant handler %u %u %u unregistered", selector, tenant_id, traffic_id);
3756  SCMutexUnlock(&master->lock);
3757  return 0;
3758  }
3759  prev = map;
3760  map = map->next;
3761  }
3762 
3763  SCMutexUnlock(&master->lock);
3764  return -1;
3765 }
3766 
3767 int DetectEngineTentantRegisterLivedev(uint32_t tenant_id, int device_id)
3768 {
3769  return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_LIVEDEV, tenant_id, (uint32_t)device_id);
3770 }
3771 
3772 int DetectEngineTentantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
3773 {
3774  return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
3775 }
3776 
3777 int DetectEngineTentantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
3778 {
3779  return DetectEngineTentantUnregisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
3780 }
3781 
3783 {
3784  SCLogInfo("registering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
3785  return DetectEngineTentantRegisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
3786 }
3787 
3789 {
3790  SCLogInfo("unregistering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
3791  return DetectEngineTentantUnregisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
3792 }
3793 
3794 static uint32_t DetectEngineTentantGetIdFromPcap(const void *ctx, const Packet *p)
3795 {
3796  return p->pcap_v.tenant_id;
3797 }
3798 
3800 {
3801  DetectEngineMasterCtx *master = &g_master_de_ctx;
3802  SCMutexLock(&master->lock);
3803 
3804  if (master->list == NULL) {
3805  SCMutexUnlock(&master->lock);
3806  return NULL;
3807  }
3808 
3809  DetectEngineCtx *de_ctx = master->list;
3810  while (de_ctx) {
3812  de_ctx->tenant_id == tenant_id)
3813  {
3814  de_ctx->ref_cnt++;
3815  break;
3816  }
3817 
3818  de_ctx = de_ctx->next;
3819  }
3820 
3821  SCMutexUnlock(&master->lock);
3822  return de_ctx;
3823 }
3824 
3826 {
3827  BUG_ON((*de_ctx)->ref_cnt == 0);
3828  (*de_ctx)->ref_cnt--;
3829  *de_ctx = NULL;
3830 }
3831 
3832 static int DetectEngineAddToList(DetectEngineCtx *instance)
3833 {
3834  DetectEngineMasterCtx *master = &g_master_de_ctx;
3835 
3836  if (instance == NULL)
3837  return -1;
3838 
3839  if (master->list == NULL) {
3840  master->list = instance;
3841  } else {
3842  instance->next = master->list;
3843  master->list = instance;
3844  }
3845 
3846  return 0;
3847 }
3848 
3850 {
3851  int r;
3852 
3853  if (de_ctx == NULL)
3854  return -1;
3855 
3856  SCLogDebug("adding de_ctx %p to master", de_ctx);
3857 
3858  DetectEngineMasterCtx *master = &g_master_de_ctx;
3859  SCMutexLock(&master->lock);
3860  r = DetectEngineAddToList(de_ctx);
3861  SCMutexUnlock(&master->lock);
3862  return r;
3863 }
3864 
3866 {
3867  DetectEngineMasterCtx *master = &g_master_de_ctx;
3868 
3869  SCMutexLock(&master->lock);
3870  DetectEngineCtx *instance = master->list;
3871  if (instance == NULL) {
3872  SCMutexUnlock(&master->lock);
3873  return -1;
3874  }
3875 
3876  /* remove from active list */
3877  if (instance == de_ctx) {
3878  master->list = instance->next;
3879  } else {
3880  DetectEngineCtx *prev = instance;
3881  instance = instance->next; /* already checked first element */
3882 
3883  while (instance) {
3884  DetectEngineCtx *next = instance->next;
3885 
3886  if (instance == de_ctx) {
3887  prev->next = instance->next;
3888  break;
3889  }
3890 
3891  prev = instance;
3892  instance = next;
3893  }
3894  if (instance == NULL) {
3895  SCMutexUnlock(&master->lock);
3896  return -1;
3897  }
3898  }
3899 
3900  /* instance is now detached from list */
3901  instance->next = NULL;
3902 
3903  /* add to free list */
3904  if (master->free_list == NULL) {
3905  master->free_list = instance;
3906  } else {
3907  instance->next = master->free_list;
3908  master->free_list = instance;
3909  }
3910  SCLogDebug("detect engine %p moved to free list (%u refs)", de_ctx, de_ctx->ref_cnt);
3911 
3912  SCMutexUnlock(&master->lock);
3913  return 0;
3914 }
3915 
3917 {
3918  DetectEngineMasterCtx *master = &g_master_de_ctx;
3919  SCMutexLock(&master->lock);
3920 
3921  DetectEngineCtx *prev = NULL;
3922  DetectEngineCtx *instance = master->free_list;
3923  while (instance) {
3924  DetectEngineCtx *next = instance->next;
3925 
3926  SCLogDebug("detect engine %p has %u ref(s)", instance, instance->ref_cnt);
3927 
3928  if (instance->ref_cnt == 0) {
3929  if (prev == NULL) {
3930  master->free_list = next;
3931  } else {
3932  prev->next = next;
3933  }
3934 
3935  SCLogDebug("freeing detect engine %p", instance);
3936  DetectEngineCtxFree(instance);
3937  instance = NULL;
3938  }
3939 
3940  prev = instance;
3941  instance = next;
3942  }
3943  SCMutexUnlock(&master->lock);
3944 }
3945 
3946 static int reloads = 0;
3947 
3948 /** \brief Reload the detection engine
3949  *
3950  * \param filename YAML file to load for the detect config
3951  *
3952  * \retval -1 error
3953  * \retval 0 ok
3954  */
3956 {
3957  DetectEngineCtx *new_de_ctx = NULL;
3958  DetectEngineCtx *old_de_ctx = NULL;
3959 
3960  char prefix[128];
3961  memset(prefix, 0, sizeof(prefix));
3962 
3963  SCLogNotice("rule reload starting");
3964 
3965  if (suri->conf_filename != NULL) {
3966  snprintf(prefix, sizeof(prefix), "detect-engine-reloads.%d", reloads++);
3967  if (ConfYamlLoadFileWithPrefix(suri->conf_filename, prefix) != 0) {
3968  SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to load yaml %s",
3969  suri->conf_filename);
3970  return -1;
3971  }
3972 
3973  ConfNode *node = ConfGetNode(prefix);
3974  if (node == NULL) {
3975  SCLogError(SC_ERR_CONF_YAML_ERROR, "failed to properly setup yaml %s",
3976  suri->conf_filename);
3977  return -1;
3978  }
3979 #if 0
3980  ConfDump();
3981 #endif
3982  }
3983 
3984  /* get a reference to the current de_ctx */
3985  old_de_ctx = DetectEngineGetCurrent();
3986  if (old_de_ctx == NULL)
3987  return -1;
3988  SCLogDebug("get ref to old_de_ctx %p", old_de_ctx);
3989 
3990  /* only reload a regular 'normal' and 'delayed detect stub' detect engines */
3991  if (!(old_de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
3992  old_de_ctx->type == DETECT_ENGINE_TYPE_DD_STUB))
3993  {
3994  DetectEngineDeReference(&old_de_ctx);
3995  SCLogNotice("rule reload complete");
3996  return -1;
3997  }
3998 
3999  /* get new detection engine */
4000  new_de_ctx = DetectEngineCtxInitWithPrefix(prefix);
4001  if (new_de_ctx == NULL) {
4002  SCLogError(SC_ERR_INITIALIZATION, "initializing detection engine "
4003  "context failed.");
4004  DetectEngineDeReference(&old_de_ctx);
4005  return -1;
4006  }
4007  if (SigLoadSignatures(new_de_ctx,
4008  suri->sig_file, suri->sig_file_exclusive) != 0) {
4009  DetectEngineCtxFree(new_de_ctx);
4010  DetectEngineDeReference(&old_de_ctx);
4011  return -1;
4012  }
4013  SCLogDebug("set up new_de_ctx %p", new_de_ctx);
4014 
4015  /* add to master */
4016  DetectEngineAddToMaster(new_de_ctx);
4017 
4018  /* move to old free list */
4019  DetectEngineMoveToFreeList(old_de_ctx);
4020  DetectEngineDeReference(&old_de_ctx);
4021 
4022  SCLogDebug("going to reload the threads to use new_de_ctx %p", new_de_ctx);
4023  /* update the threads */
4024  DetectEngineReloadThreads(new_de_ctx);
4025  SCLogDebug("threads now run new_de_ctx %p", new_de_ctx);
4026 
4027  /* walk free list, freeing the old_de_ctx */
4029 
4031 
4032  SCLogDebug("old_de_ctx should have been freed");
4033 
4034  SCLogNotice("rule reload complete");
4035  return 0;
4036 }
4037 
4038 static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len)
4039 {
4040  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
4041  return det_ctx->tenant_id % h->array_size;
4042 }
4043 
4044 static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len)
4045 {
4048  return (det1->tenant_id == det2->tenant_id);
4049 }
4050 
4051 static void TenantIdFree(void *d)
4052 {
4053  DetectEngineThreadCtxFree(d);
4054 }
4055 
4057 {
4058  DetectEngineMasterCtx *master = &g_master_de_ctx;
4059  SCMutexLock(&master->lock);
4060 
4061  if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
4062  SCLogInfo("error, no tenant selector");
4063  SCMutexUnlock(&master->lock);
4064  return -1;
4065  }
4066 
4067  DetectEngineCtx *stub_de_ctx = NULL;
4068  DetectEngineCtx *list = master->list;
4069  for ( ; list != NULL; list = list->next) {
4070  SCLogDebug("list %p tenant %u", list, list->tenant_id);
4071 
4072  if (list->type == DETECT_ENGINE_TYPE_NORMAL ||
4073  list->type == DETECT_ENGINE_TYPE_MT_STUB ||
4075  {
4076  stub_de_ctx = list;
4077  break;
4078  }
4079  }
4080  if (stub_de_ctx == NULL) {
4081  stub_de_ctx = DetectEngineCtxInitStubForMT();
4082  if (stub_de_ctx == NULL) {
4083  SCMutexUnlock(&master->lock);
4084  return -1;
4085  }
4086 
4087  if (master->list == NULL) {
4088  master->list = stub_de_ctx;
4089  } else {
4090  stub_de_ctx->next = master->list;
4091  master->list = stub_de_ctx;
4092  }
4093  }
4094 
4095  /* update the threads */
4096  SCLogDebug("MT reload starting");
4097  DetectEngineReloadThreads(stub_de_ctx);
4098  SCLogDebug("MT reload done");
4099 
4100  SCMutexUnlock(&master->lock);
4101 
4102  /* walk free list, freeing the old_de_ctx */
4104 
4105  SCLogDebug("old_de_ctx should have been freed");
4106  return 0;
4107 }
4108 
4109 static int g_parse_metadata = 0;
4110 
4112 {
4113  g_parse_metadata = 1;
4114 }
4115 
4117 {
4118  g_parse_metadata = 0;
4119 }
4120 
4122 {
4123  return g_parse_metadata;
4124 }
4125 
4127 {
4128  switch (type) {
4129  case DETECT_SM_LIST_MATCH:
4130  return "packet";
4131  case DETECT_SM_LIST_PMATCH:
4132  return "packet/stream payload";
4133 
4134  case DETECT_SM_LIST_TMATCH:
4135  return "tag";
4136 
4138  return "base64_data";
4139 
4141  return "post-match";
4142 
4144  return "suppress";
4146  return "threshold";
4147 
4148  case DETECT_SM_LIST_MAX:
4149  return "max (internal)";
4150  }
4151  return "error";
4152 }
4153 
4154 /* events api */
4156 {
4158  det_ctx->events++;
4159 }
4160 
4162 {
4163  return det_ctx->decoder_events;
4164 }
4165 
4166 int DetectEngineGetEventInfo(const char *event_name, int *event_id,
4167  AppLayerEventType *event_type)
4168 {
4169  *event_id = SCMapEnumNameToValue(event_name, det_ctx_event_table);
4170  if (*event_id == -1) {
4171  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
4172  "det_ctx's enum map table.", event_name);
4173  /* this should be treated as fatal */
4174  return -1;
4175  }
4176  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
4177 
4178  return 0;
4179 }
4180 
4181 /*************************************Unittest*********************************/
4182 
4183 #ifdef UNITTESTS
4184 
4185 static int DetectEngineInitYamlConf(const char *conf)
4186 {
4188  ConfInit();
4189  return ConfYamlLoadString(conf, strlen(conf));
4190 }
4191 
4192 static void DetectEngineDeInitYamlConf(void)
4193 {
4194  ConfDeInit();
4196 
4197  return;
4198 }
4199 
4200 static int DetectEngineTest01(void)
4201 {
4202  const char *conf =
4203  "%YAML 1.1\n"
4204  "---\n"
4205  "detect-engine:\n"
4206  " - profile: medium\n"
4207  " - custom-values:\n"
4208  " toclient_src_groups: 2\n"
4209  " toclient_dst_groups: 2\n"
4210  " toclient_sp_groups: 2\n"
4211  " toclient_dp_groups: 3\n"
4212  " toserver_src_groups: 2\n"
4213  " toserver_dst_groups: 4\n"
4214  " toserver_sp_groups: 2\n"
4215  " toserver_dp_groups: 25\n"
4216  " - inspection-recursion-limit: 0\n";
4217 
4218  DetectEngineCtx *de_ctx = NULL;
4219  int result = 0;
4220 
4221  if (DetectEngineInitYamlConf(conf) == -1)
4222  return 0;
4224  if (de_ctx == NULL)
4225  goto end;
4226 
4227  result = (de_ctx->inspection_recursion_limit == -1);
4228 
4229  end:
4230  if (de_ctx != NULL)
4232 
4233  DetectEngineDeInitYamlConf();
4234 
4235  return result;
4236 }
4237 
4238 static int DetectEngineTest02(void)
4239 {
4240  const char *conf =
4241  "%YAML 1.1\n"
4242  "---\n"
4243  "detect-engine:\n"
4244  " - profile: medium\n"
4245  " - custom-values:\n"
4246  " toclient_src_groups: 2\n"
4247  " toclient_dst_groups: 2\n"
4248  " toclient_sp_groups: 2\n"
4249  " toclient_dp_groups: 3\n"
4250  " toserver_src_groups: 2\n"
4251  " toserver_dst_groups: 4\n"
4252  " toserver_sp_groups: 2\n"
4253  " toserver_dp_groups: 25\n"
4254  " - inspection-recursion-limit:\n";
4255 
4256  DetectEngineCtx *de_ctx = NULL;
4257  int result = 0;
4258 
4259  if (DetectEngineInitYamlConf(conf) == -1)
4260  return 0;
4262  if (de_ctx == NULL)
4263  goto end;
4264 
4265  result = (de_ctx->inspection_recursion_limit == -1);
4266 
4267  end:
4268  if (de_ctx != NULL)
4270 
4271  DetectEngineDeInitYamlConf();
4272 
4273  return result;
4274 }
4275 
4276 static int DetectEngineTest03(void)
4277 {
4278  const char *conf =
4279  "%YAML 1.1\n"
4280  "---\n"
4281  "detect-engine:\n"
4282  " - profile: medium\n"
4283  " - custom-values:\n"
4284  " toclient_src_groups: 2\n"
4285  " toclient_dst_groups: 2\n"
4286  " toclient_sp_groups: 2\n"
4287  " toclient_dp_groups: 3\n"
4288  " toserver_src_groups: 2\n"
4289  " toserver_dst_groups: 4\n"
4290  " toserver_sp_groups: 2\n"
4291  " toserver_dp_groups: 25\n";
4292 
4293  DetectEngineCtx *de_ctx = NULL;
4294  int result = 0;
4295 
4296  if (DetectEngineInitYamlConf(conf) == -1)
4297  return 0;
4299  if (de_ctx == NULL)
4300  goto end;
4301 
4302  result = (de_ctx->inspection_recursion_limit ==
4304 
4305  end:
4306  if (de_ctx != NULL)
4308 
4309  DetectEngineDeInitYamlConf();
4310 
4311  return result;
4312 }
4313 
4314 static int DetectEngineTest04(void)
4315 {
4316  const char *conf =
4317  "%YAML 1.1\n"
4318  "---\n"
4319  "detect-engine:\n"
4320  " - profile: medium\n"
4321  " - custom-values:\n"
4322  " toclient_src_groups: 2\n"
4323  " toclient_dst_groups: 2\n"
4324  " toclient_sp_groups: 2\n"
4325  " toclient_dp_groups: 3\n"
4326  " toserver_src_groups: 2\n"
4327  " toserver_dst_groups: 4\n"
4328  " toserver_sp_groups: 2\n"
4329  " toserver_dp_groups: 25\n"
4330  " - inspection-recursion-limit: 10\n";
4331 
4332  DetectEngineCtx *de_ctx = NULL;
4333  int result = 0;
4334 
4335  if (DetectEngineInitYamlConf(conf) == -1)
4336  return 0;
4338  if (de_ctx == NULL)
4339  goto end;
4340 
4341  result = (de_ctx->inspection_recursion_limit == 10);
4342 
4343  end:
4344  if (de_ctx != NULL)
4346 
4347  DetectEngineDeInitYamlConf();
4348 
4349  return result;
4350 }
4351 
4352 static int DetectEngineTest08(void)
4353 {
4354  const char *conf =
4355  "%YAML 1.1\n"
4356  "---\n"
4357  "detect-engine:\n"
4358  " - profile: custom\n"
4359  " - custom-values:\n"
4360  " toclient-groups: 23\n"
4361  " toserver-groups: 27\n";
4362 
4363  DetectEngineCtx *de_ctx = NULL;
4364  int result = 0;
4365 
4366  if (DetectEngineInitYamlConf(conf) == -1)
4367  return 0;
4369  if (de_ctx == NULL)
4370  goto end;
4371 
4372  if (de_ctx->max_uniq_toclient_groups == 23 &&
4374  result = 1;
4375 
4376  end:
4377  if (de_ctx != NULL)
4379 
4380  DetectEngineDeInitYamlConf();
4381 
4382  return result;
4383 }
4384 
4385 /** \test bug 892 bad values */
4386 static int DetectEngineTest09(void)
4387 {
4388  const char *conf =
4389  "%YAML 1.1\n"
4390  "---\n"
4391  "detect-engine:\n"
4392  " - profile: custom\n"
4393  " - custom-values:\n"
4394  " toclient-groups: BA\n"
4395  " toserver-groups: BA\n"
4396  " - inspection-recursion-limit: 10\n";
4397 
4398  DetectEngineCtx *de_ctx = NULL;
4399  int result = 0;
4400 
4401  if (DetectEngineInitYamlConf(conf) == -1)
4402  return 0;
4404  if (de_ctx == NULL)
4405  goto end;
4406 
4407  if (de_ctx->max_uniq_toclient_groups == 20 &&
4409  result = 1;
4410 
4411  end:
4412  if (de_ctx != NULL)
4414 
4415  DetectEngineDeInitYamlConf();
4416 
4417  return result;
4418 }
4419 
4420 #endif
4421 
4423 {
4424 #ifdef UNITTESTS
4425  UtRegisterTest("DetectEngineTest01", DetectEngineTest01);
4426  UtRegisterTest("DetectEngineTest02", DetectEngineTest02);
4427  UtRegisterTest("DetectEngineTest03", DetectEngineTest03);
4428  UtRegisterTest("DetectEngineTest04", DetectEngineTest04);
4429  UtRegisterTest("DetectEngineTest08", DetectEngineTest08);
4430  UtRegisterTest("DetectEngineTest09", DetectEngineTest09);
4431 #endif
4432  return;
4433 }
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HEADER
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_HEADER
Definition: detect-engine-content-inspection.h:33
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:59
DE_STATE_ID_FILE_INSPECT
#define DE_STATE_ID_FILE_INSPECT
Definition: detect-engine-state.h:60
SCProfilingSghThreadCleanup
void SCProfilingSghThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rulegroups.c:358
DetectEngineTenantMapping_
Definition: detect.h:1408
util-byte.h
tm-threads.h
ConfGetInt
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:437
DetectEngineCtx_::tenant_id
int tenant_id
Definition: detect.h:765
DetectEngineAppInspectionEngine_
Definition: detect.h:395
FILE_DECODER_EVENT_LZMA_DATA_ERROR
@ FILE_DECODER_EVENT_LZMA_DATA_ERROR
Definition: detect.h:1224
ENGINE_PROFILE_MEDIUM
@ ENGINE_PROFILE_MEDIUM
Definition: detect.h:956
DetectBufferType_::supports_transforms
bool supports_transforms
Definition: detect.h:431
DetectEngineSyncer_::m
SCMutex m
Definition: detect-engine.c:1468
DetectBufferType_::mpm
bool mpm
Definition: detect.h:429
detect-content.h
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1033
DetectEngineIPOnlyThreadDeinit
void DetectEngineIPOnlyThreadDeinit(DetectEngineIPOnlyThreadCtx *io_tctx)
Deinitialize the IP Only thread detection engine context.
Definition: detect-engine-iponly.c:939
detect-engine.h
DetectEngineResetMaxSigId
void DetectEngineResetMaxSigId(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:2403
DetectEngineMTApply
int DetectEngineMTApply(void)
Definition: detect-engine.c:4056
StringParseUint16
int StringParseUint16(uint16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:324
SCProfilingKeywordDestroyCtx
void SCProfilingKeywordDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-keywords.c:278
PACKET_ALERT_FLAG_STREAM_MATCH
#define PACKET_ALERT_FLAG_STREAM_MATCH
Definition: decode.h:285
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:90
DetectEngineThreadCtx_::to_clear_idx
uint32_t to_clear_idx
Definition: detect.h:1054
DetectEngineTentantRegisterPcapFile
int DetectEngineTentantRegisterPcapFile(uint32_t tenant_id)
Definition: detect-engine.c:3782
SC_ERR_MT_DUPLICATE_TENANT
@ SC_ERR_MT_DUPLICATE_TENANT
Definition: util-error.h:300
SCProfilingKeywordThreadCleanup
void SCProfilingKeywordThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-keywords.c:351
SCProfilingSghThreadSetup
void SCProfilingSghThreadSetup(SCProfileSghDetectCtx *ctx, DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rulegroups.c:321
DetectParseDupSigHashInit
int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:2130
SignatureInitData_::list_set
bool list_set
Definition: detect.h:499
RELOAD
@ RELOAD
Definition: detect-engine.c:1463
DetectLoaderThreadSpawn
void DetectLoaderThreadSpawn(void)
spawn the detect loader manager thread
Definition: detect-engine-loader.c:615
AppLayerParserIsEnabled
int AppLayerParserIsEnabled(AppProto alproto)
simple way to globally test if a alproto is registered and fully enabled in the configuration.
Definition: app-layer-parser.c:1378
offset
uint64_t offset
Definition: util-streaming-buffer.h:2
DetectEngineDeReference
void DetectEngineDeReference(DetectEngineCtx **de_ctx)
Definition: detect-engine.c:3825
DETECT_CI_FLAGS_START
#define DETECT_CI_FLAGS_START
Definition: detect-engine-content-inspection.h:38
LiveDevice_::id
int id
Definition: util-device.h:46
RUNMODE_UNITTEST
@ RUNMODE_UNITTEST
Definition: runmodes.h:39
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
DetectEngineMustParseMetadata
int DetectEngineMustParseMetadata(void)
Definition: detect-engine.c:4121
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:370
MpmFactoryDeRegisterAllMpmCtxProfiles
void MpmFactoryDeRegisterAllMpmCtxProfiles(DetectEngineCtx *de_ctx)
Definition: util-mpm.c:232
DetectEngineThreadCtx_::counter_match_list
uint16_t counter_match_list
Definition: detect.h:1046
flow-util.h
DetectEnginePktInspectionEngine
Definition: detect.h:454
DetectEngineMasterCtx_::tenant_mapping_list
DetectEngineTenantMapping * tenant_mapping_list
Definition: detect.h:1439
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it's lock.
Definition: util-atomic.h:81
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:421
FILE_DECODER_EVENT_NO_MEM
@ FILE_DECODER_EVENT_NO_MEM
Definition: detect.h:1213
detect-engine-siggroup.h
Packet_::vlan_id
uint16_t vlan_id[2]
Definition: decode.h:436
DetectEngineMasterCtx_::list
DetectEngineCtx * list
Definition: detect.h:1428
DetectEngineCtxInitWithPrefix
DetectEngineCtx * DetectEngineCtxInitWithPrefix(const char *prefix)
Definition: detect-engine.c:1990
MpmStoreFree
void MpmStoreFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by MpmStoreInit() function.
Definition: detect-engine-mpm.c:1185
FILE_DECODER_EVENT_LZMA_FORMAT_ERROR
@ FILE_DECODER_EVENT_LZMA_FORMAT_ERROR
Definition: detect.h:1223
ConfNode_::val
char * val
Definition: conf.h:34
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:517
DetectEngineCtx_::type
enum DetectEngineType type
Definition: detect.h:894
DetectEnginePruneFreeList
void DetectEnginePruneFreeList(void)
Definition: detect-engine.c:3916
DetectEnginePktInspectionEngine::mpm
uint16_t mpm
Definition: detect.h:456
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3015
SCFree
#define SCFree(a)
Definition: util-mem.h:322
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectEngineTransforms
Definition: detect.h:369
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
Definition: detect-engine-content-inspection.h:35
SIG_FLAG_INIT_NEED_FLUSH
#define SIG_FLAG_INIT_NEED_FLUSH
Definition: detect.h:263
MpmTableElmt_::name
const char * name
Definition: util-mpm.h:142
DetectEngineTentantUnregisterVlanId
int DetectEngineTentantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
Definition: detect-engine.c:3777
DetectEngineCtxInitStubForDD
DetectEngineCtx * DetectEngineCtxInitStubForDD(void)
Definition: detect-engine.c:1980
KEYWORD_PROFILING_SET_LIST
#define KEYWORD_PROFILING_SET_LIST(ctx, list)
Definition: util-profiling.h:65
DetectEngineCtx_::max_uniq_toclient_groups
uint16_t max_uniq_toclient_groups
Definition: detect.h:819
IDLE
@ IDLE
Definition: detect-engine.c:1462
DetectEngineCtx_::ref_cnt
uint32_t ref_cnt
Definition: detect.h:897
DetectEngineAppInspectionEngine_::Callback
InspectEngineFuncPtr Callback
Definition: detect.h:410
Signature_::alproto
AppProto alproto
Definition: detect.h:526
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
SigString_
Definition: detect.h:714
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:97
DetectEngineCtx_::non_pf_store_cnt_max
uint32_t non_pf_store_cnt_max
Definition: detect.h:784
PacketEnqueue
void PacketEnqueue(PacketQueue *q, Packet *p)
Definition: packet-queue.c:173
DetectEngineGetByTenantId
DetectEngineCtx * DetectEngineGetByTenantId(int tenant_id)
Definition: detect-engine.c:3799
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:2
DetectPort_::port
uint16_t port
Definition: detect.h:192
TM_FLAG_DETECT_TM
#define TM_FLAG_DETECT_TM
Definition: tm-modules.h:34
SCClassConfLoadClassficationConfigFile
void SCClassConfLoadClassficationConfigFile(DetectEngineCtx *de_ctx, FILE *fd)
Loads the Classtype info from the classification.config file.
Definition: util-classification-config.c:528
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:47
Flow_::proto
uint8_t proto
Definition: flow.h:361
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:71
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:109
AppLayerParserGetStateProgress
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
Definition: app-layer-parser.c:1023
DetectEngineThreadCtx_::decoder_events
AppLayerDecoderEvents * decoder_events
Definition: detect.h:1140
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:330
InspectionBuffer
Definition: detect.h:342
DetectEngineThreadKeywordCtxItem_::InitFunc
void *(* InitFunc)(void *)
Definition: detect.h:732
Packet_::flags
uint32_t flags
Definition: decode.h:444
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
DetectEngineAppInspectionEngine_::GetData
InspectionBufferGetDataPtr GetData
Definition: detect.h:413
DetectEngineThreadKeywordCtxItem_
Definition: detect.h:731
Tmq_::pq
PacketQueue * pq
Definition: tm-queues.h:35
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:437
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:342
DETECT_SM_LIST_THRESHOLD
@ DETECT_SM_LIST_THRESHOLD
Definition: detect.h:104
AppLayerEventType
enum AppLayerEventType_ AppLayerEventType
DetectBufferTypeRegisterSetupCallback
void DetectBufferTypeRegisterSetupCallback(const char *name, void(*SetupCallback)(const DetectEngineCtx *, Signature *))
Definition: detect-engine.c:933
DetectEngineThreadKeywordCtxItem_::data
void * data
Definition: detect.h:734
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1103
util-hash.h
InspectionBufferGetDataPtr
InspectionBuffer *(* InspectionBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id)
Definition: detect.h:375
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
DetectEngineReloadTenantBlocking
int DetectEngineReloadTenantBlocking(uint32_t tenant_id, const char *yaml, int reload_cnt)
Reload a tenant and wait for loading to complete.
Definition: detect-engine.c:3364
DetectEngineTransforms::transforms
int transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:370
LiveDevice_
Definition: util-device.h:40
DetectEngineCtx_::inspection_recursion_limit
int inspection_recursion_limit
Definition: detect.h:833
SpmTableElmt_::name
const char * name
Definition: util-spm.h:62
LiveDevice_::tenant_id_set
bool tenant_id_set
Definition: util-device.h:43
DetectAddressMapFree
void DetectAddressMapFree(DetectEngineCtx *de_ctx)
Definition: detect-engine-address.c:1349
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:761
DetectEngineReloadSetIdle
void DetectEngineReloadSetIdle(void)
Definition: detect-engine.c:1501
ConfYamlLoadFileWithPrefix
int ConfYamlLoadFileWithPrefix(const char *filename, const char *prefix)
Load configuration from a YAML file, insert in tree at 'prefix'.
Definition: conf-yaml-loader.c:482
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:455
DetectMetadataHashInit
int DetectMetadataHashInit(DetectEngineCtx *de_ctx)
Definition: detect-metadata.c:63
DetectEngineThreadCtx_::global_keyword_ctxs_array
void ** global_keyword_ctxs_array
Definition: detect.h:1134
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:3124
SC_ERR_INVALID_SIGNATURE
@ SC_ERR_INVALID_SIGNATURE
Definition: util-error.h:69
DetectEngineThreadCtx_::bj_values
uint64_t * bj_values
Definition: detect.h:1113
TmThreadCountThreadsByTmmFlags
uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags)
returns a count of all the threads that match the flag
Definition: tm-threads.c:1921
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:290
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
InspectionBuffer::orig
const uint8_t * orig
Definition: detect.h:353
SC_ERR_MT_NO_SELECTOR
@ SC_ERR_MT_NO_SELECTOR
Definition: util-error.h:299
FILE_DECODER_EVENT_LZMA_UNKNOWN_ERROR
@ FILE_DECODER_EVENT_LZMA_UNKNOWN_ERROR
Definition: detect.h:1226
DetectEngineAddToMaster
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:3849
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:449
SCSigSignatureOrderingModuleCleanup
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
Definition: detect-engine-sigorder.c:803
DetectEngineCtx_::keyword_id
int keyword_id
Definition: detect.h:873
TenantLoaderCtx_::yaml
const char * yaml
Definition: detect-engine.c:3289
PrefilterDeinit
void PrefilterDeinit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:483
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
DetectEngineThreadCtx_::inspect
struct DetectEngineThreadCtx_::@105 inspect
util-var-name.h
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:224
ConfDump
void ConfDump(void)
Dump configuration to stdout.
Definition: conf.c:780
HashTable_
Definition: util-hash.h:35
FILE_DECODER_EVENT_INVALID_SWF_VERSION
@ FILE_DECODER_EVENT_INVALID_SWF_VERSION
Definition: detect.h:1215
DetectEngineThreadCtx_::flags
uint16_t flags
Definition: detect.h:1069
DetectEngineTenantMapping_::next
struct DetectEngineTenantMapping_ * next
Definition: detect.h:1414
DetectEngineSetEvent
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
Definition: detect-engine.c:4155
DetectEngineThreadCtx_::buffers_size
uint32_t buffers_size
Definition: detect.h:1053
MIN
#define MIN(x, y)
Definition: suricata-common.h:360
AppLayerDecoderEventsFreeEvents
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
Definition: app-layer-events.c:148
DetectBufferRunValidateCallback
bool DetectBufferRunValidateCallback(const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
Definition: detect-engine.c:962
DetectEngineCtx_::profile_sgh_ctx
struct SCProfileSghDetectCtx_ * profile_sgh_ctx
Definition: detect.h:887
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:78
VarNameStoreActivateStaging
void VarNameStoreActivateStaging(void)
Definition: util-var-name.c:340
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:205
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *de_ctx)
Free a DetectEngineCtx::
Definition: detect-engine.c:2030
DetectBufferMpmRegistery_
one time registration of keywords at start up
Definition: detect.h:605
InspectionBuffer::size
uint32_t size
Definition: detect.h:350
DetectEngineThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: detect.h:1107
InspectionBuffer::flags
uint8_t flags
Definition: detect.h:346
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:575
SCInstance_::conf_filename
const char * conf_filename
Definition: suricata.h:164
DetectEngineCtx_::prefilter_setting
enum DetectEnginePrefilterSetting prefilter_setting
Definition: detect.h:905
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:486
DetectParseDupSigHashFree
void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
Frees the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:2147
DetectBufferType_
Definition: detect.h:424
m
SCMutex m
Definition: flow-hash.h:5
SigTableElmt_::Free
void(* Free)(void *)
Definition: detect.h:1192
DetectEngineGetVersion
uint32_t DetectEngineGetVersion(void)
Definition: detect-engine.c:3105
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
DetectEngineContentInspection
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer, uint32_t buffer_len, uint32_t stream_start_offset, uint8_t flags, uint8_t inspection_mode)
Run the actual payload match functions.
Definition: detect-engine-content-inspection.c:103
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:248
SC_ERR_DETECT_PREPARE
@ SC_ERR_DETECT_PREPARE
Definition: util-error.h:205
detect-engine-payload.h
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:985
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
MAX
#define MAX(x, y)
Definition: suricata-common.h:364
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:79
MPM_AC
@ MPM_AC
Definition: util-mpm.h:35
SigMatchData_
Data needed for Match()
Definition: detect.h:327
InspectionBufferMultipleForList::init
uint32_t init
Definition: detect.h:366
DetectEngineCtx_::mpm_matcher
uint16_t mpm_matcher
Definition: detect.h:810
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:69
DetectEngineThreadCtx_::counter_fnonmpm_list
uint16_t counter_fnonmpm_list
Definition: detect.h:1045
DetectEngineCtx_::version
uint32_t version
Definition: detect.h:855
SC_ERR_INVALID_ARGUMENTS
@ SC_ERR_INVALID_ARGUMENTS
Definition: util-error.h:82
DETECT_TRANSFORMS_MAX
#define DETECT_TRANSFORMS_MAX
Definition: detect.h:58
InspectionBuffer::orig_len
uint32_t orig_len
Definition: detect.h:352
DetectPort_::port2
uint16_t port2
Definition: detect.h:193
ThresholdHashInit
void ThresholdHashInit(DetectEngineCtx *de_ctx)
Init threshold context hash tables.
Definition: detect-engine-threshold.c:652
DetectEngineThreadCtx_::counter_nonmpm_list
uint16_t counter_nonmpm_list
Definition: detect.h:1044
DetectEngineThreadCtx_::events
uint16_t events
Definition: detect.h:1141
detect-engine-prefilter.h
AppLayerDecoderEvents_
Data structure to store app layer decoder events.
Definition: app-layer-events.h:34
DetectEngineThreadCtx_::mtcu
MpmThreadCtx mtcu
Definition: detect.h:1101
util-unittest.h
InspectionBufferGet
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
Definition: detect-engine.c:1041
APP_LAYER_EVENT_TYPE_TRANSACTION
@ APP_LAYER_EVENT_TYPE_TRANSACTION
Definition: app-layer-events.h:57
DetectBufferTypeCloseRegistration
void DetectBufferTypeCloseRegistration(void)
Definition: detect-engine.c:1237
DetectEnginePktInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:462
MPM_AC_BS
@ MPM_AC_BS
Definition: util-mpm.h:36
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:54
DetectEngineInspectGenericList
int DetectEngineInspectGenericList(ThreadVars *tv, const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, const uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Definition: detect-engine.c:1533
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:78
HashTableFree
void HashTableFree(HashTable *ht)
Definition: util-hash.c:79
DetectEngineCtx_::app_mpms_list
DetectBufferMpmRegistery * app_mpms_list
Definition: detect.h:929
TenantLoaderCtx_
Definition: detect-engine.c:3286
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:860
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:83
DetectBufferTypeSupportsPacket
void DetectBufferTypeSupportsPacket(const char *name)
Definition: detect-engine.c:830
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:116
DetectEngineThreadCtx_::mtcs
MpmThreadCtx mtcs
Definition: detect.h:1102
HashTable_::array_size
uint32_t array_size
Definition: util-hash.h:37
SigGroupHeadHashInit
int SigGroupHeadHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table in the detection engine context to hold the SigGroupHeads.
Definition: detect-engine-siggroup.c:256
SCRConfDeInitContext
void SCRConfDeInitContext(DetectEngineCtx *de_ctx)
Releases de_ctx resources related to Reference Config API.
Definition: util-reference-config.c:190
InspectionBufferMultipleForList::size
uint32_t size
Definition: detect.h:364
DetectEngineCtx_::udp_whitelist
DetectPort * udp_whitelist
Definition: detect.h:910
DetectEngineThreadCtx_::mt_det_ctxs_hash
HashTable * mt_det_ctxs_hash
Definition: detect.h:1020
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
DetectBufferType_::string
const char * string
Definition: detect.h:425
DetectEnginePktInspectionRun
bool DetectEnginePktInspectionRun(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p, uint8_t *alert_flags)
Definition: detect-engine.c:1394
DETECT_PREFILTER_AUTO
@ DETECT_PREFILTER_AUTO
Definition: detect.h:743
DetectEngineThreadCtx_::keyword_ctxs_size
int keyword_ctxs_size
Definition: detect.h:1131
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
DetectAppLayerMpmRegisterByParentId
void DetectAppLayerMpmRegisterByParentId(DetectEngineCtx *de_ctx, const int id, const int parent_id, DetectEngineTransforms *transforms)
copy a mpm engine from parent_id, add in transforms
Definition: detect-engine-mpm.c:144
SigString_::sig_error
char * sig_error
Definition: detect.h:717
TmThreadContinueDetectLoaderThreads
void TmThreadContinueDetectLoaderThreads()
Unpauses all threads present in tv_root.
Definition: detect-engine-loader.c:520
DetectEngineAppInspectionEngine_::id
uint8_t id
Definition: detect.h:398
PacketQueue_::mutex_q
SCMutex mutex_q
Definition: packet-queue.h:54
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:46
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1118
util-signal.h
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:401
SC_ERR_SIZE_PARSE
@ SC_ERR_SIZE_PARSE
Definition: util-error.h:230
TENANT_SELECTOR_UNKNOWN
@ TENANT_SELECTOR_UNKNOWN
Definition: detect.h:1402
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
InspectionBufferInit
void InspectionBufferInit(InspectionBuffer *buffer, uint32_t initial_size)
Definition: detect-engine.c:1090
DetectEngineMultiTenantEnabled
int DetectEngineMultiTenantEnabled(void)
Definition: detect-engine.c:3156
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:58
DetectEngineTenantMapping_::tenant_id
uint32_t tenant_id
Definition: detect.h:1409
InspectionBufferMultipleForList
Definition: detect.h:362
ThreadVars_::tmm_flags
uint8_t tmm_flags
Definition: threadvars.h:78
MPM_AC_KS
@ MPM_AC_KS
Definition: util-mpm.h:37
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:98
FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR
@ FILE_DECODER_EVENT_LZMA_MEMLIMIT_ERROR
Definition: detect.h:1221
ConfNodeRemove
void ConfNodeRemove(ConfNode *node)
Remove (and SCFree) the provided configuration node.
Definition: conf.c:668
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
app-layer-htp.h
DetectEngineTenantSelectors
DetectEngineTenantSelectors
Definition: detect.h:1400
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1231
InspectionBufferPktInspectFunc
int(* InspectionBufferPktInspectFunc)(struct DetectEngineThreadCtx_ *, const struct DetectEnginePktInspectionEngine *engine, const struct Signature_ *s, Packet *p, uint8_t *alert_flags)
Definition: detect.h:442
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:35
FILE_DECODER_EVENT_Z_STREAM_ERROR
@ FILE_DECODER_EVENT_Z_STREAM_ERROR
Definition: detect.h:1217
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
util-device.h
util-debug.h
DetectBufferTypeRegisterValidateCallback
void DetectBufferTypeRegisterValidateCallback(const char *name, bool(*ValidateCallback)(const Signature *, const char **sigerror))
Definition: detect-engine.c:952
DetectEngineMoveToFreeList
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:3865
type
uint8_t type
Definition: decode-icmpv4.h:2
VarNameStoreFree
void VarNameStoreFree(uint32_t de_ctx_version)
Definition: util-var-name.c:364
SC_ERR_CONF_YAML_ERROR
@ SC_ERR_CONF_YAML_ERROR
Definition: util-error.h:274
util-error.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:16
SCProfilingPrefilterDestroyCtx
void SCProfilingPrefilterDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-prefilter.c:223
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:457
DetectEngineThreadCtx_::match_array_len
uint32_t match_array_len
Definition: detect.h:1087
TmModule_::PktAcqBreakLoop
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
DET_CTX_EVENT_TEST
@ DET_CTX_EVENT_TEST
Definition: detect.h:1211
DetectEngineInspectPacketPayload
int DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p)
Do the content inspection & validation for a signature.
Definition: detect-engine-payload.c:150
DetectMpmInitializePktMpms
void DetectMpmInitializePktMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:374
DetectEngineThreadCtx_
Definition: detect.h:1004
PKT_STREAM_ADD
#define PKT_STREAM_ADD
Definition: decode.h:1074
MPM_HS
@ MPM_HS
Definition: util-mpm.h:38
det_ctx_event_table
SCEnumCharMap det_ctx_event_table[]
Definition: detect-engine.c:104
DetectLoadersInit
void DetectLoadersInit(void)
Definition: detect-engine-loader.c:469
ThreadVars_::tm_slots
struct TmSlot_ * tm_slots
Definition: threadvars.h:95
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:493
InspectEngineFuncPtr
int(* InspectEngineFuncPtr)(ThreadVars *tv, struct DetectEngineCtx_ *de_ctx, struct DetectEngineThreadCtx_ *det_ctx, const struct Signature_ *sig, const SigMatchData *smd, Flow *f, uint8_t flags, void *alstate, void *tx, uint64_t tx_id)
Definition: detect.h:381
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
DETECT_SM_LIST_BASE64_DATA
@ DETECT_SM_LIST_BASE64_DATA
Definition: detect.h:95
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:228
DetectEngineThreadKeywordCtxItem_::id
int id
Definition: detect.h:736
PKT_PSEUDO_STREAM_END
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1078
DetectEngineAppInspectionEngineSignatureFree
void DetectEngineAppInspectionEngineSignatureFree(Signature *s)
free app inspect engines for a signature
Definition: detect-engine.c:667
DetectEngineThreadCtx_::buffers
InspectionBuffer * buffers
Definition: detect.h:1052
detect-engine-file.h
DetectEngineMasterCtx_::keyword_list
DetectEngineThreadKeywordCtxItem * keyword_list
Definition: detect.h:1444
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:279
res
PoolThreadReserved res
Definition: stream-tcp-private.h:60
flow-worker.h
DetectEngineMasterCtx_::tenant_selector
enum DetectEngineTenantSelectors tenant_selector
Definition: detect.h:1435
SigLoadSignatures
int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, int sig_file_exclusive)
Load signatures.
Definition: detect-engine-loader.c:276
DetectPktInspectEngineRegister
void DetectPktInspectEngineRegister(const char *name, InspectionBufferGetPktDataPtr GetPktData, InspectionBufferPktInspectFunc Callback)
register inspect engine at start up time
Definition: detect-engine.c:128
InspectionBufferCheckAndExpand
void InspectionBufferCheckAndExpand(InspectionBuffer *buffer, uint32_t min_size)
make sure that the buffer has at least 'min_size' bytes Expand the buffer if necessary
Definition: detect-engine.c:1119
DetectEngineInspectStreamPayload
int DetectEngineInspectStreamPayload(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p)
Do the content inspection & validation for a signature on the raw stream.
Definition: detect-engine-payload.c:263
util-reference-config.h
DetectEngineCtx_::buffer_type_id
int buffer_type_id
Definition: detect.h:924
Packet_::pcap_v
PcapPacketVars pcap_v
Definition: decode.h:481
SignatureInitData_::list
int list
Definition: detect.h:498
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:571
VarNameStoreSetupStaging
int VarNameStoreSetupStaging(uint32_t de_ctx_version)
setup staging store. Include current store if there is one.
Definition: util-var-name.c:247
SCEnter
#define SCEnter(...)
Definition: util-debug.h:337
detect-engine-mpm.h
DetectEngineThreadCtx_::multi_inspect
struct DetectEngineThreadCtx_::@106 multi_inspect
DetectMetadataHashFree
void DetectMetadataHashFree(DetectEngineCtx *de_ctx)
Definition: detect-metadata.c:74
DetectBufferTypeMaxId
int DetectBufferTypeMaxId(void)
Definition: detect-engine.c:735
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCRealloc
#define SCRealloc(x, a)
Definition: util-mem.h:238
DetectEngineEnabled
int DetectEngineEnabled(void)
Check if detection is enabled.
Definition: detect-engine.c:3091
SC_ERR_MT_NO_MAPPING
@ SC_ERR_MT_NO_MAPPING
Definition: util-error.h:304
SigMatchList2DataArray
SigMatchData * SigMatchList2DataArray(SigMatch *head)
convert SigMatch list to SigMatchData array
Definition: detect-parse.c:1596
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:2726
DetectEngineReloadIsIdle
int DetectEngineReloadIsIdle(void)
Definition: detect-engine.c:1509
DetectEngineAppInspectionEngine_::mpm
uint16_t mpm
Definition: detect.h:399
DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_MATCH
Definition: detect-engine-state.h:39
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1106
TVT_PPT
@ TVT_PPT
Definition: tm-threads-common.h:85
SigMatchData_::type
uint8_t type
Definition: detect.h:328
detect-engine-port.h
LiveDevice_::tenant_id
uint32_t tenant_id
Definition: util-device.h:54
InspectionBuffer::inspect_offset
uint64_t inspect_offset
Definition: detect.h:344
ENGINE_PROFILE_LOW
@ ENGINE_PROFILE_LOW
Definition: detect.h:955
AppLayerParserSupportsTxDetectFlags
bool AppLayerParserSupportsTxDetectFlags(AppProto alproto)
Definition: app-layer-parser.c:1146
DetectEngineMasterCtx_::free_list
DetectEngineCtx * free_list
Definition: detect.h:1433
DetectEngineSyncState
DetectEngineSyncState
Definition: detect-engine.c:1461
LiveDevice_::dev
char * dev
Definition: util-device.h:41
PatternMatchThreadPrepare
void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:678
ConfYamlLoadString
int ConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:451
DetectEngineThreadKeywordCtxItem_::next
struct DetectEngineThreadKeywordCtxItem_ * next
Definition: detect.h:735
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:113
DetectPort_
Port structure for detection engine.
Definition: detect.h:191
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
InspectionBuffer::buf
uint8_t * buf
Definition: detect.h:349
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:570
TRUE
#define TRUE
Definition: suricata-common.h:33
DetectBufferType_::ValidateCallback
bool(* ValidateCallback)(const struct Signature_ *, const char **sigerror)
Definition: detect.h:433
SCMalloc
#define SCMalloc(a)
Definition: util-mem.h:222
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:122
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:265
hashlittle_safe
uint32_t hashlittle_safe(const void *key, size_t length, uint32_t initval)
Definition: util-hash-lookup3.c:484
SignatureInitData_::transform_cnt
int transform_cnt
Definition: detect.h:502
DetectEngineThreadCtx_::base64_decoded_len
int base64_decoded_len
Definition: detect.h:1137
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1947
detect-engine-tag.h
Signature_::action
uint8_t action
Definition: detect.h:535
util-profiling.h
DetectEngineThreadCtxInfo
void DetectEngineThreadCtxInfo(ThreadVars *t, DetectEngineThreadCtx *det_ctx)
Definition: detect-engine.c:2952
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:81
DetectEngineCtx_::profile_ctx
struct SCProfileDetectCtx_ * profile_ctx
Definition: detect.h:883
FALSE
#define FALSE
Definition: suricata-common.h:34
DetectEngineLoadTenantBlocking
int DetectEngineLoadTenantBlocking(uint32_t tenant_id, const char *yaml)
Load a tenant and wait for loading to complete.
Definition: detect-engine.c:3350
FILE_DECODER_EVENT_Z_DATA_ERROR
@ FILE_DECODER_EVENT_Z_DATA_ERROR
Definition: detect.h:1216
TmModuleDetectLoaderRegister
void TmModuleDetectLoaderRegister(void)
Definition: detect-engine-loader.c:640
Signature_::flags
uint32_t flags
Definition: detect.h:523
PACKET_ALERT_FLAG_DROP_FLOW
#define PACKET_ALERT_FLAG_DROP_FLOW
Definition: decode.h:281
FILE_DECODER_EVENT_Z_BUF_ERROR
@ FILE_DECODER_EVENT_Z_BUF_ERROR
Definition: detect.h:1218
DetectEngineInspectBufferGeneric
int DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Definition: detect-engine.c:1578
SC_ERR_FOPEN
@ SC_ERR_FOPEN
Definition: util-error.h:74
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:1985
FILE_DECODER_EVENT_LZMA_BUF_ERROR
@ FILE_DECODER_EVENT_LZMA_BUF_ERROR
Definition: detect.h:1225
RuleMatchCandidateTxArrayFree
void RuleMatchCandidateTxArrayFree(DetectEngineThreadCtx *det_ctx)
Definition: detect.c:974
Packet_
Definition: decode.h:408
DE_STATE_FLAG_BASE
#define DE_STATE_FLAG_BASE
Definition: detect-engine-state.h:64
PatternMatchThreadPrint
void PatternMatchThreadPrint(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:667
SCCalloc
#define SCCalloc(nm, a)
Definition: util-mem.h:253
conf-yaml-loader.h
SCRConfLoadReferenceConfigFile
int SCRConfLoadReferenceConfigFile(DetectEngineCtx *de_ctx, FILE *fd)
Loads the Reference info from the reference.config file.
Definition: util-reference-config.c:493
THV_CAPTURE_INJECT_PKT
#define THV_CAPTURE_INJECT_PKT
Definition: threadvars.h:53
PcapPacketVars_::tenant_id
uint32_t tenant_id
Definition: source-pcap.h:37
DETECT_CI_FLAGS_END
#define DETECT_CI_FLAGS_END
Definition: detect-engine-content-inspection.h:39
DetectAppLayerInspectEngineRegister2
void DetectAppLayerInspectEngineRegister2(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr2 Callback2, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
Definition: detect-engine.c:231
SCProfilingRuleThreadCleanup
void SCProfilingRuleThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rules.c:631
FILE_DECODER_EVENT_LZMA_DECODER_ERROR
@ FILE_DECODER_EVENT_LZMA_DECODER_ERROR
Definition: detect.h:1220
conf.h
DetectBufferType_::packet
bool packet
Definition: detect.h:430
SinglePatternMatchDefaultMatcher
uint16_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition: util-spm.c:68
DetectEngineMasterCtx_::multi_tenant_enabled
int multi_tenant_enabled
Definition: detect.h:1421
TmModuleGetById
TmModule * TmModuleGetById(int id)
Returns a TM Module by its id.
Definition: tm-modules.c:90
TmSlot_
Definition: tm-threads.h:52
DetectEnginePktInspectionEngine::v1
struct DetectEnginePktInspectionEngine::@95 v1
TenantLoaderCtx
struct TenantLoaderCtx_ TenantLoaderCtx
util-magic.h
DetectEngineCtx_::max_uniq_toserver_groups
uint16_t max_uniq_toserver_groups
Definition: detect.h:820
Packet_::livedev
struct LiveDevice_ * livedev
Definition: decode.h:554
ENGINE_PROFILE_UNKNOWN
@ ENGINE_PROFILE_UNKNOWN
Definition: detect.h:954
TmEcode
TmEcode
Definition: tm-threads-common.h:77
DetectEnginePktInspectionEngine::Callback
InspectionBufferPktInspectFunc Callback
Definition: detect.h:460
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:591
DetectEngineSyncer_::state
enum DetectEngineSyncState state
Definition: detect-engine.c:1469
SpmMakeThreadCtx
SpmThreadCtx * SpmMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:148
DetectEngineCtx_::profile_keyword_ctx
struct SCProfileKeywordDetectCtx_ * profile_keyword_ctx
Definition: detect.h:884
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1171
reputation.h
ConfCreateContextBackup
void ConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:699
SCProfilingPrefilterThreadCleanup
void SCProfilingPrefilterThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-prefilter.c:261
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:516
util-action.h
HashListTable_
Definition: util-hashlist.h:37
DetectEngineTentantRegisterVlanId
int DetectEngineTentantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
Definition: detect-engine.c:3772
DetectEngineCtx_::byte_extract_max_local_id
int32_t byte_extract_max_local_id
Definition: detect.h:852
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:264
PacketQueue_::cond_q
SCCondT cond_q
Definition: packet-queue.h:55
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:356
SC_ERR_INVALID_YAML_CONF_ENTRY
@ SC_ERR_INVALID_YAML_CONF_ENTRY
Definition: util-error.h:169
ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL
Definition: detect.h:964
SpmDestroyGlobalThreadCtx
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:139
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
Definition: dete