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