suricata
util-mpm-ac-ks.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-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 Ken Steele <suricata@tilera.com>
22  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23  *
24  * Aho-corasick MPM optimized for the Tilera Tile-Gx architecture.
25  *
26  * Efficient String Matching: An Aid to Bibliographic Search
27  * Alfred V. Aho and Margaret J. Corasick
28  *
29  * - Started with util-mpm-ac.c:
30  * - Uses the delta table for calculating transitions,
31  * instead of having separate goto and failure
32  * transitions.
33  * - If we cross 2 ** 16 states, we use 4 bytes in the
34  * transition table to hold each state, otherwise we use
35  * 2 bytes.
36  * - This version of the MPM is heavy on memory, but it
37  * performs well. If you can fit the ruleset with this
38  * mpm on your box without hitting swap, this is the MPM
39  * to go for.
40  *
41  * - Added these optimizations:
42  * - Compress the input alphabet from 256 characters down
43  * to the actual characters used in the patterns, plus
44  * one character for all the unused characters.
45  * - Reduce the size of the delta table so that each state
46  * is the smallest power of two that is larger than the
47  * size of the compressed alphabet.
48  * - Specialized the search function based on state count
49  * (small for 8-bit large for 16-bit) and the size of
50  * the alphabet, so that it is constant inside the
51  * function for better optimization.
52  *
53  * \todo - Do a proper analysis of our existing MPMs and suggest a good
54  * one based on the pattern distribution and the expected
55  * traffic(say http).
56 
57  * - Irrespective of whether we cross 2 ** 16 states or
58  * not,shift to using uint32_t for state type, so that we can
59  * integrate it's status as a final state or not in the
60  * topmost byte. We are already doing it if state_count is >
61  * 2 ** 16.
62  * - Test case-sensitive patterns if they have any ascii chars.
63  * If they don't treat them as nocase.
64  * - Reorder the compressed alphabet to put the most common characters
65  * first.
66  */
67 
68 #include "suricata-common.h"
69 #include "suricata.h"
70 
71 #include "detect.h"
72 #include "detect-parse.h"
73 #include "detect-engine.h"
74 #include "detect-engine-build.h"
75 
76 #include "conf.h"
77 #include "util-debug.h"
78 #include "util-unittest.h"
79 #include "util-unittest-helper.h"
80 #include "util-memcmp.h"
81 #include "util-memcpy.h"
82 #include "util-validate.h"
83 #include "util-mpm-ac-ks.h"
84 
85 #if __BYTE_ORDER == __LITTLE_ENDIAN
86 
87 void SCACTileInitCtx(MpmCtx *);
89 int SCACTileAddPatternCI(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
90  uint32_t, SigIntId, uint8_t);
91 int SCACTileAddPatternCS(MpmCtx *, uint8_t *, uint16_t, uint16_t, uint16_t,
92  uint32_t, SigIntId, uint8_t);
93 int SCACTilePreparePatterns(MpmCtx *mpm_ctx);
94 uint32_t SCACTileSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
95  PrefilterRuleStore *pmq, const uint8_t *buf,
96  uint32_t buflen);
97 void SCACTilePrintInfo(MpmCtx *mpm_ctx);
98 #ifdef UNITTESTS
99 static void SCACTileRegisterTests(void);
100 #endif
101 
102 uint32_t SCACTileSearchLarge(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
103  PrefilterRuleStore *pmq,
104  const uint8_t *buf, uint32_t buflen);
105 uint32_t SCACTileSearchSmall256(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
106  PrefilterRuleStore *pmq,
107  const uint8_t *buf, uint32_t buflen);
108 uint32_t SCACTileSearchSmall128(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
109  PrefilterRuleStore *pmq,
110  const uint8_t *buf, uint32_t buflen);
111 uint32_t SCACTileSearchSmall64(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
112  PrefilterRuleStore *pmq,
113  const uint8_t *buf, uint32_t buflen);
114 uint32_t SCACTileSearchSmall32(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
115  PrefilterRuleStore *pmq,
116  const uint8_t *buf, uint32_t buflen);
117 uint32_t SCACTileSearchSmall16(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
118  PrefilterRuleStore *pmq,
119  const uint8_t *buf, uint32_t buflen);
120 uint32_t SCACTileSearchSmall8(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
121  PrefilterRuleStore *pmq,
122  const uint8_t *buf, uint32_t buflen);
123 
124 uint32_t SCACTileSearchTiny256(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
125  PrefilterRuleStore *pmq,
126  const uint8_t *buf, uint32_t buflen);
127 uint32_t SCACTileSearchTiny128(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
128  PrefilterRuleStore *pmq,
129  const uint8_t *buf, uint32_t buflen);
130 uint32_t SCACTileSearchTiny64(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
131  PrefilterRuleStore *pmq,
132  const uint8_t *buf, uint32_t buflen);
133 uint32_t SCACTileSearchTiny32(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
134  PrefilterRuleStore *pmq,
135  const uint8_t *buf, uint32_t buflen);
136 uint32_t SCACTileSearchTiny16(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
137  PrefilterRuleStore *pmq,
138  const uint8_t *buf, uint32_t buflen);
139 uint32_t SCACTileSearchTiny8(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
140  PrefilterRuleStore *pmq,
141  const uint8_t *buf, uint32_t buflen);
142 
143 
144 static void SCACTileDestroyInitCtx(MpmCtx *mpm_ctx);
145 
146 
147 /* a placeholder to denote a failure transition in the goto table */
148 #define SC_AC_TILE_FAIL (-1)
149 
150 #define STATE_QUEUE_CONTAINER_SIZE 65536
151 
152 /**
153  * \brief Helper structure used by AC during state table creation
154  */
155 typedef struct StateQueue_ {
157  int top;
158  int bot;
160 
161 /**
162  * \internal
163  * \brief Initialize the AC context with user specified conf parameters. We
164  * aren't retrieving anything for AC conf now, but we will certainly
165  * need it, when we customize AC.
166  */
167 static void SCACTileGetConfig(void)
168 {
169 }
170 
171 /**
172  * \internal
173  * \brief Count the occurrences of each character in the pattern and
174  * accumulate into a histogram. Really only used to detect unused
175  * characters, so could just set to 1 instead of counting.
176  */
177 static inline void SCACTileHistogramAlphabet(SCACTileCtx *ctx,
178  MpmPattern *p)
179 {
180  for (int i = 0; i < p->len; i++) {
181  ctx->alpha_hist[p->ci[i]]++;
182  }
183 }
184 
185 /* Use Alphabet Histogram to create compressed alphabet.
186  */
187 static void SCACTileInitTranslateTable(SCACTileCtx *ctx)
188 {
189  /* Count the number of ASCII values actually appearing in any
190  * pattern. Create compressed mapping table with unused
191  * characters mapping to zero.
192  */
193  for (int i = 0; i < 256; i++) {
194  /* Move all upper case counts to lower case */
195  if (i >= 'A' && i <= 'Z') {
196  ctx->alpha_hist[i - 'A' + 'a'] += ctx->alpha_hist[i];
197  ctx->alpha_hist[i] = 0;
198  }
199  if (ctx->alpha_hist[i]) {
200  ctx->alphabet_size++;
201  DEBUG_VALIDATE_BUG_ON(ctx->alphabet_size > UINT8_MAX);
202  ctx->translate_table[i] = (uint8_t)ctx->alphabet_size;
203  } else
204  ctx->translate_table[i] = 0;
205  }
206  /* Fix up translation table for uppercase */
207  for (int i = 'A'; i <= 'Z'; i++)
208  ctx->translate_table[i] = ctx->translate_table[i - 'A' + 'a'];
209 
210  SCLogDebug(" Alphabet size %d", ctx->alphabet_size);
211 
212  /* Round alphabet size up to next power-of-two Leave one extra
213  * space For the unused-characters = 0 mapping.
214  */
215  ctx->alphabet_size += 1; /* Extra space for unused-character */
216  if (ctx->alphabet_size <= 8) {
217  ctx->alphabet_storage = 8;
218  } else if (ctx->alphabet_size <= 16) {
219  ctx->alphabet_storage = 16;
220  } else if (ctx->alphabet_size <= 32) {
221  ctx->alphabet_storage = 32;
222  } else if (ctx->alphabet_size <= 64) {
223  ctx->alphabet_storage = 64;
224  } else if (ctx->alphabet_size <= 128) {
225  ctx->alphabet_storage = 128;
226  } else
227  ctx->alphabet_storage = 256;
228 }
229 
230 static void SCACTileReallocOutputTable(SCACTileCtx *ctx, int new_state_count)
231 {
232 
233  /* reallocate space in the output table for the new state */
234  size_t size = ctx->allocated_state_count * sizeof(SCACTileOutputTable);
235  void *ptmp = SCRealloc(ctx->output_table, size);
236  if (ptmp == NULL) {
237  SCFree(ctx->output_table);
238  ctx->output_table = NULL;
239  FatalError("Error allocating memory");
240  }
241  ctx->output_table = ptmp;
242 }
243 
244 static void SCACTileReallocState(SCACTileCtx *ctx, int new_state_count)
245 {
246  /* reallocate space in the goto table to include a new state */
247  size_t size = ctx->allocated_state_count * sizeof(int32_t) * 256;
248  void *ptmp = SCRealloc(ctx->goto_table, size);
249  if (ptmp == NULL) {
250  SCFree(ctx->goto_table);
251  ctx->goto_table = NULL;
252  FatalError("Error allocating memory");
253  }
254  ctx->goto_table = ptmp;
255 
256  SCACTileReallocOutputTable(ctx, new_state_count);
257 }
258 
259 /**
260  * \internal
261  * \brief Initialize a new state in the goto and output tables.
262  *
263  * \param mpm_ctx Pointer to the mpm context.
264  *
265  * \retval The state id, of the newly created state.
266  */
267 static inline int SCACTileInitNewState(MpmCtx *mpm_ctx)
268 {
269  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
270  SCACTileCtx *ctx = search_ctx->init_ctx;
271  int aa = 0;
272 
273  /* Exponentially increase the allocated space when needed. */
274  if (ctx->allocated_state_count < ctx->state_count + 1) {
275  if (ctx->allocated_state_count == 0)
276  ctx->allocated_state_count = 256;
277  else
278  ctx->allocated_state_count *= 2;
279 
280  SCACTileReallocState(ctx, ctx->allocated_state_count);
281  }
282 
283  /* set all transitions for the newly assigned state as FAIL transitions */
284  for (aa = 0; aa < ctx->alphabet_size; aa++) {
285  ctx->goto_table[ctx->state_count][aa] = SC_AC_TILE_FAIL;
286  }
287 
288  memset(ctx->output_table + ctx->state_count, 0,
289  sizeof(SCACTileOutputTable));
290 
291  return ctx->state_count++;
292 }
293 
294 /**
295  * \internal
296  * \brief Adds a pid to the output table for a state.
297  *
298  * \param state The state to whose output table we should add the pid.
299  * \param pid The pattern id to add.
300  * \param mpm_ctx Pointer to the mpm context.
301  */
302 static void SCACTileSetOutputState(int32_t state, MpmPatternIndex pindex, MpmCtx *mpm_ctx)
303 {
304  void *ptmp;
305  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
306  SCACTileCtx *ctx = search_ctx->init_ctx;
307 
308  SCACTileOutputTable *output_state = &ctx->output_table[state];
309  uint32_t i = 0;
310 
311  /* Don't add the pattern more than once to the same state. */
312  for (i = 0; i < output_state->no_of_entries; i++) {
313  if (output_state->patterns[i] == pindex)
314  return;
315  }
316 
317  /* Increase the size of the array of pids for this state and add
318  * the new pid. */
319  output_state->no_of_entries++;
320  ptmp = SCRealloc(output_state->patterns,
321  output_state->no_of_entries * sizeof(MpmPatternIndex));
322  if (ptmp == NULL) {
323  SCFree(output_state->patterns);
324  output_state->patterns = NULL;
325  FatalError("Error allocating memory");
326  }
327  output_state->patterns = ptmp;
328 
329  output_state->patterns[output_state->no_of_entries - 1] = pindex;
330 }
331 
332 /**
333  * \brief Helper function used by SCACTileCreateGotoTable. Adds a
334  * pattern to the goto table.
335  *
336  * \param pattern Pointer to the pattern.
337  * \param pattern_len Pattern length.
338  * \param pid The pattern id, that corresponds to this pattern. We
339  * need it to updated the output table for this pattern.
340  * \param mpm_ctx Pointer to the mpm context.
341  */
342 static void SCACTileEnter(uint8_t *pattern, uint16_t pattern_len,
343  MpmPatternIndex pindex, MpmCtx *mpm_ctx)
344 {
345  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
346  SCACTileCtx *ctx = search_ctx->init_ctx;
347 
348  int32_t state = 0;
349  int32_t newstate = 0;
350  int i = 0;
351  int p = 0;
352  int tc;
353 
354  /* Walk down the trie till we have a match for the pattern prefix */
355  state = 0;
356  for (i = 0; i < pattern_len; i++) {
357  tc = ctx->translate_table[pattern[i]];
358  if (ctx->goto_table[state][tc] == SC_AC_TILE_FAIL)
359  break;
360  state = ctx->goto_table[state][tc];
361  }
362 
363  /* Add the non-matching pattern suffix to the trie, from the last state
364  * we left off */
365  for (p = i; p < pattern_len; p++) {
366  newstate = SCACTileInitNewState(mpm_ctx);
367  tc = ctx->translate_table[pattern[p]];
368  ctx->goto_table[state][tc] = newstate;
369  state = newstate;
370  }
371 
372  /* Add this pattern id, to the output table of the last state, where the
373  * pattern ends in the trie */
374  SCACTileSetOutputState(state, pindex, mpm_ctx);
375 }
376 
377 /**
378  * \internal
379  * \brief Create the goto table.
380  *
381  * \param mpm_ctx Pointer to the mpm context.
382  */
383 static void SCACTileCreateGotoTable(MpmCtx *mpm_ctx)
384 {
385  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
386  SCACTileCtx *ctx = search_ctx->init_ctx;
387 
388  uint32_t i = 0;
389 
390  /* add each pattern to create the goto table */
391  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
392  SCACTileEnter(ctx->parray[i]->ci, ctx->parray[i]->len,
393  i, mpm_ctx);
394  }
395 
396  int aa = 0;
397  for (aa = 0; aa < ctx->alphabet_size; aa++) {
398  if (ctx->goto_table[0][aa] == SC_AC_TILE_FAIL) {
399  ctx->goto_table[0][aa] = 0;
400  }
401  }
402 }
403 
404 static inline int SCACTileStateQueueIsEmpty(StateQueue *q)
405 {
406  if (q->top == q->bot)
407  return 1;
408  else
409  return 0;
410 }
411 
412 static inline void SCACTileEnqueue(StateQueue *q, int32_t state)
413 {
414  int i = 0;
415 
416  /*if we already have this */
417  for (i = q->bot; i < q->top; i++) {
418  if (q->store[i] == state)
419  return;
420  }
421 
422  q->store[q->top++] = state;
423 
425  q->top = 0;
426 
427  if (q->top == q->bot) {
428  FatalError("Just ran out of space in the queue. "
429  "Fatal Error. Exiting. Please file a bug report on this");
430  }
431 }
432 
433 static inline int32_t SCACTileDequeue(StateQueue *q)
434 {
436  q->bot = 0;
437 
438  if (q->bot == q->top) {
439  FatalError("StateQueue behaving weirdly. "
440  "Fatal Error. Exiting. Please file a bug report on this");
441  }
442 
443  return q->store[q->bot++];
444 }
445 
446 /**
447  * \internal
448  * \brief Club the output data from 2 states and store it in the 1st state.
449  * dst_state_data = {dst_state_data} UNION {src_state_data}
450  *
451  * \param dst_state First state(also the destination) for the union operation.
452  * \param src_state Second state for the union operation.
453  * \param mpm_ctx Pointer to the mpm context.
454  */
455 static void SCACTileClubOutputStates(int32_t dst_state,
456  int32_t src_state,
457  MpmCtx *mpm_ctx)
458 {
459  void *ptmp;
460  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
461  SCACTileCtx *ctx = search_ctx->init_ctx;
462 
463  uint32_t i = 0;
464  uint32_t j = 0;
465 
466  SCACTileOutputTable *output_dst_state = &ctx->output_table[dst_state];
467  SCACTileOutputTable *output_src_state = &ctx->output_table[src_state];
468 
469  for (i = 0; i < output_src_state->no_of_entries; i++) {
470  for (j = 0; j < output_dst_state->no_of_entries; j++) {
471  if (output_src_state->patterns[i] == output_dst_state->patterns[j]) {
472  break;
473  }
474  }
475  if (j == output_dst_state->no_of_entries) {
476  output_dst_state->no_of_entries++;
477 
478  ptmp = SCRealloc(output_dst_state->patterns,
479  (output_dst_state->no_of_entries * sizeof(uint32_t)));
480  if (ptmp == NULL) {
481  SCFree(output_dst_state->patterns);
482  output_dst_state->patterns = NULL;
483  FatalError("Error allocating memory");
484  }
485  output_dst_state->patterns = ptmp;
486 
487  output_dst_state->patterns[output_dst_state->no_of_entries - 1] =
488  output_src_state->patterns[i];
489  }
490  }
491 }
492 
493 /**
494  * \internal
495  * \brief Create the failure table.
496  *
497  * \param mpm_ctx Pointer to the mpm context.
498  */
499 static void SCACTileCreateFailureTable(MpmCtx *mpm_ctx)
500 {
501  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
502  SCACTileCtx *ctx = search_ctx->init_ctx;
503 
504  int aa = 0;
505  int32_t state = 0;
506  int32_t r_state = 0;
507 
508  StateQueue q;
509  memset(&q, 0, sizeof(StateQueue));
510 
511  /* Allocate space for the failure table. A failure entry in the table for
512  * every state(SCACTileCtx->state_count) */
513  ctx->failure_table = SCCalloc(ctx->state_count, sizeof(int32_t));
514  if (ctx->failure_table == NULL) {
515  FatalError("Error allocating memory");
516  }
517 
518  /* Add the failure transitions for the 0th state, and add every non-fail
519  * transition from the 0th state to the queue for further processing
520  * of failure states */
521  for (aa = 0; aa < ctx->alphabet_size; aa++) {
522  int32_t temp_state = ctx->goto_table[0][aa];
523  if (temp_state != 0) {
524  SCACTileEnqueue(&q, temp_state);
525  ctx->failure_table[temp_state] = 0;
526  }
527  }
528 
529  while (!SCACTileStateQueueIsEmpty(&q)) {
530  /* pick up every state from the queue and add failure transitions */
531  r_state = SCACTileDequeue(&q);
532  for (aa = 0; aa < ctx->alphabet_size; aa++) {
533  int32_t temp_state = ctx->goto_table[r_state][aa];
534  if (temp_state == SC_AC_TILE_FAIL)
535  continue;
536  SCACTileEnqueue(&q, temp_state);
537  state = ctx->failure_table[r_state];
538 
539  while(ctx->goto_table[state][aa] == SC_AC_TILE_FAIL)
540  state = ctx->failure_table[state];
541  ctx->failure_table[temp_state] = ctx->goto_table[state][aa];
542  SCACTileClubOutputStates(temp_state, ctx->failure_table[temp_state],
543  mpm_ctx);
544  }
545  }
546 }
547 
548 /*
549  * Set the next state for 1 byte next-state.
550  */
551 static void SCACTileSetState1Byte(SCACTileCtx *ctx, int state, int aa,
552  int next_state, int outputs)
553 {
554  uint8_t *state_table = (uint8_t*)ctx->state_table;
555  DEBUG_VALIDATE_BUG_ON(next_state < 0 || next_state > UINT8_MAX);
556  uint8_t encoded_next_state = (uint8_t)next_state;
557 
558  if (next_state == SC_AC_TILE_FAIL) {
559  FatalError("Error FAIL state in output");
560  }
561 
562  if (outputs == 0)
563  encoded_next_state |= (1 << 7);
564 
565  state_table[state * ctx->alphabet_storage + aa] = encoded_next_state;
566 }
567 
568 /*
569  * Set the next state for 2 byte next-state.
570  */
571 static void SCACTileSetState2Bytes(SCACTileCtx *ctx, int state, int aa,
572  int next_state, int outputs)
573 {
574  uint16_t *state_table = (uint16_t*)ctx->state_table;
575  DEBUG_VALIDATE_BUG_ON(next_state < 0 || next_state > UINT16_MAX);
576  uint16_t encoded_next_state = (uint16_t)next_state;
577 
578  if (next_state == SC_AC_TILE_FAIL) {
579  FatalError("Error FAIL state in output");
580  }
581 
582  if (outputs == 0)
583  encoded_next_state |= (1 << 15);
584 
585  state_table[state * ctx->alphabet_storage + aa] = encoded_next_state;
586 }
587 
588 /*
589  * Set the next state for 4 byte next-state.
590  */
591 static void SCACTileSetState4Bytes(SCACTileCtx *ctx, int state, int aa,
592  int next_state, int outputs)
593 {
594  uint32_t *state_table = (uint32_t*)ctx->state_table;
595  uint32_t encoded_next_state = next_state;
596 
597  if (next_state == SC_AC_TILE_FAIL) {
598  FatalError("Error FAIL state in output");
599  }
600 
601  if (outputs == 0)
602  encoded_next_state |= (1UL << 31);
603 
604  state_table[state * ctx->alphabet_storage + aa] = encoded_next_state;
605 }
606 
607 /**
608  * \internal
609  * \brief Create the delta table.
610  *
611  * \param mpm_ctx Pointer to the mpm context.
612  */
613 static inline void SCACTileCreateDeltaTable(MpmCtx *mpm_ctx)
614 {
615  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
616  SCACTileCtx *ctx = search_ctx->init_ctx;
617 
618  int aa = 0;
619  int32_t r_state = 0;
620 
621  if (ctx->state_count < 32767) {
622  if (ctx->state_count < 128) {
623  ctx->bytes_per_state = 1;
624  ctx->SetNextState = SCACTileSetState1Byte;
625 
626  switch(ctx->alphabet_storage) {
627  case 8:
628  ctx->Search = SCACTileSearchTiny8;
629  break;
630  case 16:
631  ctx->Search = SCACTileSearchTiny16;
632  break;
633  case 32:
634  ctx->Search = SCACTileSearchTiny32;
635  break;
636  case 64:
637  ctx->Search = SCACTileSearchTiny64;
638  break;
639  case 128:
640  ctx->Search = SCACTileSearchTiny128;
641  break;
642  default:
643  ctx->Search = SCACTileSearchTiny256;
644  }
645  } else {
646  /* 16-bit state needed */
647  ctx->bytes_per_state = 2;
648  ctx->SetNextState = SCACTileSetState2Bytes;
649 
650  switch(ctx->alphabet_storage) {
651  case 8:
652  ctx->Search = SCACTileSearchSmall8;
653  break;
654  case 16:
655  ctx->Search = SCACTileSearchSmall16;
656  break;
657  case 32:
658  ctx->Search = SCACTileSearchSmall32;
659  break;
660  case 64:
661  ctx->Search = SCACTileSearchSmall64;
662  break;
663  case 128:
664  ctx->Search = SCACTileSearchSmall128;
665  break;
666  default:
667  ctx->Search = SCACTileSearchSmall256;
668  }
669  }
670  } else {
671  /* 32-bit next state */
672  ctx->Search = SCACTileSearchLarge;
673  ctx->bytes_per_state = 4;
674  ctx->SetNextState = SCACTileSetState4Bytes;
675 
676  ctx->alphabet_storage = 256; /* Change? */
677  }
678 
679  StateQueue q;
680  memset(&q, 0, sizeof(StateQueue));
681 
682  for (aa = 0; aa < ctx->alphabet_size; aa++) {
683  int temp_state = ctx->goto_table[0][aa];
684  if (temp_state != 0)
685  SCACTileEnqueue(&q, temp_state);
686  }
687 
688  while (!SCACTileStateQueueIsEmpty(&q)) {
689  r_state = SCACTileDequeue(&q);
690 
691  for (aa = 0; aa < ctx->alphabet_size; aa++) {
692  int temp_state = ctx->goto_table[r_state][aa];
693  if (temp_state != SC_AC_TILE_FAIL) {
694  SCACTileEnqueue(&q, temp_state);
695  } else {
696  int f_state = ctx->failure_table[r_state];
697  ctx->goto_table[r_state][aa] = ctx->goto_table[f_state][aa];
698  }
699  }
700  }
701 }
702 
703 static void SCACTileClubOutputStatePresenceWithDeltaTable(MpmCtx *mpm_ctx)
704 {
705  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
706  SCACTileCtx *ctx = search_ctx->init_ctx;
707 
708  int aa = 0;
709  uint32_t state = 0;
710 
711  /* Allocate next-state table. */
712  int size = ctx->state_count * ctx->bytes_per_state * ctx->alphabet_storage;
713  void *state_table = SCCalloc(1, size);
714  if (unlikely(state_table == NULL)) {
715  FatalError("Error allocating memory");
716  }
717  ctx->state_table = state_table;
718 
719  mpm_ctx->memory_cnt++;
720  mpm_ctx->memory_size += size;
721 
722  SCLogDebug("Delta Table size %d, alphabet: %d, %d-byte states: %d",
723  size, ctx->alphabet_size, ctx->bytes_per_state, ctx->state_count);
724 
725  /* Copy next state from Goto table, which is 32 bits and encode it into the next
726  * state table, which can be 1, 2 or 4 bytes each and include if there is an
727  * output.
728  */
729  for (state = 0; state < ctx->state_count; state++) {
730  for (aa = 0; aa < ctx->alphabet_size; aa++) {
731  int next_state = ctx->goto_table[state][aa];
732  int next_state_outputs = ctx->output_table[next_state].no_of_entries;
733  ctx->SetNextState(ctx, state, aa, next_state, next_state_outputs);
734  }
735  }
736 }
737 
738 static inline void SCACTileInsertCaseSensitiveEntriesForPatterns(MpmCtx *mpm_ctx)
739 {
740  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
741  SCACTileCtx *ctx = search_ctx->init_ctx;
742 
743  uint32_t state = 0;
744  uint32_t k = 0;
745 
746  for (state = 0; state < ctx->state_count; state++) {
747  if (ctx->output_table[state].no_of_entries == 0)
748  continue;
749 
750  for (k = 0; k < ctx->output_table[state].no_of_entries; k++) {
751  if (ctx->pattern_list[ctx->output_table[state].patterns[k]].cs != NULL) {
752  /* TODO - Find better way to store this. */
753  ctx->output_table[state].patterns[k] &= 0x0FFFFFFF;
754  ctx->output_table[state].patterns[k] |= (uint32_t)1 << 31;
755  }
756  }
757  }
758 }
759 
760 #if 0
761 static void SCACTilePrintDeltaTable(MpmCtx *mpm_ctx)
762 {
763  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
764  SCACTileCtx *ctx = search_ctx->init_ctx;
765 
766  int i = 0, j = 0;
767 
768  printf("##############Delta Table##############\n");
769  for (i = 0; i < ctx->state_count; i++) {
770  printf("%d: \n", i);
771  for (j = 0; j < ctx->alphabet_size; j++) {
772  if (SCACTileGetDelta(i, j, mpm_ctx) != 0) {
773  printf(" %c -> %d\n", j, SCACTileGetDelta(i, j, mpm_ctx));
774  }
775  }
776  }
777 }
778 #endif
779 
780 /**
781  * \brief Process the patterns and prepare the state table.
782  *
783  * \param mpm_ctx Pointer to the mpm context.
784  */
785 static void SCACTilePrepareStateTable(MpmCtx *mpm_ctx)
786 {
787  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
788  SCACTileCtx *ctx = search_ctx->init_ctx;
789 
790  /* Create Alphabet compression and Lower Case translation table. */
791  SCACTileInitTranslateTable(ctx);
792 
793  /* create the 0th state in the goto table and output_table */
794  SCACTileInitNewState(mpm_ctx);
795 
796  /* create the goto table */
797  SCACTileCreateGotoTable(mpm_ctx);
798  /* create the failure table */
799  SCACTileCreateFailureTable(mpm_ctx);
800  /* create the final state(delta) table */
801  SCACTileCreateDeltaTable(mpm_ctx);
802  /* club the output state presence with delta transition entries */
803  SCACTileClubOutputStatePresenceWithDeltaTable(mpm_ctx);
804 
805  /* club nocase entries */
806  SCACTileInsertCaseSensitiveEntriesForPatterns(mpm_ctx);
807 
808 #if 0
809  SCACTilePrintDeltaTable(mpm_ctx);
810 #endif
811 
812  /* we don't need these anymore */
813  SCFree(ctx->goto_table);
814  ctx->goto_table = NULL;
815  SCFree(ctx->failure_table);
816  ctx->failure_table = NULL;
817 }
818 
819 
820 /**
821  * \brief Process Internal AC MPM tables to create the Search Context
822  *
823  * The search context is only the data needed to search the MPM.
824  *
825  * \param mpm_ctx Pointer to the mpm context.
826  */
827 static void SCACTilePrepareSearch(MpmCtx *mpm_ctx)
828 {
829  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
830  SCACTileCtx *ctx = search_ctx->init_ctx;
831 
832  /* Resize the output table to be only as big as its final size. */
833  SCACTileReallocOutputTable(ctx, ctx->state_count);
834 
835  search_ctx->Search = ctx->Search;
836  memcpy(search_ctx->translate_table, ctx->translate_table, sizeof(ctx->translate_table));
837 
838  /* Move the state table from the Init context */
839  search_ctx->state_table = ctx->state_table;
840  ctx->state_table = NULL; /* So that it won't get freed twice. */
841 
842  /* Move the output_table from the Init context to the Search Context */
843  /* TODO: Could be made more compact */
844  search_ctx->output_table = ctx->output_table;
845  ctx->output_table = NULL;
846  search_ctx->state_count = ctx->state_count;
847 
848  search_ctx->pattern_list = ctx->pattern_list;
849  ctx->pattern_list = NULL;
850  search_ctx->pattern_cnt = mpm_ctx->pattern_cnt;
851 
852  /* One bit per pattern, rounded up to the next byte size. */
853  search_ctx->mpm_bitarray_size = (mpm_ctx->pattern_cnt + 7) / 8;
854 
855  /* Can now free the Initialization data */
856  SCACTileDestroyInitCtx(mpm_ctx);
857 }
858 
859 /**
860  * \brief Process the patterns added to the mpm, and create the internal tables.
861  *
862  * \param mpm_ctx Pointer to the mpm context.
863  */
865 {
866  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
867 
868  if (mpm_ctx->pattern_cnt == 0 || search_ctx->init_ctx == NULL) {
869  SCLogDebug("no patterns supplied to this mpm_ctx");
870  return 0;
871  }
872  SCACTileCtx *ctx = search_ctx->init_ctx;
873  if (mpm_ctx->init_hash == NULL) {
874  SCLogDebug("no patterns supplied to this mpm_ctx");
875  return 0;
876  }
877 
878  /* alloc the pattern array */
879  ctx->parray = (MpmPattern **)SCCalloc(mpm_ctx->pattern_cnt, sizeof(MpmPattern *));
880  if (ctx->parray == NULL)
881  goto error;
882 
883  /* populate it with the patterns in the hash */
884  uint32_t i = 0, p = 0;
885  for (i = 0; i < MPM_INIT_HASH_SIZE; i++) {
886  MpmPattern *node = mpm_ctx->init_hash[i], *nnode = NULL;
887  while(node != NULL) {
888  nnode = node->next;
889  node->next = NULL;
890  ctx->parray[p++] = node;
891  SCACTileHistogramAlphabet(ctx, node);
892  node = nnode;
893  }
894  }
895 
896  /* we no longer need the hash, so free it's memory */
897  SCFree(mpm_ctx->init_hash);
898  mpm_ctx->init_hash = NULL;
899 
900  /* Handle case patterns by storing a copy of the pattern to compare
901  * to each possible match (no-case).
902  *
903  * Allocate the memory for the array and each of the strings as one block.
904  */
905  size_t string_space_needed = 0;
906  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
907  if (!(ctx->parray[i]->flags & MPM_PATTERN_FLAG_NOCASE)) {
908  /* Round up to next 8 byte aligned length */
909  uint32_t space = ((ctx->parray[i]->len + 7) / 8) * 8;
910  string_space_needed += space;
911  }
912  }
913 
914  size_t pattern_list_size = mpm_ctx->pattern_cnt * sizeof(SCACTilePatternList);
915  size_t mem_size = string_space_needed + pattern_list_size;
916  void *mem_block = SCCalloc(1, mem_size);
917  if (mem_block == NULL) {
918  FatalError("Error allocating memory");
919  }
920  mpm_ctx->memory_cnt++;
921  mpm_ctx->memory_size += mem_size;
922  /* Split the allocated block into pattern list array and string space. */
923  ctx->pattern_list = mem_block;
924  uint8_t *string_space = mem_block + pattern_list_size;
925 
926  /* Now make the copies of the no-case strings. */
927  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
928  if (!(ctx->parray[i]->flags & MPM_PATTERN_FLAG_NOCASE)) {
929  uint16_t len = ctx->parray[i]->len;
930  uint32_t space = ((len + 7) / 8) * 8;
931  memcpy(string_space, ctx->parray[i]->original_pat, len);
932  ctx->pattern_list[i].cs = string_space;
933  ctx->pattern_list[i].patlen = len;
934  string_space += space;
935  }
936  ctx->pattern_list[i].offset = ctx->parray[i]->offset;
937  ctx->pattern_list[i].depth = ctx->parray[i]->depth;
938  ctx->pattern_list[i].pid = ctx->parray[i]->id;
939 
940  /* ACPatternList now owns this memory */
941  ctx->pattern_list[i].sids_size = ctx->parray[i]->sids_size;
942  ctx->pattern_list[i].sids = ctx->parray[i]->sids;
943  ctx->parray[i]->sids = NULL;
944  ctx->parray[i]->sids_size = 0;
945  }
946 
947  /* prepare the state table required by AC */
948  SCACTilePrepareStateTable(mpm_ctx);
949 
950  /* Convert to the Search Context structure */
951  SCACTilePrepareSearch(mpm_ctx);
952 
953  return 0;
954 
955 error:
956  return -1;
957 }
958 
959 /**
960  * \brief Initialize the AC context.
961  *
962  * \param mpm_ctx Mpm context.
963  */
964 void SCACTileInitCtx(MpmCtx *mpm_ctx)
965 {
966  if (mpm_ctx->ctx != NULL)
967  return;
968 
969  /* Search Context */
970  mpm_ctx->ctx = SCCalloc(1, sizeof(SCACTileSearchCtx));
971  if (mpm_ctx->ctx == NULL) {
972  exit(EXIT_FAILURE);
973  }
974 
975  mpm_ctx->memory_cnt++;
976  mpm_ctx->memory_size += sizeof(SCACTileSearchCtx);
977 
978  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
979 
980  /* MPM Creation context */
981  search_ctx->init_ctx = SCCalloc(1, sizeof(SCACTileCtx));
982  if (search_ctx->init_ctx == NULL) {
983  exit(EXIT_FAILURE);
984  }
985 
986  mpm_ctx->memory_cnt++;
987  mpm_ctx->memory_size += sizeof(SCACTileCtx);
988 
989  /* initialize the hash we use to speed up pattern insertions */
990  mpm_ctx->init_hash = SCCalloc(MPM_INIT_HASH_SIZE, sizeof(MpmPattern *));
991  if (mpm_ctx->init_hash == NULL) {
992  exit(EXIT_FAILURE);
993  }
994 
995  /* get conf values for AC from our yaml file. We have no conf values for
996  * now. We will certainly need this, as we develop the algo */
997  SCACTileGetConfig();
998 }
999 
1000 static void SCACTileDestroyInitCtx(MpmCtx *mpm_ctx)
1001 {
1002  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
1003  SCACTileCtx *ctx = search_ctx->init_ctx;
1004 
1005  if (ctx == NULL)
1006  return;
1007 
1008  if (mpm_ctx->init_hash != NULL) {
1009  SCFree(mpm_ctx->init_hash);
1010  mpm_ctx->init_hash = NULL;
1011  }
1012 
1013  if (ctx->parray != NULL) {
1014  uint32_t i;
1015  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
1016  if (ctx->parray[i] != NULL) {
1017  MpmFreePattern(mpm_ctx, ctx->parray[i]);
1018  }
1019  }
1020 
1021  SCFree(ctx->parray);
1022  ctx->parray = NULL;
1023  }
1024 
1025  if (ctx->state_table != NULL) {
1026  SCFree(ctx->state_table);
1027 
1028  mpm_ctx->memory_cnt--;
1029  mpm_ctx->memory_size -= (ctx->state_count *
1030  ctx->bytes_per_state * ctx->alphabet_storage);
1031  }
1032 
1033  if (ctx->output_table != NULL) {
1034  uint32_t state;
1035  for (state = 0; state < ctx->state_count; state++) {
1036  if (ctx->output_table[state].patterns != NULL) {
1037  SCFree(ctx->output_table[state].patterns);
1038  }
1039  }
1040  SCFree(ctx->output_table);
1041  }
1042 
1043  if (ctx->pattern_list != NULL) {
1044  uint32_t i;
1045  for (i = 0; i < mpm_ctx->pattern_cnt; i++) {
1046  if (ctx->pattern_list[i].cs != NULL)
1047  SCFree(ctx->pattern_list[i].cs);
1048  if (ctx->pattern_list[i].sids != NULL)
1049  SCFree(ctx->pattern_list[i].sids);
1050  }
1051  SCFree(ctx->pattern_list);
1052  }
1053 
1054  SCFree(ctx);
1055  search_ctx->init_ctx = NULL;
1056  mpm_ctx->memory_cnt--;
1057  mpm_ctx->memory_size -= sizeof(SCACTileCtx);
1058 }
1059 
1060 /**
1061  * \brief Destroy the mpm context.
1062  *
1063  * \param mpm_ctx Pointer to the mpm context.
1064  */
1066 {
1067  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
1068  if (search_ctx == NULL)
1069  return;
1070 
1071  /* Destroy Initialization data */
1072  SCACTileDestroyInitCtx(mpm_ctx);
1073 
1074  /* Free Search tables */
1075  SCFree(search_ctx->state_table);
1076 
1077  if (search_ctx->pattern_list != NULL) {
1078  uint32_t i;
1079  for (i = 0; i < search_ctx->pattern_cnt; i++) {
1080  if (search_ctx->pattern_list[i].sids != NULL)
1081  SCFree(search_ctx->pattern_list[i].sids);
1082  }
1083  SCFree(search_ctx->pattern_list);
1084  }
1085 
1086  if (search_ctx->output_table != NULL) {
1087  uint32_t state;
1088  for (state = 0; state < search_ctx->state_count; state++) {
1089  if (search_ctx->output_table[state].patterns != NULL) {
1090  SCFree(search_ctx->output_table[state].patterns);
1091  }
1092  }
1093  SCFree(search_ctx->output_table);
1094  }
1095 
1096  SCFree(search_ctx);
1097  mpm_ctx->ctx = NULL;
1098 
1099  mpm_ctx->memory_cnt--;
1100  mpm_ctx->memory_size -= sizeof(SCACTileSearchCtx);
1101 }
1102 
1103 /*
1104  * Heavily optimized pattern matching routine for TILE-Gx.
1105  */
1106 
1107 #define SCHECK(x) ((x) > 0)
1108 #define BUF_TYPE int32_t
1109 // Extract byte N=0,1,2,3 from x
1110 #define BYTE0(x) (((x) & 0x000000ff) >> 0)
1111 #define BYTE1(x) (((x) & 0x0000ff00) >> 8)
1112 #define BYTE2(x) (((x) & 0x00ff0000) >> 16)
1113 #define BYTE3(x) (((x) & 0xff000000) >> 24)
1114 #define EXTRA 4 // need 4 extra bytes to avoid OOB reads
1116 static int CheckMatch(const SCACTileSearchCtx *ctx, PrefilterRuleStore *pmq,
1117  const uint8_t *buf, uint32_t buflen,
1118  uint16_t state, int i, int matches,
1119  uint8_t *mpm_bitarray)
1120 {
1121  const SCACTilePatternList *pattern_list = ctx->pattern_list;
1122  const uint8_t *buf_offset = buf + i + 1; // Lift out of loop
1123  uint32_t no_of_entries = ctx->output_table[state].no_of_entries;
1124  MpmPatternIndex *patterns = ctx->output_table[state].patterns;
1125  uint32_t k;
1126 
1127  for (k = 0; k < no_of_entries; k++) {
1128  MpmPatternIndex pindex = patterns[k] & 0x0FFFFFFF;
1129  if (mpm_bitarray[pindex / 8] & (1 << (pindex % 8))) {
1130  /* Pattern already seen by this MPM. */
1131  continue;
1132  }
1133  const SCACTilePatternList *pat = &pattern_list[pindex];
1134  const int offset = i - pat->patlen + 1;
1135  if (offset < (int)pat->offset || (pat->depth && i > pat->depth))
1136  continue;
1137 
1138  /* Double check case-sensitive match now. */
1139  if (patterns[k] >> 31) {
1140  const uint16_t patlen = pat->patlen;
1141  if (SCMemcmp(pat->cs, buf_offset - patlen, patlen) != 0) {
1142  /* Case-sensitive match failed. */
1143  continue;
1144  }
1145  }
1146  /* New match found */
1147  mpm_bitarray[pindex / 8] |= (1 << (pindex % 8));
1148 
1149  /* Always add the Signature IDs, since they could be different in the current MPM
1150  * than in a previous MPM on the same PMQ when finding the same pattern.
1151  */
1152  PrefilterAddSids(pmq, pattern_list[pindex].sids,
1153  pattern_list[pindex].sids_size);
1154  matches++;
1155  }
1156 
1157  return matches;
1158 }
1159 
1160 /**
1161  * \brief The aho corasick search function.
1162  *
1163  * \param mpm_ctx Pointer to the mpm context.
1164  * \param mpm_thread_ctx Pointer to the mpm thread context.
1165  * \param pmq Pointer to the Pattern Matcher Queue to hold
1166  * search matches.
1167  * \param buf Buffer to be searched.
1168  * \param buflen Buffer length.
1169  *
1170  * \retval matches Match count.
1171  */
1172 uint32_t SCACTileSearch(const MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx,
1173  PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
1174 {
1175  const SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
1176 
1177  if (buflen == 0)
1178  return 0;
1179 
1180  /* Context specific matching function. */
1181  return search_ctx->Search(search_ctx, mpm_thread_ctx, pmq, buf, buflen);
1182 }
1183 
1184 /* This function handles (ctx->state_count >= 32767) */
1185 uint32_t SCACTileSearchLarge(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx,
1186  PrefilterRuleStore *pmq,
1187  const uint8_t *buf, uint32_t buflen)
1188 {
1189  uint32_t i = 0;
1190  int matches = 0;
1191 
1192  uint8_t mpm_bitarray[ctx->mpm_bitarray_size];
1193  memset(mpm_bitarray, 0, ctx->mpm_bitarray_size);
1194 
1195  const uint8_t* restrict xlate = ctx->translate_table;
1196  register int state = 0;
1197  int32_t (*state_table_u32)[256] = ctx->state_table;
1198  for (i = 0; i < buflen; i++) {
1199  state = state_table_u32[state & 0x00FFFFFF][xlate[buf[i]]];
1200  if (SCHECK(state)) {
1201  DEBUG_VALIDATE_BUG_ON(state < 0 || state > UINT16_MAX);
1202  matches = CheckMatch(ctx, pmq, buf, buflen, (uint16_t)state, i, matches, mpm_bitarray);
1203  }
1204  } /* for (i = 0; i < buflen; i++) */
1205 
1206  return matches;
1207 }
1208 
1209 /*
1210  * Search with Alphabet size of 256 and 16-bit next-state entries.
1211  * Next state entry has MSB as "match" and 15 LSB bits as next-state index.
1212  */
1213 // y = 1<<log_mult * (x & (1<<width -1))
1214 #define SINDEX_INTERNAL(y, x, log_mult, width) \
1215  ((1<<log_mult) * (x & ((1<<width) - 1)))
1216 
1217 /* Type of next_state */
1218 #define STYPE int16_t
1219 #define SLOAD(x) *(STYPE * restrict)(x)
1221 #define FUNC_NAME SCACTileSearchSmall256
1222 // y = 256 * (x & 0x7FFF)
1223 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 8, 15)
1224 #include "util-mpm-ac-ks-small.c"
1225 
1226 /* Search with Alphabet size of 128 */
1227 #undef FUNC_NAME
1228 #undef SINDEX
1229 #define FUNC_NAME SCACTileSearchSmall128
1230 // y = 128 * (x & 0x7FFF)
1231 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 7, 15)
1232 #include "util-mpm-ac-ks-small.c"
1233 
1234 /* Search with Alphabet size of 64 */
1235 #undef FUNC_NAME
1236 #undef SINDEX
1237 #define FUNC_NAME SCACTileSearchSmall64
1238 // y = 64 * (x & 0x7FFF)
1239 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 6, 15)
1240 #include "util-mpm-ac-ks-small.c"
1241 
1242 /* Search with Alphabet size of 32 */
1243 #undef FUNC_NAME
1244 #undef SINDEX
1245 #define FUNC_NAME SCACTileSearchSmall32
1246 // y = 32 * (x & 0x7FFF)
1247 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 5, 15)
1248 #include "util-mpm-ac-ks-small.c"
1249 
1250 /* Search with Alphabet size of 16 */
1251 #undef FUNC_NAME
1252 #undef SINDEX
1253 #define FUNC_NAME SCACTileSearchSmall16
1254 // y = 16 * (x & 0x7FFF)
1255 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 4, 15)
1256 #include "util-mpm-ac-ks-small.c"
1257 
1258 /* Search with Alphabet size of 8 */
1259 #undef FUNC_NAME
1260 #undef SINDEX
1261 #define FUNC_NAME SCACTileSearchSmall8
1262 // y = 8 * (x & 0x7FFF)
1263 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 3, 15)
1264 #include "util-mpm-ac-ks-small.c"
1265 
1266 /*
1267  * Search with Alphabet size of 256 and 8-bit next-state entries.
1268  * Next state entry has MSB as "match" and 15 LSB bits as next-state index.
1269  */
1270 #undef STYPE
1271 #define STYPE int8_t
1273 #undef FUNC_NAME
1274 #undef SINDEX
1275 #define FUNC_NAME SCACTileSearchTiny256
1276 // y = 256 * (x & 0x7F)
1277 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 8, 7)
1278 #include "util-mpm-ac-ks-small.c"
1279 
1280 /* Search with Alphabet size of 128 */
1281 #undef FUNC_NAME
1282 #undef SINDEX
1283 #define FUNC_NAME SCACTileSearchTiny128
1284 // y = 128 * (x & 0x7F)
1285 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 7, 7)
1286 #include "util-mpm-ac-ks-small.c"
1287 
1288 /* Search with Alphabet size of 64 */
1289 #undef FUNC_NAME
1290 #undef SINDEX
1291 #define FUNC_NAME SCACTileSearchTiny64
1292 // y = 64 * (x & 0x7F)
1293 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 6, 7)
1294 #include "util-mpm-ac-ks-small.c"
1295 
1296 /* Search with Alphabet size of 32 */
1297 #undef FUNC_NAME
1298 #undef SINDEX
1299 #define FUNC_NAME SCACTileSearchTiny32
1300 // y = 32 * (x & 0x7F)
1301 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 5, 7)
1302 #include "util-mpm-ac-ks-small.c"
1303 
1304 /* Search with Alphabet size of 16 */
1305 #undef FUNC_NAME
1306 #undef SINDEX
1307 #define FUNC_NAME SCACTileSearchTiny16
1308 // y = 16 * (x & 0x7F)
1309 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 4, 7)
1310 #include "util-mpm-ac-ks-small.c"
1311 
1312 /* Search with Alphabet size of 8 */
1313 #undef FUNC_NAME
1314 #undef SINDEX
1315 #define FUNC_NAME SCACTileSearchTiny8
1316 // y = 8 * (x & 0x7F)
1317 #define SINDEX(y,x) SINDEX_INTERNAL(y, x, 3, 7)
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 SCACTileAddPatternCI(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,
1344  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 SCACTileAddPatternCS(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,
1369  pid, sid, flags);
1370 }
1371 
1373 {
1374  SCACTileSearchCtx *search_ctx = (SCACTileSearchCtx *)mpm_ctx->ctx;
1375  SCACTileCtx *ctx = search_ctx->init_ctx;
1376 
1377  printf("MPM AC Information:\n");
1378  printf("Memory allocs: %" PRIu32 "\n", mpm_ctx->memory_cnt);
1379  printf("Memory alloced: %" PRIu32 "\n", mpm_ctx->memory_size);
1380  printf(" Sizeof:\n");
1381  printf(" MpmCtx %" PRIuMAX "\n", (uintmax_t)sizeof(MpmCtx));
1382  printf(" SCACTileCtx: %" PRIuMAX "\n", (uintmax_t)sizeof(SCACTileCtx));
1383  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1384  printf(" MpmPattern %" PRIuMAX "\n", (uintmax_t)sizeof(MpmPattern));
1385  printf("Unique Patterns: %" PRIu32 "\n", mpm_ctx->pattern_cnt);
1386  printf("Smallest: %" PRIu32 "\n", mpm_ctx->minlen);
1387  printf("Largest: %" PRIu32 "\n", mpm_ctx->maxlen);
1388  printf("Total states in the state table: %u\n", ctx->state_count);
1389  printf("\n");
1390 }
1391 
1392 /************************** Mpm Registration ***************************/
1393 
1394 /**
1395  * \brief Register the aho-corasick mpm 'ks' originally developed by
1396  * Ken Steele for Tilera Tile-Gx processor.
1397  */
1399 {
1400  mpm_table[MPM_AC_KS].name = "ac-ks";
1408 #ifdef UNITTESTS
1409  mpm_table[MPM_AC_KS].RegisterUnittests = SCACTileRegisterTests;
1410 #endif
1412 }
1413 
1414 
1415 /*************************************Unittests********************************/
1416 
1417 #ifdef UNITTESTS
1418 #include "detect-engine-alert.h"
1419 
1420 static int SCACTileTest01(void)
1421 {
1422  int result = 0;
1423  MpmCtx mpm_ctx;
1424  MpmThreadCtx mpm_thread_ctx;
1425  PrefilterRuleStore pmq;
1426 
1427  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1428  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1429  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1430 
1431  /* 1 match */
1432  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1433  PmqSetup(&pmq);
1434 
1435  SCACTilePreparePatterns(&mpm_ctx);
1436 
1437  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1438 
1439  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1440  (uint8_t *)buf, strlen(buf));
1441 
1442  if (cnt == 1)
1443  result = 1;
1444  else
1445  printf("1 != %" PRIu32 " ",cnt);
1446 
1447  SCACTileDestroyCtx(&mpm_ctx);
1448  PmqFree(&pmq);
1449  return result;
1450 }
1451 
1452 static int SCACTileTest02(void)
1453 {
1454  int result = 0;
1455  MpmCtx mpm_ctx;
1456  MpmThreadCtx mpm_thread_ctx;
1457  PrefilterRuleStore pmq;
1458 
1459  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1460  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1461  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1462 
1463  /* 1 match */
1464  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abce", 4, 0, 0, 0, 0, 0);
1465  PmqSetup(&pmq);
1466 
1467  SCACTilePreparePatterns(&mpm_ctx);
1468 
1469  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1470  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1471  (uint8_t *)buf, strlen(buf));
1472 
1473  if (cnt == 0)
1474  result = 1;
1475  else
1476  printf("0 != %" PRIu32 " ",cnt);
1477 
1478  SCACTileDestroyCtx(&mpm_ctx);
1479  PmqFree(&pmq);
1480  return result;
1481 }
1482 
1483 static int SCACTileTest03(void)
1484 {
1485  int result = 0;
1486  MpmCtx mpm_ctx;
1487  MpmThreadCtx mpm_thread_ctx;
1488  PrefilterRuleStore pmq;
1489 
1490  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1491  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1492  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1493 
1494  /* 1 match */
1495  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1496  /* 1 match */
1497  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcde", 4, 0, 0, 1, 0, 0);
1498  /* 1 match */
1499  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghj", 4, 0, 0, 2, 0, 0);
1500  PmqSetup(&pmq);
1501 
1502  SCACTilePreparePatterns(&mpm_ctx);
1503 
1504  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1505  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1506  (uint8_t *)buf, strlen(buf));
1507 
1508  if (cnt == 3)
1509  result = 1;
1510  else
1511  printf("3 != %" PRIu32 " ",cnt);
1512 
1513  SCACTileDestroyCtx(&mpm_ctx);
1514  PmqFree(&pmq);
1515  return result;
1516 }
1517 
1518 static int SCACTileTest04(void)
1519 {
1520  int result = 0;
1521  MpmCtx mpm_ctx;
1522  MpmThreadCtx mpm_thread_ctx;
1523  PrefilterRuleStore pmq;
1524 
1525  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1526  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1527  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1528 
1529  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1530  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"bcdegh", 6, 0, 0, 1, 0, 0);
1531  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"fghjxyz", 7, 0, 0, 2, 0, 0);
1532  PmqSetup(&pmq);
1533 
1534  SCACTilePreparePatterns(&mpm_ctx);
1535 
1536  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1537  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1538  (uint8_t *)buf, strlen(buf));
1539 
1540  if (cnt == 1)
1541  result = 1;
1542  else
1543  printf("1 != %" PRIu32 " ",cnt);
1544 
1545  SCACTileDestroyCtx(&mpm_ctx);
1546  PmqFree(&pmq);
1547  return result;
1548 }
1549 
1550 static int SCACTileTest05(void)
1551 {
1552  int result = 0;
1553  MpmCtx mpm_ctx;
1554  MpmThreadCtx mpm_thread_ctx;
1555  PrefilterRuleStore pmq;
1556 
1557  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1558  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1559  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1560 
1561  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
1562  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
1563  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghJikl", 7, 0, 0, 2, 0, 0);
1564  PmqSetup(&pmq);
1565 
1566  SCACTilePreparePatterns(&mpm_ctx);
1567 
1568  const char *buf = "abcdefghjiklmnopqrstuvwxyz";
1569  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1570  (uint8_t *)buf, strlen(buf));
1571 
1572  if (cnt == 3)
1573  result = 1;
1574  else
1575  printf("3 != %" PRIu32 " ",cnt);
1576 
1577  SCACTileDestroyCtx(&mpm_ctx);
1578  PmqFree(&pmq);
1579  return result;
1580 }
1581 
1582 static int SCACTileTest06(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_KS);
1592 
1593  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1594  PmqSetup(&pmq);
1595 
1596  SCACTilePreparePatterns(&mpm_ctx);
1597 
1598  const char *buf = "abcd";
1599  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1600  (uint8_t *)buf, strlen(buf));
1601 
1602  if (cnt == 1)
1603  result = 1;
1604  else
1605  printf("1 != %" PRIu32 " ",cnt);
1606 
1607  SCACTileDestroyCtx(&mpm_ctx);
1608  PmqFree(&pmq);
1609  return result;
1610 }
1611 
1612 static int SCACTileTest07(void)
1613 {
1614  MpmCtx mpm_ctx;
1615  MpmThreadCtx mpm_thread_ctx;
1616  PrefilterRuleStore pmq;
1617 
1618  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1619  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1620  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1621 
1622  /* should match 30 times */
1623  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"A", 1, 0, 0, 0, 0, 0);
1624  /* should match 29 times */
1625  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 1, 0, 0);
1626  /* should match 28 times */
1627  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAA", 3, 0, 0, 2, 0, 0);
1628  /* 26 */
1629  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAA", 5, 0, 0, 3, 0, 0);
1630  /* 21 */
1631  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAA", 10, 0, 0, 4, 0, 0);
1632  /* 1 */
1633  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
1634  30, 0, 0, 5, 0, 0);
1635  PmqSetup(&pmq);
1636  /* total matches: 135: 6 unique */
1637 
1638  SCACTilePreparePatterns(&mpm_ctx);
1639 
1640  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1641  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1642  (uint8_t *)buf, strlen(buf));
1643  FAIL_IF_NOT(cnt == 6);
1644 
1645  SCACTileDestroyCtx(&mpm_ctx);
1646  PmqFree(&pmq);
1647  PASS;
1648 }
1649 
1650 static int SCACTileTest08(void)
1651 {
1652  int result = 0;
1653  MpmCtx mpm_ctx;
1654  MpmThreadCtx mpm_thread_ctx;
1655  PrefilterRuleStore pmq;
1656 
1657  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1658  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1659  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1660 
1661  /* 1 match */
1662  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
1663  PmqSetup(&pmq);
1664 
1665  SCACTilePreparePatterns(&mpm_ctx);
1666 
1667  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1668  (uint8_t *)"a", 1);
1669 
1670  if (cnt == 0)
1671  result = 1;
1672  else
1673  printf("0 != %" PRIu32 " ",cnt);
1674 
1675  SCACTileDestroyCtx(&mpm_ctx);
1676  PmqFree(&pmq);
1677  return result;
1678 }
1679 
1680 static int SCACTileTest09(void)
1681 {
1682  int result = 0;
1683  MpmCtx mpm_ctx;
1684  MpmThreadCtx mpm_thread_ctx;
1685  PrefilterRuleStore pmq;
1686 
1687  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1688  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1689  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1690 
1691  /* 1 match */
1692  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ab", 2, 0, 0, 0, 0, 0);
1693  PmqSetup(&pmq);
1694 
1695  SCACTilePreparePatterns(&mpm_ctx);
1696 
1697  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1698  (uint8_t *)"ab", 2);
1699 
1700  if (cnt == 1)
1701  result = 1;
1702  else
1703  printf("1 != %" PRIu32 " ",cnt);
1704 
1705  SCACTileDestroyCtx(&mpm_ctx);
1706  PmqFree(&pmq);
1707  return result;
1708 }
1709 
1710 static int SCACTileTest10(void)
1711 {
1712  int result = 0;
1713  MpmCtx mpm_ctx;
1714  MpmThreadCtx mpm_thread_ctx;
1715  PrefilterRuleStore pmq;
1716 
1717  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1718  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1719  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1720 
1721  /* 1 match */
1722  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcdefgh", 8, 0, 0, 0, 0, 0);
1723  PmqSetup(&pmq);
1724 
1725  SCACTilePreparePatterns(&mpm_ctx);
1726 
1727  const char *buf = "01234567890123456789012345678901234567890123456789"
1728  "01234567890123456789012345678901234567890123456789"
1729  "abcdefgh"
1730  "01234567890123456789012345678901234567890123456789"
1731  "01234567890123456789012345678901234567890123456789";
1732  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1733  (uint8_t *)buf, strlen(buf));
1734 
1735  if (cnt == 1)
1736  result = 1;
1737  else
1738  printf("1 != %" PRIu32 " ",cnt);
1739 
1740  SCACTileDestroyCtx(&mpm_ctx);
1741  PmqFree(&pmq);
1742  return result;
1743 }
1744 
1745 static int SCACTileTest11(void)
1746 {
1747  int result = 0;
1748  MpmCtx mpm_ctx;
1749  MpmThreadCtx mpm_thread_ctx;
1750  PrefilterRuleStore pmq;
1751 
1752  memset(&mpm_ctx, 0, sizeof(MpmCtx));
1753  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1754  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1755 
1756  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"he", 2, 0, 0, 1, 0, 0) == -1)
1757  goto end;
1758  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"she", 3, 0, 0, 2, 0, 0) == -1)
1759  goto end;
1760  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"his", 3, 0, 0, 3, 0, 0) == -1)
1761  goto end;
1762  if (MpmAddPatternCS(&mpm_ctx, (uint8_t *)"hers", 4, 0, 0, 4, 0, 0) == -1)
1763  goto end;
1764  PmqSetup(&pmq);
1765 
1766  if (SCACTilePreparePatterns(&mpm_ctx) == -1)
1767  goto end;
1768 
1769  result = 1;
1770 
1771  const char *buf = "he";
1772  result &= (SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1773  strlen(buf)) == 1);
1774  buf = "she";
1775  result &= (SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1776  strlen(buf)) == 2);
1777  buf = "his";
1778  result &= (SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1779  strlen(buf)) == 1);
1780  buf = "hers";
1781  result &= (SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq, (uint8_t *)buf,
1782  strlen(buf)) == 2);
1783 
1784  end:
1785  SCACTileDestroyCtx(&mpm_ctx);
1786  PmqFree(&pmq);
1787  return result;
1788 }
1789 
1790 static int SCACTileTest12(void)
1791 {
1792  int result = 0;
1793  MpmCtx mpm_ctx;
1794  MpmThreadCtx mpm_thread_ctx;
1795  PrefilterRuleStore pmq;
1796 
1797  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1798  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1799  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1800 
1801  /* 1 match */
1802  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"wxyz", 4, 0, 0, 0, 0, 0);
1803  /* 1 match */
1804  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"vwxyz", 5, 0, 0, 1, 0, 0);
1805  PmqSetup(&pmq);
1806 
1807  SCACTilePreparePatterns(&mpm_ctx);
1808 
1809  const char *buf = "abcdefghijklmnopqrstuvwxyz";
1810  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1811  (uint8_t *)buf, strlen(buf));
1812 
1813  if (cnt == 2)
1814  result = 1;
1815  else
1816  printf("2 != %" PRIu32 " ",cnt);
1817 
1818  SCACTileDestroyCtx(&mpm_ctx);
1819  PmqFree(&pmq);
1820  return result;
1821 }
1822 
1823 static int SCACTileTest13(void)
1824 {
1825  int result = 0;
1826  MpmCtx mpm_ctx;
1827  MpmThreadCtx mpm_thread_ctx;
1828  PrefilterRuleStore pmq;
1829 
1830  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1831  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1832  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1833 
1834  /* 1 match */
1835  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCD";
1836  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1837  PmqSetup(&pmq);
1838 
1839  SCACTilePreparePatterns(&mpm_ctx);
1840 
1841  const char *buf = "abcdefghijklmnopqrstuvwxyzABCD";
1842  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1843  (uint8_t *)buf, strlen(buf));
1844 
1845  if (cnt == 1)
1846  result = 1;
1847  else
1848  printf("1 != %" PRIu32 " ",cnt);
1849 
1850  SCACTileDestroyCtx(&mpm_ctx);
1851  PmqFree(&pmq);
1852  return result;
1853 }
1854 
1855 static int SCACTileTest14(void)
1856 {
1857  int result = 0;
1858  MpmCtx mpm_ctx;
1859  MpmThreadCtx mpm_thread_ctx;
1860  PrefilterRuleStore pmq;
1861 
1862  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1863  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1864  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1865 
1866  /* 1 match */
1867  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDE";
1868  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1869  PmqSetup(&pmq);
1870 
1871  SCACTilePreparePatterns(&mpm_ctx);
1872 
1873  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDE";
1874  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1875  (uint8_t *)buf, strlen(buf));
1876 
1877  if (cnt == 1)
1878  result = 1;
1879  else
1880  printf("1 != %" PRIu32 " ",cnt);
1881 
1882  SCACTileDestroyCtx(&mpm_ctx);
1883  PmqFree(&pmq);
1884  return result;
1885 }
1886 
1887 static int SCACTileTest15(void)
1888 {
1889  int result = 0;
1890  MpmCtx mpm_ctx;
1891  MpmThreadCtx mpm_thread_ctx;
1892  PrefilterRuleStore pmq;
1893 
1894  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1895  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1896  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1897 
1898  /* 1 match */
1899  const char pat[] = "abcdefghijklmnopqrstuvwxyzABCDEF";
1900  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1901  PmqSetup(&pmq);
1902 
1903  SCACTilePreparePatterns(&mpm_ctx);
1904 
1905  const char *buf = "abcdefghijklmnopqrstuvwxyzABCDEF";
1906  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1907  (uint8_t *)buf, strlen(buf));
1908 
1909  if (cnt == 1)
1910  result = 1;
1911  else
1912  printf("1 != %" PRIu32 " ",cnt);
1913 
1914  SCACTileDestroyCtx(&mpm_ctx);
1915  PmqFree(&pmq);
1916  return result;
1917 }
1918 
1919 static int SCACTileTest16(void)
1920 {
1921  int result = 0;
1922  MpmCtx mpm_ctx;
1923  MpmThreadCtx mpm_thread_ctx;
1924  PrefilterRuleStore pmq;
1925 
1926  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1927  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1928  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1929 
1930  /* 1 match */
1931  const char pat[] = "abcdefghijklmnopqrstuvwxyzABC";
1932  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1933  PmqSetup(&pmq);
1934 
1935  SCACTilePreparePatterns(&mpm_ctx);
1936 
1937  const char *buf = "abcdefghijklmnopqrstuvwxyzABC";
1938  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1939  (uint8_t *)buf, strlen(buf));
1940 
1941  if (cnt == 1)
1942  result = 1;
1943  else
1944  printf("1 != %" PRIu32 " ",cnt);
1945 
1946  SCACTileDestroyCtx(&mpm_ctx);
1947  PmqFree(&pmq);
1948  return result;
1949 }
1950 
1951 static int SCACTileTest17(void)
1952 {
1953  int result = 0;
1954  MpmCtx mpm_ctx;
1955  MpmThreadCtx mpm_thread_ctx;
1956  PrefilterRuleStore pmq;
1957 
1958  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1959  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1960  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1961 
1962  /* 1 match */
1963  const char pat[] = "abcdefghijklmnopqrstuvwxyzAB";
1964  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
1965  PmqSetup(&pmq);
1966 
1967  SCACTilePreparePatterns(&mpm_ctx);
1968 
1969  const char *buf = "abcdefghijklmnopqrstuvwxyzAB";
1970  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
1971  (uint8_t *)buf, strlen(buf));
1972 
1973  if (cnt == 1)
1974  result = 1;
1975  else
1976  printf("1 != %" PRIu32 " ",cnt);
1977 
1978  SCACTileDestroyCtx(&mpm_ctx);
1979  PmqFree(&pmq);
1980  return result;
1981 }
1982 
1983 static int SCACTileTest18(void)
1984 {
1985  int result = 0;
1986  MpmCtx mpm_ctx;
1987  MpmThreadCtx mpm_thread_ctx;
1988  PrefilterRuleStore pmq;
1989 
1990  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
1991  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
1992  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
1993 
1994  /* 1 match */
1995  const char pat[] = "abcde"
1996  "fghij"
1997  "klmno"
1998  "pqrst"
1999  "uvwxy"
2000  "z";
2001  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
2002  PmqSetup(&pmq);
2003 
2004  SCACTilePreparePatterns(&mpm_ctx);
2005 
2006  const char *buf = "abcde""fghij""klmno""pqrst""uvwxy""z";
2007  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2008  (uint8_t *)buf, strlen(buf));
2009 
2010  if (cnt == 1)
2011  result = 1;
2012  else
2013  printf("1 != %" PRIu32 " ",cnt);
2014 
2015  SCACTileDestroyCtx(&mpm_ctx);
2016  PmqFree(&pmq);
2017  return result;
2018 }
2019 
2020 static int SCACTileTest19(void)
2021 {
2022  int result = 0;
2023  MpmCtx mpm_ctx;
2024  MpmThreadCtx mpm_thread_ctx;
2025  PrefilterRuleStore pmq;
2026 
2027  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2028  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2029  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2030 
2031  /* 1 */
2032  const char pat[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
2033  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
2034  PmqSetup(&pmq);
2035 
2036  SCACTilePreparePatterns(&mpm_ctx);
2037 
2038  const char *buf = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
2039  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2040  (uint8_t *)buf, strlen(buf));
2041 
2042  if (cnt == 1)
2043  result = 1;
2044  else
2045  printf("1 != %" PRIu32 " ",cnt);
2046 
2047  SCACTileDestroyCtx(&mpm_ctx);
2048  PmqFree(&pmq);
2049  return result;
2050 }
2051 
2052 static int SCACTileTest20(void)
2053 {
2054  int result = 0;
2055  MpmCtx mpm_ctx;
2056  MpmThreadCtx mpm_thread_ctx;
2057  PrefilterRuleStore pmq;
2058 
2059  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2060  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2061  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2062 
2063  /* 1 */
2064  const char pat[] = "AAAAA"
2065  "AAAAA"
2066  "AAAAA"
2067  "AAAAA"
2068  "AAAAA"
2069  "AAAAA"
2070  "AA";
2071  MpmAddPatternCS(&mpm_ctx, (uint8_t *)pat, sizeof(pat) - 1, 0, 0, 0, 0, 0);
2072  PmqSetup(&pmq);
2073 
2074  SCACTilePreparePatterns(&mpm_ctx);
2075 
2076  const char *buf = "AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA";
2077  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2078  (uint8_t *)buf, strlen(buf));
2079 
2080  if (cnt == 1)
2081  result = 1;
2082  else
2083  printf("1 != %" PRIu32 " ",cnt);
2084 
2085  SCACTileDestroyCtx(&mpm_ctx);
2086  PmqFree(&pmq);
2087  return result;
2088 }
2089 
2090 static int SCACTileTest21(void)
2091 {
2092  int result = 0;
2093  MpmCtx mpm_ctx;
2094  MpmThreadCtx mpm_thread_ctx;
2095  PrefilterRuleStore pmq;
2096 
2097  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2098  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2099  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2100 
2101  /* 1 */
2102  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2103  PmqSetup(&pmq);
2104 
2105  SCACTilePreparePatterns(&mpm_ctx);
2106 
2107  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2108  (uint8_t *)"AA", 2);
2109 
2110  if (cnt == 1)
2111  result = 1;
2112  else
2113  printf("1 != %" PRIu32 " ",cnt);
2114 
2115  SCACTileDestroyCtx(&mpm_ctx);
2116  PmqFree(&pmq);
2117  return result;
2118 }
2119 
2120 static int SCACTileTest22(void)
2121 {
2122  int result = 0;
2123  MpmCtx mpm_ctx;
2124  MpmThreadCtx mpm_thread_ctx;
2125  PrefilterRuleStore pmq;
2126 
2127  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2128  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2129  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2130 
2131  /* 1 match */
2132  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcd", 4, 0, 0, 0, 0, 0);
2133  /* 1 match */
2134  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"abcde", 5, 0, 0, 1, 0, 0);
2135  PmqSetup(&pmq);
2136 
2137  SCACTilePreparePatterns(&mpm_ctx);
2138 
2139  const char *buf = "abcdefghijklmnopqrstuvwxyz";
2140  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2141  (uint8_t *)buf, strlen(buf));
2142 
2143  if (cnt == 2)
2144  result = 1;
2145  else
2146  printf("2 != %" PRIu32 " ",cnt);
2147 
2148  SCACTileDestroyCtx(&mpm_ctx);
2149  PmqFree(&pmq);
2150  return result;
2151 }
2152 
2153 static int SCACTileTest23(void)
2154 {
2155  int result = 0;
2156  MpmCtx mpm_ctx;
2157  MpmThreadCtx mpm_thread_ctx;
2158  PrefilterRuleStore pmq;
2159 
2160  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2161  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2162  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2163 
2164  /* 1 */
2165  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2166  PmqSetup(&pmq);
2167 
2168  SCACTilePreparePatterns(&mpm_ctx);
2169 
2170  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2171  (uint8_t *)"aa", 2);
2172 
2173  if (cnt == 0)
2174  result = 1;
2175  else
2176  printf("1 != %" PRIu32 " ",cnt);
2177 
2178  SCACTileDestroyCtx(&mpm_ctx);
2179  PmqFree(&pmq);
2180  return result;
2181 }
2182 
2183 static int SCACTileTest24(void)
2184 {
2185  int result = 0;
2186  MpmCtx mpm_ctx;
2187  MpmThreadCtx mpm_thread_ctx;
2188  PrefilterRuleStore pmq;
2189 
2190  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2191  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2192  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2193 
2194  /* 1 */
2195  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"AA", 2, 0, 0, 0, 0, 0);
2196  PmqSetup(&pmq);
2197 
2198  SCACTilePreparePatterns(&mpm_ctx);
2199 
2200  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2201  (uint8_t *)"aa", 2);
2202 
2203  if (cnt == 1)
2204  result = 1;
2205  else
2206  printf("1 != %" PRIu32 " ",cnt);
2207 
2208  SCACTileDestroyCtx(&mpm_ctx);
2209  PmqFree(&pmq);
2210  return result;
2211 }
2212 
2213 static int SCACTileTest25(void)
2214 {
2215  int result = 0;
2216  MpmCtx mpm_ctx;
2217  MpmThreadCtx mpm_thread_ctx;
2218  PrefilterRuleStore pmq;
2219 
2220  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2221  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2222  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2223 
2224  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"ABCD", 4, 0, 0, 0, 0, 0);
2225  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"bCdEfG", 6, 0, 0, 1, 0, 0);
2226  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"fghiJkl", 7, 0, 0, 2, 0, 0);
2227  PmqSetup(&pmq);
2228 
2229  SCACTilePreparePatterns(&mpm_ctx);
2230 
2231  const char *buf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2232  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2233  (uint8_t *)buf, strlen(buf));
2234 
2235  if (cnt == 3)
2236  result = 1;
2237  else
2238  printf("3 != %" PRIu32 " ",cnt);
2239 
2240  SCACTileDestroyCtx(&mpm_ctx);
2241  PmqFree(&pmq);
2242  return result;
2243 }
2244 
2245 static int SCACTileTest26(void)
2246 {
2247  int result = 0;
2248  MpmCtx mpm_ctx;
2249  MpmThreadCtx mpm_thread_ctx;
2250  PrefilterRuleStore pmq;
2251 
2252  memset(&mpm_ctx, 0x00, sizeof(MpmCtx));
2253  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2254  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2255 
2256  MpmAddPatternCI(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 0, 0, 0);
2257  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"Works", 5, 0, 0, 1, 0, 0);
2258  PmqSetup(&pmq);
2259 
2260  SCACTilePreparePatterns(&mpm_ctx);
2261 
2262  const char *buf = "works";
2263  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2264  (uint8_t *)buf, strlen(buf));
2265 
2266  if (cnt == 1)
2267  result = 1;
2268  else
2269  printf("3 != %" PRIu32 " ",cnt);
2270 
2271  SCACTileDestroyCtx(&mpm_ctx);
2272  PmqFree(&pmq);
2273  return result;
2274 }
2275 
2276 static int SCACTileTest27(void)
2277 {
2278  int result = 0;
2279  MpmCtx mpm_ctx;
2280  MpmThreadCtx mpm_thread_ctx;
2281  PrefilterRuleStore pmq;
2282 
2283  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2284  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2285  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2286 
2287  /* 0 match */
2288  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"ONE", 3, 0, 0, 0, 0, 0);
2289  PmqSetup(&pmq);
2290 
2291  SCACTilePreparePatterns(&mpm_ctx);
2292 
2293  const char *buf = "tone";
2294  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2295  (uint8_t *)buf, strlen(buf));
2296 
2297  if (cnt == 0)
2298  result = 1;
2299  else
2300  printf("0 != %" PRIu32 " ",cnt);
2301 
2302  SCACTileDestroyCtx(&mpm_ctx);
2303  PmqFree(&pmq);
2304  return result;
2305 }
2306 
2307 static int SCACTileTest28(void)
2308 {
2309  int result = 0;
2310  MpmCtx mpm_ctx;
2311  MpmThreadCtx mpm_thread_ctx;
2312  PrefilterRuleStore pmq;
2313 
2314  memset(&mpm_ctx, 0, sizeof(MpmCtx));
2315  memset(&mpm_thread_ctx, 0, sizeof(MpmThreadCtx));
2316  MpmInitCtx(&mpm_ctx, MPM_AC_KS);
2317 
2318  /* 0 match */
2319  MpmAddPatternCS(&mpm_ctx, (uint8_t *)"one", 3, 0, 0, 0, 0, 0);
2320  PmqSetup(&pmq);
2321 
2322  SCACTilePreparePatterns(&mpm_ctx);
2323 
2324  const char *buf = "tONE";
2325  uint32_t cnt = SCACTileSearch(&mpm_ctx, &mpm_thread_ctx, &pmq,
2326  (uint8_t *)buf, strlen(buf));
2327 
2328  if (cnt == 0)
2329  result = 1;
2330  else
2331  printf("0 != %" PRIu32 " ",cnt);
2332 
2333  SCACTileDestroyCtx(&mpm_ctx);
2334  PmqFree(&pmq);
2335  return result;
2336 }
2337 
2338 static int SCACTileTest29(void)
2339 {
2340  uint8_t buf[] = "onetwothreefourfivesixseveneightnine";
2341  uint16_t buflen = sizeof(buf) - 1;
2342  Packet *p = NULL;
2343  ThreadVars th_v;
2344  DetectEngineThreadCtx *det_ctx = NULL;
2345  int result = 0;
2346 
2347  memset(&th_v, 0, sizeof(th_v));
2348  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2349 
2351  if (de_ctx == NULL)
2352  goto end;
2353 
2354  de_ctx->flags |= DE_QUIET;
2355 
2356  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
2357  "(content:\"onetwothreefourfivesixseveneightnine\"; sid:1;)");
2358  if (de_ctx->sig_list == NULL)
2359  goto end;
2360  de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any "
2361  "(content:\"onetwothreefourfivesixseveneightnine\"; fast_pattern:3,3; sid:2;)");
2362  if (de_ctx->sig_list->next == NULL)
2363  goto end;
2364 
2366  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2367 
2368  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2369  if (PacketAlertCheck(p, 1) != 1) {
2370  printf("if (PacketAlertCheck(p, 1) != 1) failure\n");
2371  goto end;
2372  }
2373  if (PacketAlertCheck(p, 2) != 1) {
2374  printf("if (PacketAlertCheck(p, 1) != 2) failure\n");
2375  goto end;
2376  }
2377 
2378  result = 1;
2379 end:
2380  if (de_ctx != NULL) {
2383 
2384  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2386  }
2387 
2388  UTHFreePackets(&p, 1);
2389  return result;
2390 }
2391 
2392 void SCACTileRegisterTests(void)
2393 {
2394  UtRegisterTest("SCACTileTest01", SCACTileTest01);
2395  UtRegisterTest("SCACTileTest02", SCACTileTest02);
2396  UtRegisterTest("SCACTileTest03", SCACTileTest03);
2397  UtRegisterTest("SCACTileTest04", SCACTileTest04);
2398  UtRegisterTest("SCACTileTest05", SCACTileTest05);
2399  UtRegisterTest("SCACTileTest06", SCACTileTest06);
2400  UtRegisterTest("SCACTileTest07", SCACTileTest07);
2401  UtRegisterTest("SCACTileTest08", SCACTileTest08);
2402  UtRegisterTest("SCACTileTest09", SCACTileTest09);
2403  UtRegisterTest("SCACTileTest10", SCACTileTest10);
2404  UtRegisterTest("SCACTileTest11", SCACTileTest11);
2405  UtRegisterTest("SCACTileTest12", SCACTileTest12);
2406  UtRegisterTest("SCACTileTest13", SCACTileTest13);
2407  UtRegisterTest("SCACTileTest14", SCACTileTest14);
2408  UtRegisterTest("SCACTileTest15", SCACTileTest15);
2409  UtRegisterTest("SCACTileTest16", SCACTileTest16);
2410  UtRegisterTest("SCACTileTest17", SCACTileTest17);
2411  UtRegisterTest("SCACTileTest18", SCACTileTest18);
2412  UtRegisterTest("SCACTileTest19", SCACTileTest19);
2413  UtRegisterTest("SCACTileTest20", SCACTileTest20);
2414  UtRegisterTest("SCACTileTest21", SCACTileTest21);
2415  UtRegisterTest("SCACTileTest22", SCACTileTest22);
2416  UtRegisterTest("SCACTileTest23", SCACTileTest23);
2417  UtRegisterTest("SCACTileTest24", SCACTileTest24);
2418  UtRegisterTest("SCACTileTest25", SCACTileTest25);
2419  UtRegisterTest("SCACTileTest26", SCACTileTest26);
2420  UtRegisterTest("SCACTileTest27", SCACTileTest27);
2421  UtRegisterTest("SCACTileTest28", SCACTileTest28);
2422  UtRegisterTest("SCACTileTest29", SCACTileTest29);
2423 }
2424 #endif
2425 
2426 #else /* we're big endian */
2427 
2428 void MpmACTileRegister(void)
2429 {
2430  /* no-op on big endian */
2431 }
2432 
2433 #endif /* little endian check */
SCACTileSearchCtx
struct SCACTileSearchCtx_ SCACTileSearchCtx
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
SCACTileSearchCtx_
Definition: util-mpm-ac-ks.h:115
MpmPatternIndex
uint32_t MpmPatternIndex
Definition: util-mpm.h:44
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
MpmThreadCtx_
Definition: util-mpm.h:46
SCACTileSearchSmall256
uint32_t SCACTileSearchSmall256(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
MpmFreePattern
void MpmFreePattern(MpmCtx *mpm_ctx, MpmPattern *p)
Definition: util-mpm.c:357
SCACTileSearchCtx_::Search
uint32_t(* Search)(const struct SCACTileSearchCtx_ *ctx, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm-ac-ks.h:122
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
MpmTableElmt_::name
const char * name
Definition: util-mpm.h:147
STATE_QUEUE_CONTAINER_SIZE
#define STATE_QUEUE_CONTAINER_SIZE
Definition: util-mpm-ac-ks.c:150
PrefilterRuleStore_
structure for storing potential rule matches
Definition: util-prefilter.h:34
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
util-mpm-ac-ks.h
SCACTileSearchSmall32
uint32_t SCACTileSearchSmall32(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
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
StateQueue_
Helper structure used by AC during state table creation.
Definition: util-mpm-ac-ks.c:155
SC_AC_TILE_FAIL
#define SC_AC_TILE_FAIL
Definition: util-mpm-ac-ks.c:148
ctx
struct Thresholds ctx
SCACTilePatternList_::offset
uint16_t offset
Definition: util-mpm-ac-ks.h:33
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:843
MPM_FEATURE_FLAG_OFFSET
#define MPM_FEATURE_FLAG_OFFSET
Definition: util-mpm.h:143
util-memcpy.h
MpmCtx_::memory_size
uint32_t memory_size
Definition: util-mpm.h:103
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2623
SCACTileSearchTiny8
uint32_t SCACTileSearchTiny8(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
SCACTileOutputTable
struct SCACTileOutputTable_ SCACTileOutputTable
MpmTableElmt_::AddPatternNocase
int(* AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, SigIntId, uint8_t)
Definition: util-mpm.h:165
SCACTileSearchCtx_::output_table
SCACTileOutputTable * output_table
Definition: util-mpm-ac-ks.h:132
SCACTileSearchSmall128
uint32_t SCACTileSearchSmall128(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
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:164
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:359
MpmTableElmt_::feature_flags
uint8_t feature_flags
Definition: util-mpm.h:174
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1938
StateQueue
struct StateQueue_ StateQueue
Helper structure used by AC during state table creation.
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:55
SCACTileSearchCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm-ac-ks.h:141
SCACTileSearchCtx_::state_table
void * state_table
Definition: util-mpm-ac-ks.h:129
MpmTableElmt_::InitCtx
void(* InitCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:148
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
SCHECK
#define SCHECK(x)
Definition: util-mpm-ac-ks.c:1107
util-memcmp.h
SCACTileSearchCtx_::state_count
uint32_t state_count
Definition: util-mpm-ac-ks.h:139
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
Definition: util-mpm.c:210
Signature_::next
struct Signature_ * next
Definition: detect.h:675
MpmTableElmt_::PrintCtx
void(* PrintCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:169
SCACTileOutputTable_
Definition: util-mpm-ac-ks.h:44
util-debug.h
SCACTileSearchTiny16
uint32_t SCACTileSearchTiny16(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
MpmPattern_::next
struct MpmPattern_ * next
Definition: util-mpm.h:79
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1095
SCACTileSearchCtx_::mpm_bitarray_size
uint32_t mpm_bitarray_size
Definition: util-mpm-ac-ks.h:136
SCACTileSearchSmall8
uint32_t SCACTileSearchSmall8(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
SCACTileOutputTable_::patterns
MpmPatternIndex * patterns
Definition: util-mpm-ac-ks.h:46
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
SCACTilePatternList
struct SCACTilePatternList_ SCACTilePatternList
util-mpm-ac-ks-small.c
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3359
SCACTilePreparePatterns
int SCACTilePreparePatterns(MpmCtx *mpm_ctx)
Process the patterns added to the mpm, and create the internal tables.
Definition: util-mpm-ac-ks.c:864
MPM_FEATURE_FLAG_DEPTH
#define MPM_FEATURE_FLAG_DEPTH
Definition: util-mpm.h:142
SCACTileSearch
uint32_t SCACTileSearch(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-ks.c:1172
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2289
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:99
MPM_AC_KS
@ MPM_AC_KS
Definition: util-mpm.h:37
SCACTileSearchCtx_::init_ctx
SCACTileCtx * init_ctx
Definition: util-mpm-ac-ks.h:144
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2211
Packet_
Definition: decode.h:473
detect-engine-build.h
detect-engine-alert.h
conf.h
MPM_INIT_HASH_SIZE
#define MPM_INIT_HASH_SIZE
Definition: util-mpm.h:30
SCACTileSearchTiny128
uint32_t SCACTileSearchTiny128(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:166
SCACTilePatternList_::sids
SigIntId * sids
Definition: util-mpm-ac-ks.h:41
StateQueue_::bot
int bot
Definition: util-mpm-ac-ks.c:158
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:168
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:250
SCACTilePrintInfo
void SCACTilePrintInfo(MpmCtx *mpm_ctx)
Definition: util-mpm-ac-ks.c:1372
SCACTileSearchCtx_::pattern_list
SCACTilePatternList * pattern_list
Definition: util-mpm-ac-ks.h:133
SCACTileSearchTiny64
uint32_t SCACTileSearchTiny64(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
MpmACTileRegister
void MpmACTileRegister(void)
Register the aho-corasick mpm 'ks' originally developed by Ken Steele for Tilera Tile-Gx processor.
Definition: util-mpm-ac-ks.c:1398
SCACTilePatternList_::cs
uint8_t * cs
Definition: util-mpm-ac-ks.h:30
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2144
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:132
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
flags
uint8_t flags
Definition: decode-gre.h:0
SCACTilePatternList_::depth
uint16_t depth
Definition: util-mpm-ac-ks.h:34
suricata-common.h
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:97
SCACTilePatternList_::patlen
uint16_t patlen
Definition: util-mpm-ac-ks.h:31
SCACTileSearchTiny256
uint32_t SCACTileSearchTiny256(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
SCACTileAddPatternCI
int SCACTileAddPatternCI(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-ks.c:1338
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3586
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:851
util-validate.h
SCACTileCtx
struct SCACTileCtx_ SCACTileCtx
SCACTileCtx_
Definition: util-mpm-ac-ks.h:54
SCACTilePatternList_
Definition: util-mpm-ac-ks.h:29
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:150
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
MpmCtx_::memory_cnt
uint32_t memory_cnt
Definition: util-mpm.h:102
MpmCtx_::init_hash
MpmPattern ** init_hash
Definition: util-mpm.h:108
SCACTileInitCtx
void SCACTileInitCtx(MpmCtx *)
Initialize the AC context.
Definition: util-mpm-ac-ks.c:964
MpmPattern_::len
uint16_t len
Definition: util-mpm.h:56
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2584
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
SCACTileSearchLarge
uint32_t SCACTileSearchLarge(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
Definition: util-mpm-ac-ks.c:1185
SCACTileDestroyCtx
void SCACTileDestroyCtx(MpmCtx *)
Destroy the mpm context.
Definition: util-mpm-ac-ks.c:1065
suricata.h
PmqFree
void PmqFree(PrefilterRuleStore *pmq)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
SCACTileSearchTiny32
uint32_t SCACTileSearchTiny32(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
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:439
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:845
MpmCtx_
Definition: util-mpm.h:88
SigIntId
#define SigIntId
Definition: suricata-common.h:315
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCACTileSearchCtx_::translate_table
uint8_t translate_table[256]
Definition: util-mpm-ac-ks.h:126
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:259
SCACTileAddPatternCS
int SCACTileAddPatternCS(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-ks.c:1364
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
MpmTableElmt_::RegisterUnittests
void(* RegisterUnittests)(void)
Definition: util-mpm.h:172
PmqSetup
int PmqSetup(PrefilterRuleStore *pmq)
Setup a pmq.
Definition: util-prefilter.c:37
SCACTileSearchSmall16
uint32_t SCACTileSearchSmall16(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
SCACTileSearchSmall64
uint32_t SCACTileSearchSmall64(const SCACTileSearchCtx *ctx, MpmThreadCtx *mpm_thread_ctx, PrefilterRuleStore *pmq, const uint8_t *buf, uint32_t buflen)
StateQueue_::top
int top
Definition: util-mpm-ac-ks.c:157
StateQueue_::store
int32_t store[STATE_QUEUE_CONTAINER_SIZE]
Definition: util-mpm-ac-ks.c:156
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:450