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