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  GenericVarFree(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 (xb->expire > (uint32_t)SCTIME_SECS(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, uint32_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, uint32_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, uint32_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, uint32_t ts)
158 {
159  XBit *fb = HostBitGet(h, idx);
160  if (fb != NULL) {
161  if (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, uint32_t ts)
171 {
172  XBit *fb = HostBitGet(h, idx);
173  if (fb == NULL) {
174  return 1;
175  }
176 
177  if (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  HostInitConfig(true);
210  Host *h = HostAlloc();
211  if (h == NULL)
212  goto end;
213 
214  HostBitAdd(h, 0, 0);
215 
216  XBit *fb = HostBitGet(h,0);
217  if (fb != NULL)
218  ret = 1;
219 
220  HostFree(h);
221 end:
222  HostCleanup();
223  return ret;
224 }
225 
226 static 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);
240 end:
241  HostCleanup();
242  return ret;
243 }
244 
245 static 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, 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);
273 end:
274  HostCleanup();
275  return ret;
276 }
277 
278 static 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, 30);
288  HostBitAdd(h, 1, 30);
289  HostBitAdd(h, 2, 30);
290  HostBitAdd(h, 3, 30);
291 
292  XBit *fb = HostBitGet(h,0);
293  if (fb != NULL)
294  ret = 1;
295 
296  HostFree(h);
297 end:
298  HostCleanup();
299  return ret;
300 }
301 
302 static 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, 30);
312  HostBitAdd(h, 1, 30);
313  HostBitAdd(h, 2, 30);
314  HostBitAdd(h, 3, 30);
315 
316  XBit *fb = HostBitGet(h,1);
317  if (fb != NULL)
318  ret = 1;
319 
320  HostFree(h);
321 end:
322  HostCleanup();
323  return ret;
324 }
325 
326 static 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, 90);
336  HostBitAdd(h, 1, 90);
337  HostBitAdd(h, 2, 90);
338  HostBitAdd(h, 3, 90);
339 
340  XBit *fb = HostBitGet(h,2);
341  if (fb != NULL)
342  ret = 1;
343 
344  HostFree(h);
345 end:
346  HostCleanup();
347  return ret;
348 }
349 
350 static 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, 90);
360  HostBitAdd(h, 1, 90);
361  HostBitAdd(h, 2, 90);
362  HostBitAdd(h, 3, 90);
363 
364  XBit *fb = HostBitGet(h,3);
365  if (fb != NULL)
366  ret = 1;
367 
368  HostFree(h);
369 end:
370  HostCleanup();
371  return ret;
372 }
373 
374 static 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, 90);
384  HostBitAdd(h, 1, 90);
385  HostBitAdd(h, 2, 90);
386  HostBitAdd(h, 3, 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);
402 end:
403  HostCleanup();
404  return ret;
405 }
406 
407 static 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, 90);
417  HostBitAdd(h, 1, 90);
418  HostBitAdd(h, 2, 90);
419  HostBitAdd(h, 3, 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);
435 end:
436  HostCleanup();
437  return ret;
438 }
439 
440 static 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, 90);
450  HostBitAdd(h, 1, 90);
451  HostBitAdd(h, 2, 90);
452  HostBitAdd(h, 3, 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);
468 end:
469  HostCleanup();
470  return ret;
471 }
472 
473 static 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, 90);
483  HostBitAdd(h, 1, 90);
484  HostBitAdd(h, 2, 90);
485  HostBitAdd(h, 3, 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);
501 end:
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 }
GenericVar_::type
uint8_t type
Definition: util-var.h:51
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
XBit_::expire
uint32_t expire
Definition: util-var.h:62
host-storage.h
HostAlloc
Host * HostAlloc(void)
Definition: host.c:106
HostBitToggle
void HostBitToggle(Host *h, uint32_t idx, uint32_t expire)
Definition: host-bit.c:147
XBit_::next
GenericVar * next
Definition: util-var.h:61
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
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
HostBitIsset
int HostBitIsset(Host *h, uint32_t idx, uint32_t ts)
Definition: host-bit.c:157
util-unittest.h
HostBitIsnotset
int HostBitIsnotset(Host *h, uint32_t idx, uint32_t ts)
Definition: host-bit.c:170
util-debug.h
GenericVar_::next
struct GenericVar_ * next
Definition: util-var.h:54
HostBitUnset
void HostBitUnset(Host *h, uint32_t idx)
Definition: host-bit.c:139
HostCleanup
void HostCleanup(void)
Cleanup the host engine.
Definition: host.c:332
detect.h
HostHasHostBits
int HostHasHostBits(Host *host)
Definition: host-bit.c:58
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:65
GenericVar_::idx
uint32_t idx
Definition: util-var.h:53
HostBitSet
void HostBitSet(Host *h, uint32_t idx, uint32_t expire)
Definition: host-bit.c:131
GenericVarRemove
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition: util-var.c:117
SCTime_t
Definition: util-time.h:40
XBit_::type
uint8_t type
Definition: util-var.h:58
HostBitRegisterTests
void HostBitRegisterTests(void)
Definition: host-bit.c:508
suricata-common.h
GenericVar_
Definition: util-var.h:50
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
FatalError
#define FatalError(...)
Definition: util-debug.h:502
HostBitsTimedoutCheck
int HostBitsTimedoutCheck(Host *h, SCTime_t ts)
Definition: host-bit.c:67
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
HostStorageId_
Definition: host-storage.h:31
HostStorageId_::id
int id
Definition: host-storage.h:32
HostFree
void HostFree(Host *h)
Definition: host.c:125
HostInitConfig
void HostInitConfig(bool quiet)
initialize the configuration
Definition: host.c:168
XBit_::idx
uint32_t idx
Definition: util-var.h:60
XBit_
Definition: util-var.h:57
GenericVarFree
void GenericVarFree(GenericVar *gv)
Definition: util-var.c:48
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