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