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