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