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