suricata
detect-engine-port.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2019 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 Victor Julien <victor@inliniac.net>
22  *
23  * Ports part of the detection engine.
24  *
25  * \todo more unit testing
26  *
27  */
28 
29 #include "suricata-common.h"
30 #include "decode.h"
31 #include "detect.h"
32 #include "flow-var.h"
33 
34 #include "util-cidr.h"
35 #include "util-unittest-helper.h"
36 #include "util-rule-vars.h"
37 
38 #include "detect-parse.h"
39 #include "detect-engine.h"
40 #include "detect-engine-mpm.h"
41 
42 #include "detect-engine-siggroup.h"
43 #include "detect-engine-port.h"
44 
45 #include "conf.h"
46 #include "util-debug.h"
47 #include "util-error.h"
48 
49 #include "pkt-var.h"
50 #include "host.h"
51 #include "util-profiling.h"
52 #include "util-var.h"
53 #include "util-byte.h"
54 
55 static int DetectPortCutNot(DetectPort *, DetectPort **);
56 static int DetectPortCut(DetectEngineCtx *, DetectPort *, DetectPort *,
57  DetectPort **);
58 DetectPort *PortParse(const char *str);
59 static bool DetectPortIsValidRange(char *, uint16_t *);
60 
61 /**
62  * \brief Alloc a DetectPort structure and update counters
63  *
64  * \retval dp newly created DetectPort on success; or NULL in case of error.
65  */
67 {
68  DetectPort *dp = SCCalloc(1, sizeof(DetectPort));
69  if (unlikely(dp == NULL))
70  return NULL;
71  return dp;
72 }
73 
74 /**
75  * \brief Free a DetectPort and its members
76  *
77  * \param dp Pointer to the DetectPort that has to be freed.
78  */
80 {
81  if (dp == NULL)
82  return;
83 
84  /* only free the head if we have the original */
85  if (dp->sh != NULL && !(dp->flags & PORT_SIGGROUPHEAD_COPY)) {
87  }
88  dp->sh = NULL;
89 
90  SCFree(dp);
91 }
92 
93 /**
94  * \brief Helper function used to print the list of ports
95  * present in this DetectPort list.
96  *
97  * \param head Pointer to the DetectPort list head
98  */
100 {
101  DetectPort *cur;
102 #ifdef DEBUG
103  uint16_t cnt = 0;
104 #endif
105  SCLogDebug("= list start:");
106  if (head != NULL) {
107  for (cur = head; cur != NULL; cur = cur->next) {
108  DetectPortPrint(cur);
109 #ifdef DEBUG
110  cnt++;
111 #endif
112  }
113  SCLogDebug(" ");
114  }
115  SCLogDebug("= list end (cnt %" PRIu32 ")", cnt);
116 }
117 
118 /**
119  * \brief Free a DetectPort list and each of its members
120  *
121  * \param head Pointer to the DetectPort list head
122  */
124 {
125  if (head == NULL)
126  return;
127 
128  DetectPort *cur, *next;
129 
130  for (cur = head; cur != NULL; ) {
131  next = cur->next;
132  cur->next = NULL;
133  DetectPortFree(de_ctx, cur);
134  cur = next;
135  }
136 }
137 
138 /**
139  * \brief function for inserting a port group object. This also makes sure
140  * SigGroupContainer lists are handled correctly.
141  *
142  * \param de_ctx Pointer to the current detection engine context
143  * \param head Pointer to the DetectPort list head
144  * \param dp DetectPort to search in the DetectPort list
145  *
146  * \retval 1 inserted
147  * \retval 0 not inserted, memory of new is freed
148  * \retval -1 error
149  *
150  * \todo rewrite to avoid recursive calls
151  * */
153  DetectPort *new)
154 {
155  if (new == NULL)
156  return 0;
157 
158  //BUG_ON(new->next != NULL);
159  //BUG_ON(new->prev != NULL);
160 
161  /* see if it already exists or overlaps with existing ports */
162  if (*head != NULL) {
163  DetectPort *cur = NULL;
164  int r = 0;
165 
166  for (cur = *head; cur != NULL; cur = cur->next) {
167  r = DetectPortCmp(new,cur);
168  BUG_ON(r == PORT_ER);
169 
170  /* if so, handle that */
171  if (r == PORT_EQ) {
172  SCLogDebug("PORT_EQ %p %p", cur, new);
173  /* exact overlap/match */
174  if (cur != new) {
175  DetectPortFree(de_ctx, new);
176  return 0;
177  }
178  return 1;
179  } else if (r == PORT_GT) {
180  SCLogDebug("PORT_GT (cur->next %p)", cur->next);
181  /* only add it now if we are bigger than the last
182  * group. Otherwise we'll handle it later. */
183  if (cur->next == NULL) {
184  SCLogDebug("adding GT");
185  /* put in the list */
186  new->prev = cur;
187  cur->next = new;
188  return 1;
189  }
190  } else if (r == PORT_LT) {
191  SCLogDebug("PORT_LT");
192 
193  /* see if we need to insert the ag anywhere */
194  /* put in the list */
195  if (cur->prev != NULL)
196  cur->prev->next = new;
197  new->prev = cur->prev;
198  new->next = cur;
199  cur->prev = new;
200 
201  /* update head if required */
202  if (*head == cur) {
203  *head = new;
204  }
205  return 1;
206 
207  /* alright, those were the simple cases,
208  * lets handle the more complex ones now */
209 
210  } else {
211  DetectPort *c = NULL;
212  r = DetectPortCut(de_ctx, cur, new, &c);
213  if (r == -1)
214  return -1;
215 
216  if (c != NULL) {
217  SCLogDebug("inserting C (%p)", c);
218  if (SCLogDebugEnabled()) {
219  DetectPortPrint(c);
220  }
221  r = DetectPortInsert(de_ctx, head, c);
222  if (r == -1) {
224  return -1;
225  }
226  }
227 
228  r = DetectPortInsert(de_ctx, head, new);
229  if (r == -1) {
230  return -1;
231  }
232 
233  return 1;
234 
235  }
236  }
237 
238  /* head is NULL, so get a group and set head to it */
239  } else {
240  SCLogDebug("setting new head %p", new);
241  *head = new;
242  }
243 
244  return 1;
245 }
246 
247 /**
248  * \brief Function that cuts port groups and merge them
249  *
250  * \param de_ctx Pointer to the current detection engine context
251  * \param a pointer to DetectPort "a"
252  * \param b pointer to DetectPort "b"
253  * \param c pointer to DetectPort "c"
254  *
255  * \retval 0 ok
256  * \retval -1 error
257  * */
258 static int DetectPortCut(DetectEngineCtx *de_ctx, DetectPort *a,
259  DetectPort *b, DetectPort **c)
260 {
261  uint16_t a_port1 = a->port;
262  uint16_t a_port2 = a->port2;
263  uint16_t b_port1 = b->port;
264  uint16_t b_port2 = b->port2;
265 
266  /* default to NULL */
267  *c = NULL;
268 
269  int r = DetectPortCmp(a,b);
270  BUG_ON(r != PORT_ES && r != PORT_EB && r != PORT_LE && r != PORT_GE);
271 
272  /**
273  * We have 3 parts: [aaa[abab]bbb]
274  * part a: a_port1 <-> b_port1 - 1
275  * part b: b_port1 <-> a_port2
276  * part c: a_port2 + 1 <-> b_port2
277  */
278  if (r == PORT_LE) {
279  SCLogDebug("cut r == PORT_LE");
280  a->port = a_port1;
281  a->port2 = b_port1 - 1;
282 
283  b->port = b_port1;
284  b->port2 = a_port2;
285 
286  DetectPort *tmp_c = DetectPortInit();
287  if (tmp_c == NULL) {
288  goto error;
289  }
290  *c = tmp_c;
291 
292  tmp_c->port = a_port2 + 1;
293  tmp_c->port2 = b_port2;
294 
295  /**
296  * We have 3 parts: [bbb[baba]aaa]
297  * part a: b_port1 <-> a_port1 - 1
298  * part b: a_port1 <-> b_port2
299  * part c: b_port2 + 1 <-> a_port2
300  */
301  } else if (r == PORT_GE) {
302  SCLogDebug("cut r == PORT_GE");
303  a->port = b_port1;
304  a->port2 = a_port1 - 1;
305 
306  b->port = a_port1;
307  b->port2 = b_port2;
308 
309  DetectPort *tmp_c = DetectPortInit();
310  if (tmp_c == NULL) {
311  goto error;
312  }
313  *c = tmp_c;
314 
315  tmp_c->port = b_port2 + 1;
316  tmp_c->port2 = a_port2;
317 
318  /**
319  * We have 2 or three parts:
320  *
321  * 2 part: [[abab]bbb] or [bbb[baba]]
322  * part a: a_port1 <-> a_port2
323  * part b: a_port2 + 1 <-> b_port2
324  *
325  * part a: b_port1 <-> a_port1 - 1
326  * part b: a_port1 <-> a_port2
327  *
328  * 3 part [bbb[aaa]bbb]
329  * becomes[aaa[bbb]ccc]
330  *
331  * part a: b_port1 <-> a_port1 - 1
332  * part b: a_port1 <-> a_port2
333  * part c: a_port2 + 1 <-> b_port2
334  */
335  } else if (r == PORT_ES) {
336  SCLogDebug("cut r == PORT_ES");
337  if (a_port1 == b_port1) {
338  SCLogDebug("1");
339  a->port = a_port1;
340  a->port2 = a_port2;
341 
342  b->port = a_port2 + 1;
343  b->port2 = b_port2;
344  } else if (a_port2 == b_port2) {
345  SCLogDebug("2");
346  a->port = b_port1;
347  a->port2 = a_port1 - 1;
348 
349  b->port = a_port1;
350  b->port2 = a_port2;
351  } else {
352  SCLogDebug("3");
353  a->port = b_port1;
354  a->port2 = a_port1 - 1;
355 
356  b->port = a_port1;
357  b->port2 = a_port2;
358 
359  DetectPort *tmp_c = DetectPortInit();
360  if (tmp_c == NULL) {
361  goto error;
362  }
363  *c = tmp_c;
364 
365  tmp_c->port = a_port2 + 1;
366  tmp_c->port2 = b_port2;
367  }
368  /**
369  * We have 2 or three parts:
370  *
371  * 2 part: [[baba]aaa] or [aaa[abab]]
372  * part a: b_port1 <-> b_port2
373  * part b: b_port2 + 1 <-> a_port2
374  *
375  * part a: a_port1 <-> b_port1 - 1
376  * part b: b_port1 <-> b_port2
377  *
378  * 3 part [aaa[bbb]aaa]
379  * becomes[aaa[bbb]ccc]
380  *
381  * part a: a_port1 <-> b_port2 - 1
382  * part b: b_port1 <-> b_port2
383  * part c: b_port2 + 1 <-> a_port2
384  */
385  } else if (r == PORT_EB) {
386  SCLogDebug("cut r == PORT_EB");
387  if (a_port1 == b_port1) {
388  SCLogDebug("1");
389  a->port = b_port1;
390  a->port2 = b_port2;
391 
392  b->port = b_port2 + 1;
393  b->port2 = a_port2;
394  } else if (a_port2 == b_port2) {
395  SCLogDebug("2");
396 
397  a->port = a_port1;
398  a->port2 = b_port1 - 1;
399 
400  b->port = b_port1;
401  b->port2 = b_port2;
402 
403  } else {
404  SCLogDebug("3");
405  a->port = a_port1;
406  a->port2 = b_port1 - 1;
407 
408  b->port = b_port1;
409  b->port2 = b_port2;
410 
411  DetectPort *tmp_c = DetectPortInit();
412  if (tmp_c == NULL) {
413  goto error;
414  }
415  *c = tmp_c;
416 
417  tmp_c->port = b_port2 + 1;
418  tmp_c->port2 = a_port2;
419  }
420  }
421 
422  return 0;
423 
424 error:
425  return -1;
426 }
427 
428 /**
429  * \brief Function that cuts port groups implementing group negation
430  *
431  * \param a pointer to DetectPort "a"
432  * \param b pointer to DetectPort "b"
433  *
434  * \retval 0 ok
435  * \retval -1 error
436  * */
437 static int DetectPortCutNot(DetectPort *a, DetectPort **b)
438 {
439  uint16_t a_port1 = a->port;
440  uint16_t a_port2 = a->port2;
441 
442  /* default to NULL */
443  *b = NULL;
444 
445  if (a_port1 != 0x0000 && a_port2 != 0xFFFF) {
446  a->port = 0x0000;
447  a->port2 = a_port1 - 1;
448 
449  DetectPort *tmp_b;
450  tmp_b = DetectPortInit();
451  if (tmp_b == NULL) {
452  return -1;
453  }
454 
455  tmp_b->port = a_port2 + 1;
456  tmp_b->port2 = 0xFFFF;
457  *b = tmp_b;
458 
459  } else if (a_port1 == 0x0000 && a_port2 != 0xFFFF) {
460  a->port = a_port2 + 1;
461  a->port2 = 0xFFFF;
462 
463  } else if (a_port1 != 0x0000 && a_port2 == 0xFFFF) {
464  a->port = 0x0000;
465  a->port2 = a_port1 - 1;
466  } else {
467  return -1;
468  }
469 
470  return 0;
471 }
472 
473 /**
474  * \brief Function that compare port groups
475  *
476  * \param a pointer to DetectPort "a"
477  * \param b pointer to DetectPort "b"
478  *
479  * \retval PORT_XX (Port enum value, XX is EQ, ES, EB, LE, etc)
480  * \retval PORT_ER on error
481  * */
483 {
484  uint16_t a_port1 = a->port;
485  uint16_t a_port2 = a->port2;
486  uint16_t b_port1 = b->port;
487  uint16_t b_port2 = b->port2;
488 
489  /* PORT_EQ */
490  if (a_port1 == b_port1 && a_port2 == b_port2) {
491  //SCLogDebug("PORT_EQ");
492  return PORT_EQ;
493  /* PORT_ES */
494  } else if (a_port1 >= b_port1 && a_port1 <= b_port2 && a_port2 <= b_port2) {
495  //SCLogDebug("PORT_ES");
496  return PORT_ES;
497  /* PORT_EB */
498  } else if (a_port1 <= b_port1 && a_port2 >= b_port2) {
499  //SCLogDebug("PORT_EB");
500  return PORT_EB;
501  } else if (a_port1 < b_port1 && a_port2 < b_port2 && a_port2 >= b_port1) {
502  //SCLogDebug("PORT_LE");
503  return PORT_LE;
504  } else if (a_port1 < b_port1 && a_port2 < b_port2) {
505  //SCLogDebug("PORT_LT");
506  return PORT_LT;
507  } else if (a_port1 > b_port1 && a_port1 <= b_port2 && a_port2 > b_port2) {
508  //SCLogDebug("PORT_GE");
509  return PORT_GE;
510  } else if (a_port1 > b_port2) {
511  //SCLogDebug("PORT_GT");
512  return PORT_GT;
513  }
514 
515  return PORT_ER;
516 }
517 
518 /**
519  * \brief Function that return a copy of DetectPort src sigs
520  *
521  * \param de_ctx Pointer to the current Detection Engine Context
522  * \param src Pointer to a DetectPort group to copy
523  *
524  * \retval Pointer to a DetectPort instance (copy of src)
525  * \retval NULL on error
526  * */
528 {
529  if (src == NULL)
530  return NULL;
531 
533  if (dst == NULL) {
534  return NULL;
535  }
536 
537  dst->port = src->port;
538  dst->port2 = src->port2;
539 
541  return dst;
542 }
543 
544 /**
545  * \brief Function Match to Match a port against a DetectPort group
546  *
547  * \param dp Pointer to DetectPort group where we try to match the port
548  * \param port To compare/match
549  *
550  * \retval 1 if port is in the range (it match)
551  * \retval 0 if port is not in the range
552  * */
553 static int DetectPortMatch(DetectPort *dp, uint16_t port)
554 {
555  if (port >= dp->port &&
556  port <= dp->port2) {
557  return 1;
558  }
559 
560  return 0;
561 }
562 
563 /**
564  * \brief Helper function that print the DetectPort info
565  * \retval none
566  */
568 {
569  if (dp == NULL)
570  return;
571 
572  SCLogDebug("=> port %p %" PRIu32 "-%" PRIu32 "", dp, dp->port, dp->port2);
573 }
574 
575 /**
576  * \brief Function that find the group matching port in a group head
577  *
578  * \param dp Pointer to DetectPort group where we try to find the group
579  * \param port port to search/lookup
580  *
581  * \retval Pointer to the DetectPort group of our port if it matched
582  * \retval NULL if port is not in the list
583  * */
585 {
586  if (dp == NULL)
587  return NULL;
588 
589  for (DetectPort *p = dp; p != NULL; p = p->next) {
590  if (DetectPortMatch(p, port) == 1) {
591  //SCLogDebug("match, port %" PRIu32 ", dp ", port);
592  //DetectPortPrint(p); SCLogDebug("");
593  return p;
594  }
595  }
596 
597  return NULL;
598 }
599 
600 /**
601  * \brief Checks if two port group lists are equal.
602  *
603  * \param list1 Pointer to the first port group list.
604  * \param list2 Pointer to the second port group list.
605  *
606  * \retval true On success.
607  * \retval false On failure.
608  */
610 {
611  DetectPort *item = list1;
612  DetectPort *it = list2;
613 
614  // First, compare items one by one.
615  while (item != NULL && it != NULL) {
616  if (DetectPortCmp(item, it) != PORT_EQ) {
617  return false;
618  }
619 
620  item = item->next;
621  it = it->next;
622  }
623 
624  // Are the lists of the same size?
625  return item == NULL && it == NULL;
626 }
627 
628 /******************* parsing routines ************************/
629 
630 /**
631  * \brief Wrapper function that call the internal/real function
632  * to insert the new DetectPort
633  * \param head Pointer to the head of the DetectPort group list
634  * \param new Pointer to the new DetectPort group list
635  *
636  * \retval 1 inserted
637  * \retval 0 not inserted, memory of new is freed
638  * \retval -1 error
639  */
640 static int DetectPortParseInsert(DetectPort **head, DetectPort *new)
641 {
642  return DetectPortInsert(NULL, head, new);
643 }
644 
645 /**
646  * \brief Function to parse and insert the string in the DetectPort head list
647  *
648  * \param head Pointer to the head of the DetectPort group list
649  * \param s Pointer to the port string
650  *
651  * \retval 0 on success
652  * \retval -1 on error
653  */
654 static int DetectPortParseInsertString(const DetectEngineCtx *de_ctx,
655  DetectPort **head, const char *s)
656 {
657  DetectPort *port = NULL;
658  int r = 0;
659 
660  SCLogDebug("head %p, *head %p, s %s", head, *head, s);
661 
662  /** parse the port */
663  port = PortParse(s);
664  if (port == NULL) {
665  SCLogError(" failed to parse port \"%s\"", s);
666  return -1;
667  }
668 
669  /** handle the not case, we apply the negation then insert the part(s) */
670  if (port->flags & PORT_FLAG_NOT) {
671  DetectPort *port2 = NULL;
672 
673  if (DetectPortCutNot(port, &port2) < 0) {
674  goto error;
675  }
676 
677  /** normally, a 'not' will at most result in two ports */
678  if (port2 != NULL) {
679  if (DetectPortParseInsert(head, port2) < 0) {
680  if (port2 != NULL)
681  SCFree(port2);
682  goto error;
683  }
684  }
685  }
686 
687  r = DetectPortParseInsert(head, port);
688  if (r < 0)
689  goto error;
690 
691  return 0;
692 
693 error:
694  SCLogError("DetectPortParseInsertString error");
695  if (port != NULL)
697  return -1;
698 }
699 
700 /**
701  * \brief Parses a port string and updates the 2 port heads with the
702  * port groups.
703  *
704  * \todo We don't seem to be handling negated cases, like [port,![!port,port]],
705  * since we pass around negate without keeping a count of ! with depth.
706  * Can solve this by keeping a count of the negations with depth, so that
707  * an even no of negations would count as no negation and an odd no of
708  * negations would count as a negation.
709  *
710  * \param gh Pointer to the port group head that should hold port ranges
711  * that are not negated.
712  * \param ghn Pointer to the port group head that should hold port ranges
713  * that are negated.
714  * \param s Pointer to the character string holding the port to be
715  * parsed.
716  * \param negate Flag that indicates if the received port string is negated
717  * or not. 0 if it is not, 1 it it is.
718  *
719  * \retval 0 On successfully parsing.
720  * \retval -1 On failure.
721  */
722 static int DetectPortParseDo(const DetectEngineCtx *de_ctx,
723  DetectPort **head, DetectPort **nhead,
724  const char *s, int negate,
725  ResolvedVariablesList *var_list, int recur)
726 {
727  size_t u = 0;
728  size_t x = 0;
729  int o_set = 0, n_set = 0, d_set = 0;
730  int range = 0;
731  int depth = 0;
732  size_t size = strlen(s);
733  char port[1024] = "";
734  const char *rule_var_port = NULL;
735  int r = 0;
736 
737  if (recur++ > 64) {
738  SCLogError("port block recursion "
739  "limit reached (max 64)");
740  goto error;
741  }
742 
743  SCLogDebug("head %p, *head %p, negate %d", head, *head, negate);
744 
745  for (; u < size && x < sizeof(port); u++) {
746  port[x] = s[u];
747  x++;
748 
749  if (s[u] == ':')
750  range = 1;
751 
752  if (range == 1 && s[u] == '!') {
753  SCLogError("Can't have a negated value in a range.");
754  return -1;
755  } else if (!o_set && s[u] == '!') {
756  SCLogDebug("negation encountered");
757  n_set = 1;
758  BUG_ON(x == 0); /* always false; added to guide static code analyzers like Coverity */
759  x--;
760  } else if (s[u] == '[') {
761  if (!o_set) {
762  o_set = 1;
763  x = 0;
764  }
765  depth++;
766  } else if (s[u] == ']') {
767  if (depth == 1) {
768  port[x - 1] = '\0';
769  SCLogDebug("Parsed port from DetectPortParseDo - %s", port);
770  x = 0;
771 
772  r = DetectPortParseDo(
773  de_ctx, head, nhead, port, negate ? negate : n_set, var_list, recur);
774  if (r == -1)
775  goto error;
776 
777  n_set = 0;
778  }
779  depth--;
780  range = 0;
781  } else if (depth == 0 && s[u] == ',') {
782  if (o_set == 1) {
783  o_set = 0;
784  } else if (d_set == 1) {
785  char *temp_rule_var_port = NULL,
786  *alloc_rule_var_port = NULL;
787 
788  port[x - 1] = '\0';
789 
790  rule_var_port = SCRuleVarsGetConfVar(de_ctx, port, SC_RULE_VARS_PORT_GROUPS);
791  if (rule_var_port == NULL)
792  goto error;
793  if (strlen(rule_var_port) == 0) {
794  SCLogError("variable %s resolved "
795  "to nothing. This is likely a misconfiguration. "
796  "Note that a negated port needs to be quoted, "
797  "\"!$HTTP_PORTS\" instead of !$HTTP_PORTS. See issue #295.",
798  s);
799  goto error;
800  }
801  if (negate == 1 || n_set == 1) {
802  /* add +1 to safisfy gcc 15 + -Wformat-truncation=2 */
803  const size_t str_size = strlen(rule_var_port) + 3 + 1;
804  alloc_rule_var_port = SCMalloc(str_size);
805  if (unlikely(alloc_rule_var_port == NULL))
806  goto error;
807  snprintf(alloc_rule_var_port, str_size, "[%s]", rule_var_port);
808  } else {
809  alloc_rule_var_port = SCStrdup(rule_var_port);
810  if (unlikely(alloc_rule_var_port == NULL))
811  goto error;
812  }
813  temp_rule_var_port = alloc_rule_var_port;
814  r = DetectPortParseDo(de_ctx, head, nhead, temp_rule_var_port,
815  (negate + n_set) % 2, var_list, recur);
816  if (r == -1) {
817  SCFree(alloc_rule_var_port);
818  goto error;
819  }
820  d_set = 0;
821  n_set = 0;
822  SCFree(alloc_rule_var_port);
823  } else {
824  port[x - 1] = '\0';
825  SCLogDebug("Parsed port from DetectPortParseDo - %s", port);
826 
827  if (negate == 0 && n_set == 0) {
828  r = DetectPortParseInsertString(de_ctx, head, port);
829  } else {
830  r = DetectPortParseInsertString(de_ctx, nhead, port);
831  }
832  if (r == -1)
833  goto error;
834 
835  n_set = 0;
836  }
837  x = 0;
838  range = 0;
839  } else if (depth == 0 && s[u] == '$') {
840  d_set = 1;
841  } else if (depth == 0 && u == size-1) {
842  range = 0;
843  if (x == 1024) {
844  port[x - 1] = '\0';
845  } else {
846  port[x] = '\0';
847  }
848  SCLogDebug("%s", port);
849 
850  if (AddVariableToResolveList(var_list, port) == -1) {
851  SCLogError("Found a loop in a port "
852  "groups declaration. This is likely a misconfiguration.");
853  goto error;
854  }
855 
856  x = 0;
857  if (d_set == 1) {
858  char *temp_rule_var_port = NULL,
859  *alloc_rule_var_port = NULL;
860 
861  rule_var_port = SCRuleVarsGetConfVar(de_ctx, port, SC_RULE_VARS_PORT_GROUPS);
862  if (rule_var_port == NULL)
863  goto error;
864  if (strlen(rule_var_port) == 0) {
865  SCLogError("variable %s resolved "
866  "to nothing. This is likely a misconfiguration. "
867  "Note that a negated port needs to be quoted, "
868  "\"!$HTTP_PORTS\" instead of !$HTTP_PORTS. See issue #295.",
869  s);
870  goto error;
871  }
872  if ((negate + n_set) % 2) {
873  /* add +1 to safisfy gcc 15 + -Wformat-truncation=2 */
874  const size_t str_size = strlen(rule_var_port) + 3 + 1;
875  alloc_rule_var_port = SCMalloc(str_size);
876  if (unlikely(alloc_rule_var_port == NULL))
877  goto error;
878  snprintf(alloc_rule_var_port, str_size, "[%s]", rule_var_port);
879  } else {
880  alloc_rule_var_port = SCStrdup(rule_var_port);
881  if (unlikely(alloc_rule_var_port == NULL))
882  goto error;
883  }
884  temp_rule_var_port = alloc_rule_var_port;
885  r = DetectPortParseDo(de_ctx, head, nhead, temp_rule_var_port,
886  (negate + n_set) % 2, var_list, recur);
887  SCFree(alloc_rule_var_port);
888  if (r == -1)
889  goto error;
890 
891  d_set = 0;
892  } else {
893  if (!((negate + n_set) % 2)) {
894  r = DetectPortParseInsertString(de_ctx, head, port);
895  } else {
896  r = DetectPortParseInsertString(de_ctx, nhead, port);
897  }
898  if (r == -1)
899  goto error;
900  }
901  n_set = 0;
902  } else if (depth == 1 && s[u] == ',') {
903  range = 0;
904  }
905  }
906 
907  if (depth > 0) {
908  SCLogError("not every port block was "
909  "properly closed in \"%s\", %d missing closing brackets (]). "
910  "Note: problem might be in a variable.",
911  s, depth);
912  goto error;
913  } else if (depth < 0) {
914  SCLogError("not every port block was "
915  "properly opened in \"%s\", %d missing opening brackets ([). "
916  "Note: problem might be in a variable.",
917  s, depth * -1);
918  goto error;
919  }
920 
921  return 0;
922 error:
923  return -1;
924 }
925 
926 /**
927  * \brief Check if the port group list covers the complete port space.
928  * \retval 0 no
929  * \retval 1 yes
930  */
931 static int DetectPortIsCompletePortSpace(DetectPort *p)
932 {
933  uint16_t next_port = 0;
934 
935  if (p == NULL)
936  return 0;
937 
938  if (p->port != 0x0000)
939  return 0;
940 
941  /* if we're ending with 0xFFFF while we know
942  we started with 0x0000 it's the complete space */
943  if (p->port2 == 0xFFFF)
944  return 1;
945 
946  next_port = p->port2 + 1;
947  p = p->next;
948 
949  for ( ; p != NULL; p = p->next) {
950  if (p->port != next_port)
951  return 0;
952 
953  if (p->port2 == 0xFFFF)
954  return 1;
955 
956  next_port = p->port2 + 1;
957  }
958 
959  return 0;
960 }
961 
962 /**
963  * \brief Helper function for the parsing process
964  *
965  * \param head Pointer to the head of the DetectPort group list
966  * \param nhead Pointer to the new head of the DetectPort group list
967  *
968  * \retval 0 on success
969  * \retval -1 on error
970  */
971 static int DetectPortParseMergeNotPorts(const DetectEngineCtx *de_ctx,
972  DetectPort **head, DetectPort **nhead)
973 {
974  DetectPort *port = NULL;
975  DetectPort *pg, *pg2;
976  int r = 0;
977 
978  /** check if the full port space is negated */
979  if (DetectPortIsCompletePortSpace(*nhead) == 1) {
980  SCLogError("Complete port space is negated");
981  goto error;
982  }
983 
984  /**
985  * step 0: if the head list is empty, but the nhead list isn't
986  * we have a pure not thingy. In that case we add a 0:65535
987  * first.
988  */
989  if (*head == NULL && *nhead != NULL) {
990  SCLogDebug("inserting 0:65535 into head");
991  r = DetectPortParseInsertString(de_ctx, head,"0:65535");
992  if (r < 0) {
993  goto error;
994  }
995  }
996 
997  /** step 1: insert our ghn members into the gh list */
998  for (pg = *nhead; pg != NULL; pg = pg->next) {
999  /** work with a copy of the port so we can easily clean up
1000  * the ghn group later.
1001  */
1002  port = DetectPortCopySingle(NULL, pg);
1003  if (port == NULL) {
1004  goto error;
1005  }
1006  r = DetectPortParseInsert(head, port);
1007  if (r < 0) {
1008  goto error;
1009  }
1010  port = NULL;
1011  }
1012 
1013  /** step 2: pull the port blocks that match our 'not' blocks */
1014  for (pg = *nhead; pg != NULL; pg = pg->next) {
1015  SCLogDebug("pg %p", pg);
1016  DetectPortPrint(pg);
1017 
1018  for (pg2 = *head; pg2 != NULL;) {
1019  SCLogDebug("pg2 %p", pg2);
1020  DetectPortPrint(pg2);
1021 
1022  r = DetectPortCmp(pg, pg2);
1023  if (r == PORT_EQ || r == PORT_EB) { /* XXX more ??? */
1024  if (pg2->prev != NULL)
1025  pg2->prev->next = pg2->next;
1026  if (pg2->next != NULL)
1027  pg2->next->prev = pg2->prev;
1028  if (*head == pg2)
1029  *head = pg2->next;
1030  /** store the next ptr and remove the group */
1031  DetectPort *next_pg2 = pg2->next;
1032  DetectPortFree(de_ctx, pg2);
1033  pg2 = next_pg2;
1034  } else {
1035  pg2 = pg2->next;
1036  }
1037  }
1038  }
1039 
1040  for (pg2 = *head; pg2 != NULL; pg2 = pg2->next) {
1041  SCLogDebug("pg2 %p", pg2);
1042  DetectPortPrint(pg2);
1043  }
1044 
1045  if (*head == NULL) {
1046  SCLogError("no ports left after merging ports with negated ports");
1047  goto error;
1048  }
1049 
1050  return 0;
1051 error:
1052  if (port != NULL)
1053  DetectPortFree(de_ctx, port);
1054  return -1;
1055 }
1056 
1058 {
1059  SCLogDebug("Testing port conf vars for any misconfigured values");
1060 
1061  ResolvedVariablesList var_list;
1062  TAILQ_INIT(&var_list);
1063 
1064  SCConfNode *port_vars_node = SCConfGetNode("vars.port-groups");
1065  if (port_vars_node == NULL) {
1066  return 0;
1067  }
1068 
1069  SCConfNode *seq_node;
1070  TAILQ_FOREACH(seq_node, &port_vars_node->head, next) {
1071  SCLogDebug("Testing %s - %s\n", seq_node->name, seq_node->val);
1072 
1073  DetectPort *gh = DetectPortInit();
1074  if (gh == NULL) {
1075  goto error;
1076  }
1077  DetectPort *ghn = NULL;
1078 
1079  if (seq_node->val == NULL) {
1080  SCLogError("Port var \"%s\" probably has a sequence(something "
1081  "in brackets) value set without any quotes. Please "
1082  "quote it using \"..\".",
1083  seq_node->name);
1084  DetectPortCleanupList(NULL, gh);
1085  goto error;
1086  }
1087 
1088  int r = DetectPortParseDo(NULL, &gh, &ghn, seq_node->val,
1089  /* start with negate no */0, &var_list, 0);
1090 
1091  CleanVariableResolveList(&var_list);
1092 
1093  if (r < 0) {
1094  DetectPortCleanupList(NULL, gh);
1095  SCLogError("failed to parse port var \"%s\" with value \"%s\". "
1096  "Please check its syntax",
1097  seq_node->name, seq_node->val);
1098  goto error;
1099  }
1100 
1101  if (DetectPortIsCompletePortSpace(ghn)) {
1102  SCLogError("Port var - \"%s\" has the complete Port range negated "
1103  "with its value \"%s\". Port space range is NIL. "
1104  "Probably have a !any or a port range that supplies "
1105  "a NULL port range",
1106  seq_node->name, seq_node->val);
1107  DetectPortCleanupList(NULL, gh);
1108  DetectPortCleanupList(NULL, ghn);
1109  goto error;
1110  }
1111 
1112  if (gh != NULL)
1113  DetectPortCleanupList(NULL, gh);
1114  if (ghn != NULL)
1115  DetectPortCleanupList(NULL, ghn);
1116  }
1117 
1118  return 0;
1119  error:
1120  return -1;
1121 }
1122 
1123 
1124 /**
1125  * \brief Function for parsing port strings
1126  *
1127  * \param de_ctx Pointer to the detection engine context
1128  * \param head Pointer to the head of the DetectPort group list
1129  * \param str Pointer to the port string
1130  *
1131  * \retval 0 on success
1132  * \retval -1 on error
1133  */
1135  DetectPort **head, const char *str)
1136 {
1137  SCLogDebug("Port string to be parsed - str %s", str);
1138 
1139  /* negate port list */
1140  DetectPort *nhead = NULL;
1141 
1142  int r = DetectPortParseDo(de_ctx, head, &nhead, str,
1143  /* start with negate no */ 0, NULL, 0);
1144  if (r < 0)
1145  goto error;
1146 
1147  SCLogDebug("head %p %p, nhead %p", head, *head, nhead);
1148 
1149  /* merge the 'not' port groups */
1150  if (DetectPortParseMergeNotPorts(de_ctx, head, &nhead) < 0)
1151  goto error;
1152 
1153  /* free the temp negate head */
1154  DetectPortCleanupList(de_ctx, nhead);
1155  return 0;
1156 
1157 error:
1158  DetectPortCleanupList(de_ctx, nhead);
1159  return -1;
1160 }
1161 
1162 /**
1163  * \brief Helper function for parsing port strings
1164  *
1165  * \param str Pointer to the port string
1166  *
1167  * \retval DetectPort pointer of the parse string on success
1168  * \retval NULL on error
1169  */
1170 DetectPort *PortParse(const char *str)
1171 {
1172  char *port2 = NULL;
1173  char portstr[16];
1174 
1175  /* strip leading spaces */
1176  while (isspace(*str))
1177  str++;
1178  if (strlen(str) >= 16)
1179  return NULL;
1180  strlcpy(portstr, str, sizeof(portstr));
1181 
1182  DetectPort *dp = DetectPortInit();
1183  if (dp == NULL)
1184  goto error;
1185 
1186  /* we dup so we can put a nul-termination in it later */
1187  char *port = portstr;
1188 
1189  /* handle the negation case */
1190  if (port[0] == '!') {
1191  dp->flags |= PORT_FLAG_NOT;
1192  port++;
1193  }
1194 
1195  if ((port2 = strchr(port, ':')) != NULL) {
1196  /* 80:81 range format */
1197  port2[0] = '\0';
1198  port2++;
1199 
1200  if (strcmp(port, "") != 0) {
1201  if (!DetectPortIsValidRange(port, &dp->port))
1202  goto error;
1203  } else {
1204  dp->port = 0;
1205  }
1206 
1207  if (strcmp(port2, "") != 0) {
1208  if (!DetectPortIsValidRange(port2, &dp->port2))
1209  goto error;
1210  } else {
1211  dp->port2 = 65535;
1212  }
1213 
1214  /* a > b is illegal, a == b is ok */
1215  if (dp->port > dp->port2)
1216  goto error;
1217  } else {
1218  if (strcasecmp(port,"any") == 0) {
1219  dp->port = 0;
1220  dp->port2 = 65535;
1221  } else {
1222  if (!DetectPortIsValidRange(port, &dp->port))
1223  goto error;
1224  dp->port2 = dp->port;
1225  }
1226  }
1227 
1228  return dp;
1229 
1230 error:
1231  if (dp != NULL)
1232  DetectPortCleanupList(NULL, dp);
1233  return NULL;
1234 }
1235 
1236 /**
1237  * \brief Helper function to check if a parsed port is in the valid range
1238  * of available ports
1239  *
1240  * \param str Pointer to the port string
1241  *
1242  *
1243  * \retval true if port is in the valid range
1244  * \retval false if invalid
1245  */
1246 static bool DetectPortIsValidRange(char *port, uint16_t *port_val)
1247 {
1248  return StringParseUint16(port_val, 10, 0, (const char *)port) >= 0;
1249 }
1250 
1251 /********************** End parsing routines ********************/
1252 
1253 /* hash table */
1254 
1255 /**
1256  * \brief The hash function to be the used by the hash table -
1257  * DetectEngineCtx->dport_hash_table.
1258  *
1259  * \param ht Pointer to the hash table.
1260  * \param data Pointer to the DetectPort.
1261  * \param datalen Not used in our case.
1262  *
1263  * \retval hash The generated hash value.
1264  */
1265 static uint32_t DetectPortHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1266 {
1267  DetectPort *p = (DetectPort *)data;
1268  SCLogDebug("hashing port %p", p);
1269 
1270  uint32_t hash = ((uint32_t)p->port << 16) | p->port2;
1271 
1272  hash %= ht->array_size;
1273  SCLogDebug("hash %"PRIu32, hash);
1274  return hash;
1275 }
1276 
1277 /**
1278  * \brief The Compare function to be used by the DetectPort hash table -
1279  * DetectEngineCtx->dport_hash_table.
1280  *
1281  * \param data1 Pointer to the first DetectPort.
1282  * \param len1 Not used.
1283  * \param data2 Pointer to the second DetectPort.
1284  * \param len2 Not used.
1285  *
1286  * \retval 1 If the 2 DetectPort sent as args match.
1287  * \retval 0 If the 2 DetectPort sent as args do not match.
1288  */
1289 static char DetectPortCompareFunc(void *data1, uint16_t len1,
1290  void *data2, uint16_t len2)
1291 {
1292  DetectPort *dp1 = (DetectPort *)data1;
1293  DetectPort *dp2 = (DetectPort *)data2;
1294 
1295  if (data1 == NULL || data2 == NULL)
1296  return 0;
1297 
1298  if (dp1->port == dp2->port && dp1->port2 == dp2->port2)
1299  return 1;
1300 
1301  return 0;
1302 }
1303 
1304 static void DetectPortHashFreeFunc(void *ptr)
1305 {
1306  DetectPort *p = ptr;
1307  DetectPortFree(NULL, p);
1308 }
1309 
1310 /**
1311  * \brief Initializes the hash table in the detection engine context to hold the
1312  * DetectPort hash.
1313  *
1314  * \param de_ctx Pointer to the detection engine context.
1315  *
1316  * \retval 0 On success.
1317  * \retval -1 On failure.
1318  */
1320 {
1321  de_ctx->dport_hash_table = HashListTableInit(4096, DetectPortHashFunc,
1322  DetectPortCompareFunc,
1323  DetectPortHashFreeFunc);
1324  if (de_ctx->dport_hash_table == NULL)
1325  return -1;
1326 
1327  return 0;
1328 }
1329 
1330 /**
1331  * \brief Adds a DetectPort to the detection engine context DetectPort
1332  * hash table.
1333  *
1334  * \param de_ctx Pointer to the detection engine context.
1335  * \param dp Pointer to the DetectPort.
1336  *
1337  * \retval ret 0 on Successfully adding the DetectPort; -1 on failure.
1338  */
1340 {
1341  int ret = HashListTableAdd(de_ctx->dport_hash_table, (void *)dp, 0);
1342  return ret;
1343 }
1344 
1345 /**
1346  * \brief Used to lookup a DetectPort hash from the detection engine context
1347  * DetectPort hash table.
1348  *
1349  * \param de_ctx Pointer to the detection engine context.
1350  * \param sgh Pointer to the DetectPort.
1351  *
1352  * \retval rsgh On success a pointer to the DetectPort if the DetectPort is
1353  * found in the hash table; NULL on failure.
1354  */
1356 {
1357  SCEnter();
1358 
1359  DetectPort *rdp = HashListTableLookup(de_ctx->dport_hash_table, (void *)dp, 0);
1360 
1361  SCReturnPtr(rdp, "DetectPort");
1362 }
1363 
1364 /**
1365  * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
1366  * DetectPortInit() function.
1367  *
1368  * \param de_ctx Pointer to the detection engine context.
1369  */
1371 {
1372  if (de_ctx->sgh_hash_table == NULL)
1373  return;
1374 
1376  de_ctx->dport_hash_table = NULL;
1377 }
1378 
1379 /*---------------------- Unittests -------------------------*/
1380 
1381 #ifdef UNITTESTS
1382 #include "packet.h"
1383 
1384 /**
1385  * \test Check if a DetectPort is properly allocated
1386  */
1387 static int PortTestParse01 (void)
1388 {
1389  DetectPort *dd = NULL;
1390  int r = DetectPortParse(NULL,&dd,"80");
1391  FAIL_IF_NOT(r == 0);
1392  DetectPortFree(NULL, dd);
1393  PASS;
1394 }
1395 
1396 /**
1397  * \test Check if two ports are properly allocated in the DetectPort group
1398  */
1399 static int PortTestParse02 (void)
1400 {
1401  DetectPort *dd = NULL;
1402  int r = DetectPortParse(NULL,&dd,"80");
1403  FAIL_IF_NOT(r == 0);
1404  r = DetectPortParse(NULL,&dd,"22");
1405  FAIL_IF_NOT(r == 0);
1406  DetectPortCleanupList(NULL, dd);
1407  PASS;
1408 }
1409 
1410 /**
1411  * \test Check if two port ranges are properly allocated in the DetectPort group
1412  */
1413 static int PortTestParse03 (void)
1414 {
1415  DetectPort *dd = NULL;
1416  int r = DetectPortParse(NULL,&dd,"80:88");
1417  FAIL_IF_NOT(r == 0);
1418  r = DetectPortParse(NULL,&dd,"85:100");
1419  FAIL_IF_NOT(r == 0);
1420  DetectPortCleanupList(NULL, dd);
1421  PASS;
1422 }
1423 
1424 /**
1425  * \test Check if a negated port range is properly allocated in the DetectPort
1426  */
1427 static int PortTestParse04 (void)
1428 {
1429  DetectPort *dd = NULL;
1430  int r = DetectPortParse(NULL,&dd,"!80:81");
1431  FAIL_IF_NOT(r == 0);
1432  DetectPortCleanupList(NULL, dd);
1433  PASS;
1434 }
1435 
1436 /**
1437  * \test Check if a negated port range is properly fragmented in the allowed
1438  * real groups, ex !80:81 should allow 0:79 and 82:65535
1439  */
1440 static int PortTestParse05 (void)
1441 {
1442  DetectPort *dd = NULL;
1443  int r = DetectPortParse(NULL,&dd,"!80:81");
1444  FAIL_IF_NOT(r == 0);
1445  FAIL_IF_NULL(dd->next);
1446  FAIL_IF_NOT(dd->port == 0);
1447  FAIL_IF_NOT(dd->port2 == 79);
1448  FAIL_IF_NOT(dd->next->port == 82);
1449  FAIL_IF_NOT(dd->next->port2 == 65535);
1450  DetectPortCleanupList(NULL, dd);
1451  PASS;
1452 }
1453 
1454 /**
1455  * \test Check if a negated port range is properly fragmented in the allowed
1456  * real groups
1457  */
1458 static int PortTestParse07 (void)
1459 {
1460  DetectPort *dd = NULL;
1461 
1462  int r = DetectPortParse(NULL,&dd,"!21:902");
1463  FAIL_IF_NOT(r == 0);
1464  FAIL_IF_NULL(dd->next);
1465 
1466  FAIL_IF_NOT(dd->port == 0);
1467  FAIL_IF_NOT(dd->port2 == 20);
1468  FAIL_IF_NOT(dd->next->port == 903);
1469  FAIL_IF_NOT(dd->next->port2 == 65535);
1470 
1471  DetectPortCleanupList(NULL, dd);
1472  PASS;
1473 }
1474 
1475 /**
1476  * \test Check if we dont allow invalid port range specification
1477  */
1478 static int PortTestParse08 (void)
1479 {
1480  DetectPort *dd = NULL;
1481 
1482  int r = DetectPortParse(NULL,&dd,"[80:!80]");
1483  FAIL_IF(r == 0);
1484 
1485  DetectPortCleanupList(NULL, dd);
1486  PASS;
1487 }
1488 
1489 /**
1490  * \test Check if we autocomplete correctly an open range
1491  */
1492 static int PortTestParse09 (void)
1493 {
1494  DetectPort *dd = NULL;
1495 
1496  int r = DetectPortParse(NULL,&dd,"1024:");
1497  FAIL_IF_NOT(r == 0);
1498  FAIL_IF_NULL(dd);
1499 
1500  FAIL_IF_NOT(dd->port == 1024);
1501  FAIL_IF_NOT(dd->port2 == 0xffff);
1502 
1503  DetectPortCleanupList(NULL, dd);
1504  PASS;
1505 }
1506 
1507 /**
1508  * \test Test we don't allow a port that is too big
1509  */
1510 static int PortTestParse10 (void)
1511 {
1512  DetectPort *dd = NULL;
1513  int r = DetectPortParse(NULL,&dd,"77777777777777777777777777777777777777777777");
1514  FAIL_IF(r == 0);
1515  PASS;
1516 }
1517 
1518 /**
1519  * \test Test second port of range being too big
1520  */
1521 static int PortTestParse11 (void)
1522 {
1523  DetectPort *dd = NULL;
1524 
1525  int r = DetectPortParse(NULL,&dd,"1024:65536");
1526  FAIL_IF(r == 0);
1527  PASS;
1528 }
1529 
1530 /**
1531  * \test Test second port of range being just right
1532  */
1533 static int PortTestParse12 (void)
1534 {
1535  DetectPort *dd = NULL;
1536  int r = DetectPortParse(NULL,&dd,"1024:65535");
1537  FAIL_IF_NOT(r == 0);
1538  DetectPortFree(NULL, dd);
1539  PASS;
1540 }
1541 
1542 /**
1543  * \test Test first port of range being too big
1544  */
1545 static int PortTestParse13 (void)
1546 {
1547  DetectPort *dd = NULL;
1548  int r = DetectPortParse(NULL,&dd,"65536:65535");
1549  FAIL_IF(r == 0);
1550  PASS;
1551 }
1552 
1553 /**
1554  * \test Test merging port groups
1555  */
1556 static int PortTestParse14 (void)
1557 {
1558  DetectPort *dd = NULL;
1559 
1560  int r = DetectPortParseInsertString(NULL, &dd, "0:100");
1561  FAIL_IF_NOT(r == 0);
1562  r = DetectPortParseInsertString(NULL, &dd, "1000:65535");
1563  FAIL_IF_NOT(r == 0);
1564  FAIL_IF_NULL(dd->next);
1565 
1566  FAIL_IF_NOT(dd->port == 0);
1567  FAIL_IF_NOT(dd->port2 == 100);
1568  FAIL_IF_NOT(dd->next->port == 1000);
1569  FAIL_IF_NOT(dd->next->port2 == 65535);
1570 
1571  DetectPortCleanupList(NULL, dd);
1572  PASS;
1573 }
1574 
1575 /**
1576  * \test Test merging negated port groups
1577  */
1578 static int PortTestParse15 (void)
1579 {
1580  DetectPort *dd = NULL;
1581 
1582  int r = DetectPortParse(NULL,&dd,"![0:100,1000:3000]");
1583  FAIL_IF_NOT(r == 0);
1584  FAIL_IF_NULL(dd->next);
1585 
1586  FAIL_IF_NOT(dd->port == 101);
1587  FAIL_IF_NOT(dd->port2 == 999);
1588  FAIL_IF_NOT(dd->next->port == 3001);
1589  FAIL_IF_NOT(dd->next->port2 == 65535);
1590 
1591  DetectPortCleanupList(NULL, dd);
1592  PASS;
1593 }
1594 
1595 static int PortTestParse16 (void)
1596 {
1597  DetectPort *dd = NULL;
1598  int r = DetectPortParse(NULL,&dd,"\
1599 [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\
1600 1:65535\
1601 ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
1602 ");
1603  FAIL_IF_NOT(r == 0);
1604  DetectPortFree(NULL, dd);
1605  dd = NULL;
1606  r = DetectPortParse(NULL,&dd,"\
1607 [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\
1608 1:65535\
1609 ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
1610 ");
1611  FAIL_IF(r == 0);
1612  PASS;
1613 }
1614 
1615 /**
1616  * \test Test general functions
1617  */
1618 static int PortTestFunctions02(void)
1619 {
1620  DetectPort *head = NULL;
1621  DetectPort *dp1= NULL;
1622  DetectPort *dp2= NULL;
1623  int result = 0;
1624 
1625  /* Parse */
1626  int r = DetectPortParse(NULL,&head, "![0:100,1000:65535]");
1627  if (r != 0 || head->next != NULL)
1628  goto end;
1629 
1630  r = DetectPortParse(NULL, &dp1, "!200:300");
1631  if (r != 0 || dp1->next == NULL)
1632  goto end;
1633 
1634  /* Merge Nots */
1635  r = DetectPortParseMergeNotPorts(NULL, &head, &dp1);
1636  if (r != 0 || head->next != NULL)
1637  goto end;
1638 
1639  r = DetectPortParse(NULL, &dp2, "!100:500");
1640  if (r != 0 || dp2->next == NULL)
1641  goto end;
1642 
1643  /* Merge Nots */
1644  r = DetectPortParseMergeNotPorts(NULL, &head, &dp2);
1645  if (r != 0 || head->next != NULL)
1646  goto end;
1647 
1648  if (!(head->port == 200))
1649  goto end;
1650  if (!(head->port2 == 300))
1651  goto end;
1652 
1653  result = 1;
1654 
1655 end:
1656  if (dp1 != NULL)
1657  DetectPortCleanupList(NULL, dp1);
1658  if (dp2 != NULL)
1659  DetectPortCleanupList(NULL, dp2);
1660  if (head != NULL)
1661  DetectPortCleanupList(NULL, head);
1662  return result;
1663 }
1664 
1665 /**
1666  * \test Test general functions
1667  */
1668 static int PortTestFunctions03(void)
1669 {
1670  DetectPort *dp1= NULL;
1671  DetectPort *dp2= NULL;
1672  DetectPort *dp3= NULL;
1673  int result = 0;
1674 
1675  int r = DetectPortParse(NULL, &dp1, "200:300");
1676  if (r != 0)
1677  goto end;
1678 
1679  r = DetectPortParse(NULL, &dp2, "250:300");
1680  if (r != 0)
1681  goto end;
1682 
1683  /* Cut */
1684  DetectPortCut(NULL, dp1, dp2, &dp3);
1685  if (r != 0)
1686  goto end;
1687 
1688  if (!(dp1->port == 200))
1689  goto end;
1690  if (!(dp1->port2 == 249))
1691  goto end;
1692  if (!(dp2->port == 250))
1693  goto end;
1694  if (!(dp2->port2 == 300))
1695  goto end;
1696 
1697  dp1->port = 0;
1698  dp1->port2 = 500;
1699  dp2->port = 250;
1700  dp2->port2 = 750;
1701 
1702  /* Cut */
1703  DetectPortCut(NULL, dp1, dp2, &dp3);
1704  if (r != 0)
1705  goto end;
1706  if (!(dp1->port == 0))
1707  goto end;
1708  if (!(dp1->port2 == 249))
1709  goto end;
1710  if (!(dp2->port == 250))
1711  goto end;
1712  if (!(dp2->port2 == 500))
1713  goto end;
1714  if (!(dp3->port == 501))
1715  goto end;
1716  if (!(dp3->port2 == 750))
1717  goto end;
1718 
1719  result = 1;
1720 
1721 end:
1722  if (dp1 != NULL)
1723  DetectPortCleanupList(NULL, dp1);
1724  if (dp2 != NULL)
1725  DetectPortCleanupList(NULL, dp2);
1726  if (dp3 != NULL)
1727  DetectPortCleanupList(NULL, dp3);
1728  return result;
1729 }
1730 
1731 /**
1732  * \test Test general functions
1733  */
1734 static int PortTestFunctions04(void)
1735 {
1736  DetectPort *dp1 = NULL;
1737  DetectPort *dp2 = NULL;
1738  int result = 0;
1739 
1740  int r = DetectPortParse(NULL, &dp1, "200:300");
1741  if (r != 0)
1742  goto end;
1743 
1744  /* Cut Not */
1745  r = DetectPortCutNot(dp1, &dp2);
1746  if (r != 0)
1747  goto end;
1748 
1749  if (!(dp1->port == 0))
1750  goto end;
1751  if (!(dp1->port2 == 199))
1752  goto end;
1753  if (!(dp2->port == 301))
1754  goto end;
1755  if (!(dp2->port2 == 65535))
1756  goto end;
1757 
1758  result = 1;
1759 end:
1760  if (dp1 != NULL)
1761  DetectPortCleanupList(NULL, dp1);
1762  if (dp2 != NULL)
1763  DetectPortCleanupList(NULL, dp2);
1764  return result;
1765 }
1766 
1767 /**
1768  * \test Test general functions
1769  */
1770 static int PortTestFunctions07(void)
1771 {
1772  DetectPort *dd = NULL;
1773 
1774  // This one should fail due to negation in a range
1775  FAIL_IF(DetectPortParse(NULL, &dd, "[80:!99]") == 0);
1776 
1777  // Correct: from 80 till 100 but 99 excluded
1778  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[80:100,!99]") == 0);
1779  FAIL_IF_NULL(dd->next);
1780  FAIL_IF_NOT(dd->port == 80);
1781  FAIL_IF_NOT(dd->port2 == 98);
1782  FAIL_IF_NOT(dd->next->port == 100);
1783 
1784  // Also good: from 1 till 80 except of 2 and 4
1785  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[1:80,![2,4]]") == 0);
1786  FAIL_IF_NOT(dd->port == 1);
1790 
1791  DetectPortCleanupList(NULL, dd);
1792  PASS;
1793 }
1794 
1795 /**
1796  * \test Test packet Matches
1797  * \param raw_eth_pkt pointer to the ethernet packet
1798  * \param pktsize size of the packet
1799  * \param sig pointer to the signature to test
1800  * \param sid sid number of the signature
1801  * \retval return 1 if match
1802  * \retval return 0 if not
1803  */
1804 static int PortTestMatchReal(uint8_t *raw_eth_pkt, uint16_t pktsize, const char *sig,
1805  uint32_t sid)
1806 {
1807  int result = 0;
1809  Packet *p = UTHBuildPacketFromEth(raw_eth_pkt, pktsize);
1810  result = UTHPacketMatchSig(p, sig);
1811  PacketFree(p);
1812  FlowShutdown();
1813  return result;
1814 }
1815 
1816 /**
1817  * \brief Wrapper for PortTestMatchReal
1818  */
1819 static int PortTestMatchRealWrp(const char *sig, uint32_t sid)
1820 {
1821  /* Real HTTP packeth doing a GET method
1822  * tcp.sport=47370 tcp.dport=80
1823  * ip.src=192.168.28.131 ip.dst=192.168.1.1
1824  */
1825  uint8_t raw_eth_pkt[] = {
1826  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
1827  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
1828  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
1829  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
1830  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
1831  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
1832  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
1833  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
1834  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
1835  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
1836  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
1837  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
1838  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
1839  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
1840  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
1841  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
1842  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
1843  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
1844  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
1845  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
1846  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
1847  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
1848  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
1849  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
1850  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
1851  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
1852  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
1853  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
1854  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
1855  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
1856  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
1857  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
1858  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
1859  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
1860  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
1861  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
1862  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
1863  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
1864  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
1865  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
1866  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
1867  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
1868  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
1869  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
1870  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
1871  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
1872  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
1873  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
1874  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
1875  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
1876  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
1877  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
1878  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
1879  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
1880  0x76,0x65,0x0d,0x0a,0x0d,0x0a };
1881  /* end raw_eth_pkt */
1882 
1883  return PortTestMatchReal(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
1884  sig, sid);
1885 }
1886 
1887 /**
1888  * \test Check if we match a dest port
1889  */
1890 static int PortTestMatchReal01(void)
1891 {
1892  /* tcp.sport=47370 tcp.dport=80 */
1893  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
1894  return PortTestMatchRealWrp(sig, 1);
1895 }
1896 
1897 /**
1898  * \test Check if we match a source port
1899  */
1900 static int PortTestMatchReal02(void)
1901 {
1902  const char *sig = "alert tcp any 47370 -> any any (msg:\"Nothing..\";"
1903  " content:\"GET\"; sid:1;)";
1904  return PortTestMatchRealWrp(sig, 1);
1905 }
1906 
1907 /**
1908  * \test Check if we match both of them
1909  */
1910 static int PortTestMatchReal03(void)
1911 {
1912  const char *sig = "alert tcp any 47370 -> any 80 (msg:\"Nothing..\";"
1913  " content:\"GET\"; sid:1;)";
1914  return PortTestMatchRealWrp(sig, 1);
1915 }
1916 
1917 /**
1918  * \test Check if we negate dest ports correctly
1919  */
1920 static int PortTestMatchReal04(void)
1921 {
1922  const char *sig = "alert tcp any any -> any !80 (msg:\"Nothing..\";"
1923  " content:\"GET\"; sid:1;)";
1924  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
1925 }
1926 
1927 /**
1928  * \test Check if we negate source ports correctly
1929  */
1930 static int PortTestMatchReal05(void)
1931 {
1932  const char *sig = "alert tcp any !47370 -> any any (msg:\"Nothing..\";"
1933  " content:\"GET\"; sid:1;)";
1934  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
1935 }
1936 
1937 /**
1938  * \test Check if we negate both ports correctly
1939  */
1940 static int PortTestMatchReal06(void)
1941 {
1942  const char *sig = "alert tcp any !47370 -> any !80 (msg:\"Nothing..\";"
1943  " content:\"GET\"; sid:1;)";
1944  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
1945 }
1946 
1947 /**
1948  * \test Check if we match a dest port range
1949  */
1950 static int PortTestMatchReal07(void)
1951 {
1952  const char *sig = "alert tcp any any -> any 70:100 (msg:\"Nothing..\";"
1953  " content:\"GET\"; sid:1;)";
1954  return PortTestMatchRealWrp(sig, 1);
1955 }
1956 
1957 /**
1958  * \test Check if we match a source port range
1959  */
1960 static int PortTestMatchReal08(void)
1961 {
1962  const char *sig = "alert tcp any 47000:50000 -> any any (msg:\"Nothing..\";"
1963  " content:\"GET\"; sid:1;)";
1964  return PortTestMatchRealWrp(sig, 1);
1965 }
1966 
1967 /**
1968  * \test Check if we match both port ranges
1969  */
1970 static int PortTestMatchReal09(void)
1971 {
1972  const char *sig = "alert tcp any 47000:50000 -> any 70:100 (msg:\"Nothing..\";"
1973  " content:\"GET\"; sid:1;)";
1974  return PortTestMatchRealWrp(sig, 1);
1975 }
1976 
1977 /**
1978  * \test Check if we negate a dest port range
1979  */
1980 static int PortTestMatchReal10(void)
1981 {
1982  const char *sig = "alert tcp any any -> any !70:100 (msg:\"Nothing..\";"
1983  " content:\"GET\"; sid:1;)";
1984  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
1985 }
1986 
1987 /**
1988  * \test Check if we negate a source port range
1989  */
1990 static int PortTestMatchReal11(void)
1991 {
1992  const char *sig = "alert tcp any !47000:50000 -> any any (msg:\"Nothing..\";"
1993  " content:\"GET\"; sid:1;)";
1994  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
1995 }
1996 
1997 /**
1998  * \test Check if we negate both port ranges
1999  */
2000 static int PortTestMatchReal12(void)
2001 {
2002  const char *sig = "alert tcp any !47000:50000 -> any !70:100 (msg:\"Nothing..\";"
2003  " content:\"GET\"; sid:1;)";
2004  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2005 }
2006 
2007 /**
2008  * \test Check if we autocomplete ranges correctly
2009  */
2010 static int PortTestMatchReal13(void)
2011 {
2012  const char *sig = "alert tcp any 47000:50000 -> any !81: (msg:\"Nothing..\";"
2013  " content:\"GET\"; sid:1;)";
2014  return PortTestMatchRealWrp(sig, 1);
2015 }
2016 
2017 /**
2018  * \test Check if we autocomplete ranges correctly
2019  */
2020 static int PortTestMatchReal14(void)
2021 {
2022  const char *sig = "alert tcp any !48000:50000 -> any :100 (msg:\"Nothing..\";"
2023  " content:\"GET\"; sid:1;)";
2024  return PortTestMatchRealWrp(sig, 1);
2025 }
2026 
2027 /**
2028  * \test Check if we autocomplete ranges correctly
2029  */
2030 static int PortTestMatchReal15(void)
2031 {
2032  const char *sig = "alert tcp any :50000 -> any 81:100 (msg:\"Nothing..\";"
2033  " content:\"GET\"; sid:1;)";
2034  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2035 }
2036 
2037 /**
2038  * \test Check if we separate ranges correctly
2039  */
2040 static int PortTestMatchReal16(void)
2041 {
2042  const char *sig = "alert tcp any 100: -> any ![0:79,81:65535] (msg:\"Nothing..\";"
2043  " content:\"GET\"; sid:1;)";
2044  return PortTestMatchRealWrp(sig, 1);
2045 }
2046 
2047 /**
2048  * \test Check if we separate ranges correctly
2049  */
2050 static int PortTestMatchReal17(void)
2051 {
2052  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any ![0:80,82:65535] "
2053  "(msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2054  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2055 }
2056 
2057 /**
2058  * \test Check if we separate ranges correctly
2059  */
2060 static int PortTestMatchReal18(void)
2061 {
2062  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any 80 (msg:\"Nothing"
2063  " at all\"; content:\"GET\"; sid:1;)";
2064  return PortTestMatchRealWrp(sig, 1);
2065 }
2066 
2067 /**
2068  * \test Check if we separate ranges correctly
2069  */
2070 static int PortTestMatchReal19(void)
2071 {
2072  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\";"
2073  " content:\"GET\"; sid:1;)";
2074  return PortTestMatchRealWrp(sig, 1);
2075 }
2076 
2077 static int PortTestMatchDoubleNegation(void)
2078 {
2079  DetectPort *head = NULL, *nhead = NULL;
2080  FAIL_IF(DetectPortParseDo(NULL, &head, &nhead, "![!80]", 0, NULL, 0) == -1);
2081  FAIL_IF_NOT(head != NULL);
2082  FAIL_IF_NOT(nhead == NULL);
2083  DetectPortCleanupList(NULL, head);
2084  PASS;
2085 }
2086 
2087 // Test that negation is successfully parsed with whitespace for port strings of
2088 // length < 16
2089 static int DetectPortParseDoTest(void)
2090 {
2093  DetectPort *head = NULL;
2094  DetectPort *nhead = NULL;
2095  const char *str = "[30:50, !45]";
2096  int r = DetectPortParseDo(de_ctx, &head, &nhead, str, 0, NULL, 0);
2097 
2098  // Assertions
2099  FAIL_IF_NULL(head);
2100  FAIL_IF_NULL(nhead);
2101  FAIL_IF(r < 0);
2102  FAIL_IF(head->port != 30);
2103  FAIL_IF(head->port2 != 50);
2104  FAIL_IF(nhead->port != 45);
2105  FAIL_IF(nhead->port2 != 45);
2106  DetectPortCleanupList(NULL, head);
2107  DetectPortCleanupList(NULL, nhead);
2109  PASS;
2110 }
2111 
2112 static int DetectPortParseDoTest2(void)
2113 {
2116  DetectPort *head = NULL;
2117  DetectPort *nhead = NULL;
2118  const char *str = "[30:50, !45]";
2119  int r = DetectPortParseDo(de_ctx, &head, &nhead, str, 0, NULL, 0);
2120  FAIL_IF(r < 0);
2121  DetectPortCleanupList(NULL, head);
2122  DetectPortCleanupList(NULL, nhead);
2124  PASS;
2125 }
2126 
2127 // Verifies correct parsing when negation port string length < 16
2128 static int PortParseTestLessThan14Spaces(void)
2129 {
2130  const char *str = " 45";
2131  DetectPort *dp = PortParse(str);
2132  FAIL_IF_NULL(dp);
2133  FAIL_IF(dp->port != 45);
2134  FAIL_IF(dp->port2 != 45);
2135  DetectPortFree(NULL, dp);
2136  PASS;
2137 }
2138 
2139 // Verifies NULL returned when negation port string length == 16
2140 static int PortParseTest14Spaces(void)
2141 {
2142  const char *str = " 45";
2143  DetectPort *dp = PortParse(str);
2144  FAIL_IF_NULL(dp);
2145  FAIL_IF(dp->port != 45);
2146  FAIL_IF(dp->port2 != 45);
2147  DetectPortFree(NULL, dp);
2148  PASS;
2149 }
2150 
2151 // Verifies NULL returned when negation port string length >= 16
2152 static int PortParseTestMoreThan14Spaces(void)
2153 {
2154  const char *str = " 45";
2155  DetectPort *dp = PortParse(str);
2156  FAIL_IF_NULL(dp);
2157  FAIL_IF(dp->port != 45);
2158  FAIL_IF(dp->port2 != 45);
2159  DetectPortFree(NULL, dp);
2160  PASS;
2161 }
2162 
2163 void DetectPortTests(void)
2164 {
2165  UtRegisterTest("PortTestParse01", PortTestParse01);
2166  UtRegisterTest("PortTestParse02", PortTestParse02);
2167  UtRegisterTest("PortTestParse03", PortTestParse03);
2168  UtRegisterTest("PortTestParse04", PortTestParse04);
2169  UtRegisterTest("PortTestParse05", PortTestParse05);
2170  UtRegisterTest("PortTestParse07", PortTestParse07);
2171  UtRegisterTest("PortTestParse08", PortTestParse08);
2172  UtRegisterTest("PortTestParse09", PortTestParse09);
2173  UtRegisterTest("PortTestParse10", PortTestParse10);
2174  UtRegisterTest("PortTestParse11", PortTestParse11);
2175  UtRegisterTest("PortTestParse12", PortTestParse12);
2176  UtRegisterTest("PortTestParse13", PortTestParse13);
2177  UtRegisterTest("PortTestParse14", PortTestParse14);
2178  UtRegisterTest("PortTestParse15", PortTestParse15);
2179  UtRegisterTest("PortTestParse16", PortTestParse16);
2180  UtRegisterTest("PortTestFunctions02", PortTestFunctions02);
2181  UtRegisterTest("PortTestFunctions03", PortTestFunctions03);
2182  UtRegisterTest("PortTestFunctions04", PortTestFunctions04);
2183  UtRegisterTest("PortTestFunctions07", PortTestFunctions07);
2184  UtRegisterTest("PortTestMatchReal01", PortTestMatchReal01);
2185  UtRegisterTest("PortTestMatchReal02", PortTestMatchReal02);
2186  UtRegisterTest("PortTestMatchReal03", PortTestMatchReal03);
2187  UtRegisterTest("PortTestMatchReal04", PortTestMatchReal04);
2188  UtRegisterTest("PortTestMatchReal05", PortTestMatchReal05);
2189  UtRegisterTest("PortTestMatchReal06", PortTestMatchReal06);
2190  UtRegisterTest("PortTestMatchReal07", PortTestMatchReal07);
2191  UtRegisterTest("PortTestMatchReal08", PortTestMatchReal08);
2192  UtRegisterTest("PortTestMatchReal09", PortTestMatchReal09);
2193  UtRegisterTest("PortTestMatchReal10", PortTestMatchReal10);
2194  UtRegisterTest("PortTestMatchReal11", PortTestMatchReal11);
2195  UtRegisterTest("PortTestMatchReal12", PortTestMatchReal12);
2196  UtRegisterTest("PortTestMatchReal13", PortTestMatchReal13);
2197  UtRegisterTest("PortTestMatchReal14", PortTestMatchReal14);
2198  UtRegisterTest("PortTestMatchReal15", PortTestMatchReal15);
2199  UtRegisterTest("PortTestMatchReal16", PortTestMatchReal16);
2200  UtRegisterTest("PortTestMatchReal17", PortTestMatchReal17);
2201  UtRegisterTest("PortTestMatchReal18", PortTestMatchReal18);
2202  UtRegisterTest("PortTestMatchReal19", PortTestMatchReal19);
2203  UtRegisterTest("PortTestMatchDoubleNegation", PortTestMatchDoubleNegation);
2204  UtRegisterTest("DetectPortParseDoTest", DetectPortParseDoTest);
2205  UtRegisterTest("DetectPortParseDoTest2", DetectPortParseDoTest2);
2206  UtRegisterTest("PortParseTestLessThan14Spaces", PortParseTestLessThan14Spaces);
2207  UtRegisterTest("PortParseTest14Spaces", PortParseTest14Spaces);
2208  UtRegisterTest("PortParseTestMoreThan14Spaces", PortParseTestMoreThan14Spaces);
2209 }
2210 
2211 #endif /* UNITTESTS */
DetectEngineCtx_::sgh_hash_table
HashListTable * sgh_hash_table
Definition: detect.h:1029
util-byte.h
host.h
DetectPortCmp
int DetectPortCmp(DetectPort *a, DetectPort *b)
Function that compare port groups.
Definition: detect-engine-port.c:482
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:262
DetectPortHashInit
int DetectPortHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table in the detection engine context to hold the DetectPort hash.
Definition: detect-engine-port.c:1319
detect-engine-siggroup.h
DetectPortListsAreEqual
bool DetectPortListsAreEqual(DetectPort *list1, DetectPort *list2)
Checks if two port group lists are equal.
Definition: detect-engine-port.c:609
DetectPortInsert
int DetectPortInsert(DetectEngineCtx *de_ctx, DetectPort **head, DetectPort *new)
function for inserting a port group object. This also makes sure SigGroupContainer lists are handled ...
Definition: detect-engine-port.c:152
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
PORT_EQ
@ PORT_EQ
Definition: detect.h:212
DetectPortFree
void DetectPortFree(const DetectEngineCtx *de_ctx, DetectPort *dp)
Free a DetectPort and its members.
Definition: detect-engine-port.c:79
PORT_LT
@ PORT_LT
Definition: detect.h:210
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectPort_::port
uint16_t port
Definition: detect.h:224
PORT_SIGGROUPHEAD_COPY
#define PORT_SIGGROUPHEAD_COPY
Definition: detect.h:220
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
StringParseUint16
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:295
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2912
PORT_EB
@ PORT_EB
Definition: detect.h:214
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:237
UTHPacketMatchSig
int UTHPacketMatchSig(Packet *p, const char *sig)
Definition: util-unittest-helper.c:833
DetectEngineCtx_::dport_hash_table
HashListTable * dport_hash_table
Definition: detect.h:1136
p
Packet * p
Definition: fuzz_dataset.c:30
DetectPort_::sh
struct SigGroupHead_ * sh
Definition: detect.h:234
DetectPortPrintList
void DetectPortPrintList(DetectPort *head)
Helper function used to print the list of ports present in this DetectPort list.
Definition: detect-engine-port.c:99
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:244
CleanVariableResolveList
void CleanVariableResolveList(ResolvedVariablesList *var_list)
Definition: util-var.c:168
DetectPortTestConfVars
int DetectPortTestConfVars(void)
Definition: detect-engine-port.c:1057
util-var.h
PortParse
DetectPort * PortParse(const char *str)
Helper function for parsing port strings.
Definition: detect-engine-port.c:1170
DetectPort_::port2
uint16_t port2
Definition: detect.h:225
DetectPortInit
DetectPort * DetectPortInit(void)
Alloc a DetectPort structure and update counters.
Definition: detect-engine-port.c:66
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectPort_::flags
uint8_t flags
Definition: detect.h:227
DetectPortPrint
void DetectPortPrint(DetectPort *dp)
Helper function that print the DetectPort info.
Definition: detect-engine-port.c:567
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:113
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:574
DetectPortCopySingle
DetectPort * DetectPortCopySingle(DetectEngineCtx *de_ctx, DetectPort *src)
Function that return a copy of DetectPort src sigs.
Definition: detect-engine-port.c:527
util-cidr.h
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1134
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:34
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
SC_RULE_VARS_PORT_GROUPS
@ SC_RULE_VARS_PORT_GROUPS
Definition: util-rule-vars.h:32
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
util-error.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect-engine-mpm.h
detect.h
StreamContentInspectEngineData::s
const Signature * s
Definition: detect-engine-payload.c:264
pkt-var.h
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:221
detect-engine-port.h
PORT_ES
@ PORT_ES
Definition: detect.h:213
DetectPort_
Port structure for detection engine.
Definition: detect.h:223
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:322
util-profiling.h
util-rule-vars.h
Packet_
Definition: decode.h:516
conf.h
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:300
HashListTable_
Definition: util-hashlist.h:37
SigGroupHeadFree
void SigGroupHeadFree(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Free a SigGroupHead and its members.
Definition: detect-engine-siggroup.c:162
PORT_ER
@ PORT_ER
Definition: detect.h:209
PORT_LE
@ PORT_LE
Definition: detect.h:211
Flow_::next
struct Flow_ * next
Definition: flow.h:406
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:87
PORT_GE
@ PORT_GE
Definition: detect.h:215
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:718
packet.h
DetectPort_::prev
struct DetectPort_ * prev
Definition: detect.h:236
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
Packet_::next
struct Packet_ * next
Definition: decode.h:648
str
#define str(s)
Definition: suricata-common.h:313
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:183
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
src
uint16_t src
Definition: app-layer-dnp3.h:5
AddVariableToResolveList
int AddVariableToResolveList(ResolvedVariablesList *list, const char *var)
Definition: util-var.c:139
UTHBuildPacketFromEth
Packet * UTHBuildPacketFromEth(uint8_t *raw_eth, uint16_t pktsize)
UTHBuildPacketFromEth is a wrapper that build a packet for the rawbytes.
Definition: util-unittest-helper.c:379
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2873
PORT_FLAG_NOT
#define PORT_FLAG_NOT
Definition: detect.h:219
DetectPortHashAdd
int DetectPortHashAdd(DetectEngineCtx *de_ctx, DetectPort *dp)
Adds a DetectPort to the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1339
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:43
SCConfNode_::name
char * name
Definition: conf.h:38
DetectPortTests
void DetectPortTests(void)
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
DetectPortHashFree
void DetectPortHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by DetectPortInit() function.
Definition: detect-engine-port.c:1370
SCRuleVarsGetConfVar
const char * SCRuleVarsGetConfVar(const DetectEngineCtx *de_ctx, const char *conf_var_name, SCRuleVarsType conf_vars_type)
Definition: util-rule-vars.c:64
DetectPortHashLookup
DetectPort * DetectPortHashLookup(DetectEngineCtx *de_ctx, DetectPort *dp)
Used to lookup a DetectPort hash from the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1355
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCConfNode_
Definition: conf.h:37
flow-var.h
SCConfNode_::val
char * val
Definition: conf.h:39
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:123
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:767
DetectPortLookupGroup
DetectPort * DetectPortLookupGroup(DetectPort *dp, uint16_t port)
Function that find the group matching port in a group head.
Definition: detect-engine-port.c:584
SigGroupHeadCopySigs
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
Copies the bitarray holding the sids from the source SigGroupHead to the destination SigGroupHead.
Definition: detect-engine-siggroup.c:389
PORT_GT
@ PORT_GT
Definition: detect.h:216