suricata
ippair-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 ippair 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 "ippair-bit.h"
34 #include "ippair.h"
35 #include "detect.h"
36 #include "util-var.h"
37 #include "util-debug.h"
38 #include "util-unittest.h"
39 #include "ippair-storage.h"
40 
41 static int ippair_bit_id = -1; /**< IPPair storage id for bits */
42 
43 static void XBitFreeAll(void *store)
44 {
45  GenericVar *gv = store;
46  GenericVarFree(gv);
47 }
48 
49 void IPPairBitInitCtx(void)
50 {
51  ippair_bit_id = IPPairStorageRegister("bit", sizeof(void *), NULL, XBitFreeAll);
52  if (ippair_bit_id == -1) {
53  FatalError(SC_ERR_FATAL, "Can't initiate ippair storage for bits");
54  }
55 }
56 
57 /* lock before using this */
58 int IPPairHasBits(IPPair *ippair)
59 {
60  if (ippair == NULL)
61  return 0;
62  return IPPairGetStorageById(ippair, ippair_bit_id) ? 1 : 0;
63 }
64 
65 /** \retval 1 ippair timed out wrt xbits
66  * \retval 0 ippair still has active (non-expired) xbits */
67 int IPPairBitsTimedoutCheck(IPPair *h, struct timeval *ts)
68 {
69  GenericVar *gv = IPPairGetStorageById(h, ippair_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)ts->tv_sec)
74  return 0;
75  }
76  }
77  return 1;
78 }
79 
80 /* get the bit with idx from the ippair */
81 static XBit *IPPairBitGet(IPPair *h, uint32_t idx)
82 {
83  GenericVar *gv = IPPairGetStorageById(h, ippair_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 IPPairBitAdd(IPPair *h, uint32_t idx, uint32_t expire)
95 {
96  XBit *fb = IPPairBitGet(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 = IPPairGetStorageById(h, ippair_bit_id);
108  GenericVarAppend(&gv, (GenericVar *)fb);
109  IPPairSetStorageById(h, ippair_bit_id, gv);
110 
111  // bit already set, lets update it's timer
112  } else {
113  fb->expire = expire;
114  }
115 }
116 
117 static void IPPairBitRemove(IPPair *h, uint32_t idx)
118 {
119  XBit *fb = IPPairBitGet(h, idx);
120  if (fb == NULL)
121  return;
122 
123  GenericVar *gv = IPPairGetStorageById(h, ippair_bit_id);
124  if (gv) {
125  GenericVarRemove(&gv, (GenericVar *)fb);
126  XBitFree(fb);
127  IPPairSetStorageById(h, ippair_bit_id, gv);
128  }
129 }
130 
131 void IPPairBitSet(IPPair *h, uint32_t idx, uint32_t expire)
132 {
133  XBit *fb = IPPairBitGet(h, idx);
134  if (fb == NULL) {
135  IPPairBitAdd(h, idx, expire);
136  }
137 }
138 
139 void IPPairBitUnset(IPPair *h, uint32_t idx)
140 {
141  XBit *fb = IPPairBitGet(h, idx);
142  if (fb != NULL) {
143  IPPairBitRemove(h, idx);
144  }
145 }
146 
147 void IPPairBitToggle(IPPair *h, uint32_t idx, uint32_t expire)
148 {
149  XBit *fb = IPPairBitGet(h, idx);
150  if (fb != NULL) {
151  IPPairBitRemove(h, idx);
152  } else {
153  IPPairBitAdd(h, idx, expire);
154  }
155 }
156 
157 int IPPairBitIsset(IPPair *h, uint32_t idx, uint32_t ts)
158 {
159  XBit *fb = IPPairBitGet(h, idx);
160  if (fb != NULL) {
161  if (fb->expire < ts) {
162  IPPairBitRemove(h, idx);
163  return 0;
164  }
165 
166  return 1;
167  }
168  return 0;
169 }
170 
171 int IPPairBitIsnotset(IPPair *h, uint32_t idx, uint32_t ts)
172 {
173  XBit *fb = IPPairBitGet(h, idx);
174  if (fb == NULL) {
175  return 1;
176  }
177 
178  if (fb->expire < ts) {
179  IPPairBitRemove(h, idx);
180  return 1;
181  }
182 
183  return 0;
184 }
185 
186 
187 /* TESTS */
188 #ifdef UNITTESTS
189 static int IPPairBitTest01 (void)
190 {
191  int ret = 0;
192 
194  IPPair *h = IPPairAlloc();
195  if (h == NULL)
196  goto end;
197 
198  IPPairBitAdd(h, 0, 0);
199 
200  XBit *fb = IPPairBitGet(h,0);
201  if (fb != NULL)
202  ret = 1;
203 
204  IPPairFree(h);
205 end:
206  IPPairCleanup();
207  return ret;
208 }
209 
210 static int IPPairBitTest02 (void)
211 {
212  int ret = 0;
213 
215  IPPair *h = IPPairAlloc();
216  if (h == NULL)
217  goto end;
218 
219  XBit *fb = IPPairBitGet(h,0);
220  if (fb == NULL)
221  ret = 1;
222 
223  IPPairFree(h);
224 end:
225  IPPairCleanup();
226  return ret;
227 }
228 
229 static int IPPairBitTest03 (void)
230 {
231  int ret = 0;
232 
234  IPPair *h = IPPairAlloc();
235  if (h == NULL)
236  goto end;
237 
238  IPPairBitAdd(h, 0, 30);
239 
240  XBit *fb = IPPairBitGet(h,0);
241  if (fb == NULL) {
242  printf("fb == NULL although it was just added: ");
243  goto end;
244  }
245 
246  IPPairBitRemove(h, 0);
247 
248  fb = IPPairBitGet(h,0);
249  if (fb != NULL) {
250  printf("fb != NULL although it was just removed: ");
251  goto end;
252  } else {
253  ret = 1;
254  }
255 
256  IPPairFree(h);
257 end:
258  IPPairCleanup();
259  return ret;
260 }
261 
262 static int IPPairBitTest04 (void)
263 {
264  int ret = 0;
265 
267  IPPair *h = IPPairAlloc();
268  if (h == NULL)
269  goto end;
270 
271  IPPairBitAdd(h, 0,30);
272  IPPairBitAdd(h, 1,30);
273  IPPairBitAdd(h, 2,30);
274  IPPairBitAdd(h, 3,30);
275 
276  XBit *fb = IPPairBitGet(h,0);
277  if (fb != NULL)
278  ret = 1;
279 
280  IPPairFree(h);
281 end:
282  IPPairCleanup();
283  return ret;
284 }
285 
286 static int IPPairBitTest05 (void)
287 {
288  int ret = 0;
289 
291  IPPair *h = IPPairAlloc();
292  if (h == NULL)
293  goto end;
294 
295  IPPairBitAdd(h, 0,90);
296  IPPairBitAdd(h, 1,90);
297  IPPairBitAdd(h, 2,90);
298  IPPairBitAdd(h, 3,90);
299 
300  XBit *fb = IPPairBitGet(h,1);
301  if (fb != NULL)
302  ret = 1;
303 
304  IPPairFree(h);
305 end:
306  IPPairCleanup();
307  return ret;
308 }
309 
310 static int IPPairBitTest06 (void)
311 {
312  int ret = 0;
313 
315  IPPair *h = IPPairAlloc();
316  if (h == NULL)
317  goto end;
318 
319  IPPairBitAdd(h, 0,90);
320  IPPairBitAdd(h, 1,90);
321  IPPairBitAdd(h, 2,90);
322  IPPairBitAdd(h, 3,90);
323 
324  XBit *fb = IPPairBitGet(h,2);
325  if (fb != NULL)
326  ret = 1;
327 
328  IPPairFree(h);
329 end:
330  IPPairCleanup();
331  return ret;
332 }
333 
334 static int IPPairBitTest07 (void)
335 {
336  int ret = 0;
337 
339  IPPair *h = IPPairAlloc();
340  if (h == NULL)
341  goto end;
342 
343  IPPairBitAdd(h, 0,90);
344  IPPairBitAdd(h, 1,90);
345  IPPairBitAdd(h, 2,90);
346  IPPairBitAdd(h, 3,90);
347 
348  XBit *fb = IPPairBitGet(h,3);
349  if (fb != NULL)
350  ret = 1;
351 
352  IPPairFree(h);
353 end:
354  IPPairCleanup();
355  return ret;
356 }
357 
358 static int IPPairBitTest08 (void)
359 {
360  int ret = 0;
361 
363  IPPair *h = IPPairAlloc();
364  if (h == NULL)
365  goto end;
366 
367  IPPairBitAdd(h, 0,90);
368  IPPairBitAdd(h, 1,90);
369  IPPairBitAdd(h, 2,90);
370  IPPairBitAdd(h, 3,90);
371 
372  XBit *fb = IPPairBitGet(h,0);
373  if (fb == NULL)
374  goto end;
375 
376  IPPairBitRemove(h,0);
377 
378  fb = IPPairBitGet(h,0);
379  if (fb != NULL) {
380  printf("fb != NULL even though it was removed: ");
381  goto end;
382  }
383 
384  ret = 1;
385  IPPairFree(h);
386 end:
387  IPPairCleanup();
388  return ret;
389 }
390 
391 static int IPPairBitTest09 (void)
392 {
393  int ret = 0;
394 
396  IPPair *h = IPPairAlloc();
397  if (h == NULL)
398  goto end;
399 
400  IPPairBitAdd(h, 0,90);
401  IPPairBitAdd(h, 1,90);
402  IPPairBitAdd(h, 2,90);
403  IPPairBitAdd(h, 3,90);
404 
405  XBit *fb = IPPairBitGet(h,1);
406  if (fb == NULL)
407  goto end;
408 
409  IPPairBitRemove(h,1);
410 
411  fb = IPPairBitGet(h,1);
412  if (fb != NULL) {
413  printf("fb != NULL even though it was removed: ");
414  goto end;
415  }
416 
417  ret = 1;
418  IPPairFree(h);
419 end:
420  IPPairCleanup();
421  return ret;
422 }
423 
424 static int IPPairBitTest10 (void)
425 {
426  int ret = 0;
427 
429  IPPair *h = IPPairAlloc();
430  if (h == NULL)
431  goto end;
432 
433  IPPairBitAdd(h, 0,90);
434  IPPairBitAdd(h, 1,90);
435  IPPairBitAdd(h, 2,90);
436  IPPairBitAdd(h, 3,90);
437 
438  XBit *fb = IPPairBitGet(h,2);
439  if (fb == NULL)
440  goto end;
441 
442  IPPairBitRemove(h,2);
443 
444  fb = IPPairBitGet(h,2);
445  if (fb != NULL) {
446  printf("fb != NULL even though it was removed: ");
447  goto end;
448  }
449 
450  ret = 1;
451  IPPairFree(h);
452 end:
453  IPPairCleanup();
454  return ret;
455 }
456 
457 static int IPPairBitTest11 (void)
458 {
459  int ret = 0;
460 
462  IPPair *h = IPPairAlloc();
463  if (h == NULL)
464  goto end;
465 
466  IPPairBitAdd(h, 0,90);
467  IPPairBitAdd(h, 1,90);
468  IPPairBitAdd(h, 2,90);
469  IPPairBitAdd(h, 3,90);
470 
471  XBit *fb = IPPairBitGet(h,3);
472  if (fb == NULL)
473  goto end;
474 
475  IPPairBitRemove(h,3);
476 
477  fb = IPPairBitGet(h,3);
478  if (fb != NULL) {
479  printf("fb != NULL even though it was removed: ");
480  goto end;
481  }
482 
483  ret = 1;
484  IPPairFree(h);
485 end:
486  IPPairCleanup();
487  return ret;
488 }
489 
490 #endif /* UNITTESTS */
491 
493 {
494 #ifdef UNITTESTS
495  UtRegisterTest("IPPairBitTest01", IPPairBitTest01);
496  UtRegisterTest("IPPairBitTest02", IPPairBitTest02);
497  UtRegisterTest("IPPairBitTest03", IPPairBitTest03);
498  UtRegisterTest("IPPairBitTest04", IPPairBitTest04);
499  UtRegisterTest("IPPairBitTest05", IPPairBitTest05);
500  UtRegisterTest("IPPairBitTest06", IPPairBitTest06);
501  UtRegisterTest("IPPairBitTest07", IPPairBitTest07);
502  UtRegisterTest("IPPairBitTest08", IPPairBitTest08);
503  UtRegisterTest("IPPairBitTest09", IPPairBitTest09);
504  UtRegisterTest("IPPairBitTest10", IPPairBitTest10);
505  UtRegisterTest("IPPairBitTest11", IPPairBitTest11);
506 #endif /* UNITTESTS */
507 }
IPPairBitUnset
void IPPairBitUnset(IPPair *h, uint32_t idx)
Definition: ippair-bit.c:139
GenericVar_::type
uint8_t type
Definition: util-var.h:49
ts
uint64_t ts
Definition: source-erf-file.c:54
GenericVarAppend
void GenericVarAppend(GenericVar **list, GenericVar *gv)
Definition: util-var.c:92
XBit_::expire
uint32_t expire
Definition: util-var.h:60
ippair.h
XBit_::next
GenericVar * next
Definition: util-var.h:59
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
ippair-bit.h
threads.h
IPPairBitsTimedoutCheck
int IPPairBitsTimedoutCheck(IPPair *h, struct timeval *ts)
Definition: ippair-bit.c:67
IPPairBitSet
void IPPairBitSet(IPPair *h, uint32_t idx, uint32_t expire)
Definition: ippair-bit.c:131
IPPairAlloc
IPPair * IPPairAlloc(void)
Definition: ippair.c:108
util-var.h
util-unittest.h
IPPairFree
void IPPairFree(IPPair *h)
Definition: ippair.c:130
util-debug.h
GenericVar_::next
struct GenericVar_ * next
Definition: util-var.h:52
IPPairBitToggle
void IPPairBitToggle(IPPair *h, uint32_t idx, uint32_t expire)
Definition: ippair-bit.c:147
IPPairCleanup
void IPPairCleanup(void)
Cleanup the ippair engine.
Definition: ippair.c:338
detect.h
IPPairInitConfig
void IPPairInitConfig(char quiet)
initialize the configuration
Definition: ippair.c:168
TRUE
#define TRUE
Definition: suricata-common.h:33
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:227
GenericVar_::idx
uint32_t idx
Definition: util-var.h:51
IPPairBitIsnotset
int IPPairBitIsnotset(IPPair *h, uint32_t idx, uint32_t ts)
Definition: ippair-bit.c:171
GenericVarRemove
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition: util-var.c:111
XBit_::type
uint8_t type
Definition: util-var.h:56
IPPairStorageRegister
int IPPairStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Definition: ippair-storage.c:61
IPPairGetStorageById
void * IPPairGetStorageById(IPPair *h, int id)
Definition: ippair-storage.c:35
IPPairHasBits
int IPPairHasBits(IPPair *ippair)
Definition: ippair-bit.c:58
suricata-common.h
IPPair_
Definition: ippair.h:58
GenericVar_
Definition: util-var.h:48
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
IPPairBitInitCtx
void IPPairBitInitCtx(void)
Definition: ippair-bit.c:49
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
XBit_::idx
uint32_t idx
Definition: util-var.h:58
IPPairBitIsset
int IPPairBitIsset(IPPair *h, uint32_t idx, uint32_t ts)
Definition: ippair-bit.c:157
IPPairBitRegisterTests
void IPPairBitRegisterTests(void)
Definition: ippair-bit.c:492
XBit_
Definition: util-var.h:55
IPPairSetStorageById
int IPPairSetStorageById(IPPair *h, int id, void *ptr)
Definition: ippair-storage.c:40
GenericVarFree
void GenericVarFree(GenericVar *gv)
Definition: util-var.c:47
ippair-storage.h
XBitFree
void XBitFree(XBit *fb)
Definition: util-var.c:39