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