suricata
host-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 host 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 "host-bit.h"
34#include "host.h"
35#include "detect.h"
36#include "util-var.h"
37#include "util-debug.h"
38#include "util-unittest.h"
39#include "host-storage.h"
40
41static HostStorageId host_bit_id = { .id = -1 }; /**< Host storage id for bits */
42
43static void HostBitFreeAll(void *store)
44{
45 GenericVar *gv = store;
47}
48
50{
51 host_bit_id = HostStorageRegister("bit", sizeof(void *), NULL, HostBitFreeAll);
52 if (host_bit_id.id == -1) {
53 FatalError("Can't initiate host storage for bits");
54 }
55}
56
57/* lock before using this */
59{
60 if (host == NULL)
61 return 0;
62 return HostGetStorageById(host, host_bit_id) ? 1 : 0;
63}
64
65/** \retval 1 host timed out wrt xbits
66 * \retval 0 host still has active (non-expired) xbits */
68{
69 GenericVar *gv = HostGetStorageById(h, host_bit_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 host */
81static XBit *HostBitGet(Host *h, uint32_t idx)
82{
83 GenericVar *gv = HostGetStorageById(h, host_bit_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 HostBitAdd(Host *h, uint32_t idx, SCTime_t expire)
95{
96 XBit *fb = HostBitGet(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 = HostGetStorageById(h, host_bit_id);
108 GenericVarAppend(&gv, (GenericVar *)fb);
109 HostSetStorageById(h, host_bit_id, gv);
110
111 // bit already set, lets update it's time
112 } else {
113 fb->expire = expire;
114 }
115}
116
117static void HostBitRemove(Host *h, uint32_t idx)
118{
119 XBit *fb = HostBitGet(h, idx);
120 if (fb == NULL)
121 return;
122
123 GenericVar *gv = HostGetStorageById(h, host_bit_id);
124 if (gv) {
125 GenericVarRemove(&gv, (GenericVar *)fb);
126 XBitFree(fb);
127 HostSetStorageById(h, host_bit_id, gv);
128 }
129}
130
131void HostBitSet(Host *h, uint32_t idx, SCTime_t expire)
132{
133 XBit *fb = HostBitGet(h, idx);
134 if (fb == NULL) {
135 HostBitAdd(h, idx, expire);
136 }
137}
138
139void HostBitUnset(Host *h, uint32_t idx)
140{
141 XBit *fb = HostBitGet(h, idx);
142 if (fb != NULL) {
143 HostBitRemove(h, idx);
144 }
145}
146
147void HostBitToggle(Host *h, uint32_t idx, SCTime_t expire)
148{
149 XBit *fb = HostBitGet(h, idx);
150 if (fb != NULL) {
151 HostBitRemove(h, idx);
152 } else {
153 HostBitAdd(h, idx, expire);
154 }
155}
156
157int HostBitIsset(Host *h, uint32_t idx, SCTime_t ts)
158{
159 XBit *fb = HostBitGet(h, idx);
160 if (fb != NULL) {
161 if (SCTIME_CMP_LT(fb->expire, ts)) {
162 HostBitRemove(h,idx);
163 return 0;
164 }
165 return 1;
166 }
167 return 0;
168}
169
170int HostBitIsnotset(Host *h, uint32_t idx, SCTime_t ts)
171{
172 XBit *fb = HostBitGet(h, idx);
173 if (fb == NULL) {
174 return 1;
175 }
176
177 if (SCTIME_CMP_LT(fb->expire, ts)) {
178 HostBitRemove(h,idx);
179 return 1;
180 }
181 return 0;
182}
183
184int HostBitList(Host *h, XBit **iter)
185{
186 GenericVar *gv = (GenericVar *)*iter;
187 if (gv == NULL) {
188 gv = HostGetStorageById(h, host_bit_id);
189 } else {
190 gv = gv->next;
191 }
192
193 for ( ; gv != NULL; gv = gv->next) {
194 if (gv->type == DETECT_XBITS) {
195 *iter = (XBit *)gv;
196 return 1;
197 }
198 }
199 *iter = NULL;
200 return 0;
201}
202
203/* TESTS */
204#ifdef UNITTESTS
205static int HostBitTest01 (void)
206{
207 int ret = 0;
208
209 HostInitConfig(true);
210 Host *h = HostAlloc();
211 if (h == NULL)
212 goto end;
213
214 HostBitAdd(h, 0, SCTIME_FROM_SECS(0));
215
216 XBit *fb = HostBitGet(h,0);
217 if (fb != NULL)
218 ret = 1;
219
220 HostFree(h);
221end:
222 HostCleanup();
223 return ret;
224}
225
226static int HostBitTest02 (void)
227{
228 int ret = 0;
229
230 HostInitConfig(true);
231 Host *h = HostAlloc();
232 if (h == NULL)
233 goto end;
234
235 XBit *fb = HostBitGet(h,0);
236 if (fb == NULL)
237 ret = 1;
238
239 HostFree(h);
240end:
241 HostCleanup();
242 return ret;
243}
244
245static int HostBitTest03 (void)
246{
247 int ret = 0;
248
249 HostInitConfig(true);
250 Host *h = HostAlloc();
251 if (h == NULL)
252 goto end;
253
254 HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
255
256 XBit *fb = HostBitGet(h,0);
257 if (fb == NULL) {
258 printf("fb == NULL although it was just added: ");
259 goto end;
260 }
261
262 HostBitRemove(h, 0);
263
264 fb = HostBitGet(h,0);
265 if (fb != NULL) {
266 printf("fb != NULL although it was just removed: ");
267 goto end;
268 } else {
269 ret = 1;
270 }
271
272 HostFree(h);
273end:
274 HostCleanup();
275 return ret;
276}
277
278static int HostBitTest04 (void)
279{
280 int ret = 0;
281
282 HostInitConfig(true);
283 Host *h = HostAlloc();
284 if (h == NULL)
285 goto end;
286
287 HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
288 HostBitAdd(h, 1, SCTIME_FROM_SECS(30));
289 HostBitAdd(h, 2, SCTIME_FROM_SECS(30));
290 HostBitAdd(h, 3, SCTIME_FROM_SECS(30));
291
292 XBit *fb = HostBitGet(h,0);
293 if (fb != NULL)
294 ret = 1;
295
296 HostFree(h);
297end:
298 HostCleanup();
299 return ret;
300}
301
302static int HostBitTest05 (void)
303{
304 int ret = 0;
305
306 HostInitConfig(true);
307 Host *h = HostAlloc();
308 if (h == NULL)
309 goto end;
310
311 HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
312 HostBitAdd(h, 1, SCTIME_FROM_SECS(30));
313 HostBitAdd(h, 2, SCTIME_FROM_SECS(30));
314 HostBitAdd(h, 3, SCTIME_FROM_SECS(30));
315
316 XBit *fb = HostBitGet(h,1);
317 if (fb != NULL)
318 ret = 1;
319
320 HostFree(h);
321end:
322 HostCleanup();
323 return ret;
324}
325
326static int HostBitTest06 (void)
327{
328 int ret = 0;
329
330 HostInitConfig(true);
331 Host *h = HostAlloc();
332 if (h == NULL)
333 goto end;
334
335 HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
336 HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
337 HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
338 HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
339
340 XBit *fb = HostBitGet(h,2);
341 if (fb != NULL)
342 ret = 1;
343
344 HostFree(h);
345end:
346 HostCleanup();
347 return ret;
348}
349
350static int HostBitTest07 (void)
351{
352 int ret = 0;
353
354 HostInitConfig(true);
355 Host *h = HostAlloc();
356 if (h == NULL)
357 goto end;
358
359 HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
360 HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
361 HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
362 HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
363
364 XBit *fb = HostBitGet(h,3);
365 if (fb != NULL)
366 ret = 1;
367
368 HostFree(h);
369end:
370 HostCleanup();
371 return ret;
372}
373
374static int HostBitTest08 (void)
375{
376 int ret = 0;
377
378 HostInitConfig(true);
379 Host *h = HostAlloc();
380 if (h == NULL)
381 goto end;
382
383 HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
384 HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
385 HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
386 HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
387
388 XBit *fb = HostBitGet(h,0);
389 if (fb == NULL)
390 goto end;
391
392 HostBitRemove(h,0);
393
394 fb = HostBitGet(h,0);
395 if (fb != NULL) {
396 printf("fb != NULL even though it was removed: ");
397 goto end;
398 }
399
400 ret = 1;
401 HostFree(h);
402end:
403 HostCleanup();
404 return ret;
405}
406
407static int HostBitTest09 (void)
408{
409 int ret = 0;
410
411 HostInitConfig(true);
412 Host *h = HostAlloc();
413 if (h == NULL)
414 goto end;
415
416 HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
417 HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
418 HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
419 HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
420
421 XBit *fb = HostBitGet(h,1);
422 if (fb == NULL)
423 goto end;
424
425 HostBitRemove(h,1);
426
427 fb = HostBitGet(h,1);
428 if (fb != NULL) {
429 printf("fb != NULL even though it was removed: ");
430 goto end;
431 }
432
433 ret = 1;
434 HostFree(h);
435end:
436 HostCleanup();
437 return ret;
438}
439
440static int HostBitTest10 (void)
441{
442 int ret = 0;
443
444 HostInitConfig(true);
445 Host *h = HostAlloc();
446 if (h == NULL)
447 goto end;
448
449 HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
450 HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
451 HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
452 HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
453
454 XBit *fb = HostBitGet(h,2);
455 if (fb == NULL)
456 goto end;
457
458 HostBitRemove(h,2);
459
460 fb = HostBitGet(h,2);
461 if (fb != NULL) {
462 printf("fb != NULL even though it was removed: ");
463 goto end;
464 }
465
466 ret = 1;
467 HostFree(h);
468end:
469 HostCleanup();
470 return ret;
471}
472
473static int HostBitTest11 (void)
474{
475 int ret = 0;
476
477 HostInitConfig(true);
478 Host *h = HostAlloc();
479 if (h == NULL)
480 goto end;
481
482 HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
483 HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
484 HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
485 HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
486
487 XBit *fb = HostBitGet(h,3);
488 if (fb == NULL)
489 goto end;
490
491 HostBitRemove(h,3);
492
493 fb = HostBitGet(h,3);
494 if (fb != NULL) {
495 printf("fb != NULL even though it was removed: ");
496 goto end;
497 }
498
499 ret = 1;
500 HostFree(h);
501end:
502 HostCleanup();
503 return ret;
504}
505
506#endif /* UNITTESTS */
507
509{
510#ifdef UNITTESTS
511 UtRegisterTest("HostBitTest01", HostBitTest01);
512 UtRegisterTest("HostBitTest02", HostBitTest02);
513 UtRegisterTest("HostBitTest03", HostBitTest03);
514 UtRegisterTest("HostBitTest04", HostBitTest04);
515 UtRegisterTest("HostBitTest05", HostBitTest05);
516 UtRegisterTest("HostBitTest06", HostBitTest06);
517 UtRegisterTest("HostBitTest07", HostBitTest07);
518 UtRegisterTest("HostBitTest08", HostBitTest08);
519 UtRegisterTest("HostBitTest09", HostBitTest09);
520 UtRegisterTest("HostBitTest10", HostBitTest10);
521 UtRegisterTest("HostBitTest11", HostBitTest11);
522#endif /* UNITTESTS */
523}
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
HostStorageId HostStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Register a Host storage.
int HostSetStorageById(Host *h, HostStorageId id, void *ptr)
Store a pointer in a given Host storage.
void * HostGetStorageById(Host *h, HostStorageId id)
Get a value from a given Host storage.
void HostBitSet(Host *h, uint32_t idx, SCTime_t expire)
Definition host-bit.c:131
void HostBitUnset(Host *h, uint32_t idx)
Definition host-bit.c:139
int HostBitIsnotset(Host *h, uint32_t idx, SCTime_t ts)
Definition host-bit.c:170
void HostBitToggle(Host *h, uint32_t idx, SCTime_t expire)
Definition host-bit.c:147
int HostHasHostBits(Host *host)
Definition host-bit.c:58
int HostBitsTimedoutCheck(Host *h, SCTime_t ts)
Definition host-bit.c:67
int HostBitList(Host *h, XBit **iter)
Definition host-bit.c:184
void HostBitRegisterTests(void)
Definition host-bit.c:508
int HostBitIsset(Host *h, uint32_t idx, SCTime_t ts)
Definition host-bit.c:157
void HostBitInitCtx(void)
Definition host-bit.c:49
void HostCleanup(void)
Cleanup the host engine.
Definition host.c:332
void HostInitConfig(bool quiet)
initialize the configuration
Definition host.c:168
Host * HostAlloc(void)
Definition host.c:106
void HostFree(Host *h)
Definition host.c:125
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
Definition host.h:58
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