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