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  if(atoi(port) >= 0 && atoi(port) <= 65535)
1469  return 1;
1470  else
1471  return 0;
1472 }
1473 /********************** End parsing routines ********************/
1474 
1475 /* hash table */
1476 
1477 /**
1478  * \brief The hash function to be the used by the hash table -
1479  * DetectEngineCtx->dport_hash_table.
1480  *
1481  * \param ht Pointer to the hash table.
1482  * \param data Pointer to the DetectPort.
1483  * \param datalen Not used in our case.
1484  *
1485  * \retval hash The generated hash value.
1486  */
1487 static uint32_t DetectPortHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1488 {
1489  DetectPort *p = (DetectPort *)data;
1490  uint32_t hash = 0;
1491 
1492  SCLogDebug("hashing sgh %p", p);
1493 
1494  hash = ((uint32_t)p->port << 16) | p->port2;
1495 
1496  hash %= ht->array_size;
1497  SCLogDebug("hash %"PRIu32, hash);
1498  return hash;
1499 }
1500 
1501 /**
1502  * \brief The Compare function to be used by the DetectPort hash table -
1503  * DetectEngineCtx->dport_hash_table.
1504  *
1505  * \param data1 Pointer to the first DetectPort.
1506  * \param len1 Not used.
1507  * \param data2 Pointer to the second DetectPort.
1508  * \param len2 Not used.
1509  *
1510  * \retval 1 If the 2 DetectPort sent as args match.
1511  * \retval 0 If the 2 DetectPort sent as args do not match.
1512  */
1513 static char DetectPortCompareFunc(void *data1, uint16_t len1,
1514  void *data2, uint16_t len2)
1515 {
1516  DetectPort *dp1 = (DetectPort *)data1;
1517  DetectPort *dp2 = (DetectPort *)data2;
1518 
1519  if (data1 == NULL || data2 == NULL)
1520  return 0;
1521 
1522  if (dp1->port == dp2->port && dp1->port2 == dp2->port2)
1523  return 1;
1524 
1525  return 0;
1526 }
1527 
1528 static void DetectPortHashFreeFunc(void *ptr)
1529 {
1530  DetectPort *p = ptr;
1531  DetectPortFree(NULL, p);
1532 }
1533 
1534 /**
1535  * \brief Initializes the hash table in the detection engine context to hold the
1536  * DetectPort hash.
1537  *
1538  * \param de_ctx Pointer to the detection engine context.
1539  *
1540  * \retval 0 On success.
1541  * \retval -1 On failure.
1542  */
1544 {
1545  de_ctx->dport_hash_table = HashListTableInit(4096, DetectPortHashFunc,
1546  DetectPortCompareFunc,
1547  DetectPortHashFreeFunc);
1548  if (de_ctx->dport_hash_table == NULL)
1549  goto error;
1550 
1551  return 0;
1552 
1553 error:
1554  return -1;
1555 }
1556 
1557 /**
1558  * \brief Adds a DetectPort to the detection engine context DetectPort
1559  * hash table.
1560  *
1561  * \param de_ctx Pointer to the detection engine context.
1562  * \param dp Pointer to the DetectPort.
1563  *
1564  * \retval ret 0 on Successfully adding the DetectPort; -1 on failure.
1565  */
1567 {
1568  int ret = HashListTableAdd(de_ctx->dport_hash_table, (void *)dp, 0);
1569  return ret;
1570 }
1571 
1572 /**
1573  * \brief Used to lookup a DetectPort hash from the detection engine context
1574  * DetectPort hash table.
1575  *
1576  * \param de_ctx Pointer to the detection engine context.
1577  * \param sgh Pointer to the DetectPort.
1578  *
1579  * \retval rsgh On success a pointer to the DetectPort if the DetectPort is
1580  * found in the hash table; NULL on failure.
1581  */
1583 {
1584  SCEnter();
1585 
1586  DetectPort *rdp = HashListTableLookup(de_ctx->dport_hash_table, (void *)dp, 0);
1587 
1588  SCReturnPtr(rdp, "DetectPort");
1589 }
1590 
1591 /**
1592  * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
1593  * DetectPortInit() function.
1594  *
1595  * \param de_ctx Pointer to the detection engine context.
1596  */
1598 {
1599  if (de_ctx->sgh_hash_table == NULL)
1600  return;
1601 
1603  de_ctx->dport_hash_table = NULL;
1604 
1605  return;
1606 }
1607 
1608 /*---------------------- Unittests -------------------------*/
1609 
1610 #ifdef UNITTESTS
1611 /**
1612  * \brief Do a sorted insert, where the top of the list should be the biggest
1613  * port range.
1614  *
1615  * \todo XXX current sorting only works for overlapping ranges
1616  *
1617  * \param head Pointer to the DetectPort list head
1618  * \param dp Pointer to DetectPort to search in the DetectPort list
1619  * \retval 0 if dp is added correctly
1620  */
1621 static int PortTestDetectPortAdd(DetectPort **head, DetectPort *dp)
1622 {
1623  DetectPort *cur, *prev_cur = NULL;
1624 
1625  //SCLogDebug("DetectPortAdd: adding "); DetectPortPrint(ag); SCLogDebug("");
1626 
1627  if (*head != NULL) {
1628  for (cur = *head; cur != NULL; cur = cur->next) {
1629  prev_cur = cur;
1630  int r = DetectPortCmp(dp,cur);
1631  if (r == PORT_EB) {
1632  /* insert here */
1633  dp->prev = cur->prev;
1634  dp->next = cur;
1635 
1636  cur->prev = dp;
1637  if (*head == cur) {
1638  *head = dp;
1639  } else {
1640  dp->prev->next = dp;
1641  }
1642  return 0;
1643  }
1644  }
1645  dp->prev = prev_cur;
1646  if (prev_cur != NULL)
1647  prev_cur->next = dp;
1648  } else {
1649  *head = dp;
1650  }
1651 
1652  return 0;
1653 }
1654 
1655 
1656 /**
1657  * \test Check if a DetectPort is properly allocated
1658  */
1659 static int PortTestParse01 (void)
1660 {
1661  DetectPort *dd = NULL;
1662 
1663  int r = DetectPortParse(NULL,&dd,"80");
1664  if (r == 0) {
1665  DetectPortFree(NULL, dd);
1666  return 1;
1667  }
1668 
1669  return 0;
1670 }
1671 
1672 /**
1673  * \test Check if two ports are properly allocated in the DetectPort group
1674  */
1675 static int PortTestParse02 (void)
1676 {
1677  DetectPort *dd = NULL;
1678  int result = 0;
1679 
1680  int r = DetectPortParse(NULL,&dd,"80");
1681  if (r == 0) {
1682  r = DetectPortParse(NULL,&dd,"22");
1683  if (r == 0) {
1684  result = 1;
1685  }
1686 
1687  DetectPortCleanupList(NULL, dd);
1688  return result;
1689  }
1690 
1691  return result;
1692 }
1693 
1694 /**
1695  * \test Check if two port ranges are properly allocated in the DetectPort group
1696  */
1697 static int PortTestParse03 (void)
1698 {
1699  DetectPort *dd = NULL;
1700  int result = 0;
1701 
1702  int r = DetectPortParse(NULL,&dd,"80:88");
1703  if (r == 0) {
1704  r = DetectPortParse(NULL,&dd,"85:100");
1705  if (r == 0) {
1706  result = 1;
1707  }
1708 
1709  DetectPortCleanupList(NULL, dd);
1710 
1711  return result;
1712  }
1713 
1714  return result;
1715 }
1716 
1717 /**
1718  * \test Check if a negated port range is properly allocated in the DetectPort
1719  */
1720 static int PortTestParse04 (void)
1721 {
1722  DetectPort *dd = NULL;
1723 
1724  int r = DetectPortParse(NULL,&dd,"!80:81");
1725  if (r == 0) {
1726  DetectPortCleanupList(NULL, dd);
1727  return 1;
1728  }
1729 
1730  return 0;
1731 }
1732 
1733 /**
1734  * \test Check if a negated port range is properly fragmented in the allowed
1735  * real groups, ex !80:81 should allow 0:79 and 82:65535
1736  */
1737 static int PortTestParse05 (void)
1738 {
1739  DetectPort *dd = NULL;
1740  int result = 0;
1741 
1742  int r = DetectPortParse(NULL,&dd,"!80:81");
1743  if (r != 0)
1744  goto end;
1745 
1746  if (dd->next == NULL)
1747  goto end;
1748 
1749  if (dd->port != 0 || dd->port2 != 79)
1750  goto end;
1751 
1752  if (dd->next->port != 82 || dd->next->port2 != 65535)
1753  goto end;
1754 
1755  DetectPortCleanupList(NULL, dd);
1756  result = 1;
1757 end:
1758  return result;
1759 }
1760 
1761 /**
1762  * \test Check if we copy a DetectPort correctly
1763  */
1764 static int PortTestParse06 (void)
1765 {
1766  DetectPort *dd = NULL, *copy = NULL;
1767  int result = 0;
1768 
1769  int r = DetectPortParse(NULL,&dd,"22");
1770  if (r != 0)
1771  goto end;
1772 
1773  r = DetectPortParse(NULL,&dd,"80");
1774  if (r != 0)
1775  goto end;
1776 
1777  r = DetectPortParse(NULL,&dd,"143");
1778  if (r != 0)
1779  goto end;
1780 
1781  copy = DetectPortCopy(NULL,dd);
1782  if (copy == NULL)
1783  goto end;
1784 
1785  if (DetectPortCmp(dd,copy) != PORT_EQ)
1786  goto end;
1787 
1788  if (copy->next == NULL)
1789  goto end;
1790 
1791  if (DetectPortCmp(dd->next,copy->next) != PORT_EQ)
1792  goto end;
1793 
1794  if (copy->next->next == NULL)
1795  goto end;
1796 
1797  if (DetectPortCmp(dd->next->next,copy->next->next) != PORT_EQ)
1798  goto end;
1799 
1800  if (copy->port != 22 || copy->next->port != 80 ||
1801  copy->next->next->port != 143)
1802  goto end;
1803 
1804  result = 1;
1805 
1806 end:
1807  if (copy != NULL)
1808  DetectPortCleanupList(NULL, copy);
1809  if (dd != NULL)
1810  DetectPortCleanupList(NULL, dd);
1811  return result;
1812 }
1813 
1814 /**
1815  * \test Check if a negated port range is properly fragmented in the allowed
1816  * real groups
1817  */
1818 static int PortTestParse07 (void)
1819 {
1820  DetectPort *dd = NULL;
1821  int result = 0;
1822 
1823  int r = DetectPortParse(NULL,&dd,"!21:902");
1824  if (r != 0)
1825  goto end;
1826 
1827  if (dd->next == NULL)
1828  goto end;
1829 
1830  if (dd->port != 0 || dd->port2 != 20)
1831  goto end;
1832 
1833  if (dd->next->port != 903 || dd->next->port2 != 65535)
1834  goto end;
1835 
1836  DetectPortCleanupList(NULL, dd);
1837  result = 1;
1838 end:
1839  return result;
1840 }
1841 
1842 /**
1843  * \test Check if we dont allow invalid port range specification
1844  */
1845 static int PortTestParse08 (void)
1846 {
1847  DetectPort *dd = NULL;
1848  int result = 0;
1849 
1850  int r = DetectPortParse(NULL,&dd,"[80:!80]");
1851  if (r == 0)
1852  goto end;
1853 
1854  DetectPortCleanupList(NULL, dd);
1855  result = 1;
1856 end:
1857  return result;
1858 }
1859 
1860 /**
1861  * \test Check if we autocomplete correctly an open range
1862  */
1863 static int PortTestParse09 (void)
1864 {
1865  DetectPort *dd = NULL;
1866  int result = 0;
1867 
1868  int r = DetectPortParse(NULL,&dd,"1024:");
1869  if (r != 0)
1870  goto end;
1871 
1872  if (dd == NULL)
1873  goto end;
1874 
1875  if (dd->port != 1024 || dd->port2 != 0xffff)
1876  goto end;
1877 
1878  DetectPortCleanupList(NULL, dd);
1879  result = 1;
1880 end:
1881  return result;
1882 }
1883 
1884 /**
1885  * \test Test we don't allow a port that is too big
1886  */
1887 static int PortTestParse10 (void)
1888 {
1889  DetectPort *dd = NULL;
1890  int result = 0;
1891 
1892  int r = DetectPortParse(NULL,&dd,"77777777777777777777777777777777777777777777");
1893  if (r != 0) {
1894  result = 1 ;
1895  goto end;
1896  }
1897 
1898  DetectPortFree(NULL, dd);
1899 
1900 end:
1901  return result;
1902 }
1903 
1904 /**
1905  * \test Test second port of range being too big
1906  */
1907 static int PortTestParse11 (void)
1908 {
1909  DetectPort *dd = NULL;
1910  int result = 0;
1911 
1912  int r = DetectPortParse(NULL,&dd,"1024:65536");
1913  if (r != 0) {
1914  result = 1 ;
1915  goto end;
1916  }
1917 
1918  DetectPortFree(NULL, dd);
1919 
1920 end:
1921  return result;
1922 }
1923 
1924 /**
1925  * \test Test second port of range being just right
1926  */
1927 static int PortTestParse12 (void)
1928 {
1929  DetectPort *dd = NULL;
1930  int result = 0;
1931 
1932  int r = DetectPortParse(NULL,&dd,"1024:65535");
1933  if (r != 0) {
1934  goto end;
1935  }
1936 
1937  DetectPortFree(NULL, dd);
1938 
1939  result = 1 ;
1940 end:
1941  return result;
1942 }
1943 
1944 /**
1945  * \test Test first port of range being too big
1946  */
1947 static int PortTestParse13 (void)
1948 {
1949  DetectPort *dd = NULL;
1950  int result = 0;
1951 
1952  int r = DetectPortParse(NULL,&dd,"65536:65535");
1953  if (r != 0) {
1954  result = 1 ;
1955  goto end;
1956  }
1957 
1958  DetectPortFree(NULL, dd);
1959 
1960 end:
1961  return result;
1962 }
1963 
1964 /**
1965  * \test Test merging port groups
1966  */
1967 static int PortTestParse14 (void)
1968 {
1969  DetectPort *dd = NULL;
1970  int result = 0;
1971 
1972  int r = DetectPortParseInsertString(NULL, &dd, "0:100");
1973  if (r != 0)
1974  goto end;
1975  r = DetectPortParseInsertString(NULL, &dd, "1000:65535");
1976  if (r != 0 || dd->next == NULL)
1977  goto end;
1978 
1979  result = 1;
1980  result &= (dd->port == 0) ? 1 : 0;
1981  result &= (dd->port2 == 100) ? 1 : 0;
1982  result &= (dd->next->port == 1000) ? 1 : 0;
1983  result &= (dd->next->port2 == 65535) ? 1 : 0;
1984 
1985  DetectPortFree(NULL, dd);
1986 
1987 end:
1988  return result;
1989 }
1990 
1991 /**
1992  * \test Test merging negated port groups
1993  */
1994 static int PortTestParse15 (void)
1995 {
1996  DetectPort *dd = NULL;
1997  int result = 0;
1998 
1999  int r = DetectPortParse(NULL,&dd,"![0:100,1000:3000]");
2000  if (r != 0 || dd->next == NULL)
2001  goto end;
2002 
2003  result = 1;
2004  result &= (dd->port == 101) ? 1 : 0;
2005  result &= (dd->port2 == 999) ? 1 : 0;
2006  result &= (dd->next->port == 3001) ? 1 : 0;
2007  result &= (dd->next->port2 == 65535) ? 1 : 0;
2008 
2009  DetectPortFree(NULL, dd);
2010 
2011 end:
2012  return result;
2013 }
2014 
2015 /**
2016  * \test Test parse, copy and cmp functions
2017  */
2018 static int PortTestParse16 (void)
2019 {
2020  DetectPort *dd = NULL, *copy = NULL;
2021  int result = 0;
2022 
2023  int r = DetectPortParse(NULL,&dd,"22");
2024  if (r != 0)
2025  goto end;
2026 
2027  r = DetectPortParse(NULL,&dd,"80");
2028  if (r != 0)
2029  goto end;
2030 
2031  r = DetectPortParse(NULL,&dd,"143");
2032  if (r != 0)
2033  goto end;
2034 
2035  copy = DetectPortCopy(NULL,dd);
2036  if (copy == NULL)
2037  goto end;
2038 
2039  if (DetectPortCmp(dd,copy) != PORT_EQ)
2040  goto end;
2041 
2042  if (copy->next == NULL)
2043  goto end;
2044 
2045  if (DetectPortCmp(dd->next,copy->next) != PORT_EQ)
2046  goto end;
2047 
2048  if (copy->next->next == NULL)
2049  goto end;
2050 
2051  if (DetectPortCmp(dd->next->next,copy->next->next) != PORT_EQ)
2052  goto end;
2053 
2054  if (copy->port != 22 || copy->next->port != 80 || copy->next->next->port != 143)
2055  goto end;
2056 
2057  if (copy->next->prev != copy)
2058  goto end;
2059 
2060  result = 1;
2061 
2062 end:
2063  if (copy != NULL)
2064  DetectPortCleanupList(NULL, copy);
2065  if (dd != NULL)
2066  DetectPortCleanupList(NULL, dd);
2067  return result;
2068 }
2069 
2070 /**
2071  * \test Test general functions
2072  */
2073 static int PortTestFunctions01(void)
2074 {
2075  DetectPort *head = NULL;
2076  DetectPort *dp1= NULL;
2077  int result = 0;
2078 
2079  /* Parse */
2080  int r = DetectPortParse(NULL,&head,"![0:100,1000:65535]");
2081  if (r != 0 || head->next != NULL)
2082  goto end;
2083 
2084  /* We should have only one DetectPort */
2085  if (!(head->port == 101))
2086  goto end;
2087  if (!(head->port2 == 999))
2088  goto end;
2089  if (!(head->next == NULL))
2090  goto end;
2091 
2092  r = DetectPortParse(NULL, &dp1,"2000:3000");
2093  if (r != 0 || dp1->next != NULL)
2094  goto end;
2095  if (!(dp1->port == 2000))
2096  goto end;
2097  if (!(dp1->port2 == 3000))
2098  goto end;
2099 
2100  /* Add */
2101  r = PortTestDetectPortAdd(&head, dp1);
2102  if (r != 0 || head->next == NULL)
2103  goto end;
2104  if (!(head->port == 101))
2105  goto end;
2106  if (!(head->port2 == 999))
2107  goto end;
2108  if (!(head->next->port == 2000))
2109  goto end;
2110  if (!(head->next->port2 == 3000))
2111  goto end;
2112 
2113  /* Match */
2114  if (!DetectPortMatch(head, 150))
2115  goto end;
2116  if (DetectPortMatch(head->next, 1500))
2117  goto end;
2118  if ((DetectPortMatch(head, 3500)))
2119  goto end;
2120  if ((DetectPortMatch(head, 50)))
2121  goto end;
2122 
2123  result = 1;
2124 end:
2125  if (dp1 != NULL)
2126  DetectPortFree(NULL, dp1);
2127  if (head != NULL)
2128  DetectPortFree(NULL, head);
2129  return result;
2130 }
2131 
2132 /**
2133  * \test Test general functions
2134  */
2135 static int PortTestFunctions02(void)
2136 {
2137  DetectPort *head = NULL;
2138  DetectPort *dp1= NULL;
2139  DetectPort *dp2= NULL;
2140  int result = 0;
2141 
2142  /* Parse */
2143  int r = DetectPortParse(NULL,&head, "![0:100,1000:65535]");
2144  if (r != 0 || head->next != NULL)
2145  goto end;
2146 
2147  r = DetectPortParse(NULL, &dp1, "!200:300");
2148  if (r != 0 || dp1->next == NULL)
2149  goto end;
2150 
2151  /* Merge Nots */
2152  r = DetectPortParseMergeNotPorts(NULL, &head, &dp1);
2153  if (r != 0 || head->next != NULL)
2154  goto end;
2155 
2156  r = DetectPortParse(NULL, &dp2, "!100:500");
2157  if (r != 0 || dp2->next == NULL)
2158  goto end;
2159 
2160  /* Merge Nots */
2161  r = DetectPortParseMergeNotPorts(NULL, &head, &dp2);
2162  if (r != 0 || head->next != NULL)
2163  goto end;
2164 
2165  if (!(head->port == 200))
2166  goto end;
2167  if (!(head->port2 == 300))
2168  goto end;
2169 
2170  result = 1;
2171 
2172 end:
2173  if (dp1 != NULL)
2174  DetectPortFree(NULL, dp1);
2175  if (dp2 != NULL)
2176  DetectPortFree(NULL, dp2);
2177  if (head != NULL)
2178  DetectPortFree(NULL, head);
2179  return result;
2180 }
2181 
2182 /**
2183  * \test Test general functions
2184  */
2185 static int PortTestFunctions03(void)
2186 {
2187  DetectPort *dp1= NULL;
2188  DetectPort *dp2= NULL;
2189  DetectPort *dp3= NULL;
2190  int result = 0;
2191 
2192  int r = DetectPortParse(NULL, &dp1, "200:300");
2193  if (r != 0)
2194  goto end;
2195 
2196  r = DetectPortParse(NULL, &dp2, "250:300");
2197  if (r != 0)
2198  goto end;
2199 
2200  /* Cut */
2201  DetectPortCut(NULL, dp1, dp2, &dp3);
2202  if (r != 0)
2203  goto end;
2204 
2205  if (!(dp1->port == 200))
2206  goto end;
2207  if (!(dp1->port2 == 249))
2208  goto end;
2209  if (!(dp2->port == 250))
2210  goto end;
2211  if (!(dp2->port2 == 300))
2212  goto end;
2213 
2214  dp1->port = 0;
2215  dp1->port2 = 500;
2216  dp2->port = 250;
2217  dp2->port2 = 750;
2218 
2219  /* Cut */
2220  DetectPortCut(NULL, dp1, dp2, &dp3);
2221  if (r != 0)
2222  goto end;
2223  if (!(dp1->port == 0))
2224  goto end;
2225  if (!(dp1->port2 == 249))
2226  goto end;
2227  if (!(dp2->port == 250))
2228  goto end;
2229  if (!(dp2->port2 == 500))
2230  goto end;
2231  if (!(dp3->port == 501))
2232  goto end;
2233  if (!(dp3->port2 == 750))
2234  goto end;
2235 
2236  result = 1;
2237 
2238 end:
2239  if (dp1 != NULL)
2240  DetectPortFree(NULL, dp1);
2241  if (dp2 != NULL)
2242  DetectPortFree(NULL, dp2);
2243  if (dp3 != NULL)
2244  DetectPortFree(NULL, dp3);
2245  return result;
2246 }
2247 
2248 /**
2249  * \test Test general functions
2250  */
2251 static int PortTestFunctions04(void)
2252 {
2253  DetectPort *dp1= NULL;
2254  DetectPort *dp2= NULL;
2255  int result = 0;
2256 
2257  int r = DetectPortParse(NULL, &dp1, "200:300");
2258  if (r != 0)
2259  goto end;
2260 
2261  dp2 = DetectPortInit();
2262 
2263  /* Cut Not */
2264  DetectPortCutNot(dp1, &dp2);
2265  if (r != 0)
2266  goto end;
2267 
2268  if (!(dp1->port == 0))
2269  goto end;
2270  if (!(dp1->port2 == 199))
2271  goto end;
2272  if (!(dp2->port == 301))
2273  goto end;
2274  if (!(dp2->port2 == 65535))
2275  goto end;
2276 
2277  result = 1;
2278 end:
2279  if (dp1 != NULL)
2280  DetectPortFree(NULL, dp1);
2281  if (dp2 != NULL)
2282  DetectPortFree(NULL, dp2);
2283  return result;
2284 }
2285 
2286 /**
2287  * \test Test general functions
2288  */
2289 static int PortTestFunctions05(void)
2290 {
2291  DetectPort *dp1 = NULL;
2292  DetectPort *dp2 = NULL;
2293  DetectPort *dp3 = NULL;
2294  int result = 0;
2295  int r = 0;
2296 
2298  Signature s[2];
2299  memset(s,0x00,sizeof(s));
2300 
2301  s[0].num = 0;
2302  s[1].num = 1;
2303 
2304  r = DetectPortParse(NULL, &dp1, "1024:65535");
2305  if (r != 0) {
2306  printf("r != 0 but %d: ", r);
2307  goto end;
2308  }
2309  SigGroupHeadAppendSig(de_ctx, &dp1->sh, &s[0]);
2310 
2311  r = DetectPortParse(NULL, &dp2, "any");
2312  if (r != 0) {
2313  printf("r != 0 but %d: ", r);
2314  goto end;
2315  }
2316  SigGroupHeadAppendSig(de_ctx, &dp2->sh, &s[1]);
2317 
2318  SCLogDebug("dp1");
2319  DetectPortPrint(dp1);
2320  SCLogDebug("dp2");
2321  DetectPortPrint(dp2);
2322 
2323  DetectPortInsert(de_ctx, &dp3, dp1);
2324  DetectPortInsert(de_ctx, &dp3, dp2);
2325 
2326  if (dp3 == NULL)
2327  goto end;
2328 
2329  SCLogDebug("dp3");
2330  DetectPort *x = dp3;
2331  for ( ; x != NULL; x = x->next) {
2332  DetectPortPrint(x);
2333  //SigGroupHeadPrintSigs(de_ctx, x->sh);
2334  }
2335 
2336  DetectPort *one = dp3;
2337  DetectPort *two = dp3->next;
2338 
2339  int sig = 0;
2340  if ((one->sh->init->sig_array[sig / 8] & (1 << (sig % 8)))) {
2341  printf("sig %d part of 'one', but it shouldn't: ", sig);
2342  goto end;
2343  }
2344  sig = 1;
2345  if (!(one->sh->init->sig_array[sig / 8] & (1 << (sig % 8)))) {
2346  printf("sig %d part of 'one', but it shouldn't: ", sig);
2347  goto end;
2348  }
2349  sig = 1;
2350  if (!(two->sh->init->sig_array[sig / 8] & (1 << (sig % 8)))) {
2351  printf("sig %d part of 'two', but it shouldn't: ", sig);
2352  goto end;
2353  }
2354 
2355  result = 1;
2356 end:
2357  if (dp1 != NULL)
2358  DetectPortFree(NULL, dp1);
2359  if (dp2 != NULL)
2360  DetectPortFree(NULL, dp2);
2361  return result;
2362 }
2363 
2364 /**
2365  * \test Test general functions
2366  */
2367 static int PortTestFunctions06(void)
2368 {
2369  DetectPort *dp1 = NULL;
2370  DetectPort *dp2 = NULL;
2371  DetectPort *dp3 = NULL;
2372  int result = 0;
2373  int r = 0;
2374 
2376  Signature s[2];
2377  memset(s,0x00,sizeof(s));
2378 
2379  s[0].num = 0;
2380  s[1].num = 1;
2381 
2382  r = DetectPortParse(NULL, &dp1, "1024:65535");
2383  if (r != 0) {
2384  printf("r != 0 but %d: ", r);
2385  goto end;
2386  }
2387  SigGroupHeadAppendSig(de_ctx, &dp1->sh, &s[0]);
2388 
2389  r = DetectPortParse(NULL, &dp2, "any");
2390  if (r != 0) {
2391  printf("r != 0 but %d: ", r);
2392  goto end;
2393  }
2394  SigGroupHeadAppendSig(de_ctx, &dp2->sh, &s[1]);
2395 
2396  SCLogDebug("dp1");
2397  DetectPortPrint(dp1);
2398  SCLogDebug("dp2");
2399  DetectPortPrint(dp2);
2400 
2401  DetectPortInsert(de_ctx, &dp3, dp2);
2402  DetectPortInsert(de_ctx, &dp3, dp1);
2403 
2404  if (dp3 == NULL)
2405  goto end;
2406 
2407  SCLogDebug("dp3");
2408  DetectPort *x = dp3;
2409  for ( ; x != NULL; x = x->next) {
2410  DetectPortPrint(x);
2411  //SigGroupHeadPrintSigs(de_ctx, x->sh);
2412  }
2413 
2414  DetectPort *one = dp3;
2415  DetectPort *two = dp3->next;
2416 
2417  int sig = 0;
2418  if ((one->sh->init->sig_array[sig / 8] & (1 << (sig % 8)))) {
2419  printf("sig %d part of 'one', but it shouldn't: ", sig);
2420  goto end;
2421  }
2422  sig = 1;
2423  if (!(one->sh->init->sig_array[sig / 8] & (1 << (sig % 8)))) {
2424  printf("sig %d part of 'one', but it shouldn't: ", sig);
2425  goto end;
2426  }
2427  sig = 1;
2428  if (!(two->sh->init->sig_array[sig / 8] & (1 << (sig % 8)))) {
2429  printf("sig %d part of 'two', but it shouldn't: ", sig);
2430  goto end;
2431  }
2432 
2433  result = 1;
2434 end:
2435  if (dp1 != NULL)
2436  DetectPortFree(NULL, dp1);
2437  if (dp2 != NULL)
2438  DetectPortFree(NULL, dp2);
2439  return result;
2440 }
2441 
2442 /**
2443  * \test Test general functions
2444  */
2445 static int PortTestFunctions07(void)
2446 {
2447  DetectPort *dd = NULL;
2448 
2449  // This one should fail due to negation in a range
2450  FAIL_IF(DetectPortParse(NULL, &dd, "[80:!99]") == 0);
2451 
2452  // Correct: from 80 till 100 but 99 excluded
2453  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[80:100,!99]") == 0);
2454  FAIL_IF_NULL(dd->next);
2455  FAIL_IF_NOT(dd->port == 80);
2456  FAIL_IF_NOT(dd->port2 == 98);
2457  FAIL_IF_NOT(dd->next->port == 100);
2458 
2459  // Also good: from 1 till 80 except of 2 and 4
2460  FAIL_IF_NOT(DetectPortParse(NULL, &dd, "[1:80,![2,4]]") == 0);
2461  FAIL_IF_NOT(dd->port == 1);
2465 
2466  DetectPortCleanupList(NULL, dd);
2467  PASS;
2468 }
2469 
2470 /**
2471  * \test Test packet Matches
2472  * \param raw_eth_pkt pointer to the ethernet packet
2473  * \param pktsize size of the packet
2474  * \param sig pointer to the signature to test
2475  * \param sid sid number of the signature
2476  * \retval return 1 if match
2477  * \retval return 0 if not
2478  */
2479 static int PortTestMatchReal(uint8_t *raw_eth_pkt, uint16_t pktsize, const char *sig,
2480  uint32_t sid)
2481 {
2482  int result = 0;
2484  Packet *p = UTHBuildPacketFromEth(raw_eth_pkt, pktsize);
2485  result = UTHPacketMatchSig(p, sig);
2486  PACKET_RECYCLE(p);
2487  FlowShutdown();
2488  return result;
2489 }
2490 
2491 /**
2492  * \brief Wrapper for PortTestMatchReal
2493  */
2494 static int PortTestMatchRealWrp(const char *sig, uint32_t sid)
2495 {
2496  /* Real HTTP packeth doing a GET method
2497  * tcp.sport=47370 tcp.dport=80
2498  * ip.src=192.168.28.131 ip.dst=192.168.1.1
2499  */
2500  uint8_t raw_eth_pkt[] = {
2501  0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
2502  0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
2503  0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
2504  0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
2505  0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
2506  0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
2507  0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
2508  0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
2509  0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
2510  0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
2511  0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
2512  0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
2513  0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
2514  0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
2515  0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
2516  0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
2517  0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
2518  0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
2519  0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
2520  0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
2521  0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
2522  0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
2523  0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
2524  0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
2525  0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
2526  0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
2527  0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
2528  0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
2529  0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
2530  0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
2531  0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
2532  0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
2533  0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
2534  0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
2535  0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
2536  0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
2537  0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
2538  0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
2539  0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
2540  0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
2541  0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
2542  0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
2543  0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
2544  0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
2545  0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
2546  0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
2547  0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
2548  0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
2549  0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
2550  0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
2551  0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
2552  0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
2553  0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
2554  0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
2555  0x76,0x65,0x0d,0x0a,0x0d,0x0a };
2556  /* end raw_eth_pkt */
2557 
2558  return PortTestMatchReal(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
2559  sig, sid);
2560 }
2561 
2562 /**
2563  * \test Check if we match a dest port
2564  */
2565 static int PortTestMatchReal01(void)
2566 {
2567  /* tcp.sport=47370 tcp.dport=80 */
2568  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2569  return PortTestMatchRealWrp(sig, 1);
2570 }
2571 
2572 /**
2573  * \test Check if we match a source port
2574  */
2575 static int PortTestMatchReal02(void)
2576 {
2577  const char *sig = "alert tcp any 47370 -> any any (msg:\"Nothing..\";"
2578  " content:\"GET\"; sid:1;)";
2579  return PortTestMatchRealWrp(sig, 1);
2580 }
2581 
2582 /**
2583  * \test Check if we match both of them
2584  */
2585 static int PortTestMatchReal03(void)
2586 {
2587  const char *sig = "alert tcp any 47370 -> any 80 (msg:\"Nothing..\";"
2588  " content:\"GET\"; sid:1;)";
2589  return PortTestMatchRealWrp(sig, 1);
2590 }
2591 
2592 /**
2593  * \test Check if we negate dest ports correctly
2594  */
2595 static int PortTestMatchReal04(void)
2596 {
2597  const char *sig = "alert tcp any any -> any !80 (msg:\"Nothing..\";"
2598  " content:\"GET\"; sid:1;)";
2599  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2600 }
2601 
2602 /**
2603  * \test Check if we negate source ports correctly
2604  */
2605 static int PortTestMatchReal05(void)
2606 {
2607  const char *sig = "alert tcp any !47370 -> any any (msg:\"Nothing..\";"
2608  " content:\"GET\"; sid:1;)";
2609  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2610 }
2611 
2612 /**
2613  * \test Check if we negate both ports correctly
2614  */
2615 static int PortTestMatchReal06(void)
2616 {
2617  const char *sig = "alert tcp any !47370 -> any !80 (msg:\"Nothing..\";"
2618  " content:\"GET\"; sid:1;)";
2619  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2620 }
2621 
2622 /**
2623  * \test Check if we match a dest port range
2624  */
2625 static int PortTestMatchReal07(void)
2626 {
2627  const char *sig = "alert tcp any any -> any 70:100 (msg:\"Nothing..\";"
2628  " content:\"GET\"; sid:1;)";
2629  return PortTestMatchRealWrp(sig, 1);
2630 }
2631 
2632 /**
2633  * \test Check if we match a source port range
2634  */
2635 static int PortTestMatchReal08(void)
2636 {
2637  const char *sig = "alert tcp any 47000:50000 -> any any (msg:\"Nothing..\";"
2638  " content:\"GET\"; sid:1;)";
2639  return PortTestMatchRealWrp(sig, 1);
2640 }
2641 
2642 /**
2643  * \test Check if we match both port ranges
2644  */
2645 static int PortTestMatchReal09(void)
2646 {
2647  const char *sig = "alert tcp any 47000:50000 -> any 70:100 (msg:\"Nothing..\";"
2648  " content:\"GET\"; sid:1;)";
2649  return PortTestMatchRealWrp(sig, 1);
2650 }
2651 
2652 /**
2653  * \test Check if we negate a dest port range
2654  */
2655 static int PortTestMatchReal10(void)
2656 {
2657  const char *sig = "alert tcp any any -> any !70:100 (msg:\"Nothing..\";"
2658  " content:\"GET\"; sid:1;)";
2659  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2660 }
2661 
2662 /**
2663  * \test Check if we negate a source port range
2664  */
2665 static int PortTestMatchReal11(void)
2666 {
2667  const char *sig = "alert tcp any !47000:50000 -> any any (msg:\"Nothing..\";"
2668  " content:\"GET\"; sid:1;)";
2669  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2670 }
2671 
2672 /**
2673  * \test Check if we negate both port ranges
2674  */
2675 static int PortTestMatchReal12(void)
2676 {
2677  const char *sig = "alert tcp any !47000:50000 -> any !70:100 (msg:\"Nothing..\";"
2678  " content:\"GET\"; sid:1;)";
2679  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2680 }
2681 
2682 /**
2683  * \test Check if we autocomplete ranges correctly
2684  */
2685 static int PortTestMatchReal13(void)
2686 {
2687  const char *sig = "alert tcp any 47000:50000 -> any !81: (msg:\"Nothing..\";"
2688  " content:\"GET\"; sid:1;)";
2689  return PortTestMatchRealWrp(sig, 1);
2690 }
2691 
2692 /**
2693  * \test Check if we autocomplete ranges correctly
2694  */
2695 static int PortTestMatchReal14(void)
2696 {
2697  const char *sig = "alert tcp any !48000:50000 -> any :100 (msg:\"Nothing..\";"
2698  " content:\"GET\"; sid:1;)";
2699  return PortTestMatchRealWrp(sig, 1);
2700 }
2701 
2702 /**
2703  * \test Check if we autocomplete ranges correctly
2704  */
2705 static int PortTestMatchReal15(void)
2706 {
2707  const char *sig = "alert tcp any :50000 -> any 81:100 (msg:\"Nothing..\";"
2708  " content:\"GET\"; sid:1;)";
2709  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2710 }
2711 
2712 /**
2713  * \test Check if we separate ranges correctly
2714  */
2715 static int PortTestMatchReal16(void)
2716 {
2717  const char *sig = "alert tcp any 100: -> any ![0:79,81:65535] (msg:\"Nothing..\";"
2718  " content:\"GET\"; sid:1;)";
2719  return PortTestMatchRealWrp(sig, 1);
2720 }
2721 
2722 /**
2723  * \test Check if we separate ranges correctly
2724  */
2725 static int PortTestMatchReal17(void)
2726 {
2727  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any ![0:80,82:65535] "
2728  "(msg:\"Nothing..\"; content:\"GET\"; sid:1;)";
2729  return (PortTestMatchRealWrp(sig, 1) == 0)? 1 : 0;
2730 }
2731 
2732 /**
2733  * \test Check if we separate ranges correctly
2734  */
2735 static int PortTestMatchReal18(void)
2736 {
2737  const char *sig = "alert tcp any ![0:39999,48000:50000] -> any 80 (msg:\"Nothing"
2738  " at all\"; content:\"GET\"; sid:1;)";
2739  return PortTestMatchRealWrp(sig, 1);
2740 }
2741 
2742 /**
2743  * \test Check if we separate ranges correctly
2744  */
2745 static int PortTestMatchReal19(void)
2746 {
2747  const char *sig = "alert tcp any any -> any 80 (msg:\"Nothing..\";"
2748  " content:\"GET\"; sid:1;)";
2749  return PortTestMatchRealWrp(sig, 1);
2750 }
2751 
2752 static int PortTestMatchDoubleNegation(void)
2753 {
2754  int result = 0;
2755  DetectPort *head = NULL, *nhead = NULL;
2756 
2757  if (DetectPortParseDo(NULL, &head, &nhead, "![!80]", 0, NULL) == -1)
2758  return result;
2759 
2760  result = (head != NULL);
2761  result = (nhead == NULL);
2762 
2763  return result;
2764 }
2765 
2766 #endif /* UNITTESTS */
2767 
2769 {
2770 #ifdef UNITTESTS
2771  UtRegisterTest("PortTestParse01", PortTestParse01);
2772  UtRegisterTest("PortTestParse02", PortTestParse02);
2773  UtRegisterTest("PortTestParse03", PortTestParse03);
2774  UtRegisterTest("PortTestParse04", PortTestParse04);
2775  UtRegisterTest("PortTestParse05", PortTestParse05);
2776  UtRegisterTest("PortTestParse06", PortTestParse06);
2777  UtRegisterTest("PortTestParse07", PortTestParse07);
2778  UtRegisterTest("PortTestParse08", PortTestParse08);
2779  UtRegisterTest("PortTestParse09", PortTestParse09);
2780  UtRegisterTest("PortTestParse10", PortTestParse10);
2781  UtRegisterTest("PortTestParse11", PortTestParse11);
2782  UtRegisterTest("PortTestParse12", PortTestParse12);
2783  UtRegisterTest("PortTestParse13", PortTestParse13);
2784  UtRegisterTest("PortTestParse14", PortTestParse14);
2785  UtRegisterTest("PortTestParse15", PortTestParse15);
2786  UtRegisterTest("PortTestParse16", PortTestParse16);
2787  UtRegisterTest("PortTestFunctions01", PortTestFunctions01);
2788  UtRegisterTest("PortTestFunctions02", PortTestFunctions02);
2789  UtRegisterTest("PortTestFunctions03", PortTestFunctions03);
2790  UtRegisterTest("PortTestFunctions04", PortTestFunctions04);
2791  UtRegisterTest("PortTestFunctions05", PortTestFunctions05);
2792  UtRegisterTest("PortTestFunctions06", PortTestFunctions06);
2793  UtRegisterTest("PortTestFunctions07", PortTestFunctions07);
2794  UtRegisterTest("PortTestMatchReal01", PortTestMatchReal01);
2795  UtRegisterTest("PortTestMatchReal02", PortTestMatchReal02);
2796  UtRegisterTest("PortTestMatchReal03", PortTestMatchReal03);
2797  UtRegisterTest("PortTestMatchReal04", PortTestMatchReal04);
2798  UtRegisterTest("PortTestMatchReal05", PortTestMatchReal05);
2799  UtRegisterTest("PortTestMatchReal06", PortTestMatchReal06);
2800  UtRegisterTest("PortTestMatchReal07", PortTestMatchReal07);
2801  UtRegisterTest("PortTestMatchReal08", PortTestMatchReal08);
2802  UtRegisterTest("PortTestMatchReal09", PortTestMatchReal09);
2803  UtRegisterTest("PortTestMatchReal10", PortTestMatchReal10);
2804  UtRegisterTest("PortTestMatchReal11", PortTestMatchReal11);
2805  UtRegisterTest("PortTestMatchReal12", PortTestMatchReal12);
2806  UtRegisterTest("PortTestMatchReal13", PortTestMatchReal13);
2807  UtRegisterTest("PortTestMatchReal14", PortTestMatchReal14);
2808  UtRegisterTest("PortTestMatchReal15", PortTestMatchReal15);
2809  UtRegisterTest("PortTestMatchReal16", PortTestMatchReal16);
2810  UtRegisterTest("PortTestMatchReal17", PortTestMatchReal17);
2811  UtRegisterTest("PortTestMatchReal18", PortTestMatchReal18);
2812  UtRegisterTest("PortTestMatchReal19", PortTestMatchReal19);
2813  UtRegisterTest("PortTestMatchDoubleNegation", PortTestMatchDoubleNegation);
2814 
2815 
2816 #endif /* UNITTESTS */
2817 }
2818 
#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:209
#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:37
void DetectPortTests(void)
#define PACKET_RECYCLE(p)
Definition: decode.h:827
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:492
#define TRUE
SigIntId num
Definition: detect.h:502
main detection engine ctx
Definition: detect.h:720
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:211
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:195
#define PORT_FLAG_ANY
Definition: detect.h:193
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:759
#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:194
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:174
uint8_t flags
Definition: detect.h:202
int DetectPortCmp(DetectPort *a, DetectPort *b)
Function that compare port groups.
#define SCFree(a)
Definition: util-mem.h:236
uint8_t address
Definition: decode-ppp.h:311
uint16_t port
Definition: detect.h:199
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:599
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:212
#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:220
#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:200
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:864
uint8_t * sig_array
Definition: detect.h:1277
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:198
#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:444
SigGroupHeadInitData * init
Definition: detect.h:1323