suricata
util-mpm-ac.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * First iteration of aho-corasick MPM from -
24  *
25  * Efficient String Matching: An Aid to Bibliographic Search
26  * Alfred V. Aho and Margaret J. Corasick
27  *
28  * - Uses the delta table for calculating transitions, instead of having
29  * separate goto and failure transitions.
30  * - If we cross 2 ** 16 states, we use 4 bytes in the transition table
31  * to hold each state, otherwise we use 2 bytes.
32  * - This version of the MPM is heavy on memory, but it performs well.
33  * If you can fit the ruleset with this mpm on your box without hitting
34  * swap, this is the MPM to go for.
35  *
36  * \todo - Do a proper analysis of our existing MPMs and suggest a good one based
37  * on the pattern distribution and the expected traffic(say http).
38  * - Tried out loop unrolling without any perf increase. Need to dig deeper.
39  * - Irrespective of whether we cross 2 ** 16 states or not,shift to using
40  * uint32_t for state type, so that we can integrate it's status as a
41  * final state or not in the topmost byte. We are already doing it if
42  * state_count is > 2 ** 16.
43  * - Test case-sensitive patterns if they have any ascii chars. If they
44  * don't treat them as nocase.
45  * - Carry out other optimizations we are working on. hashes, compression.
46  */
47 
48 #include "suricata-common.h"
49 #include "suricata.h"
50 
51 #include "detect.h"
52 #include "detect-parse.h"
53 #include "detect-engine.h"
54 #include "detect-engine-build.h"
55 
56 #include "conf.h"
57 #include "util-debug.h"
58 #include "util-unittest.h"
59 #include "util-unittest-helper.h"
60 #include "util-memcmp.h"
61 #include "util-mpm-ac.h"
62 #include "util-memcpy.h"
63 #include "util-validate.h"
64 #include "util-mpm-ac-queue.h"
65 
66 void SCACInitCtx(MpmCtx *);
67 void SCACDestroyCtx(MpmCtx *);
69  MpmCtx *, const uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t);
70 int SCACAddPatternCS(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
71  uint32_t, SigIntId, uint8_t);
72 int SCACPreparePatterns(MpmConfig *, MpmCtx *mpm_ctx);
73 uint32_t SCACSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
74  PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen);
75 void SCACPrintInfo(MpmCtx *mpm_ctx);
76 #ifdef UNITTESTS
77 static void SCACRegisterTests(void);
78 #endif
79 
80 /* a placeholder to denote a failure transition in the goto table */
81 #define SC_AC_FAIL (-1)
82 
83 #define AC_CASE_MASK 0x80000000
84 #define AC_PID_MASK 0x7FFFFFFF
85 #define AC_CASE_BIT 31
86 
87 static int construct_both_16_and_32_state_tables = 0;
88 
89 /**
90  * \internal
91  * \brief Initialize the AC context with user specified conf parameters. We
92  * aren't retrieving anything for AC conf now, but we will certainly
93  * need it, when we customize AC.
94  */
95 static void SCACGetConfig(void)
96 {
97  // SCConfNode *ac_conf;
98  // const char *hash_val = NULL;
99 
100  // SCConfNode *pm = SCConfGetNode("pattern-matcher");
101 }
102 
103 /**
104  * \internal
105  * \brief Check if size_t multiplication would overflow and perform operation
106  * if safe. In case of an overflow we exit().
107  *
108  * \param a First size_t value to multiplicate.
109  * \param b Second size_t value to multiplicate.
110  *
111  * \retval The product of a and b, guaranteed to not overflow.
112  */
113 static inline size_t SCACCheckSafeSizetMult(size_t a, size_t b)
114 {
115  /* check for safety of multiplication operation */
116  if (b > 0 && a > SIZE_MAX / b) {
117  SCLogError("%" PRIuMAX " * %" PRIuMAX " > %" PRIuMAX
118  " would overflow size_t calculating buffer size",
119  (uintmax_t)a, (uintmax_t)b, (uintmax_t)SIZE_MAX);
120  exit(EXIT_FAILURE);
121  }
122  return a * b;
123 }
124 
125 /**
126  * \internal
127  * \brief Initialize a new state in the goto and output tables.
128  *
129  * \param mpm_ctx Pointer to the mpm context.
130  *
131  * \retval The state id, of the newly created state.
132  */
133 static inline int SCACReallocState(SCACCtx *ctx, uint32_t cnt)
134 {
135  void *ptmp = NULL;
136  size_t size = 0;
137 
138  /* reallocate space in the goto table to include a new state */
139  size = SCACCheckSafeSizetMult((size_t) cnt, (size_t) ctx->single_state_size);
140  if (size > 0)
141  ptmp = SCRealloc(ctx->goto_table, size);
142  if (ptmp == NULL) {
143  SCFree(ctx->goto_table);
144  ctx->goto_table = NULL;
145  FatalError("Error allocating memory");
146  }
147  ctx->goto_table = ptmp;
148 
149  /* reallocate space in the output table for the new state */
150  size_t oldsize = SCACCheckSafeSizetMult((size_t) ctx->state_count,
151  sizeof(SCACOutputTable));
152  size = SCACCheckSafeSizetMult((size_t) cnt, sizeof(SCACOutputTable));
153  SCLogDebug("oldsize %"PRIuMAX" size %"PRIuMAX" cnt %d ctx->state_count %u",
154  (uintmax_t) oldsize, (uintmax_t) size, cnt, ctx->state_count);
155 
156  ptmp = NULL;
157  if (size > 0)
158  ptmp = SCRealloc(ctx->output_table, size);
159  if (ptmp == NULL) {
160  SCFree(ctx->output_table);
161  ctx->output_table = NULL;
162  FatalError("Error allocating memory");
163  }
164  ctx->output_table = ptmp;
165 
166  memset(((uint8_t *)ctx->output_table + oldsize), 0, (size - oldsize));
167 
168  /* \todo using it temporarily now during dev, since I have restricted
169  * state var in SCACCtx->state_table to uint16_t. */
170  //if (ctx->state_count > 65536) {
171  // printf("state count exceeded\n");
172  // exit(EXIT_FAILURE);
173  //}
174 
175  return 0;//ctx->state_count++;
176 }
177 
178 /** \internal
179  * \brief Shrink state after setup is done
180  *
181  * Shrinks only the output table, goto table is freed after calling this
182  */
183 static void SCACShrinkState(SCACCtx *ctx)
184 {
185  /* reallocate space in the output table for the new state */
186 #ifdef DEBUG
187  int oldsize = ctx->allocated_state_count * sizeof(SCACOutputTable);
188 #endif
189  int newsize = ctx->state_count * sizeof(SCACOutputTable);
190 
191  SCLogDebug("oldsize %d newsize %d ctx->allocated_state_count %u "
192  "ctx->state_count %u: shrink by %d bytes", oldsize,
193  newsize, ctx->allocated_state_count, ctx->state_count,
194  oldsize - newsize);
195 
196  void *ptmp = SCRealloc(ctx->output_table, newsize);
197  if (ptmp == NULL) {
198  SCFree(ctx->output_table);
199  ctx->output_table = NULL;
200  FatalError("Error allocating memory");
201  }
202  ctx->output_table = ptmp;
203 }
204 
205 static inline int SCACInitNewState(MpmCtx *mpm_ctx)
206 {
207  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
208 
209  /* Exponentially increase the allocated space when needed. */
210  if (ctx->allocated_state_count < ctx->state_count + 1) {
211  if (ctx->allocated_state_count == 0)
212  ctx->allocated_state_count = 256;
213  else
214  ctx->allocated_state_count *= 2;
215 
216  SCACReallocState(ctx, ctx->allocated_state_count);
217 
218  }
219 #if 0
220  if (ctx->allocated_state_count > 260) {
221  SCACOutputTable *output_state = &ctx->output_table[260];
222  SCLogInfo("output_state %p %p %u", output_state, output_state->pids, output_state->no_of_entries);
223  }
224 #endif
225  int ascii_code = 0;
226  /* set all transitions for the newly assigned state as FAIL transitions */
227  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
228  ctx->goto_table[ctx->state_count][ascii_code] = SC_AC_FAIL;
229  }
230 
231  return ctx->state_count++;
232 }
233 
234 /**
235  * \internal
236  * \brief Adds a pid to the output table for a state.
237  *
238  * \param state The state to whose output table we should add the pid.
239  * \param pid The pattern id to add.
240  * \param mpm_ctx Pointer to the mpm context.
241  */
242 static void SCACSetOutputState(int32_t state, uint32_t pid, MpmCtx *mpm_ctx)
243 {
244  void *ptmp;
245  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
246  SCACOutputTable *output_state = &ctx->output_table[state];
247  uint32_t i = 0;
248 
249  for (i = 0; i < output_state->no_of_entries; i++) {
250  if (output_state->pids[i] == pid)
251  return;
252  }
253 
254  output_state->no_of_entries++;
255  ptmp = SCRealloc(output_state->pids,
256  output_state->no_of_entries * sizeof(uint32_t));
257  if (ptmp == NULL) {
258  SCFree(output_state->pids);
259  output_state->pids = NULL;
260  FatalError("Error allocating memory");
261  }
262  output_state->pids = ptmp;
263 
264  output_state->pids[output_state->no_of_entries - 1] = pid;
265 }
266 
267 /**
268  * \brief Helper function used by SCACCreateGotoTable. Adds a pattern to the
269  * goto table.
270  *
271  * \param pattern Pointer to the pattern.
272  * \param pattern_len Pattern length.
273  * \param pid The pattern id, that corresponds to this pattern. We
274  * need it to updated the output table for this pattern.
275  * \param mpm_ctx Pointer to the mpm context.
276  */
277 static inline void SCACEnter(uint8_t *pattern, uint16_t pattern_len, uint32_t pid,
278  MpmCtx *mpm_ctx)
279 {
280  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
281  int32_t state = 0;
282  int32_t newstate = 0;
283  int i = 0;
284  int p = 0;
285 
286  /* walk down the trie till we have a match for the pattern prefix */
287  state = 0;
288  for (i = 0; i < pattern_len; i++) {
289  if (ctx->goto_table[state][pattern[i]] != SC_AC_FAIL) {
290  state = ctx->goto_table[state][pattern[i]];
291  } else {
292  break;
293  }
294  }
295 
296  /* add the non-matching pattern suffix to the trie, from the last state
297  * we left off */
298  for (p = i; p < pattern_len; p++) {
299  newstate = SCACInitNewState(mpm_ctx);
300  ctx->goto_table[state][pattern[p]] = newstate;
301  state = newstate;
302  }
303 
304  /* add this pattern id, to the output table of the last state, where the
305  * pattern ends in the trie */
306  SCACSetOutputState(state, pid, mpm_ctx);
307 }
308 
309 /**
310  * \internal
311  * \brief Create the goto table.
312  *
313  * \param mpm_ctx Pointer to the mpm context.
314  */
315 static inline void SCACCreateGotoTable(MpmCtx *mpm_ctx)
316 {
317  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
318  uint32_t i = 0;
319 
320  /* add each pattern to create the goto table */
321  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
322  SCACEnter(ctx->parray[i]->ci, ctx->parray[i]->len,
323  ctx->parray[i]->id, mpm_ctx);
324  }
325 
326  int ascii_code = 0;
327  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
328  if (ctx->goto_table[0][ascii_code] == SC_AC_FAIL) {
329  ctx->goto_table[0][ascii_code] = 0;
330  }
331  }
332 }
333 
334 static inline void SCACDetermineLevel1Gap(MpmCtx *mpm_ctx)
335 {
336  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
337  uint32_t u = 0;
338 
339  uint8_t map[256];
340  memset(map, 0, sizeof(map));
341 
342  for (u = 0; u < mpm_ctx->pattern_cnt; u++)
343  map[ctx->parray[u]->ci[0]] = 1;
344 
345  for (u = 0; u < 256; u++) {
346  if (map[u] == 0)
347  continue;
348  int32_t newstate = SCACInitNewState(mpm_ctx);
349  ctx->goto_table[0][u] = newstate;
350  }
351 }
352 
353 /**
354  * \internal
355  * \brief Club the output data from 2 states and store it in the 1st state.
356  * dst_state_data = {dst_state_data} UNION {src_state_data}
357  *
358  * \param dst_state First state(also the destination) for the union operation.
359  * \param src_state Second state for the union operation.
360  * \param mpm_ctx Pointer to the mpm context.
361  */
362 static inline void SCACClubOutputStates(int32_t dst_state, int32_t src_state,
363  MpmCtx *mpm_ctx)
364 {
365  void *ptmp;
366  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
367  uint32_t i = 0;
368  uint32_t j = 0;
369 
370  SCACOutputTable *output_dst_state = &ctx->output_table[dst_state];
371  SCACOutputTable *output_src_state = &ctx->output_table[src_state];
372 
373  for (i = 0; i < output_src_state->no_of_entries; i++) {
374  for (j = 0; j < output_dst_state->no_of_entries; j++) {
375  if (output_src_state->pids[i] == output_dst_state->pids[j]) {
376  break;
377  }
378  }
379  if (j == output_dst_state->no_of_entries) {
380  output_dst_state->no_of_entries++;
381 
382  ptmp = SCRealloc(output_dst_state->pids,
383  (output_dst_state->no_of_entries * sizeof(uint32_t)));
384  if (ptmp == NULL) {
385  SCFree(output_dst_state->pids);
386  output_dst_state->pids = NULL;
387  FatalError("Error allocating memory");
388  }
389  output_dst_state->pids = ptmp;
390 
391  output_dst_state->pids[output_dst_state->no_of_entries - 1] =
392  output_src_state->pids[i];
393  }
394  }
395 }
396 
397 /**
398  * \internal
399  * \brief Create the failure table.
400  *
401  * \param mpm_ctx Pointer to the mpm context.
402  */
403 static inline void SCACCreateFailureTable(MpmCtx *mpm_ctx)
404 {
405  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
406  int ascii_code = 0;
407  int32_t state = 0;
408  int32_t r_state = 0;
409 
411 
412  /* allot space for the failure table. A failure entry in the table for
413  * every state(SCACCtx->state_count) */
414  ctx->failure_table = SCCalloc(ctx->state_count, sizeof(int32_t));
415  if (ctx->failure_table == NULL) {
416  FatalError("Error allocating memory");
417  }
418 
419  /* add the failure transitions for the 0th state, and add every non-fail
420  * transition from the 0th state to the queue for further processing
421  * of failure states */
422  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
423  int32_t temp_state = ctx->goto_table[0][ascii_code];
424  if (temp_state != 0) {
425  SCACEnqueue(q, temp_state);
426  ctx->failure_table[temp_state] = 0;
427  }
428  }
429 
430  while (!SCACStateQueueIsEmpty(q)) {
431  /* pick up every state from the queue and add failure transitions */
432  r_state = SCACDequeue(q);
433  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
434  int32_t temp_state = ctx->goto_table[r_state][ascii_code];
435  if (temp_state == SC_AC_FAIL)
436  continue;
437  SCACEnqueue(q, temp_state);
438  state = ctx->failure_table[r_state];
439 
440  while(ctx->goto_table[state][ascii_code] == SC_AC_FAIL)
441  state = ctx->failure_table[state];
442  ctx->failure_table[temp_state] = ctx->goto_table[state][ascii_code];
443  SCACClubOutputStates(temp_state, ctx->failure_table[temp_state],
444  mpm_ctx);
445  }
446  }
448 }
449 
450 /**
451  * \internal
452  * \brief Create the delta table.
453  *
454  * \param mpm_ctx Pointer to the mpm context.
455  */
456 static inline void SCACCreateDeltaTable(MpmCtx *mpm_ctx)
457 {
458  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
459  int ascii_code = 0;
460  int32_t r_state = 0;
461 
462  if ((ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
463  ctx->state_table_u16 = SCCalloc(ctx->state_count, sizeof(*ctx->state_table_u16));
464  if (ctx->state_table_u16 == NULL) {
465  FatalError("Error allocating memory");
466  }
467  mpm_ctx->memory_cnt++;
468  mpm_ctx->memory_size += (ctx->state_count * sizeof(*ctx->state_table_u16));
469 
471 
472  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
473  DEBUG_VALIDATE_BUG_ON(ctx->goto_table[0][ascii_code] > UINT16_MAX);
474  SC_AC_STATE_TYPE_U16 temp_state = (uint16_t)ctx->goto_table[0][ascii_code];
475  ctx->state_table_u16[0][ascii_code] = temp_state;
476  if (temp_state != 0)
477  SCACEnqueue(q, temp_state);
478  }
479 
480  while (!SCACStateQueueIsEmpty(q)) {
481  r_state = SCACDequeue(q);
482 
483  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
484  int32_t temp_state = ctx->goto_table[r_state][ascii_code];
485  if (temp_state != SC_AC_FAIL) {
486  SCACEnqueue(q, temp_state);
487  DEBUG_VALIDATE_BUG_ON(temp_state > UINT16_MAX);
488  ctx->state_table_u16[r_state][ascii_code] = (uint16_t)temp_state;
489  } else {
490  ctx->state_table_u16[r_state][ascii_code] =
491  ctx->state_table_u16[ctx->failure_table[r_state]][ascii_code];
492  }
493  }
494  }
496  }
497 
498  if (!(ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
499  /* create space for the state table. We could have used the existing goto
500  * table, but since we have it set to hold 32 bit state values, we will create
501  * a new state table here of type SC_AC_STATE_TYPE(current set to uint16_t) */
502  ctx->state_table_u32 = SCCalloc(ctx->state_count, sizeof(*ctx->state_table_u32));
503  if (ctx->state_table_u32 == NULL) {
504  FatalError("Error allocating memory");
505  }
506  mpm_ctx->memory_cnt++;
507  mpm_ctx->memory_size += (ctx->state_count * sizeof(*ctx->state_table_u32));
508 
510 
511  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
512  SC_AC_STATE_TYPE_U32 temp_state = ctx->goto_table[0][ascii_code];
513  ctx->state_table_u32[0][ascii_code] = temp_state;
514  if (temp_state != 0)
515  SCACEnqueue(q, temp_state);
516  }
517 
518  while (!SCACStateQueueIsEmpty(q)) {
519  r_state = SCACDequeue(q);
520 
521  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
522  int32_t temp_state = ctx->goto_table[r_state][ascii_code];
523  if (temp_state != SC_AC_FAIL) {
524  SCACEnqueue(q, temp_state);
525  ctx->state_table_u32[r_state][ascii_code] = temp_state;
526  } else {
527  ctx->state_table_u32[r_state][ascii_code] =
528  ctx->state_table_u32[ctx->failure_table[r_state]][ascii_code];
529  }
530  }
531  }
533  }
534 }
535 
536 static inline void SCACClubOutputStatePresenceWithDeltaTable(MpmCtx *mpm_ctx)
537 {
538  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
539  int ascii_code = 0;
540  uint32_t state = 0;
541  uint32_t temp_state = 0;
542 
543  if ((ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
544  for (state = 0; state < ctx->state_count; state++) {
545  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
546  temp_state = ctx->state_table_u16[state & 0x7FFF][ascii_code];
547  if (ctx->output_table[temp_state & 0x7FFF].no_of_entries != 0)
548  ctx->state_table_u16[state & 0x7FFF][ascii_code] |= (1 << 15);
549  }
550  }
551  }
552 
553  if (!(ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
554  for (state = 0; state < ctx->state_count; state++) {
555  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
556  temp_state = ctx->state_table_u32[state & 0x00FFFFFF][ascii_code];
557  if (ctx->output_table[temp_state & 0x00FFFFFF].no_of_entries != 0)
558  ctx->state_table_u32[state & 0x00FFFFFF][ascii_code] |= (1 << 24);
559  }
560  }
561  }
562 }
563 
564 static inline void SCACInsertCaseSensitiveEntriesForPatterns(MpmCtx *mpm_ctx)
565 {
566  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
567  uint32_t state = 0;
568  uint32_t k = 0;
569 
570  for (state = 0; state < ctx->state_count; state++) {
571  if (ctx->output_table[state].no_of_entries == 0)
572  continue;
573 
574  for (k = 0; k < ctx->output_table[state].no_of_entries; k++) {
575  if (ctx->pid_pat_list[ctx->output_table[state].pids[k]].cs != NULL) {
576  ctx->output_table[state].pids[k] &= AC_PID_MASK;
577  ctx->output_table[state].pids[k] |= ((uint32_t)1 << AC_CASE_BIT);
578  }
579  }
580  }
581 }
582 
583 #if 0
584 static void SCACPrintDeltaTable(MpmCtx *mpm_ctx)
585 {
586  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
587  int i = 0, j = 0;
588 
589  printf("##############Delta Table##############\n");
590  for (i = 0; i < ctx->state_count; i++) {
591  printf("%d: \n", i);
592  for (j = 0; j < 256; j++) {
593  if (SCACGetDelta(i, j, mpm_ctx) != 0) {
594  printf(" %c -> %d\n", j, SCACGetDelta(i, j, mpm_ctx));
595  }
596  }
597  }
598 }
599 #endif
600 
601 /**
602  * \brief Process the patterns and prepare the state table.
603  *
604  * \param mpm_ctx Pointer to the mpm context.
605  */
606 static void SCACPrepareStateTable(MpmCtx *mpm_ctx)
607 {
608  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
609 
610  /* create the 0th state in the goto table and output_table */
611  SCACInitNewState(mpm_ctx);
612 
613  SCACDetermineLevel1Gap(mpm_ctx);
614 
615  /* create the goto table */
616  SCACCreateGotoTable(mpm_ctx);
617  /* create the failure table */
618  SCACCreateFailureTable(mpm_ctx);
619  /* create the final state(delta) table */
620  SCACCreateDeltaTable(mpm_ctx);
621  /* club the output state presence with delta transition entries */
622  SCACClubOutputStatePresenceWithDeltaTable(mpm_ctx);
623 
624  /* club nocase entries */
625  SCACInsertCaseSensitiveEntriesForPatterns(mpm_ctx);
626 
627  /* shrink the memory */
628  SCACShrinkState(ctx);
629 
630 #if 0
631  SCACPrintDeltaTable(mpm_ctx);
632 #endif
633 
634  /* we don't need these anymore */
635  SCFree(ctx->goto_table);
636  ctx->goto_table = NULL;
637  SCFree(ctx->failure_table);
638  ctx->failure_table = NULL;
639 }
640 
641 /**
642  * \brief Process the patterns added to the mpm, and create the internal tables.
643  *
644  * \param mpm_conf Pointer to the generic MPM matcher configuration
645  * \param mpm_ctx Pointer to the mpm context.
646  */
647 int SCACPreparePatterns(MpmConfig *mpm_conf, MpmCtx *mpm_ctx)
648 {
649  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
650 
651  if (mpm_ctx->pattern_cnt == 0 || mpm_ctx->init_hash == NULL) {
652  SCLogDebug("no patterns supplied to this mpm_ctx");
653  return 0;
654  }
655 
656  /* alloc the pattern array */
657  ctx->parray = (MpmPattern **)SCCalloc(mpm_ctx->pattern_cnt, sizeof(MpmPattern *));
658  if (ctx->parray == NULL)
659  goto error;
660  mpm_ctx->memory_cnt++;
661  mpm_ctx->memory_size += (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
662 
663  /* populate it with the patterns in the hash */
664  uint32_t i = 0, p = 0;
665  for (i = 0; i < MPM_INIT_HASH_SIZE; i++) {
666  MpmPattern *node = mpm_ctx->init_hash[i], *nnode = NULL;
667  while(node != NULL) {
668  nnode = node->next;
669  node->next = NULL;
670  ctx->parray[p++] = node;
671  node = nnode;
672  }
673  }
674 
675  /* we no longer need the hash, so free it's memory */
676  SCFree(mpm_ctx->init_hash);
677  mpm_ctx->init_hash = NULL;
678 
679  /* the memory consumed by a single state in our goto table */
680  ctx->single_state_size = sizeof(int32_t) * 256;
681 
682  /* handle no case patterns */
683  ctx->pid_pat_list = SCCalloc((mpm_ctx->max_pat_id + 1), sizeof(SCACPatternList));
684  if (ctx->pid_pat_list == NULL) {
685  FatalError("Error allocating memory");
686  }
687 
688  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
689  if (!(ctx->parray[i]->flags & MPM_PATTERN_FLAG_NOCASE)) {
690  ctx->pid_pat_list[ctx->parray[i]->id].cs = SCMalloc(ctx->parray[i]->len);
691  if (ctx->pid_pat_list[ctx->parray[i]->id].cs == NULL) {
692  FatalError("Error allocating memory");
693  }
694  memcpy(ctx->pid_pat_list[ctx->parray[i]->id].cs,
695  ctx->parray[i]->original_pat, ctx->parray[i]->len);
696  ctx->pid_pat_list[ctx->parray[i]->id].patlen = ctx->parray[i]->len;
697  }
698  ctx->pid_pat_list[ctx->parray[i]->id].offset = ctx->parray[i]->offset;
699  ctx->pid_pat_list[ctx->parray[i]->id].depth = ctx->parray[i]->depth;
700  ctx->pid_pat_list[ctx->parray[i]->id].endswith =
701  (ctx->parray[i]->flags & MPM_PATTERN_FLAG_ENDSWITH) != 0;
702 
703  /* ACPatternList now owns this memory */
704  //SCLogInfo("ctx->parray[i]->sids_size %u", ctx->parray[i]->sids_size);
705  ctx->pid_pat_list[ctx->parray[i]->id].sids_size = ctx->parray[i]->sids_size;
706  ctx->pid_pat_list[ctx->parray[i]->id].sids = ctx->parray[i]->sids;
707 
708  ctx->parray[i]->sids_size = 0;
709  ctx->parray[i]->sids = NULL;
710  }
711 
712  /* prepare the state table required by AC */
713  SCACPrepareStateTable(mpm_ctx);
714 
715  /* free all the stored patterns. Should save us a good 100-200 mbs */
716  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
717  if (ctx->parray[i] != NULL) {
718  MpmFreePattern(mpm_ctx, ctx->parray[i]);
719  }
720  }
721  SCFree(ctx->parray);
722  ctx->parray = NULL;
723  mpm_ctx->memory_cnt--;
724  mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
725 
726  ctx->pattern_id_bitarray_size = (mpm_ctx->max_pat_id / 8) + 1;
727  SCLogDebug("ctx->pattern_id_bitarray_size %u", ctx->pattern_id_bitarray_size);
728 
729  return 0;
730 
731 error:
732  return -1;
733 }
734 
735 /**
736  * \brief Initialize the AC context.
737  *
738  * \param mpm_ctx Mpm context.
739  */
740 void SCACInitCtx(MpmCtx *mpm_ctx)
741 {
742  if (mpm_ctx->ctx != NULL)
743  return;
744 
745  mpm_ctx->ctx = SCCalloc(1, sizeof(SCACCtx));
746  if (mpm_ctx->ctx == NULL) {
747  exit(EXIT_FAILURE);
748  }
749 
750  mpm_ctx->memory_cnt++;
751  mpm_ctx->memory_size += sizeof(SCACCtx);
752 
753  /* initialize the hash we use to speed up pattern insertions */
754  mpm_ctx->init_hash = SCCalloc(MPM_INIT_HASH_SIZE, sizeof(MpmPattern *));
755  if (mpm_ctx->init_hash == NULL) {
756  exit(EXIT_FAILURE);
757  }
758 
759  /* get conf values for AC from our yaml file. We have no conf values for
760  * now. We will certainly need this, as we develop the algo */
761  SCACGetConfig();
762 
763  SCReturn;
764 }
765 
766 /**
767  * \brief Destroy the mpm context.
768  *
769  * \param mpm_ctx Pointer to the mpm context.
770  */
771 void SCACDestroyCtx(MpmCtx *mpm_ctx)
772 {
773  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
774  if (ctx == NULL)
775  return;
776 
777  if (mpm_ctx->init_hash != NULL) {
778  SCFree(mpm_ctx->init_hash);
779  mpm_ctx->init_hash = NULL;
780  mpm_ctx->memory_cnt--;
781  mpm_ctx->memory_size -= (MPM_INIT_HASH_SIZE * sizeof(MpmPattern *));
782  }
783 
784  if (ctx->parray != NULL) {
785  uint32_t i;
786  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
787  if (ctx->parray[i] != NULL) {
788  MpmFreePattern(mpm_ctx, ctx->parray[i]);
789  }
790  }
791 
792  SCFree(ctx->parray);
793  ctx->parray = NULL;
794  mpm_ctx->memory_cnt--;
795  mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
796  }
797 
798  if (ctx->state_table_u16 != NULL) {
799  SCFree(ctx->state_table_u16);
800  ctx->state_table_u16 = NULL;
801 
802  mpm_ctx->memory_cnt++;
803  mpm_ctx->memory_size -= (ctx->state_count *
804  sizeof(SC_AC_STATE_TYPE_U16) * 256);
805  }
806  if (ctx->state_table_u32 != NULL) {
807  SCFree(ctx->state_table_u32);
808  ctx->state_table_u32 = NULL;
809 
810  mpm_ctx->memory_cnt++;
811  mpm_ctx->memory_size -= (ctx->state_count *
812  sizeof(SC_AC_STATE_TYPE_U32) * 256);
813  }
814 
815  if (ctx->output_table != NULL) {
816  uint32_t state_count;
817  for (state_count = 0; state_count < ctx->state_count; state_count++) {
818  if (ctx->output_table[state_count].pids != NULL) {
819  SCFree(ctx->output_table[state_count].pids);
820  }
821  }
822  SCFree(ctx->output_table);
823  }
824 
825  if (ctx->pid_pat_list != NULL) {
826  uint32_t i;
827  for (i = 0; i < (mpm_ctx->max_pat_id + 1); i++) {
828  if (ctx->pid_pat_list[i].cs != NULL)
829  SCFree(ctx->pid_pat_list[i].cs);
830  if (ctx->pid_pat_list[i].sids != NULL)
831  SCFree(ctx->pid_pat_list[i].sids);
832  }
833  SCFree(ctx->pid_pat_list);
834  }
835 
836  SCFree(mpm_ctx->ctx);
837  mpm_ctx->ctx = NULL;
838  mpm_ctx->memory_cnt--;
839  mpm_ctx->memory_size -= sizeof(SCACCtx);
840 }
841 
842 /**
843  * \brief The aho corasick search function.
844  *
845  * \param mpm_ctx Pointer to the mpm context.
846  * \param mpm_thread_ctx Pointer to the mpm thread context.
847  * \param pmq Pointer to the Pattern Matcher Queue to hold
848  * search matches.
849  * \param buf Buffer to be searched.
850  * \param buflen Buffer length.
851  *
852  * \retval matches Match count: counts unique matches per pattern.
853  */
854 uint32_t SCACSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
855  PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
856 {
857  const SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
858  int matches = 0;
859 
860  /* \todo tried loop unrolling with register var, with no perf increase. Need
861  * to dig deeper */
862  /* \todo Change it for stateful MPM. Supply the state using mpm_thread_ctx */
863  const SCACPatternList *pid_pat_list = ctx->pid_pat_list;
864 
865  uint8_t bitarray[ctx->pattern_id_bitarray_size];
866  memset(bitarray, 0, ctx->pattern_id_bitarray_size);
867 
868  if (ctx->state_count < 32767) {
869  register SC_AC_STATE_TYPE_U16 state = 0;
870  const SC_AC_STATE_TYPE_U16(*state_table_u16)[256] = ctx->state_table_u16;
871  for (uint32_t i = 0; i < buflen; i++) {
872  state = state_table_u16[state & 0x7FFF][u8_tolower(buf[i])];
873  if (state & 0x8000) {
874  const uint32_t no_of_entries = ctx->output_table[state & 0x7FFF].no_of_entries;
875  const uint32_t *pids = ctx->output_table[state & 0x7FFF].pids;
876  for (uint32_t k = 0; k < no_of_entries; k++) {
877  if (pids[k] & AC_CASE_MASK) {
878  const uint32_t lower_pid = pids[k] & AC_PID_MASK;
879  const SCACPatternList *pat = &pid_pat_list[lower_pid];
880  const int offset = i - pat->patlen + 1;
881 
882  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
883  continue;
884  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
885  continue;
886 
887  if (SCMemcmp(pat->cs, buf + offset, pat->patlen) != 0) {
888  /* inside loop */
889  continue;
890  }
891  if (!(bitarray[(lower_pid) / 8] & (1 << ((lower_pid) % 8)))) {
892  bitarray[(lower_pid) / 8] |= (1 << ((lower_pid) % 8));
893  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
894  matches++;
895  }
896  } else {
897  const SCACPatternList *pat = &pid_pat_list[pids[k]];
898  const int offset = i - pat->patlen + 1;
899 
900  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
901  continue;
902  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
903  continue;
904 
905  if (!(bitarray[pids[k] / 8] & (1 << (pids[k] % 8)))) {
906  bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
907  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
908  matches++;
909  }
910  }
911  }
912  }
913  }
914  } else {
915  register SC_AC_STATE_TYPE_U32 state = 0;
916  const SC_AC_STATE_TYPE_U32(*state_table_u32)[256] = ctx->state_table_u32;
917  for (uint32_t i = 0; i < buflen; i++) {
918  state = state_table_u32[state & 0x00FFFFFF][u8_tolower(buf[i])];
919  if (state & 0xFF000000) {
920  const uint32_t no_of_entries = ctx->output_table[state & 0x00FFFFFF].no_of_entries;
921  const uint32_t *pids = ctx->output_table[state & 0x00FFFFFF].pids;
922  for (uint32_t k = 0; k < no_of_entries; k++) {
923  if (pids[k] & AC_CASE_MASK) {
924  const uint32_t lower_pid = pids[k] & 0x0000FFFF;
925  const SCACPatternList *pat = &pid_pat_list[lower_pid];
926  const int offset = i - pat->patlen + 1;
927 
928  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
929  continue;
930  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
931  continue;
932 
933  if (SCMemcmp(pat->cs, buf + offset,
934  pat->patlen) != 0) {
935  /* inside loop */
936  continue;
937  }
938  if (!(bitarray[(lower_pid) / 8] & (1 << ((lower_pid) % 8)))) {
939  bitarray[(lower_pid) / 8] |= (1 << ((lower_pid) % 8));
940  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
941  matches++;
942  }
943  } else {
944  const SCACPatternList *pat = &pid_pat_list[pids[k]];
945  const int offset = i - pat->patlen + 1;
946 
947  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
948  continue;
949  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
950  continue;
951 
952  if (!(bitarray[pids[k] / 8] & (1 << (pids[k] % 8)))) {
953  bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
954  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
955  matches++;
956  }
957  }
958  }
959  }
960  }
961  }
962  return matches;
963 }
964 
965 /**
966  * \brief Add a case insensitive pattern. Although we have different calls for
967  * adding case sensitive and insensitive patterns, we make a single call
968  * for either case. No special treatment for either case.
969  *
970  * \param mpm_ctx Pointer to the mpm context.
971  * \param pat The pattern to add.
972  * \param patnen The pattern length.
973  * \param offset Ignored.
974  * \param depth Ignored.
975  * \param pid The pattern id.
976  * \param sid Ignored.
977  * \param flags Flags associated with this pattern.
978  *
979  * \retval 0 On success.
980  * \retval -1 On failure.
981  */
982 int SCACAddPatternCI(MpmCtx *mpm_ctx, const uint8_t *pat, uint16_t patlen, uint16_t offset,
983  uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
984 {
986  return MpmAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
987 }
988 
989 /**
990  * \brief Add a case sensitive pattern. Although we have different calls for
991  * adding case sensitive and insensitive patterns, we make a single call
992  * for either case. No special treatment for either case.
993  *
994  * \param mpm_ctx Pointer to the mpm context.
995  * \param pat The pattern to add.
996  * \param patnen The pattern length.
997  * \param offset Ignored.
998  * \param depth Ignored.
999  * \param pid The pattern id.
1000  * \param sid Ignored.
1001  * \param flags Flags associated with this pattern.
1002  *
1003  * \retval 0 On success.
1004  * \retval -1 On failure.
1005  */
1006 int SCACAddPatternCS(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1007  uint16_t offset, uint16_t depth, uint32_t pid,
1008  SigIntId sid, uint8_t flags)
1009 {
1010  return MpmAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1011 }
1012 
1013 void SCACPrintInfo(MpmCtx *mpm_ctx)
1014 {
1015  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
1016 
1017  printf("MPM AC Information:\n");
1018  printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
1019  printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
1020  printf(" Sizeof:\n");
1021  printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
1022  printf(" SCACCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCACCtx));
1023  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1024  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1025  printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
1026  printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
1027  printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
1028  printf("Total states in the state table: %" PRIu32 "\n", ctx->state_count);
1029  printf("\n");
1030 }
1031 
1032 
1033 /************************** Mpm Registration ***************************/
1034 
1035 /**
1036  * \brief Register the aho-corasick mpm.
1037  */
1038 void MpmACRegister(void)
1039 {
1040  mpm_table[MPM_AC].name = "ac";
1043  mpm_table[MPM_AC].ConfigInit = NULL;
1044  mpm_table[MPM_AC].ConfigDeinit = NULL;
1049  mpm_table[MPM_AC].CacheRuleset = NULL;
1052 #ifdef UNITTESTS
1053  mpm_table[MPM_AC].RegisterUnittests = SCACRegisterTests;
1054 #endif
1056 }
1057 
1058 /*************************************Unittests********************************/
1059 
1060 #ifdef UNITTESTS
1061 #include "detect-engine-alert.h"
1062 
1063 static int SCACTest01(void)
1064 {
1065  int result = 0;
1066  MpmCtx mpm_ctx;
1067  MpmThreadCtx mpm_thread_ctx;
1068  PrefilterRuleStore pmq;
1069 
1070  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1071  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1072  MpmInitCtx(&mpm_ctx, MPM_AC);
1073 
1074  /* 1 match */
1075  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1076  PmqSetup(&pmq);
1077 
1078  SCACPreparePatterns(NULL, &mpm_ctx);
1079 
1080  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1081 
1082  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1083  (uint8_t *)buf, strlen(buf));
1084 
1085  if (cnt == 1)
1086  result = 1;
1087  else
1088  printf("1 != %" PRIu32 " ",cnt);
1089 
1090  SCACDestroyCtx(&mpm_ctx);
1091  PmqFree(&pmq);
1092  return result;
1093 }
1094 
1095 static int SCACTest02(void)
1096 {
1097  int result = 0;
1098  MpmCtx mpm_ctx;
1099  MpmThreadCtx mpm_thread_ctx;
1100  PrefilterRuleStore pmq;
1101 
1102  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1103  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1104  MpmInitCtx(&mpm_ctx, MPM_AC);
1105 
1106  /* 1 match */
1107  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1108  PmqSetup(&pmq);
1109 
1110  SCACPreparePatterns(NULL, &mpm_ctx);
1111 
1112  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1113  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1114  (uint8_t *)buf, strlen(buf));
1115 
1116  if (cnt == 0)
1117  result = 1;
1118  else
1119  printf("0 != %" PRIu32 " ",cnt);
1120 
1121  SCACDestroyCtx(&mpm_ctx);
1122  PmqFree(&pmq);
1123  return result;
1124 }
1125 
1126 static int SCACTest03(void)
1127 {
1128  int result = 0;
1129  MpmCtx mpm_ctx;
1130  MpmThreadCtx mpm_thread_ctx;
1131  PrefilterRuleStore pmq;
1132 
1133  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1134  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1135  MpmInitCtx(&mpm_ctx, MPM_AC);
1136 
1137  /* 1 match */
1138  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1139  /* 1 match */
1140  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1141  /* 1 match */
1142  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1143  PmqSetup(&pmq);
1144 
1145  SCACPreparePatterns(NULL, &mpm_ctx);
1146 
1147  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1148  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1149  (uint8_t *)buf, strlen(buf));
1150 
1151  if (cnt == 3)
1152  result = 1;
1153  else
1154  printf("3 != %" PRIu32 " ",cnt);
1155 
1156  SCACDestroyCtx(&mpm_ctx);
1157  PmqFree(&pmq);
1158  return result;
1159 }
1160 
1161 static int SCACTest04(void)
1162 {
1163  int result = 0;
1164  MpmCtx mpm_ctx;
1165  MpmThreadCtx mpm_thread_ctx;
1166  PrefilterRuleStore pmq;
1167 
1168  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1169  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1170  MpmInitCtx(&mpm_ctx, MPM_AC);
1171 
1172  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1173  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1174  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1175  PmqSetup(&pmq);
1176 
1177  SCACPreparePatterns(NULL, &mpm_ctx);
1178 
1179  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1180  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1181  (uint8_t *)buf, strlen(buf));
1182 
1183  if (cnt == 1)
1184  result = 1;
1185  else
1186  printf("1 != %" PRIu32 " ",cnt);
1187 
1188  SCACDestroyCtx(&mpm_ctx);
1189  PmqFree(&pmq);
1190  return result;
1191 }
1192 
1193 static int SCACTest05(void)
1194 {
1195  int result = 0;
1196  MpmCtx mpm_ctx;
1197  MpmThreadCtx mpm_thread_ctx;
1198  PrefilterRuleStore pmq;
1199 
1200  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1201  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1202  MpmInitCtx(&mpm_ctx, MPM_AC);
1203 
1204  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1205  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1206  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1207  PmqSetup(&pmq);
1208 
1209  SCACPreparePatterns(NULL, &mpm_ctx);
1210 
1211  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1212  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1213  (uint8_t *)buf, strlen(buf));
1214 
1215  if (cnt == 3)
1216  result = 1;
1217  else
1218  printf("3 != %" PRIu32 " ",cnt);
1219 
1220  SCACDestroyCtx(&mpm_ctx);
1221  PmqFree(&pmq);
1222  return result;
1223 }
1224 
1225 static int SCACTest06(void)
1226 {
1227  int result = 0;
1228  MpmCtx mpm_ctx;
1229  MpmThreadCtx mpm_thread_ctx;
1230  PrefilterRuleStore pmq;
1231 
1232  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1233  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1234  MpmInitCtx(&mpm_ctx, MPM_AC);
1235 
1236  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1237  PmqSetup(&pmq);
1238 
1239  SCACPreparePatterns(NULL, &mpm_ctx);
1240 
1241  const char *buf = "abcd";
1242  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1243  (uint8_t *)buf, strlen(buf));
1244 
1245  if (cnt == 1)
1246  result = 1;
1247  else
1248  printf("1 != %" PRIu32 " ",cnt);
1249 
1250  SCACDestroyCtx(&mpm_ctx);
1251  PmqFree(&pmq);
1252  return result;
1253 }
1254 
1255 static int SCACTest07(void)
1256 {
1257  MpmCtx mpm_ctx;
1258  MpmThreadCtx mpm_thread_ctx;
1259  PrefilterRuleStore pmq;
1260 
1261  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1262  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1263  MpmInitCtx(&mpm_ctx, MPM_AC);
1264 
1265  /* should match 30 times */
1266  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1267  /* should match 29 times */
1268  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1269  /* should match 28 times */
1270  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1271  /* 26 */
1272  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1273  /* 21 */
1274  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1275  /* 1 */
1276  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
1277  30, 0, 0, 5, 0, 0);
1278  PmqSetup(&pmq);
1279  /* total matches: 135: unique matches: 6 */
1280 
1281  SCACPreparePatterns(NULL, &mpm_ctx);
1282 
1283  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1284  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1285  (uint8_t *)buf, strlen(buf));
1286  FAIL_IF_NOT(cnt == 6);
1287 
1288  SCACDestroyCtx(&mpm_ctx);
1289  PmqFree(&pmq);
1290  PASS;
1291 }
1292 
1293 static int SCACTest08(void)
1294 {
1295  int result = 0;
1296  MpmCtx mpm_ctx;
1297  MpmThreadCtx mpm_thread_ctx;
1298  PrefilterRuleStore pmq;
1299 
1300  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1301  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1302  MpmInitCtx(&mpm_ctx, MPM_AC);
1303 
1304  /* 1 match */
1305  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1306  PmqSetup(&pmq);
1307 
1308  SCACPreparePatterns(NULL, &mpm_ctx);
1309 
1310  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1311  (uint8_t *)"a", 1);
1312 
1313  if (cnt == 0)
1314  result = 1;
1315  else
1316  printf("0 != %" PRIu32 " ",cnt);
1317 
1318  SCACDestroyCtx(&mpm_ctx);
1319  PmqFree(&pmq);
1320  return result;
1321 }
1322 
1323 static int SCACTest09(void)
1324 {
1325  int result = 0;
1326  MpmCtx mpm_ctx;
1327  MpmThreadCtx mpm_thread_ctx;
1328  PrefilterRuleStore pmq;
1329 
1330  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1331  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1332  MpmInitCtx(&mpm_ctx, MPM_AC);
1333 
1334  /* 1 match */
1335  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1336  PmqSetup(&pmq);
1337 
1338  SCACPreparePatterns(NULL, &mpm_ctx);
1339 
1340  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1341  (uint8_t *)"ab", 2);
1342 
1343  if (cnt == 1)
1344  result = 1;
1345  else
1346  printf("1 != %" PRIu32 " ",cnt);
1347 
1348  SCACDestroyCtx(&mpm_ctx);
1349  PmqFree(&pmq);
1350  return result;
1351 }
1352 
1353 static int SCACTest10(void)
1354 {
1355  int result = 0;
1356  MpmCtx mpm_ctx;
1357  MpmThreadCtx mpm_thread_ctx;
1358  PrefilterRuleStore pmq;
1359 
1360  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1361  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1362  MpmInitCtx(&mpm_ctx, MPM_AC);
1363 
1364  /* 1 match */
1365  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1366  PmqSetup(&pmq);
1367 
1368  SCACPreparePatterns(NULL, &mpm_ctx);
1369 
1370  const char *buf = "01234567890123456789012345678901234567890123456789"
1371  "01234567890123456789012345678901234567890123456789"
1372  "abcdefgh"
1373  "01234567890123456789012345678901234567890123456789"
1374  "01234567890123456789012345678901234567890123456789";
1375  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1376  (uint8_t *)buf, strlen(buf));
1377 
1378  if (cnt == 1)
1379  result = 1;
1380  else
1381  printf("1 != %" PRIu32 " ",cnt);
1382 
1383  SCACDestroyCtx(&mpm_ctx);
1384  PmqFree(&pmq);
1385  return result;
1386 }
1387 
1388 static int SCACTest11(void)
1389 {
1390  int result = 0;
1391  MpmCtx mpm_ctx;
1392  MpmThreadCtx mpm_thread_ctx;
1393  PrefilterRuleStore pmq;
1394 
1395  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1396  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1397  MpmInitCtx(&mpm_ctx, MPM_AC);
1398 
1399  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1400  goto end;
1401  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1402  goto end;
1403  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1404  goto end;
1405  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1406  goto end;
1407  PmqSetup(&pmq);
1408 
1409  if (SCACPreparePatterns(NULL, &mpm_ctx) == -1)
1410  goto end;
1411 
1412  result = 1;
1413 
1414  const char *buf = "he";
1415  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1416  strlen(buf)) == 1);
1417  buf = "she";
1418  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1419  strlen(buf)) == 2);
1420  buf = "his";
1421  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1422  strlen(buf)) == 1);
1423  buf = "hers";
1424  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1425  strlen(buf)) == 2);
1426 
1427  end:
1428  SCACDestroyCtx(&mpm_ctx);
1429  PmqFree(&pmq);
1430  return result;
1431 }
1432 
1433 static int SCACTest12(void)
1434 {
1435  int result = 0;
1436  MpmCtx mpm_ctx;
1437  MpmThreadCtx mpm_thread_ctx;
1438  PrefilterRuleStore pmq;
1439 
1440  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1441  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1442  MpmInitCtx(&mpm_ctx, MPM_AC);
1443 
1444  /* 1 match */
1445  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1446  /* 1 match */
1447  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1448  PmqSetup(&pmq);
1449 
1450  SCACPreparePatterns(NULL, &mpm_ctx);
1451 
1452  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1453  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1454  (uint8_t *)buf, strlen(buf));
1455 
1456  if (cnt == 2)
1457  result = 1;
1458  else
1459  printf("2 != %" PRIu32 " ",cnt);
1460 
1461  SCACDestroyCtx(&mpm_ctx);
1462  PmqFree(&pmq);
1463  return result;
1464 }
1465 
1466 static int SCACTest13(void)
1467 {
1468  int result = 0;
1469  MpmCtx mpm_ctx;
1470  MpmThreadCtx mpm_thread_ctx;
1471  PrefilterRuleStore pmq;
1472 
1473  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1474  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1475  MpmInitCtx(&mpm_ctx, MPM_AC);
1476 
1477  /* 1 match */
1478  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1479  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1480  PmqSetup(&pmq);
1481 
1482  SCACPreparePatterns(NULL, &mpm_ctx);
1483 
1484  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1485  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1486  (uint8_t *)buf, strlen(buf));
1487 
1488  if (cnt == 1)
1489  result = 1;
1490  else
1491  printf("1 != %" PRIu32 " ",cnt);
1492 
1493  SCACDestroyCtx(&mpm_ctx);
1494  PmqFree(&pmq);
1495  return result;
1496 }
1497 
1498 static int SCACTest14(void)
1499 {
1500  int result = 0;
1501  MpmCtx mpm_ctx;
1502  MpmThreadCtx mpm_thread_ctx;
1503  PrefilterRuleStore pmq;
1504 
1505  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1506  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1507  MpmInitCtx(&mpm_ctx, MPM_AC);
1508 
1509  /* 1 match */
1510  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1511  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1512  PmqSetup(&pmq);
1513 
1514  SCACPreparePatterns(NULL, &mpm_ctx);
1515 
1516  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1517  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1518  (uint8_t *)buf, strlen(buf));
1519 
1520  if (cnt == 1)
1521  result = 1;
1522  else
1523  printf("1 != %" PRIu32 " ",cnt);
1524 
1525  SCACDestroyCtx(&mpm_ctx);
1526  PmqFree(&pmq);
1527  return result;
1528 }
1529 
1530 static int SCACTest15(void)
1531 {
1532  int result = 0;
1533  MpmCtx mpm_ctx;
1534  MpmThreadCtx mpm_thread_ctx;
1535  PrefilterRuleStore pmq;
1536 
1537  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1538  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1539  MpmInitCtx(&mpm_ctx, MPM_AC);
1540 
1541  /* 1 match */
1542  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1543  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1544  PmqSetup(&pmq);
1545 
1546  SCACPreparePatterns(NULL, &mpm_ctx);
1547 
1548  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1549  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1550  (uint8_t *)buf, strlen(buf));
1551 
1552  if (cnt == 1)
1553  result = 1;
1554  else
1555  printf("1 != %" PRIu32 " ",cnt);
1556 
1557  SCACDestroyCtx(&mpm_ctx);
1558  PmqFree(&pmq);
1559  return result;
1560 }
1561 
1562 static int SCACTest16(void)
1563 {
1564  int result = 0;
1565  MpmCtx mpm_ctx;
1566  MpmThreadCtx mpm_thread_ctx;
1567  PrefilterRuleStore pmq;
1568 
1569  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1570  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1571  MpmInitCtx(&mpm_ctx, MPM_AC);
1572 
1573  /* 1 match */
1574  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1575  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1576  PmqSetup(&pmq);
1577 
1578  SCACPreparePatterns(NULL, &mpm_ctx);
1579 
1580  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1581  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1582  (uint8_t *)buf, strlen(buf));
1583 
1584  if (cnt == 1)
1585  result = 1;
1586  else
1587  printf("1 != %" PRIu32 " ",cnt);
1588 
1589  SCACDestroyCtx(&mpm_ctx);
1590  PmqFree(&pmq);
1591  return result;
1592 }
1593 
1594 static int SCACTest17(void)
1595 {
1596  int result = 0;
1597  MpmCtx mpm_ctx;
1598  MpmThreadCtx mpm_thread_ctx;
1599  PrefilterRuleStore pmq;
1600 
1601  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1602  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1603  MpmInitCtx(&mpm_ctx, MPM_AC);
1604 
1605  /* 1 match */
1606  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1607  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1608  PmqSetup(&pmq);
1609 
1610  SCACPreparePatterns(NULL, &mpm_ctx);
1611 
1612  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1613  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1614  (uint8_t *)buf, strlen(buf));
1615 
1616  if (cnt == 1)
1617  result = 1;
1618  else
1619  printf("1 != %" PRIu32 " ",cnt);
1620 
1621  SCACDestroyCtx(&mpm_ctx);
1622  PmqFree(&pmq);
1623  return result;
1624 }
1625 
1626 static int SCACTest18(void)
1627 {
1628  int result = 0;
1629  MpmCtx mpm_ctx;
1630  MpmThreadCtx mpm_thread_ctx;
1631  PrefilterRuleStore pmq;
1632 
1633  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1634  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1635  MpmInitCtx(&mpm_ctx, MPM_AC);
1636 
1637  /* 1 match */
1638  const char pat[] = "abcde"
1639  "fghij"
1640  "klmno"
1641  "pqrst"
1642  "uvwxy"
1643  "z";
1644  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1645  PmqSetup(&pmq);
1646 
1647  SCACPreparePatterns(NULL, &mpm_ctx);
1648 
1649  const char *buf = "abcde""fghij""klmno""pqrst""uvwxy""z";
1650  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1651  (uint8_t *)buf, strlen(buf));
1652 
1653  if (cnt == 1)
1654  result = 1;
1655  else
1656  printf("1 != %" PRIu32 " ",cnt);
1657 
1658  SCACDestroyCtx(&mpm_ctx);
1659  PmqFree(&pmq);
1660  return result;
1661 }
1662 
1663 static int SCACTest19(void)
1664 {
1665  int result = 0;
1666  MpmCtx mpm_ctx;
1667  MpmThreadCtx mpm_thread_ctx;
1668  PrefilterRuleStore pmq;
1669 
1670  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1671  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1672  MpmInitCtx(&mpm_ctx, MPM_AC);
1673 
1674  /* 1 */
1675  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1676  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1677  PmqSetup(&pmq);
1678 
1679  SCACPreparePatterns(NULL, &mpm_ctx);
1680 
1681  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1682  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1683  (uint8_t *)buf, strlen(buf));
1684 
1685  if (cnt == 1)
1686  result = 1;
1687  else
1688  printf("1 != %" PRIu32 " ",cnt);
1689 
1690  SCACDestroyCtx(&mpm_ctx);
1691  PmqFree(&pmq);
1692  return result;
1693 }
1694 
1695 static int SCACTest20(void)
1696 {
1697  int result = 0;
1698  MpmCtx mpm_ctx;
1699  MpmThreadCtx mpm_thread_ctx;
1700  PrefilterRuleStore pmq;
1701 
1702  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1703  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1704  MpmInitCtx(&mpm_ctx, MPM_AC);
1705 
1706  /* 1 */
1707  const char pat[] = "AAAAA"
1708  "AAAAA"
1709  "AAAAA"
1710  "AAAAA"
1711  "AAAAA"
1712  "AAAAA"
1713  "AA";
1714  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1715  PmqSetup(&pmq);
1716 
1717  SCACPreparePatterns(NULL, &mpm_ctx);
1718 
1719  const char *buf = "AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA";
1720  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1721  (uint8_t *)buf, strlen(buf));
1722 
1723  if (cnt == 1)
1724  result = 1;
1725  else
1726  printf("1 != %" PRIu32 " ",cnt);
1727 
1728  SCACDestroyCtx(&mpm_ctx);
1729  PmqFree(&pmq);
1730  return result;
1731 }
1732 
1733 static int SCACTest21(void)
1734 {
1735  int result = 0;
1736  MpmCtx mpm_ctx;
1737  MpmThreadCtx mpm_thread_ctx;
1738  PrefilterRuleStore pmq;
1739 
1740  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1741  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1742  MpmInitCtx(&mpm_ctx, MPM_AC);
1743 
1744  /* 1 */
1745  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1746  PmqSetup(&pmq);
1747 
1748  SCACPreparePatterns(NULL, &mpm_ctx);
1749 
1750  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1751  (uint8_t *)"AA", 2);
1752 
1753  if (cnt == 1)
1754  result = 1;
1755  else
1756  printf("1 != %" PRIu32 " ",cnt);
1757 
1758  SCACDestroyCtx(&mpm_ctx);
1759  PmqFree(&pmq);
1760  return result;
1761 }
1762 
1763 static int SCACTest22(void)
1764 {
1765  int result = 0;
1766  MpmCtx mpm_ctx;
1767  MpmThreadCtx mpm_thread_ctx;
1768  PrefilterRuleStore pmq;
1769 
1770  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1771  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1772  MpmInitCtx(&mpm_ctx, MPM_AC);
1773 
1774  /* 1 match */
1775  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1776  /* 1 match */
1777  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
1778  PmqSetup(&pmq);
1779 
1780  SCACPreparePatterns(NULL, &mpm_ctx);
1781 
1782  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1783  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1784  (uint8_t *)buf, strlen(buf));
1785 
1786  if (cnt == 2)
1787  result = 1;
1788  else
1789  printf("2 != %" PRIu32 " ",cnt);
1790 
1791  SCACDestroyCtx(&mpm_ctx);
1792  PmqFree(&pmq);
1793  return result;
1794 }
1795 
1796 static int SCACTest23(void)
1797 {
1798  int result = 0;
1799  MpmCtx mpm_ctx;
1800  MpmThreadCtx mpm_thread_ctx;
1801  PrefilterRuleStore pmq;
1802 
1803  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1804  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1805  MpmInitCtx(&mpm_ctx, MPM_AC);
1806 
1807  /* 1 */
1808  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1809  PmqSetup(&pmq);
1810 
1811  SCACPreparePatterns(NULL, &mpm_ctx);
1812 
1813  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1814  (uint8_t *)"aa", 2);
1815 
1816  if (cnt == 0)
1817  result = 1;
1818  else
1819  printf("1 != %" PRIu32 " ",cnt);
1820 
1821  SCACDestroyCtx(&mpm_ctx);
1822  PmqFree(&pmq);
1823  return result;
1824 }
1825 
1826 static int SCACTest24(void)
1827 {
1828  int result = 0;
1829  MpmCtx mpm_ctx;
1830  MpmThreadCtx mpm_thread_ctx;
1831  PrefilterRuleStore pmq;
1832 
1833  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1834  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1835  MpmInitCtx(&mpm_ctx, MPM_AC);
1836 
1837  /* 1 */
1838  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1839  PmqSetup(&pmq);
1840 
1841  SCACPreparePatterns(NULL, &mpm_ctx);
1842 
1843  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1844  (uint8_t *)"aa", 2);
1845 
1846  if (cnt == 1)
1847  result = 1;
1848  else
1849  printf("1 != %" PRIu32 " ",cnt);
1850 
1851  SCACDestroyCtx(&mpm_ctx);
1852  PmqFree(&pmq);
1853  return result;
1854 }
1855 
1856 static int SCACTest25(void)
1857 {
1858  int result = 0;
1859  MpmCtx mpm_ctx;
1860  MpmThreadCtx mpm_thread_ctx;
1861  PrefilterRuleStore pmq;
1862 
1863  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1864  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1865  MpmInitCtx(&mpm_ctx, MPM_AC);
1866 
1867  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1868  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1869  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
1870  PmqSetup(&pmq);
1871 
1872  SCACPreparePatterns(NULL, &mpm_ctx);
1873 
1874  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1875  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1876  (uint8_t *)buf, strlen(buf));
1877 
1878  if (cnt == 3)
1879  result = 1;
1880  else
1881  printf("3 != %" PRIu32 " ",cnt);
1882 
1883  SCACDestroyCtx(&mpm_ctx);
1884  PmqFree(&pmq);
1885  return result;
1886 }
1887 
1888 static int SCACTest26(void)
1889 {
1890  int result = 0;
1891  MpmCtx mpm_ctx;
1892  MpmThreadCtx mpm_thread_ctx;
1893  PrefilterRuleStore pmq;
1894 
1895  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1896  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1897  MpmInitCtx(&mpm_ctx, MPM_AC);
1898 
1899  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
1900  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
1901  PmqSetup(&pmq);
1902 
1903  SCACPreparePatterns(NULL, &mpm_ctx);
1904 
1905  const char *buf = "works";
1906  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1907  (uint8_t *)buf, strlen(buf));
1908 
1909  if (cnt == 1)
1910  result = 1;
1911  else
1912  printf("3 != %" PRIu32 " ",cnt);
1913 
1914  SCACDestroyCtx(&mpm_ctx);
1915  PmqFree(&pmq);
1916  return result;
1917 }
1918 
1919 static int SCACTest27(void)
1920 {
1921  int result = 0;
1922  MpmCtx mpm_ctx;
1923  MpmThreadCtx mpm_thread_ctx;
1924  PrefilterRuleStore pmq;
1925 
1926  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1927  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1928  MpmInitCtx(&mpm_ctx, MPM_AC);
1929 
1930  /* 0 match */
1931  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
1932  PmqSetup(&pmq);
1933 
1934  SCACPreparePatterns(NULL, &mpm_ctx);
1935 
1936  const char *buf = "tone";
1937  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1938  (uint8_t *)buf, strlen(buf));
1939 
1940  if (cnt == 0)
1941  result = 1;
1942  else
1943  printf("0 != %" PRIu32 " ",cnt);
1944 
1945  SCACDestroyCtx(&mpm_ctx);
1946  PmqFree(&pmq);
1947  return result;
1948 }
1949 
1950 static int SCACTest28(void)
1951 {
1952  MpmCtx mpm_ctx;
1953  MpmThreadCtx mpm_thread_ctx;
1954  PrefilterRuleStore pmq;
1955 
1956  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1957  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1958  MpmInitCtx(&mpm_ctx, MPM_AC);
1959 
1960  /* 0 match */
1961  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
1962  PmqSetup(&pmq);
1963 
1964  SCACPreparePatterns(NULL, &mpm_ctx);
1965 
1966  const char *buf = "tONE";
1967  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1968  (uint8_t *)buf, strlen(buf));
1969  FAIL_IF_NOT(cnt == 0);
1970 
1971  SCACDestroyCtx(&mpm_ctx);
1972  PmqFree(&pmq);
1973  PASS;
1974 }
1975 
1976 static int SCACTest29(void)
1977 {
1978  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
1979  uint16_t buflen = sizeof(buf) - 1;
1980  ThreadVars th_v;
1981  DetectEngineThreadCtx *det_ctx = NULL;
1982 
1983  memset(&th_v, 0, sizeof(th_v));
1984  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1985  FAIL_IF_NULL(p);
1986 
1989  de_ctx->flags |= DE_QUIET;
1990 
1992  "alert tcp any any -> any any "
1993  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
1994  FAIL_IF_NULL(s);
1996  "alert tcp any any -> any any "
1997  "(content:\"onetwothreefourfivesixseveneightnine\"; fast_pattern:3,3; sid:2;)");
1998  FAIL_IF_NULL(s);
1999 
2001  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2002 
2003  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2004 
2005  FAIL_IF(PacketAlertCheck(p, 1) != 1);
2006  FAIL_IF(PacketAlertCheck(p, 2) != 1);
2007 
2008  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2010  StatsThreadCleanup(&th_v);
2011 
2012  UTHFreePackets(&p, 1);
2013  PASS;
2014 }
2015 
2016 /** \test endswith logic */
2017 static int SCACTest30(void)
2018 {
2019  MpmCtx mpm_ctx;
2020  MpmThreadCtx mpm_thread_ctx;
2021  PrefilterRuleStore pmq;
2022 
2023  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2024  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2025  MpmInitCtx(&mpm_ctx, MPM_AC);
2026 
2027  /* 0 match */
2028  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"xyz", 3, 0, 0, 0, 0, MPM_PATTERN_FLAG_ENDSWITH);
2029  PmqSetup(&pmq);
2030 
2031  SCACPreparePatterns(NULL, &mpm_ctx);
2032 
2033  const char *buf1 = "abcdefghijklmnopqrstuvwxyz";
2034  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf1, strlen(buf1));
2035  FAIL_IF_NOT(cnt == 1);
2036  const char *buf2 = "xyzxyzxyzxyzxyzxyzxyza";
2037  cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf2, strlen(buf2));
2038  FAIL_IF_NOT(cnt == 0);
2039 
2040  SCACDestroyCtx(&mpm_ctx);
2041  PmqFree(&pmq);
2042  PASS;
2043 }
2044 
2045 void SCACRegisterTests(void)
2046 {
2047  UtRegisterTest("SCACTest01", SCACTest01);
2048  UtRegisterTest("SCACTest02", SCACTest02);
2049  UtRegisterTest("SCACTest03", SCACTest03);
2050  UtRegisterTest("SCACTest04", SCACTest04);
2051  UtRegisterTest("SCACTest05", SCACTest05);
2052  UtRegisterTest("SCACTest06", SCACTest06);
2053  UtRegisterTest("SCACTest07", SCACTest07);
2054  UtRegisterTest("SCACTest08", SCACTest08);
2055  UtRegisterTest("SCACTest09", SCACTest09);
2056  UtRegisterTest("SCACTest10", SCACTest10);
2057  UtRegisterTest("SCACTest11", SCACTest11);
2058  UtRegisterTest("SCACTest12", SCACTest12);
2059  UtRegisterTest("SCACTest13", SCACTest13);
2060  UtRegisterTest("SCACTest14", SCACTest14);
2061  UtRegisterTest("SCACTest15", SCACTest15);
2062  UtRegisterTest("SCACTest16", SCACTest16);
2063  UtRegisterTest("SCACTest17", SCACTest17);
2064  UtRegisterTest("SCACTest18", SCACTest18);
2065  UtRegisterTest("SCACTest19", SCACTest19);
2066  UtRegisterTest("SCACTest20", SCACTest20);
2067  UtRegisterTest("SCACTest21", SCACTest21);
2068  UtRegisterTest("SCACTest22", SCACTest22);
2069  UtRegisterTest("SCACTest23", SCACTest23);
2070  UtRegisterTest("SCACTest24", SCACTest24);
2071  UtRegisterTest("SCACTest25", SCACTest25);
2072  UtRegisterTest("SCACTest26", SCACTest26);
2073  UtRegisterTest("SCACTest27", SCACTest27);
2074  UtRegisterTest("SCACTest28", SCACTest28);
2075  UtRegisterTest("SCACTest29", SCACTest29);
2076  UtRegisterTest("SCACTest30", SCACTest30);
2077 }
2078 #endif /* UNITTESTS */
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SCACOutputTable_::no_of_entries
uint32_t no_of_entries
Definition: util-mpm-ac.h:51
SCACInitCtx
void SCACInitCtx(MpmCtx *)
Initialize the AC context.
Definition: util-mpm-ac.c:740
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
MpmThreadCtx_
Definition: util-mpm.h:46
MpmFreePattern
void MpmFreePattern(MpmCtx *mpm_ctx, MpmPattern *p)
Definition: util-mpm.c:353
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
MpmTableElmt_::name
const char * name
Definition: util-mpm.h:151
PrefilterRuleStore_
structure for storing potential rule matches
Definition: util-prefilter.h:34
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:275
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:142
SCACPatternList_::patlen
uint16_t patlen
Definition: util-mpm-ac.h:35
SCACPrintInfo
void SCACPrintInfo(MpmCtx *mpm_ctx)
Definition: util-mpm-ac.c:1013
StateQueue_
Helper structure used by AC during state table creation.
Definition: util-mpm-ac-queue.h:33
ctx
struct Thresholds ctx
AC_CASE_BIT
#define AC_CASE_BIT
Definition: util-mpm-ac.c:85
util-mpm-ac-queue.h
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
MPM_FEATURE_FLAG_OFFSET
#define MPM_FEATURE_FLAG_OFFSET
Definition: util-mpm.h:147
util-memcpy.h
MpmCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:108
SC_AC_STATE_TYPE_U32
#define SC_AC_STATE_TYPE_U32
Definition: util-mpm-ac.h:31
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2643
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:453
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:105
MpmTableElmt_::AddPattern
int(* AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:172
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:365
MpmTableElmt_::feature_flags
uint8_t feature_flags
Definition: util-mpm.h:184
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2420
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3437
SCACPreparePatterns
int SCACPreparePatterns(MpmConfig *, MpmCtx *mpm_ctx)
Process the patterns added to the mpm, and create the internal tables.
Definition: util-mpm-ac.c:647
MpmTableElmt_::InitCtx
void(* InitCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:152
SC_AC_STATE_TYPE_U16
#define SC_AC_STATE_TYPE_U16
Definition: util-mpm-ac.h:30
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
util-memcmp.h
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
Definition: util-mpm.c:209
MpmTableElmt_::PrintCtx
void(* PrintCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:179
MpmCtx_::max_pat_id
uint32_t max_pat_id
Definition: util-mpm.h:110
SCACStateQueueFree
void SCACStateQueueFree(StateQueue *q)
Definition: util-mpm-ac-queue.c:36
SCACOutputTable
struct SCACOutputTable_ SCACOutputTable
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
MpmPattern_::next
struct MpmPattern_ * next
Definition: util-mpm.h:79
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
SCACStateQueueAlloc
StateQueue * SCACStateQueueAlloc(void)
Definition: util-mpm-ac-queue.c:22
DetectEngineThreadCtx_
Definition: detect.h:1244
SCACPatternList_::endswith
bool endswith
Definition: util-mpm-ac.h:40
MpmAddPattern
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
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3369
MPM_FEATURE_FLAG_DEPTH
#define MPM_FEATURE_FLAG_DEPTH
Definition: util-mpm.h:146
SCACPatternList_::cs
uint8_t * cs
Definition: util-mpm-ac.h:34
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:104
SCACAddPatternCI
int SCACAddPatternCI(MpmCtx *, const uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Add a case insensitive pattern. Although we have different calls for adding case sensitive and insens...
Definition: util-mpm-ac.c:982
SCACSearch
uint32_t SCACSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
The aho corasick search function.
Definition: util-mpm-ac.c:854
SCACAddPatternCS
int SCACAddPatternCS(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Add a case sensitive pattern. Although we have different calls for adding case sensitive and insensit...
Definition: util-mpm-ac.c:1006
SCReturn
#define SCReturn
Definition: util-debug.h:279
Packet_
Definition: decode.h:501
detect-engine-build.h
MpmAddPatternCI
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
detect-engine-alert.h
conf.h
SCACPatternList_::sids
SigIntId * sids
Definition: util-mpm-ac.h:44
MPM_INIT_HASH_SIZE
#define MPM_INIT_HASH_SIZE
Definition: util-mpm.h:30
SC_AC_FAIL
#define SC_AC_FAIL
Definition: util-mpm-ac.c:81
MpmTableElmt_::CacheRuleset
int(* CacheRuleset)(MpmConfig *)
Definition: util-mpm.h:176
util-mpm-ac.h
MpmPattern_
Definition: util-mpm.h:54
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:178
MpmAddPatternCS
int MpmAddPatternCS(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:249
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:225
SCACPatternList_::depth
uint16_t depth
Definition: util-mpm-ac.h:38
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2204
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
SCACPatternList_::offset
uint16_t offset
Definition: util-mpm-ac.h:37
MPM_PATTERN_FLAG_NOCASE
#define MPM_PATTERN_FLAG_NOCASE
Definition: util-mpm.h:136
SCACCtx_
Definition: util-mpm-ac.h:54
SCACDestroyCtx
void SCACDestroyCtx(MpmCtx *)
Destroy the mpm context.
Definition: util-mpm-ac.c:771
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:102
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3605
MpmTableElmt_::AddPatternNocase
int(* AddPatternNocase)(struct MpmCtx_ *, const uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:173
FatalError
#define FatalError(...)
Definition: util-debug.h:510
SCACPatternList_
Definition: util-mpm-ac.h:33
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
MPM_PATTERN_FLAG_ENDSWITH
#define MPM_PATTERN_FLAG_ENDSWITH
Definition: util-mpm.h:144
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:267
MpmTableElmt_::Prepare
int(* Prepare)(MpmConfig *, struct MpmCtx_ *)
Definition: util-mpm.h:175
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:154
SCACCtx
struct SCACCtx_ SCACCtx
SCFree
#define SCFree(p)
Definition: util-mem.h:61
MpmACRegister
void MpmACRegister(void)
Register the aho-corasick mpm.
Definition: util-mpm-ac.c:1038
MpmConfig_
Definition: util-mpm.h:89
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
MpmCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:107
SCACOutputTable_
Definition: util-mpm-ac.h:47
MpmCtx_::init_hash
MpmPattern ** init_hash
Definition: util-mpm.h:113
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2604
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
MpmTableElmt_::ConfigDeinit
void(* ConfigDeinit)(MpmConfig **)
Definition: util-mpm.h:158
suricata.h
MpmTableElmt_::ConfigCacheDirSet
void(* ConfigCacheDirSet)(MpmConfig *, const char *dir_path)
Definition: util-mpm.h:159
PmqFree
void PmqFree(PrefilterRuleStore *pmq)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
AC_PID_MASK
#define AC_PID_MASK
Definition: util-mpm-ac.c:84
SCACOutputTable_::pids
uint32_t * pids
Definition: util-mpm-ac.h:49
MpmTableElmt_::ConfigInit
MpmConfig *(* ConfigInit)(void)
Definition: util-mpm.h:157
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:934
AC_CASE_MASK
#define AC_CASE_MASK
Definition: util-mpm-ac.c:83
MpmCtx_
Definition: util-mpm.h:93
SigIntId
#define SigIntId
Definition: suricata-common.h:332
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
MpmCtx_::ctx
void * ctx
Definition: util-mpm.h:94
StatsThreadCleanup
void StatsThreadCleanup(ThreadVars *tv)
Definition: counters.c:1304
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290
SCACPatternList_::sids_size
uint32_t sids_size
Definition: util-mpm-ac.h:43
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
MpmTableElmt_::RegisterUnittests
void(* RegisterUnittests)(void)
Definition: util-mpm.h:182
PmqSetup
int PmqSetup(PrefilterRuleStore *pmq)
Setup a pmq.
Definition: util-prefilter.c:37
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:456
MPM_AC
@ MPM_AC
Definition: util-mpm.h:36