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