Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/ippair-bit.c
Line
Count
Source
1
/* Copyright (C) 2014-2021 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
 *
23
 * Implements per ippair bits. Actually, not a bit,
24
 * but called that way because of Snort's flowbits.
25
 * It's a binary storage.
26
 *
27
 * \todo move away from a linked list implementation
28
 * \todo use different datatypes, such as string, int, etc.
29
 */
30
31
#include "suricata-common.h"
32
#include "threads.h"
33
#include "ippair-bit.h"
34
#include "ippair.h"
35
#include "detect.h"
36
#include "util-var.h"
37
#include "util-debug.h"
38
#include "util-unittest.h"
39
#include "ippair-storage.h"
40
41
static IPPairStorageId g_ippair_bit_storage_id = { .id = -1 }; /**< IPPair storage id for bits */
42
43
static void XBitFreeAll(void *store)
44
0
{
45
0
    GenericVar *gv = store;
46
0
    GenericVarFree(gv);
47
0
}
48
49
void IPPairBitInitCtx(void)
50
71
{
51
71
    g_ippair_bit_storage_id = IPPairStorageRegister("bit", sizeof(void *), NULL, XBitFreeAll);
52
71
    if (g_ippair_bit_storage_id.id == -1) {
53
0
        FatalError("Can't initiate ippair storage for bits");
54
0
    }
55
71
}
56
57
/* lock before using this */
58
int IPPairHasBits(IPPair *ippair)
59
0
{
60
0
    if (ippair == NULL)
61
0
        return 0;
62
0
    return IPPairGetStorageById(ippair, g_ippair_bit_storage_id) ? 1 : 0;
63
0
}
64
65
/** \retval 1 ippair timed out wrt xbits
66
  * \retval 0 ippair still has active (non-expired) xbits */
