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 SCIPPairStorageId 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 = SCIPPairStorageRegister("bit", 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 SCIPPairGetStorageById(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 = SCIPPairGetStorageById(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 = SCIPPairGetStorageById(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 = SCIPPairGetStorageById(h, g_ippair_bit_storage_id);
108  GenericVarAppend(&gv, (GenericVar *)fb);
109  SCIPPairSetStorageById(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 = SCIPPairGetStorageById(h, g_ippair_bit_storage_id);
124  if (gv) {
125  GenericVarRemove(&gv, (GenericVar *)fb);
126  XBitFree(fb);
127  SCIPPairSetStorageById(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 {
192  SCStorageInit();
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();
207  PASS;
208 }
209 
210 static int IPPairBitTest02 (void)
211 {
213  SCStorageInit();
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();
226  PASS;
227 }
228 
229 static int IPPairBitTest03 (void)
230 {
232  SCStorageInit();
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();
252  PASS;
253 }
254 
255 static int IPPairBitTest04 (void)
256 {
258  SCStorageInit();
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();
276  PASS;
277 }
278 
279 static int IPPairBitTest05 (void)
280 {
282  SCStorageInit();
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();
300  PASS;
301 }
302 
303 static int IPPairBitTest06 (void)
304 {
306  SCStorageInit();
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();
324  PASS;
325 }
326 
327 static int IPPairBitTest07 (void)
328 {
330  SCStorageInit();
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();
348  PASS;
349 }
350 
351 static int IPPairBitTest08 (void)
352 {
354  SCStorageInit();
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();
377  PASS;
378 }
379 
380 static int IPPairBitTest09 (void)
381 {
383  SCStorageInit();
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();
406  PASS;
407 }
408 
409 static int IPPairBitTest10 (void)
410 {
412  SCStorageInit();
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();
435  PASS;
436 }
437 
438 static int IPPairBitTest11 (void)
439 {
441  SCStorageInit();
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();
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
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
SCStorageInit
void SCStorageInit(void)
Definition: util-storage.c:68
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:103
ippair-bit.h
SCIPPairGetStorageById
void * SCIPPairGetStorageById(IPPair *h, SCIPPairStorageId id)
Definition: ippair-storage.c:35
threads.h
IPPairBitSet
void IPPairBitSet(IPPair *h, uint32_t idx, SCTime_t expire)
Definition: ippair-bit.c:131
SCIPPairStorageRegister
SCIPPairStorageId SCIPPairStorageRegister(const char *name, void(*Free)(void *))
Definition: ippair-storage.c:51
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:157
SCIPPairSetStorageById
int SCIPPairSetStorageById(IPPair *h, SCIPPairStorageId id, void *ptr)
Definition: ippair-storage.c:40
IPPairAlloc
IPPair * IPPairAlloc(void)
Definition: ippair.c:104
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
SCIPPairStorageId::id
int id
Definition: ippair-storage.h:32
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:66
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: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:517
IPPairBitInitCtx
void IPPairBitInitCtx(void)
Definition: ippair-bit.c:49
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
SCStorageCleanup
void SCStorageCleanup(void)
Definition: util-storage.c:76
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
SCStorageFinalize
int SCStorageFinalize(void)
Definition: util-storage.c:135
XBitFree
void XBitFree(XBit *fb)
Definition: util-var.c:40