suricata
detect-engine-iponly.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
23  *
24  * Signatures that only inspect IP addresses are processed here
25  * We use radix trees for src dst ipv4 and ipv6 addresses
26  * This radix trees hold information for subnets and hosts in a
27  * hierarchical distribution
28  */
29 
30 #include "suricata-common.h"
31 #include "detect.h"
32 #include "decode.h"
33 #include "flow.h"
34 
35 #include "detect-parse.h"
36 #include "detect-engine.h"
37 
38 #include "detect-engine-siggroup.h"
39 #include "detect-engine-address.h"
40 #include "detect-engine-proto.h"
41 #include "detect-engine-port.h"
42 #include "detect-engine-mpm.h"
43 #include "detect-engine-build.h"
44 
46 #include "detect-engine-iponly.h"
47 #include "detect-threshold.h"
49 #include "util-rule-vars.h"
50 #include "detect-engine-alert.h"
51 
52 #include "flow-util.h"
53 #include "util-debug.h"
54 #include "util-unittest.h"
55 #include "util-unittest-helper.h"
56 #include "util-print.h"
57 #include "util-byte.h"
58 #include "util-profiling.h"
59 #include "util-validate.h"
60 #include "util-cidr.h"
61 
62 #ifdef OS_WIN32
63 #include <winsock.h>
64 #else
65 #include <netinet/in.h>
66 #endif /* OS_WIN32 */
67 
68 /**
69  * \brief This function creates a new IPOnlyCIDRItem
70  *
71  * \retval IPOnlyCIDRItem address of the new instance
72  */
73 static IPOnlyCIDRItem *IPOnlyCIDRItemNew(void)
74 {
75  SCEnter();
76  IPOnlyCIDRItem *item = NULL;
77 
78  item = SCCalloc(1, sizeof(IPOnlyCIDRItem));
79  if (unlikely(item == NULL))
80  SCReturnPtr(NULL, "IPOnlyCIDRItem");
81 
82  SCReturnPtr(item, "IPOnlyCIDRItem");
83 }
84 
85 /**
86  * \brief Compares two list items
87  *
88  * \retval An integer less than, equal to, or greater than zero if lhs is
89  * considered to be respectively less than, equal to, or greater than
90  * rhs.
91  */
92 static int IPOnlyCIDRItemCompareReal(const IPOnlyCIDRItem *lhs, const IPOnlyCIDRItem *rhs)
93 {
94  if (lhs->netmask == rhs->netmask) {
95  uint8_t i = 0;
96  for (; i < lhs->netmask / 32 || i < 1; i++) {
97  if (lhs->ip[i] < rhs->ip[i])
98  return -1;
99  if (lhs->ip[i] > rhs->ip[i])
100  return 1;
101  }
102  return 0;
103  }
104 
105  return lhs->netmask < rhs->netmask ? -1 : 1;
106 }
107 
108 static int IPOnlyCIDRItemCompare(const void *lhsv, const void *rhsv)
109 {
110  const IPOnlyCIDRItem *lhs = *(const IPOnlyCIDRItem **)lhsv;
111  const IPOnlyCIDRItem *rhs = *(const IPOnlyCIDRItem **)rhsv;
112 
113  return IPOnlyCIDRItemCompareReal(lhs, rhs);
114 }
115 
116 static void IPOnlyCIDRListQSort(IPOnlyCIDRItem **head)
117 {
118  if (unlikely(head == NULL || *head == NULL))
119  return;
120 
121  // First count the number of elements in the list
122  size_t len = 0;
123  IPOnlyCIDRItem *curr = *head;
124 
125  while (curr) {
126  curr = curr->next;
127  len++;
128  }
129 
130  // Place a pointer to the list item in an array for sorting
131  IPOnlyCIDRItem **tmp = SCMalloc(len * sizeof(IPOnlyCIDRItem *));
132 
133  if (unlikely(tmp == NULL)) {
134  SCLogError("Failed to allocate enough memory to sort IP-only CIDR items.");
135  return;
136  }
137 
138  curr = *head;
139  for (size_t i = 0; i < len; i++) {
140  tmp[i] = curr;
141  curr = curr->next;
142  }
143 
144  // Perform the sort using the qsort algorithm
145  qsort(tmp, len, sizeof(IPOnlyCIDRItem *), IPOnlyCIDRItemCompare);
146 
147  // Update the links to the next element
148  *head = tmp[0];
149 
150  for (size_t i = 0; i + 1 < len; i++) {
151  tmp[i]->next = tmp[i + 1];
152  }
153 
154  tmp[len - 1]->next = NULL;
155 
156  SCFree(tmp);
157 }
158 
159 //declaration for using it already
160 static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
161  IPOnlyCIDRItem *item);
162 
163 static int InsertRange(
164  IPOnlyCIDRItem **pdd, IPOnlyCIDRItem *dd, const uint32_t first_in, const uint32_t last_in)
165 {
166  DEBUG_VALIDATE_BUG_ON(dd == NULL);
167  DEBUG_VALIDATE_BUG_ON(pdd == NULL);
168 
169  uint32_t first = first_in;
170  uint32_t last = last_in;
171 
172  dd->netmask = 32;
173  /* Find the maximum netmask starting from current address first
174  * and not crossing last.
175  * To extend the mask, we need to start from a power of 2.
176  * And we need to pay attention to unsigned overflow back to 0.0.0.0
177  */
178  while (dd->netmask > 0 && (first & (1UL << (32 - dd->netmask))) == 0 &&
179  first + (1UL << (32 - (dd->netmask - 1))) - 1 <= last) {
180  dd->netmask--;
181  }
182  dd->ip[0] = htonl(first);
183  first += 1UL << (32 - dd->netmask);
184  // case whatever-255.255.255.255 looping to 0.0.0.0/0
185  while (first <= last && first != 0) {
186  IPOnlyCIDRItem *new = IPOnlyCIDRItemNew();
187  if (new == NULL)
188  goto error;
189  new->negated = dd->negated;
190  new->family = dd->family;
191  new->netmask = 32;
192  while (new->netmask > 0 && (first & (1UL << (32 - new->netmask))) == 0 &&
193  first + (1UL << (32 - (new->netmask - 1))) - 1 <= last) {
194  new->netmask--;
195  }
196  new->ip[0] = htonl(first);
197  first += 1UL << (32 - new->netmask);
198  dd = IPOnlyCIDRItemInsert(dd, new);
199  }
200  // update head of list
201  *pdd = dd;
202  return 0;
203 error:
204  return -1;
205 }
206 
207 /**
208  * \internal
209  * \brief Parses an ipv4/ipv6 address string and updates the result into the
210  * IPOnlyCIDRItem instance sent as the argument.
211  *
212  * \param pdd Double pointer to the IPOnlyCIDRItem instance which should be updated
213  * with the address (in cidr) details from the parsed ip string.
214  * \param str Pointer to address string that has to be parsed.
215  *
216  * \retval 0 On successfully parsing the address string.
217  * \retval -1 On failure.
218  */
219 static int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem **pdd, const char *str)
220 {
221  char buf[256] = "";
222  char *ip = NULL, *ip2 = NULL;
223  char *mask = NULL;
224  int r = 0;
225  IPOnlyCIDRItem *dd = *pdd;
226 
227  while (*str != '\0' && *str == ' ')
228  str++;
229 
230  SCLogDebug("str %s", str);
231  strlcpy(buf, str, sizeof(buf));
232  ip = buf;
233 
234  /* first handle 'any' */
235  if (strcasecmp(str, "any") == 0) {
236  /* if any, insert 0.0.0.0/0 and ::/0 as well */
237  SCLogDebug("adding 0.0.0.0/0 and ::/0 as we\'re handling \'any\'");
238 
239  IPOnlyCIDRItemParseSingle(&dd, "0.0.0.0/0");
240  BUG_ON(dd->family == 0);
241 
242  dd->next = IPOnlyCIDRItemNew();
243  if (dd->next == NULL)
244  goto error;
245 
246  IPOnlyCIDRItemParseSingle(&dd->next, "::/0");
247  BUG_ON(dd->family == 0);
248 
249  SCLogDebug("address is \'any\'");
250  return 0;
251  }
252 
253  /* handle the negation case */
254  if (ip[0] == '!') {
255  dd->negated = (dd->negated)? 0 : 1;
256  ip++;
257  }
258 
259  /* see if the address is an ipv4 or ipv6 address */
260  if ((strchr(str, ':')) == NULL) {
261  /* IPv4 Address */
262  struct in_addr in;
263 
264  dd->family = AF_INET;
265 
266  if ((mask = strchr(ip, '/')) != NULL) {
267  /* 1.2.3.4/xxx format (either dotted or cidr notation */
268  ip[mask - ip] = '\0';
269  mask++;
270  uint32_t netmask = 0;
271  size_t u = 0;
272 
273  if ((strchr (mask, '.')) == NULL) {
274  /* 1.2.3.4/24 format */
275 
276  for (u = 0; u < strlen(mask); u++) {
277  if(!isdigit((unsigned char)mask[u]))
278  goto error;
279  }
280 
281  uint8_t cidr;
282  if (StringParseU8RangeCheck(&cidr, 10, 0, (const char *)mask, 0, 32) <= 0)
283  goto error;
284 
285  dd->netmask = cidr;
286  netmask = CIDRGet(cidr);
287  } else {
288  /* 1.2.3.4/255.255.255.0 format */
289  r = inet_pton(AF_INET, mask, &in);
290  if (r <= 0)
291  goto error;
292 
293  int cidr = CIDRFromMask(in.s_addr);
294  if (cidr < 0)
295  goto error;
296 
297  dd->netmask = (uint8_t)cidr;
298  }
299 
300  r = inet_pton(AF_INET, ip, &in);
301  if (r <= 0)
302  goto error;
303 
304  dd->ip[0] = in.s_addr & netmask;
305 
306  } else if ((ip2 = strchr(ip, '-')) != NULL) {
307  /* 1.2.3.4-1.2.3.6 range format */
308  ip[ip2 - ip] = '\0';
309  ip2++;
310 
311  uint32_t first, last;
312 
313  r = inet_pton(AF_INET, ip, &in);
314  if (r <= 0)
315  goto error;
316  first = SCNtohl(in.s_addr);
317 
318  r = inet_pton(AF_INET, ip2, &in);
319  if (r <= 0)
320  goto error;
321  last = SCNtohl(in.s_addr);
322 
323  /* a > b is illegal, a = b is ok */
324  if (first > last)
325  goto error;
326 
327  SCLogDebug("Creating CIDR range for [%s - %s]", ip, ip2);
328  return InsertRange(pdd, dd, first, last);
329  } else {
330  /* 1.2.3.4 format */
331  r = inet_pton(AF_INET, ip, &in);
332  if (r <= 0)
333  goto error;
334 
335  /* single host */
336  dd->ip[0] = in.s_addr;
337  dd->netmask = 32;
338  }
339  } else {
340  /* IPv6 Address */
341  struct in6_addr in6, mask6;
342  uint32_t ip6addr[4], netmask[4];
343 
344  dd->family = AF_INET6;
345 
346  if ((mask = strchr(ip, '/')) != NULL) {
347  mask[0] = '\0';
348  mask++;
349 
350  r = inet_pton(AF_INET6, ip, &in6);
351  if (r <= 0)
352  goto error;
353 
354  /* Format is cidr val */
355  if (StringParseU8RangeCheck(&dd->netmask, 10, 0,
356  (const char *)mask, 0, 128) < 0) {
357  goto error;
358  }
359 
360  memcpy(&ip6addr, &in6.s6_addr, sizeof(ip6addr));
361  CIDRGetIPv6(dd->netmask, &mask6);
362  memcpy(&netmask, &mask6.s6_addr, sizeof(netmask));
363 
364  dd->ip[0] = ip6addr[0] & netmask[0];
365  dd->ip[1] = ip6addr[1] & netmask[1];
366  dd->ip[2] = ip6addr[2] & netmask[2];
367  dd->ip[3] = ip6addr[3] & netmask[3];
368  } else {
369  r = inet_pton(AF_INET6, ip, &in6);
370  if (r <= 0)
371  goto error;
372 
373  memcpy(dd->ip, &in6.s6_addr, sizeof(dd->ip));
374  dd->netmask = 128;
375  }
376 
377  }
378 
379  BUG_ON(dd->family == 0);
380  return 0;
381 
382 error:
383  return -1;
384 }
385 
386 /**
387  * \brief Setup a single address string, parse it and add the resulting
388  * Address items in cidr format to the list of gh
389  *
390  * \param gh Pointer to the IPOnlyCIDRItem list Head to which the
391  * resulting Address-Range(s) from the parsed ip string has to
392  * be added.
393  * \param s Pointer to the ip address string to be parsed.
394  *
395  * \retval 0 On success.
396  * \retval -1 On failure.
397  */
398 static int IPOnlyCIDRItemSetup(IPOnlyCIDRItem **gh, char *s)
399 {
400  SCLogDebug("gh %p, s %s", *gh, s);
401 
402  /* parse the address */
403  if (IPOnlyCIDRItemParseSingle(gh, s) == -1) {
404  SCLogError("address parsing error \"%s\"", s);
405  goto error;
406  }
407 
408  return 0;
409 
410 error:
411  return -1;
412 }
413 
414 /**
415  * \brief This function insert a IPOnlyCIDRItem
416  * to a list of IPOnlyCIDRItems
417  * \param head Pointer to the head of IPOnlyCIDRItems list
418  * \param item Pointer to the item to insert in the list
419  *
420  * \retval IPOnlyCIDRItem address of the new head if apply
421  */
422 static IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
423  IPOnlyCIDRItem *item)
424 {
425  if (item == NULL)
426  return head;
427 
428  /* Always insert item as head */
429  item->next = head;
430  return item;
431 }
432 
433 /**
434  * \brief This function insert a IPOnlyCIDRItem list
435  * to a list of IPOnlyCIDRItems sorted by netmask
436  * ascending
437  * \param head Pointer to the head of IPOnlyCIDRItems list
438  * \param item Pointer to the list of items to insert in the list
439  *
440  * \retval IPOnlyCIDRItem address of the new head if apply
441  */
442 static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
443  IPOnlyCIDRItem *item)
444 {
445  IPOnlyCIDRItem *it, *prev = NULL;
446 
447  /* The first element */
448  if (head == NULL) {
449  SCLogDebug("Head is NULL to insert item (%p)",item);
450  return item;
451  }
452 
453  if (item == NULL) {
454  SCLogDebug("Item is NULL");
455  return head;
456  }
457 
458  SCLogDebug("Inserting item(%p)->netmask %u head %p", item, item->netmask, head);
459 
460  prev = item;
461  while (prev != NULL) {
462  it = prev->next;
463 
464  /* Separate from the item list */
465  prev->next = NULL;
466 
467  //SCLogDebug("Before:");
468  //IPOnlyCIDRListPrint(head);
469  head = IPOnlyCIDRItemInsertReal(head, prev);
470  //SCLogDebug("After:");
471  //IPOnlyCIDRListPrint(head);
472  prev = it;
473  }
474 
475  return head;
476 }
477 
478 /**
479  * \brief This function free a IPOnlyCIDRItem list
480  * \param tmphead Pointer to the list
481  */
483 {
484  SCEnter();
485 #ifdef DEBUG
486  uint32_t i = 0;
487 #endif
488  IPOnlyCIDRItem *it, *next = NULL;
489 
490  if (tmphead == NULL) {
491  SCLogDebug("temphead is NULL");
492  return;
493  }
494 
495  it = tmphead;
496  next = it->next;
497 
498  while (it != NULL) {
499 #ifdef DEBUG
500  i++;
501  SCLogDebug("Item(%p) %"PRIu32" removed", it, i);
502 #endif
503  SCFree(it);
504  it = next;
505 
506  if (next != NULL)
507  next = next->next;
508  }
509  SCReturn;
510 }
511 
512 /**
513  * \brief This function update a list of IPOnlyCIDRItems
514  * setting the signature internal id (signum) to "i"
515  *
516  * \param tmphead Pointer to the list
517  * \param i number of signature internal id
518  */
519 static void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i)
520 {
521  while (tmphead != NULL) {
522  tmphead->signum = i;
523  tmphead = tmphead->next;
524  }
525 }
526 
527 #ifdef UNITTESTS
528 /**
529  * \brief This function print a IPOnlyCIDRItem list
530  * \param tmphead Pointer to the head of IPOnlyCIDRItems list
531  */
532 static void IPOnlyCIDRListPrint(IPOnlyCIDRItem *tmphead)
533 {
534 #ifdef DEBUG
535  uint32_t i = 0;
536 
537  while (tmphead != NULL) {
538  i++;
539  SCLogDebug("Item %"PRIu32" has netmask %"PRIu8" negated:"
540  " %s; IP: %s; signum: %"PRIu32, i, tmphead->netmask,
541  (tmphead->negated) ? "yes":"no",
542  inet_ntoa(*(struct in_addr*)&tmphead->ip[0]),
543  tmphead->signum);
544  tmphead = tmphead->next;
545  }
546 #endif
547 }
548 #endif
549 
550 /** \brief user data for storing signature id's in the radix tree
551  *
552  * Bit array representing signature internal id's (Signature::num).
553  */
554 typedef struct SigNumArray_ {
555  uint8_t *array; /* bit array of sig nums */
556  uint32_t size; /* size in bytes of the array */
558 
559 /**
560  * \brief This function print a SigNumArray, it's used with the
561  * radix tree print function to help debugging
562  * \param tmp Pointer to the head of SigNumArray
563  */
564 static void SigNumArrayPrint(void *tmp)
565 {
566  SigNumArray *sna = (SigNumArray *)tmp;
567  for (uint32_t u = 0; u < sna->size; u++) {
568  uint8_t bitarray = sna->array[u];
569  for (uint8_t i = 0; i < 8; i++) {
570  if (bitarray & 0x01)
571  printf("%" PRIu32 " ", u * 8 + i);
572  bitarray = bitarray >> 1;
573  }
574  }
575 }
576 
577 /**
578  * \brief This function creates a new SigNumArray with the
579  * size fixed to the io_ctx->max_idx
580  * \param de_ctx Pointer to the current detection context
581  * \param io_ctx Pointer to the current ip only context
582  *
583  * \retval SigNumArray address of the new instance
584  */
585 static SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
586  DetectEngineIPOnlyCtx *io_ctx)
587 {
588  SigNumArray *new = SCCalloc(1, sizeof(SigNumArray));
589 
590  if (unlikely(new == NULL)) {
591  FatalError("Fatal error encountered in SigNumArrayNew. Exiting...");
592  }
593 
594  new->array = SCCalloc(1, io_ctx->max_idx / 8 + 1);
595  if (new->array == NULL) {
596  exit(EXIT_FAILURE);
597  }
598 
599  new->size = io_ctx->max_idx / 8 + 1;
600 
601  SCLogDebug("max idx= %u", io_ctx->max_idx);
602 
603  return new;
604 }
605 
606 /**
607  * \brief This function creates a new SigNumArray with the
608  * same data as the argument
609  *
610  * \param orig Pointer to the original SigNumArray to copy
611  *
612  * \retval SigNumArray address of the new instance
613  */
614 static SigNumArray *SigNumArrayCopy(SigNumArray *orig)
615 {
616  SigNumArray *new = SCCalloc(1, sizeof(SigNumArray));
617 
618  if (unlikely(new == NULL)) {
619  FatalError("Fatal error encountered in SigNumArrayCopy. Exiting...");
620  }
621 
622  new->size = orig->size;
623 
624  new->array = SCMalloc(orig->size);
625  if (new->array == NULL) {
626  exit(EXIT_FAILURE);
627  }
628 
629  memcpy(new->array, orig->array, orig->size);
630  return new;
631 }
632 
633 /**
634  * \brief This function free() a SigNumArray
635  * \param orig Pointer to the original SigNumArray to copy
636  */
637 static void SigNumArrayFree(void *tmp)
638 {
639  SigNumArray *sna = (SigNumArray *)tmp;
640 
641  if (sna == NULL)
642  return;
643 
644  if (sna->array != NULL)
645  SCFree(sna->array);
646 
647  SCFree(sna);
648 }
649 
650 /**
651  * \brief This function parses and return a list of IPOnlyCIDRItem
652  *
653  * \param s Pointer to the string of the addresses
654  * (in the format of signatures)
655  * \param negate flag to indicate if all this string is negated or not
656  *
657  * \retval 0 if success
658  * \retval -1 if fails
659  */
660 static IPOnlyCIDRItem *IPOnlyCIDRListParse2(
661  const DetectEngineCtx *de_ctx, const char *s, int negate)
662 {
663  size_t x = 0;
664  size_t u = 0;
665  int o_set = 0, n_set = 0, d_set = 0;
666  int depth = 0;
667  size_t size = strlen(s);
668  char address[8196] = "";
669  const char *rule_var_address = NULL;
670  char *temp_rule_var_address = NULL;
672  IPOnlyCIDRItem *subhead;
673  head = subhead = NULL;
674 
675  SCLogDebug("s %s negate %s", s, negate ? "true" : "false");
676 
677  for (u = 0, x = 0; u < size && x < sizeof(address); u++) {
678  address[x] = s[u];
679  x++;
680 
681  if (!o_set && s[u] == '!') {
682  n_set = 1;
683  x--;
684  } else if (s[u] == '[') {
685  if (!o_set) {
686  o_set = 1;
687  x = 0;
688  }
689  depth++;
690  } else if (s[u] == ']') {
691  if (depth == 1) {
692  address[x - 1] = '\0';
693  x = 0;
694 
695  if ( (subhead = IPOnlyCIDRListParse2(de_ctx, address,
696  (negate + n_set) % 2)) == NULL)
697  goto error;
698 
699  head = IPOnlyCIDRItemInsert(head, subhead);
700  n_set = 0;
701  }
702  depth--;
703  } else if (depth == 0 && s[u] == ',') {
704  if (o_set == 1) {
705  o_set = 0;
706  } else if (d_set == 1) {
707  address[x - 1] = '\0';
708 
709  rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
711  if (rule_var_address == NULL)
712  goto error;
713 
714  if ((negate + n_set) % 2) {
715  /* add +1 to safisfy gcc 15 + -Wformat-truncation=2 */
716  const size_t str_size = strlen(rule_var_address) + 3 + 1;
717  temp_rule_var_address = SCMalloc(str_size);
718  if (unlikely(temp_rule_var_address == NULL)) {
719  goto error;
720  }
721 
722  snprintf(temp_rule_var_address, str_size, "[%s]", rule_var_address);
723  } else {
724  temp_rule_var_address = SCStrdup(rule_var_address);
725  if (unlikely(temp_rule_var_address == NULL)) {
726  goto error;
727  }
728  }
729 
730  subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
731  (negate + n_set) % 2);
732  head = IPOnlyCIDRItemInsert(head, subhead);
733 
734  d_set = 0;
735  n_set = 0;
736 
737  SCFree(temp_rule_var_address);
738 
739  } else {
740  address[x - 1] = '\0';
741 
742  subhead = IPOnlyCIDRItemNew();
743  if (subhead == NULL)
744  goto error;
745 
746  if (!((negate + n_set) % 2))
747  subhead->negated = 0;
748  else
749  subhead->negated = 1;
750 
751  if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
752  IPOnlyCIDRListFree(subhead);
753  subhead = NULL;
754  goto error;
755  }
756  head = IPOnlyCIDRItemInsert(head, subhead);
757 
758  n_set = 0;
759  }
760  x = 0;
761  } else if (depth == 0 && s[u] == '$') {
762  d_set = 1;
763  } else if (depth == 0 && u == size - 1) {
764  if (x == sizeof(address)) {
765  address[x - 1] = '\0';
766  } else {
767  address[x] = '\0';
768  }
769  x = 0;
770 
771  if (d_set == 1) {
772  rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
774  if (rule_var_address == NULL)
775  goto error;
776 
777  if ((negate + n_set) % 2) {
778  /* add +1 to safisfy gcc 15 + -Wformat-truncation=2 */
779  const size_t str_size = strlen(rule_var_address) + 3 + 1;
780  temp_rule_var_address = SCMalloc(str_size);
781  if (unlikely(temp_rule_var_address == NULL)) {
782  goto error;
783  }
784  snprintf(temp_rule_var_address, str_size, "[%s]", rule_var_address);
785  } else {
786  temp_rule_var_address = SCStrdup(rule_var_address);
787  if (unlikely(temp_rule_var_address == NULL)) {
788  goto error;
789  }
790  }
791  subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
792  (negate + n_set) % 2);
793  head = IPOnlyCIDRItemInsert(head, subhead);
794 
795  d_set = 0;
796 
797  SCFree(temp_rule_var_address);
798  } else {
799  subhead = IPOnlyCIDRItemNew();
800  if (subhead == NULL)
801  goto error;
802 
803  if (!((negate + n_set) % 2))
804  subhead->negated = 0;
805  else
806  subhead->negated = 1;
807 
808  if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
809  IPOnlyCIDRListFree(subhead);
810  subhead = NULL;
811  goto error;
812  }
813  head = IPOnlyCIDRItemInsert(head, subhead);
814  }
815  n_set = 0;
816  }
817  }
818 
819  return head;
820 
821 error:
822  SCLogError("Error parsing addresses");
823  return head;
824 }
825 
826 
827 /**
828  * \brief Parses an address group sent as a character string and updates the
829  * IPOnlyCIDRItem list
830  *
831  * \param gh Pointer to the IPOnlyCIDRItem list
832  * \param str Pointer to the character string containing the address group
833  * that has to be parsed.
834  *
835  * \retval 0 On success.
836  * \retval -1 On failure.
837  */
838 static int IPOnlyCIDRListParse(const DetectEngineCtx *de_ctx, IPOnlyCIDRItem **gh, const char *str)
839 {
840  SCLogDebug("gh %p, str %s", gh, str);
841 
842  if (gh == NULL)
843  goto error;
844 
845  *gh = IPOnlyCIDRListParse2(de_ctx, str, 0);
846  if (*gh == NULL) {
847  SCLogDebug("IPOnlyCIDRListParse2 returned null");
848  goto error;
849  }
850 
851  return 0;
852 
853 error:
854  return -1;
855 }
856 
857 /**
858  * \brief Parses an address group sent as a character string and updates the
859  * IPOnlyCIDRItem lists src and dst of the Signature *s
860  *
861  * \param s Pointer to the signature structure
862  * \param addrstr Pointer to the character string containing the address group
863  * that has to be parsed.
864  * \param flag to indicate if we are parsing the src string or the dst string
865  *
866  * \retval 0 On success.
867  * \retval -1 On failure.
868  */
870  Signature *s, const char *addrstr, char flag)
871 {
872  SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
873 
874  /* pass on to the address(list) parser */
875  if (flag == 0) {
876  if (strcasecmp(addrstr, "any") == 0) {
877  s->flags |= SIG_FLAG_SRC_ANY;
878  if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_src, "[0.0.0.0/0,::/0]") < 0)
879  goto error;
880 
881  } else if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_src, (char *)addrstr) < 0) {
882  goto error;
883  }
884 
885  /* IPOnlyCIDRListPrint(s->CidrSrc); */
886  } else {
887  if (strcasecmp(addrstr, "any") == 0) {
888  s->flags |= SIG_FLAG_DST_ANY;
889  if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_dst, "[0.0.0.0/0,::/0]") < 0)
890  goto error;
891 
892  } else if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_dst, (char *)addrstr) < 0) {
893  goto error;
894  }
895 
896  /* IPOnlyCIDRListPrint(s->CidrDst); */
897  }
898 
899  return 0;
900 
901 error:
902  SCLogError("failed to parse addresses");
903  return -1;
904 }
905 
906 static const SCRadix4Config iponly_radix4_config = { SigNumArrayFree, SigNumArrayPrint };
907 static const SCRadix6Config iponly_radix6_config = { SigNumArrayFree, SigNumArrayPrint };
908 
909 /**
910  * \brief Setup the IP Only detection engine context
911  *
912  * \param de_ctx Pointer to the current detection engine
913  * \param io_ctx Pointer to the current ip only detection engine
914  */
916 {
921 
922  io_ctx->sig_mapping = SCCalloc(1, de_ctx->sig_array_len * sizeof(uint32_t));
923  if (io_ctx->sig_mapping == NULL) {
924  FatalError("Unable to allocate iponly signature tracking area");
925  }
926  io_ctx->sig_mapping_size = 0;
927 }
928 
930 {
931  SigIntId loc = io_ctx->sig_mapping_size;
932  io_ctx->sig_mapping[loc] = signum;
933  io_ctx->sig_mapping_size++;
934  return loc;
935 }
936 
937 /**
938  * \brief Print stats of the IP Only engine
939  *
940  * \param de_ctx Pointer to the current detection engine
941  * \param io_ctx Pointer to the current ip only detection engine
942  */
944 {
945  /* XXX: how are we going to print the stats now? */
946 }
947 
948 /**
949  * \brief Deinitialize the IP Only detection engine context
950  *
951  * \param de_ctx Pointer to the current detection engine
952  * \param io_ctx Pointer to the current ip only detection engine
953  */
955 {
956 
957  if (io_ctx == NULL)
958  return;
959 
960  SCRadix4TreeRelease(&io_ctx->tree_ipv4src, &iponly_radix4_config);
961  SCRadix4TreeRelease(&io_ctx->tree_ipv4dst, &iponly_radix4_config);
962 
963  SCRadix6TreeRelease(&io_ctx->tree_ipv6src, &iponly_radix6_config);
964  SCRadix6TreeRelease(&io_ctx->tree_ipv6dst, &iponly_radix6_config);
965 
966  if (io_ctx->sig_mapping != NULL)
967  SCFree(io_ctx->sig_mapping);
968  io_ctx->sig_mapping = NULL;
969 }
970 
971 static inline int IPOnlyMatchCompatSMs(
972  ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Packet *p)
973 {
976  while (smd) {
979  if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) > 0) {
980  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
981  if (smd->is_last)
982  break;
983  smd++;
984  continue;
985  }
986  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
987  return 0;
988  }
989  return 1;
990 }
991 
992 /**
993  * \brief Match a packet against the IP Only detection engine contexts
994  *
995  * \param de_ctx Pointer to the current detection engine
996  * \param io_ctx Pointer to the current ip only detection engine
997  * \param io_ctx Pointer to the current ip only thread detection engine
998  * \param p Pointer to the Packet to match against
999  */
1001  DetectEngineThreadCtx *det_ctx, const DetectEngineIPOnlyCtx *io_ctx, Packet *p)
1002 {
1003  SigNumArray *src = NULL;
1004  SigNumArray *dst = NULL;
1005  void *user_data_src = NULL, *user_data_dst = NULL;
1006 
1007  SCEnter();
1008 
1009  if (p->src.family == AF_INET) {
1011  &io_ctx->tree_ipv4src, (uint8_t *)&GET_IPV4_SRC_ADDR_U32(p), &user_data_src);
1012  } else if (p->src.family == AF_INET6) {
1014  &io_ctx->tree_ipv6src, (uint8_t *)&GET_IPV6_SRC_ADDR(p), &user_data_src);
1015  }
1016 
1017  if (p->dst.family == AF_INET) {
1019  &io_ctx->tree_ipv4dst, (uint8_t *)&GET_IPV4_DST_ADDR_U32(p), &user_data_dst);
1020  } else if (p->dst.family == AF_INET6) {
1022  &io_ctx->tree_ipv6dst, (uint8_t *)&GET_IPV6_DST_ADDR(p), &user_data_dst);
1023  }
1024 
1025  src = user_data_src;
1026  dst = user_data_dst;
1027 
1028  if (src == NULL || dst == NULL)
1029  SCReturn;
1030 
1031  for (uint32_t u = 0; u < src->size; u++) {
1032  SCLogDebug("And %"PRIu8" & %"PRIu8, src->array[u], dst->array[u]);
1033 
1034  uint8_t bitarray = dst->array[u] & src->array[u];
1035 
1036  /* We have to move the logic of the signature checking
1037  * to the main detect loop, in order to apply the
1038  * priority of actions (pass, drop, reject, alert) */
1039  if (!bitarray)
1040  continue;
1041 
1042  /* We have a match :) Let's see from which signum's */
1043 
1044  for (uint8_t i = 0; i < 8; i++, bitarray = bitarray >> 1) {
1045  if (bitarray & 0x01) {
1046  const Signature *s = de_ctx->sig_array[io_ctx->sig_mapping[u * 8 + i]];
1047 
1048  if ((s->proto.flags & DETECT_PROTO_IPV4) && !PacketIsIPv4(p)) {
1049  SCLogDebug("ip version didn't match");
1050  continue;
1051  }
1052  if ((s->proto.flags & DETECT_PROTO_IPV6) && !PacketIsIPv6(p)) {
1053  SCLogDebug("ip version didn't match");
1054  continue;
1055  }
1056  if (DetectProtoContainsProto(&s->proto, PacketGetIPProto(p)) == 0) {
1057  SCLogDebug("proto didn't match");
1058  continue;
1059  }
1060 
1061  /* check the source & dst port in the sig */
1062  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP ||
1063  p->proto == IPPROTO_SCTP) {
1064  if (!(s->flags & SIG_FLAG_DP_ANY)) {
1065  if (p->flags & PKT_IS_FRAGMENT)
1066  continue;
1067 
1068  const DetectPort *dport = DetectPortLookupGroup(s->dp, p->dp);
1069  if (dport == NULL) {
1070  SCLogDebug("dport didn't match.");
1071  continue;
1072  }
1073  }
1074  if (!(s->flags & SIG_FLAG_SP_ANY)) {
1075  if (p->flags & PKT_IS_FRAGMENT)
1076  continue;
1077 
1078  const DetectPort *sport = DetectPortLookupGroup(s->sp, p->sp);
1079  if (sport == NULL) {
1080  SCLogDebug("sport didn't match.");
1081  continue;
1082  }
1083  }
1084  } else if ((s->flags & (SIG_FLAG_DP_ANY | SIG_FLAG_SP_ANY)) !=
1086  SCLogDebug("port-less protocol and sig needs ports");
1087  continue;
1088  }
1089 
1090  if (!IPOnlyMatchCompatSMs(tv, det_ctx, s, p)) {
1091  continue;
1092  }
1093 
1094  SCLogDebug("Signum %" PRIu32 " match (sid: %" PRIu32 ", msg: %s)", u * 8 + i, s->id,
1095  s->msg);
1096 
1097  if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) {
1100 
1101  SCLogDebug("running match functions, sm %p", smd);
1102 
1103  if (smd != NULL) {
1104  while (1) {
1106  (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
1107  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1108  if (smd->is_last)
1109  break;
1110  smd++;
1111  }
1112  }
1113  }
1114  AlertQueueAppend(det_ctx, s, p, 0, 0);
1115  }
1116  }
1117  }
1118  SCReturn;
1119 }
1120 
1121 static void IPOnlyPrepareUpdateBitarray(const IPOnlyCIDRItem *src, SigNumArray *sna)
1122 {
1123  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1124  if (src->negated > 0)
1125  /* Unset it */
1126  sna->array[src->signum / 8] &= ~tmp;
1127  else
1128  /* Set it */
1129  sna->array[src->signum / 8] |= tmp;
1130 }
1131 
1132 /**
1133  * \brief Build the radix trees from the lists of parsed addresses in CIDR format
1134  * the result should be 4 radix trees: src/dst ipv4 and src/dst ipv6
1135  * holding SigNumArrays, each of them with a hierarchical relation
1136  * of subnets and hosts
1137  *
1138  * \param de_ctx Pointer to the current detection engine
1139  */
1141 {
1142  SCLogDebug("Preparing Final Lists");
1143 
1144  /*
1145  IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_src);
1146  IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_dst);
1147  */
1148 
1149  IPOnlyCIDRListQSort(&de_ctx->io_ctx.ip_src);
1150  IPOnlyCIDRListQSort(&de_ctx->io_ctx.ip_dst);
1151 
1152  SCRadix4Node *node4 = NULL;
1153  SCRadix6Node *node6 = NULL;
1154 
1155  /* Prepare Src radix trees */
1156  for (IPOnlyCIDRItem *src = de_ctx->io_ctx.ip_src; src != NULL;) {
1157  if (src->family == AF_INET) {
1158  /*
1159  SCLogDebug("To IPv4");
1160  SCLogDebug("Item has netmask %"PRIu16" negated: %s; IP: %s; "
1161  "signum: %"PRIu16, src->netmask,
1162  (src->negated) ? "yes":"no",
1163  inet_ntoa( *(struct in_addr*)&src->ip[0]),
1164  src->signum);
1165  */
1166 
1167  void *user_data = NULL;
1168  if (src->netmask == 32)
1170  &de_ctx->io_ctx.tree_ipv4src, (uint8_t *)&src->ip[0], &user_data);
1171  else
1172  (void)SCRadix4TreeFindNetblock(&de_ctx->io_ctx.tree_ipv4src, (uint8_t *)&src->ip[0],
1173  src->netmask, &user_data);
1174  if (user_data == NULL) {
1175  SCLogDebug("Exact match not found");
1176 
1177  /** Not found, look if there's a subnet of this range with
1178  * bigger netmask */
1180  &de_ctx->io_ctx.tree_ipv4src, (uint8_t *)&src->ip[0], &user_data);
1181  if (user_data == NULL) {
1182  SCLogDebug("best match not found");
1183 
1184  /* Not found, insert a new one */
1185  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1186  IPOnlyPrepareUpdateBitarray(src, sna);
1187 
1188  if (src->netmask == 32)
1190  &iponly_radix4_config, (uint8_t *)&src->ip[0], sna);
1191  else
1193  &iponly_radix4_config, (uint8_t *)&src->ip[0], src->netmask, sna);
1194  if (node4 == NULL)
1195  SCLogError("Error inserting in the "
1196  "src ipv4 radix tree");
1197  } else {
1198  SCLogDebug("Best match found");
1199 
1200  /* Found, copy the sig num table, add this signum and insert */
1201  SigNumArray *sna = SigNumArrayCopy((SigNumArray *)user_data);
1202  IPOnlyPrepareUpdateBitarray(src, sna);
1203 
1204  if (src->netmask == 32)
1206  &iponly_radix4_config, (uint8_t *)&src->ip[0], sna);
1207  else
1209  &iponly_radix4_config, (uint8_t *)&src->ip[0], src->netmask, sna);
1210  if (node4 == NULL) {
1211  char tmpstr[64];
1212  PrintInet(src->family, &src->ip[0], tmpstr, sizeof(tmpstr));
1213  SCLogError("Error inserting in the"
1214  " src ipv4 radix tree ip %s netmask %" PRIu8,
1215  tmpstr, src->netmask);
1216  exit(-1);
1217  }
1218  }
1219  } else {
1220  SCLogDebug("Exact match found");
1221 
1222  /* it's already inserted. Update it */
1223  SigNumArray *sna = (SigNumArray *)user_data;
1224  IPOnlyPrepareUpdateBitarray(src, sna);
1225  }
1226  } else if (src->family == AF_INET6) {
1227  SCLogDebug("To IPv6");
1228 
1229  void *user_data = NULL;
1230  if (src->netmask == 128)
1232  &de_ctx->io_ctx.tree_ipv6src, (uint8_t *)&src->ip[0], &user_data);
1233  else
1234  (void)SCRadix6TreeFindNetblock(&de_ctx->io_ctx.tree_ipv6src, (uint8_t *)&src->ip[0],
1235  src->netmask, &user_data);
1236  if (user_data == NULL) {
1237  /* Not found, look if there's a subnet of this range with bigger netmask */
1239  &de_ctx->io_ctx.tree_ipv6src, (uint8_t *)&src->ip[0], &user_data);
1240  if (user_data == NULL) {
1241  /* Not found, insert a new one */
1242  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1243  IPOnlyPrepareUpdateBitarray(src, sna);
1244 
1245  if (src->netmask == 128)
1247  &iponly_radix6_config, (uint8_t *)&src->ip[0], sna);
1248  else
1250  &iponly_radix6_config, (uint8_t *)&src->ip[0], src->netmask, sna);
1251  if (node6 == NULL)
1252  SCLogError("Error inserting in the src "
1253  "ipv6 radix tree");
1254  } else {
1255  /* Found, copy the sig num table, add this signum and insert */
1256  SigNumArray *sna = SigNumArrayCopy((SigNumArray *)user_data);
1257  IPOnlyPrepareUpdateBitarray(src, sna);
1258 
1259  if (src->netmask == 128)
1261  &iponly_radix6_config, (uint8_t *)&src->ip[0], sna);
1262  else
1264  &iponly_radix6_config, (uint8_t *)&src->ip[0], src->netmask, sna);
1265  if (node6 == NULL)
1266  SCLogError("Error inserting in the src "
1267  "ipv6 radix tree");
1268  }
1269  } else {
1270  /* it's already inserted. Update it */
1271  SigNumArray *sna = (SigNumArray *)user_data;
1272  IPOnlyPrepareUpdateBitarray(src, sna);
1273  }
1274  }
1275  IPOnlyCIDRItem *tmpaux = src;
1276  src = src->next;
1277  SCFree(tmpaux);
1278  }
1279 
1280  SCLogDebug("dsts:");
1281 
1282  /* Prepare Dst radix trees */
1283  for (IPOnlyCIDRItem *dst = de_ctx->io_ctx.ip_dst; dst != NULL;) {
1284  if (dst->family == AF_INET) {
1285  SCLogDebug("To IPv4");
1286  SCLogDebug("Item has netmask %"PRIu8" negated: %s; IP: %s; signum:"
1287  " %"PRIu32"", dst->netmask, (dst->negated)?"yes":"no",
1288  inet_ntoa(*(struct in_addr*)&dst->ip[0]), dst->signum);
1289 
1290  void *user_data = NULL;
1291  if (dst->netmask == 32)
1293  &de_ctx->io_ctx.tree_ipv4dst, (uint8_t *)&dst->ip[0], &user_data);
1294  else
1295  (void)SCRadix4TreeFindNetblock(&de_ctx->io_ctx.tree_ipv4dst, (uint8_t *)&dst->ip[0],
1296  dst->netmask, &user_data);
1297  if (user_data == NULL) {
1298  SCLogDebug("Exact match not found");
1299 
1300  /**
1301  * Not found, look if there's a subnet of this range
1302  * with bigger netmask
1303  */
1305  &de_ctx->io_ctx.tree_ipv4dst, (uint8_t *)&dst->ip[0], &user_data);
1306  if (user_data == NULL) {
1307  SCLogDebug("Best match not found");
1308 
1309  /** Not found, insert a new one */
1310  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1311  IPOnlyPrepareUpdateBitarray(dst, sna);
1312 
1313  if (dst->netmask == 32)
1315  &iponly_radix4_config, (uint8_t *)&dst->ip[0], sna);
1316  else
1318  &iponly_radix4_config, (uint8_t *)&dst->ip[0], dst->netmask, sna);
1319  if (node4 == NULL)
1320  SCLogError("Error inserting in the dst "
1321  "ipv4 radix tree");
1322  } else {
1323  SCLogDebug("Best match found");
1324 
1325  /* Found, copy the sig num table, add this signum and insert */
1326  SigNumArray *sna = SigNumArrayCopy((SigNumArray *)user_data);
1327  IPOnlyPrepareUpdateBitarray(dst, sna);
1328 
1329  if (dst->netmask == 32)
1331  &iponly_radix4_config, (uint8_t *)&dst->ip[0], sna);
1332  else
1334  &iponly_radix4_config, (uint8_t *)&dst->ip[0], dst->netmask, sna);
1335 
1336  if (node4 == NULL)
1337  SCLogError("Error inserting in the dst "
1338  "ipv4 radix tree");
1339  }
1340  } else {
1341  SCLogDebug("Exact match found");
1342 
1343  /* it's already inserted. Update it */
1344  SigNumArray *sna = (SigNumArray *)user_data;
1345  IPOnlyPrepareUpdateBitarray(dst, sna);
1346  }
1347  } else if (dst->family == AF_INET6) {
1348  SCLogDebug("To IPv6");
1349 
1350  void *user_data = NULL;
1351  if (dst->netmask == 128)
1353  &de_ctx->io_ctx.tree_ipv6dst, (uint8_t *)&dst->ip[0], &user_data);
1354  else
1355  (void)SCRadix6TreeFindNetblock(&de_ctx->io_ctx.tree_ipv6dst, (uint8_t *)&dst->ip[0],
1356  dst->netmask, &user_data);
1357  if (user_data == NULL) {
1358  /** Not found, look if there's a subnet of this range with
1359  * bigger netmask
1360  */
1362  &de_ctx->io_ctx.tree_ipv6dst, (uint8_t *)&dst->ip[0], &user_data);
1363  if (user_data == NULL) {
1364  /* Not found, insert a new one */
1365  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1366  IPOnlyPrepareUpdateBitarray(dst, sna);
1367 
1368  if (dst->netmask == 128)
1370  &iponly_radix6_config, (uint8_t *)&dst->ip[0], sna);
1371  else
1373  &iponly_radix6_config, (uint8_t *)&dst->ip[0], dst->netmask, sna);
1374  if (node6 == NULL)
1375  SCLogError("Error inserting in the dst "
1376  "ipv6 radix tree");
1377  } else {
1378  /* Found, copy the sig num table, add this signum and insert */
1379  SigNumArray *sna = SigNumArrayCopy((SigNumArray *)user_data);
1380  IPOnlyPrepareUpdateBitarray(dst, sna);
1381 
1382  if (dst->netmask == 128)
1384  &iponly_radix6_config, (uint8_t *)&dst->ip[0], sna);
1385  else
1387  &iponly_radix6_config, (uint8_t *)&dst->ip[0], dst->netmask, sna);
1388  if (node6 == NULL)
1389  SCLogError("Error inserting in the dst "
1390  "ipv6 radix tree");
1391  }
1392  } else {
1393  /* it's already inserted. Update it */
1394  SigNumArray *sna = (SigNumArray *)user_data;
1395  IPOnlyPrepareUpdateBitarray(dst, sna);
1396  }
1397  }
1398  IPOnlyCIDRItem *tmpaux = dst;
1399  dst = dst->next;
1400  SCFree(tmpaux);
1401  }
1402 }
1403 
1404 /**
1405  * \brief Add a signature to the lists of Addresses in CIDR format (sorted)
1406  * this step is necessary to build the radix tree with a hierarchical
1407  * relation between nodes
1408  * \param de_ctx Pointer to the current detection engine context
1409  * \param de_ctx Pointer to the current ip only detection engine contest
1410  * \param s Pointer to the current signature
1411  */
1413  Signature *s)
1414 {
1415  if (!(s->type == SIG_TYPE_IPONLY))
1416  return;
1417 
1418  SigIntId mapped_signum = IPOnlyTrackSigNum(io_ctx, s->iid);
1419  SCLogDebug("Adding IPs from rule: %" PRIu32 " (%s) as %" PRIu32 " mapped to %" PRIu32 "\n",
1420  s->id, s->msg, s->iid, mapped_signum);
1421  /* Set the internal signum to the list before merging */
1422  IPOnlyCIDRListSetSigNum(s->init_data->cidr_src, mapped_signum);
1423 
1424  IPOnlyCIDRListSetSigNum(s->init_data->cidr_dst, mapped_signum);
1425 
1426  /**
1427  * ipv4 and ipv6 are mixed, but later we will separate them into
1428  * different trees
1429  */
1430  io_ctx->ip_src = IPOnlyCIDRItemInsert(io_ctx->ip_src, s->init_data->cidr_src);
1431  io_ctx->ip_dst = IPOnlyCIDRItemInsert(io_ctx->ip_dst, s->init_data->cidr_dst);
1432 
1433  if (mapped_signum > io_ctx->max_idx)
1434  io_ctx->max_idx = mapped_signum;
1435 
1436  /** no longer ref to this, it's in the table now */
1437  s->init_data->cidr_src = NULL;
1438  s->init_data->cidr_dst = NULL;
1439 }
1440 
1441 #ifdef UNITTESTS
1442 /**
1443  * \test check that we set a Signature as IPOnly because it has no rule
1444  * option appending a SigMatch and no port is fixed
1445  */
1446 
1447 static int IPOnlyTestSig01(void)
1448 {
1450  FAIL_IF(de_ctx == NULL);
1451  de_ctx->flags |= DE_QUIET;
1452 
1453  Signature *s = SigInit(de_ctx,"alert tcp any any -> any any (sid:400001; rev:1;)");
1454  FAIL_IF(s == NULL);
1455 
1456  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1457  SigFree(de_ctx, s);
1459  PASS;
1460 }
1461 
1462 /**
1463  * \test check that we don't set a Signature as IPOnly because it has no rule
1464  * option appending a SigMatch but a port is fixed
1465  */
1466 
1467 static int IPOnlyTestSig02 (void)
1468 {
1470  FAIL_IF(de_ctx == NULL);
1471  de_ctx->flags |= DE_QUIET;
1472 
1473  Signature *s = SigInit(de_ctx,"alert tcp any any -> any 80 (sid:400001; rev:1;)");
1474  FAIL_IF(s == NULL);
1475 
1476  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1477  SigFree(de_ctx, s);
1479  PASS;
1480 }
1481 
1482 /**
1483  * \test check that we set don't set a Signature as IPOnly
1484  * because it has rule options appending a SigMatch like content, and pcre
1485  */
1486 
1487 static int IPOnlyTestSig03 (void)
1488 {
1489  int result = 1;
1491  Signature *s=NULL;
1492 
1494  if (de_ctx == NULL)
1495  goto end;
1496  de_ctx->flags |= DE_QUIET;
1497 
1498  /* combination of pcre and content */
1499  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (pcre and content) \"; content:\"php\"; pcre:\"/require(_once)?/i\"; classtype:misc-activity; sid:400001; rev:1;)");
1500  if (s == NULL) {
1501  goto end;
1502  }
1503  if(SignatureIsIPOnly(de_ctx, s))
1504  {
1505  printf("got a IPOnly signature (content): ");
1506  result=0;
1507  }
1508  SigFree(de_ctx, s);
1509 
1510  /* content */
1511  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (content) \"; content:\"match something\"; classtype:misc-activity; sid:400001; rev:1;)");
1512  if (s == NULL) {
1513  goto end;
1514  }
1515  if(SignatureIsIPOnly(de_ctx, s))
1516  {
1517  printf("got a IPOnly signature (content): ");
1518  result=0;
1519  }
1520  SigFree(de_ctx, s);
1521 
1522  /* uricontent */
1523  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (uricontent) \"; uricontent:\"match something\"; classtype:misc-activity; sid:400001; rev:1;)");
1524  if (s == NULL) {
1525  goto end;
1526  }
1527  if(SignatureIsIPOnly(de_ctx, s))
1528  {
1529  printf("got a IPOnly signature (uricontent): ");
1530  result=0;
1531  }
1532  SigFree(de_ctx, s);
1533 
1534  /* pcre */
1535  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (pcre) \"; pcre:\"/e?idps rule[sz]/i\"; classtype:misc-activity; sid:400001; rev:1;)");
1536  if (s == NULL) {
1537  goto end;
1538  }
1539  if(SignatureIsIPOnly(de_ctx, s))
1540  {
1541  printf("got a IPOnly signature (pcre): ");
1542  result=0;
1543  }
1544  SigFree(de_ctx, s);
1545 
1546  /* flow */
1547  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (flow) \"; flow:to_server; classtype:misc-activity; sid:400001; rev:1;)");
1548  if (s == NULL) {
1549  goto end;
1550  }
1551  if(SignatureIsIPOnly(de_ctx, s))
1552  {
1553  printf("got a IPOnly signature (flow): ");
1554  result=0;
1555  }
1556  SigFree(de_ctx, s);
1557 
1558  /* dsize */
1559  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (dsize) \"; dsize:100; classtype:misc-activity; sid:400001; rev:1;)");
1560  if (s == NULL) {
1561  goto end;
1562  }
1563  if(SignatureIsIPOnly(de_ctx, s))
1564  {
1565  printf("got a IPOnly signature (dsize): ");
1566  result=0;
1567  }
1568  SigFree(de_ctx, s);
1569 
1570  /* flowbits */
1571  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (flowbits) \"; flowbits:unset; classtype:misc-activity; sid:400001; rev:1;)");
1572  if (s == NULL) {
1573  goto end;
1574  }
1575  if(SignatureIsIPOnly(de_ctx, s))
1576  {
1577  printf("got a IPOnly signature (flowbits): ");
1578  result=0;
1579  }
1580  SigFree(de_ctx, s);
1581 
1582  /* flowvar */
1583  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (flowvar) \"; pcre:\"/(?<flow_var>.*)/i\"; flowvar:var,\"str\"; classtype:misc-activity; sid:400001; rev:1;)");
1584  if (s == NULL) {
1585  goto end;
1586  }
1587  if(SignatureIsIPOnly(de_ctx, s))
1588  {
1589  printf("got a IPOnly signature (flowvar): ");
1590  result=0;
1591  }
1592  SigFree(de_ctx, s);
1593 
1594  /* pktvar */
1595  s = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTest40-03 sig is not IPOnly (pktvar) \"; pcre:\"/(?<pkt_var>.*)/i\"; pktvar:var,\"str\"; classtype:misc-activity; sid:400001; rev:1;)");
1596  if (s == NULL) {
1597  goto end;
1598  }
1599  if(SignatureIsIPOnly(de_ctx, s))
1600  {
1601  printf("got a IPOnly signature (pktvar): ");
1602  result=0;
1603  }
1604  SigFree(de_ctx, s);
1605 
1606 end:
1607  if (de_ctx != NULL)
1609  return result;
1610 }
1611 
1612 /**
1613  * \test
1614  */
1615 static int IPOnlyTestSig04 (void)
1616 {
1617  int result = 1;
1618  IPOnlyCIDRItem *head = NULL;
1619 
1620  // Test a linked list of size 0, 1, 2, ..., 5
1621  for (int size = 0; size < 6; size++) {
1622  IPOnlyCIDRItem *new = NULL;
1623 
1624  if (size > 0) {
1625  new = IPOnlyCIDRItemNew();
1626  new->netmask = 10;
1627  new->ip[0] = 3;
1628 
1629  head = IPOnlyCIDRItemInsert(head, new);
1630  }
1631 
1632  if (size > 1) {
1633  new = IPOnlyCIDRItemNew();
1634  new->netmask = 11;
1635 
1636  head = IPOnlyCIDRItemInsert(head, new);
1637  }
1638 
1639  if (size > 2) {
1640  new = IPOnlyCIDRItemNew();
1641  new->netmask = 9;
1642 
1643  head = IPOnlyCIDRItemInsert(head, new);
1644  }
1645 
1646  if (size > 3) {
1647  new = IPOnlyCIDRItemNew();
1648  new->netmask = 10;
1649  new->ip[0] = 1;
1650 
1651  head = IPOnlyCIDRItemInsert(head, new);
1652  }
1653 
1654  if (size > 4) {
1655  new = IPOnlyCIDRItemNew();
1656  new->netmask = 10;
1657  new->ip[0] = 2;
1658 
1659  head = IPOnlyCIDRItemInsert(head, new);
1660  }
1661 
1662  IPOnlyCIDRListPrint(head);
1663 
1664  IPOnlyCIDRListQSort(&head);
1665 
1666  if (size == 0) {
1667  if (head != NULL) {
1668  result = 0;
1669  goto end;
1670  }
1671  }
1672 
1673  /**
1674  * Validate the following list entries for each size
1675  * 1 - 10
1676  * 2 - 10<3> 11
1677  * 3 - 9 10<3> 11
1678  * 4 - 9 10<1> 10<3> 11
1679  * 5 - 9 10<1> 10<2> 10<3> 11
1680  */
1681  new = head;
1682  if (size >= 3) {
1683  if (new->netmask != 9) {
1684  result = 0;
1685  goto end;
1686  }
1687  new = new->next;
1688  }
1689 
1690  if (size >= 4) {
1691  if (new->netmask != 10 || new->ip[0] != 1) {
1692  result = 0;
1693  goto end;
1694  }
1695  new = new->next;
1696  }
1697 
1698  if (size >= 5) {
1699  if (new->netmask != 10 || new->ip[0] != 2) {
1700  result = 0;
1701  goto end;
1702  }
1703  new = new->next;
1704  }
1705 
1706  if (size >= 1) {
1707  if (new->netmask != 10 || new->ip[0] != 3) {
1708  result = 0;
1709  goto end;
1710  }
1711  new = new->next;
1712  }
1713 
1714  if (size >= 2) {
1715  if (new->netmask != 11) {
1716  result = 0;
1717  goto end;
1718  }
1719  new = new->next;
1720  }
1721 
1722  if (new != NULL) {
1723  result = 0;
1724  goto end;
1725  }
1726 
1728  head = NULL;
1729  }
1730 
1731 end:
1732  if (head) {
1734  head = NULL;
1735  }
1736  return result;
1737 }
1738 
1739 /**
1740  * \test Test a set of ip only signatures making use a lot of
1741  * addresses for src and dst (all should match)
1742  */
1743 static int IPOnlyTestSig05(void)
1744 {
1745  int result = 0;
1746  uint8_t *buf = (uint8_t *)"Hi all!";
1747  uint16_t buflen = strlen((char *)buf);
1748 
1749  uint8_t numpkts = 1;
1750  uint8_t numsigs = 7;
1751 
1752  Packet *p[1];
1753 
1754  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1755 
1756  const char *sigs[numsigs];
1757  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1758  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1759  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1760  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1761  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1762  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1763  sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1764 
1765  /* Sid numbers (we could extract them from the sig) */
1766  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1767  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1768 
1769  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1770 
1771  UTHFreePackets(p, numpkts);
1772 
1773  return result;
1774 }
1775 
1776 /**
1777  * \test Test a set of ip only signatures making use a lot of
1778  * addresses for src and dst (none should match)
1779  */
1780 static int IPOnlyTestSig06(void)
1781 {
1782  int result = 0;
1783  uint8_t *buf = (uint8_t *)"Hi all!";
1784  uint16_t buflen = strlen((char *)buf);
1785 
1786  uint8_t numpkts = 1;
1787  uint8_t numsigs = 7;
1788 
1789  Packet *p[1];
1790 
1791  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "80.58.0.33", "195.235.113.3");
1792 
1793  const char *sigs[numsigs];
1794  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1795  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1796  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1797  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1798  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1799  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1800  sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1801 
1802  /* Sid numbers (we could extract them from the sig) */
1803  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1804  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1805 
1806  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1807 
1808  UTHFreePackets(p, numpkts);
1809 
1810  return result;
1811 }
1812 
1813 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
1814  * which is why these unittests fail. When we fix 608, we need to renable
1815  * these sigs */
1816 #if 0
1817 /**
1818  * \test Test a set of ip only signatures making use a lot of
1819  * addresses for src and dst (all should match)
1820  */
1821 static int IPOnlyTestSig07(void)
1822 {
1823  int result = 0;
1824  uint8_t *buf = (uint8_t *)"Hi all!";
1825  uint16_t buflen = strlen((char *)buf);
1826 
1827  uint8_t numpkts = 1;
1828  uint8_t numsigs = 7;
1829 
1830  Packet *p[1];
1831 
1832  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1833 
1834  char *sigs[numsigs];
1835  sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1836  sigs[1]= "alert tcp [192.168.1.2,192.168.1.5,192.168.1.4] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
1837  sigs[2]= "alert tcp [192.168.1.0/24,!192.168.1.1] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1838  sigs[3]= "alert tcp [192.0.0.0/8,!192.168.0.0/16,192.168.1.0/24,!192.168.1.1] any -> [192.168.1.0/24,!192.168.1.5] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1839  sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1840  sigs[5]= "alert tcp any any -> [192.168.0.0/16,!192.168.1.0/24,192.168.1.1] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1841  sigs[6]= "alert tcp [78.129.202.0/24,192.168.1.5,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> 192.168.1.1 any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
1842 
1843  /* Sid numbers (we could extract them from the sig) */
1844  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1845  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1846 
1847  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1848 
1849  UTHFreePackets(p, numpkts);
1850 
1851  return result;
1852 }
1853 #endif
1854 
1855 /**
1856  * \test Test a set of ip only signatures making use a lot of
1857  * addresses for src and dst (none should match)
1858  */
1859 static int IPOnlyTestSig08(void)
1860 {
1861  int result = 0;
1862  uint8_t *buf = (uint8_t *)"Hi all!";
1863  uint16_t buflen = strlen((char *)buf);
1864 
1865  uint8_t numpkts = 1;
1866  uint8_t numsigs = 7;
1867 
1868  Packet *p[1];
1869 
1870  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
1871 
1872  const char *sigs[numsigs];
1873  sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1874  sigs[1]= "alert tcp [192.168.1.2,192.168.1.5,192.168.1.4] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
1875  sigs[2]= "alert tcp [192.168.1.0/24,!192.168.1.1] any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1876  sigs[3]= "alert tcp [192.0.0.0/8,!192.168.0.0/16,192.168.1.0/24,!192.168.1.1] any -> [192.168.1.0/24,!192.168.1.5] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1877  sigs[4]= "alert tcp any any -> !192.168.1.5 any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1878  sigs[5]= "alert tcp any any -> [192.168.0.0/16,!192.168.1.0/24,192.168.1.1] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1879  sigs[6]= "alert tcp [78.129.202.0/24,192.168.1.5,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> 192.168.1.1 any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
1880 
1881  /* Sid numbers (we could extract them from the sig) */
1882  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1883  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1884 
1885  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1886 
1887  UTHFreePackets(p, numpkts);
1888 
1889  return result;
1890 }
1891 
1892 /**
1893  * \test Test a set of ip only signatures making use a lot of
1894  * addresses for src and dst (all should match)
1895  */
1896 static int IPOnlyTestSig09(void)
1897 {
1898  int result = 0;
1899  uint8_t *buf = (uint8_t *)"Hi all!";
1900  uint16_t buflen = strlen((char *)buf);
1901 
1902  uint8_t numpkts = 1;
1903  uint8_t numsigs = 7;
1904 
1905  Packet *p[1];
1906 
1907  p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562");
1908 
1909  const char *sigs[numsigs];
1910  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1911  sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1912  sigs[2]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1913  sigs[3]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:0/96 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1914  sigs[4]= "alert tcp 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1915  sigs[5]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1916  sigs[6]= "alert tcp 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1917 
1918  /* Sid numbers (we could extract them from the sig) */
1919  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1920  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1921 
1922  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1923 
1924  UTHFreePackets(p, numpkts);
1925 
1926  return result;
1927 }
1928 
1929 /**
1930  * \test Test a set of ip only signatures making use a lot of
1931  * addresses for src and dst (none should match)
1932  */
1933 static int IPOnlyTestSig10(void)
1934 {
1935  int result = 0;
1936  uint8_t *buf = (uint8_t *)"Hi all!";
1937  uint16_t buflen = strlen((char *)buf);
1938 
1939  uint8_t numpkts = 1;
1940  uint8_t numsigs = 7;
1941 
1942  Packet *p[1];
1943 
1944  p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565");
1945 
1946  const char *sigs[numsigs];
1947  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1948  sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1949  sigs[2]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1950  sigs[3]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> !3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562/96 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1951  sigs[4]= "alert tcp !3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1952  sigs[5]= "alert tcp any any -> !3FFE:FFFF:7654:FEDA:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1953  sigs[6]= "alert tcp 3FFE:FFFF:7654:FEDA:0:0:0:0/64 any -> 3FFE:FFFF:7654:FEDB:0:0:0:0/64 any (msg:\"Testing src/dst ip (sid 7)\"; content:\"Hi all\";sid:7;)";
1954 
1955  /* Sid numbers (we could extract them from the sig) */
1956  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1957  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1958 
1959  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1960 
1961  UTHFreePackets(p, numpkts);
1962 
1963  return result;
1964 }
1965 
1966 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
1967  * which is why these unittests fail. When we fix 608, we need to renable
1968  * these sigs */
1969 #if 0
1970 /**
1971  * \test Test a set of ip only signatures making use a lot of
1972  * addresses for src and dst (all should match) with ipv4 and ipv6 mixed
1973  */
1974 static int IPOnlyTestSig11(void)
1975 {
1976  int result = 0;
1977  uint8_t *buf = (uint8_t *)"Hi all!";
1978  uint16_t buflen = strlen((char *)buf);
1979 
1980  uint8_t numpkts = 2;
1981  uint8_t numsigs = 7;
1982 
1983  Packet *p[2];
1984 
1985  p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562");
1986  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
1987 
1988  char *sigs[numsigs];
1989  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1 any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.5 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1990  sigs[1]= "alert tcp [192.168.1.1,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.4,192.168.1.5,!192.168.1.0/24] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.0/24] any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
1991  sigs[2]= "alert tcp [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1992  sigs[3]= "alert tcp [3FFE:FFFF:0:0:0:0:0:0/32,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.0/24,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1993  sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1994  sigs[5]= "alert tcp any any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1995  sigs[6]= "alert tcp [78.129.202.0/24,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.0.0.0/8] any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
1996 
1997  /* Sid numbers (we could extract them from the sig) */
1998  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1999  uint32_t results[2][7] = {{ 1, 1, 1, 1, 1, 1, 1}, { 1, 1, 1, 1, 1, 1, 1}};
2000 
2001  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2002 
2003  UTHFreePackets(p, numpkts);
2004 
2005  return result;
2006 }
2007 #endif
2008 
2009 /**
2010  * \test Test a set of ip only signatures making use a lot of
2011  * addresses for src and dst (none should match) with ipv4 and ipv6 mixed
2012  */
2013 static int IPOnlyTestSig12(void)
2014 {
2015  int result = 0;
2016  uint8_t *buf = (uint8_t *)"Hi all!";
2017  uint16_t buflen = strlen((char *)buf);
2018 
2019  uint8_t numpkts = 2;
2020  uint8_t numsigs = 7;
2021 
2022  Packet *p[2];
2023 
2024  p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"3FBE:FFFF:7654:FEDA:1245:BA98:3210:4562","3FBE:FFFF:7654:FEDA:1245:BA98:3210:4565");
2025  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"195.85.1.1","80.198.1.5");
2026 
2027  const char *sigs[numsigs];
2028  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1 any -> 3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.5 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
2029  sigs[1]= "alert tcp [192.168.1.1,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.4,192.168.1.5,!192.168.1.0/24] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.0/24] any (msg:\"Testing src/dst ip (sid 2)\"; sid:2;)";
2030  sigs[2]= "alert tcp [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
2031  sigs[3]= "alert tcp [3FFE:FFFF:0:0:0:0:0:0/32,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.1] any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,192.168.1.0/24,!3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565] any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
2032  sigs[4]= "alert tcp any any -> [!3FBE:FFFF:7654:FEDA:1245:BA98:3210:4565,!80.198.1.5] any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2033  sigs[5]= "alert tcp any any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!3FFE:FFFF:7654:FEDA:0:0:0:0/64,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.168.1.5] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
2034  sigs[6]= "alert tcp [78.129.202.0/24,3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565,192.168.1.1,78.129.205.64,78.129.214.103,78.129.223.19,78.129.233.17,78.137.168.33,78.140.132.11,78.140.133.15,78.140.138.105,78.140.139.105,78.140.141.107,78.140.141.114,78.140.143.103,78.140.143.13,78.140.145.144,78.140.170.164,78.140.23.18,78.143.16.7,78.143.46.124,78.157.129.71] any -> [3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562,192.0.0.0/8] any (msg:\"ET RBN Known Russian Business Network IP TCP - BLOCKING (246)\"; sid:7;)"; /* real sid:"2407490" */
2035 
2036  /* Sid numbers (we could extract them from the sig) */
2037  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2038  uint32_t results[2][7] = {{ 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}};
2039 
2040  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2041 
2042  UTHFreePackets(p, numpkts);
2043 
2044  return result;
2045 }
2046 
2047 static int IPOnlyTestSig13(void)
2048 {
2050  FAIL_IF(de_ctx == NULL);
2051  de_ctx->flags |= DE_QUIET;
2052 
2053  Signature *s = SigInit(de_ctx,
2054  "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2055  "flowbits:set,myflow1; sid:1; rev:1;)");
2056  FAIL_IF(s == NULL);
2057 
2058  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
2059  SigFree(de_ctx, s);
2061  PASS;
2062 }
2063 
2064 static int IPOnlyTestSig14(void)
2065 {
2067  FAIL_IF(de_ctx == NULL);
2068  de_ctx->flags |= DE_QUIET;
2069 
2070  Signature *s = SigInit(de_ctx,
2071  "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2072  "flowbits:set,myflow1; flowbits:isset,myflow2; sid:1; rev:1;)");
2073  FAIL_IF(s == NULL);
2074 
2075  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 1);
2076  SigFree(de_ctx, s);
2078  PASS;
2079 }
2080 
2081 static int IPOnlyTestSig15(void)
2082 {
2083  int result = 0;
2084  uint8_t *buf = (uint8_t *)"Hi all!";
2085  uint16_t buflen = strlen((char *)buf);
2086 
2087  uint8_t numpkts = 1;
2088  uint8_t numsigs = 7;
2089 
2090  Packet *p[1];
2091  Flow f;
2092  GenericVar flowvar;
2093  memset(&f, 0, sizeof(Flow));
2094  memset(&flowvar, 0, sizeof(GenericVar));
2095  FLOW_INITIALIZE(&f);
2096 
2097  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
2098 
2099  p[0]->flow = &f;
2100  p[0]->flow->flowvar = &flowvar;
2101  p[0]->flags |= PKT_HAS_FLOW;
2103 
2104  const char *sigs[numsigs];
2105  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; "
2106  "flowbits:set,one; sid:1;)";
2107  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; "
2108  "flowbits:set,two; sid:2;)";
2109  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; "
2110  "flowbits:set,three; sid:3;)";
2111  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; "
2112  "flowbits:set,four; sid:4;)";
2113  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; "
2114  "flowbits:set,five; sid:5;)";
2115  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; "
2116  "flowbits:set,six; sid:6;)";
2117  sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; "
2118  "flowbits:set,seven; content:\"Hi all\"; sid:7;)";
2119 
2120  /* Sid numbers (we could extract them from the sig) */
2121  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2122  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2123 
2124  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2125 
2126  UTHFreePackets(p, numpkts);
2127 
2128  FLOW_DESTROY(&f);
2129  return result;
2130 }
2131 
2132 /**
2133  * \brief Unittest to show #599. We fail to match if we have negated addresses.
2134  */
2135 static int IPOnlyTestSig16(void)
2136 {
2137  int result = 0;
2138  uint8_t *buf = (uint8_t *)"Hi all!";
2139  uint16_t buflen = strlen((char *)buf);
2140 
2141  uint8_t numpkts = 1;
2142  uint8_t numsigs = 2;
2143 
2144  Packet *p[1];
2145 
2146  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "100.100.0.0", "50.0.0.0");
2147 
2148  const char *sigs[numsigs];
2149  sigs[0]= "alert tcp !100.100.0.1 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2150  sigs[1]= "alert tcp any any -> !50.0.0.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2151 
2152  /* Sid numbers (we could extract them from the sig) */
2153  uint32_t sid[2] = { 1, 2};
2154  uint32_t results[2] = { 1, 1};
2155 
2156  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2157 
2158  UTHFreePackets(p, numpkts);
2159 
2160  return result;
2161 }
2162 
2163 /**
2164  * \brief Unittest to show #611. Ports on portless protocols.
2165  */
2166 static int IPOnlyTestSig17(void)
2167 {
2168  int result = 0;
2169  uint8_t *buf = (uint8_t *)"Hi all!";
2170  uint16_t buflen = strlen((char *)buf);
2171 
2172  uint8_t numpkts = 1;
2173  uint8_t numsigs = 2;
2174 
2175  Packet *p[1];
2176 
2177  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_ICMP, "100.100.0.0", "50.0.0.0");
2178 
2179  const char *sigs[numsigs];
2180  sigs[0]= "alert ip 100.100.0.0 80 -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2181  sigs[1]= "alert ip any any -> 50.0.0.0 123 (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2182 
2183  uint32_t sid[2] = { 1, 2};
2184  uint32_t results[2] = { 0, 0}; /* neither should match */
2185 
2186  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2187 
2188  UTHFreePackets(p, numpkts);
2189 
2190  return result;
2191 }
2192 
2193 /**
2194  * \brief Unittest to show #3568 -- IP address range handling
2195  */
2196 static int IPOnlyTestSig18(void)
2197 {
2198  int result = 0;
2199  uint8_t *buf = (uint8_t *)"Hi all!";
2200  uint16_t buflen = strlen((char *)buf);
2201 
2202  uint8_t numpkts = 4;
2203  uint8_t numsigs = 4;
2204 
2205  Packet *p[4];
2206 
2207  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "10.10.10.1", "50.0.0.1");
2208  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "220.10.10.1", "5.0.0.1");
2209  p[2] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "0.0.0.1", "50.0.0.1");
2210  p[3] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "255.255.255.254", "5.0.0.1");
2211 
2212  const char *sigs[numsigs];
2213  // really many IP addresses
2214  sigs[0]= "alert ip 1.2.3.4-219.6.7.8 any -> any any (sid:1;)";
2215  sigs[1]= "alert ip 51.2.3.4-253.1.2.3 any -> any any (sid:2;)";
2216  sigs[2]= "alert ip 0.0.0.0-50.0.0.2 any -> any any (sid:3;)";
2217  sigs[3]= "alert ip 50.0.0.0-255.255.255.255 any -> any any (sid:4;)";
2218 
2219  uint32_t sid[4] = { 1, 2, 3, 4, };
2220  uint32_t results[4][4] = {
2221  { 1, 0, 1, 0, }, { 0, 1, 0, 1}, { 0, 0, 1, 0 }, { 0, 0, 0, 1}};
2222 
2223  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2224 
2225  UTHFreePackets(p, numpkts);
2226 
2227  FAIL_IF(result != 1);
2228 
2229  PASS;
2230 }
2231 
2232 /** \test build IP-only tree */
2233 static int IPOnlyTestBug5066v1(void)
2234 {
2236  FAIL_IF(de_ctx == NULL);
2237  de_ctx->flags |= DE_QUIET;
2238 
2240  de_ctx, "alert ip [1.2.3.4/24,1.2.3.64/27] any -> any any (sid:1;)");
2241  FAIL_IF_NULL(s);
2242  s = DetectEngineAppendSig(de_ctx, "alert ip [1.2.3.4/24] any -> any any (sid:2;)");
2243  FAIL_IF_NULL(s);
2244 
2246 
2248  PASS;
2249 }
2250 
2251 static int IPOnlyTestBug5066v2(void)
2252 {
2253  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2254  FAIL_IF_NULL(x);
2255 
2256  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.4/24") != 0);
2257 
2258  char ip[16];
2259  PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2260  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2261 
2262  FAIL_IF_NOT(strcmp(ip, "1.2.3.0") == 0);
2263  FAIL_IF_NOT(x->netmask == 24);
2264 
2265  IPOnlyCIDRListFree(x);
2266  PASS;
2267 }
2268 
2269 static int IPOnlyTestBug5066v3(void)
2270 {
2271  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2272  FAIL_IF_NULL(x);
2273 
2274  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.64/26") != 0);
2275 
2276  char ip[16];
2277  PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2278  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2279 
2280  FAIL_IF_NOT(strcmp(ip, "1.2.3.64") == 0);
2281  FAIL_IF_NOT(x->netmask == 26);
2282 
2283  IPOnlyCIDRListFree(x);
2284  PASS;
2285 }
2286 
2287 static int IPOnlyTestBug5066v4(void)
2288 {
2289  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2290  FAIL_IF_NULL(x);
2291 
2292  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "2000::1:1/122") != 0);
2293 
2294  char ip[64];
2295  PrintInet(AF_INET6, (const void *)&x->ip, ip, sizeof(ip));
2296  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2297 
2298  FAIL_IF_NOT(strcmp(ip, "2000:0000:0000:0000:0000:0000:0001:0000") == 0);
2299  FAIL_IF_NOT(x->netmask == 122);
2300 
2301  IPOnlyCIDRListFree(x);
2302  PASS;
2303 }
2304 
2305 static int IPOnlyTestBug5066v5(void)
2306 {
2307  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2308  FAIL_IF_NULL(x);
2309 
2310  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "2000::1:40/122") != 0);
2311 
2312  char ip[64];
2313  PrintInet(AF_INET6, (const void *)&x->ip, ip, sizeof(ip));
2314  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2315 
2316  FAIL_IF_NOT(strcmp(ip, "2000:0000:0000:0000:0000:0000:0001:0040") == 0);
2317  FAIL_IF_NOT(x->netmask == 122);
2318 
2319  IPOnlyCIDRListFree(x);
2320  PASS;
2321 }
2322 
2323 static int IPOnlyTestBug5168v1(void)
2324 {
2325  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2326  FAIL_IF_NULL(x);
2327 
2328  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.64/0.0.0.0") != 0);
2329 
2330  char ip[16];
2331  PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2332  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2333 
2334  FAIL_IF_NOT(strcmp(ip, "0.0.0.0") == 0);
2335  FAIL_IF_NOT(x->netmask == 0);
2336 
2337  IPOnlyCIDRListFree(x);
2338  PASS;
2339 }
2340 
2341 static int IPOnlyTestBug5168v2(void)
2342 {
2343  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2344  FAIL_IF_NULL(x);
2345  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "0.0.0.5/0.0.0.5") != -1);
2346  IPOnlyCIDRListFree(x);
2347  PASS;
2348 }
2349 
2350 #endif /* UNITTESTS */
2351 
2353 {
2354 #ifdef UNITTESTS
2355  UtRegisterTest("IPOnlyTestSig01", IPOnlyTestSig01);
2356  UtRegisterTest("IPOnlyTestSig02", IPOnlyTestSig02);
2357  UtRegisterTest("IPOnlyTestSig03", IPOnlyTestSig03);
2358  UtRegisterTest("IPOnlyTestSig04", IPOnlyTestSig04);
2359 
2360  UtRegisterTest("IPOnlyTestSig05", IPOnlyTestSig05);
2361  UtRegisterTest("IPOnlyTestSig06", IPOnlyTestSig06);
2362 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2363  * which is why these unittests fail. When we fix 608, we need to renable
2364  * these sigs */
2365 #if 0
2366  UtRegisterTest("IPOnlyTestSig07", IPOnlyTestSig07, 1);
2367 #endif
2368  UtRegisterTest("IPOnlyTestSig08", IPOnlyTestSig08);
2369 
2370  UtRegisterTest("IPOnlyTestSig09", IPOnlyTestSig09);
2371  UtRegisterTest("IPOnlyTestSig10", IPOnlyTestSig10);
2372 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2373  * which is why these unittests fail. When we fix 608, we need to renable
2374  * these sigs */
2375 #if 0
2376  UtRegisterTest("IPOnlyTestSig11", IPOnlyTestSig11, 1);
2377 #endif
2378  UtRegisterTest("IPOnlyTestSig12", IPOnlyTestSig12);
2379  UtRegisterTest("IPOnlyTestSig13", IPOnlyTestSig13);
2380  UtRegisterTest("IPOnlyTestSig14", IPOnlyTestSig14);
2381  UtRegisterTest("IPOnlyTestSig15", IPOnlyTestSig15);
2382  UtRegisterTest("IPOnlyTestSig16", IPOnlyTestSig16);
2383 
2384  UtRegisterTest("IPOnlyTestSig17", IPOnlyTestSig17);
2385  UtRegisterTest("IPOnlyTestSig18", IPOnlyTestSig18);
2386 
2387  UtRegisterTest("IPOnlyTestBug5066v1", IPOnlyTestBug5066v1);
2388  UtRegisterTest("IPOnlyTestBug5066v2", IPOnlyTestBug5066v2);
2389  UtRegisterTest("IPOnlyTestBug5066v3", IPOnlyTestBug5066v3);
2390  UtRegisterTest("IPOnlyTestBug5066v4", IPOnlyTestBug5066v4);
2391  UtRegisterTest("IPOnlyTestBug5066v5", IPOnlyTestBug5066v5);
2392 
2393  UtRegisterTest("IPOnlyTestBug5168v1", IPOnlyTestBug5168v1);
2394  UtRegisterTest("IPOnlyTestBug5168v2", IPOnlyTestBug5168v2);
2395 #endif
2396 }
IPOnlyRegisterTests
void IPOnlyRegisterTests(void)
Definition: detect-engine-iponly.c:2352
util-byte.h
Packet_::proto
uint8_t proto
Definition: decode.h:523
len
uint8_t len
Definition: app-layer-dnp3.h:2
SCRadix4Node_
Structure for the node in the radix tree.
Definition: util-radix4-tree.h:36
SCRadix6AddKeyIPV6Netblock
SCRadix6Node * SCRadix6AddKeyIPV6Netblock(SCRadix6Tree *tree, const SCRadix6Config *config, const uint8_t *key_stream, uint8_t netmask, void *user)
Adds a new IPV6 netblock to the Radix6 tree.
Definition: util-radix6-tree.c:214
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
detect-engine-proto.h
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
SCRadix6TreeFindExactMatch
SCRadix6Node * SCRadix6TreeFindExactMatch(const SCRadix6Tree *tree, const uint8_t *key, void **user_data)
Definition: util-radix6-tree.c:161
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1268
DetectEngineIPOnlyCtx_::tree_ipv6dst
SCRadix6Tree tree_ipv6dst
Definition: detect.h:849
flow-util.h
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:32
detect-engine-siggroup.h
IPOnlyCIDRItem_::netmask
uint8_t netmask
Definition: detect.h:336
SCRadix6TreeFindBestMatch
SCRadix6Node * SCRadix6TreeFindBestMatch(const SCRadix6Tree *tree, const uint8_t *key, void **user_data)
Definition: util-radix6-tree.c:173
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:2057
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectEngineIPOnlyCtx_::tree_ipv4dst
SCRadix4Tree tree_ipv4dst
Definition: detect.h:848
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
KEYWORD_PROFILING_SET_LIST
#define KEYWORD_PROFILING_SET_LIST(ctx, list)
Definition: util-profiling.h:46
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1448
SC_RULE_VARS_ADDRESS_GROUPS
@ SC_RULE_VARS_ADDRESS_GROUPS
Definition: util-rule-vars.h:31
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:279
IPOnlySigParseAddress
int IPOnlySigParseAddress(const DetectEngineCtx *de_ctx, Signature *s, const char *addrstr, char flag)
Parses an address group sent as a character string and updates the IPOnlyCIDRItem lists src and dst o...
Definition: detect-engine-iponly.c:869
IPOnlyDeinit
void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Deinitialize the IP Only detection engine context.
Definition: detect-engine-iponly.c:954
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
SigMatchData_::is_last
bool is_last
Definition: detect.h:367
DetectEngineIPOnlyCtx_::ip_src
IPOnlyCIDRItem * ip_src
Definition: detect.h:852
IPOnlyCIDRItem_
Definition: detect.h:332
SCRadix4TreeInitialize
SCRadix4Tree SCRadix4TreeInitialize(void)
Definition: util-radix4-tree.c:166
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:368
Packet_::flags
uint32_t flags
Definition: decode.h:544
CIDRGet
uint32_t CIDRGet(int cidr)
Definition: util-cidr.c:57
Flow_
Flow data structure.
Definition: flow.h:348
UTHBuildPacketSrcDst
Packet * UTHBuildPacketSrcDst(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst)
UTHBuildPacketSrcDst is a wrapper that build packets specifying IPs and defaulting ports.
Definition: util-unittest-helper.c:406
DetectEngineIPOnlyCtx_::tree_ipv4src
SCRadix4Tree tree_ipv4src
Definition: detect.h:848
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2633
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:242
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:225
SCRadix6TreeFindNetblock
SCRadix6Node * SCRadix6TreeFindNetblock(const SCRadix6Tree *tree, const uint8_t *key, const uint8_t netmask, void **user_data)
Definition: util-radix6-tree.c:167
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:365
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:731
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3437
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:532
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:241
SigMatchData_
Data needed for Match()
Definition: detect.h:365
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:50
SigMatchData_::type
uint16_t type
Definition: detect.h:366
GET_IPV6_DST_ADDR
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:204
util-unittest.h
DetectEngineIPOnlyCtx_::tree_ipv6src
SCRadix6Tree tree_ipv6src
Definition: detect.h:849
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
SCRadix4TreeRelease
void SCRadix4TreeRelease(SCRadix4Tree *tree, const SCRadix4Config *config)
Definition: util-radix4-tree.c:172
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:64
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:127
util-cidr.h
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
decode.h
util-debug.h
SCRadix4TreeFindExactMatch
SCRadix4Node * SCRadix4TreeFindExactMatch(const SCRadix4Tree *tree, const uint8_t *key, void **user_data)
Definition: util-radix4-tree.c:142
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
IPOnlyCIDRItem_::negated
uint8_t negated
Definition: detect.h:338
IPOnlyInit
void IPOnlyInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Setup the IP Only detection engine context.
Definition: detect-engine-iponly.c:915
DetectEngineThreadCtx_
Definition: detect.h:1244
SIG_TYPE_IPONLY
@ SIG_TYPE_IPONLY
Definition: detect.h:66
PKT_IS_FRAGMENT
#define PKT_IS_FRAGMENT
Definition: decode.h:1292
SignatureInitData_::cidr_dst
IPOnlyCIDRItem * cidr_dst
Definition: detect.h:618
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:281
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:231
Packet_::sp
Port sp
Definition: decode.h:508
detect-engine-port.h
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:117
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3095
DetectPort_
Port structure for detection engine.
Definition: detect.h:220
SignatureInitData_::cidr_src
IPOnlyCIDRItem * cidr_src
Definition: detect.h:618
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
IPOnlyPrepare
void IPOnlyPrepare(DetectEngineCtx *de_ctx)
Build the radix trees from the lists of parsed addresses in CIDR format the result should be 4 radix ...
Definition: detect-engine-iponly.c:1140
CIDRFromMask
int CIDRFromMask(uint32_t netmask)
Turn 32 bit mask into CIDR.
Definition: util-cidr.c:35
util-profiling.h
util-rule-vars.h
SigIntId
#define SigIntId
Definition: detect-engine-state.h:38
SCReturn
#define SCReturn
Definition: util-debug.h:283
Signature_::flags
uint32_t flags
Definition: detect.h:669
IPOnlyCIDRItem_::next
struct IPOnlyCIDRItem_ * next
Definition: detect.h:344
AlertQueueAppend
void AlertQueueAppend(DetectEngineThreadCtx *det_ctx, const Signature *s, Packet *p, uint64_t tx_id, uint8_t alert_flags)
Append signature to local packet alert queue for later preprocessing.
Definition: detect-engine-alert.c:353
DetectEngineIPOnlyCtx_::sig_mapping
uint32_t * sig_mapping
Definition: detect.h:857
Packet_
Definition: decode.h:501
detect-engine-build.h
IPOnlyPrint
void IPOnlyPrint(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Print stats of the IP Only engine.
Definition: detect-engine-iponly.c:943
detect-engine-alert.h
IPOnlyAddSignature
void IPOnlyAddSignature(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx, Signature *s)
Add a signature to the lists of Addresses in CIDR format (sorted) this step is necessary to build the...
Definition: detect-engine-iponly.c:1412
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:747
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:297
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1419
SCRadix4AddKeyIPV4Netblock
SCRadix4Node * SCRadix4AddKeyIPV4Netblock(SCRadix4Tree *tree, const SCRadix4Config *config, const uint8_t *key_stream, uint8_t netmask, void *user)
Adds a new IPV4 netblock to the Radix4 tree.
Definition: util-radix4-tree.c:206
Signature_::sp
DetectPort * sp
Definition: detect.h:719
StringParseU8RangeCheck
int StringParseU8RangeCheck(uint8_t *res, int base, size_t len, const char *str, uint8_t min, uint8_t max)
Definition: util-byte.c:474
IPOnlyCIDRListFree
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
This function free a IPOnlyCIDRItem list.
Definition: detect-engine-iponly.c:482
Flow_::flowvar
GenericVar * flowvar
Definition: flow.h:481
Flow_::next
struct Flow_ * next
Definition: flow.h:388
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2185
SigNumArray_::array
uint8_t * array
Definition: detect-engine-iponly.c:555
DetectEngineIPOnlyCtx_::ip_dst
IPOnlyCIDRItem * ip_dst
Definition: detect.h:852
CIDRGetIPv6
void CIDRGetIPv6(int cidr, struct in6_addr *in6)
Creates a cidr ipv6 netblock, based on the cidr netblock value.
Definition: util-cidr.c:82
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:37
DETECT_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:31
Packet_::flow
struct Flow_ * flow
Definition: decode.h:546
SigNumArray_
user data for storing signature id's in the radix tree
Definition: detect-engine-iponly.c:554
SCRadix6Config_
Definition: util-radix6-tree.h:69
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
Signature_::proto
DetectProto proto
Definition: detect.h:687
SCRadix4Config_
Definition: util-radix4-tree.h:71
suricata-common.h
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:243
UTHBuildPacketIPV6SrcDst
Packet * UTHBuildPacketIPV6SrcDst(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst)
UTHBuildPacketSrcDst is a wrapper that build packets specifying IPs and defaulting ports (IPV6)
Definition: util-unittest-helper.c:424
GenericVar_
Definition: util-var.h:53
SCRadix6AddKeyIPV6
SCRadix6Node * SCRadix6AddKeyIPV6(SCRadix6Tree *tree, const SCRadix6Config *config, const uint8_t *key_stream, void *user)
Adds a new IPV6 address to the Radix6 tree.
Definition: util-radix6-tree.c:196
IPOnlyCIDRItem_::ip
uint32_t ip[4]
Definition: detect.h:340
util-classification-config.h
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:514
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
SCRadix4TreeFindBestMatch
SCRadix4Node * SCRadix4TreeFindBestMatch(const SCRadix4Tree *tree, const uint8_t *key, void **user_data)
Definition: util-radix4-tree.c:154
DetectEngineIPOnlyCtx_::sig_mapping_size
uint32_t sig_mapping_size
Definition: detect.h:858
SCRadix6Node_
Structure for the node in the radix tree.
Definition: util-radix6-tree.h:36
UTHGenericTest
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perform a generic check taking care of as maximum common unittest eleme...
Definition: util-unittest-helper.c:571
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
HtpBodyChunk_::next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:123
Signature_::dp
DetectPort * dp
Definition: detect.h:719
str
#define str(s)
Definition: suricata-common.h:308
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:271
Signature_::iid
SigIntId iid
Definition: detect.h:680
head
Flow * head
Definition: flow-hash.h:1
GET_IPV6_SRC_ADDR
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:203
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SignatureIsIPOnly
int SignatureIsIPOnly(DetectEngineCtx *de_ctx, const Signature *s)
Test is a initialized signature is IP only.
Definition: detect-engine-build.c:191
SCNtohl
#define SCNtohl(x)
Definition: suricata-common.h:430
IPOnlyTrackSigNum
SigIntId IPOnlyTrackSigNum(DetectEngineIPOnlyCtx *io_ctx, SigIntId signum)
Definition: detect-engine-iponly.c:929
SCRadix4AddKeyIPV4
SCRadix4Node * SCRadix4AddKeyIPV4(SCRadix4Tree *tree, const SCRadix4Config *config, const uint8_t *key_stream, void *user)
Adds a new IPV4 address to the Radix4 tree.
Definition: util-radix4-tree.c:188
Signature_::id
uint32_t id
Definition: detect.h:713
detect-engine-iponly.h
detect-parse.h
src
uint16_t src
Definition: app-layer-dnp3.h:5
Signature_
Signature container.
Definition: detect.h:668
detect-threshold.h
address
uint8_t address
Definition: decode-ppp.h:0
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2594
SCRadix6TreeInitialize
SCRadix6Tree SCRadix6TreeInitialize(void)
Definition: util-radix6-tree.c:360
IPOnlyMatchPacket
void IPOnlyMatchPacket(ThreadVars *tv, const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectEngineIPOnlyCtx *io_ctx, Packet *p)
Match a packet against the IP Only detection engine contexts.
Definition: detect-engine-iponly.c:1000
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:950
Address_::family
char family
Definition: decode.h:113
Packet_::dst
Address dst
Definition: decode.h:506
SigNumArray
struct SigNumArray_ SigNumArray
user data for storing signature id's in the radix tree
DetectEngineIPOnlyCtx_
IP only rules matching ctx.
Definition: detect.h:846
SCRadix6TreeRelease
void SCRadix6TreeRelease(SCRadix6Tree *tree, const SCRadix6Config *config)
Definition: util-radix6-tree.c:366
IPPROTO_SCTP
#define IPPROTO_SCTP
Definition: decode.h:1230
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:934
GET_IPV4_SRC_ADDR_U32
#define GET_IPV4_SRC_ADDR_U32(p)
Definition: decode.h:196
DetectEngineCtx_::io_ctx
DetectEngineIPOnlyCtx io_ctx
Definition: detect.h:970
GET_IPV4_DST_ADDR_U32
#define GET_IPV4_DST_ADDR_U32(p)
Definition: decode.h:197
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
SigNumArray_::size
uint32_t size
Definition: detect-engine-iponly.c:556
Signature_::msg
char * msg
Definition: detect.h:736
flow.h
Packet_::dp
Port dp
Definition: decode.h:516
SCRuleVarsGetConfVar
const char * SCRuleVarsGetConfVar(const DetectEngineCtx *de_ctx, const char *conf_var_name, SCRuleVarsType conf_vars_type)
Definition: util-rule-vars.c:65
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectEngineCtx_::sig_array_len
uint32_t sig_array_len
Definition: detect.h:951
Signature_::type
enum SignatureType type
Definition: detect.h:671
IPOnlyCIDRItem_::signum
SigIntId signum
Definition: detect.h:341
SIGMATCH_IPONLY_COMPAT
#define SIGMATCH_IPONLY_COMPAT
Definition: detect.h:1651
FLOW_PKT_TOSERVER_FIRST
#define FLOW_PKT_TOSERVER_FIRST
Definition: flow.h:228
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
detect-engine-address.h
Packet_::src
Address src
Definition: decode.h:505
IPOnlyCIDRItem_::family
uint8_t family
Definition: detect.h:334
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:244
DetectPortLookupGroup
DetectPort * DetectPortLookupGroup(DetectPort *dp, uint16_t port)
Function that find the group matching port in a group head.
Definition: detect-engine-port.c:613
detect-engine-threshold.h
SCRadix4TreeFindNetblock
SCRadix4Node * SCRadix4TreeFindNetblock(const SCRadix4Tree *tree, const uint8_t *key, const uint8_t netmask, void **user_data)
Definition: util-radix4-tree.c:148
DetectEngineIPOnlyCtx_::max_idx
uint32_t max_idx
Definition: detect.h:853
DetectProtoContainsProto
int DetectProtoContainsProto(const DetectProto *dp, int proto)
see if a DetectProto contains a certain proto
Definition: detect-engine-proto.c:135
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:456