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