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  return;
1005 }
1006 
1007 void SCHSPrintInfo(MpmCtx *mpm_ctx)
1008 {
1009  SCHSCtx *ctx = (SCHSCtx *)mpm_ctx->ctx;
1010 
1011  printf("MPM HS Information:\n");
1012  printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
1013  printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
1014  printf(" Sizeof:\n");
1015  printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
1016  printf(" SCHSCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCHSCtx));
1017  printf(" SCHSPattern %" PRIuMAX "\n", (uintmax_t)sizeof(SCHSPattern));
1018  printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
1019  printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
1020  printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
1021  printf("\n");
1022 
1023  if (ctx) {
1024  PatternDatabase *pd = ctx->pattern_db;
1025  char *db_info = NULL;
1026  if (hs_database_info(pd->hs_db, &db_info) == HS_SUCCESS) {
1027  printf("HS Database Info: %s\n", db_info);
1028  SCFree(db_info);
1029  }
1030  printf("HS Database Size: %" PRIuMAX " bytes\n",
1031  (uintmax_t)ctx->hs_db_size);
1032  }
1033 
1034  printf("\n");
1035 }
1036 
1037 /************************** Mpm Registration ***************************/
1038 
1039 /**
1040  * \brief Register the Hyperscan MPM.
1041  */
1042 void MpmHSRegister(void)
1043 {
1044  mpm_table[MPM_HS].name = "hs";
1045  mpm_table[MPM_HS].InitCtx = SCHSInitCtx;
1046  mpm_table[MPM_HS].InitThreadCtx = SCHSInitThreadCtx;
1047  mpm_table[MPM_HS].DestroyCtx = SCHSDestroyCtx;
1048  mpm_table[MPM_HS].DestroyThreadCtx = SCHSDestroyThreadCtx;
1049  mpm_table[MPM_HS].AddPattern = SCHSAddPatternCS;
1050  mpm_table[MPM_HS].AddPatternNocase = SCHSAddPatternCI;
1051  mpm_table[MPM_HS].Prepare = SCHSPreparePatterns;
1052  mpm_table[MPM_HS].Search = SCHSSearch;
1053  mpm_table[MPM_HS].PrintCtx = SCHSPrintInfo;
1054  mpm_table[MPM_HS].PrintThreadCtx = SCHSPrintSearchStats;
1055 #ifdef UNITTESTS
1056  mpm_table[MPM_HS].RegisterUnittests = SCHSRegisterTests;
1057 #endif
1059  /* Set Hyperscan memory allocators */
1060  SCHSSetAllocators();
1061 }
1062 
1063 /**
1064  * \brief Clean up global memory used by all Hyperscan MPM instances.
1065  *
1066  * Currently, this is just the global scratch prototype.
1067  */
1068 void MpmHSGlobalCleanup(void)
1069 {
1070  SCMutexLock(&g_scratch_proto_mutex);
1071  if (g_scratch_proto) {
1072  SCLogDebug("Cleaning up Hyperscan global scratch");
1073  hs_free_scratch(g_scratch_proto);
1074  g_scratch_proto = NULL;
1075  }
1076  SCMutexUnlock(&g_scratch_proto_mutex);
1077 
1078  SCMutexLock(&g_db_table_mutex);
1079  if (g_db_table != NULL) {
1080  SCLogDebug("Clearing Hyperscan database cache");
1081  HashTableFree(g_db_table);
1082  g_db_table = NULL;
1083  }
1084  SCMutexUnlock(&g_db_table_mutex);
1085 }
1086 
1087 /*************************************Unittests********************************/
1088 
1089 #ifdef UNITTESTS
1090 #include "detect-engine-alert.h"
1091 
1092 static int SCHSTest01(void)
1093 {
1094  int result = 0;
1095  MpmCtx mpm_ctx;
1096  MpmThreadCtx mpm_thread_ctx;
1097  PrefilterRuleStore pmq;
1098 
1099  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1100  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1101  MpmInitCtx(&mpm_ctx, MPM_HS);
1102 
1103  /* 1 match */
1104  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1105  PmqSetup(&pmq);
1106 
1107  SCHSPreparePatterns(&mpm_ctx);
1108  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1109 
1110  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1111 
1112  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1113  strlen(buf));
1114 
1115  if (cnt == 1)
1116  result = 1;
1117  else
1118  printf("1 != %" PRIu32 " ", cnt);
1119 
1120  SCHSDestroyCtx(&mpm_ctx);
1121  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1122  PmqFree(&pmq);
1123  return result;
1124 }
1125 
1126 static int SCHSTest02(void)
1127 {
1128  int result = 0;
1129  MpmCtx mpm_ctx;
1130  MpmThreadCtx mpm_thread_ctx;
1131  PrefilterRuleStore pmq;
1132 
1133  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1134  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1135  MpmInitCtx(&mpm_ctx, MPM_HS);
1136 
1137  /* 1 match */
1138  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1139  PmqSetup(&pmq);
1140 
1141  SCHSPreparePatterns(&mpm_ctx);
1142  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1143 
1144  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1145  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1146  strlen(buf));
1147 
1148  if (cnt == 0)
1149  result = 1;
1150  else
1151  printf("0 != %" PRIu32 " ", cnt);
1152 
1153  SCHSDestroyCtx(&mpm_ctx);
1154  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1155  PmqFree(&pmq);
1156  return result;
1157 }
1158 
1159 static int SCHSTest03(void)
1160 {
1161  int result = 0;
1162  MpmCtx mpm_ctx;
1163  MpmThreadCtx mpm_thread_ctx;
1164  PrefilterRuleStore pmq;
1165 
1166  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1167  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1168  MpmInitCtx(&mpm_ctx, MPM_HS);
1169 
1170  /* 1 match */
1171  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1172  /* 1 match */
1173  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1174  /* 1 match */
1175  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1176  PmqSetup(&pmq);
1177 
1178  SCHSPreparePatterns(&mpm_ctx);
1179  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1180 
1181  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1182  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1183  strlen(buf));
1184 
1185  if (cnt == 3)
1186  result = 1;
1187  else
1188  printf("3 != %" PRIu32 " ", cnt);
1189 
1190  SCHSDestroyCtx(&mpm_ctx);
1191  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1192  PmqFree(&pmq);
1193  return result;
1194 }
1195 
1196 static int SCHSTest04(void)
1197 {
1198  int result = 0;
1199  MpmCtx mpm_ctx;
1200  MpmThreadCtx mpm_thread_ctx;
1201  PrefilterRuleStore pmq;
1202 
1203  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1204  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1205  MpmInitCtx(&mpm_ctx, MPM_HS);
1206 
1207  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1208  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1209  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1210  PmqSetup(&pmq);
1211 
1212  SCHSPreparePatterns(&mpm_ctx);
1213  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1214 
1215  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1216  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1217  strlen(buf));
1218 
1219  if (cnt == 1)
1220  result = 1;
1221  else
1222  printf("1 != %" PRIu32 " ", cnt);
1223 
1224  SCHSDestroyCtx(&mpm_ctx);
1225  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1226  PmqFree(&pmq);
1227  return result;
1228 }
1229 
1230 static int SCHSTest05(void)
1231 {
1232  int result = 0;
1233  MpmCtx mpm_ctx;
1234  MpmThreadCtx mpm_thread_ctx;
1235  PrefilterRuleStore pmq;
1236 
1237  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1238  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1239  MpmInitCtx(&mpm_ctx, MPM_HS);
1240 
1241  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1242  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1243  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1244  PmqSetup(&pmq);
1245 
1246  SCHSPreparePatterns(&mpm_ctx);
1247  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1248 
1249  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1250  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1251  strlen(buf));
1252 
1253  if (cnt == 3)
1254  result = 1;
1255  else
1256  printf("3 != %" PRIu32 " ", cnt);
1257 
1258  SCHSDestroyCtx(&mpm_ctx);
1259  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1260  PmqFree(&pmq);
1261  return result;
1262 }
1263 
1264 static int SCHSTest06(void)
1265 {
1266  int result = 0;
1267  MpmCtx mpm_ctx;
1268  MpmThreadCtx mpm_thread_ctx;
1269  PrefilterRuleStore pmq;
1270 
1271  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1272  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1273  MpmInitCtx(&mpm_ctx, MPM_HS);
1274 
1275  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1276  PmqSetup(&pmq);
1277 
1278  SCHSPreparePatterns(&mpm_ctx);
1279  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1280 
1281  const char *buf = "abcd";
1282  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1283  strlen(buf));
1284 
1285  if (cnt == 1)
1286  result = 1;
1287  else
1288  printf("1 != %" PRIu32 " ", cnt);
1289 
1290  SCHSDestroyCtx(&mpm_ctx);
1291  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1292  PmqFree(&pmq);
1293  return result;
1294 }
1295 
1296 static int SCHSTest07(void)
1297 {
1298  int result = 0;
1299  MpmCtx mpm_ctx;
1300  MpmThreadCtx mpm_thread_ctx;
1301  PrefilterRuleStore pmq;
1302 
1303  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1304  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1305  MpmInitCtx(&mpm_ctx, MPM_HS);
1306 
1307  /* should match 30 times */
1308  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1309  /* should match 29 times */
1310  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1311  /* should match 28 times */
1312  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1313  /* 26 */
1314  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1315  /* 21 */
1316  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1317  /* 1 */
1318  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 30,
1319  0, 0, 5, 0, 0);
1320  PmqSetup(&pmq);
1321 
1322  SCHSPreparePatterns(&mpm_ctx);
1323  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1324 
1325  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1326  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1327  strlen(buf));
1328 
1329  if (cnt == 6)
1330  result = 1;
1331  else
1332  printf("6 != %" PRIu32 " ", cnt);
1333 
1334  SCHSDestroyCtx(&mpm_ctx);
1335  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1336  PmqFree(&pmq);
1337  return result;
1338 }
1339 
1340 static int SCHSTest08(void)
1341 {
1342  int result = 0;
1343  MpmCtx mpm_ctx;
1344  MpmThreadCtx mpm_thread_ctx;
1345  PrefilterRuleStore pmq;
1346 
1347  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1348  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1349  MpmInitCtx(&mpm_ctx, MPM_HS);
1350 
1351  /* 1 match */
1352  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1353  PmqSetup(&pmq);
1354 
1355  SCHSPreparePatterns(&mpm_ctx);
1356  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1357 
1358  uint32_t cnt =
1359  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"a", 1);
1360 
1361  if (cnt == 0)
1362  result = 1;
1363  else
1364  printf("0 != %" PRIu32 " ", cnt);
1365 
1366  SCHSDestroyCtx(&mpm_ctx);
1367  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1368  PmqFree(&pmq);
1369  return result;
1370 }
1371 
1372 static int SCHSTest09(void)
1373 {
1374  int result = 0;
1375  MpmCtx mpm_ctx;
1376  MpmThreadCtx mpm_thread_ctx;
1377  PrefilterRuleStore pmq;
1378 
1379  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1380  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1381  MpmInitCtx(&mpm_ctx, MPM_HS);
1382 
1383  /* 1 match */
1384  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1385  PmqSetup(&pmq);
1386 
1387  SCHSPreparePatterns(&mpm_ctx);
1388  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1389 
1390  uint32_t cnt =
1391  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"ab", 2);
1392 
1393  if (cnt == 1)
1394  result = 1;
1395  else
1396  printf("1 != %" PRIu32 " ", cnt);
1397 
1398  SCHSDestroyCtx(&mpm_ctx);
1399  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1400  PmqFree(&pmq);
1401  return result;
1402 }
1403 
1404 static int SCHSTest10(void)
1405 {
1406  int result = 0;
1407  MpmCtx mpm_ctx;
1408  MpmThreadCtx mpm_thread_ctx;
1409  PrefilterRuleStore pmq;
1410 
1411  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1412  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1413  MpmInitCtx(&mpm_ctx, MPM_HS);
1414 
1415  /* 1 match */
1416  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1417  PmqSetup(&pmq);
1418 
1419  SCHSPreparePatterns(&mpm_ctx);
1420  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1421 
1422  const char *buf = "01234567890123456789012345678901234567890123456789"
1423  "01234567890123456789012345678901234567890123456789"
1424  "abcdefgh"
1425  "01234567890123456789012345678901234567890123456789"
1426  "01234567890123456789012345678901234567890123456789";
1427  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1428  strlen(buf));
1429 
1430  if (cnt == 1)
1431  result = 1;
1432  else
1433  printf("1 != %" PRIu32 " ", cnt);
1434 
1435  SCHSDestroyCtx(&mpm_ctx);
1436  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1437  PmqFree(&pmq);
1438  return result;
1439 }
1440 
1441 static int SCHSTest11(void)
1442 {
1443  int result = 0;
1444  MpmCtx mpm_ctx;
1445  MpmThreadCtx mpm_thread_ctx;
1446  PrefilterRuleStore pmq;
1447 
1448  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1449  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1450  MpmInitCtx(&mpm_ctx, MPM_HS);
1451 
1452  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1453  goto end;
1454  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1455  goto end;
1456  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1457  goto end;
1458  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1459  goto end;
1460  PmqSetup(&pmq);
1461 
1462  if (SCHSPreparePatterns(&mpm_ctx) == -1)
1463  goto end;
1464 
1465  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1466 
1467  result = 1;
1468 
1469  const char *buf = "he";
1470  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1471  strlen(buf)) == 1);
1472  buf = "she";
1473  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1474  strlen(buf)) == 2);
1475  buf = "his";
1476  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1477  strlen(buf)) == 1);
1478  buf = "hers";
1479  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1480  strlen(buf)) == 2);
1481 
1482 end:
1483  SCHSDestroyCtx(&mpm_ctx);
1484  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1485  PmqFree(&pmq);
1486  return result;
1487 }
1488 
1489 static int SCHSTest12(void)
1490 {
1491  int result = 0;
1492  MpmCtx mpm_ctx;
1493  MpmThreadCtx mpm_thread_ctx;
1494  PrefilterRuleStore pmq;
1495 
1496  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1497  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1498  MpmInitCtx(&mpm_ctx, MPM_HS);
1499 
1500  /* 1 match */
1501  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1502  /* 1 match */
1503  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1504  PmqSetup(&pmq);
1505 
1506  SCHSPreparePatterns(&mpm_ctx);
1507  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1508 
1509  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1510  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1511  strlen(buf));
1512 
1513  if (cnt == 2)
1514  result = 1;
1515  else
1516  printf("2 != %" PRIu32 " ", cnt);
1517 
1518  SCHSDestroyCtx(&mpm_ctx);
1519  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1520  PmqFree(&pmq);
1521  return result;
1522 }
1523 
1524 static int SCHSTest13(void)
1525 {
1526  int result = 0;
1527  MpmCtx mpm_ctx;
1528  MpmThreadCtx mpm_thread_ctx;
1529  PrefilterRuleStore pmq;
1530 
1531  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1532  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1533  MpmInitCtx(&mpm_ctx, MPM_HS);
1534 
1535  /* 1 match */
1536  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1537  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1538  PmqSetup(&pmq);
1539 
1540  SCHSPreparePatterns(&mpm_ctx);
1541  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1542 
1543  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1544  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1545  strlen(buf));
1546 
1547  if (cnt == 1)
1548  result = 1;
1549  else
1550  printf("1 != %" PRIu32 " ", cnt);
1551 
1552  SCHSDestroyCtx(&mpm_ctx);
1553  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1554  PmqFree(&pmq);
1555  return result;
1556 }
1557 
1558 static int SCHSTest14(void)
1559 {
1560  int result = 0;
1561  MpmCtx mpm_ctx;
1562  MpmThreadCtx mpm_thread_ctx;
1563  PrefilterRuleStore pmq;
1564 
1565  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1566  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1567  MpmInitCtx(&mpm_ctx, MPM_HS);
1568 
1569  /* 1 match */
1570  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1571  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1572  PmqSetup(&pmq);
1573 
1574  SCHSPreparePatterns(&mpm_ctx);
1575  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1576 
1577  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1578  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1579  strlen(buf));
1580 
1581  if (cnt == 1)
1582  result = 1;
1583  else
1584  printf("1 != %" PRIu32 " ", cnt);
1585 
1586  SCHSDestroyCtx(&mpm_ctx);
1587  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1588  PmqFree(&pmq);
1589  return result;
1590 }
1591 
1592 static int SCHSTest15(void)
1593 {
1594  int result = 0;
1595  MpmCtx mpm_ctx;
1596  MpmThreadCtx mpm_thread_ctx;
1597  PrefilterRuleStore pmq;
1598 
1599  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1600  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1601  MpmInitCtx(&mpm_ctx, MPM_HS);
1602 
1603  /* 1 match */
1604  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1605  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1606  PmqSetup(&pmq);
1607 
1608  SCHSPreparePatterns(&mpm_ctx);
1609  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1610 
1611  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1612  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1613  strlen(buf));
1614 
1615  if (cnt == 1)
1616  result = 1;
1617  else
1618  printf("1 != %" PRIu32 " ", cnt);
1619 
1620  SCHSDestroyCtx(&mpm_ctx);
1621  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1622  PmqFree(&pmq);
1623  return result;
1624 }
1625 
1626 static int SCHSTest16(void)
1627 {
1628  int result = 0;
1629  MpmCtx mpm_ctx;
1630  MpmThreadCtx mpm_thread_ctx;
1631  PrefilterRuleStore pmq;
1632 
1633  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1634  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1635  MpmInitCtx(&mpm_ctx, MPM_HS);
1636 
1637  /* 1 match */
1638  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1639  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1640  PmqSetup(&pmq);
1641 
1642  SCHSPreparePatterns(&mpm_ctx);
1643  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1644 
1645  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1646  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1647  strlen(buf));
1648 
1649  if (cnt == 1)
1650  result = 1;
1651  else
1652  printf("1 != %" PRIu32 " ", cnt);
1653 
1654  SCHSDestroyCtx(&mpm_ctx);
1655  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1656  PmqFree(&pmq);
1657  return result;
1658 }
1659 
1660 static int SCHSTest17(void)
1661 {
1662  int result = 0;
1663  MpmCtx mpm_ctx;
1664  MpmThreadCtx mpm_thread_ctx;
1665  PrefilterRuleStore pmq;
1666 
1667  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1668  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1669  MpmInitCtx(&mpm_ctx, MPM_HS);
1670 
1671  /* 1 match */
1672  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1673  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1674  PmqSetup(&pmq);
1675 
1676  SCHSPreparePatterns(&mpm_ctx);
1677  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1678 
1679  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1680  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1681  strlen(buf));
1682 
1683  if (cnt == 1)
1684  result = 1;
1685  else
1686  printf("1 != %" PRIu32 " ", cnt);
1687 
1688  SCHSDestroyCtx(&mpm_ctx);
1689  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1690  PmqFree(&pmq);
1691  return result;
1692 }
1693 
1694 static int SCHSTest18(void)
1695 {
1696  int result = 0;
1697  MpmCtx mpm_ctx;
1698  MpmThreadCtx mpm_thread_ctx;
1699  PrefilterRuleStore pmq;
1700 
1701  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1702  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1703  MpmInitCtx(&mpm_ctx, MPM_HS);
1704 
1705  /* 1 match */
1706  const char pat[] = "abcde"
1707  "fghij"
1708  "klmno"
1709  "pqrst"
1710  "uvwxy"
1711  "z";
1712  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1713  PmqSetup(&pmq);
1714 
1715  SCHSPreparePatterns(&mpm_ctx);
1716  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1717 
1718  const char *buf = "abcde"
1719  "fghij"
1720  "klmno"
1721  "pqrst"
1722  "uvwxy"
1723  "z";
1724  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1725  strlen(buf));
1726 
1727  if (cnt == 1)
1728  result = 1;
1729  else
1730  printf("1 != %" PRIu32 " ", cnt);
1731 
1732  SCHSDestroyCtx(&mpm_ctx);
1733  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1734  PmqFree(&pmq);
1735  return result;
1736 }
1737 
1738 static int SCHSTest19(void)
1739 {
1740  int result = 0;
1741  MpmCtx mpm_ctx;
1742  MpmThreadCtx mpm_thread_ctx;
1743  PrefilterRuleStore pmq;
1744 
1745  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1746  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1747  MpmInitCtx(&mpm_ctx, MPM_HS);
1748 
1749  /* 1 */
1750  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1751  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1752  PmqSetup(&pmq);
1753 
1754  SCHSPreparePatterns(&mpm_ctx);
1755  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1756 
1757  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1758  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1759  strlen(buf));
1760 
1761  if (cnt == 1)
1762  result = 1;
1763  else
1764  printf("1 != %" PRIu32 " ", cnt);
1765 
1766  SCHSDestroyCtx(&mpm_ctx);
1767  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1768  PmqFree(&pmq);
1769  return result;
1770 }
1771 
1772 static int SCHSTest20(void)
1773 {
1774  int result = 0;
1775  MpmCtx mpm_ctx;
1776  MpmThreadCtx mpm_thread_ctx;
1777  PrefilterRuleStore pmq;
1778 
1779  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1780  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1781  MpmInitCtx(&mpm_ctx, MPM_HS);
1782 
1783  /* 1 */
1784  const char pat[] = "AAAAA"
1785  "AAAAA"
1786  "AAAAA"
1787  "AAAAA"
1788  "AAAAA"
1789  "AAAAA"
1790  "AA";
1791  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1792  PmqSetup(&pmq);
1793 
1794  SCHSPreparePatterns(&mpm_ctx);
1795  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1796 
1797  const char *buf = "AAAAA"
1798  "AAAAA"
1799  "AAAAA"
1800  "AAAAA"
1801  "AAAAA"
1802  "AAAAA"
1803  "AA";
1804  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1805  strlen(buf));
1806 
1807  if (cnt == 1)
1808  result = 1;
1809  else
1810  printf("1 != %" PRIu32 " ", cnt);
1811 
1812  SCHSDestroyCtx(&mpm_ctx);
1813  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1814  PmqFree(&pmq);
1815  return result;
1816 }
1817 
1818 static int SCHSTest21(void)
1819 {
1820  int result = 0;
1821  MpmCtx mpm_ctx;
1822  MpmThreadCtx mpm_thread_ctx;
1823  PrefilterRuleStore pmq;
1824 
1825  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1826  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1827  MpmInitCtx(&mpm_ctx, MPM_HS);
1828 
1829  /* 1 */
1830  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1831  PmqSetup(&pmq);
1832 
1833  SCHSPreparePatterns(&mpm_ctx);
1834  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1835 
1836  uint32_t cnt =
1837  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"AA", 2);
1838 
1839  if (cnt == 1)
1840  result = 1;
1841  else
1842  printf("1 != %" PRIu32 " ", cnt);
1843 
1844  SCHSDestroyCtx(&mpm_ctx);
1845  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1846  PmqFree(&pmq);
1847  return result;
1848 }
1849 
1850 static int SCHSTest22(void)
1851 {
1852  int result = 0;
1853  MpmCtx mpm_ctx;
1854  MpmThreadCtx mpm_thread_ctx;
1855  PrefilterRuleStore pmq;
1856 
1857  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1858  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1859  MpmInitCtx(&mpm_ctx, MPM_HS);
1860 
1861  /* 1 match */
1862  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1863  /* 1 match */
1864  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
1865  PmqSetup(&pmq);
1866 
1867  SCHSPreparePatterns(&mpm_ctx);
1868  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1869 
1870  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1871  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1872  strlen(buf));
1873 
1874  if (cnt == 2)
1875  result = 1;
1876  else
1877  printf("2 != %" PRIu32 " ", cnt);
1878 
1879  SCHSDestroyCtx(&mpm_ctx);
1880  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1881  PmqFree(&pmq);
1882  return result;
1883 }
1884 
1885 static int SCHSTest23(void)
1886 {
1887  int result = 0;
1888  MpmCtx mpm_ctx;
1889  MpmThreadCtx mpm_thread_ctx;
1890  PrefilterRuleStore pmq;
1891 
1892  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1893  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1894  MpmInitCtx(&mpm_ctx, MPM_HS);
1895 
1896  /* 1 */
1897  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1898  PmqSetup(&pmq);
1899 
1900  SCHSPreparePatterns(&mpm_ctx);
1901  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1902 
1903  uint32_t cnt =
1904  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"aa", 2);
1905 
1906  if (cnt == 0)
1907  result = 1;
1908  else
1909  printf("1 != %" PRIu32 " ", cnt);
1910 
1911  SCHSDestroyCtx(&mpm_ctx);
1912  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1913  PmqFree(&pmq);
1914  return result;
1915 }
1916 
1917 static int SCHSTest24(void)
1918 {
1919  int result = 0;
1920  MpmCtx mpm_ctx;
1921  MpmThreadCtx mpm_thread_ctx;
1922  PrefilterRuleStore pmq;
1923 
1924  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1925  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1926  MpmInitCtx(&mpm_ctx, MPM_HS);
1927 
1928  /* 1 */
1929  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1930  PmqSetup(&pmq);
1931 
1932  SCHSPreparePatterns(&mpm_ctx);
1933  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1934 
1935  uint32_t cnt =
1936  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"aa", 2);
1937 
1938  if (cnt == 1)
1939  result = 1;
1940  else
1941  printf("1 != %" PRIu32 " ", cnt);
1942 
1943  SCHSDestroyCtx(&mpm_ctx);
1944  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1945  PmqFree(&pmq);
1946  return result;
1947 }
1948 
1949 static int SCHSTest25(void)
1950 {
1951  int result = 0;
1952  MpmCtx mpm_ctx;
1953  MpmThreadCtx mpm_thread_ctx;
1954  PrefilterRuleStore pmq;
1955 
1956  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1957  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1958  MpmInitCtx(&mpm_ctx, MPM_HS);
1959 
1960  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1961  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1962  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
1963  PmqSetup(&pmq);
1964 
1965  SCHSPreparePatterns(&mpm_ctx);
1966  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1967 
1968  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1969  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1970  strlen(buf));
1971 
1972  if (cnt == 3)
1973  result = 1;
1974  else
1975  printf("3 != %" PRIu32 " ", cnt);
1976 
1977  SCHSDestroyCtx(&mpm_ctx);
1978  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1979  PmqFree(&pmq);
1980  return result;
1981 }
1982 
1983 static int SCHSTest26(void)
1984 {
1985  int result = 0;
1986  MpmCtx mpm_ctx;
1987  MpmThreadCtx mpm_thread_ctx;
1988  PrefilterRuleStore pmq;
1989 
1990  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1991  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1992  MpmInitCtx(&mpm_ctx, MPM_HS);
1993 
1994  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
1995  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
1996  PmqSetup(&pmq);
1997 
1998  SCHSPreparePatterns(&mpm_ctx);
1999  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2000 
2001  const char *buf = "works";
2002  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2003  strlen(buf));
2004 
2005  if (cnt == 1)
2006  result = 1;
2007  else
2008  printf("3 != %" PRIu32 " ", cnt);
2009 
2010  SCHSDestroyCtx(&mpm_ctx);
2011  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2012  PmqFree(&pmq);
2013  return result;
2014 }
2015 
2016 static int SCHSTest27(void)
2017 {
2018  int result = 0;
2019  MpmCtx mpm_ctx;
2020  MpmThreadCtx mpm_thread_ctx;
2021  PrefilterRuleStore pmq;
2022 
2023  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2024  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2025  MpmInitCtx(&mpm_ctx, MPM_HS);
2026 
2027  /* 0 match */
2028  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
2029  PmqSetup(&pmq);
2030 
2031  SCHSPreparePatterns(&mpm_ctx);
2032  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2033 
2034  const char *buf = "tone";
2035  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2036  strlen(buf));
2037 
2038  if (cnt == 0)
2039  result = 1;
2040  else
2041  printf("0 != %" PRIu32 " ", cnt);
2042 
2043  SCHSDestroyCtx(&mpm_ctx);
2044  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2045  PmqFree(&pmq);
2046  return result;
2047 }
2048 
2049 static int SCHSTest28(void)
2050 {
2051  int result = 0;
2052  MpmCtx mpm_ctx;
2053  MpmThreadCtx mpm_thread_ctx;
2054  PrefilterRuleStore pmq;
2055 
2056  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2057  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2058  MpmInitCtx(&mpm_ctx, MPM_HS);
2059 
2060  /* 0 match */
2061  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2062  PmqSetup(&pmq);
2063 
2064  SCHSPreparePatterns(&mpm_ctx);
2065  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2066 
2067  const char *buf = "tONE";
2068  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2069  strlen(buf));
2070 
2071  if (cnt == 0)
2072  result = 1;
2073  else
2074  printf("0 != %" PRIu32 " ", cnt);
2075 
2076  SCHSDestroyCtx(&mpm_ctx);
2077  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2078  PmqFree(&pmq);
2079  return result;
2080 }
2081 
2082 static int SCHSTest29(void)
2083 {
2084  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
2085  uint16_t buflen = sizeof(buf) - 1;
2086  Packet *p = NULL;
2087  ThreadVars th_v;
2088  DetectEngineThreadCtx *det_ctx = NULL;
2089  int result = 0;
2090 
2091  memset(&th_v, 0, sizeof(th_v));
2092  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2093 
2095  if (de_ctx == NULL)
2096  goto end;
2098 
2099  de_ctx->flags |= DE_QUIET;
2100 
2101  de_ctx->sig_list = SigInit(
2102  de_ctx, "alert tcp any any -> any any "
2103  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2104  if (de_ctx->sig_list == NULL)
2105  goto end;
2106  de_ctx->sig_list->next =
2107  SigInit(de_ctx, "alert tcp any any -> any any "
2108  "(content:\"onetwothreefourfivesixseveneightnine\"; "
2109  "fast_pattern:3,3; sid:2;)");
2110  if (de_ctx->sig_list->next == NULL)
2111  goto end;
2112 
2114  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2115 
2116  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2117  if (PacketAlertCheck(p, 1) != 1) {
2118  printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
2119  goto end;
2120  }
2121  if (PacketAlertCheck(p, 2) != 1) {
2122  printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
2123  goto end;
2124  }
2125 
2126  result = 1;
2127 end:
2128  if (de_ctx != NULL) {
2131 
2132  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2134  }
2135 
2136  UTHFreePackets(&p, 1);
2137  return result;
2138 }
2139 
2140 static void SCHSRegisterTests(void)
2141 {
2142  UtRegisterTest("SCHSTest01", SCHSTest01);
2143  UtRegisterTest("SCHSTest02", SCHSTest02);
2144  UtRegisterTest("SCHSTest03", SCHSTest03);
2145  UtRegisterTest("SCHSTest04", SCHSTest04);
2146  UtRegisterTest("SCHSTest05", SCHSTest05);
2147  UtRegisterTest("SCHSTest06", SCHSTest06);
2148  UtRegisterTest("SCHSTest07", SCHSTest07);
2149  UtRegisterTest("SCHSTest08", SCHSTest08);
2150  UtRegisterTest("SCHSTest09", SCHSTest09);
2151  UtRegisterTest("SCHSTest10", SCHSTest10);
2152  UtRegisterTest("SCHSTest11", SCHSTest11);
2153  UtRegisterTest("SCHSTest12", SCHSTest12);
2154  UtRegisterTest("SCHSTest13", SCHSTest13);
2155  UtRegisterTest("SCHSTest14", SCHSTest14);
2156  UtRegisterTest("SCHSTest15", SCHSTest15);
2157  UtRegisterTest("SCHSTest16", SCHSTest16);
2158  UtRegisterTest("SCHSTest17", SCHSTest17);
2159  UtRegisterTest("SCHSTest18", SCHSTest18);
2160  UtRegisterTest("SCHSTest19", SCHSTest19);
2161  UtRegisterTest("SCHSTest20", SCHSTest20);
2162  UtRegisterTest("SCHSTest21", SCHSTest21);
2163  UtRegisterTest("SCHSTest22", SCHSTest22);
2164  UtRegisterTest("SCHSTest23", SCHSTest23);
2165  UtRegisterTest("SCHSTest24", SCHSTest24);
2166  UtRegisterTest("SCHSTest25", SCHSTest25);
2167  UtRegisterTest("SCHSTest26", SCHSTest26);
2168  UtRegisterTest("SCHSTest27", SCHSTest27);
2169  UtRegisterTest("SCHSTest28", SCHSTest28);
2170  UtRegisterTest("SCHSTest29", SCHSTest29);
2171 }
2172 #endif /* UNITTESTS */
2173 #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:174
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
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:49
SCHSPattern_::sids_size
uint32_t sids_size
Definition: util-mpm-hs.h:44
util-hash.h
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:839
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:2533
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:324
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:340
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:1895
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:54
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
MPM_HS
@ MPM_HS
Definition: util-mpm.h:38
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:668
MpmTableElmt_::PrintCtx
void(* PrintCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:169
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
DetectEngineThreadCtx_
Definition: detect.h:1095
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:57
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:842
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:2314
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:484
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2218
Packet_
Definition: decode.h:437
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:2149
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
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3244
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3454
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:97
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:847
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:2494
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:841
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:431