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