• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.29
/src/flow-bit.c
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
{
41,601✔
48
    GenericVar *gv = f->flowvar;
41,601✔
49
    for ( ; gv != NULL; gv = gv->next) {
68,200✔
50
        if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
37,237✔
51
            return (FlowBit *)gv;
10,638✔
52
        }
10,638✔
53
    }
37,237✔
54

55
    return NULL;
30,963✔
56
}
41,601✔
57

58
/** \brief add a flowbit to the flow
59
 *  \retval -1 error
60
 *  \retval 0 not added, already set before
61
 *  \retval 1 added */
62
static int FlowBitAdd(Flow *f, uint32_t idx)
63
{
5,064✔
64
    FlowBit *fb = FlowBitGet(f, idx);
5,064✔
65
    if (fb == NULL) {
5,064✔
66
        fb = SCMalloc(sizeof(FlowBit));
3,549✔
67
        if (unlikely(fb == NULL))
3,549✔
68
            return -1;
×
69

70
        fb->type = DETECT_FLOWBITS;
3,549✔
71
        fb->idx = idx;
3,549✔
72
        fb->next = NULL;
3,549✔
73
        GenericVarAppend(&f->flowvar, (GenericVar *)fb);
3,549✔
74
        return 1;
3,549✔
75
    } else {
3,549✔
76
        return 0;
1,515✔
77
    }
1,515✔
78
}
5,064✔
79

80
static void FlowBitRemove(Flow *f, uint32_t idx)
81
{
5,674✔
82
    FlowBit *fb = FlowBitGet(f, idx);
5,674✔
83
    if (fb == NULL)
5,674✔
84
        return;
3,969✔
85

86
    GenericVarRemove(&f->flowvar, (GenericVar *)fb);
1,705✔
87
    FlowBitFree(fb);
1,705✔
88
}
1,705✔
89

90
/** \brief add a flowbit to the flow
91
 *  \retval -1 error
92
 *  \retval 0 not added, already set before
93
 *  \retval 1 added */
94
int FlowBitSet(Flow *f, uint32_t idx)
95
{
3,350✔
96
    return FlowBitAdd(f, idx);
3,350✔
97
}
3,350✔
98

99
void FlowBitUnset(Flow *f, uint32_t idx)
100
{
4,123✔
101
    FlowBitRemove(f, idx);
4,123✔
102
}
4,123✔
103

104
/**
105
 * \retval bool true if bit is set, false is unset
106
 */
107
bool FlowBitToggle(Flow *f, uint32_t idx)
108
{
3,265✔
109
    FlowBit *fb = FlowBitGet(f, idx);
3,265✔
110
    if (fb != NULL) {
3,265✔
111
        FlowBitRemove(f, idx);
1,551✔
112
        return false;
1,551✔
113
    } else {
1,714✔
114
        FlowBitAdd(f, idx);
1,714✔
115
        return true;
1,714✔
116
    }
1,714✔
117
}
3,265✔
118

119
int FlowBitIsset(Flow *f, uint32_t idx)
120
{
14,472✔
121
    int r = 0;
14,472✔
122

123
    FlowBit *fb = FlowBitGet(f, idx);
14,472✔
124
    if (fb != NULL) {
14,472✔
125
        r = 1;
3,848✔
126
    }
3,848✔
127

128
    return r;
14,472✔
129
}
14,472✔
130

131
int FlowBitIsnotset(Flow *f, uint32_t idx)
132
{
13,126✔
133
    int r = 0;
13,126✔
134

135
    FlowBit *fb = FlowBitGet(f, idx);
13,126✔
136
    if (fb == NULL) {
13,126✔
137
        r = 1;
11,107✔
138
    }
11,107✔
139

140
    return r;
13,126✔
141
}
13,126✔
142

143
void FlowBitFree(FlowBit *fb)
144
{
3,549✔
145
    if (fb == NULL)
3,549✔
146
        return;
×
147

148
    SCFree(fb);
3,549✔
149
}
3,549✔
150

151

152
/* TESTS */
153
#ifdef UNITTESTS
154
static int FlowBitTest01 (void)
155
{
156
    Flow f;
157
    memset(&f, 0, sizeof(Flow));
158

159
    FlowBitAdd(&f, 0);
160

161
    FlowBit *fb = FlowBitGet(&f, 0);
162
    FAIL_IF_NULL(fb);
163

164
    SCGenericVarFree(f.flowvar);
165
    PASS;
166
}
167

168
static int FlowBitTest02 (void)
169
{
170
    Flow f;
171
    memset(&f, 0, sizeof(Flow));
172

173
    FlowBit *fb = FlowBitGet(&f, 0);
174
    FAIL_IF_NOT_NULL(fb);
175

176
    SCGenericVarFree(f.flowvar);
177
    PASS;
178
}
179

180
static int FlowBitTest03 (void)
181
{
182
    Flow f;
183
    memset(&f, 0, sizeof(Flow));
184

185
    FlowBitAdd(&f, 0);
186

187
    FlowBit *fb = FlowBitGet(&f,0);
188
    FAIL_IF_NULL(fb);
189

190
    FlowBitRemove(&f, 0);
191

192
    fb = FlowBitGet(&f, 0);
193
    FAIL_IF_NOT_NULL(fb);
194

195
    SCGenericVarFree(f.flowvar);
196
    PASS;
197
}
198

199
static int FlowBitTest04 (void)
200
{
201
    Flow f;
202
    memset(&f, 0, sizeof(Flow));
203

204
    FlowBitAdd(&f, 0);
205
    FlowBitAdd(&f, 1);
206
    FlowBitAdd(&f, 2);
207
    FlowBitAdd(&f, 3);
208

209
    FlowBit *fb = FlowBitGet(&f, 0);
210
    FAIL_IF_NULL(fb);
211

212
    SCGenericVarFree(f.flowvar);
213
    PASS;
214
}
215

