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