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