suricata
util-mpm-hs.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2016 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 Jim Xu <jim.xu@windriver.com>
22  * \author Justin Viiret <justin.viiret@intel.com>
23  *
24  * MPM pattern matcher that calls the Hyperscan regex matcher.
25  */
26 
27 #include "suricata-common.h"
28 #include "suricata.h"
29 
30 #include "detect.h"
31 #include "detect-parse.h"
32 #include "detect-engine.h"
33 #include "detect-engine-build.h"
34 
35 #include "conf.h"
36 #include "util-conf.h"
37 #include "util-debug.h"
38 #include "util-unittest.h"
39 #include "util-unittest-helper.h"
40 #include "util-memcmp.h"
41 #include "util-mpm-hs.h"
42 #include "util-mpm-hs-cache.h"
43 #include "util-mpm-hs-core.h"
44 #include "util-memcpy.h"
45 #include "util-hash.h"
46 #include "util-hash-lookup3.h"
47 #include "util-hyperscan.h"
48 #include "util-path.h"
49 
50 #ifdef BUILD_HYPERSCAN
51 
52 #include <hs.h>
53 
54 void SCHSInitCtx(MpmCtx *);
55 void SCHSInitThreadCtx(MpmCtx *, MpmThreadCtx *);
56 void SCHSDestroyCtx(MpmCtx *);
57 void SCHSDestroyThreadCtx(MpmCtx *, MpmThreadCtx *);
58 int SCHSAddPatternCI(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
59  uint32_t, SigIntId, uint8_t);
60 int SCHSAddPatternCS(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
61  uint32_t, SigIntId, uint8_t);
62 int SCHSPreparePatterns(MpmConfig *mpm_conf, MpmCtx *mpm_ctx);
63 uint32_t SCHSSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
64  PrefilterRuleStore *pmq, const uint8_t *buf, const uint32_t buflen);
65 void SCHSPrintInfo(MpmCtx *mpm_ctx);
66 void SCHSPrintSearchStats(MpmThreadCtx *mpm_thread_ctx);
67 #ifdef UNITTESTS
68 static void SCHSRegisterTests(void);
69 #endif
70 
71 /* size of the hash table used to speed up pattern insertions initially */
72 #define INIT_HASH_SIZE 65536
73 
74 /* Initial size of the global database hash (used for de-duplication). */
75 #define INIT_DB_HASH_SIZE 1000
76 
77 /* Global prototype scratch, built incrementally as Hyperscan databases are
78  * built and then cloned for each thread context. Access is serialised via
79  * g_scratch_proto_mutex. */
80 static hs_scratch_t *g_scratch_proto = NULL;
81 static SCMutex g_scratch_proto_mutex = SCMUTEX_INITIALIZER;
82 
83 /* Global hash table of Hyperscan databases, used for de-duplication. Access is
84  * serialised via g_db_table_mutex. */
85 static HashTable *g_db_table = NULL;
86 static SCMutex g_db_table_mutex = SCMUTEX_INITIALIZER;
87 
88 /**
89  * \internal
90  * \brief Wraps SCMalloc (which is a macro) so that it can be passed to
91  * hs_set_allocator() for Hyperscan's use.
92  */
93 static void *SCHSMalloc(size_t size)
94 {
95  return SCMalloc(size);
96 }
97 
98 /**
99  * \internal
100  * \brief Wraps SCFree (which is a macro) so that it can be passed to
101  * hs_set_allocator() for Hyperscan's use.
102  */
103 static void SCHSFree(void *ptr)
104 {
105  SCFree(ptr);
106 }
107 
108 /** \brief Register Suricata malloc/free with Hyperscan.
109  *
110  * Requests that Hyperscan use Suricata's allocator for allocation of
111  * databases, scratch space, etc.
112  */
113 static void SCHSSetAllocators(void)
114 {
115  hs_error_t err = hs_set_allocator(SCHSMalloc, SCHSFree);
116  if (err != HS_SUCCESS) {
117  FatalError("Failed to set Hyperscan allocator.");
118  }
119 }
120 
121 /**
122  * \internal
123  * \brief Creates a hash of the pattern. We use it for the hashing process
124  * during the initial pattern insertion time, to cull duplicate sigs.
125  *
126  * \param pat Pointer to the pattern.
127  * \param patlen Pattern length.
128  *
129  * \retval hash A 32 bit unsigned hash.
130  */
131 static inline uint32_t SCHSInitHashRaw(uint8_t *pat, uint16_t patlen)
132 {
133  uint32_t hash = patlen * pat[0];
134  if (patlen > 1)
135  hash += pat[1];
136 
137  return (hash % INIT_HASH_SIZE);
138 }
139 
140 /**
141  * \internal
142  * \brief Looks up a pattern. We use it for the hashing process during
143  * the initial pattern insertion time, to cull duplicate sigs.
144  *
145  * \param ctx Pointer to the HS ctx.
146  * \param pat Pointer to the pattern.
147  * \param patlen Pattern length.
148  * \param flags Flags. We don't need this.
149  *
150  * \retval hash A 32 bit unsigned hash.
151  */
152 static inline SCHSPattern *SCHSInitHashLookup(SCHSCtx *ctx, uint8_t *pat,
153  uint16_t patlen, uint16_t offset,
154  uint16_t depth, char flags,
155  uint32_t pid)
156 {
157  uint32_t hash = SCHSInitHashRaw(pat, patlen);
158 
159  if (ctx->init_hash == NULL) {
160  return NULL;
161  }
162 
163  SCHSPattern *t = ctx->init_hash[hash];
164  for (; t != NULL; t = t->next) {
165  /* Since Hyperscan uses offset/depth, we must distinguish between
166  * patterns with the same ID but different offset/depth here. */
167  if (t->id == pid && t->offset == offset && t->depth == depth) {
168  BUG_ON(t->len != patlen);
169  BUG_ON(SCMemcmp(t->original_pat, pat, patlen) != 0);
170  return t;
171  }
172  }
173 
174  return NULL;
175 }
176 
177 /**
178  * \internal
179  * \brief Allocates a new pattern instance.
180  *
181  * \param mpm_ctx Pointer to the mpm context.
182  *
183  * \retval p Pointer to the newly created pattern.
184  */
185 static inline SCHSPattern *SCHSAllocPattern(MpmCtx *mpm_ctx)
186 {
187  SCHSPattern *p = SCCalloc(1, sizeof(SCHSPattern));
188  if (unlikely(p == NULL)) {
189  exit(EXIT_FAILURE);
190  }
191 
192  mpm_ctx->memory_cnt++;
193  mpm_ctx->memory_size += sizeof(SCHSPattern);
194 
195  return p;
196 }
197 
198 /**
199  * \internal
200  * \brief Used to free SCHSPattern instances.
201  *
202  * \param mpm_ctx Pointer to the mpm context.
203  * \param p Pointer to the SCHSPattern instance to be freed.
204  * \param free Free the above pointer or not.
205  */
206 static inline void SCHSFreePattern(MpmCtx *mpm_ctx, SCHSPattern *p)
207 {
208  if (p != NULL && p->original_pat != NULL) {
209  SCFree(p->original_pat);
210  mpm_ctx->memory_cnt--;
211  mpm_ctx->memory_size -= p->len;
212  }
213 
214  if (p != NULL && p->sids != NULL) {
215  SCFree(p->sids);
216  }
217 
218  if (p != NULL) {
219  SCFree(p);
220  mpm_ctx->memory_cnt--;
221  mpm_ctx->memory_size -= sizeof(SCHSPattern);
222  }
223 }
224 
225 static inline uint32_t SCHSInitHash(SCHSPattern *p)
226 {
227  uint32_t hash = p->len * p->original_pat[0];
228  if (p->len > 1)
229  hash += p->original_pat[1];
230 
231  return (hash % INIT_HASH_SIZE);
232 }
233 
234 static inline int SCHSInitHashAdd(SCHSCtx *ctx, SCHSPattern *p)
235 {
236  uint32_t hash = SCHSInitHash(p);
237 
238  if (ctx->init_hash == NULL) {
239  return -1;
240  }
241 
242  if (ctx->init_hash[hash] == NULL) {
243  ctx->init_hash[hash] = p;
244  return 0;
245  }
246 
247  SCHSPattern *tt = NULL;
248  SCHSPattern *t = ctx->init_hash[hash];
249 
250  /* get the list tail */
251  do {
252  tt = t;
253  t = t->next;
254  } while (t != NULL);
255 
256  tt->next = p;
257 
258  return 0;
259 }
260 
261 /**
262  * \internal
263  * \brief Add a pattern to the mpm-hs context.
264  *
265  * \param mpm_ctx Mpm context.
266  * \param pat Pointer to the pattern.
267  * \param patlen Length of the pattern.
268  * \param pid Pattern id
269  * \param sid Signature id (internal id).
270  * \param flags Pattern's MPM_PATTERN_* flags.
271  *
272  * \retval 0 On success.
273  * \retval -1 On failure.
274  */
275 static int SCHSAddPattern(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
276  uint16_t offset, uint16_t depth, uint32_t pid,
277  SigIntId sid, uint8_t flags)
278 {
279  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
280 
281  if (offset != 0) {
283  }
284  if (depth != 0) {
286  }
287 
288  if (patlen == 0) {
289  SCLogWarning("pattern length 0");
290  return 0;
291  }
292 
293  /* check if we have already inserted this pattern */
294  SCHSPattern *p =
295  SCHSInitHashLookup(ctx, pat, patlen, offset, depth, flags, pid);
296  if (p == NULL) {
297  SCLogDebug("Allocing new pattern");
298 
299  /* p will never be NULL */
300  p = SCHSAllocPattern(mpm_ctx);
301 
302  p->len = patlen;
303  p->flags = flags;
304  p->id = pid;
305 
306  p->offset = offset;
307  p->depth = depth;
308 
309  p->original_pat = SCMalloc(patlen);
310  if (p->original_pat == NULL)
311  goto error;
312  mpm_ctx->memory_cnt++;
313  mpm_ctx->memory_size += patlen;
314  memcpy(p->original_pat, pat, patlen);
315 
316  /* put in the pattern hash */
317  if (SCHSInitHashAdd(ctx, p) != 0)
318  goto error;
319 
320  mpm_ctx->pattern_cnt++;
321 
322  if (!(mpm_ctx->flags & MPMCTX_FLAGS_NODEPTH)) {
323  if (depth) {
324  mpm_ctx->maxdepth = MAX(mpm_ctx->maxdepth, depth);
325  SCLogDebug("%p: depth %u max %u", mpm_ctx, depth, mpm_ctx->maxdepth);
326  } else {
327  mpm_ctx->flags |= MPMCTX_FLAGS_NODEPTH;
328  mpm_ctx->maxdepth = 0;
329  SCLogDebug("%p: alas, no depth for us", mpm_ctx);
330  }
331  }
332 
333  if (mpm_ctx->maxlen < patlen)
334  mpm_ctx->maxlen = patlen;
335 
336  if (mpm_ctx->minlen == 0) {
337  mpm_ctx->minlen = patlen;
338  } else {
339  if (mpm_ctx->minlen > patlen)
340  mpm_ctx->minlen = patlen;
341  }
342 
343  p->sids_size = 1;
344  p->sids = SCMalloc(p->sids_size * sizeof(SigIntId));
345  BUG_ON(p->sids == NULL);
346  p->sids[0] = sid;
347  } else {
348  /* TODO figure out how we can be called multiple times for the same CTX with the same sid */
349 
350  int found = 0;
351  uint32_t x = 0;
352  for (x = 0; x < p->sids_size; x++) {
353  if (p->sids[x] == sid) {
354  found = 1;
355  break;
356  }
357  }
358  if (!found) {
359  SigIntId *sids = SCRealloc(p->sids, (sizeof(SigIntId) * (p->sids_size + 1)));
360  BUG_ON(sids == NULL);
361  p->sids = sids;
362  p->sids[p->sids_size] = sid;
363  p->sids_size++;
364  }
365  }
366 
367  return 0;
368 
369 error:
370  SCHSFreePattern(mpm_ctx, p);
371  return -1;
372 }
373 
374 /**
375  * \brief Pattern database information used only as input to the Hyperscan
376  * compiler.
377  */
378 typedef struct SCHSCompileData_ {
379  unsigned int *ids;
380  unsigned int *flags;
381  char **expressions;
382  hs_expr_ext_t **ext;
383  unsigned int pattern_cnt;
384 } SCHSCompileData;
385 
386 static SCHSCompileData *CompileDataAlloc(unsigned int pattern_cnt)
387 {
388  SCHSCompileData *cd = SCCalloc(pattern_cnt, sizeof(SCHSCompileData));
389  if (cd == NULL) {
390  goto error;
391  }
392 
393  cd->pattern_cnt = pattern_cnt;
394 
395  cd->ids = SCCalloc(pattern_cnt, sizeof(unsigned int));
396  if (cd->ids == NULL) {
397  goto error;
398  }
399 
400  cd->flags = SCCalloc(pattern_cnt, sizeof(unsigned int));
401  if (cd->flags == NULL) {
402  goto error;
403  }
404 
405  cd->expressions = SCCalloc(pattern_cnt, sizeof(char *));
406  if (cd->expressions == NULL) {
407  goto error;
408  }
409 
410  cd->ext = SCCalloc(pattern_cnt, sizeof(hs_expr_ext_t *));
411  if (cd->ext == NULL) {
412  goto error;
413  }
414 
415  return cd;
416 
417 error:
418  SCLogDebug("SCHSCompileData alloc failed");
419  if (cd) {
420  SCFree(cd->ids);
421  SCFree(cd->flags);
422  SCFree(cd->expressions);
423  SCFree(cd->ext);
424  SCFree(cd);
425  }
426  return NULL;
427 }
428 
429 static void CompileDataFree(SCHSCompileData *cd)
430 {
431  if (cd == NULL) {
432  return;
433  }
434 
435  SCFree(cd->ids);
436  SCFree(cd->flags);
437  if (cd->expressions) {
438  for (unsigned int i = 0; i < cd->pattern_cnt; i++) {
439  SCFree(cd->expressions[i]);
440  }
441  SCFree(cd->expressions);
442  }
443  if (cd->ext) {
444  for (unsigned int i = 0; i < cd->pattern_cnt; i++) {
445  SCFree(cd->ext[i]);
446  }
447  SCFree(cd->ext);
448  }
449  SCFree(cd);
450 }
451 
452 static uint32_t SCHSPatternHash(const SCHSPattern *p, uint32_t hash)
453 {
454  BUG_ON(p->original_pat == NULL);
455  BUG_ON(p->sids == NULL);
456 
457  hash = hashlittle_safe(&p->len, sizeof(p->len), hash);
458  hash = hashlittle_safe(&p->flags, sizeof(p->flags), hash);
459  hash = hashlittle_safe(p->original_pat, p->len, hash);
460  hash = hashlittle_safe(&p->id, sizeof(p->id), hash);
461  hash = hashlittle_safe(&p->offset, sizeof(p->offset), hash);
462  hash = hashlittle_safe(&p->depth, sizeof(p->depth), hash);
463  hash = hashlittle_safe(&p->sids_size, sizeof(p->sids_size), hash);
464  hash = hashlittle_safe(p->sids, p->sids_size * sizeof(SigIntId), hash);
465  return hash;
466 }
467 
468 static char SCHSPatternCompare(const SCHSPattern *p1, const SCHSPattern *p2)
469 {
470  if ((p1->len != p2->len) || (p1->flags != p2->flags) ||
471  (p1->id != p2->id) || (p1->offset != p2->offset) ||
472  (p1->depth != p2->depth) || (p1->sids_size != p2->sids_size)) {
473  return 0;
474  }
475 
476  if (SCMemcmp(p1->original_pat, p2->original_pat, p1->len) != 0) {
477  return 0;
478  }
479 
480  if (SCMemcmp(p1->sids, p2->sids, p1->sids_size * sizeof(p1->sids[0])) !=
481  0) {
482  return 0;
483  }
484 
485  return 1;
486 }
487 
488 static uint32_t PatternDatabaseHash(HashTable *ht, void *data, uint16_t len)
489 {
490  const PatternDatabase *pd = data;
491  uint32_t hash = 0;
492  hash = hashword(&pd->pattern_cnt, 1, hash);
493 
494  for (uint32_t i = 0; i < pd->pattern_cnt; i++) {
495  hash = SCHSPatternHash(pd->parray[i], hash);
496  }
497 
498  hash %= ht->array_size;
499  return hash;
500 }
501 
502 static char PatternDatabaseCompare(void *data1, uint16_t len1, void *data2,
503  uint16_t len2)
504 {
505  const PatternDatabase *pd1 = data1;
506  const PatternDatabase *pd2 = data2;
507 
508  if (pd1->pattern_cnt != pd2->pattern_cnt) {
509  return 0;
510  }
511 
512  for (uint32_t i = 0; i < pd1->pattern_cnt; i++) {
513  if (SCHSPatternCompare(pd1->parray[i], pd2->parray[i]) == 0) {
514  return 0;
515  }
516  }
517 
518  return 1;
519 }
520 
521 static void PatternDatabaseFree(PatternDatabase *pd)
522 {
523  BUG_ON(pd->ref_cnt != 0);
524 
525  if (pd->parray != NULL) {
526  for (uint32_t i = 0; i < pd->pattern_cnt; i++) {
527  SCHSPattern *p = pd->parray[i];
528  if (p != NULL) {
529  SCFree(p->original_pat);
530  SCFree(p->sids);
531  SCFree(p);
532  }
533  }
534  SCFree(pd->parray);
535  }
536 
537  hs_free_database(pd->hs_db);
538 
539  SCFree(pd);
540 }
541 
542 static void PatternDatabaseTableFree(void *data)
543 {
544  /* Stub function handed to hash table; actual freeing of PatternDatabase
545  * structures is done in MPM destruction when the ref_cnt drops to zero. */
546 }
547 
548 static PatternDatabase *PatternDatabaseAlloc(uint32_t pattern_cnt)
549 {
550  PatternDatabase *pd = SCCalloc(1, sizeof(PatternDatabase));
551  if (pd == NULL) {
552  return NULL;
553  }
554  pd->pattern_cnt = pattern_cnt;
555  pd->ref_cnt = 0;
556  pd->hs_db = NULL;
557  pd->cached = false;
558 
559  /* alloc the pattern array */
560  pd->parray = (SCHSPattern **)SCCalloc(pd->pattern_cnt, sizeof(SCHSPattern *));
561  if (pd->parray == NULL) {
562  SCFree(pd);
563  return NULL;
564  }
565 
566  return pd;
567 }
568 
569 static int HSCheckPatterns(MpmCtx *mpm_ctx, SCHSCtx *ctx)
570 {
571  if (mpm_ctx->pattern_cnt == 0 || ctx->init_hash == NULL) {
572  SCLogDebug("no patterns supplied to this mpm_ctx");
573  return 0;
574  }
575  return 1;
576 }
577 
578 static void HSPatternArrayPopulate(SCHSCtx *ctx, PatternDatabase *pd)
579 {
580  for (uint32_t i = 0, p = 0; i < INIT_HASH_SIZE; i++) {
581  SCHSPattern *node = ctx->init_hash[i];
582  SCHSPattern *nnode = NULL;
583  while (node != NULL) {
584  nnode = node->next;
585  node->next = NULL;
586  pd->parray[p++] = node;
587  node = nnode;
588  }
589  }
590 }
591 
592 static void HSPatternArrayInit(SCHSCtx *ctx, PatternDatabase *pd)
593 {
594  HSPatternArrayPopulate(ctx, pd);
595  /* we no longer need the hash, so free its memory */
596  SCFree(ctx->init_hash);
597  ctx->init_hash = NULL;
598 }
599 
600 static int HSGlobalPatternDatabaseInit(void)
601 {
602  if (g_db_table == NULL) {
603  g_db_table = HashTableInit(INIT_DB_HASH_SIZE, PatternDatabaseHash,
604  PatternDatabaseCompare,
605  PatternDatabaseTableFree);
606  if (g_db_table == NULL) {
607  return -1;
608  }
609  }
610  return 0;
611 }
612 
613 static void HSLogCompileError(hs_compile_error_t *compile_err)
614 {
615  SCLogError("failed to compile hyperscan database");
616  if (compile_err) {
617  SCLogError("compile error: %s", compile_err->message);
618  hs_free_compile_error(compile_err);
619  }
620 }
621 
622 static int HSScratchAlloc(const hs_database_t *db)
623 {
624  SCMutexLock(&g_scratch_proto_mutex);
625  hs_error_t err = hs_alloc_scratch(db, &g_scratch_proto);
626  SCMutexUnlock(&g_scratch_proto_mutex);
627  if (err != HS_SUCCESS) {
628  SCLogError("failed to allocate scratch");
629  return -1;
630  }
631  return 0;
632 }
633 
634 static int PatternDatabaseGetSize(PatternDatabase *pd, size_t *db_size)
635 {
636  hs_error_t err = hs_database_size(pd->hs_db, db_size);
637  if (err != HS_SUCCESS) {
638  SCLogError("failed to query database size: %s", HSErrorToStr(err));
639  return -1;
640  }
641  return 0;
642 }
643 
644 static void SCHSCleanupOnError(PatternDatabase *pd, SCHSCompileData *cd)
645 {
646  if (pd) {
647  PatternDatabaseFree(pd);
648  }
649  if (cd) {
650  CompileDataFree(cd);
651  }
652 }
653 
654 static int CompileDataExtensionsInit(hs_expr_ext_t **ext, const SCHSPattern *p)
655 {
656  if (p->flags & (MPM_PATTERN_FLAG_OFFSET | MPM_PATTERN_FLAG_DEPTH)) {
657  *ext = SCCalloc(1, sizeof(hs_expr_ext_t));
658  if ((*ext) == NULL) {
659  return -1;
660  }
661  if (p->flags & MPM_PATTERN_FLAG_OFFSET) {
662  (*ext)->flags |= HS_EXT_FLAG_MIN_OFFSET;
663  (*ext)->min_offset = p->offset + p->len;
664  }
665  if (p->flags & MPM_PATTERN_FLAG_DEPTH) {
666  (*ext)->flags |= HS_EXT_FLAG_MAX_OFFSET;
667  (*ext)->max_offset = p->offset + p->depth;
668  }
669  }
670 
671  return 0;
672 }
673 
674 /**
675  * \brief Initialize the pattern database - try to get existing pd
676  * from the global hash table, or load it from disk if caching is enabled.
677  *
678  * \param PatternDatabase* [in/out] Pointer to the pattern database to use.
679  * \param SCHSCompileData* [in] Pointer to the compile data.
680  * \retval 0 On success, negative value on failure.
681  */
682 static int PatternDatabaseGetCached(
683  PatternDatabase **pd, SCHSCompileData *cd, const char *cache_dir_path)
684 {
685  /* Check global hash table to see if we've seen this pattern database
686  * before, and reuse the Hyperscan database if so. */
687  PatternDatabase *pd_cached = HashTableLookup(g_db_table, *pd, 1);
688  if (pd_cached != NULL) {
689  SCLogDebug("Reusing cached database %p with %" PRIu32
690  " patterns (ref_cnt=%" PRIu32 ")",
691  pd_cached->hs_db, pd_cached->pattern_cnt,
692  pd_cached->ref_cnt);
693  pd_cached->ref_cnt++;
694  PatternDatabaseFree(*pd);
695  CompileDataFree(cd);
696  *pd = pd_cached;
697  return 0;
698  } else if (cache_dir_path) {
699  pd_cached = *pd;
700  uint64_t db_lookup_hash = HSHashDb(pd_cached);
701  if (HSLoadCache(&pd_cached->hs_db, db_lookup_hash, cache_dir_path) == 0) {
702  pd_cached->ref_cnt = 1;
703  pd_cached->cached = true;
704  if (HSScratchAlloc(pd_cached->hs_db) != 0) {
705  goto recover;
706  }
707  if (HashTableAdd(g_db_table, pd_cached, 1) < 0) {
708  goto recover;
709  }
710  CompileDataFree(cd);
711  return 0;
712 
713  recover:
714  pd_cached->ref_cnt = 0;
715  pd_cached->cached = false;
716  return -1;
717  }
718  }
719 
720  return -1; // not cached
721 }
722 
723 static int PatternDatabaseCompile(PatternDatabase *pd, SCHSCompileData *cd)
724 {
725  for (uint32_t i = 0; i < pd->pattern_cnt; i++) {
726  const SCHSPattern *p = pd->parray[i];
727  cd->ids[i] = i;
728  cd->flags[i] = HS_FLAG_SINGLEMATCH;
729  if (p->flags & MPM_PATTERN_FLAG_NOCASE) {
730  cd->flags[i] |= HS_FLAG_CASELESS;
731  }
732  cd->expressions[i] = HSRenderPattern(p->original_pat, p->len);
733  if (CompileDataExtensionsInit(&cd->ext[i], p) != 0) {
734  return -1;
735  }
736  }
737 
738  hs_compile_error_t *compile_err = NULL;
739  hs_error_t err = hs_compile_ext_multi((const char *const *)cd->expressions, cd->flags, cd->ids,
740  (const hs_expr_ext_t *const *)cd->ext, cd->pattern_cnt, HS_MODE_BLOCK, NULL, &pd->hs_db,
741  &compile_err);
742  if (err != HS_SUCCESS) {
743  HSLogCompileError(compile_err);
744  return -1;
745  }
746 
747  if (HSScratchAlloc(pd->hs_db) != 0) {
748  return -1;
749  }
750 
751  if (HashTableAdd(g_db_table, pd, 1) < 0) {
752  return -1;
753  }
754  pd->ref_cnt = 1;
755  return 0;
756 }
757 
758 /**
759  * \brief Process the patterns added to the mpm, and create the internal tables.
760  *
761  * \param mpm_conf Pointer to the generic MPM matcher configuration
762  * \param mpm_ctx Pointer to the mpm context.
763  */
764 int SCHSPreparePatterns(MpmConfig *mpm_conf, MpmCtx *mpm_ctx)
765 {
766  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
767 
768  if (HSCheckPatterns(mpm_ctx, ctx) == 0) {
769  return 0;
770  }
771 
772  SCHSCompileData *cd = CompileDataAlloc(mpm_ctx->pattern_cnt);
773  PatternDatabase *pd = PatternDatabaseAlloc(mpm_ctx->pattern_cnt);
774  if (cd == NULL || pd == NULL) {
775  goto error;
776  }
777 
778  HSPatternArrayInit(ctx, pd);
779  pd->no_cache = !(mpm_ctx->flags & MPMCTX_FLAGS_CACHE_TO_DISK);
780  /* Serialise whole database compilation as a relatively easy way to ensure
781  * dedupe is safe. */
782  SCMutexLock(&g_db_table_mutex);
783  if (HSGlobalPatternDatabaseInit() == -1) {
784  SCMutexUnlock(&g_db_table_mutex);
785  goto error;
786  }
787 
788  const char *cache_path = pd->no_cache || !mpm_conf ? NULL : mpm_conf->cache_dir_path;
789  if (PatternDatabaseGetCached(&pd, cd, cache_path) == 0 && pd != NULL) {
790  cd = NULL;
791  ctx->pattern_db = pd;
792  if (PatternDatabaseGetSize(pd, &ctx->hs_db_size) != 0) {
793  SCMutexUnlock(&g_db_table_mutex);
794  goto error;
795  }
796 
797  if (pd->ref_cnt == 1) {
798  // freshly allocated
799  mpm_ctx->memory_cnt++;
800  mpm_ctx->memory_size += ctx->hs_db_size;
801  }
802  SCMutexUnlock(&g_db_table_mutex);
803  return 0;
804  }
805 
806  BUG_ON(ctx->pattern_db != NULL); /* already built? */
807  BUG_ON(mpm_ctx->pattern_cnt == 0);
808 
809  if (PatternDatabaseCompile(pd, cd) != 0) {
810  SCMutexUnlock(&g_db_table_mutex);
811  goto error;
812  }
813 
814  ctx->pattern_db = pd;
815  if (PatternDatabaseGetSize(pd, &ctx->hs_db_size) != 0) {
816  SCMutexUnlock(&g_db_table_mutex);
817  goto error;
818  }
819 
820  mpm_ctx->memory_cnt++;
821  mpm_ctx->memory_size += ctx->hs_db_size;
822 
823  SCMutexUnlock(&g_db_table_mutex);
824  CompileDataFree(cd);
825  return 0;
826 
827 error:
828  SCHSCleanupOnError(pd, cd);
829  return -1;
830 }
831 
832 /**
833  * \brief Cache the initialized and compiled ruleset
834  */
835 static int SCHSCacheRuleset(MpmConfig *mpm_conf)
836 {
837  if (!mpm_conf || !mpm_conf->cache_dir_path) {
838  return -1;
839  }
840 
841  SCLogDebug("Caching the loaded ruleset to %s", mpm_conf->cache_dir_path);
842  if (SCCreateDirectoryTree(mpm_conf->cache_dir_path, true) != 0) {
843  SCLogWarning("Failed to create Hyperscan cache folder, make sure "
844  "the parent folder is writeable "
845  "or adjust sgh-mpm-caching-path setting (%s)",
846  mpm_conf->cache_dir_path);
847  return -1;
848  }
849  PatternDatabaseCache pd_stats = { 0 };
850  struct HsIteratorData iter_data = { .pd_stats = &pd_stats,
851  .cache_path = mpm_conf->cache_dir_path };
852  SCMutexLock(&g_db_table_mutex);
853  HashTableIterate(g_db_table, HSSaveCacheIterator, &iter_data);
854  SCMutexUnlock(&g_db_table_mutex);
855  SCLogNotice("Rule group caching - loaded: %u newly cached: %u total cacheable: %u",
856  pd_stats.hs_dbs_cache_loaded_cnt, pd_stats.hs_dbs_cache_saved_cnt,
857  pd_stats.hs_cacheable_dbs_cnt);
858  return 0;
859 }
860 
861 /**
862  * \brief Init the mpm thread context.
863  *
864  * \param mpm_ctx Pointer to the mpm context.
865  * \param mpm_thread_ctx Pointer to the mpm thread context.
866  */
867 void SCHSInitThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx)
868 {
869  memset(mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
870 
871  SCHSThreadCtx *ctx = SCCalloc(1, sizeof(SCHSThreadCtx));
872  if (ctx == NULL) {
873  exit(EXIT_FAILURE);
874  }
875  mpm_thread_ctx->ctx = ctx;
876 
877  mpm_thread_ctx->memory_cnt++;
878  mpm_thread_ctx->memory_size += sizeof(SCHSThreadCtx);
879 
880  ctx->scratch = NULL;
881  ctx->scratch_size = 0;
882 
883  SCMutexLock(&g_scratch_proto_mutex);
884 
885  if (g_scratch_proto == NULL) {
886  /* There is no scratch prototype: this means that we have not compiled
887  * any Hyperscan databases. */
888  SCMutexUnlock(&g_scratch_proto_mutex);
889  SCLogDebug("No scratch space prototype");
890  return;
891  }
892 
893  hs_error_t err = hs_clone_scratch(g_scratch_proto,
894  (hs_scratch_t **)&ctx->scratch);
895 
896  SCMutexUnlock(&g_scratch_proto_mutex);
897 
898  if (err != HS_SUCCESS) {
899  FatalError("Unable to clone scratch prototype");
900  }
901 
902  err = hs_scratch_size(ctx->scratch, &ctx->scratch_size);
903  if (err != HS_SUCCESS) {
904  FatalError("Unable to query scratch size");
905  }
906 
907  mpm_thread_ctx->memory_cnt++;
908  mpm_thread_ctx->memory_size += ctx->scratch_size;
909 }
910 
911 /**
912  * \brief Initialize the HS context.
913  *
914  * \param mpm_ctx Mpm context.
915  */
916 void SCHSInitCtx(MpmCtx *mpm_ctx)
917 {
918  if (mpm_ctx->ctx != NULL)
919  return;
920 
921  mpm_ctx->ctx = SCCalloc(1, sizeof(SCHSCtx));
922  if (mpm_ctx->ctx == NULL) {
923  exit(EXIT_FAILURE);
924  }
925 
926  mpm_ctx->memory_cnt++;
927  mpm_ctx->memory_size += sizeof(SCHSCtx);
928 
929  /* initialize the hash we use to speed up pattern insertions */
930  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
931  ctx->init_hash = SCCalloc(INIT_HASH_SIZE, sizeof(SCHSPattern *));
932  if (ctx->init_hash == NULL) {
933  exit(EXIT_FAILURE);
934  }
935 }
936 
937 /**
938  * \brief Destroy the mpm thread context.
939  *
940  * \param mpm_ctx Pointer to the mpm context.
941  * \param mpm_thread_ctx Pointer to the mpm thread context.
942  */
943 void SCHSDestroyThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx)
944 {
945  SCHSPrintSearchStats(mpm_thread_ctx);
946 
947  if (mpm_thread_ctx->ctx != NULL) {
948  SCHSThreadCtx *thr_ctx = (SCHSThreadCtx *)mpm_thread_ctx->ctx;
949 
950  if (thr_ctx->scratch != NULL) {
951  hs_free_scratch(thr_ctx->scratch);
952  mpm_thread_ctx->memory_cnt--;
953  mpm_thread_ctx->memory_size -= thr_ctx->scratch_size;
954  }
955 
956  SCFree(mpm_thread_ctx->ctx);
957  mpm_thread_ctx->ctx = NULL;
958  mpm_thread_ctx->memory_cnt--;
959  mpm_thread_ctx->memory_size -= sizeof(SCHSThreadCtx);
960  }
961 }
962 
963 /**
964  * \brief Destroy the mpm context.
965  *
966  * \param mpm_ctx Pointer to the mpm context.
967  */
968 void SCHSDestroyCtx(MpmCtx *mpm_ctx)
969 {
970  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
971  if (ctx == NULL)
972  return;
973 
974  if (ctx->init_hash != NULL) {
975  SCFree(ctx->init_hash);
976  ctx->init_hash = NULL;
977  mpm_ctx->memory_cnt--;
978  mpm_ctx->memory_size -= (INIT_HASH_SIZE * sizeof(SCHSPattern *));
979  }
980 
981  /* Decrement pattern database ref count, and delete it entirely if the
982  * count has dropped to zero. */
983  SCMutexLock(&g_db_table_mutex);
984  PatternDatabase *pd = ctx->pattern_db;
985  if (pd) {
986  BUG_ON(pd->ref_cnt == 0);
987  pd->ref_cnt--;
988  if (pd->ref_cnt == 0) {
989  HashTableRemove(g_db_table, pd, 1);
990  PatternDatabaseFree(pd);
991  }
992  }
993  SCMutexUnlock(&g_db_table_mutex);
994 
995  SCFree(mpm_ctx->ctx);
996  mpm_ctx->ctx = NULL;
997  mpm_ctx->memory_cnt--;
998  mpm_ctx->memory_size -= sizeof(SCHSCtx);
999 }
1000 
1001 typedef struct SCHSCallbackCtx_ {
1002  SCHSCtx *ctx;
1003  void *pmq;
1004  uint32_t match_count;
1005 } SCHSCallbackCtx;
1006 
1007 /* Hyperscan MPM match event handler */
1008 static int SCHSMatchEvent(unsigned int id, unsigned long long from,
1009  unsigned long long to, unsigned int flags,
1010  void *ctx)
1011 {
1012  SCHSCallbackCtx *cctx = ctx;
1013  PrefilterRuleStore *pmq = cctx->pmq;
1014  const PatternDatabase *pd = cctx->ctx->pattern_db;
1015  const SCHSPattern *pat = pd->parray[id];
1016 
1017  SCLogDebug("Hyperscan Match %" PRIu32 ": id=%" PRIu32 " @ %" PRIuMAX
1018  " (pat id=%" PRIu32 ")",
1019  cctx->match_count, (uint32_t)id, (uintmax_t)to, pat->id);
1020 
1021  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
1022 
1023  cctx->match_count++;
1024  return 0;
1025 }
1026 
1027 /**
1028  * \brief The Hyperscan search function.
1029  *
1030  * \param mpm_ctx Pointer to the mpm context.
1031  * \param mpm_thread_ctx Pointer to the mpm thread context.
1032  * \param pmq Pointer to the Pattern Matcher Queue to hold
1033  * search matches.
1034  * \param buf Buffer to be searched.
1035  * \param buflen Buffer length.
1036  *
1037  * \retval matches Match count.
1038  */
1039 uint32_t SCHSSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
1040  PrefilterRuleStore *pmq, const uint8_t *buf, const uint32_t buflen)
1041 {
1042  uint32_t ret = 0;
1043  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
1044  SCHSThreadCtx *hs_thread_ctx = (SCHSThreadCtx *)(mpm_thread_ctx->ctx);
1045  const PatternDatabase *pd = ctx->pattern_db;
1046 
1047  if (unlikely(buflen == 0)) {
1048  return 0;
1049  }
1050 
1051  SCHSCallbackCtx cctx = {.ctx = ctx, .pmq = pmq, .match_count = 0};
1052 
1053  /* scratch should have been cloned from g_scratch_proto at thread init. */
1054  hs_scratch_t *scratch = hs_thread_ctx->scratch;
1055  BUG_ON(pd->hs_db == NULL);
1056  BUG_ON(scratch == NULL);
1057 
1058  hs_error_t err = hs_scan(pd->hs_db, (const char *)buf, buflen, 0, scratch,
1059  SCHSMatchEvent, &cctx);
1060  if (err != HS_SUCCESS) {
1061  /* An error value (other than HS_SCAN_TERMINATED) from hs_scan()
1062  * indicates that it was passed an invalid database or scratch region,
1063  * which is not something we can recover from at scan time. */
1064  SCLogError("Hyperscan returned error %d", err);
1065  exit(EXIT_FAILURE);
1066  } else {
1067  ret = cctx.match_count;
1068  }
1069 
1070  return ret;
1071 }
1072 
1073 /**
1074  * \brief Add a case insensitive pattern. Although we have different calls for
1075  * adding case sensitive and insensitive patterns, we make a single call
1076  * for either case. No special treatment for either case.
1077  *
1078  * \param mpm_ctx Pointer to the mpm context.
1079  * \param pat The pattern to add.
1080  * \param patlen The pattern length.
1081  * \param offset The pattern offset.
1082  * \param depth The pattern depth.
1083  * \param pid The pattern id.
1084  * \param sid The pattern signature id.
1085  * \param flags Flags associated with this pattern.
1086  *
1087  * \retval 0 On success.
1088  * \retval -1 On failure.
1089  */
1090 int SCHSAddPatternCI(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1091  uint16_t offset, uint16_t depth, uint32_t pid,
1092  SigIntId sid, uint8_t flags)
1093 {
1095  return SCHSAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1096 }
1097 
1098 /**
1099  * \brief Add a case sensitive pattern. Although we have different calls for
1100  * adding case sensitive and insensitive patterns, we make a single call
1101  * for either case. No special treatment for either case.
1102  *
1103  * \param mpm_ctx Pointer to the mpm context.
1104  * \param pat The pattern to add.
1105  * \param patlen The pattern length.
1106  * \param offset The pattern offset.
1107  * \param depth The pattern depth.
1108  * \param pid The pattern id.
1109  * \param sid The pattern signature id.
1110  * \param flags Flags associated with this pattern.
1111  *
1112  * \retval 0 On success.
1113  * \retval -1 On failure.
1114  */
1115 int SCHSAddPatternCS(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1116  uint16_t offset, uint16_t depth, uint32_t pid,
1117  SigIntId sid, uint8_t flags)
1118 {
1119  return SCHSAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1120 }
1121 
1122 void SCHSPrintSearchStats(MpmThreadCtx *mpm_thread_ctx)
1123 {
1124 }
1125 
1126 void SCHSPrintInfo(MpmCtx *mpm_ctx)
1127 {
1128  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
1129 
1130  printf("MPM HS Information:\n");
1131  printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
1132  printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
1133  printf(" Sizeof:\n");
1134  printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
1135  printf(" SCHSCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCHSCtx));
1136  printf(" SCHSPattern %" PRIuMAX "\n", (uintmax_t)sizeof(SCHSPattern));
1137  printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
1138  printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
1139  printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
1140  printf("\n");
1141 
1142  if (ctx) {
1143  PatternDatabase *pd = ctx->pattern_db;
1144  char *db_info = NULL;
1145  if (hs_database_info(pd->hs_db, &db_info) == HS_SUCCESS) {
1146  printf("HS Database Info: %s\n", db_info);
1147  SCFree(db_info);
1148  }
1149  printf("HS Database Size: %" PRIuMAX " bytes\n",
1150  (uintmax_t)ctx->hs_db_size);
1151  }
1152 
1153  printf("\n");
1154 }
1155 
1156 static MpmConfig *SCHSConfigInit(void)
1157 {
1158  MpmConfig *c = SCCalloc(1, sizeof(MpmConfig));
1159  return c;
1160 }
1161 
1162 static void SCHSConfigDeinit(MpmConfig **c)
1163 {
1164  if (c != NULL) {
1165  SCFree(*c);
1166  (*c) = NULL;
1167  }
1168 }
1169 
1170 static void SCHSConfigCacheDirSet(MpmConfig *c, const char *dir_path)
1171 {
1172  c->cache_dir_path = dir_path;
1173 }
1174 
1175 /************************** Mpm Registration ***************************/
1176 
1177 /**
1178  * \brief Register the Hyperscan MPM.
1179  */
1180 void MpmHSRegister(void)
1181 {
1182  mpm_table[MPM_HS].name = "hs";
1183  mpm_table[MPM_HS].InitCtx = SCHSInitCtx;
1184  mpm_table[MPM_HS].InitThreadCtx = SCHSInitThreadCtx;
1185  mpm_table[MPM_HS].DestroyCtx = SCHSDestroyCtx;
1186  mpm_table[MPM_HS].DestroyThreadCtx = SCHSDestroyThreadCtx;
1187  mpm_table[MPM_HS].ConfigInit = SCHSConfigInit;
1188  mpm_table[MPM_HS].ConfigDeinit = SCHSConfigDeinit;
1189  mpm_table[MPM_HS].ConfigCacheDirSet = SCHSConfigCacheDirSet;
1190  mpm_table[MPM_HS].AddPattern = SCHSAddPatternCS;
1191  mpm_table[MPM_HS].AddPatternNocase = SCHSAddPatternCI;
1192  mpm_table[MPM_HS].Prepare = SCHSPreparePatterns;
1193  mpm_table[MPM_HS].CacheRuleset = SCHSCacheRuleset;
1194  mpm_table[MPM_HS].Search = SCHSSearch;
1195  mpm_table[MPM_HS].PrintCtx = SCHSPrintInfo;
1196  mpm_table[MPM_HS].PrintThreadCtx = SCHSPrintSearchStats;
1197 #ifdef UNITTESTS
1198  mpm_table[MPM_HS].RegisterUnittests = SCHSRegisterTests;
1199 #endif
1201  /* Set Hyperscan memory allocators */
1202  SCHSSetAllocators();
1203 }
1204 
1205 /**
1206  * \brief Clean up global memory used by all Hyperscan MPM instances.
1207  *
1208  * Currently, this is just the global scratch prototype.
1209  */
1210 void MpmHSGlobalCleanup(void)
1211 {
1212  SCMutexLock(&g_scratch_proto_mutex);
1213  if (g_scratch_proto) {
1214  SCLogDebug("Cleaning up Hyperscan global scratch");
1215  hs_free_scratch(g_scratch_proto);
1216  g_scratch_proto = NULL;
1217  }
1218  SCMutexUnlock(&g_scratch_proto_mutex);
1219 
1220  SCMutexLock(&g_db_table_mutex);
1221  if (g_db_table != NULL) {
1222  SCLogDebug("Clearing Hyperscan database cache");
1223  HashTableFree(g_db_table);
1224  g_db_table = NULL;
1225  }
1226  SCMutexUnlock(&g_db_table_mutex);
1227 }
1228 
1229 /*************************************Unittests********************************/
1230 
1231 #ifdef UNITTESTS
1232 #include "detect-engine-alert.h"
1233 
1234 static int SCHSTest01(void)
1235 {
1236  int result = 0;
1237  MpmCtx mpm_ctx;
1238  MpmThreadCtx mpm_thread_ctx;
1239  PrefilterRuleStore pmq;
1240 
1241  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1242  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1243  MpmInitCtx(&mpm_ctx, MPM_HS);
1244 
1245  /* 1 match */
1246  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1247  PmqSetup(&pmq);
1248 
1249  SCHSPreparePatterns(NULL, &mpm_ctx);
1250  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1251 
1252  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1253 
1254  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1255  strlen(buf));
1256 
1257  if (cnt == 1)
1258  result = 1;
1259  else
1260  printf("1 != %" PRIu32 " ", cnt);
1261 
1262  SCHSDestroyCtx(&mpm_ctx);
1263  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1264  PmqFree(&pmq);
1265  return result;
1266 }
1267 
1268 static int SCHSTest02(void)
1269 {
1270  int result = 0;
1271  MpmCtx mpm_ctx;
1272  MpmThreadCtx mpm_thread_ctx;
1273  PrefilterRuleStore pmq;
1274 
1275  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1276  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1277  MpmInitCtx(&mpm_ctx, MPM_HS);
1278 
1279  /* 1 match */
1280  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1281  PmqSetup(&pmq);
1282 
1283  SCHSPreparePatterns(NULL, &mpm_ctx);
1284  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1285 
1286  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1287  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1288  strlen(buf));
1289 
1290  if (cnt == 0)
1291  result = 1;
1292  else
1293  printf("0 != %" PRIu32 " ", cnt);
1294 
1295  SCHSDestroyCtx(&mpm_ctx);
1296  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1297  PmqFree(&pmq);
1298  return result;
1299 }
1300 
1301 static int SCHSTest03(void)
1302 {
1303  int result = 0;
1304  MpmCtx mpm_ctx;
1305  MpmThreadCtx mpm_thread_ctx;
1306  PrefilterRuleStore pmq;
1307 
1308  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1309  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1310  MpmInitCtx(&mpm_ctx, MPM_HS);
1311 
1312  /* 1 match */
1313  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1314  /* 1 match */
1315  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1316  /* 1 match */
1317  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1318  PmqSetup(&pmq);
1319 
1320  SCHSPreparePatterns(NULL, &mpm_ctx);
1321  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1322 
1323  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1324  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1325  strlen(buf));
1326 
1327  if (cnt == 3)
1328  result = 1;
1329  else
1330  printf("3 != %" PRIu32 " ", cnt);
1331 
1332  SCHSDestroyCtx(&mpm_ctx);
1333  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1334  PmqFree(&pmq);
1335  return result;
1336 }
1337 
1338 static int SCHSTest04(void)
1339 {
1340  int result = 0;
1341  MpmCtx mpm_ctx;
1342  MpmThreadCtx mpm_thread_ctx;
1343  PrefilterRuleStore pmq;
1344 
1345  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1346  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1347  MpmInitCtx(&mpm_ctx, MPM_HS);
1348 
1349  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1350  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1351  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1352  PmqSetup(&pmq);
1353 
1354  SCHSPreparePatterns(NULL, &mpm_ctx);
1355  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1356 
1357  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1358  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1359  strlen(buf));
1360 
1361  if (cnt == 1)
1362  result = 1;
1363  else
1364  printf("1 != %" PRIu32 " ", cnt);
1365 
1366  SCHSDestroyCtx(&mpm_ctx);
1367  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1368  PmqFree(&pmq);
1369  return result;
1370 }
1371 
1372 static int SCHSTest05(void)
1373 {
1374  int result = 0;
1375  MpmCtx mpm_ctx;
1376  MpmThreadCtx mpm_thread_ctx;
1377  PrefilterRuleStore pmq;
1378 
1379  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1380  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1381  MpmInitCtx(&mpm_ctx, MPM_HS);
1382 
1383  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1384  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1385  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1386  PmqSetup(&pmq);
1387 
1388  SCHSPreparePatterns(NULL, &mpm_ctx);
1389  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1390 
1391  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1392  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1393  strlen(buf));
1394 
1395  if (cnt == 3)
1396  result = 1;
1397  else
1398  printf("3 != %" PRIu32 " ", cnt);
1399 
1400  SCHSDestroyCtx(&mpm_ctx);
1401  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1402  PmqFree(&pmq);
1403  return result;
1404 }
1405 
1406 static int SCHSTest06(void)
1407 {
1408  int result = 0;
1409  MpmCtx mpm_ctx;
1410  MpmThreadCtx mpm_thread_ctx;
1411  PrefilterRuleStore pmq;
1412 
1413  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1414  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1415  MpmInitCtx(&mpm_ctx, MPM_HS);
1416 
1417  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1418  PmqSetup(&pmq);
1419 
1420  SCHSPreparePatterns(NULL, &mpm_ctx);
1421  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1422 
1423  const char *buf = "abcd";
1424  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1425  strlen(buf));
1426 
1427  if (cnt == 1)
1428  result = 1;
1429  else
1430  printf("1 != %" PRIu32 " ", cnt);
1431 
1432  SCHSDestroyCtx(&mpm_ctx);
1433  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1434  PmqFree(&pmq);
1435  return result;
1436 }
1437 
1438 static int SCHSTest07(void)
1439 {
1440  int result = 0;
1441  MpmCtx mpm_ctx;
1442  MpmThreadCtx mpm_thread_ctx;
1443  PrefilterRuleStore pmq;
1444 
1445  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1446  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1447  MpmInitCtx(&mpm_ctx, MPM_HS);
1448 
1449  /* should match 30 times */
1450  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1451  /* should match 29 times */
1452  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1453  /* should match 28 times */
1454  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1455  /* 26 */
1456  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1457  /* 21 */
1458  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1459  /* 1 */
1460  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 30,
1461  0, 0, 5, 0, 0);
1462  PmqSetup(&pmq);
1463 
1464  SCHSPreparePatterns(NULL, &mpm_ctx);
1465  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1466 
1467  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1468  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1469  strlen(buf));
1470 
1471  if (cnt == 6)
1472  result = 1;
1473  else
1474  printf("6 != %" PRIu32 " ", cnt);
1475 
1476  SCHSDestroyCtx(&mpm_ctx);
1477  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1478  PmqFree(&pmq);
1479  return result;
1480 }
1481 
1482 static int SCHSTest08(void)
1483 {
1484  int result = 0;
1485  MpmCtx mpm_ctx;
1486  MpmThreadCtx mpm_thread_ctx;
1487  PrefilterRuleStore pmq;
1488 
1489  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1490  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1491  MpmInitCtx(&mpm_ctx, MPM_HS);
1492 
1493  /* 1 match */
1494  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1495  PmqSetup(&pmq);
1496 
1497  SCHSPreparePatterns(NULL, &mpm_ctx);
1498  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1499 
1500  uint32_t cnt =
1501  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"a", 1);
1502 
1503  if (cnt == 0)
1504  result = 1;
1505  else
1506  printf("0 != %" PRIu32 " ", cnt);
1507 
1508  SCHSDestroyCtx(&mpm_ctx);
1509  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1510  PmqFree(&pmq);
1511  return result;
1512 }
1513 
1514 static int SCHSTest09(void)
1515 {
1516  int result = 0;
1517  MpmCtx mpm_ctx;
1518  MpmThreadCtx mpm_thread_ctx;
1519  PrefilterRuleStore pmq;
1520 
1521  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1522  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1523  MpmInitCtx(&mpm_ctx, MPM_HS);
1524 
1525  /* 1 match */
1526  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1527  PmqSetup(&pmq);
1528 
1529  SCHSPreparePatterns(NULL, &mpm_ctx);
1530  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1531 
1532  uint32_t cnt =
1533  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"ab", 2);
1534 
1535  if (cnt == 1)
1536  result = 1;
1537  else
1538  printf("1 != %" PRIu32 " ", cnt);
1539 
1540  SCHSDestroyCtx(&mpm_ctx);
1541  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1542  PmqFree(&pmq);
1543  return result;
1544 }
1545 
1546 static int SCHSTest10(void)
1547 {
1548  int result = 0;
1549  MpmCtx mpm_ctx;
1550  MpmThreadCtx mpm_thread_ctx;
1551  PrefilterRuleStore pmq;
1552 
1553  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1554  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1555  MpmInitCtx(&mpm_ctx, MPM_HS);
1556 
1557  /* 1 match */
1558  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1559  PmqSetup(&pmq);
1560 
1561  SCHSPreparePatterns(NULL, &mpm_ctx);
1562  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1563 
1564  const char *buf = "01234567890123456789012345678901234567890123456789"
1565  "01234567890123456789012345678901234567890123456789"
1566  "abcdefgh"
1567  "01234567890123456789012345678901234567890123456789"
1568  "01234567890123456789012345678901234567890123456789";
1569  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1570  strlen(buf));
1571 
1572  if (cnt == 1)
1573  result = 1;
1574  else
1575  printf("1 != %" PRIu32 " ", cnt);
1576 
1577  SCHSDestroyCtx(&mpm_ctx);
1578  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1579  PmqFree(&pmq);
1580  return result;
1581 }
1582 
1583 static int SCHSTest11(void)
1584 {
1585  int result = 0;
1586  MpmCtx mpm_ctx;
1587  MpmThreadCtx mpm_thread_ctx;
1588  PrefilterRuleStore pmq;
1589 
1590  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1591  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1592  MpmInitCtx(&mpm_ctx, MPM_HS);
1593 
1594  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1595  goto end;
1596  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1597  goto end;
1598  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1599  goto end;
1600  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1601  goto end;
1602  PmqSetup(&pmq);
1603 
1604  if (SCHSPreparePatterns(NULL, &mpm_ctx) == -1)
1605  goto end;
1606 
1607  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1608 
1609  result = 1;
1610 
1611  const char *buf = "he";
1612  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1613  strlen(buf)) == 1);
1614  buf = "she";
1615  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1616  strlen(buf)) == 2);
1617  buf = "his";
1618  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1619  strlen(buf)) == 1);
1620  buf = "hers";
1621  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1622  strlen(buf)) == 2);
1623 
1624 end:
1625  SCHSDestroyCtx(&mpm_ctx);
1626  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1627  PmqFree(&pmq);
1628  return result;
1629 }
1630 
1631 static int SCHSTest12(void)
1632 {
1633  int result = 0;
1634  MpmCtx mpm_ctx;
1635  MpmThreadCtx mpm_thread_ctx;
1636  PrefilterRuleStore pmq;
1637 
1638  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1639  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1640  MpmInitCtx(&mpm_ctx, MPM_HS);
1641 
1642  /* 1 match */
1643  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1644  /* 1 match */
1645  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1646  PmqSetup(&pmq);
1647 
1648  SCHSPreparePatterns(NULL, &mpm_ctx);
1649  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1650 
1651  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1652  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1653  strlen(buf));
1654 
1655  if (cnt == 2)
1656  result = 1;
1657  else
1658  printf("2 != %" PRIu32 " ", cnt);
1659 
1660  SCHSDestroyCtx(&mpm_ctx);
1661  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1662  PmqFree(&pmq);
1663  return result;
1664 }
1665 
1666 static int SCHSTest13(void)
1667 {
1668  int result = 0;
1669  MpmCtx mpm_ctx;
1670  MpmThreadCtx mpm_thread_ctx;
1671  PrefilterRuleStore pmq;
1672 
1673  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1674  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1675  MpmInitCtx(&mpm_ctx, MPM_HS);
1676 
1677  /* 1 match */
1678  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1679  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1680  PmqSetup(&pmq);
1681 
1682  SCHSPreparePatterns(NULL, &mpm_ctx);
1683  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1684 
1685  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1686  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1687  strlen(buf));
1688 
1689  if (cnt == 1)
1690  result = 1;
1691  else
1692  printf("1 != %" PRIu32 " ", cnt);
1693 
1694  SCHSDestroyCtx(&mpm_ctx);
1695  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1696  PmqFree(&pmq);
1697  return result;
1698 }
1699 
1700 static int SCHSTest14(void)
1701 {
1702  int result = 0;
1703  MpmCtx mpm_ctx;
1704  MpmThreadCtx mpm_thread_ctx;
1705  PrefilterRuleStore pmq;
1706 
1707  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1708  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1709  MpmInitCtx(&mpm_ctx, MPM_HS);
1710 
1711  /* 1 match */
1712  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1713  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1714  PmqSetup(&pmq);
1715 
1716  SCHSPreparePatterns(NULL, &mpm_ctx);
1717  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1718 
1719  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1720  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1721  strlen(buf));
1722 
1723  if (cnt == 1)
1724  result = 1;
1725  else
1726  printf("1 != %" PRIu32 " ", cnt);
1727 
1728  SCHSDestroyCtx(&mpm_ctx);
1729  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1730  PmqFree(&pmq);
1731  return result;
1732 }
1733 
1734 static int SCHSTest15(void)
1735 {
1736  int result = 0;
1737  MpmCtx mpm_ctx;
1738  MpmThreadCtx mpm_thread_ctx;
1739  PrefilterRuleStore pmq;
1740 
1741  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1742  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1743  MpmInitCtx(&mpm_ctx, MPM_HS);
1744 
1745  /* 1 match */
1746  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1747  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1748  PmqSetup(&pmq);
1749 
1750  SCHSPreparePatterns(NULL, &mpm_ctx);
1751  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1752 
1753  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1754  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1755  strlen(buf));
1756 
1757  if (cnt == 1)
1758  result = 1;
1759  else
1760  printf("1 != %" PRIu32 " ", cnt);
1761 
1762  SCHSDestroyCtx(&mpm_ctx);
1763  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1764  PmqFree(&pmq);
1765  return result;
1766 }
1767 
1768 static int SCHSTest16(void)
1769 {
1770  int result = 0;
1771  MpmCtx mpm_ctx;
1772  MpmThreadCtx mpm_thread_ctx;
1773  PrefilterRuleStore pmq;
1774 
1775  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1776  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1777  MpmInitCtx(&mpm_ctx, MPM_HS);
1778 
1779  /* 1 match */
1780  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1781  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1782  PmqSetup(&pmq);
1783 
1784  SCHSPreparePatterns(NULL, &mpm_ctx);
1785  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1786 
1787  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1788  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1789  strlen(buf));
1790 
1791  if (cnt == 1)
1792  result = 1;
1793  else
1794  printf("1 != %" PRIu32 " ", cnt);
1795 
1796  SCHSDestroyCtx(&mpm_ctx);
1797  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1798  PmqFree(&pmq);
1799  return result;
1800 }
1801 
1802 static int SCHSTest17(void)
1803 {
1804  int result = 0;
1805  MpmCtx mpm_ctx;
1806  MpmThreadCtx mpm_thread_ctx;
1807  PrefilterRuleStore pmq;
1808 
1809  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1810  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1811  MpmInitCtx(&mpm_ctx, MPM_HS);
1812 
1813  /* 1 match */
1814  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1815  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1816  PmqSetup(&pmq);
1817 
1818  SCHSPreparePatterns(NULL, &mpm_ctx);
1819  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1820 
1821  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1822  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1823  strlen(buf));
1824 
1825  if (cnt == 1)
1826  result = 1;
1827  else
1828  printf("1 != %" PRIu32 " ", cnt);
1829 
1830  SCHSDestroyCtx(&mpm_ctx);
1831  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1832  PmqFree(&pmq);
1833  return result;
1834 }
1835 
1836 static int SCHSTest18(void)
1837 {
1838  int result = 0;
1839  MpmCtx mpm_ctx;
1840  MpmThreadCtx mpm_thread_ctx;
1841  PrefilterRuleStore pmq;
1842 
1843  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1844  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1845  MpmInitCtx(&mpm_ctx, MPM_HS);
1846 
1847  /* 1 match */
1848  const char pat[] = "abcde"
1849  "fghij"
1850  "klmno"
1851  "pqrst"
1852  "uvwxy"
1853  "z";
1854  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1855  PmqSetup(&pmq);
1856 
1857  SCHSPreparePatterns(NULL, &mpm_ctx);
1858  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1859 
1860  const char *buf = "abcde"
1861  "fghij"
1862  "klmno"
1863  "pqrst"
1864  "uvwxy"
1865  "z";
1866  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1867  strlen(buf));
1868 
1869  if (cnt == 1)
1870  result = 1;
1871  else
1872  printf("1 != %" PRIu32 " ", cnt);
1873 
1874  SCHSDestroyCtx(&mpm_ctx);
1875  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1876  PmqFree(&pmq);
1877  return result;
1878 }
1879 
1880 static int SCHSTest19(void)
1881 {
1882  int result = 0;
1883  MpmCtx mpm_ctx;
1884  MpmThreadCtx mpm_thread_ctx;
1885  PrefilterRuleStore pmq;
1886 
1887  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1888  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1889  MpmInitCtx(&mpm_ctx, MPM_HS);
1890 
1891  /* 1 */
1892  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1893  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1894  PmqSetup(&pmq);
1895 
1896  SCHSPreparePatterns(NULL, &mpm_ctx);
1897  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1898 
1899  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1900  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1901  strlen(buf));
1902 
1903  if (cnt == 1)
1904  result = 1;
1905  else
1906  printf("1 != %" PRIu32 " ", cnt);
1907 
1908  SCHSDestroyCtx(&mpm_ctx);
1909  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1910  PmqFree(&pmq);
1911  return result;
1912 }
1913 
1914 static int SCHSTest20(void)
1915 {
1916  int result = 0;
1917  MpmCtx mpm_ctx;
1918  MpmThreadCtx mpm_thread_ctx;
1919  PrefilterRuleStore pmq;
1920 
1921  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1922  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1923  MpmInitCtx(&mpm_ctx, MPM_HS);
1924 
1925  /* 1 */
1926  const char pat[] = "AAAAA"
1927  "AAAAA"
1928  "AAAAA"
1929  "AAAAA"
1930  "AAAAA"
1931  "AAAAA"
1932  "AA";
1933  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1934  PmqSetup(&pmq);
1935 
1936  SCHSPreparePatterns(NULL, &mpm_ctx);
1937  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1938 
1939  const char *buf = "AAAAA"
1940  "AAAAA"
1941  "AAAAA"
1942  "AAAAA"
1943  "AAAAA"
1944  "AAAAA"
1945  "AA";
1946  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1947  strlen(buf));
1948 
1949  if (cnt == 1)
1950  result = 1;
1951  else
1952  printf("1 != %" PRIu32 " ", cnt);
1953 
1954  SCHSDestroyCtx(&mpm_ctx);
1955  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1956  PmqFree(&pmq);
1957  return result;
1958 }
1959 
1960 static int SCHSTest21(void)
1961 {
1962  int result = 0;
1963  MpmCtx mpm_ctx;
1964  MpmThreadCtx mpm_thread_ctx;
1965  PrefilterRuleStore pmq;
1966 
1967  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1968  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1969  MpmInitCtx(&mpm_ctx, MPM_HS);
1970 
1971  /* 1 */
1972  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1973  PmqSetup(&pmq);
1974 
1975  SCHSPreparePatterns(NULL, &mpm_ctx);
1976  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1977 
1978  uint32_t cnt =
1979  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"AA", 2);
1980 
1981  if (cnt == 1)
1982  result = 1;
1983  else
1984  printf("1 != %" PRIu32 " ", cnt);
1985 
1986  SCHSDestroyCtx(&mpm_ctx);
1987  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1988  PmqFree(&pmq);
1989  return result;
1990 }
1991 
1992 static int SCHSTest22(void)
1993 {
1994  int result = 0;
1995  MpmCtx mpm_ctx;
1996  MpmThreadCtx mpm_thread_ctx;
1997  PrefilterRuleStore pmq;
1998 
1999  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2000  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2001  MpmInitCtx(&mpm_ctx, MPM_HS);
2002 
2003  /* 1 match */
2004  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
2005  /* 1 match */
2006  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
2007  PmqSetup(&pmq);
2008 
2009  SCHSPreparePatterns(NULL, &mpm_ctx);
2010  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2011 
2012  const char *buf = "abcdefghijklmnopqrstuvwxyz";
2013  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2014  strlen(buf));
2015 
2016  if (cnt == 2)
2017  result = 1;
2018  else
2019  printf("2 != %" PRIu32 " ", cnt);
2020 
2021  SCHSDestroyCtx(&mpm_ctx);
2022  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2023  PmqFree(&pmq);
2024  return result;
2025 }
2026 
2027 static int SCHSTest23(void)
2028 {
2029  int result = 0;
2030  MpmCtx mpm_ctx;
2031  MpmThreadCtx mpm_thread_ctx;
2032  PrefilterRuleStore pmq;
2033 
2034  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2035  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2036  MpmInitCtx(&mpm_ctx, MPM_HS);
2037 
2038  /* 1 */
2039  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2040  PmqSetup(&pmq);
2041 
2042  SCHSPreparePatterns(NULL, &mpm_ctx);
2043  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2044 
2045  uint32_t cnt =
2046  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"aa", 2);
2047 
2048  if (cnt == 0)
2049  result = 1;
2050  else
2051  printf("1 != %" PRIu32 " ", cnt);
2052 
2053  SCHSDestroyCtx(&mpm_ctx);
2054  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2055  PmqFree(&pmq);
2056  return result;
2057 }
2058 
2059 static int SCHSTest24(void)
2060 {
2061  int result = 0;
2062  MpmCtx mpm_ctx;
2063  MpmThreadCtx mpm_thread_ctx;
2064  PrefilterRuleStore pmq;
2065 
2066  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2067  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2068  MpmInitCtx(&mpm_ctx, MPM_HS);
2069 
2070  /* 1 */
2071  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2072  PmqSetup(&pmq);
2073 
2074  SCHSPreparePatterns(NULL, &mpm_ctx);
2075  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2076 
2077  uint32_t cnt =
2078  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"aa", 2);
2079 
2080  if (cnt == 1)
2081  result = 1;
2082  else
2083  printf("1 != %" PRIu32 " ", cnt);
2084 
2085  SCHSDestroyCtx(&mpm_ctx);
2086  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2087  PmqFree(&pmq);
2088  return result;
2089 }
2090 
2091 static int SCHSTest25(void)
2092 {
2093  int result = 0;
2094  MpmCtx mpm_ctx;
2095  MpmThreadCtx mpm_thread_ctx;
2096  PrefilterRuleStore pmq;
2097 
2098  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2099  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2100  MpmInitCtx(&mpm_ctx, MPM_HS);
2101 
2102  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
2103  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
2104  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
2105  PmqSetup(&pmq);
2106 
2107  SCHSPreparePatterns(NULL, &mpm_ctx);
2108  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2109 
2110  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2111  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2112  strlen(buf));
2113 
2114  if (cnt == 3)
2115  result = 1;
2116  else
2117  printf("3 != %" PRIu32 " ", cnt);
2118 
2119  SCHSDestroyCtx(&mpm_ctx);
2120  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2121  PmqFree(&pmq);
2122  return result;
2123 }
2124 
2125 static int SCHSTest26(void)
2126 {
2127  int result = 0;
2128  MpmCtx mpm_ctx;
2129  MpmThreadCtx mpm_thread_ctx;
2130  PrefilterRuleStore pmq;
2131 
2132  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2133  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2134  MpmInitCtx(&mpm_ctx, MPM_HS);
2135 
2136  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
2137  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
2138  PmqSetup(&pmq);
2139 
2140  SCHSPreparePatterns(NULL, &mpm_ctx);
2141  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2142 
2143  const char *buf = "works";
2144  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2145  strlen(buf));
2146 
2147  if (cnt == 1)
2148  result = 1;
2149  else
2150  printf("3 != %" PRIu32 " ", cnt);
2151 
2152  SCHSDestroyCtx(&mpm_ctx);
2153  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2154  PmqFree(&pmq);
2155  return result;
2156 }
2157 
2158 static int SCHSTest27(void)
2159 {
2160  int result = 0;
2161  MpmCtx mpm_ctx;
2162  MpmThreadCtx mpm_thread_ctx;
2163  PrefilterRuleStore pmq;
2164 
2165  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2166  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2167  MpmInitCtx(&mpm_ctx, MPM_HS);
2168 
2169  /* 0 match */
2170  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
2171  PmqSetup(&pmq);
2172 
2173  SCHSPreparePatterns(NULL, &mpm_ctx);
2174  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2175 
2176  const char *buf = "tone";
2177  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2178  strlen(buf));
2179 
2180  if (cnt == 0)
2181  result = 1;
2182  else
2183  printf("0 != %" PRIu32 " ", cnt);
2184 
2185  SCHSDestroyCtx(&mpm_ctx);
2186  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2187  PmqFree(&pmq);
2188  return result;
2189 }
2190 
2191 static int SCHSTest28(void)
2192 {
2193  int result = 0;
2194  MpmCtx mpm_ctx;
2195  MpmThreadCtx mpm_thread_ctx;
2196  PrefilterRuleStore pmq;
2197 
2198  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2199  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2200  MpmInitCtx(&mpm_ctx, MPM_HS);
2201 
2202  /* 0 match */
2203  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2204  PmqSetup(&pmq);
2205 
2206  SCHSPreparePatterns(NULL, &mpm_ctx);
2207  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2208 
2209  const char *buf = "tONE";
2210  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2211  strlen(buf));
2212 
2213  if (cnt == 0)
2214  result = 1;
2215  else
2216  printf("0 != %" PRIu32 " ", cnt);
2217 
2218  SCHSDestroyCtx(&mpm_ctx);
2219  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2220  PmqFree(&pmq);
2221  return result;
2222 }
2223 
2224 static int SCHSTest29(void)
2225 {
2226  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
2227  uint16_t buflen = sizeof(buf) - 1;
2228  Packet *p = NULL;
2229  ThreadVars th_v;
2230  DetectEngineThreadCtx *det_ctx = NULL;
2231  int result = 0;
2232 
2233  memset(&th_v, 0, sizeof(th_v));
2234  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2235 
2237  if (de_ctx == NULL)
2238  goto end;
2240 
2241  de_ctx->flags |= DE_QUIET;
2242 
2243  de_ctx->sig_list = SigInit(
2244  de_ctx, "alert tcp any any -> any any "
2245  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2246  if (de_ctx->sig_list == NULL)
2247  goto end;
2248  de_ctx->sig_list->next =
2249  SigInit(de_ctx, "alert tcp any any -> any any "
2250  "(content:\"onetwothreefourfivesixseveneightnine\"; "
2251  "fast_pattern:3,3; sid:2;)");
2252  if (de_ctx->sig_list->next == NULL)
2253  goto end;
2254 
2256  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2257 
2258  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2259  if (PacketAlertCheck(p, 1) != 1) {
2260  printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
2261  goto end;
2262  }
2263  if (PacketAlertCheck(p, 2) != 1) {
2264  printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
2265  goto end;
2266  }
2267 
2268  result = 1;
2269 end:
2270  if (de_ctx != NULL) {
2273 
2274  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2276  }
2277 
2278  UTHFreePackets(&p, 1);
2279  return result;
2280 }
2281 
2282 static void SCHSRegisterTests(void)
2283 {
2284  UtRegisterTest("SCHSTest01", SCHSTest01);
2285  UtRegisterTest("SCHSTest02", SCHSTest02);
2286  UtRegisterTest("SCHSTest03", SCHSTest03);
2287  UtRegisterTest("SCHSTest04", SCHSTest04);
2288  UtRegisterTest("SCHSTest05", SCHSTest05);
2289  UtRegisterTest("SCHSTest06", SCHSTest06);
2290  UtRegisterTest("SCHSTest07", SCHSTest07);
2291  UtRegisterTest("SCHSTest08", SCHSTest08);
2292  UtRegisterTest("SCHSTest09", SCHSTest09);
2293  UtRegisterTest("SCHSTest10", SCHSTest10);
2294  UtRegisterTest("SCHSTest11", SCHSTest11);
2295  UtRegisterTest("SCHSTest12", SCHSTest12);
2296  UtRegisterTest("SCHSTest13", SCHSTest13);
2297  UtRegisterTest("SCHSTest14", SCHSTest14);
2298  UtRegisterTest("SCHSTest15", SCHSTest15);
2299  UtRegisterTest("SCHSTest16", SCHSTest16);
2300  UtRegisterTest("SCHSTest17", SCHSTest17);
2301  UtRegisterTest("SCHSTest18", SCHSTest18);
2302  UtRegisterTest("SCHSTest19", SCHSTest19);
2303  UtRegisterTest("SCHSTest20", SCHSTest20);
2304  UtRegisterTest("SCHSTest21", SCHSTest21);
2305  UtRegisterTest("SCHSTest22", SCHSTest22);
2306  UtRegisterTest("SCHSTest23", SCHSTest23);
2307  UtRegisterTest("SCHSTest24", SCHSTest24);
2308  UtRegisterTest("SCHSTest25", SCHSTest25);
2309  UtRegisterTest("SCHSTest26", SCHSTest26);
2310  UtRegisterTest("SCHSTest27", SCHSTest27);
2311  UtRegisterTest("SCHSTest28", SCHSTest28);
2312  UtRegisterTest("SCHSTest29", SCHSTest29);
2313 }
2314 #endif /* UNITTESTS */
2315 #endif /* BUILD_HYPERSCAN */
MpmTableElmt_::PrintThreadCtx
void(* PrintThreadCtx)(struct MpmThreadCtx_ *)
Definition: util-mpm.h:179
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
hashword
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
Definition: util-hash-lookup3.c:172
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
MpmTableElmt_::InitThreadCtx
void(* InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:153
MpmThreadCtx_
Definition: util-mpm.h:46
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
MpmTableElmt_::name
const char * name
Definition: util-mpm.h:151
PrefilterRuleStore_
structure for storing potential rule matches
Definition: util-prefilter.h:34
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
HashTableIterate
void HashTableIterate(HashTable *ht, void(*CallbackFn)(void *, void *), void *aux)
Definition: util-hash.c:212
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:141
MpmThreadCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:49
util-hash.h
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:931
MPM_FEATURE_FLAG_OFFSET
#define MPM_FEATURE_FLAG_OFFSET
Definition: util-mpm.h:147
util-memcpy.h
MpmCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:108
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2674
MpmTableElmt_::AddPatternNocase
int(* AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:173
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
HashTable_
Definition: util-hash.h:35
DE_QUIET
#define DE_QUIET
Definition: detect.h:329
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:105
MpmTableElmt_::AddPattern
int(* AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:172
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:365
MpmTableElmt_::feature_flags
uint8_t feature_flags
Definition: util-mpm.h:183
util-hyperscan.h
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2347
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:55
MpmCtx_::maxdepth
uint16_t maxdepth
Definition: util-mpm.h:99
MAX
#define MAX(x, y)
Definition: suricata-common.h:412
MpmTableElmt_::InitCtx
void(* InitCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:152
util-unittest.h
util-unittest-helper.h
HashTableFree
void HashTableFree(HashTable *ht)
Definition: util-hash.c:78
MpmConfig_::cache_dir_path
const char * cache_dir_path
Definition: util-mpm.h:90
HashTable_::array_size
uint32_t array_size
Definition: util-hash.h:37
util-memcmp.h
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
Definition: util-mpm.c:209
Signature_::next
struct Signature_ * next
Definition: detect.h:752
MpmTableElmt_::PrintCtx
void(* PrintCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:178
util-debug.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1223
MPM_HS
@ MPM_HS
Definition: util-mpm.h:38
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
MpmThreadCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:50
HashTableLookup
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:183
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3400
HashTableRemove
int HashTableRemove(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:142
DetectEngineCtx_::mpm_matcher
uint8_t mpm_matcher
Definition: detect.h:934
MPM_PATTERN_FLAG_OFFSET
#define MPM_PATTERN_FLAG_OFFSET
Definition: util-mpm.h:140
MPM_FEATURE_FLAG_DEPTH
#define MPM_FEATURE_FLAG_DEPTH
Definition: util-mpm.h:146
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
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3097
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:104
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
hashlittle_safe
uint32_t hashlittle_safe(const void *key, size_t length, uint32_t initval)
Definition: util-hash-lookup3.c:482
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2200
Packet_
Definition: decode.h:492
detect-engine-build.h
detect-engine-alert.h
conf.h
MpmTableElmt_::CacheRuleset
int(* CacheRuleset)(MpmConfig *)
Definition: util-mpm.h:175
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:177
MpmAddPatternCS
int MpmAddPatternCS(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:249
MPMCTX_FLAGS_NODEPTH
#define MPMCTX_FLAGS_NODEPTH
Definition: util-mpm.h:86
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2129
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
MPM_PATTERN_FLAG_NOCASE
#define MPM_PATTERN_FLAG_NOCASE
Definition: util-mpm.h:136
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
util-conf.h
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:102
util-path.h
util-mpm-hs-core.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3626
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:940
util-hash-lookup3.h
HSRenderPattern
char * HSRenderPattern(const uint8_t *pat, uint16_t pat_len)
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
MpmTableElmt_::Prepare
int(* Prepare)(MpmConfig *, struct MpmCtx_ *)
Definition: util-mpm.h:174
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:154
SCFree
#define SCFree(p)
Definition: util-mem.h:61
MpmConfig_
Definition: util-mpm.h:89
detect-parse.h
MpmCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:107
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
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2635
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
MpmTableElmt_::ConfigDeinit
void(* ConfigDeinit)(MpmConfig **)
Definition: util-mpm.h:158
suricata.h
MpmTableElmt_::ConfigCacheDirSet
void(* ConfigCacheDirSet)(MpmConfig *, const char *dir_path)
Definition: util-mpm.h:159
util-mpm-hs.h
PmqFree
void PmqFree(PrefilterRuleStore *pmq)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
id
uint32_t id
Definition: detect-flowbits.c:933
MpmTableElmt_::ConfigInit
MpmConfig *(* ConfigInit)(void)
Definition: util-mpm.h:157
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:933
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:155
MpmCtx_
Definition: util-mpm.h:93
util-mpm-hs-cache.h
MPM_PATTERN_FLAG_DEPTH
#define MPM_PATTERN_FLAG_DEPTH
Definition: util-mpm.h:138
SigIntId
#define SigIntId
Definition: suricata-common.h:332
MpmCtx_::flags
uint8_t flags
Definition: util-mpm.h:97
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:237
MPMCTX_FLAGS_CACHE_TO_DISK
#define MPMCTX_FLAGS_CACHE_TO_DISK
Definition: util-mpm.h:87
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
MpmHSRegister
void MpmHSRegister(void)
MpmCtx_::ctx
void * ctx
Definition: util-mpm.h:94
MpmAddPatternCI
int MpmAddPatternCI(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:258
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290
SCMutex
#define SCMutex
Definition: threads-debug.h:114
MpmThreadCtx_::ctx
void * ctx
Definition: util-mpm.h:47
MpmTableElmt_::RegisterUnittests
void(* RegisterUnittests)(void)
Definition: util-mpm.h:181
PmqSetup
int PmqSetup(PrefilterRuleStore *pmq)
Setup a pmq.
Definition: util-prefilter.c:37
MpmHSGlobalCleanup
void MpmHSGlobalCleanup(void)
SCCreateDirectoryTree
int SCCreateDirectoryTree(const char *path, const bool final)
Recursively create a directory.
Definition: util-path.c:137
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:456