suricata
ippair-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 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 IPPairStorageId g_ippair_bit_storage_id = { .id = -1 }; /**< IPPair storage id for bits */
42 
43 static void XBitFreeAll(void *store)
44 {
45  GenericVar *gv = store;
46  SCGenericVarFree(gv);
47 }
48 
49 void IPPairBitInitCtx(void)
50 {
51  g_ippair_bit_storage_id = IPPairStorageRegister("bit", sizeof(void *), NULL, XBitFreeAll);
52  if (g_ippair_bit_storage_id.id == -1) {
53  FatalError("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, g_ippair_bit_storage_id) ? 1 : 0;
63 }
64 
65 /** \retval 1 ippair timed out wrt xbits
66  * \retval 0 ippair still has active (non-expired) xbits */
68 {
69  GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id);
70  for ( ; gv != NULL; gv = gv->next) {
71  if (gv->type == DETECT_XBITS) {
72  XBit *xb = (XBit *)gv;
73  if (SCTIME_CMP_GT(xb->expire, ts))
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, g_ippair_bit_storage_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, SCTime_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, g_ippair_bit_storage_id);
108  GenericVarAppend(&gv, (GenericVar *)fb);
109  IPPairSetStorageById(h, g_ippair_bit_storage_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, g_ippair_bit_storage_id);
124  if (gv) {
125  GenericVarRemove(&gv, (GenericVar *)fb);
126  XBitFree(fb);
127  IPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
128  }
129 }
130 
131 void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_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, SCTime_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, SCTime_t ts)
158 {
159  XBit *fb = IPPairBitGet(h, idx);
160  if (fb != NULL) {
161  if (SCTIME_CMP_LT(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, SCTime_t ts)
172 {
173  XBit *fb = IPPairBitGet(h, idx);
174  if (fb == NULL) {
175  return 1;
176  }
177 
178  if (SCTIME_CMP_LT(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  StorageCleanup();
192  StorageInit();
194  StorageFinalize();
195  IPPairInitConfig(true);
196  IPPair *h = IPPairAlloc();
197  FAIL_IF_NULL(h);
198 
199  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(0));
200 
201  XBit *fb = IPPairBitGet(h,0);
202  FAIL_IF_NULL(fb);
203 
204  IPPairFree(h);
205  IPPairShutdown();
206  StorageCleanup();
207  PASS;
208 }
209 
210 static int IPPairBitTest02 (void)
211 {
212  StorageCleanup();
213  StorageInit();
215  StorageFinalize();
216  IPPairInitConfig(true);
217  IPPair *h = IPPairAlloc();
218  FAIL_IF_NULL(h);
219 
220  XBit *fb = IPPairBitGet(h,0);
221  FAIL_IF_NOT_NULL(fb);
222 
223  IPPairFree(h);
224  IPPairShutdown();
225  StorageCleanup();
226  PASS;
227 }
228 
229 static int IPPairBitTest03 (void)
230 {
231  StorageCleanup();
232  StorageInit();
234  StorageFinalize();
235  IPPairInitConfig(true);
236  IPPair *h = IPPairAlloc();
237  FAIL_IF_NULL(h);
238 
239  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(30));
240 
241  XBit *fb = IPPairBitGet(h,0);
242  FAIL_IF_NULL(fb);
243 
244  IPPairBitRemove(h, 0);
245 
246  fb = IPPairBitGet(h,0);
247  FAIL_IF_NOT_NULL(fb);
248 
249  IPPairFree(h);
250  IPPairShutdown();
251  StorageCleanup();
252  PASS;
253 }
254 
255 static int IPPairBitTest04 (void)
256 {
257  StorageCleanup();
258  StorageInit();
260  StorageFinalize();
261  IPPairInitConfig(true);
262  IPPair *h = IPPairAlloc();
263  FAIL_IF_NULL(h);
264 
265  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(30));
266  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(30));
267  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(30));
268  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(30));
269 
270  XBit *fb = IPPairBitGet(h,0);
271  FAIL_IF_NULL(fb);
272 
273  IPPairFree(h);
274  IPPairShutdown();
275  StorageCleanup();
276  PASS;
277 }
278 
279 static int IPPairBitTest05 (void)
280 {
281  StorageCleanup();
282  StorageInit();
284  StorageFinalize();
285  IPPairInitConfig(true);
286  IPPair *h = IPPairAlloc();
287  FAIL_IF_NULL(h);
288 
289  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
290  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
291  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
292  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
293 
294  XBit *fb = IPPairBitGet(h,1);
295  FAIL_IF_NULL(fb);
296 
297  IPPairFree(h);
298  IPPairShutdown();
299  StorageCleanup();
300  PASS;
301 }
302 
303 static int IPPairBitTest06 (void)
304 {
305  StorageCleanup();
306  StorageInit();
308  StorageFinalize();
309  IPPairInitConfig(true);
310  IPPair *h = IPPairAlloc();
311  FAIL_IF_NULL(h);
312 
313  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
314  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
315  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
316  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
317 
318  XBit *fb = IPPairBitGet(h,2);
319  FAIL_IF_NULL(fb);
320 
321  IPPairFree(h);
322  IPPairShutdown();
323  StorageCleanup();
324  PASS;
325 }
326 
327 static int IPPairBitTest07 (void)
328 {
329  StorageCleanup();
330  StorageInit();
332  StorageFinalize();
333  IPPairInitConfig(true);
334  IPPair *h = IPPairAlloc();
335  FAIL_IF_NULL(h);
336 
337  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
338  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
339  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
340  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
341 
342  XBit *fb = IPPairBitGet(h,3);
343  FAIL_IF_NULL(fb);
344 
345  IPPairFree(h);
346  IPPairShutdown();
347  StorageCleanup();
348  PASS;
349 }
350 
351 static int IPPairBitTest08 (void)
352 {
353  StorageCleanup();
354  StorageInit();
356  StorageFinalize();
357  IPPairInitConfig(true);
358  IPPair *h = IPPairAlloc();
359  FAIL_IF_NULL(h);
360 
361  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
362  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
363  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
364  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
365 
366  XBit *fb = IPPairBitGet(h,0);
367  FAIL_IF_NULL(fb);
368 
369  IPPairBitRemove(h,0);
370 
371  fb = IPPairBitGet(h,0);
372  FAIL_IF_NOT_NULL(fb);
373 
374  IPPairFree(h);
375  IPPairShutdown();
376  StorageCleanup();
377  PASS;
378 }
379 
380 static int IPPairBitTest09 (void)
381 {
382  StorageCleanup();
383  StorageInit();
385  StorageFinalize();
386  IPPairInitConfig(true);
387  IPPair *h = IPPairAlloc();
388  FAIL_IF_NULL(h);
389 
390  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
391  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
392  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
393  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
394 
395  XBit *fb = IPPairBitGet(h,1);
396  FAIL_IF_NULL(fb);
397 
398  IPPairBitRemove(h,1);
399 
400  fb = IPPairBitGet(h,1);
401  FAIL_IF_NOT_NULL(fb);
402 
403  IPPairFree(h);
404  IPPairShutdown();
405  StorageCleanup();
406  PASS;
407 }
408 
409 static int IPPairBitTest10 (void)
410 {
411  StorageCleanup();
412  StorageInit();
414  StorageFinalize();
415  IPPairInitConfig(true);
416  IPPair *h = IPPairAlloc();
417  FAIL_IF_NULL(h);
418 
419  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
420  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
421  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
422  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
423 
424  XBit *fb = IPPairBitGet(h,2);
425  FAIL_IF_NULL(fb);
426 
427  IPPairBitRemove(h,2);
428 
429  fb = IPPairBitGet(h,2);
430  FAIL_IF_NOT_NULL(fb);
431 
432  IPPairFree(h);
433  IPPairShutdown();
434  StorageCleanup();
435  PASS;
436 }
437 
438 static int IPPairBitTest11 (void)
439 {
440  StorageCleanup();
441  StorageInit();
443  StorageFinalize();
444  IPPairInitConfig(true);
445  IPPair *h = IPPairAlloc();
446  FAIL_IF_NULL(h);
447 
448  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
449  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
450  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
451  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
452 
453  XBit *fb = IPPairBitGet(h,3);
454  FAIL_IF_NULL(fb);
455 
456  IPPairBitRemove(h,3);
457 
458  fb = IPPairBitGet(h,3);
459  FAIL_IF_NOT_NULL(fb);
460 
461  IPPairFree(h);
462  IPPairShutdown();
463  StorageCleanup();
464  PASS;
465 }
466 
467 #endif /* UNITTESTS */
468 
470 {
471 #ifdef UNITTESTS
472  UtRegisterTest("IPPairBitTest01", IPPairBitTest01);
473  UtRegisterTest("IPPairBitTest02", IPPairBitTest02);
474  UtRegisterTest("IPPairBitTest03", IPPairBitTest03);
475  UtRegisterTest("IPPairBitTest04", IPPairBitTest04);
476  UtRegisterTest("IPPairBitTest05", IPPairBitTest05);
477  UtRegisterTest("IPPairBitTest06", IPPairBitTest06);
478  UtRegisterTest("IPPairBitTest07", IPPairBitTest07);
479  UtRegisterTest("IPPairBitTest08", IPPairBitTest08);
480  UtRegisterTest("IPPairBitTest09", IPPairBitTest09);
481  UtRegisterTest("IPPairBitTest10", IPPairBitTest10);
482  UtRegisterTest("IPPairBitTest11", IPPairBitTest11);
483 #endif /* UNITTESTS */
484 }
IPPairBitUnset
void IPPairBitUnset(IPPair *h, uint32_t idx)
Definition: ippair-bit.c:139
IPPairStorageRegister
IPPairStorageId IPPairStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Definition: ippair-storage.c:56
ts
uint64_t ts
Definition: source-erf-file.c:55
GenericVarAppend
void GenericVarAppend(GenericVar **list, GenericVar *gv)
Definition: util-var.c:98
ippair.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
IPPairInitConfig
void IPPairInitConfig(bool quiet)
initialize the configuration
Definition: ippair.c:162
XBit_::next
GenericVar * next
Definition: util-var.h:65
StorageInit
void StorageInit(void)
Definition: util-storage.c:70
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
IPPairBitSet
void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_t expire)
Definition: ippair-bit.c:131
XBit_::expire
SCTime_t expire
Definition: util-var.h:66
StorageCleanup
void StorageCleanup(void)
Definition: util-storage.c:78
IPPairBitIsset
int IPPairBitIsset(IPPair *h, uint32_t idx, SCTime_t ts)
Definition: ippair-bit.c:157
IPPairAlloc
IPPair * IPPairAlloc(void)
Definition: ippair.c:104
IPPairSetStorageById
int IPPairSetStorageById(IPPair *h, IPPairStorageId id, void *ptr)
Definition: ippair-storage.c:40
IPPairStorageId::id
int id
Definition: ippair-storage.h:32
util-var.h
util-unittest.h
IPPairFree
void IPPairFree(IPPair *h)
Definition: ippair.c:124
IPPairShutdown
void IPPairShutdown(void)
shutdown the flow engine
Definition: ippair.c:290
SCTIME_FROM_SECS
#define SCTIME_FROM_SECS(s)
Definition: util-time.h:69
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
GenericVar_::next
struct GenericVar_ * next
Definition: util-var.h:57
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
detect.h
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:64
GenericVar_::idx
uint32_t idx
Definition: util-var.h:56
GenericVarRemove
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition: util-var.c:117
StorageFinalize
int StorageFinalize(void)
Definition: util-storage.c:140
SCTime_t
Definition: util-time.h:40
SCTIME_CMP_LT
#define SCTIME_CMP_LT(a, b)
Definition: util-time.h:105
IPPairHasBits
int IPPairHasBits(IPPair *ippair)
Definition: ippair-bit.c:58
IPPairBitIsnotset
int IPPairBitIsnotset(IPPair *h, uint32_t idx, SCTime_t ts)
Definition: ippair-bit.c:171
XBit_::type
uint16_t type
Definition: util-var.h:62
SCGenericVarFree
void SCGenericVarFree(GenericVar *gv)
Definition: util-var.c:48
suricata-common.h
IPPair_
Definition: ippair.h:58
GenericVar_
Definition: util-var.h:53
FatalError
#define FatalError(...)
Definition: util-debug.h:514
IPPairBitInitCtx
void IPPairBitInitCtx(void)
Definition: ippair-bit.c:49
IPPairGetStorageById
void * IPPairGetStorageById(IPPair *h, IPPairStorageId id)
Definition: ippair-storage.c:35
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCTIME_CMP_GT
#define SCTIME_CMP_GT(a, b)
Definition: util-time.h:104
GenericVar_::type
uint16_t type
Definition: util-var.h:54
IPPairBitToggle
void IPPairBitToggle(IPPair *h, uint32_t idx, SCTime_t expire)
Definition: ippair-bit.c:147
XBit_::idx
uint32_t idx
Definition: util-var.h:64
IPPairBitsTimedoutCheck
int IPPairBitsTimedoutCheck(IPPair *h, SCTime_t ts)
Definition: ippair-bit.c:67
IPPairBitRegisterTests
void IPPairBitRegisterTests(void)
Definition: ippair-bit.c:469
XBit_
Definition: util-var.h:61
ippair-storage.h
IPPairStorageId
Definition: ippair-storage.h:31
XBitFree
void XBitFree(XBit *fb)
Definition: util-var.c:40