1 /* Copyright (C) 2007-2016 Open Information Security Foundation
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
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.
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
21 * \author Jim Xu <jim.xu@windriver.com>
22 * \author Justin Viiret <justin.viiret@intel.com>
24 * MPM pattern matcher that calls the Hyperscan regex matcher.
27 #include "suricata-common.h"
31 #include "detect-parse.h"
32 #include "detect-engine.h"
35 #include "util-debug.h"
36 #include "util-unittest.h"
37 #include "util-unittest-helper.h"
38 #include "util-memcmp.h"
39 #include "util-mpm-hs.h"
40 #include "util-memcpy.h"
41 #include "util-hash.h"
42 #include "util-hash-lookup3.h"
43 #include "util-hyperscan.h"
45 #ifdef BUILD_HYPERSCAN
49 void SCHSInitCtx(MpmCtx
*);
50 void SCHSInitThreadCtx(MpmCtx
*, MpmThreadCtx
*);
51 void SCHSDestroyCtx(MpmCtx
*);
52 void SCHSDestroyThreadCtx(MpmCtx
*, MpmThreadCtx
*);
53 int SCHSAddPatternCI(MpmCtx
*, uint8_t *, uint16_t, uint16_t, uint16_t,
54 uint32_t, SigIntId
, uint8_t);
55 int SCHSAddPatternCS(MpmCtx
*, uint8_t *, uint16_t, uint16_t, uint16_t,
56 uint32_t, SigIntId
, uint8_t);
57 int SCHSPreparePatterns(MpmCtx
*mpm_ctx
);
58 uint32_t SCHSSearch(const MpmCtx
*mpm_ctx
, MpmThreadCtx
*mpm_thread_ctx
,
59 PrefilterRuleStore
*pmq
, const uint8_t *buf
, const uint32_t buflen
);
60 void SCHSPrintInfo(MpmCtx
*mpm_ctx
);
61 void SCHSPrintSearchStats(MpmThreadCtx
*mpm_thread_ctx
);
62 void SCHSRegisterTests(void);
64 /* size of the hash table used to speed up pattern insertions initially */
65 #define INIT_HASH_SIZE 65536
67 /* Initial size of the global database hash (used for de-duplication). */
68 #define INIT_DB_HASH_SIZE 1000
70 /* Global prototype scratch, built incrementally as Hyperscan databases are
71 * built and then cloned for each thread context. Access is serialised via
72 * g_scratch_proto_mutex. */
73 static hs_scratch_t
*g_scratch_proto
= NULL
;
74 static SCMutex g_scratch_proto_mutex
= SCMUTEX_INITIALIZER
;
76 /* Global hash table of Hyperscan databases, used for de-duplication. Access is
77 * serialised via g_db_table_mutex. */
78 static HashTable
*g_db_table
= NULL
;
79 static SCMutex g_db_table_mutex
= SCMUTEX_INITIALIZER
;
83 * \brief Wraps SCMalloc (which is a macro) so that it can be passed to
84 * hs_set_allocator() for Hyperscan's use.
86 static void *SCHSMalloc(size_t size
)
88 return SCMalloc(size
);
93 * \brief Wraps SCFree (which is a macro) so that it can be passed to
94 * hs_set_allocator() for Hyperscan's use.
96 static void SCHSFree(void *ptr
)
101 /** \brief Register Suricata malloc/free with Hyperscan.
103 * Requests that Hyperscan use Suricata's allocator for allocation of
104 * databases, scratch space, etc.
106 static void SCHSSetAllocators(void)
108 hs_error_t err
= hs_set_allocator(SCHSMalloc
, SCHSFree
);
109 if (err
!= HS_SUCCESS
) {
110 FatalError(SC_ERR_FATAL
, "Failed to set Hyperscan allocator.");
116 * \brief Creates a hash of the pattern. We use it for the hashing process
117 * during the initial pattern insertion time, to cull duplicate sigs.
119 * \param pat Pointer to the pattern.
120 * \param patlen Pattern length.
122 * \retval hash A 32 bit unsigned hash.
124 static inline uint32_t SCHSInitHashRaw(uint8_t *pat
, uint16_t patlen
)
126 uint32_t hash
= patlen
* pat
[0];
130 return (hash
% INIT_HASH_SIZE
);
135 * \brief Looks up a pattern. We use it for the hashing process during
136 * the initial pattern insertion time, to cull duplicate sigs.
138 * \param ctx Pointer to the HS ctx.
139 * \param pat Pointer to the pattern.
140 * \param patlen Pattern length.
141 * \param flags Flags. We don't need this.
143 * \retval hash A 32 bit unsigned hash.
145 static inline SCHSPattern
*SCHSInitHashLookup(SCHSCtx
*ctx
, uint8_t *pat
,
146 uint16_t patlen
, uint16_t offset
,
147 uint16_t depth
, char flags
,
150 uint32_t hash
= SCHSInitHashRaw(pat
, patlen
);
152 if (ctx
->init_hash
== NULL
) {
156 SCHSPattern
*t
= ctx
->init_hash
[hash
];
157 for (; t
!= NULL
; t
= t
->next
) {
158 /* Since Hyperscan uses offset/depth, we must distinguish between
159 * patterns with the same ID but different offset/depth here. */
160 if (t
->id
== pid
&& t
->offset
== offset
&& t
->depth
== depth
) {
161 BUG_ON(t
->len
!= patlen
);
162 BUG_ON(SCMemcmp(t
->original_pat
, pat
, patlen
) != 0);
172 * \brief Allocates a new pattern instance.
174 * \param mpm_ctx Pointer to the mpm context.
176 * \retval p Pointer to the newly created pattern.
178 static inline SCHSPattern
*SCHSAllocPattern(MpmCtx
*mpm_ctx
)
180 SCHSPattern
*p
= SCMalloc(sizeof(SCHSPattern
));
181 if (unlikely(p
== NULL
)) {
184 memset(p
, 0, sizeof(SCHSPattern
));
186 mpm_ctx
->memory_cnt
++;
187 mpm_ctx
->memory_size
+= sizeof(SCHSPattern
);
194 * \brief Used to free SCHSPattern instances.
196 * \param mpm_ctx Pointer to the mpm context.
197 * \param p Pointer to the SCHSPattern instance to be freed.
198 * \param free Free the above pointer or not.
200 static inline void SCHSFreePattern(MpmCtx
*mpm_ctx
, SCHSPattern
*p
)
202 if (p
!= NULL
&& p
->original_pat
!= NULL
) {
203 SCFree(p
->original_pat
);
204 mpm_ctx
->memory_cnt
--;
205 mpm_ctx
->memory_size
-= p
->len
;
208 if (p
!= NULL
&& p
->sids
!= NULL
) {
214 mpm_ctx
->memory_cnt
--;
215 mpm_ctx
->memory_size
-= sizeof(SCHSPattern
);
219 static inline uint32_t SCHSInitHash(SCHSPattern
*p
)
221 uint32_t hash
= p
->len
* p
->original_pat
[0];
223 hash
+= p
->original_pat
[1];
225 return (hash
% INIT_HASH_SIZE
);
228 static inline int SCHSInitHashAdd(SCHSCtx
*ctx
, SCHSPattern
*p
)
230 uint32_t hash
= SCHSInitHash(p
);
232 if (ctx
->init_hash
== NULL
) {
236 if (ctx
->init_hash
[hash
] == NULL
) {
237 ctx
->init_hash
[hash
] = p
;
241 SCHSPattern
*tt
= NULL
;
242 SCHSPattern
*t
= ctx
->init_hash
[hash
];
244 /* get the list tail */
257 * \brief Add a pattern to the mpm-hs context.
259 * \param mpm_ctx Mpm context.
260 * \param pat Pointer to the pattern.
261 * \param patlen Length of the pattern.
262 * \param pid Pattern id
263 * \param sid Signature id (internal id).
264 * \param flags Pattern's MPM_PATTERN_* flags.
266 * \retval 0 On success.
267 * \retval -1 On failure.
269 static int SCHSAddPattern(MpmCtx
*mpm_ctx
, uint8_t *pat
, uint16_t patlen
,
270 uint16_t offset
, uint16_t depth
, uint32_t pid
,
271 SigIntId sid
, uint8_t flags
)
273 SCHSCtx
*ctx
= (SCHSCtx
*)mpm_ctx
->ctx
;
276 flags
|= MPM_PATTERN_FLAG_OFFSET
;
279 flags
|= MPM_PATTERN_FLAG_DEPTH
;
283 SCLogWarning(SC_ERR_INVALID_ARGUMENTS
, "pattern length 0");
287 /* check if we have already inserted this pattern */
289 SCHSInitHashLookup(ctx
, pat
, patlen
, offset
, depth
, flags
, pid
);
291 SCLogDebug("Allocing new pattern");
293 /* p will never be NULL */
294 p
= SCHSAllocPattern(mpm_ctx
);
303 p
->original_pat
= SCMalloc(patlen
);
304 if (p
->original_pat
== NULL
)
306 mpm_ctx
->memory_cnt
++;
307 mpm_ctx
->memory_size
+= patlen
;
308 memcpy(p
->original_pat
, pat
, patlen
);
310 /* put in the pattern hash */
311 SCHSInitHashAdd(ctx
, p
);
313 mpm_ctx
->pattern_cnt
++;
315 if (!(mpm_ctx
->flags
& MPMCTX_FLAGS_NODEPTH
)) {
317 mpm_ctx
->maxdepth
= MAX(mpm_ctx
->maxdepth
, depth
);
318 SCLogDebug("%p: depth %u max %u", mpm_ctx
, depth
, mpm_ctx
->maxdepth
);
320 mpm_ctx
->flags
|= MPMCTX_FLAGS_NODEPTH
;
321 mpm_ctx
->maxdepth
= 0;
322 SCLogDebug("%p: alas, no depth for us", mpm_ctx
);
326 if (mpm_ctx
->maxlen
< patlen
)
327 mpm_ctx
->maxlen
= patlen
;
329 if (mpm_ctx
->minlen
== 0) {
330 mpm_ctx
->minlen
= patlen
;
332 if (mpm_ctx
->minlen
> patlen
)
333 mpm_ctx
->minlen
= patlen
;
337 p
->sids
= SCMalloc(p
->sids_size
* sizeof(SigIntId
));
338 BUG_ON(p
->sids
== NULL
);
341 /* TODO figure out how we can be called multiple times for the same CTX with the same sid */
345 for (x
= 0; x
< p
->sids_size
; x
++) {
346 if (p
->sids
[x
] == sid
) {
352 SigIntId
*sids
= SCRealloc(p
->sids
, (sizeof(SigIntId
) * (p
->sids_size
+ 1)));
353 BUG_ON(sids
== NULL
);
355 p
->sids
[p
->sids_size
] = sid
;
363 SCHSFreePattern(mpm_ctx
, p
);
368 * \brief Pattern database information used only as input to the Hyperscan
371 typedef struct SCHSCompileData_
{
376 unsigned int pattern_cnt
;
379 static SCHSCompileData
*SCHSAllocCompileData(unsigned int pattern_cnt
)
381 SCHSCompileData
*cd
= SCMalloc(pattern_cnt
* sizeof(SCHSCompileData
));
385 memset(cd
, 0, pattern_cnt
* sizeof(SCHSCompileData
));
387 cd
->pattern_cnt
= pattern_cnt
;
389 cd
->ids
= SCMalloc(pattern_cnt
* sizeof(unsigned int));
390 if (cd
->ids
== NULL
) {
393 memset(cd
->ids
, 0, pattern_cnt
* sizeof(unsigned int));
395 cd
->flags
= SCMalloc(pattern_cnt
* sizeof(unsigned int));
396 if (cd
->flags
== NULL
) {
399 memset(cd
->flags
, 0, pattern_cnt
* sizeof(unsigned int));
401 cd
->expressions
= SCMalloc(pattern_cnt
* sizeof(char *));
402 if (cd
->expressions
== NULL
) {
405 memset(cd
->expressions
, 0, pattern_cnt
* sizeof(char *));
407 cd
->ext
= SCMalloc(pattern_cnt
* sizeof(hs_expr_ext_t
*));
408 if (cd
->ext
== NULL
) {
411 memset(cd
->ext
, 0, pattern_cnt
* sizeof(hs_expr_ext_t
*));
416 SCLogDebug("SCHSCompileData alloc failed");
420 SCFree(cd
->expressions
);
427 static void SCHSFreeCompileData(SCHSCompileData
*cd
)
435 if (cd
->expressions
) {
436 for (unsigned int i
= 0; i
< cd
->pattern_cnt
; i
++) {
437 SCFree(cd
->expressions
[i
]);
439 SCFree(cd
->expressions
);
442 for (unsigned int i
= 0; i
< cd
->pattern_cnt
; i
++) {
450 typedef struct PatternDatabase_
{
451 SCHSPattern
**parray
;
452 hs_database_t
*hs_db
;
453 uint32_t pattern_cnt
;
455 /* Reference count: number of MPM contexts using this pattern database. */
459 static uint32_t SCHSPatternHash(const SCHSPattern
*p
, uint32_t hash
)
461 BUG_ON(p
->original_pat
== NULL
);
462 BUG_ON(p
->sids
== NULL
);
464 hash
= hashlittle_safe(&p
->len
, sizeof(p
->len
), hash
);
465 hash
= hashlittle_safe(&p
->flags
, sizeof(p
->flags
), hash
);
466 hash
= hashlittle_safe(p
->original_pat
, p
->len
, hash
);
467 hash
= hashlittle_safe(&p
->id
, sizeof(p
->id
), hash
);
468 hash
= hashlittle_safe(&p
->offset
, sizeof(p
->offset
), hash
);
469 hash
= hashlittle_safe(&p
->depth
, sizeof(p
->depth
), hash
);
470 hash
= hashlittle_safe(&p
->sids_size
, sizeof(p
->sids_size
), hash
);
471 hash
= hashlittle_safe(p
->sids
, p
->sids_size
* sizeof(SigIntId
), hash
);
475 static char SCHSPatternCompare(const SCHSPattern
*p1
, const SCHSPattern
*p2
)
477 if ((p1
->len
!= p2
->len
) || (p1
->flags
!= p2
->flags
) ||
478 (p1
->id
!= p2
->id
) || (p1
->offset
!= p2
->offset
) ||
479 (p1
->depth
!= p2
->depth
) || (p1
->sids_size
!= p2
->sids_size
)) {
483 if (SCMemcmp(p1
->original_pat
, p2
->original_pat
, p1
->len
) != 0) {
487 if (SCMemcmp(p1
->sids
, p2
->sids
, p1
->sids_size
* sizeof(p1
->sids
[0])) !=
495 static uint32_t PatternDatabaseHash(HashTable
*ht
, void *data
, uint16_t len
)
497 const PatternDatabase
*pd
= data
;
499 hash
= hashword(&pd
->pattern_cnt
, 1, hash
);
501 for (uint32_t i
= 0; i
< pd
->pattern_cnt
; i
++) {
502 hash
= SCHSPatternHash(pd
->parray
[i
], hash
);
505 hash
%= ht
->array_size
;
509 static char PatternDatabaseCompare(void *data1
, uint16_t len1
, void *data2
,
512 const PatternDatabase
*pd1
= data1
;
513 const PatternDatabase
*pd2
= data2
;
515 if (pd1
->pattern_cnt
!= pd2
->pattern_cnt
) {
519 for (uint32_t i
= 0; i
< pd1
->pattern_cnt
; i
++) {
520 if (SCHSPatternCompare(pd1
->parray
[i
], pd2
->parray
[i
]) == 0) {
528 static void PatternDatabaseFree(PatternDatabase
*pd
)
530 BUG_ON(pd
->ref_cnt
!= 0);
532 if (pd
->parray
!= NULL
) {
533 for (uint32_t i
= 0; i
< pd
->pattern_cnt
; i
++) {
534 SCHSPattern
*p
= pd
->parray
[i
];
536 SCFree(p
->original_pat
);
544 hs_free_database(pd
->hs_db
);
549 static void PatternDatabaseTableFree(void *data
)
551 /* Stub function handed to hash table; actual freeing of PatternDatabase
552 * structures is done in MPM destruction when the ref_cnt drops to zero. */
555 static PatternDatabase
*PatternDatabaseAlloc(uint32_t pattern_cnt
)
557 PatternDatabase
*pd
= SCMalloc(sizeof(PatternDatabase
));
561 memset(pd
, 0, sizeof(PatternDatabase
));
562 pd
->pattern_cnt
= pattern_cnt
;
566 /* alloc the pattern array */
568 (SCHSPattern
**)SCMalloc(pd
->pattern_cnt
* sizeof(SCHSPattern
*));
569 if (pd
->parray
== NULL
) {
573 memset(pd
->parray
, 0, pd
->pattern_cnt
* sizeof(SCHSPattern
*));
579 * \brief Process the patterns added to the mpm, and create the internal tables.
581 * \param mpm_ctx Pointer to the mpm context.
583 int SCHSPreparePatterns(MpmCtx
*mpm_ctx
)
585 SCHSCtx
*ctx
= (SCHSCtx
*)mpm_ctx
->ctx
;
587 if (mpm_ctx
->pattern_cnt
== 0 || ctx
->init_hash
== NULL
) {
588 SCLogDebug("no patterns supplied to this mpm_ctx");
593 hs_compile_error_t
*compile_err
= NULL
;
594 SCHSCompileData
*cd
= NULL
;
595 PatternDatabase
*pd
= NULL
;
597 cd
= SCHSAllocCompileData(mpm_ctx
->pattern_cnt
);
602 pd
= PatternDatabaseAlloc(mpm_ctx
->pattern_cnt
);
607 /* populate the pattern array with the patterns in the hash */
608 for (uint32_t i
= 0, p
= 0; i
< INIT_HASH_SIZE
; i
++) {
609 SCHSPattern
*node
= ctx
->init_hash
[i
], *nnode
= NULL
;
610 while (node
!= NULL
) {
613 pd
->parray
[p
++] = node
;
618 /* we no longer need the hash, so free its memory */
619 SCFree(ctx
->init_hash
);
620 ctx
->init_hash
= NULL
;
622 /* Serialise whole database compilation as a relatively easy way to ensure
624 SCMutexLock(&g_db_table_mutex
);
626 /* Init global pattern database hash if necessary. */
627 if (g_db_table
== NULL
) {
628 g_db_table
= HashTableInit(INIT_DB_HASH_SIZE
, PatternDatabaseHash
,
629 PatternDatabaseCompare
,
630 PatternDatabaseTableFree
);
631 if (g_db_table
== NULL
) {
632 SCMutexUnlock(&g_db_table_mutex
);
637 /* Check global hash table to see if we've seen this pattern database
638 * before, and reuse the Hyperscan database if so. */
639 PatternDatabase
*pd_cached
= HashTableLookup(g_db_table
, pd
, 1);
641 if (pd_cached
!= NULL
) {
642 SCLogDebug("Reusing cached database %p with %" PRIu32
643 " patterns (ref_cnt=%" PRIu32
")",
644 pd_cached
->hs_db
, pd_cached
->pattern_cnt
,
646 pd_cached
->ref_cnt
++;
647 ctx
->pattern_db
= pd_cached
;
648 SCMutexUnlock(&g_db_table_mutex
);
649 PatternDatabaseFree(pd
);
650 SCHSFreeCompileData(cd
);
654 BUG_ON(ctx
->pattern_db
!= NULL
); /* already built? */
656 for (uint32_t i
= 0; i
< pd
->pattern_cnt
; i
++) {
657 const SCHSPattern
*p
= pd
->parray
[i
];
660 cd
->flags
[i
] = HS_FLAG_SINGLEMATCH
;
661 if (p
->flags
& MPM_PATTERN_FLAG_NOCASE
) {
662 cd
->flags
[i
] |= HS_FLAG_CASELESS
;
665 cd
->expressions
[i
] = HSRenderPattern(p
->original_pat
, p
->len
);
667 if (p
->flags
& (MPM_PATTERN_FLAG_OFFSET
| MPM_PATTERN_FLAG_DEPTH
)) {
668 cd
->ext
[i
] = SCMalloc(sizeof(hs_expr_ext_t
));
669 if (cd
->ext
[i
] == NULL
) {
670 SCMutexUnlock(&g_db_table_mutex
);
673 memset(cd
->ext
[i
], 0, sizeof(hs_expr_ext_t
));
675 if (p
->flags
& MPM_PATTERN_FLAG_OFFSET
) {
676 cd
->ext
[i
]->flags
|= HS_EXT_FLAG_MIN_OFFSET
;
677 cd
->ext
[i
]->min_offset
= p
->offset
+ p
->len
;
679 if (p
->flags
& MPM_PATTERN_FLAG_DEPTH
) {
680 cd
->ext
[i
]->flags
|= HS_EXT_FLAG_MAX_OFFSET
;
681 cd
->ext
[i
]->max_offset
= p
->offset
+ p
->depth
;
686 BUG_ON(mpm_ctx
->pattern_cnt
== 0);
688 err
= hs_compile_ext_multi((const char *const *)cd
->expressions
, cd
->flags
,
689 cd
->ids
, (const hs_expr_ext_t
*const *)cd
->ext
,
690 cd
->pattern_cnt
, HS_MODE_BLOCK
, NULL
, &pd
->hs_db
,
693 if (err
!= HS_SUCCESS
) {
694 SCLogError(SC_ERR_FATAL
, "failed to compile hyperscan database");
696 SCLogError(SC_ERR_FATAL
, "compile error: %s", compile_err
->message
);
698 hs_free_compile_error(compile_err
);
699 SCMutexUnlock(&g_db_table_mutex
);
703 ctx
->pattern_db
= pd
;
705 SCMutexLock(&g_scratch_proto_mutex
);
706 err
= hs_alloc_scratch(pd
->hs_db
, &g_scratch_proto
);
707 SCMutexUnlock(&g_scratch_proto_mutex
);
708 if (err
!= HS_SUCCESS
) {
709 SCLogError(SC_ERR_FATAL
, "failed to allocate scratch");
710 SCMutexUnlock(&g_db_table_mutex
);
714 err
= hs_database_size(pd
->hs_db
, &ctx
->hs_db_size
);
715 if (err
!= HS_SUCCESS
) {
716 SCLogError(SC_ERR_FATAL
, "failed to query database size");
717 SCMutexUnlock(&g_db_table_mutex
);
721 mpm_ctx
->memory_cnt
++;
722 mpm_ctx
->memory_size
+= ctx
->hs_db_size
;
724 SCLogDebug("Built %" PRIu32
" patterns into a database of size %" PRIuMAX
725 " bytes", mpm_ctx
->pattern_cnt
, (uintmax_t)ctx
->hs_db_size
);
727 /* Cache this database globally for later. */
729 int r
= HashTableAdd(g_db_table
, pd
, 1);
730 SCMutexUnlock(&g_db_table_mutex
);
734 SCHSFreeCompileData(cd
);
739 PatternDatabaseFree(pd
);
742 SCHSFreeCompileData(cd
);
748 * \brief Init the mpm thread context.
750 * \param mpm_ctx Pointer to the mpm context.
751 * \param mpm_thread_ctx Pointer to the mpm thread context.
753 void SCHSInitThreadCtx(MpmCtx
*mpm_ctx
, MpmThreadCtx
*mpm_thread_ctx
)
755 memset(mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
757 SCHSThreadCtx
*ctx
= SCMalloc(sizeof(SCHSThreadCtx
));
761 mpm_thread_ctx
->ctx
= ctx
;
763 memset(ctx
, 0, sizeof(SCHSThreadCtx
));
764 mpm_thread_ctx
->memory_cnt
++;
765 mpm_thread_ctx
->memory_size
+= sizeof(SCHSThreadCtx
);
768 ctx
->scratch_size
= 0;
770 SCMutexLock(&g_scratch_proto_mutex
);
772 if (g_scratch_proto
== NULL
) {
773 /* There is no scratch prototype: this means that we have not compiled
774 * any Hyperscan databases. */
775 SCMutexUnlock(&g_scratch_proto_mutex
);
776 SCLogDebug("No scratch space prototype");
780 hs_error_t err
= hs_clone_scratch(g_scratch_proto
,
781 (hs_scratch_t
**)&ctx
->scratch
);
783 SCMutexUnlock(&g_scratch_proto_mutex
);
785 if (err
!= HS_SUCCESS
) {
786 FatalError(SC_ERR_FATAL
, "Unable to clone scratch prototype");
789 err
= hs_scratch_size(ctx
->scratch
, &ctx
->scratch_size
);
790 if (err
!= HS_SUCCESS
) {
791 FatalError(SC_ERR_FATAL
, "Unable to query scratch size");
794 mpm_thread_ctx
->memory_cnt
++;
795 mpm_thread_ctx
->memory_size
+= ctx
->scratch_size
;
799 * \brief Initialize the HS context.
801 * \param mpm_ctx Mpm context.
803 void SCHSInitCtx(MpmCtx
*mpm_ctx
)
805 if (mpm_ctx
->ctx
!= NULL
)
808 mpm_ctx
->ctx
= SCMalloc(sizeof(SCHSCtx
));
809 if (mpm_ctx
->ctx
== NULL
) {
812 memset(mpm_ctx
->ctx
, 0, sizeof(SCHSCtx
));
814 mpm_ctx
->memory_cnt
++;
815 mpm_ctx
->memory_size
+= sizeof(SCHSCtx
);
817 /* initialize the hash we use to speed up pattern insertions */
818 SCHSCtx
*ctx
= (SCHSCtx
*)mpm_ctx
->ctx
;
819 ctx
->init_hash
= SCMalloc(sizeof(SCHSPattern
*) * INIT_HASH_SIZE
);
820 if (ctx
->init_hash
== NULL
) {
823 memset(ctx
->init_hash
, 0, sizeof(SCHSPattern
*) * INIT_HASH_SIZE
);
827 * \brief Destroy the mpm thread context.
829 * \param mpm_ctx Pointer to the mpm context.
830 * \param mpm_thread_ctx Pointer to the mpm thread context.
832 void SCHSDestroyThreadCtx(MpmCtx
*mpm_ctx
, MpmThreadCtx
*mpm_thread_ctx
)
834 SCHSPrintSearchStats(mpm_thread_ctx
);
836 if (mpm_thread_ctx
->ctx
!= NULL
) {
837 SCHSThreadCtx
*thr_ctx
= (SCHSThreadCtx
*)mpm_thread_ctx
->ctx
;
839 if (thr_ctx
->scratch
!= NULL
) {
840 hs_free_scratch(thr_ctx
->scratch
);
841 mpm_thread_ctx
->memory_cnt
--;
842 mpm_thread_ctx
->memory_size
-= thr_ctx
->scratch_size
;
845 SCFree(mpm_thread_ctx
->ctx
);
846 mpm_thread_ctx
->ctx
= NULL
;
847 mpm_thread_ctx
->memory_cnt
--;
848 mpm_thread_ctx
->memory_size
-= sizeof(SCHSThreadCtx
);
853 * \brief Destroy the mpm context.
855 * \param mpm_ctx Pointer to the mpm context.
857 void SCHSDestroyCtx(MpmCtx
*mpm_ctx
)
859 SCHSCtx
*ctx
= (SCHSCtx
*)mpm_ctx
->ctx
;
863 if (ctx
->init_hash
!= NULL
) {
864 SCFree(ctx
->init_hash
);
865 ctx
->init_hash
= NULL
;
866 mpm_ctx
->memory_cnt
--;
867 mpm_ctx
->memory_size
-= (INIT_HASH_SIZE
* sizeof(SCHSPattern
*));
870 /* Decrement pattern database ref count, and delete it entirely if the
871 * count has dropped to zero. */
872 SCMutexLock(&g_db_table_mutex
);
873 PatternDatabase
*pd
= ctx
->pattern_db
;
875 BUG_ON(pd
->ref_cnt
== 0);
877 if (pd
->ref_cnt
== 0) {
878 HashTableRemove(g_db_table
, pd
, 1);
879 PatternDatabaseFree(pd
);
882 SCMutexUnlock(&g_db_table_mutex
);
884 SCFree(mpm_ctx
->ctx
);
885 mpm_ctx
->memory_cnt
--;
886 mpm_ctx
->memory_size
-= sizeof(SCHSCtx
);
889 typedef struct SCHSCallbackCtx_
{
892 uint32_t match_count
;
895 /* Hyperscan MPM match event handler */
896 static int SCHSMatchEvent(unsigned int id
, unsigned long long from
,
897 unsigned long long to
, unsigned int flags
,
900 SCHSCallbackCtx
*cctx
= ctx
;
901 PrefilterRuleStore
*pmq
= cctx
->pmq
;
902 const PatternDatabase
*pd
= cctx
->ctx
->pattern_db
;
903 const SCHSPattern
*pat
= pd
->parray
[id
];
905 SCLogDebug("Hyperscan Match %" PRIu32
": id=%" PRIu32
" @ %" PRIuMAX
906 " (pat id=%" PRIu32
")",
907 cctx
->match_count
, (uint32_t)id
, (uintmax_t)to
, pat
->id
);
909 PrefilterAddSids(pmq
, pat
->sids
, pat
->sids_size
);
916 * \brief The Hyperscan search function.
918 * \param mpm_ctx Pointer to the mpm context.
919 * \param mpm_thread_ctx Pointer to the mpm thread context.
920 * \param pmq Pointer to the Pattern Matcher Queue to hold
922 * \param buf Buffer to be searched.
923 * \param buflen Buffer length.
925 * \retval matches Match count.
927 uint32_t SCHSSearch(const MpmCtx
*mpm_ctx
, MpmThreadCtx
*mpm_thread_ctx
,
928 PrefilterRuleStore
*pmq
, const uint8_t *buf
, const uint32_t buflen
)
931 SCHSCtx
*ctx
= (SCHSCtx
*)mpm_ctx
->ctx
;
932 SCHSThreadCtx
*hs_thread_ctx
= (SCHSThreadCtx
*)(mpm_thread_ctx
->ctx
);
933 const PatternDatabase
*pd
= ctx
->pattern_db
;
935 if (unlikely(buflen
== 0)) {
939 SCHSCallbackCtx cctx
= {.ctx
= ctx
, .pmq
= pmq
, .match_count
= 0};
941 /* scratch should have been cloned from g_scratch_proto at thread init. */
942 hs_scratch_t
*scratch
= hs_thread_ctx
->scratch
;
943 BUG_ON(pd
->hs_db
== NULL
);
944 BUG_ON(scratch
== NULL
);
946 hs_error_t err
= hs_scan(pd
->hs_db
, (const char *)buf
, buflen
, 0, scratch
,
947 SCHSMatchEvent
, &cctx
);
948 if (err
!= HS_SUCCESS
) {
949 /* An error value (other than HS_SCAN_TERMINATED) from hs_scan()
950 * indicates that it was passed an invalid database or scratch region,
951 * which is not something we can recover from at scan time. */
952 SCLogError(SC_ERR_FATAL
, "Hyperscan returned error %d", err
);
955 ret
= cctx
.match_count
;
962 * \brief Add a case insensitive pattern. Although we have different calls for
963 * adding case sensitive and insensitive patterns, we make a single call
964 * for either case. No special treatment for either case.
966 * \param mpm_ctx Pointer to the mpm context.
967 * \param pat The pattern to add.
968 * \param patlen The pattern length.
969 * \param offset The pattern offset.
970 * \param depth The pattern depth.
971 * \param pid The pattern id.
972 * \param sid The pattern signature id.
973 * \param flags Flags associated with this pattern.
975 * \retval 0 On success.
976 * \retval -1 On failure.
978 int SCHSAddPatternCI(MpmCtx
*mpm_ctx
, uint8_t *pat
, uint16_t patlen
,
979 uint16_t offset
, uint16_t depth
, uint32_t pid
,
980 SigIntId sid
, uint8_t flags
)
982 flags
|= MPM_PATTERN_FLAG_NOCASE
;
983 return SCHSAddPattern(mpm_ctx
, pat
, patlen
, offset
, depth
, pid
, sid
, flags
);
987 * \brief Add a case sensitive pattern. Although we have different calls for
988 * adding case sensitive and insensitive patterns, we make a single call
989 * for either case. No special treatment for either case.
991 * \param mpm_ctx Pointer to the mpm context.
992 * \param pat The pattern to add.
993 * \param patlen The pattern length.
994 * \param offset The pattern offset.
995 * \param depth The pattern depth.
996 * \param pid The pattern id.
997 * \param sid The pattern signature id.
998 * \param flags Flags associated with this pattern.
1000 * \retval 0 On success.
1001 * \retval -1 On failure.
1003 int SCHSAddPatternCS(MpmCtx
*mpm_ctx
, uint8_t *pat
, uint16_t patlen
,
1004 uint16_t offset
, uint16_t depth
, uint32_t pid
,
1005 SigIntId sid
, uint8_t flags
)
1007 return SCHSAddPattern(mpm_ctx
, pat
, patlen
, offset
, depth
, pid
, sid
, flags
);
1010 void SCHSPrintSearchStats(MpmThreadCtx
*mpm_thread_ctx
)
1015 void SCHSPrintInfo(MpmCtx
*mpm_ctx
)
1017 SCHSCtx
*ctx
= (SCHSCtx
*)mpm_ctx
->ctx
;
1019 printf("MPM HS Information:\n");
1020 printf("Memory allocs: %" PRIu32
"\n", mpm_ctx
->memory_cnt
);
1021 printf("Memory alloced: %" PRIu32
"\n", mpm_ctx
->memory_size
);
1022 printf(" Sizeof:\n");
1023 printf(" MpmCtx %" PRIuMAX
"\n", (uintmax_t)sizeof(MpmCtx
));
1024 printf(" SCHSCtx: %" PRIuMAX
"\n", (uintmax_t)sizeof(SCHSCtx
));
1025 printf(" SCHSPattern %" PRIuMAX
"\n", (uintmax_t)sizeof(SCHSPattern
));
1026 printf("Unique Patterns: %" PRIu32
"\n", mpm_ctx
->pattern_cnt
);
1027 printf("Smallest: %" PRIu32
"\n", mpm_ctx
->minlen
);
1028 printf("Largest: %" PRIu32
"\n", mpm_ctx
->maxlen
);
1032 PatternDatabase
*pd
= ctx
->pattern_db
;
1033 char *db_info
= NULL
;
1034 if (hs_database_info(pd
->hs_db
, &db_info
) == HS_SUCCESS
) {
1035 printf("HS Database Info: %s\n", db_info
);
1038 printf("HS Database Size: %" PRIuMAX
" bytes\n",
1039 (uintmax_t)ctx
->hs_db_size
);
1045 /************************** Mpm Registration ***************************/
1048 * \brief Register the Hyperscan MPM.
1050 void MpmHSRegister(void)
1052 mpm_table
[MPM_HS
].name
= "hs";
1053 mpm_table
[MPM_HS
].InitCtx
= SCHSInitCtx
;
1054 mpm_table
[MPM_HS
].InitThreadCtx
= SCHSInitThreadCtx
;
1055 mpm_table
[MPM_HS
].DestroyCtx
= SCHSDestroyCtx
;
1056 mpm_table
[MPM_HS
].DestroyThreadCtx
= SCHSDestroyThreadCtx
;
1057 mpm_table
[MPM_HS
].AddPattern
= SCHSAddPatternCS
;
1058 mpm_table
[MPM_HS
].AddPatternNocase
= SCHSAddPatternCI
;
1059 mpm_table
[MPM_HS
].Prepare
= SCHSPreparePatterns
;
1060 mpm_table
[MPM_HS
].Search
= SCHSSearch
;
1061 mpm_table
[MPM_HS
].PrintCtx
= SCHSPrintInfo
;
1062 mpm_table
[MPM_HS
].PrintThreadCtx
= SCHSPrintSearchStats
;
1063 mpm_table
[MPM_HS
].RegisterUnittests
= SCHSRegisterTests
;
1065 /* Set Hyperscan memory allocators */
1066 SCHSSetAllocators();
1070 * \brief Clean up global memory used by all Hyperscan MPM instances.
1072 * Currently, this is just the global scratch prototype.
1074 void MpmHSGlobalCleanup(void)
1076 SCMutexLock(&g_scratch_proto_mutex
);
1077 if (g_scratch_proto
) {
1078 SCLogPerf("Cleaning up Hyperscan global scratch");
1079 hs_free_scratch(g_scratch_proto
);
1080 g_scratch_proto
= NULL
;
1082 SCMutexUnlock(&g_scratch_proto_mutex
);
1084 SCMutexLock(&g_db_table_mutex
);
1085 if (g_db_table
!= NULL
) {
1086 SCLogPerf("Clearing Hyperscan database cache");
1087 HashTableFree(g_db_table
);
1090 SCMutexUnlock(&g_db_table_mutex
);
1093 /*************************************Unittests********************************/
1097 static int SCHSTest01(void)
1101 MpmThreadCtx mpm_thread_ctx
;
1102 PrefilterRuleStore pmq
;
1104 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1105 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1106 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1109 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1112 SCHSPreparePatterns(&mpm_ctx
);
1113 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1115 const char *buf
= "abcdefghjiklmnopqrstuvwxyz";
1117 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1123 printf("1 != %" PRIu32
" ", cnt
);
1125 SCHSDestroyCtx(&mpm_ctx
);
1126 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1131 static int SCHSTest02(void)
1135 MpmThreadCtx mpm_thread_ctx
;
1136 PrefilterRuleStore pmq
;
1138 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1139 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1140 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1143 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1146 SCHSPreparePatterns(&mpm_ctx
);
1147 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1149 const char *buf
= "abcdefghjiklmnopqrstuvwxyz";
1150 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1156 printf("0 != %" PRIu32
" ", cnt
);
1158 SCHSDestroyCtx(&mpm_ctx
);
1159 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1164 static int SCHSTest03(void)
1168 MpmThreadCtx mpm_thread_ctx
;
1169 PrefilterRuleStore pmq
;
1171 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1172 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1173 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1176 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1178 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1180 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1183 SCHSPreparePatterns(&mpm_ctx
);
1184 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1186 const char *buf
= "abcdefghjiklmnopqrstuvwxyz";
1187 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1193 printf("3 != %" PRIu32
" ", cnt
);
1195 SCHSDestroyCtx(&mpm_ctx
);
1196 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1201 static int SCHSTest04(void)
1205 MpmThreadCtx mpm_thread_ctx
;
1206 PrefilterRuleStore pmq
;
1208 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1209 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1210 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1212 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1213 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1214 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1217 SCHSPreparePatterns(&mpm_ctx
);
1218 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1220 const char *buf
= "abcdefghjiklmnopqrstuvwxyz";
1221 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1227 printf("1 != %" PRIu32
" ", cnt
);
1229 SCHSDestroyCtx(&mpm_ctx
);
1230 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1235 static int SCHSTest05(void)
1239 MpmThreadCtx mpm_thread_ctx
;
1240 PrefilterRuleStore pmq
;
1242 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1243 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1244 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1246 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1247 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1248 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1251 SCHSPreparePatterns(&mpm_ctx
);
1252 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1254 const char *buf
= "abcdefghjiklmnopqrstuvwxyz";
1255 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1261 printf("3 != %" PRIu32
" ", cnt
);
1263 SCHSDestroyCtx(&mpm_ctx
);
1264 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1269 static int SCHSTest06(void)
1273 MpmThreadCtx mpm_thread_ctx
;
1274 PrefilterRuleStore pmq
;
1276 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1277 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1278 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1280 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1283 SCHSPreparePatterns(&mpm_ctx
);
1284 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1286 const char *buf
= "abcd";
1287 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1293 printf("1 != %" PRIu32
" ", cnt
);
1295 SCHSDestroyCtx(&mpm_ctx
);
1296 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1301 static int SCHSTest07(void)
1305 MpmThreadCtx mpm_thread_ctx
;
1306 PrefilterRuleStore pmq
;
1308 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1309 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1310 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1312 /* should match 30 times */
1313 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1314 /* should match 29 times */
1315 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1316 /* should match 28 times */
1317 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1319 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1321 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1323 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 30,
1327 SCHSPreparePatterns(&mpm_ctx
);
1328 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1330 const char *buf
= "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1331 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1337 printf("6 != %" PRIu32
" ", cnt
);
1339 SCHSDestroyCtx(&mpm_ctx
);
1340 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1345 static int SCHSTest08(void)
1349 MpmThreadCtx mpm_thread_ctx
;
1350 PrefilterRuleStore pmq
;
1352 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1353 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1354 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1357 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1360 SCHSPreparePatterns(&mpm_ctx
);
1361 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1364 SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)"a", 1);
1369 printf("0 != %" PRIu32
" ", cnt
);
1371 SCHSDestroyCtx(&mpm_ctx
);
1372 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1377 static int SCHSTest09(void)
1381 MpmThreadCtx mpm_thread_ctx
;
1382 PrefilterRuleStore pmq
;
1384 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1385 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1386 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1389 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1392 SCHSPreparePatterns(&mpm_ctx
);
1393 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1396 SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)"ab", 2);
1401 printf("1 != %" PRIu32
" ", cnt
);
1403 SCHSDestroyCtx(&mpm_ctx
);
1404 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1409 static int SCHSTest10(void)
1413 MpmThreadCtx mpm_thread_ctx
;
1414 PrefilterRuleStore pmq
;
1416 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1417 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1418 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1421 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1424 SCHSPreparePatterns(&mpm_ctx
);
1425 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1427 const char *buf
= "01234567890123456789012345678901234567890123456789"
1428 "01234567890123456789012345678901234567890123456789"
1430 "01234567890123456789012345678901234567890123456789"
1431 "01234567890123456789012345678901234567890123456789";
1432 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1438 printf("1 != %" PRIu32
" ", cnt
);
1440 SCHSDestroyCtx(&mpm_ctx
);
1441 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1446 static int SCHSTest11(void)
1450 MpmThreadCtx mpm_thread_ctx
;
1451 PrefilterRuleStore pmq
;
1453 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
1454 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1455 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1457 if (MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1459 if (MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1461 if (MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1463 if (MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1467 if (SCHSPreparePatterns(&mpm_ctx
) == -1)
1470 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1474 const char *buf
= "he";
1475 result
&= (SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1478 result
&= (SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1481 result
&= (SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1484 result
&= (SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1488 SCHSDestroyCtx(&mpm_ctx
);
1489 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1494 static int SCHSTest12(void)
1498 MpmThreadCtx mpm_thread_ctx
;
1499 PrefilterRuleStore pmq
;
1501 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1502 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1503 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1506 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1508 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1511 SCHSPreparePatterns(&mpm_ctx
);
1512 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1514 const char *buf
= "abcdefghijklmnopqrstuvwxyz";
1515 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1521 printf("2 != %" PRIu32
" ", cnt
);
1523 SCHSDestroyCtx(&mpm_ctx
);
1524 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1529 static int SCHSTest13(void)
1533 MpmThreadCtx mpm_thread_ctx
;
1534 PrefilterRuleStore pmq
;
1536 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1537 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1538 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1541 const char *pat
= "abcdefghijklmnopqrstuvwxyzABCD";
1542 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1545 SCHSPreparePatterns(&mpm_ctx
);
1546 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1548 const char *buf
= "abcdefghijklmnopqrstuvwxyzABCD";
1549 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1555 printf("1 != %" PRIu32
" ", cnt
);
1557 SCHSDestroyCtx(&mpm_ctx
);
1558 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1563 static int SCHSTest14(void)
1567 MpmThreadCtx mpm_thread_ctx
;
1568 PrefilterRuleStore pmq
;
1570 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1571 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1572 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1575 const char *pat
= "abcdefghijklmnopqrstuvwxyzABCDE";
1576 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1579 SCHSPreparePatterns(&mpm_ctx
);
1580 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1582 const char *buf
= "abcdefghijklmnopqrstuvwxyzABCDE";
1583 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1589 printf("1 != %" PRIu32
" ", cnt
);
1591 SCHSDestroyCtx(&mpm_ctx
);
1592 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1597 static int SCHSTest15(void)
1601 MpmThreadCtx mpm_thread_ctx
;
1602 PrefilterRuleStore pmq
;
1604 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1605 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1606 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1609 const char *pat
= "abcdefghijklmnopqrstuvwxyzABCDEF";
1610 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1613 SCHSPreparePatterns(&mpm_ctx
);
1614 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1616 const char *buf
= "abcdefghijklmnopqrstuvwxyzABCDEF";
1617 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1623 printf("1 != %" PRIu32
" ", cnt
);
1625 SCHSDestroyCtx(&mpm_ctx
);
1626 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1631 static int SCHSTest16(void)
1635 MpmThreadCtx mpm_thread_ctx
;
1636 PrefilterRuleStore pmq
;
1638 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1639 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1640 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1643 const char *pat
= "abcdefghijklmnopqrstuvwxyzABC";
1644 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1647 SCHSPreparePatterns(&mpm_ctx
);
1648 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1650 const char *buf
= "abcdefghijklmnopqrstuvwxyzABC";
1651 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1657 printf("1 != %" PRIu32
" ", cnt
);
1659 SCHSDestroyCtx(&mpm_ctx
);
1660 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1665 static int SCHSTest17(void)
1669 MpmThreadCtx mpm_thread_ctx
;
1670 PrefilterRuleStore pmq
;
1672 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1673 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1674 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1677 const char *pat
= "abcdefghijklmnopqrstuvwxyzAB";
1678 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1681 SCHSPreparePatterns(&mpm_ctx
);
1682 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1684 const char *buf
= "abcdefghijklmnopqrstuvwxyzAB";
1685 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1691 printf("1 != %" PRIu32
" ", cnt
);
1693 SCHSDestroyCtx(&mpm_ctx
);
1694 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1699 static int SCHSTest18(void)
1703 MpmThreadCtx mpm_thread_ctx
;
1704 PrefilterRuleStore pmq
;
1706 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1707 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1708 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1711 const char *pat
= "abcde"
1717 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1720 SCHSPreparePatterns(&mpm_ctx
);
1721 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1723 const char *buf
= "abcde"
1729 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1735 printf("1 != %" PRIu32
" ", cnt
);
1737 SCHSDestroyCtx(&mpm_ctx
);
1738 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1743 static int SCHSTest19(void)
1747 MpmThreadCtx mpm_thread_ctx
;
1748 PrefilterRuleStore pmq
;
1750 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1751 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1752 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1755 const char *pat
= "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1756 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1759 SCHSPreparePatterns(&mpm_ctx
);
1760 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1762 const char *buf
= "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1763 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1769 printf("1 != %" PRIu32
" ", cnt
);
1771 SCHSDestroyCtx(&mpm_ctx
);
1772 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1777 static int SCHSTest20(void)
1781 MpmThreadCtx mpm_thread_ctx
;
1782 PrefilterRuleStore pmq
;
1784 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1785 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1786 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1789 const char *pat
= "AAAAA"
1796 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)pat
, strlen(pat
), 0, 0, 0, 0, 0);
1799 SCHSPreparePatterns(&mpm_ctx
);
1800 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1802 const char *buf
= "AAAAA"
1809 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1815 printf("1 != %" PRIu32
" ", cnt
);
1817 SCHSDestroyCtx(&mpm_ctx
);
1818 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1823 static int SCHSTest21(void)
1827 MpmThreadCtx mpm_thread_ctx
;
1828 PrefilterRuleStore pmq
;
1830 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1831 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1832 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1835 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1838 SCHSPreparePatterns(&mpm_ctx
);
1839 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1842 SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)"AA", 2);
1847 printf("1 != %" PRIu32
" ", cnt
);
1849 SCHSDestroyCtx(&mpm_ctx
);
1850 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1855 static int SCHSTest22(void)
1859 MpmThreadCtx mpm_thread_ctx
;
1860 PrefilterRuleStore pmq
;
1862 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1863 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1864 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1867 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1869 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
1872 SCHSPreparePatterns(&mpm_ctx
);
1873 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1875 const char *buf
= "abcdefghijklmnopqrstuvwxyz";
1876 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1882 printf("2 != %" PRIu32
" ", cnt
);
1884 SCHSDestroyCtx(&mpm_ctx
);
1885 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1890 static int SCHSTest23(void)
1894 MpmThreadCtx mpm_thread_ctx
;
1895 PrefilterRuleStore pmq
;
1897 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1898 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1899 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1902 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1905 SCHSPreparePatterns(&mpm_ctx
);
1906 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1909 SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)"aa", 2);
1914 printf("1 != %" PRIu32
" ", cnt
);
1916 SCHSDestroyCtx(&mpm_ctx
);
1917 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1922 static int SCHSTest24(void)
1926 MpmThreadCtx mpm_thread_ctx
;
1927 PrefilterRuleStore pmq
;
1929 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1930 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1931 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1934 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1937 SCHSPreparePatterns(&mpm_ctx
);
1938 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1941 SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)"aa", 2);
1946 printf("1 != %" PRIu32
" ", cnt
);
1948 SCHSDestroyCtx(&mpm_ctx
);
1949 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1954 static int SCHSTest25(void)
1958 MpmThreadCtx mpm_thread_ctx
;
1959 PrefilterRuleStore pmq
;
1961 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1962 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1963 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1965 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1966 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1967 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
1970 SCHSPreparePatterns(&mpm_ctx
);
1971 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1973 const char *buf
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1974 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
1980 printf("3 != %" PRIu32
" ", cnt
);
1982 SCHSDestroyCtx(&mpm_ctx
);
1983 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
1988 static int SCHSTest26(void)
1992 MpmThreadCtx mpm_thread_ctx
;
1993 PrefilterRuleStore pmq
;
1995 memset(&mpm_ctx
, 0x00, sizeof(MpmCtx
));
1996 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
1997 MpmInitCtx(&mpm_ctx
, MPM_HS
);
1999 MpmAddPatternCI(&mpm_ctx
, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
2000 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
2003 SCHSPreparePatterns(&mpm_ctx
);
2004 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
2006 const char *buf
= "works";
2007 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
2013 printf("3 != %" PRIu32
" ", cnt
);
2015 SCHSDestroyCtx(&mpm_ctx
);
2016 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
2021 static int SCHSTest27(void)
2025 MpmThreadCtx mpm_thread_ctx
;
2026 PrefilterRuleStore pmq
;
2028 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
2029 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
2030 MpmInitCtx(&mpm_ctx
, MPM_HS
);
2033 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
2036 SCHSPreparePatterns(&mpm_ctx
);
2037 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
2039 const char *buf
= "tone";
2040 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
2046 printf("0 != %" PRIu32
" ", cnt
);
2048 SCHSDestroyCtx(&mpm_ctx
);
2049 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
2054 static int SCHSTest28(void)
2058 MpmThreadCtx mpm_thread_ctx
;
2059 PrefilterRuleStore pmq
;
2061 memset(&mpm_ctx
, 0, sizeof(MpmCtx
));
2062 memset(&mpm_thread_ctx
, 0, sizeof(MpmThreadCtx
));
2063 MpmInitCtx(&mpm_ctx
, MPM_HS
);
2066 MpmAddPatternCS(&mpm_ctx
, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2069 SCHSPreparePatterns(&mpm_ctx
);
2070 SCHSInitThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
2072 const char *buf
= "tONE";
2073 uint32_t cnt
= SCHSSearch(&mpm_ctx
, &mpm_thread_ctx
, &pmq
, (uint8_t *)buf
,
2079 printf("0 != %" PRIu32
" ", cnt
);
2081 SCHSDestroyCtx(&mpm_ctx
);
2082 SCHSDestroyThreadCtx(&mpm_ctx
, &mpm_thread_ctx
);
2087 static int SCHSTest29(void)
2089 uint8_t *buf
= (uint8_t *)"onetwothreefourfivesixseveneightnine";
2090 uint16_t buflen
= strlen((char *)buf
);
2093 DetectEngineThreadCtx
*det_ctx
= NULL
;
2096 memset(&th_v
, 0, sizeof(th_v
));
2097 p
= UTHBuildPacket(buf
, buflen
, IPPROTO_TCP
);
2099 DetectEngineCtx
*de_ctx
= DetectEngineCtxInit();
2102 de_ctx
->mpm_matcher
= MPM_HS
;
2104 de_ctx
->flags
|= DE_QUIET
;
2106 de_ctx
->sig_list
= SigInit(
2107 de_ctx
, "alert tcp any any -> any any "
2108 "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2109 if (de_ctx
->sig_list
== NULL
)
2111 de_ctx
->sig_list
->next
=
2112 SigInit(de_ctx
, "alert tcp any any -> any any "
2113 "(content:\"onetwothreefourfivesixseveneightnine\"; "
2114 "fast_pattern:3,3; sid:2;)");
2115 if (de_ctx
->sig_list
->next
== NULL
)
2118 SigGroupBuild(de_ctx
);
2119 DetectEngineThreadCtxInit(&th_v
, (void *)de_ctx
, (void *)&det_ctx
);
2121 SigMatchSignatures(&th_v
, de_ctx
, det_ctx
, p
);
2122 if (PacketAlertCheck(p
, 1) != 1) {
2123 printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
2126 if (PacketAlertCheck(p
, 2) != 1) {
2127 printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
2133 if (de_ctx
!= NULL
) {
2134 SigGroupCleanup(de_ctx
);
2135 SigCleanSignatures(de_ctx
);
2137 DetectEngineThreadCtxDeinit(&th_v
, (void *)det_ctx
);
2138 DetectEngineCtxFree(de_ctx
);
2141 UTHFreePackets(&p
, 1);
2145 #endif /* UNITTESTS */
2147 void SCHSRegisterTests(void)
2150 UtRegisterTest("SCHSTest01", SCHSTest01
);
2151 UtRegisterTest("SCHSTest02", SCHSTest02
);
2152 UtRegisterTest("SCHSTest03", SCHSTest03
);
2153 UtRegisterTest("SCHSTest04", SCHSTest04
);
2154 UtRegisterTest("SCHSTest05", SCHSTest05
);
2155 UtRegisterTest("SCHSTest06", SCHSTest06
);
2156 UtRegisterTest("SCHSTest07", SCHSTest07
);
2157 UtRegisterTest("SCHSTest08", SCHSTest08
);
2158 UtRegisterTest("SCHSTest09", SCHSTest09
);
2159 UtRegisterTest("SCHSTest10", SCHSTest10
);
2160 UtRegisterTest("SCHSTest11", SCHSTest11
);
2161 UtRegisterTest("SCHSTest12", SCHSTest12
);
2162 UtRegisterTest("SCHSTest13", SCHSTest13
);
2163 UtRegisterTest("SCHSTest14", SCHSTest14
);
2164 UtRegisterTest("SCHSTest15", SCHSTest15
);
2165 UtRegisterTest("SCHSTest16", SCHSTest16
);
2166 UtRegisterTest("SCHSTest17", SCHSTest17
);
2167 UtRegisterTest("SCHSTest18", SCHSTest18
);
2168 UtRegisterTest("SCHSTest19", SCHSTest19
);
2169 UtRegisterTest("SCHSTest20", SCHSTest20
);
2170 UtRegisterTest("SCHSTest21", SCHSTest21
);
2171 UtRegisterTest("SCHSTest22", SCHSTest22
);
2172 UtRegisterTest("SCHSTest23", SCHSTest23
);
2173 UtRegisterTest("SCHSTest24", SCHSTest24
);
2174 UtRegisterTest("SCHSTest25", SCHSTest25
);
2175 UtRegisterTest("SCHSTest26", SCHSTest26
);
2176 UtRegisterTest("SCHSTest27", SCHSTest27
);
2177 UtRegisterTest("SCHSTest28", SCHSTest28
);
2178 UtRegisterTest("SCHSTest29", SCHSTest29
);
2184 #endif /* BUILD_HYPERSCAN */