suricata
detect-engine.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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 "detect.h"
27 #include "flow.h"
28 #include "flow-private.h"
29 #include "flow-util.h"
30 #include "flow-worker.h"
31 #include "conf.h"
32 #include "conf-yaml-loader.h"
33 #include "datasets.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-build.h"
42 #include "detect-engine-siggroup.h"
43 #include "detect-engine-address.h"
44 #include "detect-engine-port.h"
46 #include "detect-engine-mpm.h"
47 #include "detect-engine-iponly.h"
48 #include "detect-engine-tag.h"
49 #include "detect-engine-frame.h"
50 
51 #include "detect-engine-file.h"
52 
53 #include "detect-engine.h"
54 #include "detect-engine-state.h"
55 #include "detect-engine-payload.h"
56 #include "detect-fast-pattern.h"
57 #include "detect-byte-extract.h"
58 #include "detect-content.h"
59 #include "detect-uricontent.h"
60 #include "detect-tcphdr.h"
63 
64 #include "detect-engine-loader.h"
65 
67 #include "util-reference-config.h"
68 #include "util-threshold-config.h"
69 #include "util-error.h"
70 #include "util-hash.h"
71 #include "util-byte.h"
72 #include "util-debug.h"
73 #include "util-unittest.h"
74 #include "util-action.h"
75 #include "util-magic.h"
76 #include "util-signal.h"
77 #include "util-spm.h"
78 #include "util-device.h"
79 #include "util-var-name.h"
80 #include "util-path.h"
81 #include "util-profiling.h"
82 #include "util-validate.h"
83 #include "util-hash-string.h"
84 #include "util-enum.h"
85 #include "util-conf.h"
86 
87 #include "tm-threads.h"
88 #include "runmodes.h"
89 
90 #include "reputation.h"
91 
92 #define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000
93 
94 static int DetectEngineCtxLoadConf(DetectEngineCtx *);
95 
96 static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER,
97  0, 99, NULL, NULL, TENANT_SELECTOR_UNKNOWN, NULL, NULL, 0};
98 
99 static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len);
100 static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len);
101 static void TenantIdFree(void *d);
102 static uint32_t DetectEngineTenantGetIdFromLivedev(const void *ctx, const Packet *p);
103 static uint32_t DetectEngineTenantGetIdFromVlanId(const void *ctx, const Packet *p);
104 static uint32_t DetectEngineTenantGetIdFromPcap(const void *ctx, const Packet *p);
105 
106 static DetectEngineAppInspectionEngine *g_app_inspect_engines = NULL;
107 static DetectEnginePktInspectionEngine *g_pkt_inspect_engines = NULL;
108 static DetectEngineFrameInspectionEngine *g_frame_inspect_engines = NULL;
109 
110 // clang-format off
112  /* SIG_TYPE_NOT_SET */ { SIG_PROP_FLOW_ACTION_PACKET, },
113  /* SIG_TYPE_IPONLY */ { SIG_PROP_FLOW_ACTION_FLOW, },
114  /* SIG_TYPE_LIKE_IPONLY */ { SIG_PROP_FLOW_ACTION_FLOW, },
115  /* SIG_TYPE_PDONLY */ { SIG_PROP_FLOW_ACTION_FLOW, },
116  /* SIG_TYPE_DEONLY */ { SIG_PROP_FLOW_ACTION_PACKET, },
117  /* SIG_TYPE_PKT */ { SIG_PROP_FLOW_ACTION_PACKET, },
118  /* SIG_TYPE_PKT_STREAM */ { SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL, },
119  /* SIG_TYPE_STREAM */ { SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL, },
120  /* SIG_TYPE_APPLAYER */ { SIG_PROP_FLOW_ACTION_FLOW, },
121  /* SIG_TYPE_APP_TX */ { SIG_PROP_FLOW_ACTION_FLOW, },
122 };
123 // clang-format on
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) {
135  FatalError("failed to register inspect engine %s", name);
136  }
137 
138  if ((sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) ||
139  (Callback == NULL))
140  {
141  SCLogError("Invalid arguments");
142  BUG_ON(1);
143  }
144 
145  DetectEnginePktInspectionEngine *new_engine = SCCalloc(1, sizeof(*new_engine));
146  if (unlikely(new_engine == NULL)) {
147  FatalError("failed to register inspect engine %s: %s", name, strerror(errno));
148  }
149  new_engine->sm_list = (uint16_t)sm_list;
150  new_engine->sm_list_base = (uint16_t)sm_list;
151  new_engine->v1.Callback = Callback;
152  new_engine->v1.GetData = GetPktData;
153 
154  if (g_pkt_inspect_engines == NULL) {
155  g_pkt_inspect_engines = new_engine;
156  } else {
157  DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
158  while (t->next != NULL) {
159  t = t->next;
160  }
161 
162  t->next = new_engine;
163  }
164 }
165 
166 /** \brief register inspect engine at start up time
167  *
168  * \note errors are fatal */
169 static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alproto, uint32_t dir,
170  int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData,
171  InspectionMultiBufferGetDataPtr GetMultiData)
172 {
173  BUG_ON(progress >= 48);
174 
176  const int sm_list = DetectBufferTypeGetByName(name);
177  if (sm_list == -1) {
178  FatalError("failed to register inspect engine %s", name);
179  }
180  SCLogDebug("name %s id %d", name, sm_list);
181 
182  if ((alproto >= ALPROTO_FAILED) || (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) ||
183  (sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) ||
184  (progress < 0 || progress >= SHRT_MAX) || (Callback == NULL)) {
185  SCLogError("Invalid arguments");
186  BUG_ON(1);
187  } else if (Callback == DetectEngineInspectBufferGeneric && GetData == NULL) {
188  SCLogError("Invalid arguments: must register "
189  "GetData with DetectEngineInspectBufferGeneric");
190  BUG_ON(1);
191  } else if (Callback == DetectEngineInspectMultiBufferGeneric && GetMultiData == NULL) {
192  SCLogError("Invalid arguments: must register "
193  "GetData with DetectEngineInspectMultiBufferGeneric");
194  BUG_ON(1);
195  }
196 
197  uint8_t direction;
198  if (dir == SIG_FLAG_TOSERVER) {
199  direction = 0;
200  } else {
201  direction = 1;
202  }
203  // every DNS or HTTP2 can be accessed from DOH2
204  if (alproto == ALPROTO_HTTP2 || alproto == ALPROTO_DNS) {
205  AppLayerInspectEngineRegisterInternal(
206  name, ALPROTO_DOH2, dir, progress, Callback, GetData, GetMultiData);
207  }
208 
209  DetectEngineAppInspectionEngine *new_engine =
211  if (unlikely(new_engine == NULL)) {
212  exit(EXIT_FAILURE);
213  }
214  new_engine->alproto = alproto;
215  new_engine->dir = direction;
216  new_engine->sm_list = (uint16_t)sm_list;
217  new_engine->sm_list_base = (uint16_t)sm_list;
218  new_engine->progress = (int16_t)progress;
219  new_engine->v2.Callback = Callback;
220  if (Callback == DetectEngineInspectBufferGeneric) {
221  new_engine->v2.GetData = GetData;
222  } else if (Callback == DetectEngineInspectMultiBufferGeneric) {
223  new_engine->v2.GetMultiData = GetMultiData;
224  }
225 
226  if (g_app_inspect_engines == NULL) {
227  g_app_inspect_engines = new_engine;
228  } else {
229  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
230  while (t->next != NULL) {
231  t = t->next;
232  }
233 
234  t->next = new_engine;
235  }
236 }
237 
238 void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir,
239  int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
240 {
241  AppLayerInspectEngineRegisterInternal(name, alproto, dir, progress, Callback, GetData, NULL);
242 }
243 
244 /* copy an inspect engine with transforms to a new list id. */
245 static void DetectAppLayerInspectEngineCopy(
247  int sm_list, int new_list,
248  const DetectEngineTransforms *transforms)
249 {
250  const DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
251  while (t) {
252  if (t->sm_list == sm_list) {
254  if (unlikely(new_engine == NULL)) {
255  exit(EXIT_FAILURE);
256  }
257  new_engine->alproto = t->alproto;
258  new_engine->dir = t->dir;
259  DEBUG_VALIDATE_BUG_ON(new_list < 0 || new_list > UINT16_MAX);
260  new_engine->sm_list = (uint16_t)new_list; /* use new list id */
261  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
262  new_engine->sm_list_base = (uint16_t)sm_list;
263  new_engine->progress = t->progress;
264  new_engine->v2 = t->v2;
265  new_engine->v2.transforms = transforms; /* assign transforms */
266 
267  if (de_ctx->app_inspect_engines == NULL) {
268  de_ctx->app_inspect_engines = new_engine;
269  } else {
271  while (list->next != NULL) {
272  list = list->next;
273  }
274 
275  list->next = new_engine;
276  }
277  }
278  t = t->next;
279  }
280 }
281 
282 /* copy inspect engines from global registrations to de_ctx list */
283 static void DetectAppLayerInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
284 {
285  const DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
287  while (t) {
289  if (unlikely(new_engine == NULL)) {
290  exit(EXIT_FAILURE);
291  }
292  new_engine->alproto = t->alproto;
293  new_engine->dir = t->dir;
294  new_engine->sm_list = t->sm_list;
295  new_engine->sm_list_base = t->sm_list;
296  new_engine->progress = t->progress;
297  new_engine->v2 = t->v2;
298 
299  if (list == NULL) {
300  de_ctx->app_inspect_engines = new_engine;
301  } else {
302  list->next = new_engine;
303  }
304  list = new_engine;
305 
306  t = t->next;
307  }
308 }
309 
310 /* copy an inspect engine with transforms to a new list id. */
311 static void DetectPktInspectEngineCopy(
313  int sm_list, int new_list,
314  const DetectEngineTransforms *transforms)
315 {
316  const DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
317  while (t) {
318  if (t->sm_list == sm_list) {
320  if (unlikely(new_engine == NULL)) {
321  exit(EXIT_FAILURE);
322  }
323  DEBUG_VALIDATE_BUG_ON(new_list < 0 || new_list > UINT16_MAX);
324  new_engine->sm_list = (uint16_t)new_list; /* use new list id */
325  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
326  new_engine->sm_list_base = (uint16_t)sm_list;
327  new_engine->v1 = t->v1;
328  new_engine->v1.transforms = transforms; /* assign transforms */
329 
330  if (de_ctx->pkt_inspect_engines == NULL) {
331  de_ctx->pkt_inspect_engines = new_engine;
332  } else {
334  while (list->next != NULL) {
335  list = list->next;
336  }
337 
338  list->next = new_engine;
339  }
340  }
341  t = t->next;
342  }
343 }
344 
345 /* copy inspect engines from global registrations to de_ctx list */
346 static void DetectPktInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
347 {
348  const DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
349  while (t) {
350  SCLogDebug("engine %p", t);
352  if (unlikely(new_engine == NULL)) {
353  exit(EXIT_FAILURE);
354  }
355  new_engine->sm_list = t->sm_list;
356  new_engine->sm_list_base = t->sm_list;
357  new_engine->v1 = t->v1;
358 
359  if (de_ctx->pkt_inspect_engines == NULL) {
360  de_ctx->pkt_inspect_engines = new_engine;
361  } else {
363  while (list->next != NULL) {
364  list = list->next;
365  }
366 
367  list->next = new_engine;
368  }
369 
370  t = t->next;
371  }
372 }
373 
374 /** \brief register inspect engine at start up time
375  *
376  * \note errors are fatal */
378  InspectionBufferFrameInspectFunc Callback, AppProto alproto, uint8_t type)
379 {
380  const int sm_list = DetectEngineBufferTypeRegister(de_ctx, name);
381  if (sm_list < 0) {
382  FatalError("failed to register inspect engine %s", name);
383  }
384 
385  if ((sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) || (Callback == NULL)) {
386  SCLogError("Invalid arguments");
387  BUG_ON(1);
388  }
389 
390  uint8_t direction;
391  if (dir == SIG_FLAG_TOSERVER) {
392  direction = 0;
393  } else {
394  direction = 1;
395  }
396 
397  DetectEngineFrameInspectionEngine *new_engine = SCCalloc(1, sizeof(*new_engine));
398  if (unlikely(new_engine == NULL)) {
399  FatalError("failed to register inspect engine %s: %s", name, strerror(errno));
400  }
401  new_engine->sm_list = (uint16_t)sm_list;
402  new_engine->sm_list_base = (uint16_t)sm_list;
403  new_engine->dir = direction;
404  new_engine->v1.Callback = Callback;
405  new_engine->alproto = alproto;
406  new_engine->type = type;
407 
408  if (de_ctx->frame_inspect_engines == NULL) {
409  de_ctx->frame_inspect_engines = new_engine;
410  } else {
412  while (list->next != NULL) {
413  list = list->next;
414  }
415 
416  list->next = new_engine;
417  }
418 }
419 
420 /* copy an inspect engine with transforms to a new list id. */
421 static void DetectFrameInspectEngineCopy(DetectEngineCtx *de_ctx, int sm_list, int new_list,
422  const DetectEngineTransforms *transforms)
423 {
424  /* take the list from the detect engine as the buffers can be registered
425  * dynamically. */
427  while (t) {
428  if (t->sm_list == sm_list) {
431  if (unlikely(new_engine == NULL)) {
432  exit(EXIT_FAILURE);
433  }
434  DEBUG_VALIDATE_BUG_ON(new_list < 0 || new_list > UINT16_MAX);
435  new_engine->sm_list = (uint16_t)new_list; /* use new list id */
436  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
437  new_engine->sm_list_base = (uint16_t)sm_list;
438  new_engine->dir = t->dir;
439  new_engine->alproto = t->alproto;
440  new_engine->type = t->type;
441  new_engine->v1 = t->v1;
442  new_engine->v1.transforms = transforms; /* assign transforms */
443 
444  /* append to the list */
446  while (list->next != NULL) {
447  list = list->next;
448  }
449 
450  list->next = new_engine;
451  }
452  t = t->next;
453  }
454 }
455 
456 /* copy inspect engines from global registrations to de_ctx list */
457 static void DetectFrameInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
458 {
459  const DetectEngineFrameInspectionEngine *t = g_frame_inspect_engines;
460  while (t) {
461  SCLogDebug("engine %p", t);
464  if (unlikely(new_engine == NULL)) {
465  exit(EXIT_FAILURE);
466  }
467  new_engine->sm_list = t->sm_list;
468  new_engine->sm_list_base = t->sm_list;
469  new_engine->dir = t->dir;
470  new_engine->alproto = t->alproto;
471  new_engine->type = t->type;
472  new_engine->v1 = t->v1;
473 
474  if (de_ctx->frame_inspect_engines == NULL) {
475  de_ctx->frame_inspect_engines = new_engine;
476  } else {
478  while (list->next != NULL) {
479  list = list->next;
480  }
481 
482  list->next = new_engine;
483  }
484 
485  t = t->next;
486  }
487 }
488 
489 /** \internal
490  * \brief append the stream inspection
491  *
492  * If stream inspection is MPM, then prepend it.
493  */
494 static void AppendStreamInspectEngine(
495  Signature *s, SigMatchData *stream, uint8_t direction, uint8_t id)
496 {
497  bool prepend = false;
498 
500  if (unlikely(new_engine == NULL)) {
501  exit(EXIT_FAILURE);
502  }
504  SCLogDebug("stream is mpm");
505  prepend = true;
506  new_engine->mpm = true;
507  }
508  new_engine->alproto = ALPROTO_UNKNOWN; /* all */
509  new_engine->dir = direction;
510  new_engine->stream = true;
511  new_engine->sm_list = DETECT_SM_LIST_PMATCH;
512  new_engine->sm_list_base = DETECT_SM_LIST_PMATCH;
513  new_engine->smd = stream;
514  new_engine->v2.Callback = DetectEngineInspectStream;
515  new_engine->progress = 0;
516 
517  /* append */
518  if (s->app_inspect == NULL) {
519  s->app_inspect = new_engine;
520  new_engine->id = DE_STATE_FLAG_BASE; /* id is used as flag in stateful detect */
521  } else if (prepend) {
522  new_engine->next = s->app_inspect;
523  s->app_inspect = new_engine;
524  new_engine->id = id;
525 
526  } else {
528  while (a->next != NULL) {
529  a = a->next;
530  }
531 
532  a->next = new_engine;
533  new_engine->id = id;
534  }
535  SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
536 }
537 
538 static void AppendFrameInspectEngine(DetectEngineCtx *de_ctx,
540  const int mpm_list)
541 {
542  bool prepend = false;
543 
544  if (u->alproto == ALPROTO_UNKNOWN) {
545  /* special case, inspect engine applies to all protocols */
546  } else if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, u->alproto))
547  return;
548 
549  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
550  if (u->dir == 1)
551  return;
552  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
553  if (u->dir == 0)
554  return;
555  }
556 
559  if (unlikely(new_engine == NULL)) {
560  exit(EXIT_FAILURE);
561  }
562  if (mpm_list == u->sm_list) {
564  prepend = true;
565  new_engine->mpm = true;
566  }
567 
568  new_engine->type = u->type;
569  new_engine->sm_list = u->sm_list;
570  new_engine->sm_list_base = u->sm_list_base;
571  new_engine->smd = smd;
572  new_engine->v1 = u->v1;
573  SCLogDebug("sm_list %d new_engine->v1 %p/%p", new_engine->sm_list, new_engine->v1.Callback,
574  new_engine->v1.transforms);
575 
576  if (s->frame_inspect == NULL) {
577  s->frame_inspect = new_engine;
578  } else if (prepend) {
579  new_engine->next = s->frame_inspect;
580  s->frame_inspect = new_engine;
581  } else {
583  while (a->next != NULL) {
584  a = a->next;
585  }
586  new_engine->next = a->next;
587  a->next = new_engine;
588  }
589 }
590 
591 static void AppendPacketInspectEngine(DetectEngineCtx *de_ctx,
593  const int mpm_list)
594 {
595  bool prepend = false;
596 
597  DetectEnginePktInspectionEngine *new_engine =
599  if (unlikely(new_engine == NULL)) {
600  exit(EXIT_FAILURE);
601  }
602  if (mpm_list == e->sm_list) {
604  prepend = true;
605  new_engine->mpm = true;
606  }
607 
608  new_engine->sm_list = e->sm_list;
609  new_engine->sm_list_base = e->sm_list_base;
610  new_engine->smd = smd;
611  new_engine->v1 = e->v1;
612  SCLogDebug("sm_list %d new_engine->v1 %p/%p/%p", new_engine->sm_list, new_engine->v1.Callback,
613  new_engine->v1.GetData, new_engine->v1.transforms);
614 
615  if (s->pkt_inspect == NULL) {
616  s->pkt_inspect = new_engine;
617  } else if (prepend) {
618  new_engine->next = s->pkt_inspect;
619  s->pkt_inspect = new_engine;
620  } else {
622  while (a->next != NULL) {
623  a = a->next;
624  }
625  new_engine->next = a->next;
626  a->next = new_engine;
627  }
628 }
629 
630 static void AppendAppInspectEngine(DetectEngineCtx *de_ctx,
632  const int mpm_list, const int files_id, uint8_t *last_id, bool *head_is_mpm)
633 {
634  if (t->alproto == ALPROTO_UNKNOWN) {
635  /* special case, inspect engine applies to all protocols */
636  } else if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, t->alproto))
637  return;
638 
639  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
640  if (t->dir == 1)
641  return;
642  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
643  if (t->dir == 0)
644  return;
645  }
646  SCLogDebug("app engine: t %p t->id %u => alproto:%s files:%s", t, t->id,
647  AppProtoToString(t->alproto), BOOL2STR(t->sm_list == files_id));
648 
649  DetectEngineAppInspectionEngine *new_engine =
651  if (unlikely(new_engine == NULL)) {
652  exit(EXIT_FAILURE);
653  }
654  bool prepend = false;
655  if (mpm_list == t->sm_list) {
657  prepend = true;
658  *head_is_mpm = true;
659  new_engine->mpm = true;
660  }
661 
662  new_engine->alproto = t->alproto;
663  new_engine->dir = t->dir;
664  new_engine->sm_list = t->sm_list;
665  new_engine->sm_list_base = t->sm_list_base;
666  new_engine->smd = smd;
667  new_engine->progress = t->progress;
668  new_engine->v2 = t->v2;
669  SCLogDebug("sm_list %d new_engine->v2 %p/%p/%p", new_engine->sm_list, new_engine->v2.Callback,
670  new_engine->v2.GetData, new_engine->v2.transforms);
671 
672  if (s->app_inspect == NULL) {
673  s->app_inspect = new_engine;
674  if (new_engine->sm_list == files_id) {
675  new_engine->id = DE_STATE_ID_FILE_INSPECT;
676  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
677  } else {
678  new_engine->id = DE_STATE_FLAG_BASE; /* id is used as flag in stateful detect */
679  SCLogDebug("sid %u: engine %p/%u %s", s->id, new_engine, new_engine->id,
681  }
682 
683  /* prepend engine if forced or if our engine has a lower progress. */
684  } else if (prepend || (!(*head_is_mpm) && s->app_inspect->progress > new_engine->progress)) {
685  new_engine->next = s->app_inspect;
686  s->app_inspect = new_engine;
687  if (new_engine->sm_list == files_id) {
688  new_engine->id = DE_STATE_ID_FILE_INSPECT;
689  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
690  } else {
691  new_engine->id = ++(*last_id);
692  SCLogDebug("sid %u: engine %p/%u %s", s->id, new_engine, new_engine->id,
694  }
695 
696  } else {
698  while (a->next != NULL) {
699  if (a->next && a->next->progress > new_engine->progress) {
700  break;
701  }
702  a = a->next;
703  }
704 
705  new_engine->next = a->next;
706  a->next = new_engine;
707  if (new_engine->sm_list == files_id) {
708  new_engine->id = DE_STATE_ID_FILE_INSPECT;
709  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
710  } else {
711  new_engine->id = ++(*last_id);
712  SCLogDebug("sid %u: engine %p/%u %s", s->id, new_engine, new_engine->id,
714  }
715  }
716 
717  SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
718 
720 }
721 
722 /**
723  * \note for the file inspect engine, the id DE_STATE_ID_FILE_INSPECT
724  * is assigned.
725  */
727 {
728  const int mpm_list = s->init_data->mpm_sm ? s->init_data->mpm_sm_list : -1;
729  const int files_id = DetectBufferTypeGetByName("files");
730  bool head_is_mpm = false;
731  uint8_t last_id = DE_STATE_FLAG_BASE;
732 
733  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
735  SCLogDebug("smd %p, id %u", smd, s->init_data->buffers[x].id);
736 
737  const DetectBufferType *b =
739  if (b == NULL)
740  FatalError("unknown buffer");
741 
742  if (b->frame) {
744  u != NULL; u = u->next) {
745  if (u->sm_list == s->init_data->buffers[x].id) {
746  AppendFrameInspectEngine(de_ctx, u, s, smd, mpm_list);
747  }
748  }
749  } else if (b->packet) {
750  /* set up pkt inspect engines */
751  for (const DetectEnginePktInspectionEngine *e = de_ctx->pkt_inspect_engines; e != NULL;
752  e = e->next) {
753  SCLogDebug("e %p sm_list %u", e, e->sm_list);
754  if (e->sm_list == s->init_data->buffers[x].id) {
755  AppendPacketInspectEngine(de_ctx, e, s, smd, mpm_list);
756  }
757  }
758  } else {
759  SCLogDebug("app %s id %u parent %u rule %u xforms %u", b->name, b->id, b->parent_id,
760  s->init_data->buffers[x].id, b->transforms.cnt);
761  for (const DetectEngineAppInspectionEngine *t = de_ctx->app_inspect_engines; t != NULL;
762  t = t->next) {
763  if (t->sm_list == s->init_data->buffers[x].id) {
764  AppendAppInspectEngine(
765  de_ctx, t, s, smd, mpm_list, files_id, &last_id, &head_is_mpm);
766  }
767  }
768  }
769  }
770 
773  {
774  /* if engine is added multiple times, we pass it the same list */
776  BUG_ON(stream == NULL);
777  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
778  AppendStreamInspectEngine(s, stream, 0, last_id + 1);
779  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
780  AppendStreamInspectEngine(s, stream, 1, last_id + 1);
781  } else {
782  AppendStreamInspectEngine(s, stream, 0, last_id + 1);
783  AppendStreamInspectEngine(s, stream, 1, last_id + 1);
784  }
785 
787  SCLogDebug("set SIG_FLAG_FLUSH on %u", s->id);
788  s->flags |= SIG_FLAG_FLUSH;
789  }
790  }
791 
792 #ifdef DEBUG
794  while (iter) {
795  SCLogDebug("%u: engine %s id %u progress %d %s", s->id,
797  iter->sm_list == mpm_list ? "MPM" : "");
798  iter = iter->next;
799  }
800 #endif
801  return 0;
802 }
803 
804 /** \brief free app inspect engines for a signature
805  *
806  * For lists that are registered multiple times, like http_header and
807  * http_cookie, making the engines owner of the lists is complicated.
808  * Multiple engines in a sig may be pointing to the same list. To
809  * address this the 'free' code needs to be extra careful about not
810  * double freeing, so it takes an approach to first fill an array
811  * of the to-free pointers before freeing them.
812  */
814 {
815  int engines = 0;
816 
818  while (ie) {
819  ie = ie->next;
820  engines++;
821  }
823  while (e) {
824  e = e->next;
825  engines++;
826  }
828  while (u) {
829  u = u->next;
830  engines++;
831  }
832  if (engines == 0) {
833  BUG_ON(s->pkt_inspect);
834  BUG_ON(s->frame_inspect);
835  return;
836  }
837 
838  SigMatchData *bufs[engines];
839  memset(&bufs, 0, (engines * sizeof(SigMatchData *)));
840  int arrays = 0;
841 
842  /* free engines and put smd in the array */
843  ie = s->app_inspect;
844  while (ie) {
846 
847  bool skip = false;
848  for (int i = 0; i < arrays; i++) {
849  if (bufs[i] == ie->smd) {
850  skip = true;
851  break;
852  }
853  }
854  if (!skip) {
855  bufs[arrays++] = ie->smd;
856  }
857  SCFree(ie);
858  ie = next;
859  }
860  e = s->pkt_inspect;
861  while (e) {
863 
864  bool skip = false;
865  for (int i = 0; i < arrays; i++) {
866  if (bufs[i] == e->smd) {
867  skip = true;
868  break;
869  }
870  }
871  if (!skip) {
872  bufs[arrays++] = e->smd;
873  }
874  SCFree(e);
875  e = next;
876  }
877  u = s->frame_inspect;
878  while (u) {
880 
881  bool skip = false;
882  for (int i = 0; i < arrays; i++) {
883  if (bufs[i] == u->smd) {
884  skip = true;
885  break;
886  }
887  }
888  if (!skip) {
889  bufs[arrays++] = u->smd;
890  }
891  SCFree(u);
892  u = next;
893  }
894 
895  for (int i = 0; i < engines; i++) {
896  if (bufs[i] == NULL)
897  continue;
898  SigMatchData *smd = bufs[i];
899  while (1) {
900  if (sigmatch_table[smd->type].Free != NULL) {
901  sigmatch_table[smd->type].Free(de_ctx, smd->ctx);
902  }
903  if (smd->is_last)
904  break;
905  smd++;
906  }
907  SCFree(bufs[i]);
908  }
909 }
910 
911 /* code for registering buffers */
912 
913 #include "util-hash-lookup3.h"
914 
915 static HashListTable *g_buffer_type_hash = NULL;
916 static int g_buffer_type_id = DETECT_SM_LIST_DYNAMIC_START;
917 static int g_buffer_type_reg_closed = 0;
918 
920 {
921  return g_buffer_type_id;
922 }
923 
924 static uint32_t DetectBufferTypeHashNameFunc(HashListTable *ht, void *data, uint16_t datalen)
925 {
926  const DetectBufferType *map = (DetectBufferType *)data;
927  uint32_t hash = hashlittle_safe(map->name, strlen(map->name), 0);
928  hash += hashlittle_safe((uint8_t *)&map->transforms, sizeof(map->transforms), 0);
929  hash %= ht->array_size;
930  return hash;
931 }
932 
933 static uint32_t DetectBufferTypeHashIdFunc(HashListTable *ht, void *data, uint16_t datalen)
934 {
935  const DetectBufferType *map = (DetectBufferType *)data;
936  uint32_t hash = map->id;
937  hash %= ht->array_size;
938  return hash;
939 }
940 
941 static char DetectBufferTypeCompareNameFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
942 {
943  DetectBufferType *map1 = (DetectBufferType *)data1;
944  DetectBufferType *map2 = (DetectBufferType *)data2;
945 
946  char r = (strcmp(map1->name, map2->name) == 0);
947  r &= (memcmp((uint8_t *)&map1->transforms, (uint8_t *)&map2->transforms, sizeof(map2->transforms)) == 0);
948  return r;
949 }
950 
951 static char DetectBufferTypeCompareIdFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
952 {
953  DetectBufferType *map1 = (DetectBufferType *)data1;
954  DetectBufferType *map2 = (DetectBufferType *)data2;
955  return map1->id == map2->id;
956 }
957 
958 static void DetectBufferTypeFreeFunc(void *data)
959 {
960  DetectBufferType *map = (DetectBufferType *)data;
961 
962  if (map == NULL) {
963  return;
964  }
965 
966  /* Release transformation option memory, if any */
967  for (int i = 0; i < map->transforms.cnt; i++) {
968  if (map->transforms.transforms[i].options == NULL)
969  continue;
970  if (sigmatch_table[map->transforms.transforms[i].transform].Free == NULL) {
971  SCLogError("%s allocates transform option memory but has no free routine",
973  continue;
974  }
976  }
977 
978  SCFree(map);
979 }
980 
981 static int DetectBufferTypeInit(void)
982 {
983  BUG_ON(g_buffer_type_hash);
984  g_buffer_type_hash = HashListTableInit(256, DetectBufferTypeHashNameFunc,
985  DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
986  if (g_buffer_type_hash == NULL)
987  return -1;
988 
989  return 0;
990 }
991 #if 0
992 static void DetectBufferTypeFree(void)
993 {
994  if (g_buffer_type_hash == NULL)
995  return;
996 
997  HashListTableFree(g_buffer_type_hash);
998  g_buffer_type_hash = NULL;
999 }
1000 #endif
1001 static int DetectBufferTypeAdd(const char *string)
1002 {
1003  BUG_ON(string == NULL || strlen(string) >= 32);
1004 
1005  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1006  if (map == NULL)
1007  return -1;
1008 
1009  strlcpy(map->name, string, sizeof(map->name));
1010  map->id = g_buffer_type_id++;
1011 
1012  BUG_ON(HashListTableAdd(g_buffer_type_hash, (void *)map, 0) != 0);
1013  SCLogDebug("buffer %s registered with id %d", map->name, map->id);
1014  return map->id;
1015 }
1016 
1017 static DetectBufferType *DetectBufferTypeLookupByName(const char *string)
1018 {
1019  DetectBufferType map;
1020  memset(&map, 0, sizeof(map));
1021  strlcpy(map.name, string, sizeof(map.name));
1022 
1023  DetectBufferType *res = HashListTableLookup(g_buffer_type_hash, &map, 0);
1024  return res;
1025 }
1026 
1027 int DetectBufferTypeRegister(const char *name)
1028 {
1029  BUG_ON(g_buffer_type_reg_closed);
1030  if (g_buffer_type_hash == NULL)
1031  DetectBufferTypeInit();
1032 
1033  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1034  if (!exists) {
1035  return DetectBufferTypeAdd(name);
1036  } else {
1037  return exists->id;
1038  }
1039 }
1040 
1042 {
1043  BUG_ON(g_buffer_type_reg_closed);
1045  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1046  BUG_ON(!exists);
1047  exists->multi_instance = true;
1048  SCLogDebug("%p %s -- %d supports multi instance", exists, name, exists->id);
1049 }
1050 
1051 void DetectBufferTypeSupportsFrames(const char *name)
1052 {
1053  BUG_ON(g_buffer_type_reg_closed);
1055  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1056  BUG_ON(!exists);
1057  exists->frame = true;
1058  SCLogDebug("%p %s -- %d supports frame inspection", exists, name, exists->id);
1059 }
1060 
1061 void DetectBufferTypeSupportsPacket(const char *name)
1062 {
1063  BUG_ON(g_buffer_type_reg_closed);
1065  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1066  BUG_ON(!exists);
1067  exists->packet = true;
1068  SCLogDebug("%p %s -- %d supports packet inspection", exists, name, exists->id);
1069 }
1070 
1071 void DetectBufferTypeSupportsMpm(const char *name)
1072 {
1073  BUG_ON(g_buffer_type_reg_closed);
1075  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1076  BUG_ON(!exists);
1077  exists->mpm = true;
1078  SCLogDebug("%p %s -- %d supports mpm", exists, name, exists->id);
1079 }
1080 
1082 {
1083  BUG_ON(g_buffer_type_reg_closed);
1085  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1086  BUG_ON(!exists);
1087  exists->supports_transforms = true;
1088  SCLogDebug("%p %s -- %d supports transformations", exists, name, exists->id);
1089 }
1090 
1091 int DetectBufferTypeGetByName(const char *name)
1092 {
1093  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1094  if (!exists) {
1095  return -1;
1096  }
1097  return exists->id;
1098 }
1099 
1100 static DetectBufferType *DetectEngineBufferTypeLookupByName(
1101  const DetectEngineCtx *de_ctx, const char *string)
1102 {
1103  DetectBufferType map;
1104  memset(&map, 0, sizeof(map));
1105  strlcpy(map.name, string, sizeof(map.name));
1106 
1108  return res;
1109 }
1110 
1112 {
1113  DetectBufferType lookup;
1114  memset(&lookup, 0, sizeof(lookup));
1115  lookup.id = id;
1116  const DetectBufferType *res =
1117  HashListTableLookup(de_ctx->buffer_type_hash_id, (void *)&lookup, 0);
1118  return res;
1119 }
1120 
1122 {
1124  return res ? res->name : NULL;
1125 }
1126 
1127 static int DetectEngineBufferTypeAdd(DetectEngineCtx *de_ctx, const char *string)
1128 {
1129  BUG_ON(string == NULL || strlen(string) >= 32);
1130 
1131  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1132  if (map == NULL)
1133  return -1;
1134 
1135  strlcpy(map->name, string, sizeof(map->name));
1136  map->id = de_ctx->buffer_type_id++;
1137 
1138  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_name, (void *)map, 0) != 0);
1139  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_id, (void *)map, 0) != 0);
1140  SCLogDebug("buffer %s registered with id %d", map->name, map->id);
1141  return map->id;
1142 }
1143 
1145  const int direction, const AppProto alproto, const uint8_t frame_type)
1146 {
1147  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1148  if (exists) {
1149  return exists->id;
1150  }
1151 
1152  const int buffer_id = DetectEngineBufferTypeAdd(de_ctx, name);
1153  if (buffer_id < 0) {
1154  return -1;
1155  }
1156 
1157  /* TODO hack we need the map to get the name. Should we return the map at reg? */
1158  const DetectBufferType *map = DetectEngineBufferTypeGetById(de_ctx, buffer_id);
1159  BUG_ON(!map);
1160 
1161  /* register MPM/inspect engines */
1162  if (direction & SIG_FLAG_TOSERVER) {
1164  PrefilterGenericMpmFrameRegister, alproto, frame_type);
1166  DetectEngineInspectFrameBufferGeneric, alproto, frame_type);
1167  }
1168  if (direction & SIG_FLAG_TOCLIENT) {
1170  PrefilterGenericMpmFrameRegister, alproto, frame_type);
1172  DetectEngineInspectFrameBufferGeneric, alproto, frame_type);
1173  }
1174 
1175  return buffer_id;
1176 }
1177 
1179 {
1180  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1181  if (!exists) {
1182  return DetectEngineBufferTypeAdd(de_ctx, name);
1183  } else {
1184  return exists->id;
1185  }
1186 }
1187 
1188 void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
1189 {
1190  BUG_ON(desc == NULL || strlen(desc) >= 128);
1191 
1192  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1193  if (!exists) {
1194  return;
1195  }
1196  strlcpy(exists->description, desc, sizeof(exists->description));
1197 }
1198 
1200 {
1202  if (!exists) {
1203  return NULL;
1204  }
1205  return exists->description;
1206 }
1207 
1208 const char *DetectBufferTypeGetDescriptionByName(const char *name)
1209 {
1210  const DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1211  if (!exists) {
1212  return NULL;
1213  }
1214  return exists->description;
1215 }
1216 
1218 {
1219  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1220  BUG_ON(!exists);
1221  exists->frame = true;
1222  SCLogDebug("%p %s -- %d supports frame inspection", exists, name, exists->id);
1223 }
1224 
1226 {
1227  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1228  BUG_ON(!exists);
1229  exists->packet = true;
1230  SCLogDebug("%p %s -- %d supports packet inspection", exists, name, exists->id);
1231 }
1232 
1234 {
1235  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1236  BUG_ON(!exists);
1237  exists->mpm = true;
1238  SCLogDebug("%p %s -- %d supports mpm", exists, name, exists->id);
1239 }
1240 
1242 {
1243  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1244  BUG_ON(!exists);
1245  exists->supports_transforms = true;
1246  SCLogDebug("%p %s -- %d supports transformations", exists, name, exists->id);
1247 }
1248 
1250 {
1252  if (map == NULL)
1253  return false;
1254  SCLogDebug("map %p id %d multi_instance? %s", map, id, BOOL2STR(map->multi_instance));
1255  return map->multi_instance;
1256 }
1257 
1259 {
1261  if (map == NULL)
1262  return false;
1263  SCLogDebug("map %p id %d packet? %d", map, id, map->packet);
1264  return map->packet;
1265 }
1266 
1268 {
1270  if (map == NULL)
1271  return false;
1272  SCLogDebug("map %p id %d mpm? %d", map, id, map->mpm);
1273  return map->mpm;
1274 }
1275 
1277 {
1279  if (map == NULL)
1280  return false;
1281  SCLogDebug("map %p id %d frame? %d", map, id, map->frame);
1282  return map->frame;
1283 }
1284 
1286  void (*SetupCallback)(const DetectEngineCtx *, Signature *))
1287 {
1288  BUG_ON(g_buffer_type_reg_closed);
1290  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1291  BUG_ON(!exists);
1292  exists->SetupCallback = SetupCallback;
1293 }
1294 
1296 {
1298  if (map && map->SetupCallback) {
1299  map->SetupCallback(de_ctx, s);
1300  }
1301 }
1302 
1304  bool (*ValidateCallback)(const Signature *, const char **sigerror))
1305 {
1306  BUG_ON(g_buffer_type_reg_closed);
1308  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1309  BUG_ON(!exists);
1310  exists->ValidateCallback = ValidateCallback;
1311 }
1312 
1314  const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
1315 {
1317  if (map && map->ValidateCallback) {
1318  return map->ValidateCallback(s, sigerror);
1319  }
1320  return true;
1321 }
1322 
1323 SigMatch *DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
1324 {
1325  for (uint32_t i = 0; i < s->init_data->buffer_index; i++) {
1326  if (buf_id == s->init_data->buffers[i].id) {
1327  return s->init_data->buffers[i].head;
1328  }
1329  }
1330  return NULL;
1331 }
1332 
1333 SigMatch *DetectBufferGetLastSigMatch(const Signature *s, const uint32_t buf_id)
1334 {
1335  SigMatch *last = NULL;
1336  for (uint32_t i = 0; i < s->init_data->buffer_index; i++) {
1337  if (buf_id == s->init_data->buffers[i].id) {
1338  last = s->init_data->buffers[i].tail;
1339  }
1340  }
1341  return last;
1342 }
1343 
1344 bool DetectBufferIsPresent(const Signature *s, const uint32_t buf_id)
1345 {
1346  for (uint32_t i = 0; i < s->init_data->buffer_index; i++) {
1347  if (buf_id == s->init_data->buffers[i].id) {
1348  return true;
1349  }
1350  }
1351  return false;
1352 }
1353 
1355 {
1356  BUG_ON(s->init_data == NULL);
1357 
1359  SCLogError("Rule buffer cannot be reset after base64_data.");
1360  return -1;
1361  }
1362 
1363  if (s->init_data->list && s->init_data->transforms.cnt) {
1364  SCLogError("no matches following transform(s)");
1365  return -1;
1366  }
1367  s->init_data->list = list;
1368  s->init_data->list_set = true;
1369 
1370  // check if last has matches -> if no, error
1371  if (s->init_data->curbuf && s->init_data->curbuf->head == NULL) {
1372  SCLogError("previous sticky buffer has no matches");
1373  return -1;
1374  }
1375 
1376  for (uint32_t x = 0; x < s->init_data->buffers_size; x++) {
1378  for (SigMatch *sm = b->head; sm != NULL; sm = sm->next) {
1379  SCLogDebug(
1380  "buf:%p: id:%u: '%s' pos %u", b, b->id, sigmatch_table[sm->type].name, sm->idx);
1381  }
1382  if ((uint32_t)list == b->id) {
1383  SCLogDebug("found buffer %p for list %d", b, list);
1384  if (s->init_data->buffers[x].sm_init) {
1385  s->init_data->buffers[x].sm_init = false;
1386  SCLogDebug("sm_init was true for %p list %d", b, list);
1387  s->init_data->curbuf = b;
1388  return 0;
1389 
1391  // fall through
1392  } else {
1393  SCLogWarning("duplicate instance for %s in '%s'",
1395  s->init_data->curbuf = b;
1396  return 0;
1397  }
1398  }
1399  }
1400 
1401  if (list < DETECT_SM_LIST_MAX)
1402  return 0;
1403 
1405  SCLogError("failed to expand rule buffer array");
1406  return -1;
1407  }
1408 
1409  /* initialize new buffer */
1411  s->init_data->curbuf->id = list;
1412  s->init_data->curbuf->head = NULL;
1413  s->init_data->curbuf->tail = NULL;
1416  SCLogDebug("new: idx %u list %d set up curbuf %p", s->init_data->buffer_index - 1, list,
1417  s->init_data->curbuf);
1418 
1419  return 0;
1420 }
1421 
1423 {
1424  BUG_ON(s->init_data == NULL);
1425 
1426  if (s->init_data->list && s->init_data->transforms.cnt) {
1427  if (s->init_data->list == DETECT_SM_LIST_NOTSET ||
1429  SCLogError("previous transforms not consumed "
1430  "(list: %u, transform_cnt %u)",
1432  SCReturnInt(-1);
1433  }
1434 
1435  SCLogDebug("buffer %d has transform(s) registered: %d",
1439  if (new_list == -1) {
1440  SCReturnInt(-1);
1441  }
1442  int base_list = s->init_data->list;
1443  SCLogDebug("new_list %d", new_list);
1444  s->init_data->list = new_list;
1445  s->init_data->list_set = false;
1446  // reset transforms now that we've set up the list
1447  s->init_data->transforms.cnt = 0;
1448 
1449  if (s->init_data->curbuf && s->init_data->curbuf->head != NULL) {
1451  SCLogError("failed to expand rule buffer array");
1452  return -1;
1453  }
1457  }
1458  if (s->init_data->curbuf == NULL) {
1459  SCLogError("failed to setup buffer");
1461  SCReturnInt(-1);
1462  }
1463  s->init_data->curbuf->id = new_list;
1464  SCLogDebug("new list after applying transforms: %u", new_list);
1465  }
1466 
1467  SCReturnInt(0);
1468 }
1469 
1471 {
1472  /* single buffers */
1473  for (uint32_t i = 0; i < det_ctx->inspect.to_clear_idx; i++)
1474  {
1475  const uint32_t idx = det_ctx->inspect.to_clear_queue[i];
1476  InspectionBuffer *buffer = &det_ctx->inspect.buffers[idx];
1477  buffer->inspect = NULL;
1478  buffer->initialized = false;
1479  }
1480  det_ctx->inspect.to_clear_idx = 0;
1481 
1482  /* multi buffers */
1483  for (uint32_t i = 0; i < det_ctx->multi_inspect.to_clear_idx; i++)
1484  {
1485  const uint32_t idx = det_ctx->multi_inspect.to_clear_queue[i];
1486  InspectionBufferMultipleForList *mbuffer = &det_ctx->multi_inspect.buffers[idx];
1487  for (uint32_t x = 0; x <= mbuffer->max; x++) {
1488  InspectionBuffer *buffer = &mbuffer->inspection_buffers[x];
1489  buffer->inspect = NULL;
1490  buffer->initialized = false;
1491  }
1492  mbuffer->init = 0;
1493  mbuffer->max = 0;
1494  }
1495  det_ctx->multi_inspect.to_clear_idx = 0;
1496 }
1497 
1499 {
1500  return &det_ctx->inspect.buffers[list_id];
1501 }
1502 
1503 static InspectionBufferMultipleForList *InspectionBufferGetMulti(
1504  DetectEngineThreadCtx *det_ctx, const int list_id)
1505 {
1506  InspectionBufferMultipleForList *buffer = &det_ctx->multi_inspect.buffers[list_id];
1507  if (!buffer->init) {
1508  det_ctx->multi_inspect.to_clear_queue[det_ctx->multi_inspect.to_clear_idx++] = list_id;
1509  buffer->init = 1;
1510  }
1511  return buffer;
1512 }
1513 
1514 /** \brief for a InspectionBufferMultipleForList get a InspectionBuffer
1515  * \param fb the multiple buffer array
1516  * \param local_id the index to get a buffer
1517  * \param buffer the inspect buffer or NULL in case of error */
1519  DetectEngineThreadCtx *det_ctx, const int list_id, const uint32_t local_id)
1520 {
1521  if (unlikely(local_id >= 1024)) {
1523  return NULL;
1524  }
1525 
1526  InspectionBufferMultipleForList *fb = InspectionBufferGetMulti(det_ctx, list_id);
1527 
1528  if (local_id >= fb->size) {
1529  uint32_t old_size = fb->size;
1530  uint32_t new_size = local_id + 1;
1531  uint32_t grow_by = new_size - old_size;
1532  SCLogDebug("size is %u, need %u, so growing by %u", old_size, new_size, grow_by);
1533 
1534  SCLogDebug("fb->inspection_buffers %p", fb->inspection_buffers);
1535  void *ptr = SCRealloc(fb->inspection_buffers, (local_id + 1) * sizeof(InspectionBuffer));
1536  if (ptr == NULL)
1537  return NULL;
1538 
1539  InspectionBuffer *to_zero = (InspectionBuffer *)ptr + old_size;
1540  SCLogDebug("ptr %p to_zero %p", ptr, to_zero);
1541  memset((uint8_t *)to_zero, 0, (grow_by * sizeof(InspectionBuffer)));
1542  fb->inspection_buffers = ptr;
1543  fb->size = new_size;
1544  }
1545 
1546  fb->max = MAX(fb->max, local_id);
1547  InspectionBuffer *buffer = &fb->inspection_buffers[local_id];
1548  SCLogDebug("using buffer %p", buffer);
1549 #ifdef DEBUG_VALIDATION
1550  buffer->multi = true;
1551 #endif
1552  return buffer;
1553 }
1554 
1555 void InspectionBufferInit(InspectionBuffer *buffer, uint32_t initial_size)
1556 {
1557  memset(buffer, 0, sizeof(*buffer));
1558  buffer->buf = SCCalloc(initial_size, sizeof(uint8_t));
1559  if (buffer->buf != NULL) {
1560  buffer->size = initial_size;
1561  }
1562 }
1563 
1564 /** \brief setup the buffer empty */
1566 {
1567 #ifdef DEBUG_VALIDATION
1569  DEBUG_VALIDATE_BUG_ON(!buffer->multi);
1570 #endif
1571  buffer->inspect = NULL;
1572  buffer->inspect_len = 0;
1573  buffer->len = 0;
1574  buffer->initialized = true;
1575 }
1576 
1577 /** \brief setup the buffer with our initial data */
1579  const uint8_t *data, const uint32_t data_len)
1580 {
1581 #ifdef DEBUG_VALIDATION
1582  DEBUG_VALIDATE_BUG_ON(!buffer->multi);
1583 #endif
1584  buffer->inspect = buffer->orig = data;
1585  buffer->inspect_len = buffer->orig_len = data_len;
1586  buffer->len = 0;
1587  buffer->initialized = true;
1588 
1589  InspectionBufferApplyTransforms(buffer, transforms);
1590 }
1591 
1592 /** \brief setup the buffer with our initial data */
1593 void InspectionBufferSetup(DetectEngineThreadCtx *det_ctx, const int list_id,
1594  InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
1595 {
1596 #ifdef DEBUG_VALIDATION
1597  DEBUG_VALIDATE_BUG_ON(buffer->multi);
1598  DEBUG_VALIDATE_BUG_ON(buffer != InspectionBufferGet(det_ctx, list_id));
1599 #endif
1600  if (buffer->inspect == NULL) {
1601 #ifdef UNITTESTS
1602  if (det_ctx && list_id != -1)
1603 #endif
1604  det_ctx->inspect.to_clear_queue[det_ctx->inspect.to_clear_idx++] = list_id;
1605  }
1606  buffer->inspect = buffer->orig = data;
1607  buffer->inspect_len = buffer->orig_len = data_len;
1608  buffer->len = 0;
1609  buffer->initialized = true;
1610 }
1611 
1613 {
1614  if (buffer->buf != NULL) {
1615  SCFree(buffer->buf);
1616  }
1617  memset(buffer, 0, sizeof(*buffer));
1618 }
1619 
1620 /**
1621  * \brief make sure that the buffer has at least 'min_size' bytes
1622  * Expand the buffer if necessary
1623  */
1624 void InspectionBufferCheckAndExpand(InspectionBuffer *buffer, uint32_t min_size)
1625 {
1626  if (likely(buffer->size >= min_size))
1627  return;
1628 
1629  uint32_t new_size = (buffer->size == 0) ? 4096 : buffer->size;
1630  while (new_size < min_size) {
1631  new_size *= 2;
1632  }
1633 
1634  void *ptr = SCRealloc(buffer->buf, new_size);
1635  if (ptr != NULL) {
1636  buffer->buf = ptr;
1637  buffer->size = new_size;
1638  }
1639 }
1640 
1641 void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
1642 {
1643  InspectionBufferCheckAndExpand(buffer, buf_len);
1644 
1645  if (buffer->size) {
1646  uint32_t copy_size = MIN(buf_len, buffer->size);
1647  memcpy(buffer->buf, buf, copy_size);
1648  buffer->inspect = buffer->buf;
1649  buffer->inspect_len = copy_size;
1650  buffer->initialized = true;
1651  }
1652 }
1653 
1654 /** \brief Check content byte array compatibility with transforms
1655  *
1656  * The "content" array is presented to the transforms so that each
1657  * transform may validate that it's compatible with the transform.
1658  *
1659  * When a transform indicates the byte array is incompatible, none of the
1660  * subsequent transforms, if any, are invoked. This means the first validation
1661  * failure terminates the loop.
1662  *
1663  * \param de_ctx Detection engine context.
1664  * \param sm_list The SM list id.
1665  * \param content The byte array being validated
1666  * \param namestr returns the name of the transform that is incompatible with
1667  * content.
1668  *
1669  * \retval true (false) If any of the transforms indicate the byte array is
1670  * (is not) compatible.
1671  **/
1673  const uint8_t *content, uint16_t content_len, const char **namestr)
1674 {
1675  const DetectBufferType *dbt = DetectEngineBufferTypeGetById(de_ctx, sm_list);
1676  BUG_ON(dbt == NULL);
1677 
1678  for (int i = 0; i < dbt->transforms.cnt; i++) {
1679  const TransformData *t = &dbt->transforms.transforms[i];
1681  continue;
1682 
1683  if (sigmatch_table[t->transform].TransformValidate(content, content_len, t->options)) {
1684  continue;
1685  }
1686 
1687  if (namestr) {
1688  *namestr = sigmatch_table[t->transform].name;
1689  }
1690 
1691  return false;
1692  }
1693 
1694  return true;
1695 }
1696 
1698  const DetectEngineTransforms *transforms)
1699 {
1700  if (transforms) {
1701  for (int i = 0; i < DETECT_TRANSFORMS_MAX; i++) {
1702  const int id = transforms->transforms[i].transform;
1703  if (id == 0)
1704  break;
1705  BUG_ON(sigmatch_table[id].Transform == NULL);
1706  sigmatch_table[id].Transform(buffer, transforms->transforms[i].options);
1707  SCLogDebug("applied transform %s", sigmatch_table[id].name);
1708  }
1709  }
1710 }
1711 
1712 static void DetectBufferTypeSetupDetectEngine(DetectEngineCtx *de_ctx)
1713 {
1714  const int size = g_buffer_type_id;
1715  BUG_ON(!(size > 0));
1716 
1717  de_ctx->buffer_type_hash_name = HashListTableInit(256, DetectBufferTypeHashNameFunc,
1718  DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
1721  HashListTableInit(256, DetectBufferTypeHashIdFunc, DetectBufferTypeCompareIdFunc,
1722  NULL); // entries owned by buffer_type_hash_name
1723  BUG_ON(de_ctx->buffer_type_hash_id == NULL);
1724  de_ctx->buffer_type_id = g_buffer_type_id;
1725 
1726  SCLogDebug("DETECT_SM_LIST_DYNAMIC_START %u", DETECT_SM_LIST_DYNAMIC_START);
1727  HashListTableBucket *b = HashListTableGetListHead(g_buffer_type_hash);
1728  while (b) {
1730 
1731  DetectBufferType *copy = SCCalloc(1, sizeof(*copy));
1732  BUG_ON(!copy);
1733  memcpy(copy, map, sizeof(*copy));
1734  int r = HashListTableAdd(de_ctx->buffer_type_hash_name, (void *)copy, 0);
1735  BUG_ON(r != 0);
1736  r = HashListTableAdd(de_ctx->buffer_type_hash_id, (void *)copy, 0);
1737  BUG_ON(r != 0);
1738 
1739  SCLogDebug("name %s id %d mpm %s packet %s -- %s. "
1740  "Callbacks: Setup %p Validate %p",
1741  map->name, map->id, map->mpm ? "true" : "false", map->packet ? "true" : "false",
1742  map->description, map->SetupCallback, map->ValidateCallback);
1743  b = HashListTableGetListNext(b);
1744  }
1745 
1748  DetectAppLayerInspectEngineCopyListToDetectCtx(de_ctx);
1750  DetectFrameInspectEngineCopyListToDetectCtx(de_ctx);
1752  DetectPktInspectEngineCopyListToDetectCtx(de_ctx);
1753 }
1754 
1755 static void DetectBufferTypeFreeDetectEngine(DetectEngineCtx *de_ctx)
1756 {
1757  if (de_ctx) {
1762 
1764  while (ilist) {
1766  SCFree(ilist);
1767  ilist = next;
1768  }
1770  while (mlist) {
1771  DetectBufferMpmRegistry *next = mlist->next;
1772  SCFree(mlist);
1773  mlist = next;
1774  }
1776  while (plist) {
1778  SCFree(plist);
1779  plist = next;
1780  }
1782  while (pmlist) {
1783  DetectBufferMpmRegistry *next = pmlist->next;
1784  SCFree(pmlist);
1785  pmlist = next;
1786  }
1788  while (framelist) {
1790  SCFree(framelist);
1791  framelist = next;
1792  }
1794  while (framemlist) {
1795  DetectBufferMpmRegistry *next = framemlist->next;
1796  SCFree(framemlist);
1797  framemlist = next;
1798  }
1800  }
1801 }
1802 
1804 {
1805  BUG_ON(g_buffer_type_hash == NULL);
1806 
1807  g_buffer_type_reg_closed = 1;
1808 }
1809 
1811  DetectEngineCtx *de_ctx, const int id, TransformData *transforms, int transform_cnt)
1812 {
1813  const DetectBufferType *base_map = DetectEngineBufferTypeGetById(de_ctx, id);
1814  if (!base_map) {
1815  return -1;
1816  }
1817  if (!base_map->supports_transforms) {
1818  SCLogError("buffer '%s' does not support transformations", base_map->name);
1819  return -1;
1820  }
1821 
1822  SCLogDebug("base_map %s", base_map->name);
1823 
1825  memset(&t, 0, sizeof(t));
1826  for (int i = 0; i < transform_cnt; i++) {
1827  t.transforms[i] = transforms[i];
1828  }
1829  t.cnt = transform_cnt;
1830 
1831  DetectBufferType lookup_map;
1832  memset(&lookup_map, 0, sizeof(lookup_map));
1833  strlcpy(lookup_map.name, base_map->name, sizeof(lookup_map.name));
1834  lookup_map.transforms = t;
1836 
1837  SCLogDebug("res %p", res);
1838  if (res != NULL) {
1839  return res->id;
1840  }
1841 
1842  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1843  if (map == NULL)
1844  return -1;
1845 
1846  strlcpy(map->name, base_map->name, sizeof(map->name));
1847  map->id = de_ctx->buffer_type_id++;
1848  map->parent_id = base_map->id;
1849  map->transforms = t;
1850  map->mpm = base_map->mpm;
1851  map->packet = base_map->packet;
1852  map->frame = base_map->frame;
1853  map->SetupCallback = base_map->SetupCallback;
1854  map->ValidateCallback = base_map->ValidateCallback;
1855  if (map->frame) {
1857  } else if (map->packet) {
1859  map->id, map->parent_id, &map->transforms);
1860  } else {
1862  map->id, map->parent_id, &map->transforms);
1863  }
1864 
1865  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_name, (void *)map, 0) != 0);
1866  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_id, (void *)map, 0) != 0);
1867  SCLogDebug("buffer %s registered with id %d, parent %d", map->name, map->id, map->parent_id);
1868 
1869  if (map->frame) {
1870  DetectFrameInspectEngineCopy(de_ctx, map->parent_id, map->id, &map->transforms);
1871  } else if (map->packet) {
1872  DetectPktInspectEngineCopy(de_ctx, map->parent_id, map->id, &map->transforms);
1873  } else {
1874  DetectAppLayerInspectEngineCopy(de_ctx, map->parent_id, map->id, &map->transforms);
1875  }
1876  return map->id;
1877 }
1878 
1879 /* returns false if no match, true if match */
1880 static int DetectEngineInspectRulePacketMatches(
1881  DetectEngineThreadCtx *det_ctx,
1882  const DetectEnginePktInspectionEngine *engine,
1883  const Signature *s,
1884  Packet *p, uint8_t *_alert_flags)
1885 {
1886  SCEnter();
1887 
1888  /* run the packet match functions */
1890  const SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
1891 
1892  SCLogDebug("running match functions, sm %p", smd);
1893  while (1) {
1895  if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) <= 0) {
1896  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
1897  SCLogDebug("no match");
1899  }
1900  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1901  if (smd->is_last) {
1902  SCLogDebug("match and is_last");
1903  break;
1904  }
1905  smd++;
1906  }
1908 }
1909 
1910 static int DetectEngineInspectRulePayloadMatches(
1911  DetectEngineThreadCtx *det_ctx,
1912  const DetectEnginePktInspectionEngine *engine,
1913  const Signature *s, Packet *p, uint8_t *alert_flags)
1914 {
1915  SCEnter();
1916 
1917  DetectEngineCtx *de_ctx = det_ctx->de_ctx;
1918 
1920  /* if we have stream msgs, inspect against those first,
1921  * but not for a "dsize" signature */
1922  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1923  int pmatch = 0;
1924  if (p->flags & PKT_DETECT_HAS_STREAMDATA) {
1925  pmatch = DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, p->flow, p);
1926  if (pmatch) {
1927  *alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH;
1928  }
1929  }
1930  /* no match? then inspect packet payload */
1931  if (pmatch == 0) {
1932  SCLogDebug("no match in stream, fall back to packet payload");
1933 
1934  /* skip if we don't have to inspect the packet and segment was
1935  * added to stream */
1936  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET) && (p->flags & PKT_STREAM_ADD)) {
1938  }
1940  SCLogDebug("SIG_FLAG_REQUIRE_STREAM_ONLY, so no match");
1942  }
1943  if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, p->flow, p) != 1) {
1945  }
1946  }
1947  } else {
1948  if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, p->flow, p) != 1) {
1950  }
1951  }
1953 }
1954 
1956  DetectEngineThreadCtx *det_ctx, const Signature *s,
1957  Flow *f, Packet *p,
1958  uint8_t *alert_flags)
1959 {
1960  SCEnter();
1961 
1962  for (DetectEnginePktInspectionEngine *e = s->pkt_inspect; e != NULL; e = e->next) {
1963  if (e->v1.Callback(det_ctx, e, s, p, alert_flags) != DETECT_ENGINE_INSPECT_SIG_MATCH) {
1964  SCLogDebug("sid %u: e %p Callback returned no match", s->id, e);
1965  return false;
1966  }
1967  SCLogDebug("sid %u: e %p Callback returned true", s->id, e);
1968  }
1969 
1970  SCLogDebug("sid %u: returning true", s->id);
1971  return true;
1972 }
1973 
1974 /**
1975  * \param data pointer to SigMatchData. Allowed to be NULL.
1976  */
1977 static int DetectEnginePktInspectionAppend(Signature *s, InspectionBufferPktInspectFunc Callback,
1978  SigMatchData *data, const int list_id)
1979 {
1980  DetectEnginePktInspectionEngine *e = SCCalloc(1, sizeof(*e));
1981  if (e == NULL)
1982  return -1;
1983 
1984  e->mpm = s->init_data->mpm_sm_list == list_id;
1985  DEBUG_VALIDATE_BUG_ON(list_id < 0 || list_id > UINT16_MAX);
1986  e->sm_list = (uint16_t)list_id;
1987  e->sm_list_base = (uint16_t)list_id;
1988  e->v1.Callback = Callback;
1989  e->smd = data;
1990 
1991  if (s->pkt_inspect == NULL) {
1992  s->pkt_inspect = e;
1993  } else {
1995  while (a->next != NULL) {
1996  a = a->next;
1997  }
1998  a->next = e;
1999  }
2000  return 0;
2001 }
2002 
2004 {
2005  /* only handle PMATCH here if we're not an app inspect rule */
2007  if (DetectEnginePktInspectionAppend(
2008  s, DetectEngineInspectRulePayloadMatches, NULL, DETECT_SM_LIST_PMATCH) < 0)
2009  return -1;
2010  SCLogDebug("sid %u: DetectEngineInspectRulePayloadMatches appended", s->id);
2011  }
2012 
2013  if (s->sm_arrays[DETECT_SM_LIST_MATCH]) {
2014  if (DetectEnginePktInspectionAppend(
2015  s, DetectEngineInspectRulePacketMatches, NULL, DETECT_SM_LIST_MATCH) < 0)
2016  return -1;
2017  SCLogDebug("sid %u: DetectEngineInspectRulePacketMatches appended", s->id);
2018  }
2019 
2020  return 0;
2021 }
2022 
2023 /* code to control the main thread to do a reload */
2024 
2026  IDLE, /**< ready to start a reload */
2027  RELOAD, /**< command main thread to do the reload */
2028 };
2029 
2030 
2031 typedef struct DetectEngineSyncer_ {
2035 
2036 static DetectEngineSyncer detect_sync = { SCMUTEX_INITIALIZER, IDLE };
2037 
2038 /* tell main to start reloading */
2040 {
2041  int r = 0;
2042  SCMutexLock(&detect_sync.m);
2043  if (detect_sync.state == IDLE) {
2044  detect_sync.state = RELOAD;
2045  } else {
2046  r = -1;
2047  }
2048  SCMutexUnlock(&detect_sync.m);
2049  return r;
2050 }
2051 
2052 /* main thread checks this to see if it should start */
2054 {
2055  int r = 0;
2056  SCMutexLock(&detect_sync.m);
2057  if (detect_sync.state == RELOAD) {
2058  r = 1;
2059  }
2060  SCMutexUnlock(&detect_sync.m);
2061  return r;
2062 }
2063 
2064 /* main thread sets done when it's done */
2066 {
2067  SCMutexLock(&detect_sync.m);
2068  detect_sync.state = IDLE;
2069  SCMutexUnlock(&detect_sync.m);
2070 }
2071 
2072 /* caller loops this until it returns 1 */
2074 {
2075  int r = 0;
2076  SCMutexLock(&detect_sync.m);
2077  if (detect_sync.state == IDLE) {
2078  r = 1;
2079  }
2080  SCMutexUnlock(&detect_sync.m);
2081  return r;
2082 }
2083 
2084 /** \brief Do the content inspection & validation for a signature
2085  *
2086  * \param de_ctx Detection engine context
2087  * \param det_ctx Detection engine thread context
2088  * \param s Signature to inspect
2089  * \param sm SigMatch to inspect
2090  * \param f Flow
2091  * \param flags app layer flags
2092  * \param state App layer state
2093  *
2094  * \retval 0 no match
2095  * \retval 1 match
2096  */
2098  const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
2099  uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
2100 {
2101  SigMatchData *smd = engine->smd;
2102  SCLogDebug("running match functions, sm %p", smd);
2103  if (smd != NULL) {
2104  while (1) {
2105  int match = 0;
2107  match = sigmatch_table[smd->type].
2108  AppLayerTxMatch(det_ctx, f, flags, alstate, txv, s, smd->ctx);
2109  KEYWORD_PROFILING_END(det_ctx, smd->type, (match == 1));
2110  if (match == 0)
2112  if (match == 2) {
2114  }
2115 
2116  if (smd->is_last)
2117  break;
2118  smd++;
2119  }
2120  }
2121 
2123 }
2124 
2125 
2126 /**
2127  * \brief Do the content inspection & validation for a signature
2128  *
2129  * \param de_ctx Detection engine context
2130  * \param det_ctx Detection engine thread context
2131  * \param s Signature to inspect
2132  * \param f Flow
2133  * \param flags app layer flags
2134  * \param state App layer state
2135  *
2136  * \retval 0 no match.
2137  * \retval 1 match.
2138  * \retval 2 Sig can't match.
2139  */
2141  const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
2142  void *alstate, void *txv, uint64_t tx_id)
2143 {
2144  const int list_id = engine->sm_list;
2145  SCLogDebug("running inspect on %d", list_id);
2146 
2147  const bool eof = (AppLayerParserGetStateProgress(f->proto, f->alproto, txv, flags) > engine->progress);
2148 
2149  SCLogDebug("list %d mpm? %s transforms %p",
2150  engine->sm_list, engine->mpm ? "true" : "false", engine->v2.transforms);
2151 
2152  /* if prefilter didn't already run, we need to consider transformations */
2153  const DetectEngineTransforms *transforms = NULL;
2154  if (!engine->mpm) {
2155  transforms = engine->v2.transforms;
2156  }
2157 
2158  const InspectionBuffer *buffer = engine->v2.GetData(det_ctx, transforms,
2159  f, flags, txv, list_id);
2160  if (unlikely(buffer == NULL)) {
2163  }
2164 
2165  const uint32_t data_len = buffer->inspect_len;
2166  const uint8_t *data = buffer->inspect;
2167  const uint64_t offset = buffer->inspect_offset;
2168 
2169  uint8_t ci_flags = eof ? DETECT_CI_FLAGS_END : 0;
2170  ci_flags |= (offset == 0 ? DETECT_CI_FLAGS_START : 0);
2171  ci_flags |= buffer->flags;
2172 
2173  /* Inspect all the uricontents fetched on each
2174  * transaction at the app layer */
2175  const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f, data,
2177  if (match) {
2179  } else {
2182  }
2183 }
2184 
2185 // wrapper for both DetectAppLayerInspectEngineRegister and DetectAppLayerMpmRegister
2186 // with cast of callback function
2187 void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, int progress,
2188  InspectionMultiBufferGetDataPtr GetData, int priority, int tx_min_progress)
2189 {
2190  AppLayerInspectEngineRegisterInternal(
2191  name, alproto, dir, progress, DetectEngineInspectMultiBufferGeneric, NULL, GetData);
2193  alproto, tx_min_progress);
2194 }
2195 
2198  const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
2199 {
2200  uint32_t local_id = 0;
2201  const DetectEngineTransforms *transforms = NULL;
2202  if (!engine->mpm) {
2203  transforms = engine->v2.transforms;
2204  }
2205 
2206  do {
2207  InspectionBuffer *buffer = engine->v2.GetMultiData(
2208  det_ctx, transforms, f, flags, txv, engine->sm_list, local_id);
2209 
2210  if (buffer == NULL || buffer->inspect == NULL)
2211  break;
2212 
2213  // The GetData functions set buffer->flags to DETECT_CI_FLAGS_SINGLE
2214  // This is not meant for streaming buffers
2215  const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
2217  if (match) {
2219  }
2220  local_id++;
2221  } while (1);
2223 }
2224 
2225 /**
2226  * \brief Do the content inspection & validation for a signature
2227  *
2228  * \param de_ctx Detection engine context
2229  * \param det_ctx Detection engine thread context
2230  * \param s Signature to inspect
2231  * \param p Packet
2232  *
2233  * \retval 0 no match.
2234  * \retval 1 match.
2235  */
2237  DetectEngineThreadCtx *det_ctx,
2238  const DetectEnginePktInspectionEngine *engine,
2239  const Signature *s, Packet *p, uint8_t *_alert_flags)
2240 {
2241  const int list_id = engine->sm_list;
2242  SCLogDebug("running inspect on %d", list_id);
2243 
2244  SCLogDebug("list %d transforms %p",
2245  engine->sm_list, engine->v1.transforms);
2246 
2247  /* if prefilter didn't already run, we need to consider transformations */
2248  const DetectEngineTransforms *transforms = NULL;
2249  if (!engine->mpm) {
2250  transforms = engine->v1.transforms;
2251  }
2252 
2253  const InspectionBuffer *buffer = engine->v1.GetData(det_ctx, transforms, p,
2254  list_id);
2255  if (unlikely(buffer == NULL)) {
2257  }
2258 
2259  uint8_t ci_flags = DETECT_CI_FLAGS_START|DETECT_CI_FLAGS_END;
2260  ci_flags |= buffer->flags;
2261 
2262  /* Inspect all the uricontents fetched on each
2263  * transaction at the app layer */
2264  const bool match = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx, s, engine->smd, p,
2265  p->flow, buffer->inspect, buffer->inspect_len, 0, ci_flags,
2267  if (match) {
2269  } else {
2271  }
2272 }
2273 
2274 /** \internal
2275  * \brief inject a pseudo packet into each detect thread that doesn't use the
2276  * new det_ctx yet
2277  */
2278 static void InjectPackets(ThreadVars **detect_tvs,
2279  DetectEngineThreadCtx **new_det_ctx,
2280  int no_of_detect_tvs)
2281 {
2282  /* inject a fake packet if the detect thread isn't using the new ctx yet,
2283  * this speeds up the process */
2284  for (int i = 0; i < no_of_detect_tvs; i++) {
2285  if (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
2286  if (detect_tvs[i]->inq != NULL) {
2287  Packet *p = PacketGetFromAlloc();
2288  if (p != NULL) {
2291  PacketQueue *q = detect_tvs[i]->inq->pq;
2292  SCMutexLock(&q->mutex_q);
2293  PacketEnqueue(q, p);
2294  SCCondSignal(&q->cond_q);
2295  SCMutexUnlock(&q->mutex_q);
2296  }
2297  }
2298  }
2299  }
2300 }
2301 
2302 /** \internal
2303  * \brief Update detect threads with new detect engine
2304  *
2305  * Atomically update each detect thread with a new thread context
2306  * that is associated to the new detection engine(s).
2307  *
2308  * If called in unix socket mode, it's possible that we don't have
2309  * detect threads yet.
2310  *
2311  * \retval -1 error
2312  * \retval 0 no detection threads
2313  * \retval 1 successful reload
2314  */
2315 static int DetectEngineReloadThreads(DetectEngineCtx *new_de_ctx)
2316 {
2317  SCEnter();
2318  uint32_t i = 0;
2319 
2320  /* count detect threads in use */
2321  uint32_t no_of_detect_tvs = TmThreadCountThreadsByTmmFlags(TM_FLAG_DETECT_TM);
2322  /* can be zero in unix socket mode */
2323  if (no_of_detect_tvs == 0) {
2324  return 0;
2325  }
2326 
2327  /* prepare swap structures */
2328  DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs];
2329  DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs];
2330  ThreadVars *detect_tvs[no_of_detect_tvs];
2331  memset(old_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
2332  memset(new_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
2333  memset(detect_tvs, 0x00, (no_of_detect_tvs * sizeof(ThreadVars *)));
2334 
2335  /* start the process of swapping detect threads ctxs */
2336 
2337  /* get reference to tv's and setup new_det_ctx array */
2339  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
2340  if ((tv->tmm_flags & TM_FLAG_DETECT_TM) == 0) {
2341  continue;
2342  }
2343  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
2344  TmModule *tm = TmModuleGetById(s->tm_id);
2345  if (!(tm->flags & TM_FLAG_DETECT_TM)) {
2346  continue;
2347  }
2348 
2349  if (suricata_ctl_flags != 0) {
2351  goto error;
2352  }
2353 
2354  old_det_ctx[i] = FlowWorkerGetDetectCtxPtr(SC_ATOMIC_GET(s->slot_data));
2355  detect_tvs[i] = tv;
2356 
2357  new_det_ctx[i] = DetectEngineThreadCtxInitForReload(tv, new_de_ctx, 1);
2358  if (new_det_ctx[i] == NULL) {
2359  SCLogError("Detect engine thread init "
2360  "failure in live rule swap. Let's get out of here");
2362  goto error;
2363  }
2364  SCLogDebug("live rule swap created new det_ctx - %p and de_ctx "
2365  "- %p\n", new_det_ctx[i], new_de_ctx);
2366  i++;
2367  break;
2368  }
2369  }
2370  BUG_ON(i != no_of_detect_tvs);
2371 
2372  /* atomically replace the det_ctx data */
2373  i = 0;
2374  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
2375  if ((tv->tmm_flags & TM_FLAG_DETECT_TM) == 0) {
2376  continue;
2377  }
2378  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
2379  TmModule *tm = TmModuleGetById(s->tm_id);
2380  if (!(tm->flags & TM_FLAG_DETECT_TM)) {
2381  continue;
2382  }
2383  SCLogDebug("swapping new det_ctx - %p with older one - %p",
2384  new_det_ctx[i], SC_ATOMIC_GET(s->slot_data));
2385  FlowWorkerReplaceDetectCtx(SC_ATOMIC_GET(s->slot_data), new_det_ctx[i++]);
2386  break;
2387  }
2388  }
2390 
2391  /* threads now all have new data, however they may not have started using
2392  * it and may still use the old data */
2393 
2394  SCLogDebug("Live rule swap has swapped %d old det_ctx's with new ones, "
2395  "along with the new de_ctx", no_of_detect_tvs);
2396 
2397  InjectPackets(detect_tvs, new_det_ctx, no_of_detect_tvs);
2398 
2399  /* loop waiting for detect threads to switch to the new det_ctx. Try to
2400  * wake up capture if needed (break loop). */
2401  uint32_t threads_done = 0;
2402 retry:
2403  for (i = 0; i < no_of_detect_tvs; i++) {
2404  if (suricata_ctl_flags != 0) {
2405  threads_done = no_of_detect_tvs;
2406  break;
2407  }
2408  usleep(1000);
2409  if (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) == 1) {
2410  SCLogDebug("new_det_ctx - %p used by detect engine", new_det_ctx[i]);
2411  threads_done++;
2412  } else {
2413  TmThreadsCaptureBreakLoop(detect_tvs[i]);
2414  }
2415  }
2416  if (threads_done < no_of_detect_tvs) {
2417  threads_done = 0;
2418  SleepMsec(250);
2419  goto retry;
2420  }
2421 
2422  /* this is to make sure that if someone initiated shutdown during a live
2423  * rule swap, the live rule swap won't clean up the old det_ctx and
2424  * de_ctx, till all detect threads have stopped working and sitting
2425  * silently after setting RUNNING_DONE flag and while waiting for
2426  * THV_DEINIT flag */
2427  if (i != no_of_detect_tvs) { // not all threads we swapped
2428  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
2429  if ((tv->tmm_flags & TM_FLAG_DETECT_TM) == 0) {
2430  continue;
2431  }
2432 
2434  usleep(100);
2435  }
2436  }
2437  }
2438 
2439  /* free all the ctxs */
2440  for (i = 0; i < no_of_detect_tvs; i++) {
2441  SCLogDebug("Freeing old_det_ctx - %p used by detect",
2442  old_det_ctx[i]);
2443  DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]);
2444  }
2445 
2447 
2448  return 1;
2449 
2450  error:
2451  for (i = 0; i < no_of_detect_tvs; i++) {
2452  if (new_det_ctx[i] != NULL)
2453  DetectEngineThreadCtxDeinit(NULL, new_det_ctx[i]);
2454  }
2455  return -1;
2456 }
2457 
2458 static DetectEngineCtx *DetectEngineCtxInitReal(
2459  enum DetectEngineType type, const char *prefix, uint32_t tenant_id)
2460 {
2462  if (unlikely(de_ctx == NULL))
2463  goto error;
2464 
2465  memset(&de_ctx->sig_stat, 0, sizeof(SigFileLoaderStat));
2466  TAILQ_INIT(&de_ctx->sig_stat.failed_sigs);
2467  de_ctx->sigerror = NULL;
2468  de_ctx->type = type;
2470  de_ctx->tenant_id = tenant_id;
2471 
2474  SCLogDebug("stub %u with version %u", type, de_ctx->version);
2475  return de_ctx;
2476  }
2477 
2478  if (prefix != NULL) {
2479  strlcpy(de_ctx->config_prefix, prefix, sizeof(de_ctx->config_prefix));
2480  }
2481 
2482  int failure_fatal = 0;
2483  if (ConfGetBool("engine.init-failure-fatal", (int *)&failure_fatal) != 1) {
2484  SCLogDebug("ConfGetBool could not load the value.");
2485  }
2486  de_ctx->failure_fatal = (failure_fatal == 1);
2487 
2490  SCLogConfig("pattern matchers: MPM: %s, SPM: %s",
2493 
2495  if (de_ctx->spm_global_thread_ctx == NULL) {
2496  SCLogDebug("Unable to alloc SpmGlobalThreadCtx.");
2497  goto error;
2498  }
2499 
2501  if (de_ctx->sm_types_prefilter == NULL) {
2502  goto error;
2503  }
2505  if (de_ctx->sm_types_silent_error == NULL) {
2506  goto error;
2507  }
2508  if (DetectEngineCtxLoadConf(de_ctx) == -1) {
2509  goto error;
2510  }
2511 
2517  DetectBufferTypeSetupDetectEngine(de_ctx);
2519 
2520  /* init iprep... ignore errors for now */
2521  (void)SRepInit(de_ctx);
2522 
2526  goto error;
2527  }
2528 
2529  if (ActionInitConfig() < 0) {
2530  goto error;
2531  }
2533  if (SCRConfLoadReferenceConfigFile(de_ctx, NULL) < 0) {
2535  goto error;
2536  }
2537 
2539  SCLogDebug("dectx with version %u", de_ctx->version);
2540  return de_ctx;
2541 error:
2542  if (de_ctx != NULL) {
2544  }
2545  return NULL;
2546 }
2547 
2549 {
2550  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_MT_STUB, NULL, 0);
2551 }
2552 
2554 {
2555  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_DD_STUB, NULL, 0);
2556 }
2557 
2559 {
2560  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_NORMAL, NULL, 0);
2561 }
2562 
2563 DetectEngineCtx *DetectEngineCtxInitWithPrefix(const char *prefix, uint32_t tenant_id)
2564 {
2565  if (prefix == NULL || strlen(prefix) == 0)
2566  return DetectEngineCtxInit();
2567  else
2568  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_NORMAL, prefix, tenant_id);
2569 }
2570 
2571 static void DetectEngineCtxFreeThreadKeywordData(DetectEngineCtx *de_ctx)
2572 {
2574 }
2575 
2576 static void DetectEngineCtxFreeFailedSigs(DetectEngineCtx *de_ctx)
2577 {
2578  SigString *item = NULL;
2579  SigString *sitem;
2580 
2581  TAILQ_FOREACH_SAFE(item, &de_ctx->sig_stat.failed_sigs, next, sitem) {
2582  SCFree(item->filename);
2583  SCFree(item->sig_str);
2584  if (item->sig_error) {
2585  SCFree(item->sig_error);
2586  }
2587  TAILQ_REMOVE(&de_ctx->sig_stat.failed_sigs, item, next);
2588  SCFree(item);
2589  }
2590 }
2591 
2592 /**
2593  * \brief Free a DetectEngineCtx::
2594  *
2595  * \param de_ctx DetectEngineCtx:: to be freed
2596  */
2598 {
2599 
2600  if (de_ctx == NULL)
2601  return;
2602 
2603 #ifdef PROFILE_RULES
2604  if (de_ctx->profile_ctx != NULL) {
2605  SCProfilingRuleDestroyCtx(de_ctx->profile_ctx);
2606  de_ctx->profile_ctx = NULL;
2607  }
2608 #endif
2609 #ifdef PROFILING
2610  if (de_ctx->profile_keyword_ctx != NULL) {
2611  SCProfilingKeywordDestroyCtx(de_ctx);//->profile_keyword_ctx);
2612 // de_ctx->profile_keyword_ctx = NULL;
2613  }
2614  if (de_ctx->profile_sgh_ctx != NULL) {
2616  }
2618 #endif
2619 
2620  /* Normally the hashes are freed elsewhere, but
2621  * to be sure look at them again here.
2622  */
2628  if (de_ctx->sig_array)
2630 
2631  if (de_ctx->filedata_config)
2633 
2637 
2639 
2643 
2645 
2646  DetectEngineCtxFreeThreadKeywordData(de_ctx);
2648  DetectEngineCtxFreeFailedSigs(de_ctx);
2649 
2652 
2653  /* if we have a config prefix, remove the config from the tree */
2654  if (strlen(de_ctx->config_prefix) > 0) {
2655  /* remove config */
2657  if (node != NULL) {
2658  ConfNodeRemove(node); /* frees node */
2659  }
2660 #if 0
2661  ConfDump();
2662 #endif
2663  }
2664 
2667 
2668  DetectBufferTypeFreeDetectEngine(de_ctx);
2671 
2672  if (de_ctx->tenant_path) {
2674  }
2675 
2676  if (de_ctx->requirements) {
2677  SCDetectRequiresStatusFree(de_ctx->requirements);
2678  }
2679 
2680  SCFree(de_ctx);
2681  //DetectAddressGroupPrintMemory();
2682  //DetectSigGroupPrintMemory();
2683  //DetectPortPrintMemory();
2684 }
2685 
2686 /** \brief Function that load DetectEngineCtx config for grouping sigs
2687  * used by the engine
2688  * \retval 0 if no config provided, 1 if config was provided
2689  * and loaded successfully
2690  */
2691 static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
2692 {
2693  uint8_t profile = ENGINE_PROFILE_MEDIUM;
2694  const char *max_uniq_toclient_groups_str = NULL;
2695  const char *max_uniq_toserver_groups_str = NULL;
2696  const char *sgh_mpm_context = NULL;
2697  const char *de_ctx_profile = NULL;
2698 
2699  (void)ConfGet("detect.profile", &de_ctx_profile);
2700  (void)ConfGet("detect.sgh-mpm-context", &sgh_mpm_context);
2701 
2702  ConfNode *de_ctx_custom = ConfGetNode("detect-engine");
2703  ConfNode *opt = NULL;
2704 
2705  if (de_ctx_custom != NULL) {
2706  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
2707  if (de_ctx_profile == NULL) {
2708  if (opt->val && strcmp(opt->val, "profile") == 0) {
2709  de_ctx_profile = opt->head.tqh_first->val;
2710  }
2711  }
2712 
2713  if (sgh_mpm_context == NULL) {
2714  if (opt->val && strcmp(opt->val, "sgh-mpm-context") == 0) {
2715  sgh_mpm_context = opt->head.tqh_first->val;
2716  }
2717  }
2718  }
2719  }
2720 
2721  if (de_ctx_profile != NULL) {
2722  if (strcmp(de_ctx_profile, "low") == 0 ||
2723  strcmp(de_ctx_profile, "lowest") == 0) { // legacy
2724  profile = ENGINE_PROFILE_LOW;
2725  } else if (strcmp(de_ctx_profile, "medium") == 0) {
2726  profile = ENGINE_PROFILE_MEDIUM;
2727  } else if (strcmp(de_ctx_profile, "high") == 0 ||
2728  strcmp(de_ctx_profile, "highest") == 0) { // legacy
2729  profile = ENGINE_PROFILE_HIGH;
2730  } else if (strcmp(de_ctx_profile, "custom") == 0) {
2731  profile = ENGINE_PROFILE_CUSTOM;
2732  } else {
2733  SCLogError("invalid value for detect.profile: '%s'. "
2734  "Valid options: low, medium, high and custom.",
2735  de_ctx_profile);
2736  return -1;
2737  }
2738 
2739  SCLogDebug("Profile for detection engine groups is \"%s\"", de_ctx_profile);
2740  } else {
2741  SCLogDebug("Profile for detection engine groups not provided "
2742  "at suricata.yaml. Using default (\"medium\").");
2743  }
2744 
2745  /* detect-engine.sgh-mpm-context option parsing */
2746  if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context, "auto") == 0) {
2747  /* for now, since we still haven't implemented any intelligence into
2748  * understanding the patterns and distributing mpm_ctx across sgh */
2750  de_ctx->mpm_matcher == MPM_HS) {
2752  } else {
2754  }
2755  } else {
2756  if (strcmp(sgh_mpm_context, "single") == 0) {
2758  } else if (strcmp(sgh_mpm_context, "full") == 0) {
2760  } else {
2761  SCLogError("You have supplied an "
2762  "invalid conf value for detect-engine.sgh-mpm-context-"
2763  "%s",
2764  sgh_mpm_context);
2765  exit(EXIT_FAILURE);
2766  }
2767  }
2768 
2769  if (RunmodeIsUnittests()) {
2771  }
2772 
2773  /* parse profile custom-values */
2774  opt = NULL;
2775  switch (profile) {
2776  case ENGINE_PROFILE_LOW:
2779  break;
2780 
2781  case ENGINE_PROFILE_HIGH:
2784  break;
2785 
2786  case ENGINE_PROFILE_CUSTOM:
2787  (void)ConfGet("detect.custom-values.toclient-groups",
2788  &max_uniq_toclient_groups_str);
2789  (void)ConfGet("detect.custom-values.toserver-groups",
2790  &max_uniq_toserver_groups_str);
2791 
2792  if (de_ctx_custom != NULL) {
2793  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
2794  if (opt->val && strcmp(opt->val, "custom-values") == 0) {
2795  if (max_uniq_toclient_groups_str == NULL) {
2796  max_uniq_toclient_groups_str = (char *)ConfNodeLookupChildValue
2797  (opt->head.tqh_first, "toclient-sp-groups");
2798  }
2799  if (max_uniq_toclient_groups_str == NULL) {
2800  max_uniq_toclient_groups_str = (char *)ConfNodeLookupChildValue
2801  (opt->head.tqh_first, "toclient-groups");
2802  }
2803  if (max_uniq_toserver_groups_str == NULL) {
2804  max_uniq_toserver_groups_str = (char *)ConfNodeLookupChildValue
2805  (opt->head.tqh_first, "toserver-dp-groups");
2806  }
2807  if (max_uniq_toserver_groups_str == NULL) {
2808  max_uniq_toserver_groups_str = (char *)ConfNodeLookupChildValue
2809  (opt->head.tqh_first, "toserver-groups");
2810  }
2811  }
2812  }
2813  }
2814  if (max_uniq_toclient_groups_str != NULL) {
2816  (uint16_t)strlen(max_uniq_toclient_groups_str),
2817  (const char *)max_uniq_toclient_groups_str) <= 0) {
2819 
2820  SCLogWarning("parsing '%s' for "
2821  "toclient-groups failed, using %u",
2822  max_uniq_toclient_groups_str, de_ctx->max_uniq_toclient_groups);
2823  }
2824  } else {
2826  }
2827  SCLogConfig("toclient-groups %u", de_ctx->max_uniq_toclient_groups);
2828 
2829  if (max_uniq_toserver_groups_str != NULL) {
2831  (uint16_t)strlen(max_uniq_toserver_groups_str),
2832  (const char *)max_uniq_toserver_groups_str) <= 0) {
2834 
2835  SCLogWarning("parsing '%s' for "
2836  "toserver-groups failed, using %u",
2837  max_uniq_toserver_groups_str, de_ctx->max_uniq_toserver_groups);
2838  }
2839  } else {
2841  }
2842  SCLogConfig("toserver-groups %u", de_ctx->max_uniq_toserver_groups);
2843  break;
2844 
2845  /* Default (or no config provided) is profile medium */
2846  case ENGINE_PROFILE_MEDIUM:
2848  default:
2851  break;
2852  }
2853 
2854  intmax_t value = 0;
2855  if (ConfGetInt("detect.inspection-recursion-limit", &value) == 1)
2856  {
2857  if (value >= 0 && value <= INT_MAX) {
2858  de_ctx->inspection_recursion_limit = (int)value;
2859  }
2860 
2861  /* fall back to old config parsing */
2862  } else {
2863  ConfNode *insp_recursion_limit_node = NULL;
2864  char *insp_recursion_limit = NULL;
2865 
2866  if (de_ctx_custom != NULL) {
2867  opt = NULL;
2868  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
2869  if (opt->val && strcmp(opt->val, "inspection-recursion-limit") != 0)
2870  continue;
2871 
2872  insp_recursion_limit_node = ConfNodeLookupChild(opt, opt->val);
2873  if (insp_recursion_limit_node == NULL) {
2874  SCLogError("Error retrieving conf "
2875  "entry for detect-engine:inspection-recursion-limit");
2876  break;
2877  }
2878  insp_recursion_limit = insp_recursion_limit_node->val;
2879  SCLogDebug("Found detect-engine.inspection-recursion-limit - %s:%s",
2880  insp_recursion_limit_node->name, insp_recursion_limit_node->val);
2881  break;
2882  }
2883 
2884  if (insp_recursion_limit != NULL) {
2886  0, (const char *)insp_recursion_limit) < 0) {
2887  SCLogWarning("Invalid value for "
2888  "detect-engine.inspection-recursion-limit: %s "
2889  "resetting to %d",
2890  insp_recursion_limit, DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT);
2893  }
2894  } else {
2897  }
2898  }
2899  }
2900 
2903 
2904  SCLogDebug("de_ctx->inspection_recursion_limit: %d",
2906 
2907  /* parse port grouping whitelisting settings */
2908 
2909  const char *ports = NULL;
2910  (void)ConfGet("detect.grouping.tcp-whitelist", &ports);
2911  if (ports) {
2912  SCLogConfig("grouping: tcp-whitelist %s", ports);
2913  } else {
2914  ports = "53, 80, 139, 443, 445, 1433, 3306, 3389, 6666, 6667, 8080";
2915  SCLogConfig("grouping: tcp-whitelist (default) %s", ports);
2916 
2917  }
2918  if (DetectPortParse(de_ctx, &de_ctx->tcp_whitelist, ports) != 0) {
2919  SCLogWarning("'%s' is not a valid value "
2920  "for detect.grouping.tcp-whitelist",
2921  ports);
2922  }
2924  for ( ; x != NULL; x = x->next) {
2925  if (x->port != x->port2) {
2926  SCLogWarning("'%s' is not a valid value "
2927  "for detect.grouping.tcp-whitelist: only single ports allowed",
2928  ports);
2930  de_ctx->tcp_whitelist = NULL;
2931  break;
2932  }
2933  }
2934 
2935  ports = NULL;
2936  (void)ConfGet("detect.grouping.udp-whitelist", &ports);
2937  if (ports) {
2938  SCLogConfig("grouping: udp-whitelist %s", ports);
2939  } else {
2940  ports = "53, 135, 5060";
2941  SCLogConfig("grouping: udp-whitelist (default) %s", ports);
2942 
2943  }
2944  if (DetectPortParse(de_ctx, &de_ctx->udp_whitelist, ports) != 0) {
2945  SCLogWarning("'%s' is not a valid value "
2946  "for detect.grouping.udp-whitelist",
2947  ports);
2948  }
2949  for (x = de_ctx->udp_whitelist; x != NULL; x = x->next) {
2950  if (x->port != x->port2) {
2951  SCLogWarning("'%s' is not a valid value "
2952  "for detect.grouping.udp-whitelist: only single ports allowed",
2953  ports);
2955  de_ctx->udp_whitelist = NULL;
2956  break;
2957  }
2958  }
2959 
2961  const char *pf_setting = NULL;
2962  if (ConfGet("detect.prefilter.default", &pf_setting) == 1 && pf_setting) {
2963  if (strcasecmp(pf_setting, "mpm") == 0) {
2965  } else if (strcasecmp(pf_setting, "auto") == 0) {
2967  }
2968  }
2969  switch (de_ctx->prefilter_setting) {
2970  case DETECT_PREFILTER_MPM:
2971  SCLogConfig("prefilter engines: MPM");
2972  break;
2973  case DETECT_PREFILTER_AUTO:
2974  SCLogConfig("prefilter engines: MPM and keywords");
2975  break;
2976  }
2977 
2978  return 0;
2979 }
2980 
2981 /*
2982  * getting & (re)setting the internal sig i
2983  */
2984 
2985 //inline uint32_t DetectEngineGetMaxSigId(DetectEngineCtx *de_ctx)
2986 //{
2987 // return de_ctx->signum;
2988 //}
2989 
2991 {
2992  de_ctx->signum = 0;
2993 }
2994 
2995 static int DetectEngineThreadCtxInitGlobalKeywords(DetectEngineThreadCtx *det_ctx)
2996 {
2997  const DetectEngineMasterCtx *master = &g_master_de_ctx;
2998 
2999  if (master->keyword_id > 0) {
3000  // coverity[suspicious_sizeof : FALSE]
3001  det_ctx->global_keyword_ctxs_array = (void **)SCCalloc(master->keyword_id, sizeof(void *));
3002  if (det_ctx->global_keyword_ctxs_array == NULL) {
3003  SCLogError("setting up thread local detect ctx");
3004  return TM_ECODE_FAILED;
3005  }
3006  det_ctx->global_keyword_ctxs_size = master->keyword_id;
3007 
3008  const DetectEngineThreadKeywordCtxItem *item = master->keyword_list;
3009  while (item) {
3010  det_ctx->global_keyword_ctxs_array[item->id] = item->InitFunc(item->data);
3011  if (det_ctx->global_keyword_ctxs_array[item->id] == NULL) {
3012  SCLogError("setting up thread local detect ctx "
3013  "for keyword \"%s\" failed",
3014  item->name);
3015  return TM_ECODE_FAILED;
3016  }
3017  item = item->next;
3018  }
3019  }
3020  return TM_ECODE_OK;
3021 }
3022 
3023 static void DetectEngineThreadCtxDeinitGlobalKeywords(DetectEngineThreadCtx *det_ctx)
3024 {
3025  if (det_ctx->global_keyword_ctxs_array == NULL ||
3026  det_ctx->global_keyword_ctxs_size == 0) {
3027  return;
3028  }
3029 
3030  const DetectEngineMasterCtx *master = &g_master_de_ctx;
3031  if (master->keyword_id > 0) {
3032  const DetectEngineThreadKeywordCtxItem *item = master->keyword_list;
3033  while (item) {
3034  if (det_ctx->global_keyword_ctxs_array[item->id] != NULL)
3035  item->FreeFunc(det_ctx->global_keyword_ctxs_array[item->id]);
3036 
3037  item = item->next;
3038  }
3039  det_ctx->global_keyword_ctxs_size = 0;
3041  det_ctx->global_keyword_ctxs_array = NULL;
3042  }
3043 }
3044 
3045 static int DetectEngineThreadCtxInitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
3046 {
3047  if (de_ctx->keyword_id > 0) {
3048  // coverity[suspicious_sizeof : FALSE]
3049  det_ctx->keyword_ctxs_array = SCCalloc(de_ctx->keyword_id, sizeof(void *));
3050  if (det_ctx->keyword_ctxs_array == NULL) {
3051  SCLogError("setting up thread local detect ctx");
3052  return TM_ECODE_FAILED;
3053  }
3054 
3055  det_ctx->keyword_ctxs_size = de_ctx->keyword_id;
3056 
3058  for (; hb != NULL; hb = HashListTableGetListNext(hb)) {
3060 
3061  det_ctx->keyword_ctxs_array[item->id] = item->InitFunc(item->data);
3062  if (det_ctx->keyword_ctxs_array[item->id] == NULL) {
3063  SCLogError("setting up thread local detect ctx "
3064  "for keyword \"%s\" failed",
3065  item->name);
3066  return TM_ECODE_FAILED;
3067  }
3068  }
3069  }
3070  return TM_ECODE_OK;
3071 }
3072 
3073 static void DetectEngineThreadCtxDeinitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
3074 {
3075  if (de_ctx->keyword_id > 0) {
3077  for (; hb != NULL; hb = HashListTableGetListNext(hb)) {
3079 
3080  if (det_ctx->keyword_ctxs_array[item->id] != NULL)
3081  item->FreeFunc(det_ctx->keyword_ctxs_array[item->id]);
3082  }
3083  det_ctx->keyword_ctxs_size = 0;
3084  SCFree(det_ctx->keyword_ctxs_array);
3085  det_ctx->keyword_ctxs_array = NULL;
3086  }
3087 }
3088 
3089 /** NOTE: master MUST be locked before calling this */
3090 static TmEcode DetectEngineThreadCtxInitForMT(ThreadVars *tv, DetectEngineThreadCtx *det_ctx)
3091 {
3092  DetectEngineMasterCtx *master = &g_master_de_ctx;
3093  DetectEngineTenantMapping *map_array = NULL;
3094  uint32_t map_array_size = 0;
3095  uint32_t map_cnt = 0;
3096  uint32_t max_tenant_id = 0;
3097  DetectEngineCtx *list = master->list;
3098  HashTable *mt_det_ctxs_hash = NULL;
3099 
3100  if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
3101  SCLogError("no tenant selector set: "
3102  "set using multi-detect.selector");
3103  return TM_ECODE_FAILED;
3104  }
3105 
3106  uint32_t tcnt = 0;
3107  while (list) {
3108  if (list->tenant_id > max_tenant_id)
3109  max_tenant_id = list->tenant_id;
3110 
3111  list = list->next;
3112  tcnt++;
3113  }
3114 
3115  mt_det_ctxs_hash = HashTableInit(tcnt * 2, TenantIdHash, TenantIdCompare, TenantIdFree);
3116  if (mt_det_ctxs_hash == NULL) {
3117  goto error;
3118  }
3119 
3120  if (tcnt == 0) {
3121  SCLogInfo("no tenants left, or none registered yet");
3122  } else {
3123  max_tenant_id++;
3124 
3126  while (map) {
3127  map_cnt++;
3128  map = map->next;
3129  }
3130 
3131  if (map_cnt > 0) {
3132  map_array_size = map_cnt + 1;
3133 
3134  map_array = SCCalloc(map_array_size, sizeof(*map_array));
3135  if (map_array == NULL)
3136  goto error;
3137 
3138  /* fill the array */
3139  map_cnt = 0;
3140  map = master->tenant_mapping_list;
3141  while (map) {
3142  if (map_cnt >= map_array_size) {
3143  goto error;
3144  }
3145  map_array[map_cnt].traffic_id = map->traffic_id;
3146  map_array[map_cnt].tenant_id = map->tenant_id;
3147  map_cnt++;
3148  map = map->next;
3149  }
3150 
3151  }
3152 
3153  /* set up hash for tenant lookup */
3154  list = master->list;
3155  while (list) {
3156  SCLogDebug("tenant-id %u", list->tenant_id);
3157  if (list->tenant_id != 0) {
3159  if (mt_det_ctx == NULL)
3160  goto error;
3161  if (HashTableAdd(mt_det_ctxs_hash, mt_det_ctx, 0) != 0) {
3162  goto error;
3163  }
3164  }
3165  list = list->next;
3166  }
3167  }
3168 
3169  det_ctx->mt_det_ctxs_hash = mt_det_ctxs_hash;
3170  mt_det_ctxs_hash = NULL;
3171 
3172  det_ctx->mt_det_ctxs_cnt = max_tenant_id;
3173 
3174  det_ctx->tenant_array = map_array;
3175  det_ctx->tenant_array_size = map_array_size;
3176 
3177  switch (master->tenant_selector) {
3179  SCLogDebug("TENANT_SELECTOR_UNKNOWN");
3180  break;
3181  case TENANT_SELECTOR_VLAN:
3182  det_ctx->TenantGetId = DetectEngineTenantGetIdFromVlanId;
3183  SCLogDebug("TENANT_SELECTOR_VLAN");
3184  break;
3186  det_ctx->TenantGetId = DetectEngineTenantGetIdFromLivedev;
3187  SCLogDebug("TENANT_SELECTOR_LIVEDEV");
3188  break;
3190  det_ctx->TenantGetId = DetectEngineTenantGetIdFromPcap;
3191  SCLogDebug("TENANT_SELECTOR_DIRECT");
3192  break;
3193  }
3194 
3195  return TM_ECODE_OK;
3196 error:
3197  if (map_array != NULL)
3198  SCFree(map_array);
3199  if (mt_det_ctxs_hash != NULL)
3200  HashTableFree(mt_det_ctxs_hash);
3201 
3202  return TM_ECODE_FAILED;
3203 }
3204 
3205 /** \internal
3206  * \brief Helper for DetectThread setup functions
3207  */
3208 static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
3209 {
3211 
3212  PmqSetup(&det_ctx->pmq);
3213 
3215  if (det_ctx->spm_thread_ctx == NULL) {
3216  return TM_ECODE_FAILED;
3217  }
3218 
3219  /* sized to the max of our sgh settings. A max setting of 0 implies that all
3220  * sgh's have: sgh->non_pf_store_cnt == 0 */
3221  if (de_ctx->non_pf_store_cnt_max > 0) {
3223  BUG_ON(det_ctx->non_pf_id_array == NULL);
3224  }
3225 
3226  /* DeState */
3227  if (de_ctx->sig_array_len > 0) {
3228  det_ctx->match_array_len = de_ctx->sig_array_len;
3229  det_ctx->match_array = SCCalloc(det_ctx->match_array_len, sizeof(Signature *));
3230  if (det_ctx->match_array == NULL) {
3231  return TM_ECODE_FAILED;
3232  }
3233 
3235  }
3236 
3237  /* Alert processing queue */
3238  AlertQueueInit(det_ctx);
3239 
3240  /* byte_extract storage */
3241  det_ctx->byte_values = SCMalloc(sizeof(*det_ctx->byte_values) *
3243  if (det_ctx->byte_values == NULL) {
3244  return TM_ECODE_FAILED;
3245  }
3246 
3247  /* Allocate space for base64 decoded data. */
3250  if (det_ctx->base64_decoded == NULL) {
3251  return TM_ECODE_FAILED;
3252  }
3254  det_ctx->base64_decoded_len = 0;
3255  }
3256 
3258  det_ctx->inspect.buffers = SCCalloc(det_ctx->inspect.buffers_size, sizeof(InspectionBuffer));
3259  if (det_ctx->inspect.buffers == NULL) {
3260  return TM_ECODE_FAILED;
3261  }
3262  det_ctx->inspect.to_clear_queue = SCCalloc(det_ctx->inspect.buffers_size, sizeof(uint32_t));
3263  if (det_ctx->inspect.to_clear_queue == NULL) {
3264  return TM_ECODE_FAILED;
3265  }
3266  det_ctx->inspect.to_clear_idx = 0;
3267 
3270  if (det_ctx->multi_inspect.buffers == NULL) {
3271  return TM_ECODE_FAILED;
3272  }
3273  det_ctx->multi_inspect.to_clear_queue = SCCalloc(det_ctx->multi_inspect.buffers_size, sizeof(uint32_t));
3274  if (det_ctx->multi_inspect.to_clear_queue == NULL) {
3275  return TM_ECODE_FAILED;
3276  }
3277  det_ctx->multi_inspect.to_clear_idx = 0;
3278 
3279 
3280  DetectEngineThreadCtxInitKeywords(de_ctx, det_ctx);
3281  DetectEngineThreadCtxInitGlobalKeywords(det_ctx);
3282 #ifdef PROFILE_RULES
3283  SCProfilingRuleThreadSetup(de_ctx->profile_ctx, det_ctx);
3284 #endif
3285 #ifdef PROFILING
3289 #endif
3290  SC_ATOMIC_INIT(det_ctx->so_far_used_by_detect);
3291 
3292  return TM_ECODE_OK;
3293 }
3294 
3295 /** \brief initialize thread specific detection engine context
3296  *
3297  * \note there is a special case when using delayed detect. In this case the
3298  * function is called twice per thread. The first time the rules are not
3299  * yet loaded. de_ctx->delayed_detect_initialized will be 0. The 2nd
3300  * time they will be loaded. de_ctx->delayed_detect_initialized will be 1.
3301  * This is needed to do the per thread counter registration before the
3302  * packet runtime starts. In delayed detect mode, the first call will
3303  * return a NULL ptr through the data ptr.
3304  *
3305  * \param tv ThreadVars for this thread
3306  * \param initdata pointer to de_ctx
3307  * \param data[out] pointer to store our thread detection ctx
3308  *
3309  * \retval TM_ECODE_OK if all went well
3310  * \retval TM_ECODE_FAILED on serious errors
3311  */
3312 TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
3313 {
3314  DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(DetectEngineThreadCtx));
3315  if (unlikely(det_ctx == NULL))
3316  return TM_ECODE_FAILED;
3317 
3318  det_ctx->tv = tv;
3319  det_ctx->de_ctx = DetectEngineGetCurrent();
3320  if (det_ctx->de_ctx == NULL) {
3321 #ifdef UNITTESTS
3322  if (RunmodeIsUnittests()) {
3323  det_ctx->de_ctx = (DetectEngineCtx *)initdata;
3324  } else {
3325  DetectEngineThreadCtxDeinit(tv, det_ctx);
3326  return TM_ECODE_FAILED;
3327  }
3328 #else
3329  DetectEngineThreadCtxDeinit(tv, det_ctx);
3330  return TM_ECODE_FAILED;
3331 #endif
3332  }
3333 
3334  if (det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
3335  det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_TENANT)
3336  {
3337  if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
3338  DetectEngineThreadCtxDeinit(tv, det_ctx);
3339  return TM_ECODE_FAILED;
3340  }
3341  }
3342 
3343  /** alert counter setup */
3344  det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", tv);
3345  det_ctx->counter_alerts_overflow = StatsRegisterCounter("detect.alert_queue_overflow", tv);
3346  det_ctx->counter_alerts_suppressed = StatsRegisterCounter("detect.alerts_suppressed", tv);
3347 
3348  /* Register counter for Lua rule errors. */
3349  det_ctx->lua_rule_errors = StatsRegisterCounter("detect.lua.errors", tv);
3350 
3351  /* Register a counter for Lua blocked function attempts. */
3352  det_ctx->lua_blocked_function_errors =
3353  StatsRegisterCounter("detect.lua.blocked_function_errors", tv);
3354 
3355  /* Register a counter for Lua instruction limit errors. */
3356  det_ctx->lua_instruction_limit_errors =
3357  StatsRegisterCounter("detect.lua.instruction_limit_errors", tv);
3358 
3359  /* Register a counter for Lua memory limit errors. */
3360  det_ctx->lua_memory_limit_errors = StatsRegisterCounter("detect.lua.memory_limit_errors", tv);
3361 
3362 #ifdef PROFILING
3363  det_ctx->counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
3364  det_ctx->counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
3365  det_ctx->counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
3366  det_ctx->counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
3367 #endif
3368 
3370  if (DetectEngineThreadCtxInitForMT(tv, det_ctx) != TM_ECODE_OK) {
3371  DetectEngineThreadCtxDeinit(tv, det_ctx);
3372  return TM_ECODE_FAILED;
3373  }
3374  }
3375 
3376  /* pass thread data back to caller */
3377  *data = (void *)det_ctx;
3378 
3379  return TM_ECODE_OK;
3380 }
3381 
3382 /**
3383  * \internal
3384  * \brief initialize a det_ctx for reload cases
3385  * \param new_de_ctx the new detection engine
3386  * \param mt flag to indicate if MT should be set up for this det_ctx
3387  * this should only be done for the 'root' det_ctx
3388  *
3389  * \retval det_ctx detection engine thread ctx or NULL in case of error
3390  */
3392  ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
3393 {
3394  DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(DetectEngineThreadCtx));
3395  if (unlikely(det_ctx == NULL))
3396  return NULL;
3397 
3398  det_ctx->tenant_id = new_de_ctx->tenant_id;
3399  det_ctx->tv = tv;
3400  det_ctx->de_ctx = DetectEngineReference(new_de_ctx);
3401  if (det_ctx->de_ctx == NULL) {
3402  SCFree(det_ctx);
3403  return NULL;
3404  }
3405 
3406  /* most of the init happens here */
3407  if (det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
3408  det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_TENANT)
3409  {
3410  if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
3411  DetectEngineDeReference(&det_ctx->de_ctx);
3412  SCFree(det_ctx);
3413  return NULL;
3414  }
3415  }
3416 
3417  /** alert counter setup */
3418  det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", tv);
3419  det_ctx->counter_alerts_overflow = StatsRegisterCounter("detect.alert_queue_overflow", tv);
3420  det_ctx->counter_alerts_suppressed = StatsRegisterCounter("detect.alerts_suppressed", tv);
3421 #ifdef PROFILING
3422  uint16_t counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", tv);
3423  uint16_t counter_nonmpm_list = StatsRegisterAvgCounter("detect.nonmpm_list", tv);
3424  uint16_t counter_fnonmpm_list = StatsRegisterAvgCounter("detect.fnonmpm_list", tv);
3425  uint16_t counter_match_list = StatsRegisterAvgCounter("detect.match_list", tv);
3426  det_ctx->counter_mpm_list = counter_mpm_list;
3427  det_ctx->counter_nonmpm_list = counter_nonmpm_list;
3428  det_ctx->counter_fnonmpm_list = counter_fnonmpm_list;
3429  det_ctx->counter_match_list = counter_match_list;
3430 #endif
3431 
3432  if (mt && DetectEngineMultiTenantEnabled()) {
3433  if (DetectEngineThreadCtxInitForMT(tv, det_ctx) != TM_ECODE_OK) {
3434  DetectEngineDeReference(&det_ctx->de_ctx);
3435  SCFree(det_ctx);
3436  return NULL;
3437  }
3438  }
3439 
3440  return det_ctx;
3441 }
3442 
3443 static void DetectEngineThreadCtxFree(DetectEngineThreadCtx *det_ctx)
3444 {
3445 #if DEBUG
3446  SCLogDebug("PACKET PKT_STREAM_ADD: %"PRIu64, det_ctx->pkt_stream_add_cnt);
3447 
3448  SCLogDebug("PAYLOAD MPM %"PRIu64"/%"PRIu64, det_ctx->payload_mpm_cnt, det_ctx->payload_mpm_size);
3449  SCLogDebug("STREAM MPM %"PRIu64"/%"PRIu64, det_ctx->stream_mpm_cnt, det_ctx->stream_mpm_size);
3450 
3451  SCLogDebug("PAYLOAD SIG %"PRIu64"/%"PRIu64, det_ctx->payload_persig_cnt, det_ctx->payload_persig_size);
3452  SCLogDebug("STREAM SIG %"PRIu64"/%"PRIu64, det_ctx->stream_persig_cnt, det_ctx->stream_persig_size);
3453 #endif
3454 
3455  if (det_ctx->tenant_array != NULL) {
3456  SCFree(det_ctx->tenant_array);
3457  det_ctx->tenant_array = NULL;
3458  }
3459 
3460 #ifdef PROFILE_RULES
3462 #endif
3463 #ifdef PROFILING
3466  SCProfilingSghThreadCleanup(det_ctx);
3467 #endif
3468 
3469  /** \todo get rid of this static */
3470  if (det_ctx->de_ctx != NULL) {
3471  PatternMatchThreadDestroy(&det_ctx->mtc, det_ctx->de_ctx->mpm_matcher);
3472  }
3473 
3474  PmqFree(&det_ctx->pmq);
3475 
3476  if (det_ctx->spm_thread_ctx != NULL) {
3478  }
3479 
3480  if (det_ctx->non_pf_id_array != NULL)
3481  SCFree(det_ctx->non_pf_id_array);
3482 
3483  if (det_ctx->match_array != NULL)
3484  SCFree(det_ctx->match_array);
3485 
3487 
3488  AlertQueueFree(det_ctx);
3489 
3490  if (det_ctx->byte_values != NULL)
3491  SCFree(det_ctx->byte_values);
3492 
3493  /* Decoded base64 data. */
3494  if (det_ctx->base64_decoded != NULL) {
3495  SCFree(det_ctx->base64_decoded);
3496  }
3497 
3498  if (det_ctx->inspect.buffers) {
3499  for (uint32_t i = 0; i < det_ctx->inspect.buffers_size; i++) {
3500  InspectionBufferFree(&det_ctx->inspect.buffers[i]);
3501  }
3502  SCFree(det_ctx->inspect.buffers);
3503  }
3504  if (det_ctx->inspect.to_clear_queue) {
3505  SCFree(det_ctx->inspect.to_clear_queue);
3506  }
3507  if (det_ctx->multi_inspect.buffers) {
3508  for (uint32_t i = 0; i < det_ctx->multi_inspect.buffers_size; i++) {
3510  for (uint32_t x = 0; x < fb->size; x++) {
3512  }
3514  }
3515  SCFree(det_ctx->multi_inspect.buffers);
3516  }
3517  if (det_ctx->multi_inspect.to_clear_queue) {
3519  }
3520 
3521  DetectEngineThreadCtxDeinitGlobalKeywords(det_ctx);
3522  if (det_ctx->de_ctx != NULL) {
3523  DetectEngineThreadCtxDeinitKeywords(det_ctx->de_ctx, det_ctx);
3524 #ifdef UNITTESTS
3525  if (!RunmodeIsUnittests() || det_ctx->de_ctx->ref_cnt > 0)
3526  DetectEngineDeReference(&det_ctx->de_ctx);
3527 #else
3528  DetectEngineDeReference(&det_ctx->de_ctx);
3529 #endif
3530  }
3531 
3533 
3534  SCFree(det_ctx);
3535 
3537 }
3538 
3540 {
3541  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
3542 
3543  if (det_ctx == NULL) {
3544  SCLogWarning("argument \"data\" NULL");
3545  return TM_ECODE_OK;
3546  }
3547 
3548  if (det_ctx->mt_det_ctxs_hash != NULL) {
3549  HashTableFree(det_ctx->mt_det_ctxs_hash);
3550  det_ctx->mt_det_ctxs_hash = NULL;
3551  }
3552  DetectEngineThreadCtxFree(det_ctx);
3553 
3554  return TM_ECODE_OK;
3555 }
3556 
3557 static uint32_t DetectKeywordCtxHashFunc(HashListTable *ht, void *data, uint16_t datalen)
3558 {
3560  const char *name = ctx->name;
3561  uint64_t hash = StringHashDjb2((const uint8_t *)name, strlen(name)) + (ptrdiff_t)ctx->data;
3562  hash %= ht->array_size;
3563  return hash;
3564 }
3565 
3566 static char DetectKeywordCtxCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
3567 {
3568  DetectEngineThreadKeywordCtxItem *ctx1 = data1;
3569  DetectEngineThreadKeywordCtxItem *ctx2 = data2;
3570  const char *name1 = ctx1->name;
3571  const char *name2 = ctx2->name;
3572  return (strcmp(name1, name2) == 0 && ctx1->data == ctx2->data);
3573 }
3574 
3575 static void DetectKeywordCtxFreeFunc(void *ptr)
3576 {
3577  SCFree(ptr);
3578 }
3579 
3580 /** \brief Register Thread keyword context Funcs
3581  *
3582  * \param de_ctx detection engine to register in
3583  * \param name keyword name for error printing
3584  * \param InitFunc function ptr
3585  * \param data keyword init data to pass to Func. Can be NULL.
3586  * \param FreeFunc function ptr
3587  * \param mode 0 normal (ctx per keyword instance) 1 shared (one ctx per det_ct)
3588  *
3589  * \retval id for retrieval of ctx at runtime
3590  * \retval -1 on error
3591  *
3592  * \note make sure "data" remains valid and it free'd elsewhere. It's
3593  * recommended to store it in the keywords global ctx so that
3594  * it's freed when the de_ctx is freed.
3595  */
3596 int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *), int mode)
3597 {
3598  BUG_ON(de_ctx == NULL || InitFunc == NULL || FreeFunc == NULL);
3599 
3600  if (de_ctx->keyword_hash == NULL) {
3601  de_ctx->keyword_hash = HashListTableInit(4096, // TODO
3602  DetectKeywordCtxHashFunc, DetectKeywordCtxCompareFunc, DetectKeywordCtxFreeFunc);
3603  BUG_ON(de_ctx->keyword_hash == NULL);
3604  }
3605 
3606  if (mode) {
3607  DetectEngineThreadKeywordCtxItem search = { .data = data, .name = name };
3608 
3610  HashListTableLookup(de_ctx->keyword_hash, (void *)&search, 0);
3611  if (item)
3612  return item->id;
3613 
3614  /* fall through */
3615  }
3616 
3618  if (unlikely(item == NULL))
3619  return -1;
3620 
3621  item->InitFunc = InitFunc;
3622  item->FreeFunc = FreeFunc;
3623  item->data = data;
3624  item->name = name;
3625  item->id = de_ctx->keyword_id++;
3626 
3627  if (HashListTableAdd(de_ctx->keyword_hash, (void *)item, 0) < 0) {
3628  SCFree(item);
3629  return -1;
3630  }
3631  return item->id;
3632 }
3633 
3634 /** \brief Remove Thread keyword context registration
3635  *
3636  * \param de_ctx detection engine to deregister from
3637  * \param det_ctx detection engine thread context to deregister from
3638  * \param data keyword init data to pass to Func. Can be NULL.
3639  * \param name keyword name for error printing
3640  *
3641  * \retval 1 Item unregistered
3642  * \retval 0 otherwise
3643  *
3644  * \note make sure "data" remains valid and it free'd elsewhere. It's
3645  * recommended to store it in the keywords global ctx so that
3646  * it's freed when the de_ctx is freed.
3647  */
3648 int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
3649 {
3650  /* might happen if we call this before a call to *Register* */
3651  if (de_ctx->keyword_hash == NULL)
3652  return 1;
3653  DetectEngineThreadKeywordCtxItem remove = { .data = data, .name = name };
3654  if (HashListTableRemove(de_ctx->keyword_hash, (void *)&remove, 0) == 0)
3655  return 1;
3656  return 0;
3657 }
3658 /** \brief Retrieve thread local keyword ctx by id
3659  *
3660  * \param det_ctx detection engine thread ctx to retrieve the ctx from
3661  * \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
3662  * keyword init.
3663  *
3664  * \retval ctx or NULL on error
3665  */
3667 {
3668  if (id < 0 || id > det_ctx->keyword_ctxs_size || det_ctx->keyword_ctxs_array == NULL)
3669  return NULL;
3670 
3671  return det_ctx->keyword_ctxs_array[id];
3672 }
3673 
3674 
3675 /** \brief Register Thread keyword context Funcs (Global)
3676  *
3677  * IDs stay static over reloads and between tenants
3678  *
3679  * \param name keyword name for error printing
3680  * \param InitFunc function ptr
3681  * \param FreeFunc function ptr
3682  *
3683  * \retval id for retrieval of ctx at runtime
3684  * \retval -1 on error
3685  */
3687  void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *))
3688 {
3689  int id;
3690  BUG_ON(InitFunc == NULL || FreeFunc == NULL);
3691 
3692  DetectEngineMasterCtx *master = &g_master_de_ctx;
3693 
3694  /* if already registered, return existing id */
3696  while (item != NULL) {
3697  if (strcmp(name, item->name) == 0) {
3698  id = item->id;
3699  return id;
3700  }
3701 
3702  item = item->next;
3703  }
3704 
3705  item = SCCalloc(1, sizeof(*item));
3706  if (unlikely(item == NULL)) {
3707  return -1;
3708  }
3709  item->InitFunc = InitFunc;
3710  item->FreeFunc = FreeFunc;
3711  item->name = name;
3712  item->data = data;
3713 
3714  item->next = master->keyword_list;
3715  master->keyword_list = item;
3716  item->id = master->keyword_id++;
3717 
3718  id = item->id;
3719  return id;
3720 }
3721 
3722 /** \brief Retrieve thread local keyword ctx by id
3723  *
3724  * \param det_ctx detection engine thread ctx to retrieve the ctx from
3725  * \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
3726  * keyword init.
3727  *
3728  * \retval ctx or NULL on error
3729  */
3731 {
3732  if (id < 0 || id > det_ctx->global_keyword_ctxs_size ||
3733  det_ctx->global_keyword_ctxs_array == NULL) {
3734  return NULL;
3735  }
3736 
3737  return det_ctx->global_keyword_ctxs_array[id];
3738 }
3739 
3740 /** \brief Check if detection is enabled
3741  * \retval bool true or false */
3743 {
3744  DetectEngineMasterCtx *master = &g_master_de_ctx;
3745  SCMutexLock(&master->lock);
3746 
3747  if (master->list == NULL) {
3748  SCMutexUnlock(&master->lock);
3749  return 0;
3750  }
3751 
3752  SCMutexUnlock(&master->lock);
3753  return 1;
3754 }
3755 
3757 {
3758  uint32_t version;
3759  DetectEngineMasterCtx *master = &g_master_de_ctx;
3760  SCMutexLock(&master->lock);
3761  version = master->version;
3762  SCMutexUnlock(&master->lock);
3763  return version;
3764 }
3765 
3767 {
3768  DetectEngineMasterCtx *master = &g_master_de_ctx;
3769  SCMutexLock(&master->lock);
3770  master->version++;
3771  SCLogDebug("master version now %u", master->version);
3772  SCMutexUnlock(&master->lock);
3773 }
3774 
3776 {
3777  DetectEngineMasterCtx *master = &g_master_de_ctx;
3778  SCMutexLock(&master->lock);
3779 
3780  DetectEngineCtx *de_ctx = master->list;
3781  while (de_ctx) {
3785  {
3786  de_ctx->ref_cnt++;
3787  SCLogDebug("de_ctx %p ref_cnt %u", de_ctx, de_ctx->ref_cnt);
3788  SCMutexUnlock(&master->lock);
3789  return de_ctx;
3790  }
3791  de_ctx = de_ctx->next;
3792  }
3793 
3794  SCMutexUnlock(&master->lock);
3795  return NULL;
3796 }
3797 
3799 {
3800  if (de_ctx == NULL)
3801  return NULL;
3802  de_ctx->ref_cnt++;
3803  return de_ctx;
3804 }
3805 
3806 /** TODO locking? Not needed if this is a one time setting at startup */
3808 {
3809  DetectEngineMasterCtx *master = &g_master_de_ctx;
3810  return (master->multi_tenant_enabled);
3811 }
3812 
3813 /** \internal
3814  * \brief load a tenant from a yaml file
3815  *
3816  * \param tenant_id the tenant id by which the config is known
3817  * \param filename full path of a yaml file
3818  * \param loader_id id of loader thread or -1
3819  *
3820  * \retval 0 ok
3821  * \retval -1 failed
3822  */
3823 static int DetectEngineMultiTenantLoadTenant(uint32_t tenant_id, const char *filename, int loader_id)
3824 {
3825  DetectEngineCtx *de_ctx = NULL;
3826  char prefix[64];
3827 
3828  snprintf(prefix, sizeof(prefix), "multi-detect.%u", tenant_id);
3829 
3830  SCStat st;
3831  if (SCStatFn(filename, &st) != 0) {
3832  SCLogError("failed to stat file %s", filename);
3833  goto error;
3834  }
3835 
3836  de_ctx = DetectEngineGetByTenantId(tenant_id);
3837  if (de_ctx != NULL) {
3838  SCLogError("tenant %u already registered", tenant_id);
3840  goto error;
3841  }
3842 
3843  ConfNode *node = ConfGetNode(prefix);
3844  if (node == NULL) {
3845  SCLogError("failed to properly setup yaml %s", filename);
3846  goto error;
3847  }
3848 
3849  de_ctx = DetectEngineCtxInitWithPrefix(prefix, tenant_id);
3850  if (de_ctx == NULL) {
3851  SCLogError("initializing detection engine "
3852  "context failed.");
3853  goto error;
3854  }
3855  SCLogDebug("de_ctx %p with prefix %s", de_ctx, de_ctx->config_prefix);
3856 
3858  de_ctx->tenant_id = tenant_id;
3859  de_ctx->loader_id = loader_id;
3860  de_ctx->tenant_path = SCStrdup(filename);
3861  if (de_ctx->tenant_path == NULL) {
3862  SCLogError("Failed to duplicate path");
3863  goto error;
3864  }
3865 
3866  if (SigLoadSignatures(de_ctx, NULL, false) < 0) {
3867  SCLogError("Loading signatures failed.");
3868  goto error;
3869  }
3870 
3872 
3873  return 0;
3874 
3875 error:
3876  if (de_ctx != NULL) {
3878  }
3879  return -1;
3880 }
3881 
3882 static int DetectEngineMultiTenantReloadTenant(uint32_t tenant_id, const char *filename, int reload_cnt)
3883 {
3884  DetectEngineCtx *old_de_ctx = DetectEngineGetByTenantId(tenant_id);
3885  if (old_de_ctx == NULL) {
3886  SCLogError("tenant detect engine not found");
3887  return -1;
3888  }
3889 
3890  if (filename == NULL)
3891  filename = old_de_ctx->tenant_path;
3892 
3893  char prefix[64];
3894  snprintf(prefix, sizeof(prefix), "multi-detect.%u.reload.%d", tenant_id, reload_cnt);
3895  reload_cnt++;
3896  SCLogDebug("prefix %s", prefix);
3897 
3898  if (ConfYamlLoadFileWithPrefix(filename, prefix) != 0) {
3899  SCLogError("failed to load yaml");
3900  goto error;
3901  }
3902 
3903  ConfNode *node = ConfGetNode(prefix);
3904  if (node == NULL) {
3905  SCLogError("failed to properly setup yaml %s", filename);
3906  goto error;
3907  }
3908 
3909  DetectEngineCtx *new_de_ctx = DetectEngineCtxInitWithPrefix(prefix, tenant_id);
3910  if (new_de_ctx == NULL) {
3911  SCLogError("initializing detection engine "
3912  "context failed.");
3913  goto error;
3914  }
3915  SCLogDebug("de_ctx %p with prefix %s", new_de_ctx, new_de_ctx->config_prefix);
3916 
3917  new_de_ctx->type = DETECT_ENGINE_TYPE_TENANT;
3918  new_de_ctx->tenant_id = tenant_id;
3919  new_de_ctx->loader_id = old_de_ctx->loader_id;
3920  new_de_ctx->tenant_path = SCStrdup(filename);
3921  if (new_de_ctx->tenant_path == NULL) {
3922  SCLogError("Failed to duplicate path");
3923  goto error;
3924  }
3925 
3926  if (SigLoadSignatures(new_de_ctx, NULL, false) < 0) {
3927  SCLogError("Loading signatures failed.");
3928  goto error;
3929  }
3930 
3931  DetectEngineAddToMaster(new_de_ctx);
3932 
3933  /* move to free list */
3934  DetectEngineMoveToFreeList(old_de_ctx);
3935  DetectEngineDeReference(&old_de_ctx);
3936  return 0;
3937 
3938 error:
3939  DetectEngineDeReference(&old_de_ctx);
3940  return -1;
3941 }
3942 
3943 
3944 typedef struct TenantLoaderCtx_ {
3945  uint32_t tenant_id;
3946  int reload_cnt; /**< used by reload */
3947  char *yaml; /**< heap alloc'd copy of file path for the yaml */
3949 
3950 static void DetectLoaderFreeTenant(void *ctx)
3951 {
3953  if (t->yaml != NULL) {
3954  SCFree(t->yaml);
3955  }
3956  SCFree(t);
3957 }
3958 
3959 static int DetectLoaderFuncLoadTenant(void *vctx, int loader_id)
3960 {
3961  TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx;
3962 
3963  SCLogDebug("loader %d", loader_id);
3964  if (DetectEngineMultiTenantLoadTenant(ctx->tenant_id, ctx->yaml, loader_id) != 0) {
3965  return -1;
3966  }
3967  return 0;
3968 }
3969 
3970 static int DetectLoaderSetupLoadTenant(uint32_t tenant_id, const char *yaml)
3971 {
3972  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
3973  if (t == NULL)
3974  return -ENOMEM;
3975 
3976  t->tenant_id = tenant_id;
3977  t->yaml = SCStrdup(yaml);
3978  if (t->yaml == NULL) {
3979  SCFree(t);
3980  return -ENOMEM;
3981  }
3982 
3983  return DetectLoaderQueueTask(-1, DetectLoaderFuncLoadTenant, t, DetectLoaderFreeTenant);
3984 }
3985 
3986 static int DetectLoaderFuncReloadTenant(void *vctx, int loader_id)
3987 {
3988  TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx;
3989 
3990  SCLogDebug("loader_id %d", loader_id);
3991 
3992  if (DetectEngineMultiTenantReloadTenant(ctx->tenant_id, ctx->yaml, ctx->reload_cnt) != 0) {
3993  return -1;
3994  }
3995  return 0;
3996 }
3997 
3998 static int DetectLoaderSetupReloadTenants(const int reload_cnt)
3999 {
4000  int ret = 0;
4001  DetectEngineMasterCtx *master = &g_master_de_ctx;
4002  SCMutexLock(&master->lock);
4003 
4004  DetectEngineCtx *de_ctx = master->list;
4005  while (de_ctx) {
4007  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
4008  if (t == NULL) {
4009  ret = -1;
4010  goto error;
4011  }
4012  t->tenant_id = de_ctx->tenant_id;
4013  t->reload_cnt = reload_cnt;
4014  int loader_id = de_ctx->loader_id;
4015 
4016  int r = DetectLoaderQueueTask(
4017  loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant);
4018  if (r < 0) {
4019  ret = -2;
4020  goto error;
4021  }
4022  }
4023 
4024  de_ctx = de_ctx->next;
4025  }
4026 error:
4027  SCMutexUnlock(&master->lock);
4028  return ret;
4029 }
4030 
4031 static int DetectLoaderSetupReloadTenant(uint32_t tenant_id, const char *yaml, int reload_cnt)
4032 {
4033  DetectEngineCtx *old_de_ctx = DetectEngineGetByTenantId(tenant_id);
4034  if (old_de_ctx == NULL)
4035  return -ENOENT;
4036  int loader_id = old_de_ctx->loader_id;
4037  DetectEngineDeReference(&old_de_ctx);
4038 
4039  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
4040  if (t == NULL)
4041  return -ENOMEM;
4042 
4043  t->tenant_id = tenant_id;
4044  if (yaml != NULL) {
4045  t->yaml = SCStrdup(yaml);
4046  if (t->yaml == NULL) {
4047  SCFree(t);
4048  return -ENOMEM;
4049  }
4050  }
4051  t->reload_cnt = reload_cnt;
4052 
4053  SCLogDebug("loader_id %d", loader_id);
4054 
4055  return DetectLoaderQueueTask(
4056  loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant);
4057 }
4058 
4059 /** \brief Load a tenant and wait for loading to complete
4060  */
4061 int DetectEngineLoadTenantBlocking(uint32_t tenant_id, const char *yaml)
4062 {
4063  int r = DetectLoaderSetupLoadTenant(tenant_id, yaml);
4064  if (r < 0)
4065  return r;
4066 
4067  if (DetectLoadersSync() != 0)
4068  return -1;
4069 
4070  return 0;
4071 }
4072 
4073 /** \brief Reload a tenant and wait for loading to complete
4074  */
4075 int DetectEngineReloadTenantBlocking(uint32_t tenant_id, const char *yaml, int reload_cnt)
4076 {
4077  int r = DetectLoaderSetupReloadTenant(tenant_id, yaml, reload_cnt);
4078  if (r < 0)
4079  return r;
4080 
4081  if (DetectLoadersSync() != 0)
4082  return -1;
4083 
4084  return 0;
4085 }
4086 
4087 /** \brief Reload all tenants and wait for loading to complete
4088  */
4089 int DetectEngineReloadTenantsBlocking(const int reload_cnt)
4090 {
4091  int r = DetectLoaderSetupReloadTenants(reload_cnt);
4092  if (r < 0)
4093  return r;
4094 
4095  if (DetectLoadersSync() != 0)
4096  return -1;
4097 
4098  return 0;
4099 }
4100 
4101 static int DetectEngineMultiTenantSetupLoadLivedevMappings(const ConfNode *mappings_root_node,
4102  bool failure_fatal)
4103 {
4104  ConfNode *mapping_node = NULL;
4105 
4106  int mapping_cnt = 0;
4107  if (mappings_root_node != NULL) {
4108  TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
4109  ConfNode *tenant_id_node = ConfNodeLookupChild(mapping_node, "tenant-id");
4110  if (tenant_id_node == NULL)
4111  goto bad_mapping;
4112  ConfNode *device_node = ConfNodeLookupChild(mapping_node, "device");
4113  if (device_node == NULL)
4114  goto bad_mapping;
4115 
4116  uint32_t tenant_id = 0;
4117  if (StringParseUint32(&tenant_id, 10, (uint16_t)strlen(tenant_id_node->val),
4118  tenant_id_node->val) < 0) {
4119  SCLogError("tenant-id "
4120  "of %s is invalid",
4121  tenant_id_node->val);
4122  goto bad_mapping;
4123  }
4124 
4125  const char *dev = device_node->val;
4126  LiveDevice *ld = LiveGetDevice(dev);
4127  if (ld == NULL) {
4128  SCLogWarning("device %s not found", dev);
4129  goto bad_mapping;
4130  }
4131 
4132  if (ld->tenant_id_set) {
4133  SCLogWarning("device %s already mapped to tenant-id %u", dev, ld->tenant_id);
4134  goto bad_mapping;
4135  }
4136 
4137  ld->tenant_id = tenant_id;
4138  ld->tenant_id_set = true;
4139 
4140  if (DetectEngineTenantRegisterLivedev(tenant_id, ld->id) != 0) {
4141  goto error;
4142  }
4143 
4144  SCLogConfig("device %s connected to tenant-id %u", dev, tenant_id);
4145  mapping_cnt++;
4146  continue;
4147 
4148  bad_mapping:
4149  if (failure_fatal)
4150  goto error;
4151  }
4152  }
4153  SCLogConfig("%d device - tenant-id mappings defined", mapping_cnt);
4154  return mapping_cnt;
4155 
4156 error:
4157  return 0;
4158 }
4159 
4160 static int DetectEngineMultiTenantSetupLoadVlanMappings(const ConfNode *mappings_root_node,
4161  bool failure_fatal)
4162 {
4163  ConfNode *mapping_node = NULL;
4164 
4165  int mapping_cnt = 0;
4166  if (mappings_root_node != NULL) {
4167  TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
4168  ConfNode *tenant_id_node = ConfNodeLookupChild(mapping_node, "tenant-id");
4169  if (tenant_id_node == NULL)
4170  goto bad_mapping;
4171  ConfNode *vlan_id_node = ConfNodeLookupChild(mapping_node, "vlan-id");
4172  if (vlan_id_node == NULL)
4173  goto bad_mapping;
4174 
4175  uint32_t tenant_id = 0;
4176  if (StringParseUint32(&tenant_id, 10, (uint16_t)strlen(tenant_id_node->val),
4177  tenant_id_node->val) < 0) {
4178  SCLogError("tenant-id "
4179  "of %s is invalid",
4180  tenant_id_node->val);
4181  goto bad_mapping;
4182  }
4183 
4184  uint16_t vlan_id = 0;
4185  if (StringParseUint16(
4186  &vlan_id, 10, (uint16_t)strlen(vlan_id_node->val), vlan_id_node->val) < 0) {
4187  SCLogError("vlan-id "
4188  "of %s is invalid",
4189  vlan_id_node->val);
4190  goto bad_mapping;
4191  }
4192  if (vlan_id == 0 || vlan_id >= 4095) {
4193  SCLogError("vlan-id "
4194  "of %s is invalid. Valid range 1-4094.",
4195  vlan_id_node->val);
4196  goto bad_mapping;
4197  }
4198 
4199  if (DetectEngineTenantRegisterVlanId(tenant_id, vlan_id) != 0) {
4200  goto error;
4201  }
4202  SCLogConfig("vlan %u connected to tenant-id %u", vlan_id, tenant_id);
4203  mapping_cnt++;
4204  continue;
4205 
4206  bad_mapping:
4207  if (failure_fatal)
4208  goto error;
4209  }
4210  }
4211  return mapping_cnt;
4212 
4213 error:
4214  return 0;
4215 }
4216 
4217 /**
4218  * \brief setup multi-detect / multi-tenancy
4219  *
4220  * See if MT is enabled. If so, setup the selector, tenants and mappings.
4221  * Tenants and mappings are optional, and can also dynamically be added
4222  * and removed from the unix socket.
4223  */
4224 int DetectEngineMultiTenantSetup(const bool unix_socket)
4225 {
4227  DetectEngineMasterCtx *master = &g_master_de_ctx;
4228  int failure_fatal = 0;
4229  (void)ConfGetBool("engine.init-failure-fatal", &failure_fatal);
4230 
4231  int enabled = 0;
4232  (void)ConfGetBool("multi-detect.enabled", &enabled);
4233  if (enabled == 1) {
4238 
4239  SCMutexLock(&master->lock);
4240  master->multi_tenant_enabled = 1;
4241 
4242  const char *handler = NULL;
4243  if (ConfGet("multi-detect.selector", &handler) == 1) {
4244  SCLogConfig("multi-tenant selector type %s", handler);
4245 
4246  if (strcmp(handler, "vlan") == 0) {
4247  tenant_selector = master->tenant_selector = TENANT_SELECTOR_VLAN;
4248 
4249  int vlanbool = 0;
4250  if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
4251  SCLogError("vlan tracking is disabled, "
4252  "can't use multi-detect selector 'vlan'");
4253  SCMutexUnlock(&master->lock);
4254  goto error;
4255  }
4256 
4257  } else if (strcmp(handler, "direct") == 0) {
4258  tenant_selector = master->tenant_selector = TENANT_SELECTOR_DIRECT;
4259  } else if (strcmp(handler, "device") == 0) {
4260  tenant_selector = master->tenant_selector = TENANT_SELECTOR_LIVEDEV;
4261  if (EngineModeIsIPS()) {
4262  SCLogWarning("multi-tenant 'device' mode not supported for IPS");
4263  SCMutexUnlock(&master->lock);
4264  goto error;
4265  }
4266 
4267  } else {
4268  SCLogError("unknown value %s "
4269  "multi-detect.selector",
4270  handler);
4271  SCMutexUnlock(&master->lock);
4272  goto error;
4273  }
4274  }
4275  SCMutexUnlock(&master->lock);
4276  SCLogConfig("multi-detect is enabled (multi tenancy). Selector: %s", handler);
4277 
4278  /* traffic -- tenant mappings */
4279  ConfNode *mappings_root_node = ConfGetNode("multi-detect.mappings");
4280 
4281  if (tenant_selector == TENANT_SELECTOR_VLAN) {
4282  int mapping_cnt = DetectEngineMultiTenantSetupLoadVlanMappings(mappings_root_node,
4283  failure_fatal);
4284  if (mapping_cnt == 0) {
4285  /* no mappings are valid when we're in unix socket mode,
4286  * they can be added on the fly. Otherwise warn/error
4287  * depending on failure_fatal */
4288 
4289  if (unix_socket) {
4290  SCLogNotice("no tenant traffic mappings defined, "
4291  "tenants won't be used until mappings are added");
4292  } else {
4293  if (failure_fatal) {
4294  SCLogError("no multi-detect mappings defined");
4295  goto error;
4296  } else {
4297  SCLogWarning("no multi-detect mappings defined");
4298  }
4299  }
4300  }
4301  } else if (tenant_selector == TENANT_SELECTOR_LIVEDEV) {
4302  int mapping_cnt = DetectEngineMultiTenantSetupLoadLivedevMappings(mappings_root_node,
4303  failure_fatal);
4304  if (mapping_cnt == 0) {
4305  if (failure_fatal) {
4306  SCLogError("no multi-detect mappings defined");
4307  goto error;
4308  } else {
4309  SCLogWarning("no multi-detect mappings defined");
4310  }
4311  }
4312  }
4313 
4314  /* tenants */
4315  ConfNode *tenants_root_node = ConfGetNode("multi-detect.tenants");
4316  ConfNode *tenant_node = NULL;
4317 
4318  if (tenants_root_node != NULL) {
4319  const char *path = NULL;
4320  ConfNode *path_node = ConfGetNode("multi-detect.config-path");
4321  if (path_node) {
4322  path = path_node->val;
4323  SCLogConfig("tenants config path: %s", path);
4324  }
4325 
4326  TAILQ_FOREACH(tenant_node, &tenants_root_node->head, next) {
4327  ConfNode *id_node = ConfNodeLookupChild(tenant_node, "id");
4328  if (id_node == NULL) {
4329  goto bad_tenant;
4330  }
4331  ConfNode *yaml_node = ConfNodeLookupChild(tenant_node, "yaml");
4332  if (yaml_node == NULL) {
4333  goto bad_tenant;
4334  }
4335 
4336  uint32_t tenant_id = 0;
4337  if (StringParseUint32(
4338  &tenant_id, 10, (uint16_t)strlen(id_node->val), id_node->val) < 0) {
4339  SCLogError("tenant_id "
4340  "of %s is invalid",
4341  id_node->val);
4342  goto bad_tenant;
4343  }
4344  SCLogDebug("tenant id: %u, %s", tenant_id, yaml_node->val);
4345 
4346  char yaml_path[PATH_MAX] = "";
4347  if (path) {
4348  PathMerge(yaml_path, PATH_MAX, path, yaml_node->val);
4349  } else {
4350  strlcpy(yaml_path, yaml_node->val, sizeof(yaml_path));
4351  }
4352  SCLogDebug("tenant path: %s", yaml_path);
4353 
4354  /* setup the yaml in this loop so that it's not done by the loader
4355  * threads. ConfYamlLoadFileWithPrefix is not thread safe. */
4356  char prefix[64];
4357  snprintf(prefix, sizeof(prefix), "multi-detect.%u", tenant_id);
4358  if (ConfYamlLoadFileWithPrefix(yaml_path, prefix) != 0) {
4359  SCLogError("failed to load yaml %s", yaml_path);
4360  goto bad_tenant;
4361  }
4362 
4363  int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_path);
4364  if (r < 0) {
4365  /* error logged already */
4366  goto bad_tenant;
4367  }
4368  continue;
4369 
4370  bad_tenant:
4371  if (failure_fatal)
4372  goto error;
4373  }
4374  }
4375 
4376  /* wait for our loaders to complete their tasks */
4377  if (DetectLoadersSync() != 0) {
4378  goto error;
4379  }
4380 
4382 
4383  } else {
4384  SCLogDebug("multi-detect not enabled (multi tenancy)");
4385  }
4386  return 0;
4387 error:
4388  return -1;
4389 }
4390 
4391 static uint32_t DetectEngineTenantGetIdFromVlanId(const void *ctx, const Packet *p)
4392 {
4393  const DetectEngineThreadCtx *det_ctx = ctx;
4394  uint32_t x = 0;
4395  uint32_t vlan_id = 0;
4396 
4397  if (p->vlan_idx == 0)
4398  return 0;
4399 
4400  vlan_id = p->vlan_id[0];
4401 
4402  if (det_ctx == NULL || det_ctx->tenant_array == NULL || det_ctx->tenant_array_size == 0)
4403  return 0;
4404 
4405  /* not very efficient, but for now we're targeting only limited amounts.
4406  * Can use hash/tree approach later. */
4407  for (x = 0; x < det_ctx->tenant_array_size; x++) {
4408  if (det_ctx->tenant_array[x].traffic_id == vlan_id)
4409  return det_ctx->tenant_array[x].tenant_id;
4410  }
4411 
4412  return 0;
4413 }
4414 
4415 static uint32_t DetectEngineTenantGetIdFromLivedev(const void *ctx, const Packet *p)
4416 {
4417  const DetectEngineThreadCtx *det_ctx = ctx;
4418  const LiveDevice *ld = p->livedev;
4419 
4420  if (ld == NULL || det_ctx == NULL)
4421  return 0;
4422 
4423  SCLogDebug("using tenant-id %u for packet on device %s", ld->tenant_id, ld->dev);
4424  return ld->tenant_id;
4425 }
4426 
4427 static int DetectEngineTenantRegisterSelector(
4428  enum DetectEngineTenantSelectors selector, uint32_t tenant_id, uint32_t traffic_id)
4429 {
4430  DetectEngineMasterCtx *master = &g_master_de_ctx;
4431  SCMutexLock(&master->lock);
4432 
4433  if (!(master->tenant_selector == TENANT_SELECTOR_UNKNOWN || master->tenant_selector == selector)) {
4434  SCLogInfo("conflicting selector already set");
4435  SCMutexUnlock(&master->lock);
4436  return -1;
4437  }
4438 
4440  while (m) {
4441  if (m->traffic_id == traffic_id) {
4442  SCLogInfo("traffic id already registered");
4443  SCMutexUnlock(&master->lock);
4444  return -1;
4445  }
4446  m = m->next;
4447  }
4448 
4449  DetectEngineTenantMapping *map = SCCalloc(1, sizeof(*map));
4450  if (map == NULL) {
4451  SCLogInfo("memory fail");
4452  SCMutexUnlock(&master->lock);
4453  return -1;
4454  }
4455  map->traffic_id = traffic_id;
4456  map->tenant_id = tenant_id;
4457 
4458  map->next = master->tenant_mapping_list;
4459  master->tenant_mapping_list = map;
4460 
4461  master->tenant_selector = selector;
4462 
4463  SCLogDebug("tenant handler %u %u %u registered", selector, tenant_id, traffic_id);
4464  SCMutexUnlock(&master->lock);
4465  return 0;
4466 }
4467 
4468 static int DetectEngineTenantUnregisterSelector(
4469  enum DetectEngineTenantSelectors selector, uint32_t tenant_id, uint32_t traffic_id)
4470 {
4471  DetectEngineMasterCtx *master = &g_master_de_ctx;
4472  SCMutexLock(&master->lock);
4473 
4474  if (master->tenant_mapping_list == NULL) {
4475  SCMutexUnlock(&master->lock);
4476  return -1;
4477  }
4478 
4479  DetectEngineTenantMapping *prev = NULL;
4481  while (map) {
4482  if (map->traffic_id == traffic_id &&
4483  map->tenant_id == tenant_id)
4484  {
4485  if (prev != NULL)
4486  prev->next = map->next;
4487  else
4488  master->tenant_mapping_list = map->next;
4489 
4490  map->next = NULL;
4491  SCFree(map);
4492  SCLogInfo("tenant handler %u %u %u unregistered", selector, tenant_id, traffic_id);
4493  SCMutexUnlock(&master->lock);
4494  return 0;
4495  }
4496  prev = map;
4497  map = map->next;
4498  }
4499 
4500  SCMutexUnlock(&master->lock);
4501  return -1;
4502 }
4503 
4504 int DetectEngineTenantRegisterLivedev(uint32_t tenant_id, int device_id)
4505 {
4506  return DetectEngineTenantRegisterSelector(
4507  TENANT_SELECTOR_LIVEDEV, tenant_id, (uint32_t)device_id);
4508 }
4509 
4510 int DetectEngineTenantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
4511 {
4512  return DetectEngineTenantRegisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
4513 }
4514 
4515 int DetectEngineTenantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
4516 {
4517  return DetectEngineTenantUnregisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
4518 }
4519 
4520 int DetectEngineTenantRegisterPcapFile(uint32_t tenant_id)
4521 {
4522  SCLogInfo("registering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
4523  return DetectEngineTenantRegisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
4524 }
4525 
4527 {
4528  SCLogInfo("unregistering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
4529  return DetectEngineTenantUnregisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
4530 }
4531 
4532 static uint32_t DetectEngineTenantGetIdFromPcap(const void *ctx, const Packet *p)
4533 {
4534  return p->pcap_v.tenant_id;
4535 }
4536 
4538 {
4539  DetectEngineMasterCtx *master = &g_master_de_ctx;
4540  SCMutexLock(&master->lock);
4541 
4542  if (master->list == NULL) {
4543  SCMutexUnlock(&master->lock);
4544  return NULL;
4545  }
4546 
4547  DetectEngineCtx *de_ctx = master->list;
4548  while (de_ctx) {
4550  de_ctx->tenant_id == tenant_id)
4551  {
4552  de_ctx->ref_cnt++;
4553  break;
4554  }
4555 
4556  de_ctx = de_ctx->next;
4557  }
4558 
4559  SCMutexUnlock(&master->lock);
4560  return de_ctx;
4561 }
4562 
4564 {
4565  BUG_ON((*de_ctx)->ref_cnt == 0);
4566  (*de_ctx)->ref_cnt--;
4567  *de_ctx = NULL;
4568 }
4569 
4570 static int DetectEngineAddToList(DetectEngineCtx *instance)
4571 {
4572  DetectEngineMasterCtx *master = &g_master_de_ctx;
4573 
4574  if (instance == NULL)
4575  return -1;
4576 
4577  if (master->list == NULL) {
4578  master->list = instance;
4579  } else {
4580  instance->next = master->list;
4581  master->list = instance;
4582  }
4583 
4584  return 0;
4585 }
4586 
4588 {
4589  int r;
4590 
4591  if (de_ctx == NULL)
4592  return -1;
4593 
4594  SCLogDebug("adding de_ctx %p to master", de_ctx);
4595 
4596  DetectEngineMasterCtx *master = &g_master_de_ctx;
4597  SCMutexLock(&master->lock);
4598  r = DetectEngineAddToList(de_ctx);
4599  SCMutexUnlock(&master->lock);
4600  return r;
4601 }
4602 
4603 static int DetectEngineMoveToFreeListNoLock(DetectEngineMasterCtx *master, DetectEngineCtx *de_ctx)
4604 {
4605  DetectEngineCtx *instance = master->list;
4606  if (instance == NULL) {
4607  return -1;
4608  }
4609 
4610  /* remove from active list */
4611  if (instance == de_ctx) {
4612  master->list = instance->next;
4613  } else {
4614  DetectEngineCtx *prev = instance;
4615  instance = instance->next; /* already checked first element */
4616 
4617  while (instance) {
4618  DetectEngineCtx *next = instance->next;
4619 
4620  if (instance == de_ctx) {
4621  prev->next = instance->next;
4622  break;
4623  }
4624 
4625  prev = instance;
4626  instance = next;
4627  }
4628  if (instance == NULL) {
4629  return -1;
4630  }
4631  }
4632 
4633  /* instance is now detached from list */
4634  instance->next = NULL;
4635 
4636  /* add to free list */
4637  if (master->free_list == NULL) {
4638  master->free_list = instance;
4639  } else {
4640  instance->next = master->free_list;
4641  master->free_list = instance;
4642  }
4643  SCLogDebug("detect engine %p moved to free list (%u refs)", de_ctx, de_ctx->ref_cnt);
4644  return 0;
4645 }
4646 
4648 {
4649  int ret = 0;
4650  DetectEngineMasterCtx *master = &g_master_de_ctx;
4651  SCMutexLock(&master->lock);
4652  ret = DetectEngineMoveToFreeListNoLock(master, de_ctx);
4653  SCMutexUnlock(&master->lock);
4654  return ret;
4655 }
4656 
4658 {
4659  DetectEngineMasterCtx *master = &g_master_de_ctx;
4660  SCMutexLock(&master->lock);
4661 
4662  DetectEngineCtx *prev = NULL;
4663  DetectEngineCtx *instance = master->free_list;
4664  while (instance) {
4665  DetectEngineCtx *next = instance->next;
4666 
4667  SCLogDebug("detect engine %p has %u ref(s)", instance, instance->ref_cnt);
4668 
4669  if (instance->ref_cnt == 0) {
4670  if (prev == NULL) {
4671  master->free_list = next;
4672  } else {
4673  prev->next = next;
4674  }
4675 
4676  SCLogDebug("freeing detect engine %p", instance);
4677  DetectEngineCtxFree(instance);
4678  instance = NULL;
4679  }
4680 
4681  prev = instance;
4682  instance = next;
4683  }
4684  SCMutexUnlock(&master->lock);
4685 }
4686 
4688 {
4689  DetectEngineMasterCtx *master = &g_master_de_ctx;
4690  SCMutexLock(&master->lock);
4691 
4692  DetectEngineCtx *instance = master->list;
4693  while (instance) {
4694  DetectEngineCtx *next = instance->next;
4695  DEBUG_VALIDATE_BUG_ON(instance->ref_cnt);
4696  SCLogDebug("detect engine %p has %u ref(s)", instance, instance->ref_cnt);
4697  instance->ref_cnt = 0;
4698  DetectEngineMoveToFreeListNoLock(master, instance);
4699  instance = next;
4700  }
4701  SCMutexUnlock(&master->lock);
4703 }
4704 
4705 static int reloads = 0;
4706 
4707 /** \brief Reload the detection engine
4708  *
4709  * \param filename YAML file to load for the detect config
4710  *
4711  * \retval -1 error
4712  * \retval 0 ok
4713  */
4715 {
4716  DetectEngineCtx *new_de_ctx = NULL;
4717  DetectEngineCtx *old_de_ctx = NULL;
4718 
4719  char prefix[128];
4720  memset(prefix, 0, sizeof(prefix));
4721 
4722  SCLogNotice("rule reload starting");
4723 
4724  if (suri->conf_filename != NULL) {
4725  snprintf(prefix, sizeof(prefix), "detect-engine-reloads.%d", reloads++);
4726  SCLogConfig("Reloading %s", suri->conf_filename);
4727  if (ConfYamlLoadFileWithPrefix(suri->conf_filename, prefix) != 0) {
4728  SCLogError("failed to load yaml %s", suri->conf_filename);
4729  return -1;
4730  }
4731 
4732  ConfNode *node = ConfGetNode(prefix);
4733  if (node == NULL) {
4734  SCLogError("failed to properly setup yaml %s", suri->conf_filename);
4735  return -1;
4736  }
4737 
4738  if (suri->additional_configs) {
4739  for (int i = 0; suri->additional_configs[i] != NULL; i++) {
4740  SCLogConfig("Reloading %s", suri->additional_configs[i]);
4741  ConfYamlHandleInclude(node, suri->additional_configs[i]);
4742  }
4743  }
4744 
4745 #if 0
4746  ConfDump();
4747 #endif
4748  }
4749 
4750  /* get a reference to the current de_ctx */
4751  old_de_ctx = DetectEngineGetCurrent();
4752  if (old_de_ctx == NULL)
4753  return -1;
4754  SCLogDebug("get ref to old_de_ctx %p", old_de_ctx);
4755  DatasetReload();
4756 
4757  /* only reload a regular 'normal' and 'delayed detect stub' detect engines */
4758  if (!(old_de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
4759  old_de_ctx->type == DETECT_ENGINE_TYPE_DD_STUB))
4760  {
4761  DetectEngineDeReference(&old_de_ctx);
4762  SCLogNotice("rule reload complete");
4763  return -1;
4764  }
4765 
4766  /* get new detection engine */
4767  new_de_ctx = DetectEngineCtxInitWithPrefix(prefix, old_de_ctx->tenant_id);
4768  if (new_de_ctx == NULL) {
4769  SCLogError("initializing detection engine "
4770  "context failed.");
4771  DetectEngineDeReference(&old_de_ctx);
4772  return -1;
4773  }
4774  if (SigLoadSignatures(new_de_ctx,
4775  suri->sig_file, suri->sig_file_exclusive) != 0) {
4776  DetectEngineCtxFree(new_de_ctx);
4777  DetectEngineDeReference(&old_de_ctx);
4778  return -1;
4779  }
4780  SCLogDebug("set up new_de_ctx %p", new_de_ctx);
4781 
4782  /* add to master */
4783  DetectEngineAddToMaster(new_de_ctx);
4784 
4785  /* move to old free list */
4786  DetectEngineMoveToFreeList(old_de_ctx);
4787  DetectEngineDeReference(&old_de_ctx);
4788 
4789  SCLogDebug("going to reload the threads to use new_de_ctx %p", new_de_ctx);
4790  /* update the threads */
4791  DetectEngineReloadThreads(new_de_ctx);
4792  SCLogDebug("threads now run new_de_ctx %p", new_de_ctx);
4793 
4794  /* walk free list, freeing the old_de_ctx */
4796 
4798 
4800 
4801  SCLogDebug("old_de_ctx should have been freed");
4802 
4803  SCLogNotice("rule reload complete");
4804 
4805 #ifdef HAVE_MALLOC_TRIM
4806  /* The reload process potentially frees up large amounts of memory.
4807  * Encourage the memory management system to reclaim as much as it
4808  * can.
4809  */
4810  malloc_trim(0);
4811 #endif
4812 
4813  return 0;
4814 }
4815 
4816 static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len)
4817 {
4818  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
4819  return det_ctx->tenant_id % h->array_size;
4820 }
4821 
4822 static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len)
4823 {
4826  return (det1->tenant_id == det2->tenant_id);
4827 }
4828 
4829 static void TenantIdFree(void *d)
4830 {
4831  DetectEngineThreadCtxFree(d);
4832 }
4833 
4835 {
4836  DetectEngineMasterCtx *master = &g_master_de_ctx;
4837  SCMutexLock(&master->lock);
4838 
4839  if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
4840  SCLogInfo("error, no tenant selector");
4841  SCMutexUnlock(&master->lock);
4842  return -1;
4843  }
4844 
4845  DetectEngineCtx *stub_de_ctx = NULL;
4846  DetectEngineCtx *list = master->list;
4847  for ( ; list != NULL; list = list->next) {
4848  SCLogDebug("list %p tenant %u", list, list->tenant_id);
4849 
4850  if (list->type == DETECT_ENGINE_TYPE_NORMAL ||
4851  list->type == DETECT_ENGINE_TYPE_MT_STUB ||
4853  {
4854  stub_de_ctx = list;
4855  break;
4856  }
4857  }
4858  if (stub_de_ctx == NULL) {
4859  stub_de_ctx = DetectEngineCtxInitStubForMT();
4860  if (stub_de_ctx == NULL) {
4861  SCMutexUnlock(&master->lock);
4862  return -1;
4863  }
4864 
4865  if (master->list == NULL) {
4866  master->list = stub_de_ctx;
4867  } else {
4868  stub_de_ctx->next = master->list;
4869  master->list = stub_de_ctx;
4870  }
4871  }
4872 
4873  /* update the threads */
4874  SCLogDebug("MT reload starting");
4875  DetectEngineReloadThreads(stub_de_ctx);
4876  SCLogDebug("MT reload done");
4877 
4878  SCMutexUnlock(&master->lock);
4879 
4880  /* walk free list, freeing the old_de_ctx */
4882  // needed for VarNameStoreFree
4884 
4885  SCLogDebug("old_de_ctx should have been freed");
4886  return 0;
4887 }
4888 
4889 static int g_parse_metadata = 0;
4890 
4892 {
4893  g_parse_metadata = 1;
4894 }
4895 
4897 {
4898  g_parse_metadata = 0;
4899 }
4900 
4902 {
4903  return g_parse_metadata;
4904 }
4905 
4907 {
4908  switch (type) {
4909  case DETECT_SM_LIST_MATCH:
4910  return "packet";
4911  case DETECT_SM_LIST_PMATCH:
4912  return "packet/stream payload";
4913 
4914  case DETECT_SM_LIST_TMATCH:
4915  return "tag";
4916 
4918  return "base64_data";
4919 
4921  return "post-match";
4922 
4924  return "suppress";
4926  return "threshold";
4927 
4928  case DETECT_SM_LIST_MAX:
4929  return "max (internal)";
4930  }
4931  return "error";
4932 }
4933 
4934 /* events api */
4936 {
4938  det_ctx->events++;
4939 }
4940 
4941 /*************************************Unittest*********************************/
4942 
4943 #ifdef UNITTESTS
4944 
4945 static int DetectEngineInitYamlConf(const char *conf)
4946 {
4948  ConfInit();
4949  return ConfYamlLoadString(conf, strlen(conf));
4950 }
4951 
4952 static void DetectEngineDeInitYamlConf(void)
4953 {
4954  ConfDeInit();
4956 }
4957 
4958 static int DetectEngineTest01(void)
4959 {
4960  const char *conf =
4961  "%YAML 1.1\n"
4962  "---\n"
4963  "detect-engine:\n"
4964  " - profile: medium\n"
4965  " - custom-values:\n"
4966  " toclient_src_groups: 2\n"
4967  " toclient_dst_groups: 2\n"
4968  " toclient_sp_groups: 2\n"
4969  " toclient_dp_groups: 3\n"
4970  " toserver_src_groups: 2\n"
4971  " toserver_dst_groups: 4\n"
4972  " toserver_sp_groups: 2\n"
4973  " toserver_dp_groups: 25\n"
4974  " - inspection-recursion-limit: 0\n";
4975 
4976  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
4977 
4980 
4982 
4984 
4985  DetectEngineDeInitYamlConf();
4986 
4987  PASS;
4988 }
4989 
4990 static int DetectEngineTest02(void)
4991 {
4992  const char *conf =
4993  "%YAML 1.1\n"
4994  "---\n"
4995  "detect-engine:\n"
4996  " - profile: medium\n"
4997  " - custom-values:\n"
4998  " toclient_src_groups: 2\n"
4999  " toclient_dst_groups: 2\n"
5000  " toclient_sp_groups: 2\n"
5001  " toclient_dp_groups: 3\n"
5002  " toserver_src_groups: 2\n"
5003  " toserver_dst_groups: 4\n"
5004  " toserver_sp_groups: 2\n"
5005  " toserver_dp_groups: 25\n"
5006  " - inspection-recursion-limit:\n";
5007 
5008  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5009 
5012 
5013  FAIL_IF_NOT(
5015 
5017 
5018  DetectEngineDeInitYamlConf();
5019 
5020  PASS;
5021 }
5022 
5023 static int DetectEngineTest03(void)
5024 {
5025  const char *conf =
5026  "%YAML 1.1\n"
5027  "---\n"
5028  "detect-engine:\n"
5029  " - profile: medium\n"
5030  " - custom-values:\n"
5031  " toclient_src_groups: 2\n"
5032  " toclient_dst_groups: 2\n"
5033  " toclient_sp_groups: 2\n"
5034  " toclient_dp_groups: 3\n"
5035  " toserver_src_groups: 2\n"
5036  " toserver_dst_groups: 4\n"
5037  " toserver_sp_groups: 2\n"
5038  " toserver_dp_groups: 25\n";
5039 
5040  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5041 
5044 
5045  FAIL_IF_NOT(
5047 
5049 
5050  DetectEngineDeInitYamlConf();
5051 
5052  PASS;
5053 }
5054 
5055 static int DetectEngineTest04(void)
5056 {
5057  const char *conf =
5058  "%YAML 1.1\n"
5059  "---\n"
5060  "detect-engine:\n"
5061  " - profile: medium\n"
5062  " - custom-values:\n"
5063  " toclient_src_groups: 2\n"
5064  " toclient_dst_groups: 2\n"
5065  " toclient_sp_groups: 2\n"
5066  " toclient_dp_groups: 3\n"
5067  " toserver_src_groups: 2\n"
5068  " toserver_dst_groups: 4\n"
5069  " toserver_sp_groups: 2\n"
5070  " toserver_dp_groups: 25\n"
5071  " - inspection-recursion-limit: 10\n";
5072 
5073  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5074 
5077 
5079 
5081 
5082  DetectEngineDeInitYamlConf();
5083 
5084  PASS;
5085 }
5086 
5087 static int DetectEngineTest08(void)
5088 {
5089  const char *conf =
5090  "%YAML 1.1\n"
5091  "---\n"
5092  "detect-engine:\n"
5093  " - profile: custom\n"
5094  " - custom-values:\n"
5095  " toclient-groups: 23\n"
5096  " toserver-groups: 27\n";
5097 
5098  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5099 
5102 
5105 
5107 
5108  DetectEngineDeInitYamlConf();
5109 
5110  PASS;
5111 }
5112 
5113 /** \test bug 892 bad values */
5114 static int DetectEngineTest09(void)
5115 {
5116  const char *conf =
5117  "%YAML 1.1\n"
5118  "---\n"
5119  "detect-engine:\n"
5120  " - profile: custom\n"
5121  " - custom-values:\n"
5122  " toclient-groups: BA\n"
5123  " toserver-groups: BA\n"
5124  " - inspection-recursion-limit: 10\n";
5125 
5126  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5127 
5130 
5133 
5135 
5136  DetectEngineDeInitYamlConf();
5137 
5138  PASS;
5139 }
5140 
5141 #endif
5142 
5144 {
5145 #ifdef UNITTESTS
5146  UtRegisterTest("DetectEngineTest01", DetectEngineTest01);
5147  UtRegisterTest("DetectEngineTest02", DetectEngineTest02);
5148  UtRegisterTest("DetectEngineTest03", DetectEngineTest03);
5149  UtRegisterTest("DetectEngineTest04", DetectEngineTest04);
5150  UtRegisterTest("DetectEngineTest08", DetectEngineTest08);
5151  UtRegisterTest("DetectEngineTest09", DetectEngineTest09);
5152 #endif
5153 }
DetectEngineThreadCtx_::byte_values
uint64_t * byte_values
Definition: detect.h:1130
DetectEngineAppInspectionEngine_::stream
bool stream
Definition: detect.h:434
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
DE_STATE_ID_FILE_INSPECT
#define DE_STATE_ID_FILE_INSPECT
Definition: detect-engine-state.h:59
SCProfilingSghThreadCleanup
void SCProfilingSghThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rulegroups.c:350
DetectEngineCtxInitWithPrefix
DetectEngineCtx * DetectEngineCtxInitWithPrefix(const char *prefix, uint32_t tenant_id)
Definition: detect-engine.c:2563
DetectEngineTenantMapping_
Definition: detect.h:1523
util-byte.h
DetectAppLayerMpmMultiRegister
void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
Definition: detect-engine-mpm.c:159
tm-threads.h
ConfGetInt
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:399
DetectEngineAppInspectionEngine_
Definition: detect.h:429
util-hash-string.h
DetectBufferType_::supports_transforms
bool supports_transforms
Definition: detect.h:462
SignatureInitDataBuffer_::head
SigMatch * head
Definition: detect.h:535
DetectEngineSyncer_::m
SCMutex m
Definition: detect-engine.c:2032
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:433
DetectBufferType_::mpm
bool mpm
Definition: detect.h:459
detect-content.h
SignatureInitDataBuffer_::sm_init
bool sm_init
Definition: detect.h:529
detect-engine.h
DetectEngineResetMaxSigId
void DetectEngineResetMaxSigId(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:2990
DetectEngineMTApply
int DetectEngineMTApply(void)
Definition: detect-engine.c:4834
SCProfilingKeywordDestroyCtx
void SCProfilingKeywordDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-keywords.c:268
PACKET_ALERT_FLAG_STREAM_MATCH
#define PACKET_ALERT_FLAG_STREAM_MATCH
Definition: decode.h:259
DetectEngineBufferTypeSupportsPacketGetById
bool DetectEngineBufferTypeSupportsPacketGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1258
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:116
DetectEngineThreadCtxInitForReload
DetectEngineThreadCtx * DetectEngineThreadCtxInitForReload(ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
Definition: detect-engine.c:3391
DetectEngineThreadCtx_::to_clear_idx
uint32_t to_clear_idx
Definition: detect.h:1155
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SCRunmodeGet
int SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:261
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:586
SCProfilingKeywordThreadCleanup
void SCProfilingKeywordThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-keywords.c:338
THashDataGetResult::data
THashData * data
Definition: util-thash.h:191
AlertQueueFree
void AlertQueueFree(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine-alert.c:235
SCProfilingSghThreadSetup
void SCProfilingSghThreadSetup(SCProfileSghDetectCtx *ctx, DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rulegroups.c:313
DetectParseDupSigHashInit
int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:2392
SignatureInitData_::list_set
bool list_set
Definition: detect.h:571
RELOAD
@ RELOAD
Definition: detect-engine.c:2027
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:127
DetectLoaderThreadSpawn
void DetectLoaderThreadSpawn(void)
spawn the detect loader manager thread
Definition: detect-engine-loader.c:642
Signature_::sig_str
char * sig_str
Definition: detect.h:668
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SinglePatternMatchDefaultMatcher
uint8_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
DetectEngineDeReference
void DetectEngineDeReference(DetectEngineCtx **de_ctx)
Definition: detect-engine.c:4563
DETECT_CI_FLAGS_START
#define DETECT_CI_FLAGS_START
Definition: detect-engine-content-inspection.h:40
DetectEngineInspectBufferGeneric
uint8_t 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:2140
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1291
DetectEngineMustParseMetadata
int DetectEngineMustParseMetadata(void)
Definition: detect-engine.c:4901
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:262
MpmFactoryDeRegisterAllMpmCtxProfiles
void MpmFactoryDeRegisterAllMpmCtxProfiles(DetectEngineCtx *de_ctx)
Definition: util-mpm.c:169
DetectEngineThreadCtx_::counter_match_list
uint16_t counter_match_list
Definition: detect.h:1149
flow-util.h
DetectEnginePktInspectionEngine
Definition: detect.h:486
DetectEngineMasterCtx_::tenant_mapping_list
DetectEngineTenantMapping * tenant_mapping_list
Definition: detect.h:1554
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:451
DetectEngineInspectMultiBufferGeneric
uint8_t DetectEngineInspectMultiBufferGeneric(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)
Definition: detect-engine.c:2196
detect-engine-siggroup.h
SigTableElmt_::name
const char * name
Definition: detect.h:1301
DetectEngineMasterCtx_::list
DetectEngineCtx * list
Definition: detect.h:1543
InspectionBuffer::initialized
bool initialized
Definition: detect.h:377
MpmStoreFree
void MpmStoreFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by MpmStoreInit() function.
Definition: detect-engine-mpm.c:1526
DetectFrameMpmRegisterByParentId
void DetectFrameMpmRegisterByParentId(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:359
ConfNode_::val
char * val
Definition: conf.h:34
DetectEngineBufferTypeSupportsPacket
void DetectEngineBufferTypeSupportsPacket(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1225
DetectEngineBufferRunSetupCallback
void DetectEngineBufferRunSetupCallback(const DetectEngineCtx *de_ctx, const int id, Signature *s)
Definition: detect-engine.c:1295
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:482
DetectEngineCtx_::type
enum DetectEngineType type
Definition: detect.h:959
DetectEnginePruneFreeList
void DetectEnginePruneFreeList(void)
Definition: detect-engine.c:4657
SigLoadSignatures
int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, bool sig_file_exclusive)
Load signatures.
Definition: detect-engine-loader.c:287
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3666
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
ENGINE_PROFILE_LOW
@ ENGINE_PROFILE_LOW
Definition: detect.h:1050
DetectEngineTransforms
Definition: detect.h:408
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SIG_FLAG_INIT_NEED_FLUSH
#define SIG_FLAG_INIT_NEED_FLUSH
Definition: detect.h:293
MpmTableElmt_::name
const char * name
Definition: util-mpm.h:147
DetectEngineCtxInitStubForDD
DetectEngineCtx * DetectEngineCtxInitStubForDD(void)
Definition: detect-engine.c:2553
KEYWORD_PROFILING_SET_LIST
#define KEYWORD_PROFILING_SET_LIST(ctx, list)
Definition: util-profiling.h:46
DetectEngineCtx_::max_uniq_toclient_groups
uint16_t max_uniq_toclient_groups
Definition: detect.h:896
ActionInitConfig
int ActionInitConfig(void)
Load the action order from config. If none is provided, it will be default to ACTION_PASS,...
Definition: util-action.c:105
IDLE
@ IDLE
Definition: detect-engine.c:2026
DetectEngineCtx_::ref_cnt
uint32_t ref_cnt
Definition: detect.h:962
DetectEngineAppInspectionEngine_::Callback
InspectEngineFuncPtr Callback
Definition: detect.h:444
PathMerge
int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname)
Definition: util-path.c:74
Signature_::alproto
AppProto alproto
Definition: detect.h:606
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
SigString_
Definition: detect.h:788
DetectEngineCtx_::non_pf_store_cnt_max
uint32_t non_pf_store_cnt_max
Definition: detect.h:865
PacketEnqueue
void PacketEnqueue(PacketQueue *q, Packet *p)
Definition: packet-queue.c:175
DetectEngineCtx_::filedata_config
DetectFileDataCfg * filedata_config
Definition: detect.h:945
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectEngineFrameInspectionEngine::sm_list_base
uint16_t sm_list_base
Definition: detect.h:517
DetectPort_::port
uint16_t port
Definition: detect.h:218
SigMatchData_::is_last
bool is_last
Definition: detect.h:360
DetectBufferTypeSupportsFrames
void DetectBufferTypeSupportsFrames(const char *name)
Definition: detect-engine.c:1051
TM_FLAG_DETECT_TM
#define TM_FLAG_DETECT_TM
Definition: tm-modules.h:35
DetectMpmInitializeFrameMpms
void DetectMpmInitializeFrameMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:461
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:49
Flow_::proto
uint8_t proto
Definition: flow.h:382
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:84
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:135
DetectBufferSetActiveList
int DetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
Definition: detect-engine.c:1354
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:1067
DetectEngineThreadCtx_::decoder_events
AppLayerDecoderEvents * decoder_events
Definition: detect.h:1220
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:361
InspectionMultiBufferGetDataPtr
InspectionBuffer *(* InspectionMultiBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id, const uint32_t local_id)
Definition: detect.h:419
InspectionBuffer
Definition: detect.h:373
DetectEngineThreadKeywordCtxItem_::InitFunc
void *(* InitFunc)(void *)
Definition: detect.h:807
Packet_::flags
uint32_t flags
Definition: decode.h:516
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
DetectEngineAppInspectionEngine_::GetData
InspectionBufferGetDataPtr GetData
Definition: detect.h:441
DetectEngineThreadKeywordCtxItem_
Definition: detect.h:806
DetectEngineCtx_::pkt_mpms_list
DetectBufferMpmRegistry * pkt_mpms_list
Definition: detect.h:995
Tmq_::pq
PacketQueue * pq
Definition: tm-queues.h:35
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:507
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:360
TmThreadContinueDetectLoaderThreads
void TmThreadContinueDetectLoaderThreads(void)
Unpauses all threads present in tv_root.
Definition: detect-engine-loader.c:545
DETECT_SM_LIST_THRESHOLD
@ DETECT_SM_LIST_THRESHOLD
Definition: detect.h:130
DetectBufferTypeRegisterSetupCallback
void DetectBufferTypeRegisterSetupCallback(const char *name, void(*SetupCallback)(const DetectEngineCtx *, Signature *))
Definition: detect-engine.c:1285
DetectEngineThreadKeywordCtxItem_::data
void * data
Definition: detect.h:809
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1197
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:414
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:78
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:4075
ctx
struct Thresholds ctx
LiveDevice_
Definition: util-device.h:50
DetectEngineCtx_::inspection_recursion_limit
int inspection_recursion_limit
Definition: detect.h:885
SpmTableElmt_::name
const char * name
Definition: util-spm.h:60
LiveDevice_::tenant_id_set
bool tenant_id_set
Definition: util-device.h:54
DetectAddressMapFree
void DetectAddressMapFree(DetectEngineCtx *de_ctx)
Definition: detect-engine-address.c:1337
DetectEngineFrameInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:521
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:841
StringParseUint16
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:337
DetectEngineReloadSetIdle
void DetectEngineReloadSetIdle(void)
Definition: detect-engine.c:2065
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:551
LiveDevice_::id
uint16_t id
Definition: util-device.h:56
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:487
DetectMetadataHashInit
int DetectMetadataHashInit(DetectEngineCtx *de_ctx)
Definition: detect-metadata.c:69
DetectEngineThreadCtx_::lua_blocked_function_errors
uint16_t lua_blocked_function_errors
Definition: detect.h:1227
DetectEngineThreadCtx_::global_keyword_ctxs_array
void ** global_keyword_ctxs_array
Definition: detect.h:1218
DETECT_EVENT_TOO_MANY_BUFFERS
@ DETECT_EVENT_TOO_MANY_BUFFERS
Definition: detect.h:1324
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:3775
TransformData_::options
void * options
Definition: detect.h:405
DetectEngineFrameInspectionEngine::mpm
bool mpm
Definition: detect.h:515
TmThreadCountThreadsByTmmFlags
uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags)
returns a count of all the threads that match the flag
Definition: tm-threads.c:2015
DetectBufferTypeSupportsMultiInstance
void DetectBufferTypeSupportsMultiInstance(const char *name)
Definition: detect-engine.c:1041
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
InspectionBuffer::orig
const uint8_t * orig
Definition: detect.h:387
DetectEngineInspectPacketPayload
uint8_t 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:152
DetectEngineAddToMaster
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:4587
ConfYamlHandleInclude
int ConfYamlHandleInclude(ConfNode *parent, const char *filename)
Include a file in the configuration.
Definition: conf-yaml-loader.c:114
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:481
SCSigSignatureOrderingModuleCleanup
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
Definition: detect-engine-sigorder.c:823
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1121
DetectEngineCtx_::keyword_id
int keyword_id
Definition: detect.h:941
DetectEngineMultiTenantSetup
int DetectEngineMultiTenantSetup(const bool unix_socket)
setup multi-detect / multi-tenancy
Definition: detect-engine.c:4224
PrefilterDeinit
void PrefilterDeinit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:623
SignatureProperties
Definition: detect.h:86
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
DetectBufferMpmRegistry_::next
struct DetectBufferMpmRegistry_ * next
Definition: detect.h:726
util-var-name.h
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:251
ConfDump
void ConfDump(void)
Dump configuration to stdout.
Definition: conf.c:746
HashTable_
Definition: util-hash.h:35
DetectEngineTenantMapping_::next
struct DetectEngineTenantMapping_ * next
Definition: detect.h:1529
DetectEngineSetEvent
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
Definition: detect-engine.c:4935
DetectEngineThreadCtx_::buffers_size
uint32_t buffers_size
Definition: detect.h:1154
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
AppLayerDecoderEventsFreeEvents
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
Definition: app-layer-events.c:133
DetectBufferType_::name
char name[32]
Definition: detect.h:455
DetectEngineCtx_::profile_sgh_ctx
struct SCProfileSghDetectCtx_ * profile_sgh_ctx
Definition: detect.h:954
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:80
DetectBufferMpmRegistry_
one time registration of keywords at start up
Definition: detect.h:685
SCReferenceConfDeinit
void SCReferenceConfDeinit(DetectEngineCtx *de_ctx)
Definition: util-reference-config.c:72
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:231
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *de_ctx)
Free a DetectEngineCtx::
Definition: detect-engine.c:2597
DetectEngineAppInspectionEngine_::sm_list_base
uint16_t sm_list_base
Definition: detect.h:436
InspectionBuffer::size
uint32_t size
Definition: detect.h:384
DetectEngineThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: detect.h:1127
DetectEngineReloadTenantsBlocking
int DetectEngineReloadTenantsBlocking(const int reload_cnt)
Reload all tenants and wait for loading to complete.
Definition: detect-engine.c:4089
InspectionBuffer::flags
uint8_t flags
Definition: detect.h:378
detect-engine-frame.h
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
SignatureInitDataBuffer_::multi_capable
bool multi_capable
Definition: detect.h:532
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:654
SCInstance_::conf_filename
const char * conf_filename
Definition: suricata.h:160
DetectEngineCtx_::prefilter_setting
enum DetectEnginePrefilterSetting prefilter_setting
Definition: detect.h:970
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:553
DetectParseDupSigHashFree
void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
Frees the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:2409
DetectBufferType_
Definition: detect.h:454
m
SCMutex m
Definition: flow-hash.h:6
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:622
PrefilterGenericMpmFrameRegister
int PrefilterGenericMpmFrameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-frame.c:207
DetectEngineGetVersion
uint32_t DetectEngineGetVersion(void)
Definition: detect-engine.c:3756
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:55
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:245
detect-engine-payload.h
DetectEngineThreadCtx_::lua_instruction_limit_errors
uint16_t lua_instruction_limit_errors
Definition: detect.h:1230
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1422
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:268
MAX
#define MAX(x, y)
Definition: suricata-common.h:395
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:83
DetectBufferIsPresent
bool DetectBufferIsPresent(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1344
SigMatchData_
Data needed for Match()
Definition: detect.h:358
InspectionBufferMultipleForList::init
uint32_t init
Definition: detect.h:400
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:50
DetectEngineThreadCtx_::counter_fnonmpm_list
uint16_t counter_fnonmpm_list
Definition: detect.h:1148
SigMatchData_::type
uint16_t type
Definition: detect.h:359
DetectEngineCtx_::version
uint32_t version
Definition: detect.h:919
DETECT_TRANSFORMS_MAX
#define DETECT_TRANSFORMS_MAX
Definition: detect.h:46
InspectionBuffer::orig_len
uint32_t orig_len
Definition: detect.h:386
DetectPort_::port2
uint16_t port2
Definition: detect.h:219
DetectEngineThreadCtx_::counter_nonmpm_list
uint16_t counter_nonmpm_list
Definition: detect.h:1147
DetectEngineThreadCtx_::events
uint16_t events
Definition: detect.h:1221
detect-engine-prefilter.h
util-unittest.h
TransformData_
Definition: detect.h:403
InspectionBufferGet
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
Definition: detect-engine.c:1498
PrefilterMultiGenericMpmRegister
int PrefilterMultiGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:804
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:650
DetectBufferTypeCloseRegistration
void DetectBufferTypeCloseRegistration(void)
Definition: detect-engine.c:1803
DetectEnginePktInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:495
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectEngineBufferTypeGetById
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1111
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:82
HashTableFree
void HashTableFree(HashTable *ht)
Definition: util-hash.c:78
TenantLoaderCtx_
Definition: detect-engine.c:3944
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1091
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:64
DetectBufferTypeSupportsPacket
void DetectBufferTypeSupportsPacket(const char *name)
Definition: detect-engine.c:1061
DetectEngineFrameInspectionEngine::Callback
InspectionBufferFrameInspectFunc Callback
Definition: detect.h:519
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:114
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:255
SCRConfDeInitContext
void SCRConfDeInitContext(DetectEngineCtx *de_ctx)
Releases de_ctx resources related to Reference Config API.
Definition: util-reference-config.c:179
InspectionBufferMultipleForList::size
uint32_t size
Definition: detect.h:398
DetectEngineCtx_::udp_whitelist
DetectPort * udp_whitelist
Definition: detect.h:975
DetectEngineThreadCtx_::mt_det_ctxs_hash
HashTable * mt_det_ctxs_hash
Definition: detect.h:1107
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
DetectEnginePktInspectionRun
bool DetectEnginePktInspectionRun(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p, uint8_t *alert_flags)
Definition: detect-engine.c:1955
DETECT_PREFILTER_AUTO
@ DETECT_PREFILTER_AUTO
Definition: detect.h:818
DetectEngineThreadCtx_::keyword_ctxs_size
int keyword_ctxs_size
Definition: detect.h:1215
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:168
AlertQueueInit
void AlertQueueInit(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine-alert.c:222
DetectAppLayerMultiRegister
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectionMultiBufferGetDataPtr GetData, int priority, int tx_min_progress)
Definition: detect-engine.c:2187
DetectEngineThreadCtx_::lua_rule_errors
uint16_t lua_rule_errors
Definition: detect.h:1224
SigString_::sig_error
char * sig_error
Definition: detect.h:791
DetectEngineAppInspectionEngine_::id
uint8_t id
Definition: detect.h:432
DetectEngineThreadCtx_::counter_alerts_suppressed
uint16_t counter_alerts_suppressed
Definition: detect.h:1144
PacketQueue_::mutex_q
SCMutex mutex_q
Definition: packet-queue.h:56
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:45
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1329
util-signal.h
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:435
TENANT_SELECTOR_UNKNOWN
@ TENANT_SELECTOR_UNKNOWN
Definition: detect.h:1517
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
InspectionBufferInit
void InspectionBufferInit(InspectionBuffer *buffer, uint32_t initial_size)
Definition: detect-engine.c:1555
DetectEngineMultiTenantEnabled
int DetectEngineMultiTenantEnabled(void)
Definition: detect-engine.c:3807
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
DetectEngineTenantMapping_::tenant_id
uint32_t tenant_id
Definition: detect.h:1524
InspectionBufferMultipleForList
Definition: detect.h:396
ThreadVars_::tmm_flags
uint8_t tmm_flags
Definition: threadvars.h:78
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:124
ConfNodeRemove
void ConfNodeRemove(ConfNode *node)
Remove (and SCFree) the provided configuration node.
Definition: conf.c:638
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:267
app-layer-htp.h
InspectionBufferSetupMultiEmpty
void InspectionBufferSetupMultiEmpty(InspectionBuffer *buffer)
setup the buffer empty
Definition: detect-engine.c:1565
DetectEngineTenantSelectors
DetectEngineTenantSelectors
Definition: detect.h:1516
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1182
InspectionBufferPktInspectFunc
int(* InspectionBufferPktInspectFunc)(struct DetectEngineThreadCtx_ *, const struct DetectEnginePktInspectionEngine *engine, const struct Signature_ *s, Packet *p, uint8_t *alert_flags)
Definition: detect.h:474
datasets.h
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
DetectEngineCtx_::requirements
SCDetectRequiresStatus * requirements
Definition: detect.h:1041
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:312
SigTableElmt_::TransformValidate
bool(* TransformValidate)(const uint8_t *content, uint16_t content_len, void *context)
Definition: detect.h:1283
util-device.h
DetectEngineThreadCtx_::counter_alerts_overflow
uint16_t counter_alerts_overflow
Definition: detect.h:1142
util-debug.h
DetectBufferTypeRegisterValidateCallback
void DetectBufferTypeRegisterValidateCallback(const char *name, bool(*ValidateCallback)(const Signature *, const char **sigerror))
Definition: detect-engine.c:1303
DetectEngineMoveToFreeList
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:4647
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
util-error.h
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint8_t matcher)
Definition: util-spm.c:138
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
SCProfilingPrefilterDestroyCtx
void SCProfilingPrefilterDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-prefilter.c:236
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:489
DetectEngineThreadCtx_::match_array_len
uint32_t match_array_len
Definition: detect.h:1186
MPM_HS
@ MPM_HS
Definition: util-mpm.h:38
MPM_AC
@ MPM_AC
Definition: util-mpm.h:36
SignatureInitData_::buffers_size
uint32_t buffers_size
Definition: detect.h:593
DetectMpmInitializePktMpms
void DetectMpmInitializePktMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:628
RUNMODE_CONF_TEST
@ RUNMODE_CONF_TEST
Definition: runmodes.h:53
DetectEngineThreadCtx_
Definition: detect.h:1090
PKT_STREAM_ADD
#define PKT_STREAM_ADD
Definition: decode.h:1268
DetectLoadersInit
void DetectLoadersInit(void)
Definition: detect-engine-loader.c:500
ThreadVars_::tm_slots
struct TmSlot_ * tm_slots
Definition: threadvars.h:95
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:565
DetectEngineBufferTypeGetDescriptionById
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1199
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
DETECT_SM_LIST_BASE64_DATA
@ DETECT_SM_LIST_BASE64_DATA
Definition: detect.h:121
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:255
DetectEngineThreadKeywordCtxItem_::id
int id
Definition: detect.h:811
PKT_PSEUDO_STREAM_END
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1275
DetectEngineThreadCtx_::buffers
InspectionBuffer * buffers
Definition: detect.h:1153
detect-engine-file.h
DetectEngineMasterCtx_::keyword_list
DetectEngineThreadKeywordCtxItem * keyword_list
Definition: detect.h:1559
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:563
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:248
flow-worker.h
DetectEngineMasterCtx_::tenant_selector
enum DetectEngineTenantSelectors tenant_selector
Definition: detect.h:1550
DetectEngineCtx_::keyword_hash
HashListTable * keyword_hash
Definition: detect.h:943
BOOL2STR
#define BOOL2STR(b)
Definition: util-debug.h:527
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:1624
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:248
util-reference-config.h
Packet_::pcap_v
PcapPacketVars pcap_v
Definition: decode.h:562
SignatureInitData_::list
int list
Definition: detect.h:570
DetectEngineCtx_::failure_fatal
bool failure_fatal
Definition: detect.h:842
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:649
DetectEngineAppInspectionEngine_::GetMultiData
InspectionMultiBufferGetDataPtr GetMultiData
Definition: detect.h:442
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
DetectMetadataHashFree
void DetectMetadataHashFree(DetectEngineCtx *de_ctx)
Definition: detect-metadata.c:80
DetectBufferTypeMaxId
int DetectBufferTypeMaxId(void)
Definition: detect-engine.c:919
DatasetPostReloadCleanup
void DatasetPostReloadCleanup(void)
Definition: datasets.c:812
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectEngineBufferTypeValidateTransform
bool DetectEngineBufferTypeValidateTransform(DetectEngineCtx *de_ctx, int sm_list, const uint8_t *content, uint16_t content_len, const char **namestr)
Check content byte array compatibility with transforms.
Definition: detect-engine.c:1672
DetectEngineCtx_::sm_types_prefilter
bool * sm_types_prefilter
Definition: detect.h:1017
DetectEngineEnabled
int DetectEngineEnabled(void)
Check if detection is enabled.
Definition: detect-engine.c:3742
SigMatchList2DataArray
SigMatchData * SigMatchList2DataArray(SigMatch *head)
convert SigMatch list to SigMatchData array
Definition: detect-parse.c:1856
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3312
DetectEngineReloadIsIdle
int DetectEngineReloadIsIdle(void)
Definition: detect-engine.c:2073
DetectEngineFrameInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:516
DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_MATCH
Definition: detect-engine-state.h:38
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1312
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:353
DetectEngineCtx_::mpm_matcher
uint8_t mpm_matcher
Definition: detect.h:844
detect-engine-port.h
SCProfilingRuleDestroyCtx
void SCProfilingRuleDestroyCtx(struct SCProfileDetectCtx_ *)
LiveDevice_::tenant_id
uint32_t tenant_id
Definition: util-device.h:64
SCClassConfDeinit
void SCClassConfDeinit(DetectEngineCtx *de_ctx)
Definition: util-classification-config.c:81
InspectionBuffer::inspect_offset
uint64_t inspect_offset
Definition: detect.h:375
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
Definition: detect-engine-content-inspection.h:36
DetectEngineCtx_::frame_inspect_engines
DetectEngineFrameInspectionEngine * frame_inspect_engines
Definition: detect.h:997
DetectEngineMasterCtx_::free_list
DetectEngineCtx * free_list
Definition: detect.h:1548
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:313
DetectEngineSyncState
DetectEngineSyncState
Definition: detect-engine.c:2025
LiveDevice_::dev
char * dev
Definition: util-device.h:51
PatternMatchThreadPrepare
void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:911
ConfYamlLoadString
int ConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:520
DetectEngineThreadKeywordCtxItem_::next
struct DetectEngineThreadKeywordCtxItem_ * next
Definition: detect.h:810
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:114
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:104
DetectEngineBufferTypeRegister
int DetectEngineBufferTypeRegister(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1178
DetectPort_
Port structure for detection engine.
Definition: detect.h:217
InspectionBuffer::buf
uint8_t * buf
Definition: detect.h:383
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:648
SCProfilingRuleThreadCleanup
void SCProfilingRuleThreadCleanup(DetectEngineThreadCtx *)
DetectBufferType_::ValidateCallback
bool(* ValidateCallback)(const struct Signature_ *, const char **sigerror)
Definition: detect.h:465
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:124
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
hashlittle_safe
uint32_t hashlittle_safe(const void *key, size_t length, uint32_t initval)
Definition: util-hash-lookup3.c:482
DetectEngineThreadCtx_::base64_decoded_len
int base64_decoded_len
Definition: detect.h:1133
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2228
detect-engine-tag.h
DetectEngineThreadCtx_::lua_memory_limit_errors
uint16_t lua_memory_limit_errors
Definition: detect.h:1233
util-profiling.h
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:83
DetectEngineInspectStream
uint8_t DetectEngineInspectStream(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
inspect engine for stateful rules
Definition: detect-engine-payload.c:298
DetectEngineLoadTenantBlocking
int DetectEngineLoadTenantBlocking(uint32_t tenant_id, const char *yaml)
Load a tenant and wait for loading to complete.
Definition: detect-engine.c:4061
TmModuleDetectLoaderRegister
void TmModuleDetectLoaderRegister(void)
Definition: detect-engine-loader.c:658
Signature_::flags
uint32_t flags
Definition: detect.h:602
MPM_AC_KS
@ MPM_AC_KS
Definition: util-mpm.h:37
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2558
RuleMatchCandidateTxArrayFree
void RuleMatchCandidateTxArrayFree(DetectEngineThreadCtx *det_ctx)
Definition: detect.c:987
DetectEngineInitializeFastPatternList
void DetectEngineInitializeFastPatternList(DetectEngineCtx *de_ctx)
Definition: detect-fast-pattern.c:149
Packet_
Definition: decode.h:479
DetectEngineFrameInspectionEngine::alproto
AppProto alproto
Definition: detect.h:512
ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
Definition: detect.h:1059
DE_STATE_FLAG_BASE
#define DE_STATE_FLAG_BASE
Definition: detect-engine-state.h:63
detect-engine-build.h
type
uint16_t type
Definition: decode-vlan.c:107
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:485
DetectEngineTenantRegisterLivedev
int DetectEngineTenantRegisterLivedev(uint32_t tenant_id, int device_id)
Definition: detect-engine.c:4504
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:42
DetectEngineBufferTypeSupportsFrames
void DetectEngineBufferTypeSupportsFrames(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1217
InspectionBufferFrameInspectFunc
int(* InspectionBufferFrameInspectFunc)(struct DetectEngineThreadCtx_ *, const struct DetectEngineFrameInspectionEngine *engine, const struct Signature_ *s, Packet *p, const struct Frames *frames, const struct Frame *frame)
Definition: detect.h:507
DetectEngineCtx_::frame_mpms_list
DetectBufferMpmRegistry * frame_mpms_list
Definition: detect.h:998
conf.h
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@80 v2
DetectEngineCtx_::sgh_mpm_ctx_cnf
uint8_t sgh_mpm_ctx_cnf
Definition: detect.h:939
DetectBufferType_::packet
bool packet
Definition: detect.h:460
DetectEngineMasterCtx_::multi_tenant_enabled
int multi_tenant_enabled
Definition: detect.h:1536
TmModuleGetById
TmModule * TmModuleGetById(int id)
Returns a TM Module by its id.
Definition: tm-modules.c:79
TmSlot_
Definition: tm-threads.h:53
DetectEngineFrameInspectionEngine
Definition: detect.h:511
TenantLoaderCtx
struct TenantLoaderCtx_ TenantLoaderCtx
util-magic.h
DetectEngineCtx_::max_uniq_toserver_groups
uint16_t max_uniq_toserver_groups
Definition: detect.h:897
SignatureInitDataBufferCheckExpand
int SignatureInitDataBufferCheckExpand(Signature *s)
check if buffers array still has space left, expand if not
Definition: detect-parse.c:1493
Packet_::livedev
struct LiveDevice_ * livedev
Definition: decode.h:593
TmEcode
TmEcode
Definition: tm-threads-common.h:81
DetectEnginePktInspectionEngine::Callback
InspectionBufferPktInspectFunc Callback
Definition: detect.h:493
ALPROTO_DOH2
@ ALPROTO_DOH2
Definition: app-layer-protos.h:61
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:670
DetectEngineSyncer_::state
enum DetectEngineSyncState state
Definition: detect-engine.c:2033
SpmMakeThreadCtx
SpmThreadCtx * SpmMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:153
DetectEngineCtx_::profile_keyword_ctx
struct SCProfileKeywordDetectCtx_ * profile_keyword_ctx
Definition: detect.h:951
SCInstance_::additional_configs
const char ** additional_configs
Definition: suricata.h:161
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:1269
reputation.h
ConfCreateContextBackup
void ConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:669
SCProfilingPrefilterThreadCleanup
void SCProfilingPrefilterThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-prefilter.c:281
util-action.h
HashListTable_
Definition: util-hashlist.h:37
DetectEngineCtx_::byte_extract_max_local_id
int32_t byte_extract_max_local_id
Definition: detect.h:916
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:409
DetectEnginePktInspectionEngine::sm_list_base
uint16_t sm_list_base
Definition: detect.h:490
ALPROTO_HTTP2
@ ALPROTO_HTTP2
Definition: app-layer-protos.h:64
SIG_PROP_FLOW_ACTION_PACKET
@ SIG_PROP_FLOW_ACTION_PACKET
Definition: detect.h:81
signature_properties
const struct SignatureProperties signature_properties[SIG_TYPE_MAX]
Definition: detect-engine.c:111
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:252
PacketQueue_::cond_q
SCCondT cond_q
Definition: packet-queue.h:57
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:329
DetectEngineFrameInspectionEngine::dir
uint8_t dir
Definition: detect.h:513
SIG_FLAG_REQUIRE_STREAM_ONLY
#define SIG_FLAG_REQUIRE_STREAM_ONLY
Definition: detect.h:257
SpmDestroyGlobalThreadCtx
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:144
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
Definition: detect-engine-state.h:39
DetectEngineThreadCtx_::mtc
MpmThreadCtx mtc
Definition: detect.h:1196
DetectEngineRegisterTests
void DetectEngineRegisterTests(void)
Definition: detect-engine.c:5143
SigString_::filename
char * filename
Definition: detect.h:789
DetectBufferType_::multi_instance
bool multi_instance
Definition: detect.h:463
DetectLoaderQueueTask
int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx, LoaderFreeFunc FreeFunc)
Definition: detect-engine-loader.c:423
DETECT_ENGINE_TYPE_TENANT
@ DETECT_ENGINE_TYPE_TENANT
Definition: detect.h:826
DetectEngineBufferTypeSupportsTransformations
void DetectEngineBufferTypeSupportsTransformations(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1241
DetectEngineBufferTypeSupportsMpmGetById
bool DetectEngineBufferTypeSupportsMpmGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1267
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:957
DetectSigmatchListEnumToString
const char * DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
Definition: detect-engine.c:4906
TmModule_
Definition: tm-modules.h:44
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:430
SRepReloadComplete
void SRepReloadComplete(void)
Increment effective reputation version after a rule/reputation reload is complete.
Definition: reputation.c:172
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:292
detect-engine-content-inspection.h
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:781
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:141
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:449
DetectEngineBufferTypeSupportsFramesGetById
bool DetectEngineBufferTypeSupportsFramesGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1276
DetectBufferType_::id
int id
Definition: detect.h:457
DetectEngineCtx_::spm_matcher
uint8_t spm_matcher
Definition: detect.h:845
DetectEngineBufferTypeRegisterWithFrameEngines
int DetectEngineBufferTypeRegisterWithFrameEngines(DetectEngineCtx *de_ctx, const char *name, const int direction, const AppProto alproto, const uint8_t frame_type)
Definition: detect-engine.c:1144
SCReferenceConfInit
void SCReferenceConfInit(DetectEngineCtx *de_ctx)
Definition: util-reference-config.c:52
DetectEnginePktInspectionEngine::GetData
InspectionBufferGetPktDataPtr GetData
Definition: detect.h:492
DETECT_ENGINE_TYPE_NORMAL
@ DETECT_ENGINE_TYPE_NORMAL
Definition: detect.h:823
SignatureInitDataBuffer_::tail
SigMatch * tail
Definition: detect.h:536
InspectionBufferCopy
void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
Definition: detect-engine.c:1641
FlowWorkerGetDetectCtxPtr
void * FlowWorkerGetDetectCtxPtr(void *flow_worker)
Definition: flow-worker.c:715
detect-fast-pattern.h
DetectBufferType_::frame
bool frame
Definition: detect.h:461
DetectEngineBufferTypeSupportsMultiInstanceGetById
bool DetectEngineBufferTypeSupportsMultiInstanceGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1249
SCCondSignal
#define SCCondSignal
Definition: threads-debug.h:139
ThreadVars_::inq
Tmq * inq
Definition: threadvars.h:89
util-conf.h
DetectEngineCtx_::sig_stat
SigFileLoaderStat sig_stat
Definition: detect.h:1008
Packet_::flow
struct Flow_ * flow
Definition: decode.h:518
DetectEngineFrameMpmRegister
void DetectEngineFrameMpmRegister(DetectEngineCtx *de_ctx, const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id), AppProto alproto, uint8_t type)
Definition: detect-engine-mpm.c:398
DetectEngineThreadCtx_::to_clear_queue
uint32_t * to_clear_queue
Definition: detect.h:1156
SpmDestroyThreadCtx
void SpmDestroyThreadCtx(SpmThreadCtx *thread_ctx)
Definition: util-spm.c:163
DetectEngineCtx_::profile_prefilter_ctx
struct SCProfilePrefilterDetectCtx_ * profile_prefilter_ctx
Definition: detect.h:952
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
DetectEnginePktInspectionEngine::v1
struct DetectEnginePktInspectionEngine::@83 v1
TENANT_SELECTOR_DIRECT
@ TENANT_SELECTOR_DIRECT
Definition: detect.h:1518
DetectEnginePktInspectionSetup
int DetectEnginePktInspectionSetup(Signature *s)
Definition: detect-engine.c:2003
DetectBufferTypeRegister
int DetectBufferTypeRegister(const char *name)
Definition: detect-engine.c:1027
InspectEngineFuncPtr
uint8_t(* InspectEngineFuncPtr)(struct DetectEngineCtx_ *de_ctx, struct DetectEngineThreadCtx_ *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const struct Signature_ *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Definition: detect.h:424
SleepMsec
#define SleepMsec(msec)
Definition: tm-threads.h:45
flags
uint8_t flags
Definition: decode-gre.h:0
DetectRegisterThreadCtxFuncs
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *), int mode)
Register Thread keyword context Funcs.
Definition: detect-engine.c:3596
MpmStoreInit
int MpmStoreInit(DetectEngineCtx *de_ctx)
Initializes the MpmStore mpm hash table to be used by the detection engine context.
Definition: detect-engine-mpm.c:1363
DetectEngineMasterCtx_::keyword_id
int keyword_id
Definition: detect.h:1560
DetectEngineCtx_::app_mpms_list
DetectBufferMpmRegistry * app_mpms_list
Definition: detect.h:990
suricata-common.h
SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
@ SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
Definition: detect.h:83
DetectEngineCtxInitStubForMT
DetectEngineCtx * DetectEngineCtxInitStubForMT(void)
Definition: detect-engine.c:2548
DetectBufferTypeSupportsMpm
void DetectBufferTypeSupportsMpm(const char *name)
Definition: detect-engine.c:1071
DetectEngineThreadCtx_::inspect
struct DetectEngineThreadCtx_::@96 inspect
util-path.h
DetectEngineThreadCtx_::tenant_id
uint32_t tenant_id
Definition: detect.h:1093
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
detect-byte-extract.h
DetectEngineCtx_::buffer_type_hash_name
HashListTable * buffer_type_hash_name
Definition: detect.h:985
DetectEngineCtx_::next
struct DetectEngineCtx_ * next
Definition: detect.h:964
DETECT_ENGINE_TYPE_DD_STUB
@ DETECT_ENGINE_TYPE_DD_STUB
Definition: detect.h:824
InspectionBufferApplyTransforms
void InspectionBufferApplyTransforms(InspectionBuffer *buffer, const DetectEngineTransforms *transforms)
Definition: detect-engine.c:1697
TENANT_SELECTOR_VLAN
@ TENANT_SELECTOR_VLAN
Definition: detect.h:1519
DetectEngineBumpVersion
void DetectEngineBumpVersion(void)
Definition: detect-engine.c:3766
AppLayerDecoderEventsSetEventRaw
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
Definition: app-layer-events.c:91
DetectBufferGetFirstSigMatch
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1323
DetectEngineFrameInspectionEngine::next
struct DetectEngineFrameInspectionEngine * next
Definition: detect.h:524
SigTableElmt_::Transform
void(* Transform)(InspectionBuffer *, void *context)
Definition: detect.h:1282
SignatureInitData_::curbuf
SignatureInitDataBuffer * curbuf
Definition: detect.h:594
ConfNode_::name
char * name
Definition: conf.h:33
DetectEngineInspectFrameBufferGeneric
int DetectEngineInspectFrameBufferGeneric(DetectEngineThreadCtx *det_ctx, const DetectEngineFrameInspectionEngine *engine, const Signature *s, Packet *p, const Frames *frames, const Frame *frame)
Do the content inspection & validation for a signature.
Definition: detect-engine-frame.c:556
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3539
util-spm.h
DetectEnginePktInspectionEngine::next
struct DetectEnginePktInspectionEngine * next
Definition: detect.h:497
DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT
#define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT
Definition: detect-engine.c:92
version
uint8_t version
Definition: decode-gre.h:1
ConfRestoreContextBackup
void ConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:679
PatternMatchDefaultMatcher
uint8_t PatternMatchDefaultMatcher(void)
Function to return the multi pattern matcher algorithm to be used by the engine, based on the mpm-alg...
Definition: detect-engine-mpm.c:854
DetectEngineFrameInspectionEngine::v1
struct DetectEngineFrameInspectionEngine::@84 v1
util-classification-config.h
DetectEngineTenantRegisterPcapFile
int DetectEngineTenantRegisterPcapFile(uint32_t tenant_id)
Definition: detect-engine.c:4520
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
InspectionBufferSetupMulti
void InspectionBufferSetupMulti(InspectionBuffer *buffer, const DetectEngineTransforms *transforms, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1578
FatalError
#define FatalError(...)
Definition: util-debug.h:502
SigGroupHeadHashFree
void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by SigGroupHeadHashInit() function.
Definition: detect-engine-siggroup.c:310
DetectEngineInspectGenericList
uint8_t DetectEngineInspectGenericList(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct 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:2097
DetectEngineAppInspectionEngineSignatureFree
void DetectEngineAppInspectionEngineSignatureFree(DetectEngineCtx *de_ctx, Signature *s)
free app inspect engines for a signature
Definition: detect-engine.c:813
DETECT_ENGINE_CONTENT_INSPECTION_MODE_HEADER
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_HEADER
Definition: detect-engine-content-inspection.h:33
util-hash-lookup3.h
DETECT_SM_LIST_TMATCH
@ DETECT_SM_LIST_TMATCH
Definition: detect.h:126
DetectEngineCtx_::tcp_whitelist
DetectPort * tcp_whitelist
Definition: detect.h:974
DetectEngineCtx_::loader_id
int loader_id
Definition: detect.h:967
SCInstance_::sig_file
char * sig_file
Definition: suricata.h:128
ENGINE_PROFILE_CUSTOM
@ ENGINE_PROFILE_CUSTOM
Definition: detect.h:1053
TransformData_::transform
int transform
Definition: detect.h:404
DETECT_ENGINE_INSPECT_SIG_NO_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
Definition: detect-engine-state.h:37
DetectEngineCtx_::pkt_inspect_engines
DetectEnginePktInspectionEngine * pkt_inspect_engines
Definition: detect.h:994
DetectBufferGetLastSigMatch
SigMatch * DetectBufferGetLastSigMatch(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1333
DetectEngineBufferTypeSupportsMpm
void DetectEngineBufferTypeSupportsMpm(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1233
SIG_TYPE_MAX
@ SIG_TYPE_MAX
Definition: detect.h:77
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
DetectEngineCtx_::sm_types_silent_error
bool * sm_types_silent_error
Definition: detect.h:1018
DetectEngineThreadCtx_::non_pf_id_array
SigIntId * non_pf_id_array
Definition: detect.h:1102
DetectEngineAppInspectionEngine_::progress
int16_t progress
Definition: detect.h:437
DetectEngineThreadKeywordCtxItem_::FreeFunc
void(* FreeFunc)(void *)
Definition: detect.h:808
DetectBufferTypeGetDescriptionByName
const char * DetectBufferTypeGetDescriptionByName(const char *name)
Definition: detect-engine.c:1208
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:232
DetectEngineFreeFastPatternList
void DetectEngineFreeFastPatternList(DetectEngineCtx *de_ctx)
Definition: detect-fast-pattern.c:171
DetectBufferTypeSupportsTransformations
void DetectBufferTypeSupportsTransformations(const char *name)
Definition: detect-engine.c:1081
detect-engine-sigorder.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
DetectAddressMapInit
int DetectAddressMapInit(DetectEngineCtx *de_ctx)
Definition: detect-engine-address.c:1326
ConfInit
void ConfInit(void)
Initialize the configuration system.
Definition: conf.c:120
ENGINE_PROFILE_UNKNOWN
@ ENGINE_PROFILE_UNKNOWN
Definition: detect.h:1049
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:376
SignatureInitData_::buffers
SignatureInitDataBuffer * buffers
Definition: detect.h:591
DetectEngineCtx_::app_inspect_engines
DetectEngineAppInspectionEngine * app_inspect_engines
Definition: detect.h:993
DetectEngineCtx_::filemagic_thread_ctx_id
int filemagic_thread_ctx_id
Definition: detect.h:888
DetectEngineSyncer_
Definition: detect-engine.c:2031
DetectEngineThreadCtx_::global_keyword_ctxs_size
int global_keyword_ctxs_size
Definition: detect.h:1217
PrefilterInit
void PrefilterInit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:630
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:374
DetectEngineThreadCtx_::tv
ThreadVars * tv
Definition: detect.h:1098
DetectThreadCtxGetGlobalKeywordThreadCtx
void * DetectThreadCtxGetGlobalKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3730
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
DETECT_TBLSIZE
int DETECT_TBLSIZE
Definition: detect-engine-register.c:301
SRepInit
int SRepInit(DetectEngineCtx *de_ctx)
init reputation
Definition: reputation.c:577
DetectEngineReloadStart
int DetectEngineReloadStart(void)
Definition: detect-engine.c:2039
DetectEngineUnsetParseMetadata
void DetectEngineUnsetParseMetadata(void)
Definition: detect-engine.c:4896
PKT_SRC_DETECT_RELOAD_FLUSH
@ PKT_SRC_DETECT_RELOAD_FLUSH
Definition: decode.h:64
DetectEngineThreadCtx_::counter_alerts
uint16_t counter_alerts
Definition: detect.h:1140
InspectionBuffer::len
uint32_t len
Definition: detect.h:382
InspectionBufferSetup
void InspectionBufferSetup(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1593
DetectEngineThreadCtx_::keyword_ctxs_array
void ** keyword_ctxs_array
Definition: detect.h:1214
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DetectEngineMasterCtx_
Definition: detect.h:1532
ConfNode_
Definition: conf.h:32
Signature_::id
uint32_t id
Definition: detect.h:636
HashListTableBucket_
Definition: util-hashlist.h:28
DetectEngineThreadKeywordCtxItem_::name
const char * name
Definition: detect.h:812
detect-tcphdr.h
DetectEngineThreadCtx_::base64_decoded_len_max
int base64_decoded_len_max
Definition: detect.h:1134
HashListTableRemove
int HashListTableRemove(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:154
DatasetReload
void DatasetReload(void)
Definition: datasets.c:790
DetectBufferType_::transforms
DetectEngineTransforms transforms
Definition: detect.h:466
detect-engine-iponly.h
DetectEngineType
DetectEngineType
Definition: detect.h:822
detect-parse.h
SignatureInitDataBuffer_::id
uint32_t id
Definition: detect.h:528
Signature_
Signature container.
Definition: detect.h:601
SigMatch_
a single match condition for a signature
Definition: detect.h:349
DetectEngineCtx_::tenant_path
char * tenant_path
Definition: detect.h:1038
DetectEngineAppInspectionEngine_::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:446
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:132
DetectEngineThreadCtx_::multi_inspect
struct DetectEngineThreadCtx_::@97 multi_inspect
InspectionBufferClean
void InspectionBufferClean(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine.c:1470
DetectBufferType_::parent_id
int parent_id
Definition: detect.h:458
DETECT_PREFILTER_MPM
@ DETECT_PREFILTER_MPM
Definition: detect.h:817
ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL
Definition: detect.h:1058
TenantLoaderCtx_::yaml
char * yaml
Definition: detect-engine.c:3947
DetectLoadersSync
int DetectLoadersSync(void)
wait for loader tasks to complete
Definition: detect-engine-loader.c:457
SCProfilingSghDestroyCtx
void SCProfilingSghDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-rulegroups.c:304
HashTableInit
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hash.c:35
DetectEngineTenantMapping_::traffic_id
uint32_t traffic_id
Definition: detect.h:1527
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:74
spm_table
SpmTableElmt spm_table[SPM_TABLE_SIZE]
Definition: util-spm.c:62
DetectEngineReference
DetectEngineCtx * DetectEngineReference(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:3798
ENGINE_PROFILE_HIGH
@ ENGINE_PROFILE_HIGH
Definition: detect.h:1052
DetectEngineThreadCtx_::base64_decoded
uint8_t * base64_decoded
Definition: detect.h:1132
TenantLoaderCtx_::reload_cnt
int reload_cnt
Definition: detect-engine.c:3946
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
DetectEngineSyncer
struct DetectEngineSyncer_ DetectEngineSyncer
DetectMpmInitializeAppMpms
void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:236
EngineModeIsIPS
int EngineModeIsIPS(void)
Definition: suricata.c:229
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:410
DetectEngineThreadCtx_::de_ctx
DetectEngineCtx * de_ctx
Definition: detect.h:1212
suricata.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:858
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:431
PmqFree
void PmqFree(PrefilterRuleStore *pmq)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
InspectionBufferMultipleForListGet
InspectionBuffer * InspectionBufferMultipleForListGet(DetectEngineThreadCtx *det_ctx, const int list_id, const uint32_t local_id)
for a InspectionBufferMultipleForList get a InspectionBuffer
Definition: detect-engine.c:1518
DETECT_ENGINE_TYPE_MT_STUB
@ DETECT_ENGINE_TYPE_MT_STUB
Definition: detect.h:825
detect-uricontent.h
ConfDeInit
void ConfDeInit(void)
De-initializes the configuration system.
Definition: conf.c:688
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:987
ThresholdCacheThreadFree
void ThresholdCacheThreadFree(void)
Definition: detect-engine-threshold.c:454
Packet_::vlan_id
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition: decode.h:506
DetectEngineReload
int DetectEngineReload(const SCInstance *suri)
Reload the detection engine.
Definition: detect-engine.c:4714
DetectEngineBufferRunValidateCallback
bool DetectEngineBufferRunValidateCallback(const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
Definition: detect-engine.c:1313
DetectEngineCtx_::sigerror
const char * sigerror
Definition: detect.h:931
DetectBufferType_::SetupCallback
void(* SetupCallback)(const struct DetectEngineCtx_ *, struct Signature_ *)
Definition: detect.h:464
DetectAppLayerInspectEngineRegister
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
Definition: detect-engine.c:238
DetectEngineThreadCtx_::mt_det_ctxs_cnt
uint32_t mt_det_ctxs_cnt
Definition: detect.h:1105
DetectEngineContentInspectionBuffer
bool DetectEngineContentInspectionBuffer(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const InspectionBuffer *b, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
Definition: detect-engine-content-inspection.c:741
likely
#define likely(expr)
Definition: util-optimize.h:32
DetectEngineMasterCtx_::lock
SCMutex lock
Definition: detect.h:1533
DetectEnginePktInspectionEngine::mpm
bool mpm
Definition: detect.h:488
SCInstance_
Definition: suricata.h:123
DetectEngineCtx_::spm_global_thread_ctx
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition: detect.h:892
DetectEngineClearMaster
void DetectEngineClearMaster(void)
Definition: detect-engine.c:4687
SRepDestroy
void SRepDestroy(DetectEngineCtx *de_ctx)
Definition: reputation.c:654
StatsRegisterAvgCounter
uint16_t StatsRegisterAvgCounter(const char *name, struct ThreadVars_ *tv)
Registers a counter, whose value holds the average of all the values assigned to it.
Definition: counters.c:981
SIG_PROP_FLOW_ACTION_FLOW
@ SIG_PROP_FLOW_ACTION_FLOW
Definition: detect.h:82
DetectBufferTypeSetDescriptionByName
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
Definition: detect-engine.c:1188
SignatureInitData_::transforms
DetectEngineTransforms transforms
Definition: detect.h:573
SCClassConfInit
void SCClassConfInit(DetectEngineCtx *de_ctx)
Definition: util-classification-config.c:61
SigString_::sig_str
char * sig_str
Definition: detect.h:790
SCStatFn
#define SCStatFn(pathname, statbuf)
Definition: util-path.h:35
DetectUnregisterThreadCtxFuncs
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
Definition: detect-engine.c:3648
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
SCInstance_::sig_file_exclusive
bool sig_file_exclusive
Definition: suricata.h:129
TVT_PPT
@ TVT_PPT
Definition: tm-threads-common.h:89
DetectEngineFrameInspectEngineRegister
void DetectEngineFrameInspectEngineRegister(DetectEngineCtx *de_ctx, const char *name, int dir, InspectionBufferFrameInspectFunc Callback, AppProto alproto, uint8_t type)
register inspect engine at start up time
Definition: detect-engine.c:377
DetectEngineTenantRegisterVlanId
int DetectEngineTenantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
Definition: detect-engine.c:4510
flow.h
SignatureInitDataBuffer_
Definition: detect.h:527
DetectEngineSetParseMetadata
void DetectEngineSetParseMetadata(void)
Definition: detect-engine.c:4891
DetectEngineContentInspection
bool DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer, const uint32_t buffer_len, const uint32_t stream_start_offset, const uint8_t flags, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
Definition: detect-engine-content-inspection.c:717
SigIntId
#define SigIntId
Definition: suricata-common.h:315
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:91
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:237
DetectPktMpmRegisterByParentId
void DetectPktMpmRegisterByParentId(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:590
TENANT_SELECTOR_LIVEDEV
@ TENANT_SELECTOR_LIVEDEV
Definition: detect.h:1520
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:459
DetectEngineFrameInspectionEngine::type
uint8_t type
Definition: detect.h:514
StatsRegisterCounter
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:961
DetectSigmatchListEnum
DetectSigmatchListEnum
Definition: detect.h:112
DetectEngineMasterCtx_::version
uint32_t version
Definition: detect.h:1539
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectEngineCtx_::sig_array_len
uint32_t sig_array_len
Definition: detect.h:859
util-enum.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
DetectEngineTenantUnregisterPcapFile
int DetectEngineTenantUnregisterPcapFile(uint32_t tenant_id)
Definition: detect-engine.c:4526
TenantLoaderCtx_::tenant_id
uint32_t tenant_id
Definition: detect-engine.c:3945
DetectEngineCtx_::signum
uint32_t signum
Definition: detect.h:861
DetectEngineCtx_::tenant_id
uint32_t tenant_id
Definition: detect.h:847
SignatureInitData_::buffer_index
uint32_t buffer_index
Definition: detect.h:592
detect-engine-loader.h
SigFileLoaderStat_
Signature loader statistics.
Definition: detect.h:797
DetectEngineInspectPktBufferGeneric
int DetectEngineInspectPktBufferGeneric(DetectEngineThreadCtx *det_ctx, const DetectEnginePktInspectionEngine *engine, const Signature *s, Packet *p, uint8_t *_alert_flags)
Do the content inspection & validation for a signature.
Definition: detect-engine.c:2236
DetectEngineCtx_::buffer_type_hash_id
HashListTable * buffer_type_hash_id
Definition: detect.h:986
DetectEngineGetByTenantId
DetectEngineCtx * DetectEngineGetByTenantId(uint32_t tenant_id)
Definition: detect-engine.c:4537
DetectEngineCtx_::base64_decode_max_len
uint32_t base64_decode_max_len
Definition: detect.h:926
InspectionBufferFree
void InspectionBufferFree(InspectionBuffer *buffer)
Definition: detect-engine.c:1612
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:124
DETECT_SM_LIST_SUPPRESS
@ DETECT_SM_LIST_SUPPRESS
Definition: detect.h:129
SCMutex
#define SCMutex
Definition: threads-debug.h:114
InspectionBufferMultipleForList::inspection_buffers
InspectionBuffer * inspection_buffers
Definition: detect.h:397
InspectionBufferMultipleForList::max
uint32_t max
Definition: detect.h:399
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
DetectEngineAppInspectionEngine2Signature
int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:726
SCClassConfLoadClassificationConfigFile
bool SCClassConfLoadClassificationConfigFile(DetectEngineCtx *de_ctx, FILE *fd)
Loads the Classtype info from the classification.config file.
Definition: util-classification-config.c:524
DetectEngineTenantUnregisterVlanId
int DetectEngineTenantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
Definition: detect-engine.c:4515
SCStat
struct stat SCStat
Definition: util-path.h:33
detect-engine-address.h
PmqSetup
int PmqSetup(PrefilterRuleStore *pmq)
Setup a pmq.
Definition: util-prefilter.c:37
PatternMatchThreadDestroy
void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:906
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:77
SCProfilingRuleThreadSetup
void SCProfilingRuleThreadSetup(struct SCProfileDetectCtx_ *, DetectEngineThreadCtx *)
VarNameStoreActivate
int VarNameStoreActivate(void)
Definition: util-var-name.c:214
DetectEngineThreadCtx_::counter_mpm_list
uint16_t counter_mpm_list
Definition: detect.h:1146
RuleMatchCandidateTxArrayInit
void RuleMatchCandidateTxArrayInit(DetectEngineThreadCtx *det_ctx, uint32_t size)
Definition: detect.c:974
SCProfilingKeywordThreadSetup
void SCProfilingKeywordThreadSetup(SCProfileKeywordDetectCtx *ctx, DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-keywords.c:284
util-threshold-config.h
DetectEngineReloadIsStart
int DetectEngineReloadIsStart(void)
Definition: detect-engine.c:2053
DetectRegisterThreadCtxGlobalFuncs
int DetectRegisterThreadCtxGlobalFuncs(const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *))
Register Thread keyword context Funcs (Global)
Definition: detect-engine.c:3686
DetectEngineThreadCtx_::tenant_array_size
uint32_t tenant_array_size
Definition: detect.h:1110
DetectEngineThreadCtx_::tenant_array
struct DetectEngineTenantMapping_ * tenant_array
Definition: detect.h:1109
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:170
detect-engine-threshold.h
FlowWorkerReplaceDetectCtx
void FlowWorkerReplaceDetectCtx(void *flow_worker, void *detect_ctx)
Definition: flow-worker.c:708
StringHashDjb2
uint32_t StringHashDjb2(const uint8_t *data, uint32_t datalen)
Definition: util-hash-string.c:22
DetectEngineBufferTypeGetByIdTransforms
int DetectEngineBufferTypeGetByIdTransforms(DetectEngineCtx *de_ctx, const int id, TransformData *transforms, int transform_cnt)
Definition: detect-engine.c:1810
DetectEngineThreadCtx_::TenantGetId
uint32_t(* TenantGetId)(const void *, const Packet *p)
Definition: detect.h:1112
SCProfilingPrefilterThreadSetup
void SCProfilingPrefilterThreadSetup(SCProfilePrefilterDetectCtx *ctx, DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-prefilter.c:245
SCClassConfDeInitContext
void SCClassConfDeInitContext(DetectEngineCtx *de_ctx)
Releases resources used by the Classification Config API.
Definition: util-classification-config.c:190
DetectBufferType_::description
char description[128]
Definition: detect.h:456
ENGINE_PROFILE_MEDIUM
@ ENGINE_PROFILE_MEDIUM
Definition: detect.h:1051
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:250
DetectEngineFrameInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:523
DetectEngineThreadCtx_::match_array
Signature ** match_array
Definition: detect.h:1183
ConfNodeLookupChildValue
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:809