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