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