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