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 
41 static HostStorageId host_bit_id = { .id = -1 }; /**< Host storage id for bits */
42 
43 static void HostBitFreeAll(void *store)
44 {
45  GenericVar *gv = store;
46  SCGenericVarFree(gv);
47 }
48 
49 void HostBitInitCtx(void)
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 */
81 static 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 */
94 static 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 
117 static 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 
131 void 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 
139 void HostBitUnset(Host *h, uint32_t idx)
140 {
141  XBit *fb = HostBitGet(h, idx);
142  if (fb != NULL) {
143  HostBitRemove(h, idx);
144  }
145 }
146 
147 void 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 
157 int 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 
170 int 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 
184 int 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
205 static int HostBitTest01 (void)
206 {
207  int ret = 0;
208 
209  StorageCleanup();
210  StorageInit();
211  HostBitInitCtx();
212  StorageFinalize();
213 
214  HostInitConfig(true);
215  Host *h = HostAlloc();
216  if (h == NULL)
217  goto end;
218 
219  HostBitAdd(h, 0, SCTIME_FROM_SECS(0));
220 
221  XBit *fb = HostBitGet(h,0);
222  if (fb != NULL)
223  ret = 1;
224 
225  HostFree(h);
226 end:
227  HostShutdown();
228  StorageCleanup();
229  return ret;
230 }
231 
232 static int HostBitTest02 (void)
233 {
234  int ret = 0;
235 
236  StorageCleanup();
237  StorageInit();
238  HostBitInitCtx();
239  StorageFinalize();
240 
241  HostInitConfig(true);
242  Host *h = HostAlloc();
243  if (h == NULL)
244  goto end;
245 
246  XBit *fb = HostBitGet(h,0);
247  if (fb == NULL)
248  ret = 1;
249 
250  HostFree(h);
251 end:
252  HostShutdown();
253  StorageCleanup();
254  return ret;
255 }
256 
257 static int HostBitTest03 (void)
258 {
259  int ret = 0;
260 
261  StorageCleanup();
262  StorageInit();
263  HostBitInitCtx();
264  StorageFinalize();
265 
266  HostInitConfig(true);
267  Host *h = HostAlloc();
268  if (h == NULL)
269  goto end;
270 
271  HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
272 
273  XBit *fb = HostBitGet(h,0);
274  if (fb == NULL) {
275  printf("fb == NULL although it was just added: ");
276  goto end;
277  }
278 
279  HostBitRemove(h, 0);
280 
281  fb = HostBitGet(h,0);
282  if (fb != NULL) {
283  printf("fb != NULL although it was just removed: ");
284  goto end;
285  } else {
286  ret = 1;
287  }
288 
289  HostFree(h);
290 end:
291  HostShutdown();
292  StorageCleanup();
293  return ret;
294 }
295 
296 static int HostBitTest04 (void)
297 {
298  int ret = 0;
299 
300  StorageCleanup();
301  StorageInit();
302  HostBitInitCtx();
303  StorageFinalize();
304 
305  HostInitConfig(true);
306  Host *h = HostAlloc();
307  if (h == NULL)
308  goto end;
309 
310  HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
311  HostBitAdd(h, 1, SCTIME_FROM_SECS(30));
312  HostBitAdd(h, 2, SCTIME_FROM_SECS(30));
313  HostBitAdd(h, 3, SCTIME_FROM_SECS(30));
314 
315  XBit *fb = HostBitGet(h,0);
316  if (fb != NULL)
317  ret = 1;
318 
319  HostFree(h);
320 end:
321  HostShutdown();
322  StorageCleanup();
323  return ret;
324 }
325 
326 static int HostBitTest05 (void)
327 {
328  int ret = 0;
329 
330  StorageCleanup();
331  StorageInit();
332  HostBitInitCtx();
333  StorageFinalize();
334 
335  HostInitConfig(true);
336  Host *h = HostAlloc();
337  if (h == NULL)
338  goto end;
339 
340  HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
341  HostBitAdd(h, 1, SCTIME_FROM_SECS(30));
342  HostBitAdd(h, 2, SCTIME_FROM_SECS(30));
343  HostBitAdd(h, 3, SCTIME_FROM_SECS(30));
344 
345  XBit *fb = HostBitGet(h,1);
346  if (fb != NULL)
347  ret = 1;
348 
349  HostFree(h);
350 end:
351  HostShutdown();
352  StorageCleanup();
353  return ret;
354 }
355 
356 static int HostBitTest06 (void)
357 {
358  int ret = 0;
359 
360  StorageCleanup();
361  StorageInit();
362  HostBitInitCtx();
363  StorageFinalize();
364 
365  HostInitConfig(true);
366  Host *h = HostAlloc();
367  if (h == NULL)
368  goto end;
369 
370  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
371  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
372  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
373  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
374 
375  XBit *fb = HostBitGet(h,2);
376  if (fb != NULL)
377  ret = 1;
378 
379  HostFree(h);
380 end:
381  HostShutdown();
382  StorageCleanup();
383  return ret;
384 }
385 
386 static int HostBitTest07 (void)
387 {
388  int ret = 0;
389 
390  StorageCleanup();
391  StorageInit();
392  HostBitInitCtx();
393  StorageFinalize();
394 
395  HostInitConfig(true);
396  Host *h = HostAlloc();
397  if (h == NULL)
398  goto end;
399 
400  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
401  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
402  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
403  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
404 
405  XBit *fb = HostBitGet(h,3);
406  if (fb != NULL)
407  ret = 1;
408 
409  HostFree(h);
410 end:
411  HostShutdown();
412  StorageCleanup();
413  return ret;
414 }
415 
416 static int HostBitTest08 (void)
417 {
418  int ret = 0;
419 
420  StorageCleanup();
421  StorageInit();
422  HostBitInitCtx();
423  StorageFinalize();
424 
425  HostInitConfig(true);
426  Host *h = HostAlloc();
427  if (h == NULL)
428  goto end;
429 
430  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
431  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
432  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
433  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
434 
435  XBit *fb = HostBitGet(h,0);
436  if (fb == NULL)
437  goto end;
438 
439  HostBitRemove(h,0);
440 
441  fb = HostBitGet(h,0);
442  if (fb != NULL) {
443  printf("fb != NULL even though it was removed: ");
444  goto end;
445  }
446 
447  ret = 1;
448  HostFree(h);
449 end:
450  HostShutdown();
451  StorageCleanup();
452  return ret;
453 }
454 
455 static int HostBitTest09 (void)
456 {
457  int ret = 0;
458 
459  StorageCleanup();
460  StorageInit();
461  HostBitInitCtx();
462  StorageFinalize();
463 
464  HostInitConfig(true);
465  Host *h = HostAlloc();
466  if (h == NULL)
467  goto end;
468 
469  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
470  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
471  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
472  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
473 
474  XBit *fb = HostBitGet(h,1);
475  if (fb == NULL)
476  goto end;
477 
478  HostBitRemove(h,1);
479 
480  fb = HostBitGet(h,1);
481  if (fb != NULL) {
482  printf("fb != NULL even though it was removed: ");
483  goto end;
484  }
485 
486  ret = 1;
487  HostFree(h);
488 end:
489  HostShutdown();
490  StorageCleanup();
491  return ret;
492 }
493 
494 static int HostBitTest10 (void)
495 {
496  int ret = 0;
497 
498  StorageCleanup();
499  StorageInit();
500  HostBitInitCtx();
501  StorageFinalize();
502 
503  HostInitConfig(true);
504  Host *h = HostAlloc();
505  if (h == NULL)
506  goto end;
507 
508  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
509  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
510  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
511  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
512 
513  XBit *fb = HostBitGet(h,2);
514  if (fb == NULL)
515  goto end;
516 
517  HostBitRemove(h,2);
518 
519  fb = HostBitGet(h,2);
520  if (fb != NULL) {
521  printf("fb != NULL even though it was removed: ");
522  goto end;
523  }
524 
525  ret = 1;
526  HostFree(h);
527 end:
528  HostShutdown();
529  StorageCleanup();
530  return ret;
531 }
532 
533 static int HostBitTest11 (void)
534 {
535  int ret = 0;
536 
537  StorageCleanup();
538  StorageInit();
539  HostBitInitCtx();
540  StorageFinalize();
541 
542  HostInitConfig(true);
543  Host *h = HostAlloc();
544  if (h == NULL)
545  goto end;
546 
547  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
548  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
549  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
550  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
551 
552  XBit *fb = HostBitGet(h,3);
553  if (fb == NULL)
554  goto end;
555 
556  HostBitRemove(h,3);
557 
558  fb = HostBitGet(h,3);
559  if (fb != NULL) {
560  printf("fb != NULL even though it was removed: ");
561  goto end;
562  }
563 
564  ret = 1;
565  HostFree(h);
566 end:
567  HostShutdown();
568  StorageCleanup();
569  return ret;
570 }
571 
572 #endif /* UNITTESTS */
573 
575 {
576 #ifdef UNITTESTS
577  UtRegisterTest("HostBitTest01", HostBitTest01);
578  UtRegisterTest("HostBitTest02", HostBitTest02);
579  UtRegisterTest("HostBitTest03", HostBitTest03);
580  UtRegisterTest("HostBitTest04", HostBitTest04);
581  UtRegisterTest("HostBitTest05", HostBitTest05);
582  UtRegisterTest("HostBitTest06", HostBitTest06);
583  UtRegisterTest("HostBitTest07", HostBitTest07);
584  UtRegisterTest("HostBitTest08", HostBitTest08);
585  UtRegisterTest("HostBitTest09", HostBitTest09);
586  UtRegisterTest("HostBitTest10", HostBitTest10);
587  UtRegisterTest("HostBitTest11", HostBitTest11);
588 #endif /* UNITTESTS */
589 }
host.h
HostBitList
int HostBitList(Host *h, XBit **iter)
Definition: host-bit.c:184
ts
uint64_t ts
Definition: source-erf-file.c:55
GenericVarAppend
void GenericVarAppend(GenericVar **list, GenericVar *gv)
Definition: util-var.c:98
host-storage.h
HostAlloc
Host * HostAlloc(void)
Definition: host.c:106
XBit_::next
GenericVar * next
Definition: util-var.h:65
StorageInit
void StorageInit(void)
Definition: util-storage.c:70
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
HostStorageRegister
HostStorageId HostStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Register a Host storage.
Definition: host-storage.c:59
threads.h
XBit_::expire
SCTime_t expire
Definition: util-var.h:66
HostBitSet
void HostBitSet(Host *h, uint32_t idx, SCTime_t expire)
Definition: host-bit.c:131
StorageCleanup
void StorageCleanup(void)
Definition: util-storage.c:78
HostGetStorageById
void * HostGetStorageById(Host *h, HostStorageId id)
Get a value from a given Host storage.
Definition: host-storage.c:88
util-var.h
HostBitInitCtx
void HostBitInitCtx(void)
Definition: host-bit.c:49
util-unittest.h
SCTIME_FROM_SECS
#define SCTIME_FROM_SECS(s)
Definition: util-time.h:69
util-debug.h
GenericVar_::next
struct GenericVar_ * next
Definition: util-var.h:57
HostBitUnset
void HostBitUnset(Host *h, uint32_t idx)
Definition: host-bit.c:139
detect.h
HostHasHostBits
int HostHasHostBits(Host *host)
Definition: host-bit.c:58
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:64
GenericVar_::idx
uint32_t idx
Definition: util-var.h:56
GenericVarRemove
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition: util-var.c:117
StorageFinalize
int StorageFinalize(void)
Definition: util-storage.c:140
SCTime_t
Definition: util-time.h:40
HostBitIsset
int HostBitIsset(Host *h, uint32_t idx, SCTime_t ts)
Definition: host-bit.c:157
HostBitRegisterTests
void HostBitRegisterTests(void)
Definition: host-bit.c:574
SCTIME_CMP_LT
#define SCTIME_CMP_LT(a, b)
Definition: util-time.h:105
HostBitToggle
void HostBitToggle(Host *h, uint32_t idx, SCTime_t expire)
Definition: host-bit.c:147
XBit_::type
uint16_t type
Definition: util-var.h:62
SCGenericVarFree
void SCGenericVarFree(GenericVar *gv)
Definition: util-var.c:48
suricata-common.h
GenericVar_
Definition: util-var.h:53
HostBitIsnotset
int HostBitIsnotset(Host *h, uint32_t idx, SCTime_t ts)
Definition: host-bit.c:170
HostShutdown
void HostShutdown(void)
shutdown the flow engine
Definition: host.c:296
FatalError
#define FatalError(...)
Definition: util-debug.h:514
HostBitsTimedoutCheck
int HostBitsTimedoutCheck(Host *h, SCTime_t ts)
Definition: host-bit.c:67
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCTIME_CMP_GT
#define SCTIME_CMP_GT(a, b)
Definition: util-time.h:104
HostStorageId_
Definition: host-storage.h:31
HostStorageId_::id
int id
Definition: host-storage.h:32
HostFree
void HostFree(Host *h)
Definition: host.c:125
GenericVar_::type
uint16_t type
Definition: util-var.h:54
HostInitConfig
void HostInitConfig(bool quiet)
initialize the configuration
Definition: host.c:168
XBit_::idx
uint32_t idx
Definition: util-var.h:64
XBit_
Definition: util-var.h:61
Host_
Definition: host.h:58
HostSetStorageById
int HostSetStorageById(Host *h, HostStorageId id, void *ptr)
Store a pointer in a given Host storage.
Definition: host-storage.c:75
host-bit.h
XBitFree
void XBitFree(XBit *fb)
Definition: util-var.c:40