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