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