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