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