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