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