Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-engine-iponly.c
Line
Count
Source
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
38
#include "detect-engine-siggroup.h"
39
#include "detect-engine-address.h"
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
45
#include "detect-engine-threshold.h"
46
#include "detect-engine-iponly.h"
47
#include "detect-threshold.h"
48
#include "util-classification-config.h"
49
#include "util-rule-vars.h"
50
51
#include "flow-util.h"
52
#include "util-debug.h"
53
#include "util-unittest.h"
54
#include "util-unittest-helper.h"
55
#include "util-print.h"
56
#include "util-byte.h"
57
#include "util-profiling.h"
58
#include "util-validate.h"
59
#include "util-cidr.h"
60
61
#ifdef OS_WIN32
62
#include <winsock.h>
63
#else
64
#include <netinet/in.h>
65
#endif /* OS_WIN32 */
66
67
/**
68
 * \brief This function creates a new IPOnlyCIDRItem
69
 *
70
 * \retval IPOnlyCIDRItem address of the new instance
71
 */
72
static IPOnlyCIDRItem *IPOnlyCIDRItemNew(void)
73
632k
{
74
632k
    SCEnter();
75
632k
    IPOnlyCIDRItem *item = NULL;
76
77
632k
    item = SCMalloc(sizeof(IPOnlyCIDRItem));
78
632k
    if (unlikely(item == NULL))
79
0
        SCReturnPtr(NULL, "IPOnlyCIDRItem");
80
632k
    memset(item, 0, sizeof(IPOnlyCIDRItem));
81
82
632k
    SCReturnPtr(item, "IPOnlyCIDRItem");
83
632k
}
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
 */
92
static int IPOnlyCIDRItemCompareReal(const IPOnlyCIDRItem *lhs, const IPOnlyCIDRItem *rhs)
93
333k
{
94
333k
    if (lhs->netmask == rhs->netmask) {
95
184k
        uint8_t i = 0;
96
400k
        for (; i < lhs->netmask / 32 || i < 1; i++) {
97
280k
            if (lhs->ip[i] < rhs->ip[i])
98
21.6k
                return -1;
99
258k
            if (lhs->ip[i] > rhs->ip[i])
100
42.1k
                return 1;
101
258k
        }
102
120k
        return 0;
103
184k
    }
104
105
149k
    return lhs->netmask < rhs->netmask ? -1 : 1;
106
333k
}
107
108
static int IPOnlyCIDRItemCompare(const void *lhsv, const void *rhsv)
109
333k
{
110
333k
    const IPOnlyCIDRItem *lhs = *(const IPOnlyCIDRItem **)lhsv;
111
333k
    const IPOnlyCIDRItem *rhs = *(const IPOnlyCIDRItem **)rhsv;
112
113
333k
    return IPOnlyCIDRItemCompareReal(lhs, rhs);
114
333k
}
115
116
static void IPOnlyCIDRListQSort(IPOnlyCIDRItem **head)
117
280k
{
118
280k
    if (unlikely(head == NULL || *head == NULL))
119
264k
        return;
120
121
    // First count the number of elements in the list
122
16.4k
    size_t len = 0;
123
16.4k
    IPOnlyCIDRItem *curr = *head;
124
125
125k
    while (curr) {
126
108k
        curr = curr->next;
127
108k
        len++;
128
108k
    }
129
130
    // Place a pointer to the list item in an array for sorting
131
16.4k
    IPOnlyCIDRItem **tmp = SCMalloc(len * sizeof(IPOnlyCIDRItem *));
132
133
16.4k
    if (unlikely(tmp == NULL)) {
134
0
        SCLogError("Failed to allocate enough memory to sort IP-only CIDR items.");
135
0
        return;
136
0
    }
137
138
16.4k
    curr = *head;
139
125k
    for (size_t i = 0; i < len; i++) {
140
108k
        tmp[i] = curr;
141
108k
        curr = curr->next;
142
108k
    }
143
144
    // Perform the sort using the qsort algorithm
145
16.4k
    qsort(tmp, len, sizeof(IPOnlyCIDRItem *), IPOnlyCIDRItemCompare);
146
147
    // Update the links to the next element
148
16.4k
    *head = tmp[0];
149
150
108k
    for (size_t i = 0; i + 1 < len; i++) {
151
92.2k
        tmp[i]->next = tmp[i + 1];
152
92.2k
    }
153
154
16.4k
    tmp[len - 1]->next = NULL;
155
156
16.4k
    SCFree(tmp);
157
16.4k
}
158
159
//declaration for using it already
160
static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
161
                                            IPOnlyCIDRItem *item);
162
163
static int InsertRange(
164
        IPOnlyCIDRItem **pdd, IPOnlyCIDRItem *dd, const uint32_t first_in, const uint32_t last_in)
165
2.36k
{
166
2.36k
    DEBUG_VALIDATE_BUG_ON(dd == NULL);
167
2.36k
    DEBUG_VALIDATE_BUG_ON(pdd == NULL);
168
169
2.36k
    uint32_t first = first_in;
170
2.36k
    uint32_t last = last_in;
171
172
2.36k
    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
7.64k
    while (dd->netmask > 0 && (first & (1UL << (32 - dd->netmask))) == 0 &&
179
5.66k
            first + (1UL << (32 - (dd->netmask - 1))) - 1 <= last) {
180
5.28k
        dd->netmask--;
181
5.28k
    }
182
2.36k
    dd->ip[0] = htonl(first);
183
2.36k
    first += 1UL << (32 - dd->netmask);
184
    // case whatever-255.255.255.255 looping to 0.0.0.0/0
185
48.6k
    while (first <= last && first != 0) {
186
46.3k
        IPOnlyCIDRItem *new = IPOnlyCIDRItemNew();
187
46.3k
        if (new == NULL)
188
0
            goto error;
189
46.3k
        new->negated = dd->negated;
190
46.3k
        new->family = dd->family;
191
46.3k
        new->netmask = 32;
192
654k
        while (new->netmask > 0 && (first & (1UL << (32 - new->netmask))) == 0 &&
193
626k
                first + (1UL << (32 - (new->netmask - 1))) - 1 <= last) {
194
608k
            new->netmask--;
195
608k
        }
196
46.3k
        new->ip[0] = htonl(first);
197
46.3k
        first += 1UL << (32 - new->netmask);
198
46.3k
        dd = IPOnlyCIDRItemInsert(dd, new);
199
46.3k
    }
200
    // update head of list
201
2.36k
    *pdd = dd;
202
2.36k
    return 0;
203
0
error:
204
0
    return -1;
205
2.36k
}
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
 */
219
static int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem **pdd, const char *str)
220
600k
{
221
600k
    char buf[256] = "";
222
600k
    char *ip = NULL, *ip2 = NULL;
223
600k
    char *mask = NULL;
224
600k
    int r = 0;
225
600k
    IPOnlyCIDRItem *dd = *pdd;
226
227
604k
    while (*str != '\0' && *str == ' ')
228
4.62k
        str++;
229
230
600k
    SCLogDebug("str %s", str);
231
600k
    strlcpy(buf, str, sizeof(buf));
232
600k
    ip = buf;
233
234
    /* first handle 'any' */
235
600k
    if (strcasecmp(str, "any") == 0) {
236
        /* if any, insert 0.0.0.0/0 and ::/0 as well */
237
14.5k
        SCLogDebug("adding 0.0.0.0/0 and ::/0 as we\'re handling \'any\'");
238
239
14.5k
        IPOnlyCIDRItemParseSingle(&dd, "0.0.0.0/0");
240
14.5k
        BUG_ON(dd->family == 0);
241
242
14.5k
        dd->next = IPOnlyCIDRItemNew();
243
14.5k
        if (dd->next == NULL)
244
0
            goto error;
245
246
14.5k
        IPOnlyCIDRItemParseSingle(&dd->next, "::/0");
247
14.5k
        BUG_ON(dd->family == 0);
248
249
14.5k
        SCLogDebug("address is \'any\'");
250
14.5k
        return 0;
251
14.5k
    }
252
253
    /* handle the negation case */
254
585k
    if (ip[0] == '!') {
255
4.32k
        dd->negated = (dd->negated)? 0 : 1;
256
4.32k
        ip++;
257
4.32k
    }
258
259
    /* see if the address is an ipv4 or ipv6 address */
260
585k
    if ((strchr(str, ':')) == NULL) {
261
        /* IPv4 Address */
262
273k
        struct in_addr in;
263
264
273k
        dd->family = AF_INET;
265
266
273k
        if ((mask = strchr(ip, '/')) != NULL) {
267
            /* 1.2.3.4/xxx format (either dotted or cidr notation */
268
234k
            ip[mask - ip] = '\0';
269
234k
            mask++;
270
234k
            uint32_t netmask = 0;
271
234k
            size_t u = 0;
272
273
234k
            if ((strchr (mask, '.')) == NULL) {
274
                /* 1.2.3.4/24 format */
275
276
488k
                for (u = 0; u < strlen(mask); u++) {
277
254k
                    if(!isdigit((unsigned char)mask[u]))
278
0
                        goto error;
279
254k
                }
280
281
234k
                uint8_t cidr;
282
234k
                if (StringParseU8RangeCheck(&cidr, 10, 0, (const char *)mask, 0, 32) <= 0)
283
0
                    goto error;
284
285
234k
                dd->netmask = cidr;
286
234k
                netmask = CIDRGet(cidr);
287
234k
            } else {
288
                /* 1.2.3.4/255.255.255.0 format */
289
478
                r = inet_pton(AF_INET, mask, &in);
290
478
                if (r <= 0)
291
0
                    goto error;
292
293
478
                int cidr = CIDRFromMask(in.s_addr);
294
478
                if (cidr < 0)
295
0
                    goto error;
296
297
478
                dd->netmask = (uint8_t)cidr;
298
478
            }
299
300
234k
            r = inet_pton(AF_INET, ip, &in);
301
234k
            if (r <= 0)
302
135
                goto error;
303
304
234k
            dd->ip[0] = in.s_addr & netmask;
305
306
234k
        } else if ((ip2 = strchr(ip, '-')) != NULL) {
307
            /* 1.2.3.4-1.2.3.6 range format */
308
2.37k
            ip[ip2 - ip] = '\0';
309
2.37k
            ip2++;
310
311
2.37k
            uint32_t first, last;
312
313
2.37k
            r = inet_pton(AF_INET, ip, &in);
314
2.37k
            if (r <= 0)
315
11
                goto error;
316
2.36k
            first = SCNtohl(in.s_addr);
317
318
2.36k
            r = inet_pton(AF_INET, ip2, &in);
319
2.36k
            if (r <= 0)
320
0
                goto error;
321
2.36k
            last = SCNtohl(in.s_addr);
322
323
            /* a > b is illegal, a = b is ok */
324
2.36k
            if (first > last)
325
0
                goto error;
326
327
2.36k
            SCLogDebug("Creating CIDR range for [%s - %s]", ip, ip2);
328
2.36k
            return InsertRange(pdd, dd, first, last);
329
36.8k
        } else {
330
            /* 1.2.3.4 format */
331
36.8k
            r = inet_pton(AF_INET, ip, &in);
332
36.8k
            if (r <= 0)
333
703
                goto error;
334
335
            /* single host */
336
36.1k
            dd->ip[0] = in.s_addr;
337
36.1k
            dd->netmask = 32;
338
36.1k
        }
339
312k
    } else {
340
        /* IPv6 Address */
341
312k
        struct in6_addr in6, mask6;
342
312k
        uint32_t ip6addr[4], netmask[4];
343
344
312k
        dd->family = AF_INET6;
345
346
312k
        if ((mask = strchr(ip, '/')) != NULL)  {
347
229k
            mask[0] = '\0';
348
229k
            mask++;
349
350
229k
            r = inet_pton(AF_INET6, ip, &in6);
351
229k
            if (r <= 0)
352
268
                goto error;
353
354
            /* Format is cidr val */
355
229k
            if (StringParseU8RangeCheck(&dd->netmask, 10, 0,
356
229k
                                        (const char *)mask, 0, 128) < 0) {
357
5.85k
                goto error;
358
5.85k
            }
359
360
223k
            memcpy(&ip6addr, &in6.s6_addr, sizeof(ip6addr));
361
223k
            CIDRGetIPv6(dd->netmask, &mask6);
362
223k
            memcpy(&netmask, &mask6.s6_addr, sizeof(netmask));
363
364
223k
            dd->ip[0] = ip6addr[0] & netmask[0];
365
223k
            dd->ip[1] = ip6addr[1] & netmask[1];
366
223k
            dd->ip[2] = ip6addr[2] & netmask[2];
367
223k
            dd->ip[3] = ip6addr[3] & netmask[3];
368
223k
        } else {
369
82.2k
            r = inet_pton(AF_INET6, ip, &in6);
370
82.2k
            if (r <= 0)
371
1.48k
                goto error;
372
373
80.7k
            memcpy(dd->ip, &in6.s6_addr, sizeof(dd->ip));
374
80.7k
            dd->netmask = 128;
375
80.7k
        }
376
377
312k
    }
378
379
575k
    BUG_ON(dd->family == 0);
380
575k
    return 0;
381
382
8.45k
error:
383
8.45k
    return -1;
384
575k
}
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
 */
