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