67
int IPPairBitsTimedoutCheck(IPPair *h, SCTime_t ts)
68
0
{
69
0
    GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
70
0
    for ( ; gv != NULL; gv = gv->next) {
71
0
        if (gv->type == DETECT_XBITS) {
72
0
            XBit *xb = (XBit *)gv;
73
0
            if (xb->expire > (uint32_t)SCTIME_SECS(ts))
74
0
                return 0;
75
0
        }
76
0
    }
77
0
    return 1;
78
0
}
79
80
/* get the bit with idx from the ippair */
81
static XBit *IPPairBitGet(IPPair *h, uint32_t idx)
82
684
{
83
684
    GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
84
1.08k
    for ( ; gv != NULL; gv = gv->next) {
85
577
        if (gv->type == DETECT_XBITS && gv->idx == idx) {
86
176
            return (XBit *)gv;
87
176
        }
88
577
    }
89
90
508
    return NULL;
91
684
}
92
93
/* add a flowbit to the flow */
94
static void IPPairBitAdd(IPPair *h, uint32_t idx, uint32_t expire)
95
50
{
96
50
    XBit *fb = IPPairBitGet(h, idx);
97
50
    if (fb == NULL) {
98
50
        fb = SCMalloc(sizeof(XBit));
99
50
        if (unlikely(fb == NULL))
100
0
            return;
101
102
50
        fb->type = DETECT_XBITS;
103
50
        fb->idx = idx;
104
50
        fb->next = NULL;
105
50
        fb->expire = expire;
106
107
50
        GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
108
50
        GenericVarAppend(&gv, (GenericVar *)fb);
109
50
        IPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
110
111
        // bit already set, lets update it's timer
112
50
    } else {
113
0
        fb->expire = expire;
114
0
    }
115
50
}
116
117
static void IPPairBitRemove(IPPair *h, uint32_t idx)
118
0
{
119
0
    XBit *fb = IPPairBitGet(h, idx);
120
0
    if (fb == NULL)
121
0
        return;
122
123
0
    GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
124
0
    if (gv) {
125
0
        GenericVarRemove(&gv, (GenericVar *)fb);
126
0
        XBitFree(fb);
127
0
        IPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
128
0
    }
129
0
}
130
131
void IPPairBitSet(IPPair *h, uint32_t idx, uint32_t expire)
132
226
{
133
226
    XBit *fb = IPPairBitGet(h, idx);
134
226
    if (fb == NULL) {
135
50
        IPPairBitAdd(h, idx, expire);
136
50
    }
137
226
}
138
139
void IPPairBitUnset(IPPair *h, uint32_t idx)
140
0
{
141
0
    XBit *fb = IPPairBitGet(h, idx);
142
0
    if (fb != NULL) {
143
0
        IPPairBitRemove(h, idx);
144
0
    }
145
0
}
146
147
void IPPairBitToggle(IPPair *h, uint32_t idx, uint32_t expire)
148
0
{
149
0
    XBit *fb = IPPairBitGet(h, idx);
150
0
    if (fb != NULL) {
151
0
        IPPairBitRemove(h, idx);
152
0
    } else {
153
0
        IPPairBitAdd(h, idx, expire);
154
0
    }
155
0
}
156
157
int IPPairBitIsset(IPPair *h, uint32_t idx, uint32_t ts)
158
269
{
159
269
    XBit *fb = IPPairBitGet(h, idx);
160
269
    if (fb != NULL) {
161
0
        if (fb->expire < ts) {
162
0
            IPPairBitRemove(h, idx);
163
0
            return 0;
164
0
        }
165
166
0
        return 1;
167
0
    }
168
269
    return 0;
169
269
}
170
171
int IPPairBitIsnotset(IPPair *h, uint32_t idx, uint32_t ts)
172
0
{
173
0
    XBit *fb = IPPairBitGet(h, idx);
174
0
    if (fb == NULL) {
175
0
        return 1;
176
0
    }
177
178
0
    if (fb->expire < ts) {
179
0
        IPPairBitRemove(h, idx);
180
0
        return 1;
181
0
    }
182
183
0
    return 0;
184
0
}
185
186
187
/* TESTS */
188
#ifdef UNITTESTS
189
static int IPPairBitTest01 (void)
190
{
191
    int ret = 0;
192
193
    IPPairInitConfig(true);
194
    IPPair *h = IPPairAlloc();
195
    if (h == NULL)
196
        goto end;
197
198
    IPPairBitAdd(h, 0, 0);
199
200
    XBit *fb = IPPairBitGet(h,0);
201
    if (fb != NULL)
202
        ret = 1;
203
204
    IPPairFree(h);
205
end:
206
    IPPairCleanup();
207
    return ret;
208
}
209
210
static int IPPairBitTest02 (void)
211
{
212
    int ret = 0;
213
214
    IPPairInitConfig(true);
215
    IPPair *h = IPPairAlloc();
216
    if (h == NULL)
217
        goto end;
218
219
    XBit *fb = IPPairBitGet(h,0);
220
    if (fb == NULL)
221
        ret = 1;
222
223
    IPPairFree(h);
224
end:
225
    IPPairCleanup();
226
    return ret;
227
}
228
229
static int IPPairBitTest03 (void)
230
{
231
    int ret = 0;
232
233
    IPPairInitConfig(true);
234
    IPPair *h = IPPairAlloc();
235
    if (h == NULL)
236
        goto end;
237
238
    IPPairBitAdd(h, 0, 30);
239
240
    XBit *fb = IPPairBitGet(h,0);
241
    if (fb == NULL) {
242
        printf("fb == NULL although it was just added: ");
243
        goto end;
244
    }
245
246
    IPPairBitRemove(h, 0);
247
248
    fb = IPPairBitGet(h,0);
249
    if (fb != NULL) {
250
        printf("fb != NULL although it was just removed: ");
251
        goto end;
252
    } else {
253
        ret = 1;
254
    }
255
256
    IPPairFree(h);
257
end:
258
    IPPairCleanup();
259
    return ret;
260
}
261
262
static int IPPairBitTest04 (void)
263
{
264
    int ret = 0;
265
266
    IPPairInitConfig(true);
267
    IPPair *h = IPPairAlloc();
268
    if (h == NULL)
269
        goto end;
270
271
    IPPairBitAdd(h, 0,30);
272
    IPPairBitAdd(h, 1,30);
273
    IPPairBitAdd(h, 2,30);
274
    IPPairBitAdd(h, 3,30);
275
276
    XBit *fb = IPPairBitGet(h,0);
277
    if (fb != NULL)
278
        ret = 1;
279
280
    IPPairFree(h);
281
end:
282
    IPPairCleanup();
283
    return ret;
284
}
285
286
static int IPPairBitTest05 (void)
287
{
288
    int ret = 0;
289
290
    IPPairInitConfig(true);
291
    IPPair *h = IPPairAlloc();
292
    if (h == NULL)
293
        goto end;
294
295
    IPPairBitAdd(h, 0,90);
296
    IPPairBitAdd(h, 1,90);
297
    IPPairBitAdd(h, 2,90);
298
    IPPairBitAdd(h, 3,90);
299
300
    XBit *fb = IPPairBitGet(h,1);
301
    if (fb != NULL)
302
        ret = 1;
303
304
    IPPairFree(h);
305
end:
306
    IPPairCleanup();
307
    return ret;
308
}
309
310
static int IPPairBitTest06 (void)
311
{
312
    int ret = 0;
313
314
    IPPairInitConfig(true);
315
    IPPair *h = IPPairAlloc();
316
    if (h == NULL)
317
        goto end;
318
319
    IPPairBitAdd(h, 0,90);
320
    IPPairBitAdd(h, 1,90);
321
    IPPairBitAdd(h, 2,90);
322
    IPPairBitAdd(h, 3,90);
323
324
    XBit *fb = IPPairBitGet(h,2);
325
    if (fb != NULL)
326
        ret = 1;
327
328
    IPPairFree(h);
329
end:
330
    IPPairCleanup();
331
    return ret;
332
}
333
334
static int IPPairBitTest07 (void)
335
{
336
    int ret = 0;
337
338
    IPPairInitConfig(true);
339
    IPPair *h = IPPairAlloc();
340
    if (h == NULL)
341
        goto end;
342
343
    IPPairBitAdd(h, 0,90);
344
    IPPairBitAdd(h, 1,90);
345
    IPPairBitAdd(h, 2,90);
346
    IPPairBitAdd(h, 3,90);
347
348
    XBit *fb = IPPairBitGet(h,3);
349
    if (fb != NULL)
350
        ret = 1;
351
352
    IPPairFree(h);
353
end:
354
    IPPairCleanup();
355
    return ret;
356
}
357
358
static int IPPairBitTest08 (void)
359
{
360
    int ret = 0;
361
362
    IPPairInitConfig(true);
363
    IPPair *h = IPPairAlloc();
364
    if (h == NULL)
365
        goto end;
366
367
    IPPairBitAdd(h, 0,90);
368
    IPPairBitAdd(h, 1,90);
369
    IPPairBitAdd(h, 2,90);
370
    IPPairBitAdd(h, 3,90);
371
372
    XBit *fb = IPPairBitGet(h,0);
373
    if (fb == NULL)
374
        goto end;
375
376
    IPPairBitRemove(h,0);
377
378
    fb = IPPairBitGet(h,0);
379
    if (fb != NULL) {
380
        printf("fb != NULL even though it was removed: ");
381
        goto end;
382
    }
383
384
    ret = 1;
385
    IPPairFree(h);
386
end:
387
    IPPairCleanup();
388
    return ret;
389
}
390
391
static int IPPairBitTest09 (void)
392
{
393
    int ret = 0;
394
395
    IPPairInitConfig(true);
396
    IPPair *h = IPPairAlloc();
397
    if (h == NULL)
398
        goto end;
399
400
    IPPairBitAdd(h, 0,90);
401
    IPPairBitAdd(h, 1,90);
402
    IPPairBitAdd(h, 2,90);
403
    IPPairBitAdd(h, 3,90);
404
405
    XBit *fb = IPPairBitGet(h,1);
406
    if (fb == NULL)
407
        goto end;
408
409
    IPPairBitRemove(h,1);
410
411
    fb = IPPairBitGet(h,1);
412
    if (fb != NULL) {
413
        printf("fb != NULL even though it was removed: ");
414
        goto end;
415
    }
416
417
    ret = 1;
418
    IPPairFree(h);
419
end:
420
    IPPairCleanup();
421
    return ret;
422
}
423
424
static int IPPairBitTest10 (void)
425
{
426
    int ret = 0;
427
428
    IPPairInitConfig(true);
429
    IPPair *h = IPPairAlloc();
430
    if (h == NULL)
431
        goto end;
432
433
    IPPairBitAdd(h, 0,90);
434
    IPPairBitAdd(h, 1,90);
435
    IPPairBitAdd(h, 2,90);
436
    IPPairBitAdd(h, 3,90);
437
438
    XBit *fb = IPPairBitGet(h,2);
439
    if (fb == NULL)
440
        goto end;
441
442
    IPPairBitRemove(h,2);
443
444
    fb = IPPairBitGet(h,2);
445
    if (fb != NULL) {
446
        printf("fb != NULL even though it was removed: ");
447
        goto end;
448
    }
449
450
    ret = 1;
451
    IPPairFree(h);
452
end:
453
    IPPairCleanup();
454
    return ret;
455
}
456
457
static int IPPairBitTest11 (void)
458
{
459
    int ret = 0;
460
461
    IPPairInitConfig(true);
462
    IPPair *h = IPPairAlloc();
463
    if (h == NULL)
464
        goto end;
465
466
    IPPairBitAdd(h, 0,90);
467
    IPPairBitAdd(h, 1,90);
468
    IPPairBitAdd(h, 2,90);
469
    IPPairBitAdd(h, 3,90);
470
471
    XBit *fb = IPPairBitGet(h,3);
472
    if (fb == NULL)
473
        goto end;
474
475
    IPPairBitRemove(h,3);
476
477
    fb = IPPairBitGet(h,3);
478
    if (fb != NULL) {
479
        printf("fb != NULL even though it was removed: ");
480
        goto end;
481
    }
482
483
    ret = 1;
484
    IPPairFree(h);
485
end:
486
    IPPairCleanup();
487
    return ret;
488
}
489
490
#endif /* UNITTESTS */
491
492
void IPPairBitRegisterTests(void)
493
0
{
494
#ifdef UNITTESTS
495
    UtRegisterTest("IPPairBitTest01", IPPairBitTest01);
496
    UtRegisterTest("IPPairBitTest02", IPPairBitTest02);
497
    UtRegisterTest("IPPairBitTest03", IPPairBitTest03);
498
    UtRegisterTest("IPPairBitTest04", IPPairBitTest04);
499
    UtRegisterTest("IPPairBitTest05", IPPairBitTest05);
500
    UtRegisterTest("IPPairBitTest06", IPPairBitTest06);
501
    UtRegisterTest("IPPairBitTest07", IPPairBitTest07);
502
    UtRegisterTest("IPPairBitTest08", IPPairBitTest08);
503
    UtRegisterTest("IPPairBitTest09", IPPairBitTest09);
504
    UtRegisterTest("IPPairBitTest10", IPPairBitTest10);
505
    UtRegisterTest("IPPairBitTest11", IPPairBitTest11);
506
#endif /* UNITTESTS */
507
0
}