398
static int IPOnlyCIDRItemSetup(IPOnlyCIDRItem **gh, char *s)
399
571k
{
400
571k
    SCLogDebug("gh %p, s %s", *gh, s);
401
402
    /* parse the address */
403
571k
    if (IPOnlyCIDRItemParseSingle(gh, s) == -1) {
404
8.45k
        SCLogError("address parsing error \"%s\"", s);
405
8.45k
        goto error;
406
8.45k
    }
407
408
562k
    return 0;
409
410
8.45k
error:
411
8.45k
    return -1;
412
571k
}
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
 */
422
static IPOnlyCIDRItem *IPOnlyCIDRItemInsertReal(IPOnlyCIDRItem *head,
423
                                         IPOnlyCIDRItem *item)
424
472k
{
425
472k
    if (item == NULL)
426
0
        return head;
427
428
    /* Always insert item as head */
429
472k
    item->next = head;
430
472k
    return item;
431
472k
}
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
 */
442
static IPOnlyCIDRItem *IPOnlyCIDRItemInsert(IPOnlyCIDRItem *head,
443
                                     IPOnlyCIDRItem *item)
444
871k
{
445
871k
    IPOnlyCIDRItem *it, *prev = NULL;
446
447
    /* The first element */
448
871k
    if (head == NULL) {
449
502k
        SCLogDebug("Head is NULL to insert item (%p)",item);
450
502k
        return item;
451
502k
    }
452
453
369k
    if (item == NULL) {
454
0
        SCLogDebug("Item is NULL");
455
0
        return head;
456
0
    }
457
458
369k
    SCLogDebug("Inserting item(%p)->netmask %u head %p", item, item->netmask, head);
459
460
369k
    prev = item;
461
841k
    while (prev != NULL) {
462
472k
        it = prev->next;
463
464
        /* Separate from the item list */
465
472k
        prev->next = NULL;
466
467
        //SCLogDebug("Before:");
468
        //IPOnlyCIDRListPrint(head);
469
472k
        head = IPOnlyCIDRItemInsertReal(head, prev);
470
        //SCLogDebug("After:");
471
        //IPOnlyCIDRListPrint(head);
472
472k
        prev = it;
473
472k
    }
474
475
369k
    return head;
476
369k
}
477
478
/**
479
 * \brief This function free a IPOnlyCIDRItem list
480
 * \param tmphead Pointer to the list
481
 */
482
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
483
231k
{
484
231k
    SCEnter();
485
#ifdef DEBUG
486
    uint32_t i = 0;
487
#endif
488
231k
    IPOnlyCIDRItem *it, *next = NULL;
489
490
231k
    if (tmphead == NULL) {
491
0
        SCLogDebug("temphead is NULL");
492
0
        return;
493
0
    }
494
495
231k
    it = tmphead;
496
231k
    next = it->next;
497
498
755k
    while (it != NULL) {
499
#ifdef DEBUG
500
        i++;
501
        SCLogDebug("Item(%p) %"PRIu32" removed", it, i);
502
#endif
503
523k
        SCFree(it);
504
523k
        it = next;
505
506
523k
        if (next != NULL)
507
291k
            next = next->next;
508
523k
    }
509
231k
    SCReturn;
510
231k
}
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
 */
519
static void IPOnlyCIDRListSetSigNum(IPOnlyCIDRItem *tmphead, SigIntId i)
520
31.3k
{
521
140k
    while (tmphead != NULL) {
522
108k
        tmphead->signum = i;
523
108k
        tmphead = tmphead->next;
524
108k
    }
525
31.3k
}
526
527
#ifdef UNITTESTS
528
/**
529
 * \brief This function print a IPOnlyCIDRItem list
530
 * \param tmphead Pointer to the head of IPOnlyCIDRItems list
531
 */
532
static 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
 */
554
typedef struct SigNumArray_ {
555
    uint8_t *array; /* bit array of sig nums */
556
    uint32_t size;  /* size in bytes of the array */
557
} SigNumArray;
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
 */
564
static void SigNumArrayPrint(void *tmp)
565
0
{
566
0
    SigNumArray *sna = (SigNumArray *)tmp;
567
0
    for (uint32_t u = 0; u < sna->size; u++) {
568
0
        uint8_t bitarray = sna->array[u];
569
0
        for (uint8_t i = 0; i < 8; i++) {
570
0
            if (bitarray & 0x01)
571
0
                printf("%" PRIu32 " ", u * 8 + i);
572
0
            bitarray = bitarray >> 1;
573
0
        }
574
0
    }
575
0
}
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
 */
585
static SigNumArray *SigNumArrayNew(DetectEngineCtx *de_ctx,
586
                            DetectEngineIPOnlyCtx *io_ctx)
587
38.8k
{
588
38.8k
    SigNumArray *new = SCMalloc(sizeof(SigNumArray));
589
590
38.8k
    if (unlikely(new == NULL)) {
591
0
        FatalError("Fatal error encountered in SigNumArrayNew. Exiting...");
592
0
    }
593
38.8k
    memset(new, 0, sizeof(SigNumArray));
594
595
38.8k
    new->array = SCMalloc(io_ctx->max_idx / 8 + 1);
596
38.8k
    if (new->array == NULL) {
597
0
       exit(EXIT_FAILURE);
598
0
    }
599
600
38.8k
    memset(new->array, 0, io_ctx->max_idx / 8 + 1);
601
38.8k
    new->size = io_ctx->max_idx / 8 + 1;
602
603
38.8k
    SCLogDebug("max idx= %u", io_ctx->max_idx);
604
605
38.8k
    return new;
606
38.8k
}
607
608
/**
609
 * \brief This function creates a new SigNumArray with the
610
 *        same data as the argument
611
 *
612
 * \param orig Pointer to the original SigNumArray to copy
613
 *
614
 * \retval SigNumArray address of the new instance
615
 */
616
static SigNumArray *SigNumArrayCopy(SigNumArray *orig)
617
19.5k
{
618
19.5k
    SigNumArray *new = SCMalloc(sizeof(SigNumArray));
619
620
19.5k
    if (unlikely(new == NULL)) {
621
0
        FatalError("Fatal error encountered in SigNumArrayCopy. Exiting...");
622
0
    }
623
624
19.5k
    memset(new, 0, sizeof(SigNumArray));
625
19.5k
    new->size = orig->size;
626
627
19.5k
    new->array = SCMalloc(orig->size);
628
19.5k
    if (new->array == NULL) {
629
0
        exit(EXIT_FAILURE);
630
0
    }
631
632
19.5k
    memcpy(new->array, orig->array, orig->size);
633
19.5k
    return new;
634
19.5k
}
635
636
/**
637
 * \brief This function free() a SigNumArray
638
 * \param orig Pointer to the original SigNumArray to copy
639
 */
640
static void SigNumArrayFree(void *tmp)
641
58.4k
{
642
58.4k
    SigNumArray *sna = (SigNumArray *)tmp;
643
644
58.4k
    if (sna == NULL)
645
0
        return;
646
647
58.4k
    if (sna->array != NULL)
648
58.4k
        SCFree(sna->array);
649
650
58.4k
    SCFree(sna);
651
58.4k
}
652
653
/**
654
 * \brief This function parses and return a list of IPOnlyCIDRItem
655
 *
656
 * \param s Pointer to the string of the addresses
657
 *          (in the format of signatures)
658
 * \param negate flag to indicate if all this string is negated or not
659
 *
660
 * \retval 0 if success
661
 * \retval -1 if fails
662
 */
663
static IPOnlyCIDRItem *IPOnlyCIDRListParse2(
664
        const DetectEngineCtx *de_ctx, const char *s, int negate)
665
489k
{
666
489k
    size_t x = 0;
667
489k
    size_t u = 0;
668
489k
    int o_set = 0, n_set = 0, d_set = 0;
669
489k
    int depth = 0;
670
489k
    size_t size = strlen(s);
671
489k
    char address[8196] = "";
672
489k
    const char *rule_var_address = NULL;
673
489k
    char *temp_rule_var_address = NULL;
674
489k
    IPOnlyCIDRItem *head;
675
489k
    IPOnlyCIDRItem *subhead;
676
489k
    head = subhead = NULL;
677
678
489k
    SCLogDebug("s %s negate %s", s, negate ? "true" : "false");
679
680
12.3M
    for (u = 0, x = 0; u < size && x < sizeof(address); u++) {
681
11.8M
        address[x] = s[u];
682
11.8M
        x++;
683
684
11.8M
        if (!o_set && s[u] == '!') {
685
1.30k
            n_set = 1;
686
1.30k
            x--;
687
11.8M
        } else if (s[u] == '[') {
688
430k
            if (!o_set) {
689
234k
                o_set = 1;
690
234k
                x = 0;
691
234k
            }
692
430k
            depth++;
693
11.4M
        } else if (s[u] == ']') {
694
430k
            if (depth == 1) {
695
233k
                address[x - 1] = '\0';
696
233k
                x = 0;
697
698
233k
                if ( (subhead = IPOnlyCIDRListParse2(de_ctx, address,
699
233k
                                                (negate + n_set) % 2)) == NULL)
700
2.41k
                    goto error;
701
702
230k
                head = IPOnlyCIDRItemInsert(head, subhead);
703
230k
                n_set = 0;
704
230k
            }
705
428k
            depth--;
706
10.9M
        } else if (depth == 0 && s[u] == ',') {
707
320k
            if (o_set == 1) {
708
12.3k
                o_set = 0;
709
308k
            } else if (d_set == 1) {
710
0
                address[x - 1] = '\0';
711
712
0
                rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
713
0
                                                  SC_RULE_VARS_ADDRESS_GROUPS);
714
0
                if (rule_var_address == NULL)
715
0
                    goto error;
716
717
0
                if ((negate + n_set) % 2) {
718
0
                    temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
719
0
                    if (unlikely(temp_rule_var_address == NULL)) {
720
0
                        goto error;
721
0
                    }
722
723
0
                    snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
724
0
                             "[%s]", rule_var_address);
725
0
                } else {
726
0
                    temp_rule_var_address = SCStrdup(rule_var_address);
727
0
                    if (unlikely(temp_rule_var_address == NULL)) {
728
0
                        goto error;
729
0
                    }
730
0
                }
731
732
0
                subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
733
0
                                               (negate + n_set) % 2);
734
0
                head = IPOnlyCIDRItemInsert(head, subhead);
735
736
0
                d_set = 0;
737
0
                n_set = 0;
738
739
0
                SCFree(temp_rule_var_address);
740
741
308k
            } else {
742
308k
                address[x - 1] = '\0';
743
744
308k
                subhead = IPOnlyCIDRItemNew();
745
308k
                if (subhead == NULL)
746
0
                    goto error;
747
748
308k
                if (!((negate + n_set) % 2))
749
308k
                    subhead->negated = 0;
750
0
                else
751
0
                    subhead->negated = 1;
752
753
308k
                if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
754
3.81k
                    IPOnlyCIDRListFree(subhead);
755
3.81k
                    subhead = NULL;
756
3.81k
                    goto error;
757
3.81k
                }
