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