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 "ippair-storage.h"
39 
40 static SCIPPairStorageId g_ippair_bit_storage_id = { .id = -1 }; /**< IPPair storage id for bits */
41 
42 static void XBitFreeAll(void *store)
43 {
44  GenericVar *gv = store;
45  SCGenericVarFree(gv);
46 }
47 
48 void IPPairBitInitCtx(void)
49 {
50  g_ippair_bit_storage_id = SCIPPairStorageRegister("bit", XBitFreeAll);
51  if (g_ippair_bit_storage_id.id == -1) {
52  FatalError("Can't initiate ippair storage for bits");
53  }
54 }
55 
56 /* lock before using this */
57 int IPPairHasBits(IPPair *ippair)
58 {
59  if (ippair == NULL)
60  return 0;
61  return SCIPPairGetStorageById(ippair, g_ippair_bit_storage_id) ? 1 : 0;
62 }
63 
64 /** \retval 1 ippair timed out wrt xbits
65  * \retval 0 ippair still has active (non-expired) xbits */
67 {
68  GenericVar *gv = SCIPPairGetStorageById(h, g_ippair_bit_storage_id);
69  for ( ; gv != NULL; gv = gv->next) {
70  if (gv->type == DETECT_XBITS) {
71  XBit *xb = (XBit *)gv;
72  if (SCTIME_CMP_GT(xb->expire, ts))
73  return 0;
74  }
75  }
76  return 1;
77 }
78 
79 /* get the bit with idx from the ippair */
80 static XBit *IPPairBitGet(IPPair *h, uint32_t idx)
81 {
82  GenericVar *gv = SCIPPairGetStorageById(h, g_ippair_bit_storage_id);
83  for ( ; gv != NULL; gv = gv->next) {
84  if (gv->type == DETECT_XBITS && gv->idx == idx) {
85  return (XBit *)gv;
86  }
87  }
88 
89  return NULL;
90 }
91 
92 /* add a flowbit to the flow */
93 static void IPPairBitAdd(IPPair *h, uint32_t idx, SCTime_t expire)
94 {
95  XBit *fb = IPPairBitGet(h, idx);
96  if (fb == NULL) {
97  fb = SCMalloc(sizeof(XBit));
98  if (unlikely(fb == NULL))
99  return;
100 
101  fb->type = DETECT_XBITS;
102  fb->idx = idx;
103  fb->next = NULL;
104  fb->expire = expire;
105 
106  GenericVar *gv = SCIPPairGetStorageById(h, g_ippair_bit_storage_id);
107  GenericVarAppend(&gv, (GenericVar *)fb);
108  SCIPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
109 
110  // bit already set, lets update it's timer
111  } else {
112  fb->expire = expire;
113  }
114 }
115 
116 static void IPPairBitRemove(IPPair *h, uint32_t idx)
117 {
118  XBit *fb = IPPairBitGet(h, idx);
119  if (fb == NULL)
120  return;
121 
122  GenericVar *gv = SCIPPairGetStorageById(h, g_ippair_bit_storage_id);
123  if (gv) {
124  GenericVarRemove(&gv, (GenericVar *)fb);
125  XBitFree(fb);
126  SCIPPairSetStorageById(h, g_ippair_bit_storage_id, gv);
127  }
128 }
129 
130 void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_t expire)
131 {
132  XBit *fb = IPPairBitGet(h, idx);
133  if (fb == NULL) {
134  IPPairBitAdd(h, idx, expire);
135  }
136 }
137 
138 void IPPairBitUnset(IPPair *h, uint32_t idx)
139 {
140  XBit *fb = IPPairBitGet(h, idx);
141  if (fb != NULL) {
142  IPPairBitRemove(h, idx);
143  }
144 }
145 
146 void IPPairBitToggle(IPPair *h, uint32_t idx, SCTime_t expire)
147 {
148  XBit *fb = IPPairBitGet(h, idx);
149  if (fb != NULL) {
150  IPPairBitRemove(h, idx);
151  } else {
152  IPPairBitAdd(h, idx, expire);
153  }
154 }
155 
156 int IPPairBitIsset(IPPair *h, uint32_t idx, SCTime_t ts)
157 {
158  XBit *fb = IPPairBitGet(h, idx);
159  if (fb != NULL) {
160  if (SCTIME_CMP_LT(fb->expire, ts)) {
161  IPPairBitRemove(h, idx);
162  return 0;
163  }
164 
165  return 1;
166  }
167  return 0;
168 }
169 
170 int IPPairBitIsnotset(IPPair *h, uint32_t idx, SCTime_t ts)
171 {
172  XBit *fb = IPPairBitGet(h, idx);
173  if (fb == NULL) {
174  return 1;
175  }
176 
177  if (SCTIME_CMP_LT(fb->expire, ts)) {
178  IPPairBitRemove(h, idx);
179  return 1;
180  }
181 
182  return 0;
183 }
184 
185 
186 /* TESTS */
187 #ifdef UNITTESTS
188 static int IPPairBitTest01 (void)
189 {
191  SCStorageInit();
194  IPPairInitConfig(true);
195  IPPair *h = IPPairAlloc();
196  FAIL_IF_NULL(h);
197 
198  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(0));
199 
200  XBit *fb = IPPairBitGet(h,0);
201  FAIL_IF_NULL(fb);
202 
203  IPPairFree(h);
204  IPPairShutdown();
206  PASS;
207 }
208 
209 static int IPPairBitTest02 (void)
210 {
212  SCStorageInit();
215  IPPairInitConfig(true);
216  IPPair *h = IPPairAlloc();
217  FAIL_IF_NULL(h);
218 
219  XBit *fb = IPPairBitGet(h,0);
220  FAIL_IF_NOT_NULL(fb);
221 
222  IPPairFree(h);
223  IPPairShutdown();
225  PASS;
226 }
227 
228 static int IPPairBitTest03 (void)
229 {
231  SCStorageInit();
234  IPPairInitConfig(true);
235  IPPair *h = IPPairAlloc();
236  FAIL_IF_NULL(h);
237 
238  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(30));
239 
240  XBit *fb = IPPairBitGet(h,0);
241  FAIL_IF_NULL(fb);
242 
243  IPPairBitRemove(h, 0);
244 
245  fb = IPPairBitGet(h,0);
246  FAIL_IF_NOT_NULL(fb);
247 
248  IPPairFree(h);
249  IPPairShutdown();
251  PASS;
252 }
253 
254 static int IPPairBitTest04 (void)
255 {
257  SCStorageInit();
260  IPPairInitConfig(true);
261  IPPair *h = IPPairAlloc();
262  FAIL_IF_NULL(h);
263 
264  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(30));
265  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(30));
266  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(30));
267  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(30));
268 
269  XBit *fb = IPPairBitGet(h,0);
270  FAIL_IF_NULL(fb);
271 
272  IPPairFree(h);
273  IPPairShutdown();
275  PASS;
276 }
277 
278 static int IPPairBitTest05 (void)
279 {
281  SCStorageInit();
284  IPPairInitConfig(true);
285  IPPair *h = IPPairAlloc();
286  FAIL_IF_NULL(h);
287 
288  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
289  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
290  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
291  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
292 
293  XBit *fb = IPPairBitGet(h,1);
294  FAIL_IF_NULL(fb);
295 
296  IPPairFree(h);
297  IPPairShutdown();
299  PASS;
300 }
301 
302 static int IPPairBitTest06 (void)
303 {
305  SCStorageInit();
308  IPPairInitConfig(true);
309  IPPair *h = IPPairAlloc();
310  FAIL_IF_NULL(h);
311 
312  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
313  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
314  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
315  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
316 
317  XBit *fb = IPPairBitGet(h,2);
318  FAIL_IF_NULL(fb);
319 
320  IPPairFree(h);
321  IPPairShutdown();
323  PASS;
324 }
325 
326 static int IPPairBitTest07 (void)
327 {
329  SCStorageInit();
332  IPPairInitConfig(true);
333  IPPair *h = IPPairAlloc();
334  FAIL_IF_NULL(h);
335 
336  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
337  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
338  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
339  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
340 
341  XBit *fb = IPPairBitGet(h,3);
342  FAIL_IF_NULL(fb);
343 
344  IPPairFree(h);
345  IPPairShutdown();
347  PASS;
348 }
349 
350 static int IPPairBitTest08 (void)
351 {
353  SCStorageInit();
356  IPPairInitConfig(true);
357  IPPair *h = IPPairAlloc();
358  FAIL_IF_NULL(h);
359 
360  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
361  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
362  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
363  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
364 
365  XBit *fb = IPPairBitGet(h,0);
366  FAIL_IF_NULL(fb);
367 
368  IPPairBitRemove(h,0);
369 
370  fb = IPPairBitGet(h,0);
371  FAIL_IF_NOT_NULL(fb);
372 
373  IPPairFree(h);
374  IPPairShutdown();
376  PASS;
377 }
378 
379 static int IPPairBitTest09 (void)
380 {
382  SCStorageInit();
385  IPPairInitConfig(true);
386  IPPair *h = IPPairAlloc();
387  FAIL_IF_NULL(h);
388 
389  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
390  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
391  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
392  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
393 
394  XBit *fb = IPPairBitGet(h,1);
395  FAIL_IF_NULL(fb);
396 
397  IPPairBitRemove(h,1);
398 
399  fb = IPPairBitGet(h,1);
400  FAIL_IF_NOT_NULL(fb);
401 
402  IPPairFree(h);
403  IPPairShutdown();
405  PASS;
406 }
407 
408 static int IPPairBitTest10 (void)
409 {
411  SCStorageInit();
414  IPPairInitConfig(true);
415  IPPair *h = IPPairAlloc();
416  FAIL_IF_NULL(h);
417 
418  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
419  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
420  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
421  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
422 
423  XBit *fb = IPPairBitGet(h,2);
424  FAIL_IF_NULL(fb);
425 
426  IPPairBitRemove(h,2);
427 
428  fb = IPPairBitGet(h,2);
429  FAIL_IF_NOT_NULL(fb);
430 
431  IPPairFree(h);
432  IPPairShutdown();
434  PASS;
435 }
436 
437 static int IPPairBitTest11 (void)
438 {
440  SCStorageInit();
443  IPPairInitConfig(true);
444  IPPair *h = IPPairAlloc();
445  FAIL_IF_NULL(h);
446 
447  IPPairBitAdd(h, 0, SCTIME_FROM_SECS(90));
448  IPPairBitAdd(h, 1, SCTIME_FROM_SECS(90));
449  IPPairBitAdd(h, 2, SCTIME_FROM_SECS(90));
450  IPPairBitAdd(h, 3, SCTIME_FROM_SECS(90));
451 
452  XBit *fb = IPPairBitGet(h,3);
453  FAIL_IF_NULL(fb);
454 
455  IPPairBitRemove(h,3);
456 
457  fb = IPPairBitGet(h,3);
458  FAIL_IF_NOT_NULL(fb);
459 
460  IPPairFree(h);
461  IPPairShutdown();
463  PASS;
464 }
465 
466 #endif /* UNITTESTS */
467 
469 {
470 #ifdef UNITTESTS
471  UtRegisterTest("IPPairBitTest01", IPPairBitTest01);
472  UtRegisterTest("IPPairBitTest02", IPPairBitTest02);
473  UtRegisterTest("IPPairBitTest03", IPPairBitTest03);
474  UtRegisterTest("IPPairBitTest04", IPPairBitTest04);
475  UtRegisterTest("IPPairBitTest05", IPPairBitTest05);
476  UtRegisterTest("IPPairBitTest06", IPPairBitTest06);
477  UtRegisterTest("IPPairBitTest07", IPPairBitTest07);
478  UtRegisterTest("IPPairBitTest08", IPPairBitTest08);
479  UtRegisterTest("IPPairBitTest09", IPPairBitTest09);
480  UtRegisterTest("IPPairBitTest10", IPPairBitTest10);
481  UtRegisterTest("IPPairBitTest11", IPPairBitTest11);
482 #endif /* UNITTESTS */
483 }
IPPairBitUnset
void IPPairBitUnset(IPPair *h, uint32_t idx)
Definition: ippair-bit.c:138
ts
uint64_t ts
Definition: source-erf-file.c:68
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
SCStorageInit
void SCStorageInit(void)
Definition: util-storage.c:67
IPPairInitConfig
void IPPairInitConfig(bool quiet)
initialize the configuration
Definition: ippair.c:162
SCIPPairStorageId
Definition: ippair-storage.h:31
XBit_::next
GenericVar * next
Definition: util-var.h:65
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:101
ippair-bit.h
SCIPPairGetStorageById
void * SCIPPairGetStorageById(IPPair *h, SCIPPairStorageId id)
Definition: ippair-storage.c:34
threads.h
IPPairBitSet
void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_t expire)
Definition: ippair-bit.c:130
SCIPPairStorageRegister
SCIPPairStorageId SCIPPairStorageRegister(const char *name, void(*Free)(void *))
Definition: ippair-storage.c:50
XBit_::expire
SCTime_t expire
Definition: util-var.h:66
IPPairBitIsset
int IPPairBitIsset(IPPair *h, uint32_t idx, SCTime_t ts)
Definition: ippair-bit.c:156
SCIPPairSetStorageById
int SCIPPairSetStorageById(IPPair *h, SCIPPairStorageId id, void *ptr)
Definition: ippair-storage.c:39
IPPairAlloc
IPPair * IPPairAlloc(void)
Definition: ippair.c:104
util-var.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
SCIPPairStorageId::id
int id
Definition: ippair-storage.h:32
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:73
GenericVar_::idx
uint32_t idx
Definition: util-var.h:56
GenericVarRemove
void GenericVarRemove(GenericVar **list, GenericVar *gv)
Definition: util-var.c:117
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:57
IPPairBitIsnotset
int IPPairBitIsnotset(IPPair *h, uint32_t idx, SCTime_t ts)
Definition: ippair-bit.c:170
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:517
IPPairBitInitCtx
void IPPairBitInitCtx(void)
Definition: ippair-bit.c:48
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:146
SCStorageCleanup
void SCStorageCleanup(void)
Definition: util-storage.c:75
XBit_::idx
uint32_t idx
Definition: util-var.h:64
IPPairBitsTimedoutCheck
int IPPairBitsTimedoutCheck(IPPair *h, SCTime_t ts)
Definition: ippair-bit.c:66
IPPairBitRegisterTests
void IPPairBitRegisterTests(void)
Definition: ippair-bit.c:468
XBit_
Definition: util-var.h:61
ippair-storage.h
SCStorageFinalize
int SCStorageFinalize(void)
Definition: util-storage.c:134
XBitFree
void XBitFree(XBit *fb)
Definition: util-var.c:40