758
304k
                head = IPOnlyCIDRItemInsert(head, subhead);
759
760
304k
                n_set = 0;
761
304k
            }
762
316k
            x = 0;
763
10.6M
        } else if (depth == 0 && s[u] == '$') {
764
2.96k
            d_set = 1;
765
10.6M
        } else if (depth == 0 && u == size - 1) {
766
263k
            if (x == sizeof(address)) {
767
0
                address[x - 1] = '\0';
768
263k
            } else {
769
263k
                address[x] = '\0';
770
263k
            }
771
263k
            x = 0;
772
773
263k
            if (d_set == 1) {
774
0
                rule_var_address = SCRuleVarsGetConfVar(de_ctx, address,
775
0
                                                    SC_RULE_VARS_ADDRESS_GROUPS);
776
0
                if (rule_var_address == NULL)
777
0
                    goto error;
778
779
0
                if ((negate + n_set) % 2) {
780
0
                    temp_rule_var_address = SCMalloc(strlen(rule_var_address) + 3);
781
0
                    if (unlikely(temp_rule_var_address == NULL)) {
782
0
                        goto error;
783
0
                    }
784
0
                    snprintf(temp_rule_var_address, strlen(rule_var_address) + 3,
785
0
                            "[%s]", rule_var_address);
786
0
                } else {
787
0
                    temp_rule_var_address = SCStrdup(rule_var_address);
788
0
                    if (unlikely(temp_rule_var_address == NULL)) {
789
0
                        goto error;
790
0
                    }
791
0
                }
792
0
                subhead = IPOnlyCIDRListParse2(de_ctx, temp_rule_var_address,
793
0
                                               (negate + n_set) % 2);
794
0
                head = IPOnlyCIDRItemInsert(head, subhead);
795
796
0
                d_set = 0;
797
798
0
                SCFree(temp_rule_var_address);
799
263k
            } else {
800
263k
                subhead = IPOnlyCIDRItemNew();
801
263k
                if (subhead == NULL)
802
0
                    goto error;
803
804
263k
                if (!((negate + n_set) % 2))
805
263k
                    subhead->negated = 0;
806
0
                else
807
0
                    subhead->negated = 1;
808
809
263k
                if (IPOnlyCIDRItemSetup(&subhead, address) < 0) {
810
4.63k
                    IPOnlyCIDRListFree(subhead);
811
4.63k
                    subhead = NULL;
812
4.63k
                    goto error;
813
4.63k
                }
814
258k
                head = IPOnlyCIDRItemInsert(head, subhead);
815
258k
            }
816
258k
            n_set = 0;
817
258k
        }
818
11.8M
    }
819
820
479k
    return head;
821
822
10.8k
error:
823
10.8k
    SCLogError("Error parsing addresses");
824
10.8k
    return head;
825
489k
}
826
827
828
/**
829
 * \brief Parses an address group sent as a character string and updates the
830
 *        IPOnlyCIDRItem list
831
 *
832
 * \param gh  Pointer to the IPOnlyCIDRItem list
833
 * \param str Pointer to the character string containing the address group
834
 *            that has to be parsed.
835
 *
836
 * \retval  0 On success.
837
 * \retval -1 On failure.
838
 */
839
static int IPOnlyCIDRListParse(const DetectEngineCtx *de_ctx, IPOnlyCIDRItem **gh, const char *str)
840
256k
{
841
256k
    SCLogDebug("gh %p, str %s", gh, str);
842
843
256k
    if (gh == NULL)
844
0
        goto error;
845
846
256k
    *gh = IPOnlyCIDRListParse2(de_ctx, str, 0);
847
256k
    if (*gh == NULL) {
848
1.93k
        SCLogDebug("IPOnlyCIDRListParse2 returned null");
849
1.93k
        goto error;
850
1.93k
    }
851
852
254k
    return 0;
853
854
1.93k
error:
855
1.93k
    return -1;
856
256k
}
857
858
/**
859
 * \brief Parses an address group sent as a character string and updates the
860
 *        IPOnlyCIDRItem lists src and dst of the Signature *s
861
 *
862
 * \param s Pointer to the signature structure
863
 * \param addrstr Pointer to the character string containing the address group
864
 *            that has to be parsed.
865
 * \param flag to indicate if we are parsing the src string or the dst string
866
 *
867
 * \retval  0 On success.
868
 * \retval -1 On failure.
869
 */
870
int IPOnlySigParseAddress(const DetectEngineCtx *de_ctx,
871
                          Signature *s, const char *addrstr, char flag)
872
256k
{
873
256k
    SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
874
875
    /* pass on to the address(list) parser */
876
256k
    if (flag == 0) {
877
128k
        if (strcasecmp(addrstr, "any") == 0) {
878
99.8k
            s->flags |= SIG_FLAG_SRC_ANY;
879
99.8k
            if (IPOnlyCIDRListParse(de_ctx, &s->cidr_src, "[0.0.0.0/0,::/0]") < 0)
880
0
                goto error;
881
882
99.8k
        } else if (IPOnlyCIDRListParse(de_ctx, &s->cidr_src, (char *)addrstr) < 0) {
883
851
            goto error;
884
851
        }
885
886
        /* IPOnlyCIDRListPrint(s->CidrSrc); */
887
128k
    } else {
888
127k
        if (strcasecmp(addrstr, "any") == 0) {
889
96.0k
            s->flags |= SIG_FLAG_DST_ANY;
890
96.0k
            if (IPOnlyCIDRListParse(de_ctx, &s->cidr_dst, "[0.0.0.0/0,::/0]") < 0)
891
0
                goto error;
892
893
96.0k
        } else if (IPOnlyCIDRListParse(de_ctx, &s->cidr_dst, (char *)addrstr) < 0) {
894
1.08k
            goto error;
895
1.08k
        }
896
897
        /* IPOnlyCIDRListPrint(s->CidrDst); */
898
127k
    }
899
900
254k
    return 0;
901
902
1.93k
error:
903
1.93k
    SCLogError("failed to parse addresses");
904
1.93k
    return -1;
905
256k
}
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
 */
913
void IPOnlyInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
914
140k
{
915
140k
    io_ctx->tree_ipv4src = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
916
140k
    io_ctx->tree_ipv4dst = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
917
140k
    io_ctx->tree_ipv6src = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
918
140k
    io_ctx->tree_ipv6dst = SCRadixCreateRadixTree(SigNumArrayFree, SigNumArrayPrint);
919
920
140k
    io_ctx->sig_mapping = SCCalloc(1, de_ctx->sig_array_len * sizeof(uint32_t));
921
140k
    if (io_ctx->sig_mapping == NULL) {
922
0
        FatalError("Unable to allocate iponly signature tracking area");
923
0
    }
924
140k
    io_ctx->sig_mapping_size = 0;
925
140k
}
926
927
SigIntId IPOnlyTrackSigNum(DetectEngineIPOnlyCtx *io_ctx, SigIntId signum)
928
15.6k
{
929
15.6k
    SigIntId loc = io_ctx->sig_mapping_size;
930
15.6k
    io_ctx->sig_mapping[loc] = signum;
931
15.6k
    io_ctx->sig_mapping_size++;
932
15.6k
    return loc;
933
15.6k
}
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
 */
941
void IPOnlyPrint(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
942
140k
{
943
    /* XXX: how are we going to print the stats now? */
944
140k
}
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
 */
952
void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
953
64.3k
{
954
955
64.3k
    if (io_ctx == NULL)
956
0
        return;
957
958
64.3k
    if (io_ctx->tree_ipv4src != NULL)
959
64.3k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv4src);
960
64.3k
    io_ctx->tree_ipv4src = NULL;
961
962
64.3k
    if (io_ctx->tree_ipv4dst != NULL)
963
64.3k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv4dst);
964
64.3k
    io_ctx->tree_ipv4dst = NULL;
965
966
64.3k
    if (io_ctx->tree_ipv6src != NULL)
967
64.3k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv6src);
968
64.3k
    io_ctx->tree_ipv6src = NULL;
969
970
64.3k
    if (io_ctx->tree_ipv6dst != NULL)
971
64.3k
        SCRadixReleaseRadixTree(io_ctx->tree_ipv6dst);
972
64.3k
    io_ctx->tree_ipv6dst = NULL;
973
974
64.3k
    if (io_ctx->sig_mapping != NULL)
975
64.3k
        SCFree(io_ctx->sig_mapping);
976
64.3k
    io_ctx->sig_mapping = NULL;
977
64.3k
}
978
979
static inline
980
int IPOnlyMatchCompatSMs(ThreadVars *tv,
981
                         DetectEngineThreadCtx *det_ctx,
982
                         Signature *s, Packet *p)
983
53.7k
{
984
53.7k
    KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_MATCH);
985
53.7k
    SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
986
53.7k
    if (smd) {
987
411
        while (1) {
988
411
            DEBUG_VALIDATE_BUG_ON(!(sigmatch_table[smd->type].flags & SIGMATCH_IPONLY_COMPAT));
989
411
            KEYWORD_PROFILING_START;
990
411
            if (sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx) > 0) {
991
21
                KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
992
21
                if (smd->is_last)
993
21
                    break;
994
0
                smd++;
995
0
                continue;
996
21
            }
997
390
            KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
998
390
            return 0;
999
411
        }
1000
411
    }
1001
53.3k
    return 1;
1002
53.7k
}
1003
1004
/**
1005
 * \brief Match a packet against the IP Only detection engine contexts
1006
 *
1007
 * \param de_ctx Pointer to the current detection engine
1008
 * \param io_ctx Pointer to the current ip only detection engine
1009
 * \param io_ctx Pointer to the current ip only thread detection engine
1010
 * \param p Pointer to the Packet to match against
1011
 */
1012
void IPOnlyMatchPacket(ThreadVars *tv, const DetectEngineCtx *de_ctx,
1013
        DetectEngineThreadCtx *det_ctx, const DetectEngineIPOnlyCtx *io_ctx, Packet *p)
1014
2.69M
{
1015
2.69M
    SigNumArray *src = NULL;
1016
2.69M
    SigNumArray *dst = NULL;
1017
2.69M
    void *user_data_src = NULL, *user_data_dst = NULL;
1018
1019
2.69M
    SCEnter();
1020
1021
2.69M
    if (p->src.family == AF_INET) {
1022
808k
        (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_SRC_ADDR_U32(p),
1023
808k
                                              io_ctx->tree_ipv4src, &user_data_src);
1024
1.88M
    } else if (p->src.family == AF_INET6) {
1025
229k
        (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p),
1026
229k
                                              io_ctx->tree_ipv6src, &user_data_src);
1027
229k
    }
1028
1029
2.69M
    if (p->dst.family == AF_INET) {
1030
808k
        (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_DST_ADDR_U32(p),
1031
808k
                                              io_ctx->tree_ipv4dst, &user_data_dst);
1032
1.88M
    } else if (p->dst.family == AF_INET6) {
1033
229k
        (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p),
1034
229k
                                              io_ctx->tree_ipv6dst, &user_data_dst);
1035
229k
    }
1036
1037
2.69M
    src = user_data_src;
1038
2.69M
    dst = user_data_dst;
1039
1040
2.69M
    if (src == NULL || dst == NULL)
1041
2.63M
        SCReturn;
1042
1043
57.5k
    uint32_t u;
