suricata
ippair-bit.c
Go to the documentation of this file.
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
41static IPPairStorageId g_ippair_bit_storage_id = { .id = -1 }; /**< IPPair storage id for bits */
42
43static void XBitFreeAll(void *store)
44{
45 GenericVar *gv = store;
47}
48
50{
51 g_ippair_bit_storage_id = IPPairStorageRegister("bit", sizeof(void *), NULL, XBitFreeAll);
52 if (g_ippair_bit_storage_id.id == -1) {
53 FatalError("Can't initiate ippair storage for bits");
54 }
55}
56
57/* lock before using this */
59{
60 if (ippair == NULL)
61 return 0;
62 return IPPairGetStorageById(ippair, g_ippair_bit_storage_id) ? 1 : 0;
63}
64
65/** \retval 1 ippair timed out wrt xbits
66 * \retval 0 ippair still has active (non-expired) xbits */
68{
69 GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
70 for ( ; gv != NULL; gv = gv->next) {
71 if (gv->type == DETECT_XBITS) {
72 XBit *xb = (XBit *)gv;
73 if (SCTIME_CMP_GT(xb->expire, ts))
74 return 0;
75 }
76 }
77 return 1;
78}
79
80/* get the bit with idx from the ippair */
81static XBit *IPPairBitGet(IPPair *h, uint32_t idx)
82{
83 GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
84 for ( ; gv != NULL; gv = gv->next) {
85 if (gv->type == DETECT_XBITS && gv->idx == idx) {
86 return (XBit *)gv;
87 }
88 }
89
90 return NULL;
91}
92
93/* add a flowbit to the flow */
94static void IPPairBitAdd(IPPair *h, uint32_t idx, SCTime_t expire)
95{
96 XBit *fb = IPPairBitGet(h, idx);
97 if (fb == NULL) {
98 fb = SCMalloc(sizeof(XBit));
99 if (unlikely(fb == NULL))
100 return;
101
102 fb->type = DETECT_XBITS;
103 fb->idx = idx;
104 fb->next = NULL;
105 fb->expire = expire;
106
107 GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
108 GenericVarAppend(&gv, (GenericVar *)fb);
109 IPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
110
111 // bit already set, lets update it's timer
112 } else {
113 fb->expire = expire;
114 }
115}
116
117static void IPPairBitRemove(IPPair *h, uint32_t idx)
118{
119 XBit *fb = IPPairBitGet(h, idx);
120 if (fb == NULL)
121 return;
122
123 GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
124 if (gv) {
125 GenericVarRemove(&gv, (GenericVar *)fb);
126 XBitFree(fb);
127 IPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
128 }
129}
130
131void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_t expire)
132{
133 XBit *fb = IPPairBitGet(h, idx);
134 if (fb == NULL) {
135 IPPairBitAdd(h, idx, expire);
136 }
137}
138
139void IPPairBitUnset(IPPair *h, uint32_t idx)
140{
141 XBit *fb = IPPairBitGet(h, idx);
142 if (fb != NULL) {
143 IPPairBitRemove(h, idx);
144 }
145}
146
147void IPPairBitToggle(IPPair *h, uint32_t idx, SCTime_t expire)
148{
149 XBit *fb = IPPairBitGet(h, idx);
150 if (fb != NULL) {
151 IPPairBitRemove(h, idx);
152 } else {
153 IPPairBitAdd(h, idx, expire);
154 }
155}
156
157int IPPairBitIsset(IPPair *h, uint32_t idx, SCTime_t ts)
158{
159 XBit *fb = IPPairBitGet(h, idx);
160 if (fb != NULL) {
161 if (SCTIME_CMP_LT(fb->expire, ts)) {
162 IPPairBitRemove(h, idx);
163 return 0;
164 }
165
166 return 1;
167 }
168 return 0;
169}
170
171int IPPairBitIsnotset(IPPair *h, uint32_t idx, SCTime_t ts)
172{
173 XBit *fb = IPPairBitGet(h, idx);
174 if (fb == NULL) {
175 return 1;
176 }
177
178 if (SCTIME_CMP_LT(fb->expire, ts)) {
179 IPPairBitRemove(h, idx);
180 return 1;
181 }
182
183 return 0;
184}
185
186
187/* TESTS */
188#ifdef UNITTESTS
189static 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, SCTIME_FROM_SECS(0));
199
200 XBit *fb = IPPairBitGet(h,0);
201 if (fb != NULL)
202 ret = 1;
203
204 IPPairFree(h);
205end:
207 return ret;
208}
209
210static 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);
224end:
226 return ret;
227}
228
229static 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, SCTIME_FROM_SECS(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);
257end:
259 return ret;
260}
261
262static 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, SCTIME_FROM_SECS(30));
272 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(30));
273 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(30));
274 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(30));
275
276 XBit *fb = IPPairBitGet(h,0);
277 if (fb != NULL)
278 ret = 1;
279
280 IPPairFree(h);
281end:
283 return ret;
284}
285
286static 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, SCTIME_FROM_SECS(90));
296 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
297 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
298 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
299
300 XBit *fb = IPPairBitGet(h,1);
301 if (fb != NULL)
302 ret = 1;
303
304 IPPairFree(h);
305end:
307 return ret;
308}
309
310static 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, SCTIME_FROM_SECS(90));
320 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
321 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
322 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
323
324 XBit *fb = IPPairBitGet(h,2);
325 if (fb != NULL)
326 ret = 1;
327
328 IPPairFree(h);
329end:
331 return ret;
332}
333
334static 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, SCTIME_FROM_SECS(90));
344 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
345 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
346 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
347
348 XBit *fb = IPPairBitGet(h,3);
349 if (fb != NULL)
350 ret = 1;
351
352 IPPairFree(h);
353end:
355 return ret;
356}
357
358static 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, SCTIME_FROM_SECS(90));
368 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
369 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
370 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(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);
386end:
388 return ret;
389}
390
391static 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, SCTIME_FROM_SECS(90));
401 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
402 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
403 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(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);
419end:
421 return ret;
422}
423
424static 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, SCTIME_FROM_SECS(90));
434 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
435 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
436 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(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);
452end:
454 return ret;
455}
456
457static 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, SCTIME_FROM_SECS(90));
467 IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
468 IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
469 IPPairBitAdd(h, 3, SCTIME_FROM_SECS(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);
485end:
487 return ret;
488}
489
490#endif /* UNITTESTS */
491
493{
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}
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void IPPairBitRegisterTests(void)
Definition ippair-bit.c:492
void IPPairBitUnset(IPPair *h, uint32_t idx)
Definition ippair-bit.c:139
int IPPairHasBits(IPPair *ippair)
Definition ippair-bit.c:58
int IPPairBitsTimedoutCheck(IPPair *h, SCTime_t ts)
Definition ippair-bit.c:67
void IPPairBitInitCtx(void)
Definition ippair-bit.c:49
int IPPairBitIsset(IPPair *h, uint32_t idx, SCTime_t ts)
Definition ippair-bit.c:157
void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_t expire)
Definition ippair-bit.c:131
void IPPairBitToggle(IPPair *h, uint32_t idx, SCTime_t expire)
Definition ippair-bit.c:147
int IPPairBitIsnotset(IPPair *h, uint32_t idx, SCTime_t ts)
Definition ippair-bit.c:171
void * IPPairGetStorageById(IPPair *h, IPPairStorageId id)
IPPairStorageId IPPairStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
int IPPairSetStorageById(IPPair *h, IPPairStorageId id, void *ptr)
void IPPairCleanup(void)
Cleanup the ippair engine.
Definition ippair.c:327
void IPPairInitConfig(bool quiet)
initialize the configuration
Definition ippair.c:162
void IPPairFree(IPPair *h)
Definition ippair.c:124
IPPair * IPPairAlloc(void)
Definition ippair.c:104
uint64_t ts
uint16_t type
Definition util-var.h:54
uint32_t idx
Definition util-var.h:56
struct GenericVar_ * next
Definition util-var.h:57
uint16_t type
Definition util-var.h:61
GenericVar * next
Definition util-var.h:64
SCTime_t expire
Definition util-var.h:65
uint32_t idx
Definition util-var.h:63
#define FatalError(...)
Definition util-debug.h:510
#define SCMalloc(sz)
Definition util-mem.h:47
#define unlikely(expr)
#define SCTIME_FROM_SECS(s)
Definition util-time.h:69
#define SCTIME_CMP_GT(a, b)
Definition util-time.h:104
#define SCTIME_CMP_LT(a, b)
Definition util-time.h:105
void GenericVarAppend(GenericVar **list, GenericVar *gv)
Definition util-var.c:98
void GenericVarFree(GenericVar *gv)
Definition util-var.c:48
void XBitFree(XBit *fb)
Definition util-var.c:40
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition util-var.c:117