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