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 = TAILQ_HEAD_INITIALIZER(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:967
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
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: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:937
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:2652
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:1074
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:1170
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:1134
TAILQ_HEAD_INITIALIZER
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:236
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:19
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:317
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:394
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:308
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:2613
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: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: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: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: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