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