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(SC_ERR_FATAL, "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(SC_ERR_INVALID_ARGUMENTS, "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(SC_ERR_FATAL, "failed to compile hyperscan database");
696  if (compile_err) {
697  SCLogError(SC_ERR_FATAL, "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(SC_ERR_FATAL, "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(SC_ERR_FATAL, "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(SC_ERR_FATAL, "Unable to clone scratch prototype");
788  }
789 
790  err = hs_scratch_size(ctx->scratch, &ctx->scratch_size);
791  if (err != HS_SUCCESS) {
792  FatalError(SC_ERR_FATAL, "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(SC_ERR_FATAL, "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  SCLogPerf("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  SCLogPerf("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 
1098 static int SCHSTest01(void)
1099 {
1100  int result = 0;
1101  MpmCtx mpm_ctx;
1102  MpmThreadCtx mpm_thread_ctx;
1103  PrefilterRuleStore pmq;
1104 
1105  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1106  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1107  MpmInitCtx(&mpm_ctx, MPM_HS);
1108 
1109  /* 1 match */
1110  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1111  PmqSetup(&pmq);
1112 
1113  SCHSPreparePatterns(&mpm_ctx);
1114  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1115 
1116  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1117 
1118  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1119  strlen(buf));
1120 
1121  if (cnt == 1)
1122  result = 1;
1123  else
1124  printf("1 != %" PRIu32 " ", cnt);
1125 
1126  SCHSDestroyCtx(&mpm_ctx);
1127  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1128  PmqFree(&pmq);
1129  return result;
1130 }
1131 
1132 static int SCHSTest02(void)
1133 {
1134  int result = 0;
1135  MpmCtx mpm_ctx;
1136  MpmThreadCtx mpm_thread_ctx;
1137  PrefilterRuleStore pmq;
1138 
1139  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1140  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1141  MpmInitCtx(&mpm_ctx, MPM_HS);
1142 
1143  /* 1 match */
1144  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1145  PmqSetup(&pmq);
1146 
1147  SCHSPreparePatterns(&mpm_ctx);
1148  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1149 
1150  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1151  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1152  strlen(buf));
1153 
1154  if (cnt == 0)
1155  result = 1;
1156  else
1157  printf("0 != %" PRIu32 " ", cnt);
1158 
1159  SCHSDestroyCtx(&mpm_ctx);
1160  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1161  PmqFree(&pmq);
1162  return result;
1163 }
1164 
1165 static int SCHSTest03(void)
1166 {
1167  int result = 0;
1168  MpmCtx mpm_ctx;
1169  MpmThreadCtx mpm_thread_ctx;
1170  PrefilterRuleStore pmq;
1171 
1172  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1173  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1174  MpmInitCtx(&mpm_ctx, MPM_HS);
1175 
1176  /* 1 match */
1177  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1178  /* 1 match */
1179  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1180  /* 1 match */
1181  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1182  PmqSetup(&pmq);
1183 
1184  SCHSPreparePatterns(&mpm_ctx);
1185  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1186 
1187  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1188  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1189  strlen(buf));
1190 
1191  if (cnt == 3)
1192  result = 1;
1193  else
1194  printf("3 != %" PRIu32 " ", cnt);
1195 
1196  SCHSDestroyCtx(&mpm_ctx);
1197  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1198  PmqFree(&pmq);
1199  return result;
1200 }
1201 
1202 static int SCHSTest04(void)
1203 {
1204  int result = 0;
1205  MpmCtx mpm_ctx;
1206  MpmThreadCtx mpm_thread_ctx;
1207  PrefilterRuleStore pmq;
1208 
1209  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1210  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1211  MpmInitCtx(&mpm_ctx, MPM_HS);
1212 
1213  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1214  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1215  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1216  PmqSetup(&pmq);
1217 
1218  SCHSPreparePatterns(&mpm_ctx);
1219  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1220 
1221  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1222  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1223  strlen(buf));
1224 
1225  if (cnt == 1)
1226  result = 1;
1227  else
1228  printf("1 != %" PRIu32 " ", cnt);
1229 
1230  SCHSDestroyCtx(&mpm_ctx);
1231  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1232  PmqFree(&pmq);
1233  return result;
1234 }
1235 
1236 static int SCHSTest05(void)
1237 {
1238  int result = 0;
1239  MpmCtx mpm_ctx;
1240  MpmThreadCtx mpm_thread_ctx;
1241  PrefilterRuleStore pmq;
1242 
1243  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1244  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1245  MpmInitCtx(&mpm_ctx, MPM_HS);
1246 
1247  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1248  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1249  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1250  PmqSetup(&pmq);
1251 
1252  SCHSPreparePatterns(&mpm_ctx);
1253  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1254 
1255  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1256  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1257  strlen(buf));
1258 
1259  if (cnt == 3)
1260  result = 1;
1261  else
1262  printf("3 != %" PRIu32 " ", cnt);
1263 
1264  SCHSDestroyCtx(&mpm_ctx);
1265  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1266  PmqFree(&pmq);
1267  return result;
1268 }
1269 
1270 static int SCHSTest06(void)
1271 {
1272  int result = 0;
1273  MpmCtx mpm_ctx;
1274  MpmThreadCtx mpm_thread_ctx;
1275  PrefilterRuleStore pmq;
1276 
1277  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1278  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1279  MpmInitCtx(&mpm_ctx, MPM_HS);
1280 
1281  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1282  PmqSetup(&pmq);
1283 
1284  SCHSPreparePatterns(&mpm_ctx);
1285  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1286 
1287  const char *buf = "abcd";
1288  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1289  strlen(buf));
1290 
1291  if (cnt == 1)
1292  result = 1;
1293  else
1294  printf("1 != %" PRIu32 " ", cnt);
1295 
1296  SCHSDestroyCtx(&mpm_ctx);
1297  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1298  PmqFree(&pmq);
1299  return result;
1300 }
1301 
1302 static int SCHSTest07(void)
1303 {
1304  int result = 0;
1305  MpmCtx mpm_ctx;
1306  MpmThreadCtx mpm_thread_ctx;
1307  PrefilterRuleStore pmq;
1308 
1309  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1310  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1311  MpmInitCtx(&mpm_ctx, MPM_HS);
1312 
1313  /* should match 30 times */
1314  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1315  /* should match 29 times */
1316  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1317  /* should match 28 times */
1318  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1319  /* 26 */
1320  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1321  /* 21 */
1322  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1323  /* 1 */
1324  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 30,
1325  0, 0, 5, 0, 0);
1326  PmqSetup(&pmq);
1327 
1328  SCHSPreparePatterns(&mpm_ctx);
1329  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1330 
1331  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1332  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1333  strlen(buf));
1334 
1335  if (cnt == 6)
1336  result = 1;
1337  else
1338  printf("6 != %" PRIu32 " ", cnt);
1339 
1340  SCHSDestroyCtx(&mpm_ctx);
1341  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1342  PmqFree(&pmq);
1343  return result;
1344 }
1345 
1346 static int SCHSTest08(void)
1347 {
1348  int result = 0;
1349  MpmCtx mpm_ctx;
1350  MpmThreadCtx mpm_thread_ctx;
1351  PrefilterRuleStore pmq;
1352 
1353  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1354  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1355  MpmInitCtx(&mpm_ctx, MPM_HS);
1356 
1357  /* 1 match */
1358  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1359  PmqSetup(&pmq);
1360 
1361  SCHSPreparePatterns(&mpm_ctx);
1362  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1363 
1364  uint32_t cnt =
1365  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"a", 1);
1366 
1367  if (cnt == 0)
1368  result = 1;
1369  else
1370  printf("0 != %" PRIu32 " ", cnt);
1371 
1372  SCHSDestroyCtx(&mpm_ctx);
1373  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1374  PmqFree(&pmq);
1375  return result;
1376 }
1377 
1378 static int SCHSTest09(void)
1379 {
1380  int result = 0;
1381  MpmCtx mpm_ctx;
1382  MpmThreadCtx mpm_thread_ctx;
1383  PrefilterRuleStore pmq;
1384 
1385  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1386  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1387  MpmInitCtx(&mpm_ctx, MPM_HS);
1388 
1389  /* 1 match */
1390  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1391  PmqSetup(&pmq);
1392 
1393  SCHSPreparePatterns(&mpm_ctx);
1394  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1395 
1396  uint32_t cnt =
1397  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"ab", 2);
1398 
1399  if (cnt == 1)
1400  result = 1;
1401  else
1402  printf("1 != %" PRIu32 " ", cnt);
1403 
1404  SCHSDestroyCtx(&mpm_ctx);
1405  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1406  PmqFree(&pmq);
1407  return result;
1408 }
1409 
1410 static int SCHSTest10(void)
1411 {
1412  int result = 0;
1413  MpmCtx mpm_ctx;
1414  MpmThreadCtx mpm_thread_ctx;
1415  PrefilterRuleStore pmq;
1416 
1417  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1418  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1419  MpmInitCtx(&mpm_ctx, MPM_HS);
1420 
1421  /* 1 match */
1422  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1423  PmqSetup(&pmq);
1424 
1425  SCHSPreparePatterns(&mpm_ctx);
1426  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1427 
1428  const char *buf = "01234567890123456789012345678901234567890123456789"
1429  "01234567890123456789012345678901234567890123456789"
1430  "abcdefgh"
1431  "01234567890123456789012345678901234567890123456789"
1432  "01234567890123456789012345678901234567890123456789";
1433  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1434  strlen(buf));
1435 
1436  if (cnt == 1)
1437  result = 1;
1438  else
1439  printf("1 != %" PRIu32 " ", cnt);
1440 
1441  SCHSDestroyCtx(&mpm_ctx);
1442  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1443  PmqFree(&pmq);
1444  return result;
1445 }
1446 
1447 static int SCHSTest11(void)
1448 {
1449  int result = 0;
1450  MpmCtx mpm_ctx;
1451  MpmThreadCtx mpm_thread_ctx;
1452  PrefilterRuleStore pmq;
1453 
1454  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1455  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1456  MpmInitCtx(&mpm_ctx, MPM_HS);
1457 
1458  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1459  goto end;
1460  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1461  goto end;
1462  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1463  goto end;
1464  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1465  goto end;
1466  PmqSetup(&pmq);
1467 
1468  if (SCHSPreparePatterns(&mpm_ctx) == -1)
1469  goto end;
1470 
1471  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1472 
1473  result = 1;
1474 
1475  const char *buf = "he";
1476  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1477  strlen(buf)) == 1);
1478  buf = "she";
1479  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1480  strlen(buf)) == 2);
1481  buf = "his";
1482  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1483  strlen(buf)) == 1);
1484  buf = "hers";
1485  result &= (SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1486  strlen(buf)) == 2);
1487 
1488 end:
1489  SCHSDestroyCtx(&mpm_ctx);
1490  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1491  PmqFree(&pmq);
1492  return result;
1493 }
1494 
1495 static int SCHSTest12(void)
1496 {
1497  int result = 0;
1498  MpmCtx mpm_ctx;
1499  MpmThreadCtx mpm_thread_ctx;
1500  PrefilterRuleStore pmq;
1501 
1502  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1503  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1504  MpmInitCtx(&mpm_ctx, MPM_HS);
1505 
1506  /* 1 match */
1507  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1508  /* 1 match */
1509  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1510  PmqSetup(&pmq);
1511 
1512  SCHSPreparePatterns(&mpm_ctx);
1513  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1514 
1515  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1516  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1517  strlen(buf));
1518 
1519  if (cnt == 2)
1520  result = 1;
1521  else
1522  printf("2 != %" PRIu32 " ", cnt);
1523 
1524  SCHSDestroyCtx(&mpm_ctx);
1525  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1526  PmqFree(&pmq);
1527  return result;
1528 }
1529 
1530 static int SCHSTest13(void)
1531 {
1532  int result = 0;
1533  MpmCtx mpm_ctx;
1534  MpmThreadCtx mpm_thread_ctx;
1535  PrefilterRuleStore pmq;
1536 
1537  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1538  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1539  MpmInitCtx(&mpm_ctx, MPM_HS);
1540 
1541  /* 1 match */
1542  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1543  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1544  PmqSetup(&pmq);
1545 
1546  SCHSPreparePatterns(&mpm_ctx);
1547  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1548 
1549  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1550  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1551  strlen(buf));
1552 
1553  if (cnt == 1)
1554  result = 1;
1555  else
1556  printf("1 != %" PRIu32 " ", cnt);
1557 
1558  SCHSDestroyCtx(&mpm_ctx);
1559  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1560  PmqFree(&pmq);
1561  return result;
1562 }
1563 
1564 static int SCHSTest14(void)
1565 {
1566  int result = 0;
1567  MpmCtx mpm_ctx;
1568  MpmThreadCtx mpm_thread_ctx;
1569  PrefilterRuleStore pmq;
1570 
1571  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1572  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1573  MpmInitCtx(&mpm_ctx, MPM_HS);
1574 
1575  /* 1 match */
1576  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1577  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1578  PmqSetup(&pmq);
1579 
1580  SCHSPreparePatterns(&mpm_ctx);
1581  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1582 
1583  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1584  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1585  strlen(buf));
1586 
1587  if (cnt == 1)
1588  result = 1;
1589  else
1590  printf("1 != %" PRIu32 " ", cnt);
1591 
1592  SCHSDestroyCtx(&mpm_ctx);
1593  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1594  PmqFree(&pmq);
1595  return result;
1596 }
1597 
1598 static int SCHSTest15(void)
1599 {
1600  int result = 0;
1601  MpmCtx mpm_ctx;
1602  MpmThreadCtx mpm_thread_ctx;
1603  PrefilterRuleStore pmq;
1604 
1605  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1606  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1607  MpmInitCtx(&mpm_ctx, MPM_HS);
1608 
1609  /* 1 match */
1610  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1611  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1612  PmqSetup(&pmq);
1613 
1614  SCHSPreparePatterns(&mpm_ctx);
1615  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1616 
1617  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1618  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1619  strlen(buf));
1620 
1621  if (cnt == 1)
1622  result = 1;
1623  else
1624  printf("1 != %" PRIu32 " ", cnt);
1625 
1626  SCHSDestroyCtx(&mpm_ctx);
1627  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1628  PmqFree(&pmq);
1629  return result;
1630 }
1631 
1632 static int SCHSTest16(void)
1633 {
1634  int result = 0;
1635  MpmCtx mpm_ctx;
1636  MpmThreadCtx mpm_thread_ctx;
1637  PrefilterRuleStore pmq;
1638 
1639  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1640  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1641  MpmInitCtx(&mpm_ctx, MPM_HS);
1642 
1643  /* 1 match */
1644  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1645  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1646  PmqSetup(&pmq);
1647 
1648  SCHSPreparePatterns(&mpm_ctx);
1649  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1650 
1651  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1652  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1653  strlen(buf));
1654 
1655  if (cnt == 1)
1656  result = 1;
1657  else
1658  printf("1 != %" PRIu32 " ", cnt);
1659 
1660  SCHSDestroyCtx(&mpm_ctx);
1661  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1662  PmqFree(&pmq);
1663  return result;
1664 }
1665 
1666 static int SCHSTest17(void)
1667 {
1668  int result = 0;
1669  MpmCtx mpm_ctx;
1670  MpmThreadCtx mpm_thread_ctx;
1671  PrefilterRuleStore pmq;
1672 
1673  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1674  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1675  MpmInitCtx(&mpm_ctx, MPM_HS);
1676 
1677  /* 1 match */
1678  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1679  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1680  PmqSetup(&pmq);
1681 
1682  SCHSPreparePatterns(&mpm_ctx);
1683  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1684 
1685  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1686  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1687  strlen(buf));
1688 
1689  if (cnt == 1)
1690  result = 1;
1691  else
1692  printf("1 != %" PRIu32 " ", cnt);
1693 
1694  SCHSDestroyCtx(&mpm_ctx);
1695  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1696  PmqFree(&pmq);
1697  return result;
1698 }
1699 
1700 static int SCHSTest18(void)
1701 {
1702  int result = 0;
1703  MpmCtx mpm_ctx;
1704  MpmThreadCtx mpm_thread_ctx;
1705  PrefilterRuleStore pmq;
1706 
1707  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1708  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1709  MpmInitCtx(&mpm_ctx, MPM_HS);
1710 
1711  /* 1 match */
1712  const char pat[] = "abcde"
1713  "fghij"
1714  "klmno"
1715  "pqrst"
1716  "uvwxy"
1717  "z";
1718  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1719  PmqSetup(&pmq);
1720 
1721  SCHSPreparePatterns(&mpm_ctx);
1722  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1723 
1724  const char *buf = "abcde"
1725  "fghij"
1726  "klmno"
1727  "pqrst"
1728  "uvwxy"
1729  "z";
1730  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1731  strlen(buf));
1732 
1733  if (cnt == 1)
1734  result = 1;
1735  else
1736  printf("1 != %" PRIu32 " ", cnt);
1737 
1738  SCHSDestroyCtx(&mpm_ctx);
1739  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1740  PmqFree(&pmq);
1741  return result;
1742 }
1743 
1744 static int SCHSTest19(void)
1745 {
1746  int result = 0;
1747  MpmCtx mpm_ctx;
1748  MpmThreadCtx mpm_thread_ctx;
1749  PrefilterRuleStore pmq;
1750 
1751  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1752  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1753  MpmInitCtx(&mpm_ctx, MPM_HS);
1754 
1755  /* 1 */
1756  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1757  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1758  PmqSetup(&pmq);
1759 
1760  SCHSPreparePatterns(&mpm_ctx);
1761  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1762 
1763  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1764  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1765  strlen(buf));
1766 
1767  if (cnt == 1)
1768  result = 1;
1769  else
1770  printf("1 != %" PRIu32 " ", cnt);
1771 
1772  SCHSDestroyCtx(&mpm_ctx);
1773  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1774  PmqFree(&pmq);
1775  return result;
1776 }
1777 
1778 static int SCHSTest20(void)
1779 {
1780  int result = 0;
1781  MpmCtx mpm_ctx;
1782  MpmThreadCtx mpm_thread_ctx;
1783  PrefilterRuleStore pmq;
1784 
1785  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1786  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1787  MpmInitCtx(&mpm_ctx, MPM_HS);
1788 
1789  /* 1 */
1790  const char pat[] = "AAAAA"
1791  "AAAAA"
1792  "AAAAA"
1793  "AAAAA"
1794  "AAAAA"
1795  "AAAAA"
1796  "AA";
1797  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1798  PmqSetup(&pmq);
1799 
1800  SCHSPreparePatterns(&mpm_ctx);
1801  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1802 
1803  const char *buf = "AAAAA"
1804  "AAAAA"
1805  "AAAAA"
1806  "AAAAA"
1807  "AAAAA"
1808  "AAAAA"
1809  "AA";
1810  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1811  strlen(buf));
1812 
1813  if (cnt == 1)
1814  result = 1;
1815  else
1816  printf("1 != %" PRIu32 " ", cnt);
1817 
1818  SCHSDestroyCtx(&mpm_ctx);
1819  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1820  PmqFree(&pmq);
1821  return result;
1822 }
1823 
1824 static int SCHSTest21(void)
1825 {
1826  int result = 0;
1827  MpmCtx mpm_ctx;
1828  MpmThreadCtx mpm_thread_ctx;
1829  PrefilterRuleStore pmq;
1830 
1831  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1832  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1833  MpmInitCtx(&mpm_ctx, MPM_HS);
1834 
1835  /* 1 */
1836  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1837  PmqSetup(&pmq);
1838 
1839  SCHSPreparePatterns(&mpm_ctx);
1840  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1841 
1842  uint32_t cnt =
1843  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"AA", 2);
1844 
1845  if (cnt == 1)
1846  result = 1;
1847  else
1848  printf("1 != %" PRIu32 " ", cnt);
1849 
1850  SCHSDestroyCtx(&mpm_ctx);
1851  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1852  PmqFree(&pmq);
1853  return result;
1854 }
1855 
1856 static int SCHSTest22(void)
1857 {
1858  int result = 0;
1859  MpmCtx mpm_ctx;
1860  MpmThreadCtx mpm_thread_ctx;
1861  PrefilterRuleStore pmq;
1862 
1863  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1864  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1865  MpmInitCtx(&mpm_ctx, MPM_HS);
1866 
1867  /* 1 match */
1868  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1869  /* 1 match */
1870  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
1871  PmqSetup(&pmq);
1872 
1873  SCHSPreparePatterns(&mpm_ctx);
1874  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1875 
1876  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1877  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1878  strlen(buf));
1879 
1880  if (cnt == 2)
1881  result = 1;
1882  else
1883  printf("2 != %" PRIu32 " ", cnt);
1884 
1885  SCHSDestroyCtx(&mpm_ctx);
1886  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1887  PmqFree(&pmq);
1888  return result;
1889 }
1890 
1891 static int SCHSTest23(void)
1892 {
1893  int result = 0;
1894  MpmCtx mpm_ctx;
1895  MpmThreadCtx mpm_thread_ctx;
1896  PrefilterRuleStore pmq;
1897 
1898  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1899  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1900  MpmInitCtx(&mpm_ctx, MPM_HS);
1901 
1902  /* 1 */
1903  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1904  PmqSetup(&pmq);
1905 
1906  SCHSPreparePatterns(&mpm_ctx);
1907  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1908 
1909  uint32_t cnt =
1910  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"aa", 2);
1911 
1912  if (cnt == 0)
1913  result = 1;
1914  else
1915  printf("1 != %" PRIu32 " ", cnt);
1916 
1917  SCHSDestroyCtx(&mpm_ctx);
1918  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1919  PmqFree(&pmq);
1920  return result;
1921 }
1922 
1923 static int SCHSTest24(void)
1924 {
1925  int result = 0;
1926  MpmCtx mpm_ctx;
1927  MpmThreadCtx mpm_thread_ctx;
1928  PrefilterRuleStore pmq;
1929 
1930  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1931  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1932  MpmInitCtx(&mpm_ctx, MPM_HS);
1933 
1934  /* 1 */
1935  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1936  PmqSetup(&pmq);
1937 
1938  SCHSPreparePatterns(&mpm_ctx);
1939  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1940 
1941  uint32_t cnt =
1942  SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)"aa", 2);
1943 
1944  if (cnt == 1)
1945  result = 1;
1946  else
1947  printf("1 != %" PRIu32 " ", cnt);
1948 
1949  SCHSDestroyCtx(&mpm_ctx);
1950  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1951  PmqFree(&pmq);
1952  return result;
1953 }
1954 
1955 static int SCHSTest25(void)
1956 {
1957  int result = 0;
1958  MpmCtx mpm_ctx;
1959  MpmThreadCtx mpm_thread_ctx;
1960  PrefilterRuleStore pmq;
1961 
1962  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1963  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1964  MpmInitCtx(&mpm_ctx, MPM_HS);
1965 
1966  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1967  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1968  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
1969  PmqSetup(&pmq);
1970 
1971  SCHSPreparePatterns(&mpm_ctx);
1972  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1973 
1974  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1975  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1976  strlen(buf));
1977 
1978  if (cnt == 3)
1979  result = 1;
1980  else
1981  printf("3 != %" PRIu32 " ", cnt);
1982 
1983  SCHSDestroyCtx(&mpm_ctx);
1984  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1985  PmqFree(&pmq);
1986  return result;
1987 }
1988 
1989 static int SCHSTest26(void)
1990 {
1991  int result = 0;
1992  MpmCtx mpm_ctx;
1993  MpmThreadCtx mpm_thread_ctx;
1994  PrefilterRuleStore pmq;
1995 
1996  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1997  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1998  MpmInitCtx(&mpm_ctx, MPM_HS);
1999 
2000  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
2001  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
2002  PmqSetup(&pmq);
2003 
2004  SCHSPreparePatterns(&mpm_ctx);
2005  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2006 
2007  const char *buf = "works";
2008  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2009  strlen(buf));
2010 
2011  if (cnt == 1)
2012  result = 1;
2013  else
2014  printf("3 != %" PRIu32 " ", cnt);
2015 
2016  SCHSDestroyCtx(&mpm_ctx);
2017  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2018  PmqFree(&pmq);
2019  return result;
2020 }
2021 
2022 static int SCHSTest27(void)
2023 {
2024  int result = 0;
2025  MpmCtx mpm_ctx;
2026  MpmThreadCtx mpm_thread_ctx;
2027  PrefilterRuleStore pmq;
2028 
2029  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2030  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2031  MpmInitCtx(&mpm_ctx, MPM_HS);
2032 
2033  /* 0 match */
2034  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
2035  PmqSetup(&pmq);
2036 
2037  SCHSPreparePatterns(&mpm_ctx);
2038  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2039 
2040  const char *buf = "tone";
2041  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2042  strlen(buf));
2043 
2044  if (cnt == 0)
2045  result = 1;
2046  else
2047  printf("0 != %" PRIu32 " ", cnt);
2048 
2049  SCHSDestroyCtx(&mpm_ctx);
2050  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2051  PmqFree(&pmq);
2052  return result;
2053 }
2054 
2055 static int SCHSTest28(void)
2056 {
2057  int result = 0;
2058  MpmCtx mpm_ctx;
2059  MpmThreadCtx mpm_thread_ctx;
2060  PrefilterRuleStore pmq;
2061 
2062  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2063  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2064  MpmInitCtx(&mpm_ctx, MPM_HS);
2065 
2066  /* 0 match */
2067  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2068  PmqSetup(&pmq);
2069 
2070  SCHSPreparePatterns(&mpm_ctx);
2071  SCHSInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2072 
2073  const char *buf = "tONE";
2074  uint32_t cnt = SCHSSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
2075  strlen(buf));
2076 
2077  if (cnt == 0)
2078  result = 1;
2079  else
2080  printf("0 != %" PRIu32 " ", cnt);
2081 
2082  SCHSDestroyCtx(&mpm_ctx);
2083  SCHSDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2084  PmqFree(&pmq);
2085  return result;
2086 }
2087 
2088 static int SCHSTest29(void)
2089 {
2090  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
2091  uint16_t buflen = sizeof(buf) - 1;
2092  Packet *p = NULL;
2093  ThreadVars th_v;
2094  DetectEngineThreadCtx *det_ctx = NULL;
2095  int result = 0;
2096 
2097  memset(&th_v, 0, sizeof(th_v));
2098  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2099 
2101  if (de_ctx == NULL)
2102  goto end;
2104 
2105  de_ctx->flags |= DE_QUIET;
2106 
2107  de_ctx->sig_list = SigInit(
2108  de_ctx, "alert tcp any any -> any any "
2109  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2110  if (de_ctx->sig_list == NULL)
2111  goto end;
2112  de_ctx->sig_list->next =
2113  SigInit(de_ctx, "alert tcp any any -> any any "
2114  "(content:\"onetwothreefourfivesixseveneightnine\"; "
2115  "fast_pattern:3,3; sid:2;)");
2116  if (de_ctx->sig_list->next == NULL)
2117  goto end;
2118 
2120  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2121 
2122  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2123  if (PacketAlertCheck(p, 1) != 1) {
2124  printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
2125  goto end;
2126  }
2127  if (PacketAlertCheck(p, 2) != 1) {
2128  printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
2129  goto end;
2130  }
2131 
2132  result = 1;
2133 end:
2134  if (de_ctx != NULL) {
2137 
2138  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2140  }
2141 
2142  UTHFreePackets(&p, 1);
2143  return result;
2144 }
2145 
2146 #endif /* UNITTESTS */
2147 
2148 void SCHSRegisterTests(void)
2149 {
2150 #ifdef UNITTESTS
2151  UtRegisterTest("SCHSTest01", SCHSTest01);
2152  UtRegisterTest("SCHSTest02", SCHSTest02);
2153  UtRegisterTest("SCHSTest03", SCHSTest03);
2154  UtRegisterTest("SCHSTest04", SCHSTest04);
2155  UtRegisterTest("SCHSTest05", SCHSTest05);
2156  UtRegisterTest("SCHSTest06", SCHSTest06);
2157  UtRegisterTest("SCHSTest07", SCHSTest07);
2158  UtRegisterTest("SCHSTest08", SCHSTest08);
2159  UtRegisterTest("SCHSTest09", SCHSTest09);
2160  UtRegisterTest("SCHSTest10", SCHSTest10);
2161  UtRegisterTest("SCHSTest11", SCHSTest11);
2162  UtRegisterTest("SCHSTest12", SCHSTest12);
2163  UtRegisterTest("SCHSTest13", SCHSTest13);
2164  UtRegisterTest("SCHSTest14", SCHSTest14);
2165  UtRegisterTest("SCHSTest15", SCHSTest15);
2166  UtRegisterTest("SCHSTest16", SCHSTest16);
2167  UtRegisterTest("SCHSTest17", SCHSTest17);
2168  UtRegisterTest("SCHSTest18", SCHSTest18);
2169  UtRegisterTest("SCHSTest19", SCHSTest19);
2170  UtRegisterTest("SCHSTest20", SCHSTest20);
2171  UtRegisterTest("SCHSTest21", SCHSTest21);
2172  UtRegisterTest("SCHSTest22", SCHSTest22);
2173  UtRegisterTest("SCHSTest23", SCHSTest23);
2174  UtRegisterTest("SCHSTest24", SCHSTest24);
2175  UtRegisterTest("SCHSTest25", SCHSTest25);
2176  UtRegisterTest("SCHSTest26", SCHSTest26);
2177  UtRegisterTest("SCHSTest27", SCHSTest27);
2178  UtRegisterTest("SCHSTest28", SCHSTest28);
2179  UtRegisterTest("SCHSTest29", SCHSTest29);
2180 #endif
2181 
2182  return;
2183 }
2184 
2185 #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:32
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
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
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2117
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:2446
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:288
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:338
util-hyperscan.h
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1786
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:45
MpmCtx_::maxdepth
uint16_t maxdepth
Definition: util-mpm.h:94
MAX
#define MAX(x, y)
Definition: suricata-common.h:376
SC_ERR_INVALID_ARGUMENTS
@ SC_ERR_INVALID_ARGUMENTS
Definition: util-error.h:82
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:79
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
MPM_HS
@ MPM_HS
Definition: util-mpm.h:38
DetectEngineThreadCtx_
Definition: detect.h:1034
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:193
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:56
HashTableRemove
int HashTableRemove(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:152
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
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:113
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:281
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:2025
Packet_
Definition: decode.h:433
detect-engine-build.h
SCHSPattern_::flags
uint8_t flags
Definition: util-mpm-hs.h:34
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:1957
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:3155
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3369
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
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:222
SCHSThreadCtx_::scratch
void * scratch
Definition: util-mpm-hs.h:66
PmqFree
void PmqFree(PrefilterRuleStore *)
Cleanup and free a Pmq.
Definition: util-prefilter.c:125
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:255
FatalError
#define FatalError(x,...)
Definition: util-debug.h:530
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
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:148
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:242
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
PmqSetup
int PmqSetup(PrefilterRuleStore *)
Setup a pmq.
Definition: util-prefilter.c:36
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:34
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2407
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
suricata.h
util-mpm-hs.h
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:296
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
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:469