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