1044
115k
    for (u = 0; u < src->size; u++) {
1045
58.0k
        SCLogDebug("And %"PRIu8" & %"PRIu8, src->array[u], dst->array[u]);
1046
1047
58.0k
        uint8_t bitarray = dst->array[u] & src->array[u];
1048
1049
        /* We have to move the logic of the signature checking
1050
         * to the main detect loop, in order to apply the
1051
         * priority of actions (pass, drop, reject, alert) */
1052
58.0k
        if (bitarray) {
1053
            /* We have a match :) Let's see from which signum's */
1054
57.0k
            uint8_t i = 0;
1055
1056
513k
            for (; i < 8; i++, bitarray = bitarray >> 1) {
1057
456k
                if (bitarray & 0x01) {
1058
89.2k
                    Signature *s = de_ctx->sig_array[io_ctx->sig_mapping[u * 8 + i]];
1059
1060
89.2k
                    if ((s->proto.flags & DETECT_PROTO_IPV4) && !PKT_IS_IPV4(p)) {
1061
0
                        SCLogDebug("ip version didn't match");
1062
0
                        continue;
1063
0
                    }
1064
89.2k
                    if ((s->proto.flags & DETECT_PROTO_IPV6) && !PKT_IS_IPV6(p)) {
1065
550
                        SCLogDebug("ip version didn't match");
1066
550
                        continue;
1067
550
                    }
1068
1069
88.6k
                    if (DetectProtoContainsProto(&s->proto, IP_GET_IPPROTO(p)) == 0) {
1070
13.8k
                        SCLogDebug("proto didn't match");
1071
13.8k
                        continue;
1072
13.8k
                    }
1073
1074
                    /* check the source & dst port in the sig */
1075
74.8k
                    if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
1076
62.4k
                        if (!(s->flags & SIG_FLAG_DP_ANY)) {
1077
14.7k
                            if (p->flags & PKT_IS_FRAGMENT)
1078
592
                                continue;
1079
1080
14.1k
                            DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
1081
14.1k
                            if (dport == NULL) {
1082
13.5k
                                SCLogDebug("dport didn't match.");
1083
13.5k
                                continue;
1084
13.5k
                            }
1085
14.1k
                        }
1086
48.2k
                        if (!(s->flags & SIG_FLAG_SP_ANY)) {
1087
6.43k
                            if (p->flags & PKT_IS_FRAGMENT)
1088
564
                                continue;
1089
1090
5.86k
                            DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
1091
5.86k
                            if (sport == NULL) {
1092
5.80k
                                SCLogDebug("sport didn't match.");
1093
5.80k
                                continue;
1094
5.80k
                            }
1095
5.86k
                        }
1096
48.2k
                    } else if ((s->flags & (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) != (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) {
1097
604
                        SCLogDebug("port-less protocol and sig needs ports");
1098
604
                        continue;
1099
604
                    }
1100
1101
53.7k
                    if (!IPOnlyMatchCompatSMs(tv, det_ctx, s, p)) {
1102
390
                        continue;
1103
390
                    }
1104
1105
53.3k
                    SCLogDebug("Signum %"PRIu32" match (sid: %"PRIu32", msg: %s)",
1106
53.3k
                               u * 8 + i, s->id, s->msg);
1107
1108
53.3k
                    if (s->sm_arrays[DETECT_SM_LIST_POSTMATCH] != NULL) {
1109
9.11k
                        KEYWORD_PROFILING_SET_LIST(det_ctx, DETECT_SM_LIST_POSTMATCH);
1110
9.11k
                        SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_POSTMATCH];
1111
1112
9.11k
                        SCLogDebug("running match functions, sm %p", smd);
1113
1114
9.11k
                        if (smd != NULL) {
1115
31.7k
                            while (1) {
1116
31.7k
                                KEYWORD_PROFILING_START;
1117
31.7k
                                (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
1118
31.7k
                                KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
1119
31.7k
                                if (smd->is_last)
1120
9.11k
                                    break;
1121
22.6k
                                smd++;
1122
22.6k
                            }
1123
9.11k
                        }
1124
9.11k
                    }
1125
53.3k
                    AlertQueueAppend(det_ctx, s, p, 0, 0);
1126
53.3k
                }
1127
456k
            }
1128
57.0k
        }
1129
58.0k
    }
1130
57.5k
    SCReturn;
1131
2.69M
}
1132
1133
/**
1134
 * \brief Build the radix trees from the lists of parsed addresses in CIDR format
1135
 *        the result should be 4 radix trees: src/dst ipv4 and src/dst ipv6
1136
 *        holding SigNumArrays, each of them with a hierarchical relation
1137
 *        of subnets and hosts
1138
 *
1139
 * \param de_ctx Pointer to the current detection engine
1140
 */
1141
void IPOnlyPrepare(DetectEngineCtx *de_ctx)
1142
64.3k
{
1143
64.3k
    SCLogDebug("Preparing Final Lists");
1144
1145
    /*
1146
       IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_src);
1147
       IPOnlyCIDRListPrint((de_ctx->io_ctx).ip_dst);
1148
     */
1149
1150
64.3k
    IPOnlyCIDRListQSort(&(de_ctx->io_ctx).ip_src);
1151
64.3k
    IPOnlyCIDRListQSort(&(de_ctx->io_ctx).ip_dst);
1152
1153
64.3k
    IPOnlyCIDRItem *src, *dst;
1154
64.3k
    SCRadixNode *node = NULL;
1155
1156
    /* Prepare Src radix trees */
1157
85.0k
    for (src = (de_ctx->io_ctx).ip_src; src != NULL; ) {
1158
20.6k
        if (src->family == AF_INET) {
1159
        /*
1160
            SCLogDebug("To IPv4");
1161
            SCLogDebug("Item has netmask %"PRIu16" negated: %s; IP: %s; "
1162
                       "signum: %"PRIu16, src->netmask,
1163
                        (src->negated) ? "yes":"no",
1164
                        inet_ntoa( *(struct in_addr*)&src->ip[0]),
1165
                        src->signum);
1166
        */
1167
1168
10.3k
            void *user_data = NULL;
1169
10.3k
            if (src->netmask == 32)
1170
569
                (void)SCRadixFindKeyIPV4ExactMatch((uint8_t *)&src->ip[0],
1171
569
                                                    (de_ctx->io_ctx).tree_ipv4src,
1172
569
                                                    &user_data);
1173
9.79k
            else
1174
9.79k
                (void)SCRadixFindKeyIPV4Netblock((uint8_t *)&src->ip[0],
1175
9.79k
                                                  (de_ctx->io_ctx).tree_ipv4src,
1176
9.79k
                                                  src->netmask, &user_data);
1177
10.3k
            if (user_data == NULL) {
1178
5.58k
                SCLogDebug("Exact match not found");
1179
1180
                /** Not found, look if there's a subnet of this range with
1181
                 * bigger netmask */
1182
5.58k
                (void)SCRadixFindKeyIPV4BestMatch((uint8_t *)&src->ip[0],
1183
5.58k
                                                   (de_ctx->io_ctx).tree_ipv4src,
1184
5.58k
                                                   &user_data);
1185
5.58k
                if (user_data == NULL) {
1186
4.28k
                    SCLogDebug("best match not found");
1187
1188
                    /* Not found, insert a new one */
1189
4.28k
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1190
1191
                    /* Update the sig */
1192
4.28k
                    uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1193
1194
4.28k
                    if (src->negated > 0)
1195
                        /* Unset it */
1196
0
                        sna->array[src->signum / 8] &= ~tmp;
1197
4.28k
                    else
1198
                        /* Set it */
1199
4.28k
                        sna->array[src->signum / 8] |= tmp;
1200
1201
4.28k
                    if (src->netmask == 32)
1202
54
                        node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1203
54
                                                 (de_ctx->io_ctx).tree_ipv4src, sna);
1204
4.23k
                    else
1205
4.23k
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1206
4.23k
                                                         (de_ctx->io_ctx).tree_ipv4src,
1207
4.23k
                                                         sna, src->netmask);
1208
1209
4.28k
                    if (node == NULL)
1210
0
                        SCLogError("Error inserting in the "
1211
4.28k
                                   "src ipv4 radix tree");
1212
4.28k
                } else {
1213
1.29k
                    SCLogDebug("Best match found");
1214
1215
                    /* Found, copy the sig num table, add this signum and insert */
1216
1.29k
                    SigNumArray *sna = NULL;
1217
1.29k
                    sna = SigNumArrayCopy((SigNumArray *) user_data);
1218
1219
                    /* Update the sig */
1220
1.29k
                    uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1221
1222
1.29k
                    if (src->negated > 0)
1223
                        /* Unset it */
1224
0
                        sna->array[src->signum / 8] &= ~tmp;
1225
1.29k
                    else
1226
                        /* Set it */
1227
1.29k
                        sna->array[src->signum / 8] |= tmp;
1228
1229
1.29k
                    if (src->netmask == 32)
1230
296
                        node = SCRadixAddKeyIPV4((uint8_t *)&src->ip[0],
1231
296
                                                 (de_ctx->io_ctx).tree_ipv4src, sna);
1232
998
                    else
1233
998
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&src->ip[0],
1234
998
                                                         (de_ctx->io_ctx).tree_ipv4src, sna,
1235
998
                                                         src->netmask);
1236
1237
1.29k
                    if (node == NULL) {
1238
0
                        char tmpstr[64];
1239
0
                        PrintInet(src->family, &src->ip[0], tmpstr, sizeof(tmpstr));
1240
0
                        SCLogError("Error inserting in the"
1241
0
                                   " src ipv4 radix tree ip %s netmask %" PRIu8,
1242
0
                                tmpstr, src->netmask);
1243
                        //SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1244
0
                        exit(-1);
1245
0
                    }
1246
1.29k
                }
1247
5.58k
            } else {
1248
4.78k
                SCLogDebug("Exact match found");
1249
1250
                /* it's already inserted. Update it */
1251
4.78k
                SigNumArray *sna = (SigNumArray *)user_data;
1252
1253
                /* Update the sig */
1254
4.78k
                uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1255
1256
4.78k
                if (src->negated > 0)
1257
                    /* Unset it */
1258
0
                    sna->array[src->signum / 8] &= ~tmp;
1259
4.78k
                else
1260
                    /* Set it */
1261
4.78k
                    sna->array[src->signum / 8] |= tmp;
1262
4.78k
            }
1263
10.3k
        } else if (src->family == AF_INET6) {
1264
10.3k
            SCLogDebug("To IPv6");
1265
1266
10.3k
            void *user_data = NULL;
1267
10.3k
            if (src->netmask == 128)
1268
2.03k
                (void)SCRadixFindKeyIPV6ExactMatch((uint8_t *)&src->ip[0],
1269
2.03k
                                                    (de_ctx->io_ctx).tree_ipv6src,
1270
2.03k
                                                    &user_data);
1271
8.29k
            else
1272
8.29k
                (void)SCRadixFindKeyIPV6Netblock((uint8_t *)&src->ip[0],
1273
8.29k
                                                  (de_ctx->io_ctx).tree_ipv6src,
1274
8.29k
                                                  src->netmask, &user_data);
1275
1276
10.3k
            if (user_data == NULL) {
1277
                /* Not found, look if there's a subnet of this range with bigger netmask */
1278
4.90k
                (void)SCRadixFindKeyIPV6BestMatch((uint8_t *)&src->ip[0],
1279
4.90k
                                                   (de_ctx->io_ctx).tree_ipv6src,
1280
4.90k
                                                   &user_data);
1281
1282
4.90k
                if (user_data == NULL) {
1283
                    /* Not found, insert a new one */
1284
3.68k
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1285
1286
                    /* Update the sig */
1287
3.68k
                    uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1288
1289
3.68k
                    if (src->negated > 0)
1290
                        /* Unset it */
1291
1
                        sna->array[src->signum / 8] &= ~tmp;
1292
3.68k
                    else
1293
                        /* Set it */
1294
3.68k
                        sna->array[src->signum / 8] |= tmp;
1295
1296
3.68k
                    if (src->netmask == 128)
1297
118
                        node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1298
118
                                                 (de_ctx->io_ctx).tree_ipv6src, sna);
1299
3.56k
                    else
1300
3.56k
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1301
3.56k
                                                         (de_ctx->io_ctx).tree_ipv6src,
1302
3.56k
                                                         sna, src->netmask);
1303
3.68k
                    if (node == NULL)
1304
0
                        SCLogError("Error inserting in the src "
1305
3.68k
                                   "ipv6 radix tree");
1306
3.68k
                } else {
1307
                    /* Found, copy the sig num table, add this signum and insert */
1308
1.21k
                    SigNumArray *sna = NULL;
1309
1.21k
                    sna = SigNumArrayCopy((SigNumArray *)user_data);
1310
1311
                    /* Update the sig */
1312
1.21k
                    uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1313
1.21k
                    if (src->negated > 0)
1314
                        /* Unset it */
1315
13
                        sna->array[src->signum / 8] &= ~tmp;
1316
1.20k
                    else
1317
                        /* Set it */
1318
1.20k
                        sna->array[src->signum / 8] |= tmp;
1319
1320
1.21k
                    if (src->netmask == 128)
1321
969
                        node = SCRadixAddKeyIPV6((uint8_t *)&src->ip[0],
1322
969
                                                 (de_ctx->io_ctx).tree_ipv6src, sna);
1323
247
                    else
1324
247
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&src->ip[0],
1325
247
                                                         (de_ctx->io_ctx).tree_ipv6src,
1326
247
                                                         sna, src->netmask);
