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