diff options
Diffstat (limited to 'src/ippair-bit.c')
-rw-r--r-- | src/ippair-bit.c | 507 |
1 files changed, 507 insertions, 0 deletions
diff --git a/src/ippair-bit.c b/src/ippair-bit.c new file mode 100644 index 0000000..1d3d8fa --- /dev/null +++ b/src/ippair-bit.c @@ -0,0 +1,507 @@ +/* Copyright (C) 2014-2021 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien <victor@inliniac.net> + * + * Implements per ippair bits. Actually, not a bit, + * but called that way because of Snort's flowbits. + * It's a binary storage. + * + * \todo move away from a linked list implementation + * \todo use different datatypes, such as string, int, etc. + */ + +#include "suricata-common.h" +#include "threads.h" +#include "ippair-bit.h" +#include "ippair.h" +#include "detect.h" +#include "util-var.h" +#include "util-debug.h" +#include "util-unittest.h" +#include "ippair-storage.h" + +static IPPairStorageId g_ippair_bit_storage_id = { .id = -1 }; /**< IPPair storage id for bits */ + +static void XBitFreeAll(void *store) +{ + GenericVar *gv = store; + GenericVarFree(gv); +} + +void IPPairBitInitCtx(void) +{ + g_ippair_bit_storage_id = IPPairStorageRegister("bit", sizeof(void *), NULL, XBitFreeAll); + if (g_ippair_bit_storage_id.id == -1) { + FatalError("Can't initiate ippair storage for bits"); + } +} + +/* lock before using this */ +int IPPairHasBits(IPPair *ippair) +{ + if (ippair == NULL) + return 0; + return IPPairGetStorageById(ippair, g_ippair_bit_storage_id) ? 1 : 0; +} + +/** \retval 1 ippair timed out wrt xbits + * \retval 0 ippair still has active (non-expired) xbits */ +int IPPairBitsTimedoutCheck(IPPair *h, SCTime_t ts) +{ + GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id); + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_XBITS) { + XBit *xb = (XBit *)gv; + if (xb->expire > (uint32_t)SCTIME_SECS(ts)) + return 0; + } + } + return 1; +} + +/* get the bit with idx from the ippair */ +static XBit *IPPairBitGet(IPPair *h, uint32_t idx) +{ + GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id); + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_XBITS && gv->idx == idx) { + return (XBit *)gv; + } + } + + return NULL; +} + +/* add a flowbit to the flow */ +static void IPPairBitAdd(IPPair *h, uint32_t idx, uint32_t expire) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb == NULL) { + fb = SCMalloc(sizeof(XBit)); + if (unlikely(fb == NULL)) + return; + + fb->type = DETECT_XBITS; + fb->idx = idx; + fb->next = NULL; + fb->expire = expire; + + GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id); + GenericVarAppend(&gv, (GenericVar *)fb); + IPPairSetStorageById(h, g_ippair_bit_storage_id, gv); + + // bit already set, lets update it's timer + } else { + fb->expire = expire; + } +} + +static void IPPairBitRemove(IPPair *h, uint32_t idx) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb == NULL) + return; + + GenericVar *gv = IPPairGetStorageById(h, g_ippair_bit_storage_id); + if (gv) { + GenericVarRemove(&gv, (GenericVar *)fb); + XBitFree(fb); + IPPairSetStorageById(h, g_ippair_bit_storage_id, gv); + } +} + +void IPPairBitSet(IPPair *h, uint32_t idx, uint32_t expire) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb == NULL) { + IPPairBitAdd(h, idx, expire); + } +} + +void IPPairBitUnset(IPPair *h, uint32_t idx) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb != NULL) { + IPPairBitRemove(h, idx); + } +} + +void IPPairBitToggle(IPPair *h, uint32_t idx, uint32_t expire) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb != NULL) { + IPPairBitRemove(h, idx); + } else { + IPPairBitAdd(h, idx, expire); + } +} + +int IPPairBitIsset(IPPair *h, uint32_t idx, uint32_t ts) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb != NULL) { + if (fb->expire < ts) { + IPPairBitRemove(h, idx); + return 0; + } + + return 1; + } + return 0; +} + +int IPPairBitIsnotset(IPPair *h, uint32_t idx, uint32_t ts) +{ + XBit *fb = IPPairBitGet(h, idx); + if (fb == NULL) { + return 1; + } + + if (fb->expire < ts) { + IPPairBitRemove(h, idx); + return 1; + } + + return 0; +} + + +/* TESTS */ +#ifdef UNITTESTS +static int IPPairBitTest01 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0, 0); + + XBit *fb = IPPairBitGet(h,0); + if (fb != NULL) + ret = 1; + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest02 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + XBit *fb = IPPairBitGet(h,0); + if (fb == NULL) + ret = 1; + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest03 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0, 30); + + XBit *fb = IPPairBitGet(h,0); + if (fb == NULL) { + printf("fb == NULL although it was just added: "); + goto end; + } + + IPPairBitRemove(h, 0); + + fb = IPPairBitGet(h,0); + if (fb != NULL) { + printf("fb != NULL although it was just removed: "); + goto end; + } else { + ret = 1; + } + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest04 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,30); + IPPairBitAdd(h, 1,30); + IPPairBitAdd(h, 2,30); + IPPairBitAdd(h, 3,30); + + XBit *fb = IPPairBitGet(h,0); + if (fb != NULL) + ret = 1; + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest05 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,1); + if (fb != NULL) + ret = 1; + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest06 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,2); + if (fb != NULL) + ret = 1; + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest07 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,3); + if (fb != NULL) + ret = 1; + + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest08 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,0); + if (fb == NULL) + goto end; + + IPPairBitRemove(h,0); + + fb = IPPairBitGet(h,0); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest09 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,1); + if (fb == NULL) + goto end; + + IPPairBitRemove(h,1); + + fb = IPPairBitGet(h,1); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest10 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,2); + if (fb == NULL) + goto end; + + IPPairBitRemove(h,2); + + fb = IPPairBitGet(h,2); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +static int IPPairBitTest11 (void) +{ + int ret = 0; + + IPPairInitConfig(true); + IPPair *h = IPPairAlloc(); + if (h == NULL) + goto end; + + IPPairBitAdd(h, 0,90); + IPPairBitAdd(h, 1,90); + IPPairBitAdd(h, 2,90); + IPPairBitAdd(h, 3,90); + + XBit *fb = IPPairBitGet(h,3); + if (fb == NULL) + goto end; + + IPPairBitRemove(h,3); + + fb = IPPairBitGet(h,3); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + IPPairFree(h); +end: + IPPairCleanup(); + return ret; +} + +#endif /* UNITTESTS */ + +void IPPairBitRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("IPPairBitTest01", IPPairBitTest01); + UtRegisterTest("IPPairBitTest02", IPPairBitTest02); + UtRegisterTest("IPPairBitTest03", IPPairBitTest03); + UtRegisterTest("IPPairBitTest04", IPPairBitTest04); + UtRegisterTest("IPPairBitTest05", IPPairBitTest05); + UtRegisterTest("IPPairBitTest06", IPPairBitTest06); + UtRegisterTest("IPPairBitTest07", IPPairBitTest07); + UtRegisterTest("IPPairBitTest08", IPPairBitTest08); + UtRegisterTest("IPPairBitTest09", IPPairBitTest09); + UtRegisterTest("IPPairBitTest10", IPPairBitTest10); + UtRegisterTest("IPPairBitTest11", IPPairBitTest11); +#endif /* UNITTESTS */ +} |