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