1327
1.21k
                    if (node == NULL)
1328
0
                        SCLogError("Error inserting in the src "
1329
1.21k
                                   "ipv6 radix tree");
1330
1.21k
                }
1331
5.42k
            } else {
1332
                /* it's already inserted. Update it */
1333
5.42k
                SigNumArray *sna = (SigNumArray *)user_data;
1334
1335
                /* Update the sig */
1336
5.42k
                uint8_t tmp = (uint8_t)(1 << (src->signum % 8));
1337
5.42k
                if (src->negated > 0)
1338
                    /* Unset it */
1339
95
                    sna->array[src->signum / 8] &= ~tmp;
1340
5.33k
                else
1341
                    /* Set it */
1342
5.33k
                    sna->array[src->signum / 8] |= tmp;
1343
5.42k
            }
1344
10.3k
        }
1345
20.6k
        IPOnlyCIDRItem *tmpaux = src;
1346
20.6k
        src = src->next;
1347
20.6k
        SCFree(tmpaux);
1348
20.6k
    }
1349
1350
64.3k
    SCLogDebug("dsts:");
1351
1352
    /* Prepare Dst radix trees */
1353
87.5k
    for (dst = (de_ctx->io_ctx).ip_dst; dst != NULL; ) {
1354
23.2k
        if (dst->family == AF_INET) {
1355
1356
11.7k
            SCLogDebug("To IPv4");
1357
11.7k
            SCLogDebug("Item has netmask %"PRIu8" negated: %s; IP: %s; signum:"
1358
11.7k
                       " %"PRIu32"", dst->netmask, (dst->negated)?"yes":"no",
1359
11.7k
                       inet_ntoa(*(struct in_addr*)&dst->ip[0]), dst->signum);
1360
1361
11.7k
            void *user_data = NULL;
1362
11.7k
            if (dst->netmask == 32)
1363
1.54k
                (void) SCRadixFindKeyIPV4ExactMatch((uint8_t *) &dst->ip[0],
1364
1.54k
                                                    (de_ctx->io_ctx).tree_ipv4dst,
1365
1.54k
                                                    &user_data);
1366
10.2k
            else
1367
10.2k
                (void) SCRadixFindKeyIPV4Netblock((uint8_t *) &dst->ip[0],
1368
10.2k
                                                  (de_ctx->io_ctx).tree_ipv4dst,
1369
10.2k
                                                  dst->netmask,
1370
10.2k
                                                  &user_data);
1371
1372
11.7k
            if (user_data == NULL) {
1373
6.95k
                SCLogDebug("Exact match not found");
1374
1375
                /**
1376
                 * Not found, look if there's a subnet of this range
1377
                 * with bigger netmask
1378
                 */
1379
6.95k
                (void) SCRadixFindKeyIPV4BestMatch((uint8_t *)&dst->ip[0],
1380
6.95k
                                                   (de_ctx->io_ctx).tree_ipv4dst,
1381
6.95k
                                                   &user_data);
1382
6.95k
                if (user_data == NULL) {
1383
4.90k
                    SCLogDebug("Best match not found");
1384
1385
                    /** Not found, insert a new one */
1386
4.90k
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1387
1388
                    /** Update the sig */
1389
4.90k
                    uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1390
4.90k
                    if (dst->negated > 0)
1391
                        /** Unset it */
1392
0
                        sna->array[dst->signum / 8] &= ~tmp;
1393
4.90k
                    else
1394
                        /** Set it */
1395
4.90k
                        sna->array[dst->signum / 8] |= tmp;
1396
1397
4.90k
                    if (dst->netmask == 32)
1398
353
                        node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1399
353
                                                 (de_ctx->io_ctx).tree_ipv4dst, sna);
1400
4.55k
                    else
1401
4.55k
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1402
4.55k
                                                         (de_ctx->io_ctx).tree_ipv4dst,
1403
4.55k
                                                         sna, dst->netmask);
1404
1405
4.90k
                    if (node == NULL)
1406
0
                        SCLogError("Error inserting in the dst "
1407
4.90k
                                   "ipv4 radix tree");
1408
4.90k
                } else {
1409
2.05k
                    SCLogDebug("Best match found");
1410
1411
                    /* Found, copy the sig num table, add this signum and insert */
1412
2.05k
                    SigNumArray *sna = NULL;
1413
2.05k
                    sna = SigNumArrayCopy((SigNumArray *) user_data);
1414
1415
                    /* Update the sig */
1416
2.05k
                    uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1417
2.05k
                    if (dst->negated > 0)
1418
                        /* Unset it */
1419
0
                        sna->array[dst->signum / 8] &= ~tmp;
1420
2.05k
                    else
1421
                        /* Set it */
1422
2.05k
                        sna->array[dst->signum / 8] |= tmp;
1423
1424
2.05k
                    if (dst->netmask == 32)
1425
816
                        node = SCRadixAddKeyIPV4((uint8_t *)&dst->ip[0],
1426
816
                                                 (de_ctx->io_ctx).tree_ipv4dst, sna);
1427
1.23k
                    else
1428
1.23k
                        node = SCRadixAddKeyIPV4Netblock((uint8_t *)&dst->ip[0],
1429
1.23k
                                                         (de_ctx->io_ctx).tree_ipv4dst,
1430
1.23k
                                                          sna, dst->netmask);
1431
1432
2.05k
                    if (node == NULL)
1433
0
                        SCLogError("Error inserting in the dst "
1434
2.05k
                                   "ipv4 radix tree");
1435
2.05k
                }
1436
6.95k
            } else {
1437
4.83k
                SCLogDebug("Exact match found");
1438
1439
                /* it's already inserted. Update it */
1440
4.83k
                SigNumArray *sna = (SigNumArray *)user_data;
1441
1442
                /* Update the sig */
1443
4.83k
                uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1444
4.83k
                if (dst->negated > 0)
1445
                    /* Unset it */
1446
0
                    sna->array[dst->signum / 8] &= ~tmp;
1447
4.83k
                else
1448
                    /* Set it */
1449
4.83k
                    sna->array[dst->signum / 8] |= tmp;
1450
4.83k
            }
1451
11.7k
        } else if (dst->family == AF_INET6) {
1452
11.4k
            SCLogDebug("To IPv6");
1453
1454
11.4k
            void *user_data = NULL;
1455
11.4k
            if (dst->netmask == 128)
1456
3.10k
                (void) SCRadixFindKeyIPV6ExactMatch((uint8_t *)&dst->ip[0],
1457
3.10k
                                                    (de_ctx->io_ctx).tree_ipv6dst,
1458
3.10k
                                                    &user_data);
1459
8.36k
            else
1460
8.36k
                (void) SCRadixFindKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1461
8.36k
                                                  (de_ctx->io_ctx).tree_ipv6dst,
1462
8.36k
                                                  dst->netmask, &user_data);
1463
1464
11.4k
            if (user_data == NULL) {
1465
                /** Not found, look if there's a subnet of this range with
1466
                 * bigger netmask
1467
                 */
1468
5.05k
                (void) SCRadixFindKeyIPV6BestMatch((uint8_t *)&dst->ip[0],
1469
5.05k
                                                   (de_ctx->io_ctx).tree_ipv6dst,
1470
5.05k
                                                   &user_data);
1471
1472
5.05k
                if (user_data == NULL) {
1473
                    /* Not found, insert a new one */
1474
3.69k
                    SigNumArray *sna = SigNumArrayNew(de_ctx, &de_ctx->io_ctx);
1475
1476
                    /* Update the sig */
1477
3.69k
                    uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1478
3.69k
                    if (dst->negated > 0)
1479
                        /* Unset it */
1480
18
                        sna->array[dst->signum / 8] &= ~tmp;
1481
3.67k
                    else
1482
                        /* Set it */
1483
3.67k
                        sna->array[dst->signum / 8] |= tmp;
1484
1485
3.69k
                    if (dst->netmask == 128)
1486
149
                        node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1487
149
                                                 (de_ctx->io_ctx).tree_ipv6dst, sna);
1488
3.54k
                    else
1489
3.54k
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1490
3.54k
                                                         (de_ctx->io_ctx).tree_ipv6dst,
1491
3.54k
                                                          sna, dst->netmask);
1492
1493
3.69k
                    if (node == NULL)
1494
0
                        SCLogError("Error inserting in the dst "
1495
3.69k
                                   "ipv6 radix tree");
1496
3.69k
                } else {
1497
                    /* Found, copy the sig num table, add this signum and insert */
1498
1.35k
                    SigNumArray *sna = NULL;
1499
1.35k
                    sna = SigNumArrayCopy((SigNumArray *)user_data);
1500
1501
                    /* Update the sig */
1502
1.35k
                    uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1503
1.35k
                    if (dst->negated > 0)
1504
                        /* Unset it */
1505
18
                        sna->array[dst->signum / 8] &= ~tmp;
1506
1.33k
                    else
1507
                        /* Set it */
1508
1.33k
                        sna->array[dst->signum / 8] |= tmp;
1509
1510
1.35k
                    if (dst->netmask == 128)
1511
1.09k
                        node = SCRadixAddKeyIPV6((uint8_t *)&dst->ip[0],
1512
1.09k
                                                 (de_ctx->io_ctx).tree_ipv6dst, sna);
1513
258
                    else
1514
258
                        node = SCRadixAddKeyIPV6Netblock((uint8_t *)&dst->ip[0],
1515
258
                                                         (de_ctx->io_ctx).tree_ipv6dst,
1516
258
                                                         sna, dst->netmask);
1517
1518
1.35k
                    if (node == NULL)
1519
0
                        SCLogError("Error inserting in the dst "
1520
1.35k
                                   "ipv6 radix tree");
1521
1.35k
                }
1522
6.41k
            } else {
1523
                /* it's already inserted. Update it */
1524
6.41k
                SigNumArray *sna = (SigNumArray *)user_data;
1525
1526
                /* Update the sig */
1527
6.41k
                uint8_t tmp = (uint8_t)(1 << (dst->signum % 8));
1528
6.41k
                if (dst->negated > 0)
1529
                    /* Unset it */
1530
405
                    sna->array[dst->signum / 8] &= ~tmp;
1531
6.01k
                else
1532
                    /* Set it */
1533
6.01k
                    sna->array[dst->signum / 8] |= tmp;
1534
6.41k
            }
1535
11.4k
        }
1536
23.2k
        IPOnlyCIDRItem *tmpaux = dst;
