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 "host-storage.h"
39 
40 static SCHostStorageId host_bit_id = { .id = -1 }; /**< Host storage id for bits */
41 
42 static void HostBitFreeAll(void *store)
43 {
44  GenericVar *gv = store;
45  SCGenericVarFree(gv);
46 }
47 
48 void HostBitInitCtx(void)
49 {
50  host_bit_id = SCHostStorageRegister("bit", HostBitFreeAll);
51  if (host_bit_id.id == -1) {
52  FatalError("Can't initiate host storage for bits");
53  }
54 }
55 
56 /* lock before using this */
58 {
59  if (host == NULL)
60  return 0;
61  return SCHostGetStorageById(host, host_bit_id) ? 1 : 0;
62 }
63 
64 /** \retval 1 host timed out wrt xbits
65  * \retval 0 host still has active (non-expired) xbits */
67 {
68  GenericVar *gv = SCHostGetStorageById(h, host_bit_id);
69  for ( ; gv != NULL; gv = gv->next) {
70  if (gv->type == DETECT_XBITS) {
71  XBit *xb = (XBit *)gv;
72  if (SCTIME_CMP_GT(xb->expire, ts))
73  return 0;
74  }
75  }
76  return 1;
77 }
78 
79 /* get the bit with idx from the host */
80 static XBit *HostBitGet(Host *h, uint32_t idx)
81 {
82  GenericVar *gv = SCHostGetStorageById(h, host_bit_id);
83  for ( ; gv != NULL; gv = gv->next) {
84  if (gv->type == DETECT_XBITS && gv->idx == idx) {
85  return (XBit *)gv;
86  }
87  }
88 
89  return NULL;
90 }
91 
92 /* add a flowbit to the flow */
93 static void HostBitAdd(Host *h, uint32_t idx, SCTime_t expire)
94 {
95  XBit *fb = HostBitGet(h, idx);
96  if (fb == NULL) {
97  fb = SCMalloc(sizeof(XBit));
98  if (unlikely(fb == NULL))
99  return;
100 
101  fb->type = DETECT_XBITS;
102  fb->idx = idx;
103  fb->next = NULL;
104  fb->expire = expire;
105 
106  GenericVar *gv = SCHostGetStorageById(h, host_bit_id);
107  GenericVarAppend(&gv, (GenericVar *)fb);
108  SCHostSetStorageById(h, host_bit_id, gv);
109 
110  // bit already set, lets update it's time
111  } else {
112  fb->expire = expire;
113  }
114 }
115 
116 static void HostBitRemove(Host *h, uint32_t idx)
117 {
118  XBit *fb = HostBitGet(h, idx);
119  if (fb == NULL)
120  return;
121 
122  GenericVar *gv = SCHostGetStorageById(h, host_bit_id);
123  if (gv) {
124  GenericVarRemove(&gv, (GenericVar *)fb);
125  XBitFree(fb);
126  SCHostSetStorageById(h, host_bit_id, gv);
127  }
128 }
129 
130 void HostBitSet(Host *h, uint32_t idx, SCTime_t expire)
131 {
132  XBit *fb = HostBitGet(h, idx);
133  if (fb == NULL) {
134  HostBitAdd(h, idx, expire);
135  }
136 }
137 
138 void HostBitUnset(Host *h, uint32_t idx)
139 {
140  XBit *fb = HostBitGet(h, idx);
141  if (fb != NULL) {
142  HostBitRemove(h, idx);
143  }
144 }
145 
146 void HostBitToggle(Host *h, uint32_t idx, SCTime_t expire)
147 {
148  XBit *fb = HostBitGet(h, idx);
149  if (fb != NULL) {
150  HostBitRemove(h, idx);
151  } else {
152  HostBitAdd(h, idx, expire);
153  }
154 }
155 
156 int HostBitIsset(Host *h, uint32_t idx, SCTime_t ts)
157 {
158  XBit *fb = HostBitGet(h, idx);
159  if (fb != NULL) {
160  if (SCTIME_CMP_LT(fb->expire, ts)) {
161  HostBitRemove(h,idx);
162  return 0;
163  }
164  return 1;
165  }
166  return 0;
167 }
168 
169 int HostBitIsnotset(Host *h, uint32_t idx, SCTime_t ts)
170 {
171  XBit *fb = HostBitGet(h, idx);
172  if (fb == NULL) {
173  return 1;
174  }
175 
176  if (SCTIME_CMP_LT(fb->expire, ts)) {
177  HostBitRemove(h,idx);
178  return 1;
179  }
180  return 0;
181 }
182 
183 int HostBitList(Host *h, XBit **iter)
184 {
185  GenericVar *gv = (GenericVar *)*iter;
186  if (gv == NULL) {
187  gv = SCHostGetStorageById(h, host_bit_id);
188  } else {
189  gv = gv->next;
190  }
191 
192  for ( ; gv != NULL; gv = gv->next) {
193  if (gv->type == DETECT_XBITS) {
194  *iter = (XBit *)gv;
195  return 1;
196  }
197  }
198  *iter = NULL;
199  return 0;
200 }
201 
202 /* TESTS */
203 #ifdef UNITTESTS
204 static int HostBitTest01 (void)
205 {
206  int ret = 0;
207 
209  SCStorageInit();
210  HostBitInitCtx();
212 
213  HostInitConfig(true);
214  Host *h = HostAlloc();
215  if (h == NULL)
216  goto end;
217 
218  HostBitAdd(h, 0, SCTIME_FROM_SECS(0));
219 
220  XBit *fb = HostBitGet(h,0);
221  if (fb != NULL)
222  ret = 1;
223 
224  HostFree(h);
225 end:
226  HostShutdown();
228  return ret;
229 }
230 
231 static int HostBitTest02 (void)
232 {
233  int ret = 0;
234 
236  SCStorageInit();
237  HostBitInitCtx();
239 
240  HostInitConfig(true);
241  Host *h = HostAlloc();
242  if (h == NULL)
243  goto end;
244 
245  XBit *fb = HostBitGet(h,0);
246  if (fb == NULL)
247  ret = 1;
248 
249  HostFree(h);
250 end:
251  HostShutdown();
253  return ret;
254 }
255 
256 static int HostBitTest03 (void)
257 {
258  int ret = 0;
259 
261  SCStorageInit();
262  HostBitInitCtx();
264 
265  HostInitConfig(true);
266  Host *h = HostAlloc();
267  if (h == NULL)
268  goto end;
269 
270  HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
271 
272  XBit *fb = HostBitGet(h,0);
273  if (fb == NULL) {
274  printf("fb == NULL although it was just added: ");
275  goto end;
276  }
277 
278  HostBitRemove(h, 0);
279 
280  fb = HostBitGet(h,0);
281  if (fb != NULL) {
282  printf("fb != NULL although it was just removed: ");
283  goto end;
284  } else {
285  ret = 1;
286  }
287 
288  HostFree(h);
289 end:
290  HostShutdown();
292  return ret;
293 }
294 
295 static int HostBitTest04 (void)
296 {
297  int ret = 0;
298 
300  SCStorageInit();
301  HostBitInitCtx();
303 
304  HostInitConfig(true);
305  Host *h = HostAlloc();
306  if (h == NULL)
307  goto end;
308 
309  HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
310  HostBitAdd(h, 1, SCTIME_FROM_SECS(30));
311  HostBitAdd(h, 2, SCTIME_FROM_SECS(30));
312  HostBitAdd(h, 3, SCTIME_FROM_SECS(30));
313 
314  XBit *fb = HostBitGet(h,0);
315  if (fb != NULL)
316  ret = 1;
317 
318  HostFree(h);
319 end:
320  HostShutdown();
322  return ret;
323 }
324 
325 static int HostBitTest05 (void)
326 {
327  int ret = 0;
328 
330  SCStorageInit();
331  HostBitInitCtx();
333 
334  HostInitConfig(true);
335  Host *h = HostAlloc();
336  if (h == NULL)
337  goto end;
338 
339  HostBitAdd(h, 0, SCTIME_FROM_SECS(30));
340  HostBitAdd(h, 1, SCTIME_FROM_SECS(30));
341  HostBitAdd(h, 2, SCTIME_FROM_SECS(30));
342  HostBitAdd(h, 3, SCTIME_FROM_SECS(30));
343 
344  XBit *fb = HostBitGet(h,1);
345  if (fb != NULL)
346  ret = 1;
347 
348  HostFree(h);
349 end:
350  HostShutdown();
352  return ret;
353 }
354 
355 static int HostBitTest06 (void)
356 {
357  int ret = 0;
358 
360  SCStorageInit();
361  HostBitInitCtx();
363 
364  HostInitConfig(true);
365  Host *h = HostAlloc();
366  if (h == NULL)
367  goto end;
368 
369  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
370  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
371  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
372  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
373 
374  XBit *fb = HostBitGet(h,2);
375  if (fb != NULL)
376  ret = 1;
377 
378  HostFree(h);
379 end:
380  HostShutdown();
382  return ret;
383 }
384 
385 static int HostBitTest07 (void)
386 {
387  int ret = 0;
388 
390  SCStorageInit();
391  HostBitInitCtx();
393 
394  HostInitConfig(true);
395  Host *h = HostAlloc();
396  if (h == NULL)
397  goto end;
398 
399  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
400  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
401  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
402  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
403 
404  XBit *fb = HostBitGet(h,3);
405  if (fb != NULL)
406  ret = 1;
407 
408  HostFree(h);
409 end:
410  HostShutdown();
412  return ret;
413 }
414 
415 static int HostBitTest08 (void)
416 {
417  int ret = 0;
418 
420  SCStorageInit();
421  HostBitInitCtx();
423 
424  HostInitConfig(true);
425  Host *h = HostAlloc();
426  if (h == NULL)
427  goto end;
428 
429  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
430  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
431  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
432  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
433 
434  XBit *fb = HostBitGet(h,0);
435  if (fb == NULL)
436  goto end;
437 
438  HostBitRemove(h,0);
439 
440  fb = HostBitGet(h,0);
441  if (fb != NULL) {
442  printf("fb != NULL even though it was removed: ");
443  goto end;
444  }
445 
446  ret = 1;
447  HostFree(h);
448 end:
449  HostShutdown();
451  return ret;
452 }
453 
454 static int HostBitTest09 (void)
455 {
456  int ret = 0;
457 
459  SCStorageInit();
460  HostBitInitCtx();
462 
463  HostInitConfig(true);
464  Host *h = HostAlloc();
465  if (h == NULL)
466  goto end;
467 
468  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
469  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
470  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
471  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
472 
473  XBit *fb = HostBitGet(h,1);
474  if (fb == NULL)
475  goto end;
476 
477  HostBitRemove(h,1);
478 
479  fb = HostBitGet(h,1);
480  if (fb != NULL) {
481  printf("fb != NULL even though it was removed: ");
482  goto end;
483  }
484 
485  ret = 1;
486  HostFree(h);
487 end:
488  HostShutdown();
490  return ret;
491 }
492 
493 static int HostBitTest10 (void)
494 {
495  int ret = 0;
496 
498  SCStorageInit();
499  HostBitInitCtx();
501 
502  HostInitConfig(true);
503  Host *h = HostAlloc();
504  if (h == NULL)
505  goto end;
506 
507  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
508  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
509  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
510  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
511 
512  XBit *fb = HostBitGet(h,2);
513  if (fb == NULL)
514  goto end;
515 
516  HostBitRemove(h,2);
517 
518  fb = HostBitGet(h,2);
519  if (fb != NULL) {
520  printf("fb != NULL even though it was removed: ");
521  goto end;
522  }
523 
524  ret = 1;
525  HostFree(h);
526 end:
527  HostShutdown();
529  return ret;
530 }
531 
532 static int HostBitTest11 (void)
533 {
534  int ret = 0;
535 
537  SCStorageInit();
538  HostBitInitCtx();
540 
541  HostInitConfig(true);
542  Host *h = HostAlloc();
543  if (h == NULL)
544  goto end;
545 
546  HostBitAdd(h, 0, SCTIME_FROM_SECS(90));
547  HostBitAdd(h, 1, SCTIME_FROM_SECS(90));
548  HostBitAdd(h, 2, SCTIME_FROM_SECS(90));
549  HostBitAdd(h, 3, SCTIME_FROM_SECS(90));
550 
551  XBit *fb = HostBitGet(h,3);
552  if (fb == NULL)
553  goto end;
554 
555  HostBitRemove(h,3);
556 
557  fb = HostBitGet(h,3);
558  if (fb != NULL) {
559  printf("fb != NULL even though it was removed: ");
560  goto end;
561  }
562 
563  ret = 1;
564  HostFree(h);
565 end:
566  HostShutdown();
568  return ret;
569 }
570 
571 #endif /* UNITTESTS */
572 
574 {
575 #ifdef UNITTESTS
576  UtRegisterTest("HostBitTest01", HostBitTest01);
577  UtRegisterTest("HostBitTest02", HostBitTest02);
578  UtRegisterTest("HostBitTest03", HostBitTest03);
579  UtRegisterTest("HostBitTest04", HostBitTest04);
580  UtRegisterTest("HostBitTest05", HostBitTest05);
581  UtRegisterTest("HostBitTest06", HostBitTest06);
582  UtRegisterTest("HostBitTest07", HostBitTest07);
583  UtRegisterTest("HostBitTest08", HostBitTest08);
584  UtRegisterTest("HostBitTest09", HostBitTest09);
585  UtRegisterTest("HostBitTest10", HostBitTest10);
586  UtRegisterTest("HostBitTest11", HostBitTest11);
587 #endif /* UNITTESTS */
588 }
host.h
HostBitList
int HostBitList(Host *h, XBit **iter)
Definition: host-bit.c:183
ts
uint64_t ts
Definition: source-erf-file.c:68
GenericVarAppend
void GenericVarAppend(GenericVar **list, GenericVar *gv)
Definition: util-var.c:98
host-storage.h
HostAlloc
Host * HostAlloc(void)
Definition: host.c:106
SCStorageInit
void SCStorageInit(void)
Definition: util-storage.c:67
XBit_::next
GenericVar * next
Definition: util-var.h:65
SCHostGetStorageById
void * SCHostGetStorageById(Host *h, SCHostStorageId id)
Get a value from a given Host storage.
Definition: host-storage.c:84
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:101
SCHostSetStorageById
int SCHostSetStorageById(Host *h, SCHostStorageId id, void *ptr)
Store a pointer in a given Host storage.
Definition: host-storage.c:71
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:130
util-var.h
HostBitInitCtx
void HostBitInitCtx(void)
Definition: host-bit.c:48
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:138
detect.h
HostHasHostBits
int HostHasHostBits(Host *host)
Definition: host-bit.c:57
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:73
GenericVar_::idx
uint32_t idx
Definition: util-var.h:56
GenericVarRemove
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition: util-var.c:117
SCTime_t
Definition: util-time.h:40
HostBitIsset
int HostBitIsset(Host *h, uint32_t idx, SCTime_t ts)
Definition: host-bit.c:156
HostBitRegisterTests
void HostBitRegisterTests(void)
Definition: host-bit.c:573
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:146
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:169
HostShutdown
void HostShutdown(void)
shutdown the flow engine
Definition: host.c:296
FatalError
#define FatalError(...)
Definition: util-debug.h:517
HostBitsTimedoutCheck
int HostBitsTimedoutCheck(Host *h, SCTime_t ts)
Definition: host-bit.c:66
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
SCStorageCleanup
void SCStorageCleanup(void)
Definition: util-storage.c:75
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
SCHostStorageRegister
SCHostStorageId SCHostStorageRegister(const char *name, void(*Free)(void *))
Register a Host storage.
Definition: host-storage.c:56
SCStorageFinalize
int SCStorageFinalize(void)
Definition: util-storage.c:134
host-bit.h
XBitFree
void XBitFree(XBit *fb)
Definition: util-var.c:40