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