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