1537
23.2k
        dst = dst->next;
1538
23.2k
        SCFree(tmpaux);
1539
23.2k
    }
1540
1541
    /* print all the trees: for debugging it might print too much info
1542
    SCLogDebug("Radix tree src ipv4:");
1543
    SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4src);
1544
    SCLogDebug("Radix tree src ipv6:");
1545
    SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6src);
1546
    SCLogDebug("__________________");
1547
1548
    SCLogDebug("Radix tree dst ipv4:");
1549
    SCRadixPrintTree((de_ctx->io_ctx).tree_ipv4dst);
1550
    SCLogDebug("Radix tree dst ipv6:");
1551
    SCRadixPrintTree((de_ctx->io_ctx).tree_ipv6dst);
1552
    SCLogDebug("__________________");
1553
    */
1554
64.3k
}
1555
1556
/**
1557
 * \brief Add a signature to the lists of Addresses in CIDR format (sorted)
1558
 *        this step is necessary to build the radix tree with a hierarchical
1559
 *        relation between nodes
1560
 * \param de_ctx Pointer to the current detection engine context
1561
 * \param de_ctx Pointer to the current ip only detection engine contest
1562
 * \param s Pointer to the current signature
1563
 */
1564
void IPOnlyAddSignature(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx,
1565
                        Signature *s)
1566
15.6k
{
1567
15.6k
    if (!(s->type == SIG_TYPE_IPONLY))
1568
0
        return;
1569
1570
15.6k
    SigIntId mapped_signum = IPOnlyTrackSigNum(io_ctx, s->num);
1571
15.6k
    SCLogDebug("Adding IPs from rule: %" PRIu32 " (%s) as %" PRIu32 " mapped to %" PRIu32 "\n",
1572
15.6k
            s->id, s->msg, s->num, mapped_signum);
1573
    /* Set the internal signum to the list before merging */
1574
15.6k
    IPOnlyCIDRListSetSigNum(s->cidr_src, mapped_signum);
1575
1576
15.6k
    IPOnlyCIDRListSetSigNum(s->cidr_dst, mapped_signum);
1577
1578
    /**
1579
     * ipv4 and ipv6 are mixed, but later we will separate them into
1580
     * different trees
1581
     */
1582
15.6k
    io_ctx->ip_src = IPOnlyCIDRItemInsert(io_ctx->ip_src, s->cidr_src);
1583
15.6k
    io_ctx->ip_dst = IPOnlyCIDRItemInsert(io_ctx->ip_dst, s->cidr_dst);
1584
1585
15.6k
    if (mapped_signum > io_ctx->max_idx)
1586
7.44k
        io_ctx->max_idx = mapped_signum;
1587
1588
    /** no longer ref to this, it's in the table now */
1589
15.6k
    s->cidr_src = NULL;
1590
15.6k
    s->cidr_dst = NULL;
1591
15.6k
}
1592
1593
#ifdef UNITTESTS
1594
/**
1595
 * \test check that we set a Signature as IPOnly because it has no rule
1596
 *       option appending a SigMatch and no port is fixed
1597
 */
1598
1599
static int IPOnlyTestSig01(void)
1600
{
1601
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1602
    FAIL_IF(de_ctx == NULL);
1603
    de_ctx->flags |= DE_QUIET;
1604
1605
    Signature *s = SigInit(de_ctx,"alert tcp any any -> any any (sid:400001; rev:1;)");
1606
    FAIL_IF(s == NULL);
1607
1608
    FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1609
    SigFree(de_ctx, s);
1610
    DetectEngineCtxFree(de_ctx);
1611
    PASS;
1612
}
1613
1614
/**
1615
 * \test check that we don't set a Signature as IPOnly because it has no rule
1616
 *       option appending a SigMatch but a port is fixed
1617
 */
1618
1619
static int IPOnlyTestSig02 (void)
1620
{
1621
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1622
    FAIL_IF(de_ctx == NULL);
1623
    de_ctx->flags |= DE_QUIET;
1624
1625
    Signature *s = SigInit(de_ctx,"alert tcp any any -> any 80 (sid:400001; rev:1;)");
1626
    FAIL_IF(s == NULL);
1627
1628
    FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
1629
    SigFree(de_ctx, s);
1630
    DetectEngineCtxFree(de_ctx);
1631
    PASS;
1632
}
1633
1634
/**
1635
 * \test check that we set don't set a Signature as IPOnly
1636
 *  because it has rule options appending a SigMatch like content, and pcre
1637
 */
1638
1639
static int IPOnlyTestSig03 (void)
1640
{
1641
    int result = 1;
1642
    DetectEngineCtx *de_ctx;
1643
    Signature *s=NULL;
1644
1645
    de_ctx = DetectEngineCtxInit();
1646
    if (de_ctx == NULL)
1647
        goto end;
1648
    de_ctx->flags |= DE_QUIET;
1649
1650
    /* combination of pcre and content */
1651
    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;)");
1652
    if (s == NULL) {
1653
        goto end;
1654
    }
1655
    if(SignatureIsIPOnly(de_ctx, s))
1656
    {
1657
        printf("got a IPOnly signature (content): ");
1658
        result=0;
1659
    }
1660
    SigFree(de_ctx, s);
1661
1662
    /* content */
1663
    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;)");
1664
    if (s == NULL) {
1665
        goto end;
1666
    }
1667
    if(SignatureIsIPOnly(de_ctx, s))
1668
    {
1669
        printf("got a IPOnly signature (content): ");
1670
        result=0;
1671
    }
1672
    SigFree(de_ctx, s);
1673
1674
    /* uricontent */
1675
    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;)");
1676
    if (s == NULL) {
1677
        goto end;
1678
    }
1679
    if(SignatureIsIPOnly(de_ctx, s))
1680
    {
1681
        printf("got a IPOnly signature (uricontent): ");
1682
        result=0;
1683
    }
1684
    SigFree(de_ctx, s);
1685
1686
    /* pcre */
1687
    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;)");
1688
    if (s == NULL) {
1689
        goto end;
1690
    }
1691
    if(SignatureIsIPOnly(de_ctx, s))
1692
    {
1693
        printf("got a IPOnly signature (pcre): ");
1694
        result=0;
1695
    }
1696
    SigFree(de_ctx, s);
1697
1698
    /* flow */
1699
    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;)");
1700
    if (s == NULL) {
1701
        goto end;
1702
    }
1703
    if(SignatureIsIPOnly(de_ctx, s))
1704
    {
1705
        printf("got a IPOnly signature (flow): ");
1706
        result=0;
1707
    }
1708
    SigFree(de_ctx, s);
1709
1710
    /* dsize */
1711
    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;)");
1712
    if (s == NULL) {
1713
        goto end;
1714
    }
1715
    if(SignatureIsIPOnly(de_ctx, s))
1716
    {
1717
        printf("got a IPOnly signature (dsize): ");
1718
        result=0;
1719
    }
1720
    SigFree(de_ctx, s);
1721
1722
    /* flowbits */
1723
    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;)");
1724
    if (s == NULL) {
1725
        goto end;
1726
    }
1727
    if(SignatureIsIPOnly(de_ctx, s))
1728
    {
1729
        printf("got a IPOnly signature (flowbits): ");
1730
        result=0;
1731
    }
1732
    SigFree(de_ctx, s);
1733
1734
    /* flowvar */
1735
    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;)");
1736
    if (s == NULL) {
1737
        goto end;
1738
    }
1739
    if(SignatureIsIPOnly(de_ctx, s))
1740
    {
1741
        printf("got a IPOnly signature (flowvar): ");
1742
        result=0;
1743
    }
1744
    SigFree(de_ctx, s);
1745
1746
    /* pktvar */
1747
    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;)");
1748
    if (s == NULL) {
1749
        goto end;
1750
    }
1751
    if(SignatureIsIPOnly(de_ctx, s))
1752
    {
1753
        printf("got a IPOnly signature (pktvar): ");
1754
        result=0;
1755
    }
1756
    SigFree(de_ctx, s);
1757
1758
end:
1759
    if (de_ctx != NULL)
1760
        DetectEngineCtxFree(de_ctx);
1761
    return result;
1762
}
1763
1764
/**
1765
 * \test
1766
 */
1767
static int IPOnlyTestSig04 (void)
1768
{
1769
    int result = 1;
1770
    IPOnlyCIDRItem *head = NULL;
1771
1772
    // Test a linked list of size 0, 1, 2, ..., 5
1773
    for (int size = 0; size < 6; size++) {
1774
        IPOnlyCIDRItem *new = NULL;
1775
1776
        if (size > 0) {
1777
            new = IPOnlyCIDRItemNew();
1778
            new->netmask = 10;
1779
            new->ip[0] = 3;
1780
1781
            head = IPOnlyCIDRItemInsert(head, new);
1782
        }
1783
1784
        if (size > 1) {
1785
            new = IPOnlyCIDRItemNew();
1786
            new->netmask = 11;
1787
1788
            head = IPOnlyCIDRItemInsert(head, new);
1789
        }
1790
1791
        if (size > 2) {
1792
            new = IPOnlyCIDRItemNew();
1793
            new->netmask = 9;
1794
1795
            head = IPOnlyCIDRItemInsert(head, new);
1796
        }
1797
1798
        if (size > 3) {
1799
            new = IPOnlyCIDRItemNew();
1800
            new->netmask = 10;
1801
            new->ip[0] = 1;
1802
1803
            head = IPOnlyCIDRItemInsert(head, new);
1804
        }
1805
1806
        if (size > 4) {
1807
            new = IPOnlyCIDRItemNew();
1808
            new->netmask = 10;
1809
            new->ip[0] = 2;
1810
1811
            head = IPOnlyCIDRItemInsert(head, new);
1812
        }
1813
1814
        IPOnlyCIDRListPrint(head);
1815
1816
        IPOnlyCIDRListQSort(&head);
1817
1818
        if (size == 0) {
1819
            if (head != NULL) {
1820
                result = 0;
1821
                goto end;
1822
            }
1823
        }
1824
1825
        /**
1826
         * Validate the following list entries for each size
1827
         * 1 - 10
1828
         * 2 - 10<3> 11
1829
         * 3 - 9     10<3> 11
1830
         * 4 - 9     10<1> 10<3> 11
1831
         * 5 - 9     10<1> 10<2> 10<3> 11
1832
         */
1833
        new = head;
1834
        if (size >= 3) {
1835
            if (new->netmask != 9) {
1836
                result = 0;
1837
                goto end;
1838
            }
1839
            new = new->next;
1840
        }
1841
1842
        if (size >= 4) {
1843
            if (new->netmask != 10 || new->ip[0] != 1) {
1844
                result = 0;
1845
                goto end;
1846
            }
1847
            new = new->next;
1848
        }
1849
1850
        if (size >= 5) {
1851
            if (new->netmask != 10 || new->ip[0] != 2) {
1852
                result = 0;
1853
                goto end;
1854
            }
1855
            new = new->next;
1856
        }
1857
1858
        if (size >= 1) {
1859
            if (new->netmask != 10 || new->ip[0] != 3) {
1860
                result = 0;
1861
                goto end;
1862
            }
1863
            new = new->next;
1864
        }
1865
1866
        if (size >= 2) {
1867
            if (new->netmask != 11) {
1868
                result = 0;
1869
                goto end;
1870
            }
1871
            new = new->next;
1872
        }
1873
1874
        if (new != NULL) {
1875
            result = 0;
1876
            goto end;
1877
        }
1878
1879
        IPOnlyCIDRListFree(head);
1880
        head = NULL;
1881
    }
1882
1883
end:
1884
    if (head) {
1885
        IPOnlyCIDRListFree(head);
1886
        head = NULL;
1887
    }
1888
    return result;
1889
}
1890
1891
/**
1892
 * \test Test a set of ip only signatures making use a lot of
1893
 * addresses for src and dst (all should match)
1894
 */
