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