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-events.h"
37 #include "app-layer-htp.h"
38 
39 #include "detect-parse.h"
40 #include "detect-engine-sigorder.h"
41 
42 #include "detect-engine-build.h"
43 #include "detect-engine-buffer.h"
44 #include "detect-engine-siggroup.h"
45 #include "detect-engine-address.h"
46 #include "detect-engine-port.h"
48 #include "detect-engine-mpm.h"
49 #include "detect-engine-iponly.h"
50 #include "detect-engine-tag.h"
51 #include "detect-engine-frame.h"
52 
53 #include "detect-engine-file.h"
54 
55 #include "detect-engine.h"
56 #include "detect-engine-state.h"
57 #include "detect-engine-payload.h"
58 #include "detect-fast-pattern.h"
59 #include "detect-byte-extract.h"
60 #include "detect-content.h"
61 #include "detect-uricontent.h"
62 #include "detect-tcphdr.h"
65 
66 #include "detect-engine-loader.h"
67 
68 #include "detect-engine-alert.h"
69 
71 #include "util-reference-config.h"
72 #include "util-threshold-config.h"
73 #include "util-error.h"
74 #include "util-hash.h"
75 #include "util-byte.h"
76 #include "util-debug.h"
77 #include "util-unittest.h"
78 #include "util-action.h"
79 #include "util-magic.h"
80 #include "util-signal.h"
81 #include "util-spm.h"
82 #include "util-device-private.h"
83 #include "util-var-name.h"
84 #include "util-path.h"
85 #include "util-profiling.h"
86 #include "util-validate.h"
87 #include "util-hash-string.h"
88 #include "util-enum.h"
89 #include "util-conf.h"
90 
91 #include "tm-threads.h"
92 #include "runmodes.h"
93 
94 #include "reputation.h"
95 
96 #define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT 3000
97 
98 #define DEFAULT_MAX_FLOWBITS_PER_SIGNATURE 8
99 
100 static int DetectEngineCtxLoadConf(DetectEngineCtx *);
101 
102 static DetectEngineMasterCtx g_master_de_ctx = { SCMUTEX_INITIALIZER,
103  0, 99, NULL, NULL, TENANT_SELECTOR_UNKNOWN, NULL, NULL, 0};
104 
105 static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len);
106 static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len);
107 static void TenantIdFree(void *d);
108 static uint32_t DetectEngineTenantGetIdFromLivedev(const void *ctx, const Packet *p);
109 static uint32_t DetectEngineTenantGetIdFromVlanId(const void *ctx, const Packet *p);
110 static uint32_t DetectEngineTenantGetIdFromPcap(const void *ctx, const Packet *p);
111 
112 static bool DetectEngineMultiTenantEnabledWithLock(void);
113 static DetectEngineAppInspectionEngine *g_app_inspect_engines = NULL;
114 static DetectEnginePktInspectionEngine *g_pkt_inspect_engines = NULL;
115 static DetectEngineFrameInspectionEngine *g_frame_inspect_engines = NULL;
116 
117 // clang-format off
118 // rule types documentation tag start: SignatureProperties
120  /* SIG_TYPE_NOT_SET */ { SIG_PROP_FLOW_ACTION_PACKET, },
121  /* SIG_TYPE_IPONLY */ { SIG_PROP_FLOW_ACTION_FLOW, },
122  /* SIG_TYPE_LIKE_IPONLY */ { SIG_PROP_FLOW_ACTION_FLOW, },
123  /* SIG_TYPE_PDONLY */ { SIG_PROP_FLOW_ACTION_FLOW, },
124  /* SIG_TYPE_DEONLY */ { SIG_PROP_FLOW_ACTION_PACKET, },
125  /* SIG_TYPE_PKT */ { SIG_PROP_FLOW_ACTION_PACKET, },
126  /* SIG_TYPE_PKT_STREAM */ { SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL, },
127  /* SIG_TYPE_STREAM */ { SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL, },
128  /* SIG_TYPE_APPLAYER */ { SIG_PROP_FLOW_ACTION_FLOW, },
129  /* SIG_TYPE_APP_TX */ { SIG_PROP_FLOW_ACTION_FLOW, },
130 };
131 // rule types documentation tag end: SignatureProperties
132 // clang-format on
133 
134 const char *DetectTableToString(enum DetectTable table)
135 {
136  switch (table) {
138  return "not_set";
140  return "pre_flow";
142  return "pre_stream";
144  return "packet_filter";
146  return "packet_td";
148  return "app_filter";
149  case DETECT_TABLE_APP_TD:
150  return "app_td";
151  default:
152  return "unknown";
153  }
154 }
155 
156 /** \brief register inspect engine at start up time
157  *
158  * \note errors are fatal */
162 {
164  const int sm_list = DetectBufferTypeGetByName(name);
165  if (sm_list == -1) {
166  FatalError("failed to register inspect engine %s", name);
167  }
168 
169  if ((sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) ||
170  (Callback == NULL))
171  {
172  SCLogError("Invalid arguments");
173  BUG_ON(1);
174  }
175 
176  DetectEnginePktInspectionEngine *new_engine = SCCalloc(1, sizeof(*new_engine));
177  if (unlikely(new_engine == NULL)) {
178  FatalError("failed to register inspect engine %s: %s", name, strerror(errno));
179  }
180  new_engine->sm_list = (uint16_t)sm_list;
181  new_engine->sm_list_base = (uint16_t)sm_list;
182  new_engine->v1.Callback = Callback;
183  new_engine->v1.GetData = GetPktData;
184 
185  if (g_pkt_inspect_engines == NULL) {
186  g_pkt_inspect_engines = new_engine;
187  } else {
188  DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
189  while (t->next != NULL) {
190  t = t->next;
191  }
192 
193  t->next = new_engine;
194  }
195 }
196 
197 /** \brief register inspect engine at start up time
198  *
199  * \note errors are fatal */
200 static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alproto, uint32_t dir,
201  uint8_t sub_state, uint8_t progress, InspectEngineFuncPtr Callback,
203  InspectionMultiBufferGetDataPtr GetMultiData)
204 {
205  /* ignore special case unknown */
206  if (alproto != ALPROTO_UNKNOWN && AppLayerParserIsEnabled(alproto)) {
207  DEBUG_VALIDATE_BUG_ON(AppLayerParserSupportsSubStates(alproto) && sub_state == 0);
208  DEBUG_VALIDATE_BUG_ON(!AppLayerParserSupportsSubStates(alproto) && sub_state != 0);
209  }
210  BUG_ON(progress >= APP_LAYER_MAX_PROGRESS);
211 
213  const int sm_list = DetectBufferTypeGetByName(name);
214  if (sm_list == -1) {
215  FatalError("failed to register inspect engine %s", name);
216  }
217  SCLogDebug("name %s id %d", name, sm_list);
218 
219  if ((alproto == ALPROTO_FAILED) || (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) ||
220  (sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) || (progress >= 48) ||
221  (Callback == NULL)) {
222  SCLogError("Invalid arguments");
223  BUG_ON(1);
224  } else if (Callback == DetectEngineInspectBufferGeneric && GetData == NULL) {
225  SCLogError("Invalid arguments: must register "
226  "GetData with DetectEngineInspectBufferGeneric");
227  BUG_ON(1);
228  } else if (Callback == DetectEngineInspectBufferSingle && GetDataSingle == NULL) {
229  SCLogError("Invalid arguments: must register "
230  "GetData with DetectEngineInspectBufferGeneric");
231  BUG_ON(1);
232  } else if (Callback == DetectEngineInspectMultiBufferGeneric && GetMultiData == NULL) {
233  SCLogError("Invalid arguments: must register "
234  "GetData with DetectEngineInspectMultiBufferGeneric");
235  BUG_ON(1);
236  }
237 
238  uint8_t direction;
239  if (dir == SIG_FLAG_TOSERVER) {
240  direction = 0;
241  } else {
242  direction = 1;
243  }
244  DetectEngineAppInspectionEngine *new_engine =
246  if (unlikely(new_engine == NULL)) {
247  exit(EXIT_FAILURE);
248  }
249  new_engine->alproto = alproto;
250  new_engine->dir = direction;
251  new_engine->sm_list = (uint16_t)sm_list;
252  new_engine->sm_list_base = (uint16_t)sm_list;
253  new_engine->progress = progress;
254  new_engine->sub_state = sub_state;
255  new_engine->v2.Callback = Callback;
256  if (Callback == DetectEngineInspectBufferGeneric) {
257  new_engine->v2.GetData = GetData;
258  } else if (Callback == DetectEngineInspectBufferSingle) {
259  new_engine->v2.GetDataSingle = GetDataSingle;
260  } else if (Callback == DetectEngineInspectMultiBufferGeneric) {
261  new_engine->v2.GetMultiData = GetMultiData;
262  }
263 
264  if (g_app_inspect_engines == NULL) {
265  g_app_inspect_engines = new_engine;
266  } else {
267  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
268  while (t->next != NULL) {
269  t = t->next;
270  }
271 
272  t->next = new_engine;
273  }
274 }
275 
276 void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir,
277  uint8_t progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
278 {
279  /* before adding, check that we don't add a duplicate entry, which will
280  * propagate all the way into the packet runtime if allowed. */
281  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
282  while (t != NULL) {
283  const uint32_t t_direction = t->dir == 0 ? SIG_FLAG_TOSERVER : SIG_FLAG_TOCLIENT;
284  const int sm_list = DetectBufferTypeGetByName(name);
285 
286  if (t->sm_list == sm_list && t->alproto == alproto && t_direction == dir &&
287  t->sub_state == 0 && t->progress == progress && t->v2.Callback == Callback &&
288  t->v2.GetData == GetData) {
290  return;
291  }
292  t = t->next;
293  }
294 
295  AppLayerInspectEngineRegisterInternal(
296  name, alproto, dir, 0, (uint8_t)progress, Callback, GetData, NULL, NULL);
297 }
298 
299 void DetectAppLayerInspectEngineRegisterSubState(const char *name, AppProto alproto, uint32_t dir,
300  uint8_t sub_state, uint8_t progress, InspectEngineFuncPtr Callback,
302 {
303  /* before adding, check that we don't add a duplicate entry, which will
304  * propagate all the way into the packet runtime if allowed. */
305  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
306  while (t != NULL) {
307  const uint32_t t_direction = t->dir == 0 ? SIG_FLAG_TOSERVER : SIG_FLAG_TOCLIENT;
308  const int sm_list = DetectBufferTypeGetByName(name);
309 
310  if (t->sm_list == sm_list && t->alproto == alproto && t_direction == dir &&
311  t->sub_state == sub_state && t->progress == progress &&
312  t->v2.Callback == Callback && t->v2.GetData == GetData) {
314  return;
315  }
316  t = t->next;
317  }
318 
319  AppLayerInspectEngineRegisterInternal(
320  name, alproto, dir, sub_state, progress, Callback, GetData, NULL, NULL);
321 }
322 void DetectAppLayerInspectEngineRegisterSingle(const char *name, AppProto alproto, uint32_t dir,
323  uint8_t progress, InspectEngineFuncPtr Callback, InspectionSingleBufferGetDataPtr GetData)
324 {
325  /* before adding, check that we don't add a duplicate entry, which will
326  * propagate all the way into the packet runtime if allowed. */
327  DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
328  while (t != NULL) {
329  const uint32_t t_direction = t->dir == 0 ? SIG_FLAG_TOSERVER : SIG_FLAG_TOCLIENT;
330  const int sm_list = DetectBufferTypeGetByName(name);
331 
332  if (t->sm_list == sm_list && t->alproto == alproto && t_direction == dir &&
333  t->progress == progress && t->v2.Callback == Callback &&
334  t->v2.GetDataSingle == GetData) {
336  return;
337  }
338  t = t->next;
339  }
340 
341  AppLayerInspectEngineRegisterInternal(
342  name, alproto, dir, 0, (uint8_t)progress, Callback, NULL, GetData, NULL);
343 }
344 
345 /* copy an inspect engine with transforms to a new list id. */
346 static void DetectAppLayerInspectEngineCopy(
348  int sm_list, int new_list,
349  const DetectEngineTransforms *transforms)
350 {
351  const DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
352  while (t) {
353  if (t->sm_list == sm_list) {
355  if (unlikely(new_engine == NULL)) {
356  exit(EXIT_FAILURE);
357  }
358  new_engine->alproto = t->alproto;
359  new_engine->dir = t->dir;
360  DEBUG_VALIDATE_BUG_ON(new_list < 0 || new_list > UINT16_MAX);
361  new_engine->sm_list = (uint16_t)new_list; /* use new list id */
362  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
363  new_engine->sm_list_base = (uint16_t)sm_list;
364  new_engine->progress = t->progress;
365  new_engine->sub_state = t->sub_state;
366  new_engine->v2 = t->v2;
367  new_engine->v2.transforms = transforms; /* assign transforms */
368 
369  if (de_ctx->app_inspect_engines == NULL) {
370  de_ctx->app_inspect_engines = new_engine;
371  } else {
373  while (list->next != NULL) {
374  list = list->next;
375  }
376 
377  list->next = new_engine;
378  }
379  }
380  t = t->next;
381  }
382 }
383 
384 /* copy inspect engines from global registrations to de_ctx list */
385 static void DetectAppLayerInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
386 {
387  const DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
389  while (t) {
391  if (unlikely(new_engine == NULL)) {
392  exit(EXIT_FAILURE);
393  }
394  new_engine->alproto = t->alproto;
395  new_engine->dir = t->dir;
396  new_engine->sm_list = t->sm_list;
397  new_engine->sm_list_base = t->sm_list;
398  new_engine->progress = t->progress;
399  new_engine->sub_state = t->sub_state;
400  new_engine->v2 = t->v2;
401 
402  if (list == NULL) {
403  de_ctx->app_inspect_engines = new_engine;
404  } else {
405  list->next = new_engine;
406  }
407  list = new_engine;
408 
409  t = t->next;
410  }
411 }
412 
413 /* copy an inspect engine with transforms to a new list id. */
414 static void DetectPktInspectEngineCopy(
416  int sm_list, int new_list,
417  const DetectEngineTransforms *transforms)
418 {
419  const DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
420  while (t) {
421  if (t->sm_list == sm_list) {
423  if (unlikely(new_engine == NULL)) {
424  exit(EXIT_FAILURE);
425  }
426  DEBUG_VALIDATE_BUG_ON(new_list < 0 || new_list > UINT16_MAX);
427  new_engine->sm_list = (uint16_t)new_list; /* use new list id */
428  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
429  new_engine->sm_list_base = (uint16_t)sm_list;
430  new_engine->v1 = t->v1;
431  new_engine->v1.transforms = transforms; /* assign transforms */
432 
433  if (de_ctx->pkt_inspect_engines == NULL) {
434  de_ctx->pkt_inspect_engines = new_engine;
435  } else {
437  while (list->next != NULL) {
438  list = list->next;
439  }
440 
441  list->next = new_engine;
442  }
443  }
444  t = t->next;
445  }
446 }
447 
448 /* copy inspect engines from global registrations to de_ctx list */
449 static void DetectPktInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
450 {
451  const DetectEnginePktInspectionEngine *t = g_pkt_inspect_engines;
452  while (t) {
453  SCLogDebug("engine %p", t);
455  if (unlikely(new_engine == NULL)) {
456  exit(EXIT_FAILURE);
457  }
458  new_engine->sm_list = t->sm_list;
459  new_engine->sm_list_base = t->sm_list;
460  new_engine->v1 = t->v1;
461 
462  if (de_ctx->pkt_inspect_engines == NULL) {
463  de_ctx->pkt_inspect_engines = new_engine;
464  } else {
466  while (list->next != NULL) {
467  list = list->next;
468  }
469 
470  list->next = new_engine;
471  }
472 
473  t = t->next;
474  }
475 }
476 
477 /** \brief register inspect engine at start up time
478  *
479  * \note errors are fatal */
481  InspectionBufferFrameInspectFunc Callback, AppProto alproto, uint8_t type)
482 {
483  const int sm_list = DetectEngineBufferTypeRegister(de_ctx, name);
484  if (sm_list < 0) {
485  FatalError("failed to register inspect engine %s", name);
486  }
487 
488  if ((sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) || (Callback == NULL)) {
489  SCLogError("Invalid arguments");
490  BUG_ON(1);
491  }
492 
493  uint8_t direction;
494  if (dir == SIG_FLAG_TOSERVER) {
495  direction = 0;
496  } else {
497  direction = 1;
498  }
499 
500  DetectEngineFrameInspectionEngine *new_engine = SCCalloc(1, sizeof(*new_engine));
501  if (unlikely(new_engine == NULL)) {
502  FatalError("failed to register inspect engine %s: %s", name, strerror(errno));
503  }
504  new_engine->sm_list = (uint16_t)sm_list;
505  new_engine->sm_list_base = (uint16_t)sm_list;
506  new_engine->dir = direction;
507  new_engine->v1.Callback = Callback;
508  new_engine->alproto = alproto;
509  new_engine->type = type;
510 
511  if (de_ctx->frame_inspect_engines == NULL) {
512  de_ctx->frame_inspect_engines = new_engine;
513  } else {
515  while (list->next != NULL) {
516  list = list->next;
517  }
518 
519  list->next = new_engine;
520  }
521 }
522 
523 /* copy an inspect engine with transforms to a new list id. */
524 static void DetectFrameInspectEngineCopy(DetectEngineCtx *de_ctx, int sm_list, int new_list,
525  const DetectEngineTransforms *transforms)
526 {
527  /* take the list from the detect engine as the buffers can be registered
528  * dynamically. */
530  while (t) {
531  if (t->sm_list == sm_list) {
534  if (unlikely(new_engine == NULL)) {
535  exit(EXIT_FAILURE);
536  }
537  DEBUG_VALIDATE_BUG_ON(new_list < 0 || new_list > UINT16_MAX);
538  new_engine->sm_list = (uint16_t)new_list; /* use new list id */
539  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > UINT16_MAX);
540  new_engine->sm_list_base = (uint16_t)sm_list;
541  new_engine->dir = t->dir;
542  new_engine->alproto = t->alproto;
543  new_engine->type = t->type;
544  new_engine->v1 = t->v1;
545  new_engine->v1.transforms = transforms; /* assign transforms */
546 
547  /* append to the list */
549  while (list->next != NULL) {
550  list = list->next;
551  }
552 
553  list->next = new_engine;
554  }
555  t = t->next;
556  }
557 }
558 
559 /* copy inspect engines from global registrations to de_ctx list */
560 static void DetectFrameInspectEngineCopyListToDetectCtx(DetectEngineCtx *de_ctx)
561 {
562  const DetectEngineFrameInspectionEngine *t = g_frame_inspect_engines;
563  while (t) {
564  SCLogDebug("engine %p", t);
567  if (unlikely(new_engine == NULL)) {
568  exit(EXIT_FAILURE);
569  }
570  new_engine->sm_list = t->sm_list;
571  new_engine->sm_list_base = t->sm_list;
572  new_engine->dir = t->dir;
573  new_engine->alproto = t->alproto;
574  new_engine->type = t->type;
575  new_engine->v1 = t->v1;
576 
577  if (de_ctx->frame_inspect_engines == NULL) {
578  de_ctx->frame_inspect_engines = new_engine;
579  } else {
581  while (list->next != NULL) {
582  list = list->next;
583  }
584 
585  list->next = new_engine;
586  }
587 
588  t = t->next;
589  }
590 }
591 
592 /** \internal
593  * \brief append the stream inspection
594  *
595  * If stream inspection is MPM, then prepend it.
596  */
597 static void AppendStreamInspectEngine(
598  Signature *s, SigMatchData *stream, uint8_t direction, uint8_t id)
599 {
600  bool prepend = false;
601 
603  if (unlikely(new_engine == NULL)) {
604  exit(EXIT_FAILURE);
605  }
607  SCLogDebug("stream is mpm");
608  prepend = true;
609  new_engine->mpm = true;
610  }
611  new_engine->alproto = ALPROTO_UNKNOWN; /* all */
612  new_engine->dir = direction;
613  new_engine->stream = true;
614  new_engine->sm_list = DETECT_SM_LIST_PMATCH;
615  new_engine->sm_list_base = DETECT_SM_LIST_PMATCH;
616  new_engine->smd = stream;
617  new_engine->v2.Callback = DetectEngineInspectStream;
618  new_engine->progress = 0;
619 
620  /* append */
621  if (s->app_inspect == NULL) {
622  s->app_inspect = new_engine;
623  new_engine->id = DE_STATE_FLAG_BASE; /* id is used as flag in stateful detect */
624  } else if (prepend) {
625  new_engine->next = s->app_inspect;
626  s->app_inspect = new_engine;
627  new_engine->id = id;
628 
629  } else {
631  while (a->next != NULL) {
632  a = a->next;
633  }
634 
635  a->next = new_engine;
636  new_engine->id = id;
637  }
638  SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
639 }
640 
641 static void AppendFrameInspectEngine(DetectEngineCtx *de_ctx,
643  const int mpm_list)
644 {
645  bool prepend = false;
646 
647  if (u->alproto == ALPROTO_UNKNOWN) {
648  /* special case, inspect engine applies to all protocols */
649  } else if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, u->alproto))
650  return;
651 
652  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
653  if (u->dir == 1)
654  return;
655  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
656  if (u->dir == 0)
657  return;
658  }
659 
662  if (unlikely(new_engine == NULL)) {
663  exit(EXIT_FAILURE);
664  }
665  if (mpm_list == u->sm_list) {
667  prepend = true;
668  new_engine->mpm = true;
669  }
670 
671  new_engine->type = u->type;
672  new_engine->sm_list = u->sm_list;
673  new_engine->sm_list_base = u->sm_list_base;
674  new_engine->smd = smd;
675  new_engine->v1 = u->v1;
676  SCLogDebug("sm_list %d new_engine->v1 %p/%p", new_engine->sm_list, new_engine->v1.Callback,
677  new_engine->v1.transforms);
678 
679  if (s->frame_inspect == NULL) {
680  s->frame_inspect = new_engine;
681  } else if (prepend) {
682  new_engine->next = s->frame_inspect;
683  s->frame_inspect = new_engine;
684  } else {
686  while (a->next != NULL) {
687  a = a->next;
688  }
689  new_engine->next = a->next;
690  a->next = new_engine;
691  }
692 }
693 
694 static void AppendPacketInspectEngine(DetectEngineCtx *de_ctx,
696  const int mpm_list)
697 {
698  bool prepend = false;
699 
700  DetectEnginePktInspectionEngine *new_engine =
702  if (unlikely(new_engine == NULL)) {
703  exit(EXIT_FAILURE);
704  }
705  if (mpm_list == e->sm_list) {
707  prepend = true;
708  new_engine->mpm = true;
709  }
710 
711  new_engine->sm_list = e->sm_list;
712  new_engine->sm_list_base = e->sm_list_base;
713  new_engine->smd = smd;
714  new_engine->v1 = e->v1;
715  SCLogDebug("sm_list %d new_engine->v1 %p/%p/%p", new_engine->sm_list, new_engine->v1.Callback,
716  new_engine->v1.GetData, new_engine->v1.transforms);
717 
718  if (s->pkt_inspect == NULL) {
719  s->pkt_inspect = new_engine;
720  } else if (prepend) {
721  new_engine->next = s->pkt_inspect;
722  s->pkt_inspect = new_engine;
723  } else {
725  while (a->next != NULL) {
726  a = a->next;
727  }
728  new_engine->next = a->next;
729  a->next = new_engine;
730  }
731 }
732 
733 static void AppendAppInspectEngine(DetectEngineCtx *de_ctx,
735  const int mpm_list, const int files_id, uint8_t *last_id, bool *head_is_mpm)
736 {
737  if (t->alproto == ALPROTO_UNKNOWN) {
738  /* special case, inspect engine applies to all protocols */
739  } else if (s->alproto != ALPROTO_UNKNOWN) {
741  /* SIGNATURE_HOOK_TYPE_APP rules are exact about their protocol */
742  if (!(AppProtoEqualsStrict(s->alproto, t->alproto))) {
743  return;
744  }
745 
746  /* skip engines not for us */
747  if (s->init_data->hook.t.app.sub_state != t->sub_state) {
748  return;
749  }
750  } else {
751  /* other rules use the more relax AppProtoEquals logic */
752  if (!AppProtoEquals(s->alproto, t->alproto)) {
753  return;
754  }
755  }
756  }
757 
758  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
759  if (t->dir == 1)
760  return;
761  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
762  if (t->dir == 0)
763  return;
764  }
765  SCLogDebug("app engine: t %p t->id %u => alproto:%s files:%s", t, t->id,
766  AppProtoToString(t->alproto), BOOL2STR(t->sm_list == files_id));
767 
768  DetectEngineAppInspectionEngine *new_engine =
770  if (unlikely(new_engine == NULL)) {
771  exit(EXIT_FAILURE);
772  }
773  bool prepend = false;
774  if (mpm_list == t->sm_list) {
776  prepend = true;
777  *head_is_mpm = true;
778  new_engine->mpm = true;
779  }
780 
781  new_engine->alproto = t->alproto;
782  new_engine->dir = t->dir;
783  new_engine->sm_list = t->sm_list;
784  new_engine->sm_list_base = t->sm_list_base;
785  new_engine->smd = smd;
786  new_engine->match_on_null = smd ? DetectContentInspectionMatchOnAbsentBuffer(smd) : false;
787  new_engine->progress = t->progress;
788  new_engine->sub_state = t->sub_state;
789  new_engine->v2 = t->v2;
790  SCLogDebug("sm_list %d new_engine->v2 %p/%p/%p", new_engine->sm_list, new_engine->v2.Callback,
791  new_engine->v2.GetData, new_engine->v2.transforms);
792 
793  if (s->app_inspect == NULL) {
794  s->app_inspect = new_engine;
795  if (new_engine->sm_list == files_id) {
796  new_engine->id = DE_STATE_ID_FILE_INSPECT;
797  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
798  } else {
799  new_engine->id = DE_STATE_FLAG_BASE; /* id is used as flag in stateful detect */
800  SCLogDebug("sid %u: engine %p/%u %s", s->id, new_engine, new_engine->id,
802  }
803 
804  /* prepend engine if forced or if our engine has a lower progress. */
805  } else if (prepend || (!(*head_is_mpm) && s->app_inspect->progress > new_engine->progress)) {
806  new_engine->next = s->app_inspect;
807  s->app_inspect = new_engine;
808  if (new_engine->sm_list == files_id) {
809  new_engine->id = DE_STATE_ID_FILE_INSPECT;
810  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
811  } else {
812  new_engine->id = ++(*last_id);
813  SCLogDebug("sid %u: engine %p/%u %s", s->id, new_engine, new_engine->id,
815  }
816 
817  } else {
819  while (a->next != NULL) {
820  if (a->next && a->next->progress > new_engine->progress) {
821  break;
822  }
823  a = a->next;
824  }
825 
826  new_engine->next = a->next;
827  a->next = new_engine;
828  if (new_engine->sm_list == files_id) {
829  new_engine->id = DE_STATE_ID_FILE_INSPECT;
830  SCLogDebug("sid %u: engine %p/%u is FILE ENGINE", s->id, new_engine, new_engine->id);
831  } else {
832  new_engine->id = ++(*last_id);
833  SCLogDebug("sid %u: engine %p/%u %s", s->id, new_engine, new_engine->id,
835  }
836  }
837 
838  SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
839 
841 }
842 
843 /**
844  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT
845  */
847  const AppProto p, const uint8_t sub_state, const uint8_t state, const uint8_t direction)
848 {
849  if (!((direction & (STREAM_TOSERVER | STREAM_TOCLIENT)) == STREAM_TOSERVER) &&
850  !((direction & (STREAM_TOSERVER | STREAM_TOCLIENT)) == STREAM_TOCLIENT))
851  return NULL;
852 
853  if (sub_state == 0) {
854  const char *pname = AppLayerParserGetStateNameById(IPPROTO_TCP, // TODO
855  p, state, direction);
856  if (pname == NULL) {
857  if (state == 0) {
858  if (direction == STREAM_TOSERVER) {
859  pname = "request_started";
860  } else {
861  pname = "response_started";
862  }
863  } else {
864  const int complete = AppLayerParserGetStateProgressCompletionStatus(p, direction);
865  if (state == complete) {
866  if (direction == STREAM_TOSERVER) {
867  pname = "request_complete";
868  } else {
869  pname = "response_complete";
870  }
871  }
872  }
873  }
874  return pname;
875  } else {
877  const char *name = AppLayerParserGetSubStateProgressName(p, sub_state, state, direction);
878  return name;
879  }
880 }
881 
882 /** \brief get the sm_list for a app hook
883  * \param sub_state sub_state to use or 0 if not in use
884  * */
886  const AppProto p, const uint8_t sub_state, const uint8_t state, const uint8_t direction)
887 {
888  const char *app_proto = AppProtoToStringRaw(p);
889  if (app_proto == NULL) {
890  SCLogError("unknown app_proto %u", p);
891  return -1;
892  }
893 
894  char generic_hook_name[256];
895  if (sub_state == 0) {
896  const char *name = DetectEngineAppHookToName(
897  p, 0, state, direction & (STREAM_TOSERVER | STREAM_TOCLIENT));
898  if (name == NULL) {
899  return -1;
900  }
901 
902  snprintf(generic_hook_name, sizeof(generic_hook_name), "%s:%s:generic", app_proto, name);
903 
904  int list = DetectBufferTypeGetByName(generic_hook_name);
905  if (list < 0) {
906  SCLogError(
907  "no list registered as %s for %s hook %s", generic_hook_name, app_proto, name);
908  return -1;
909  }
910  return list;
911  } else {
913 
914  const char *sname = AppLayerParserGetSubStateName(p, sub_state);
915  if (sname == NULL)
916  return -1;
917 
918  const char *name = AppLayerParserGetSubStateProgressName(p, sub_state, state, direction);
919  if (name == NULL)
920  return -1;
921 
922  snprintf(generic_hook_name, sizeof(generic_hook_name), "%s:%s:%s:generic", app_proto, sname,
923  name);
924 
925  int list = DetectBufferTypeGetByName(generic_hook_name);
926  if (list < 0) {
927  SCLogError("no list registered as %s for %s sub_state %s hook %s", generic_hook_name,
928  app_proto, sname, name);
929  return -1;
930  }
931  return list;
932  }
933 }
934 
935 /**
936  * \note for the file inspect engine, the id DE_STATE_ID_FILE_INSPECT
937  * is assigned.
938  */
940 {
941  const int mpm_list = s->init_data->mpm_sm ? s->init_data->mpm_sm_list : -1;
942  const int files_id = DetectBufferTypeGetByName("files");
943  bool head_is_mpm = false;
944  uint8_t last_id = DE_STATE_FLAG_BASE;
945  SCLogDebug("%u: setup app inspect engines. %u buffers", s->id, s->init_data->buffer_index);
946 
947  if (s->flags & SIG_FLAG_FW_HOOK_LTE) {
948  SCLogDebug("need an inspect engine per state, range 0-%u", s->app_progress_hook);
949  for (uint8_t state = 0; state < s->app_progress_hook; state++) {
950  uint8_t dir = 0;
951  uint8_t direction = 0;
955  if (s->flags & SIG_FLAG_TOSERVER) {
956  direction = STREAM_TOSERVER;
957  dir = 0;
958  } else if (s->flags & SIG_FLAG_TOCLIENT) {
959  direction = STREAM_TOCLIENT;
960  dir = 1;
961  }
962 
963  int sm_list = DetectEngineAppHookToSmlist(s->init_data->hook.t.app.alproto,
964  s->init_data->hook.t.app.sub_state, 0, direction);
965  if (sm_list < 0)
966  return -1;
967 
969  .alproto = s->init_data->hook.t.app.alproto,
970  .progress = state,
971  .sub_state = s->init_data->hook.t.app.sub_state,
972  .sm_list = (uint16_t)sm_list,
973  .sm_list_base = (uint16_t)sm_list,
974  .dir = dir,
975  };
976  AppendAppInspectEngine(de_ctx, &t, s, NULL, mpm_list, files_id, &last_id, &head_is_mpm);
977  SCLogDebug("sid %u: appended pass-tru engine at hook:%u sm_list:%d for "
978  "SIG_FLAG_INIT_HOOK_LTE",
979  s->id, state, sm_list);
980  }
981  }
982 
983  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
985  SCLogDebug("smd %p, id %u", smd, s->init_data->buffers[x].id);
986 
987  const DetectBufferType *b =
989  if (b == NULL)
990  FatalError("unknown buffer");
991 
992  if (b->frame) {
994  u != NULL; u = u->next) {
995  if (u->sm_list == s->init_data->buffers[x].id) {
996  AppendFrameInspectEngine(de_ctx, u, s, smd, mpm_list);
997  }
998  }
999  } else if (b->packet) {
1000  /* set up pkt inspect engines */
1001  for (const DetectEnginePktInspectionEngine *e = de_ctx->pkt_inspect_engines; e != NULL;
1002  e = e->next) {
1003  SCLogDebug("e %p sm_list %u", e, e->sm_list);
1004  if (e->sm_list == s->init_data->buffers[x].id) {
1005  AppendPacketInspectEngine(de_ctx, e, s, smd, mpm_list);
1006  }
1007  }
1008  } else {
1009  SCLogDebug("app %s id %u parent %u rule %u xforms %u", b->name, b->id, b->parent_id,
1010  s->init_data->buffers[x].id, b->transforms.cnt);
1011  for (const DetectEngineAppInspectionEngine *t = de_ctx->app_inspect_engines; t != NULL;
1012  t = t->next) {
1013  if (t->sm_list == s->init_data->buffers[x].id) {
1014  if (s->flags & SIG_FLAG_TXBOTHDIR) {
1015  // ambiguous keywords have app engines in both directions
1016  // so we skip the wrong direction for this buffer
1017  if (s->init_data->buffers[x].only_tc && t->dir == 0) {
1018  continue;
1019  } else if (s->init_data->buffers[x].only_ts && t->dir == 1) {
1020  continue;
1021  }
1022  }
1023  AppendAppInspectEngine(
1024  de_ctx, t, s, smd, mpm_list, files_id, &last_id, &head_is_mpm);
1025  }
1026  }
1027  }
1028  }
1029 
1030  /* handle rules that have an app-layer hook w/o bringing their own app inspect engine,
1031  * e.g. `alert dns:request_complete ... (sid:1;)`
1032  *
1033  * Here we use a minimal stub inspect engine in which we set:
1034  * - alproto
1035  * - progress
1036  * - sm_list/sm_list_base to get the mapping to the hook name
1037  * - dir based on sig direction
1038  *
1039  * The inspect engine has no callback and is thus considered a straight match.
1040  */
1042  uint8_t dir = 0;
1046  if (s->flags & SIG_FLAG_TOSERVER)
1047  dir = 0;
1048  else if (s->flags & SIG_FLAG_TOCLIENT)
1049  dir = 1;
1050 
1052  .alproto = s->init_data->hook.t.app.alproto,
1053  .progress = s->init_data->hook.t.app.app_progress,
1054  .sub_state = s->init_data->hook.t.app.sub_state,
1055  .sm_list = (uint16_t)s->init_data->hook.sm_list,
1056  .sm_list_base = (uint16_t)s->init_data->hook.sm_list,
1057  .dir = dir,
1058  };
1059  AppendAppInspectEngine(de_ctx, &t, s, NULL, mpm_list, files_id, &last_id, &head_is_mpm);
1060  }
1061 
1064  {
1065  /* if engine is added multiple times, we pass it the same list */
1067  BUG_ON(stream == NULL);
1068  if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
1069  AppendStreamInspectEngine(s, stream, 0, last_id + 1);
1070  } else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
1071  AppendStreamInspectEngine(s, stream, 1, last_id + 1);
1072  } else {
1073  AppendStreamInspectEngine(s, stream, 0, last_id + 1);
1074  AppendStreamInspectEngine(s, stream, 1, last_id + 1);
1075  }
1076 
1078  SCLogDebug("set SIG_FLAG_FLUSH on %u", s->id);
1079  s->flags |= SIG_FLAG_FLUSH;
1080  }
1081  }
1082 
1083 #ifdef DEBUG
1085  while (iter) {
1086  SCLogDebug("%u: engine %s id %u progress %d %s", s->id,
1088  iter->sm_list == mpm_list ? "MPM" : "");
1089  iter = iter->next;
1090  }
1091 #endif
1092  return 0;
1093 }
1094 
1095 /** \brief free app inspect engines for a signature
1096  *
1097  * For lists that are registered multiple times, like http_header and
1098  * http_cookie, making the engines owner of the lists is complicated.
1099  * Multiple engines in a sig may be pointing to the same list. To
1100  * address this the 'free' code needs to be extra careful about not
1101  * double freeing, so it takes an approach to first fill an array
1102  * of the to-free pointers before freeing them.
1103  */
1105 {
1106  int engines = 0;
1107 
1109  while (ie) {
1110  ie = ie->next;
1111  engines++;
1112  }
1114  while (e) {
1115  e = e->next;
1116  engines++;
1117  }
1119  while (u) {
1120  u = u->next;
1121  engines++;
1122  }
1123  if (engines == 0) {
1124  BUG_ON(s->pkt_inspect);
1125  BUG_ON(s->frame_inspect);
1126  return;
1127  }
1128 
1129  SigMatchData *bufs[engines];
1130  memset(&bufs, 0, (engines * sizeof(SigMatchData *)));
1131  int arrays = 0;
1132 
1133  /* free engines and put smd in the array */
1134  ie = s->app_inspect;
1135  while (ie) {
1137 
1138  bool skip = false;
1139  for (int i = 0; i < arrays; i++) {
1140  if (bufs[i] == ie->smd) {
1141  skip = true;
1142  break;
1143  }
1144  }
1145  if (!skip) {
1146  bufs[arrays++] = ie->smd;
1147  }
1148  SCFree(ie);
1149  ie = next;
1150  }
1151  e = s->pkt_inspect;
1152  while (e) {
1154 
1155  bool skip = false;
1156  for (int i = 0; i < arrays; i++) {
1157  if (bufs[i] == e->smd) {
1158  skip = true;
1159  break;
1160  }
1161  }
1162  if (!skip) {
1163  bufs[arrays++] = e->smd;
1164  }
1165  SCFree(e);
1166  e = next;
1167  }
1168  u = s->frame_inspect;
1169  while (u) {
1171 
1172  bool skip = false;
1173  for (int i = 0; i < arrays; i++) {
1174  if (bufs[i] == u->smd) {
1175  skip = true;
1176  break;
1177  }
1178  }
1179  if (!skip) {
1180  bufs[arrays++] = u->smd;
1181  }
1182  SCFree(u);
1183  u = next;
1184  }
1185 
1186  for (int i = 0; i < engines; i++) {
1187  if (bufs[i] == NULL)
1188  continue;
1189  SigMatchData *smd = bufs[i];
1190  while (1) {
1191  if (sigmatch_table[smd->type].Free != NULL) {
1192  sigmatch_table[smd->type].Free(de_ctx, smd->ctx);
1193  }
1194  if (smd->is_last)
1195  break;
1196  smd++;
1197  }
1198  SCFree(bufs[i]);
1199  }
1200 }
1201 
1202 /* code for registering buffers */
1203 
1204 #include "util-hash-lookup3.h"
1205 
1206 static HashListTable *g_buffer_type_hash = NULL;
1207 static int g_buffer_type_id = DETECT_SM_LIST_DYNAMIC_START;
1208 static int g_buffer_type_reg_closed = 0;
1209 
1211 {
1212  return g_buffer_type_id;
1213 }
1214 
1215 static void DetectBufferAddTransformData(DetectBufferType *map)
1216 {
1217  for (int i = 0; i < map->transforms.cnt; i++) {
1218  const TransformData *t = &map->transforms.transforms[i];
1221  &map->xform_id[i].id_data, &map->xform_id[i].id_data_len, t->options);
1222  SCLogDebug("transform identity data: [%p] \"%s\" [%d]", map->xform_id[i].id_data,
1223  (char *)map->xform_id[i].id_data, map->xform_id[i].id_data_len);
1224  }
1225  }
1226 }
1227 
1228 static uint32_t DetectBufferTypeHashNameFunc(HashListTable *ht, void *data, uint16_t datalen)
1229 {
1230  const DetectBufferType *map = (DetectBufferType *)data;
1231  uint32_t hash = hashlittle_safe(map->name, strlen(map->name), 0);
1232 
1233  // Add the transform data
1234  // - Collect transform id and position
1235  // - Collect identity data, if any
1236  hash += hashlittle_safe((uint8_t *)&map->transforms.cnt, sizeof(map->transforms.cnt), 0);
1237  for (int i = 0; i < map->transforms.cnt; i++) {
1238  const TransformData *t = &map->transforms.transforms[i];
1239  int tval = t->transform;
1240  hash += hashlittle_safe((uint8_t *)&tval, sizeof(tval), 0);
1241  if (map->xform_id[i].id_data) {
1242  hash += hashlittle_safe(
1243  &map->xform_id[i].id_data_len, sizeof(map->xform_id[i].id_data_len), 0);
1244  hash += hashlittle_safe(map->xform_id[i].id_data, map->xform_id[i].id_data_len, 0);
1245  }
1246  }
1247  hash %= ht->array_size;
1248  SCLogDebug("map->name %s, hash %d", map->name, hash);
1249  return hash;
1250 }
1251 
1252 static uint32_t DetectBufferTypeHashIdFunc(HashListTable *ht, void *data, uint16_t datalen)
1253 {
1254  const DetectBufferType *map = (DetectBufferType *)data;
1255  uint32_t hash = map->id;
1256  hash %= ht->array_size;
1257  return hash;
1258 }
1259 
1260 static char DetectBufferTypeCompareNameFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
1261 {
1262  DetectBufferType *map1 = (DetectBufferType *)data1;
1263  DetectBufferType *map2 = (DetectBufferType *)data2;
1264 
1265  char r = (strcmp(map1->name, map2->name) == 0);
1266 
1267  // Compare the transforms
1268  // the transform supports identity, that data will also be added.
1269  r &= map1->transforms.cnt == map2->transforms.cnt;
1270  if (r && map1->transforms.cnt) {
1271  for (int i = 0; i < map1->transforms.cnt; i++) {
1272  if (map1->transforms.transforms[i].transform !=
1273  map2->transforms.transforms[i].transform) {
1274  r = 0;
1275  break;
1276  }
1277 
1278  SCLogDebug("%s: transform ids match; checking specialized data", map1->name);
1279  // Checks
1280  // - Both NULL: --> ok, continue
1281  // - One NULL: --> no match, break?
1282  // - identity data lengths match: --> ok, continue
1283  // - identity data matches: ok
1284 
1285  // Stop if only one is NULL
1286  if ((map1->xform_id[i].id_data == NULL) ^ (map2->xform_id[i].id_data == NULL)) {
1287  SCLogDebug("identity data: only one is null");
1288  r = 0;
1289  break;
1290  } else if (map1->xform_id[i].id_data == NULL) { /* continue when both are null */
1291  SCLogDebug("identity data: both null");
1292  r = 1;
1293  continue;
1294  } else if (map1->xform_id[i].id_data_len != map2->xform_id[i].id_data_len) {
1295  // Stop when id data lengths aren't equal
1296  SCLogDebug("id data: unequal lengths");
1297  r = 0;
1298  break;
1299  }
1300 
1301  // stop if the identity data is different
1302  r &= memcmp(map1->xform_id[i].id_data, map2->xform_id[i].id_data,
1303  map1->xform_id[i].id_data_len) == 0;
1304  if (r == 0)
1305  break;
1306  SCLogDebug("identity data: data matches");
1307  }
1308  }
1309  return r;
1310 }
1311 
1312 static char DetectBufferTypeCompareIdFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
1313 {
1314  DetectBufferType *map1 = (DetectBufferType *)data1;
1315  DetectBufferType *map2 = (DetectBufferType *)data2;
1316  return map1->id == map2->id;
1317 }
1318 
1319 static void DetectBufferTypeFreeFunc(void *data)
1320 {
1321  DetectBufferType *map = (DetectBufferType *)data;
1322 
1323  if (map == NULL) {
1324  return;
1325  }
1326 
1327  /* Release transformation option memory, if any */
1328  for (int i = 0; i < map->transforms.cnt; i++) {
1329  if (map->transforms.transforms[i].options == NULL)
1330  continue;
1331 
1332  if (sigmatch_table[map->transforms.transforms[i].transform].Free == NULL) {
1333  SCLogError("%s allocates transform option memory but has no free routine",
1335  continue;
1336  }
1338  }
1339 
1340  SCFree(map);
1341 }
1342 
1343 static int DetectBufferTypeInit(void)
1344 {
1345  BUG_ON(g_buffer_type_hash);
1346  g_buffer_type_hash = HashListTableInit(256, DetectBufferTypeHashNameFunc,
1347  DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
1348  if (g_buffer_type_hash == NULL)
1349  return -1;
1350 
1351  return 0;
1352 }
1353 #if 0
1354 static void DetectBufferTypeFree(void)
1355 {
1356  if (g_buffer_type_hash == NULL)
1357  return;
1358 
1359  HashListTableFree(g_buffer_type_hash);
1360  g_buffer_type_hash = NULL;
1361 }
1362 #endif
1363 static int DetectBufferTypeAdd(const char *string)
1364 {
1365  BUG_ON(string == NULL || strlen(string) >= 64);
1366 
1367  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1368  if (map == NULL)
1369  return -1;
1370 
1371  strlcpy(map->name, string, sizeof(map->name));
1372  map->id = g_buffer_type_id++;
1373 
1374  BUG_ON(HashListTableAdd(g_buffer_type_hash, (void *)map, 0) != 0);
1375  SCLogDebug("buffer %s registered with id %d", map->name, map->id);
1376  return map->id;
1377 }
1378 
1379 static DetectBufferType *DetectBufferTypeLookupByName(const char *string)
1380 {
1381  DetectBufferType map;
1382  memset(&map, 0, sizeof(map));
1383  strlcpy(map.name, string, sizeof(map.name));
1384 
1385  DetectBufferType *res = HashListTableLookup(g_buffer_type_hash, &map, 0);
1386  return res;
1387 }
1388 
1390 {
1391  BUG_ON(g_buffer_type_reg_closed);
1392  if (g_buffer_type_hash == NULL)
1393  DetectBufferTypeInit();
1394 
1395  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1396  if (!exists) {
1397  return DetectBufferTypeAdd(name);
1398  } else {
1399  return exists->id;
1400  }
1401 }
1402 
1404 {
1405  BUG_ON(g_buffer_type_reg_closed);
1407  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1408  BUG_ON(!exists);
1409  exists->multi_instance = true;
1410  SCLogDebug("%p %s -- %d supports multi instance", exists, name, exists->id);
1411 }
1412 
1414 {
1415  BUG_ON(g_buffer_type_reg_closed);
1417  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1418  BUG_ON(!exists);
1419  exists->frame = true;
1420  SCLogDebug("%p %s -- %d supports frame inspection", exists, name, exists->id);
1421 }
1422 
1424 {
1425  BUG_ON(g_buffer_type_reg_closed);
1427  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1428  BUG_ON(!exists);
1429  exists->packet = true;
1430  SCLogDebug("%p %s -- %d supports packet inspection", exists, name, exists->id);
1431 }
1432 
1434 {
1435  BUG_ON(g_buffer_type_reg_closed);
1437  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1438  BUG_ON(!exists);
1439  exists->mpm = true;
1440  SCLogDebug("%p %s -- %d supports mpm", exists, name, exists->id);
1441 }
1442 
1444 {
1445  BUG_ON(g_buffer_type_reg_closed);
1447  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1448  BUG_ON(!exists);
1449  exists->supports_transforms = true;
1450  SCLogDebug("%p %s -- %d supports transformations", exists, name, exists->id);
1451 }
1452 
1454 {
1455  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1456  if (!exists) {
1457  return -1;
1458  }
1459  return exists->id;
1460 }
1461 
1462 static DetectBufferType *DetectEngineBufferTypeLookupByName(
1463  const DetectEngineCtx *de_ctx, const char *string)
1464 {
1465  DetectBufferType map;
1466  memset(&map, 0, sizeof(map));
1467  strlcpy(map.name, string, sizeof(map.name));
1468 
1470  return res;
1471 }
1472 
1474 {
1475  DetectBufferType lookup;
1476  memset(&lookup, 0, sizeof(lookup));
1477  lookup.id = id;
1478  const DetectBufferType *res =
1479  HashListTableLookup(de_ctx->buffer_type_hash_id, (void *)&lookup, 0);
1480  return res;
1481 }
1482 
1484 {
1486  return res ? res->name : NULL;
1487 }
1488 
1489 static int DetectEngineBufferTypeAdd(DetectEngineCtx *de_ctx, const char *string)
1490 {
1491  BUG_ON(string == NULL || strlen(string) >= 32);
1492 
1493  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1494  if (map == NULL)
1495  return -1;
1496 
1497  strlcpy(map->name, string, sizeof(map->name));
1498  map->id = de_ctx->buffer_type_id++;
1499 
1500  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_name, (void *)map, 0) != 0);
1501  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_id, (void *)map, 0) != 0);
1502  SCLogDebug("buffer %s registered with id %d", map->name, map->id);
1503  return map->id;
1504 }
1505 
1507  const int direction, const AppProto alproto, const uint8_t frame_type)
1508 {
1509  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1510  if (exists) {
1511  return exists->id;
1512  }
1513 
1514  const int buffer_id = DetectEngineBufferTypeAdd(de_ctx, name);
1515  if (buffer_id < 0) {
1516  return -1;
1517  }
1518 
1519  /* TODO hack we need the map to get the name. Should we return the map at reg? */
1520  const DetectBufferType *map = DetectEngineBufferTypeGetById(de_ctx, buffer_id);
1521  BUG_ON(!map);
1522 
1523  /* register MPM/inspect engines */
1524  if (direction & SIG_FLAG_TOSERVER) {
1526  PrefilterGenericMpmFrameRegister, alproto, frame_type);
1528  DetectEngineInspectFrameBufferGeneric, alproto, frame_type);
1529  }
1530  if (direction & SIG_FLAG_TOCLIENT) {
1532  PrefilterGenericMpmFrameRegister, alproto, frame_type);
1534  DetectEngineInspectFrameBufferGeneric, alproto, frame_type);
1535  }
1536 
1537  return buffer_id;
1538 }
1539 
1541 {
1542  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1543  if (!exists) {
1544  return DetectEngineBufferTypeAdd(de_ctx, name);
1545  } else {
1546  return exists->id;
1547  }
1548 }
1549 
1550 void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
1551 {
1552  BUG_ON(desc == NULL || strlen(desc) >= 128);
1553 
1554  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1555  if (!exists) {
1556  return;
1557  }
1558  strlcpy(exists->description, desc, sizeof(exists->description));
1559 }
1560 
1562 {
1563  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1564  if (!exists) {
1565  return;
1566  }
1567  exists->run_always = true;
1568 }
1569 
1571 {
1572  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, id);
1573  if (name == NULL) {
1574  return;
1575  }
1576  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1577  BUG_ON(!exists);
1578  exists->run_always = true;
1579 }
1580 
1582 {
1584  if (!exists) {
1585  return NULL;
1586  }
1587  return exists->description;
1588 }
1589 
1591 {
1592  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1593  BUG_ON(!exists);
1594  exists->frame = true;
1595  SCLogDebug("%p %s -- %d supports frame inspection", exists, name, exists->id);
1596 }
1597 
1599 {
1600  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1601  BUG_ON(!exists);
1602  exists->packet = true;
1603  SCLogDebug("%p %s -- %d supports packet inspection", exists, name, exists->id);
1604 }
1605 
1607 {
1608  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1609  BUG_ON(!exists);
1610  exists->mpm = true;
1611  SCLogDebug("%p %s -- %d supports mpm", exists, name, exists->id);
1612 }
1613 
1615 {
1616  DetectBufferType *exists = DetectEngineBufferTypeLookupByName(de_ctx, name);
1617  BUG_ON(!exists);
1618  exists->supports_transforms = true;
1619  SCLogDebug("%p %s -- %d supports transformations", exists, name, exists->id);
1620 }
1621 
1623 {
1625  if (map == NULL)
1626  return false;
1627  SCLogDebug("map %p id %d multi_instance? %s", map, id, BOOL2STR(map->multi_instance));
1628  return map->multi_instance;
1629 }
1630 
1632 {
1634  if (map == NULL)
1635  return false;
1636  SCLogDebug("map %p id %d packet? %d", map, id, map->packet);
1637  return map->packet;
1638 }
1639 
1641 {
1643  if (map == NULL)
1644  return false;
1645  SCLogDebug("map %p id %d mpm? %d", map, id, map->mpm);
1646  return map->mpm;
1647 }
1648 
1650 {
1652  if (map == NULL)
1653  return false;
1654  SCLogDebug("map %p id %d frame? %d", map, id, map->frame);
1655  return map->frame;
1656 }
1657 
1659  void (*SetupCallback)(const DetectEngineCtx *, Signature *, const DetectBufferType *))
1660 {
1661  BUG_ON(g_buffer_type_reg_closed);
1663  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1664  BUG_ON(!exists);
1665  exists->SetupCallback = SetupCallback;
1666 }
1667 
1669 {
1671  if (map && map->SetupCallback) {
1672  map->SetupCallback(de_ctx, s, map);
1673  }
1674 }
1675 
1677  const char *name, bool (*ValidateCallback)(const Signature *, const char **sigerror,
1678  const DetectBufferType *))
1679 {
1680  BUG_ON(g_buffer_type_reg_closed);
1682  DetectBufferType *exists = DetectBufferTypeLookupByName(name);
1683  BUG_ON(!exists);
1684  exists->ValidateCallback = ValidateCallback;
1685 }
1686 
1688  const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
1689 {
1691  // only run validation if the buffer is not transformed
1692  if (map && map->ValidateCallback && map->transforms.cnt == 0) {
1693  return map->ValidateCallback(s, sigerror, map);
1694  }
1695  return true;
1696 }
1697 
1698 bool DetectBufferIsPresent(const Signature *s, const uint32_t buf_id)
1699 {
1700  for (uint32_t i = 0; i < s->init_data->buffer_index; i++) {
1701  if (buf_id == s->init_data->buffers[i].id) {
1702  return true;
1703  }
1704  }
1705  return false;
1706 }
1707 
1708 /** \brief Check content byte array compatibility with transforms
1709  *
1710  * The "content" array is presented to the transforms so that each
1711  * transform may validate that it's compatible with the transform.
1712  *
1713  * When a transform indicates the byte array is incompatible, none of the
1714  * subsequent transforms, if any, are invoked. This means the first validation
1715  * failure terminates the loop.
1716  *
1717  * \param de_ctx Detection engine context.
1718  * \param sm_list The SM list id.
1719  * \param content The byte array being validated
1720  * \param namestr returns the name of the transform that is incompatible with
1721  * content.
1722  *
1723  * \retval true (false) If any of the transforms indicate the byte array is
1724  * (is not) compatible.
1725  **/
1727  const uint8_t *content, uint16_t content_len, const char **namestr)
1728 {
1729  const DetectBufferType *dbt = DetectEngineBufferTypeGetById(de_ctx, sm_list);
1730  BUG_ON(dbt == NULL);
1731 
1732  for (int i = 0; i < dbt->transforms.cnt; i++) {
1733  const TransformData *t = &dbt->transforms.transforms[i];
1735  continue;
1736 
1737  if (sigmatch_table[t->transform].TransformValidate(content, content_len, t->options)) {
1738  continue;
1739  }
1740 
1741  if (namestr) {
1742  *namestr = sigmatch_table[t->transform].name;
1743  }
1744 
1745  return false;
1746  }
1747 
1748  return true;
1749 }
1750 
1751 static void DetectBufferTypeSetupDetectEngine(DetectEngineCtx *de_ctx)
1752 {
1753  const int size = g_buffer_type_id;
1754  BUG_ON(!(size > 0));
1755 
1756  de_ctx->buffer_type_hash_name = HashListTableInit(256, DetectBufferTypeHashNameFunc,
1757  DetectBufferTypeCompareNameFunc, DetectBufferTypeFreeFunc);
1760  HashListTableInit(256, DetectBufferTypeHashIdFunc, DetectBufferTypeCompareIdFunc,
1761  NULL); // entries owned by buffer_type_hash_name
1762  BUG_ON(de_ctx->buffer_type_hash_id == NULL);
1763  de_ctx->buffer_type_id = g_buffer_type_id;
1764 
1765  SCLogDebug("DETECT_SM_LIST_DYNAMIC_START %u", DETECT_SM_LIST_DYNAMIC_START);
1766  HashListTableBucket *b = HashListTableGetListHead(g_buffer_type_hash);
1767  while (b) {
1769 
1770  DetectBufferType *copy = SCCalloc(1, sizeof(*copy));
1771  BUG_ON(!copy);
1772  memcpy(copy, map, sizeof(*copy));
1773  int r = HashListTableAdd(de_ctx->buffer_type_hash_name, (void *)copy, 0);
1774  BUG_ON(r != 0);
1775  r = HashListTableAdd(de_ctx->buffer_type_hash_id, (void *)copy, 0);
1776  BUG_ON(r != 0);
1777 
1778  SCLogDebug("name %s id %d mpm %s packet %s -- %s. "
1779  "Callbacks: Setup %p Validate %p",
1780  map->name, map->id, map->mpm ? "true" : "false", map->packet ? "true" : "false",
1781  map->description, map->SetupCallback, map->ValidateCallback);
1782  b = HashListTableGetListNext(b);
1783  }
1784 
1787  DetectAppLayerInspectEngineCopyListToDetectCtx(de_ctx);
1789  DetectFrameInspectEngineCopyListToDetectCtx(de_ctx);
1791  DetectPktInspectEngineCopyListToDetectCtx(de_ctx);
1792 }
1793 
1794 static void DetectBufferTypeFreeDetectEngine(DetectEngineCtx *de_ctx)
1795 {
1796  if (de_ctx) {
1801 
1803  while (ilist) {
1805  SCFree(ilist);
1806  ilist = next;
1807  }
1809  while (mlist) {
1810  DetectBufferMpmRegistry *next = mlist->next;
1811  SCFree(mlist);
1812  mlist = next;
1813  }
1815  while (plist) {
1817  SCFree(plist);
1818  plist = next;
1819  }
1821  while (pmlist) {
1822  DetectBufferMpmRegistry *next = pmlist->next;
1823  SCFree(pmlist);
1824  pmlist = next;
1825  }
1827  while (framelist) {
1829  SCFree(framelist);
1830  framelist = next;
1831  }
1833  while (framemlist) {
1834  DetectBufferMpmRegistry *next = framemlist->next;
1835  SCFree(framemlist);
1836  framemlist = next;
1837  }
1839  }
1840 }
1841 
1843 {
1844  BUG_ON(g_buffer_type_hash == NULL);
1845 
1846  g_buffer_type_reg_closed = 1;
1847 }
1848 
1850  DetectEngineCtx *de_ctx, const int id, TransformData *transforms, uint8_t transform_cnt)
1851 {
1852  const DetectBufferType *base_map = DetectEngineBufferTypeGetById(de_ctx, id);
1853  if (!base_map) {
1854  return -1;
1855  }
1856  if (!base_map->supports_transforms) {
1857  SCLogError("buffer '%s' does not support transformations", base_map->name);
1858  return -1;
1859  }
1860 
1861  SCLogDebug("base_map %s", base_map->name);
1862 
1864  memset(&t, 0, sizeof(t));
1865  for (int i = 0; i < transform_cnt; i++) {
1866  t.transforms[i] = transforms[i];
1867  }
1868  t.cnt = transform_cnt;
1869 
1870  DetectBufferType lookup_map;
1871  memset(&lookup_map, 0, sizeof(lookup_map));
1872  strlcpy(lookup_map.name, base_map->name, sizeof(lookup_map.name));
1873  lookup_map.transforms = t;
1874 
1875  /* Add transform identity data from transforms */
1876  if (t.cnt) {
1877  DetectBufferAddTransformData(&lookup_map);
1878  }
1880 
1881  SCLogDebug("res %p", res);
1882  if (res != NULL) {
1883  return res->id;
1884  }
1885 
1886  DetectBufferType *map = SCCalloc(1, sizeof(*map));
1887  if (map == NULL)
1888  return -1;
1889 
1890  strlcpy(map->name, base_map->name, sizeof(map->name));
1891  map->id = de_ctx->buffer_type_id++;
1892  map->parent_id = base_map->id;
1893  map->transforms = t;
1894  map->mpm = base_map->mpm;
1895  map->packet = base_map->packet;
1896  map->frame = base_map->frame;
1897  map->SetupCallback = base_map->SetupCallback;
1898  map->ValidateCallback = base_map->ValidateCallback;
1899  if (map->frame) {
1901  } else if (map->packet) {
1903  map->id, map->parent_id, &map->transforms);
1904  } else {
1906  map->id, map->parent_id, &map->transforms);
1907  }
1908 
1909  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_name, (void *)map, 0) != 0);
1910  BUG_ON(HashListTableAdd(de_ctx->buffer_type_hash_id, (void *)map, 0) != 0);
1911  SCLogDebug("buffer %s registered with id %d, parent %d", map->name, map->id, map->parent_id);
1912 
1913  if (map->frame) {
1914  DetectFrameInspectEngineCopy(de_ctx, map->parent_id, map->id, &map->transforms);
1915  } else if (map->packet) {
1916  DetectPktInspectEngineCopy(de_ctx, map->parent_id, map->id, &map->transforms);
1917  } else {
1918  DetectAppLayerInspectEngineCopy(de_ctx, map->parent_id, map->id, &map->transforms);
1919  }
1920  return map->id;
1921 }
1922 
1923 /* returns false if no match, true if match */
1924 static int DetectEngineInspectRulePacketMatches(
1925  DetectEngineThreadCtx *det_ctx,
1926  const DetectEnginePktInspectionEngine *engine,
1927  const Signature *s,
1928  Packet *p, uint8_t *_alert_flags)
1929 {
1930  SCEnter();
1931 
1932  /* run the packet match functions */
1934  const SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
1935 
1936  SCLogDebug("running match functions, sm %p", smd);
1937  while (1) {
1939  if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) <= 0) {
1940  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
1941  SCLogDebug("no match");
1943  }
1944  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1945  if (smd->is_last) {
1946  SCLogDebug("match and is_last");
1947  break;
1948  }
1949  smd++;
1950  }
1952 }
1953 
1954 static int DetectEngineInspectRulePayloadMatches(
1955  DetectEngineThreadCtx *det_ctx,
1956  const DetectEnginePktInspectionEngine *engine,
1957  const Signature *s, Packet *p, uint8_t *alert_flags)
1958 {
1959  SCEnter();
1960 
1961  DetectEngineCtx *de_ctx = det_ctx->de_ctx;
1962 
1964  /* if we have stream msgs, inspect against those first,
1965  * but not for a "dsize" signature */
1966  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1967  int pmatch = 0;
1969  pmatch = DetectEngineInspectStreamPayload(de_ctx, det_ctx, s, p->flow, p);
1970  if (pmatch) {
1971  *alert_flags |= PACKET_ALERT_FLAG_STREAM_MATCH;
1972  }
1973  }
1974  /* no match? then inspect packet payload */
1975  if (pmatch == 0) {
1976  SCLogDebug("no match in stream, fall back to packet payload");
1977 
1978  /* skip if we don't have to inspect the packet and segment was
1979  * added to stream */
1980  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET) && (p->flags & PKT_STREAM_ADD)) {
1982  }
1984  SCLogDebug("SIG_FLAG_REQUIRE_STREAM_ONLY, so no match");
1986  }
1987  if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, p->flow, p) != 1) {
1989  }
1990  }
1991  } else {
1992  if (DetectEngineInspectPacketPayload(de_ctx, det_ctx, s, p->flow, p) != 1) {
1994  }
1995  }
1997 }
1998 
2000  DetectEngineThreadCtx *det_ctx, const Signature *s,
2001  Flow *f, Packet *p,
2002  uint8_t *alert_flags)
2003 {
2004  SCEnter();
2005 
2006  for (DetectEnginePktInspectionEngine *e = s->pkt_inspect; e != NULL; e = e->next) {
2007  if (e->v1.Callback(det_ctx, e, s, p, alert_flags) != DETECT_ENGINE_INSPECT_SIG_MATCH) {
2008  SCLogDebug("sid %u: e %p Callback returned no match", s->id, e);
2009  return false;
2010  }
2011  SCLogDebug("sid %u: e %p Callback returned true", s->id, e);
2012  }
2013 
2014  SCLogDebug("sid %u: returning true", s->id);
2015  return true;
2016 }
2017 
2018 /**
2019  * \param data pointer to SigMatchData. Allowed to be NULL.
2020  */
2021 static int DetectEnginePktInspectionAppend(Signature *s, InspectionBufferPktInspectFunc Callback,
2022  SigMatchData *data, const int list_id)
2023 {
2024  DetectEnginePktInspectionEngine *e = SCCalloc(1, sizeof(*e));
2025  if (e == NULL)
2026  return -1;
2027 
2028  e->mpm = s->init_data->mpm_sm_list == list_id;
2029  DEBUG_VALIDATE_BUG_ON(list_id < 0 || list_id > UINT16_MAX);
2030  e->sm_list = (uint16_t)list_id;
2031  e->sm_list_base = (uint16_t)list_id;
2032  e->v1.Callback = Callback;
2033  e->smd = data;
2034 
2035  if (s->pkt_inspect == NULL) {
2036  s->pkt_inspect = e;
2037  } else {
2039  while (a->next != NULL) {
2040  a = a->next;
2041  }
2042  a->next = e;
2043  }
2044  return 0;
2045 }
2046 
2048 {
2049  /* only handle PMATCH here if we're not an app inspect rule */
2051  if (DetectEnginePktInspectionAppend(
2052  s, DetectEngineInspectRulePayloadMatches, NULL, DETECT_SM_LIST_PMATCH) < 0)
2053  return -1;
2054  SCLogDebug("sid %u: DetectEngineInspectRulePayloadMatches appended", s->id);
2055  }
2056 
2057  if (s->sm_arrays[DETECT_SM_LIST_MATCH]) {
2058  if (DetectEnginePktInspectionAppend(
2059  s, DetectEngineInspectRulePacketMatches, NULL, DETECT_SM_LIST_MATCH) < 0)
2060  return -1;
2061  SCLogDebug("sid %u: DetectEngineInspectRulePacketMatches appended", s->id);
2062  }
2063 
2064  return 0;
2065 }
2066 
2067 /* code to control the main thread to do a reload */
2068 
2070  IDLE, /**< ready to start a reload */
2071  RELOAD, /**< command main thread to do the reload */
2072 };
2073 
2074 
2075 typedef struct DetectEngineSyncer_ {
2079 
2080 static DetectEngineSyncer detect_sync = { SCMUTEX_INITIALIZER, IDLE };
2081 
2082 /* tell main to start reloading */
2084 {
2085  int r = 0;
2086  SCMutexLock(&detect_sync.m);
2087  if (detect_sync.state == IDLE) {
2088  detect_sync.state = RELOAD;
2089  } else {
2090  r = -1;
2091  }
2092  SCMutexUnlock(&detect_sync.m);
2093  return r;
2094 }
2095 
2096 /* main thread checks this to see if it should start */
2098 {
2099  int r = 0;
2100  SCMutexLock(&detect_sync.m);
2101  if (detect_sync.state == RELOAD) {
2102  r = 1;
2103  }
2104  SCMutexUnlock(&detect_sync.m);
2105  return r;
2106 }
2107 
2108 /* main thread sets done when it's done */
2110 {
2111  SCMutexLock(&detect_sync.m);
2112  detect_sync.state = IDLE;
2113  SCMutexUnlock(&detect_sync.m);
2114 }
2115 
2116 /* caller loops this until it returns 1 */
2118 {
2119  int r = 0;
2120  SCMutexLock(&detect_sync.m);
2121  if (detect_sync.state == IDLE) {
2122  r = 1;
2123  }
2124  SCMutexUnlock(&detect_sync.m);
2125  return r;
2126 }
2127 
2128 /** \internal
2129  * \brief is the engine's data final for this tx?
2130  *
2131  * Past the engine's phase the answer is yes; at or beyond the tx end state it
2132  * is final too, even for engines registered at the completion state (no P+1).
2133  * AppLayerParserGetStateProgress() returns the end progress for disrupted
2134  * flows, so progress == end stays a valid finality signal there.
2135  */
2136 static bool DetectTxCompleted(
2137  Flow *f, void *txv, uint8_t flags, const DetectEngineAppInspectionEngine *engine)
2138 {
2139  if (f->alproto == ALPROTO_DOH2 && engine->alproto == ALPROTO_DOH2) {
2140  // the DNS tx from DetectGetInnerTx is always complete
2141  return true;
2142  } // else
2143  const int progress = AppLayerParserGetStateProgress(f->proto, f->alproto, txv, flags);
2144  if (progress < 0) {
2145  return false;
2146  }
2147  if (progress > engine->progress) {
2148  return true;
2149  }
2150  if (progress < engine->progress) {
2151  return false;
2152  }
2153  return progress == AppLayerParserGetTxEndState(f->proto, f->alproto, txv, flags);
2154 }
2155 
2157  const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
2158  uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
2159 {
2160  SigMatchData *smd = engine->smd;
2161  SCLogDebug("running match functions, sm %p", smd);
2162  if (smd != NULL) {
2163  while (1) {
2164  int match = 0;
2166  match = sigmatch_table[smd->type].
2167  AppLayerTxMatch(det_ctx, f, flags, alstate, txv, s, smd->ctx);
2168  KEYWORD_PROFILING_END(det_ctx, smd->type, (match == 1));
2169  if (match == 0) {
2170  /* like the buffer engines, a no match is final once the tx
2171  * moved past the phase the engine is registered at (P + 1).
2172  * stateful keywords read live tx state, so they stay
2173  * revisitable. */
2174  if ((sigmatch_table[smd->type].flags & SIGMATCH_STATEFUL) != 0) {
2176  }
2177  return DetectTxCompleted(f, txv, flags, engine)
2180  }
2181  if (match == 2) {
2183  }
2184 
2185  if (smd->is_last)
2186  break;
2187  smd++;
2188  }
2189  }
2190 
2192 }
2193 
2194 /**
2195  * \brief Do the content inspection & validation for a signature
2196  *
2197  * \param de_ctx Detection engine context
2198  * \param det_ctx Detection engine thread context
2199  * \param s Signature to inspect
2200  * \param f Flow
2201  * \param flags app layer flags
2202  * \param state App layer state
2203  *
2204  * \retval 0 no match.
2205  * \retval 1 match.
2206  * \retval 2 Sig can't match.
2207  */
2209  const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
2210  void *alstate, void *txv, uint64_t tx_id)
2211 {
2212  const int list_id = engine->sm_list;
2213  SCLogDebug("running inspect on %d", list_id);
2214 
2215  const bool eof = DetectTxCompleted(f, txv, flags, engine);
2216 
2217  SCLogDebug("list %d mpm? %s transforms %p", engine->sm_list, engine->mpm ? "true" : "false",
2218  engine->v2.transforms);
2219 
2220  /* if prefilter didn't already run, we need to consider transformations */
2221  const DetectEngineTransforms *transforms = NULL;
2222  if (!engine->mpm) {
2223  transforms = engine->v2.transforms;
2224  }
2225 
2226  const InspectionBuffer *buffer = DetectGetSingleData(
2227  det_ctx, transforms, f, flags, txv, list_id, engine->v2.GetDataSingle);
2228  if (unlikely(buffer == NULL)) {
2229  if (eof && engine->match_on_null) {
2231  }
2233  }
2234 
2235  const uint32_t data_len = buffer->inspect_len;
2236  const uint8_t *data = buffer->inspect;
2237  const uint64_t offset = buffer->inspect_offset;
2238 
2239  uint8_t ci_flags = eof ? DETECT_CI_FLAGS_END : 0;
2240  ci_flags |= (offset == 0 ? DETECT_CI_FLAGS_START : 0);
2241  ci_flags |= buffer->flags;
2242 
2243  /* Inspect all the uricontents fetched on each
2244  * transaction at the app layer */
2245  const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f, data,
2247  if (match) {
2249  } else {
2251  }
2252 }
2253 
2254 /**
2255  * \brief Do the content inspection & validation for a signature
2256  *
2257  * \param de_ctx Detection engine context
2258  * \param det_ctx Detection engine thread context
2259  * \param s Signature to inspect
2260  * \param f Flow
2261  * \param flags app layer flags
2262  * \param state App layer state
2263  *
2264  * \retval 0 no match.
2265  * \retval 1 match.
2266  * \retval 2 Sig can't match.
2267  */
2269  const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
2270  void *alstate, void *txv, uint64_t tx_id)
2271 {
2272  const int list_id = engine->sm_list;
2273  SCLogDebug("running inspect on %d", list_id);
2274 
2275  const bool eof = DetectTxCompleted(f, txv, flags, engine);
2276 
2277  SCLogDebug("list %d mpm? %s transforms %p",
2278  engine->sm_list, engine->mpm ? "true" : "false", engine->v2.transforms);
2279 
2280  /* if prefilter didn't already run, we need to consider transformations */
2281  const DetectEngineTransforms *transforms = NULL;
2282  if (!engine->mpm) {
2283  transforms = engine->v2.transforms;
2284  }
2285 
2286  const InspectionBuffer *buffer = engine->v2.GetData(det_ctx, transforms,
2287  f, flags, txv, list_id);
2288  if (unlikely(buffer == NULL)) {
2289  if (eof && engine->match_on_null) {
2291  }
2294  }
2295 
2296  const uint32_t data_len = buffer->inspect_len;
2297  const uint8_t *data = buffer->inspect;
2298  const uint64_t offset = buffer->inspect_offset;
2299 
2300  uint8_t ci_flags = eof ? DETECT_CI_FLAGS_END : 0;
2301  ci_flags |= (offset == 0 ? DETECT_CI_FLAGS_START : 0);
2302  ci_flags |= buffer->flags;
2303 
2304  /* Inspect all the uricontents fetched on each
2305  * transaction at the app layer */
2306  const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, NULL, f, data,
2308  if (match) {
2310  } else {
2313  }
2314 }
2315 
2316 // wrapper for both DetectAppLayerInspectEngineRegister and DetectAppLayerMpmRegister
2317 // with cast of callback function
2318 void DetectAppLayerMultiRegisterSubState(const char *name, AppProto alproto, uint32_t dir,
2319  uint8_t sub_state, uint8_t progress, InspectionMultiBufferGetDataPtr GetData, int priority)
2320 {
2321  BUG_ON(AppLayerParserSupportsSubStates(alproto) && sub_state == 0);
2322  AppLayerInspectEngineRegisterInternal(name, alproto, dir, sub_state, progress,
2323  DetectEngineInspectMultiBufferGeneric, NULL, NULL, GetData);
2325  GetData, alproto, sub_state, progress);
2326 }
2327 
2328 // wrapper for both DetectAppLayerInspectEngineRegister and DetectAppLayerMpmRegister
2329 // with cast of callback function
2330 void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, uint8_t progress,
2331  InspectionMultiBufferGetDataPtr GetData, int priority)
2332 {
2334  AppLayerInspectEngineRegisterInternal(name, alproto, dir, 0, (uint8_t)progress,
2335  DetectEngineInspectMultiBufferGeneric, NULL, NULL, GetData);
2337  name, dir, priority, PrefilterMultiGenericMpmRegister, GetData, alproto, progress);
2338 }
2339 
2341  const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
2342  const int list_id, InspectionSingleBufferGetDataPtr GetBuf)
2343 {
2344  InspectionBuffer *buffer = SCInspectionBufferGet(det_ctx, list_id);
2345  if (buffer->inspect == NULL) {
2346  const uint8_t *b = NULL;
2347  uint32_t b_len = 0;
2348 
2349  if (!GetBuf(txv, flow_flags, &b, &b_len))
2350  return NULL;
2351 
2352  SCInspectionBufferSetupAndApplyTransforms(det_ctx, list_id, buffer, b, b_len, transforms);
2353  }
2354  return buffer;
2355 }
2356 
2358  const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
2359  const int list_id, uint32_t index, InspectionMultiBufferGetDataPtr GetBuf)
2360 {
2361  InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, index);
2362  if (buffer == NULL) {
2363  return NULL;
2364  }
2365  if (buffer->initialized) {
2366  return buffer;
2367  }
2368 
2369  const uint8_t *data = NULL;
2370  uint32_t data_len = 0;
2371 
2372  if (!GetBuf(det_ctx, txv, flow_flags, index, &data, &data_len)) {
2374  return NULL;
2375  }
2376  InspectionBufferSetupMulti(det_ctx, buffer, transforms, data, data_len);
2377  buffer->flags = DETECT_CI_FLAGS_SINGLE;
2378  return buffer;
2379 }
2380 
2383  const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
2384 {
2385  uint32_t local_id = 0;
2386  const DetectEngineTransforms *transforms = NULL;
2387  if (!engine->mpm) {
2388  transforms = engine->v2.transforms;
2389  }
2390 
2391  do {
2392  InspectionBuffer *buffer = DetectGetMultiData(det_ctx, transforms, f, flags, txv,
2393  engine->sm_list, local_id, engine->v2.GetMultiData);
2394 
2395  if (buffer == NULL || buffer->inspect == NULL)
2396  break;
2397 
2398  // The GetData functions set buffer->flags to DETECT_CI_FLAGS_SINGLE
2399  // This is not meant for streaming buffers
2400  const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
2402  if (match) {
2404  }
2405  local_id++;
2406  } while (1);
2407  if (local_id == 0) {
2408  // That means we did not get even one buffer value from the multi-buffer
2409  const bool eof = DetectTxCompleted(f, txv, flags, engine);
2410  if (eof && engine->match_on_null) {
2412  }
2413  }
2415 }
2416 
2417 /**
2418  * \brief Do the content inspection & validation for a signature
2419  *
2420  * \param de_ctx Detection engine context
2421  * \param det_ctx Detection engine thread context
2422  * \param s Signature to inspect
2423  * \param p Packet
2424  *
2425  * \retval 0 no match.
2426  * \retval 1 match.
2427  */
2429  DetectEngineThreadCtx *det_ctx,
2430  const DetectEnginePktInspectionEngine *engine,
2431  const Signature *s, Packet *p, uint8_t *_alert_flags)
2432 {
2433  const int list_id = engine->sm_list;
2434  SCLogDebug("running inspect on %d", list_id);
2435 
2436  SCLogDebug("list %d transforms %p",
2437  engine->sm_list, engine->v1.transforms);
2438 
2439  /* if prefilter didn't already run, we need to consider transformations */
2440  const DetectEngineTransforms *transforms = NULL;
2441  if (!engine->mpm) {
2442  transforms = engine->v1.transforms;
2443  }
2444 
2445  const InspectionBuffer *buffer = engine->v1.GetData(det_ctx, transforms, p,
2446  list_id);
2447  if (unlikely(buffer == NULL)) {
2449  }
2450 
2451  uint8_t ci_flags = DETECT_CI_FLAGS_START|DETECT_CI_FLAGS_END;
2452  ci_flags |= buffer->flags;
2453 
2454  /* Inspect all the uricontents fetched on each
2455  * transaction at the app layer */
2456  const bool match = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx, s, engine->smd, p,
2457  p->flow, buffer->inspect, buffer->inspect_len, 0, ci_flags,
2459  if (match) {
2461  } else {
2463  }
2464 }
2465 
2466 /** \internal
2467  * \brief inject a pseudo packet into each detect thread
2468  * -that doesn't use the new det_ctx yet
2469  * -*or*, if the thread should flush its output logs.
2470  */
2471 static void InjectPackets(
2472  ThreadVars **detect_tvs, DetectEngineThreadCtx **new_det_ctx, int no_of_detect_tvs)
2473 {
2474  /* inject a fake packet if the detect thread that needs it. This function
2475  * is called if
2476  * - A thread isn't using a DE ctx and should
2477  * - Or, it should process a pseudo packet and flush its output logs.
2478  * to speed the process. */
2479  for (int i = 0; i < no_of_detect_tvs; i++) {
2480  if (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
2481  if (detect_tvs[i]->inq != NULL) {
2483  if (p != NULL) {
2486  PacketQueue *q = detect_tvs[i]->inq->pq;
2487  SCMutexLock(&q->mutex_q);
2488  PacketEnqueue(q, p);
2489  SCCondSignal(&q->cond_q);
2490  SCMutexUnlock(&q->mutex_q);
2491  }
2492  }
2493  }
2494  }
2495 }
2496 
2497 static void DetectEngineLoadFlowbitSettings(DetectEngineCtx *de_ctx)
2498 {
2500  char varname[128] = "detect.flowbits.max-per-signature";
2501  if (strlen(de_ctx->config_prefix) > 0) {
2502  snprintf(varname, sizeof(varname), "%s.detect.flowbits.max-per-signature",
2504  }
2505  const char *str;
2506  if (SCConfGet(varname, &str) == 1) {
2507  uint8_t val = 0;
2508  int ret = StringParseUint8(&val, 10, 0, str);
2509  if (ret > 0) {
2510  if (val > 0) {
2511  de_ctx->max_flowbits = val;
2512  } else {
2513  SCLogWarning("Invalid setting for flowbits.max-per-signature %d, resetting to the "
2514  "default",
2515  val);
2516  }
2517  } else {
2518  SCLogWarning(
2519  "Invalid setting for flowbits.max-per-signature, resetting to the default");
2520  }
2521  }
2522  SCLogConfig("Setting flowbits.max-per-signature to %d", de_ctx->max_flowbits);
2523 }
2524 
2525 /** \internal
2526  * \brief Update detect threads with new detect engine
2527  *
2528  * Atomically update each detect thread with a new thread context
2529  * that is associated to the new detection engine(s).
2530  *
2531  * If called in unix socket mode, it's possible that we don't have
2532  * detect threads yet.
2533  * NOTE: master MUST be locked before calling this
2534  *
2535  * \retval -1 error
2536  * \retval 0 no detection threads
2537  * \retval 1 successful reload
2538  */
2539 static int DetectEngineReloadThreads(DetectEngineCtx *new_de_ctx)
2540 {
2541  SCEnter();
2542  uint32_t i = 0;
2543 
2544  /* count detect threads in use */
2545  const uint32_t no_of_detect_tvs = TmThreadCountThreadsByTmmFlags(TM_FLAG_FLOWWORKER_TM);
2546  /* can be zero in unix socket mode */
2547  if (no_of_detect_tvs == 0) {
2548  return 0;
2549  }
2550 
2551  /* prepare swap structures */
2552  DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs];
2553  DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs];
2554  ThreadVars *detect_tvs[no_of_detect_tvs];
2555  memset(old_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
2556  memset(new_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
2557  memset(detect_tvs, 0x00, (no_of_detect_tvs * sizeof(ThreadVars *)));
2558 
2559  /* start the process of swapping detect threads ctxs */
2560 
2561  /* get reference to tv's and setup new_det_ctx array */
2563  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
2564  if ((tv->tmm_flags & TM_FLAG_FLOWWORKER_TM) == 0) {
2565  continue;
2566  }
2567  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
2568  TmModule *tm = TmModuleGetById(s->tm_id);
2569  if (!(tm->flags & TM_FLAG_FLOWWORKER_TM)) {
2570  continue;
2571  }
2572 
2573  if (suricata_ctl_flags != 0) {
2575  goto error;
2576  }
2577 
2578  old_det_ctx[i] = FlowWorkerGetDetectCtxPtr(SC_ATOMIC_GET(s->slot_data));
2579  detect_tvs[i] = tv;
2580 
2581  new_det_ctx[i] = DetectEngineThreadCtxInitForReload(tv, new_de_ctx, 1);
2582  if (new_det_ctx[i] == NULL) {
2583  SCLogError("Detect engine thread init "
2584  "failure in live rule swap. Let's get out of here");
2586  goto error;
2587  }
2588  SCLogDebug("live rule swap created new det_ctx - %p and de_ctx "
2589  "- %p\n", new_det_ctx[i], new_de_ctx);
2590  i++;
2591  break;
2592  }
2593  }
2594  BUG_ON(i != no_of_detect_tvs);
2595 
2596  /* atomically replace the det_ctx data */
2597  i = 0;
2598  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
2599  if ((tv->tmm_flags & TM_FLAG_FLOWWORKER_TM) == 0) {
2600  continue;
2601  }
2602  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
2603  TmModule *tm = TmModuleGetById(s->tm_id);
2604  if (!(tm->flags & TM_FLAG_FLOWWORKER_TM)) {
2605  continue;
2606  }
2607  SCLogDebug("swapping new det_ctx - %p with older one - %p",
2608  new_det_ctx[i], SC_ATOMIC_GET(s->slot_data));
2609  DEBUG_VALIDATE_BUG_ON(i >= no_of_detect_tvs); // help scan-build
2610  FlowWorkerReplaceDetectCtx(SC_ATOMIC_GET(s->slot_data), new_det_ctx[i]);
2611  i++;
2612  break;
2613  }
2614  }
2616 
2617  /* threads now all have new data, however they may not have started using
2618  * it and may still use the old data */
2619 
2620  SCLogDebug("Live rule swap has swapped %d old det_ctx's with new ones, "
2621  "along with the new de_ctx", no_of_detect_tvs);
2622 
2623  InjectPackets(detect_tvs, new_det_ctx, no_of_detect_tvs);
2624 
2625  /* loop waiting for detect threads to switch to the new det_ctx. Try to
2626  * wake up capture if needed (break loop). */
2627  uint32_t threads_done = 0;
2628 retry:
2629  for (i = 0; i < no_of_detect_tvs; i++) {
2630  if (suricata_ctl_flags != 0) {
2631  threads_done = no_of_detect_tvs;
2632  break;
2633  }
2634  SleepMsec(1);
2635  if (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) == 1) {
2636  SCLogDebug("new_det_ctx - %p used by detect engine", new_det_ctx[i]);
2637  threads_done++;
2638  } else {
2639  TmThreadsCaptureBreakLoop(detect_tvs[i]);
2640  }
2641  }
2642  if (threads_done < no_of_detect_tvs) {
2643  threads_done = 0;
2644  SleepMsec(250);
2645  goto retry;
2646  }
2647 
2648  /* this is to make sure that if someone initiated shutdown during a live
2649  * rule swap, the live rule swap won't clean up the old det_ctx and
2650  * de_ctx, till all detect threads have stopped working and sitting
2651  * silently after setting RUNNING_DONE flag and while waiting for
2652  * THV_DEINIT flag */
2653  if (i != no_of_detect_tvs) { // not all threads we swapped
2654  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
2655  if ((tv->tmm_flags & TM_FLAG_FLOWWORKER_TM) == 0) {
2656  continue;
2657  }
2658 
2660  SleepUsec(100);
2661  }
2662  }
2663  }
2664 
2665  /* free all the ctxs */
2666  for (i = 0; i < no_of_detect_tvs; i++) {
2667  SCLogDebug("Freeing old_det_ctx - %p used by detect",
2668  old_det_ctx[i]);
2669  DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]);
2670  }
2671 
2673 
2674  return 1;
2675 
2676  error:
2677  for (i = 0; i < no_of_detect_tvs; i++) {
2678  if (new_det_ctx[i] != NULL)
2679  DetectEngineThreadCtxDeinit(NULL, new_det_ctx[i]);
2680  }
2681  return -1;
2682 }
2683 
2685 {
2686  int sgh_mpm_caching = 0;
2687  if (SCConfGetBool("detect.sgh-mpm-caching", &sgh_mpm_caching) != 1) {
2688  return false;
2689  }
2690  return (bool)sgh_mpm_caching;
2691 }
2692 
2694 {
2695  if (DetectEngineMpmCachingEnabled() == false) {
2696  return NULL;
2697  }
2698 
2699  char yamlpath[] = "detect.sgh-mpm-caching-path";
2700  const char *strval = NULL;
2701  if (SCConfGet(yamlpath, &strval) == 1 && strval != NULL) {
2702  return strval;
2703  }
2704 
2705  static bool notified = false;
2706  if (!notified) {
2707  SCLogInfo("%s has no path specified, using %s", yamlpath, SGH_CACHE_DIR);
2708  notified = true;
2709  }
2710  return SGH_CACHE_DIR;
2711 }
2712 
2713 void DetectEngineMpmCacheService(uint32_t op_flags)
2714 {
2716  if (!de_ctx) {
2717  return;
2718  }
2719 
2720  if (!de_ctx->mpm_cfg || !de_ctx->mpm_cfg->cache_dir_path) {
2721  goto error;
2722  }
2723 
2724  if (mpm_table[de_ctx->mpm_matcher].CacheStatsInit != NULL) {
2726  if (de_ctx->mpm_cfg->cache_stats == NULL) {
2727  goto error;
2728  }
2729  }
2730 
2731  if (op_flags & DETECT_ENGINE_MPM_CACHE_OP_SAVE) {
2732  if (mpm_table[de_ctx->mpm_matcher].CacheRuleset != NULL) {
2734  }
2735  }
2736 
2737  if (op_flags & DETECT_ENGINE_MPM_CACHE_OP_PRUNE) {
2738  if (mpm_table[de_ctx->mpm_matcher].CachePrune != NULL) {
2740  }
2741  }
2742 
2743  if (mpm_table[de_ctx->mpm_matcher].CacheStatsPrint != NULL) {
2745  }
2746 
2747  if (mpm_table[de_ctx->mpm_matcher].CacheStatsDeinit != NULL) {
2749  de_ctx->mpm_cfg->cache_stats = NULL;
2750  }
2751 
2752 error:
2754 }
2755 
2756 static DetectEngineCtx *DetectEngineCtxInitReal(
2757  enum DetectEngineType type, const char *prefix, uint32_t tenant_id)
2758 {
2760  if (unlikely(de_ctx == NULL))
2761  goto error;
2762 
2763  memset(&de_ctx->sig_stat, 0, sizeof(SigFileLoaderStat));
2764  TAILQ_INIT(&de_ctx->sig_stat.failed_sigs);
2765  de_ctx->sigerror = NULL;
2766  de_ctx->type = type;
2768  de_ctx->tenant_id = tenant_id;
2769 
2772 
2775  if (de_ctx->mpm_cfg == NULL) {
2776  goto error;
2777  }
2778 
2782 
2784  if (SCConfGetTime("detect.sgh-mpm-caching-max-age",
2786  de_ctx->mpm_cfg->cache_max_age_seconds = 7ULL * 24ULL * 60ULL * 60ULL;
2787  }
2788  }
2789  }
2790  }
2791 
2794  SCLogDebug("stub %u with version %u", type, de_ctx->version);
2795  return de_ctx;
2796  }
2797 
2798  if (prefix != NULL) {
2799  strlcpy(de_ctx->config_prefix, prefix, sizeof(de_ctx->config_prefix));
2800  }
2801 
2802  int failure_fatal = 0;
2803  if (SCConfGetBool("engine.init-failure-fatal", (int *)&failure_fatal) != 1) {
2804  SCLogDebug("ConfGetBool could not load the value.");
2805  }
2806  de_ctx->failure_fatal = (failure_fatal == 1);
2807 
2808  SCLogConfig("pattern matchers: MPM: %s, SPM: %s", mpm_table[de_ctx->mpm_matcher].name,
2811  if (de_ctx->spm_global_thread_ctx == NULL) {
2812  SCLogDebug("Unable to alloc SpmGlobalThreadCtx.");
2813  goto error;
2814  }
2815 
2817  if (de_ctx->sm_types_prefilter == NULL) {
2818  goto error;
2819  }
2821  if (de_ctx->sm_types_silent_error == NULL) {
2822  goto error;
2823  }
2824  if (DetectEngineCtxLoadConf(de_ctx) == -1) {
2825  goto error;
2826  }
2827 
2833  DetectBufferTypeSetupDetectEngine(de_ctx);
2835 
2836  /* init iprep... ignore errors for now */
2837  (void)SRepInit(de_ctx);
2838 
2842  goto error;
2843  }
2844 
2845  if (ActionInitConfig() < 0) {
2846  goto error;
2847  }
2849  if (SCRConfLoadReferenceConfigFile(de_ctx, NULL) < 0) {
2851  goto error;
2852  }
2853 
2855  SCLogDebug("dectx with version %u", de_ctx->version);
2856  return de_ctx;
2857 error:
2858  if (de_ctx != NULL) {
2860  }
2861  return NULL;
2862 }
2863 
2865 {
2866  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_MT_STUB, NULL, 0);
2867 }
2868 
2870 {
2871  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_DD_STUB, NULL, 0);
2872 }
2873 
2875 {
2876  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_NORMAL, NULL, 0);
2877 }
2878 
2879 DetectEngineCtx *DetectEngineCtxInitWithPrefix(const char *prefix, uint32_t tenant_id)
2880 {
2881  if (prefix == NULL || strlen(prefix) == 0)
2882  return DetectEngineCtxInit();
2883  else
2884  return DetectEngineCtxInitReal(DETECT_ENGINE_TYPE_NORMAL, prefix, tenant_id);
2885 }
2886 
2887 static void DetectEngineCtxFreeThreadKeywordData(DetectEngineCtx *de_ctx)
2888 {
2890 }
2891 
2892 static void DetectEngineCtxFreeFailedSigs(DetectEngineCtx *de_ctx)
2893 {
2894  SigString *item = NULL;
2895  SigString *sitem;
2896 
2897  TAILQ_FOREACH_SAFE(item, &de_ctx->sig_stat.failed_sigs, next, sitem) {
2898  SCFree(item->filename);
2899  SCFree(item->sig_str);
2900  if (item->sig_error) {
2901  SCFree(item->sig_error);
2902  }
2903  TAILQ_REMOVE(&de_ctx->sig_stat.failed_sigs, item, next);
2904  SCFree(item);
2905  }
2906 }
2907 
2908 /**
2909  * \brief Free a DetectEngineCtx::
2910  *
2911  * \param de_ctx DetectEngineCtx:: to be freed
2912  */
2914 {
2915 
2916  if (de_ctx == NULL)
2917  return;
2918 
2919 #ifdef PROFILE_RULES
2920  if (de_ctx->profile_ctx != NULL) {
2921  SCProfilingRuleDestroyCtx(de_ctx->profile_ctx);
2922  de_ctx->profile_ctx = NULL;
2923  }
2924 #endif
2925 #ifdef PROFILING
2926  if (de_ctx->profile_keyword_ctx != NULL) {
2927  SCProfilingKeywordDestroyCtx(de_ctx);//->profile_keyword_ctx);
2928 // de_ctx->profile_keyword_ctx = NULL;
2929  }
2930  if (de_ctx->profile_sgh_ctx != NULL) {
2932  }
2934 #endif
2935 
2938  }
2939  /* Normally the hashes are freed elsewhere, but
2940  * to be sure look at them again here.
2941  */
2947  if (de_ctx->sig_array)
2949 
2950  if (de_ctx->filedata_config)
2952 
2956 
2958 
2962 
2964 
2965  DetectEngineCtxFreeThreadKeywordData(de_ctx);
2967  DetectEngineCtxFreeFailedSigs(de_ctx);
2968 
2971 
2972  /* if we have a config prefix, remove the config from the tree */
2973  if (strlen(de_ctx->config_prefix) > 0) {
2974  /* remove config */
2976  if (node != NULL) {
2977  SCConfNodeRemove(node); /* frees node */
2978  }
2979 #if 0
2980  SCConfDump();
2981 #endif
2982  }
2983 
2986 
2987  DetectBufferTypeFreeDetectEngine(de_ctx);
2990 
2991  if (de_ctx->tenant_path) {
2993  }
2994 
2995  if (de_ctx->requirements) {
2996  SCDetectRequiresStatusFree(de_ctx->requirements);
2997  }
2998 
2999  if (de_ctx->non_pf_engine_names) {
3001  }
3002  if (de_ctx->fw_policies) {
3003  for (uint32_t i = 0; i < DETECT_FIREWALL_POLICY_SIZE; i++) {
3007  }
3008  }
3010  }
3012  SCFree(de_ctx);
3013  //DetectAddressGroupPrintMemory();
3014  //DetectSigGroupPrintMemory();
3015  //DetectPortPrintMemory();
3016 }
3017 
3018 /** \brief Function that load DetectEngineCtx config for grouping sigs
3019  * used by the engine
3020  * \retval 0 if no config provided, 1 if config was provided
3021  * and loaded successfully
3022  */
3023 static int DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx)
3024 {
3025  uint8_t profile = ENGINE_PROFILE_MEDIUM;
3026  const char *max_uniq_toclient_groups_str = NULL;
3027  const char *max_uniq_toserver_groups_str = NULL;
3028  const char *sgh_mpm_context = NULL;
3029  const char *de_ctx_profile = NULL;
3030 
3031  (void)SCConfGet("detect.profile", &de_ctx_profile);
3032  (void)SCConfGet("detect.sgh-mpm-context", &sgh_mpm_context);
3033 
3034  SCConfNode *de_ctx_custom = SCConfGetNode("detect-engine");
3035  SCConfNode *opt = NULL;
3036 
3037  if (de_ctx_custom != NULL) {
3038  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
3039  if (de_ctx_profile == NULL) {
3040  if (opt->val && strcmp(opt->val, "profile") == 0) {
3041  de_ctx_profile = opt->head.tqh_first->val;
3042  }
3043  }
3044 
3045  if (sgh_mpm_context == NULL) {
3046  if (opt->val && strcmp(opt->val, "sgh-mpm-context") == 0) {
3047  sgh_mpm_context = opt->head.tqh_first->val;
3048  }
3049  }
3050  }
3051  }
3052 
3053  if (de_ctx_profile != NULL) {
3054  if (strcmp(de_ctx_profile, "low") == 0 ||
3055  strcmp(de_ctx_profile, "lowest") == 0) { // legacy
3056  profile = ENGINE_PROFILE_LOW;
3057  } else if (strcmp(de_ctx_profile, "medium") == 0) {
3058  profile = ENGINE_PROFILE_MEDIUM;
3059  } else if (strcmp(de_ctx_profile, "high") == 0 ||
3060  strcmp(de_ctx_profile, "highest") == 0) { // legacy
3061  profile = ENGINE_PROFILE_HIGH;
3062  } else if (strcmp(de_ctx_profile, "custom") == 0) {
3063  profile = ENGINE_PROFILE_CUSTOM;
3064  } else {
3065  SCLogError("invalid value for detect.profile: '%s'. "
3066  "Valid options: low, medium, high and custom.",
3067  de_ctx_profile);
3068  return -1;
3069  }
3070 
3071  SCLogDebug("Profile for detection engine groups is \"%s\"", de_ctx_profile);
3072  } else {
3073  SCLogDebug("Profile for detection engine groups not provided "
3074  "at suricata.yaml. Using default (\"medium\").");
3075  }
3076 
3077  /* detect-engine.sgh-mpm-context option parsing */
3078  if (sgh_mpm_context == NULL || strcmp(sgh_mpm_context, "auto") == 0) {
3079  /* for now, since we still haven't implemented any intelligence into
3080  * understanding the patterns and distributing mpm_ctx across sgh */
3082  de_ctx->mpm_matcher == MPM_HS) {
3084  } else {
3086  }
3087  } else {
3088  if (strcmp(sgh_mpm_context, "single") == 0) {
3090  } else if (strcmp(sgh_mpm_context, "full") == 0) {
3092  } else {
3093  SCLogError("You have supplied an "
3094  "invalid conf value for detect-engine.sgh-mpm-context-"
3095  "%s",
3096  sgh_mpm_context);
3097  exit(EXIT_FAILURE);
3098  }
3099  }
3100 
3101  if (RunmodeIsUnittests()) {
3103  }
3104 
3105  /* parse profile custom-values */
3106  opt = NULL;
3107  switch (profile) {
3108  case ENGINE_PROFILE_LOW:
3111  break;
3112 
3113  case ENGINE_PROFILE_HIGH:
3116  break;
3117 
3118  case ENGINE_PROFILE_CUSTOM:
3119  (void)SCConfGet("detect.custom-values.toclient-groups", &max_uniq_toclient_groups_str);
3120  (void)SCConfGet("detect.custom-values.toserver-groups", &max_uniq_toserver_groups_str);
3121 
3122  if (de_ctx_custom != NULL) {
3123  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
3124  if (opt->val && strcmp(opt->val, "custom-values") == 0) {
3125  if (max_uniq_toclient_groups_str == NULL) {
3126  max_uniq_toclient_groups_str = (char *)SCConfNodeLookupChildValue(
3127  opt->head.tqh_first, "toclient-sp-groups");
3128  }
3129  if (max_uniq_toclient_groups_str == NULL) {
3130  max_uniq_toclient_groups_str = (char *)SCConfNodeLookupChildValue(
3131  opt->head.tqh_first, "toclient-groups");
3132  }
3133  if (max_uniq_toserver_groups_str == NULL) {
3134  max_uniq_toserver_groups_str = (char *)SCConfNodeLookupChildValue(
3135  opt->head.tqh_first, "toserver-dp-groups");
3136  }
3137  if (max_uniq_toserver_groups_str == NULL) {
3138  max_uniq_toserver_groups_str = (char *)SCConfNodeLookupChildValue(
3139  opt->head.tqh_first, "toserver-groups");
3140  }
3141  }
3142  }
3143  }
3144  if (max_uniq_toclient_groups_str != NULL) {
3146  (uint16_t)strlen(max_uniq_toclient_groups_str),
3147  (const char *)max_uniq_toclient_groups_str) <= 0) {
3149 
3150  SCLogWarning("parsing '%s' for "
3151  "toclient-groups failed, using %u",
3152  max_uniq_toclient_groups_str, de_ctx->max_uniq_toclient_groups);
3153  }
3154  } else {
3156  }
3157  SCLogConfig("toclient-groups %u", de_ctx->max_uniq_toclient_groups);
3158 
3159  if (max_uniq_toserver_groups_str != NULL) {
3161  (uint16_t)strlen(max_uniq_toserver_groups_str),
3162  (const char *)max_uniq_toserver_groups_str) <= 0) {
3164 
3165  SCLogWarning("parsing '%s' for "
3166  "toserver-groups failed, using %u",
3167  max_uniq_toserver_groups_str, de_ctx->max_uniq_toserver_groups);
3168  }
3169  } else {
3171  }
3172  SCLogConfig("toserver-groups %u", de_ctx->max_uniq_toserver_groups);
3173  break;
3174 
3175  /* Default (or no config provided) is profile medium */
3176  case ENGINE_PROFILE_MEDIUM:
3178  default:
3181  break;
3182  }
3183 
3184  intmax_t value = 0;
3186  if (SCConfGetInt("detect.inspection-recursion-limit", &value) == 1) {
3187  if (value >= 0 && value <= INT_MAX) {
3188  de_ctx->inspection_recursion_limit = (int)value;
3189  }
3190 
3191  /* fall back to old config parsing */
3192  } else {
3193  SCConfNode *insp_recursion_limit_node = NULL;
3194  char *insp_recursion_limit = NULL;
3195 
3196  if (de_ctx_custom != NULL) {
3197  opt = NULL;
3198  TAILQ_FOREACH(opt, &de_ctx_custom->head, next) {
3199  if (opt->val && strcmp(opt->val, "inspection-recursion-limit") != 0)
3200  continue;
3201 
3202  insp_recursion_limit_node = SCConfNodeLookupChild(opt, opt->val);
3203  if (insp_recursion_limit_node == NULL) {
3204  SCLogError("Error retrieving conf "
3205  "entry for detect-engine:inspection-recursion-limit");
3206  break;
3207  }
3208  insp_recursion_limit = insp_recursion_limit_node->val;
3209  SCLogDebug("Found detect-engine.inspection-recursion-limit - %s:%s",
3210  insp_recursion_limit_node->name, insp_recursion_limit_node->val);
3211  break;
3212  }
3213 
3214  if (insp_recursion_limit != NULL) {
3216  0, (const char *)insp_recursion_limit) < 0) {
3217  SCLogWarning("Invalid value for "
3218  "detect-engine.inspection-recursion-limit: %s "
3219  "resetting to %d",
3220  insp_recursion_limit, DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT);
3223  }
3224  }
3225  }
3226  }
3227 
3230 
3231  SCLogDebug("de_ctx->inspection_recursion_limit: %d",
3233 
3234  // default value is 4
3236  if (SCConfGetInt("detect.stream-tx-log-limit", &value) == 1) {
3237  if (value >= 0 && value <= UINT8_MAX) {
3238  de_ctx->guess_applayer_log_limit = (uint8_t)value;
3239  } else {
3240  SCLogWarning("Invalid value for detect-engine.stream-tx-log-limit: must be between 0 "
3241  "and 255, will default to 4");
3242  }
3243  }
3244  int guess_applayer = 0;
3245  if ((SCConfGetBool("detect.guess-applayer-tx", &guess_applayer)) == 1) {
3246  if (guess_applayer == 1) {
3247  de_ctx->guess_applayer = true;
3248  }
3249  }
3250 
3251  /* parse port grouping priority settings */
3252 
3253  const char *ports = NULL;
3254  (void)SCConfGet("detect.grouping.tcp-priority-ports", &ports);
3255  if (ports) {
3256  SCLogConfig("grouping: tcp-priority-ports %s", ports);
3257  } else {
3258  (void)SCConfGet("detect.grouping.tcp-whitelist", &ports);
3259  if (ports) {
3260  SCLogConfig(
3261  "grouping: tcp-priority-ports from legacy 'tcp-whitelist' setting: %s", ports);
3262  } else {
3263  ports = "53, 80, 139, 443, 445, 1433, 3306, 3389, 6666, 6667, 8080";
3264  SCLogConfig("grouping: tcp-priority-ports (default) %s", ports);
3265  }
3266  }
3267  if (DetectPortParse(de_ctx, &de_ctx->tcp_priorityports, ports) != 0) {
3268  SCLogWarning("'%s' is not a valid value "
3269  "for detect.grouping.tcp-priority-ports",
3270  ports);
3271  }
3273  for ( ; x != NULL; x = x->next) {
3274  if (x->port != x->port2) {
3275  SCLogWarning("'%s' is not a valid value "
3276  "for detect.grouping.tcp-priority-ports: only single ports allowed",
3277  ports);
3279  de_ctx->tcp_priorityports = NULL;
3280  break;
3281  }
3282  }
3283 
3284  ports = NULL;
3285  (void)SCConfGet("detect.grouping.udp-priority-ports", &ports);
3286  if (ports) {
3287  SCLogConfig("grouping: udp-priority-ports %s", ports);
3288  } else {
3289  (void)SCConfGet("detect.grouping.udp-whitelist", &ports);
3290  if (ports) {
3291  SCLogConfig(
3292  "grouping: udp-priority-ports from legacy 'udp-whitelist' setting: %s", ports);
3293  } else {
3294  ports = "53, 135, 5060";
3295  SCLogConfig("grouping: udp-priority-ports (default) %s", ports);
3296  }
3297  }
3298  if (DetectPortParse(de_ctx, &de_ctx->udp_priorityports, ports) != 0) {
3299  SCLogWarning("'%s' is not a valid value "
3300  "for detect.grouping.udp-priority-ports",
3301  ports);
3302  }
3303  for (x = de_ctx->udp_priorityports; x != NULL; x = x->next) {
3304  if (x->port != x->port2) {
3305  SCLogWarning("'%s' is not a valid value "
3306  "for detect.grouping.udp-priority-ports: only single ports allowed",
3307  ports);
3309  de_ctx->udp_priorityports = NULL;
3310  break;
3311  }
3312  }
3313 
3314  DetectEngineLoadFlowbitSettings(de_ctx);
3315 
3317  const char *pf_setting = NULL;
3318  if (SCConfGet("detect.prefilter.default", &pf_setting) == 1 && pf_setting) {
3319  if (strcasecmp(pf_setting, "mpm") == 0) {
3321  } else if (strcasecmp(pf_setting, "auto") == 0) {
3323  }
3324  }
3325  switch (de_ctx->prefilter_setting) {
3326  case DETECT_PREFILTER_MPM:
3327  SCLogConfig("prefilter engines: MPM");
3328  break;
3329  case DETECT_PREFILTER_AUTO:
3330  SCLogConfig("prefilter engines: MPM and keywords");
3331  break;
3332  }
3333 
3334  return 0;
3335 }
3336 
3338 {
3339  de_ctx->signum = 0;
3340 }
3341 
3342 static int DetectEngineThreadCtxInitGlobalKeywords(DetectEngineThreadCtx *det_ctx)
3343 {
3344  const DetectEngineMasterCtx *master = &g_master_de_ctx;
3345 
3346  if (master->keyword_id > 0) {
3347  // coverity[suspicious_sizeof : FALSE]
3348  det_ctx->global_keyword_ctxs_array = (void **)SCCalloc(master->keyword_id, sizeof(void *));
3349  if (det_ctx->global_keyword_ctxs_array == NULL) {
3350  SCLogError("setting up thread local detect ctx");
3351  return TM_ECODE_FAILED;
3352  }
3353  det_ctx->global_keyword_ctxs_size = master->keyword_id;
3354 
3355  const DetectEngineThreadKeywordCtxItem *item = master->keyword_list;
3356  while (item) {
3357  det_ctx->global_keyword_ctxs_array[item->id] = item->InitFunc(item->data);
3358  if (det_ctx->global_keyword_ctxs_array[item->id] == NULL) {
3359  SCLogError("setting up thread local detect ctx "
3360  "for keyword \"%s\" failed",
3361  item->name);
3362  return TM_ECODE_FAILED;
3363  }
3364  item = item->next;
3365  }
3366  }
3367  return TM_ECODE_OK;
3368 }
3369 
3370 static void DetectEngineThreadCtxDeinitGlobalKeywords(DetectEngineThreadCtx *det_ctx)
3371 {
3372  if (det_ctx->global_keyword_ctxs_array == NULL ||
3373  det_ctx->global_keyword_ctxs_size == 0) {
3374  return;
3375  }
3376 
3377  const DetectEngineMasterCtx *master = &g_master_de_ctx;
3378  if (master->keyword_id > 0) {
3379  const DetectEngineThreadKeywordCtxItem *item = master->keyword_list;
3380  while (item) {
3381  if (det_ctx->global_keyword_ctxs_array[item->id] != NULL)
3382  item->FreeFunc(det_ctx->global_keyword_ctxs_array[item->id]);
3383 
3384  item = item->next;
3385  }
3386  det_ctx->global_keyword_ctxs_size = 0;
3388  det_ctx->global_keyword_ctxs_array = NULL;
3389  }
3390 }
3391 
3392 static int DetectEngineThreadCtxInitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
3393 {
3394  if (de_ctx->keyword_id > 0) {
3395  // coverity[suspicious_sizeof : FALSE]
3396  det_ctx->keyword_ctxs_array = SCCalloc(de_ctx->keyword_id, sizeof(void *));
3397  if (det_ctx->keyword_ctxs_array == NULL) {
3398  SCLogError("setting up thread local detect ctx");
3399  return TM_ECODE_FAILED;
3400  }
3401 
3402  det_ctx->keyword_ctxs_size = de_ctx->keyword_id;
3403 
3405  for (; hb != NULL; hb = HashListTableGetListNext(hb)) {
3407 
3408  det_ctx->keyword_ctxs_array[item->id] = item->InitFunc(item->data);
3409  if (det_ctx->keyword_ctxs_array[item->id] == NULL) {
3410  SCLogError("setting up thread local detect ctx "
3411  "for keyword \"%s\" failed",
3412  item->name);
3413  return TM_ECODE_FAILED;
3414  }
3415  }
3416  }
3417  return TM_ECODE_OK;
3418 }
3419 
3420 static void DetectEngineThreadCtxDeinitKeywords(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
3421 {
3422  if (de_ctx->keyword_id > 0) {
3424  for (; hb != NULL; hb = HashListTableGetListNext(hb)) {
3426 
3427  if (det_ctx->keyword_ctxs_array[item->id] != NULL)
3428  item->FreeFunc(det_ctx->keyword_ctxs_array[item->id]);
3429  }
3430  det_ctx->keyword_ctxs_size = 0;
3431  SCFree(det_ctx->keyword_ctxs_array);
3432  det_ctx->keyword_ctxs_array = NULL;
3433  }
3434 }
3435 
3436 /** NOTE: master MUST be locked before calling this */
3437 static TmEcode DetectEngineThreadCtxInitForMT(ThreadVars *tv, DetectEngineThreadCtx *det_ctx)
3438 {
3439  DetectEngineMasterCtx *master = &g_master_de_ctx;
3440 
3441  DetectEngineTenantMapping *map_array = NULL;
3442  uint32_t map_array_size = 0;
3443  uint32_t map_cnt = 0;
3444  uint32_t max_tenant_id = 0;
3445  DetectEngineCtx *list = master->list;
3446 
3448 
3449  /* coverity[missing_lock] */
3450  if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
3451  SCLogError("no tenant selector set: "
3452  "set using multi-detect.selector");
3453  return TM_ECODE_FAILED;
3454  }
3455 
3456  uint32_t tcnt = 0;
3457  while (list) {
3458  if (list->tenant_id > max_tenant_id)
3459  max_tenant_id = list->tenant_id;
3460 
3461  list = list->next;
3462  tcnt++;
3463  }
3464 
3465  HashTable *mt_det_ctxs_hash =
3466  HashTableInit(tcnt * 2, TenantIdHash, TenantIdCompare, TenantIdFree);
3467  if (mt_det_ctxs_hash == NULL) {
3468  goto error;
3469  }
3470 
3471  if (tcnt == 0) {
3472  SCLogInfo("no tenants left, or none registered yet");
3473  } else {
3474  max_tenant_id++;
3475 
3477  while (map) {
3478  map_cnt++;
3479  map = map->next;
3480  }
3481 
3482  if (map_cnt > 0) {
3483  map_array_size = map_cnt + 1;
3484 
3485  map_array = SCCalloc(map_array_size, sizeof(*map_array));
3486  if (map_array == NULL)
3487  goto error;
3488 
3489  /* fill the array */
3490  map_cnt = 0;
3491  map = master->tenant_mapping_list;
3492  while (map) {
3493  if (map_cnt >= map_array_size) {
3494  goto error;
3495  }
3496  map_array[map_cnt].traffic_id = map->traffic_id;
3497  map_array[map_cnt].tenant_id = map->tenant_id;
3498  map_cnt++;
3499  map = map->next;
3500  }
3501 
3502  }
3503 
3504  /* set up hash for tenant lookup */
3505  list = master->list;
3506  while (list) {
3507  SCLogDebug("tenant-id %u", list->tenant_id);
3508  if (list->tenant_id != 0) {
3510  if (mt_det_ctx == NULL)
3511  goto error;
3512  if (HashTableAdd(mt_det_ctxs_hash, mt_det_ctx, 0) != 0) {
3513  goto error;
3514  }
3515  }
3516  list = list->next;
3517  }
3518  }
3519 
3520  det_ctx->mt_det_ctxs_hash = mt_det_ctxs_hash;
3521  mt_det_ctxs_hash = NULL;
3522 
3523  det_ctx->mt_det_ctxs_cnt = max_tenant_id;
3524 
3525  det_ctx->tenant_array = map_array;
3526  det_ctx->tenant_array_size = map_array_size;
3527 
3528  switch (master->tenant_selector) {
3530  SCLogDebug("TENANT_SELECTOR_UNKNOWN");
3531  break;
3532  case TENANT_SELECTOR_VLAN:
3533  det_ctx->TenantGetId = DetectEngineTenantGetIdFromVlanId;
3534  SCLogDebug("TENANT_SELECTOR_VLAN");
3535  break;
3537  det_ctx->TenantGetId = DetectEngineTenantGetIdFromLivedev;
3538  SCLogDebug("TENANT_SELECTOR_LIVEDEV");
3539  break;
3541  det_ctx->TenantGetId = DetectEngineTenantGetIdFromPcap;
3542  SCLogDebug("TENANT_SELECTOR_DIRECT");
3543  break;
3544  }
3545 
3546  return TM_ECODE_OK;
3547 error:
3548  if (map_array != NULL)
3549  SCFree(map_array);
3550  if (mt_det_ctxs_hash != NULL)
3551  HashTableFree(mt_det_ctxs_hash);
3552 
3553  return TM_ECODE_FAILED;
3554 }
3555 
3556 /** \internal
3557  * \brief Helper for DetectThread setup functions
3558  */
3559 static TmEcode ThreadCtxDoInit (DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx)
3560 {
3561  PatternMatchThreadPrepare(&det_ctx->mtc, de_ctx);
3562 
3563  PmqSetup(&det_ctx->pmq);
3564 
3566  if (det_ctx->spm_thread_ctx == NULL) {
3567  return TM_ECODE_FAILED;
3568  }
3569 
3570  /* DeState */
3571  if (de_ctx->sig_array_len > 0) {
3572  det_ctx->match_array_len = de_ctx->sig_array_len;
3573  det_ctx->match_array = SCCalloc(det_ctx->match_array_len, sizeof(Signature *));
3574  if (det_ctx->match_array == NULL) {
3575  return TM_ECODE_FAILED;
3576  }
3577  det_ctx->replace = SCCalloc(de_ctx->sig_array_len, sizeof(Signature *));
3578  if (det_ctx->replace == NULL) {
3579  return TM_ECODE_FAILED;
3580  }
3581 
3583  }
3584 
3585  /* Alert processing queue */
3586  AlertQueueInit(det_ctx);
3587 
3588  /* byte_extract storage */
3589  det_ctx->byte_values = SCMalloc(sizeof(*det_ctx->byte_values) *
3591  if (det_ctx->byte_values == NULL) {
3592  return TM_ECODE_FAILED;
3593  }
3594 
3595  /* Allocate space for base64 decoded data. */
3598  if (det_ctx->base64_decoded == NULL) {
3599  return TM_ECODE_FAILED;
3600  }
3601  det_ctx->base64_decoded_len = 0;
3602  }
3603 
3605  det_ctx->inspect.buffers = SCCalloc(det_ctx->inspect.buffers_size, sizeof(InspectionBuffer));
3606  if (det_ctx->inspect.buffers == NULL) {
3607  return TM_ECODE_FAILED;
3608  }
3609  det_ctx->inspect.to_clear_queue = SCCalloc(det_ctx->inspect.buffers_size, sizeof(uint32_t));
3610  if (det_ctx->inspect.to_clear_queue == NULL) {
3611  return TM_ECODE_FAILED;
3612  }
3613  det_ctx->inspect.to_clear_idx = 0;
3614 
3617  if (det_ctx->multi_inspect.buffers == NULL) {
3618  return TM_ECODE_FAILED;
3619  }
3620  det_ctx->multi_inspect.to_clear_queue = SCCalloc(det_ctx->multi_inspect.buffers_size, sizeof(uint32_t));
3621  if (det_ctx->multi_inspect.to_clear_queue == NULL) {
3622  return TM_ECODE_FAILED;
3623  }
3624  det_ctx->multi_inspect.to_clear_idx = 0;
3625 
3626  if (DetectEngineThreadCtxInitKeywords(de_ctx, det_ctx) != TM_ECODE_OK)
3627  return TM_ECODE_FAILED;
3628  DetectEngineThreadCtxInitGlobalKeywords(det_ctx);
3629 #ifdef PROFILE_RULES
3630  SCProfilingRuleThreadSetup(de_ctx->profile_ctx, det_ctx);
3631 #endif
3632 #ifdef PROFILING
3636 #endif
3637  SC_ATOMIC_INIT(det_ctx->so_far_used_by_detect);
3638 
3639  if (ThresholdCacheThreadInit(det_ctx) != 0)
3640  return TM_ECODE_FAILED;
3641  return TM_ECODE_OK;
3642 }
3643 
3644 /** \brief initialize thread specific detection engine context
3645  *
3646  * \note there is a special case when using delayed detect. In this case the
3647  * function is called twice per thread. The first time the rules are not
3648  * yet loaded. de_ctx->delayed_detect_initialized will be 0. The 2nd
3649  * time they will be loaded. de_ctx->delayed_detect_initialized will be 1.
3650  * This is needed to do the per thread counter registration before the
3651  * packet runtime starts. In delayed detect mode, the first call will
3652  * return a NULL ptr through the data ptr.
3653  *
3654  * \param tv ThreadVars for this thread
3655  * \param initdata pointer to de_ctx
3656  * \param data[out] pointer to store our thread detection ctx
3657  *
3658  * \retval TM_ECODE_OK if all went well
3659  * \retval TM_ECODE_FAILED on serious errors
3660  */
3661 TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
3662 {
3663  DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(DetectEngineThreadCtx));
3664  if (unlikely(det_ctx == NULL))
3665  return TM_ECODE_FAILED;
3666 
3667  det_ctx->tv = tv;
3668  det_ctx->de_ctx = DetectEngineGetCurrent();
3669  if (det_ctx->de_ctx == NULL) {
3670 #ifdef UNITTESTS
3671  if (RunmodeIsUnittests()) {
3672  det_ctx->de_ctx = (DetectEngineCtx *)initdata;
3673  } else {
3674  DetectEngineThreadCtxDeinit(tv, det_ctx);
3675  return TM_ECODE_FAILED;
3676  }
3677 #else
3678  DetectEngineThreadCtxDeinit(tv, det_ctx);
3679  return TM_ECODE_FAILED;
3680 #endif
3681  }
3682 
3683  if (det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
3684  det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_TENANT)
3685  {
3686  if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
3687  DetectEngineThreadCtxDeinit(tv, det_ctx);
3688  return TM_ECODE_FAILED;
3689  }
3690  }
3691 
3692  /** alert counter setup */
3693  det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", &tv->stats);
3694  det_ctx->counter_alerts_overflow =
3695  StatsRegisterCounter("detect.alert_queue_overflow", &tv->stats);
3696  if (EngineModeIsFirewall()) {
3698  StatsRegisterCounter("firewall.discarded_alerts", &tv->stats);
3699  }
3700  det_ctx->counter_alerts_suppressed =
3701  StatsRegisterCounter("detect.alerts_suppressed", &tv->stats);
3702 
3703  /* Register counter for Lua rule errors. */
3704  det_ctx->lua_rule_errors = StatsRegisterCounter("detect.lua.errors", &tv->stats);
3705 
3706  /* Register a counter for Lua blocked function attempts. */
3707  det_ctx->lua_blocked_function_errors =
3708  StatsRegisterCounter("detect.lua.blocked_function_errors", &tv->stats);
3709 
3710  /* Register a counter for Lua instruction limit errors. */
3711  det_ctx->lua_instruction_limit_errors =
3712  StatsRegisterCounter("detect.lua.instruction_limit_errors", &tv->stats);
3713 
3714  /* Register a counter for Lua memory limit errors. */
3715  det_ctx->lua_memory_limit_errors =
3716  StatsRegisterCounter("detect.lua.memory_limit_errors", &tv->stats);
3717 
3718  det_ctx->json_content = NULL;
3719  det_ctx->json_content_capacity = 0;
3720  det_ctx->json_content_len = 0;
3721 
3722 #ifdef PROFILING
3723  det_ctx->counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", &tv->stats);
3724  det_ctx->counter_match_list = StatsRegisterAvgCounter("detect.match_list", &tv->stats);
3725 #endif
3726 
3728  DetectEngineMasterCtx *master = &g_master_de_ctx;
3729  SCMutexLock(&master->lock);
3730  if (DetectEngineThreadCtxInitForMT(tv, det_ctx) != TM_ECODE_OK) {
3731  DetectEngineThreadCtxDeinit(tv, det_ctx);
3732  SCMutexUnlock(&master->lock);
3733  return TM_ECODE_FAILED;
3734  }
3735  SCMutexUnlock(&master->lock);
3736  }
3737 
3738  /* pass thread data back to caller */
3739  *data = (void *)det_ctx;
3740 
3741  return TM_ECODE_OK;
3742 }
3743 
3744 /**
3745  * \internal
3746  * \brief initialize a det_ctx for reload cases
3747  * \param new_de_ctx the new detection engine
3748  * \param mt flag to indicate if MT should be set up for this det_ctx
3749  * this should only be done for the 'root' det_ctx
3750  *
3751  * \retval det_ctx detection engine thread ctx or NULL in case of error
3752  */
3754  ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
3755 {
3756  DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(DetectEngineThreadCtx));
3757  if (unlikely(det_ctx == NULL))
3758  return NULL;
3759 
3760  det_ctx->tenant_id = new_de_ctx->tenant_id;
3761  det_ctx->tv = tv;
3762  det_ctx->de_ctx = DetectEngineReference(new_de_ctx);
3763  if (det_ctx->de_ctx == NULL) {
3764  SCFree(det_ctx);
3765  return NULL;
3766  }
3767 
3768  /* most of the init happens here */
3769  if (det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
3770  det_ctx->de_ctx->type == DETECT_ENGINE_TYPE_TENANT)
3771  {
3772  if (ThreadCtxDoInit(det_ctx->de_ctx, det_ctx) != TM_ECODE_OK) {
3773  DetectEngineDeReference(&det_ctx->de_ctx);
3774  SCFree(det_ctx);
3775  return NULL;
3776  }
3777  }
3778 
3779  /** alert counter setup */
3780  det_ctx->counter_alerts = StatsRegisterCounter("detect.alert", &tv->stats);
3781  det_ctx->counter_alerts_overflow =
3782  StatsRegisterCounter("detect.alert_queue_overflow", &tv->stats);
3783  if (EngineModeIsFirewall()) {
3785  StatsRegisterCounter("firewall.discarded_alerts", &tv->stats);
3786  }
3787  det_ctx->counter_alerts_suppressed =
3788  StatsRegisterCounter("detect.alerts_suppressed", &tv->stats);
3789 #ifdef PROFILING
3790  det_ctx->counter_mpm_list = StatsRegisterAvgCounter("detect.mpm_list", &tv->stats);
3791  det_ctx->counter_match_list = StatsRegisterAvgCounter("detect.match_list", &tv->stats);
3792 #endif
3793 
3794  if (mt && DetectEngineMultiTenantEnabledWithLock()) {
3795  if (DetectEngineThreadCtxInitForMT(tv, det_ctx) != TM_ECODE_OK) {
3796  DetectEngineDeReference(&det_ctx->de_ctx);
3797  SCFree(det_ctx);
3798  return NULL;
3799  }
3800  }
3801 
3802  return det_ctx;
3803 }
3804 
3805 static void DetectEngineThreadCtxFree(DetectEngineThreadCtx *det_ctx)
3806 {
3807 #if DEBUG
3808  SCLogDebug("PACKET PKT_STREAM_ADD: %"PRIu64, det_ctx->pkt_stream_add_cnt);
3809 
3810  SCLogDebug("PAYLOAD MPM %"PRIu64"/%"PRIu64, det_ctx->payload_mpm_cnt, det_ctx->payload_mpm_size);
3811  SCLogDebug("STREAM MPM %"PRIu64"/%"PRIu64, det_ctx->stream_mpm_cnt, det_ctx->stream_mpm_size);
3812 
3813  SCLogDebug("PAYLOAD SIG %"PRIu64"/%"PRIu64, det_ctx->payload_persig_cnt, det_ctx->payload_persig_size);
3814  SCLogDebug("STREAM SIG %"PRIu64"/%"PRIu64, det_ctx->stream_persig_cnt, det_ctx->stream_persig_size);
3815 #endif
3816 
3817  if (det_ctx->tenant_array != NULL) {
3818  SCFree(det_ctx->tenant_array);
3819  det_ctx->tenant_array = NULL;
3820  }
3821 
3822 #ifdef PROFILE_RULES
3823  SCProfilingRuleThreadCleanup(det_ctx);
3824 #endif
3825 #ifdef PROFILING
3828  SCProfilingSghThreadCleanup(det_ctx);
3829 #endif
3830 
3831  /** \todo get rid of this static */
3832  if (det_ctx->de_ctx != NULL) {
3833  PatternMatchThreadDestroy(&det_ctx->mtc, det_ctx->de_ctx->mpm_matcher);
3834  }
3835 
3836  PmqFree(&det_ctx->pmq);
3837 
3838  if (det_ctx->spm_thread_ctx != NULL) {
3840  }
3841  if (det_ctx->match_array != NULL)
3842  SCFree(det_ctx->match_array);
3843  if (det_ctx->replace != NULL)
3844  SCFree(det_ctx->replace);
3845 
3847 
3848  AlertQueueFree(det_ctx);
3849 
3850  if (det_ctx->post_rule_work_queue.q)
3851  SCFree(det_ctx->post_rule_work_queue.q);
3852 
3853  if (det_ctx->byte_values != NULL)
3854  SCFree(det_ctx->byte_values);
3855 
3856  /* Decoded base64 data. */
3857  if (det_ctx->base64_decoded != NULL) {
3858  SCFree(det_ctx->base64_decoded);
3859  }
3860 
3861  if (det_ctx->inspect.buffers) {
3862  for (uint32_t i = 0; i < det_ctx->inspect.buffers_size; i++) {
3863  InspectionBufferFree(&det_ctx->inspect.buffers[i]);
3864  }
3865  SCFree(det_ctx->inspect.buffers);
3866  }
3867  if (det_ctx->inspect.to_clear_queue) {
3868  SCFree(det_ctx->inspect.to_clear_queue);
3869  }
3870  if (det_ctx->multi_inspect.buffers) {
3871  for (uint32_t i = 0; i < det_ctx->multi_inspect.buffers_size; i++) {
3873  for (uint32_t x = 0; x < fb->size; x++) {
3875  }
3877  }
3878  SCFree(det_ctx->multi_inspect.buffers);
3879  }
3880  if (det_ctx->multi_inspect.to_clear_queue) {
3882  }
3883 
3884  DetectEngineThreadCtxDeinitGlobalKeywords(det_ctx);
3885  if (det_ctx->de_ctx != NULL) {
3886  DetectEngineThreadCtxDeinitKeywords(det_ctx->de_ctx, det_ctx);
3887 #ifdef UNITTESTS
3888  if (!RunmodeIsUnittests() || det_ctx->de_ctx->ref_cnt > 0)
3889  DetectEngineDeReference(&det_ctx->de_ctx);
3890 #else
3891  DetectEngineDeReference(&det_ctx->de_ctx);
3892 #endif
3893  }
3894 
3895  if (det_ctx->json_content) {
3896  SCFree(det_ctx->json_content);
3897  det_ctx->json_content = NULL;
3898  det_ctx->json_content_capacity = 0;
3899  }
3900 
3903  SCFree(det_ctx);
3904 }
3905 
3907 {
3908  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
3909 
3910  if (det_ctx == NULL) {
3911  SCLogWarning("argument \"data\" NULL");
3912  return TM_ECODE_OK;
3913  }
3914 
3915  if (det_ctx->mt_det_ctxs_hash != NULL) {
3916  HashTableFree(det_ctx->mt_det_ctxs_hash);
3917  det_ctx->mt_det_ctxs_hash = NULL;
3918  }
3919  DetectEngineThreadCtxFree(det_ctx);
3920 
3921  return TM_ECODE_OK;
3922 }
3923 
3924 static uint32_t DetectKeywordCtxHashFunc(HashListTable *ht, void *data, uint16_t datalen)
3925 {
3927  const char *name = ctx->name;
3928  uint64_t hash =
3929  StringHashDjb2((const uint8_t *)name, (uint32_t)strlen(name)) + (ptrdiff_t)ctx->data;
3930  hash %= ht->array_size;
3931  return (uint32_t)hash;
3932 }
3933 
3934 static char DetectKeywordCtxCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
3935 {
3936  DetectEngineThreadKeywordCtxItem *ctx1 = data1;
3937  DetectEngineThreadKeywordCtxItem *ctx2 = data2;
3938  const char *name1 = ctx1->name;
3939  const char *name2 = ctx2->name;
3940  return (strcmp(name1, name2) == 0 && ctx1->data == ctx2->data);
3941 }
3942 
3943 static void DetectKeywordCtxFreeFunc(void *ptr)
3944 {
3945  SCFree(ptr);
3946 }
3947 
3948 /** \brief Register Thread keyword context Funcs
3949  *
3950  * \param de_ctx detection engine to register in
3951  * \param name keyword name for error printing
3952  * \param InitFunc function ptr
3953  * \param data keyword init data to pass to Func. Can be NULL.
3954  * \param FreeFunc function ptr
3955  * \param mode 0 normal (ctx per keyword instance) 1 shared (one ctx per det_ct)
3956  *
3957  * \retval id for retrieval of ctx at runtime
3958  * \retval -1 on error
3959  *
3960  * \note make sure "data" remains valid and it free'd elsewhere. It's
3961  * recommended to store it in the keywords global ctx so that
3962  * it's freed when the de_ctx is freed.
3963  */
3964 int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *), int mode)
3965 {
3966  BUG_ON(de_ctx == NULL || InitFunc == NULL || FreeFunc == NULL);
3967 
3968  if (de_ctx->keyword_hash == NULL) {
3969  de_ctx->keyword_hash = HashListTableInit(4096, // TODO
3970  DetectKeywordCtxHashFunc, DetectKeywordCtxCompareFunc, DetectKeywordCtxFreeFunc);
3971  BUG_ON(de_ctx->keyword_hash == NULL);
3972  }
3973 
3974  if (mode) {
3975  DetectEngineThreadKeywordCtxItem search = { .data = data, .name = name };
3976 
3978  HashListTableLookup(de_ctx->keyword_hash, (void *)&search, 0);
3979  if (item)
3980  return item->id;
3981 
3982  /* fall through */
3983  }
3984 
3986  if (unlikely(item == NULL))
3987  return -1;
3988 
3989  item->InitFunc = InitFunc;
3990  item->FreeFunc = FreeFunc;
3991  item->data = data;
3992  item->name = name;
3993  item->id = de_ctx->keyword_id++;
3994 
3995  if (HashListTableAdd(de_ctx->keyword_hash, (void *)item, 0) < 0) {
3996  SCFree(item);
3997  return -1;
3998  }
3999  return item->id;
4000 }
4001 
4002 /** \brief Remove Thread keyword context registration
4003  *
4004  * \param de_ctx detection engine to deregister from
4005  * \param det_ctx detection engine thread context to deregister from
4006  * \param data keyword init data to pass to Func. Can be NULL.
4007  * \param name keyword name for error printing
4008  *
4009  * \retval 1 Item unregistered
4010  * \retval 0 otherwise
4011  *
4012  * \note make sure "data" remains valid and it free'd elsewhere. It's
4013  * recommended to store it in the keywords global ctx so that
4014  * it's freed when the de_ctx is freed.
4015  */
4017 {
4018  /* might happen if we call this before a call to *Register* */
4019  if (de_ctx->keyword_hash == NULL)
4020  return 1;
4021  DetectEngineThreadKeywordCtxItem remove = { .data = data, .name = name };
4022  if (HashListTableRemove(de_ctx->keyword_hash, (void *)&remove, 0) == 0)
4023  return 1;
4024  return 0;
4025 }
4026 /** \brief Retrieve thread local keyword ctx by id
4027  *
4028  * \param det_ctx detection engine thread ctx to retrieve the ctx from
4029  * \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
4030  * keyword init.
4031  *
4032  * \retval ctx or NULL on error
4033  */
4035 {
4036  if (id < 0 || id > det_ctx->keyword_ctxs_size || det_ctx->keyword_ctxs_array == NULL)
4037  return NULL;
4038 
4039  return det_ctx->keyword_ctxs_array[id];
4040 }
4041 
4042 
4043 /** \brief Register Thread keyword context Funcs (Global)
4044  *
4045  * IDs stay static over reloads and between tenants
4046  *
4047  * \param name keyword name for error printing
4048  * \param InitFunc function ptr
4049  * \param FreeFunc function ptr
4050  *
4051  * \retval id for retrieval of ctx at runtime
4052  * \retval -1 on error
4053  */
4055  const char *name, void *(*InitFunc)(void *), void *data, void (*FreeFunc)(void *))
4056 {
4057  int id;
4058  BUG_ON(InitFunc == NULL || FreeFunc == NULL);
4059 
4060  DetectEngineMasterCtx *master = &g_master_de_ctx;
4061 
4062  /* if already registered, return existing id */
4064  while (item != NULL) {
4065  if (strcmp(name, item->name) == 0) {
4066  id = item->id;
4067  return id;
4068  }
4069 
4070  item = item->next;
4071  }
4072 
4073  item = SCCalloc(1, sizeof(*item));
4074  if (unlikely(item == NULL)) {
4075  return -1;
4076  }
4077  item->InitFunc = InitFunc;
4078  item->FreeFunc = FreeFunc;
4079  item->name = name;
4080  item->data = data;
4081 
4082  item->next = master->keyword_list;
4083  master->keyword_list = item;
4084  item->id = master->keyword_id++;
4085 
4086  id = item->id;
4087  return id;
4088 }
4089 
4090 /** \brief Retrieve thread local keyword ctx by id
4091  *
4092  * \param det_ctx detection engine thread ctx to retrieve the ctx from
4093  * \param id id of the ctx returned by DetectRegisterThreadCtxInitFunc at
4094  * keyword init.
4095  *
4096  * \retval ctx or NULL on error
4097  */
4099 {
4100  if (id < 0 || id > det_ctx->global_keyword_ctxs_size ||
4101  det_ctx->global_keyword_ctxs_array == NULL) {
4102  return NULL;
4103  }
4104 
4105  return det_ctx->global_keyword_ctxs_array[id];
4106 }
4107 
4108 /** \brief Check if detection is enabled
4109  * \retval bool true or false */
4111 {
4112  DetectEngineMasterCtx *master = &g_master_de_ctx;
4113  SCMutexLock(&master->lock);
4114 
4115  if (master->list == NULL) {
4116  SCMutexUnlock(&master->lock);
4117  return 0;
4118  }
4119 
4120  SCMutexUnlock(&master->lock);
4121  return 1;
4122 }
4123 
4125 {
4126  uint32_t version;
4127  DetectEngineMasterCtx *master = &g_master_de_ctx;
4128  SCMutexLock(&master->lock);
4129  version = master->version;
4130  SCMutexUnlock(&master->lock);
4131  return version;
4132 }
4133 
4135 {
4136  DetectEngineMasterCtx *master = &g_master_de_ctx;
4137  SCMutexLock(&master->lock);
4138  master->version++;
4139  SCLogDebug("master version now %u", master->version);
4140  SCMutexUnlock(&master->lock);
4141 }
4142 
4144 {
4145  DetectEngineMasterCtx *master = &g_master_de_ctx;
4146  SCMutexLock(&master->lock);
4147 
4148  DetectEngineCtx *de_ctx = master->list;
4149  while (de_ctx) {
4153  {
4154  de_ctx->ref_cnt++;
4155  SCLogDebug("de_ctx %p ref_cnt %u", de_ctx, de_ctx->ref_cnt);
4156  SCMutexUnlock(&master->lock);
4157  return de_ctx;
4158  }
4159  de_ctx = de_ctx->next;
4160  }
4161 
4162  SCMutexUnlock(&master->lock);
4163  return NULL;
4164 }
4165 
4167 {
4168  if (de_ctx == NULL)
4169  return NULL;
4170  de_ctx->ref_cnt++;
4171  return de_ctx;
4172 }
4173 
4174 static bool DetectEngineMultiTenantEnabledWithLock(void)
4175 {
4176  DetectEngineMasterCtx *master = &g_master_de_ctx;
4177  return master->multi_tenant_enabled;
4178 }
4179 
4181 {
4182  DetectEngineMasterCtx *master = &g_master_de_ctx;
4183  SCMutexLock(&master->lock);
4184  bool enabled = DetectEngineMultiTenantEnabledWithLock();
4185  SCMutexUnlock(&master->lock);
4186  return enabled;
4187 }
4188 
4189 /** \internal
4190  * \brief load a tenant from a yaml file
4191  *
4192  * \param tenant_id the tenant id by which the config is known
4193  * \param filename full path of a yaml file
4194  * \param loader_id id of loader thread or -1
4195  *
4196  * \retval 0 ok
4197  * \retval -1 failed
4198  */
4199 static int DetectEngineMultiTenantLoadTenant(uint32_t tenant_id, const char *filename, int loader_id)
4200 {
4201  DetectEngineCtx *de_ctx = NULL;
4202  char prefix[64];
4203 
4204  snprintf(prefix, sizeof(prefix), "multi-detect.%u", tenant_id);
4205 
4206  SCStat st;
4207  if (SCStatFn(filename, &st) != 0) {
4208  SCLogError("failed to stat file %s", filename);
4209  goto error;
4210  }
4211 
4212  de_ctx = DetectEngineGetByTenantId(tenant_id);
4213  if (de_ctx != NULL) {
4214  SCLogError("tenant %u already registered", tenant_id);
4216  goto error;
4217  }
4218 
4219  SCConfNode *node = SCConfGetNode(prefix);
4220  if (node == NULL) {
4221  SCLogError("failed to properly setup yaml %s", filename);
4222  goto error;
4223  }
4224 
4225  de_ctx = DetectEngineCtxInitWithPrefix(prefix, tenant_id);
4226  if (de_ctx == NULL) {
4227  SCLogError("initializing detection engine "
4228  "context failed.");
4229  goto error;
4230  }
4231  SCLogDebug("de_ctx %p with prefix %s", de_ctx, de_ctx->config_prefix);
4232 
4234  de_ctx->tenant_id = tenant_id;
4235  de_ctx->loader_id = loader_id;
4236  de_ctx->tenant_path = SCStrdup(filename);
4237  if (de_ctx->tenant_path == NULL) {
4238  SCLogError("Failed to duplicate path");
4239  goto error;
4240  }
4241 
4242  if (SigLoadSignatures(de_ctx, NULL, false) < 0) {
4243  SCLogError("Loading signatures failed.");
4244  goto error;
4245  }
4247 
4248  return 0;
4249 
4250 error:
4251  if (de_ctx != NULL) {
4253  }
4254  return -1;
4255 }
4256 
4257 static int DetectEngineMultiTenantReloadTenant(uint32_t tenant_id, const char *filename, int reload_cnt)
4258 {
4259  DetectEngineCtx *old_de_ctx = DetectEngineGetByTenantId(tenant_id);
4260  if (old_de_ctx == NULL) {
4261  SCLogError("tenant detect engine not found");
4262  return -1;
4263  }
4264 
4265  if (filename == NULL)
4266  filename = old_de_ctx->tenant_path;
4267 
4268  char prefix[64];
4269  snprintf(prefix, sizeof(prefix), "multi-detect.%u.reload.%d", tenant_id, reload_cnt);
4270  reload_cnt++;
4271  SCLogDebug("prefix %s", prefix);
4272 
4273  if (SCConfYamlLoadFileWithPrefix(filename, prefix) != 0) {
4274  SCLogError("failed to load yaml");
4275  goto error;
4276  }
4277 
4278  SCConfNode *node = SCConfGetNode(prefix);
4279  if (node == NULL) {
4280  SCLogError("failed to properly setup yaml %s", filename);
4281  goto error;
4282  }
4283 
4284  DetectEngineCtx *new_de_ctx = DetectEngineCtxInitWithPrefix(prefix, tenant_id);
4285  if (new_de_ctx == NULL) {
4286  SCLogError("initializing detection engine "
4287  "context failed.");
4288  goto error;
4289  }
4290  SCLogDebug("de_ctx %p with prefix %s", new_de_ctx, new_de_ctx->config_prefix);
4291 
4292  new_de_ctx->type = DETECT_ENGINE_TYPE_TENANT;
4293  new_de_ctx->tenant_id = tenant_id;
4294  new_de_ctx->loader_id = old_de_ctx->loader_id;
4295  new_de_ctx->tenant_path = SCStrdup(filename);
4296  if (new_de_ctx->tenant_path == NULL) {
4297  SCLogError("Failed to duplicate path");
4298  goto new_de_ctx_error;
4299  }
4300 
4301  if (SigLoadSignatures(new_de_ctx, NULL, false) < 0) {
4302  SCLogError("Loading signatures failed.");
4303  goto new_de_ctx_error;
4304  }
4305 
4306  DetectEngineAddToMaster(new_de_ctx);
4307 
4308  /* move to free list */
4309  DetectEngineMoveToFreeList(old_de_ctx);
4310  DetectEngineDeReference(&old_de_ctx);
4311  return 0;
4312 
4313 new_de_ctx_error:
4314  DetectEngineCtxFree(new_de_ctx);
4315 
4316 error:
4317  DetectEngineDeReference(&old_de_ctx);
4318  return -1;
4319 }
4320 
4321 
4322 typedef struct TenantLoaderCtx_ {
4323  uint32_t tenant_id;
4324  int reload_cnt; /**< used by reload */
4325  char *yaml; /**< heap alloc'd copy of file path for the yaml */
4327 
4328 static void DetectLoaderFreeTenant(void *ctx)
4329 {
4331  if (t->yaml != NULL) {
4332  SCFree(t->yaml);
4333  }
4334  SCFree(t);
4335 }
4336 
4337 static int DetectLoaderFuncLoadTenant(void *vctx, int loader_id)
4338 {
4339  TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx;
4340 
4341  SCLogDebug("loader %d", loader_id);
4342  if (DetectEngineMultiTenantLoadTenant(ctx->tenant_id, ctx->yaml, loader_id) != 0) {
4343  return -1;
4344  }
4345  return 0;
4346 }
4347 
4348 static int DetectLoaderSetupLoadTenant(uint32_t tenant_id, const char *yaml)
4349 {
4350  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
4351  if (t == NULL)
4352  return -ENOMEM;
4353 
4354  t->tenant_id = tenant_id;
4355  t->yaml = SCStrdup(yaml);
4356  if (t->yaml == NULL) {
4357  SCFree(t);
4358  return -ENOMEM;
4359  }
4360 
4361  return DetectLoaderQueueTask(-1, DetectLoaderFuncLoadTenant, t, DetectLoaderFreeTenant);
4362 }
4363 
4364 static int DetectLoaderFuncReloadTenant(void *vctx, int loader_id)
4365 {
4366  TenantLoaderCtx *ctx = (TenantLoaderCtx *)vctx;
4367 
4368  SCLogDebug("loader_id %d", loader_id);
4369 
4370  if (DetectEngineMultiTenantReloadTenant(ctx->tenant_id, ctx->yaml, ctx->reload_cnt) != 0) {
4371  return -1;
4372  }
4373  return 0;
4374 }
4375 
4376 static int DetectLoaderSetupReloadTenants(const int reload_cnt)
4377 {
4378  int ret = 0;
4379  DetectEngineMasterCtx *master = &g_master_de_ctx;
4380  SCMutexLock(&master->lock);
4381 
4382  DetectEngineCtx *de_ctx = master->list;
4383  while (de_ctx) {
4385  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
4386  if (t == NULL) {
4387  ret = -1;
4388  goto error;
4389  }
4390  t->tenant_id = de_ctx->tenant_id;
4391  t->reload_cnt = reload_cnt;
4392  int loader_id = de_ctx->loader_id;
4393 
4394  int r = DetectLoaderQueueTask(
4395  loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant);
4396  if (r < 0) {
4397  ret = -2;
4398  goto error;
4399  }
4400  }
4401 
4402  de_ctx = de_ctx->next;
4403  }
4404 error:
4405  SCMutexUnlock(&master->lock);
4406  return ret;
4407 }
4408 
4409 static int DetectLoaderSetupReloadTenant(uint32_t tenant_id, const char *yaml, int reload_cnt)
4410 {
4411  DetectEngineCtx *old_de_ctx = DetectEngineGetByTenantId(tenant_id);
4412  if (old_de_ctx == NULL)
4413  return -ENOENT;
4414  int loader_id = old_de_ctx->loader_id;
4415  DetectEngineDeReference(&old_de_ctx);
4416 
4417  TenantLoaderCtx *t = SCCalloc(1, sizeof(*t));
4418  if (t == NULL)
4419  return -ENOMEM;
4420 
4421  t->tenant_id = tenant_id;
4422  if (yaml != NULL) {
4423  t->yaml = SCStrdup(yaml);
4424  if (t->yaml == NULL) {
4425  SCFree(t);
4426  return -ENOMEM;
4427  }
4428  }
4429  t->reload_cnt = reload_cnt;
4430 
4431  SCLogDebug("loader_id %d", loader_id);
4432 
4433  return DetectLoaderQueueTask(
4434  loader_id, DetectLoaderFuncReloadTenant, t, DetectLoaderFreeTenant);
4435 }
4436 
4437 /** \brief Load a tenant and wait for loading to complete
4438  */
4439 int DetectEngineLoadTenantBlocking(uint32_t tenant_id, const char *yaml)
4440 {
4441  int r = DetectLoaderSetupLoadTenant(tenant_id, yaml);
4442  if (r < 0)
4443  return r;
4444 
4445  if (DetectLoadersSync() != 0)
4446  return -1;
4447 
4448  return 0;
4449 }
4450 
4451 /** \brief Reload a tenant and wait for loading to complete
4452  */
4453 int DetectEngineReloadTenantBlocking(uint32_t tenant_id, const char *yaml, int reload_cnt)
4454 {
4455  int r = DetectLoaderSetupReloadTenant(tenant_id, yaml, reload_cnt);
4456  if (r < 0)
4457  return r;
4458 
4459  if (DetectLoadersSync() != 0)
4460  return -1;
4461 
4462  return 0;
4463 }
4464 
4465 /** \brief Reload all tenants and wait for loading to complete
4466  */
4467 int DetectEngineReloadTenantsBlocking(const int reload_cnt)
4468 {
4469  int r = DetectLoaderSetupReloadTenants(reload_cnt);
4470  if (r < 0)
4471  return r;
4472 
4473  if (DetectLoadersSync() != 0)
4474  return -1;
4475 
4476  return 0;
4477 }
4478 
4479 static int DetectEngineMultiTenantSetupLoadLivedevMappings(
4480  const SCConfNode *mappings_root_node, bool failure_fatal)
4481 {
4482  SCConfNode *mapping_node = NULL;
4483 
4484  int mapping_cnt = 0;
4485  if (mappings_root_node != NULL) {
4486  TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
4487  SCConfNode *tenant_id_node = SCConfNodeLookupChild(mapping_node, "tenant-id");
4488  if (tenant_id_node == NULL)
4489  goto bad_mapping;
4490  SCConfNode *device_node = SCConfNodeLookupChild(mapping_node, "device");
4491  if (device_node == NULL)
4492  goto bad_mapping;
4493 
4494  uint32_t tenant_id = 0;
4495  if (StringParseUint32(&tenant_id, 10, (uint16_t)strlen(tenant_id_node->val),
4496  tenant_id_node->val) < 0) {
4497  SCLogError("tenant-id "
4498  "of %s is invalid",
4499  tenant_id_node->val);
4500  goto bad_mapping;
4501  }
4502 
4503  const char *dev = device_node->val;
4504  LiveDevice *ld = LiveGetDevice(dev);
4505  if (ld == NULL) {
4506  SCLogWarning("device %s not found", dev);
4507  goto bad_mapping;
4508  }
4509 
4510  if (ld->tenant_id_set) {
4511  SCLogWarning("device %s already mapped to tenant-id %u", dev, ld->tenant_id);
4512  goto bad_mapping;
4513  }
4514 
4515  ld->tenant_id = tenant_id;
4516  ld->tenant_id_set = true;
4517 
4518  if (DetectEngineTenantRegisterLivedev(tenant_id, ld->id) != 0) {
4519  goto error;
4520  }
4521 
4522  SCLogConfig("device %s connected to tenant-id %u", dev, tenant_id);
4523  mapping_cnt++;
4524  continue;
4525 
4526  bad_mapping:
4527  if (failure_fatal)
4528  goto error;
4529  }
4530  }
4531  SCLogConfig("%d device - tenant-id mappings defined", mapping_cnt);
4532  return mapping_cnt;
4533 
4534 error:
4535  return 0;
4536 }
4537 
4538 static int DetectEngineMultiTenantSetupLoadVlanMappings(
4539  const SCConfNode *mappings_root_node, bool failure_fatal)
4540 {
4541  SCConfNode *mapping_node = NULL;
4542 
4543  int mapping_cnt = 0;
4544  if (mappings_root_node != NULL) {
4545  TAILQ_FOREACH(mapping_node, &mappings_root_node->head, next) {
4546  SCConfNode *tenant_id_node = SCConfNodeLookupChild(mapping_node, "tenant-id");
4547  if (tenant_id_node == NULL)
4548  goto bad_mapping;
4549  SCConfNode *vlan_id_node = SCConfNodeLookupChild(mapping_node, "vlan-id");
4550  if (vlan_id_node == NULL)
4551  goto bad_mapping;
4552 
4553  uint32_t tenant_id = 0;
4554  if (StringParseUint32(&tenant_id, 10, (uint16_t)strlen(tenant_id_node->val),
4555  tenant_id_node->val) < 0) {
4556  SCLogError("tenant-id "
4557  "of %s is invalid",
4558  tenant_id_node->val);
4559  goto bad_mapping;
4560  }
4561 
4562  uint16_t vlan_id = 0;
4563  if (StringParseUint16(
4564  &vlan_id, 10, (uint16_t)strlen(vlan_id_node->val), vlan_id_node->val) < 0) {
4565  SCLogError("vlan-id "
4566  "of %s is invalid",
4567  vlan_id_node->val);
4568  goto bad_mapping;
4569  }
4570  if (vlan_id == 0 || vlan_id >= 4095) {
4571  SCLogError("vlan-id "
4572  "of %s is invalid. Valid range 1-4094.",
4573  vlan_id_node->val);
4574  goto bad_mapping;
4575  }
4576 
4577  if (DetectEngineTenantRegisterVlanId(tenant_id, vlan_id) != 0) {
4578  goto error;
4579  }
4580  SCLogConfig("vlan %u connected to tenant-id %u", vlan_id, tenant_id);
4581  mapping_cnt++;
4582  continue;
4583 
4584  bad_mapping:
4585  if (failure_fatal)
4586  goto error;
4587  }
4588  }
4589  return mapping_cnt;
4590 
4591 error:
4592  return 0;
4593 }
4594 
4595 /**
4596  * \brief setup multi-detect / multi-tenancy
4597  *
4598  * See if MT is enabled. If so, setup the selector, tenants and mappings.
4599  * Tenants and mappings are optional, and can also dynamically be added
4600  * and removed from the unix socket.
4601  */
4602 int DetectEngineMultiTenantSetup(const bool unix_socket)
4603 {
4605  DetectEngineMasterCtx *master = &g_master_de_ctx;
4606  int failure_fatal = 0;
4607  (void)SCConfGetBool("engine.init-failure-fatal", &failure_fatal);
4608 
4609  int enabled = 0;
4610  (void)SCConfGetBool("multi-detect.enabled", &enabled);
4611  if (enabled == 1) {
4616 
4617  SCMutexLock(&master->lock);
4618  master->multi_tenant_enabled = 1;
4619 
4620  const char *handler = NULL;
4621  if (SCConfGetNonNull("multi-detect.selector", &handler) == 1) {
4622  SCLogConfig("multi-tenant selector type %s", handler);
4623 
4624  if (strcmp(handler, "vlan") == 0) {
4625  tenant_selector = master->tenant_selector = TENANT_SELECTOR_VLAN;
4626 
4627  int vlanbool = 0;
4628  if ((SCConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
4629  SCLogError("vlan tracking is disabled, "
4630  "can't use multi-detect selector 'vlan'");
4631  SCMutexUnlock(&master->lock);
4632  goto error;
4633  }
4634 
4635  } else if (strcmp(handler, "direct") == 0) {
4636  tenant_selector = master->tenant_selector = TENANT_SELECTOR_DIRECT;
4637  } else if (strcmp(handler, "device") == 0) {
4638  tenant_selector = master->tenant_selector = TENANT_SELECTOR_LIVEDEV;
4639  if (EngineModeIsIPS()) {
4640  SCLogWarning("multi-tenant 'device' mode not supported for IPS");
4641  SCMutexUnlock(&master->lock);
4642  goto error;
4643  }
4644 
4645  } else {
4646  SCLogError("unknown value %s "
4647  "multi-detect.selector",
4648  handler);
4649  SCMutexUnlock(&master->lock);
4650  goto error;
4651  }
4652  }
4653  SCMutexUnlock(&master->lock);
4654  SCLogConfig("multi-detect is enabled (multi tenancy). Selector: %s", handler);
4655 
4656  /* traffic -- tenant mappings */
4657  SCConfNode *mappings_root_node = SCConfGetNode("multi-detect.mappings");
4658 
4659  if (tenant_selector == TENANT_SELECTOR_VLAN) {
4660  int mapping_cnt = DetectEngineMultiTenantSetupLoadVlanMappings(mappings_root_node,
4661  failure_fatal);
4662  if (mapping_cnt == 0) {
4663  /* no mappings are valid when we're in unix socket mode,
4664  * they can be added on the fly. Otherwise warn/error
4665  * depending on failure_fatal */
4666 
4667  if (unix_socket) {
4668  SCLogNotice("no tenant traffic mappings defined, "
4669  "tenants won't be used until mappings are added");
4670  } else {
4671  if (failure_fatal) {
4672  SCLogError("no multi-detect mappings defined");
4673  goto error;
4674  } else {
4675  SCLogWarning("no multi-detect mappings defined");
4676  }
4677  }
4678  }
4679  } else if (tenant_selector == TENANT_SELECTOR_LIVEDEV) {
4680  int mapping_cnt = DetectEngineMultiTenantSetupLoadLivedevMappings(mappings_root_node,
4681  failure_fatal);
4682  if (mapping_cnt == 0) {
4683  if (failure_fatal) {
4684  SCLogError("no multi-detect mappings defined");
4685  goto error;
4686  } else {
4687  SCLogWarning("no multi-detect mappings defined");
4688  }
4689  }
4690  }
4691 
4692  /* tenants */
4693  SCConfNode *tenants_root_node = SCConfGetNode("multi-detect.tenants");
4694  SCConfNode *tenant_node = NULL;
4695 
4696  if (tenants_root_node != NULL) {
4697  const char *path = NULL;
4698  SCConfNode *path_node = SCConfGetNode("multi-detect.config-path");
4699  if (path_node) {
4700  path = path_node->val;
4701  SCLogConfig("tenants config path: %s", path);
4702  }
4703 
4704  TAILQ_FOREACH(tenant_node, &tenants_root_node->head, next) {
4705  SCConfNode *id_node = SCConfNodeLookupChild(tenant_node, "id");
4706  if (id_node == NULL) {
4707  goto bad_tenant;
4708  }
4709  SCConfNode *yaml_node = SCConfNodeLookupChild(tenant_node, "yaml");
4710  if (yaml_node == NULL) {
4711  goto bad_tenant;
4712  }
4713 
4714  uint32_t tenant_id = 0;
4715  if (StringParseUint32(
4716  &tenant_id, 10, (uint16_t)strlen(id_node->val), id_node->val) < 0) {
4717  SCLogError("tenant_id "
4718  "of %s is invalid",
4719  id_node->val);
4720  goto bad_tenant;
4721  }
4722  SCLogDebug("tenant id: %u, %s", tenant_id, yaml_node->val);
4723 
4724  char yaml_path[PATH_MAX] = "";
4725  if (path) {
4726  if (PathMerge(yaml_path, PATH_MAX, path, yaml_node->val) < 0)
4727  goto bad_tenant;
4728  } else {
4729  size_t r = strlcpy(yaml_path, yaml_node->val, sizeof(yaml_path));
4730  if (r >= sizeof(yaml_path))
4731  goto bad_tenant;
4732  }
4733  SCLogDebug("tenant path: %s", yaml_path);
4734 
4735  /* setup the yaml in this loop so that it's not done by the loader
4736  * threads. SCConfYamlLoadFileWithPrefix is not thread safe. */
4737  char prefix[64];
4738  snprintf(prefix, sizeof(prefix), "multi-detect.%u", tenant_id);
4739  if (SCConfYamlLoadFileWithPrefix(yaml_path, prefix) != 0) {
4740  SCLogError("failed to load yaml %s", yaml_path);
4741  goto bad_tenant;
4742  }
4743 
4744  int r = DetectLoaderSetupLoadTenant(tenant_id, yaml_path);
4745  if (r < 0) {
4746  /* error logged already */
4747  goto bad_tenant;
4748  }
4749  continue;
4750 
4751  bad_tenant:
4752  if (failure_fatal)
4753  goto error;
4754  }
4755  }
4756 
4757  /* wait for our loaders to complete their tasks */
4758  if (DetectLoadersSync() != 0) {
4759  goto error;
4760  }
4761 
4763 
4764  } else {
4765  SCLogDebug("multi-detect not enabled (multi tenancy)");
4766  }
4767  return 0;
4768 error:
4769  return -1;
4770 }
4771 
4772 static uint32_t DetectEngineTenantGetIdFromVlanId(const void *ctx, const Packet *p)
4773 {
4774  const DetectEngineThreadCtx *det_ctx = ctx;
4775  uint32_t x = 0;
4776  uint32_t vlan_id = 0;
4777 
4778  if (p->vlan_idx == 0)
4779  return 0;
4780 
4781  vlan_id = p->vlan_id[0];
4782 
4783  if (det_ctx == NULL || det_ctx->tenant_array == NULL || det_ctx->tenant_array_size == 0)
4784  return 0;
4785 
4786  /* not very efficient, but for now we're targeting only limited amounts.
4787  * Can use hash/tree approach later. */
4788  for (x = 0; x < det_ctx->tenant_array_size; x++) {
4789  if (det_ctx->tenant_array[x].traffic_id == vlan_id)
4790  return det_ctx->tenant_array[x].tenant_id;
4791  }
4792 
4793  return 0;
4794 }
4795 
4796 static uint32_t DetectEngineTenantGetIdFromLivedev(const void *ctx, const Packet *p)
4797 {
4798  const DetectEngineThreadCtx *det_ctx = ctx;
4799  const LiveDevice *ld = LiveDeviceGetById(p->livedev_id);
4800 
4801  if (ld == NULL || det_ctx == NULL)
4802  return 0;
4803 
4804  SCLogDebug("using tenant-id %u for packet on device %s", ld->tenant_id, ld->dev);
4805  return ld->tenant_id;
4806 }
4807 
4808 static int DetectEngineTenantRegisterSelector(
4809  enum DetectEngineTenantSelectors selector, uint32_t tenant_id, uint32_t traffic_id)
4810 {
4811  DetectEngineMasterCtx *master = &g_master_de_ctx;
4812  SCMutexLock(&master->lock);
4813 
4814  if (!(master->tenant_selector == TENANT_SELECTOR_UNKNOWN || master->tenant_selector == selector)) {
4815  SCLogInfo("conflicting selector already set");
4816  SCMutexUnlock(&master->lock);
4817  return -1;
4818  }
4819 
4821  while (m) {
4822  if (m->traffic_id == traffic_id) {
4823  SCLogInfo("traffic id already registered");
4824  SCMutexUnlock(&master->lock);
4825  return -1;
4826  }
4827  m = m->next;
4828  }
4829 
4830  DetectEngineTenantMapping *map = SCCalloc(1, sizeof(*map));
4831  if (map == NULL) {
4832  SCLogInfo("memory fail");
4833  SCMutexUnlock(&master->lock);
4834  return -1;
4835  }
4836  map->traffic_id = traffic_id;
4837  map->tenant_id = tenant_id;
4838 
4839  map->next = master->tenant_mapping_list;
4840  master->tenant_mapping_list = map;
4841 
4842  master->tenant_selector = selector;
4843 
4844  SCLogDebug("tenant handler %u %u %u registered", selector, tenant_id, traffic_id);
4845  SCMutexUnlock(&master->lock);
4846  return 0;
4847 }
4848 
4849 static int DetectEngineTenantUnregisterSelector(
4850  enum DetectEngineTenantSelectors selector, uint32_t tenant_id, uint32_t traffic_id)
4851 {
4852  DetectEngineMasterCtx *master = &g_master_de_ctx;
4853  SCMutexLock(&master->lock);
4854 
4855  if (master->tenant_mapping_list == NULL) {
4856  SCMutexUnlock(&master->lock);
4857  return -1;
4858  }
4859 
4860  DetectEngineTenantMapping *prev = NULL;
4862  while (map) {
4863  if (map->traffic_id == traffic_id &&
4864  map->tenant_id == tenant_id)
4865  {
4866  if (prev != NULL)
4867  prev->next = map->next;
4868  else
4869  master->tenant_mapping_list = map->next;
4870 
4871  map->next = NULL;
4872  SCFree(map);
4873  SCLogInfo("tenant handler %u %u %u unregistered", selector, tenant_id, traffic_id);
4874  SCMutexUnlock(&master->lock);
4875  return 0;
4876  }
4877  prev = map;
4878  map = map->next;
4879  }
4880 
4881  SCMutexUnlock(&master->lock);
4882  return -1;
4883 }
4884 
4885 int DetectEngineTenantRegisterLivedev(uint32_t tenant_id, int device_id)
4886 {
4887  return DetectEngineTenantRegisterSelector(
4888  TENANT_SELECTOR_LIVEDEV, tenant_id, (uint32_t)device_id);
4889 }
4890 
4891 int DetectEngineTenantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
4892 {
4893  return DetectEngineTenantRegisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
4894 }
4895 
4896 int DetectEngineTenantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
4897 {
4898  return DetectEngineTenantUnregisterSelector(TENANT_SELECTOR_VLAN, tenant_id, (uint32_t)vlan_id);
4899 }
4900 
4901 int DetectEngineTenantRegisterPcapFile(uint32_t tenant_id)
4902 {
4903  SCLogInfo("registering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
4904  return DetectEngineTenantRegisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
4905 }
4906 
4908 {
4909  SCLogInfo("unregistering %u %d 0", TENANT_SELECTOR_DIRECT, tenant_id);
4910  return DetectEngineTenantUnregisterSelector(TENANT_SELECTOR_DIRECT, tenant_id, 0);
4911 }
4912 
4913 static uint32_t DetectEngineTenantGetIdFromPcap(const void *ctx, const Packet *p)
4914 {
4915  return p->pcap_v.tenant_id;
4916 }
4917 
4919 {
4920  DetectEngineMasterCtx *master = &g_master_de_ctx;
4921  SCMutexLock(&master->lock);
4922 
4923  if (master->list == NULL) {
4924  SCMutexUnlock(&master->lock);
4925  return NULL;
4926  }
4927 
4928  DetectEngineCtx *de_ctx = master->list;
4929  while (de_ctx) {
4931  de_ctx->tenant_id == tenant_id)
4932  {
4933  de_ctx->ref_cnt++;
4934  break;
4935  }
4936 
4937  de_ctx = de_ctx->next;
4938  }
4939 
4940  SCMutexUnlock(&master->lock);
4941  return de_ctx;
4942 }
4943 
4945 {
4946  DEBUG_VALIDATE_BUG_ON((*de_ctx)->ref_cnt == 0);
4947  (*de_ctx)->ref_cnt--;
4948  *de_ctx = NULL;
4949 }
4950 
4951 static int DetectEngineAddToList(DetectEngineCtx *instance)
4952 {
4953  DetectEngineMasterCtx *master = &g_master_de_ctx;
4954 
4955  if (instance == NULL)
4956  return -1;
4957 
4958  if (master->list == NULL) {
4959  master->list = instance;
4960  } else {
4961  instance->next = master->list;
4962  master->list = instance;
4963  }
4964 
4965  return 0;
4966 }
4967 
4969 {
4970  int r;
4971 
4972  if (de_ctx == NULL)
4973  return -1;
4974 
4975  SCLogDebug("adding de_ctx %p to master", de_ctx);
4976 
4977  DetectEngineMasterCtx *master = &g_master_de_ctx;
4978  SCMutexLock(&master->lock);
4979  r = DetectEngineAddToList(de_ctx);
4980  SCMutexUnlock(&master->lock);
4981  return r;
4982 }
4983 
4984 static int DetectEngineMoveToFreeListNoLock(DetectEngineMasterCtx *master, DetectEngineCtx *de_ctx)
4985 {
4986  DetectEngineCtx *instance = master->list;
4987  if (instance == NULL) {
4988  return -1;
4989  }
4990 
4991  /* remove from active list */
4992  if (instance == de_ctx) {
4993  master->list = instance->next;
4994  } else {
4995  DetectEngineCtx *prev = instance;
4996  instance = instance->next; /* already checked first element */
4997 
4998  while (instance) {
4999  DetectEngineCtx *next = instance->next;
5000 
5001  if (instance == de_ctx) {
5002  prev->next = instance->next;
5003  break;
5004  }
5005 
5006  prev = instance;
5007  instance = next;
5008  }
5009  if (instance == NULL) {
5010  return -1;
5011  }
5012  }
5013 
5014  /* instance is now detached from list */
5015  instance->next = NULL;
5016 
5017  /* add to free list */
5018  if (master->free_list == NULL) {
5019  master->free_list = instance;
5020  } else {
5021  instance->next = master->free_list;
5022  master->free_list = instance;
5023  }
5024  SCLogDebug("detect engine %p moved to free list (%u refs)", de_ctx, de_ctx->ref_cnt);
5025  return 0;
5026 }
5027 
5029 {
5030  int ret = 0;
5031  DetectEngineMasterCtx *master = &g_master_de_ctx;
5032  SCMutexLock(&master->lock);
5033  ret = DetectEngineMoveToFreeListNoLock(master, de_ctx);
5034  SCMutexUnlock(&master->lock);
5035  return ret;
5036 }
5037 
5039 {
5040  DetectEngineMasterCtx *master = &g_master_de_ctx;
5041  SCMutexLock(&master->lock);
5042 
5043  DetectEngineCtx *prev = NULL;
5044  DetectEngineCtx *instance = master->free_list;
5045  while (instance) {
5046  DetectEngineCtx *next = instance->next;
5047 
5048  SCLogDebug("detect engine %p has %u ref(s)", instance, instance->ref_cnt);
5049 
5050  if (instance->ref_cnt == 0) {
5051  if (prev == NULL) {
5052  master->free_list = next;
5053  } else {
5054  prev->next = next;
5055  }
5056 
5057  SCLogDebug("freeing detect engine %p", instance);
5058  DetectEngineCtxFree(instance);
5059  instance = NULL;
5060  }
5061 
5062  prev = instance;
5063  instance = next;
5064  }
5065  SCMutexUnlock(&master->lock);
5066 }
5067 
5069 {
5070  DetectEngineMasterCtx *master = &g_master_de_ctx;
5071  SCMutexLock(&master->lock);
5072 
5073  DetectEngineCtx *instance = master->list;
5074  while (instance) {
5075  DetectEngineCtx *next = instance->next;
5076  DEBUG_VALIDATE_BUG_ON(instance->ref_cnt);
5077  SCLogDebug("detect engine %p has %u ref(s)", instance, instance->ref_cnt);
5078  instance->ref_cnt = 0;
5079  DetectEngineMoveToFreeListNoLock(master, instance);
5080  instance = next;
5081  }
5082  SCMutexUnlock(&master->lock);
5084 }
5085 
5086 static int reloads = 0;
5087 
5088 /** \brief Reload the detection engine
5089  *
5090  * \param filename YAML file to load for the detect config
5091  *
5092  * \retval -1 error
5093  * \retval 0 ok
5094  */
5096 {
5097  DetectEngineCtx *new_de_ctx = NULL;
5098  DetectEngineCtx *old_de_ctx = NULL;
5099 
5100  char prefix[128];
5101  memset(prefix, 0, sizeof(prefix));
5102 
5103  SCLogNotice("rule reload starting");
5104 
5105  if (suri->conf_filename != NULL) {
5106  snprintf(prefix, sizeof(prefix), "detect-engine-reloads.%d", reloads++);
5107  SCLogConfig("Reloading %s", suri->conf_filename);
5108  if (SCConfYamlLoadFileWithPrefix(suri->conf_filename, prefix) != 0) {
5109  SCLogError("failed to load yaml %s", suri->conf_filename);
5110  return -1;
5111  }
5112 
5113  SCConfNode *node = SCConfGetNode(prefix);
5114  if (node == NULL) {
5115  SCLogError("failed to properly setup yaml %s", suri->conf_filename);
5116  return -1;
5117  }
5118 
5119  if (suri->additional_configs) {
5120  for (int i = 0; suri->additional_configs[i] != NULL; i++) {
5121  SCLogConfig("Reloading %s", suri->additional_configs[i]);
5123  }
5124  }
5125 
5126 #if 0
5127  SCConfDump();
5128 #endif
5129  }
5130 
5131  /* get a reference to the current de_ctx */
5132  old_de_ctx = DetectEngineGetCurrent();
5133  if (old_de_ctx == NULL)
5134  return -1;
5135  SCLogDebug("get ref to old_de_ctx %p", old_de_ctx);
5136  DatasetReload();
5137 
5138  /* only reload a regular 'normal' and 'delayed detect stub' detect engines */
5139  if (!(old_de_ctx->type == DETECT_ENGINE_TYPE_NORMAL ||
5140  old_de_ctx->type == DETECT_ENGINE_TYPE_DD_STUB))
5141  {
5142  DetectEngineDeReference(&old_de_ctx);
5143  SCLogNotice("rule reload complete");
5144  return -1;
5145  }
5146 
5147  /* get new detection engine */
5148  new_de_ctx = DetectEngineCtxInitWithPrefix(prefix, old_de_ctx->tenant_id);
5149  if (new_de_ctx == NULL) {
5150  SCLogError("initializing detection engine "
5151  "context failed.");
5152  DetectEngineDeReference(&old_de_ctx);
5153  return -1;
5154  }
5155 
5156  if (SigLoadSignatures(new_de_ctx,
5157  suri->sig_file, suri->sig_file_exclusive) != 0) {
5158  DetectEngineCtxFree(new_de_ctx);
5159  DetectEngineDeReference(&old_de_ctx);
5160  return -1;
5161  }
5162  SCLogDebug("set up new_de_ctx %p", new_de_ctx);
5163 
5164  /* Copy over callbacks. */
5165  new_de_ctx->RateFilterCallback = old_de_ctx->RateFilterCallback;
5166  new_de_ctx->rate_filter_callback_arg = old_de_ctx->rate_filter_callback_arg;
5167 
5168  /* add to master */
5169  DetectEngineAddToMaster(new_de_ctx);
5170 
5171  /* move to old free list */
5172  DetectEngineMoveToFreeList(old_de_ctx);
5173  DetectEngineDeReference(&old_de_ctx);
5174 
5175  SCLogDebug("going to reload the threads to use new_de_ctx %p", new_de_ctx);
5176 
5177  DetectEngineMasterCtx *master = &g_master_de_ctx;
5178  SCMutexLock(&master->lock);
5179  /* update the threads */
5180  DetectEngineReloadThreads(new_de_ctx);
5181  SCMutexUnlock(&master->lock);
5182 
5183  SCLogDebug("threads now run new_de_ctx %p", new_de_ctx);
5184 
5185  /* walk free list, freeing the old_de_ctx */
5187 
5189 
5191 
5192  SCLogDebug("old_de_ctx should have been freed");
5193 
5195 
5196  SCLogNotice("rule reload complete");
5197 
5198 #ifdef HAVE_MALLOC_TRIM
5199  /* The reload process potentially frees up large amounts of memory.
5200  * Encourage the memory management system to reclaim as much as it
5201  * can.
5202  */
5203  malloc_trim(0);
5204 #endif
5205 
5206  return 0;
5207 }
5208 
5209 static uint32_t TenantIdHash(HashTable *h, void *data, uint16_t data_len)
5210 {
5211  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
5212  return det_ctx->tenant_id % h->array_size;
5213 }
5214 
5215 static char TenantIdCompare(void *d1, uint16_t d1_len, void *d2, uint16_t d2_len)
5216 {
5219  return (det1->tenant_id == det2->tenant_id);
5220 }
5221 
5222 static void TenantIdFree(void *d)
5223 {
5224  DetectEngineThreadCtxFree(d);
5225 }
5226 
5228 {
5229  DetectEngineMasterCtx *master = &g_master_de_ctx;
5230  SCMutexLock(&master->lock);
5231 
5232  if (master->tenant_selector == TENANT_SELECTOR_UNKNOWN) {
5233  SCLogInfo("error, no tenant selector");
5234  SCMutexUnlock(&master->lock);
5235  return -1;
5236  }
5237 
5238  DetectEngineCtx *stub_de_ctx = NULL;
5239  DetectEngineCtx *list = master->list;
5240  for ( ; list != NULL; list = list->next) {
5241  SCLogDebug("list %p tenant %u", list, list->tenant_id);
5242 
5243  if (list->type == DETECT_ENGINE_TYPE_NORMAL ||
5244  list->type == DETECT_ENGINE_TYPE_MT_STUB ||
5246  {
5247  stub_de_ctx = list;
5248  break;
5249  }
5250  }
5251  if (stub_de_ctx == NULL) {
5252  stub_de_ctx = DetectEngineCtxInitStubForMT();
5253  if (stub_de_ctx == NULL) {
5254  SCMutexUnlock(&master->lock);
5255  return -1;
5256  }
5257 
5258  if (master->list == NULL) {
5259  master->list = stub_de_ctx;
5260  } else {
5261  stub_de_ctx->next = master->list;
5262  master->list = stub_de_ctx;
5263  }
5264  }
5265 
5266  /* update the threads */
5267  SCLogDebug("MT reload starting");
5268  DetectEngineReloadThreads(stub_de_ctx);
5269  SCLogDebug("MT reload done");
5270 
5271  SCMutexUnlock(&master->lock);
5272 
5273  /* walk free list, freeing the old_de_ctx */
5275  // needed for VarNameStoreFree
5277 
5278  SCLogDebug("old_de_ctx should have been freed");
5279  return 0;
5280 }
5281 
5282 static int g_parse_metadata = 0;
5283 
5285 {
5286  g_parse_metadata = 1;
5287 }
5288 
5290 {
5291  g_parse_metadata = 0;
5292 }
5293 
5295 {
5296  return g_parse_metadata;
5297 }
5298 
5300 {
5301  switch (type) {
5302  case DETECT_SM_LIST_MATCH:
5303  return "packet";
5304  case DETECT_SM_LIST_PMATCH:
5305  return "packet/stream payload";
5306 
5307  case DETECT_SM_LIST_TMATCH:
5308  return "tag";
5309 
5311  return "base64_data";
5312 
5314  return "post-match";
5315 
5317  return "suppress";
5319  return "threshold";
5320 
5321  case DETECT_SM_LIST_MAX:
5322  return "max (internal)";
5323  }
5324  return "error";
5325 }
5326 
5327 /* events api */
5329 {
5331  det_ctx->events++;
5332 }
5333 
5335  const Signature *s, const char **sigerror, const DetectBufferType *map)
5336 {
5337  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
5338  if (s->init_data->buffers[x].id != (uint32_t)map->id)
5339  continue;
5340  const SigMatch *sm = s->init_data->buffers[x].head;
5341  for (; sm != NULL; sm = sm->next) {
5342  if (sm->type != DETECT_CONTENT)
5343  continue;
5344 
5345  const DetectContentData *cd = (DetectContentData *)sm->ctx;
5346  if (cd->flags & DETECT_CONTENT_NOCASE) {
5347  *sigerror = "md5-like keyword should not be used together with "
5348  "nocase, since the rule is automatically "
5349  "lowercased anyway which makes nocase redundant.";
5350  SCLogWarning("rule %u: buffer %s: %s", s->id, map->name, *sigerror);
5351  }
5352 
5353  if (cd->content_len != SC_MD5_HEX_LEN) {
5354  *sigerror = "Invalid length for md5-like keyword (should "
5355  "be 32 characters long). This rule will therefore "
5356  "never match.";
5357  SCLogError("rule %u: buffer %s: %s", s->id, map->name, *sigerror);
5358  return false;
5359  }
5360 
5361  for (size_t i = 0; i < cd->content_len; ++i) {
5362  if (!isxdigit(cd->content[i])) {
5363  *sigerror =
5364  "Invalid md5-like string (should be string of hexadecimal characters)."
5365  "This rule will therefore never match.";
5366  SCLogWarning("rule %u: buffer %s: %s", s->id, map->name, *sigerror);
5367  return false;
5368  }
5369  }
5370  }
5371  }
5372  return true;
5373 }
5374 
5376  const DetectEngineCtx *de_ctx, Signature *s, const DetectBufferType *map)
5377 {
5378  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
5379  if (s->init_data->buffers[x].id != (uint32_t)map->id)
5380  continue;
5381  SigMatch *sm = s->init_data->buffers[x].head;
5382  for (; sm != NULL; sm = sm->next) {
5383  if (sm->type != DETECT_CONTENT)
5384  continue;
5385 
5387 
5388  bool changed = false;
5389  uint32_t u;
5390  for (u = 0; u < cd->content_len; u++) {
5391  if (isupper(cd->content[u])) {
5392  cd->content[u] = u8_tolower(cd->content[u]);
5393  changed = true;
5394  }
5395  }
5396 
5397  if (changed) {
5398  SpmDestroyCtx(cd->spm_ctx);
5399  cd->spm_ctx =
5401  }
5402  }
5403  }
5404 }
5405 
5407 {
5409  if (de_ctx == NULL) {
5410  SCLogError("no detection engine available for rate filter callback registration");
5411  return false;
5412  }
5413  de_ctx->RateFilterCallback = fn;
5416  return true;
5417 }
5418 
5420 {
5421  if (det_ctx->json_content_len > SIG_JSON_CONTENT_ARRAY_LEN - 1) {
5422  SCLogDebug("json content length %u exceeds maximum %u", det_ctx->json_content_len,
5424  return -1;
5425  }
5426  if (det_ctx->json_content_len >= det_ctx->json_content_capacity) {
5427  if (det_ctx->json_content_capacity == 0) {
5428  det_ctx->json_content_capacity = 1;
5429  } else {
5430  det_ctx->json_content_capacity *= 2;
5431  }
5432  void *tmp = SCRealloc(
5433  det_ctx->json_content, det_ctx->json_content_capacity * sizeof(SigJsonContent));
5434  if (unlikely(tmp == NULL)) {
5435  return -1;
5436  }
5437  SCLogDebug("reallocated json content array to %u items", det_ctx->json_content_capacity);
5438  det_ctx->json_content = tmp;
5439  }
5440  return 0;
5441 }
5442 
5443 /*************************************Unittest*********************************/
5444 
5445 #ifdef UNITTESTS
5446 
5447 static int DetectEngineInitYamlConf(const char *conf)
5448 {
5450  SCConfInit();
5451  return SCConfYamlLoadString(conf, strlen(conf));
5452 }
5453 
5454 static void DetectEngineDeInitYamlConf(void)
5455 {
5456  SCConfDeInit();
5458 }
5459 
5460 static int DetectEngineTest01(void)
5461 {
5462  const char *conf =
5463  "%YAML 1.1\n"
5464  "---\n"
5465  "detect-engine:\n"
5466  " - profile: medium\n"
5467  " - custom-values:\n"
5468  " toclient_src_groups: 2\n"
5469  " toclient_dst_groups: 2\n"
5470  " toclient_sp_groups: 2\n"
5471  " toclient_dp_groups: 3\n"
5472  " toserver_src_groups: 2\n"
5473  " toserver_dst_groups: 4\n"
5474  " toserver_sp_groups: 2\n"
5475  " toserver_dp_groups: 25\n"
5476  " - inspection-recursion-limit: 0\n";
5477 
5478  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5479 
5482 
5484 
5486 
5487  DetectEngineDeInitYamlConf();
5488 
5489  PASS;
5490 }
5491 
5492 static int DetectEngineTest02(void)
5493 {
5494  const char *conf =
5495  "%YAML 1.1\n"
5496  "---\n"
5497  "detect-engine:\n"
5498  " - profile: medium\n"
5499  " - custom-values:\n"
5500  " toclient_src_groups: 2\n"
5501  " toclient_dst_groups: 2\n"
5502  " toclient_sp_groups: 2\n"
5503  " toclient_dp_groups: 3\n"
5504  " toserver_src_groups: 2\n"
5505  " toserver_dst_groups: 4\n"
5506  " toserver_sp_groups: 2\n"
5507  " toserver_dp_groups: 25\n"
5508  " - inspection-recursion-limit:\n";
5509 
5510  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5511 
5514 
5515  FAIL_IF_NOT(
5517 
5519 
5520  DetectEngineDeInitYamlConf();
5521 
5522  PASS;
5523 }
5524 
5525 static int DetectEngineTest03(void)
5526 {
5527  const char *conf =
5528  "%YAML 1.1\n"
5529  "---\n"
5530  "detect-engine:\n"
5531  " - profile: medium\n"
5532  " - custom-values:\n"
5533  " toclient_src_groups: 2\n"
5534  " toclient_dst_groups: 2\n"
5535  " toclient_sp_groups: 2\n"
5536  " toclient_dp_groups: 3\n"
5537  " toserver_src_groups: 2\n"
5538  " toserver_dst_groups: 4\n"
5539  " toserver_sp_groups: 2\n"
5540  " toserver_dp_groups: 25\n";
5541 
5542  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5543 
5546 
5547  FAIL_IF_NOT(
5549 
5551 
5552  DetectEngineDeInitYamlConf();
5553 
5554  PASS;
5555 }
5556 
5557 static int DetectEngineTest04(void)
5558 {
5559  const char *conf =
5560  "%YAML 1.1\n"
5561  "---\n"
5562  "detect-engine:\n"
5563  " - profile: medium\n"
5564  " - custom-values:\n"
5565  " toclient_src_groups: 2\n"
5566  " toclient_dst_groups: 2\n"
5567  " toclient_sp_groups: 2\n"
5568  " toclient_dp_groups: 3\n"
5569  " toserver_src_groups: 2\n"
5570  " toserver_dst_groups: 4\n"
5571  " toserver_sp_groups: 2\n"
5572  " toserver_dp_groups: 25\n"
5573  " - inspection-recursion-limit: 10\n";
5574 
5575  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5576 
5579 
5581 
5583 
5584  DetectEngineDeInitYamlConf();
5585 
5586  PASS;
5587 }
5588 
5589 static int DetectEngineTest08(void)
5590 {
5591  const char *conf =
5592  "%YAML 1.1\n"
5593  "---\n"
5594  "detect-engine:\n"
5595  " - profile: custom\n"
5596  " - custom-values:\n"
5597  " toclient-groups: 23\n"
5598  " toserver-groups: 27\n";
5599 
5600  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5601 
5604 
5607 
5609 
5610  DetectEngineDeInitYamlConf();
5611 
5612  PASS;
5613 }
5614 
5615 /** \test bug 892 bad values */
5616 static int DetectEngineTest09(void)
5617 {
5618  const char *conf =
5619  "%YAML 1.1\n"
5620  "---\n"
5621  "detect-engine:\n"
5622  " - profile: custom\n"
5623  " - custom-values:\n"
5624  " toclient-groups: BA\n"
5625  " toserver-groups: BA\n"
5626  " - inspection-recursion-limit: 10\n";
5627 
5628  FAIL_IF(DetectEngineInitYamlConf(conf) == -1);
5629 
5632 
5635 
5637 
5638  DetectEngineDeInitYamlConf();
5639 
5640  PASS;
5641 }
5642 
5643 /** \brief keyword thread-context init stub that always fails, used to mimic a
5644  * failing per-thread keyword init such as DetectFilemagicThreadInit. */
5645 static void *DetectEngineFailingThreadKeywordInit(void *data)
5646 {
5647  (void)data;
5648  return NULL;
5649 }
5650 
5651 static void DetectEngineNoopThreadKeywordFree(void *ctx)
5652 {
5653  (void)ctx;
5654 }
5655 
5656 /** \test Ticket #8237: a failing per-thread keyword init must make the detect
5657  * thread context init fail rather than silently continuing with a partially
5658  * initialized keyword context array. */
5659 static int DetectEngineThreadCtxInitKeywordFailTest(void)
5660 {
5661  ThreadVars th_v;
5662  memset(&th_v, 0, sizeof(th_v));
5663  DetectEngineThreadCtx *det_ctx = NULL;
5664 
5667  de_ctx->flags |= DE_QUIET;
5668 
5669  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (sid:1;)");
5670  FAIL_IF_NULL(s);
5671 
5673 
5674  /* Register a keyword whose per-thread init fails (returns NULL). */
5675  int id = DetectRegisterThreadCtxFuncs(de_ctx, "test_failing_keyword",
5676  DetectEngineFailingThreadKeywordInit, NULL, DetectEngineNoopThreadKeywordFree, 0);
5677  FAIL_IF(id < 0);
5678 
5679  /* Thread context init must report failure and not hand back a context. */
5680  TmEcode r = DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
5681  FAIL_IF(r != TM_ECODE_FAILED);
5682  FAIL_IF_NOT_NULL(det_ctx);
5683 
5685 
5686  PASS;
5687 }
5688 
5689 #endif
5690 
5691 #ifdef UNITTESTS
5692 /** \test SIGMATCH_STATEFUL uses a unique bit and only stateful keywords set it */
5693 static int DetectEngineStatefulFlagTest01(void)
5694 {
5698 
5701 
5702  PASS;
5703 }
5704 #endif
5705 
5707 {
5708 #ifdef UNITTESTS
5709  UtRegisterTest("DetectEngineStatefulFlagTest01", DetectEngineStatefulFlagTest01);
5710  UtRegisterTest("DetectEngineTest01", DetectEngineTest01);
5711  UtRegisterTest("DetectEngineTest02", DetectEngineTest02);
5712  UtRegisterTest("DetectEngineTest03", DetectEngineTest03);
5713  UtRegisterTest("DetectEngineTest04", DetectEngineTest04);
5714  UtRegisterTest("DetectEngineTest08", DetectEngineTest08);
5715  UtRegisterTest("DetectEngineTest09", DetectEngineTest09);
5717  "DetectEngineThreadCtxInitKeywordFailTest", DetectEngineThreadCtxInitKeywordFailTest);
5718 #endif
5719 }
DetectEngineThreadCtx_::byte_values
uint64_t * byte_values
Definition: detect.h:1351
DETECT_SSL_STATE
@ DETECT_SSL_STATE
Definition: detect-engine-register.h:203
DETECT_CONTENT_NOCASE
#define DETECT_CONTENT_NOCASE
Definition: detect-content.h:29
DETECT_TABLE_APP_TD
@ DETECT_TABLE_APP_TD
Definition: detect.h:571
DetectEngineAppInspectionEngine_::stream
bool stream
Definition: detect.h:425
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:62
SCProfilingSghThreadCleanup
void SCProfilingSghThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rulegroups.c:330
DetectEngineCtxInitWithPrefix
DetectEngineCtx * DetectEngineCtxInitWithPrefix(const char *prefix, uint32_t tenant_id)
Definition: detect-engine.c:2879
DetectEngineTenantMapping_
Definition: detect.h:1753
DEFAULT_MAX_FLOWBITS_PER_SIGNATURE
#define DEFAULT_MAX_FLOWBITS_PER_SIGNATURE
Definition: detect-engine.c:98
util-device-private.h
util-byte.h
SCConfYamlLoadString
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:536
tm-threads.h
DetectEngineAppInspectionEngine_
Definition: detect.h:420
DetectGetMultiData
InspectionBuffer * DetectGetMultiData(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id, uint32_t index, InspectionMultiBufferGetDataPtr GetBuf)
Definition: detect-engine.c:2357
DetectEngineThreadCtx_::inspect
struct DetectEngineThreadCtx_::@101 inspect
util-hash-string.h
DetectBufferType_::supports_transforms
bool supports_transforms
Definition: detect.h:465
SignatureInitDataBuffer_::head
SigMatch * head
Definition: detect.h:543
DetectEngineSyncer_::m
SCMutex m
Definition: detect-engine.c:2076
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:424
DETECT_ENGINE_MPM_CACHE_OP_PRUNE
#define DETECT_ENGINE_MPM_CACHE_OP_PRUNE
Definition: detect.h:1798
DetectBufferType_::mpm
bool mpm
Definition: detect.h:459
detect-content.h
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@82 v2
detect-engine.h
DetectEngineResetMaxSigId
void DetectEngineResetMaxSigId(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:3337
DetectEngineMTApply
int DetectEngineMTApply(void)
Definition: detect-engine.c:5227
SCProfilingKeywordDestroyCtx
void SCProfilingKeywordDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-keywords.c:268
DetectEngineBufferTypeSupportsPacketGetById
bool DetectEngineBufferTypeSupportsPacketGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1631
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:120
DetectEngineThreadCtxInitForReload
DetectEngineThreadCtx * DetectEngineThreadCtxInitForReload(ThreadVars *tv, DetectEngineCtx *new_de_ctx, int mt)
Definition: detect-engine.c:3753
DetectEngineThreadCtx_::to_clear_idx
uint32_t to_clear_idx
Definition: detect.h:1376
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SCConfNodeRemove
void SCConfNodeRemove(SCConfNode *node)
Remove (and SCFree) the provided configuration node.
Definition: conf.c:710
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:666
SCProfilingKeywordThreadCleanup
void SCProfilingKeywordThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-keywords.c:338
THashDataGetResult::data
THashData * data
Definition: util-thash.h:192
SCConfGetTime
int SCConfGetTime(const char *name, uint64_t *val)
Retrieve a configuration value as a time duration in seconds.
Definition: conf.c:691
DetectBufferTypeRegisterSetupCallback
void DetectBufferTypeRegisterSetupCallback(const char *name, void(*SetupCallback)(const DetectEngineCtx *, Signature *, const DetectBufferType *))
Definition: detect-engine.c:1658
AlertQueueFree
void AlertQueueFree(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine-alert.c:280
DetectEngineAppHookToName
const char * DetectEngineAppHookToName(const AppProto p, const uint8_t sub_state, const uint8_t state, const uint8_t direction)
Definition: detect-engine.c:846
SCProfilingSghThreadSetup
void SCProfilingSghThreadSetup(SCProfileSghDetectCtx *ctx, DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-rulegroups.c:295
DetectEngineThreadCtx_::counter_alerts
StatsCounterId counter_alerts
Definition: detect.h:1361
DetectParseDupSigHashInit
int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:3610
RELOAD
@ RELOAD
Definition: detect-engine.c:2071
SIG_FLAG_FW_HOOK_LTE
#define SIG_FLAG_FW_HOOK_LTE
Definition: detect.h:255
DetectGetSingleData
InspectionBuffer * DetectGetSingleData(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id, InspectionSingleBufferGetDataPtr GetBuf)
Definition: detect-engine.c:2340
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
SIG_JSON_CONTENT_ARRAY_LEN
#define SIG_JSON_CONTENT_ARRAY_LEN
Definition: detect.h:1303
DetectLoaderThreadSpawn
void DetectLoaderThreadSpawn(void)
spawn the detect loader manager thread
Definition: detect-engine-loader.c:760
AppLayerParserIsEnabled
int AppLayerParserIsEnabled(AppProto alproto)
simple way to globally test if a alproto is registered and fully enabled in the configuration.
Definition: app-layer-parser.c:1761
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:69
DetectEngineDeReference
void DetectEngineDeReference(DetectEngineCtx **de_ctx)
Definition: detect-engine.c:4944
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:2268
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1526
DetectEngineMustParseMetadata
int DetectEngineMustParseMetadata(void)
Definition: detect-engine.c:5294
AppLayerParserGetStateNameById
const char * AppLayerParserGetStateNameById(uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
Definition: app-layer-parser.c:1847
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:262
SignatureHook_::sm_list
int sm_list
Definition: detect.h:585
MpmFactoryDeRegisterAllMpmCtxProfiles
void MpmFactoryDeRegisterAllMpmCtxProfiles(DetectEngineCtx *de_ctx)
Definition: util-mpm.c:168
DETECT_TABLE_APP_FILTER
@ DETECT_TABLE_APP_FILTER
Definition: detect.h:570
flow-util.h
DetectEnginePktInspectionEngine
Definition: detect.h:492
DetectEngineMasterCtx_::tenant_mapping_list
DetectEngineTenantMapping * tenant_mapping_list
Definition: detect.h:1784
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:446
SCInspectionBufferGet
InspectionBuffer * SCInspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
Definition: detect-engine-inspect-buffer.c:56
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:2381
detect-engine-siggroup.h
SigTableElmt_::name
const char * name
Definition: detect.h:1539
DetectEngineMasterCtx_::list
DetectEngineCtx * list
Definition: detect.h:1773
InspectionBuffer::initialized
bool initialized
Definition: detect-engine-inspect-buffer.h:38
MpmStoreFree
void MpmStoreFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by MpmStoreInit() function.
Definition: detect-engine-mpm.c:1671
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:439
DetectEngineBufferTypeSupportsPacket
void DetectEngineBufferTypeSupportsPacket(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1598
DetectEngineBufferRunSetupCallback
void DetectEngineBufferRunSetupCallback(const DetectEngineCtx *de_ctx, const int id, Signature *s)
Definition: detect-engine.c:1668
DetectEngineCtx_::type
enum DetectEngineType type
Definition: detect.h:1123
DetectEnginePruneFreeList
void DetectEnginePruneFreeList(void)
Definition: detect-engine.c:5038
SigLoadSignatures
int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, bool sig_file_exclusive)
Load signatures.
Definition: detect-engine-loader.c:384
SIGMATCH_BAN_FIREWALL_RULE
#define SIGMATCH_BAN_FIREWALL_RULE
Definition: detect-engine-register.h:360
DetectEngineInspectBufferSingle
uint8_t DetectEngineInspectBufferSingle(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:2208
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:4034
DetectEngineCtx_::guess_applayer
bool guess_applayer
Definition: detect.h:1046
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectEngineTransforms
Definition: detect.h:395
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:301
MpmTableElmt_::name
const char * name
Definition: util-mpm.h:169
SCClassSCConfInit
void SCClassSCConfInit(DetectEngineCtx *de_ctx)
Definition: util-classification-config.c:61
Signature_::app_progress_hook
uint8_t app_progress_hook
Definition: detect.h:729
DetectEngineCtxInitStubForDD
DetectEngineCtx * DetectEngineCtxInitStubForDD(void)
Definition: detect-engine.c:2869
KEYWORD_PROFILING_SET_LIST
#define KEYWORD_PROFILING_SET_LIST(ctx, list)
Definition: util-profiling.h:46
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:78
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1530
DetectEngineCtx_::max_uniq_toclient_groups
uint16_t max_uniq_toclient_groups
Definition: detect.h:1057
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:2070
DetectEngineAppHookToSmlist
int DetectEngineAppHookToSmlist(const AppProto p, const uint8_t sub_state, const uint8_t state, const uint8_t direction)
get the sm_list for a app hook
Definition: detect-engine.c:885
DetectEngineCtx_::ref_cnt
uint32_t ref_cnt
Definition: detect.h:1126
DetectEngineAppInspectionEngine_::Callback
InspectEngineFuncPtr Callback
Definition: detect.h:439
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:697
DETECT_TABLE_PACKET_PRE_STREAM
@ DETECT_TABLE_PACKET_PRE_STREAM
Definition: detect.h:567
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
SigString_
Definition: detect.h:897
StatsRegisterCounter
StatsCounterId StatsRegisterCounter(const char *name, StatsThreadContext *stats)
Registers a normal, unqualified counter.
Definition: counters.c:1039
PacketEnqueue
void PacketEnqueue(PacketQueue *q, Packet *p)
Definition: packet-queue.c:175
MPM_HS
@ MPM_HS
Definition: util-mpm.h:54
DetectEngineCtx_::filedata_config
DetectFileDataCfg * filedata_config
Definition: detect.h:1109
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectEngineFrameInspectionEngine::sm_list_base
uint16_t sm_list_base
Definition: detect.h:523
DetectPort_::port
uint16_t port
Definition: detect.h:224
SigMatchData_::is_last
bool is_last
Definition: detect.h:371
SignatureHook_::app
struct SignatureHook_::@87::@88 app
DetectBufferTypeSupportsFrames
void DetectBufferTypeSupportsFrames(const char *name)
Definition: detect-engine.c:1413
name
const char * name
Definition: detect-engine-proto.c:48
DetectEngineMpmCacheService
void DetectEngineMpmCacheService(uint32_t op_flags)
Definition: detect-engine.c:2713
DetectMpmInitializeFrameMpms
void DetectMpmInitializeFrameMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:543
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:87
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:139
DetectEngineThreadCtx_::decoder_events
AppLayerDecoderEvents * decoder_events
Definition: detect.h:1452
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:372
AppLayerParserGetStateProgressCompletionStatus
uint8_t AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:1226
InspectionBuffer
Definition: detect-engine-inspect-buffer.h:34
SignatureHook_::t
union SignatureHook_::@87 t
DetectEngineThreadKeywordCtxItem_::InitFunc
void *(* InitFunc)(void *)
Definition: detect.h:916
Packet_::flags
uint32_t flags
Definition: decode.h:562
type
uint8_t type
Definition: decode-sctp.h:0
SCMutexIsLocked
#define SCMutexIsLocked(mut)
Definition: threads-debug.h:119
DetectEngineAppInspectionEngine_::GetData
InspectionBufferGetDataPtr GetData
Definition: detect.h:435
DetectEngineThreadKeywordCtxItem_
Definition: detect.h:915
DetectTable
DetectTable
Definition: detect.h:564
DetectEngineCtx_::pkt_mpms_list
DetectBufferMpmRegistry * pkt_mpms_list
Definition: detect.h:1159
Tmq_::pq
PacketQueue * pq
Definition: tm-queues.h:35
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:544
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:660
DETECT_SM_LIST_THRESHOLD
@ DETECT_SM_LIST_THRESHOLD
Definition: detect.h:134
SCConfYamlHandleInclude
int SCConfYamlHandleInclude(SCConfNode *parent, const char *filename)
Include a file in the configuration.
Definition: conf-yaml-loader.c:115
DetectEngineThreadKeywordCtxItem_::data
void * data
Definition: detect.h:918
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1429
util-hash.h
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its normalized string equivalent.
Definition: app-layer-protos.c:53
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:4453
ctx
struct Thresholds ctx
LiveDevice_
Definition: util-device-private.h:32
DetectEngineCtx_::inspection_recursion_limit
int inspection_recursion_limit
Definition: detect.h:1040
SpmTableElmt_::name
const char * name
Definition: util-spm.h:61
LiveDevice_::tenant_id_set
bool tenant_id_set
Definition: util-device-private.h:36
DetectAddressMapFree
void DetectAddressMapFree(DetectEngineCtx *de_ctx)
Definition: detect-engine-address.c:1340
DetectEngineFrameInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:527
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
StringParseUint16
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:296
DetectEngineReloadSetIdle
void DetectEngineReloadSetIdle(void)
Definition: detect-engine.c:2109
DetectBufferTypeRegisterValidateCallback
void DetectBufferTypeRegisterValidateCallback(const char *name, bool(*ValidateCallback)(const Signature *, const char **sigerror, const DetectBufferType *))
Definition: detect-engine.c:1676
LiveDevice_::id
uint16_t id
Definition: util-device-private.h:38
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:493
DetectMetadataHashInit
int DetectMetadataHashInit(DetectEngineCtx *de_ctx)
Definition: detect-metadata.c:69
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:353
DetectEngineThreadCtx_::global_keyword_ctxs_array
void ** global_keyword_ctxs_array
Definition: detect.h:1450
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:4143
TransformData_::options
void * options
Definition: detect.h:392
SCInspectionBufferSetupAndApplyTransforms
void SCInspectionBufferSetupAndApplyTransforms(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len, const DetectEngineTransforms *transforms)
setup the buffer with our initial data
Definition: detect-engine-inspect-buffer.c:197
DetectEngineFrameInspectionEngine::mpm
bool mpm
Definition: detect.h:521
SCDetectRateFilterFunc
uint8_t(* SCDetectRateFilterFunc)(const Packet *p, uint32_t sid, uint32_t gid, uint32_t rev, uint8_t original_action, uint8_t new_action, void *arg)
Function type for rate filter callback.
Definition: detect.h:991
DetectFirewallPolicies::pkt_policy_signatures
Signature * pkt_policy_signatures[DETECT_FIREWALL_POLICY_SIZE]
Definition: detect.h:965
TmThreadCountThreadsByTmmFlags
uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags)
returns a count of all the threads that match the flag
Definition: tm-threads.c:2072
DetectBufferTypeSupportsMultiInstance
void DetectBufferTypeSupportsMultiInstance(const char *name)
Definition: detect-engine.c:1403
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
LiveDeviceGetById
LiveDevice * LiveDeviceGetById(const int id)
Definition: util-device.c:460
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:4968
DetectEngineCtx_::mpm_cfg
MpmConfig * mpm_cfg
Definition: detect.h:1002
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:487
DetectAppLayerMultiRegisterSubState
void DetectAppLayerMultiRegisterSubState(const char *name, AppProto alproto, uint32_t dir, uint8_t sub_state, uint8_t progress, InspectionMultiBufferGetDataPtr GetData, int priority)
Definition: detect-engine.c:2318
SCSigSignatureOrderingModuleCleanup
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
Definition: detect-engine-sigorder.c:946
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1483
DetectEngineCtx_::keyword_id
int keyword_id
Definition: detect.h:1105
MpmTableElmt_::CacheStatsPrint
void(* CacheStatsPrint)(void *data)
Definition: util-mpm.h:195
DetectEngineBufferTypeGetByIdTransforms
int DetectEngineBufferTypeGetByIdTransforms(DetectEngineCtx *de_ctx, const int id, TransformData *transforms, uint8_t transform_cnt)
Definition: detect-engine.c:1849
DetectEngineMultiTenantSetup
int DetectEngineMultiTenantSetup(const bool unix_socket)
setup multi-detect / multi-tenancy
Definition: detect-engine.c:4602
PrefilterDeinit
void PrefilterDeinit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:1550
SignatureProperties
Definition: detect.h:90
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
DetectBufferMpmRegistry_::next
struct DetectBufferMpmRegistry_ * next
Definition: detect.h:834
util-var-name.h
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:258
HashTable_
Definition: util-hash.h:35
DetectEngineTenantMapping_::next
struct DetectEngineTenantMapping_ * next
Definition: detect.h:1759
DetectEngineSetEvent
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
Definition: detect-engine.c:5328
SIG_FLAG_TXBOTHDIR
#define SIG_FLAG_TXBOTHDIR
Definition: detect.h:253
DetectEngineThreadCtx_::buffers_size
uint32_t buffers_size
Definition: detect.h:1375
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:467
DetectContentInspectionMatchOnAbsentBuffer
bool DetectContentInspectionMatchOnAbsentBuffer(const SigMatchData *smd)
tells if we should match on absent buffer, because there is an absent keyword being used
Definition: detect-engine-content-inspection.c:789
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:524
DetectEngineCtx_::profile_sgh_ctx
struct SCProfileSghDetectCtx_ * profile_sgh_ctx
Definition: detect.h:1118
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:84
DetectBufferMpmRegistry_
one time registration of keywords at start up
Definition: detect.h:791
SCReferenceConfDeinit
void SCReferenceConfDeinit(DetectEngineCtx *de_ctx)
Definition: util-reference-config.c:72
DE_QUIET
#define DE_QUIET
Definition: detect.h:334
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:237
DetectEngineCtx_::tcp_priorityports
DetectPort * tcp_priorityports
Definition: detect.h:1138
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *de_ctx)
Free a DetectEngineCtx::
Definition: detect-engine.c:2913
DetectEngineThreadCtx_::counter_alerts_overflow
StatsCounterId counter_alerts_overflow
Definition: detect.h:1363
DetectEngineAppInspectionEngine_::sm_list_base
uint16_t sm_list_base
Definition: detect.h:429
SigTableElmt_::TransformId
void(* TransformId)(const uint8_t **data, uint32_t *length, const void *context)
Definition: detect.h:1518
DetectEngineThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: detect.h:1348
DetectEngineReloadTenantsBlocking
int DetectEngineReloadTenantsBlocking(const int reload_cnt)
Reload all tenants and wait for loading to complete.
Definition: detect-engine.c:4467
InspectionBuffer::flags
uint8_t flags
Definition: detect-engine-inspect-buffer.h:39
detect-engine-frame.h
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
p
Packet * p
Definition: fuzz_dataset.c:30
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:759
SCInstance_::conf_filename
const char * conf_filename
Definition: suricata.h:178
DetectEngineCtx_::prefilter_setting
enum DetectEnginePrefilterSetting prefilter_setting
Definition: detect.h:1134
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:625
DetectParseDupSigHashFree
void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
Frees the hash table that is used to cull duplicate sigs.
Definition: detect-parse.c:3627
DetectBufferType_
Definition: detect.h:454
m
SCMutex m
Definition: flow-hash.h:6
DetectEngineCtx_::udp_priorityports
DetectPort * udp_priorityports
Definition: detect.h:1139
DetectContentData_
Definition: detect-content.h:93
SCConfYamlLoadFileWithPrefix
int SCConfYamlLoadFileWithPrefix(const char *filename, const char *prefix)
Load configuration from a YAML file, insert in tree at 'prefix'.
Definition: conf-yaml-loader.c:566
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:587
PrefilterGenericMpmFrameRegister
int PrefilterGenericMpmFrameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-frame.c:209
ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL
Definition: detect.h:1253
DetectEngineGetVersion
uint32_t DetectEngineGetVersion(void)
Definition: detect-engine.c:4124
DetectEngineThreadCtx_::counter_alerts_suppressed
StatsCounterId counter_alerts_suppressed
Definition: detect.h:1367
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:878
SleepUsec
#define SleepUsec(usec)
Definition: tm-threads.h:44
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:56
DetectEngineThreadCtx_::lua_instruction_limit_errors
StatsCounterId lua_instruction_limit_errors
Definition: detect.h:1462
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:245
detect-engine-payload.h
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3882
DetectEngineThreadCtx_::counter_firewall_discarded_alerts
StatsCounterId counter_firewall_discarded_alerts
Definition: detect.h:1365
EngineModeIsFirewall
bool EngineModeIsFirewall(void)
Definition: suricata.c:239
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:275
DetectMd5ValidateCallback
bool DetectMd5ValidateCallback(const Signature *s, const char **sigerror, const DetectBufferType *map)
Definition: detect-engine.c:5334
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
DetectEngineMpmCachingEnabled
bool DetectEngineMpmCachingEnabled(void)
Definition: detect-engine.c:2684
DetectBufferIsPresent
bool DetectBufferIsPresent(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1698
SigMatchData_
Data needed for Match()
Definition: detect.h:369
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:50
SigMatchData_::type
uint16_t type
Definition: detect.h:370
DetectEngineCtx_::version
uint32_t version
Definition: detect.h:1080
DetectPort_::port2
uint16_t port2
Definition: detect.h:225
StatsRegisterAvgCounter
StatsCounterAvgId StatsRegisterAvgCounter(const char *name, StatsThreadContext *stats)
Registers a counter, whose value holds the average of all the values assigned to it.
Definition: counters.c:1058
DetectEngineCtx_::non_pf_engine_names
HashTable * non_pf_engine_names
Definition: detect.h:1212
SCDetectThreadCtxGetGlobalKeywordThreadCtx
void * SCDetectThreadCtxGetGlobalKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:4098
DetectEngineThreadCtx_::events
uint16_t events
Definition: detect.h:1453
detect-engine-prefilter.h
util-unittest.h
TransformData_
Definition: detect.h:390
PrefilterMultiGenericMpmRegister
int PrefilterMultiGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1784
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:755
DetectAppLayerInspectEngineRegister
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, uint8_t progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
Definition: detect-engine.c:276
DetectBufferTypeCloseRegistration
void DetectBufferTypeCloseRegistration(void)
Definition: detect-engine.c:1842
DetectEnginePktInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:501
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectBufferType_::SetupCallback
void(* SetupCallback)(const struct DetectEngineCtx_ *, struct Signature_ *, const struct DetectBufferType_ *)
Definition: detect.h:467
SIGMATCH_BAN_FIREWALL_MODE
#define SIGMATCH_BAN_FIREWALL_MODE
Definition: detect-engine-register.h:362
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
HashTableFree
void HashTableFree(HashTable *ht)
Free a HashTable and all its contents.
Definition: util-hash.c:112
MpmConfig_::cache_dir_path
const char * cache_dir_path
Definition: util-mpm.h:106
TenantLoaderCtx_
Definition: detect-engine.c:4322
SCAppLayerDecoderEventsSetEventRaw
void SCAppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
Definition: app-layer-events.c:97
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1453
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:1423
DetectEngineFrameInspectionEngine::Callback
InspectionBufferFrameInspectFunc Callback
Definition: detect.h:525
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:244
InspectionBufferMultipleForList::size
uint32_t size
Definition: detect.h:385
SCRConfDeInitContext
void SCRConfDeInitContext(DetectEngineCtx *de_ctx)
Releases de_ctx resources related to Reference Config API.
Definition: util-reference-config.c:180
DetectEngineThreadCtx_::mt_det_ctxs_hash
HashTable * mt_det_ctxs_hash
Definition: detect.h:1328
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:1999
DETECT_PREFILTER_AUTO
@ DETECT_PREFILTER_AUTO
Definition: detect.h:927
DetectEngineThreadCtx_::keyword_ctxs_size
int keyword_ctxs_size
Definition: detect.h:1447
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:269
AlertQueueInit
void AlertQueueInit(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine-alert.c:267
SigString_::sig_error
char * sig_error
Definition: detect.h:900
DetectEngineAppInspectionEngine_::id
uint8_t id
Definition: detect.h:423
DetectBufferTypeSetRunAlways
void DetectBufferTypeSetRunAlways(const char *name)
Definition: detect-engine.c:1561
PacketQueue_::mutex_q
SCMutex mutex_q
Definition: packet-queue.h:56
DetectEngineCtx_::base64_decode_max_len
uint16_t base64_decode_max_len
Definition: detect.h:1090
SIGNATURE_HOOK_TYPE_APP
@ SIGNATURE_HOOK_TYPE_APP
Definition: detect.h:558
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:46
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1366
SCConfInit
void SCConfInit(void)
Initialize the configuration system.
Definition: conf.c:121
DetectEngineThreadCtx_::multi_inspect
struct DetectEngineThreadCtx_::@102 multi_inspect
util-signal.h
SCConfDump
void SCConfDump(void)
Dump configuration to stdout.
Definition: conf.c:818
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:428
TENANT_SELECTOR_UNKNOWN
@ TENANT_SELECTOR_UNKNOWN
Definition: detect.h:1747
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
InspectionBufferMultipleForList
Definition: detect.h:383
DetectEngineTenantMapping_::tenant_id
uint32_t tenant_id
Definition: detect.h:1754
ThreadVars_::tmm_flags
uint8_t tmm_flags
Definition: threadvars.h:78
StringParseUint8
int StringParseUint8(uint8_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:323
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:128
MPM_AC_KS
@ MPM_AC_KS
Definition: util-mpm.h:53
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:274
app-layer-htp.h
DetectEngineTenantSelectors
DetectEngineTenantSelectors
Definition: detect.h:1746
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1135
InspectionBufferPktInspectFunc
int(* InspectionBufferPktInspectFunc)(struct DetectEngineThreadCtx_ *, const struct DetectEnginePktInspectionEngine *engine, const struct Signature_ *s, Packet *p, uint8_t *alert_flags)
Definition: detect.h:480
datasets.h
InspectionBufferFree
void InspectionBufferFree(InspectionBuffer *buffer)
Definition: detect-engine-inspect-buffer.c:205
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:1205
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:312
SCRunmodeGet
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:301
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
DetectBufferType_::ValidateCallback
bool(* ValidateCallback)(const struct Signature_ *, const char **sigerror, const struct DetectBufferType_ *)
Definition: detect.h:469
DetectEngineMoveToFreeList
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:5028
DetectEngineCtx_::fw_policies
struct DetectFirewallPolicies * fw_policies
Definition: detect.h:1026
SigTableElmt_::TransformValidate
bool(* TransformValidate)(const uint8_t *content, uint16_t content_len, const void *context)
Definition: detect.h:1515
DetectEngineThreadCtx_::counter_mpm_list
StatsCounterAvgId counter_mpm_list
Definition: detect.h:1369
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
util-error.h
DetectTableToString
const char * DetectTableToString(enum DetectTable table)
Definition: detect-engine.c:134
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint8_t matcher)
Definition: util-spm.c:148
DETECT_DNP3IND
@ DETECT_DNP3IND
Definition: detect-engine-register.h:260
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
SCProfilingPrefilterDestroyCtx
void SCProfilingPrefilterDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-prefilter.c:236
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:495
DetectEngineThreadCtx_::match_array_len
uint32_t match_array_len
Definition: detect.h:1413
DetectMpmInitializePktMpms
void DetectMpmInitializePktMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:710
DetectAppLayerMpmMultiRegisterSubState
void DetectAppLayerMpmMultiRegisterSubState(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData, AppProto alproto, uint8_t sub_state, uint8_t tx_min_progress)
Definition: detect-engine-mpm.c:192
DetectEngineThreadCtx_
Definition: detect.h:1316
DetectEngineThreadCtx_::lua_memory_limit_errors
StatsCounterId lua_memory_limit_errors
Definition: detect.h:1465
PKT_STREAM_ADD
#define PKT_STREAM_ADD
Definition: decode.h:1305
DetectLoadersInit
void DetectLoadersInit(void)
Definition: detect-engine-loader.c:615
ThreadVars_::tm_slots
struct TmSlot_ * tm_slots
Definition: threadvars.h:95
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:640
DetectEngineBufferTypeGetDescriptionById
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1581
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
DETECT_SM_LIST_BASE64_DATA
@ DETECT_SM_LIST_BASE64_DATA
Definition: detect.h:125
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:262
DetectEngineThreadKeywordCtxItem_::id
int id
Definition: detect.h:920
ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
Definition: detect.h:1254
PKT_PSEUDO_STREAM_END
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1313
DetectEngineThreadCtx_::buffers
InspectionBuffer * buffers
Definition: detect.h:1374
detect-engine-file.h
DetectEngineMasterCtx_::keyword_list
DetectEngineThreadKeywordCtxItem * keyword_list
Definition: detect.h:1789
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:638
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:269
flow-worker.h
SCConfGetInt
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:441
DetectEngineMasterCtx_::tenant_selector
enum DetectEngineTenantSelectors tenant_selector
Definition: detect.h:1780
DetectEngineCtx_::keyword_hash
HashListTable * keyword_hash
Definition: detect.h:1107
BOOL2STR
#define BOOL2STR(b)
Definition: util-debug.h:542
DetectPktInspectEngineRegister
void DetectPktInspectEngineRegister(const char *name, InspectionBufferGetPktDataPtr GetPktData, InspectionBufferPktInspectFunc Callback)
register inspect engine at start up time
Definition: detect-engine.c:159
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:602
DetectEngineCtx_::failure_fatal
bool failure_fatal
Definition: detect.h:996
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:754
DetectEngineAppInspectionEngine_::GetMultiData
InspectionMultiBufferGetDataPtr GetMultiData
Definition: detect.h:437
DetectEngineCtx_::max_flowbits
uint8_t max_flowbits
Definition: detect.h:999
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect-engine-mpm.h
DetectMetadataHashFree
void DetectMetadataHashFree(DetectEngineCtx *de_ctx)
Definition: detect-metadata.c:80
DetectBufferTypeMaxId
int DetectBufferTypeMaxId(void)
Definition: detect-engine.c:1210
DatasetPostReloadCleanup
void DatasetPostReloadCleanup(void)
Definition: datasets.c:565
SCConfGetNonNull
int SCConfGetNonNull(const char *name, const char **vptr)
Retrieve the non-null value of a configuration node.
Definition: conf.c:381
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
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:1726
DetectEngineCtx_::sm_types_prefilter
bool * sm_types_prefilter
Definition: detect.h:1181
DetectEngineEnabled
int DetectEngineEnabled(void)
Check if detection is enabled.
Definition: detect-engine.c:4110
SigMatchList2DataArray
SigMatchData * SigMatchList2DataArray(SigMatch *head)
convert SigMatch list to SigMatchData array
Definition: detect-parse.c:2677
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3661
MpmTableElmt_::CacheStatsDeinit
void(* CacheStatsDeinit)(void *data)
Definition: util-mpm.h:196
DetectEngineReloadIsIdle
int DetectEngineReloadIsIdle(void)
Definition: detect-engine.c:2117
DetectEngineFrameInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:522
DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_MATCH
Definition: detect-engine-state.h:41
DetectEngineBufferTypeSetRunAlways
void DetectEngineBufferTypeSetRunAlways(DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1570
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1350
InspectionSingleBufferGetDataPtr
bool(* InspectionSingleBufferGetDataPtr)(const void *txv, const uint8_t flow_flags, const uint8_t **buf, uint32_t *buf_len)
Definition: detect-engine-helper.h:45
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:364
DetectEngineCtx_::mpm_matcher
uint8_t mpm_matcher
Definition: detect.h:998
DETECT_TABLE_PACKET_PRE_FLOW
@ DETECT_TABLE_PACKET_PRE_FLOW
Definition: detect.h:566
detect-engine-port.h
LiveDevice_::tenant_id
uint32_t tenant_id
Definition: util-device-private.h:46
SCClassConfDeinit
void SCClassConfDeinit(DetectEngineCtx *de_ctx)
Definition: util-classification-config.c:81
InspectionBuffer::inspect_offset
uint64_t inspect_offset
Definition: detect-engine-inspect-buffer.h:36
DETECT_TABLE_PACKET_FILTER
@ DETECT_TABLE_PACKET_FILTER
Definition: detect.h:568
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:1161
DetectEngineMasterCtx_::free_list
DetectEngineCtx * free_list
Definition: detect.h:1778
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:269
DetectEngineSyncState
DetectEngineSyncState
Definition: detect-engine.c:2069
LiveDevice_::dev
char * dev
Definition: util-device-private.h:33
DetectEngineThreadKeywordCtxItem_::next
struct DetectEngineThreadKeywordCtxItem_ * next
Definition: detect.h:919
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:118
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:132
DetectEngineBufferTypeRegister
int DetectEngineBufferTypeRegister(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1540
DetectPort_
Port structure for detection engine.
Definition: detect.h:223
DetectEngineThreadCtx_::json_content_capacity
uint8_t json_content_capacity
Definition: detect.h:1354
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:753
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:363
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:124
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 uint64_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:751
SignatureInitData_::hook
SignatureHook hook
Definition: detect.h:604
AppLayerParserGetStateProgress
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *tx, uint8_t flags)
get the progress value for a tx/protocol
Definition: app-layer-parser.c:1199
DetectEngineThreadCtx_::lua_rule_errors
StatsCounterId lua_rule_errors
Definition: detect.h:1456
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:331
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:1399
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2371
detect-engine-tag.h
util-profiling.h
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:87
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:4439
TmModuleDetectLoaderRegister
void TmModuleDetectLoaderRegister(void)
Definition: detect-engine-loader.c:776
Signature_::flags
uint32_t flags
Definition: detect.h:693
DetectEngineFrameInspectionEngine::v1
struct DetectEngineFrameInspectionEngine::@86 v1
DetectBufferType_::xform_id
TransformIdData xform_id[DETECT_TRANSFORMS_MAX]
Definition: detect.h:472
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2874
RuleMatchCandidateTxArrayFree
void RuleMatchCandidateTxArrayFree(DetectEngineThreadCtx *det_ctx)
Definition: detect.c:1193
DetectEngineInitializeFastPatternList
void DetectEngineInitializeFastPatternList(DetectEngineCtx *de_ctx)
Definition: detect-fast-pattern.c:149
Packet_
Definition: decode.h:516
DetectEngineFrameInspectionEngine::alproto
AppProto alproto
Definition: detect.h:518
DE_STATE_FLAG_BASE
#define DE_STATE_FLAG_BASE
Definition: detect-engine-state.h:66
detect-engine-build.h
PatternMatchThreadPrepare
void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:993
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:481
DetectEngineTenantRegisterLivedev
int DetectEngineTenantRegisterLivedev(uint32_t tenant_id, int device_id)
Definition: detect-engine.c:4885
PcapPacketVars_::tenant_id
uint32_t tenant_id
Definition: source-pcap.h:39
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:1590
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:513
MpmTableElmt_::CacheStatsInit
void *(* CacheStatsInit)(void)
Definition: util-mpm.h:194
DetectEngineCtx_::frame_mpms_list
DetectBufferMpmRegistry * frame_mpms_list
Definition: detect.h:1162
MPM_AC
@ MPM_AC
Definition: util-mpm.h:52
detect-engine-alert.h
conf.h
DetectEngineCtx_::sgh_mpm_ctx_cnf
uint8_t sgh_mpm_ctx_cnf
Definition: detect.h:1103
DetectEngineAppInspectionEngine_::match_on_null
bool match_on_null
Definition: detect.h:427
DetectBufferType_::packet
bool packet
Definition: detect.h:460
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
DetectEngineMasterCtx_::multi_tenant_enabled
int multi_tenant_enabled
Definition: detect.h:1766
TmModuleGetById
TmModule * TmModuleGetById(int id)
Returns a TM Module by its id.
Definition: tm-modules.c:69
TmSlot_
Definition: tm-threads.h:53
DetectEngineFrameInspectionEngine
Definition: detect.h:517
TenantLoaderCtx
struct TenantLoaderCtx_ TenantLoaderCtx
ENGINE_PROFILE_MEDIUM
@ ENGINE_PROFILE_MEDIUM
Definition: detect.h:1246
util-magic.h
DetectEngineCtx_::max_uniq_toserver_groups
uint16_t max_uniq_toserver_groups
Definition: detect.h:1058
MpmTableElmt_::CacheRuleset
int(* CacheRuleset)(MpmConfig *)
Definition: util-mpm.h:197
DetectEngineBufferTypeGetById
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1473
DETECT_TABLE_PACKET_TD
@ DETECT_TABLE_PACKET_TD
Definition: detect.h:569
TmEcode
TmEcode
Definition: tm-threads-common.h:80
DetectEnginePktInspectionEngine::Callback
InspectionBufferPktInspectFunc Callback
Definition: detect.h:499
ThresholdCacheThreadInit
int ThresholdCacheThreadInit(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine-threshold.c:702
DetectBufferType_::name
char name[64]
Definition: detect.h:455
ALPROTO_DOH2
@ ALPROTO_DOH2
Definition: app-layer-protos.h:66
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
DetectEngineSyncer_::state
enum DetectEngineSyncState state
Definition: detect-engine.c:2077
SpmMakeThreadCtx
SpmThreadCtx * SpmMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:163
SCReferenceSCConfInit
void SCReferenceSCConfInit(DetectEngineCtx *de_ctx)
Definition: util-reference-config.c:52
DetectEngineCtx_::profile_keyword_ctx
struct SCProfileKeywordDetectCtx_ * profile_keyword_ctx
Definition: detect.h:1115
DetectEngineAppInspectionEngine_::GetDataSingle
InspectionSingleBufferGetDataPtr GetDataSingle
Definition: detect.h:436
SCInstance_::additional_configs
const char ** additional_configs
Definition: suricata.h:179
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:1501
reputation.h
SCProfilingPrefilterThreadCleanup
void SCProfilingPrefilterThreadCleanup(DetectEngineThreadCtx *det_ctx)
Definition: util-profiling-prefilter.c:281
SCConfCreateContextBackup
void SCConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:741
util-action.h
HashListTable_
Definition: util-hashlist.h:37
DetectEngineThreadCtxGetJsonContext
int DetectEngineThreadCtxGetJsonContext(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine.c:5419
DetectEngineCtx_::byte_extract_max_local_id
int32_t byte_extract_max_local_id
Definition: detect.h:1077
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:396
DetectEnginePktInspectionEngine::sm_list_base
uint16_t sm_list_base
Definition: detect.h:496
SIG_PROP_FLOW_ACTION_PACKET
@ SIG_PROP_FLOW_ACTION_PACKET
Definition: detect.h:85
DetectEngineMultiTenantEnabled
bool DetectEngineMultiTenantEnabled(void)
Definition: detect-engine.c:4180
signature_properties
const struct SignatureProperties signature_properties[SIG_TYPE_MAX]
Definition: detect-engine.c:119
DetectEngineCtx_::RateFilterCallback
SCDetectRateFilterFunc RateFilterCallback
Definition: detect.h:1217
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:292
PacketQueue_::cond_q
SCCondT cond_q
Definition: packet-queue.h:57
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:329
DetectEngineFrameInspectionEngine::dir
uint8_t dir
Definition: detect.h:519
SIG_FLAG_REQUIRE_STREAM_ONLY
#define SIG_FLAG_REQUIRE_STREAM_ONLY
Definition: detect.h:264
SpmDestroyGlobalThreadCtx
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:154
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
Definition: detect-engine-state.h:42
DetectEngineThreadCtx_::mtc
MpmThreadCtx mtc
Definition: detect.h:1425
DetectEngineRegisterTests
void DetectEngineRegisterTests(void)
Definition: detect-engine.c:5706
SigString_::filename
char * filename
Definition: detect.h:898
DetectBufferType_::multi_instance
bool multi_instance
Definition: detect.h:466
DetectLoaderQueueTask
int DetectLoaderQueueTask(int loader_id, LoaderFunc Func, void *func_ctx, LoaderFreeFunc FreeFunc)
Definition: detect-engine-loader.c:538
DETECT_ENGINE_TYPE_TENANT
@ DETECT_ENGINE_TYPE_TENANT
Definition: detect.h:935
DetectEngineBufferTypeSupportsTransformations
void DetectEngineBufferTypeSupportsTransformations(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1614
PACKET_ALERT_FLAG_STREAM_MATCH
#define PACKET_ALERT_FLAG_STREAM_MATCH
Definition: decode.h:272
InspectionMultiBufferGetDataPtr
bool(* InspectionMultiBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const void *txv, const uint8_t flow_flags, uint32_t local_id, const uint8_t **buf, uint32_t *buf_len)
Definition: detect-engine-helper.h:42
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2300
DetectEngineBufferTypeSupportsMpmGetById
bool DetectEngineBufferTypeSupportsMpmGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1640
DetectAppLayerMpmMultiRegister
void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData, AppProto alproto, uint8_t tx_min_progress)
Definition: detect-engine-mpm.c:184
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:1121
DetectSigmatchListEnumToString
const char * DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
Definition: detect-engine.c:5299
TmModule_
Definition: tm-modules.h:47
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:421
TVT_PPT
@ TVT_PPT
Definition: tm-threads-common.h:88
MpmConfig_::cache_max_age_seconds
uint64_t cache_max_age_seconds
Definition: util-mpm.h:107
SRepReloadComplete
void SRepReloadComplete(void)
Increment effective reputation version after a rule/reputation reload is complete.
Definition: reputation.c:161
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:300
detect-engine-content-inspection.h
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:444
DetectEngineBufferTypeSupportsFramesGetById
bool DetectEngineBufferTypeSupportsFramesGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1649
DetectBufferType_::id
int id
Definition: detect.h:457
DetectEngineCtx_::spm_matcher
uint8_t spm_matcher
Definition: detect.h:1003
DetectEngineBufferTypeRegisterWithFrameEngines
int DetectEngineBufferTypeRegisterWithFrameEngines(DetectEngineCtx *de_ctx, const char *name, const int direction, const AppProto alproto, const uint8_t frame_type)
Definition: detect-engine.c:1506
DetectEnginePktInspectionEngine::GetData
InspectionBufferGetPktDataPtr GetData
Definition: detect.h:498
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:850
ENGINE_PROFILE_UNKNOWN
@ ENGINE_PROFILE_UNKNOWN
Definition: detect.h:1244
DETECT_ENGINE_TYPE_NORMAL
@ DETECT_ENGINE_TYPE_NORMAL
Definition: detect.h:932
FlowWorkerGetDetectCtxPtr
void * FlowWorkerGetDetectCtxPtr(void *flow_worker)
Definition: flow-worker.c:748
detect-fast-pattern.h
APP_LAYER_MAX_PROGRESS
#define APP_LAYER_MAX_PROGRESS
Definition: app-layer-parser.h:81
DetectBufferType_::frame
bool frame
Definition: detect.h:461
DetectEngineBufferTypeSupportsMultiInstanceGetById
bool DetectEngineBufferTypeSupportsMultiInstanceGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1622
th_v
ThreadVars * th_v
Definition: fuzz_dataset.c:29
SCCondSignal
#define SCCondSignal
Definition: threads-debug.h:140
ThreadVars_::inq
Tmq * inq
Definition: threadvars.h:89
util-conf.h
DetectEngineCtx_::sig_stat
SigFileLoaderStat sig_stat
Definition: detect.h:1172
Packet_::flow
struct Flow_ * flow
Definition: decode.h:564
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:480
DetectEngineThreadCtx_::to_clear_queue
uint32_t * to_clear_queue
Definition: detect.h:1377
SpmDestroyThreadCtx
void SpmDestroyThreadCtx(SpmThreadCtx *thread_ctx)
Definition: util-spm.c:173
DetectEngineCtx_::profile_prefilter_ctx
struct SCProfilePrefilterDetectCtx_ * profile_prefilter_ctx
Definition: detect.h:1116
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
TENANT_SELECTOR_DIRECT
@ TENANT_SELECTOR_DIRECT
Definition: detect.h:1748
DETECT_CI_FLAGS_SINGLE
#define DETECT_CI_FLAGS_SINGLE
Definition: detect-engine-content-inspection.h:50
DetectEnginePktInspectionSetup
int DetectEnginePktInspectionSetup(Signature *s)
Definition: detect-engine.c:2047
DetectBufferTypeRegister
int DetectBufferTypeRegister(const char *name)
Definition: detect-engine.c:1389
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:415
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:3964
DetectAppLayerMultiRegister
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, uint8_t progress, InspectionMultiBufferGetDataPtr GetData, int priority)
Definition: detect-engine.c:2330
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:1495
DetectEngineMasterCtx_::keyword_id
int keyword_id
Definition: detect.h:1790
DetectEngineCtx_::app_mpms_list
DetectBufferMpmRegistry * app_mpms_list
Definition: detect.h:1154
suricata-common.h
DetectEnginePktInspectionEngine::v1
struct DetectEnginePktInspectionEngine::@85 v1
SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
@ SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
Definition: detect.h:87
DetectEngineCtxInitStubForMT
DetectEngineCtx * DetectEngineCtxInitStubForMT(void)
Definition: detect-engine.c:2864
SigMatch_::type
uint16_t type
Definition: detect.h:361
DetectBufferTypeSupportsMpm
void DetectBufferTypeSupportsMpm(const char *name)
Definition: detect-engine.c:1433
util-path.h
DetectEngineThreadCtx_::tenant_id
uint32_t tenant_id
Definition: detect.h:1319
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
DETECT_FIREWALL_POLICY_SIZE
#define DETECT_FIREWALL_POLICY_SIZE
Definition: detect.h:942
detect-byte-extract.h
DetectEngineCtx_::buffer_type_hash_name
HashListTable * buffer_type_hash_name
Definition: detect.h:1149
DetectEngineCtx_::next
struct DetectEngineCtx_ * next
Definition: detect.h:1128
DETECT_TABLE_NOT_SET
@ DETECT_TABLE_NOT_SET
Definition: detect.h:565
AppProtoToStringRaw
const char * AppProtoToStringRaw(AppProto alproto)
Maps the ALPROTO_*, to its registered string equivalent.
Definition: app-layer-protos.c:43
DETECT_ENGINE_TYPE_DD_STUB
@ DETECT_ENGINE_TYPE_DD_STUB
Definition: detect.h:933
TENANT_SELECTOR_VLAN
@ TENANT_SELECTOR_VLAN
Definition: detect.h:1749
DetectEngineBumpVersion
void DetectEngineBumpVersion(void)
Definition: detect-engine.c:4134
DetectEngineFrameInspectionEngine::next
struct DetectEngineFrameInspectionEngine * next
Definition: detect.h:530
SignatureHook_::type
enum SignatureHookType type
Definition: detect.h:584
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:563
Packet_::livedev_id
uint16_t livedev_id
Definition: decode.h:633
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3906
util-spm.h
DetectEnginePktInspectionEngine::next
struct DetectEnginePktInspectionEngine * next
Definition: detect.h:503
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
DetectEngineCtx_::rate_filter_callback_arg
void * rate_filter_callback_arg
Definition: detect.h:1220
DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT
#define DETECT_ENGINE_DEFAULT_INSPECTION_RECURSION_LIMIT
Definition: detect-engine.c:96
version
uint8_t version
Definition: decode-gre.h:1
MpmConfig_::cache_stats
void * cache_stats
Definition: util-mpm.h:108
detect-engine-buffer.h
PostRuleMatchWorkQueue::q
PostRuleMatchWorkQueueItem * q
Definition: detect.h:1298
TransformIdData_::id_data_len
uint32_t id_data_len
Definition: detect.h:451
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:936
AppLayerParserGetSubStateProgressName
const char * AppLayerParserGetSubStateProgressName(const AppProto alproto, const uint8_t sub_state, const uint8_t state, const uint8_t dir_flag)
Definition: app-layer-parser.c:1277
util-classification-config.h
SCConfDeInit
void SCConfDeInit(void)
De-initializes the configuration system.
Definition: conf.c:760
DetectEngineTenantRegisterPcapFile
int DetectEngineTenantRegisterPcapFile(uint32_t tenant_id)
Definition: detect-engine.c:4901
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:517
SigGroupHeadHashFree
void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by SigGroupHeadHashInit() function.
Definition: detect-engine-siggroup.c:299
SCAppLayerDecoderEventsFreeEvents
void SCAppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
Definition: app-layer-events.c:138
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)
Definition: detect-engine.c:2156
DetectEngineAppInspectionEngineSignatureFree
void DetectEngineAppInspectionEngineSignatureFree(DetectEngineCtx *de_ctx, Signature *s)
free app inspect engines for a signature
Definition: detect-engine.c:1104
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:130
DetectEngineCtx_::loader_id
int loader_id
Definition: detect.h:1131
SCInstance_::sig_file
char * sig_file
Definition: suricata.h:139
TransformData_::transform
int transform
Definition: detect.h:391
DETECT_ENGINE_INSPECT_SIG_NO_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
Definition: detect-engine-state.h:40
DetectEngineCtx_::pkt_inspect_engines
DetectEnginePktInspectionEngine * pkt_inspect_engines
Definition: detect.h:1158
DetectEngineBufferTypeSupportsMpm
void DetectEngineBufferTypeSupportsMpm(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1606
SIG_TYPE_MAX
@ SIG_TYPE_MAX
Definition: detect.h:80
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
DetectEngineCtx_::sm_types_silent_error
bool * sm_types_silent_error
Definition: detect.h:1182
DetectEngineThreadKeywordCtxItem_::FreeFunc
void(* FreeFunc)(void *)
Definition: detect.h:917
DetectAppLayerInspectEngineRegisterSubState
void DetectAppLayerInspectEngineRegisterSubState(const char *name, AppProto alproto, uint32_t dir, uint8_t sub_state, uint8_t progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
register an app inspection engine for a tx type
Definition: detect-engine.c:299
app-layer-events.h
SignatureInitDataBuffer_::only_ts
bool only_ts
Definition: detect.h:541
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:260
DetectEngineFreeFastPatternList
void DetectEngineFreeFastPatternList(DetectEngineCtx *de_ctx)
Definition: detect-fast-pattern.c:171
SIGMATCH_INFO_BITFLAGS_UINT
#define SIGMATCH_INFO_BITFLAGS_UINT
Definition: detect-engine-register.h:358
DetectBufferTypeSupportsTransformations
void DetectBufferTypeSupportsTransformations(const char *name)
Definition: detect-engine.c:1443
detect-engine-sigorder.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectEngineMpmCachingGetPath
const char * DetectEngineMpmCachingGetPath(void)
Definition: detect-engine.c:2693
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
DETECT_ENGINE_MPM_CACHE_OP_SAVE
#define DETECT_ENGINE_MPM_CACHE_OP_SAVE
Definition: detect.h:1799
DetectAddressMapInit
int DetectAddressMapInit(DetectEngineCtx *de_ctx)
Definition: detect-engine-address.c:1329
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:111
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect-engine-inspect-buffer.h:37
SignatureInitData_::buffers
SignatureInitDataBuffer * buffers
Definition: detect.h:671
DetectEngineCtx_::app_inspect_engines
DetectEngineAppInspectionEngine * app_inspect_engines
Definition: detect.h:1157
DetectEngineCtx_::filemagic_thread_ctx_id
int filemagic_thread_ctx_id
Definition: detect.h:1049
SigJsonContent
Definition: detect.h:1308
DetectEngineSyncer_
Definition: detect-engine.c:2075
DetectEngineThreadCtx_::global_keyword_ctxs_size
int global_keyword_ctxs_size
Definition: detect.h:1449
DetectEngineThreadCtx_::json_content
SigJsonContent * json_content
Definition: detect.h:1353
PrefilterInit
void PrefilterInit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:1557
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect-engine-inspect-buffer.h:35
str
#define str(s)
Definition: suricata-common.h:322
DetectEngineThreadCtx_::replace
const Signature ** replace
Definition: detect.h:1410
DetectEngineThreadCtx_::tv
ThreadVars * tv
Definition: detect.h:1324
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:184
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
DETECT_TBLSIZE
int DETECT_TBLSIZE
Definition: detect-engine-register.c:263
SRepInit
int SRepInit(DetectEngineCtx *de_ctx)
init reputation
Definition: reputation.c:557
DetectEngineReloadStart
int DetectEngineReloadStart(void)
Definition: detect-engine.c:2083
DetectEngineUnsetParseMetadata
void DetectEngineUnsetParseMetadata(void)
Definition: detect-engine.c:5289
PKT_SRC_DETECT_RELOAD_FLUSH
@ PKT_SRC_DETECT_RELOAD_FLUSH
Definition: decode.h:61
DetectEngineThreadCtx_::keyword_ctxs_array
void ** keyword_ctxs_array
Definition: detect.h:1446
SCFree
#define SCFree(p)
Definition: util-mem.h:61
AppLayerParserGetSubStateName
const char * AppLayerParserGetSubStateName(const AppProto alproto, const uint8_t sub_state)
Definition: app-layer-parser.c:1326
DetectEngineAppInspectionEngine_::sub_state
uint8_t sub_state
Definition: detect.h:431
DetectEngineMasterCtx_
Definition: detect.h:1762
Signature_::id
uint32_t id
Definition: detect.h:741
ENGINE_PROFILE_CUSTOM
@ ENGINE_PROFILE_CUSTOM
Definition: detect.h:1248
HashListTableBucket_
Definition: util-hashlist.h:28
DetectEngineThreadKeywordCtxItem_::name
const char * name
Definition: detect.h:921
detect-tcphdr.h
DetectEngineCtx_::guess_applayer_log_limit
uint8_t guess_applayer_log_limit
Definition: detect.h:1043
HashListTableRemove
int HashListTableRemove(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:154
DatasetReload
void DatasetReload(void)
Definition: datasets.c:539
ENGINE_PROFILE_LOW
@ ENGINE_PROFILE_LOW
Definition: detect.h:1245
DetectBufferType_::transforms
DetectEngineTransforms transforms
Definition: detect.h:471
detect-engine-iponly.h
SCConfRestoreContextBackup
void SCConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:751
DetectEngineType
DetectEngineType
Definition: detect.h:931
detect-parse.h
SignatureInitDataBuffer_::id
uint32_t id
Definition: detect.h:534
Signature_
Signature container.
Definition: detect.h:692
SigMatch_
a single match condition for a signature
Definition: detect.h:360
DetectEngineCtx_::tenant_path
char * tenant_path
Definition: detect.h:1202
DetectEngineAppInspectionEngine_::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:441
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:136
DetectBufferType_::parent_id
int parent_id
Definition: detect.h:458
DETECT_PREFILTER_MPM
@ DETECT_PREFILTER_MPM
Definition: detect.h:926
TenantLoaderCtx_::yaml
char * yaml
Definition: detect-engine.c:4325
DetectBufferType_::run_always
bool run_always
Definition: detect.h:464
TransformIdData_::id_data
const uint8_t * id_data
Definition: detect.h:450
DetectLoadersSync
int DetectLoadersSync(void)
wait for loader tasks to complete
Definition: detect-engine-loader.c:572
SCProfilingSghDestroyCtx
void SCProfilingSghDestroyCtx(DetectEngineCtx *de_ctx)
Definition: util-profiling-rulegroups.c:286
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:1757
AppLayerParserGetTxEndState
uint8_t AppLayerParserGetTxEndState(uint8_t ipproto, AppProto alproto, void *tx, uint8_t flags)
get the end state (progress) for a transaction.
Definition: app-layer-parser.c:1177
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:33
spm_table
SpmTableElmt spm_table[SPM_TABLE_SIZE]
Definition: util-spm.c:63
DetectEngineReference
DetectEngineCtx * DetectEngineReference(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:4166
SCDetectEngineRegisterRateFilterCallback
bool SCDetectEngineRegisterRateFilterCallback(SCDetectRateFilterFunc fn, void *arg)
Register a callback when a rate_filter has been applied to an alert.
Definition: detect-engine.c:5406
DetectEngineThreadCtx_::base64_decoded
uint8_t * base64_decoded
Definition: detect.h:1398
TenantLoaderCtx_::reload_cnt
int reload_cnt
Definition: detect-engine.c:4324
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:316
EngineModeIsIPS
int EngineModeIsIPS(void)
Definition: suricata.c:246
MpmTableElmt_::ConfigDeinit
void(* ConfigDeinit)(MpmConfig **)
Definition: util-mpm.h:176
DetectEngineThreadCtx_::de_ctx
DetectEngineCtx * de_ctx
Definition: detect.h:1444
InspectionBufferSetupMultiEmpty
void InspectionBufferSetupMultiEmpty(InspectionBuffer *buffer)
setup the buffer empty
Definition: detect-engine-inspect-buffer.c:144
suricata.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:1014
MpmTableElmt_::ConfigCacheDirSet
void(* ConfigCacheDirSet)(MpmConfig *, const char *dir_path)
Definition: util-mpm.h:177
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-engine-helper.h:39
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:422
PmqFree
void PmqFree(PrefilterRuleStore *pmq)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
MpmTableElmt_::CachePrune
int(* CachePrune)(MpmConfig *)
Definition: util-mpm.h:198
DETECT_ENGINE_TYPE_MT_STUB
@ DETECT_ENGINE_TYPE_MT_STUB
Definition: detect.h:934
SCConfNode_::name
char * name
Definition: conf.h:38
SignatureInitDataBuffer_::only_tc
bool only_tc
Definition: detect.h:540
detect-uricontent.h
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:1151
Packet_::vlan_id
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition: decode.h:543
RUNMODE_CONF_TEST
@ RUNMODE_CONF_TEST
Definition: runmodes.h:56
ENGINE_PROFILE_HIGH
@ ENGINE_PROFILE_HIGH
Definition: detect.h:1247
DetectEngineReload
int DetectEngineReload(const SCInstance *suri)
Reload the detection engine.
Definition: detect-engine.c:5095
DetectEngineBufferRunValidateCallback
bool DetectEngineBufferRunValidateCallback(const DetectEngineCtx *de_ctx, const int id, const Signature *s, const char **sigerror)
Definition: detect-engine.c:1687
DetectEngineCtx_::sigerror
const char * sigerror
Definition: detect.h:1095
DetectEngineThreadCtx_::json_content_len
uint8_t json_content_len
Definition: detect.h:1355
DetectEngineThreadCtx_::mt_det_ctxs_cnt
uint32_t mt_det_ctxs_cnt
Definition: detect.h:1326
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:772
DetectEngineMasterCtx_::lock
SCMutex lock
Definition: detect.h:1763
DetectEnginePktInspectionEngine::mpm
bool mpm
Definition: detect.h:494
SCInstance_
Definition: suricata.h:134
DetectEngineCtx_::spm_global_thread_ctx
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition: detect.h:1053
DetectEngineClearMaster
void DetectEngineClearMaster(void)
Definition: detect-engine.c:5068
DetectEngineThreadCtx_::counter_match_list
StatsCounterAvgId counter_match_list
Definition: detect.h:1370
SRepDestroy
void SRepDestroy(DetectEngineCtx *de_ctx)
Definition: reputation.c:640
MpmTableElmt_::ConfigInit
MpmConfig *(* ConfigInit)(void)
Definition: util-mpm.h:175
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:997
AppLayerParserSupportsSubStates
bool AppLayerParserSupportsSubStates(const AppProto alproto)
Definition: app-layer-parser.c:1356
SIG_PROP_FLOW_ACTION_FLOW
@ SIG_PROP_FLOW_ACTION_FLOW
Definition: detect.h:86
DetectBufferTypeSetDescriptionByName
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
Definition: detect-engine.c:1550
DetectFirewallPolicies::app_policies
HashTable * app_policies
Definition: detect.h:968
SigString_::sig_str
char * sig_str
Definition: detect.h:899
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:4016
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:140
DetectAppLayerInspectEngineRegisterSingle
void DetectAppLayerInspectEngineRegisterSingle(const char *name, AppProto alproto, uint32_t dir, uint8_t progress, InspectEngineFuncPtr Callback, InspectionSingleBufferGetDataPtr GetData)
Definition: detect-engine.c:322
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:480
Signature_::msg
char * msg
Definition: detect.h:764
DetectEngineTenantRegisterVlanId
int DetectEngineTenantRegisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
Definition: detect-engine.c:4891
flow.h
SIGMATCH_STATEFUL
#define SIGMATCH_STATEFUL
Definition: detect-engine-register.h:356
DetectEngineSetParseMetadata
void DetectEngineSetParseMetadata(void)
Definition: detect-engine.c:5284
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:95
SCDetectRegisterThreadCtxGlobalFuncs
int SCDetectRegisterThreadCtxGlobalFuncs(const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *))
Register Thread keyword context Funcs (Global)
Definition: detect-engine.c:4054
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:250
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:670
SpmDestroyCtx
void SpmDestroyCtx(SpmCtx *ctx)
Definition: util-spm.c:193
TENANT_SELECTOR_LIVEDEV
@ TENANT_SELECTOR_LIVEDEV
Definition: detect.h:1750
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
DetectEngineFrameInspectionEngine::type
uint8_t type
Definition: detect.h:520
DetectSigmatchListEnum
DetectSigmatchListEnum
Definition: detect.h:116
DetectEngineMasterCtx_::version
uint32_t version
Definition: detect.h:1769
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectEngineCtx_::sig_array_len
uint32_t sig_array_len
Definition: detect.h:1015
util-enum.h
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
SCConfNode_
Definition: conf.h:37
DetectEngineTenantUnregisterPcapFile
int DetectEngineTenantUnregisterPcapFile(uint32_t tenant_id)
Definition: detect-engine.c:4907
TenantLoaderCtx_::tenant_id
uint32_t tenant_id
Definition: detect-engine.c:4323
DetectEngineCtx_::signum
uint32_t signum
Definition: detect.h:1017
DetectEngineCtx_::tenant_id
uint32_t tenant_id
Definition: detect.h:1000
SignatureInitData_::buffer_index
uint32_t buffer_index
Definition: detect.h:672
detect-engine-loader.h
SigFileLoaderStat_
Signature loader statistics.
Definition: detect.h:906
SCConfNode_::val
char * val
Definition: conf.h:39
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:2428
DetectEngineCtx_::buffer_type_hash_id
HashListTable * buffer_type_hash_id
Definition: detect.h:1150
DetectEngineGetByTenantId
DetectEngineCtx * DetectEngineGetByTenantId(uint32_t tenant_id)
Definition: detect-engine.c:4918
SpmInitCtx
SpmCtx * SpmInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:183
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:133
SCMutex
#define SCMutex
Definition: threads-debug.h:114
DetectEngineTransforms::cnt
uint8_t cnt
Definition: detect.h:397
InspectionBufferMultipleForList::inspection_buffers
InspectionBuffer * inspection_buffers
Definition: detect.h:384
DetectLowerSetupCallback
void DetectLowerSetupCallback(const DetectEngineCtx *de_ctx, Signature *s, const DetectBufferType *map)
Definition: detect-engine.c:5375
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
DetectEngineAppInspectionEngine2Signature
int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:939
SCClassConfLoadClassificationConfigFile
bool SCClassConfLoadClassificationConfigFile(DetectEngineCtx *de_ctx, FILE *fd)
Loads the Classtype info from the classification.config file.
Definition: util-classification-config.c:520
InspectionBufferSetupMulti
void InspectionBufferSetupMulti(DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, const DetectEngineTransforms *transforms, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine-inspect-buffer.c:157
DetectEngineThreadCtx_::lua_blocked_function_errors
StatsCounterId lua_blocked_function_errors
Definition: detect.h:1459
DetectEngineTenantUnregisterVlanId
int DetectEngineTenantUnregisterVlanId(uint32_t tenant_id, uint16_t vlan_id)
Definition: detect-engine.c:4896
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:988
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:80
VarNameStoreActivate
int VarNameStoreActivate(void)
Definition: util-var-name.c:222
InspectionBufferMultipleForListGet
InspectionBuffer * InspectionBufferMultipleForListGet(DetectEngineThreadCtx *det_ctx, const int list_id, const uint32_t local_id)
for a InspectionBufferMultipleForList get a InspectionBuffer
Definition: detect-engine-inspect-buffer.c:76
RuleMatchCandidateTxArrayInit
void RuleMatchCandidateTxArrayInit(DetectEngineThreadCtx *det_ctx, uint32_t size)
Definition: detect.c:1180
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:2097
DetectEngineThreadCtx_::post_rule_work_queue
PostRuleMatchWorkQueue post_rule_work_queue
Definition: detect.h:1427
DetectEngineThreadCtx_::tenant_array_size
uint32_t tenant_array_size
Definition: detect.h:1331
DetectEngineThreadCtx_::tenant_array
struct DetectEngineTenantMapping_ * tenant_array
Definition: detect.h:1330
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:176
detect-engine-threshold.h
TM_FLAG_FLOWWORKER_TM
#define TM_FLAG_FLOWWORKER_TM
Definition: tm-modules.h:34
FlowWorkerReplaceDetectCtx
void FlowWorkerReplaceDetectCtx(void *flow_worker, void *detect_ctx)
Definition: flow-worker.c:741
StringHashDjb2
uint32_t StringHashDjb2(const uint8_t *data, uint32_t datalen)
Definition: util-hash-string.c:22
DetectEngineThreadCtx_::TenantGetId
uint32_t(* TenantGetId)(const void *, const Packet *p)
Definition: detect.h:1333
DetectEngineAppInspectionEngine_::progress
uint8_t progress
Definition: detect.h:430
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:191
PrefilterPktNonPFStatsDump
void PrefilterPktNonPFStatsDump(void)
Definition: detect-engine-prefilter.c:632
f
Flow f
Definition: fuzz_dataset.c:32
DetectBufferType_::description
char description[128]
Definition: detect.h:456
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:257
DetectEngineFrameInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:529
DetectEngineThreadCtx_::match_array
Signature ** match_array
Definition: detect.h:1407