suricata
util-mpm-ac.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * First iteration of aho-corasick MPM from -
24  *
25  * Efficient String Matching: An Aid to Bibliographic Search
26  * Alfred V. Aho and Margaret J. Corasick
27  *
28  * - Uses the delta table for calculating transitions, instead of having
29  * separate goto and failure transitions.
30  * - If we cross 2 ** 16 states, we use 4 bytes in the transition table
31  * to hold each state, otherwise we use 2 bytes.
32  * - This version of the MPM is heavy on memory, but it performs well.
33  * If you can fit the ruleset with this mpm on your box without hitting
34  * swap, this is the MPM to go for.
35  *
36  * \todo - Do a proper analysis of our existing MPMs and suggest a good one based
37  * on the pattern distribution and the expected traffic(say http).
38  * - Tried out loop unrolling without any perf increase. Need to dig deeper.
39  * - Irrespective of whether we cross 2 ** 16 states or not,shift to using
40  * uint32_t for state type, so that we can integrate it's status as a
41  * final state or not in the topmost byte. We are already doing it if
42  * state_count is > 2 ** 16.
43  * - Test case-sensitive patterns if they have any ascii chars. If they
44  * don't treat them as nocase.
45  * - Carry out other optimizations we are working on. hashes, compression.
46  */
47 
48 #include "suricata-common.h"
49 #include "suricata.h"
50 
51 #include "detect.h"
52 #include "detect-parse.h"
53 #include "detect-engine.h"
54 #include "detect-engine-build.h"
55 
56 #include "conf.h"
57 #include "util-debug.h"
58 #include "util-unittest.h"
59 #include "util-unittest-helper.h"
60 #include "util-memcmp.h"
61 #include "util-mpm-ac.h"
62 #include "util-memcpy.h"
63 #include "util-validate.h"
64 
65 void SCACInitCtx(MpmCtx *);
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("%" PRIuMAX " * %" PRIuMAX " > %" PRIuMAX
131  " 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("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("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("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("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  uint8_t 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  FatalError("Just ran out of space in the queue. Please file a bug report on this");
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  FatalError("StateQueue behaving weirdly. Please file a bug report on this");
411  }
412 
413  return q->store[q->bot++];
414 }
415 
416 /**
417  * \internal
418  * \brief Club the output data from 2 states and store it in the 1st state.
419  * dst_state_data = {dst_state_data} UNION {src_state_data}
420  *
421  * \param dst_state First state(also the destination) for the union operation.
422  * \param src_state Second state for the union operation.
423  * \param mpm_ctx Pointer to the mpm context.
424  */
425 static inline void SCACClubOutputStates(int32_t dst_state, int32_t src_state,
426  MpmCtx *mpm_ctx)
427 {
428  void *ptmp;
429  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
430  uint32_t i = 0;
431  uint32_t j = 0;
432 
433  SCACOutputTable *output_dst_state = &ctx->output_table[dst_state];
434  SCACOutputTable *output_src_state = &ctx->output_table[src_state];
435 
436  for (i = 0; i < output_src_state->no_of_entries; i++) {
437  for (j = 0; j < output_dst_state->no_of_entries; j++) {
438  if (output_src_state->pids[i] == output_dst_state->pids[j]) {
439  break;
440  }
441  }
442  if (j == output_dst_state->no_of_entries) {
443  output_dst_state->no_of_entries++;
444 
445  ptmp = SCRealloc(output_dst_state->pids,
446  (output_dst_state->no_of_entries * sizeof(uint32_t)));
447  if (ptmp == NULL) {
448  SCFree(output_dst_state->pids);
449  output_dst_state->pids = NULL;
450  FatalError("Error allocating memory");
451  }
452  output_dst_state->pids = ptmp;
453 
454  output_dst_state->pids[output_dst_state->no_of_entries - 1] =
455  output_src_state->pids[i];
456  }
457  }
458 
459  return;
460 }
461 
462 /**
463  * \internal
464  * \brief Create the failure table.
465  *
466  * \param mpm_ctx Pointer to the mpm context.
467  */
468 static inline void SCACCreateFailureTable(MpmCtx *mpm_ctx)
469 {
470  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
471  int ascii_code = 0;
472  int32_t state = 0;
473  int32_t r_state = 0;
474 
475  StateQueue *q = SCCalloc(1, sizeof(StateQueue));
476  if (q == NULL) {
477  FatalError("Error allocating memory");
478  }
479 
480  /* allot space for the failure table. A failure entry in the table for
481  * every state(SCACCtx->state_count) */
482  ctx->failure_table = SCMalloc(ctx->state_count * sizeof(int32_t));
483  if (ctx->failure_table == NULL) {
484  FatalError("Error allocating memory");
485  }
486  memset(ctx->failure_table, 0, ctx->state_count * sizeof(int32_t));
487 
488  /* add the failure transitions for the 0th state, and add every non-fail
489  * transition from the 0th state to the queue for further processing
490  * of failure states */
491  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
492  int32_t temp_state = ctx->goto_table[0][ascii_code];
493  if (temp_state != 0) {
494  SCACEnqueue(q, temp_state);
495  ctx->failure_table[temp_state] = 0;
496  }
497  }
498 
499  while (!SCACStateQueueIsEmpty(q)) {
500  /* pick up every state from the queue and add failure transitions */
501  r_state = SCACDequeue(q);
502  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
503  int32_t temp_state = ctx->goto_table[r_state][ascii_code];
504  if (temp_state == SC_AC_FAIL)
505  continue;
506  SCACEnqueue(q, temp_state);
507  state = ctx->failure_table[r_state];
508 
509  while(ctx->goto_table[state][ascii_code] == SC_AC_FAIL)
510  state = ctx->failure_table[state];
511  ctx->failure_table[temp_state] = ctx->goto_table[state][ascii_code];
512  SCACClubOutputStates(temp_state, ctx->failure_table[temp_state],
513  mpm_ctx);
514  }
515  }
516  SCFree(q);
517 
518  return;
519 }
520 
521 /**
522  * \internal
523  * \brief Create the delta table.
524  *
525  * \param mpm_ctx Pointer to the mpm context.
526  */
527 static inline void SCACCreateDeltaTable(MpmCtx *mpm_ctx)
528 {
529  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
530  int ascii_code = 0;
531  int32_t r_state = 0;
532 
533  if ((ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
534  ctx->state_table_u16 = SCCalloc(ctx->state_count, sizeof(*ctx->state_table_u16));
535  if (ctx->state_table_u16 == NULL) {
536  FatalError("Error allocating memory");
537  }
538  mpm_ctx->memory_cnt++;
539  mpm_ctx->memory_size += (ctx->state_count * sizeof(*ctx->state_table_u16));
540 
541  StateQueue *q = SCCalloc(1, sizeof(StateQueue));
542  if (q == NULL) {
543  FatalError("Error allocating memory");
544  }
545 
546  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
547  DEBUG_VALIDATE_BUG_ON(ctx->goto_table[0][ascii_code] > UINT16_MAX);
548  SC_AC_STATE_TYPE_U16 temp_state = (uint16_t)ctx->goto_table[0][ascii_code];
549  ctx->state_table_u16[0][ascii_code] = temp_state;
550  if (temp_state != 0)
551  SCACEnqueue(q, temp_state);
552  }
553 
554  while (!SCACStateQueueIsEmpty(q)) {
555  r_state = SCACDequeue(q);
556 
557  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
558  int32_t temp_state = ctx->goto_table[r_state][ascii_code];
559  if (temp_state != SC_AC_FAIL) {
560  SCACEnqueue(q, temp_state);
561  DEBUG_VALIDATE_BUG_ON(temp_state > UINT16_MAX);
562  ctx->state_table_u16[r_state][ascii_code] = (uint16_t)temp_state;
563  } else {
564  ctx->state_table_u16[r_state][ascii_code] =
565  ctx->state_table_u16[ctx->failure_table[r_state]][ascii_code];
566  }
567  }
568  }
569  SCFree(q);
570  }
571 
572  if (!(ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
573  /* create space for the state table. We could have used the existing goto
574  * table, but since we have it set to hold 32 bit state values, we will create
575  * a new state table here of type SC_AC_STATE_TYPE(current set to uint16_t) */
576  ctx->state_table_u32 = SCCalloc(ctx->state_count, sizeof(*ctx->state_table_u32));
577  if (ctx->state_table_u32 == NULL) {
578  FatalError("Error allocating memory");
579  }
580  mpm_ctx->memory_cnt++;
581  mpm_ctx->memory_size += (ctx->state_count * sizeof(*ctx->state_table_u32));
582 
583  StateQueue *q = SCCalloc(1, sizeof(StateQueue));
584  if (q == NULL) {
585  FatalError("Error allocating memory");
586  }
587 
588  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
589  SC_AC_STATE_TYPE_U32 temp_state = ctx->goto_table[0][ascii_code];
590  ctx->state_table_u32[0][ascii_code] = temp_state;
591  if (temp_state != 0)
592  SCACEnqueue(q, temp_state);
593  }
594 
595  while (!SCACStateQueueIsEmpty(q)) {
596  r_state = SCACDequeue(q);
597 
598  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
599  int32_t temp_state = ctx->goto_table[r_state][ascii_code];
600  if (temp_state != SC_AC_FAIL) {
601  SCACEnqueue(q, temp_state);
602  ctx->state_table_u32[r_state][ascii_code] = temp_state;
603  } else {
604  ctx->state_table_u32[r_state][ascii_code] =
605  ctx->state_table_u32[ctx->failure_table[r_state]][ascii_code];
606  }
607  }
608  }
609  SCFree(q);
610  }
611 
612  return;
613 }
614 
615 static inline void SCACClubOutputStatePresenceWithDeltaTable(MpmCtx *mpm_ctx)
616 {
617  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
618  int ascii_code = 0;
619  uint32_t state = 0;
620  uint32_t temp_state = 0;
621 
622  if ((ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
623  for (state = 0; state < ctx->state_count; state++) {
624  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
625  temp_state = ctx->state_table_u16[state & 0x7FFF][ascii_code];
626  if (ctx->output_table[temp_state & 0x7FFF].no_of_entries != 0)
627  ctx->state_table_u16[state & 0x7FFF][ascii_code] |= (1 << 15);
628  }
629  }
630  }
631 
632  if (!(ctx->state_count < 32767) || construct_both_16_and_32_state_tables) {
633  for (state = 0; state < ctx->state_count; state++) {
634  for (ascii_code = 0; ascii_code < 256; ascii_code++) {
635  temp_state = ctx->state_table_u32[state & 0x00FFFFFF][ascii_code];
636  if (ctx->output_table[temp_state & 0x00FFFFFF].no_of_entries != 0)
637  ctx->state_table_u32[state & 0x00FFFFFF][ascii_code] |= (1 << 24);
638  }
639  }
640  }
641 
642  return;
643 }
644 
645 static inline void SCACInsertCaseSensitiveEntriesForPatterns(MpmCtx *mpm_ctx)
646 {
647  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
648  uint32_t state = 0;
649  uint32_t k = 0;
650 
651  for (state = 0; state < ctx->state_count; state++) {
652  if (ctx->output_table[state].no_of_entries == 0)
653  continue;
654 
655  for (k = 0; k < ctx->output_table[state].no_of_entries; k++) {
656  if (ctx->pid_pat_list[ctx->output_table[state].pids[k]].cs != NULL) {
657  ctx->output_table[state].pids[k] &= AC_PID_MASK;
658  ctx->output_table[state].pids[k] |= ((uint32_t)1 << AC_CASE_BIT);
659  }
660  }
661  }
662 
663  return;
664 }
665 
666 #if 0
667 static void SCACPrintDeltaTable(MpmCtx *mpm_ctx)
668 {
669  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
670  int i = 0, j = 0;
671 
672  printf("##############Delta Table##############\n");
673  for (i = 0; i < ctx->state_count; i++) {
674  printf("%d: \n", i);
675  for (j = 0; j < 256; j++) {
676  if (SCACGetDelta(i, j, mpm_ctx) != 0) {
677  printf(" %c -> %d\n", j, SCACGetDelta(i, j, mpm_ctx));
678  }
679  }
680  }
681 
682  return;
683 }
684 #endif
685 
686 /**
687  * \brief Process the patterns and prepare the state table.
688  *
689  * \param mpm_ctx Pointer to the mpm context.
690  */
691 static void SCACPrepareStateTable(MpmCtx *mpm_ctx)
692 {
693  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
694 
695  /* create the 0th state in the goto table and output_table */
696  SCACInitNewState(mpm_ctx);
697 
698  SCACDetermineLevel1Gap(mpm_ctx);
699 
700  /* create the goto table */
701  SCACCreateGotoTable(mpm_ctx);
702  /* create the failure table */
703  SCACCreateFailureTable(mpm_ctx);
704  /* create the final state(delta) table */
705  SCACCreateDeltaTable(mpm_ctx);
706  /* club the output state presence with delta transition entries */
707  SCACClubOutputStatePresenceWithDeltaTable(mpm_ctx);
708 
709  /* club nocase entries */
710  SCACInsertCaseSensitiveEntriesForPatterns(mpm_ctx);
711 
712  /* shrink the memory */
713  SCACShrinkState(ctx);
714 
715 #if 0
716  SCACPrintDeltaTable(mpm_ctx);
717 #endif
718 
719  /* we don't need these anymore */
720  SCFree(ctx->goto_table);
721  ctx->goto_table = NULL;
722  SCFree(ctx->failure_table);
723  ctx->failure_table = NULL;
724 
725  return;
726 }
727 
728 /**
729  * \brief Process the patterns added to the mpm, and create the internal tables.
730  *
731  * \param mpm_ctx Pointer to the mpm context.
732  */
734 {
735  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
736 
737  if (mpm_ctx->pattern_cnt == 0 || mpm_ctx->init_hash == NULL) {
738  SCLogDebug("no patterns supplied to this mpm_ctx");
739  return 0;
740  }
741 
742  /* alloc the pattern array */
743  ctx->parray = (MpmPattern **)SCMalloc(mpm_ctx->pattern_cnt *
744  sizeof(MpmPattern *));
745  if (ctx->parray == NULL)
746  goto error;
747  memset(ctx->parray, 0, mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
748  mpm_ctx->memory_cnt++;
749  mpm_ctx->memory_size += (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
750 
751  /* populate it with the patterns in the hash */
752  uint32_t i = 0, p = 0;
753  for (i = 0; i < MPM_INIT_HASH_SIZE; i++) {
754  MpmPattern *node = mpm_ctx->init_hash[i], *nnode = NULL;
755  while(node != NULL) {
756  nnode = node->next;
757  node->next = NULL;
758  ctx->parray[p++] = node;
759  node = nnode;
760  }
761  }
762 
763  /* we no longer need the hash, so free it's memory */
764  SCFree(mpm_ctx->init_hash);
765  mpm_ctx->init_hash = NULL;
766 
767  /* the memory consumed by a single state in our goto table */
768  ctx->single_state_size = sizeof(int32_t) * 256;
769 
770  /* handle no case patterns */
771  ctx->pid_pat_list = SCMalloc((mpm_ctx->max_pat_id + 1)* sizeof(SCACPatternList));
772  if (ctx->pid_pat_list == NULL) {
773  FatalError("Error allocating memory");
774  }
775  memset(ctx->pid_pat_list, 0, (mpm_ctx->max_pat_id + 1) * sizeof(SCACPatternList));
776 
777  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
778  if (!(ctx->parray[i]->flags & MPM_PATTERN_FLAG_NOCASE)) {
779  ctx->pid_pat_list[ctx->parray[i]->id].cs = SCMalloc(ctx->parray[i]->len);
780  if (ctx->pid_pat_list[ctx->parray[i]->id].cs == NULL) {
781  FatalError("Error allocating memory");
782  }
783  memcpy(ctx->pid_pat_list[ctx->parray[i]->id].cs,
784  ctx->parray[i]->original_pat, ctx->parray[i]->len);
785  ctx->pid_pat_list[ctx->parray[i]->id].patlen = ctx->parray[i]->len;
786  }
787  ctx->pid_pat_list[ctx->parray[i]->id].offset = ctx->parray[i]->offset;
788  ctx->pid_pat_list[ctx->parray[i]->id].depth = ctx->parray[i]->depth;
789 
790  /* ACPatternList now owns this memory */
791  //SCLogInfo("ctx->parray[i]->sids_size %u", ctx->parray[i]->sids_size);
792  ctx->pid_pat_list[ctx->parray[i]->id].sids_size = ctx->parray[i]->sids_size;
793  ctx->pid_pat_list[ctx->parray[i]->id].sids = ctx->parray[i]->sids;
794 
795  ctx->parray[i]->sids_size = 0;
796  ctx->parray[i]->sids = NULL;
797  }
798 
799  /* prepare the state table required by AC */
800  SCACPrepareStateTable(mpm_ctx);
801 
802  /* free all the stored patterns. Should save us a good 100-200 mbs */
803  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
804  if (ctx->parray[i] != NULL) {
805  MpmFreePattern(mpm_ctx, ctx->parray[i]);
806  }
807  }
808  SCFree(ctx->parray);
809  ctx->parray = NULL;
810  mpm_ctx->memory_cnt--;
811  mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
812 
813  ctx->pattern_id_bitarray_size = (mpm_ctx->max_pat_id / 8) + 1;
814  SCLogDebug("ctx->pattern_id_bitarray_size %u", ctx->pattern_id_bitarray_size);
815 
816  return 0;
817 
818 error:
819  return -1;
820 }
821 
822 /**
823  * \brief Init the mpm thread context.
824  *
825  * \param mpm_ctx Pointer to the mpm context.
826  * \param mpm_thread_ctx Pointer to the mpm thread context.
827  * \param matchsize We don't need this.
828  */
829 void SCACInitThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx)
830 {
831  memset(mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
832 
833  mpm_thread_ctx->ctx = SCMalloc(sizeof(SCACThreadCtx));
834  if (mpm_thread_ctx->ctx == NULL) {
835  exit(EXIT_FAILURE);
836  }
837  memset(mpm_thread_ctx->ctx, 0, sizeof(SCACThreadCtx));
838  mpm_thread_ctx->memory_cnt++;
839  mpm_thread_ctx->memory_size += sizeof(SCACThreadCtx);
840 
841  return;
842 }
843 
844 /**
845  * \brief Initialize the AC context.
846  *
847  * \param mpm_ctx Mpm context.
848  */
849 void SCACInitCtx(MpmCtx *mpm_ctx)
850 {
851  if (mpm_ctx->ctx != NULL)
852  return;
853 
854  mpm_ctx->ctx = SCMalloc(sizeof(SCACCtx));
855  if (mpm_ctx->ctx == NULL) {
856  exit(EXIT_FAILURE);
857  }
858  memset(mpm_ctx->ctx, 0, sizeof(SCACCtx));
859 
860  mpm_ctx->memory_cnt++;
861  mpm_ctx->memory_size += sizeof(SCACCtx);
862 
863  /* initialize the hash we use to speed up pattern insertions */
864  mpm_ctx->init_hash = SCMalloc(sizeof(MpmPattern *) * MPM_INIT_HASH_SIZE);
865  if (mpm_ctx->init_hash == NULL) {
866  exit(EXIT_FAILURE);
867  }
868  memset(mpm_ctx->init_hash, 0, sizeof(MpmPattern *) * MPM_INIT_HASH_SIZE);
869 
870  /* get conf values for AC from our yaml file. We have no conf values for
871  * now. We will certainly need this, as we develop the algo */
872  SCACGetConfig();
873 
874  SCReturn;
875 }
876 
877 /**
878  * \brief Destroy the mpm thread context.
879  *
880  * \param mpm_ctx Pointer to the mpm context.
881  * \param mpm_thread_ctx Pointer to the mpm thread context.
882  */
883 void SCACDestroyThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx)
884 {
885  SCACPrintSearchStats(mpm_thread_ctx);
886 
887  if (mpm_thread_ctx->ctx != NULL) {
888  SCFree(mpm_thread_ctx->ctx);
889  mpm_thread_ctx->ctx = NULL;
890  mpm_thread_ctx->memory_cnt--;
891  mpm_thread_ctx->memory_size -= sizeof(SCACThreadCtx);
892  }
893 
894  return;
895 }
896 
897 /**
898  * \brief Destroy the mpm context.
899  *
900  * \param mpm_ctx Pointer to the mpm context.
901  */
902 void SCACDestroyCtx(MpmCtx *mpm_ctx)
903 {
904  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
905  if (ctx == NULL)
906  return;
907 
908  if (mpm_ctx->init_hash != NULL) {
909  SCFree(mpm_ctx->init_hash);
910  mpm_ctx->init_hash = NULL;
911  mpm_ctx->memory_cnt--;
912  mpm_ctx->memory_size -= (MPM_INIT_HASH_SIZE * sizeof(MpmPattern *));
913  }
914 
915  if (ctx->parray != NULL) {
916  uint32_t i;
917  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
918  if (ctx->parray[i] != NULL) {
919  MpmFreePattern(mpm_ctx, ctx->parray[i]);
920  }
921  }
922 
923  SCFree(ctx->parray);
924  ctx->parray = NULL;
925  mpm_ctx->memory_cnt--;
926  mpm_ctx->memory_size -= (mpm_ctx->pattern_cnt * sizeof(MpmPattern *));
927  }
928 
929  if (ctx->state_table_u16 != NULL) {
930  SCFree(ctx->state_table_u16);
931  ctx->state_table_u16 = NULL;
932 
933  mpm_ctx->memory_cnt++;
934  mpm_ctx->memory_size -= (ctx->state_count *
935  sizeof(SC_AC_STATE_TYPE_U16) * 256);
936  }
937  if (ctx->state_table_u32 != NULL) {
938  SCFree(ctx->state_table_u32);
939  ctx->state_table_u32 = NULL;
940 
941  mpm_ctx->memory_cnt++;
942  mpm_ctx->memory_size -= (ctx->state_count *
943  sizeof(SC_AC_STATE_TYPE_U32) * 256);
944  }
945 
946  if (ctx->output_table != NULL) {
947  uint32_t state_count;
948  for (state_count = 0; state_count < ctx->state_count; state_count++) {
949  if (ctx->output_table[state_count].pids != NULL) {
950  SCFree(ctx->output_table[state_count].pids);
951  }
952  }
953  SCFree(ctx->output_table);
954  }
955 
956  if (ctx->pid_pat_list != NULL) {
957  uint32_t i;
958  for (i = 0; i < (mpm_ctx->max_pat_id + 1); i++) {
959  if (ctx->pid_pat_list[i].cs != NULL)
960  SCFree(ctx->pid_pat_list[i].cs);
961  if (ctx->pid_pat_list[i].sids != NULL)
962  SCFree(ctx->pid_pat_list[i].sids);
963  }
964  SCFree(ctx->pid_pat_list);
965  }
966 
967  SCFree(mpm_ctx->ctx);
968  mpm_ctx->memory_cnt--;
969  mpm_ctx->memory_size -= sizeof(SCACCtx);
970 
971  return;
972 }
973 
974 /**
975  * \brief The aho corasick search function.
976  *
977  * \param mpm_ctx Pointer to the mpm context.
978  * \param mpm_thread_ctx Pointer to the mpm thread context.
979  * \param pmq Pointer to the Pattern Matcher Queue to hold
980  * search matches.
981  * \param buf Buffer to be searched.
982  * \param buflen Buffer length.
983  *
984  * \retval matches Match count.
985  */
986 uint32_t SCACSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
987  PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
988 {
989  const SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
990  uint32_t i = 0;
991  int matches = 0;
992 
993  /* \todo tried loop unrolling with register var, with no perf increase. Need
994  * to dig deeper */
995  /* \todo Change it for stateful MPM. Supply the state using mpm_thread_ctx */
996  const SCACPatternList *pid_pat_list = ctx->pid_pat_list;
997 
998  uint8_t bitarray[ctx->pattern_id_bitarray_size];
999  memset(bitarray, 0, ctx->pattern_id_bitarray_size);
1000 
1001  if (ctx->state_count < 32767) {
1002  register SC_AC_STATE_TYPE_U16 state = 0;
1003  SC_AC_STATE_TYPE_U16 (*state_table_u16)[256] = ctx->state_table_u16;
1004  for (i = 0; i < buflen; i++) {
1005  state = state_table_u16[state & 0x7FFF][u8_tolower(buf[i])];
1006  if (state & 0x8000) {
1007  uint32_t no_of_entries = ctx->output_table[state & 0x7FFF].no_of_entries;
1008  uint32_t *pids = ctx->output_table[state & 0x7FFF].pids;
1009  uint32_t k;
1010  for (k = 0; k < no_of_entries; k++) {
1011  if (pids[k] & AC_CASE_MASK) {
1012  uint32_t lower_pid = pids[k] & AC_PID_MASK;
1013  const SCACPatternList *pat = &pid_pat_list[lower_pid];
1014  const int offset = i - pat->patlen + 1;
1015 
1016  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
1017  continue;
1018 
1019  if (SCMemcmp(pat->cs, buf + offset, pat->patlen) != 0)
1020  {
1021  /* inside loop */
1022  continue;
1023  }
1024  if (bitarray[(lower_pid) / 8] & (1 << ((lower_pid) % 8))) {
1025  ;
1026  } else {
1027  bitarray[(lower_pid) / 8] |= (1 << ((lower_pid) % 8));
1028  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
1029  }
1030  matches++;
1031  } else {
1032  const SCACPatternList *pat = &pid_pat_list[pids[k]];
1033  const int offset = i - pat->patlen + 1;
1034 
1035  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
1036  continue;
1037 
1038  if (bitarray[pids[k] / 8] & (1 << (pids[k] % 8))) {
1039  ;
1040  } else {
1041  bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
1042  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
1043  }
1044  matches++;
1045  }
1046  //loop1:
1047  //;
1048  }
1049  }
1050  } /* for (i = 0; i < buflen; i++) */
1051 
1052  } else {
1053  register SC_AC_STATE_TYPE_U32 state = 0;
1054  SC_AC_STATE_TYPE_U32 (*state_table_u32)[256] = ctx->state_table_u32;
1055  for (i = 0; i < buflen; i++) {
1056  state = state_table_u32[state & 0x00FFFFFF][u8_tolower(buf[i])];
1057  if (state & 0xFF000000) {
1058  uint32_t no_of_entries = ctx->output_table[state & 0x00FFFFFF].no_of_entries;
1059  uint32_t *pids = ctx->output_table[state & 0x00FFFFFF].pids;
1060  uint32_t k;
1061  for (k = 0; k < no_of_entries; k++) {
1062  if (pids[k] & AC_CASE_MASK) {
1063  uint32_t lower_pid = pids[k] & 0x0000FFFF;
1064  const SCACPatternList *pat = &pid_pat_list[lower_pid];
1065  const int offset = i - pat->patlen + 1;
1066 
1067  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
1068  continue;
1069 
1070  if (SCMemcmp(pat->cs, buf + offset,
1071  pat->patlen) != 0) {
1072  /* inside loop */
1073  continue;
1074  }
1075  if (bitarray[(lower_pid) / 8] & (1 << ((lower_pid) % 8))) {
1076  ;
1077  } else {
1078  bitarray[(lower_pid) / 8] |= (1 << ((lower_pid) % 8));
1079  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
1080  }
1081  matches++;
1082  } else {
1083  const SCACPatternList *pat = &pid_pat_list[pids[k]];
1084  const int offset = i - pat->patlen + 1;
1085 
1086  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
1087  continue;
1088 
1089  if (bitarray[pids[k] / 8] & (1 << (pids[k] % 8))) {
1090  ;
1091  } else {
1092  bitarray[pids[k] / 8] |= (1 << (pids[k] % 8));
1093  PrefilterAddSids(pmq, pat->sids, pat->sids_size);
1094  }
1095  matches++;
1096  }
1097  //loop1:
1098  //;
1099  }
1100  }
1101  } /* for (i = 0; i < buflen; i++) */
1102  }
1103 
1104  return matches;
1105 }
1106 
1107 /**
1108  * \brief Add a case insensitive pattern. Although we have different calls for
1109  * adding case sensitive and insensitive patterns, we make a single call
1110  * for either case. No special treatment for either case.
1111  *
1112  * \param mpm_ctx Pointer to the mpm context.
1113  * \param pat The pattern to add.
1114  * \param patnen The pattern length.
1115  * \param offset Ignored.
1116  * \param depth Ignored.
1117  * \param pid The pattern id.
1118  * \param sid Ignored.
1119  * \param flags Flags associated with this pattern.
1120  *
1121  * \retval 0 On success.
1122  * \retval -1 On failure.
1123  */
1124 int SCACAddPatternCI(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1125  uint16_t offset, uint16_t depth, uint32_t pid,
1126  SigIntId sid, uint8_t flags)
1127 {
1129  return MpmAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1130 }
1131 
1132 /**
1133  * \brief Add a case sensitive pattern. Although we have different calls for
1134  * adding case sensitive and insensitive patterns, we make a single call
1135  * for either case. No special treatment for either case.
1136  *
1137  * \param mpm_ctx Pointer to the mpm context.
1138  * \param pat The pattern to add.
1139  * \param patnen The pattern length.
1140  * \param offset Ignored.
1141  * \param depth Ignored.
1142  * \param pid The pattern id.
1143  * \param sid Ignored.
1144  * \param flags Flags associated with this pattern.
1145  *
1146  * \retval 0 On success.
1147  * \retval -1 On failure.
1148  */
1149 int SCACAddPatternCS(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
1150  uint16_t offset, uint16_t depth, uint32_t pid,
1151  SigIntId sid, uint8_t flags)
1152 {
1153  return MpmAddPattern(mpm_ctx, pat, patlen, offset, depth, pid, sid, flags);
1154 }
1155 
1156 void SCACPrintSearchStats(MpmThreadCtx *mpm_thread_ctx)
1157 {
1158 
1159 #ifdef SC_AC_COUNTERS
1160  SCACThreadCtx *ctx = (SCACThreadCtx *)mpm_thread_ctx->ctx;
1161  printf("AC Thread Search stats (ctx %p)\n", ctx);
1162  printf("Total calls: %" PRIu32 "\n", ctx->total_calls);
1163  printf("Total matches: %" PRIu64 "\n", ctx->total_matches);
1164 #endif /* SC_AC_COUNTERS */
1165 
1166  return;
1167 }
1168 
1169 void SCACPrintInfo(MpmCtx *mpm_ctx)
1170 {
1171  SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx;
1172 
1173  printf("MPM AC Information:\n");
1174  printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
1175  printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
1176  printf(" Sizeof:\n");
1177  printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
1178  printf(" SCACCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCACCtx));
1179  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1180  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1181  printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
1182  printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
1183  printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
1184  printf("Total states in the state table: %" PRIu32 "\n", ctx->state_count);
1185  printf("\n");
1186 
1187  return;
1188 }
1189 
1190 
1191 /************************** Mpm Registration ***************************/
1192 
1193 /**
1194  * \brief Register the aho-corasick mpm.
1195  */
1196 void MpmACRegister(void)
1197 {
1198  mpm_table[MPM_AC].name = "ac";
1210 
1211  return;
1212 }
1213 
1214 /*************************************Unittests********************************/
1215 
1216 #ifdef UNITTESTS
1217 #include "detect-engine-alert.h"
1218 
1219 static int SCACTest01(void)
1220 {
1221  int result = 0;
1222  MpmCtx mpm_ctx;
1223  MpmThreadCtx mpm_thread_ctx;
1224  PrefilterRuleStore pmq;
1225 
1226  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1227  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1228  MpmInitCtx(&mpm_ctx, MPM_AC);
1229  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1230 
1231  /* 1 match */
1232  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1233  PmqSetup(&pmq);
1234 
1235  SCACPreparePatterns(&mpm_ctx);
1236 
1237  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1238 
1239  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1240  (uint8_t *)buf, strlen(buf));
1241 
1242  if (cnt == 1)
1243  result = 1;
1244  else
1245  printf("1 != %" PRIu32 " ",cnt);
1246 
1247  SCACDestroyCtx(&mpm_ctx);
1248  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1249  PmqFree(&pmq);
1250  return result;
1251 }
1252 
1253 static int SCACTest02(void)
1254 {
1255  int result = 0;
1256  MpmCtx mpm_ctx;
1257  MpmThreadCtx mpm_thread_ctx;
1258  PrefilterRuleStore pmq;
1259 
1260  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1261  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1262  MpmInitCtx(&mpm_ctx, MPM_AC);
1263  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1264 
1265  /* 1 match */
1266  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1267  PmqSetup(&pmq);
1268 
1269  SCACPreparePatterns(&mpm_ctx);
1270 
1271  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1272  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1273  (uint8_t *)buf, strlen(buf));
1274 
1275  if (cnt == 0)
1276  result = 1;
1277  else
1278  printf("0 != %" PRIu32 " ",cnt);
1279 
1280  SCACDestroyCtx(&mpm_ctx);
1281  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1282  PmqFree(&pmq);
1283  return result;
1284 }
1285 
1286 static int SCACTest03(void)
1287 {
1288  int result = 0;
1289  MpmCtx mpm_ctx;
1290  MpmThreadCtx mpm_thread_ctx;
1291  PrefilterRuleStore pmq;
1292 
1293  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1294  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1295  MpmInitCtx(&mpm_ctx, MPM_AC);
1296  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1297 
1298  /* 1 match */
1299  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1300  /* 1 match */
1301  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1302  /* 1 match */
1303  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 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 == 3)
1313  result = 1;
1314  else
1315  printf("3 != %" 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 SCACTest04(void)
1324 {
1325  int result = 0;
1326  MpmCtx mpm_ctx;
1327  MpmThreadCtx mpm_thread_ctx;
1328  PrefilterRuleStore pmq;
1329 
1330  memset(&mpm_ctx, 0, 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  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1336  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1337  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1338  PmqSetup(&pmq);
1339 
1340  SCACPreparePatterns(&mpm_ctx);
1341 
1342  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1343  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1344  (uint8_t *)buf, strlen(buf));
1345 
1346  if (cnt == 1)
1347  result = 1;
1348  else
1349  printf("1 != %" PRIu32 " ",cnt);
1350 
1351  SCACDestroyCtx(&mpm_ctx);
1352  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1353  PmqFree(&pmq);
1354  return result;
1355 }
1356 
1357 static int SCACTest05(void)
1358 {
1359  int result = 0;
1360  MpmCtx mpm_ctx;
1361  MpmThreadCtx mpm_thread_ctx;
1362  PrefilterRuleStore pmq;
1363 
1364  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1365  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1366  MpmInitCtx(&mpm_ctx, MPM_AC);
1367  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1368 
1369  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1370  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1371  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1372  PmqSetup(&pmq);
1373 
1374  SCACPreparePatterns(&mpm_ctx);
1375 
1376  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1377  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1378  (uint8_t *)buf, strlen(buf));
1379 
1380  if (cnt == 3)
1381  result = 1;
1382  else
1383  printf("3 != %" PRIu32 " ",cnt);
1384 
1385  SCACDestroyCtx(&mpm_ctx);
1386  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1387  PmqFree(&pmq);
1388  return result;
1389 }
1390 
1391 static int SCACTest06(void)
1392 {
1393  int result = 0;
1394  MpmCtx mpm_ctx;
1395  MpmThreadCtx mpm_thread_ctx;
1396  PrefilterRuleStore pmq;
1397 
1398  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1399  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1400  MpmInitCtx(&mpm_ctx, MPM_AC);
1401  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1402 
1403  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1404  PmqSetup(&pmq);
1405 
1406  SCACPreparePatterns(&mpm_ctx);
1407 
1408  const char *buf = "abcd";
1409  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1410  (uint8_t *)buf, strlen(buf));
1411 
1412  if (cnt == 1)
1413  result = 1;
1414  else
1415  printf("1 != %" 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 SCACTest07(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  /* should match 30 times */
1436  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1437  /* should match 29 times */
1438  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1439  /* should match 28 times */
1440  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1441  /* 26 */
1442  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1443  /* 21 */
1444  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1445  /* 1 */
1446  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
1447  30, 0, 0, 5, 0, 0);
1448  PmqSetup(&pmq);
1449  /* total matches: 135 */
1450 
1451  SCACPreparePatterns(&mpm_ctx);
1452 
1453  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1454  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1455  (uint8_t *)buf, strlen(buf));
1456 
1457  if (cnt == 135)
1458  result = 1;
1459  else
1460  printf("135 != %" PRIu32 " ",cnt);
1461 
1462  SCACDestroyCtx(&mpm_ctx);
1463  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1464  PmqFree(&pmq);
1465  return result;
1466 }
1467 
1468 static int SCACTest08(void)
1469 {
1470  int result = 0;
1471  MpmCtx mpm_ctx;
1472  MpmThreadCtx mpm_thread_ctx;
1473  PrefilterRuleStore pmq;
1474 
1475  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1476  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1477  MpmInitCtx(&mpm_ctx, MPM_AC);
1478  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1479 
1480  /* 1 match */
1481  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1482  PmqSetup(&pmq);
1483 
1484  SCACPreparePatterns(&mpm_ctx);
1485 
1486  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1487  (uint8_t *)"a", 1);
1488 
1489  if (cnt == 0)
1490  result = 1;
1491  else
1492  printf("0 != %" 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 SCACTest09(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 *)"ab", 2, 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 *)"ab", 2);
1520 
1521  if (cnt == 1)
1522  result = 1;
1523  else
1524  printf("1 != %" 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 SCACTest10(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 *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1546  PmqSetup(&pmq);
1547 
1548  SCACPreparePatterns(&mpm_ctx);
1549 
1550  const char *buf = "01234567890123456789012345678901234567890123456789"
1551  "01234567890123456789012345678901234567890123456789"
1552  "abcdefgh"
1553  "01234567890123456789012345678901234567890123456789"
1554  "01234567890123456789012345678901234567890123456789";
1555  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1556  (uint8_t *)buf, strlen(buf));
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 SCACTest11(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  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1582  goto end;
1583  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1584  goto end;
1585  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1586  goto end;
1587  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1588  goto end;
1589  PmqSetup(&pmq);
1590 
1591  if (SCACPreparePatterns(&mpm_ctx) == -1)
1592  goto end;
1593 
1594  result = 1;
1595 
1596  const char *buf = "he";
1597  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1598  strlen(buf)) == 1);
1599  buf = "she";
1600  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1601  strlen(buf)) == 2);
1602  buf = "his";
1603  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1604  strlen(buf)) == 1);
1605  buf = "hers";
1606  result &= (SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1607  strlen(buf)) == 2);
1608 
1609  end:
1610  SCACDestroyCtx(&mpm_ctx);
1611  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1612  PmqFree(&pmq);
1613  return result;
1614 }
1615 
1616 static int SCACTest12(void)
1617 {
1618  int result = 0;
1619  MpmCtx mpm_ctx;
1620  MpmThreadCtx mpm_thread_ctx;
1621  PrefilterRuleStore pmq;
1622 
1623  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1624  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1625  MpmInitCtx(&mpm_ctx, MPM_AC);
1626  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1627 
1628  /* 1 match */
1629  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1630  /* 1 match */
1631  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1632  PmqSetup(&pmq);
1633 
1634  SCACPreparePatterns(&mpm_ctx);
1635 
1636  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1637  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1638  (uint8_t *)buf, strlen(buf));
1639 
1640  if (cnt == 2)
1641  result = 1;
1642  else
1643  printf("2 != %" PRIu32 " ",cnt);
1644 
1645  SCACDestroyCtx(&mpm_ctx);
1646  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1647  PmqFree(&pmq);
1648  return result;
1649 }
1650 
1651 static int SCACTest13(void)
1652 {
1653  int result = 0;
1654  MpmCtx mpm_ctx;
1655  MpmThreadCtx mpm_thread_ctx;
1656  PrefilterRuleStore pmq;
1657 
1658  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1659  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1660  MpmInitCtx(&mpm_ctx, MPM_AC);
1661  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1662 
1663  /* 1 match */
1664  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1665  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1666  PmqSetup(&pmq);
1667 
1668  SCACPreparePatterns(&mpm_ctx);
1669 
1670  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1671  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1672  (uint8_t *)buf, strlen(buf));
1673 
1674  if (cnt == 1)
1675  result = 1;
1676  else
1677  printf("1 != %" PRIu32 " ",cnt);
1678 
1679  SCACDestroyCtx(&mpm_ctx);
1680  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1681  PmqFree(&pmq);
1682  return result;
1683 }
1684 
1685 static int SCACTest14(void)
1686 {
1687  int result = 0;
1688  MpmCtx mpm_ctx;
1689  MpmThreadCtx mpm_thread_ctx;
1690  PrefilterRuleStore pmq;
1691 
1692  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1693  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1694  MpmInitCtx(&mpm_ctx, MPM_AC);
1695  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1696 
1697  /* 1 match */
1698  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1699  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1700  PmqSetup(&pmq);
1701 
1702  SCACPreparePatterns(&mpm_ctx);
1703 
1704  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1705  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1706  (uint8_t *)buf, strlen(buf));
1707 
1708  if (cnt == 1)
1709  result = 1;
1710  else
1711  printf("1 != %" PRIu32 " ",cnt);
1712 
1713  SCACDestroyCtx(&mpm_ctx);
1714  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1715  PmqFree(&pmq);
1716  return result;
1717 }
1718 
1719 static int SCACTest15(void)
1720 {
1721  int result = 0;
1722  MpmCtx mpm_ctx;
1723  MpmThreadCtx mpm_thread_ctx;
1724  PrefilterRuleStore pmq;
1725 
1726  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1727  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1728  MpmInitCtx(&mpm_ctx, MPM_AC);
1729  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1730 
1731  /* 1 match */
1732  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1733  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1734  PmqSetup(&pmq);
1735 
1736  SCACPreparePatterns(&mpm_ctx);
1737 
1738  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1739  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1740  (uint8_t *)buf, strlen(buf));
1741 
1742  if (cnt == 1)
1743  result = 1;
1744  else
1745  printf("1 != %" PRIu32 " ",cnt);
1746 
1747  SCACDestroyCtx(&mpm_ctx);
1748  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1749  PmqFree(&pmq);
1750  return result;
1751 }
1752 
1753 static int SCACTest16(void)
1754 {
1755  int result = 0;
1756  MpmCtx mpm_ctx;
1757  MpmThreadCtx mpm_thread_ctx;
1758  PrefilterRuleStore pmq;
1759 
1760  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1761  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1762  MpmInitCtx(&mpm_ctx, MPM_AC);
1763  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1764 
1765  /* 1 match */
1766  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1767  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1768  PmqSetup(&pmq);
1769 
1770  SCACPreparePatterns(&mpm_ctx);
1771 
1772  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1773  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1774  (uint8_t *)buf, strlen(buf));
1775 
1776  if (cnt == 1)
1777  result = 1;
1778  else
1779  printf("1 != %" PRIu32 " ",cnt);
1780 
1781  SCACDestroyCtx(&mpm_ctx);
1782  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1783  PmqFree(&pmq);
1784  return result;
1785 }
1786 
1787 static int SCACTest17(void)
1788 {
1789  int result = 0;
1790  MpmCtx mpm_ctx;
1791  MpmThreadCtx mpm_thread_ctx;
1792  PrefilterRuleStore pmq;
1793 
1794  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1795  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1796  MpmInitCtx(&mpm_ctx, MPM_AC);
1797  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1798 
1799  /* 1 match */
1800  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1801  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1802  PmqSetup(&pmq);
1803 
1804  SCACPreparePatterns(&mpm_ctx);
1805 
1806  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1807  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1808  (uint8_t *)buf, strlen(buf));
1809 
1810  if (cnt == 1)
1811  result = 1;
1812  else
1813  printf("1 != %" PRIu32 " ",cnt);
1814 
1815  SCACDestroyCtx(&mpm_ctx);
1816  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1817  PmqFree(&pmq);
1818  return result;
1819 }
1820 
1821 static int SCACTest18(void)
1822 {
1823  int result = 0;
1824  MpmCtx mpm_ctx;
1825  MpmThreadCtx mpm_thread_ctx;
1826  PrefilterRuleStore pmq;
1827 
1828  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1829  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1830  MpmInitCtx(&mpm_ctx, MPM_AC);
1831  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1832 
1833  /* 1 match */
1834  const char pat[] = "abcde"
1835  "fghij"
1836  "klmno"
1837  "pqrst"
1838  "uvwxy"
1839  "z";
1840  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1841  PmqSetup(&pmq);
1842 
1843  SCACPreparePatterns(&mpm_ctx);
1844 
1845  const char *buf = "abcde""fghij""klmno""pqrst""uvwxy""z";
1846  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1847  (uint8_t *)buf, strlen(buf));
1848 
1849  if (cnt == 1)
1850  result = 1;
1851  else
1852  printf("1 != %" PRIu32 " ",cnt);
1853 
1854  SCACDestroyCtx(&mpm_ctx);
1855  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1856  PmqFree(&pmq);
1857  return result;
1858 }
1859 
1860 static int SCACTest19(void)
1861 {
1862  int result = 0;
1863  MpmCtx mpm_ctx;
1864  MpmThreadCtx mpm_thread_ctx;
1865  PrefilterRuleStore pmq;
1866 
1867  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1868  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1869  MpmInitCtx(&mpm_ctx, MPM_AC);
1870  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1871 
1872  /* 1 */
1873  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1874  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1875  PmqSetup(&pmq);
1876 
1877  SCACPreparePatterns(&mpm_ctx);
1878 
1879  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1880  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1881  (uint8_t *)buf, strlen(buf));
1882 
1883  if (cnt == 1)
1884  result = 1;
1885  else
1886  printf("1 != %" PRIu32 " ",cnt);
1887 
1888  SCACDestroyCtx(&mpm_ctx);
1889  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1890  PmqFree(&pmq);
1891  return result;
1892 }
1893 
1894 static int SCACTest20(void)
1895 {
1896  int result = 0;
1897  MpmCtx mpm_ctx;
1898  MpmThreadCtx mpm_thread_ctx;
1899  PrefilterRuleStore pmq;
1900 
1901  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1902  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1903  MpmInitCtx(&mpm_ctx, MPM_AC);
1904  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1905 
1906  /* 1 */
1907  const char pat[] = "AAAAA"
1908  "AAAAA"
1909  "AAAAA"
1910  "AAAAA"
1911  "AAAAA"
1912  "AAAAA"
1913  "AA";
1914  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1915  PmqSetup(&pmq);
1916 
1917  SCACPreparePatterns(&mpm_ctx);
1918 
1919  const char *buf = "AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA";
1920  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1921  (uint8_t *)buf, strlen(buf));
1922 
1923  if (cnt == 1)
1924  result = 1;
1925  else
1926  printf("1 != %" PRIu32 " ",cnt);
1927 
1928  SCACDestroyCtx(&mpm_ctx);
1929  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1930  PmqFree(&pmq);
1931  return result;
1932 }
1933 
1934 static int SCACTest21(void)
1935 {
1936  int result = 0;
1937  MpmCtx mpm_ctx;
1938  MpmThreadCtx mpm_thread_ctx;
1939  PrefilterRuleStore pmq;
1940 
1941  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1942  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1943  MpmInitCtx(&mpm_ctx, MPM_AC);
1944  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1945 
1946  /* 1 */
1947  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
1948  PmqSetup(&pmq);
1949 
1950  SCACPreparePatterns(&mpm_ctx);
1951 
1952  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1953  (uint8_t *)"AA", 2);
1954 
1955  if (cnt == 1)
1956  result = 1;
1957  else
1958  printf("1 != %" PRIu32 " ",cnt);
1959 
1960  SCACDestroyCtx(&mpm_ctx);
1961  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1962  PmqFree(&pmq);
1963  return result;
1964 }
1965 
1966 static int SCACTest22(void)
1967 {
1968  int result = 0;
1969  MpmCtx mpm_ctx;
1970  MpmThreadCtx mpm_thread_ctx;
1971  PrefilterRuleStore pmq;
1972 
1973  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1974  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1975  MpmInitCtx(&mpm_ctx, MPM_AC);
1976  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1977 
1978  /* 1 match */
1979  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1980  /* 1 match */
1981  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
1982  PmqSetup(&pmq);
1983 
1984  SCACPreparePatterns(&mpm_ctx);
1985 
1986  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1987  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1988  (uint8_t *)buf, strlen(buf));
1989 
1990  if (cnt == 2)
1991  result = 1;
1992  else
1993  printf("2 != %" PRIu32 " ",cnt);
1994 
1995  SCACDestroyCtx(&mpm_ctx);
1996  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
1997  PmqFree(&pmq);
1998  return result;
1999 }
2000 
2001 static int SCACTest23(void)
2002 {
2003  int result = 0;
2004  MpmCtx mpm_ctx;
2005  MpmThreadCtx mpm_thread_ctx;
2006  PrefilterRuleStore pmq;
2007 
2008  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2009  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2010  MpmInitCtx(&mpm_ctx, MPM_AC);
2011  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2012 
2013  /* 1 */
2014  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2015  PmqSetup(&pmq);
2016 
2017  SCACPreparePatterns(&mpm_ctx);
2018 
2019  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2020  (uint8_t *)"aa", 2);
2021 
2022  if (cnt == 0)
2023  result = 1;
2024  else
2025  printf("1 != %" PRIu32 " ",cnt);
2026 
2027  SCACDestroyCtx(&mpm_ctx);
2028  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2029  PmqFree(&pmq);
2030  return result;
2031 }
2032 
2033 static int SCACTest24(void)
2034 {
2035  int result = 0;
2036  MpmCtx mpm_ctx;
2037  MpmThreadCtx mpm_thread_ctx;
2038  PrefilterRuleStore pmq;
2039 
2040  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2041  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2042  MpmInitCtx(&mpm_ctx, MPM_AC);
2043  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2044 
2045  /* 1 */
2046  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2047  PmqSetup(&pmq);
2048 
2049  SCACPreparePatterns(&mpm_ctx);
2050 
2051  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2052  (uint8_t *)"aa", 2);
2053 
2054  if (cnt == 1)
2055  result = 1;
2056  else
2057  printf("1 != %" PRIu32 " ",cnt);
2058 
2059  SCACDestroyCtx(&mpm_ctx);
2060  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2061  PmqFree(&pmq);
2062  return result;
2063 }
2064 
2065 static int SCACTest25(void)
2066 {
2067  int result = 0;
2068  MpmCtx mpm_ctx;
2069  MpmThreadCtx mpm_thread_ctx;
2070  PrefilterRuleStore pmq;
2071 
2072  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2073  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2074  MpmInitCtx(&mpm_ctx, MPM_AC);
2075  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2076 
2077  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
2078  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
2079  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
2080  PmqSetup(&pmq);
2081 
2082  SCACPreparePatterns(&mpm_ctx);
2083 
2084  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2085  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2086  (uint8_t *)buf, strlen(buf));
2087 
2088  if (cnt == 3)
2089  result = 1;
2090  else
2091  printf("3 != %" PRIu32 " ",cnt);
2092 
2093  SCACDestroyCtx(&mpm_ctx);
2094  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2095  PmqFree(&pmq);
2096  return result;
2097 }
2098 
2099 static int SCACTest26(void)
2100 {
2101  int result = 0;
2102  MpmCtx mpm_ctx;
2103  MpmThreadCtx mpm_thread_ctx;
2104  PrefilterRuleStore pmq;
2105 
2106  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2107  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2108  MpmInitCtx(&mpm_ctx, MPM_AC);
2109  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2110 
2111  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
2112  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
2113  PmqSetup(&pmq);
2114 
2115  SCACPreparePatterns(&mpm_ctx);
2116 
2117  const char *buf = "works";
2118  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2119  (uint8_t *)buf, strlen(buf));
2120 
2121  if (cnt == 1)
2122  result = 1;
2123  else
2124  printf("3 != %" PRIu32 " ",cnt);
2125 
2126  SCACDestroyCtx(&mpm_ctx);
2127  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2128  PmqFree(&pmq);
2129  return result;
2130 }
2131 
2132 static int SCACTest27(void)
2133 {
2134  int result = 0;
2135  MpmCtx mpm_ctx;
2136  MpmThreadCtx mpm_thread_ctx;
2137  PrefilterRuleStore pmq;
2138 
2139  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2140  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2141  MpmInitCtx(&mpm_ctx, MPM_AC);
2142  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2143 
2144  /* 0 match */
2145  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
2146  PmqSetup(&pmq);
2147 
2148  SCACPreparePatterns(&mpm_ctx);
2149 
2150  const char *buf = "tone";
2151  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2152  (uint8_t *)buf, strlen(buf));
2153 
2154  if (cnt == 0)
2155  result = 1;
2156  else
2157  printf("0 != %" PRIu32 " ",cnt);
2158 
2159  SCACDestroyCtx(&mpm_ctx);
2160  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2161  PmqFree(&pmq);
2162  return result;
2163 }
2164 
2165 static int SCACTest28(void)
2166 {
2167  int result = 0;
2168  MpmCtx mpm_ctx;
2169  MpmThreadCtx mpm_thread_ctx;
2170  PrefilterRuleStore pmq;
2171 
2172  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2173  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2174  MpmInitCtx(&mpm_ctx, MPM_AC);
2175  SCACInitThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2176 
2177  /* 0 match */
2178  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2179  PmqSetup(&pmq);
2180 
2181  SCACPreparePatterns(&mpm_ctx);
2182 
2183  const char *buf = "tONE";
2184  uint32_t cnt = SCACSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2185  (uint8_t *)buf, strlen(buf));
2186 
2187  if (cnt == 0)
2188  result = 1;
2189  else
2190  printf("0 != %" PRIu32 " ",cnt);
2191 
2192  SCACDestroyCtx(&mpm_ctx);
2193  SCACDestroyThreadCtx(&mpm_ctx, &mpm_thread_ctx);
2194  PmqFree(&pmq);
2195  return result;
2196 }
2197 
2198 static int SCACTest29(void)
2199 {
2200  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
2201  uint16_t buflen = sizeof(buf) - 1;
2202  Packet *p = NULL;
2203  ThreadVars th_v;
2204  DetectEngineThreadCtx *det_ctx = NULL;
2205  int result = 0;
2206 
2207  memset(&th_v, 0, sizeof(th_v));
2208  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2209 
2211  if (de_ctx == NULL)
2212  goto end;
2213 
2214  de_ctx->flags |= DE_QUIET;
2215 
2216  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
2217  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2218  if (de_ctx->sig_list == NULL)
2219  goto end;
2220  de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any "
2221  "(content:\"onetwothreefourfivesixseveneightnine\"; fast_pattern:3,3; sid:2;)");
2222  if (de_ctx->sig_list->next == NULL)
2223  goto end;
2224 
2226  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2227 
2228  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2229  if (PacketAlertCheck(p, 1) != 1) {
2230  printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
2231  goto end;
2232  }
2233  if (PacketAlertCheck(p, 2) != 1) {
2234  printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
2235  goto end;
2236  }
2237 
2238  result = 1;
2239 end:
2240  if (de_ctx != NULL) {
2243 
2244  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2246  }
2247 
2248  UTHFreePackets(&p, 1);
2249  return result;
2250 }
2251 
2252 #endif /* UNITTESTS */
2253 
2255 {
2256 
2257 #ifdef UNITTESTS
2258  UtRegisterTest("SCACTest01", SCACTest01);
2259  UtRegisterTest("SCACTest02", SCACTest02);
2260  UtRegisterTest("SCACTest03", SCACTest03);
2261  UtRegisterTest("SCACTest04", SCACTest04);
2262  UtRegisterTest("SCACTest05", SCACTest05);
2263  UtRegisterTest("SCACTest06", SCACTest06);
2264  UtRegisterTest("SCACTest07", SCACTest07);
2265  UtRegisterTest("SCACTest08", SCACTest08);
2266  UtRegisterTest("SCACTest09", SCACTest09);
2267  UtRegisterTest("SCACTest10", SCACTest10);
2268  UtRegisterTest("SCACTest11", SCACTest11);
2269  UtRegisterTest("SCACTest12", SCACTest12);
2270  UtRegisterTest("SCACTest13", SCACTest13);
2271  UtRegisterTest("SCACTest14", SCACTest14);
2272  UtRegisterTest("SCACTest15", SCACTest15);
2273  UtRegisterTest("SCACTest16", SCACTest16);
2274  UtRegisterTest("SCACTest17", SCACTest17);
2275  UtRegisterTest("SCACTest18", SCACTest18);
2276  UtRegisterTest("SCACTest19", SCACTest19);
2277  UtRegisterTest("SCACTest20", SCACTest20);
2278  UtRegisterTest("SCACTest21", SCACTest21);
2279  UtRegisterTest("SCACTest22", SCACTest22);
2280  UtRegisterTest("SCACTest23", SCACTest23);
2281  UtRegisterTest("SCACTest24", SCACTest24);
2282  UtRegisterTest("SCACTest25", SCACTest25);
2283  UtRegisterTest("SCACTest26", SCACTest26);
2284  UtRegisterTest("SCACTest27", SCACTest27);
2285  UtRegisterTest("SCACTest28", SCACTest28);
2286  UtRegisterTest("SCACTest29", SCACTest29);
2287 #endif
2288 
2289  return;
2290 }
MpmTableElmt_::PrintThreadCtx
void(* PrintThreadCtx)(struct MpmThreadCtx_ *)
Definition: util-mpm.h:165
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:849
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
MpmTableElmt_::InitThreadCtx
void(* InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:145
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:47
MpmFreePattern
void MpmFreePattern(MpmCtx *mpm_ctx, MpmPattern *p)
Definition: util-mpm.c:352
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:143
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:269
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:141
MpmThreadCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:50
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
SCACPrintInfo
void SCACPrintInfo(MpmCtx *mpm_ctx)
Definition: util-mpm-ac.c:1169
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:827
util-memcpy.h
MpmCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:104
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:2592
MpmTableElmt_::AddPatternNocase
int(* AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:161
u8_tolower
#define u8_tolower(c)
Definition: suricata-common.h:431
DE_QUIET
#define DE_QUIET
Definition: detect.h:315
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:101
MpmTableElmt_::AddPattern
int(* AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:160
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
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1824
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:46
MpmPattern_::original_pat
uint8_t * original_pat
Definition: util-mpm.h:68
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:144
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:59
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:203
Signature_::next
struct Signature_ * next
Definition: detect.h:657
MpmTableElmt_::PrintCtx
void(* PrintCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:164
MpmCtx_::max_pat_id
uint32_t max_pat_id
Definition: util-mpm.h:106
SCACOutputTable
struct SCACOutputTable_ SCACOutputTable
util-debug.h
MpmPattern_::next
struct MpmPattern_ * next
Definition: util-mpm.h:80
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
MPM_AC
@ MPM_AC
Definition: util-mpm.h:36
DetectEngineThreadCtx_
Definition: detect.h:1075
SCACThreadCtx
struct SCACThreadCtx_ SCACThreadCtx
MpmPattern_::id
uint32_t id
Definition: util-mpm.h:74
MpmThreadCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:51
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SCACPatternList_::cs
uint8_t * cs
Definition: util-mpm-ac.h:34
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2270
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:100
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:986
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:1149
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2040
MpmPattern_::sids_size
uint32_t sids_size
Definition: util-mpm.h:77
SCReturn
#define SCReturn
Definition: util-debug.h:273
Packet_
Definition: decode.h:430
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:30
SC_AC_FAIL
#define SC_AC_FAIL
Definition: util-mpm-ac.c:81
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:162
StateQueue_::bot
int bot
Definition: util-mpm-ac-bs.c:91
util-mpm-ac.h
MpmPattern_
Definition: util-mpm.h:55
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:163
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:244
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
SCACPatternList_::depth
uint16_t depth
Definition: util-mpm-ac.h:38
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1971
MpmPattern_::ci
uint8_t * ci
Definition: util-mpm.h:72
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:133
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:902
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3308
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3522
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:98
MpmPattern_::offset
uint16_t offset
Definition: util-mpm.h:62
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:835
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:78
MpmPattern_::depth
uint16_t depth
Definition: util-mpm.h:65
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:146
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:1196
detect-parse.h
MpmCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:103
SCACOutputTable_
Definition: util-mpm-ac.h:45
MpmCtx_::init_hash
MpmPattern ** init_hash
Definition: util-mpm.h:109
MpmPattern_::len
uint16_t len
Definition: util-mpm.h:57
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2553
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:829
suricata.h
SCACRegisterTests
void SCACRegisterTests(void)
Definition: util-mpm-ac.c:2254
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:733
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:430
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:829
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:147
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:89
SCACDestroyThreadCtx
void SCACDestroyThreadCtx(MpmCtx *, MpmThreadCtx *)
Destroy the mpm thread context.
Definition: util-mpm-ac.c:883
SCACPrintSearchStats
void SCACPrintSearchStats(MpmThreadCtx *mpm_thread_ctx)
Definition: util-mpm-ac.c:1156
SigIntId
#define SigIntId
Definition: suricata-common.h:310
SCACCtx_::single_state_size
uint32_t single_state_size
Definition: util-mpm-ac.h:74
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
MpmCtx_::ctx
void * ctx
Definition: util-mpm.h:90
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:253
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:48
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:104
MpmTableElmt_::RegisterUnittests
void(* RegisterUnittests)(void)
Definition: util-mpm.h:166
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:1124
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:468