suricata
detect-flowint.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
22  *
23  * Flowvar management for integer types, part of the detection engine
24  * Keyword: flowint
25  */
26 
27 #include "suricata-common.h"
28 #include "decode.h"
29 #include "detect.h"
30 #include "threads.h"
31 #include "flow.h"
32 #include "flow-var.h"
33 #include "detect-flowint.h"
34 #include "util-spm.h"
35 #include "util-var-name.h"
36 #include "util-debug.h"
37 #include "util-unittest.h"
38 #include "util-unittest-helper.h"
39 
40 #include "detect-parse.h"
41 #include "detect-engine.h"
42 #include "detect-engine-mpm.h"
43 #include "detect-engine-sigorder.h"
44 
45 #include "pkt-var.h"
46 #include "host.h"
47 #include "util-profiling.h"
48 
49 /* name modifiers value */
50 #define PARSE_REGEX "^\\s*([a-zA-Z][\\w\\d_./]+)\\s*,\\s*([+=-]{1}|==|!=|<|<=|>|>=|isset|notset)\\s*,?\\s*([a-zA-Z][\\w\\d]+|[\\d]{1,10})?\\s*$"
51 /* Varnames must begin with a letter */
52 
53 static pcre *parse_regex;
54 static pcre_extra *parse_regex_study;
55 
57  const Signature *, const SigMatchCtx *);
58 static int DetectFlowintSetup(DetectEngineCtx *, Signature *, const char *);
59 void DetectFlowintFree(void *);
61 
63 {
64  sigmatch_table[DETECT_FLOWINT].name = "flowint";
65  sigmatch_table[DETECT_FLOWINT].desc = "operate on a per-flow integer";
66  sigmatch_table[DETECT_FLOWINT].url = DOC_URL DOC_VERSION "/rules/flow-keywords.html#flowint";
68  sigmatch_table[DETECT_FLOWINT].Setup = DetectFlowintSetup;
71 
72  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
73 }
74 
75 /**
76  * \brief This function is used to create a flowint, add/substract values,
77  * compare it with other flowints, etc
78  *
79  * \param t pointer to thread vars
80  * \param det_ctx pointer to the pattern matcher thread
81  * \param p pointer to the current packet
82  * \param s pointer to the current Signature
83  * \param m pointer to the sigmatch that we will cast into DetectFlowintData
84  *
85  * \retval 0 no match, when a var doesn't exist
86  * \retval 1 match, when a var is initialized well, add/substracted, or a true
87  * condition
88  */
90  Packet *p, const Signature *s, const SigMatchCtx *ctx)
91 {
92  const DetectFlowintData *sfd = (const DetectFlowintData *)ctx;
93  FlowVar *fv;
94  FlowVar *fvt;
95  uint32_t targetval;
96  int ret = 0;
97 
98  if (p->flow == NULL)
99  return 0;
100 
101  /** ATM If we are going to compare the current var with another
102  * that doesn't exist, the default value will be zero;
103  * if you don't want this behaviour, you can use the keyword
104  * "isset" to make it match or not before using the default
105  * value of zero;
106  * But it is mandatory that the current var exist, otherwise, it will
107  * return zero(not match).
108  */
109  if (sfd->targettype == FLOWINT_TARGET_VAR) {
110  uint32_t tvar_idx = VarNameStoreLookupByName(sfd->target.tvar.name, VAR_TYPE_FLOW_INT);
111 
112  fvt = FlowVarGet(p->flow, tvar_idx);
113  /* We don't have that variable initialized yet */
114  if (fvt == NULL)
115  targetval = 0;
116  else
117  targetval = fvt->data.fv_int.value;
118  } else {
119  targetval = sfd->target.value;
120  }
121 
122  SCLogDebug("Our var %s is at idx: %"PRIu32"", sfd->name, sfd->idx);
123 
124  if (sfd->modifier == FLOWINT_MODIFIER_SET) {
125  FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
126  SCLogDebug("Setting %s = %u", sfd->name, targetval);
127  ret = 1;
128  goto end;
129  }
130 
131  fv = FlowVarGet(p->flow, sfd->idx);
132 
133  if (sfd->modifier == FLOWINT_MODIFIER_ISSET) {
134  SCLogDebug(" Isset %s? = %u", sfd->name,(fv) ? 1 : 0);
135  if (fv != NULL)
136  ret = 1;
137  goto end;
138  }
139 
140  if (sfd->modifier == FLOWINT_MODIFIER_NOTSET) {
141  SCLogDebug(" Not set %s? = %u", sfd->name,(fv) ? 0 : 1);
142  if (fv == NULL)
143  ret = 1;
144  goto end;
145  }
146 
147  if (fv != NULL && fv->datatype == FLOWVAR_TYPE_INT) {
148  if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
149  SCLogDebug("Adding %u to %s", targetval, sfd->name);
150  FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value +
151  targetval);
152  ret = 1;
153  goto end;
154  }
155 
156  if (sfd->modifier == FLOWINT_MODIFIER_SUB) {
157  SCLogDebug("Substracting %u to %s", targetval, sfd->name);
158  FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value -
159  targetval);
160  ret = 1;
161  goto end;
162  }
163 
164  switch(sfd->modifier) {
165  case FLOWINT_MODIFIER_EQ:
166  SCLogDebug("( %u EQ %u )", fv->data.fv_int.value, targetval);
167  ret = (fv->data.fv_int.value == targetval);
168  break;
169  case FLOWINT_MODIFIER_NE:
170  SCLogDebug("( %u NE %u )", fv->data.fv_int.value, targetval);
171  ret = (fv->data.fv_int.value != targetval);
172  break;
173  case FLOWINT_MODIFIER_LT:
174  SCLogDebug("( %u LT %u )", fv->data.fv_int.value, targetval);
175  ret = (fv->data.fv_int.value < targetval);
176  break;
177  case FLOWINT_MODIFIER_LE:
178  SCLogDebug("( %u LE %u )", fv->data.fv_int.value, targetval);
179  ret = (fv->data.fv_int.value <= targetval);
180  break;
181  case FLOWINT_MODIFIER_GT:
182  SCLogDebug("( %u GT %u )", fv->data.fv_int.value, targetval);
183  ret = (fv->data.fv_int.value > targetval);
184  break;
185  case FLOWINT_MODIFIER_GE:
186  SCLogDebug("( %u GE %u )", fv->data.fv_int.value, targetval);
187  ret = (fv->data.fv_int.value >= targetval);
188  break;
189  default:
190  SCLogDebug("Unknown Modifier!");
191 #ifdef DEBUG
192  BUG_ON(1);
193 #endif
194  }
195  } else {
196  /* allow a add on a non-existing var, it will init to the "add" value,
197  * so implying a 0 set. */
198  if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
199  SCLogDebug("Adding %u to %s (new var)", targetval, sfd->name);
200  FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
201  ret = 1;
202  } else {
203  SCLogDebug("Var not found!");
204  /* It doesn't exist because it wasn't set
205  * or it is a string var, that we don't compare here
206  */
207  ret = 0;
208  }
209  }
210 
211 end:
212  return ret;
213 }
214 
215 /**
216  * \brief This function is used to parse a flowint option
217  *
218  * \param de_ctx pointer to the engine context
219  * \param rawstr pointer to the string holding the options
220  *
221  * \retval NULL if invalid option
222  * \retval DetectFlowintData pointer with the flowint parsed
223  */
224 static DetectFlowintData *DetectFlowintParse(DetectEngineCtx *de_ctx, const char *rawstr)
225 {
226  DetectFlowintData *sfd = NULL;
227  char *varname = NULL;
228  char *varval = NULL;
229  char *modstr = NULL;
230 #define MAX_SUBSTRINGS 30
231  int ret = 0, res = 0;
232  int ov[MAX_SUBSTRINGS];
233  uint8_t modifier = FLOWINT_MODIFIER_UNKNOWN;
234  unsigned long long value_long = 0;
235  const char *str_ptr;
236 
237  ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr),
238  0, 0, ov, MAX_SUBSTRINGS);
239  if (ret < 3 || ret > 4) {
240  SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for flowint(ret = %d).", rawstr, ret);
241  return NULL;
242  }
243 
244  /* Get our flowint varname */
245  res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 1, &str_ptr);
246  if (res < 0 || str_ptr == NULL) {
247  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
248  goto error;
249  }
250  varname = (char *)str_ptr;
251 
252  res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 2, &str_ptr);
253  if (res < 0 || str_ptr == NULL) {
254  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
255  goto error;
256  }
257  modstr = (char *)str_ptr;
258 
259  /* Get the modifier */
260  if (strcmp("=", modstr) == 0)
261  modifier = FLOWINT_MODIFIER_SET;
262  if (strcmp("+", modstr) == 0)
263  modifier = FLOWINT_MODIFIER_ADD;
264  if (strcmp("-", modstr) == 0)
265  modifier = FLOWINT_MODIFIER_SUB;
266 
267  if (strcmp("<", modstr) == 0)
268  modifier = FLOWINT_MODIFIER_LT;
269  if (strcmp("<=", modstr) == 0)
270  modifier = FLOWINT_MODIFIER_LE;
271  if (strcmp("!=", modstr) == 0)
272  modifier = FLOWINT_MODIFIER_NE;
273  if (strcmp("==", modstr) == 0)
274  modifier = FLOWINT_MODIFIER_EQ;
275  if (strcmp(">=", modstr) == 0)
276  modifier = FLOWINT_MODIFIER_GE;
277  if (strcmp(">", modstr) == 0)
278  modifier = FLOWINT_MODIFIER_GT;
279  if (strcmp("isset", modstr) == 0)
280  modifier = FLOWINT_MODIFIER_ISSET;
281  if (strcmp("notset", modstr) == 0)
282  modifier = FLOWINT_MODIFIER_NOTSET;
283 
284  if (modifier == FLOWINT_MODIFIER_UNKNOWN) {
285  SCLogError(SC_ERR_UNKNOWN_VALUE, "Unknown modifier");
286  goto error;
287  }
288 
289  sfd = SCMalloc(sizeof(DetectFlowintData));
290  if (unlikely(sfd == NULL))
291  goto error;
292 
293  /* If we need another arg, check it out(isset doesn't need another arg) */
294  if (modifier != FLOWINT_MODIFIER_ISSET && modifier != FLOWINT_MODIFIER_NOTSET) {
295  if (ret < 4)
296  goto error;
297 
298  res = pcre_get_substring((char *) rawstr, ov, MAX_SUBSTRINGS, 3, &str_ptr);
299  varval = (char *)str_ptr;
300  if (res < 0 || varval == NULL || strcmp(varval, "") == 0) {
301  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
302  goto error;
303  }
304 
305  if (varval[0] >= '0' && varval[0] <= '9') { /* is digit, look at the regexp */
307  value_long = atoll(varval);
308  if (value_long > UINT32_MAX) {
309  SCLogDebug("DetectFlowintParse: Cannot load this value."
310  " Values should be between 0 and %"PRIu32, UINT32_MAX);
311  goto error;
312  }
313  sfd->target.value = (uint32_t) value_long;
314  } else {
316  sfd->target.tvar.name = SCStrdup(varval);
317  if (unlikely(sfd->target.tvar.name == NULL)) {
318  SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed");
319  goto error;
320  }
321  }
322  } else {
324  }
325 
326  /* Set the name of the origin var to modify/compared with the target */
327  sfd->name = SCStrdup(varname);
328  if (unlikely(sfd->name == NULL)) {
329  SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed");
330  goto error;
331  }
332  sfd->idx = VarNameStoreSetupAdd(varname, VAR_TYPE_FLOW_INT);
333  SCLogDebug("sfd->name %s id %u", sfd->name, sfd->idx);
334  sfd->modifier = modifier;
335 
336  pcre_free_substring(varname);
337  pcre_free_substring(modstr);
338  if (varval)
339  pcre_free_substring(varval);
340  return sfd;
341 error:
342  if (varname)
343  pcre_free_substring(varname);
344  if (varval)
345  pcre_free_substring(varval);
346  if (modstr)
347  pcre_free_substring(modstr);
348  if (sfd != NULL)
349  SCFree(sfd);
350  return NULL;
351 }
352 
353 /**
354  * \brief This function is used to set up the SigMatch holding the flowint opt
355  *
356  * \param de_ctx pointer to the engine context
357  * \param s pointer to the current Signature
358  * \param rawstr pointer to the string holding the options
359  *
360  * \retval 0 if all is ok
361  * \retval -1 if we find any problem
362  */
363 static int DetectFlowintSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
364 {
365  DetectFlowintData *sfd = NULL;
366  SigMatch *sm = NULL;
367 
368  sfd = DetectFlowintParse(de_ctx, rawstr);
369  if (sfd == NULL)
370  goto error;
371 
372  /* Okay so far so good, lets get this into a SigMatch
373  * and put it in the Signature. */
374  sm = SigMatchAlloc();
375  if (sm == NULL)
376  goto error;
377 
378  sm->type = DETECT_FLOWINT;
379  sm->ctx = (SigMatchCtx *)sfd;
380 
381  switch (sfd->modifier) {
386  break;
387 
388  case FLOWINT_MODIFIER_LT:
389  case FLOWINT_MODIFIER_LE:
390  case FLOWINT_MODIFIER_NE:
391  case FLOWINT_MODIFIER_EQ:
392  case FLOWINT_MODIFIER_GE:
393  case FLOWINT_MODIFIER_GT:
397  break;
398  default:
399  goto error;
400  }
401 
402  return 0;
403 
404 error:
405  if (sfd)
406  DetectFlowintFree(sfd);
407  if (sm)
408  SCFree(sm);
409  return -1;
410 }
411 
412 /**
413  * \brief This function is used to free the data of DetectFlowintData
414  */
415 void DetectFlowintFree(void *tmp)
416 {
418  if (sfd != NULL) {
419  if (sfd->name != NULL)
420  SCFree(sfd->name);
421  if (sfd->targettype == FLOWINT_TARGET_VAR)
422  if (sfd->target.tvar.name != NULL)
423  SCFree(sfd->target.tvar.name);
424  SCFree(sfd);
425  }
426 }
427 
428 #ifdef UNITTESTS
429 /**
430  * \brief This is a helper funtion used for debugging purposes
431  */
432 static void DetectFlowintPrintData(DetectFlowintData *sfd)
433 {
434  if (sfd == NULL) {
435  SCLogDebug("DetectFlowintPrintData: Error, DetectFlowintData == NULL!");
436  return;
437  }
438 
439  SCLogDebug("Varname: %s, modifier: %"PRIu8", idx: %"PRIu32" Target: ",
440  sfd->name, sfd->modifier, sfd->idx);
441  switch(sfd->targettype) {
442  case FLOWINT_TARGET_VAR:
443  SCLogDebug("target_var: %s",
444  sfd->target.tvar.name);
445  break;
446  case FLOWINT_TARGET_VAL:
447  SCLogDebug("Value: %"PRIu32"; ", sfd->target.value);
448  break;
449  default :
450  SCLogDebug("DetectFlowintPrintData: Error, Targettype not known!");
451  }
452 }
453 
454 /**
455  * \test DetectFlowintTestParseVal01 is a test to make sure that we set the
456  * DetectFlowint correctly for setting a valid target value
457  */
458 static int DetectFlowintTestParseVal01(void)
459 {
460  int result = 0;
461  DetectFlowintData *sfd = NULL;
462  DetectEngineCtx *de_ctx;
463  de_ctx = DetectEngineCtxInit();
464  if (de_ctx == NULL)
465  return 0;
466  de_ctx->flags |= DE_QUIET;
467 
468  sfd = DetectFlowintParse(de_ctx, "myvar,=,35");
469  DetectFlowintPrintData(sfd);
470  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
471  && sfd->modifier == FLOWINT_MODIFIER_SET) {
472  result = 1;
473  }
474  if (sfd) DetectFlowintFree(sfd);
475 
476  DetectEngineCtxFree(de_ctx);
477 
478  return result;
479 }
480 
481 /**
482  * \test DetectFlowintTestParseVar01 is a test to make sure that we set the
483  * DetectFlowint correctly for setting a valid target variable
484  */
485 static int DetectFlowintTestParseVar01(void)
486 {
487  int result = 0;
488  DetectFlowintData *sfd = NULL;
489  DetectEngineCtx *de_ctx;
490  de_ctx = DetectEngineCtxInit();
491  if (de_ctx == NULL)
492  return 0;
493  de_ctx->flags |= DE_QUIET;
494 
495  sfd = DetectFlowintParse(de_ctx, "myvar,=,targetvar");
496  DetectFlowintPrintData(sfd);
497  if (sfd != NULL && !strcmp(sfd->name, "myvar")
498  && sfd->targettype == FLOWINT_TARGET_VAR
499  && sfd->target.tvar.name != NULL
500  && !strcmp(sfd->target.tvar.name, "targetvar")
501  && sfd->modifier == FLOWINT_MODIFIER_SET) {
502 
503  result = 1;
504  }
505  if (sfd) DetectFlowintFree(sfd);
506  DetectEngineCtxFree(de_ctx);
507 
508  return result;
509 }
510 
511 /**
512  * \test DetectFlowintTestParseVal02 is a test to make sure that we set the
513  * DetectFlowint correctly for adding a valid target value
514  */
515 static int DetectFlowintTestParseVal02(void)
516 {
517  int result = 0;
518  DetectFlowintData *sfd = NULL;
519  DetectEngineCtx *de_ctx;
520  de_ctx = DetectEngineCtxInit();
521  if (de_ctx == NULL)
522  return 0;
523  de_ctx->flags |= DE_QUIET;
524 
525  sfd = DetectFlowintParse(de_ctx, "myvar,+,35");
526  DetectFlowintPrintData(sfd);
527  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
528  && sfd->modifier == FLOWINT_MODIFIER_ADD) {
529  result = 1;
530  }
531  if (sfd) DetectFlowintFree(sfd);
532 
533  DetectEngineCtxFree(de_ctx);
534 
535  return result;
536 }
537 
538 /**
539  * \test DetectFlowintTestParseVar02 is a test to make sure that we set the
540  * DetectFlowint correctly for adding a valid target variable
541  */
542 static int DetectFlowintTestParseVar02(void)
543 {
544  int result = 0;
545  DetectFlowintData *sfd = NULL;
546  DetectEngineCtx *de_ctx;
547  de_ctx = DetectEngineCtxInit();
548  if (de_ctx == NULL)
549  return 0;
550  de_ctx->flags |= DE_QUIET;
551 
552  sfd = DetectFlowintParse(de_ctx, "myvar,+,targetvar");
553  DetectFlowintPrintData(sfd);
554  if (sfd != NULL && !strcmp(sfd->name, "myvar")
555  && sfd->targettype == FLOWINT_TARGET_VAR
556  && sfd->target.tvar.name != NULL
557  && !strcmp(sfd->target.tvar.name, "targetvar")
558  && sfd->modifier == FLOWINT_MODIFIER_ADD) {
559 
560  result = 1;
561  }
562  if (sfd) DetectFlowintFree(sfd);
563  DetectEngineCtxFree(de_ctx);
564 
565  return result;
566 }
567 
568 /**
569  * \test DetectFlowintTestParseVal03 is a test to make sure that we set the
570  * DetectFlowint correctly for substract a valid target value
571  */
572 static int DetectFlowintTestParseVal03(void)
573 {
574  int result = 0;
575  DetectFlowintData *sfd = NULL;
576  DetectEngineCtx *de_ctx;
577  de_ctx = DetectEngineCtxInit();
578  if (de_ctx == NULL)
579  return 0;
580  de_ctx->flags |= DE_QUIET;
581 
582  sfd = DetectFlowintParse(de_ctx, "myvar,-,35");
583  DetectFlowintPrintData(sfd);
584  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
585  && sfd->modifier == FLOWINT_MODIFIER_SUB) {
586  result = 1;
587  }
588  if (sfd) DetectFlowintFree(sfd);
589 
590  DetectEngineCtxFree(de_ctx);
591 
592  return result;
593 }
594 
595 /**
596  * \test DetectFlowintTestParseVar03 is a test to make sure that we set the
597  * DetectFlowint correctly for substract a valid target variable
598  */
599 static int DetectFlowintTestParseVar03(void)
600 {
601  int result = 0;
602  DetectFlowintData *sfd = NULL;
603  DetectEngineCtx *de_ctx;
604  de_ctx = DetectEngineCtxInit();
605  if (de_ctx == NULL)
606  return 0;
607  de_ctx->flags |= DE_QUIET;
608 
609  sfd = DetectFlowintParse(de_ctx, "myvar,-,targetvar");
610  DetectFlowintPrintData(sfd);
611  if (sfd != NULL && !strcmp(sfd->name, "myvar")
612  && sfd->targettype == FLOWINT_TARGET_VAR
613  && sfd->target.tvar.name != NULL
614  && !strcmp(sfd->target.tvar.name, "targetvar")
615  && sfd->modifier == FLOWINT_MODIFIER_SUB) {
616 
617  result = 1;
618  }
619  if (sfd) DetectFlowintFree(sfd);
620  DetectEngineCtxFree(de_ctx);
621 
622  return result;
623 }
624 
625 
626 /**
627  * \test DetectFlowintTestParseVal04 is a test to make sure that we set the
628  * DetectFlowint correctly for checking if equal to a valid target value
629  */
630 static int DetectFlowintTestParseVal04(void)
631 {
632  int result = 0;
633  DetectFlowintData *sfd = NULL;
634  DetectEngineCtx *de_ctx;
635  de_ctx = DetectEngineCtxInit();
636  if (de_ctx == NULL)
637  return 0;
638  de_ctx->flags |= DE_QUIET;
639 
640  sfd = DetectFlowintParse(de_ctx, "myvar,==,35");
641  DetectFlowintPrintData(sfd);
642  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
643  && sfd->modifier == FLOWINT_MODIFIER_EQ) {
644  result = 1;
645  }
646  if (sfd) DetectFlowintFree(sfd);
647 
648  DetectEngineCtxFree(de_ctx);
649 
650  return result;
651 }
652 
653 /**
654  * \test DetectFlowintTestParseVar04 is a test to make sure that we set the
655  * DetectFlowint correctly for checking if equal to a valid target variable
656  */
657 static int DetectFlowintTestParseVar04(void)
658 {
659  int result = 0;
660  DetectFlowintData *sfd = NULL;
661  DetectEngineCtx *de_ctx;
662  de_ctx = DetectEngineCtxInit();
663  if (de_ctx == NULL)
664  return 0;
665  de_ctx->flags |= DE_QUIET;
666 
667  sfd = DetectFlowintParse(de_ctx, "myvar,==,targetvar");
668  DetectFlowintPrintData(sfd);
669  if (sfd != NULL && !strcmp(sfd->name, "myvar")
670  && sfd->targettype == FLOWINT_TARGET_VAR
671  && sfd->target.tvar.name != NULL
672  && !strcmp(sfd->target.tvar.name, "targetvar")
673  && sfd->modifier == FLOWINT_MODIFIER_EQ) {
674 
675  result = 1;
676  }
677  if (sfd) DetectFlowintFree(sfd);
678  DetectEngineCtxFree(de_ctx);
679 
680  return result;
681 }
682 
683 /**
684  * \test DetectFlowintTestParseVal05 is a test to make sure that we set the
685  * DetectFlowint correctly for cheking if not equal to a valid target value
686  */
687 static int DetectFlowintTestParseVal05(void)
688 {
689  int result = 0;
690  DetectFlowintData *sfd = NULL;
691  DetectEngineCtx *de_ctx;
692  de_ctx = DetectEngineCtxInit();
693  if (de_ctx == NULL)
694  return 0;
695  de_ctx->flags |= DE_QUIET;
696 
697  sfd = DetectFlowintParse(de_ctx, "myvar,!=,35");
698  DetectFlowintPrintData(sfd);
699  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
700  && sfd->modifier == FLOWINT_MODIFIER_NE) {
701  result = 1;
702  }
703  if (sfd) DetectFlowintFree(sfd);
704 
705  DetectEngineCtxFree(de_ctx);
706 
707  return result;
708 }
709 
710 /**
711  * \test DetectFlowintTestParseVar05 is a test to make sure that we set the
712  * DetectFlowint correctly for checking if not equal to a valid target variable
713  */
714 static int DetectFlowintTestParseVar05(void)
715 {
716  int result = 0;
717  DetectFlowintData *sfd = NULL;
718  DetectEngineCtx *de_ctx;
719  de_ctx = DetectEngineCtxInit();
720  if (de_ctx == NULL)
721  return 0;
722  de_ctx->flags |= DE_QUIET;
723 
724  sfd = DetectFlowintParse(de_ctx, "myvar,!=,targetvar");
725  DetectFlowintPrintData(sfd);
726  if (sfd != NULL && !strcmp(sfd->name, "myvar")
727  && sfd->targettype == FLOWINT_TARGET_VAR
728  && sfd->target.tvar.name != NULL
729  && !strcmp(sfd->target.tvar.name, "targetvar")
730  && sfd->modifier == FLOWINT_MODIFIER_NE) {
731 
732  result = 1;
733  }
734  if (sfd) DetectFlowintFree(sfd);
735  DetectEngineCtxFree(de_ctx);
736 
737  return result;
738 }
739 
740 /**
741  * \test DetectFlowintTestParseVal06 is a test to make sure that we set the
742  * DetectFlowint correctly for cheking if greater than a valid target value
743  */
744 static int DetectFlowintTestParseVal06(void)
745 {
746  int result = 0;
747  DetectFlowintData *sfd = NULL;
748  DetectEngineCtx *de_ctx;
749  de_ctx = DetectEngineCtxInit();
750  if (de_ctx == NULL)
751  return 0;
752  de_ctx->flags |= DE_QUIET;
753 
754  sfd = DetectFlowintParse(de_ctx, "myvar, >,35");
755  DetectFlowintPrintData(sfd);
756  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
757  && sfd->modifier == FLOWINT_MODIFIER_GT) {
758  result = 1;
759  }
760  if (sfd) DetectFlowintFree(sfd);
761 
762  DetectEngineCtxFree(de_ctx);
763 
764  return result;
765 }
766 
767 /**
768  * \test DetectFlowintTestParseVar06 is a test to make sure that we set the
769  * DetectFlowint correctly for checking if greater than a valid target variable
770  */
771 static int DetectFlowintTestParseVar06(void)
772 {
773  int result = 0;
774  DetectFlowintData *sfd = NULL;
775  DetectEngineCtx *de_ctx;
776  de_ctx = DetectEngineCtxInit();
777  if (de_ctx == NULL)
778  return 0;
779  de_ctx->flags |= DE_QUIET;
780 
781  sfd = DetectFlowintParse(de_ctx, "myvar, >,targetvar");
782  DetectFlowintPrintData(sfd);
783  if (sfd != NULL && !strcmp(sfd->name, "myvar")
784  && sfd->targettype == FLOWINT_TARGET_VAR
785  && sfd->target.tvar.name != NULL
786  && !strcmp(sfd->target.tvar.name, "targetvar")
787  && sfd->modifier == FLOWINT_MODIFIER_GT) {
788 
789  result = 1;
790  }
791  if (sfd) DetectFlowintFree(sfd);
792  DetectEngineCtxFree(de_ctx);
793 
794  return result;
795 }
796 
797 /**
798  * \test DetectFlowintTestParseVal07 is a test to make sure that we set the
799  * DetectFlowint correctly for cheking if greater or equal than a valid target value
800  */
801 static int DetectFlowintTestParseVal07(void)
802 {
803  int result = 0;
804  DetectFlowintData *sfd = NULL;
805  DetectEngineCtx *de_ctx;
806  de_ctx = DetectEngineCtxInit();
807  if (de_ctx == NULL)
808  return 0;
809  de_ctx->flags |= DE_QUIET;
810 
811  sfd = DetectFlowintParse(de_ctx, "myvar, >= ,35");
812  DetectFlowintPrintData(sfd);
813  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
814  && sfd->modifier == FLOWINT_MODIFIER_GE) {
815  result = 1;
816  }
817  if (sfd) DetectFlowintFree(sfd);
818 
819  DetectEngineCtxFree(de_ctx);
820 
821  return result;
822 }
823 
824 /**
825  * \test DetectFlowintTestParseVar07 is a test to make sure that we set the
826  * DetectFlowint correctly for checking if greater or equal than a valid target variable
827  */
828 static int DetectFlowintTestParseVar07(void)
829 {
830  int result = 0;
831  DetectFlowintData *sfd = NULL;
832  DetectEngineCtx *de_ctx;
833  de_ctx = DetectEngineCtxInit();
834  if (de_ctx == NULL)
835  return 0;
836  de_ctx->flags |= DE_QUIET;
837 
838  sfd = DetectFlowintParse(de_ctx, "myvar, >= ,targetvar");
839  DetectFlowintPrintData(sfd);
840  if (sfd != NULL && !strcmp(sfd->name, "myvar")
841  && sfd->targettype == FLOWINT_TARGET_VAR
842  && sfd->target.tvar.name != NULL
843  && !strcmp(sfd->target.tvar.name, "targetvar")
844  && sfd->modifier == FLOWINT_MODIFIER_GE) {
845 
846  result = 1;
847  }
848  if (sfd) DetectFlowintFree(sfd);
849  DetectEngineCtxFree(de_ctx);
850 
851  return result;
852 }
853 
854 /**
855  * \test DetectFlowintTestParseVal08 is a test to make sure that we set the
856  * DetectFlowint correctly for cheking if lower or equal than a valid target value
857  */
858 static int DetectFlowintTestParseVal08(void)
859 {
860  int result = 0;
861  DetectFlowintData *sfd = NULL;
862  DetectEngineCtx *de_ctx;
863  de_ctx = DetectEngineCtxInit();
864  if (de_ctx == NULL)
865  return 0;
866  de_ctx->flags |= DE_QUIET;
867 
868  sfd = DetectFlowintParse(de_ctx, "myvar, <= ,35");
869  DetectFlowintPrintData(sfd);
870  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
871  && sfd->modifier == FLOWINT_MODIFIER_LE) {
872  result = 1;
873  }
874  if (sfd) DetectFlowintFree(sfd);
875 
876  DetectEngineCtxFree(de_ctx);
877 
878  return result;
879 }
880 
881 /**
882  * \test DetectFlowintTestParseVar08 is a test to make sure that we set the
883  * DetectFlowint correctly for checking if lower or equal than a valid target variable
884  */
885 static int DetectFlowintTestParseVar08(void)
886 {
887  int result = 0;
888  DetectFlowintData *sfd = NULL;
889  DetectEngineCtx *de_ctx;
890  de_ctx = DetectEngineCtxInit();
891  if (de_ctx == NULL)
892  return 0;
893  de_ctx->flags |= DE_QUIET;
894 
895  sfd = DetectFlowintParse(de_ctx, "myvar, <= ,targetvar");
896  DetectFlowintPrintData(sfd);
897  if (sfd != NULL && !strcmp(sfd->name, "myvar")
898  && sfd->targettype == FLOWINT_TARGET_VAR
899  && sfd->target.tvar.name != NULL
900  && !strcmp(sfd->target.tvar.name, "targetvar")
901  && sfd->modifier == FLOWINT_MODIFIER_LE) {
902 
903  result = 1;
904  }
905  if (sfd) DetectFlowintFree(sfd);
906  DetectEngineCtxFree(de_ctx);
907 
908  return result;
909 }
910 
911 /**
912  * \test DetectFlowintTestParseVal09 is a test to make sure that we set the
913  * DetectFlowint correctly for cheking if lower than a valid target value
914  */
915 static int DetectFlowintTestParseVal09(void)
916 {
917  int result = 0;
918  DetectFlowintData *sfd = NULL;
919  DetectEngineCtx *de_ctx;
920  de_ctx = DetectEngineCtxInit();
921  if (de_ctx == NULL)
922  return 0;
923  de_ctx->flags |= DE_QUIET;
924 
925  sfd = DetectFlowintParse(de_ctx, "myvar, < ,35");
926  DetectFlowintPrintData(sfd);
927  if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
928  && sfd->modifier == FLOWINT_MODIFIER_LT) {
929  result = 1;
930  }
931  if (sfd) DetectFlowintFree(sfd);
932 
933  DetectEngineCtxFree(de_ctx);
934 
935  return result;
936 }
937 
938 /**
939  * \test DetectFlowintTestParseVar09 is a test to make sure that we set the
940  * DetectFlowint correctly for checking if lower than a valid target variable
941  */
942 static int DetectFlowintTestParseVar09(void)
943 {
944  int result = 0;
945  DetectFlowintData *sfd = NULL;
946  DetectEngineCtx *de_ctx;
947  de_ctx = DetectEngineCtxInit();
948  if (de_ctx == NULL)
949  return 0;
950  de_ctx->flags |= DE_QUIET;
951 
952  sfd = DetectFlowintParse(de_ctx, "myvar, < ,targetvar");
953  DetectFlowintPrintData(sfd);
954  if (sfd != NULL && !strcmp(sfd->name, "myvar")
955  && sfd->targettype == FLOWINT_TARGET_VAR
956  && sfd->target.tvar.name != NULL
957  && !strcmp(sfd->target.tvar.name, "targetvar")
958  && sfd->modifier == FLOWINT_MODIFIER_LT) {
959 
960  result = 1;
961  }
962  if (sfd) DetectFlowintFree(sfd);
963  DetectEngineCtxFree(de_ctx);
964 
965  return result;
966 }
967 
968 /**
969  * \test DetectFlowintTestParseVar09 is a test to make sure that handle the
970  * isset keyword correctly
971  */
972 static int DetectFlowintTestParseIsset10(void)
973 {
974  int result = 1;
975  DetectFlowintData *sfd = NULL;
976  DetectEngineCtx *de_ctx;
977  de_ctx = DetectEngineCtxInit();
978  if (de_ctx == NULL)
979  return 0;
980  de_ctx->flags |= DE_QUIET;
981 
982  sfd = DetectFlowintParse(de_ctx, "myvar, isset");
983  DetectFlowintPrintData(sfd);
984  if (sfd != NULL && !strcmp(sfd->name, "myvar")
986  && sfd->modifier == FLOWINT_MODIFIER_ISSET) {
987 
988  result &= 1;
989  } else {
990  result = 0;
991  }
992 
993  if (sfd) DetectFlowintFree(sfd);
994  sfd = DetectFlowintParse(de_ctx, "myvar, notset");
995  DetectFlowintPrintData(sfd);
996  if (sfd != NULL && !strcmp(sfd->name, "myvar")
998  && sfd->modifier == FLOWINT_MODIFIER_NOTSET) {
999 
1000  result &= 1;
1001  } else {
1002  result = 0;
1003  }
1004 
1005  if (sfd) DetectFlowintFree(sfd);
1006  DetectEngineCtxFree(de_ctx);
1007 
1008  return result;
1009 }
1010 
1011 /**
1012  * \test DetectFlowintTestParseInvalidSyntaxis01 is a test to make sure that we dont set the
1013  * DetectFlowint for a invalid input option
1014  */
1015 static int DetectFlowintTestParseInvalidSyntaxis01(void)
1016 {
1017  int result = 1;
1018  DetectFlowintData *sfd = NULL;
1019  DetectEngineCtx *de_ctx;
1020  de_ctx = DetectEngineCtxInit();
1021  if (de_ctx == NULL)
1022  goto error;
1023  de_ctx->flags |= DE_QUIET;
1024 
1025  sfd = DetectFlowintParse(de_ctx, "myvar,=,9999999999");
1026  if (sfd != NULL) {
1027  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=,9532458716234857");
1028  result = 0;
1029  }
1030  if (sfd) DetectFlowintFree(sfd);
1031 
1032  sfd = DetectFlowintParse(de_ctx, "myvar,=,45targetvar");
1033  if (sfd != NULL) {
1034  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=,45targetvar ");
1035  result = 0;
1036  }
1037  if (sfd) DetectFlowintFree(sfd);
1038 
1039  sfd = DetectFlowintParse(de_ctx, "657myvar,=,targetvar");
1040  if (sfd != NULL) {
1041  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at 657myvar,=,targetvar ");
1042  result = 0;
1043  }
1044  if (sfd) DetectFlowintFree(sfd);
1045 
1046  sfd = DetectFlowintParse(de_ctx, "myvar,=<,targetvar");
1047  if (sfd != NULL) {
1048  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=<,targetvar ");
1049  result = 0;
1050  }
1051  if (sfd) DetectFlowintFree(sfd);
1052 
1053  sfd = DetectFlowintParse(de_ctx, "myvar,===,targetvar");
1054  if (sfd != NULL) {
1055  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,===,targetvar ");
1056  result = 0;
1057  }
1058  if (sfd) DetectFlowintFree(sfd);
1059 
1060  sfd = DetectFlowintParse(de_ctx, "myvar,==");
1061  if (sfd != NULL) {
1062  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,==");
1063  result = 0;
1064  }
1065  if (sfd) DetectFlowintFree(sfd);
1066 
1067  sfd = DetectFlowintParse(de_ctx, "myvar,");
1068  if (sfd != NULL) {
1069  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,");
1070  result = 0;
1071  }
1072  if (sfd) DetectFlowintFree(sfd);
1073 
1074  sfd = DetectFlowintParse(de_ctx, "myvar");
1075  if (sfd != NULL) {
1076  SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar");
1077  result = 0;
1078  }
1079  if (sfd) DetectFlowintFree(sfd);
1080 
1081  DetectEngineCtxFree(de_ctx);
1082 
1083  return result;
1084 error:
1085  if (de_ctx)
1086  DetectEngineCtxFree(de_ctx);
1087  return result;
1088 }
1089 
1090 /** \test DetectFlowintTestPacket01Real
1091  * \brief Set a counter when we see a content:"GET"
1092  * and increment it by 2 if we match a "Unauthorized"
1093  * When it reach 3(with the last +2), another counter starts
1094  * and when that counter reach 6 packets.
1095  *
1096  * All the Signatures generate an alert(its for testing)
1097  * but the ignature that increment the second counter +1, that has
1098  * a "noalert", so we can do all increments
1099  * silently until we reach 6 next packets counted
1100  */
1101 static int DetectFlowintTestPacket01Real(void)
1102 {
1103  Packet *p = NULL;
1104  ThreadVars th_v;
1105  DetectEngineThreadCtx *det_ctx = NULL;
1106  memset(&th_v, 0, sizeof(th_v));
1107 
1109  FAIL_IF(de_ctx == NULL);
1110 
1111  de_ctx->flags |= DE_QUIET;
1112 
1113  const char *sigs[5];
1114  sigs[0] = "alert tcp any any -> any any (msg:\"Setting a flowint counter\"; content:\"GET\"; flowint:myvar,=,1; flowint:maxvar,=,6; sid:101;)";
1115  sigs[1] = "alert tcp any any -> any any (msg:\"Adding to flowint counter\"; content:\"Unauthorized\"; flowint: myvar,+,2; sid:102;)";
1116  sigs[2] = "alert tcp any any -> any any (msg:\"if the flowint counter is 3 create a new counter\"; content:\"Unauthorized\"; flowint: myvar,==,3; flowint: cntpackets, =, 0; sid:103;)";
1117  sigs[3] = "alert tcp any any -> any any (msg:\"and count the rest of the packets received without generating alerts!!!\"; flowint: myvar,==,3; flowint: cntpackets, +, 1; noalert;sid:104;)";
1118  sigs[4] = "alert tcp any any -> any any (msg:\" and fire this when it reach 6\"; flowint: cntpackets, ==, maxvar; sid:105;)";
1119  FAIL_IF(UTHAppendSigs(de_ctx, sigs, 5) == 0);
1120 
1122  SCSigOrderSignatures(de_ctx);
1124  SigGroupBuild(de_ctx);
1125  DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1126 
1127  Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1128  41424, 80);
1129  FAIL_IF(f == NULL);
1130  f->proto = IPPROTO_TCP;
1131 
1132  p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1133  FAIL_IF(p == NULL);
1134  UTHAssignFlow(p, f);
1135  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1136  FAIL_IF(!PacketAlertCheck(p, 101));
1137  UTHFreePacket(p);
1138 
1139  p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1140  FAIL_IF(p == NULL);
1141  UTHAssignFlow(p, f);
1142  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1143  FAIL_IF(!PacketAlertCheck(p, 102));
1144  FAIL_IF(!PacketAlertCheck(p, 103));
1145  UTHFreePacket(p);
1146 
1147  p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1148  FAIL_IF(p == NULL);
1149  UTHAssignFlow(p, f);
1150  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1151  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1152  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1153  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1154  UTHFreePacket(p);
1155 
1156  p = UTHBuildPacket((uint8_t *)"X", 1, IPPROTO_TCP);
1157  FAIL_IF(p == NULL);
1158  UTHAssignFlow(p, f);
1159  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1160  FAIL_IF(!PacketAlertCheck(p, 105));
1161  UTHFreePacket(p);
1162 
1163  UTHFreeFlow(f);
1164  DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1165  DetectEngineCtxFree(de_ctx);
1166 
1167  PASS;
1168 }
1169 
1170 /**
1171  * \test DetectFlowintTestPacket02Real
1172  * \brief like DetectFlowintTestPacket01Real but using isset/notset keywords
1173  */
1174 static int DetectFlowintTestPacket02Real(void)
1175 {
1176  Packet *p = NULL;
1177  ThreadVars th_v;
1178  DetectEngineThreadCtx *det_ctx = NULL;
1179  memset(&th_v, 0, sizeof(th_v));
1180 
1182  FAIL_IF(de_ctx == NULL);
1183 
1184  de_ctx->flags |= DE_QUIET;
1185 
1186  const char *sigs[5];
1187  sigs[0] = "alert tcp any any -> any any (msg:\"Setting a flowint counter\"; content:\"GET\"; flowint: myvar, notset; flowint:maxvar,notset; flowint: myvar,=,1; flowint: maxvar,=,6; sid:101;)";
1188  sigs[1] = "alert tcp any any -> any any (msg:\"Adding to flowint counter\"; content:\"Unauthorized\"; flowint:myvar,isset; flowint: myvar,+,2; sid:102;)";
1189  sigs[2] = "alert tcp any any -> any any (msg:\"if the flowint counter is 3 create a new counter\"; content:\"Unauthorized\"; flowint: myvar, isset; flowint: myvar,==,3; flowint:cntpackets,notset; flowint: cntpackets, =, 0; sid:103;)";
1190  sigs[3] = "alert tcp any any -> any any (msg:\"and count the rest of the packets received without generating alerts!!!\"; flowint: cntpackets,isset; flowint: cntpackets, +, 1; noalert;sid:104;)";
1191  sigs[4] = "alert tcp any any -> any any (msg:\" and fire this when it reach 6\"; flowint: cntpackets, isset; flowint: maxvar,isset; flowint: cntpackets, ==, maxvar; sid:105;)";
1192  FAIL_IF(UTHAppendSigs(de_ctx, sigs, 5) == 0);
1193 
1195  SCSigOrderSignatures(de_ctx);
1197  SigGroupBuild(de_ctx);
1198  DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1199 
1200  Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1201  41424, 80);
1202  FAIL_IF(f == NULL);
1203  f->proto = IPPROTO_TCP;
1204 
1205  p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1206  FAIL_IF(p == NULL);
1207  UTHAssignFlow(p, f);
1208  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1209  FAIL_IF(!PacketAlertCheck(p, 101));
1210  UTHFreePacket(p);
1211 
1212  p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1213  FAIL_IF(p == NULL);
1214  UTHAssignFlow(p, f);
1215  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1216  FAIL_IF(!PacketAlertCheck(p, 102));
1217  FAIL_IF(!PacketAlertCheck(p, 103));
1218  UTHFreePacket(p);
1219 
1220  p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1221  FAIL_IF(p == NULL);
1222  UTHAssignFlow(p, f);
1223  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1224  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1225  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1226  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1227  UTHFreePacket(p);
1228 
1229  p = UTHBuildPacket((uint8_t *)"X", 1, IPPROTO_TCP);
1230  FAIL_IF(p == NULL);
1231  UTHAssignFlow(p, f);
1232  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1233  FAIL_IF(!PacketAlertCheck(p, 105));
1234  UTHFreePacket(p);
1235 
1236  UTHFreeFlow(f);
1237  DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1238  DetectEngineCtxFree(de_ctx);
1239 
1240  PASS;
1241 }
1242 
1243 /**
1244  * \test DetectFlowintTestPacket03Real
1245  * \brief Check the behaviour of isset/notset
1246  */
1247 static int DetectFlowintTestPacket03Real(void)
1248 {
1249  Packet *p = NULL;
1250  ThreadVars th_v;
1251  DetectEngineThreadCtx *det_ctx = NULL;
1252  memset(&th_v, 0, sizeof(th_v));
1253 
1255  FAIL_IF(de_ctx == NULL);
1256 
1257  de_ctx->flags |= DE_QUIET;
1258 
1259  const char *sigs[3];
1260  sigs[0] = "alert tcp any any -> any any (msg:\"check notset\"; content:\"GET\"; flowint: myvar, notset; flowint: myvar,=,0; flowint: other,=,10; sid:101;)";
1261  sigs[1] = "alert tcp any any -> any any (msg:\"check isset\"; content:\"Unauthorized\"; flowint:myvar,isset; flowint: other,isset; sid:102;)";
1262  sigs[2] = "alert tcp any any -> any any (msg:\"check notset\"; content:\"Unauthorized\"; flowint:lala,isset; sid:103;)";
1263  FAIL_IF(UTHAppendSigs(de_ctx, sigs, 3) == 0);
1264 
1266  SCSigOrderSignatures(de_ctx);
1268  SigGroupBuild(de_ctx);
1269  DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1270 
1271  Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1272  41424, 80);
1273  FAIL_IF(f == NULL);
1274  f->proto = IPPROTO_TCP;
1275 
1276  p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1277  FAIL_IF(p == NULL);
1278  UTHAssignFlow(p, f);
1279  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1280  FAIL_IF(!PacketAlertCheck(p, 101));
1281  UTHFreePacket(p);
1282 
1283  p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1284  FAIL_IF(p == NULL);
1285  UTHAssignFlow(p, f);
1286  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1287  FAIL_IF(!PacketAlertCheck(p, 102));
1288  FAIL_IF(PacketAlertCheck(p, 103));
1289  UTHFreePacket(p);
1290 
1291  p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1292  FAIL_IF(p == NULL);
1293  UTHAssignFlow(p, f);
1294  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1295  FAIL_IF(PacketAlertCheck(p, 102));
1296  FAIL_IF(PacketAlertCheck(p, 103));
1297  UTHFreePacket(p);
1298 
1299  UTHFreeFlow(f);
1300  DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1301  DetectEngineCtxFree(de_ctx);
1302 
1303  PASS;
1304 }
1305 
1306 #endif /* UNITTESTS */
1307 
1308 /**
1309  * \brief this function registers unit tests for DetectFlowint
1310  */
1312 {
1313 #ifdef UNITTESTS /* UNITTESTS */
1314  UtRegisterTest("DetectFlowintTestParseVal01", DetectFlowintTestParseVal01);
1315  UtRegisterTest("DetectFlowintTestParseVar01", DetectFlowintTestParseVar01);
1316  UtRegisterTest("DetectFlowintTestParseVal02", DetectFlowintTestParseVal02);
1317  UtRegisterTest("DetectFlowintTestParseVar02", DetectFlowintTestParseVar02);
1318  UtRegisterTest("DetectFlowintTestParseVal03", DetectFlowintTestParseVal03);
1319  UtRegisterTest("DetectFlowintTestParseVar03", DetectFlowintTestParseVar03);
1320  UtRegisterTest("DetectFlowintTestParseVal04", DetectFlowintTestParseVal04);
1321  UtRegisterTest("DetectFlowintTestParseVar04", DetectFlowintTestParseVar04);
1322  UtRegisterTest("DetectFlowintTestParseVal05", DetectFlowintTestParseVal05);
1323  UtRegisterTest("DetectFlowintTestParseVar05", DetectFlowintTestParseVar05);
1324  UtRegisterTest("DetectFlowintTestParseVal06", DetectFlowintTestParseVal06);
1325  UtRegisterTest("DetectFlowintTestParseVar06", DetectFlowintTestParseVar06);
1326  UtRegisterTest("DetectFlowintTestParseVal07", DetectFlowintTestParseVal07);
1327  UtRegisterTest("DetectFlowintTestParseVar07", DetectFlowintTestParseVar07);
1328  UtRegisterTest("DetectFlowintTestParseVal08", DetectFlowintTestParseVal08);
1329  UtRegisterTest("DetectFlowintTestParseVar08", DetectFlowintTestParseVar08);
1330  UtRegisterTest("DetectFlowintTestParseVal09", DetectFlowintTestParseVal09);
1331  UtRegisterTest("DetectFlowintTestParseVar09", DetectFlowintTestParseVar09);
1332  UtRegisterTest("DetectFlowintTestParseIsset10",
1333  DetectFlowintTestParseIsset10);
1334  UtRegisterTest("DetectFlowintTestParseInvalidSyntaxis01",
1335  DetectFlowintTestParseInvalidSyntaxis01);
1336  UtRegisterTest("DetectFlowintTestPacket01Real",
1337  DetectFlowintTestPacket01Real);
1338  UtRegisterTest("DetectFlowintTestPacket02Real",
1339  DetectFlowintTestPacket02Real);
1340  UtRegisterTest("DetectFlowintTestPacket03Real",
1341  DetectFlowintTestPacket03Real);
1342 #endif /* UNITTESTS */
1343 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1448
void UTHAssignFlow(Packet *p, Flow *f)
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
#define SCLogDebug(...)
Definition: util-debug.h:335
struct Flow_ * flow
Definition: decode.h:445
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
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:344
void DetectFlowintRegisterTests(void)
this function registers unit tests for DetectFlowint
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void DetectFlowintFree(void *)
This function is used to free the data of DetectFlowintData.
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1200
Signature container.
Definition: detect.h:522
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:313
void SCSigOrderSignatures(DetectEngineCtx *de_ctx)
Orders the signatures.
main detection engine ctx
Definition: detect.h:761
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
uint8_t datatype
Definition: flow-var.h:50
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
Lets you register the Signature ordering functions. The order in which the functions are registered...
#define PARSE_REGEX
#define DE_QUIET
Definition: detect.h:292
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
int DetectFlowintMatch(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
This function is used to create a flowint, add/substract values, compare it with other flowints...
uint8_t flags
Definition: detect.h:762
void(* Free)(void *)
Definition: detect.h:1191
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1669
uint32_t value
Definition: flow-var.h:44
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
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.
union FlowVar_::@117 data
union DetectFlowintData_::@79 target
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1170
uint8_t type
Definition: detect.h:319
const char * desc
Definition: detect.h:1202
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:346
FlowVarTypeInt fv_int
Definition: flow-var.h:58
SigMatchCtx * ctx
Definition: detect.h:321
#define SCMalloc(a)
Definition: util-mem.h:222
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index &#39;idx&#39; from the flow
Definition: flow-var.c:78
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
add to staging or return existing id if already in there
const char * url
Definition: detect.h:1203
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
#define SCStrdup(a)
Definition: util-mem.h:268
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
#define FLOWVAR_TYPE_INT
Definition: flow-var.h:34
#define MAX_SUBSTRINGS
#define DOC_VERSION
Definition: suricata.h:91
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Flow data structure.
Definition: flow.h:325
void(* RegisterTests)(void)
Definition: detect.h:1192
a single match condition for a signature
Definition: detect.h:318
void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:135
void UTHFreeFlow(Flow *flow)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectFlowintRegister(void)