suricata
util-mpm.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2021 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 Victor Julien <victor@inliniac.net>
22 *
23 * Pattern matcher utility Functions
24 */
25
26#include "suricata-common.h"
27#include "util-mpm.h"
28#include "util-debug.h"
29
30/* include pattern matchers */
31#include "util-mpm-ac.h"
32#include "util-mpm-ac-ks.h"
33#include "util-mpm-hs.h"
34#include "util-hashlist.h"
35
36#include "detect-engine.h"
37#include "util-misc.h"
38#include "conf.h"
39#include "conf-yaml-loader.h"
40#include "queue.h"
41#include "util-unittest.h"
42#include "util-memcpy.h"
43#ifdef BUILD_HYPERSCAN
44#include "hs.h"
45#endif
46
49
50/**
51 * \brief Register a new Mpm Context.
52 *
53 * \param name A new profile to be registered to store this MpmCtx.
54 * \param sm_list sm_list for this name (might be variable with xforms)
55 * \param alproto app proto or ALPROTO_UNKNOWN if not for app-layer
56 *
57 * \retval id Return the id created for the new MpmCtx profile.
58 */
60 DetectEngineCtx *de_ctx, const char *name, const int sm_list, const AppProto alproto)
61{
62 /* the very first entry */
63 if (de_ctx->mpm_ctx_factory_container == NULL) {
65 if (de_ctx->mpm_ctx_factory_container == NULL) {
66 FatalError("Error allocating memory");
67 }
69 }
70
72 MpmCtxFactoryItem *pitem = NULL;
73 while (item) {
74 if (item->sm_list == sm_list && item->alproto == alproto && item->name != NULL &&
75 strcmp(item->name, name) == 0) {
76 return item->id;
77 }
78 pitem = item;
79 item = item->next;
80 }
81
82 MpmCtxFactoryItem *nitem = SCCalloc(1, sizeof(MpmCtxFactoryItem));
83 if (unlikely(nitem == NULL)) {
84 FatalError("Error allocating memory");
85 }
86 nitem->name = name;
87 nitem->sm_list = sm_list;
89 nitem->alproto = alproto;
90
91 /* toserver */
92 nitem->mpm_ctx_ts = SCCalloc(1, sizeof(MpmCtx));
93 if (nitem->mpm_ctx_ts == NULL) {
94 FatalError("Error allocating memory");
95 }
97
98 /* toclient */
99 nitem->mpm_ctx_tc = SCCalloc(1, sizeof(MpmCtx));
100 if (nitem->mpm_ctx_tc == NULL) {
101 FatalError("Error allocating memory");
102 }
104
105 /* store the newly created item */
106 if (pitem == NULL)
108 else
109 pitem->next = nitem;
110
111 return nitem->id;
112}
113
115{
116 if (mpm_ctx == NULL)
117 return 0;
118
119 if (de_ctx->mpm_ctx_factory_container == NULL) {
120 return 0;
121 }
122
123 for (MpmCtxFactoryItem *i = de_ctx->mpm_ctx_factory_container->items; i != NULL; i = i->next) {
124 if (mpm_ctx == i->mpm_ctx_ts || mpm_ctx == i->mpm_ctx_tc) {
125 return 1;
126 }
127 }
128 return 0;
129}
130
132{
134 MpmCtx *mpm_ctx = SCCalloc(1, sizeof(MpmCtx));
135 if (unlikely(mpm_ctx == NULL)) {
136 FatalError("Error allocating memory");
137 }
138 return mpm_ctx;
139 } else if (id < -1) {
140 SCLogError("Invalid argument - %d\n", id);
141 return NULL;
142 } else if (id >= de_ctx->mpm_ctx_factory_container->max_id) {
143 /* this id does not exist */
144 return NULL;
145 } else {
147 i = i->next) {
148 if (id == i->id) {
149 return (direction == 0) ? i->mpm_ctx_ts : i->mpm_ctx_tc;
150 }
151 }
152 return NULL;
153 }
154}
155
157{
158 if (mpm_ctx == NULL)
159 return;
160
161 if (!MpmFactoryIsMpmCtxAvailable(de_ctx, mpm_ctx)) {
162 if (mpm_ctx->mpm_type != MPM_NOTSET)
163 mpm_table[mpm_ctx->mpm_type].DestroyCtx(mpm_ctx);
164 SCFree(mpm_ctx);
165 }
166}
167
169{
171 return;
172
174 while (item) {
175 if (item->mpm_ctx_ts != NULL) {
176 if (item->mpm_ctx_ts->mpm_type != MPM_NOTSET)
178 SCFree(item->mpm_ctx_ts);
179 }
180 if (item->mpm_ctx_tc != NULL) {
181 if (item->mpm_ctx_tc->mpm_type != MPM_NOTSET)
183 SCFree(item->mpm_ctx_tc);
184 }
185
186 MpmCtxFactoryItem *next = item->next;
187 SCFree(item);
188 item = next;
189 }
190
193}
194
195void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
196{
197 if (mpm_table[matcher].InitThreadCtx != NULL) {
198 mpm_table[matcher].InitThreadCtx(NULL, mpm_thread_ctx);
199 }
200}
201
202void MpmDestroyThreadCtx(MpmThreadCtx *mpm_thread_ctx, const uint16_t matcher)
203{
204 if (mpm_table[matcher].DestroyThreadCtx != NULL) {
205 mpm_table[matcher].DestroyThreadCtx(NULL, mpm_thread_ctx);
206 }
207}
208
209void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
210{
211 mpm_ctx->mpm_type = matcher;
212 mpm_table[matcher].InitCtx(mpm_ctx);
213}
214
215/* MPM matcher to use by default, i.e. when "mpm-algo" is set to "auto".
216 * If Hyperscan is available, use it. Otherwise, use AC. */
217#ifdef BUILD_HYPERSCAN
218# define DEFAULT_MPM MPM_HS
219# define DEFAULT_MPM_AC MPM_AC
220#else
221# define DEFAULT_MPM MPM_AC
222#endif
223
225{
226 memset(mpm_table, 0, sizeof(mpm_table));
228
231#ifdef BUILD_HYPERSCAN
232 #ifdef HAVE_HS_VALID_PLATFORM
233 /* Enable runtime check for SSSE3. Do not use Hyperscan MPM matcher if
234 * check is not successful. */
235 if (hs_valid_platform() != HS_SUCCESS) {
236 SCLogInfo("SSSE3 support not detected, disabling Hyperscan for "
237 "MPM");
238 /* Fall back to best Aho-Corasick variant. */
239 mpm_default_matcher = DEFAULT_MPM_AC;
240 } else {
242 }
243 #else
245 #endif /* HAVE_HS_VALID_PLATFORM */
246#endif /* BUILD_HYPERSCAN */
247}
248
249int MpmAddPatternCS(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen,
250 uint16_t offset, uint16_t depth,
251 uint32_t pid, SigIntId sid, uint8_t flags)
252{
253 return mpm_table[mpm_ctx->mpm_type].AddPattern(mpm_ctx, pat, patlen,
254 offset, depth,
255 pid, sid, flags);
256}
257
258int MpmAddPatternCI(MpmCtx *mpm_ctx, const uint8_t *pat, uint16_t patlen, uint16_t offset,
259 uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
260{
261 return mpm_table[mpm_ctx->mpm_type].AddPatternNocase(mpm_ctx, pat, patlen,
262 offset, depth,
263 pid, sid, flags);
264}
265
266
267/**
268 * \internal
269 * \brief Creates a hash of the pattern. We use it for the hashing process
270 * during the initial pattern insertion time, to cull duplicate sigs.
271 *
272 * \param pat Pointer to the pattern.
273 * \param patlen Pattern length.
274 *
275 * \retval hash A 32 bit unsigned hash.
276 */
277static inline uint32_t MpmInitHashRaw(const uint8_t *pat, uint16_t patlen)
278{
279 uint32_t hash = patlen * pat[0];
280 if (patlen > 1)
281 hash += pat[1];
282
283 return (hash % MPM_INIT_HASH_SIZE);
284}
285
286/**
287 * \internal
288 * \brief Looks up a pattern. We use it for the hashing process during the
289 * the initial pattern insertion time, to cull duplicate sigs.
290 *
291 * \param ctx Pointer to the AC ctx.
292 * \param pat Pointer to the pattern.
293 * \param patlen Pattern length.
294 * \param flags Flags. We don't need this.
295 *
296 * \retval hash A 32 bit unsigned hash.
297 */
298static inline MpmPattern *MpmInitHashLookup(MpmCtx *ctx, const uint8_t *pat, uint16_t patlen,
299 uint16_t offset, uint16_t depth, uint8_t flags, uint32_t pid)
300{
301 uint32_t hash = MpmInitHashRaw(pat, patlen);
302
303 if (ctx->init_hash == NULL) {
304 return NULL;
305 }
306
307 MpmPattern *t = ctx->init_hash[hash];
308 for ( ; t != NULL; t = t->next) {
310 if (t->id == pid)
311 return t;
312 } else {
313 if (t->len == patlen && t->offset == offset && t->depth == depth &&
314 memcmp(pat, t->original_pat, patlen) == 0 &&
315 t->flags == flags)
316 {
317 return t;
318 }
319 }
320 }
321
322 return NULL;
323}
324
325/**
326 * \internal
327 * \brief Allocs a new pattern instance.
328 *
329 * \param mpm_ctx Pointer to the mpm context.
330 *
331 * \retval p Pointer to the newly created pattern.
332 */
333static inline MpmPattern *MpmAllocPattern(MpmCtx *mpm_ctx)
334{
335 MpmPattern *p = SCCalloc(1, sizeof(MpmPattern));
336 if (unlikely(p == NULL)) {
337 exit(EXIT_FAILURE);
338 }
339
340 mpm_ctx->memory_cnt++;
341 mpm_ctx->memory_size += sizeof(MpmPattern);
342
343 return p;
344}
345
346/**
347 * \internal
348 * \brief Used to free MpmPattern instances.
349 *
350 * \param mpm_ctx Pointer to the mpm context.
351 * \param p Pointer to the MpmPattern instance to be freed.
352 */
354{
355 if (p == NULL)
356 return;
357
358 if (p->cs != NULL && p->cs != p->ci) {
359 SCFree(p->cs);
360 mpm_ctx->memory_cnt--;
361 mpm_ctx->memory_size -= p->len;
362 }
363
364 if (p->ci != NULL) {
365 SCFree(p->ci);
366 mpm_ctx->memory_cnt--;
367 mpm_ctx->memory_size -= p->len;
368 }
369
370 if (p->original_pat != NULL) {
372 mpm_ctx->memory_cnt--;
373 mpm_ctx->memory_size -= p->len;
374 }
375
376 if (p->sids != NULL) {
377 SCFree(p->sids);
378 }
379
380 SCFree(p);
381 mpm_ctx->memory_cnt--;
382 mpm_ctx->memory_size -= sizeof(MpmPattern);
383}
384
385static inline uint32_t MpmInitHash(MpmPattern *p)
386{
387 uint32_t hash = p->len * p->original_pat[0];
388 if (p->len > 1)
389 hash += p->original_pat[1];
390
391 return (hash % MPM_INIT_HASH_SIZE);
392}
393
394static inline int MpmInitHashAdd(MpmCtx *ctx, MpmPattern *p)
395{
396 uint32_t hash = MpmInitHash(p);
397
398 if (ctx->init_hash == NULL) {
399 return -1;
400 }
401
402 if (ctx->init_hash[hash] == NULL) {
403 ctx->init_hash[hash] = p;
404 return 0;
405 }
406
407 MpmPattern *tt = NULL;
408 MpmPattern *t = ctx->init_hash[hash];
409
410 /* get the list tail */
411 do {
412 tt = t;
413 t = t->next;
414 } while (t != NULL);
415
416 tt->next = p;
417
418 return 0;
419}
420
421/**
422 * \internal
423 * \brief Add a pattern to the mpm-ac context.
424 *
425 * \param mpm_ctx Mpm context.
426 * \param pat Pointer to the pattern.
427 * \param patlen Length of the pattern.
428 * \param pid Pattern id
429 * \param sid Signature id (internal id).
430 * \param flags Pattern's MPM_PATTERN_* flags.
431 *
432 * \retval 0 On success.
433 * \retval -1 On failure.
434 */
435int MpmAddPattern(MpmCtx *mpm_ctx, const uint8_t *pat, uint16_t patlen, uint16_t offset,
436 uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
437{
438 SCLogDebug("Adding pattern for ctx %p, patlen %"PRIu16" and pid %" PRIu32,
439 mpm_ctx, patlen, pid);
440
441 if (patlen == 0) {
442 SCLogWarning("pattern length 0");
443 return 0;
444 }
445
447 pid = UINT_MAX;
448
449 /* check if we have already inserted this pattern */
450 MpmPattern *p = MpmInitHashLookup(mpm_ctx, pat, patlen,
451 offset, depth, flags, pid);
452 if (p == NULL) {
453 SCLogDebug("Allocing new pattern");
454
455 /* p will never be NULL */
456 p = MpmAllocPattern(mpm_ctx);
457
458 p->len = patlen;
459 p->flags = flags;
460 p->offset = offset;
461 p->depth = depth;
463 p->id = mpm_ctx->max_pat_id++;
464 else
465 p->id = pid;
466
467 p->original_pat = SCMalloc(patlen);
468 if (p->original_pat == NULL)
469 goto error;
470 mpm_ctx->memory_cnt++;
471 mpm_ctx->memory_size += patlen;
472 memcpy(p->original_pat, pat, patlen);
473
474 p->ci = SCMalloc(patlen);
475 if (p->ci == NULL)
476 goto error;
477 mpm_ctx->memory_cnt++;
478 mpm_ctx->memory_size += patlen;
479 memcpy_tolower(p->ci, pat, patlen);
480
481 /* setup the case sensitive part of the pattern */
483 /* nocase means no difference between cs and ci */
484 p->cs = p->ci;
485 } else {
486 if (memcmp(p->ci, pat, p->len) == 0) {
487 /* no diff between cs and ci: pat is lowercase */
488 p->cs = p->ci;
489 } else {
490 p->cs = SCMalloc(patlen);
491 if (p->cs == NULL)
492 goto error;
493 mpm_ctx->memory_cnt++;
494 mpm_ctx->memory_size += patlen;
495 memcpy(p->cs, pat, patlen);
496 }
497 }
498
499 /* put in the pattern hash */
500 if (MpmInitHashAdd(mpm_ctx, p) != 0)
501 goto error;
502
503 mpm_ctx->pattern_cnt++;
504
505 if (!(mpm_ctx->flags & MPMCTX_FLAGS_NODEPTH)) {
506 if (depth) {
507 mpm_ctx->maxdepth = MAX(mpm_ctx->maxdepth, depth);
508 SCLogDebug("%p: depth %u max %u", mpm_ctx, depth, mpm_ctx->maxdepth);
509 } else {
510 mpm_ctx->flags |= MPMCTX_FLAGS_NODEPTH;
511 mpm_ctx->maxdepth = 0;
512 SCLogDebug("%p: alas, no depth for us", mpm_ctx);
513 }
514 }
515
516 if (mpm_ctx->maxlen < patlen)
517 mpm_ctx->maxlen = patlen;
518
519 if (mpm_ctx->minlen == 0) {
520 mpm_ctx->minlen = patlen;
521 } else {
522 if (mpm_ctx->minlen > patlen)
523 mpm_ctx->minlen = patlen;
524 }
525
526 /* we need the max pat id */
527 if (p->id > mpm_ctx->max_pat_id)
528 mpm_ctx->max_pat_id = p->id;
529
530 p->sids_size = 1;
531 p->sids = SCMalloc(p->sids_size * sizeof(SigIntId));
532 BUG_ON(p->sids == NULL);
533 p->sids[0] = sid;
534 } else {
535 /* we can be called multiple times for the same sid in the case
536 * of the 'single' modus. Here multiple rule groups share the
537 * same mpm ctx and might be adding the same pattern to the
538 * mpm_ctx */
539 int found = 0;
540 uint32_t x = 0;
541 for (x = 0; x < p->sids_size; x++) {
542 if (p->sids[x] == sid) {
543 found = 1;
544 break;
545 }
546 }
547
548 if (!found) {
549 SigIntId *sids = SCRealloc(p->sids, (sizeof(SigIntId) * (p->sids_size + 1)));
550 BUG_ON(sids == NULL);
551 p->sids = sids;
552 p->sids[p->sids_size] = sid;
553 p->sids_size++;
554 }
555 }
556
557 return 0;
558
559error:
560 MpmFreePattern(mpm_ctx, p);
561 return -1;
562}
563
564
565/************************************Unittests*********************************/
566
567#ifdef UNITTESTS
568#endif /* UNITTESTS */
569
571{
572#ifdef UNITTESTS
573 uint16_t i;
574
575 for (i = 0; i < MPM_TABLE_SIZE; i++) {
576 if (i == MPM_NOTSET)
577 continue;
578
579 g_ut_modules++;
580
581 if (mpm_table[i].RegisterUnittests != NULL) {
582 g_ut_covered++;
584 } else {
586 SCLogWarning("mpm module %s has no "
587 "unittest registration function.",
588 mpm_table[i].name);
589 }
590 }
591
592#endif
593}
struct HtpBodyChunk_ * next
uint16_t AppProto
uint8_t flags
Definition decode-gre.h:0
#define ENGINE_SGH_MPM_FACTORY_CONTEXT_START_ID_RANGE
Definition detect.h:1186
DetectEngineCtx * de_ctx
struct Thresholds ctx
main detection engine ctx
Definition detect.h:932
MpmCtxFactoryContainer * mpm_ctx_factory_container
Definition detect.h:996
MpmCtxFactoryItem * items
Definition util-mpm.h:131
AppProto alproto
Definition util-mpm.h:126
MpmCtx * mpm_ctx_ts
Definition util-mpm.h:122
struct MpmCtxFactoryItem * next
Definition util-mpm.h:127
const char * name
Definition util-mpm.h:121
MpmCtx * mpm_ctx_tc
Definition util-mpm.h:123
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
uint8_t mpm_type
Definition util-mpm.h:95
uint32_t max_pat_id
Definition util-mpm.h:110
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
struct MpmPattern_ * next
Definition util-mpm.h:79
uint8_t flags
Definition util-mpm.h:58
uint8_t * cs
Definition util-mpm.h:69
uint16_t depth
Definition util-mpm.h:64
SigIntId * sids
Definition util-mpm.h:77
uint8_t * original_pat
Definition util-mpm.h:67
uint32_t sids_size
Definition util-mpm.h:76
uint16_t len
Definition util-mpm.h:56
uint32_t id
Definition util-mpm.h:73
uint8_t * ci
Definition util-mpm.h:71
uint16_t offset
Definition util-mpm.h:61
void(* RegisterUnittests)(void)
Definition util-mpm.h:182
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(* InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition util-mpm.h:153
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
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition util-mpm.h:155
int coverage_unittests
Definition suricata.c:943
int g_ut_covered
Definition suricata.c:945
#define BUG_ON(x)
#define SigIntId
#define MAX(x, y)
int g_ut_modules
Definition suricata.c:944
const char * name
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#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
void MpmACTileRegister(void)
Register the aho-corasick mpm 'ks' originally developed by Ken Steele for Tilera Tile-Gx processor.
void MpmACRegister(void)
Register the aho-corasick mpm.
void MpmHSRegister(void)
int32_t MpmFactoryIsMpmCtxAvailable(const DetectEngineCtx *de_ctx, const MpmCtx *mpm_ctx)
Definition util-mpm.c:114
void MpmFreePattern(MpmCtx *mpm_ctx, MpmPattern *p)
Definition util-mpm.c:353
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition util-mpm.c:47
void MpmRegisterTests(void)
Definition util-mpm.c:570
uint8_t mpm_default_matcher
Definition util-mpm.c:48
void MpmFactoryDeRegisterAllMpmCtxProfiles(DetectEngineCtx *de_ctx)
Definition util-mpm.c:168
MpmCtx * MpmFactoryGetMpmCtxForProfile(const DetectEngineCtx *de_ctx, int32_t id, int direction)
Definition util-mpm.c:131
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
void MpmTableSetup(void)
Definition util-mpm.c:224
int32_t MpmFactoryRegisterMpmCtxProfile(DetectEngineCtx *de_ctx, const char *name, const int sm_list, const AppProto alproto)
Register a new Mpm Context.
Definition util-mpm.c:59
void MpmDestroyThreadCtx(MpmThreadCtx *mpm_thread_ctx, const uint16_t matcher)
Definition util-mpm.c:202
#define DEFAULT_MPM
Definition util-mpm.c:221
void MpmFactoryReClaimMpmCtx(const DetectEngineCtx *de_ctx, MpmCtx *mpm_ctx)
Definition util-mpm.c:156
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
int MpmAddPattern(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:435
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition util-mpm.c:195
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_GLOBAL
Definition util-mpm.h:85
#define MPM_PATTERN_CTX_OWNS_ID
Definition util-mpm.h:143
#define MPMCTX_FLAGS_NODEPTH
Definition util-mpm.h:86
struct MpmPattern_ MpmPattern
@ MPM_NOTSET
Definition util-mpm.h:33
@ MPM_TABLE_SIZE
Definition util-mpm.h:40
#define MPM_INIT_HASH_SIZE
Definition util-mpm.h:30
#define MPM_CTX_FACTORY_UNIQUE_CONTEXT
Definition util-mpm.h:118
#define unlikely(expr)
uint64_t offset