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