1895
static int IPOnlyTestSig05(void)
1896
{
1897
    int result = 0;
1898
    uint8_t *buf = (uint8_t *)"Hi all!";
1899
    uint16_t buflen = strlen((char *)buf);
1900
1901
    uint8_t numpkts = 1;
1902
    uint8_t numsigs = 7;
1903
1904
    Packet *p[1];
1905
1906
    p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1907
1908
    const char *sigs[numsigs];
1909
    sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1910
    sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1911
    sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1912
    sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1913
    sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1914
    sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1915
    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;)";
1916
1917
    /* Sid numbers (we could extract them from the sig) */
1918
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1919
    uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
1920
1921
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1922
1923
    UTHFreePackets(p, numpkts);
1924
1925
    return result;
1926
}
1927
1928
/**
1929
 * \test Test a set of ip only signatures making use a lot of
1930
 * addresses for src and dst (none should match)
1931
 */
1932
static int IPOnlyTestSig06(void)
1933
{
1934
    int result = 0;
1935
    uint8_t *buf = (uint8_t *)"Hi all!";
1936
    uint16_t buflen = strlen((char *)buf);
1937
1938
    uint8_t numpkts = 1;
1939
    uint8_t numsigs = 7;
1940
1941
    Packet *p[1];
1942
1943
    p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "80.58.0.33", "195.235.113.3");
1944
1945
    const char *sigs[numsigs];
1946
    sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
1947
    sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
1948
    sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; sid:3;)";
1949
    sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; sid:4;)";
1950
    sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
1951
    sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1952
    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;)";
1953
1954
    /* Sid numbers (we could extract them from the sig) */
1955
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
1956
    uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
1957
1958
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
1959
1960
    UTHFreePackets(p, numpkts);
1961
1962
    return result;
1963
}
1964
1965
/* \todo fix it.  We have disabled this unittest because 599 exposes 608,
1966
 * which is why these unittests fail.  When we fix 608, we need to renable
1967
 * these sigs */
1968
#if 0
1969
/**
1970
 * \test Test a set of ip only signatures making use a lot of
1971
 * addresses for src and dst (all should match)
1972
 */
1973
static int IPOnlyTestSig07(void)
1974
{
1975
    int result = 0;
1976
    uint8_t *buf = (uint8_t *)"Hi all!";
1977
    uint16_t buflen = strlen((char *)buf);
1978
1979
    uint8_t numpkts = 1;
1980
    uint8_t numsigs = 7;
1981
1982
    Packet *p[1];
1983
1984
    p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1985
1986
    char *sigs[numsigs];
1987
    sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
1988
    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;)";
1989
    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;)";
1990
    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;)";
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 -> [192.168.0.0/16,!192.168.1.0/24,192.168.1.1] any (msg:\"Testing src/dst ip (sid 6)\"; sid:6;)";
1993
    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" */
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[7] = { 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)
2010
 */
2011
static int IPOnlyTestSig08(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 = 1;
2018
    uint8_t numsigs = 7;
2019
2020
    Packet *p[1];
2021
2022
    p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
2023
2024
    const char *sigs[numsigs];
2025
    sigs[0]= "alert tcp 192.168.1.5 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 1)\"; sid:1;)";
2026
    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;)";
2027
    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;)";
2028
    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;)";
2029
    sigs[4]= "alert tcp any any -> !192.168.1.5 any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2030
    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;)";
2031
    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" */
2032
2033
    /* Sid numbers (we could extract them from the sig) */
2034
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2035
    uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
2036
2037
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2038
2039
    UTHFreePackets(p, numpkts);
2040
2041
    return result;
2042
}
2043
2044
/**
2045
 * \test Test a set of ip only signatures making use a lot of
2046
 * addresses for src and dst (all should match)
2047
 */
2048
static int IPOnlyTestSig09(void)
2049
{
2050
    int result = 0;
2051
    uint8_t *buf = (uint8_t *)"Hi all!";
2052
    uint16_t buflen = strlen((char *)buf);
2053
2054
    uint8_t numpkts = 1;
2055
    uint8_t numsigs = 7;
2056
2057
    Packet *p[1];
2058
2059
    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");
2060
2061
    const char *sigs[numsigs];
2062
    sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2063
    sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2064
    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;)";
2065
    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;)";
2066
    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;)";
2067
    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;)";
2068
    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;)";
2069
2070
    /* Sid numbers (we could extract them from the sig) */
2071
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2072
    uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2073
2074
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2075
2076
    UTHFreePackets(p, numpkts);
2077
2078
    return result;
2079
}
2080
2081
/**
2082
 * \test Test a set of ip only signatures making use a lot of
2083
 * addresses for src and dst (none should match)
2084
 */
2085
static int IPOnlyTestSig10(void)
2086
{
2087
    int result = 0;
2088
    uint8_t *buf = (uint8_t *)"Hi all!";
2089
    uint16_t buflen = strlen((char *)buf);
2090
2091
    uint8_t numpkts = 1;
2092
    uint8_t numsigs = 7;
2093
2094
    Packet *p[1];
2095
2096
    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");
2097
2098
    const char *sigs[numsigs];
2099
    sigs[0]= "alert tcp 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4565 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2100
    sigs[1]= "alert tcp any any -> 3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2101
    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;)";
2102
    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;)";
2103
    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;)";
2104
    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;)";
2105
    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;)";
2106
2107
    /* Sid numbers (we could extract them from the sig) */
2108
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2109
    uint32_t results[7] = { 0, 0, 0, 0, 0, 0, 0};
2110
2111
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2112
2113
    UTHFreePackets(p, numpkts);
2114
2115
    return result;
2116
}
2117
2118
/* \todo fix it.  We have disabled this unittest because 599 exposes 608,
2119
 * which is why these unittests fail.  When we fix 608, we need to renable
2120
 * these sigs */
2121
#if 0
2122
/**
2123
 * \test Test a set of ip only signatures making use a lot of
2124
 * addresses for src and dst (all should match) with ipv4 and ipv6 mixed
2125
 */
2126
static int IPOnlyTestSig11(void)
2127
{
2128
    int result = 0;
2129
    uint8_t *buf = (uint8_t *)"Hi all!";
2130
    uint16_t buflen = strlen((char *)buf);
2131
2132
    uint8_t numpkts = 2;
2133
    uint8_t numsigs = 7;
2134
2135
    Packet *p[2];
2136
2137
    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");
2138
    p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"192.168.1.1","192.168.1.5");
2139
2140
    char *sigs[numsigs];
2141
    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;)";
2142
    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;)";
2143
    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;)";
2144
    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;)";
2145
    sigs[4]= "alert tcp any any -> any any (msg:\"Testing src/dst ip (sid 5)\"; sid:5;)";
2146
    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;)";
2147
    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" */
2148
2149
    /* Sid numbers (we could extract them from the sig) */
2150
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2151
    uint32_t results[2][7] = {{ 1, 1, 1, 1, 1, 1, 1}, { 1, 1, 1, 1, 1, 1, 1}};
2152
2153
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2154
2155
    UTHFreePackets(p, numpkts);
2156
2157
    return result;
2158
}
2159
#endif
2160
2161
/**
2162
 * \test Test a set of ip only signatures making use a lot of
2163
 * addresses for src and dst (none should match) with ipv4 and ipv6 mixed
2164
 */
2165
static int IPOnlyTestSig12(void)
2166
{
2167
    int result = 0;
2168
    uint8_t *buf = (uint8_t *)"Hi all!";
2169
    uint16_t buflen = strlen((char *)buf);
2170
2171
    uint8_t numpkts = 2;
2172
    uint8_t numsigs = 7;
2173
2174
    Packet *p[2];
2175
2176
    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");
2177
    p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP,"195.85.1.1","80.198.1.5");
2178
2179
    const char *sigs[numsigs];
2180
    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;)";
2181
    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;)";
2182
    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;)";
2183
    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;)";
2184
    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;)";
2185
    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;)";
2186
    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" */
2187
2188
    /* Sid numbers (we could extract them from the sig) */
2189
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2190
    uint32_t results[2][7] = {{ 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}};
2191
2192
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2193
2194
    UTHFreePackets(p, numpkts);
2195
2196
    return result;
2197
}
2198
2199
static int IPOnlyTestSig13(void)
2200
{
2201
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2202
    FAIL_IF(de_ctx == NULL);
2203
    de_ctx->flags |= DE_QUIET;
2204
2205
    Signature *s = SigInit(de_ctx,
2206
                           "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2207
                           "flowbits:set,myflow1; sid:1; rev:1;)");
2208
    FAIL_IF(s == NULL);
2209
2210
    FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 0);
2211
    SigFree(de_ctx, s);
2212
    DetectEngineCtxFree(de_ctx);
2213
    PASS;
2214
}
2215
2216
static int IPOnlyTestSig14(void)
2217
{
2218
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2219
    FAIL_IF(de_ctx == NULL);
2220
    de_ctx->flags |= DE_QUIET;
2221
2222
    Signature *s = SigInit(de_ctx,
2223
                           "alert tcp any any -> any any (msg:\"Test flowbits ip only\"; "
2224
                           "flowbits:set,myflow1; flowbits:isset,myflow2; sid:1; rev:1;)");
2225
    FAIL_IF(s == NULL);
2226
2227
    FAIL_IF(SignatureIsIPOnly(de_ctx, s) == 1);
2228
    SigFree(de_ctx, s);
2229
    DetectEngineCtxFree(de_ctx);
2230
    PASS;
2231
}
2232
2233
static int IPOnlyTestSig15(void)
2234
{
2235
    int result = 0;
2236
    uint8_t *buf = (uint8_t *)"Hi all!";
2237
    uint16_t buflen = strlen((char *)buf);
2238
2239
    uint8_t numpkts = 1;
2240
    uint8_t numsigs = 7;
2241
2242
    Packet *p[1];
2243
    Flow f;
2244
    GenericVar flowvar;
2245
    memset(&f, 0, sizeof(Flow));
2246
    memset(&flowvar, 0, sizeof(GenericVar));
2247
    FLOW_INITIALIZE(&f);
2248
2249
    p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
2250
2251
    p[0]->flow = &f;
2252
    p[0]->flow->flowvar = &flowvar;
2253
    p[0]->flags |= PKT_HAS_FLOW;
2254
    p[0]->flowflags |= (FLOW_PKT_TOSERVER | FLOW_PKT_TOSERVER_FIRST);
2255
2256
    const char *sigs[numsigs];
2257
    sigs[0]= "alert tcp 192.168.1.5 any -> any any (msg:\"Testing src ip (sid 1)\"; "
2258
        "flowbits:set,one; sid:1;)";
2259
    sigs[1]= "alert tcp any any -> 192.168.1.1 any (msg:\"Testing dst ip (sid 2)\"; "
2260
        "flowbits:set,two; sid:2;)";
2261
    sigs[2]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 3)\"; "
2262
        "flowbits:set,three; sid:3;)";
2263
    sigs[3]= "alert tcp 192.168.1.5 any -> 192.168.1.1 any (msg:\"Testing src/dst ip (sid 4)\"; "
2264
        "flowbits:set,four; sid:4;)";
2265
    sigs[4]= "alert tcp 192.168.1.0/24 any -> any any (msg:\"Testing src/dst ip (sid 5)\"; "
2266
        "flowbits:set,five; sid:5;)";
2267
    sigs[5]= "alert tcp any any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 6)\"; "
2268
        "flowbits:set,six; sid:6;)";
2269
    sigs[6]= "alert tcp 192.168.1.0/24 any -> 192.168.0.0/16 any (msg:\"Testing src/dst ip (sid 7)\"; "
2270
        "flowbits:set,seven; content:\"Hi all\"; sid:7;)";
2271
2272
    /* Sid numbers (we could extract them from the sig) */
2273
    uint32_t sid[7] = { 1, 2, 3, 4, 5, 6, 7};
2274
    uint32_t results[7] = { 1, 1, 1, 1, 1, 1, 1};
