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(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_ctx Pointer to the mpm context.
704  */
706 {
707  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
708 
709  if (mpm_ctx->pattern_cnt == 0 || mpm_ctx->init_hash == NULL) {
710  SCLogDebug("no patterns supplied to this mpm_ctx");
711  return 0;
712  }
713 
714  /* alloc the pattern array */
715  ctx->parray = (MpmPattern **)SCCalloc(mpm_ctx->pattern_cnt, sizeof(MpmPattern *));
716  if (ctx->parray == NULL)
717  goto error;
718  mpm_ctx->memory_cnt++;
719  mpm_ctx->memory_size += (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
720 
721  /* populate it with the patterns in the hash */
722  uint32_t i = 0, p = 0;
723  for (i = 0; i < MPM_INIT_HASH_SIZE; i++) {
724  MpmPattern *node = mpm_ctx->init_hash[i], *nnode = NULL;
725  while(node != NULL) {
726  nnode = node->next;
727  node->next = NULL;
728  ctx->parray[p++] = node;
729  node = nnode;
730  }
731  }
732 
733  /* we no longer need the hash, so free it's memory */
734  SCFree(mpm_ctx->init_hash);
735  mpm_ctx->init_hash = NULL;
736 
737  /* the memory consumed by a single state in our goto table */
738  ctx->single_state_size = sizeof(int32_t) * 256;
739 
740  /* handle no case patterns */
741  ctx->pid_pat_list = SCCalloc((mpm_ctx->max_pat_id + 1), sizeof(SCACPatternList));
742  if (ctx->pid_pat_list == NULL) {
743  FatalError("Error allocating memory");
744  }
745 
746  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
747  if (!(ctx->parray[i]->flags & MPM_PATTERN_FLAG_NOCASE)) {
748  ctx->pid_pat_list[ctx->parray[i]->id].cs = SCMalloc(ctx->parray[i]->len);
749  if (ctx->pid_pat_list[ctx->parray[i]->id].cs == NULL) {
750  FatalError("Error allocating memory");
751  }
752  memcpy(ctx->pid_pat_list[ctx->parray[i]->id].cs,
753  ctx->parray[i]->original_pat, ctx->parray[i]->len);
754  ctx->pid_pat_list[ctx->parray[i]->id].patlen = ctx->parray[i]->len;
755  }
756  ctx->pid_pat_list[ctx->parray[i]->id].offset = ctx->parray[i]->offset;
757  ctx->pid_pat_list[ctx->parray[i]->id].depth = ctx->parray[i]->depth;
758  ctx->pid_pat_list[ctx->parray[i]->id].endswith =
759  (ctx->parray[i]->flags & MPM_PATTERN_FLAG_ENDSWITH) != 0;
760 
761  /* ACPatternList now owns this memory */
762  //SCLogInfo("ctx->parray[i]->sids_size %u", ctx->parray[i]->sids_size);
763  ctx->pid_pat_list[ctx->parray[i]->id].sids_size = ctx->parray[i]->sids_size;
764  ctx->pid_pat_list[ctx->parray[i]->id].sids = ctx->parray[i]->sids;
765 
766  ctx->parray[i]->sids_size = 0;
767  ctx->parray[i]->sids = NULL;
768  }
769 
770  /* prepare the state table required by AC */
771  SCACPrepareStateTable(mpm_ctx);
772 
773  /* free all the stored patterns. Should save us a good 100-200 mbs */
774  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
775  if (ctx->parray[i] != NULL) {
776  MpmFreePattern(mpm_ctx, ctx->parray[i]);
777  }
778  }
779  SCFree(ctx->parray);
780  ctx->parray = NULL;
781  mpm_ctx->memory_cnt--;
782  mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
783 
784  ctx->pattern_id_bitarray_size = (mpm_ctx->max_pat_id / 8) + 1;
785  SCLogDebug("ctx->pattern_id_bitarray_size %u", ctx->pattern_id_bitarray_size);
786 
787  return 0;
788 
789 error:
790  return -1;
791 }
792 
793 /**
794  * \brief Initialize the AC context.
795  *
796  * \param mpm_ctx Mpm context.
797  */
798 void SCACInitCtx(MpmCtx *mpm_ctx)
799 {
800  if (mpm_ctx->ctx != NULL)
801  return;
802 
803  mpm_ctx->ctx = SCCalloc(1, sizeof(SCACCtx));
804  if (mpm_ctx->ctx == NULL) {
805  exit(EXIT_FAILURE);
806  }
807 
808  mpm_ctx->memory_cnt++;
809  mpm_ctx->memory_size += sizeof(SCACCtx);
810 
811  /* initialize the hash we use to speed up pattern insertions */
812  mpm_ctx->init_hash = SCCalloc(MPM_INIT_HASH_SIZE, sizeof(MpmPattern *));
813  if (mpm_ctx->init_hash == NULL) {
814  exit(EXIT_FAILURE);
815  }
816 
817  /* get conf values for AC from our yaml file. We have no conf values for
818  * now. We will certainly need this, as we develop the algo */
819  SCACGetConfig();
820 
821  SCReturn;
822 }
823 
824 /**
825  * \brief Destroy the mpm context.
826  *
827  * \param mpm_ctx Pointer to the mpm context.
828  */
829 void SCACDestroyCtx(MpmCtx *mpm_ctx)
830 {
831  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
832  if (ctx == NULL)
833  return;
834 
835  if (mpm_ctx->init_hash != NULL) {
836  SCFree(mpm_ctx->init_hash);
837  mpm_ctx->init_hash = NULL;
838  mpm_ctx->memory_cnt--;
839  mpm_ctx->memory_size -= (MPM_INIT_HASH_SIZE * sizeof(MpmPattern *));
840  }
841 
842  if (ctx->parray != NULL) {
843  uint32_t i;
844  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
845  if (ctx->parray[i] != NULL) {
846  MpmFreePattern(mpm_ctx, ctx->parray[i]);
847  }
848  }
849 
850  SCFree(ctx->parray);
851  ctx->parray = NULL;
852  mpm_ctx->memory_cnt--;
853  mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
854  }
855 
856  if (ctx->state_table_u16 != NULL) {
857  SCFree(ctx->state_table_u16);
858  ctx->state_table_u16 = NULL;
859 
860  mpm_ctx->memory_cnt++;
861  mpm_ctx->memory_size -= (ctx->state_count *
862  sizeof(SC_AC_STATE_TYPE_U16) * 256);
863  }
864  if (ctx->state_table_u32 != NULL) {
865  SCFree(ctx->state_table_u32);
866  ctx->state_table_u32 = NULL;
867 
868  mpm_ctx->memory_cnt++;
869  mpm_ctx->memory_size -= (ctx->state_count *
870  sizeof(SC_AC_STATE_TYPE_U32) * 256);
871  }
872 
873  if (ctx->output_table != NULL) {
874  uint32_t state_count;
875  for (state_count = 0; state_count < ctx->state_count; state_count++) {
876  if (ctx->output_table[state_count].pids != NULL) {
877  SCFree(ctx->output_table[state_count].pids);
878  }
879  }
880  SCFree(ctx->output_table);
881  }
882 
883  if (ctx->pid_pat_list != NULL) {
884  uint32_t i;
885  for (i = 0; i < (mpm_ctx->max_pat_id + 1); i++) {
886  if (ctx->pid_pat_list[i].cs != NULL)
887  SCFree(ctx->pid_pat_list[i].cs);
888  if (ctx->pid_pat_list[i].sids != NULL)
889  SCFree(ctx->pid_pat_list[i].sids);
890  }
891  SCFree(ctx->pid_pat_list);
892  }
893 
894  SCFree(mpm_ctx->ctx);
895  mpm_ctx->ctx = NULL;
896  mpm_ctx->memory_cnt--;
897  mpm_ctx->memory_size -= sizeof(SCACCtx);
898 }
899 
900 /**
901  * \brief The aho corasick search function.
902  *
903  * \param mpm_ctx Pointer to the mpm context.
904  * \param mpm_thread_ctx Pointer to the mpm thread context.
905  * \param pmq Pointer to the Pattern Matcher Queue to hold
906  * search matches.
907  * \param buf Buffer to be searched.
908  * \param buflen Buffer length.
909  *
910  * \retval matches Match count: counts unique matches per pattern.
911  */
912 uint32_t SCACSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
913  PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
914 {
915  const SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
916  int matches = 0;
917 
918  /* \todo tried loop unrolling with register var, with no perf increase. Need
919  * to dig deeper */
920  /* \todo Change it for stateful MPM. Supply the state using mpm_thread_ctx */
921  const SCACPatternList *pid_pat_list = ctx->pid_pat_list;
922 
923  uint8_t bitarray[ctx->pattern_id_bitarray_size];
924  memset(bitarray, 0, ctx->pattern_id_bitarray_size);
925 
926  if (ctx->state_count < 32767) {
927  register SC_AC_STATE_TYPE_U16 state = 0;
928  const SC_AC_STATE_TYPE_U16(*state_table_u16)[256] = ctx->state_table_u16;
929  for (uint32_t i = 0; i < buflen; i++) {
930  state = state_table_u16[state & 0x7FFF][u8_tolower(buf[i])];
931  if (state & 0x8000) {
932  const uint32_t no_of_entries = ctx->output_table[state & 0x7FFF].no_of_entries;
933  const uint32_t *pids = ctx->output_table[state & 0x7FFF].pids;
934  for (uint32_t k = 0; k < no_of_entries; k++) {
935  if (pids[k] & AC_CASE_MASK) {
936  const uint32_t lower_pid = pids[k] & AC_PID_MASK;
937  const SCACPatternList *pat = &pid_pat_list[lower_pid];
938  const int offset = i - pat->patlen + 1;
939 
940  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
941  continue;
942  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
943  continue;
944 
945  if (SCMemcmp(pat->cs, buf + offset, pat->patlen) != 0) {
946  /* inside loop */
947  continue;
948  }
949  if (!(bitarray[(lower_pid) / 8] & (1 << ((lower_pid) % 8)))) {
950  bitarray[(lower_pid) / 8] |= (1 << ((lower_pid) % 8));
951  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
952  matches++;
953  }
954  } else {
955  const SCACPatternList *pat = &pid_pat_list[pids[k]];
956  const int offset = i - pat->patlen + 1;
957 
958  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
959  continue;
960  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
961  continue;
962 
963  if (!(bitarray[pids[k] / 8] & (1 << (pids[k] % 8)))) {
964  bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
965  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
966  matches++;
967  }
968  }
969  }
970  }
971  }
972  } else {
973  register SC_AC_STATE_TYPE_U32 state = 0;
974  const SC_AC_STATE_TYPE_U32(*state_table_u32)[256] = ctx->state_table_u32;
975  for (uint32_t i = 0; i < buflen; i++) {
976  state = state_table_u32[state & 0x00FFFFFF][u8_tolower(buf[i])];
977  if (state & 0xFF000000) {
978  const uint32_t no_of_entries = ctx->output_table[state & 0x00FFFFFF].no_of_entries;
979  const uint32_t *pids = ctx->output_table[state & 0x00FFFFFF].pids;
980  for (uint32_t k = 0; k < no_of_entries; k++) {
981  if (pids[k] & AC_CASE_MASK) {
982  const uint32_t lower_pid = pids[k] & 0x0000FFFF;
983  const SCACPatternList *pat = &pid_pat_list[lower_pid];
984  const int offset = i - pat->patlen + 1;
985 
986  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
987  continue;
988  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
989  continue;
990 
991  if (SCMemcmp(pat->cs, buf + offset,
992  pat->patlen) != 0) {
993  /* inside loop */
994  continue;
995  }
996  if (!(bitarray[(lower_pid) / 8] & (1 << ((lower_pid) % 8)))) {
997  bitarray[(lower_pid) / 8] |= (1 << ((lower_pid) % 8));
998  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
999  matches++;
1000  }
1001  } else {
1002  const SCACPatternList *pat = &pid_pat_list[pids[k]];
1003  const int offset = i - pat->patlen + 1;
1004 
1005  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
1006  continue;
1007  if (pat->endswith && (uint32_t)offset + pat->patlen != buflen)
1008  continue;
1009 
1010  if (!(bitarray[pids[k] / 8] & (1 << (pids[k] % 8)))) {
1011  bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
1012  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
1013  matches++;
1014  }
1015  }
1016  }
1017  }
1018  }
1019  }
1020  return matches;
1021 }
1022 
1023 /**
1024  * \brief Add a case insensitive pattern. Although we have different calls for
1025  * adding case sensitive and insensitive patterns, we make a single call
1026  * for either case. No special treatment for either case.
1027  *
1028  * \param mpm_ctx Pointer to the mpm context.
1029  * \param pat The pattern to add.
1030  * \param patnen The pattern length.
1031  * \param offset Ignored.
1032  * \param depth Ignored.
1033  * \param pid The pattern id.
1034  * \param sid Ignored.
1035  * \param flags Flags associated with this pattern.
1036  *
1037  * \retval 0 On success.
1038  * \retval -1 On failure.
1039  */
1040 int SCACAddPatternCI(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1041  uint16_t offset, uint16_t depth, uint32_t pid,
1042  SigIntId sid, uint8_t flags)
1043 {
1045  return MpmAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1046 }
1047 
1048 /**
1049  * \brief Add a case sensitive pattern. Although we have different calls for
1050  * adding case sensitive and insensitive patterns, we make a single call
1051  * for either case. No special treatment for either case.
1052  *
1053  * \param mpm_ctx Pointer to the mpm context.
1054  * \param pat The pattern to add.
1055  * \param patnen The pattern length.
1056  * \param offset Ignored.
1057  * \param depth Ignored.
1058  * \param pid The pattern id.
1059  * \param sid Ignored.
1060  * \param flags Flags associated with this pattern.
1061  *
1062  * \retval 0 On success.
1063  * \retval -1 On failure.
1064  */
1065 int SCACAddPatternCS(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1066  uint16_t offset, uint16_t depth, uint32_t pid,
1067  SigIntId sid, uint8_t flags)
1068 {
1069  return MpmAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1070 }
1071 
1072 void SCACPrintInfo(MpmCtx *mpm_ctx)
1073 {
1074  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
1075 
1076  printf("MPM AC Information:\n");
1077  printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
1078  printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
1079  printf(" Sizeof:\n");
1080  printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
1081  printf(" SCACCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCACCtx));
1082  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1083  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1084  printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
1085  printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
1086  printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
1087  printf("Total states in the state table: %" PRIu32 "\n", ctx->state_count);
1088  printf("\n");
1089 }
1090 
1091 
1092 /************************** Mpm Registration ***************************/
1093 
1094 /**
1095  * \brief Register the aho-corasick mpm.
1096  */
1097 void MpmACRegister(void)
1098 {
1099  mpm_table[MPM_AC].name = "ac";
1107 #ifdef UNITTESTS
1108  mpm_table[MPM_AC].RegisterUnittests = SCACRegisterTests;
1109 #endif
1111 }
1112 
1113 /*************************************Unittests********************************/
1114 
1115 #ifdef UNITTESTS
1116 #include "detect-engine-alert.h"
1117 
1118 static int SCACTest01(void)
1119 {
1120  int result = 0;
1121  MpmCtx mpm_ctx;
1122  MpmThreadCtx mpm_thread_ctx;
1123  PrefilterRuleStore pmq;
1124 
1125  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1126  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1127  MpmInitCtx(&mpm_ctx, MPM_AC);
1128 
1129  /* 1 match */
1130  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1131  PmqSetup(&pmq);
1132 
1133  SCACPreparePatterns(&mpm_ctx);
1134 
1135  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1136 
1137  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1138  (uint8_t *)buf, strlen(buf));
1139 
1140  if (cnt == 1)
1141  result = 1;
1142  else
1143  printf("1 != %" PRIu32 " ",cnt);
1144 
1145  SCACDestroyCtx(&mpm_ctx);
1146  PmqFree(&pmq);
1147  return result;
1148 }
1149 
1150 static int SCACTest02(void)
1151 {
1152  int result = 0;
1153  MpmCtx mpm_ctx;
1154  MpmThreadCtx mpm_thread_ctx;
1155  PrefilterRuleStore pmq;
1156 
1157  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1158  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1159  MpmInitCtx(&mpm_ctx, MPM_AC);
1160 
1161  /* 1 match */
1162  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1163  PmqSetup(&pmq);
1164 
1165  SCACPreparePatterns(&mpm_ctx);
1166 
1167  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1168  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1169  (uint8_t *)buf, strlen(buf));
1170 
1171  if (cnt == 0)
1172  result = 1;
1173  else
1174  printf("0 != %" PRIu32 " ",cnt);
1175 
1176  SCACDestroyCtx(&mpm_ctx);
1177  PmqFree(&pmq);
1178  return result;
1179 }
1180 
1181 static int SCACTest03(void)
1182 {
1183  int result = 0;
1184  MpmCtx mpm_ctx;
1185  MpmThreadCtx mpm_thread_ctx;
1186  PrefilterRuleStore pmq;
1187 
1188  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1189  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1190  MpmInitCtx(&mpm_ctx, MPM_AC);
1191 
1192  /* 1 match */
1193  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1194  /* 1 match */
1195  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1196  /* 1 match */
1197  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1198  PmqSetup(&pmq);
1199 
1200  SCACPreparePatterns(&mpm_ctx);
1201 
1202  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1203  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1204  (uint8_t *)buf, strlen(buf));
1205 
1206  if (cnt == 3)
1207  result = 1;
1208  else
1209  printf("3 != %" PRIu32 " ",cnt);
1210 
1211  SCACDestroyCtx(&mpm_ctx);
1212  PmqFree(&pmq);
1213  return result;
1214 }
1215 
1216 static int SCACTest04(void)
1217 {
1218  int result = 0;
1219  MpmCtx mpm_ctx;
1220  MpmThreadCtx mpm_thread_ctx;
1221  PrefilterRuleStore pmq;
1222 
1223  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1224  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1225  MpmInitCtx(&mpm_ctx, MPM_AC);
1226 
1227  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1228  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1229  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1230  PmqSetup(&pmq);
1231 
1232  SCACPreparePatterns(&mpm_ctx);
1233 
1234  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1235  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1236  (uint8_t *)buf, strlen(buf));
1237 
1238  if (cnt == 1)
1239  result = 1;
1240  else
1241  printf("1 != %" PRIu32 " ",cnt);
1242 
1243  SCACDestroyCtx(&mpm_ctx);
1244  PmqFree(&pmq);
1245  return result;
1246 }
1247 
1248 static int SCACTest05(void)
1249 {
1250  int result = 0;
1251  MpmCtx mpm_ctx;
1252  MpmThreadCtx mpm_thread_ctx;
1253  PrefilterRuleStore pmq;
1254 
1255  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1256  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1257  MpmInitCtx(&mpm_ctx, MPM_AC);
1258 
1259  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1260  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1261  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1262  PmqSetup(&pmq);
1263 
1264  SCACPreparePatterns(&mpm_ctx);
1265 
1266  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1267  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1268  (uint8_t *)buf, strlen(buf));
1269 
1270  if (cnt == 3)
1271  result = 1;
1272  else
1273  printf("3 != %" PRIu32 " ",cnt);
1274 
1275  SCACDestroyCtx(&mpm_ctx);
1276  PmqFree(&pmq);
1277  return result;
1278 }
1279 
1280 static int SCACTest06(void)
1281 {
1282  int result = 0;
1283  MpmCtx mpm_ctx;
1284  MpmThreadCtx mpm_thread_ctx;
1285  PrefilterRuleStore pmq;
1286 
1287  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1288  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1289  MpmInitCtx(&mpm_ctx, MPM_AC);
1290 
1291  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1292  PmqSetup(&pmq);
1293 
1294  SCACPreparePatterns(&mpm_ctx);
1295 
1296  const char *buf = "abcd";
1297  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1298  (uint8_t *)buf, strlen(buf));
1299 
1300  if (cnt == 1)
1301  result = 1;
1302  else
1303  printf("1 != %" PRIu32 " ",cnt);
1304 
1305  SCACDestroyCtx(&mpm_ctx);
1306  PmqFree(&pmq);
1307  return result;
1308 }
1309 
1310 static int SCACTest07(void)
1311 {
1312  MpmCtx mpm_ctx;
1313  MpmThreadCtx mpm_thread_ctx;
1314  PrefilterRuleStore pmq;
1315 
1316  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1317  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1318  MpmInitCtx(&mpm_ctx, MPM_AC);
1319 
1320  /* should match 30 times */
1321  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1322  /* should match 29 times */
1323  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1324  /* should match 28 times */
1325  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1326  /* 26 */
1327  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1328  /* 21 */
1329  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1330  /* 1 */
1331  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
1332  30, 0, 0, 5, 0, 0);
1333  PmqSetup(&pmq);
1334  /* total matches: 135: unique matches: 6 */
1335 
1336  SCACPreparePatterns(&mpm_ctx);
1337 
1338  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1339  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1340  (uint8_t *)buf, strlen(buf));
1341  FAIL_IF_NOT(cnt == 6);
1342 
1343  SCACDestroyCtx(&mpm_ctx);
1344  PmqFree(&pmq);
1345  PASS;
1346 }
1347 
1348 static int SCACTest08(void)
1349 {
1350  int result = 0;
1351  MpmCtx mpm_ctx;
1352  MpmThreadCtx mpm_thread_ctx;
1353  PrefilterRuleStore pmq;
1354 
1355  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1356  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1357  MpmInitCtx(&mpm_ctx, MPM_AC);
1358 
1359  /* 1 match */
1360  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1361  PmqSetup(&pmq);
1362 
1363  SCACPreparePatterns(&mpm_ctx);
1364 
1365  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1366  (uint8_t *)"a", 1);
1367 
1368  if (cnt == 0)
1369  result = 1;
1370  else
1371  printf("0 != %" PRIu32 " ",cnt);
1372 
1373  SCACDestroyCtx(&mpm_ctx);
1374  PmqFree(&pmq);
1375  return result;
1376 }
1377 
1378 static int SCACTest09(void)
1379 {
1380  int result = 0;
1381  MpmCtx mpm_ctx;
1382  MpmThreadCtx mpm_thread_ctx;
1383  PrefilterRuleStore pmq;
1384 
1385  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1386  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1387  MpmInitCtx(&mpm_ctx, MPM_AC);
1388 
1389  /* 1 match */
1390  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1391  PmqSetup(&pmq);
1392 
1393  SCACPreparePatterns(&mpm_ctx);
1394 
1395  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1396  (uint8_t *)"ab", 2);
1397 
1398  if (cnt == 1)
1399  result = 1;
1400  else
1401  printf("1 != %" PRIu32 " ",cnt);
1402 
1403  SCACDestroyCtx(&mpm_ctx);
1404  PmqFree(&pmq);
1405  return result;
1406 }
1407 
1408 static int SCACTest10(void)
1409 {
1410  int result = 0;
1411  MpmCtx mpm_ctx;
1412  MpmThreadCtx mpm_thread_ctx;
1413  PrefilterRuleStore pmq;
1414 
1415  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1416  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1417  MpmInitCtx(&mpm_ctx, MPM_AC);
1418 
1419  /* 1 match */
1420  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1421  PmqSetup(&pmq);
1422 
1423  SCACPreparePatterns(&mpm_ctx);
1424 
1425  const char *buf = "01234567890123456789012345678901234567890123456789"
1426  "01234567890123456789012345678901234567890123456789"
1427  "abcdefgh"
1428  "01234567890123456789012345678901234567890123456789"
1429  "01234567890123456789012345678901234567890123456789";
1430  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1431  (uint8_t *)buf, strlen(buf));
1432 
1433  if (cnt == 1)
1434  result = 1;
1435  else
1436  printf("1 != %" PRIu32 " ",cnt);
1437 
1438  SCACDestroyCtx(&mpm_ctx);
1439  PmqFree(&pmq);
1440  return result;
1441 }
1442 
1443 static int SCACTest11(void)
1444 {
1445  int result = 0;
1446  MpmCtx mpm_ctx;
1447  MpmThreadCtx mpm_thread_ctx;
1448  PrefilterRuleStore pmq;
1449 
1450  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1451  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1452  MpmInitCtx(&mpm_ctx, MPM_AC);
1453 
1454  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1455  goto end;
1456  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1457  goto end;
1458  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1459  goto end;
1460  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1461  goto end;
1462  PmqSetup(&pmq);
1463 
1464  if (SCACPreparePatterns(&mpm_ctx) == -1)
1465  goto end;
1466 
1467  result = 1;
1468 
1469  const char *buf = "he";
1470  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1471  strlen(buf)) == 1);
1472  buf = "she";
1473  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1474  strlen(buf)) == 2);
1475  buf = "his";
1476  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1477  strlen(buf)) == 1);
1478  buf = "hers";
1479  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1480  strlen(buf)) == 2);
1481 
1482  end:
1483  SCACDestroyCtx(&mpm_ctx);
1484  PmqFree(&pmq);
1485  return result;
1486 }
1487 
1488 static int SCACTest12(void)
1489 {
1490  int result = 0;
1491  MpmCtx mpm_ctx;
1492  MpmThreadCtx mpm_thread_ctx;
1493  PrefilterRuleStore pmq;
1494 
1495  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1496  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1497  MpmInitCtx(&mpm_ctx, MPM_AC);
1498 
1499  /* 1 match */
1500  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1501  /* 1 match */
1502  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1503  PmqSetup(&pmq);
1504 
1505  SCACPreparePatterns(&mpm_ctx);
1506 
1507  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1508  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1509  (uint8_t *)buf, strlen(buf));
1510 
1511  if (cnt == 2)
1512  result = 1;
1513  else
1514  printf("2 != %" PRIu32 " ",cnt);
1515 
1516  SCACDestroyCtx(&mpm_ctx);
1517  PmqFree(&pmq);
1518  return result;
1519 }
1520 
1521 static int SCACTest13(void)
1522 {
1523  int result = 0;
1524  MpmCtx mpm_ctx;
1525  MpmThreadCtx mpm_thread_ctx;
1526  PrefilterRuleStore pmq;
1527 
1528  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1529  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1530  MpmInitCtx(&mpm_ctx, MPM_AC);
1531 
1532  /* 1 match */
1533  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1534  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1535  PmqSetup(&pmq);
1536 
1537  SCACPreparePatterns(&mpm_ctx);
1538 
1539  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1540  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1541  (uint8_t *)buf, strlen(buf));
1542 
1543  if (cnt == 1)
1544  result = 1;
1545  else
1546  printf("1 != %" PRIu32 " ",cnt);
1547 
1548  SCACDestroyCtx(&mpm_ctx);
1549  PmqFree(&pmq);
1550  return result;
1551 }
1552 
1553 static int SCACTest14(void)
1554 {
1555  int result = 0;
1556  MpmCtx mpm_ctx;
1557  MpmThreadCtx mpm_thread_ctx;
1558  PrefilterRuleStore pmq;
1559 
1560  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1561  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1562  MpmInitCtx(&mpm_ctx, MPM_AC);
1563 
1564  /* 1 match */
1565  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1566  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1567  PmqSetup(&pmq);
1568 
1569  SCACPreparePatterns(&mpm_ctx);
1570 
1571  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1572  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1573  (uint8_t *)buf, strlen(buf));
1574 
1575  if (cnt == 1)
1576  result = 1;
1577  else
1578  printf("1 != %" PRIu32 " ",cnt);
1579 
1580  SCACDestroyCtx(&mpm_ctx);
1581  PmqFree(&pmq);
1582  return result;
1583 }
1584 
1585 static int SCACTest15(void)
1586 {
1587  int result = 0;
1588  MpmCtx mpm_ctx;
1589  MpmThreadCtx mpm_thread_ctx;
1590  PrefilterRuleStore pmq;
1591 
1592  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1593  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1594  MpmInitCtx(&mpm_ctx, MPM_AC);
1595 
1596  /* 1 match */
1597  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1598  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1599  PmqSetup(&pmq);
1600 
1601  SCACPreparePatterns(&mpm_ctx);
1602 
1603  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1604  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1605  (uint8_t *)buf, strlen(buf));
1606 
1607  if (cnt == 1)
1608  result = 1;
1609  else
1610  printf("1 != %" PRIu32 " ",cnt);
1611 
1612  SCACDestroyCtx(&mpm_ctx);
1613  PmqFree(&pmq);
1614  return result;
1615 }
1616 
1617 static int SCACTest16(void)
1618 {
1619  int result = 0;
1620  MpmCtx mpm_ctx;
1621  MpmThreadCtx mpm_thread_ctx;
1622  PrefilterRuleStore pmq;
1623 
1624  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1625  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1626  MpmInitCtx(&mpm_ctx, MPM_AC);
1627 
1628  /* 1 match */
1629  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1630  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1631  PmqSetup(&pmq);
1632 
1633  SCACPreparePatterns(&mpm_ctx);
1634 
1635  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1636  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1637  (uint8_t *)buf, strlen(buf));
1638 
1639  if (cnt == 1)
1640  result = 1;
1641  else
1642  printf("1 != %" PRIu32 " ",cnt);
1643 
1644  SCACDestroyCtx(&mpm_ctx);
1645  PmqFree(&pmq);
1646  return result;
1647 }
1648 
1649 static int SCACTest17(void)
1650 {
1651  int result = 0;
1652  MpmCtx mpm_ctx;
1653  MpmThreadCtx mpm_thread_ctx;
1654  PrefilterRuleStore pmq;
1655 
1656  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1657  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1658  MpmInitCtx(&mpm_ctx, MPM_AC);
1659 
1660  /* 1 match */
1661  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1662  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1663  PmqSetup(&pmq);
1664 
1665  SCACPreparePatterns(&mpm_ctx);
1666 
1667  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1668  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1669  (uint8_t *)buf, strlen(buf));
1670 
1671  if (cnt == 1)
1672  result = 1;
1673  else
1674  printf("1 != %" PRIu32 " ",cnt);
1675 
1676  SCACDestroyCtx(&mpm_ctx);
1677  PmqFree(&pmq);
1678  return result;
1679 }
1680 
1681 static int SCACTest18(void)
1682 {
1683  int result = 0;
1684  MpmCtx mpm_ctx;
1685  MpmThreadCtx mpm_thread_ctx;
1686  PrefilterRuleStore pmq;
1687 
1688  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1689  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1690  MpmInitCtx(&mpm_ctx, MPM_AC);
1691 
1692  /* 1 match */
1693  const char pat[] = "abcde"
1694  "fghij"
1695  "klmno"
1696  "pqrst"
1697  "uvwxy"
1698  "z";
1699  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1700  PmqSetup(&pmq);
1701 
1702  SCACPreparePatterns(&mpm_ctx);
1703 
1704  const char *buf = "abcde""fghij""klmno""pqrst""uvwxy""z";
1705  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1706  (uint8_t *)buf, strlen(buf));
1707 
1708  if (cnt == 1)
1709  result = 1;
1710  else
1711  printf("1 != %" PRIu32 " ",cnt);
1712 
1713  SCACDestroyCtx(&mpm_ctx);
1714  PmqFree(&pmq);
1715  return result;
1716 }
1717 
1718 static int SCACTest19(void)
1719 {
1720  int result = 0;
1721  MpmCtx mpm_ctx;
1722  MpmThreadCtx mpm_thread_ctx;
1723  PrefilterRuleStore pmq;
1724 
1725  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1726  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1727  MpmInitCtx(&mpm_ctx, MPM_AC);
1728 
1729  /* 1 */
1730  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1731  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1732  PmqSetup(&pmq);
1733 
1734  SCACPreparePatterns(&mpm_ctx);
1735 
1736  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1737  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1738  (uint8_t *)buf, strlen(buf));
1739 
1740  if (cnt == 1)
1741  result = 1;
1742  else
1743  printf("1 != %" PRIu32 " ",cnt);
1744 
1745  SCACDestroyCtx(&mpm_ctx);
1746  PmqFree(&pmq);
1747  return result;
1748 }
1749 
1750 static int SCACTest20(void)
1751 {
1752  int result = 0;
1753  MpmCtx mpm_ctx;
1754  MpmThreadCtx mpm_thread_ctx;
1755  PrefilterRuleStore pmq;
1756 
1757  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1758  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1759  MpmInitCtx(&mpm_ctx, MPM_AC);
1760 
1761  /* 1 */
1762  const char pat[] = "AAAAA"
1763  "AAAAA"
1764  "AAAAA"
1765  "AAAAA"
1766  "AAAAA"
1767  "AAAAA"
1768  "AA";
1769  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1770  PmqSetup(&pmq);
1771 
1772  SCACPreparePatterns(&mpm_ctx);
1773 
1774  const char *buf = "AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA";
1775  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1776  (uint8_t *)buf, strlen(buf));
1777 
1778  if (cnt == 1)
1779  result = 1;
1780  else
1781  printf("1 != %" PRIu32 " ",cnt);
1782 
1783  SCACDestroyCtx(&mpm_ctx);
1784  PmqFree(&pmq);
1785  return result;
1786 }
1787 
1788 static int SCACTest21(void)
1789 {
1790  int result = 0;
1791  MpmCtx mpm_ctx;
1792  MpmThreadCtx mpm_thread_ctx;
1793  PrefilterRuleStore pmq;
1794 
1795  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1796  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1797  MpmInitCtx(&mpm_ctx, MPM_AC);
1798 
1799  /* 1 */
1800  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1801  PmqSetup(&pmq);
1802 
1803  SCACPreparePatterns(&mpm_ctx);
1804 
1805  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1806  (uint8_t *)"AA", 2);
1807 
1808  if (cnt == 1)
1809  result = 1;
1810  else
1811  printf("1 != %" PRIu32 " ",cnt);
1812 
1813  SCACDestroyCtx(&mpm_ctx);
1814  PmqFree(&pmq);
1815  return result;
1816 }
1817 
1818 static int SCACTest22(void)
1819 {
1820  int result = 0;
1821  MpmCtx mpm_ctx;
1822  MpmThreadCtx mpm_thread_ctx;
1823  PrefilterRuleStore pmq;
1824 
1825  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1826  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1827  MpmInitCtx(&mpm_ctx, MPM_AC);
1828 
1829  /* 1 match */
1830  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1831  /* 1 match */
1832  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
1833  PmqSetup(&pmq);
1834 
1835  SCACPreparePatterns(&mpm_ctx);
1836 
1837  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1838  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1839  (uint8_t *)buf, strlen(buf));
1840 
1841  if (cnt == 2)
1842  result = 1;
1843  else
1844  printf("2 != %" PRIu32 " ",cnt);
1845 
1846  SCACDestroyCtx(&mpm_ctx);
1847  PmqFree(&pmq);
1848  return result;
1849 }
1850 
1851 static int SCACTest23(void)
1852 {
1853  int result = 0;
1854  MpmCtx mpm_ctx;
1855  MpmThreadCtx mpm_thread_ctx;
1856  PrefilterRuleStore pmq;
1857 
1858  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1859  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1860  MpmInitCtx(&mpm_ctx, MPM_AC);
1861 
1862  /* 1 */
1863  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1864  PmqSetup(&pmq);
1865 
1866  SCACPreparePatterns(&mpm_ctx);
1867 
1868  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1869  (uint8_t *)"aa", 2);
1870 
1871  if (cnt == 0)
1872  result = 1;
1873  else
1874  printf("1 != %" PRIu32 " ",cnt);
1875 
1876  SCACDestroyCtx(&mpm_ctx);
1877  PmqFree(&pmq);
1878  return result;
1879 }
1880 
1881 static int SCACTest24(void)
1882 {
1883  int result = 0;
1884  MpmCtx mpm_ctx;
1885  MpmThreadCtx mpm_thread_ctx;
1886  PrefilterRuleStore pmq;
1887 
1888  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1889  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1890  MpmInitCtx(&mpm_ctx, MPM_AC);
1891 
1892  /* 1 */
1893  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1894  PmqSetup(&pmq);
1895 
1896  SCACPreparePatterns(&mpm_ctx);
1897 
1898  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1899  (uint8_t *)"aa", 2);
1900 
1901  if (cnt == 1)
1902  result = 1;
1903  else
1904  printf("1 != %" PRIu32 " ",cnt);
1905 
1906  SCACDestroyCtx(&mpm_ctx);
1907  PmqFree(&pmq);
1908  return result;
1909 }
1910 
1911 static int SCACTest25(void)
1912 {
1913  int result = 0;
1914  MpmCtx mpm_ctx;
1915  MpmThreadCtx mpm_thread_ctx;
1916  PrefilterRuleStore pmq;
1917 
1918  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1919  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1920  MpmInitCtx(&mpm_ctx, MPM_AC);
1921 
1922  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1923  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1924  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
1925  PmqSetup(&pmq);
1926 
1927  SCACPreparePatterns(&mpm_ctx);
1928 
1929  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1930  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1931  (uint8_t *)buf, strlen(buf));
1932 
1933  if (cnt == 3)
1934  result = 1;
1935  else
1936  printf("3 != %" PRIu32 " ",cnt);
1937 
1938  SCACDestroyCtx(&mpm_ctx);
1939  PmqFree(&pmq);
1940  return result;
1941 }
1942 
1943 static int SCACTest26(void)
1944 {
1945  int result = 0;
1946  MpmCtx mpm_ctx;
1947  MpmThreadCtx mpm_thread_ctx;
1948  PrefilterRuleStore pmq;
1949 
1950  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1951  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1952  MpmInitCtx(&mpm_ctx, MPM_AC);
1953 
1954  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
1955  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
1956  PmqSetup(&pmq);
1957 
1958  SCACPreparePatterns(&mpm_ctx);
1959 
1960  const char *buf = "works";
1961  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1962  (uint8_t *)buf, strlen(buf));
1963 
1964  if (cnt == 1)
1965  result = 1;
1966  else
1967  printf("3 != %" PRIu32 " ",cnt);
1968 
1969  SCACDestroyCtx(&mpm_ctx);
1970  PmqFree(&pmq);
1971  return result;
1972 }
1973 
1974 static int SCACTest27(void)
1975 {
1976  int result = 0;
1977  MpmCtx mpm_ctx;
1978  MpmThreadCtx mpm_thread_ctx;
1979  PrefilterRuleStore pmq;
1980 
1981  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1982  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1983  MpmInitCtx(&mpm_ctx, MPM_AC);
1984 
1985  /* 0 match */
1986  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
1987  PmqSetup(&pmq);
1988 
1989  SCACPreparePatterns(&mpm_ctx);
1990 
1991  const char *buf = "tone";
1992  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1993  (uint8_t *)buf, strlen(buf));
1994 
1995  if (cnt == 0)
1996  result = 1;
1997  else
1998  printf("0 != %" PRIu32 " ",cnt);
1999 
2000  SCACDestroyCtx(&mpm_ctx);
2001  PmqFree(&pmq);
2002  return result;
2003 }
2004 
2005 static int SCACTest28(void)
2006 {
2007  MpmCtx mpm_ctx;
2008  MpmThreadCtx mpm_thread_ctx;
2009  PrefilterRuleStore pmq;
2010 
2011  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2012  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2013  MpmInitCtx(&mpm_ctx, MPM_AC);
2014 
2015  /* 0 match */
2016  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2017  PmqSetup(&pmq);
2018 
2019  SCACPreparePatterns(&mpm_ctx);
2020 
2021  const char *buf = "tONE";
2022  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2023  (uint8_t *)buf, strlen(buf));
2024  FAIL_IF_NOT(cnt == 0);
2025 
2026  SCACDestroyCtx(&mpm_ctx);
2027  PmqFree(&pmq);
2028  PASS;
2029 }
2030 
2031 static int SCACTest29(void)
2032 {
2033  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
2034  uint16_t buflen = sizeof(buf) - 1;
2035  ThreadVars th_v;
2036  DetectEngineThreadCtx *det_ctx = NULL;
2037 
2038  memset(&th_v, 0, sizeof(th_v));
2039  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2040  FAIL_IF_NULL(p);
2041 
2044  de_ctx->flags |= DE_QUIET;
2045 
2047  "alert tcp any any -> any any "
2048  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2049  FAIL_IF_NULL(s);
2051  "alert tcp any any -> any any "
2052  "(content:\"onetwothreefourfivesixseveneightnine\"; fast_pattern:3,3; sid:2;)");
2053  FAIL_IF_NULL(s);
2054 
2056  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2057 
2058  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2059 
2060  FAIL_IF(PacketAlertCheck(p, 1) != 1);
2061  FAIL_IF(PacketAlertCheck(p, 2) != 1);
2062 
2063  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2065  StatsThreadCleanup(&th_v);
2066 
2067  UTHFreePackets(&p, 1);
2068  PASS;
2069 }
2070 
2071 /** \test endswith logic */
2072 static int SCACTest30(void)
2073 {
2074  MpmCtx mpm_ctx;
2075  MpmThreadCtx mpm_thread_ctx;
2076  PrefilterRuleStore pmq;
2077 
2078  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2079  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2080  MpmInitCtx(&mpm_ctx, MPM_AC);
2081 
2082  /* 0 match */
2083  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"xyz", 3, 0, 0, 0, 0, MPM_PATTERN_FLAG_ENDSWITH);
2084  PmqSetup(&pmq);
2085 
2086  SCACPreparePatterns(&mpm_ctx);
2087 
2088  const char *buf1 = "abcdefghijklmnopqrstuvwxyz";
2089  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf1, strlen(buf1));
2090  FAIL_IF_NOT(cnt == 1);
2091  const char *buf2 = "xyzxyzxyzxyzxyzxyzxyza";
2092  cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf2, strlen(buf2));
2093  FAIL_IF_NOT(cnt == 0);
2094 
2095  SCACDestroyCtx(&mpm_ctx);
2096  PmqFree(&pmq);
2097  PASS;
2098 }
2099 
2100 void SCACRegisterTests(void)
2101 {
2102  UtRegisterTest("SCACTest01", SCACTest01);
2103  UtRegisterTest("SCACTest02", SCACTest02);
2104  UtRegisterTest("SCACTest03", SCACTest03);
2105  UtRegisterTest("SCACTest04", SCACTest04);
2106  UtRegisterTest("SCACTest05", SCACTest05);
2107  UtRegisterTest("SCACTest06", SCACTest06);
2108  UtRegisterTest("SCACTest07", SCACTest07);
2109  UtRegisterTest("SCACTest08", SCACTest08);
2110  UtRegisterTest("SCACTest09", SCACTest09);
2111  UtRegisterTest("SCACTest10", SCACTest10);
2112  UtRegisterTest("SCACTest11", SCACTest11);
2113  UtRegisterTest("SCACTest12", SCACTest12);
2114  UtRegisterTest("SCACTest13", SCACTest13);
2115  UtRegisterTest("SCACTest14", SCACTest14);
2116  UtRegisterTest("SCACTest15", SCACTest15);
2117  UtRegisterTest("SCACTest16", SCACTest16);
2118  UtRegisterTest("SCACTest17", SCACTest17);
2119  UtRegisterTest("SCACTest18", SCACTest18);
2120  UtRegisterTest("SCACTest19", SCACTest19);
2121  UtRegisterTest("SCACTest20", SCACTest20);
2122  UtRegisterTest("SCACTest21", SCACTest21);
2123  UtRegisterTest("SCACTest22", SCACTest22);
2124  UtRegisterTest("SCACTest23", SCACTest23);
2125  UtRegisterTest("SCACTest24", SCACTest24);
2126  UtRegisterTest("SCACTest25", SCACTest25);
2127  UtRegisterTest("SCACTest26", SCACTest26);
2128  UtRegisterTest("SCACTest27", SCACTest27);
2129  UtRegisterTest("SCACTest28", SCACTest28);
2130  UtRegisterTest("SCACTest29", SCACTest29);
2131  UtRegisterTest("SCACTest30", SCACTest30);
2132 }
2133 #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:798
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:357
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:147
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:1072
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:841
MPM_FEATURE_FLAG_OFFSET
#define MPM_FEATURE_FLAG_OFFSET
Definition: util-mpm.h:143
util-memcpy.h
MpmCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:103
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:2611
MpmTableElmt_::AddPatternNocase
int(* AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:165
MPM_AC
@ MPM_AC
Definition: util-mpm.h:36
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:436
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:100
MpmTableElmt_::AddPattern
int(* AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:164
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:174
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1938
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2587
STATE_QUEUE_CONTAINER_SIZE
#define STATE_QUEUE_CONTAINER_SIZE
Definition: util-mpm-ac.c:82
MpmTableElmt_::InitCtx
void(* InitCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:148
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:210
MpmTableElmt_::PrintCtx
void(* PrintCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:169
MpmCtx_::max_pat_id
uint32_t max_pat_id
Definition: util-mpm.h:105
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:17
DetectEngineThreadCtx_
Definition: detect.h:1093
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:3347
MPM_FEATURE_FLAG_DEPTH
#define MPM_FEATURE_FLAG_DEPTH
Definition: util-mpm.h:142
SCACPatternList_::cs
uint8_t * cs
Definition: util-mpm-ac.h:34
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:99
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:912
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:1065
SCReturn
#define SCReturn
Definition: util-debug.h:273
Packet_
Definition: decode.h:473
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_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:166
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:168
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:250
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:2144
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:132
SCACCtx_
Definition: util-mpm-ac.h:54
SCACDestroyCtx
void SCACDestroyCtx(MpmCtx *)
Destroy the mpm context.
Definition: util-mpm-ac.c:829
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:97
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3574
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:140
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:150
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:1097
detect-parse.h
Signature_
Signature container.
Definition: detect.h:601
MpmCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:102
SCACOutputTable_
Definition: util-mpm-ac.h:47
MpmCtx_::init_hash
MpmPattern ** init_hash
Definition: util-mpm.h:108
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2572
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
suricata.h
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
SCACPreparePatterns
int SCACPreparePatterns(MpmCtx *mpm_ctx)
Process the patterns added to the mpm, and create the internal tables.
Definition: util-mpm-ac.c:705
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:439
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:843
AC_CASE_MASK
#define AC_CASE_MASK
Definition: util-mpm-ac.c:84
MpmCtx_
Definition: util-mpm.h:88
SigIntId
#define SigIntId
Definition: suricata-common.h:315
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
MpmCtx_::ctx
void * ctx
Definition: util-mpm.h:89
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:259
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:172
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:1040
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