216
static int FlowBitTest05 (void)
217
{
218
    Flow f;
219
    memset(&f, 0, sizeof(Flow));
220

221
    FlowBitAdd(&f, 0);
222
    FlowBitAdd(&f, 1);
223
    FlowBitAdd(&f, 2);
224
    FlowBitAdd(&f, 3);
225

226
    FlowBit *fb = FlowBitGet(&f, 1);
227
    FAIL_IF_NULL(fb);
228

229
    SCGenericVarFree(f.flowvar);
230
    PASS;
231
}
232

233
static int FlowBitTest06 (void)
234
{
235
    Flow f;
236
    memset(&f, 0, sizeof(Flow));
237

238
    FlowBitAdd(&f, 0);
239
    FlowBitAdd(&f, 1);
240
    FlowBitAdd(&f, 2);
241
    FlowBitAdd(&f, 3);
242

243
    FlowBit *fb = FlowBitGet(&f, 2);
244
    FAIL_IF_NULL(fb);
245

246
    SCGenericVarFree(f.flowvar);
247
    PASS;
248
}
249

250
static int FlowBitTest07 (void)
251
{
252
    Flow f;
253
    memset(&f, 0, sizeof(Flow));
254

255
    FlowBitAdd(&f, 0);
256
    FlowBitAdd(&f, 1);
257
    FlowBitAdd(&f, 2);
258
    FlowBitAdd(&f, 3);
259

260
    FlowBit *fb = FlowBitGet(&f, 3);
261
    FAIL_IF_NULL(fb);
262

263
    SCGenericVarFree(f.flowvar);
264
    PASS;
265
}
266

267
static int FlowBitTest08 (void)
268
{
269
    Flow f;
270
    memset(&f, 0, sizeof(Flow));
271

272
    FlowBitAdd(&f, 0);
273
    FlowBitAdd(&f, 1);
274
    FlowBitAdd(&f, 2);
275
    FlowBitAdd(&f, 3);
276

277
    FlowBit *fb = FlowBitGet(&f,0);
278
    FAIL_IF_NULL(fb);
279

280
    FlowBitRemove(&f,0);
281

282
    fb = FlowBitGet(&f, 0);
283
    FAIL_IF_NOT_NULL(fb);
284

285
    SCGenericVarFree(f.flowvar);
286
    PASS;
287
}
288

289
static int FlowBitTest09 (void)
290
{
291
    Flow f;
292
    memset(&f, 0, sizeof(Flow));
293

294
    FlowBitAdd(&f, 0);
295
    FlowBitAdd(&f, 1);
296
    FlowBitAdd(&f, 2);
297
    FlowBitAdd(&f, 3);
298

299
    FlowBit *fb = FlowBitGet(&f,1);
300
    FAIL_IF_NULL(fb);
301

302
    FlowBitRemove(&f,1);
303

304
    fb = FlowBitGet(&f, 1);
305
    FAIL_IF_NOT_NULL(fb);
306

307
    SCGenericVarFree(f.flowvar);
308
    PASS;
309
}
310

311
static int FlowBitTest10 (void)
312
{
313
    Flow f;
314
    memset(&f, 0, sizeof(Flow));
315

316
    FlowBitAdd(&f, 0);
317
    FlowBitAdd(&f, 1);
318
    FlowBitAdd(&f, 2);
319
    FlowBitAdd(&f, 3);
320

321
    FlowBit *fb = FlowBitGet(&f,2);
322
    FAIL_IF_NULL(fb);
323

324
    FlowBitRemove(&f,2);
325

326
    fb = FlowBitGet(&f, 2);
327
    FAIL_IF_NOT_NULL(fb);
328

329
    SCGenericVarFree(f.flowvar);
330
    PASS;
331
}
332

333
static int FlowBitTest11 (void)
334
{
335
    Flow f;
336
    memset(&f, 0, sizeof(Flow));
337

338
    FlowBitAdd(&f, 0);
339
    FlowBitAdd(&f, 1);
340
    FlowBitAdd(&f, 2);
341
    FlowBitAdd(&f, 3);
342

343
    FlowBit *fb = FlowBitGet(&f,3);
344
    FAIL_IF_NULL(fb);
345

346
    FlowBitRemove(&f,3);
347

348
    fb = FlowBitGet(&f, 3);
349
    FAIL_IF_NOT_NULL(fb);
350

351
    SCGenericVarFree(f.flowvar);
352
    PASS;
353
}
354

355
#endif /* UNITTESTS */
356

357
void FlowBitRegisterTests(void)
UNCOV
358
{
×
359
#ifdef UNITTESTS
360
    UtRegisterTest("FlowBitTest01", FlowBitTest01);
361
    UtRegisterTest("FlowBitTest02", FlowBitTest02);
362
    UtRegisterTest("FlowBitTest03", FlowBitTest03);
363
    UtRegisterTest("FlowBitTest04", FlowBitTest04);
364
    UtRegisterTest("FlowBitTest05", FlowBitTest05);
365
    UtRegisterTest("FlowBitTest06", FlowBitTest06);
366
    UtRegisterTest("FlowBitTest07", FlowBitTest07);
367
    UtRegisterTest("FlowBitTest08", FlowBitTest08);
368
    UtRegisterTest("FlowBitTest09", FlowBitTest09);
369
    UtRegisterTest("FlowBitTest10", FlowBitTest10);
370
    UtRegisterTest("FlowBitTest11", FlowBitTest11);
371
#endif /* UNITTESTS */
UNCOV
372
}
×
373

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc