suricata
detect-engine-sigorder.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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  * Signature ordering part of the detection engine.
24  */
25 
26 #include "suricata-common.h"
27 #include "detect.h"
28 #include "detect-xbits.h"
29 #include "detect-flowbits.h"
30 #include "detect-flowint.h"
31 #include "detect-parse.h"
32 #include "detect-engine-sigorder.h"
33 #include "detect-pcre.h"
34 
35 #include "util-unittest.h"
36 #include "util-unittest-helper.h"
37 #include "util-debug.h"
38 #include "util-action.h"
39 #include "action-globals.h"
40 #include "flow-util.h"
41 
42 #define DETECT_FLOWVAR_NOT_USED 1
43 #define DETECT_FLOWVAR_TYPE_READ 2
44 #define DETECT_FLOWVAR_TYPE_SET_READ 3
45 #define DETECT_FLOWVAR_TYPE_SET 4
46 
47 #define DETECT_PKTVAR_NOT_USED 1
48 #define DETECT_PKTVAR_TYPE_READ 2
49 #define DETECT_PKTVAR_TYPE_SET_READ 3
50 #define DETECT_PKTVAR_TYPE_SET 4
51 
52 #define DETECT_FLOWBITS_NOT_USED 1
53 #define DETECT_FLOWBITS_TYPE_READ 2
54 #define DETECT_FLOWBITS_TYPE_SET_READ 3
55 #define DETECT_FLOWBITS_TYPE_SET 4
56 
57 #define DETECT_FLOWINT_NOT_USED 1
58 #define DETECT_FLOWINT_TYPE_READ 2
59 #define DETECT_FLOWINT_TYPE_SET_READ 3
60 #define DETECT_FLOWINT_TYPE_SET 4
61 
62 #define DETECT_XBITS_NOT_USED 1
63 #define DETECT_XBITS_TYPE_READ 2
64 #define DETECT_XBITS_TYPE_SET_READ 3
65 #define DETECT_XBITS_TYPE_SET 4
66 
67 
68 /**
69  * \brief Registers a keyword-based, signature ordering function
70  *
71  * \param de_ctx Pointer to the detection engine context from which the
72  * signatures have to be ordered.
73  * \param FuncPtr Pointer to the signature ordering function. The prototype of
74  * the signature ordering function should accept a pointer to a
75  * SCSigSignatureWrapper as its argument and shouldn't return
76  * anything
77  */
78 static void SCSigRegisterSignatureOrderingFunc(DetectEngineCtx *de_ctx,
79  int (*SWCompare)(SCSigSignatureWrapper *sw1, SCSigSignatureWrapper *sw2))
80 {
81  SCSigOrderFunc *curr = NULL;
82  SCSigOrderFunc *prev = NULL;
83  SCSigOrderFunc *temp = NULL;
84 
85  curr = de_ctx->sc_sig_order_funcs;
86 
87  /* Walk to the end of the list, and leave prev pointing at the
88  last element. */
89  prev = curr;
90  while (curr != NULL) {
91  if (curr->SWCompare == SWCompare) {
92  /* Already specified this compare */
93  return;
94  }
95  prev = curr;
96  curr = curr->next;
97  }
98 
99  if ( (temp = SCMalloc(sizeof(SCSigOrderFunc))) == NULL) {
100  SCLogError(SC_ERR_FATAL, "Fatal error encountered in SCSigRegisterSignatureOrderingFunc. Exiting...");
101  exit(EXIT_FAILURE);
102  }
103  memset(temp, 0, sizeof(SCSigOrderFunc));
104 
105  temp->SWCompare = SWCompare;
106 
107  /* Append the new compare function at the end of the list. */
108  if (prev == NULL)
109  de_ctx->sc_sig_order_funcs = temp;
110  else
111  prev->next = temp;
112 
113  return;
114 }
115 
116 /**
117  * \brief Returns the flowbit type set for this signature. If more than one
118  * flowbit has been set for the same rule, we return the flowbit type of
119  * the maximum priority/value, where priority/value is maximum for the
120  * ones that set the value and the lowest for ones that read the value.
121  * If no flowbit has been set for the rule, we return 0, which indicates
122  * the least value amongst flowbit types.
123  *
124  * \param sig Pointer to the Signature from which the flowbit value has to be
125  * returned.
126  *
127  * \retval flowbits The flowbits type for this signature if it is set; if it is
128  * not set, return 0
129  */
130 static inline int SCSigGetFlowbitsType(Signature *sig)
131 {
132  DetectFlowbitsData *fb = NULL;
133  int flowbits_user_type = DETECT_FLOWBITS_NOT_USED;
134  int read = 0;
135  int write = 0;
137 
138  while (sm != NULL) {
139  if (sm->type == DETECT_FLOWBITS) {
140  fb = (DetectFlowbitsData *)sm->ctx;
141  if (fb->cmd == DETECT_FLOWBITS_CMD_ISNOTSET ||
143  read++;
144  } else {
145 #ifdef DEBUG
146  BUG_ON(1);
147 #endif
148  }
149  }
150 
151  sm = sm->next;
152  }
153 
155  while (sm != NULL) {
156  if (sm->type == DETECT_FLOWBITS) {
157  fb = (DetectFlowbitsData *)sm->ctx;
158  if (fb->cmd == DETECT_FLOWBITS_CMD_SET ||
161  write++;
162  } else {
163 #ifdef DEBUG
164  BUG_ON(1);
165 #endif
166  }
167  }
168 
169  sm = sm->next;
170  }
171 
172  if (read > 0 && write == 0) {
173  flowbits_user_type = DETECT_FLOWBITS_TYPE_READ;
174  } else if (read == 0 && write > 0) {
175  flowbits_user_type = DETECT_FLOWBITS_TYPE_SET;
176  } else if (read > 0 && write > 0) {
177  flowbits_user_type = DETECT_FLOWBITS_TYPE_SET_READ;
178  }
179 
180  SCLogDebug("Sig %s typeval %d", sig->msg, flowbits_user_type);
181 
182  return flowbits_user_type;
183 }
184 
185 static inline int SCSigGetFlowintType(Signature *sig)
186 {
187  DetectFlowintData *fi = NULL;
188  int flowint_user_type = DETECT_FLOWINT_NOT_USED;
189  int read = 0;
190  int write = 0;
192 
193  while (sm != NULL) {
194  if (sm->type == DETECT_FLOWINT) {
195  fi = (DetectFlowintData *)sm->ctx;
196  if (fi->modifier == FLOWINT_MODIFIER_LT ||
197  fi->modifier == FLOWINT_MODIFIER_LE ||
198  fi->modifier == FLOWINT_MODIFIER_EQ ||
199  fi->modifier == FLOWINT_MODIFIER_NE ||
200  fi->modifier == FLOWINT_MODIFIER_GE ||
201  fi->modifier == FLOWINT_MODIFIER_GT ||
204  read++;
205  } else {
206 #ifdef DEBUG
207  BUG_ON(1);
208 #endif
209  }
210  }
211 
212  sm = sm->next;
213  }
214 
216  while (sm != NULL) {
217  if (sm->type == DETECT_FLOWINT) {
218  fi = (DetectFlowintData *)sm->ctx;
219  if (fi->modifier == FLOWINT_MODIFIER_SET ||
222  write++;
223  } else {
224 #ifdef DEBUG
225  BUG_ON(1);
226 #endif
227  }
228  }
229 
230  sm = sm->next;
231  }
232 
233  if (read > 0 && write == 0) {
234  flowint_user_type = DETECT_FLOWINT_TYPE_READ;
235  } else if (read == 0 && write > 0) {
236  flowint_user_type = DETECT_FLOWINT_TYPE_SET;
237  } else if (read > 0 && write > 0) {
238  flowint_user_type = DETECT_FLOWINT_TYPE_SET_READ;
239  }
240 
241  SCLogDebug("Sig %s typeval %d", sig->msg, flowint_user_type);
242 
243  return flowint_user_type;
244 }
245 
246 /**
247  * \brief Returns whether the flowvar set for this rule, sets the flowvar or
248  * reads the flowvar. If the rule sets the flowvar the function returns
249  * DETECT_FLOWVAR_TYPE_SET(3), if it reads the flowvar the function
250  * returns DETECT_FLOWVAR_TYPE_READ(2), and if flowvar is not used in this
251  * rule the function returns DETECT_FLOWVAR_NOT_USED(1)
252  *
253  * \param sig Pointer to the Signature from which the flowvar type has to be
254  * returned.
255  *
256  * \retval type DETECT_FLOWVAR_TYPE_SET(3) if the rule sets the flowvar,
257  * DETECT_FLOWVAR_TYPE_READ(2) if it reads, and
258  * DETECT_FLOWVAR_NOT_USED(1) if flowvar is not used.
259  */
260 static inline int SCSigGetFlowvarType(Signature *sig)
261 {
262  DetectPcreData *pd = NULL;
264  int read = 0;
265  int write = 0;
267 
268  while (sm != NULL) {
269  pd = (DetectPcreData *)sm->ctx;
270  if (sm->type == DETECT_PCRE) {
271  uint8_t x;
272  for (x = 0; x < pd->idx; x++) {
273  if (pd->captypes[x] == VAR_TYPE_FLOW_VAR) {
274  write++;
275  break;
276  }
277  }
278  }
279 
280  sm = sm->next;
281  }
282 
284  pd = NULL;
285  while (sm != NULL) {
286  if (sm->type == DETECT_FLOWVAR) {
287  read++;
288  }
289 
290  sm = sm->next;
291  }
292 
293  if (read > 0 && write == 0) {
295  } else if (read == 0 && write > 0) {
297  } else if (read > 0 && write > 0) {
299  }
300 
301  return type;
302 }
303 
304 /**
305  * \brief Returns whether the pktvar set for this rule, sets the flowvar or
306  * reads the pktvar. If the rule sets the pktvar the function returns
307  * DETECT_PKTVAR_TYPE_SET(3), if it reads the pktvar the function
308  * returns DETECT_PKTVAR_TYPE_READ(2), and if pktvar is not used in this
309  * rule the function returns DETECT_PKTVAR_NOT_USED(1)
310  *
311  * \param sig Pointer to the Signature from which the pktvar type has to be
312  * returned.
313  *
314  * \retval type DETECT_PKTVAR_TYPE_SET(3) if the rule sets the flowvar,
315  * DETECT_PKTVAR_TYPE_READ(2) if it reads, and
316  * DETECT_PKTVAR_NOT_USED(1) if pktvar is not used.
317  */
318 static inline int SCSigGetPktvarType(Signature *sig)
319 {
320  DetectPcreData *pd = NULL;
322  int read = 0;
323  int write = 0;
325 
326  while (sm != NULL) {
327  pd = (DetectPcreData *)sm->ctx;
328  if (sm->type == DETECT_PCRE) {
329  uint8_t x;
330  for (x = 0; x < pd->idx; x++) {
331  if (pd->captypes[x] == VAR_TYPE_PKT_VAR) {
332  write++;
333  break;
334  }
335  }
336  }
337 
338  sm = sm->next;
339  }
340 
342  pd = NULL;
343  while (sm != NULL) {
344  if (sm->type == DETECT_PKTVAR) {
345  read++;
346  }
347 
348  sm = sm->next;
349  }
350 
351  if (read > 0 && write == 0) {
353  } else if (read == 0 && write > 0) {
354  type = DETECT_PKTVAR_TYPE_SET;
355  } else if (read > 0 && write > 0) {
357  }
358 
359  return type;
360 }
361 
362 /**
363  * \brief Returns the xbit type set for this signature. If more than one
364  * xbit has been set for the same rule, we return the xbit type of
365  * the maximum priority/value, where priority/value is maximum for the
366  * ones that set the value and the lowest for ones that read the value.
367  * If no xbit has been set for the rule, we return 0, which indicates
368  * the least value amongst xbit types.
369  *
370  * \param sig Pointer to the Signature from which the xbit value has to be
371  * returned.
372  *
373  * \retval xbits The xbits type for this signature if it is set; if it is
374  * not set, return 0
375  */
376 static inline int SCSigGetXbitsType(Signature *sig, enum VarTypes type)
377 {
378  DetectXbitsData *fb = NULL;
379  int xbits_user_type = DETECT_XBITS_NOT_USED;
380  int read = 0;
381  int write = 0;
383 
384  while (sm != NULL) {
385  if (sm->type == DETECT_XBITS) {
386  fb = (DetectXbitsData *)sm->ctx;
387  if (fb->type == type) {
388  if (fb->cmd == DETECT_XBITS_CMD_ISNOTSET ||
389  fb->cmd == DETECT_XBITS_CMD_ISSET) {
390  read++;
391  } else {
392 #ifdef DEBUG
393  BUG_ON(1);
394 #endif
395  }
396  }
397  }
398 
399  sm = sm->next;
400  }
401 
403  while (sm != NULL) {
404  if (sm->type == DETECT_HOSTBITS) {
405  fb = (DetectXbitsData *)sm->ctx;
406  if (fb->type == type) {
407  if (fb->cmd == DETECT_XBITS_CMD_SET ||
408  fb->cmd == DETECT_XBITS_CMD_UNSET ||
409  fb->cmd == DETECT_XBITS_CMD_TOGGLE) {
410  write++;
411  } else {
412 #ifdef DEBUG
413  BUG_ON(1);
414 #endif
415  }
416  }
417  }
418 
419  sm = sm->next;
420  }
421 
422  if (read > 0 && write == 0) {
423  xbits_user_type = DETECT_XBITS_TYPE_READ;
424  } else if (read == 0 && write > 0) {
425  xbits_user_type = DETECT_XBITS_TYPE_SET;
426  } else if (read > 0 && write > 0) {
427  xbits_user_type = DETECT_XBITS_TYPE_SET_READ;
428  }
429 
430  SCLogDebug("Sig %s typeval %d", sig->msg, xbits_user_type);
431 
432  return xbits_user_type;
433 }
434 
435 /**
436  * \brief Processes the flowbits data for this signature and caches it for
437  * future use. This is needed to optimize the sig_ordering module.
438  *
439  * \param sw The sigwrapper/signature for which the flowbits data has to be
440  * cached
441  */
442 static inline void SCSigProcessUserDataForFlowbits(SCSigSignatureWrapper *sw)
443 {
444  sw->user[SC_RADIX_USER_DATA_FLOWBITS] = SCSigGetFlowbitsType(sw->sig);
445 }
446 
447 /**
448  * \brief Processes the flowvar data for this signature and caches it for
449  * future use. This is needed to optimize the sig_ordering module.
450  *
451  * \param sw The sigwrapper/signature for which the flowvar data has to be
452  * cached
453  */
454 static inline void SCSigProcessUserDataForFlowvar(SCSigSignatureWrapper *sw)
455 {
456  sw->user[SC_RADIX_USER_DATA_FLOWVAR] = SCSigGetFlowvarType(sw->sig);
457 }
458 
459 static inline void SCSigProcessUserDataForFlowint(SCSigSignatureWrapper *sw)
460 {
461  sw->user[SC_RADIX_USER_DATA_FLOWINT] = SCSigGetFlowintType(sw->sig);
462 }
463 
464 /**
465  * \brief Processes the pktvar data for this signature and caches it for
466  * future use. This is needed to optimize the sig_ordering module.
467  *
468  * \param sw The sigwrapper/signature for which the pktvar data has to be
469  * cached
470  */
471 static inline void SCSigProcessUserDataForPktvar(SCSigSignatureWrapper *sw)
472 {
473  sw->user[SC_RADIX_USER_DATA_PKTVAR] = SCSigGetPktvarType(sw->sig);
474 }
475 
476 /**
477  * \brief Processes the hostbits data for this signature and caches it for
478  * future use. This is needed to optimize the sig_ordering module.
479  *
480  * \param sw The sigwrapper/signature for which the hostbits data has to be
481  * cached
482  */
483 static inline void SCSigProcessUserDataForHostbits(SCSigSignatureWrapper *sw)
484 {
485  sw->user[SC_RADIX_USER_DATA_HOSTBITS] = SCSigGetXbitsType(sw->sig, VAR_TYPE_HOST_BIT);
486 }
487 
488 /**
489  * \brief Processes the hostbits data for this signature and caches it for
490  * future use. This is needed to optimize the sig_ordering module.
491  *
492  * \param sw The sigwrapper/signature for which the hostbits data has to be
493  * cached
494  */
495 static inline void SCSigProcessUserDataForIPPairbits(SCSigSignatureWrapper *sw)
496 {
497  sw->user[SC_RADIX_USER_DATA_IPPAIRBITS] = SCSigGetXbitsType(sw->sig, VAR_TYPE_IPPAIR_BIT);
498 }
499 
500 /* Return 1 if sw1 comes before sw2 in the final list. */
501 static int SCSigLessThan(SCSigSignatureWrapper *sw1,
503  SCSigOrderFunc *cmp_func_list)
504 {
505  SCSigOrderFunc *funcs = cmp_func_list;
506 
507  while (funcs != NULL) {
508  int delta = funcs->SWCompare(sw1, sw2);
509  if (delta > 0)
510  return 1;
511  else if (delta < 0)
512  return 0;
513 
514  funcs = funcs->next;
515  }
516  // They are equal, so use sid as the final decider.
517  return sw1->sig->id < sw2->sig->id;
518 }
519 
520 /* Merge sort based on a list of compare functions */
521 static SCSigSignatureWrapper *SCSigOrder(SCSigSignatureWrapper *sw,
522  SCSigOrderFunc *cmp_func_list)
523 {
524  SCSigSignatureWrapper *subA = NULL;
525  SCSigSignatureWrapper *subB = NULL;
526  SCSigSignatureWrapper *first;
527  SCSigSignatureWrapper *second;
528  SCSigSignatureWrapper *result = NULL;
529  SCSigSignatureWrapper *last = NULL;
530  SCSigSignatureWrapper *new = NULL;
531 
532  /* Divide input list into two sub-lists. */
533  while (sw != NULL) {
534  first = sw;
535  sw = sw->next;
536  /* Push the first element onto sub-list A */
537  first->next = subA;
538  subA = first;
539 
540  if (sw == NULL)
541  break;
542  second = sw;
543  sw = sw->next;
544  /* Push the second element onto sub-list B */
545  second->next = subB;
546  subB = second;
547  }
548  if (subB == NULL) {
549  /* Only zero or one element on the list. */
550  return subA;
551  }
552 
553  /* Now sort each list */
554  subA = SCSigOrder(subA, cmp_func_list);
555  subB = SCSigOrder(subB, cmp_func_list);
556 
557  /* Merge the two sorted lists. */
558  while (subA != NULL && subB != NULL) {
559  if (SCSigLessThan(subA, subB, cmp_func_list)) {
560  new = subA;
561  subA = subA->next;
562  } else {
563  new = subB;
564  subB = subB->next;
565  }
566  /* Push onto the end of the output list. */
567  new->next = NULL;
568  if (result == NULL) {
569  result = new;
570  last = new;
571  } else {
572  last->next = new;
573  last = new;
574  }
575  }
576  /* Attach the rest of any remaining list. Only one can be non-NULL here. */
577  if (subA == NULL)
578  last->next = subB;
579  else if (subB == NULL)
580  last->next = subA;
581 
582  return result;
583 }
584 
585 /**
586  * \brief Orders an incoming Signature based on its action
587  *
588  * \param de_ctx Pointer to the detection engine context from which the
589  * signatures have to be ordered.
590  * \param sw The new signature that has to be ordered based on its action
591  */
592 static int SCSigOrderByActionCompare(SCSigSignatureWrapper *sw1,
594 {
595  return ActionOrderVal(sw2->sig->action) - ActionOrderVal(sw1->sig->action);
596 }
597 
598 /**
599  * \brief Orders an incoming Signature based on its flowbits type
600  *
601  * \param de_ctx Pointer to the detection engine context from which the
602  * signatures have to be ordered.
603  * \param sw The new signature that has to be ordered based on its flowbits
604  */
605 static int SCSigOrderByFlowbitsCompare(SCSigSignatureWrapper *sw1,
607 {
608  return sw1->user[SC_RADIX_USER_DATA_FLOWBITS] -
610 }
611 
612 /**
613  * \brief Orders an incoming Signature based on its flowvar type
614  *
615  * \param de_ctx Pointer to the detection engine context from which the
616  * signatures have to be ordered.
617  * \param sw The new signature that has to be ordered based on its flowvar
618  */
619 static int SCSigOrderByFlowvarCompare(SCSigSignatureWrapper *sw1,
621 {
622  return sw1->user[SC_RADIX_USER_DATA_FLOWVAR] -
624 }
625 
626 /**
627  * \brief Orders an incoming Signature based on its pktvar type
628  *
629  * \param de_ctx Pointer to the detection engine context from which the
630  * signatures have to be ordered.
631  * \param sw The new signature that has to be ordered based on its pktvar
632  */
633 static int SCSigOrderByPktvarCompare(SCSigSignatureWrapper *sw1,
635 {
636  return sw1->user[SC_RADIX_USER_DATA_PKTVAR] -
638 }
639 
640 static int SCSigOrderByFlowintCompare(SCSigSignatureWrapper *sw1,
642 {
643  return sw1->user[SC_RADIX_USER_DATA_FLOWINT] -
645 }
646 
647 /**
648  * \brief Orders an incoming Signature based on its hostbits type
649  *
650  * \param de_ctx Pointer to the detection engine context from which the
651  * signatures have to be ordered.
652  * \param sw The new signature that has to be ordered based on its hostbits
653  */
654 static int SCSigOrderByHostbitsCompare(SCSigSignatureWrapper *sw1,
656 {
657  return sw1->user[SC_RADIX_USER_DATA_HOSTBITS] -
659 }
660 
661 /**
662  * \brief Orders an incoming Signature based on its ippairbits (xbits) type
663  *
664  * \param de_ctx Pointer to the detection engine context from which the
665  * signatures have to be ordered.
666  * \param sw The new signature that has to be ordered based on its bits
667  */
668 static int SCSigOrderByIPPairbitsCompare(SCSigSignatureWrapper *sw1,
670 {
671  return sw1->user[SC_RADIX_USER_DATA_IPPAIRBITS] -
673 }
674 
675 /**
676  * \brief Orders an incoming Signature based on its priority type
677  *
678  * \param de_ctx Pointer to the detection engine context from which the
679  * signatures have to be ordered.
680  * \param sw The new signature that has to be ordered based on its priority
681  */
682 static int SCSigOrderByPriorityCompare(SCSigSignatureWrapper *sw1,
684 {
685  return sw2->sig->prio - sw1->sig->prio;
686 }
687 
688 /**
689  * \brief Creates a Wrapper around the Signature
690  *
691  * \param Pointer to the Signature to be wrapped
692  *
693  * \retval sw Pointer to the wrapper that holds the signature
694  */
695 static inline SCSigSignatureWrapper *SCSigAllocSignatureWrapper(Signature *sig)
696 {
697  SCSigSignatureWrapper *sw = NULL;
698 
699  if ( (sw = SCMalloc(sizeof(SCSigSignatureWrapper))) == NULL)
700  return NULL;
701  memset(sw, 0, sizeof(SCSigSignatureWrapper));
702 
703  sw->sig = sig;
704 
705  /* Process data from the signature into a cache for further use by the
706  * sig_ordering module */
707  SCSigProcessUserDataForFlowbits(sw);
708  SCSigProcessUserDataForFlowvar(sw);
709  SCSigProcessUserDataForFlowint(sw);
710  SCSigProcessUserDataForPktvar(sw);
711  SCSigProcessUserDataForHostbits(sw);
712  SCSigProcessUserDataForIPPairbits(sw);
713 
714  return sw;
715 }
716 
717 /**
718  * \brief Orders the signatures
719  *
720  * \param de_ctx Pointer to the Detection Engine Context that holds the
721  * signatures to be ordered
722  */
724 {
725  Signature *sig = NULL;
726  SCSigSignatureWrapper *sigw = NULL;
727  SCSigSignatureWrapper *sigw_list = NULL;
728 
729  int i = 0;
730  SCLogDebug("ordering signatures in memory");
731 
732  sig = de_ctx->sig_list;
733  while (sig != NULL) {
734  sigw = SCSigAllocSignatureWrapper(sig);
735  /* Push signature wrapper onto a list, order doesn't matter here. */
736  sigw->next = sigw_list;
737  sigw_list = sigw;
738 
739  sig = sig->next;
740  i++;
741  }
742 
743  /* Sort the list */
744  sigw_list = SCSigOrder(sigw_list, de_ctx->sc_sig_order_funcs);
745 
746  SCLogDebug("Total Signatures to be processed by the"
747  "sigordering module: %d", i);
748 
749  /* Recreate the sig list in order */
750  de_ctx->sig_list = NULL;
751  sigw = sigw_list;
752  i = 0;
753  while (sigw != NULL) {
754  i++;
755  sigw->sig->next = NULL;
756  if (de_ctx->sig_list == NULL) {
757  /* First entry on the list */
758  de_ctx->sig_list = sigw->sig;
759  sig = de_ctx->sig_list;
760  } else {
761  sig->next = sigw->sig;
762  sig = sig->next;
763  }
764  SCSigSignatureWrapper *sigw_to_free = sigw;
765  sigw = sigw->next;
766  SCFree(sigw_to_free);
767  }
768 
769  SCLogDebug("total signatures reordered by the sigordering module: %d", i);
770 }
771 
772 /**
773  * \brief Lets you register the Signature ordering functions. The order in
774  * which the functions are registered, show the priority. The first
775  * function registered provides more priority than the function
776  * registered after it. To add a new registration function, register
777  * it by listing it in the correct position in the below sequence,
778  * based on the priority you would want to offer to that keyword.
779  *
780  * \param de_ctx Pointer to the detection engine context from which the
781  * signatures have to be ordered.
782  */
784 {
785  SCLogDebug("registering signature ordering functions");
786 
787  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
788  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
789  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowintCompare);
790  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
791  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
792  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByHostbitsCompare);
793  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByIPPairbitsCompare);
794  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
795 }
796 
797 /**
798  * \brief De-registers all the signature ordering functions registered
799  *
800  * \param de_ctx Pointer to the detection engine context from which the
801  * signatures were ordered.
802  */
804 {
805  SCSigOrderFunc *funcs;
806  void *temp;
807 
808  /* clean the memory alloted to the signature ordering funcs */
809  funcs = de_ctx->sc_sig_order_funcs;
810  while (funcs != NULL) {
811  temp = funcs;
812  funcs = funcs->next;
813  SCFree(temp);
814  }
815  de_ctx->sc_sig_order_funcs = NULL;
816 }
817 
818 /**********Unittests**********/
819 
821 Signature *SigInit(DetectEngineCtx *, const char *);
822 void SigFree(Signature *);
824 
825 #ifdef UNITTESTS
826 
827 static int SCSigOrderingTest01(void)
828 {
829  SCSigOrderFunc *temp = NULL;
830  int i = 0;
831 
833  if (de_ctx == NULL)
834  goto end;
835 
836  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
837  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
838  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
839  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
840  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
841  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
842  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
843  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
844  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
845  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
846  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
847 
848  temp = de_ctx->sc_sig_order_funcs;
849  while (temp != NULL) {
850  i++;
851  temp = temp->next;
852  }
853 
854  DetectEngineCtxFree(de_ctx);
855 
856  return (i == 5);
857  end:
858  return 0;
859 }
860 
861 static int SCSigOrderingTest02(void)
862 {
863  Signature *sig = NULL;
864 
866  FAIL_IF(de_ctx == NULL);
867 
868  sig = DetectEngineAppendSig(de_ctx,
869  "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:1;)");
870  FAIL_IF_NULL(sig);
871 
872  sig = DetectEngineAppendSig(de_ctx,
873  "drop tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:2;)");
874  FAIL_IF_NULL(sig);
875 
876  sig = DetectEngineAppendSig(de_ctx,
877  "drop tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:3;)");
878  FAIL_IF_NULL(sig);
879 
880  sig = DetectEngineAppendSig(de_ctx,
881  "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; flowvar:http_host,\"www.oisf.net\"; rev:4; priority:1; sid:4;)");
882  FAIL_IF_NULL(sig);
883 
884  sig = DetectEngineAppendSig(de_ctx,
885  "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:1; sid:5;)");
886  FAIL_IF_NULL(sig);
887 
888  sig = DetectEngineAppendSig(de_ctx,
889  "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; pcre:\"/^User-Agent: (?P<flow_http_host>.*)\\r\\n/m\"; content:\"220\"; offset:10; depth:4; rev:4; priority:3; sid:6;)");
890  FAIL_IF_NULL(sig);
891 
892  sig = DetectEngineAppendSig(de_ctx,
893  "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:3; sid:7;)");
894  FAIL_IF_NULL(sig);
895 
896  sig = DetectEngineAppendSig(de_ctx,
897  "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:8;)");
898  FAIL_IF_NULL(sig);
899 
900  sig = DetectEngineAppendSig(de_ctx,
901  "drop tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; rev:4; priority:3; flowbits:set,TEST.one; flowbits:noalert; sid:9;)");
902  FAIL_IF_NULL(sig);
903 
904  sig = DetectEngineAppendSig(de_ctx,
905  "pass tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:3; sid:10;)");
906  FAIL_IF_NULL(sig);
907 
908  sig = DetectEngineAppendSig(de_ctx,
909  "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:11;)");
910  FAIL_IF_NULL(sig);
911 
912  sig = DetectEngineAppendSig(de_ctx,
913  "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:12;)");
914  FAIL_IF_NULL(sig);
915 
916  sig = DetectEngineAppendSig(de_ctx,
917  "drop tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; pktvar:http_host,\"www.oisf.net\"; priority:2; flowbits:isnotset,TEST.two; sid:13;)");
918  FAIL_IF_NULL(sig);
919 
920  sig = DetectEngineAppendSig(de_ctx,
921  "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; flowbits:set,TEST.two; sid:14;)");
922  FAIL_IF_NULL(sig);
923 
924  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
925  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
926  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
927  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
928  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
929  SCSigOrderSignatures(de_ctx);
930 
931  sig = de_ctx->sig_list;
932 
933 #ifdef DEBUG
934  while (sig != NULL) {
935  printf("sid: %d\n", sig->id);
936  sig = sig->next;
937  }
938 #endif
939 
940  sig = de_ctx->sig_list;
941 
942  /* pass */
943  FAIL_IF_NOT(sig->id == 6);
944  sig = sig->next;
945  FAIL_IF_NOT(sig->id == 4);
946  sig = sig->next;
947  FAIL_IF_NOT(sig->id == 8);
948  sig = sig->next;
949  FAIL_IF_NOT(sig->id == 7);
950  sig = sig->next;
951  FAIL_IF_NOT(sig->id == 10);
952  sig = sig->next;
953 
954  /* drops */
955  FAIL_IF_NOT(sig->id == 9);
956  sig = sig->next;
957  FAIL_IF_NOT(sig->id == 13);
958  sig = sig->next;
959  FAIL_IF_NOT(sig->id == 2);
960  sig = sig->next;
961  FAIL_IF_NOT(sig->id == 3);
962  sig = sig->next;
963 
964  /* alerts */
965  FAIL_IF_NOT(sig->id == 14);
966  sig = sig->next;
967  FAIL_IF_NOT(sig->id == 5);
968  sig = sig->next;
969  FAIL_IF_NOT(sig->id == 1);
970  sig = sig->next;
971  FAIL_IF_NOT(sig->id == 11);
972  sig = sig->next;
973  FAIL_IF_NOT(sig->id == 12);
974  sig = sig->next;
975 
976  DetectEngineCtxFree(de_ctx);
977  PASS;
978 }
979 
980 static int SCSigOrderingTest03(void)
981 {
982  int result = 0;
983  Signature *prevsig = NULL, *sig = NULL;
984 
986  if (de_ctx == NULL)
987  goto end;
988 
989  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:3; sid:1;)");
990  if (sig == NULL) {
991  goto end;
992  }
993  prevsig = sig;
994  de_ctx->sig_list = sig;
995 
996  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:2;)");
997  if (sig == NULL) {
998  goto end;
999  }
1000  prevsig->next = sig;
1001  prevsig = sig;
1002 
1003  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P<flow_http_host>.*)\\r\\n/m\"; flowbits:unset,TEST.one; rev:4; priority:2; sid:3;)");
1004  if (sig == NULL) {
1005  goto end;
1006  }
1007  prevsig->next = sig;
1008  prevsig = sig;
1009 
1010  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; flowbits:isset,TEST.one; rev:4; priority:1; sid:4;)");
1011  if (sig == NULL) {
1012  goto end;
1013  }
1014  prevsig->next = sig;
1015  prevsig = sig;
1016 
1017  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; priority:2; sid:5;)");
1018  if (sig == NULL) {
1019  goto end;
1020  }
1021  prevsig->next = sig;
1022  prevsig = sig;
1023 
1024  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; flowbits:isnotset,TEST.one; pcre:\"/^User-Agent: (?P<flow_http_host>.*)\\r\\n/m\"; rev:4; sid:6;)");
1025  if (sig == NULL) {
1026  goto end;
1027  }
1028  prevsig->next = sig;
1029  prevsig = sig;
1030 
1031  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; flowbits:unset,TEST.one; rev:4; priority:3; sid:7;)");
1032  if (sig == NULL) {
1033  goto end;
1034  }
1035  prevsig->next = sig;
1036  prevsig = sig;
1037 
1038  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/220[- ]/\"; flowbits:toggle,TEST.one; rev:4; priority:1; pktvar:http_host,\"www.oisf.net\"; sid:8;)");
1039  if (sig == NULL) {
1040  goto end;
1041  }
1042  prevsig->next = sig;
1043  prevsig = sig;
1044 
1045 
1046  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; rev:4; flowbits:set,TEST.one; flowbits:noalert; pktvar:http_host,\"www.oisf.net\"; sid:9;)");
1047  if (sig == NULL) {
1048  goto end;
1049  }
1050  prevsig->next = sig;
1051  prevsig = sig;
1052 
1053  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:3; sid:10;)");
1054  if (sig == NULL) {
1055  goto end;
1056  }
1057  prevsig->next = sig;
1058  prevsig = sig;
1059 
1060  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:11;)");
1061  if (sig == NULL) {
1062  goto end;
1063  }
1064  prevsig->next = sig;
1065  prevsig = sig;
1066 
1067  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:12;)");
1068  if (sig == NULL) {
1069  goto end;
1070  }
1071  prevsig->next = sig;
1072  prevsig = sig;
1073 
1074  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; flowbits:isnotset,TEST.one; sid:13;)");
1075  if (sig == NULL) {
1076  goto end;
1077  }
1078  prevsig->next = sig;
1079  prevsig = sig;
1080 
1081  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; flowbits:set,TEST.one; sid:14;)");
1082  if (sig == NULL) {
1083  goto end;
1084  }
1085  prevsig->next = sig;
1086  prevsig = sig;
1087 
1088  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1089  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1090  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1091  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1092  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1093  SCSigOrderSignatures(de_ctx);
1094 
1095  result = 1;
1096 
1097  sig = de_ctx->sig_list;
1098 
1099 #ifdef DEBUG
1100  while (sig != NULL) {
1101  printf("sid: %d\n", sig->id);
1102  sig = sig->next;
1103  }
1104 #endif
1105 
1106  sig = de_ctx->sig_list;
1107 
1108  result &= (sig->id == 3);
1109  sig = sig->next;
1110  result &= (sig->id == 8);
1111  sig = sig->next;
1112  result &= (sig->id == 9);
1113  sig = sig->next;
1114  result &= (sig->id == 7);
1115  sig = sig->next;
1116  result &= (sig->id == 14);
1117  sig = sig->next;
1118  result &= (sig->id == 6);
1119  sig = sig->next;
1120  result &= (sig->id == 4);
1121  sig = sig->next;
1122  result &= (sig->id == 13);
1123  sig = sig->next;
1124  result &= (sig->id == 2);
1125  sig = sig->next;
1126  result &= (sig->id == 5);
1127  sig = sig->next;
1128  result &= (sig->id == 1);
1129  sig = sig->next;
1130  result &= (sig->id == 10);
1131  sig = sig->next;
1132  result &= (sig->id == 11);
1133  sig = sig->next;
1134  result &= (sig->id == 12);
1135  sig = sig->next;
1136 
1137 end:
1138  if (de_ctx != NULL)
1139  DetectEngineCtxFree(de_ctx);
1140  return result;
1141 }
1142 
1143 static int SCSigOrderingTest04(void)
1144 {
1145  int result = 0;
1146  Signature *prevsig = NULL, *sig = NULL;
1147 
1149  if (de_ctx == NULL)
1150  goto end;
1151 
1152  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:1;)");
1153  if (sig == NULL) {
1154  goto end;
1155  }
1156  prevsig = sig;
1157  de_ctx->sig_list = sig;
1158 
1159  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; pcre:\"/^User-Agent: (?P<flow_http_host>.*)\\r\\n/m\"; content:\"220\"; offset:10; rev:4; priority:3; sid:2;)");
1160  if (sig == NULL) {
1161  goto end;
1162  }
1163  prevsig->next = sig;
1164  prevsig = sig;
1165 
1166  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P<flow_http_host>.*)\\r\\n/m\"; rev:4; priority:3; sid:3;)");
1167  if (sig == NULL) {
1168  goto end;
1169  }
1170  prevsig->next = sig;
1171  prevsig = sig;
1172 
1173  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P<flow_http_host>.*)\\r\\n/m\"; rev:4; priority:3; flowvar:http_host,\"www.oisf.net\"; sid:4;)");
1174  if (sig == NULL) {
1175  goto end;
1176  }
1177  prevsig->next = sig;
1178  prevsig = sig;
1179 
1180  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; pcre:\"/220[- ]/\"; rev:4; priority:3; sid:5;)");
1181  if (sig == NULL) {
1182  goto end;
1183  }
1184  prevsig->next = sig;
1185  prevsig = sig;
1186 
1187  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; pktvar:http_host,\"www.oisf.net\"; rev:4; priority:1; sid:6;)");
1188  if (sig == NULL) {
1189  goto end;
1190  }
1191  prevsig->next = sig;
1192  prevsig = sig;
1193 
1194  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; flowvar:http_host,\"www.oisf.net\"; pktvar:http_host,\"www.oisf.net\"; priority:1; sid:7;)");
1195  if (sig == NULL) {
1196  goto end;
1197  }
1198  prevsig->next = sig;
1199  prevsig = sig;
1200 
1201  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; flowvar:http_host,\"www.oisf.net\"; sid:8;)");
1202  if (sig == NULL) {
1203  goto end;
1204  }
1205  prevsig->next = sig;
1206  prevsig = sig;
1207 
1208  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; flowvar:http_host,\"www.oisf.net\"; sid:9;)");
1209  if (sig == NULL) {
1210  goto end;
1211  }
1212  prevsig->next = sig;
1213  prevsig = sig;
1214 
1215  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1216  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1217  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1218  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1219  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1220  SCSigOrderSignatures(de_ctx);
1221 
1222  result = 1;
1223 
1224  sig = de_ctx->sig_list;
1225 
1226 #ifdef DEBUG
1227  while (sig != NULL) {
1228  printf("sid: %d\n", sig->id);
1229  sig = sig->next;
1230  }
1231 #endif
1232 
1233  sig = de_ctx->sig_list;
1234 
1235  /* flowvar set */
1236  result &= (sig->id == 2);
1237  sig = sig->next;
1238  result &= (sig->id == 3);
1239  sig = sig->next;
1240  result &= (sig->id == 4);
1241  sig = sig->next;
1242  result &= (sig->id == 7);
1243  sig = sig->next;
1244  result &= (sig->id == 8);
1245  sig = sig->next;
1246  result &= (sig->id == 9);
1247  sig = sig->next;
1248 
1249  /* pktvar */
1250  result &= (sig->id == 5);
1251  sig = sig->next;
1252  result &= (sig->id == 6);
1253  sig = sig->next;
1254 
1255  result &= (sig->id == 1);
1256  sig = sig->next;
1257 
1258 end:
1259  if (de_ctx)
1260  DetectEngineCtxFree(de_ctx);
1261  return result;
1262 }
1263 
1264 static int SCSigOrderingTest05(void)
1265 {
1266  int result = 0;
1267  Signature *prevsig = NULL, *sig = NULL;
1268 
1270  if (de_ctx == NULL)
1271  goto end;
1272 
1273  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:1;)");
1274  if (sig == NULL) {
1275  goto end;
1276  }
1277  prevsig = sig;
1278  de_ctx->sig_list = sig;
1279 
1280  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; content:\"220\"; offset:10; rev:4; priority:3; sid:2;)");
1281  if (sig == NULL) {
1282  goto end;
1283  }
1284  prevsig->next = sig;
1285  prevsig = sig;
1286 
1287  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; rev:4; priority:3; sid:3;)");
1288  if (sig == NULL) {
1289  goto end;
1290  }
1291  prevsig->next = sig;
1292  prevsig = sig;
1293 
1294  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; pcre:\"/^User-Agent: (?P<pkt_http_host>.*)\\r\\n/m\"; rev:4; priority:3; pktvar:http_host,\"www.oisf.net\"; sid:4;)");
1295  if (sig == NULL) {
1296  goto end;
1297  }
1298  prevsig->next = sig;
1299  prevsig = sig;
1300 
1301  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:3; sid:5;)");
1302  if (sig == NULL) {
1303  goto end;
1304  }
1305  prevsig->next = sig;
1306  prevsig = sig;
1307 
1308  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:6;)");
1309  if (sig == NULL) {
1310  goto end;
1311  }
1312  prevsig->next = sig;
1313  prevsig = sig;
1314 
1315  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; pktvar:http_host,\"www.oisf.net\"; sid:7;)");
1316  if (sig == NULL) {
1317  goto end;
1318  }
1319  prevsig->next = sig;
1320  prevsig = sig;
1321  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; pktvar:http_host,\"www.oisf.net\"; sid:8;)");
1322  if (sig == NULL) {
1323  goto end;
1324  }
1325  prevsig->next = sig;
1326  prevsig = sig;
1327 
1328 
1329  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1330  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1331  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1332  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1333  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1334  SCSigOrderSignatures(de_ctx);
1335 
1336  result = 1;
1337 
1338  sig = de_ctx->sig_list;
1339 
1340  //#ifdef DEBUG
1341  while (sig != NULL) {
1342  printf("sid: %d\n", sig->id);
1343  sig = sig->next;
1344  }
1345  //#endif
1346 
1347  sig = de_ctx->sig_list;
1348 
1349  /* pktvar set */
1350  result &= (sig->id == 2);
1351  sig = sig->next;
1352  result &= (sig->id == 3);
1353  sig = sig->next;
1354  result &= (sig->id == 4);
1355  sig = sig->next;
1356  /* pktvar read */
1357  result &= (sig->id == 7);
1358  sig = sig->next;
1359  result &= (sig->id == 8);
1360  sig = sig->next;
1361 
1362  result &= (sig->id == 1);
1363  sig = sig->next;
1364  result &= (sig->id == 5);
1365  sig = sig->next;
1366  result &= (sig->id == 6);
1367  sig = sig->next;
1368 
1369 end:
1370  if (de_ctx != NULL)
1371  DetectEngineCtxFree(de_ctx);
1372  return result;
1373 }
1374 
1375 static int SCSigOrderingTest06(void)
1376 {
1377  int result = 0;
1378  Signature *prevsig = NULL, *sig = NULL;
1379 
1381  if (de_ctx == NULL)
1382  goto end;
1383 
1384  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:1;)");
1385  if (sig == NULL) {
1386  goto end;
1387  }
1388  prevsig = sig;
1389  de_ctx->sig_list = sig;
1390 
1391  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; rev:4; priority:2; sid:2;)");
1392  if (sig == NULL) {
1393  goto end;
1394  }
1395  prevsig->next = sig;
1396  prevsig = sig;
1397 
1398  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; rev:4; priority:3; sid:3;)");
1399  if (sig == NULL) {
1400  goto end;
1401  }
1402  prevsig->next = sig;
1403  prevsig = sig;
1404 
1405  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:10; depth:4; rev:4; priority:2; sid:4;)");
1406  if (sig == NULL) {
1407  goto end;
1408  }
1409  prevsig->next = sig;
1410  prevsig = sig;
1411 
1412  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:5;)");
1413  if (sig == NULL) {
1414  goto end;
1415  }
1416  prevsig->next = sig;
1417  prevsig = sig;
1418 
1419  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:1; sid:6;)");
1420  if (sig == NULL) {
1421  goto end;
1422  }
1423  prevsig->next = sig;
1424  prevsig = sig;
1425 
1426  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:7;)");
1427  if (sig == NULL) {
1428  goto end;
1429  }
1430  prevsig->next = sig;
1431  prevsig = sig;
1432 
1433  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:8;)");
1434  if (sig == NULL) {
1435  goto end;
1436  }
1437  prevsig->next = sig;
1438  prevsig = sig;
1439 
1440  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1441  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1442  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1443  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1444  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1445  SCSigOrderSignatures(de_ctx);
1446 
1447 
1448  result = 1;
1449 
1450  sig = de_ctx->sig_list;
1451 
1452 #ifdef DEBUG
1453  while (sig != NULL) {
1454  printf("sid: %d\n", sig->id);
1455  sig = sig->next;
1456  }
1457 #endif
1458 
1459  sig = de_ctx->sig_list;
1460 
1461  result &= (sig->id == 6);
1462  sig = sig->next;
1463  result &= (sig->id == 2);
1464  sig = sig->next;
1465  result &= (sig->id == 4);
1466  sig = sig->next;
1467  result &= (sig->id == 5);
1468  sig = sig->next;
1469  result &= (sig->id == 7);
1470  sig = sig->next;
1471  result &= (sig->id == 8);
1472  sig = sig->next;
1473  result &= (sig->id == 1);
1474  sig = sig->next;
1475  result &= (sig->id == 3);
1476  sig = sig->next;
1477 
1478 
1479 end:
1480  if (de_ctx != NULL)
1481  DetectEngineCtxFree(de_ctx);
1482  return result;
1483 }
1484 
1485 static int SCSigOrderingTest07(void)
1486 {
1487  int result = 0;
1488  Signature *prevsig = NULL, *sig = NULL;
1489 
1491  if (de_ctx == NULL)
1492  goto end;
1493 
1494  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1; rev:4;)");
1495  if (sig == NULL) {
1496  goto end;
1497  }
1498  prevsig = sig;
1499  de_ctx->sig_list = sig;
1500 
1501  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; sid:2; rev:4; priority:2;)");
1502  if (sig == NULL) {
1503  goto end;
1504  }
1505  prevsig->next = sig;
1506  prevsig = sig;
1507 
1508  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; sid:3; rev:4; priority:3;)");
1509  if (sig == NULL) {
1510  goto end;
1511  }
1512  prevsig->next = sig;
1513  prevsig = sig;
1514 
1515  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; sid:4; rev:4; priority:2;)");
1516  if (sig == NULL) {
1517  goto end;
1518  }
1519  prevsig->next = sig;
1520  prevsig = sig;
1521 
1522  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:5; rev:4; priority:2;)");
1523  if (sig == NULL) {
1524  goto end;
1525  }
1526  prevsig->next = sig;
1527  prevsig = sig;
1528 
1529  sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:6; rev:4; priority:1;)");
1530  if (sig == NULL) {
1531  goto end;
1532  }
1533  prevsig->next = sig;
1534  prevsig = sig;
1535 
1536  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:7; rev:4; priority:2;)");
1537  if (sig == NULL) {
1538  goto end;
1539  }
1540  prevsig->next = sig;
1541  prevsig = sig;
1542 
1543  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; sid:8; rev:4; priority:2;)");
1544  if (sig == NULL) {
1545  goto end;
1546  }
1547  prevsig->next = sig;
1548  prevsig = sig;
1549 
1550  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1551  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1552  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1553  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1554  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1555  SCSigOrderSignatures(de_ctx);
1556 
1557  result = 1;
1558 
1559  sig = de_ctx->sig_list;
1560 
1561 #ifdef DEBUG
1562  while (sig != NULL) {
1563  printf("sid: %d\n", sig->id);
1564  sig = sig->next;
1565  }
1566 #endif
1567 
1568  sig = de_ctx->sig_list;
1569 
1570  result &= (sig->id == 2);
1571  sig = sig->next;
1572  result &= (sig->id == 4);
1573  sig = sig->next;
1574  result &= (sig->id == 5);
1575  sig = sig->next;
1576  result &= (sig->id == 7);
1577  sig = sig->next;
1578  result &= (sig->id == 6);
1579  sig = sig->next;
1580  result &= (sig->id == 8);
1581  sig = sig->next;
1582  result &= (sig->id == 1);
1583  sig = sig->next;
1584  result &= (sig->id == 3);
1585  sig = sig->next;
1586 
1587 end:
1588  if (de_ctx != NULL)
1589  DetectEngineCtxFree(de_ctx);
1590  return result;
1591 }
1592 
1593 /**
1594  * \test Order with a different Action priority
1595  * (as specified from config)
1596  */
1597 static int SCSigOrderingTest08(void)
1598 {
1599 #ifdef HAVE_LIBNET11
1600  int result = 0;
1601  Signature *prevsig = NULL, *sig = NULL;
1602  extern uint8_t action_order_sigs[4];
1603 
1604  /* Let's change the order. Default is pass, drop, reject, alert (pass has highest prio) */
1605  action_order_sigs[0] = ACTION_REJECT;
1606  action_order_sigs[1] = ACTION_DROP;
1607  action_order_sigs[2] = ACTION_ALERT;
1608  action_order_sigs[3] = ACTION_PASS;
1609 
1611  if (de_ctx == NULL)
1612  goto end;
1613 
1614  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1; rev:4;)");
1615  if (sig == NULL) {
1616  goto end;
1617  }
1618  prevsig = sig;
1619  de_ctx->sig_list = sig;
1620 
1621  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; sid:2; rev:4; priority:2;)");
1622  if (sig == NULL) {
1623  goto end;
1624  }
1625  prevsig->next = sig;
1626  prevsig = sig;
1627 
1628  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; sid:3; rev:4; priority:3;)");
1629  if (sig == NULL) {
1630  goto end;
1631  }
1632  prevsig->next = sig;
1633  prevsig = sig;
1634 
1635  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; sid:4; rev:4; priority:2;)");
1636  if (sig == NULL) {
1637  goto end;
1638  }
1639  prevsig->next = sig;
1640  prevsig = sig;
1641 
1642  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:5; rev:4; priority:2;)");
1643  if (sig == NULL) {
1644  goto end;
1645  }
1646  prevsig->next = sig;
1647  prevsig = sig;
1648 
1649  sig = SigInit(de_ctx, "reject tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:6; rev:4; priority:1;)");
1650  if (sig == NULL) {
1651  goto end;
1652  }
1653  prevsig->next = sig;
1654  prevsig = sig;
1655 
1656  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; sid:7; rev:4;)");
1657  if (sig == NULL) {
1658  goto end;
1659  }
1660  prevsig->next = sig;
1661  prevsig = sig;
1662 
1663  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; sid:8; rev:4; priority:2;)");
1664  if (sig == NULL) {
1665  goto end;
1666  }
1667  prevsig->next = sig;
1668  prevsig = sig;
1669 
1670  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1671  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1672  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1673  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1674  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1675  SCSigOrderSignatures(de_ctx);
1676 
1677  result = 1;
1678 
1679  sig = de_ctx->sig_list;
1680 
1681 #ifdef DEBUG
1682  while (sig != NULL) {
1683  printf("sid: %d\n", sig->id);
1684  sig = sig->next;
1685  }
1686 #endif
1687 
1688  sig = de_ctx->sig_list;
1689 
1690  result &= (sig->id == 6);
1691  sig = sig->next;
1692  result &= (sig->id == 8);
1693  sig = sig->next;
1694  result &= (sig->id == 1);
1695  sig = sig->next;
1696  result &= (sig->id == 3);
1697  sig = sig->next;
1698  result &= (sig->id == 2);
1699  sig = sig->next;
1700  result &= (sig->id == 4);
1701  sig = sig->next;
1702  result &= (sig->id == 5);
1703  sig = sig->next;
1704  result &= (sig->id == 7);
1705  sig = sig->next;
1706 
1707 end:
1708  /* Restore the default pre-order definition */
1709  action_order_sigs[0] = ACTION_PASS;
1710  action_order_sigs[1] = ACTION_DROP;
1711  action_order_sigs[2] = ACTION_REJECT;
1712  action_order_sigs[3] = ACTION_ALERT;
1713  if (de_ctx != NULL)
1714  DetectEngineCtxFree(de_ctx);
1715  return result;
1716 #else
1717  return 1;
1718 #endif
1719 }
1720 
1721 /**
1722  * \test Order with a different Action priority
1723  * (as specified from config)
1724  */
1725 static int SCSigOrderingTest09(void)
1726 {
1727  int result = 0;
1728  Signature *prevsig = NULL, *sig = NULL;
1729  extern uint8_t action_order_sigs[4];
1730 
1731  /* Let's change the order. Default is pass, drop, reject, alert (pass has highest prio) */
1732  action_order_sigs[0] = ACTION_DROP;
1733  action_order_sigs[1] = ACTION_REJECT;
1734  action_order_sigs[2] = ACTION_ALERT;
1735  action_order_sigs[3] = ACTION_PASS;
1736 
1738  if (de_ctx == NULL)
1739  goto end;
1740 
1741  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:1;)");
1742  if (sig == NULL) {
1743  goto end;
1744  }
1745  prevsig = sig;
1746  de_ctx->sig_list = sig;
1747 
1748  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; priority:2; sid:2;)");
1749  if (sig == NULL) {
1750  goto end;
1751  }
1752  prevsig->next = sig;
1753  prevsig = sig;
1754 
1755  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; priority:3; sid:3;)");
1756  if (sig == NULL) {
1757  goto end;
1758  }
1759  prevsig->next = sig;
1760  prevsig = sig;
1761 
1762  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; rev:4; priority:2; sid:4;)");
1763  if (sig == NULL) {
1764  goto end;
1765  }
1766  prevsig->next = sig;
1767  prevsig = sig;
1768 
1769  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:5;)");
1770  if (sig == NULL) {
1771  goto end;
1772  }
1773  prevsig->next = sig;
1774  prevsig = sig;
1775 
1776  sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:1; sid:6;)");
1777  if (sig == NULL) {
1778  goto end;
1779  }
1780  prevsig->next = sig;
1781  prevsig = sig;
1782 
1783  sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:7;)");
1784  if (sig == NULL) {
1785  goto end;
1786  }
1787  prevsig->next = sig;
1788  prevsig = sig;
1789 
1790  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:8;)");
1791  if (sig == NULL) {
1792  goto end;
1793  }
1794  prevsig->next = sig;
1795  prevsig = sig;
1796 
1797  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1798  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1799  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1800  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1801  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1802  SCSigOrderSignatures(de_ctx);
1803 
1804  result = 1;
1805 
1806  sig = de_ctx->sig_list;
1807 
1808 #ifdef DEBUG
1809  while (sig != NULL) {
1810  printf("sid: %d\n", sig->id);
1811  sig = sig->next;
1812  }
1813 #endif
1814 
1815  sig = de_ctx->sig_list;
1816 
1817  result &= (sig->id == 6);
1818  sig = sig->next;
1819  result &= (sig->id == 7);
1820  sig = sig->next;
1821  result &= (sig->id == 8);
1822  sig = sig->next;
1823  result &= (sig->id == 1);
1824  sig = sig->next;
1825  result &= (sig->id == 3);
1826  sig = sig->next;
1827  result &= (sig->id == 2);
1828  sig = sig->next;
1829  result &= (sig->id == 4);
1830  sig = sig->next;
1831  result &= (sig->id == 5);
1832  sig = sig->next;
1833 
1834 end:
1835  /* Restore the default pre-order definition */
1836  action_order_sigs[0] = ACTION_DROP;
1837  action_order_sigs[1] = ACTION_REJECT;
1838  action_order_sigs[2] = ACTION_PASS;
1839  action_order_sigs[3] = ACTION_ALERT;
1840  if (de_ctx != NULL)
1841  DetectEngineCtxFree(de_ctx);
1842  return result;
1843 }
1844 
1845 /**
1846  * \test Order with a different Action priority
1847  * (as specified from config)
1848  */
1849 static int SCSigOrderingTest10(void)
1850 {
1851  int result = 0;
1852  Signature *prevsig = NULL, *sig = NULL;
1853  extern uint8_t action_order_sigs[4];
1854 
1855  /* Let's change the order. Default is pass, drop, reject, alert (pass has highest prio) */
1856  action_order_sigs[0] = ACTION_PASS;
1857  action_order_sigs[1] = ACTION_ALERT;
1858  action_order_sigs[2] = ACTION_DROP;
1859  action_order_sigs[3] = ACTION_REJECT;
1860 
1862  if (de_ctx == NULL)
1863  goto end;
1864 
1865  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; rev:4; sid:1;)");
1866  if (sig == NULL) {
1867  goto end;
1868  }
1869  prevsig = sig;
1870  de_ctx->sig_list = sig;
1871 
1872  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; rev:4; priority:2; sid:2;)");
1873  if (sig == NULL) {
1874  goto end;
1875  }
1876  prevsig->next = sig;
1877  prevsig = sig;
1878 
1879  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:10; depth:4; rev:4; priority:3; sid:3;)");
1880  if (sig == NULL) {
1881  goto end;
1882  }
1883  prevsig->next = sig;
1884  prevsig = sig;
1885 
1886  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:10; depth:4; rev:4; priority:2; sid:4;)");
1887  if (sig == NULL) {
1888  goto end;
1889  }
1890  prevsig->next = sig;
1891  prevsig = sig;
1892 
1893  sig = SigInit(de_ctx, "pass tcp any !21:902 -> any any (msg:\"Testing sigordering pass\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:5;)");
1894  if (sig == NULL) {
1895  goto end;
1896  }
1897  prevsig->next = sig;
1898  prevsig = sig;
1899 
1900  sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering drop\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:1; sid:6;)");
1901  if (sig == NULL) {
1902  goto end;
1903  }
1904  prevsig->next = sig;
1905  prevsig = sig;
1906 
1907  sig = SigInit(de_ctx, "drop tcp any !21:902 -> any any (msg:\"Testing sigordering reject\"; content:\"220\"; offset:11; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:7;)");
1908  if (sig == NULL) {
1909  goto end;
1910  }
1911  prevsig->next = sig;
1912  prevsig = sig;
1913 
1914  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering alert\"; content:\"220\"; offset:12; depth:4; pcre:\"/220[- ]/\"; rev:4; priority:2; sid:8;)");
1915  if (sig == NULL) {
1916  goto end;
1917  }
1918  prevsig->next = sig;
1919  prevsig = sig;
1920 
1921  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1922  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
1923  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
1924  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
1925  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
1926  SCSigOrderSignatures(de_ctx);
1927 
1928  result = 1;
1929 
1930  sig = de_ctx->sig_list;
1931 
1932 #ifdef DEBUG
1933  while (sig != NULL) {
1934  printf("sid: %d\n", sig->id);
1935  sig = sig->next;
1936  }
1937 #endif
1938 
1939  sig = de_ctx->sig_list;
1940 
1941  result &= (sig->id == 2);
1942  sig = sig->next;
1943  result &= (sig->id == 4);
1944  sig = sig->next;
1945  result &= (sig->id == 5);
1946  sig = sig->next;
1947  result &= (sig->id == 8);
1948  sig = sig->next;
1949  result &= (sig->id == 1);
1950  sig = sig->next;
1951  result &= (sig->id == 3);
1952  sig = sig->next;
1953  result &= (sig->id == 6);
1954  sig = sig->next;
1955  result &= (sig->id == 7);
1956  sig = sig->next;
1957 
1958 end:
1959  /* Restore the default pre-order definition */
1960  action_order_sigs[0] = ACTION_PASS;
1961  action_order_sigs[1] = ACTION_DROP;
1962  action_order_sigs[2] = ACTION_REJECT;
1963  action_order_sigs[3] = ACTION_ALERT;
1964  if (de_ctx != NULL)
1965  DetectEngineCtxFree(de_ctx);
1966  return result;
1967 }
1968 
1969 static int SCSigOrderingTest11(void)
1970 {
1971  int result = 0;
1972  Signature *prevsig = NULL, *sig = NULL;
1973 
1975  if (de_ctx == NULL)
1976  goto end;
1977 
1978  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering set\"; flowbits:isnotset,myflow1; rev:4; sid:1;)");
1979  if (sig == NULL) {
1980  goto end;
1981  }
1982  prevsig = sig;
1983  de_ctx->sig_list = sig;
1984 
1985  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering toggle\"; flowbits:toggle,myflow2; rev:4; sid:2;)");
1986  if (sig == NULL) {
1987  goto end;
1988  }
1989  prevsig->next = sig;
1990  prevsig = sig;
1991 
1992  sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"Testing sigordering unset\"; flowbits:isset, myflow1; flowbits:unset,myflow2; rev:4; priority:3; sid:3;)");
1993  if (sig == NULL) {
1994  goto end;
1995  }
1996  prevsig->next = sig;
1997 
1998  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByActionCompare);
1999  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
2000  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
2001  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
2002  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
2003  SCSigOrderSignatures(de_ctx);
2004 
2005  result = 1;
2006 
2007  sig = de_ctx->sig_list;
2008 
2009 #ifdef DEBUG
2010  while (sig != NULL) {
2011  printf("sid: %d\n", sig->id);
2012  sig = sig->next;
2013  }
2014 #endif
2015 
2016  sig = de_ctx->sig_list;
2017 
2018  result &= (sig->id == 2);
2019  sig = sig->next;
2020  result &= (sig->id == 3);
2021  sig = sig->next;
2022  result &= (sig->id == 1);
2023  sig = sig->next;
2024 
2025 end:
2026  if (de_ctx != NULL)
2027  DetectEngineCtxFree(de_ctx);
2028  return result;
2029 }
2030 
2031 static int SCSigOrderingTest12(void)
2032 {
2033  Signature *sig = NULL;
2034  Packet *p = NULL;
2035  uint8_t buf[] = "test message";
2036  int result = 0;
2037  Flow f;
2038 
2039  FLOW_INITIALIZE(&f);
2040  f.flags |= FLOW_IPV4;
2042  f.proto = IPPROTO_TCP;
2043 
2045  if (de_ctx == NULL)
2046  goto end;
2047  de_ctx->flags |= DE_QUIET;
2048 
2049  const char *sigs[2];
2050  sigs[0] = "alert tcp any any -> any any (content:\"test\"; dsize:>0; flowbits:isset,one; flowbits:set,two; sid:1;)";
2051  sigs[1] = "alert tcp any any -> any any (content:\"test\"; dsize:>0; flowbits:set,one; sid:2;)";
2052  UTHAppendSigs(de_ctx, sigs, 2);
2053 
2054  sig = de_ctx->sig_list;
2055  if (sig == NULL)
2056  goto end;
2057  if (sig->next == NULL)
2058  goto end;
2059  if (sig->next->next != NULL)
2060  goto end;
2061  if (de_ctx->signum != 2)
2062  goto end;
2063 
2065  p = UTHBuildPacket(buf, sizeof(buf), IPPROTO_TCP);
2066  if (p == NULL) {
2067  printf("Error building packet.");
2068  goto end;
2069  }
2070  p->flow = &f;
2074 
2075  UTHMatchPackets(de_ctx, &p, 1);
2076 
2077  uint32_t sids[2] = {1, 2};
2078  uint32_t results[2] = {1, 1};
2079  result = UTHCheckPacketMatchResults(p, sids, results, 2);
2080 
2081 end:
2082  if (p != NULL)
2083  SCFree(p);
2084  if (de_ctx != NULL) {
2085  SigCleanSignatures(de_ctx);
2086  SigGroupCleanup(de_ctx);
2087  DetectEngineCtxFree(de_ctx);
2088  }
2089  FlowShutdown();
2090 
2091  return result;
2092 }
2093 
2094 /** \test Bug 1061 */
2095 static int SCSigOrderingTest13(void)
2096 {
2097  int result = 0;
2098  Signature *sig = NULL;
2099 
2101  if (de_ctx == NULL)
2102  goto end;
2103 
2104  sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flowbits:isset,bit1; flowbits:set,bit2; flowbits:set,bit3; sid:6;)");
2105  if (sig == NULL) {
2106  goto end;
2107  }
2108  sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flowbits:set,bit1; flowbits:set,bit2; sid:7;)");
2109  if (sig == NULL) {
2110  goto end;
2111  }
2112  sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flowbits:isset,bit1; flowbits:isset,bit2; flowbits:isset,bit3; sid:5;)");
2113  if (sig == NULL) {
2114  goto end;
2115  }
2116 
2117  SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbitsCompare);
2118  SCSigOrderSignatures(de_ctx);
2119 
2120  result = 1;
2121 
2122 #ifdef DEBUG
2123  sig = de_ctx->sig_list;
2124  while (sig != NULL) {
2125  printf("sid: %d\n", sig->id);
2126  sig = sig->next;
2127  }
2128 #endif
2129 
2130  sig = de_ctx->sig_list;
2131 
2132  result &= (sig->id == 7);
2133  sig = sig->next;
2134  result &= (sig->id == 6);
2135  sig = sig->next;
2136  result &= (sig->id == 5);
2137  sig = sig->next;
2138 
2139 end:
2140  if (de_ctx != NULL)
2141  DetectEngineCtxFree(de_ctx);
2142  return result;
2143 }
2144 
2145 #endif
2146 
2148 {
2149 
2150 #ifdef UNITTESTS
2151  UtRegisterTest("SCSigOrderingTest01", SCSigOrderingTest01);
2152  UtRegisterTest("SCSigOrderingTest02", SCSigOrderingTest02);
2153  UtRegisterTest("SCSigOrderingTest03", SCSigOrderingTest03);
2154  UtRegisterTest("SCSigOrderingTest04", SCSigOrderingTest04);
2155  UtRegisterTest("SCSigOrderingTest05", SCSigOrderingTest05);
2156  UtRegisterTest("SCSigOrderingTest06", SCSigOrderingTest06);
2157  UtRegisterTest("SCSigOrderingTest07", SCSigOrderingTest07);
2158  UtRegisterTest("SCSigOrderingTest08", SCSigOrderingTest08);
2159  UtRegisterTest("SCSigOrderingTest09", SCSigOrderingTest09);
2160  UtRegisterTest("SCSigOrderingTest10", SCSigOrderingTest10);
2161  UtRegisterTest("SCSigOrderingTest11", SCSigOrderingTest11);
2162  UtRegisterTest("SCSigOrderingTest12", SCSigOrderingTest12);
2163  UtRegisterTest("SCSigOrderingTest13", SCSigOrderingTest13);
2164 #endif
2165 }
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
VarTypes
Definition: util-var.h:27
int(* SWCompare)(SCSigSignatureWrapper *sw1, SCSigSignatureWrapper *sw2)
SignatureInitData * init_data
Definition: detect.h:560
#define DETECT_FLOWBITS_CMD_ISNOTSET
#define SCLogDebug(...)
Definition: util-debug.h:335
#define DETECT_FLOWVAR_NOT_USED
struct Flow_ * flow
Definition: decode.h:444
#define DETECT_FLOWINT_NOT_USED
#define DETECT_FLOWBITS_TYPE_SET
int UTHAppendSigs(DetectEngineCtx *de_ctx, const char *sigs[], int numsigs)
UTHAppendSigs: Add sigs to the detection_engine checking for errors.
#define BUG_ON(x)
uint8_t proto
Definition: flow.h:346
char * msg
Definition: detect.h:549
uint32_t id
Definition: detect.h:525
#define DETECT_FLOWBITS_CMD_UNSET
#define PASS
Pass the test.
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
#define DETECT_FLOWINT_TYPE_SET
int UTHMatchPackets(DetectEngineCtx *de_ctx, Packet **p, int num_packets)
int prio
Definition: detect.h:528
#define ACTION_REJECT
Signature * sig_list
Definition: detect.h:726
#define DETECT_FLOWINT_TYPE_SET_READ
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
#define FLOW_QUIET
Definition: flow.h:37
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:195
void SigCleanSignatures(DetectEngineCtx *de_ctx)
#define DETECT_FLOWBITS_CMD_ISSET
Signature container.
Definition: detect.h:492
uint8_t action
Definition: detect.h:505
uint32_t signum
Definition: detect.h:739
int UTHCheckPacketMatchResults(Packet *p, uint32_t sids[], uint32_t results[], int numsids)
UTHCheckPacketMatches: function to check if a packet match some sids.
void SCSigOrderSignatures(DetectEngineCtx *de_ctx)
Orders the signatures.
struct SigMatch_ * next
Definition: detect.h:328
main detection engine ctx
Definition: detect.h:720
struct SCSigOrderFunc_ * next
void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
Lets you register the Signature ordering functions. The order in which the functions are registered...
#define DETECT_XBITS_CMD_ISSET
Definition: detect-xbits.h:31
#define DETECT_XBITS_CMD_UNSET
Definition: detect-xbits.h:29
enum VarTypes type
Definition: detect-xbits.h:48
#define DE_QUIET
Definition: detect.h:298
struct SCSigSignatureWrapper_ * next
uint8_t action_order_sigs[4]
Definition: util-action.c:40
Signature wrapper used by signature ordering module while ordering signatures.
uint16_t type
uint8_t flags
Definition: detect.h:721
#define DETECT_XBITS_CMD_SET
Definition: detect-xbits.h:27
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void SigFree(Signature *)
#define DETECT_FLOWBITS_TYPE_READ
#define DETECT_XBITS_CMD_TOGGLE
Definition: detect-xbits.h:28
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define DETECT_FLOWBITS_NOT_USED
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
struct SCSigOrderFunc_ * sc_sig_order_funcs
Definition: detect.h:746
#define DETECT_PKTVAR_NOT_USED
uint8_t flowflags
Definition: decode.h:438
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.
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
#define DETECT_FLOWVAR_TYPE_READ
#define DETECT_XBITS_TYPE_SET
int SigGroupCleanup(DetectEngineCtx *de_ctx)
struct Signature_ * next
Definition: detect.h:563
uint8_t type
Definition: detect.h:325
#define DETECT_XBITS_NOT_USED
#define ACTION_ALERT
struct SigMatch_ ** smlists
Definition: detect.h:486
SigMatchCtx * ctx
Definition: detect.h:327
#define SCMalloc(a)
Definition: util-mem.h:174
uint8_t captypes[DETECT_PCRE_CAPTURE_MAX]
Definition: detect-pcre.h:44
#define DETECT_PKTVAR_TYPE_SET
#define SCFree(a)
Definition: util-mem.h:236
#define DETECT_PKTVAR_TYPE_SET_READ
#define DETECT_FLOWINT_TYPE_READ
Structure holding the signature ordering function used by the signature ordering module.
#define DETECT_FLOWVAR_TYPE_SET
#define DETECT_FLOWBITS_CMD_SET
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:599
#define DETECT_FLOWBITS_TYPE_SET_READ
#define DETECT_XBITS_TYPE_READ
#define DETECT_FLOWVAR_TYPE_SET_READ
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define PKT_HAS_FLOW
Definition: decode.h:1101
#define DETECT_PKTVAR_TYPE_READ
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
#define DETECT_XBITS_TYPE_SET_READ
int user[SC_RADIX_USER_DATA_MAX]
#define ACTION_PASS
#define DETECT_FLOWBITS_CMD_TOGGLE
AppProto alproto
application level protocol
Definition: flow.h:407
#define ACTION_DROP
uint32_t flags
Definition: decode.h:442
uint8_t ActionOrderVal(uint8_t action)
Return the priority associated to an action (to order sigs as specified at config) action_order_sigs ...
Definition: util-action.c:53
#define DETECT_XBITS_CMD_ISNOTSET
Definition: detect-xbits.h:30
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Flow data structure.
Definition: flow.h:327
#define FLOW_IPV4
Definition: flow.h:93
uint32_t flags
Definition: flow.h:377
void SCSigRegisterSignatureOrderingTests(void)
#define PKT_STREAM_EST
Definition: decode.h:1099
a single match condition for a signature
Definition: detect.h:324
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
DetectEngineCtx * DetectEngineCtxInit(void)
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:444