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  temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
716  if (unlikely(temp_rule_var_address == NULL)) {
717  goto error;
718  }
719 
720  snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
721  "[%s]", rule_var_address);
722  } else {
723  temp_rule_var_address = SCStrdup(rule_var_address);
724  if (unlikely(temp_rule_var_address == NULL)) {
725  goto error;
726  }
727  }
728 
729  subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
730  (negate + n_set) % 2);
731  head = IPOnlyCIDRItemInsert(head, subhead);
732 
733  d_set = 0;
734  n_set = 0;
735 
736  SCFree(temp_rule_var_address);
737 
738  } else {
739  address[x - 1] = '\0';
740 
741  subhead = IPOnlyCIDRItemNew();
742  if (subhead == NULL)
743  goto error;
744 
745  if (!((negate + n_set) % 2))
746  subhead->negated = 0;
747  else
748  subhead->negated = 1;
749 
750  if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
751  IPOnlyCIDRListFree(subhead);
752  subhead = NULL;
753  goto error;
754  }
755  head = IPOnlyCIDRItemInsert(head, subhead);
756 
757  n_set = 0;
758  }
759  x = 0;
760  } else if (depth == 0 && s[u] == '$') {
761  d_set = 1;
762  } else if (depth == 0 && u == size - 1) {
763  if (x == sizeof(address)) {
764  address[x - 1] = '\0';
765  } else {
766  address[x] = '\0';
767  }
768  x = 0;
769 
770  if (d_set == 1) {
771  rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
773  if (rule_var_address == NULL)
774  goto error;
775 
776  if ((negate + n_set) % 2) {
777  temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
778  if (unlikely(temp_rule_var_address == NULL)) {
779  goto error;
780  }
781  snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
782  "[%s]", rule_var_address);
783  } else {
784  temp_rule_var_address = SCStrdup(rule_var_address);
785  if (unlikely(temp_rule_var_address == NULL)) {
786  goto error;
787  }
788  }
789  subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
790  (negate + n_set) % 2);
791  head = IPOnlyCIDRItemInsert(head, subhead);
792 
793  d_set = 0;
794 
795  SCFree(temp_rule_var_address);
796  } else {
797  subhead = IPOnlyCIDRItemNew();
798  if (subhead == NULL)
799  goto error;
800 
801  if (!((negate + n_set) % 2))
802  subhead->negated = 0;
803  else
804  subhead->negated = 1;
805 
806  if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
807  IPOnlyCIDRListFree(subhead);
808  subhead = NULL;
809  goto error;
810  }
811  head = IPOnlyCIDRItemInsert(head, subhead);
812  }
813  n_set = 0;
814  }
815  }
816 
817  return head;
818 
819 error:
820  SCLogError("Error parsing addresses");
821  return head;
822 }
823 
824 
825 /**
826  * \brief Parses an address group sent as a character string and updates the
827  * IPOnlyCIDRItem list
828  *
829  * \param gh Pointer to the IPOnlyCIDRItem list
830  * \param str Pointer to the character string containing the address group
831  * that has to be parsed.
832  *
833  * \retval 0 On success.
834  * \retval -1 On failure.
835  */
836 static int IPOnlyCIDRListParse(const DetectEngineCtx *de_ctx, IPOnlyCIDRItem **gh, const char *str)
837 {
838  SCLogDebug("gh %p, str %s", gh, str);
839 
840  if (gh == NULL)
841  goto error;
842 
843  *gh = IPOnlyCIDRListParse2(de_ctx, str, 0);
844  if (*gh == NULL) {
845  SCLogDebug("IPOnlyCIDRListParse2 returned null");
846  goto error;
847  }
848 
849  return 0;
850 
851 error:
852  return -1;
853 }
854 
855 /**
856  * \brief Parses an address group sent as a character string and updates the
857  * IPOnlyCIDRItem lists src and dst of the Signature *s
858  *
859  * \param s Pointer to the signature structure
860  * \param addrstr Pointer to the character string containing the address group
861  * that has to be parsed.
862  * \param flag to indicate if we are parsing the src string or the dst string
863  *
864  * \retval 0 On success.
865  * \retval -1 On failure.
866  */
868  Signature *s, const char *addrstr, char flag)
869 {
870  SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
871 
872  /* pass on to the address(list) parser */
873  if (flag == 0) {
874  if (strcasecmp(addrstr, "any") == 0) {
875  s->flags |= SIG_FLAG_SRC_ANY;
876  if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_src, "[0.0.0.0/0,::/0]") < 0)
877  goto error;
878 
879  } else if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_src, (char *)addrstr) < 0) {
880  goto error;
881  }
882 
883  /* IPOnlyCIDRListPrint(s->CidrSrc); */
884  } else {
885  if (strcasecmp(addrstr, "any") == 0) {
886  s->flags |= SIG_FLAG_DST_ANY;
887  if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_dst, "[0.0.0.0/0,::/0]") < 0)
888  goto error;
889 
890  } else if (IPOnlyCIDRListParse(de_ctx, &s->init_data->cidr_dst, (char *)addrstr) < 0) {
891  goto error;
892  }
893 
894  /* IPOnlyCIDRListPrint(s->CidrDst); */
895  }
896 
897  return 0;
898 
899 error:
900  SCLogError("failed to parse addresses");
901  return -1;
902 }
903 
904 /**
905  * \brief Setup the IP Only detection engine context
906  *
907  * \param de_ctx Pointer to the current detection engine
908  * \param io_ctx Pointer to the current ip only detection engine
909  */
911 {
912  io_ctx->tree_ipv4src = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
913  io_ctx->tree_ipv4dst = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
914  io_ctx->tree_ipv6src = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
915  io_ctx->tree_ipv6dst = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
916 
917  io_ctx->sig_mapping = SCCalloc(1, de_ctx->sig_array_len * sizeof(uint32_t));
918  if (io_ctx->sig_mapping == NULL) {
919  FatalError("Unable to allocate iponly signature tracking area");
920  }
921  io_ctx->sig_mapping_size = 0;
922 }
923 
925 {
926  SigIntId loc = io_ctx->sig_mapping_size;
927  io_ctx->sig_mapping[loc] = signum;
928  io_ctx->sig_mapping_size++;
929  return loc;
930 }
931 
932 /**
933  * \brief Print stats of the IP Only engine
934  *
935  * \param de_ctx Pointer to the current detection engine
936  * \param io_ctx Pointer to the current ip only detection engine
937  */
939 {
940  /* XXX: how are we going to print the stats now? */
941 }
942 
943 /**
944  * \brief Deinitialize the IP Only detection engine context
945  *
946  * \param de_ctx Pointer to the current detection engine
947  * \param io_ctx Pointer to the current ip only detection engine
948  */
950 {
951 
952  if (io_ctx == NULL)
953  return;
954 
955  if (io_ctx->tree_ipv4src != NULL)
957  io_ctx->tree_ipv4src = NULL;
958 
959  if (io_ctx->tree_ipv4dst != NULL)
961  io_ctx->tree_ipv4dst = NULL;
962 
963  if (io_ctx->tree_ipv6src != NULL)
965  io_ctx->tree_ipv6src = NULL;
966 
967  if (io_ctx->tree_ipv6dst != NULL)
969  io_ctx->tree_ipv6dst = NULL;
970 
971  if (io_ctx->sig_mapping != NULL)
972  SCFree(io_ctx->sig_mapping);
973  io_ctx->sig_mapping = NULL;
974 }
975 
976 static inline int IPOnlyMatchCompatSMs(
977  ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Packet *p)
978 {
981  while (smd) {
984  if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) > 0) {
985  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
986  if (smd->is_last)
987  break;
988  smd++;
989  continue;
990  }
991  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
992  return 0;
993  }
994  return 1;
995 }
996 
997 /**
998  * \brief Match a packet against the IP Only detection engine contexts
999  *
1000  * \param de_ctx Pointer to the current detection engine
1001  * \param io_ctx Pointer to the current ip only detection engine
1002  * \param io_ctx Pointer to the current ip only thread detection engine
1003  * \param p Pointer to the Packet to match against
1004  */
1006  DetectEngineThreadCtx *det_ctx, const DetectEngineIPOnlyCtx *io_ctx, Packet *p)
1007 {
1008  SigNumArray *src = NULL;
1009  SigNumArray *dst = NULL;
1010  void *user_data_src = NULL, *user_data_dst = NULL;
1011 
1012  SCEnter();
1013 
1014  if (p->src.family == AF_INET) {
1016  io_ctx->tree_ipv4src, &user_data_src);
1017  } else if (p->src.family == AF_INET6) {
1018  (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p),
1019  io_ctx->tree_ipv6src, &user_data_src);
1020  }
1021 
1022  if (p->dst.family == AF_INET) {
1024  io_ctx->tree_ipv4dst, &user_data_dst);
1025  } else if (p->dst.family == AF_INET6) {
1026  (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p),
1027  io_ctx->tree_ipv6dst, &user_data_dst);
1028  }
1029 
1030  src = user_data_src;
1031  dst = user_data_dst;
1032 
1033  if (src == NULL || dst == NULL)
1034  SCReturn;
1035 
1036  for (uint32_t u = 0; u < src->size; u++) {
1037  SCLogDebug("And %"PRIu8" & %"PRIu8, src->array[u], dst->array[u]);
1038 
1039  uint8_t bitarray = dst->array[u] & src->array[u];
1040 
1041  /* We have to move the logic of the signature checking
1042  * to the main detect loop, in order to apply the
1043  * priority of actions (pass, drop, reject, alert) */
1044  if (!bitarray)
1045  continue;
1046 
1047  /* We have a match :) Let's see from which signum's */
1048 
1049  for (uint8_t i = 0; i < 8; i++, bitarray = bitarray >> 1) {
1050  if (bitarray & 0x01) {
1051  const Signature *s = de_ctx->sig_array[io_ctx->sig_mapping[u * 8 + i]];
1052 
1053  if ((s->proto.flags & DETECT_PROTO_IPV4) && !PacketIsIPv4(p)) {
1054  SCLogDebug("ip version didn't match");
1055  continue;
1056  }
1057  if ((s->proto.flags & DETECT_PROTO_IPV6) && !PacketIsIPv6(p)) {
1058  SCLogDebug("ip version didn't match");
1059  continue;
1060  }
1061  if (DetectProtoContainsProto(&s->proto, PacketGetIPProto(p)) == 0) {
1062  SCLogDebug("proto didn't match");
1063  continue;
1064  }
1065 
1066  /* check the source & dst port in the sig */
1067  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP ||
1068  p->proto == IPPROTO_SCTP) {
1069  if (!(s->flags & SIG_FLAG_DP_ANY)) {
1070  if (p->flags & PKT_IS_FRAGMENT)
1071  continue;
1072 
1073  const DetectPort *dport = DetectPortLookupGroup(s->dp, p->dp);
1074  if (dport == NULL) {
1075  SCLogDebug("dport didn't match.");
1076  continue;
1077  }
1078  }
1079  if (!(s->flags & SIG_FLAG_SP_ANY)) {
1080  if (p->flags & PKT_IS_FRAGMENT)
1081  continue;
1082 
1083  const DetectPort *sport = DetectPortLookupGroup(s->sp, p->sp);
1084  if (sport == NULL) {
1085  SCLogDebug("sport didn't match.");
1086  continue;
1087  }
1088  }
1089  } else if ((s->flags & (SIG_FLAG_DP_ANY | SIG_FLAG_SP_ANY)) !=
1091  SCLogDebug("port-less protocol and sig needs ports");
1092  continue;
1093  }
1094 
1095  if (!IPOnlyMatchCompatSMs(tv, det_ctx, s, p)) {
1096  continue;
1097  }
1098 
1099  SCLogDebug("Signum %" PRIu32 " match (sid: %" PRIu32 ", msg: %s)", u * 8 + i, s->id,
1100  s->msg);
1101 
1102  if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) {
1105 
1106  SCLogDebug("running match functions, sm %p", smd);
1107 
1108  if (smd != NULL) {
1109  while (1) {
1111  (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
1112  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1113  if (smd->is_last)
1114  break;
1115  smd++;
1116  }
1117  }
1118  }
1119  AlertQueueAppend(det_ctx, s, p, 0, 0);
1120  }
1121  }
1122  }
1123  SCReturn;
1124 }
1125 
1126 /**
1127  * \brief Build the radix trees from the lists of parsed addresses in CIDR format
1128  * the result should be 4 radix trees: src/dst ipv4 and src/dst ipv6
1129  * holding SigNumArrays, each of them with a hierarchical relation
1130  * of subnets and hosts
1131  *
1132  * \param de_ctx Pointer to the current detection engine
1133  */
1135 {
1136  SCLogDebug("Preparing Final Lists");
1137 
1138  /*
1139  IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_src);
1140  IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_dst);
1141  */
1142 
1143  IPOnlyCIDRListQSort(&(de_ctx->io_ctx).ip_src);
1144  IPOnlyCIDRListQSort(&(de_ctx->io_ctx).ip_dst);
1145 
1146  IPOnlyCIDRItem *src, *dst;
1147  SCRadixNode *node = NULL;
1148 
1149  /* Prepare Src radix trees */
1150  for (src = (de_ctx->io_ctx).ip_src; src != NULL; ) {
1151  if (src->family == AF_INET) {
1152  /*
1153  SCLogDebug("To IPv4");
1154  SCLogDebug("Item has netmask %"PRIu16" negated: %s; IP: %s; "
1155  "signum: %"PRIu16, src->netmask,
1156  (src->negated) ? "yes":"no",
1157  inet_ntoa( *(struct in_addr*)&src->ip[0]),
1158  src->signum);
1159  */
1160 
1161  void *user_data = NULL;
1162  if (src->netmask == 32)
1163  (void)SCRadixFindKeyIPV4ExactMatch((uint8_t *)&src->ip[0],
1164  (de_ctx->io_ctx).tree_ipv4src,
1165  &user_data);
1166  else
1167  (void)SCRadixFindKeyIPV4Netblock((uint8_t *)&src->ip[0],
1168  (de_ctx->io_ctx).tree_ipv4src,
1169  src->netmask, &user_data);
1170  if (user_data == NULL) {
1171  SCLogDebug("Exact match not found");
1172 
1173  /** Not found, look if there's a subnet of this range with
1174  * bigger netmask */
1175  (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&src->ip[0],
1176  (de_ctx->io_ctx).tree_ipv4src,
1177  &user_data);
1178  if (user_data == NULL) {
1179  SCLogDebug("best match not found");
1180 
1181  /* Not found, insert a new one */
1182  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1183 
1184  /* Update the sig */
1185  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1186 
1187  if (src->negated > 0)
1188  /* Unset it */
1189  sna->array[src->signum / 8] &= ~tmp;
1190  else
1191  /* Set it */
1192  sna->array[src->signum / 8] |= tmp;
1193 
1194  if (src->netmask == 32)
1195  node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1196  (de_ctx->io_ctx).tree_ipv4src, sna);
1197  else
1198  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1199  (de_ctx->io_ctx).tree_ipv4src,
1200  sna, src->netmask);
1201 
1202  if (node == NULL)
1203  SCLogError("Error inserting in the "
1204  "src ipv4 radix tree");
1205  } else {
1206  SCLogDebug("Best match found");
1207 
1208  /* Found, copy the sig num table, add this signum and insert */
1209  SigNumArray *sna = NULL;
1210  sna = SigNumArrayCopy((SigNumArray *) user_data);
1211 
1212  /* Update the sig */
1213  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1214 
1215  if (src->negated > 0)
1216  /* Unset it */
1217  sna->array[src->signum / 8] &= ~tmp;
1218  else
1219  /* Set it */
1220  sna->array[src->signum / 8] |= tmp;
1221 
1222  if (src->netmask == 32)
1223  node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1224  (de_ctx->io_ctx).tree_ipv4src, sna);
1225  else
1226  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1227  (de_ctx->io_ctx).tree_ipv4src, sna,
1228  src->netmask);
1229 
1230  if (node == NULL) {
1231  char tmpstr[64];
1232  PrintInet(src->family, &src->ip[0], tmpstr, sizeof(tmpstr));
1233  SCLogError("Error inserting in the"
1234  " src ipv4 radix tree ip %s netmask %" PRIu8,
1235  tmpstr, src->netmask);
1236  //SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1237  exit(-1);
1238  }
1239  }
1240  } else {
1241  SCLogDebug("Exact match found");
1242 
1243  /* it's already inserted. Update it */
1244  SigNumArray *sna = (SigNumArray *)user_data;
1245 
1246  /* Update the sig */
1247  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1248 
1249  if (src->negated > 0)
1250  /* Unset it */
1251  sna->array[src->signum / 8] &= ~tmp;
1252  else
1253  /* Set it */
1254  sna->array[src->signum / 8] |= tmp;
1255  }
1256  } else if (src->family == AF_INET6) {
1257  SCLogDebug("To IPv6");
1258 
1259  void *user_data = NULL;
1260  if (src->netmask == 128)
1261  (void)SCRadixFindKeyIPV6ExactMatch((uint8_t *)&src->ip[0],
1262  (de_ctx->io_ctx).tree_ipv6src,
1263  &user_data);
1264  else
1265  (void)SCRadixFindKeyIPV6Netblock((uint8_t *)&src->ip[0],
1266  (de_ctx->io_ctx).tree_ipv6src,
1267  src->netmask, &user_data);
1268 
1269  if (user_data == NULL) {
1270  /* Not found, look if there's a subnet of this range with bigger netmask */
1271  (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&src->ip[0],
1272  (de_ctx->io_ctx).tree_ipv6src,
1273  &user_data);
1274 
1275  if (user_data == NULL) {
1276  /* Not found, insert a new one */
1277  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1278 
1279  /* Update the sig */
1280  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1281 
1282  if (src->negated > 0)
1283  /* Unset it */
1284  sna->array[src->signum / 8] &= ~tmp;
1285  else
1286  /* Set it */
1287  sna->array[src->signum / 8] |= tmp;
1288 
1289  if (src->netmask == 128)
1290  node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1291  (de_ctx->io_ctx).tree_ipv6src, sna);
1292  else
1293  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1294  (de_ctx->io_ctx).tree_ipv6src,
1295  sna, src->netmask);
1296  if (node == NULL)
1297  SCLogError("Error inserting in the src "
1298  "ipv6 radix tree");
1299  } else {
1300  /* Found, copy the sig num table, add this signum and insert */
1301  SigNumArray *sna = NULL;
1302  sna = SigNumArrayCopy((SigNumArray *)user_data);
1303 
1304  /* Update the sig */
1305  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1306  if (src->negated > 0)
1307  /* Unset it */
1308  sna->array[src->signum / 8] &= ~tmp;
1309  else
1310  /* Set it */
1311  sna->array[src->signum / 8] |= tmp;
1312 
1313  if (src->netmask == 128)
1314  node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1315  (de_ctx->io_ctx).tree_ipv6src, sna);
1316  else
1317  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1318  (de_ctx->io_ctx).tree_ipv6src,
1319  sna, src->netmask);
1320  if (node == NULL)
1321  SCLogError("Error inserting in the src "
1322  "ipv6 radix tree");
1323  }
1324  } else {
1325  /* it's already inserted. Update it */
1326  SigNumArray *sna = (SigNumArray *)user_data;
1327 
1328  /* Update the sig */
1329  uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1330  if (src->negated > 0)
1331  /* Unset it */
1332  sna->array[src->signum / 8] &= ~tmp;
1333  else
1334  /* Set it */
1335  sna->array[src->signum / 8] |= tmp;
1336  }
1337  }
1338  IPOnlyCIDRItem *tmpaux = src;
1339  src = src->next;
1340  SCFree(tmpaux);
1341  }
1342 
1343  SCLogDebug("dsts:");
1344 
1345  /* Prepare Dst radix trees */
1346  for (dst = (de_ctx->io_ctx).ip_dst; dst != NULL; ) {
1347  if (dst->family == AF_INET) {
1348 
1349  SCLogDebug("To IPv4");
1350  SCLogDebug("Item has netmask %"PRIu8" negated: %s; IP: %s; signum:"
1351  " %"PRIu32"", dst->netmask, (dst->negated)?"yes":"no",
1352  inet_ntoa(*(struct in_addr*)&dst->ip[0]), dst->signum);
1353 
1354  void *user_data = NULL;
1355  if (dst->netmask == 32)
1356  (void) SCRadixFindKeyIPV4ExactMatch((uint8_t *) &dst->ip[0],
1357  (de_ctx->io_ctx).tree_ipv4dst,
1358  &user_data);
1359  else
1360  (void) SCRadixFindKeyIPV4Netblock((uint8_t *) &dst->ip[0],
1361  (de_ctx->io_ctx).tree_ipv4dst,
1362  dst->netmask,
1363  &user_data);
1364 
1365  if (user_data == NULL) {
1366  SCLogDebug("Exact match not found");
1367 
1368  /**
1369  * Not found, look if there's a subnet of this range
1370  * with bigger netmask
1371  */
1372  (void) SCRadixFindKeyIPV4BestMatch((uint8_t *)&dst->ip[0],
1373  (de_ctx->io_ctx).tree_ipv4dst,
1374  &user_data);
1375  if (user_data == NULL) {
1376  SCLogDebug("Best match not found");
1377 
1378  /** Not found, insert a new one */
1379  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1380 
1381  /** Update the sig */
1382  uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1383  if (dst->negated > 0)
1384  /** Unset it */
1385  sna->array[dst->signum / 8] &= ~tmp;
1386  else
1387  /** Set it */
1388  sna->array[dst->signum / 8] |= tmp;
1389 
1390  if (dst->netmask == 32)
1391  node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1392  (de_ctx->io_ctx).tree_ipv4dst, sna);
1393  else
1394  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1395  (de_ctx->io_ctx).tree_ipv4dst,
1396  sna, dst->netmask);
1397 
1398  if (node == NULL)
1399  SCLogError("Error inserting in the dst "
1400  "ipv4 radix tree");
1401  } else {
1402  SCLogDebug("Best match found");
1403 
1404  /* Found, copy the sig num table, add this signum and insert */
1405  SigNumArray *sna = NULL;
1406  sna = SigNumArrayCopy((SigNumArray *) user_data);
1407 
1408  /* Update the sig */
1409  uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1410  if (dst->negated > 0)
1411  /* Unset it */
1412  sna->array[dst->signum / 8] &= ~tmp;
1413  else
1414  /* Set it */
1415  sna->array[dst->signum / 8] |= tmp;
1416 
1417  if (dst->netmask == 32)
1418  node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1419  (de_ctx->io_ctx).tree_ipv4dst, sna);
1420  else
1421  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1422  (de_ctx->io_ctx).tree_ipv4dst,
1423  sna, dst->netmask);
1424 
1425  if (node == NULL)
1426  SCLogError("Error inserting in the dst "
1427  "ipv4 radix tree");
1428  }
1429  } else {
1430  SCLogDebug("Exact match found");
1431 
1432  /* it's already inserted. Update it */
1433  SigNumArray *sna = (SigNumArray *)user_data;
1434 
1435  /* Update the sig */
1436  uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1437  if (dst->negated > 0)
1438  /* Unset it */
1439  sna->array[dst->signum / 8] &= ~tmp;
1440  else
1441  /* Set it */
1442  sna->array[dst->signum / 8] |= tmp;
1443  }
1444  } else if (dst->family == AF_INET6) {
1445  SCLogDebug("To IPv6");
1446 
1447  void *user_data = NULL;
1448  if (dst->netmask == 128)
1449  (void) SCRadixFindKeyIPV6ExactMatch((uint8_t *)&dst->ip[0],
1450  (de_ctx->io_ctx).tree_ipv6dst,
1451  &user_data);
1452  else
1453  (void) SCRadixFindKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1454  (de_ctx->io_ctx).tree_ipv6dst,
1455  dst->netmask, &user_data);
1456 
1457  if (user_data == NULL) {
1458  /** Not found, look if there's a subnet of this range with
1459  * bigger netmask
1460  */
1461  (void) SCRadixFindKeyIPV6BestMatch((uint8_t *)&dst->ip[0],
1462  (de_ctx->io_ctx).tree_ipv6dst,
1463  &user_data);
1464 
1465  if (user_data == NULL) {
1466  /* Not found, insert a new one */
1467  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1468 
1469  /* Update the sig */
1470  uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1471  if (dst->negated > 0)
1472  /* Unset it */
1473  sna->array[dst->signum / 8] &= ~tmp;
1474  else
1475  /* Set it */
1476  sna->array[dst->signum / 8] |= tmp;
1477 
1478  if (dst->netmask == 128)
1479  node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1480  (de_ctx->io_ctx).tree_ipv6dst, sna);
1481  else
1482  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1483  (de_ctx->io_ctx).tree_ipv6dst,
1484  sna, dst->netmask);
1485 
1486  if (node == NULL)
1487  SCLogError("Error inserting in the dst "
1488  "ipv6 radix tree");
1489  } else {
1490  /* Found, copy the sig num table, add this signum and insert */
1491  SigNumArray *sna = NULL;
1492  sna = SigNumArrayCopy((SigNumArray *)user_data);
1493 
1494  /* Update the sig */
1495  uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1496  if (dst->negated > 0)
1497  /* Unset it */
1498  sna->array[dst->signum / 8] &= ~tmp;
1499  else
1500  /* Set it */
1501  sna->array[dst->signum / 8] |= tmp;
1502 
1503  if (dst->netmask == 128)
1504  node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1505  (de_ctx->io_ctx).tree_ipv6dst, sna);
1506  else
1507  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1508  (de_ctx->io_ctx).tree_ipv6dst,
1509  sna, dst->netmask);
1510 
1511  if (node == NULL)
1512  SCLogError("Error inserting in the dst "
1513  "ipv6 radix tree");
1514  }
1515  } else {
1516  /* it's already inserted. Update it */
1517  SigNumArray *sna = (SigNumArray *)user_data;
1518 
1519  /* Update the sig */
1520  uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1521  if (dst->negated > 0)
1522  /* Unset it */
1523  sna->array[dst->signum / 8] &= ~tmp;
1524  else
1525  /* Set it */
1526  sna->array[dst->signum / 8] |= tmp;
1527  }
1528  }
1529  IPOnlyCIDRItem *tmpaux = dst;
1530  dst = dst->next;
1531  SCFree(tmpaux);
1532  }
1533 
1534  /* print all the trees: for debugging it might print too much info
1535  SCLogDebug("Radix tree src ipv4:");
1536  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1537  SCLogDebug("Radix tree src ipv6:");
1538  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6src);
1539  SCLogDebug("__________________");
1540 
1541  SCLogDebug("Radix tree dst ipv4:");
1542  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4dst);
1543  SCLogDebug("Radix tree dst ipv6:");
1544  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6dst);
1545  SCLogDebug("__________________");
1546  */
1547 }
1548 
1549 /**
1550  * \brief Add a signature to the lists of Addresses in CIDR format (sorted)
1551  * this step is necessary to build the radix tree with a hierarchical
1552  * relation between nodes
1553  * \param de_ctx Pointer to the current detection engine context
1554  * \param de_ctx Pointer to the current ip only detection engine contest
1555  * \param s Pointer to the current signature
1556  */
1558  Signature *s)
1559 {
1560  if (!(s->type == SIG_TYPE_IPONLY))
1561  return;
1562 
1563  SigIntId mapped_signum = IPOnlyTrackSigNum(io_ctx, s->num);
1564  SCLogDebug("Adding IPs from rule: %" PRIu32 " (%s) as %" PRIu32 " mapped to %" PRIu32 "\n",
1565  s->id, s->msg, s->num, mapped_signum);
1566  /* Set the internal signum to the list before merging */
1567  IPOnlyCIDRListSetSigNum(s->init_data->cidr_src, mapped_signum);
1568 
1569  IPOnlyCIDRListSetSigNum(s->init_data->cidr_dst, mapped_signum);
1570 
1571  /**
1572  * ipv4 and ipv6 are mixed, but later we will separate them into
1573  * different trees
1574  */
1575  io_ctx->ip_src = IPOnlyCIDRItemInsert(io_ctx->ip_src, s->init_data->cidr_src);
1576  io_ctx->ip_dst = IPOnlyCIDRItemInsert(io_ctx->ip_dst, s->init_data->cidr_dst);
1577 
1578  if (mapped_signum > io_ctx->max_idx)
1579  io_ctx->max_idx = mapped_signum;
1580 
1581  /** no longer ref to this, it's in the table now */
1582  s->init_data->cidr_src = NULL;
1583  s->init_data->cidr_dst = NULL;
1584 }
1585 
1586 #ifdef UNITTESTS
1587 /**
1588  * \test check that we set a Signature as IPOnly because it has no rule
1589  * option appending a SigMatch and no port is fixed
1590  */
1591 
1592 static int IPOnlyTestSig01(void)
1593 {
1595  FAIL_IF(de_ctx == NULL);
1596  de_ctx->flags |= DE_QUIET;
1597 
1598  Signature *s = SigInit(de_ctx,"alert tcp any any -> any any (sid:400001; rev:1;)");
1599  FAIL_IF(s == NULL);
1600 
1601  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1602  SigFree(de_ctx, s);
1604  PASS;
1605 }
1606 
1607 /**
1608  * \test check that we don't set a Signature as IPOnly because it has no rule
1609  * option appending a SigMatch but a port is fixed
1610  */
1611 
1612 static int IPOnlyTestSig02 (void)
1613 {
1615  FAIL_IF(de_ctx == NULL);
1616  de_ctx->flags |= DE_QUIET;
1617 
1618  Signature *s = SigInit(de_ctx,"alert tcp any any -> any 80 (sid:400001; rev:1;)");
1619  FAIL_IF(s == NULL);
1620 
1621  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1622  SigFree(de_ctx, s);
1624  PASS;
1625 }
1626 
1627 /**
1628  * \test check that we set don't set a Signature as IPOnly
1629  * because it has rule options appending a SigMatch like content, and pcre
1630  */
1631 
1632 static int IPOnlyTestSig03 (void)
1633 {
1634  int result = 1;
1636  Signature *s=NULL;
1637 
1639  if (de_ctx == NULL)
1640  goto end;
1641  de_ctx->flags |= DE_QUIET;
1642 
1643  /* combination of pcre and content */
1644  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;)");
1645  if (s == NULL) {
1646  goto end;
1647  }
1648  if(SignatureIsIPOnly(de_ctx, s))
1649  {
1650  printf("got a IPOnly signature (content): ");
1651  result=0;
1652  }
1653  SigFree(de_ctx, s);
1654 
1655  /* content */
1656  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;)");
1657  if (s == NULL) {
1658  goto end;
1659  }
1660  if(SignatureIsIPOnly(de_ctx, s))
1661  {
1662  printf("got a IPOnly signature (content): ");
1663  result=0;
1664  }
1665  SigFree(de_ctx, s);
1666 
1667  /* uricontent */
1668  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;)");
1669  if (s == NULL) {
1670  goto end;
1671  }
1672  if(SignatureIsIPOnly(de_ctx, s))
1673  {
1674  printf("got a IPOnly signature (uricontent): ");
1675  result=0;
1676  }
1677  SigFree(de_ctx, s);
1678 
1679  /* pcre */
1680  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;)");
1681  if (s == NULL) {
1682  goto end;
1683  }
1684  if(SignatureIsIPOnly(de_ctx, s))
1685  {
1686  printf("got a IPOnly signature (pcre): ");
1687  result=0;
1688  }
1689  SigFree(de_ctx, s);
1690 
1691  /* flow */
1692  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;)");
1693  if (s == NULL) {
1694  goto end;
1695  }
1696  if(SignatureIsIPOnly(de_ctx, s))
1697  {
1698  printf("got a IPOnly signature (flow): ");
1699  result=0;
1700  }
1701  SigFree(de_ctx, s);
1702 
1703  /* dsize */
1704  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;)");
1705  if (s == NULL) {
1706  goto end;
1707  }
1708  if(SignatureIsIPOnly(de_ctx, s))
1709  {
1710  printf("got a IPOnly signature (dsize): ");
1711  result=0;
1712  }
1713  SigFree(de_ctx, s);
1714 
1715  /* flowbits */
1716  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;)");
1717  if (s == NULL) {
1718  goto end;
1719  }
1720  if(SignatureIsIPOnly(de_ctx, s))
1721  {
1722  printf("got a IPOnly signature (flowbits): ");
1723  result=0;
1724  }
1725  SigFree(de_ctx, s);
1726 
1727  /* flowvar */
1728  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;)");
1729  if (s == NULL) {
1730  goto end;
1731  }
1732  if(SignatureIsIPOnly(de_ctx, s))
1733  {
1734  printf("got a IPOnly signature (flowvar): ");
1735  result=0;
1736  }
1737  SigFree(de_ctx, s);
1738 
1739  /* pktvar */
1740  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;)");
1741  if (s == NULL) {
1742  goto end;
1743  }
1744  if(SignatureIsIPOnly(de_ctx, s))
1745  {
1746  printf("got a IPOnly signature (pktvar): ");
1747  result=0;
1748  }
1749  SigFree(de_ctx, s);
1750 
1751 end:
1752  if (de_ctx != NULL)
1754  return result;
1755 }
1756 
1757 /**
1758  * \test
1759  */
1760 static int IPOnlyTestSig04 (void)
1761 {
1762  int result = 1;
1763  IPOnlyCIDRItem *head = NULL;
1764 
1765  // Test a linked list of size 0, 1, 2, ..., 5
1766  for (int size = 0; size < 6; size++) {
1767  IPOnlyCIDRItem *new = NULL;
1768 
1769  if (size > 0) {
1770  new = IPOnlyCIDRItemNew();
1771  new->netmask = 10;
1772  new->ip[0] = 3;
1773 
1774  head = IPOnlyCIDRItemInsert(head, new);
1775  }
1776 
1777  if (size > 1) {
1778  new = IPOnlyCIDRItemNew();
1779  new->netmask = 11;
1780 
1781  head = IPOnlyCIDRItemInsert(head, new);
1782  }
1783 
1784  if (size > 2) {
1785  new = IPOnlyCIDRItemNew();
1786  new->netmask = 9;
1787 
1788  head = IPOnlyCIDRItemInsert(head, new);
1789  }
1790 
1791  if (size > 3) {
1792  new = IPOnlyCIDRItemNew();
1793  new->netmask = 10;
1794  new->ip[0] = 1;
1795 
1796  head = IPOnlyCIDRItemInsert(head, new);
1797  }
1798 
1799  if (size > 4) {
1800  new = IPOnlyCIDRItemNew();
1801  new->netmask = 10;
1802  new->ip[0] = 2;
1803 
1804  head = IPOnlyCIDRItemInsert(head, new);
1805  }
1806 
1807  IPOnlyCIDRListPrint(head);
1808 
1809  IPOnlyCIDRListQSort(&head);
1810 
1811  if (size == 0) {
1812  if (head != NULL) {
1813  result = 0;
1814  goto end;
1815  }
1816  }
1817 
1818  /**
1819  * Validate the following list entries for each size
1820  * 1 - 10
1821  * 2 - 10<3> 11
1822  * 3 - 9 10<3> 11
1823  * 4 - 9 10<1> 10<3> 11
1824  * 5 - 9 10<1> 10<2> 10<3> 11
1825  */
1826  new = head;
1827  if (size >= 3) {
1828  if (new->netmask != 9) {
1829  result = 0;
1830  goto end;
1831  }
1832  new = new->next;
1833  }
1834 
1835  if (size >= 4) {
1836  if (new->netmask != 10 || new->ip[0] != 1) {
1837  result = 0;
1838  goto end;
1839  }
1840  new = new->next;
1841  }
1842 
1843  if (size >= 5) {
1844  if (new->netmask != 10 || new->ip[0] != 2) {
1845  result = 0;
1846  goto end;
1847  }
1848  new = new->next;
1849  }
1850 
1851  if (size >= 1) {
1852  if (new->netmask != 10 || new->ip[0] != 3) {
1853  result = 0;
1854  goto end;
1855  }
1856  new = new->next;
1857  }
1858 
1859  if (size >= 2) {
1860  if (new->netmask != 11) {
1861  result = 0;
1862  goto end;
1863  }
1864  new = new->next;
1865  }
1866 
1867  if (new != NULL) {
1868  result = 0;
1869  goto end;
1870  }
1871 
1873  head = NULL;
1874  }
1875 
1876 end:
1877  if (head) {
1879  head = NULL;
1880  }
1881  return result;
1882 }
1883 
1884 /**
1885  * \test Test a set of ip only signatures making use a lot of
1886  * addresses for src and dst (all should match)
1887  */
1888 static int IPOnlyTestSig05(void)
1889 {
1890  int result = 0;
1891  uint8_t *buf = (uint8_t *)"Hi all!";
1892  uint16_t buflen = strlen((char *)buf);
1893 
1894  uint8_t numpkts = 1;
1895  uint8_t numsigs = 7;
1896 
1897  Packet *p[1];
1898 
1899  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1900 
1901  const char *sigs[numsigs];
1902  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1903  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1904  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1905  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1906  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1907  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1908  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;)";
1909 
1910  /* Sid numbers (we could extract them from the sig) */
1911  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1912  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1913 
1914  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1915 
1916  UTHFreePackets(p, numpkts);
1917 
1918  return result;
1919 }
1920 
1921 /**
1922  * \test Test a set of ip only signatures making use a lot of
1923  * addresses for src and dst (none should match)
1924  */
1925 static int IPOnlyTestSig06(void)
1926 {
1927  int result = 0;
1928  uint8_t *buf = (uint8_t *)"Hi all!";
1929  uint16_t buflen = strlen((char *)buf);
1930 
1931  uint8_t numpkts = 1;
1932  uint8_t numsigs = 7;
1933 
1934  Packet *p[1];
1935 
1936  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "80.58.0.33", "195.235.113.3");
1937 
1938  const char *sigs[numsigs];
1939  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1940  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1941  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1942  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1943  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1944  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1945  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;)";
1946 
1947  /* Sid numbers (we could extract them from the sig) */
1948  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1949  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1950 
1951  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1952 
1953  UTHFreePackets(p, numpkts);
1954 
1955  return result;
1956 }
1957 
1958 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
1959  * which is why these unittests fail. When we fix 608, we need to renable
1960  * these sigs */
1961 #if 0
1962 /**
1963  * \test Test a set of ip only signatures making use a lot of
1964  * addresses for src and dst (all should match)
1965  */
1966 static int IPOnlyTestSig07(void)
1967 {
1968  int result = 0;
1969  uint8_t *buf = (uint8_t *)"Hi all!";
1970  uint16_t buflen = strlen((char *)buf);
1971 
1972  uint8_t numpkts = 1;
1973  uint8_t numsigs = 7;
1974 
1975  Packet *p[1];
1976 
1977  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1978 
1979  char *sigs[numsigs];
1980  sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1981  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;)";
1982  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;)";
1983  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;)";
1984  sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1985  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;)";
1986  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" */
1987 
1988  /* Sid numbers (we could extract them from the sig) */
1989  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1990  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1991 
1992  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1993 
1994  UTHFreePackets(p, numpkts);
1995 
1996  return result;
1997 }
1998 #endif
1999 
2000 /**
2001  * \test Test a set of ip only signatures making use a lot of
2002  * addresses for src and dst (none should match)
2003  */
2004 static int IPOnlyTestSig08(void)
2005 {
2006  int result = 0;
2007  uint8_t *buf = (uint8_t *)"Hi all!";
2008  uint16_t buflen = strlen((char *)buf);
2009 
2010  uint8_t numpkts = 1;
2011  uint8_t numsigs = 7;
2012 
2013  Packet *p[1];
2014 
2015  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
2016 
2017  const char *sigs[numsigs];
2018  sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
2019  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;)";
2020  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;)";
2021  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;)";
2022  sigs[4]= "alert tcp any any -> !192.168.1.5 any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2023  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;)";
2024  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" */
2025 
2026  /* Sid numbers (we could extract them from the sig) */
2027  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2028  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
2029 
2030  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2031 
2032  UTHFreePackets(p, numpkts);
2033 
2034  return result;
2035 }
2036 
2037 /**
2038  * \test Test a set of ip only signatures making use a lot of
2039  * addresses for src and dst (all should match)
2040  */
2041 static int IPOnlyTestSig09(void)
2042 {
2043  int result = 0;
2044  uint8_t *buf = (uint8_t *)"Hi all!";
2045  uint16_t buflen = strlen((char *)buf);
2046 
2047  uint8_t numpkts = 1;
2048  uint8_t numsigs = 7;
2049 
2050  Packet *p[1];
2051 
2052  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");
2053 
2054  const char *sigs[numsigs];
2055  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2056  sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2057  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;)";
2058  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;)";
2059  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;)";
2060  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;)";
2061  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;)";
2062 
2063  /* Sid numbers (we could extract them from the sig) */
2064  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2065  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2066 
2067  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2068 
2069  UTHFreePackets(p, numpkts);
2070 
2071  return result;
2072 }
2073 
2074 /**
2075  * \test Test a set of ip only signatures making use a lot of
2076  * addresses for src and dst (none should match)
2077  */
2078 static int IPOnlyTestSig10(void)
2079 {
2080  int result = 0;
2081  uint8_t *buf = (uint8_t *)"Hi all!";
2082  uint16_t buflen = strlen((char *)buf);
2083 
2084  uint8_t numpkts = 1;
2085  uint8_t numsigs = 7;
2086 
2087  Packet *p[1];
2088 
2089  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");
2090 
2091  const char *sigs[numsigs];
2092  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2093  sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2094  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;)";
2095  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;)";
2096  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;)";
2097  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;)";
2098  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;)";
2099 
2100  /* Sid numbers (we could extract them from the sig) */
2101  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2102  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
2103 
2104  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2105 
2106  UTHFreePackets(p, numpkts);
2107 
2108  return result;
2109 }
2110 
2111 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2112  * which is why these unittests fail. When we fix 608, we need to renable
2113  * these sigs */
2114 #if 0
2115 /**
2116  * \test Test a set of ip only signatures making use a lot of
2117  * addresses for src and dst (all should match) with ipv4 and ipv6 mixed
2118  */
2119 static int IPOnlyTestSig11(void)
2120 {
2121  int result = 0;
2122  uint8_t *buf = (uint8_t *)"Hi all!";
2123  uint16_t buflen = strlen((char *)buf);
2124 
2125  uint8_t numpkts = 2;
2126  uint8_t numsigs = 7;
2127 
2128  Packet *p[2];
2129 
2130  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");
2131  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
2132 
2133  char *sigs[numsigs];
2134  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;)";
2135  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;)";
2136  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;)";
2137  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;)";
2138  sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2139  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;)";
2140  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" */
2141 
2142  /* Sid numbers (we could extract them from the sig) */
2143  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2144  uint32_t results[2][7] = {{ 1, 1, 1, 1, 1, 1, 1}, { 1, 1, 1, 1, 1, 1, 1}};
2145 
2146  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2147 
2148  UTHFreePackets(p, numpkts);
2149 
2150  return result;
2151 }
2152 #endif
2153 
2154 /**
2155  * \test Test a set of ip only signatures making use a lot of
2156  * addresses for src and dst (none should match) with ipv4 and ipv6 mixed
2157  */
2158 static int IPOnlyTestSig12(void)
2159 {
2160  int result = 0;
2161  uint8_t *buf = (uint8_t *)"Hi all!";
2162  uint16_t buflen = strlen((char *)buf);
2163 
2164  uint8_t numpkts = 2;
2165  uint8_t numsigs = 7;
2166 
2167  Packet *p[2];
2168 
2169  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");
2170  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"195.85.1.1","80.198.1.5");
2171 
2172  const char *sigs[numsigs];
2173  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;)";
2174  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;)";
2175  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;)";
2176  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;)";
2177  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;)";
2178  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;)";
2179  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" */
2180 
2181  /* Sid numbers (we could extract them from the sig) */
2182  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2183  uint32_t results[2][7] = {{ 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}};
2184 
2185  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2186 
2187  UTHFreePackets(p, numpkts);
2188 
2189  return result;
2190 }
2191 
2192 static int IPOnlyTestSig13(void)
2193 {
2195  FAIL_IF(de_ctx == NULL);
2196  de_ctx->flags |= DE_QUIET;
2197 
2198  Signature *s = SigInit(de_ctx,
2199  "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2200  "flowbits:set,myflow1; sid:1; rev:1;)");
2201  FAIL_IF(s == NULL);
2202 
2203  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
2204  SigFree(de_ctx, s);
2206  PASS;
2207 }
2208 
2209 static int IPOnlyTestSig14(void)
2210 {
2212  FAIL_IF(de_ctx == NULL);
2213  de_ctx->flags |= DE_QUIET;
2214 
2215  Signature *s = SigInit(de_ctx,
2216  "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2217  "flowbits:set,myflow1; flowbits:isset,myflow2; sid:1; rev:1;)");
2218  FAIL_IF(s == NULL);
2219 
2220  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 1);
2221  SigFree(de_ctx, s);
2223  PASS;
2224 }
2225 
2226 static int IPOnlyTestSig15(void)
2227 {
2228  int result = 0;
2229  uint8_t *buf = (uint8_t *)"Hi all!";
2230  uint16_t buflen = strlen((char *)buf);
2231 
2232  uint8_t numpkts = 1;
2233  uint8_t numsigs = 7;
2234 
2235  Packet *p[1];
2236  Flow f;
2237  GenericVar flowvar;
2238  memset(&f, 0, sizeof(Flow));
2239  memset(&flowvar, 0, sizeof(GenericVar));
2240  FLOW_INITIALIZE(&f);
2241 
2242  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
2243 
2244  p[0]->flow = &f;
2245  p[0]->flow->flowvar = &flowvar;
2246  p[0]->flags |= PKT_HAS_FLOW;
2247  p[0]->flowflags |= FLOW_PKT_TOSERVER;
2248 
2249  const char *sigs[numsigs];
2250  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; "
2251  "flowbits:set,one; sid:1;)";
2252  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; "
2253  "flowbits:set,two; sid:2;)";
2254  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; "
2255  "flowbits:set,three; sid:3;)";
2256  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; "
2257  "flowbits:set,four; sid:4;)";
2258  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; "
2259  "flowbits:set,five; sid:5;)";
2260  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; "
2261  "flowbits:set,six; sid:6;)";
2262  sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; "
2263  "flowbits:set,seven; content:\"Hi all\"; sid:7;)";
2264 
2265  /* Sid numbers (we could extract them from the sig) */
2266  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2267  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2268 
2269  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2270 
2271  UTHFreePackets(p, numpkts);
2272 
2273  FLOW_DESTROY(&f);
2274  return result;
2275 }
2276 
2277 /**
2278  * \brief Unittest to show #599. We fail to match if we have negated addresses.
2279  */
2280 static int IPOnlyTestSig16(void)
2281 {
2282  int result = 0;
2283  uint8_t *buf = (uint8_t *)"Hi all!";
2284  uint16_t buflen = strlen((char *)buf);
2285 
2286  uint8_t numpkts = 1;
2287  uint8_t numsigs = 2;
2288 
2289  Packet *p[1];
2290 
2291  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "100.100.0.0", "50.0.0.0");
2292 
2293  const char *sigs[numsigs];
2294  sigs[0]= "alert tcp !100.100.0.1 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2295  sigs[1]= "alert tcp any any -> !50.0.0.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2296 
2297  /* Sid numbers (we could extract them from the sig) */
2298  uint32_t sid[2] = { 1, 2};
2299  uint32_t results[2] = { 1, 1};
2300 
2301  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2302 
2303  UTHFreePackets(p, numpkts);
2304 
2305  return result;
2306 }
2307 
2308 /**
2309  * \brief Unittest to show #611. Ports on portless protocols.
2310  */
2311 static int IPOnlyTestSig17(void)
2312 {
2313  int result = 0;
2314  uint8_t *buf = (uint8_t *)"Hi all!";
2315  uint16_t buflen = strlen((char *)buf);
2316 
2317  uint8_t numpkts = 1;
2318  uint8_t numsigs = 2;
2319 
2320  Packet *p[1];
2321 
2322  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_ICMP, "100.100.0.0", "50.0.0.0");
2323 
2324  const char *sigs[numsigs];
2325  sigs[0]= "alert ip 100.100.0.0 80 -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2326  sigs[1]= "alert ip any any -> 50.0.0.0 123 (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2327 
2328  uint32_t sid[2] = { 1, 2};
2329  uint32_t results[2] = { 0, 0}; /* neither should match */
2330 
2331  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2332 
2333  UTHFreePackets(p, numpkts);
2334 
2335  return result;
2336 }
2337 
2338 /**
2339  * \brief Unittest to show #3568 -- IP address range handling
2340  */
2341 static int IPOnlyTestSig18(void)
2342 {
2343  int result = 0;
2344  uint8_t *buf = (uint8_t *)"Hi all!";
2345  uint16_t buflen = strlen((char *)buf);
2346 
2347  uint8_t numpkts = 4;
2348  uint8_t numsigs = 4;
2349 
2350  Packet *p[4];
2351 
2352  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "10.10.10.1", "50.0.0.1");
2353  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "220.10.10.1", "5.0.0.1");
2354  p[2] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "0.0.0.1", "50.0.0.1");
2355  p[3] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "255.255.255.254", "5.0.0.1");
2356 
2357  const char *sigs[numsigs];
2358  // really many IP addresses
2359  sigs[0]= "alert ip 1.2.3.4-219.6.7.8 any -> any any (sid:1;)";
2360  sigs[1]= "alert ip 51.2.3.4-253.1.2.3 any -> any any (sid:2;)";
2361  sigs[2]= "alert ip 0.0.0.0-50.0.0.2 any -> any any (sid:3;)";
2362  sigs[3]= "alert ip 50.0.0.0-255.255.255.255 any -> any any (sid:4;)";
2363 
2364  uint32_t sid[4] = { 1, 2, 3, 4, };
2365  uint32_t results[4][4] = {
2366  { 1, 0, 1, 0, }, { 0, 1, 0, 1}, { 0, 0, 1, 0 }, { 0, 0, 0, 1}};
2367 
2368  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2369 
2370  UTHFreePackets(p, numpkts);
2371 
2372  FAIL_IF(result != 1);
2373 
2374  PASS;
2375 }
2376 
2377 /** \test build IP-only tree */
2378 static int IPOnlyTestBug5066v1(void)
2379 {
2381  FAIL_IF(de_ctx == NULL);
2382  de_ctx->flags |= DE_QUIET;
2383 
2385  de_ctx, "alert ip [1.2.3.4/24,1.2.3.64/27] any -> any any (sid:1;)");
2386  FAIL_IF_NULL(s);
2387  s = DetectEngineAppendSig(de_ctx, "alert ip [1.2.3.4/24] any -> any any (sid:2;)");
2388  FAIL_IF_NULL(s);
2389 
2391 
2393  PASS;
2394 }
2395 
2396 static int IPOnlyTestBug5066v2(void)
2397 {
2398  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2399  FAIL_IF_NULL(x);
2400 
2401  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.4/24") != 0);
2402 
2403  char ip[16];
2404  PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2405  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2406 
2407  FAIL_IF_NOT(strcmp(ip, "1.2.3.0") == 0);
2408  FAIL_IF_NOT(x->netmask == 24);
2409 
2410  IPOnlyCIDRListFree(x);
2411  PASS;
2412 }
2413 
2414 static int IPOnlyTestBug5066v3(void)
2415 {
2416  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2417  FAIL_IF_NULL(x);
2418 
2419  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.64/26") != 0);
2420 
2421  char ip[16];
2422  PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2423  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2424 
2425  FAIL_IF_NOT(strcmp(ip, "1.2.3.64") == 0);
2426  FAIL_IF_NOT(x->netmask == 26);
2427 
2428  IPOnlyCIDRListFree(x);
2429  PASS;
2430 }
2431 
2432 static int IPOnlyTestBug5066v4(void)
2433 {
2434  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2435  FAIL_IF_NULL(x);
2436 
2437  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "2000::1:1/122") != 0);
2438 
2439  char ip[64];
2440  PrintInet(AF_INET6, (const void *)&x->ip, ip, sizeof(ip));
2441  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2442 
2443  FAIL_IF_NOT(strcmp(ip, "2000:0000:0000:0000:0000:0000:0001:0000") == 0);
2444  FAIL_IF_NOT(x->netmask == 122);
2445 
2446  IPOnlyCIDRListFree(x);
2447  PASS;
2448 }
2449 
2450 static int IPOnlyTestBug5066v5(void)
2451 {
2452  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2453  FAIL_IF_NULL(x);
2454 
2455  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "2000::1:40/122") != 0);
2456 
2457  char ip[64];
2458  PrintInet(AF_INET6, (const void *)&x->ip, ip, sizeof(ip));
2459  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2460 
2461  FAIL_IF_NOT(strcmp(ip, "2000:0000:0000:0000:0000:0000:0001:0040") == 0);
2462  FAIL_IF_NOT(x->netmask == 122);
2463 
2464  IPOnlyCIDRListFree(x);
2465  PASS;
2466 }
2467 
2468 static int IPOnlyTestBug5168v1(void)
2469 {
2470  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2471  FAIL_IF_NULL(x);
2472 
2473  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.64/0.0.0.0") != 0);
2474 
2475  char ip[16];
2476  PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2477  SCLogDebug("ip %s netmask %d", ip, x->netmask);
2478 
2479  FAIL_IF_NOT(strcmp(ip, "0.0.0.0") == 0);
2480  FAIL_IF_NOT(x->netmask == 0);
2481 
2482  IPOnlyCIDRListFree(x);
2483  PASS;
2484 }
2485 
2486 static int IPOnlyTestBug5168v2(void)
2487 {
2488  IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2489  FAIL_IF_NULL(x);
2490  FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "0.0.0.5/0.0.0.5") != -1);
2491  IPOnlyCIDRListFree(x);
2492  PASS;
2493 }
2494 
2495 #endif /* UNITTESTS */
2496 
2498 {
2499 #ifdef UNITTESTS
2500  UtRegisterTest("IPOnlyTestSig01", IPOnlyTestSig01);
2501  UtRegisterTest("IPOnlyTestSig02", IPOnlyTestSig02);
2502  UtRegisterTest("IPOnlyTestSig03", IPOnlyTestSig03);
2503  UtRegisterTest("IPOnlyTestSig04", IPOnlyTestSig04);
2504 
2505  UtRegisterTest("IPOnlyTestSig05", IPOnlyTestSig05);
2506  UtRegisterTest("IPOnlyTestSig06", IPOnlyTestSig06);
2507 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2508  * which is why these unittests fail. When we fix 608, we need to renable
2509  * these sigs */
2510 #if 0
2511  UtRegisterTest("IPOnlyTestSig07", IPOnlyTestSig07, 1);
2512 #endif
2513  UtRegisterTest("IPOnlyTestSig08", IPOnlyTestSig08);
2514 
2515  UtRegisterTest("IPOnlyTestSig09", IPOnlyTestSig09);
2516  UtRegisterTest("IPOnlyTestSig10", IPOnlyTestSig10);
2517 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2518  * which is why these unittests fail. When we fix 608, we need to renable
2519  * these sigs */
2520 #if 0
2521  UtRegisterTest("IPOnlyTestSig11", IPOnlyTestSig11, 1);
2522 #endif
2523  UtRegisterTest("IPOnlyTestSig12", IPOnlyTestSig12);
2524  UtRegisterTest("IPOnlyTestSig13", IPOnlyTestSig13);
2525  UtRegisterTest("IPOnlyTestSig14", IPOnlyTestSig14);
2526  UtRegisterTest("IPOnlyTestSig15", IPOnlyTestSig15);
2527  UtRegisterTest("IPOnlyTestSig16", IPOnlyTestSig16);
2528 
2529  UtRegisterTest("IPOnlyTestSig17", IPOnlyTestSig17);
2530  UtRegisterTest("IPOnlyTestSig18", IPOnlyTestSig18);
2531 
2532  UtRegisterTest("IPOnlyTestBug5066v1", IPOnlyTestBug5066v1);
2533  UtRegisterTest("IPOnlyTestBug5066v2", IPOnlyTestBug5066v2);
2534  UtRegisterTest("IPOnlyTestBug5066v3", IPOnlyTestBug5066v3);
2535  UtRegisterTest("IPOnlyTestBug5066v4", IPOnlyTestBug5066v4);
2536  UtRegisterTest("IPOnlyTestBug5066v5", IPOnlyTestBug5066v5);
2537 
2538  UtRegisterTest("IPOnlyTestBug5168v1", IPOnlyTestBug5168v1);
2539  UtRegisterTest("IPOnlyTestBug5168v2", IPOnlyTestBug5168v2);
2540 #endif
2541 }
IPOnlyRegisterTests
void IPOnlyRegisterTests(void)
Definition: detect-engine-iponly.c:2497
util-byte.h
Packet_::proto
uint8_t proto
Definition: decode.h:495
len
uint8_t len
Definition: app-layer-dnp3.h:2
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:127
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1264
flow-util.h
SCRadixFindKeyIPV6Netblock
SCRadixNode * SCRadixFindKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree, uint8_t netmask, void **user_data_result)
Checks if an IPV6 Netblock address is present in the tree.
Definition: util-radix-tree.c:1594
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:32
detect-engine-siggroup.h
Signature_::num
SigIntId num
Definition: detect.h:613
IPOnlyCIDRItem_::netmask
uint8_t netmask
Definition: detect.h:329
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:1628
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
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
SC_RULE_VARS_ADDRESS_GROUPS
@ SC_RULE_VARS_ADDRESS_GROUPS
Definition: util-rule-vars.h:31
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
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:867
IPOnlyDeinit
void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Deinitialize the IP Only detection engine context.
Definition: detect-engine-iponly.c:949
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
SigMatchData_::is_last
bool is_last
Definition: detect.h:360
DetectEngineIPOnlyCtx_::ip_src
IPOnlyCIDRItem * ip_src
Definition: detect.h:773
IPOnlyCIDRItem_
Definition: detect.h:325
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:361
Packet_::flags
uint32_t flags
Definition: decode.h:510
CIDRGet
uint32_t CIDRGet(int cidr)
Definition: util-cidr.c:57
Flow_
Flow data structure.
Definition: flow.h:356
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:400
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1298
DetectEngineIPOnlyCtx_::tree_ipv6dst
SCRadixTree * tree_ipv6dst
Definition: detect.h:770
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:841
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2611
DetectEngineIPOnlyCtx_::tree_ipv4src
SCRadixTree * tree_ipv4src
Definition: detect.h:769
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:239
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:232
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
SCRadixAddKeyIPV6
SCRadixNode * SCRadixAddKeyIPV6(uint8_t *key_stream, SCRadixTree *tree, void *user)
Adds a new IPV6 address to the Radix tree.
Definition: util-radix-tree.c:876
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:359
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:654
SCRadixFindKeyIPV4BestMatch
SCRadixNode * SCRadixFindKeyIPV4BestMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV4 address is present in the tree under a netblock.
Definition: util-radix-tree.c:1565
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2587
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:504
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:238
SCRadixFindKeyIPV6BestMatch
SCRadixNode * SCRadixFindKeyIPV6BestMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV6 address is present in the tree under a netblock.
Definition: util-radix-tree.c:1623
SigMatchData_
Data needed for Match()
Definition: detect.h:358
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:50
SigMatchData_::type
uint16_t type
Definition: detect.h:359
GET_IPV6_DST_ADDR
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:200
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:64
SCRadixAddKeyIPV4Netblock
SCRadixNode * SCRadixAddKeyIPV4Netblock(uint8_t *key_stream, SCRadixTree *tree, void *user, uint8_t netmask)
Adds a new IPV4 netblock to the Radix tree.
Definition: util-radix-tree.c:939
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:124
util-cidr.h
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
IPOnlyCIDRItem_::negated
uint8_t negated
Definition: detect.h:331
IPOnlyInit
void IPOnlyInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Setup the IP Only detection engine context.
Definition: detect-engine-iponly.c:910
DetectEngineThreadCtx_
Definition: detect.h:1093
SCRadixReleaseRadixTree
void SCRadixReleaseRadixTree(SCRadixTree *tree)
Frees a Radix tree and all its nodes.
Definition: util-radix-tree.c:440
SIG_TYPE_IPONLY
@ SIG_TYPE_IPONLY
Definition: detect.h:64
PKT_IS_FRAGMENT
#define PKT_IS_FRAGMENT
Definition: decode.h:1288
SignatureInitData_::cidr_dst
IPOnlyCIDRItem * cidr_dst
Definition: detect.h:560
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
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:230
Packet_::sp
Port sp
Definition: decode.h:480
detect-engine-port.h
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:114
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2285
DetectPort_
Port structure for detection engine.
Definition: detect.h:217
SCRadixCreateRadixTree
SCRadixTree * SCRadixCreateRadixTree(void(*Free)(void *), void(*PrintData)(void *))
Creates a new Radix tree.
Definition: util-radix-tree.c:405
SignatureInitData_::cidr_src
IPOnlyCIDRItem * cidr_src
Definition: detect.h:560
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
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:1134
CIDRFromMask
int CIDRFromMask(uint32_t netmask)
Turn 32 bit mask into CIDR.
Definition: util-cidr.c:35
util-profiling.h
util-rule-vars.h
SCReturn
#define SCReturn
Definition: util-debug.h:273
Signature_::flags
uint32_t flags
Definition: detect.h:602
IPOnlyCIDRItem_::next
struct IPOnlyCIDRItem_ * next
Definition: detect.h:337
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:283
DetectEngineIPOnlyCtx_::sig_mapping
uint32_t * sig_mapping
Definition: detect.h:778
Packet_
Definition: decode.h:473
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:938
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:1557
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:670
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1272
SCRadixFindKeyIPV6ExactMatch
SCRadixNode * SCRadixFindKeyIPV6ExactMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV6 address is present in the tree.
Definition: util-radix-tree.c:1611
Signature_::sp
DetectPort * sp
Definition: detect.h:642
StringParseU8RangeCheck
int StringParseU8RangeCheck(uint8_t *res, int base, size_t len, const char *str, uint8_t min, uint8_t max)
Definition: util-byte.c:462
IPOnlyCIDRListFree
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
This function free a IPOnlyCIDRItem list.
Definition: detect-engine-iponly.c:482
Flow_::flowvar
GenericVar * flowvar
Definition: flow.h:491
Flow_::next
struct Flow_ * next
Definition: flow.h:401
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2144
SigNumArray_::array
uint8_t * array
Definition: detect-engine-iponly.c:555
DetectEngineIPOnlyCtx_::ip_dst
IPOnlyCIDRItem * ip_dst
Definition: detect.h:773
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:512
SigNumArray_
user data for storing signature id's in the radix tree
Definition: detect-engine-iponly.c:554
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:620
suricata-common.h
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:240
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:418
SCRadixFindKeyIPV4Netblock
SCRadixNode * SCRadixFindKeyIPV4Netblock(uint8_t *key_stream, SCRadixTree *tree, uint8_t netmask, void **user_data_result)
Checks if an IPV4 Netblock address is present in the tree.
Definition: util-radix-tree.c:1577
GenericVar_
Definition: util-var.h:50
SCRadixAddKeyIPV6Netblock
SCRadixNode * SCRadixAddKeyIPV6Netblock(uint8_t *key_stream, SCRadixTree *tree, void *user, uint8_t netmask)
Adds a new IPV6 netblock to the Radix tree.
Definition: util-radix-tree.c:962
DetectEngineIPOnlyCtx_::tree_ipv4dst
SCRadixTree * tree_ipv4dst
Definition: detect.h:769
IPOnlyCIDRItem_::ip
uint32_t ip[4]
Definition: detect.h:333
util-classification-config.h
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:502
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
DetectEngineIPOnlyCtx_::sig_mapping_size
uint32_t sig_mapping_size
Definition: detect.h:779
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:565
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
HtpBodyChunk_::next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:178
Signature_::dp
DetectPort * dp
Definition: detect.h:642
str
#define str(s)
Definition: suricata-common.h:291
SCRadixNode_
Structure for the node in the radix tree.
Definition: util-radix-tree.h:61
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
head
Flow * head
Definition: flow-hash.h:1
GET_IPV6_SRC_ADDR
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:199
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:209
SCNtohl
#define SCNtohl(x)
Definition: suricata-common.h:413
IPOnlyTrackSigNum
SigIntId IPOnlyTrackSigNum(DetectEngineIPOnlyCtx *io_ctx, SigIntId signum)
Definition: detect-engine-iponly.c:924
Signature_::id
uint32_t id
Definition: detect.h:636
detect-engine-iponly.h
detect-parse.h
src
uint16_t src
Definition: app-layer-dnp3.h:5
Signature_
Signature container.
Definition: detect.h:601
detect-threshold.h
address
uint8_t address
Definition: decode-ppp.h:0
SCRadixFindKeyIPV4ExactMatch
SCRadixNode * SCRadixFindKeyIPV4ExactMatch(uint8_t *key_stream, SCRadixTree *tree, void **user_data_result)
Checks if an IPV4 address is present in the tree.
Definition: util-radix-tree.c:1553
SCRadixAddKeyIPV4
SCRadixNode * SCRadixAddKeyIPV4(uint8_t *key_stream, SCRadixTree *tree, void *user)
Adds a new IPV4 address to the Radix tree.
Definition: util-radix-tree.c:857
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2572
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:1005
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:858
Address_::family
char family
Definition: decode.h:109
Packet_::dst
Address dst
Definition: decode.h:478
SigNumArray
struct SigNumArray_ SigNumArray
user data for storing signature id's in the radix tree
DetectEngineIPOnlyCtx_
IP only rules matching ctx.
Definition: detect.h:767
IPPROTO_SCTP
#define IPPROTO_SCTP
Definition: decode.h:1190
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:843
GET_IPV4_SRC_ADDR_U32
#define GET_IPV4_SRC_ADDR_U32(p)
Definition: decode.h:192
DetectEngineCtx_::io_ctx
DetectEngineIPOnlyCtx io_ctx
Definition: detect.h:882
GET_IPV4_DST_ADDR_U32
#define GET_IPV4_DST_ADDR_U32(p)
Definition: decode.h:193
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:659
flow.h
SigIntId
#define SigIntId
Definition: suricata-common.h:315
Packet_::dp
Port dp
Definition: decode.h:488
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:859
DetectEngineIPOnlyCtx_::tree_ipv6src
SCRadixTree * tree_ipv6src
Definition: detect.h:770
Signature_::type
enum SignatureType type
Definition: detect.h:604
IPOnlyCIDRItem_::signum
SigIntId signum
Definition: detect.h:334
SIGMATCH_IPONLY_COMPAT
#define SIGMATCH_IPONLY_COMPAT
Definition: detect.h:1490
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:121
detect-engine-address.h
Packet_::src
Address src
Definition: decode.h:477
IPOnlyCIDRItem_::family
uint8_t family
Definition: detect.h:327
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:241
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
DetectEngineIPOnlyCtx_::max_idx
uint32_t max_idx
Definition: detect.h:774
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:450