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  "address parsing 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 %"PRIu8" negated:"
463  " %s; IP: %s; signum: %"PRIu32, 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("IPOnlyCIDRListParse2 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(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  SCEnter();
988 
989  if (p->src.family == AF_INET) {
991  io_ctx->tree_ipv4src, &user_data_src);
992  } else if (p->src.family == AF_INET6) {
993  (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p),
994  io_ctx->tree_ipv6src, &user_data_src);
995  }
996 
997  if (p->dst.family == AF_INET) {
999  io_ctx->tree_ipv4dst, &user_data_dst);
1000  } else if (p->dst.family == AF_INET6) {
1001  (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p),
1002  io_ctx->tree_ipv6dst, &user_data_dst);
1003  }
1004 
1005  src = user_data_src;
1006  dst = user_data_dst;
1007 
1008  if (src == NULL || dst == NULL)
1009  SCReturn;
1010 
1011  uint32_t u;
1012  for (u = 0; u < src->size; u++) {
1013  SCLogDebug("And %"PRIu8" & %"PRIu8, src->array[u], dst->array[u]);
1014 
1015  /* The final results will be at io_tctx */
1016  io_tctx->sig_match_array[u] = dst->array[u] & src->array[u];
1017 
1018  /* We have to move the logic of the signature checking
1019  * to the main detect loop, in order to apply the
1020  * priority of actions (pass, drop, reject, alert) */
1021  if (io_tctx->sig_match_array[u] != 0) {
1022  /* We have a match :) Let's see from which signum's */
1023  uint8_t bitarray = io_tctx->sig_match_array[u];
1024  uint8_t i = 0;
1025 
1026  for (; i < 8; i++, bitarray = bitarray >> 1) {
1027  if (bitarray & 0x01) {
1028  Signature *s = de_ctx->sig_array[u * 8 + i];
1029 
1030  if ((s->proto.flags & DETECT_PROTO_IPV4) && !PKT_IS_IPV4(p)) {
1031  SCLogDebug("ip version didn't match");
1032  continue;
1033  }
1034  if ((s->proto.flags & DETECT_PROTO_IPV6) && !PKT_IS_IPV6(p)) {
1035  SCLogDebug("ip version didn't match");
1036  continue;
1037  }
1038 
1039  if (DetectProtoContainsProto(&s->proto, IP_GET_IPPROTO(p)) == 0) {
1040  SCLogDebug("proto didn't match");
1041  continue;
1042  }
1043 
1044  /* check the source & dst port in the sig */
1045  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
1046  if (!(s->flags & SIG_FLAG_DP_ANY)) {
1047  if (p->flags & PKT_IS_FRAGMENT)
1048  continue;
1049 
1050  DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
1051  if (dport == NULL) {
1052  SCLogDebug("dport didn't match.");
1053  continue;
1054  }
1055  }
1056  if (!(s->flags & SIG_FLAG_SP_ANY)) {
1057  if (p->flags & PKT_IS_FRAGMENT)
1058  continue;
1059 
1060  DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
1061  if (sport == NULL) {
1062  SCLogDebug("sport didn't match.");
1063  continue;
1064  }
1065  }
1067  SCLogDebug("port-less protocol and sig needs ports");
1068  continue;
1069  }
1070 
1071  if (!IPOnlyMatchCompatSMs(tv, det_ctx, s, p)) {
1072  continue;
1073  }
1074 
1075  SCLogDebug("Signum %"PRIu32" match (sid: %"PRIu32", msg: %s)",
1076  u * 8 + i, s->id, s->msg);
1077 
1078  if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) {
1081 
1082  SCLogDebug("running match functions, sm %p", smd);
1083 
1084  if (smd != NULL) {
1085  while (1) {
1087  (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
1088  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1089  if (smd->is_last)
1090  break;
1091  smd++;
1092  }
1093  }
1094  }
1095  if (!(s->flags & SIG_FLAG_NOALERT)) {
1096  if (s->action & ACTION_DROP)
1098  else
1099  PacketAlertAppend(det_ctx, s, p, 0, 0);
1100  } else {
1101  /* apply actions for noalert/rule suppressed as well */
1102  DetectSignatureApplyActions(p, s, 0);
1103  }
1104  }
1105  }
1106  }
1107  }
1108  SCReturn;
1109 }
1110 
1111 /**
1112  * \brief Build the radix trees from the lists of parsed adresses in CIDR format
1113  * the result should be 4 radix trees: src/dst ipv4 and src/dst ipv6
1114  * holding SigNumArrays, each of them with a hierarchical relation
1115  * of subnets and hosts
1116  *
1117  * \param de_ctx Pointer to the current detection engine
1118  */
1120 {
1121  SCLogDebug("Preparing Final Lists");
1122 
1123  /*
1124  IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_src);
1125  IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_dst);
1126  */
1127 
1128  IPOnlyCIDRItem *src, *dst;
1129  SCRadixNode *node = NULL;
1130 
1131  /* Prepare Src radix trees */
1132  for (src = (de_ctx->io_ctx).ip_src; src != NULL; ) {
1133  if (src->family == AF_INET) {
1134  /*
1135  SCLogDebug("To IPv4");
1136  SCLogDebug("Item has netmask %"PRIu16" negated: %s; IP: %s; "
1137  "signum: %"PRIu16, src->netmask,
1138  (src->negated) ? "yes":"no",
1139  inet_ntoa( *(struct in_addr*)&src->ip[0]),
1140  src->signum);
1141  */
1142 
1143  void *user_data = NULL;
1144  if (src->netmask == 32)
1145  (void)SCRadixFindKeyIPV4ExactMatch((uint8_t *)&src->ip[0],
1146  (de_ctx->io_ctx).tree_ipv4src,
1147  &user_data);
1148  else
1149  (void)SCRadixFindKeyIPV4Netblock((uint8_t *)&src->ip[0],
1150  (de_ctx->io_ctx).tree_ipv4src,
1151  src->netmask, &user_data);
1152  if (user_data == NULL) {
1153  SCLogDebug("Exact match not found");
1154 
1155  /** Not found, look if there's a subnet of this range with
1156  * bigger netmask */
1157  (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&src->ip[0],
1158  (de_ctx->io_ctx).tree_ipv4src,
1159  &user_data);
1160  if (user_data == NULL) {
1161  SCLogDebug("best match not found");
1162 
1163  /* Not found, insert a new one */
1164  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1165 
1166  /* Update the sig */
1167  uint8_t tmp = 1 << (src->signum % 8);
1168 
1169  if (src->negated > 0)
1170  /* Unset it */
1171  sna->array[src->signum / 8] &= ~tmp;
1172  else
1173  /* Set it */
1174  sna->array[src->signum / 8] |= tmp;
1175 
1176  if (src->netmask == 32)
1177  node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1178  (de_ctx->io_ctx).tree_ipv4src, sna);
1179  else
1180  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1181  (de_ctx->io_ctx).tree_ipv4src,
1182  sna, src->netmask);
1183 
1184  if (node == NULL)
1185  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the "
1186  "src ipv4 radix tree");
1187  } else {
1188  SCLogDebug("Best match found");
1189 
1190  /* Found, copy the sig num table, add this signum and insert */
1191  SigNumArray *sna = NULL;
1192  sna = SigNumArrayCopy((SigNumArray *) user_data);
1193 
1194  /* Update the sig */
1195  uint8_t tmp = 1 << (src->signum % 8);
1196 
1197  if (src->negated > 0)
1198  /* Unset it */
1199  sna->array[src->signum / 8] &= ~tmp;
1200  else
1201  /* Set it */
1202  sna->array[src->signum / 8] |= tmp;
1203 
1204  if (src->netmask == 32)
1205  node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1206  (de_ctx->io_ctx).tree_ipv4src, sna);
1207  else
1208  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1209  (de_ctx->io_ctx).tree_ipv4src, sna,
1210  src->netmask);
1211 
1212  if (node == NULL) {
1213  char tmpstr[64];
1214  PrintInet(src->family, &src->ip[0], tmpstr, sizeof(tmpstr));
1215  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the"
1216  " src ipv4 radix tree ip %s netmask %"PRIu8, tmpstr, src->netmask);
1217  //SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1218  exit(-1);
1219  }
1220  }
1221  } else {
1222  SCLogDebug("Exact match found");
1223 
1224  /* it's already inserted. Update it */
1225  SigNumArray *sna = (SigNumArray *)user_data;
1226 
1227  /* Update the sig */
1228  uint8_t tmp = 1 << (src->signum % 8);
1229 
1230  if (src->negated > 0)
1231  /* Unset it */
1232  sna->array[src->signum / 8] &= ~tmp;
1233  else
1234  /* Set it */
1235  sna->array[src->signum / 8] |= tmp;
1236  }
1237  } else if (src->family == AF_INET6) {
1238  SCLogDebug("To IPv6");
1239 
1240  void *user_data = NULL;
1241  if (src->netmask == 128)
1242  (void)SCRadixFindKeyIPV6ExactMatch((uint8_t *)&src->ip[0],
1243  (de_ctx->io_ctx).tree_ipv6src,
1244  &user_data);
1245  else
1246  (void)SCRadixFindKeyIPV6Netblock((uint8_t *)&src->ip[0],
1247  (de_ctx->io_ctx).tree_ipv6src,
1248  src->netmask, &user_data);
1249 
1250  if (user_data == NULL) {
1251  /* Not found, look if there's a subnet of this range with bigger netmask */
1252  (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&src->ip[0],
1253  (de_ctx->io_ctx).tree_ipv6src,
1254  &user_data);
1255 
1256  if (user_data == NULL) {
1257  /* Not found, insert a new one */
1258  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1259 
1260  /* Update the sig */
1261  uint8_t tmp = 1 << (src->signum % 8);
1262 
1263  if (src->negated > 0)
1264  /* Unset it */
1265  sna->array[src->signum / 8] &= ~tmp;
1266  else
1267  /* Set it */
1268  sna->array[src->signum / 8] |= tmp;
1269 
1270  if (src->netmask == 128)
1271  node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1272  (de_ctx->io_ctx).tree_ipv6src, sna);
1273  else
1274  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1275  (de_ctx->io_ctx).tree_ipv6src,
1276  sna, src->netmask);
1277  if (node == NULL)
1278  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the src "
1279  "ipv6 radix tree");
1280  } else {
1281  /* Found, copy the sig num table, add this signum and insert */
1282  SigNumArray *sna = NULL;
1283  sna = SigNumArrayCopy((SigNumArray *)user_data);
1284 
1285  /* Update the sig */
1286  uint8_t tmp = 1 << (src->signum % 8);
1287  if (src->negated > 0)
1288  /* Unset it */
1289  sna->array[src->signum / 8] &= ~tmp;
1290  else
1291  /* Set it */
1292  sna->array[src->signum / 8] |= tmp;
1293 
1294  if (src->netmask == 128)
1295  node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1296  (de_ctx->io_ctx).tree_ipv6src, sna);
1297  else
1298  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1299  (de_ctx->io_ctx).tree_ipv6src,
1300  sna, src->netmask);
1301  if (node == NULL)
1302  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the src "
1303  "ipv6 radix tree");
1304  }
1305  } else {
1306  /* it's already inserted. Update it */
1307  SigNumArray *sna = (SigNumArray *)user_data;
1308 
1309  /* Update the sig */
1310  uint8_t tmp = 1 << (src->signum % 8);
1311  if (src->negated > 0)
1312  /* Unset it */
1313  sna->array[src->signum / 8] &= ~tmp;
1314  else
1315  /* Set it */
1316  sna->array[src->signum / 8] |= tmp;
1317  }
1318  }
1319  IPOnlyCIDRItem *tmpaux = src;
1320  src = src->next;
1321  SCFree(tmpaux);
1322  }
1323 
1324  SCLogDebug("dsts:");
1325 
1326  /* Prepare Dst radix trees */
1327  for (dst = (de_ctx->io_ctx).ip_dst; dst != NULL; ) {
1328  if (dst->family == AF_INET) {
1329 
1330  SCLogDebug("To IPv4");
1331  SCLogDebug("Item has netmask %"PRIu8" negated: %s; IP: %s; signum:"
1332  " %"PRIu32"", dst->netmask, (dst->negated)?"yes":"no",
1333  inet_ntoa(*(struct in_addr*)&dst->ip[0]), dst->signum);
1334 
1335  void *user_data = NULL;
1336  if (dst->netmask == 32)
1337  (void) SCRadixFindKeyIPV4ExactMatch((uint8_t *) &dst->ip[0],
1338  (de_ctx->io_ctx).tree_ipv4dst,
1339  &user_data);
1340  else
1341  (void) SCRadixFindKeyIPV4Netblock((uint8_t *) &dst->ip[0],
1342  (de_ctx->io_ctx).tree_ipv4dst,
1343  dst->netmask,
1344  &user_data);
1345 
1346  if (user_data == NULL) {
1347  SCLogDebug("Exact match not found");
1348 
1349  /**
1350  * Not found, look if there's a subnet of this range
1351  * with bigger netmask
1352  */
1353  (void) SCRadixFindKeyIPV4BestMatch((uint8_t *)&dst->ip[0],
1354  (de_ctx->io_ctx).tree_ipv4dst,
1355  &user_data);
1356  if (user_data == NULL) {
1357  SCLogDebug("Best match not found");
1358 
1359  /** Not found, insert a new one */
1360  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1361 
1362  /** Update the sig */
1363  uint8_t tmp = 1 << (dst->signum % 8);
1364  if (dst->negated > 0)
1365  /** Unset it */
1366  sna->array[dst->signum / 8] &= ~tmp;
1367  else
1368  /** Set it */
1369  sna->array[dst->signum / 8] |= tmp;
1370 
1371  if (dst->netmask == 32)
1372  node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1373  (de_ctx->io_ctx).tree_ipv4dst, sna);
1374  else
1375  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1376  (de_ctx->io_ctx).tree_ipv4dst,
1377  sna, dst->netmask);
1378 
1379  if (node == NULL)
1380  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1381  "ipv4 radix tree");
1382  } else {
1383  SCLogDebug("Best match found");
1384 
1385  /* Found, copy the sig num table, add this signum and insert */
1386  SigNumArray *sna = NULL;
1387  sna = SigNumArrayCopy((SigNumArray *) user_data);
1388 
1389  /* Update the sig */
1390  uint8_t tmp = 1 << (dst->signum % 8);
1391  if (dst->negated > 0)
1392  /* Unset it */
1393  sna->array[dst->signum / 8] &= ~tmp;
1394  else
1395  /* Set it */
1396  sna->array[dst->signum / 8] |= tmp;
1397 
1398  if (dst->netmask == 32)
1399  node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1400  (de_ctx->io_ctx).tree_ipv4dst, sna);
1401  else
1402  node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1403  (de_ctx->io_ctx).tree_ipv4dst,
1404  sna, dst->netmask);
1405 
1406  if (node == NULL)
1407  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1408  "ipv4 radix tree");
1409  }
1410  } else {
1411  SCLogDebug("Exact match found");
1412 
1413  /* it's already inserted. Update it */
1414  SigNumArray *sna = (SigNumArray *)user_data;
1415 
1416  /* Update the sig */
1417  uint8_t tmp = 1 << (dst->signum % 8);
1418  if (dst->negated > 0)
1419  /* Unset it */
1420  sna->array[dst->signum / 8] &= ~tmp;
1421  else
1422  /* Set it */
1423  sna->array[dst->signum / 8] |= tmp;
1424  }
1425  } else if (dst->family == AF_INET6) {
1426  SCLogDebug("To IPv6");
1427 
1428  void *user_data = NULL;
1429  if (dst->netmask == 128)
1430  (void) SCRadixFindKeyIPV6ExactMatch((uint8_t *)&dst->ip[0],
1431  (de_ctx->io_ctx).tree_ipv6dst,
1432  &user_data);
1433  else
1434  (void) SCRadixFindKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1435  (de_ctx->io_ctx).tree_ipv6dst,
1436  dst->netmask, &user_data);
1437 
1438  if (user_data == NULL) {
1439  /** Not found, look if there's a subnet of this range with
1440  * bigger netmask
1441  */
1442  (void) SCRadixFindKeyIPV6BestMatch((uint8_t *)&dst->ip[0],
1443  (de_ctx->io_ctx).tree_ipv6dst,
1444  &user_data);
1445 
1446  if (user_data == NULL) {
1447  /* Not found, insert a new one */
1448  SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1449 
1450  /* Update the sig */
1451  uint8_t tmp = 1 << (dst->signum % 8);
1452  if (dst->negated > 0)
1453  /* Unset it */
1454  sna->array[dst->signum / 8] &= ~tmp;
1455  else
1456  /* Set it */
1457  sna->array[dst->signum / 8] |= tmp;
1458 
1459  if (dst->netmask == 128)
1460  node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1461  (de_ctx->io_ctx).tree_ipv6dst, sna);
1462  else
1463  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1464  (de_ctx->io_ctx).tree_ipv6dst,
1465  sna, dst->netmask);
1466 
1467  if (node == NULL)
1468  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1469  "ipv6 radix tree");
1470  } else {
1471  /* Found, copy the sig num table, add this signum and insert */
1472  SigNumArray *sna = NULL;
1473  sna = SigNumArrayCopy((SigNumArray *)user_data);
1474 
1475  /* Update the sig */
1476  uint8_t tmp = 1 << (dst->signum % 8);
1477  if (dst->negated > 0)
1478  /* Unset it */
1479  sna->array[dst->signum / 8] &= ~tmp;
1480  else
1481  /* Set it */
1482  sna->array[dst->signum / 8] |= tmp;
1483 
1484  if (dst->netmask == 128)
1485  node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1486  (de_ctx->io_ctx).tree_ipv6dst, sna);
1487  else
1488  node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1489  (de_ctx->io_ctx).tree_ipv6dst,
1490  sna, dst->netmask);
1491 
1492  if (node == NULL)
1493  SCLogError(SC_ERR_IPONLY_RADIX, "Error inserting in the dst "
1494  "ipv6 radix tree");
1495  }
1496  } else {
1497  /* it's already inserted. Update it */
1498  SigNumArray *sna = (SigNumArray *)user_data;
1499 
1500  /* Update the sig */
1501  uint8_t tmp = 1 << (dst->signum % 8);
1502  if (dst->negated > 0)
1503  /* Unset it */
1504  sna->array[dst->signum / 8] &= ~tmp;
1505  else
1506  /* Set it */
1507  sna->array[dst->signum / 8] |= tmp;
1508  }
1509  }
1510  IPOnlyCIDRItem *tmpaux = dst;
1511  dst = dst->next;
1512  SCFree(tmpaux);
1513  }
1514 
1515  /* print all the trees: for debuggin it might print too much info
1516  SCLogDebug("Radix tree src ipv4:");
1517  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1518  SCLogDebug("Radix tree src ipv6:");
1519  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6src);
1520  SCLogDebug("__________________");
1521 
1522  SCLogDebug("Radix tree dst ipv4:");
1523  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4dst);
1524  SCLogDebug("Radix tree dst ipv6:");
1525  SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6dst);
1526  SCLogDebug("__________________");
1527  */
1528 }
1529 
1530 /**
1531  * \brief Add a signature to the lists of Adrresses in CIDR format (sorted)
1532  * this step is necesary to build the radix tree with a hierarchical
1533  * relation between nodes
1534  * \param de_ctx Pointer to the current detection engine context
1535  * \param de_ctx Pointer to the current ip only detection engine contest
1536  * \param s Pointer to the current signature
1537  */
1539  Signature *s)
1540 {
1541  if (!(s->flags & SIG_FLAG_IPONLY))
1542  return;
1543 
1544  /* Set the internal signum to the list before merging */
1545  IPOnlyCIDRListSetSigNum(s->CidrSrc, s->num);
1546 
1547  IPOnlyCIDRListSetSigNum(s->CidrDst, s->num);
1548 
1549  /**
1550  * ipv4 and ipv6 are mixed, but later we will separate them into
1551  * different trees
1552  */
1553  io_ctx->ip_src = IPOnlyCIDRItemInsert(io_ctx->ip_src, s->CidrSrc);
1554  io_ctx->ip_dst = IPOnlyCIDRItemInsert(io_ctx->ip_dst, s->CidrDst);
1555 
1556  if (s->num > io_ctx->max_idx)
1557  io_ctx->max_idx = s->num;
1558 
1559  /* enable the sig in the bitarray */
1560  io_ctx->sig_init_array[(s->num/8)] |= 1 << (s->num % 8);
1561 
1562  /** no longer ref to this, it's in the table now */
1563  s->CidrSrc = NULL;
1564  s->CidrDst = NULL;
1565 }
1566 
1567 #ifdef UNITTESTS
1568 /**
1569  * \test check that we set a Signature as IPOnly because it has no rule
1570  * option appending a SigMatch and no port is fixed
1571  */
1572 
1573 static int IPOnlyTestSig01(void)
1574 {
1576  FAIL_IF(de_ctx == NULL);
1577  de_ctx->flags |= DE_QUIET;
1578 
1579  Signature *s = SigInit(de_ctx,"alert tcp any any -> any any (sid:400001; rev:1;)");
1580  FAIL_IF(s == NULL);
1581 
1582  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1583  SigFree(s);
1584  DetectEngineCtxFree(de_ctx);
1585  PASS;
1586 }
1587 
1588 /**
1589  * \test check that we dont set a Signature as IPOnly because it has no rule
1590  * option appending a SigMatch but a port is fixed
1591  */
1592 
1593 static int IPOnlyTestSig02 (void)
1594 {
1596  FAIL_IF(de_ctx == NULL);
1597  de_ctx->flags |= DE_QUIET;
1598 
1599  Signature *s = SigInit(de_ctx,"alert tcp any any -> any 80 (sid:400001; rev:1;)");
1600  FAIL_IF(s == NULL);
1601 
1602  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1603  SigFree(s);
1604  DetectEngineCtxFree(de_ctx);
1605  PASS;
1606 }
1607 
1608 /**
1609  * \test check that we set dont set a Signature as IPOnly
1610  * because it has rule options appending a SigMatch like content, and pcre
1611  */
1612 
1613 static int IPOnlyTestSig03 (void)
1614 {
1615  int result = 1;
1616  DetectEngineCtx *de_ctx;
1617  Signature *s=NULL;
1618 
1619  de_ctx = DetectEngineCtxInit();
1620  if (de_ctx == NULL)
1621  goto end;
1622  de_ctx->flags |= DE_QUIET;
1623 
1624  /* combination of pcre and content */
1625  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;)");
1626  if (s == NULL) {
1627  goto end;
1628  }
1629  if(SignatureIsIPOnly(de_ctx, s))
1630  {
1631  printf("got a IPOnly signature (content): ");
1632  result=0;
1633  }
1634  SigFree(s);
1635 
1636  /* content */
1637  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;)");
1638  if (s == NULL) {
1639  goto end;
1640  }
1641  if(SignatureIsIPOnly(de_ctx, s))
1642  {
1643  printf("got a IPOnly signature (content): ");
1644  result=0;
1645  }
1646  SigFree(s);
1647 
1648  /* uricontent */
1649  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;)");
1650  if (s == NULL) {
1651  goto end;
1652  }
1653  if(SignatureIsIPOnly(de_ctx, s))
1654  {
1655  printf("got a IPOnly signature (uricontent): ");
1656  result=0;
1657  }
1658  SigFree(s);
1659 
1660  /* pcre */
1661  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;)");
1662  if (s == NULL) {
1663  goto end;
1664  }
1665  if(SignatureIsIPOnly(de_ctx, s))
1666  {
1667  printf("got a IPOnly signature (pcre): ");
1668  result=0;
1669  }
1670  SigFree(s);
1671 
1672  /* flow */
1673  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;)");
1674  if (s == NULL) {
1675  goto end;
1676  }
1677  if(SignatureIsIPOnly(de_ctx, s))
1678  {
1679  printf("got a IPOnly signature (flow): ");
1680  result=0;
1681  }
1682  SigFree(s);
1683 
1684  /* dsize */
1685  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;)");
1686  if (s == NULL) {
1687  goto end;
1688  }
1689  if(SignatureIsIPOnly(de_ctx, s))
1690  {
1691  printf("got a IPOnly signature (dsize): ");
1692  result=0;
1693  }
1694  SigFree(s);
1695 
1696  /* flowbits */
1697  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;)");
1698  if (s == NULL) {
1699  goto end;
1700  }
1701  if(SignatureIsIPOnly(de_ctx, s))
1702  {
1703  printf("got a IPOnly signature (flowbits): ");
1704  result=0;
1705  }
1706  SigFree(s);
1707 
1708  /* flowvar */
1709  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;)");
1710  if (s == NULL) {
1711  goto end;
1712  }
1713  if(SignatureIsIPOnly(de_ctx, s))
1714  {
1715  printf("got a IPOnly signature (flowvar): ");
1716  result=0;
1717  }
1718  SigFree(s);
1719 
1720  /* pktvar */
1721  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;)");
1722  if (s == NULL) {
1723  goto end;
1724  }
1725  if(SignatureIsIPOnly(de_ctx, s))
1726  {
1727  printf("got a IPOnly signature (pktvar): ");
1728  result=0;
1729  }
1730  SigFree(s);
1731 
1732 end:
1733  if (de_ctx != NULL)
1734  DetectEngineCtxFree(de_ctx);
1735  return result;
1736 }
1737 
1738 /**
1739  * \test
1740  */
1741 static int IPOnlyTestSig04 (void)
1742 {
1743  int result = 1;
1744 
1745  IPOnlyCIDRItem *head = NULL;
1746  IPOnlyCIDRItem *new;
1747 
1748  new = IPOnlyCIDRItemNew();
1749  new->netmask= 10;
1750 
1751  head = IPOnlyCIDRItemInsert(head, new);
1752 
1753  new = IPOnlyCIDRItemNew();
1754  new->netmask= 11;
1755 
1756  head = IPOnlyCIDRItemInsert(head, new);
1757 
1758  new = IPOnlyCIDRItemNew();
1759  new->netmask= 9;
1760 
1761  head = IPOnlyCIDRItemInsert(head, new);
1762 
1763  new = IPOnlyCIDRItemNew();
1764  new->netmask= 10;
1765 
1766  head = IPOnlyCIDRItemInsert(head, new);
1767 
1768  new = IPOnlyCIDRItemNew();
1769  new->netmask= 10;
1770 
1771  head = IPOnlyCIDRItemInsert(head, new);
1772 
1773  IPOnlyCIDRListPrint(head);
1774  new = head;
1775  if (new->netmask != 9) {
1776  result = 0;
1777  goto end;
1778  }
1779  new = new->next;
1780  if (new->netmask != 10) {
1781  result = 0;
1782  goto end;
1783  }
1784  new = new->next;
1785  if (new->netmask != 10) {
1786  result = 0;
1787  goto end;
1788  }
1789  new = new->next;
1790  if (new->netmask != 10) {
1791  result = 0;
1792  goto end;
1793  }
1794  new = new->next;
1795  if (new->netmask != 11) {
1796  result = 0;
1797  goto end;
1798  }
1799 
1800 end:
1801  IPOnlyCIDRListFree(head);
1802  return result;
1803 }
1804 
1805 /**
1806  * \test Test a set of ip only signatures making use a lot of
1807  * addresses for src and dst (all should match)
1808  */
1809 static int IPOnlyTestSig05(void)
1810 {
1811  int result = 0;
1812  uint8_t *buf = (uint8_t *)"Hi all!";
1813  uint16_t buflen = strlen((char *)buf);
1814 
1815  uint8_t numpkts = 1;
1816  uint8_t numsigs = 7;
1817 
1818  Packet *p[1];
1819 
1820  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1821 
1822  const char *sigs[numsigs];
1823  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1824  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1825  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1826  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1827  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1828  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1829  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;)";
1830 
1831  /* Sid numbers (we could extract them from the sig) */
1832  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1833  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1834 
1835  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1836 
1837  UTHFreePackets(p, numpkts);
1838 
1839  return result;
1840 }
1841 
1842 /**
1843  * \test Test a set of ip only signatures making use a lot of
1844  * addresses for src and dst (none should match)
1845  */
1846 static int IPOnlyTestSig06(void)
1847 {
1848  int result = 0;
1849  uint8_t *buf = (uint8_t *)"Hi all!";
1850  uint16_t buflen = strlen((char *)buf);
1851 
1852  uint8_t numpkts = 1;
1853  uint8_t numsigs = 7;
1854 
1855  Packet *p[1];
1856 
1857  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "80.58.0.33", "195.235.113.3");
1858 
1859  const char *sigs[numsigs];
1860  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1861  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1862  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1863  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1864  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1865  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1866  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;)";
1867 
1868  /* Sid numbers (we could extract them from the sig) */
1869  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1870  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1871 
1872  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1873 
1874  UTHFreePackets(p, numpkts);
1875 
1876  return result;
1877 }
1878 
1879 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
1880  * which is why these unittests fail. When we fix 608, we need to renable
1881  * these sigs */
1882 #if 0
1883 /**
1884  * \test Test a set of ip only signatures making use a lot of
1885  * addresses for src and dst (all should match)
1886  */
1887 static int IPOnlyTestSig07(void)
1888 {
1889  int result = 0;
1890  uint8_t *buf = (uint8_t *)"Hi all!";
1891  uint16_t buflen = strlen((char *)buf);
1892 
1893  uint8_t numpkts = 1;
1894  uint8_t numsigs = 7;
1895 
1896  Packet *p[1];
1897 
1898  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1899 
1900  char *sigs[numsigs];
1901  sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1902  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;)";
1903  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;)";
1904  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;)";
1905  sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1906  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;)";
1907  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" */
1908 
1909  /* Sid numbers (we could extract them from the sig) */
1910  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1911  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1912 
1913  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1914 
1915  UTHFreePackets(p, numpkts);
1916 
1917  return result;
1918 }
1919 #endif
1920 
1921 /**
1922  * \test Test a set of ip only signatures making use a lot of
1923  * addresses for src and dst (none should match)
1924  */
1925 static int IPOnlyTestSig08(void)
1926 {
1927  int result = 0;
1928  uint8_t *buf = (uint8_t *)"Hi all!";
1929  uint16_t buflen = strlen((char *)buf);
1930 
1931  uint8_t numpkts = 1;
1932  uint8_t numsigs = 7;
1933 
1934  Packet *p[1];
1935 
1936  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
1937 
1938  const char *sigs[numsigs];
1939  sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1940  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;)";
1941  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;)";
1942  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;)";
1943  sigs[4]= "alert tcp any any -> !192.168.1.5 any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1944  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;)";
1945  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" */
1946 
1947  /* Sid numbers (we could extract them from the sig) */
1948  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1949  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1950 
1951  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1952 
1953  UTHFreePackets(p, numpkts);
1954 
1955  return result;
1956 }
1957 
1958 /**
1959  * \test Test a set of ip only signatures making use a lot of
1960  * addresses for src and dst (all should match)
1961  */
1962 static int IPOnlyTestSig09(void)
1963 {
1964  int result = 0;
1965  uint8_t *buf = (uint8_t *)"Hi all!";
1966  uint16_t buflen = strlen((char *)buf);
1967 
1968  uint8_t numpkts = 1;
1969  uint8_t numsigs = 7;
1970 
1971  Packet *p[1];
1972 
1973  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");
1974 
1975  const char *sigs[numsigs];
1976  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1977  sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1978  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;)";
1979  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;)";
1980  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;)";
1981  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;)";
1982  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;)";
1983 
1984  /* Sid numbers (we could extract them from the sig) */
1985  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1986  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1987 
1988  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1989 
1990  UTHFreePackets(p, numpkts);
1991 
1992  return result;
1993 }
1994 
1995 /**
1996  * \test Test a set of ip only signatures making use a lot of
1997  * addresses for src and dst (none should match)
1998  */
1999 static int IPOnlyTestSig10(void)
2000 {
2001  int result = 0;
2002  uint8_t *buf = (uint8_t *)"Hi all!";
2003  uint16_t buflen = strlen((char *)buf);
2004 
2005  uint8_t numpkts = 1;
2006  uint8_t numsigs = 7;
2007 
2008  Packet *p[1];
2009 
2010  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");
2011 
2012  const char *sigs[numsigs];
2013  sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2014  sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2015  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;)";
2016  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;)";
2017  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;)";
2018  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;)";
2019  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;)";
2020 
2021  /* Sid numbers (we could extract them from the sig) */
2022  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2023  uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
2024 
2025  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2026 
2027  UTHFreePackets(p, numpkts);
2028 
2029  return result;
2030 }
2031 
2032 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2033  * which is why these unittests fail. When we fix 608, we need to renable
2034  * these sigs */
2035 #if 0
2036 /**
2037  * \test Test a set of ip only signatures making use a lot of
2038  * addresses for src and dst (all should match) with ipv4 and ipv6 mixed
2039  */
2040 static int IPOnlyTestSig11(void)
2041 {
2042  int result = 0;
2043  uint8_t *buf = (uint8_t *)"Hi all!";
2044  uint16_t buflen = strlen((char *)buf);
2045 
2046  uint8_t numpkts = 2;
2047  uint8_t numsigs = 7;
2048 
2049  Packet *p[2];
2050 
2051  p[0] = UTHBuildPacketIPV6SrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565", "3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562");
2052  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
2053 
2054  char *sigs[numsigs];
2055  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;)";
2056  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;)";
2057  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;)";
2058  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;)";
2059  sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2060  sigs[5]= "alert tcp any any -> [3FFE:FFFF:7654:FEDA:0:0:0:0/64,!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;)";
2061  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" */
2062 
2063  /* Sid numbers (we could extract them from the sig) */
2064  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2065  uint32_t results[2][7] = {{ 1, 1, 1, 1, 1, 1, 1}, { 1, 1, 1, 1, 1, 1, 1}};
2066 
2067  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2068 
2069  UTHFreePackets(p, numpkts);
2070 
2071  return result;
2072 }
2073 #endif
2074 
2075 /**
2076  * \test Test a set of ip only signatures making use a lot of
2077  * addresses for src and dst (none should match) with ipv4 and ipv6 mixed
2078  */
2079 static int IPOnlyTestSig12(void)
2080 {
2081  int result = 0;
2082  uint8_t *buf = (uint8_t *)"Hi all!";
2083  uint16_t buflen = strlen((char *)buf);
2084 
2085  uint8_t numpkts = 2;
2086  uint8_t numsigs = 7;
2087 
2088  Packet *p[2];
2089 
2090  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");
2091  p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"195.85.1.1","80.198.1.5");
2092 
2093  const char *sigs[numsigs];
2094  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;)";
2095  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;)";
2096  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;)";
2097  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;)";
2098  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;)";
2099  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;)";
2100  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" */
2101 
2102  /* Sid numbers (we could extract them from the sig) */
2103  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2104  uint32_t results[2][7] = {{ 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}};
2105 
2106  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2107 
2108  UTHFreePackets(p, numpkts);
2109 
2110  return result;
2111 }
2112 
2113 static int IPOnlyTestSig13(void)
2114 {
2116  FAIL_IF(de_ctx == NULL);
2117  de_ctx->flags |= DE_QUIET;
2118 
2119  Signature *s = SigInit(de_ctx,
2120  "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2121  "flowbits:set,myflow1; sid:1; rev:1;)");
2122  FAIL_IF(s == NULL);
2123 
2124  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
2125  SigFree(s);
2126  DetectEngineCtxFree(de_ctx);
2127  PASS;
2128 }
2129 
2130 static int IPOnlyTestSig14(void)
2131 {
2133  FAIL_IF(de_ctx == NULL);
2134  de_ctx->flags |= DE_QUIET;
2135 
2136  Signature *s = SigInit(de_ctx,
2137  "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2138  "flowbits:set,myflow1; flowbits:isset,myflow2; sid:1; rev:1;)");
2139  FAIL_IF(s == NULL);
2140 
2141  FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 1);
2142  SigFree(s);
2143  DetectEngineCtxFree(de_ctx);
2144  PASS;
2145 }
2146 
2147 static int IPOnlyTestSig15(void)
2148 {
2149  int result = 0;
2150  uint8_t *buf = (uint8_t *)"Hi all!";
2151  uint16_t buflen = strlen((char *)buf);
2152 
2153  uint8_t numpkts = 1;
2154  uint8_t numsigs = 7;
2155 
2156  Packet *p[1];
2157  Flow f;
2158  GenericVar flowvar;
2159  memset(&f, 0, sizeof(Flow));
2160  memset(&flowvar, 0, sizeof(GenericVar));
2161  FLOW_INITIALIZE(&f);
2162 
2163  p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
2164 
2165  p[0]->flow = &f;
2166  p[0]->flow->flowvar = &flowvar;
2167  p[0]->flags |= PKT_HAS_FLOW;
2168  p[0]->flowflags |= FLOW_PKT_TOSERVER;
2169 
2170  const char *sigs[numsigs];
2171  sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; "
2172  "flowbits:set,one; sid:1;)";
2173  sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; "
2174  "flowbits:set,two; sid:2;)";
2175  sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; "
2176  "flowbits:set,three; sid:3;)";
2177  sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; "
2178  "flowbits:set,four; sid:4;)";
2179  sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; "
2180  "flowbits:set,five; sid:5;)";
2181  sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; "
2182  "flowbits:set,six; sid:6;)";
2183  sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; "
2184  "flowbits:set,seven; content:\"Hi all\"; sid:7;)";
2185 
2186  /* Sid numbers (we could extract them from the sig) */
2187  uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2188  uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2189 
2190  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2191 
2192  UTHFreePackets(p, numpkts);
2193 
2194  FLOW_DESTROY(&f);
2195  return result;
2196 }
2197 
2198 /**
2199  * \brief Unittest to show #599. We fail to match if we have negated addresses.
2200  */
2201 static int IPOnlyTestSig16(void)
2202 {
2203  int result = 0;
2204  uint8_t *buf = (uint8_t *)"Hi all!";
2205  uint16_t buflen = strlen((char *)buf);
2206 
2207  uint8_t numpkts = 1;
2208  uint8_t numsigs = 2;
2209 
2210  Packet *p[1];
2211 
2212  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "100.100.0.0", "50.0.0.0");
2213 
2214  const char *sigs[numsigs];
2215  sigs[0]= "alert tcp !100.100.0.1 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2216  sigs[1]= "alert tcp any any -> !50.0.0.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2217 
2218  /* Sid numbers (we could extract them from the sig) */
2219  uint32_t sid[2] = { 1, 2};
2220  uint32_t results[2] = { 1, 1};
2221 
2222  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2223 
2224  UTHFreePackets(p, numpkts);
2225 
2226  return result;
2227 }
2228 
2229 /**
2230  * \brief Unittest to show #611. Ports on portless protocols.
2231  */
2232 static int IPOnlyTestSig17(void)
2233 {
2234  int result = 0;
2235  uint8_t *buf = (uint8_t *)"Hi all!";
2236  uint16_t buflen = strlen((char *)buf);
2237 
2238  uint8_t numpkts = 1;
2239  uint8_t numsigs = 2;
2240 
2241  Packet *p[1];
2242 
2243  p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_ICMP, "100.100.0.0", "50.0.0.0");
2244 
2245  const char *sigs[numsigs];
2246  sigs[0]= "alert ip 100.100.0.0 80 -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2247  sigs[1]= "alert ip any any -> 50.0.0.0 123 (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2248 
2249  uint32_t sid[2] = { 1, 2};
2250  uint32_t results[2] = { 0, 0}; /* neither should match */
2251 
2252  result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2253 
2254  UTHFreePackets(p, numpkts);
2255 
2256  return result;
2257 }
2258 
2259 #endif /* UNITTESTS */
2260 
2262 {
2263 #ifdef UNITTESTS
2264  UtRegisterTest("IPOnlyTestSig01", IPOnlyTestSig01);
2265  UtRegisterTest("IPOnlyTestSig02", IPOnlyTestSig02);
2266  UtRegisterTest("IPOnlyTestSig03", IPOnlyTestSig03);
2267  UtRegisterTest("IPOnlyTestSig04", IPOnlyTestSig04);
2268 
2269  UtRegisterTest("IPOnlyTestSig05", IPOnlyTestSig05);
2270  UtRegisterTest("IPOnlyTestSig06", IPOnlyTestSig06);
2271 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2272  * which is why these unittests fail. When we fix 608, we need to renable
2273  * these sigs */
2274 #if 0
2275  UtRegisterTest("IPOnlyTestSig07", IPOnlyTestSig07, 1);
2276 #endif
2277  UtRegisterTest("IPOnlyTestSig08", IPOnlyTestSig08);
2278 
2279  UtRegisterTest("IPOnlyTestSig09", IPOnlyTestSig09);
2280  UtRegisterTest("IPOnlyTestSig10", IPOnlyTestSig10);
2281 /* \todo fix it. We have disabled this unittest because 599 exposes 608,
2282  * which is why these unittests fail. When we fix 608, we need to renable
2283  * these sigs */
2284 #if 0
2285  UtRegisterTest("IPOnlyTestSig11", IPOnlyTestSig11, 1);
2286 #endif
2287  UtRegisterTest("IPOnlyTestSig12", IPOnlyTestSig12);
2288  UtRegisterTest("IPOnlyTestSig13", IPOnlyTestSig13);
2289  UtRegisterTest("IPOnlyTestSig14", IPOnlyTestSig14);
2290  UtRegisterTest("IPOnlyTestSig15", IPOnlyTestSig15);
2291  UtRegisterTest("IPOnlyTestSig16", IPOnlyTestSig16);
2292 
2293  UtRegisterTest("IPOnlyTestSig17", IPOnlyTestSig17);
2294 #endif
2295 
2296  return;
2297 }
2298 
#define GET_IPV4_SRC_ADDR_U32(p)
Definition: decode.h:213
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1448
DetectProto proto
Definition: detect.h:539
SCRadixTree * tree_ipv6src
Definition: detect.h:676
#define DETECT_PROTO_IPV6
#define SCLogDebug(...)
Definition: util-debug.h:335
Signature ** sig_array
Definition: detect.h:776
struct Flow_ * flow
Definition: decode.h:446
IPOnlyCIDRItem * ip_dst
Definition: detect.h:679
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:523
char * msg
Definition: detect.h:580
uint32_t id
Definition: detect.h:555
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
uint8_t is_last
Definition: detect.h:329
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Port sp
Definition: decode.h:416
#define GET_IPV4_DST_ADDR_U32(p)
Definition: decode.h:214
uint8_t netmask
Definition: detect.h:298
#define PKT_IS_FRAGMENT
Definition: decode.h:1109
Port dp
Definition: decode.h:424
uint8_t * sig_init_array
Definition: detect.h:689
IPOnlyCIDRItem * ip_src
Definition: detect.h:679
IPOnlyCIDRItem * CidrSrc
Definition: detect.h:568
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
Address dst
Definition: decode.h:414
#define PKT_IS_IPV6(p)
Definition: decode.h:253
Data needed for Match()
Definition: detect.h:327
IPOnlyCIDRItem * CidrDst
Definition: detect.h:568
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:281
Flow * head
Definition: flow-hash.h:102
Signature container.
Definition: detect.h:522
uint8_t action
Definition: detect.h:535
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:252
SigIntId num
Definition: detect.h:532
main detection engine ctx
Definition: detect.h:761
void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Deinitialize the IP Only detection engine context.
#define SIG_FLAG_DST_ANY
Definition: detect.h:212
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:292
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:676
DetectPort * dp
Definition: detect.h:561
char family
Definition: decode.h:112
#define SIG_FLAG_SP_ANY
Definition: detect.h:213
void DetectEngineIPOnlyThreadInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyThreadCtx *io_tctx)
Setup the IP Only thread detection engine context.
uint8_t proto
Definition: decode.h:431
uint8_t flags
Definition: detect.h:762
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:221
#define SIG_FLAG_IPONLY
Definition: detect.h:219
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:675
#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:121
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:440
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:575
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
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:1519
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1170
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:300
void IPOnlyRegisterTests(void)
#define SCNtohl(x)
DetectEngineIPOnlyCtx io_ctx
Definition: detect.h:807
GenericVar * flowvar
Definition: flow.h:448
#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:222
IP only rules matching ctx.
Definition: detect.h:669
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:220
struct IPOnlyCIDRItem_ * next
Definition: detect.h:306
uint8_t type
Definition: detect.h:328
#define SCFree(a)
Definition: util-mem.h:322
void IPOnlyPrint(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Print stats of the IP Only engine.
uint8_t address
Definition: decode-ppp.h:312
#define SIG_FLAG_NOALERT
Definition: detect.h:216
DetectPort * sp
Definition: detect.h:561
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.
SCRadixTree * tree_ipv4dst
Definition: detect.h:675
uint32_t ip[4]
Definition: detect.h:302
SigIntId signum
Definition: detect.h:303
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define IP_GET_IPPROTO(p)
Definition: decode.h:264
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
uint8_t family
Definition: detect.h:296
#define PKT_HAS_FLOW
Definition: decode.h:1094
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:690
#define SCStrdup(a)
Definition: util-mem.h:268
#define SIGMATCH_IPONLY_COMPAT
Definition: detect.h:1371
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:214
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:444
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:211
uint16_t flags
Definition: detect.h:1194
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:325
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:191
Address src
Definition: decode.h:413
SigMatchCtx * ctx
Definition: detect.h:330
DetectEngineCtx * DetectEngineCtxInit(void)
#define DEBUG_VALIDATE_BUG_ON(exp)