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