2275
2276
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2277
2278
    UTHFreePackets(p, numpkts);
2279
2280
    FLOW_DESTROY(&f);
2281
    return result;
2282
}
2283
2284
/**
2285
 * \brief Unittest to show #599.  We fail to match if we have negated addresses.
2286
 */
2287
static int IPOnlyTestSig16(void)
2288
{
2289
    int result = 0;
2290
    uint8_t *buf = (uint8_t *)"Hi all!";
2291
    uint16_t buflen = strlen((char *)buf);
2292
2293
    uint8_t numpkts = 1;
2294
    uint8_t numsigs = 2;
2295
2296
    Packet *p[1];
2297
2298
    p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "100.100.0.0", "50.0.0.0");
2299
2300
    const char *sigs[numsigs];
2301
    sigs[0]= "alert tcp !100.100.0.1 any -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2302
    sigs[1]= "alert tcp any any -> !50.0.0.1 any (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2303
2304
    /* Sid numbers (we could extract them from the sig) */
2305
    uint32_t sid[2] = { 1, 2};
2306
    uint32_t results[2] = { 1, 1};
2307
2308
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2309
2310
    UTHFreePackets(p, numpkts);
2311
2312
    return result;
2313
}
2314
2315
/**
2316
 * \brief Unittest to show #611. Ports on portless protocols.
2317
 */
2318
static int IPOnlyTestSig17(void)
2319
{
2320
    int result = 0;
2321
    uint8_t *buf = (uint8_t *)"Hi all!";
2322
    uint16_t buflen = strlen((char *)buf);
2323
2324
    uint8_t numpkts = 1;
2325
    uint8_t numsigs = 2;
2326
2327
    Packet *p[1];
2328
2329
    p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_ICMP, "100.100.0.0", "50.0.0.0");
2330
2331
    const char *sigs[numsigs];
2332
    sigs[0]= "alert ip 100.100.0.0 80 -> any any (msg:\"Testing src ip (sid 1)\"; sid:1;)";
2333
    sigs[1]= "alert ip any any -> 50.0.0.0 123 (msg:\"Testing dst ip (sid 2)\"; sid:2;)";
2334
2335
    uint32_t sid[2] = { 1, 2};
2336
    uint32_t results[2] = { 0, 0}; /* neither should match */
2337
2338
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2339
2340
    UTHFreePackets(p, numpkts);
2341
2342
    return result;
2343
}
2344
2345
/**
2346
 * \brief Unittest to show #3568 -- IP address range handling
2347
 */
2348
static int IPOnlyTestSig18(void)
2349
{
2350
    int result = 0;
2351
    uint8_t *buf = (uint8_t *)"Hi all!";
2352
    uint16_t buflen = strlen((char *)buf);
2353
2354
    uint8_t numpkts = 4;
2355
    uint8_t numsigs = 4;
2356
2357
    Packet *p[4];
2358
2359
    p[0] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "10.10.10.1", "50.0.0.1");
2360
    p[1] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "220.10.10.1", "5.0.0.1");
2361
    p[2] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "0.0.0.1", "50.0.0.1");
2362
    p[3] = UTHBuildPacketSrcDst((uint8_t *)buf, buflen, IPPROTO_TCP, "255.255.255.254", "5.0.0.1");
2363
2364
    const char *sigs[numsigs];
2365
    // really many IP addresses
2366
    sigs[0]= "alert ip 1.2.3.4-219.6.7.8 any -> any any (sid:1;)";
2367
    sigs[1]= "alert ip 51.2.3.4-253.1.2.3 any -> any any (sid:2;)";
2368
    sigs[2]= "alert ip 0.0.0.0-50.0.0.2 any -> any any (sid:3;)";
2369
    sigs[3]= "alert ip 50.0.0.0-255.255.255.255 any -> any any (sid:4;)";
2370
2371
    uint32_t sid[4] = { 1, 2, 3, 4, };
2372
    uint32_t results[4][4] = {
2373
        { 1, 0, 1, 0, }, { 0, 1, 0, 1}, { 0, 0, 1, 0 }, { 0, 0, 0, 1}};
2374
2375
    result = UTHGenericTest(p, numpkts, sigs, sid, (uint32_t *) results, numsigs);
2376
2377
    UTHFreePackets(p, numpkts);
2378
2379
    FAIL_IF(result != 1);
2380
2381
    PASS;
2382
}
2383
2384
/** \test build IP-only tree */
2385
static int IPOnlyTestBug5066v1(void)
2386
{
2387
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2388
    FAIL_IF(de_ctx == NULL);
2389
    de_ctx->flags |= DE_QUIET;
2390
2391
    Signature *s = DetectEngineAppendSig(
2392
            de_ctx, "alert ip [1.2.3.4/24,1.2.3.64/27] any -> any any (sid:1;)");
2393
    FAIL_IF_NULL(s);
2394
    s = DetectEngineAppendSig(de_ctx, "alert ip [1.2.3.4/24] any -> any any (sid:2;)");
2395
    FAIL_IF_NULL(s);
2396
2397
    SigGroupBuild(de_ctx);
2398
2399
    DetectEngineCtxFree(de_ctx);
2400
    PASS;
2401
}
2402
2403
static int IPOnlyTestBug5066v2(void)
2404
{
2405
    IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2406
    FAIL_IF_NULL(x);
2407
2408
    FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.4/24") != 0);
2409
2410
    char ip[16];
2411
    PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2412
    SCLogDebug("ip %s netmask %d", ip, x->netmask);
2413
2414
    FAIL_IF_NOT(strcmp(ip, "1.2.3.0") == 0);
2415
    FAIL_IF_NOT(x->netmask == 24);
2416
2417
    IPOnlyCIDRListFree(x);
2418
    PASS;
2419
}
2420
2421
static int IPOnlyTestBug5066v3(void)
2422
{
2423
    IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2424
    FAIL_IF_NULL(x);
2425
2426
    FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.64/26") != 0);
2427
2428
    char ip[16];
2429
    PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2430
    SCLogDebug("ip %s netmask %d", ip, x->netmask);
2431
2432
    FAIL_IF_NOT(strcmp(ip, "1.2.3.64") == 0);
2433
    FAIL_IF_NOT(x->netmask == 26);
2434
2435
    IPOnlyCIDRListFree(x);
2436
    PASS;
2437
}
2438
2439
static int IPOnlyTestBug5066v4(void)
2440
{
2441
    IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2442
    FAIL_IF_NULL(x);
2443
2444
    FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "2000::1:1/122") != 0);
2445
2446
    char ip[64];
2447
    PrintInet(AF_INET6, (const void *)&x->ip, ip, sizeof(ip));
2448
    SCLogDebug("ip %s netmask %d", ip, x->netmask);
2449
2450
    FAIL_IF_NOT(strcmp(ip, "2000:0000:0000:0000:0000:0000:0001:0000") == 0);
2451
    FAIL_IF_NOT(x->netmask == 122);
2452
2453
    IPOnlyCIDRListFree(x);
2454
    PASS;
2455
}
2456
2457
static int IPOnlyTestBug5066v5(void)
2458
{
2459
    IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2460
    FAIL_IF_NULL(x);
2461
2462
    FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "2000::1:40/122") != 0);
2463
2464
    char ip[64];
2465
    PrintInet(AF_INET6, (const void *)&x->ip, ip, sizeof(ip));
2466
    SCLogDebug("ip %s netmask %d", ip, x->netmask);
2467
2468
    FAIL_IF_NOT(strcmp(ip, "2000:0000:0000:0000:0000:0000:0001:0040") == 0);
2469
    FAIL_IF_NOT(x->netmask == 122);
2470
2471
    IPOnlyCIDRListFree(x);
2472
    PASS;
2473
}
2474
2475
static int IPOnlyTestBug5168v1(void)
2476
{
2477
    IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2478
    FAIL_IF_NULL(x);
2479
2480
    FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "1.2.3.64/0.0.0.0") != 0);
2481
2482
    char ip[16];
2483
    PrintInet(AF_INET, (const void *)&x->ip[0], ip, sizeof(ip));
2484
    SCLogDebug("ip %s netmask %d", ip, x->netmask);
2485
2486
    FAIL_IF_NOT(strcmp(ip, "0.0.0.0") == 0);
2487
    FAIL_IF_NOT(x->netmask == 0);
2488
2489
    IPOnlyCIDRListFree(x);
2490
    PASS;
2491
}
2492
2493
static int IPOnlyTestBug5168v2(void)
2494
{
2495
    IPOnlyCIDRItem *x = IPOnlyCIDRItemNew();
2496
    FAIL_IF_NULL(x);
2497
    FAIL_IF(IPOnlyCIDRItemParseSingle(&x, "0.0.0.5/0.0.0.5") != -1);
2498
    IPOnlyCIDRListFree(x);
2499
    PASS;
2500
}
2501
2502
#endif /* UNITTESTS */
2503
2504
void IPOnlyRegisterTests(void)
2505
0
{
2506
#ifdef UNITTESTS
2507
    UtRegisterTest("IPOnlyTestSig01", IPOnlyTestSig01);
2508
    UtRegisterTest("IPOnlyTestSig02", IPOnlyTestSig02);
2509
    UtRegisterTest("IPOnlyTestSig03", IPOnlyTestSig03);
2510
    UtRegisterTest("IPOnlyTestSig04", IPOnlyTestSig04);
2511
2512
    UtRegisterTest("IPOnlyTestSig05", IPOnlyTestSig05);
2513
    UtRegisterTest("IPOnlyTestSig06", IPOnlyTestSig06);
2514
/* \todo fix it.  We have disabled this unittest because 599 exposes 608,
2515
 * which is why these unittests fail.  When we fix 608, we need to renable
2516
 * these sigs */
2517
#if 0
2518
    UtRegisterTest("IPOnlyTestSig07", IPOnlyTestSig07, 1);
2519
#endif
2520
    UtRegisterTest("IPOnlyTestSig08", IPOnlyTestSig08);
2521
2522
    UtRegisterTest("IPOnlyTestSig09", IPOnlyTestSig09);
2523
    UtRegisterTest("IPOnlyTestSig10", IPOnlyTestSig10);
2524
/* \todo fix it.  We have disabled this unittest because 599 exposes 608,
2525
 * which is why these unittests fail.  When we fix 608, we need to renable
2526
 * these sigs */
2527
#if 0
2528
    UtRegisterTest("IPOnlyTestSig11", IPOnlyTestSig11, 1);
2529
#endif
2530
    UtRegisterTest("IPOnlyTestSig12", IPOnlyTestSig12);
2531
    UtRegisterTest("IPOnlyTestSig13", IPOnlyTestSig13);
2532
    UtRegisterTest("IPOnlyTestSig14", IPOnlyTestSig14);
2533
    UtRegisterTest("IPOnlyTestSig15", IPOnlyTestSig15);
2534
    UtRegisterTest("IPOnlyTestSig16", IPOnlyTestSig16);
2535
2536
    UtRegisterTest("IPOnlyTestSig17", IPOnlyTestSig17);
2537
    UtRegisterTest("IPOnlyTestSig18", IPOnlyTestSig18);
2538
2539
    UtRegisterTest("IPOnlyTestBug5066v1", IPOnlyTestBug5066v1);
2540
    UtRegisterTest("IPOnlyTestBug5066v2", IPOnlyTestBug5066v2);
2541
    UtRegisterTest("IPOnlyTestBug5066v3", IPOnlyTestBug5066v3);
2542
    UtRegisterTest("IPOnlyTestBug5066v4", IPOnlyTestBug5066v4);
2543
    UtRegisterTest("IPOnlyTestBug5066v5", IPOnlyTestBug5066v5);
2544
2545
    UtRegisterTest("IPOnlyTestBug5168v1", IPOnlyTestBug5168v1);
2546
    UtRegisterTest("IPOnlyTestBug5168v2", IPOnlyTestBug5168v2);
2547
#endif
2548
2549
0
    return;
2550
0
}
2551