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