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