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