Coverage Report

Created: 2026-06-07 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/flow-bit.c
Line
Count
Source
1
/* Copyright (C) 2007-2013 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 flow 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
 * \todo have more than one instance of the same var, and be able to match on a
30
 *       specific one, or one all at a time. So if a certain capture matches
31
 *       multiple times, we can operate on all of them.
32
 */
33
34
#include "suricata-common.h"
35
#include "threads.h"
36
#include "flow-bit.h"
37
#include "flow.h"
38
#include "flow-util.h"
39
#include "flow-private.h"
40
#include "detect.h"
41
#include "util-var.h"
42
#include "util-debug.h"
43
#include "util-unittest.h"
44
45
/* get the flowbit with idx from the flow */
46
static FlowBit *FlowBitGet(Flow *f, uint32_t idx)
47
129k
{
48
129k
    GenericVar *gv = f->flowvar;
49
233k
    for ( ; gv != NULL; gv = gv->next) {
50
145k
        if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
51
40.6k
            return (FlowBit *)gv;
52
40.6k
        }
53
145k
    }
54
55
88.8k
    return NULL;
56
129k
}
57
58
/* add a flowbit to the flow */
59
static void FlowBitAdd(Flow *f, uint32_t idx)
60
13.7k
{
61
13.7k
    FlowBit *fb = FlowBitGet(f, idx);
62
13.7k
    if (fb == NULL) {
63
3.67k
        fb = SCMalloc(sizeof(FlowBit));
64
3.67k
        if (unlikely(fb == NULL))
65
0
            return;
66
67
3.67k
        fb->type = DETECT_FLOWBITS;
68
3.67k
        fb->idx = idx;
69
3.67k
        fb->next = NULL;
70
3.67k
        GenericVarAppend(&f->flowvar, (GenericVar *)fb);
71
3.67k
    }
72
13.7k
}
73
74
static void FlowBitRemove(Flow *f, uint32_t idx)
75
9.76k
{
76
9.76k
    FlowBit *fb = FlowBitGet(f, idx);
77
9.76k
    if (fb == NULL)
78
9.00k
        return;
79
80
759
    GenericVarRemove(&f->flowvar, (GenericVar *)fb);
81
759
    FlowBitFree(fb);
82
759
}
83
84
void FlowBitSet(Flow *f, uint32_t idx)
85
13.0k
{
86
13.0k
    FlowBitAdd(f, idx);
87
13.0k
}
88
89
void FlowBitUnset(Flow *f, uint32_t idx)
90
9.14k
{
91
9.14k
    FlowBitRemove(f, idx);
92
9.14k
}
93
94
void FlowBitToggle(Flow *f, uint32_t idx)
95
1.30k
{
96
1.30k
    FlowBit *fb = FlowBitGet(f, idx);
97
1.30k
    if (fb != NULL) {
98
617
        FlowBitRemove(f, idx);
99
683
    } else {
100
683
        FlowBitAdd(f, idx);
101
683
    }
102
1.30k
}
103
104
int FlowBitIsset(Flow *f, uint32_t idx)
105
32.4k
{
106
32.4k
    int r = 0;
107
108
32.4k
    FlowBit *fb = FlowBitGet(f, idx);
109
32.4k
    if (fb != NULL) {
110
3.70k
        r = 1;
111
3.70k
    }
112
113
32.4k
    return r;
114
32.4k
}
115
116
int FlowBitIsnotset(Flow *f, uint32_t idx)
117
46.2k
{
118
46.2k
    int r = 0;
119
120
46.2k
    FlowBit *fb = FlowBitGet(f, idx);
121
46.2k
    if (fb == NULL) {
122
42.5k
        r = 1;
123
42.5k
    }
124
125
46.2k
    return r;
126
46.2k
}
127
128
void FlowBitFree(FlowBit *fb)
129
7.79k
{
130
7.79k
    if (fb == NULL)
131
0
        return;
132
133
7.79k
    SCFree(fb);
134
7.79k
}
135
136
137
/* TESTS */
138
#ifdef UNITTESTS
139
static int FlowBitTest01 (void)
140
{
141
    Flow f;
142
    memset(&f, 0, sizeof(Flow));
143
144
    FlowBitAdd(&f, 0);
145
146
    FlowBit *fb = FlowBitGet(&f, 0);
147
    FAIL_IF_NULL(fb);
148
149
    GenericVarFree(f.flowvar);
150
    PASS;
151
}
152
153
static int FlowBitTest02 (void)
154
{
155
    Flow f;
156
    memset(&f, 0, sizeof(Flow));
157
158
    FlowBit *fb = FlowBitGet(&f, 0);
159
    FAIL_IF_NOT_NULL(fb);
160
161
    GenericVarFree(f.flowvar);
162
    PASS;
163
}
164
165
static int FlowBitTest03 (void)
166
{
167
    Flow f;
168
    memset(&f, 0, sizeof(Flow));
169
170
    FlowBitAdd(&f, 0);
171
172
    FlowBit *fb = FlowBitGet(&f,0);
173
    FAIL_IF_NULL(fb);
174
175
    FlowBitRemove(&f, 0);
176
177
    fb = FlowBitGet(&f, 0);
178
    FAIL_IF_NOT_NULL(fb);
179
180
    GenericVarFree(f.flowvar);
181
    PASS;
182
}
183
184
static int FlowBitTest04 (void)
185
{
186
    Flow f;
187
    memset(&f, 0, sizeof(Flow));
188
189
    FlowBitAdd(&f, 0);
190
    FlowBitAdd(&f, 1);
191
    FlowBitAdd(&f, 2);
192
    FlowBitAdd(&f, 3);
193
194
    FlowBit *fb = FlowBitGet(&f, 0);
195
    FAIL_IF_NULL(fb);
196
197
    GenericVarFree(f.flowvar);
198
    PASS;
199
}
200
201
static int FlowBitTest05 (void)
202
{
203
    Flow f;
204
    memset(&f, 0, sizeof(Flow));
205
206
    FlowBitAdd(&f, 0);
207
    FlowBitAdd(&f, 1);
208
    FlowBitAdd(&f, 2);
209
    FlowBitAdd(&f, 3);
210
211
    FlowBit *fb = FlowBitGet(&f, 1);
212
    FAIL_IF_NULL(fb);
213
214
    GenericVarFree(f.flowvar);
215
    PASS;
216
}
217
218
static int FlowBitTest06 (void)
219
{
220
    Flow f;
221
    memset(&f, 0, sizeof(Flow));
222
223
    FlowBitAdd(&f, 0);
224
    FlowBitAdd(&f, 1);
225
    FlowBitAdd(&f, 2);
226
    FlowBitAdd(&f, 3);
227
228
    FlowBit *fb = FlowBitGet(&f, 2);
229
    FAIL_IF_NULL(fb);
230
231
    GenericVarFree(f.flowvar);
232
    PASS;
233
}
234
235
static int FlowBitTest07 (void)
236
{
237
    Flow f;
238
    memset(&f, 0, sizeof(Flow));
239
240
    FlowBitAdd(&f, 0);
241
    FlowBitAdd(&f, 1);
242
    FlowBitAdd(&f, 2);
243
    FlowBitAdd(&f, 3);
244
245
    FlowBit *fb = FlowBitGet(&f, 3);
246
    FAIL_IF_NULL(fb);
247
248
    GenericVarFree(f.flowvar);
249
    PASS;
250
}
251
252
static int FlowBitTest08 (void)
253
{
254
    Flow f;
255
    memset(&f, 0, sizeof(Flow));
256
257
    FlowBitAdd(&f, 0);
258
    FlowBitAdd(&f, 1);
259
    FlowBitAdd(&f, 2);
260
    FlowBitAdd(&f, 3);
261
262
    FlowBit *fb = FlowBitGet(&f,0);
263
    FAIL_IF_NULL(fb);
264
265
    FlowBitRemove(&f,0);
266
267
    fb = FlowBitGet(&f, 0);
268
    FAIL_IF_NOT_NULL(fb);
269
270
    GenericVarFree(f.flowvar);
271
    PASS;
272
}
273
274
static int FlowBitTest09 (void)
275
{
276
    Flow f;
277
    memset(&f, 0, sizeof(Flow));
278
279
    FlowBitAdd(&f, 0);
280
    FlowBitAdd(&f, 1);
281
    FlowBitAdd(&f, 2);
282
    FlowBitAdd(&f, 3);
283
284
    FlowBit *fb = FlowBitGet(&f,1);
285
    FAIL_IF_NULL(fb);
286
287
    FlowBitRemove(&f,1);
288
289
    fb = FlowBitGet(&f, 1);
290
    FAIL_IF_NOT_NULL(fb);
291
292
    GenericVarFree(f.flowvar);
293
    PASS;
294
}
295
296
static int FlowBitTest10 (void)
297
{
298
    Flow f;
299
    memset(&f, 0, sizeof(Flow));
300
301
    FlowBitAdd(&f, 0);
302
    FlowBitAdd(&f, 1);
303
    FlowBitAdd(&f, 2);
304
    FlowBitAdd(&f, 3);
305
306
    FlowBit *fb = FlowBitGet(&f,2);
307
    FAIL_IF_NULL(fb);
308
309
    FlowBitRemove(&f,2);
310
311
    fb = FlowBitGet(&f, 2);
312
    FAIL_IF_NOT_NULL(fb);
313
314
    GenericVarFree(f.flowvar);
315
    PASS;
316
}
317
318
static int FlowBitTest11 (void)
319
{
320
    Flow f;
321
    memset(&f, 0, sizeof(Flow));
322
323
    FlowBitAdd(&f, 0);
324
    FlowBitAdd(&f, 1);
325
    FlowBitAdd(&f, 2);
326
    FlowBitAdd(&f, 3);
327
328
    FlowBit *fb = FlowBitGet(&f,3);
329
    FAIL_IF_NULL(fb);
330
331
    FlowBitRemove(&f,3);
332
333
    fb = FlowBitGet(&f, 3);
334
    FAIL_IF_NOT_NULL(fb);
335
336
    GenericVarFree(f.flowvar);
337
    PASS;
338
}
339
340
#endif /* UNITTESTS */
341
342
void FlowBitRegisterTests(void)
343
0
{
344
#ifdef UNITTESTS
345
    UtRegisterTest("FlowBitTest01", FlowBitTest01);
346
    UtRegisterTest("FlowBitTest02", FlowBitTest02);
347
    UtRegisterTest("FlowBitTest03", FlowBitTest03);
348
    UtRegisterTest("FlowBitTest04", FlowBitTest04);
349
    UtRegisterTest("FlowBitTest05", FlowBitTest05);
350
    UtRegisterTest("FlowBitTest06", FlowBitTest06);
351
    UtRegisterTest("FlowBitTest07", FlowBitTest07);
352
    UtRegisterTest("FlowBitTest08", FlowBitTest08);
353
    UtRegisterTest("FlowBitTest09", FlowBitTest09);
354
    UtRegisterTest("FlowBitTest10", FlowBitTest10);
355
    UtRegisterTest("FlowBitTest11", FlowBitTest11);
356
#endif /* UNITTESTS */
357
0
}
358