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