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