diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /src/host-bit.c | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/host-bit.c')
-rw-r--r-- | src/host-bit.c | 523 |
1 files changed, 523 insertions, 0 deletions
diff --git a/src/host-bit.c b/src/host-bit.c new file mode 100644 index 0000000..3b03d50 --- /dev/null +++ b/src/host-bit.c @@ -0,0 +1,523 @@ +/* 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 host 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 "host-bit.h" +#include "host.h" +#include "detect.h" +#include "util-var.h" +#include "util-debug.h" +#include "util-unittest.h" +#include "host-storage.h" + +static HostStorageId host_bit_id = { .id = -1 }; /**< Host storage id for bits */ + +static void HostBitFreeAll(void *store) +{ + GenericVar *gv = store; + GenericVarFree(gv); +} + +void HostBitInitCtx(void) +{ + host_bit_id = HostStorageRegister("bit", sizeof(void *), NULL, HostBitFreeAll); + if (host_bit_id.id == -1) { + FatalError("Can't initiate host storage for bits"); + } +} + +/* lock before using this */ +int HostHasHostBits(Host *host) +{ + if (host == NULL) + return 0; + return HostGetStorageById(host, host_bit_id) ? 1 : 0; +} + +/** \retval 1 host timed out wrt xbits + * \retval 0 host still has active (non-expired) xbits */ +int HostBitsTimedoutCheck(Host *h, SCTime_t ts) +{ + GenericVar *gv = HostGetStorageById(h, host_bit_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 host */ +static XBit *HostBitGet(Host *h, uint32_t idx) +{ + GenericVar *gv = HostGetStorageById(h, host_bit_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 HostBitAdd(Host *h, uint32_t idx, uint32_t expire) +{ + XBit *fb = HostBitGet(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 = HostGetStorageById(h, host_bit_id); + GenericVarAppend(&gv, (GenericVar *)fb); + HostSetStorageById(h, host_bit_id, gv); + + // bit already set, lets update it's time + } else { + fb->expire = expire; + } +} + +static void HostBitRemove(Host *h, uint32_t idx) +{ + XBit *fb = HostBitGet(h, idx); + if (fb == NULL) + return; + + GenericVar *gv = HostGetStorageById(h, host_bit_id); + if (gv) { + GenericVarRemove(&gv, (GenericVar *)fb); + XBitFree(fb); + HostSetStorageById(h, host_bit_id, gv); + } +} + +void HostBitSet(Host *h, uint32_t idx, uint32_t expire) +{ + XBit *fb = HostBitGet(h, idx); + if (fb == NULL) { + HostBitAdd(h, idx, expire); + } +} + +void HostBitUnset(Host *h, uint32_t idx) +{ + XBit *fb = HostBitGet(h, idx); + if (fb != NULL) { + HostBitRemove(h, idx); + } +} + +void HostBitToggle(Host *h, uint32_t idx, uint32_t expire) +{ + XBit *fb = HostBitGet(h, idx); + if (fb != NULL) { + HostBitRemove(h, idx); + } else { + HostBitAdd(h, idx, expire); + } +} + +int HostBitIsset(Host *h, uint32_t idx, uint32_t ts) +{ + XBit *fb = HostBitGet(h, idx); + if (fb != NULL) { + if (fb->expire < ts) { + HostBitRemove(h,idx); + return 0; + } + return 1; + } + return 0; +} + +int HostBitIsnotset(Host *h, uint32_t idx, uint32_t ts) +{ + XBit *fb = HostBitGet(h, idx); + if (fb == NULL) { + return 1; + } + + if (fb->expire < ts) { + HostBitRemove(h,idx); + return 1; + } + return 0; +} + +int HostBitList(Host *h, XBit **iter) +{ + GenericVar *gv = (GenericVar *)*iter; + if (gv == NULL) { + gv = HostGetStorageById(h, host_bit_id); + } else { + gv = gv->next; + } + + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_XBITS) { + *iter = (XBit *)gv; + return 1; + } + } + *iter = NULL; + return 0; +} + +/* TESTS */ +#ifdef UNITTESTS +static int HostBitTest01 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 0); + + XBit *fb = HostBitGet(h,0); + if (fb != NULL) + ret = 1; + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest02 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + XBit *fb = HostBitGet(h,0); + if (fb == NULL) + ret = 1; + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest03 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 30); + + XBit *fb = HostBitGet(h,0); + if (fb == NULL) { + printf("fb == NULL although it was just added: "); + goto end; + } + + HostBitRemove(h, 0); + + fb = HostBitGet(h,0); + if (fb != NULL) { + printf("fb != NULL although it was just removed: "); + goto end; + } else { + ret = 1; + } + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest04 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 30); + HostBitAdd(h, 1, 30); + HostBitAdd(h, 2, 30); + HostBitAdd(h, 3, 30); + + XBit *fb = HostBitGet(h,0); + if (fb != NULL) + ret = 1; + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest05 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 30); + HostBitAdd(h, 1, 30); + HostBitAdd(h, 2, 30); + HostBitAdd(h, 3, 30); + + XBit *fb = HostBitGet(h,1); + if (fb != NULL) + ret = 1; + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest06 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 90); + HostBitAdd(h, 1, 90); + HostBitAdd(h, 2, 90); + HostBitAdd(h, 3, 90); + + XBit *fb = HostBitGet(h,2); + if (fb != NULL) + ret = 1; + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest07 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 90); + HostBitAdd(h, 1, 90); + HostBitAdd(h, 2, 90); + HostBitAdd(h, 3, 90); + + XBit *fb = HostBitGet(h,3); + if (fb != NULL) + ret = 1; + + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest08 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 90); + HostBitAdd(h, 1, 90); + HostBitAdd(h, 2, 90); + HostBitAdd(h, 3, 90); + + XBit *fb = HostBitGet(h,0); + if (fb == NULL) + goto end; + + HostBitRemove(h,0); + + fb = HostBitGet(h,0); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest09 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 90); + HostBitAdd(h, 1, 90); + HostBitAdd(h, 2, 90); + HostBitAdd(h, 3, 90); + + XBit *fb = HostBitGet(h,1); + if (fb == NULL) + goto end; + + HostBitRemove(h,1); + + fb = HostBitGet(h,1); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest10 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 90); + HostBitAdd(h, 1, 90); + HostBitAdd(h, 2, 90); + HostBitAdd(h, 3, 90); + + XBit *fb = HostBitGet(h,2); + if (fb == NULL) + goto end; + + HostBitRemove(h,2); + + fb = HostBitGet(h,2); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + HostFree(h); +end: + HostCleanup(); + return ret; +} + +static int HostBitTest11 (void) +{ + int ret = 0; + + HostInitConfig(true); + Host *h = HostAlloc(); + if (h == NULL) + goto end; + + HostBitAdd(h, 0, 90); + HostBitAdd(h, 1, 90); + HostBitAdd(h, 2, 90); + HostBitAdd(h, 3, 90); + + XBit *fb = HostBitGet(h,3); + if (fb == NULL) + goto end; + + HostBitRemove(h,3); + + fb = HostBitGet(h,3); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; + HostFree(h); +end: + HostCleanup(); + return ret; +} + +#endif /* UNITTESTS */ + +void HostBitRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("HostBitTest01", HostBitTest01); + UtRegisterTest("HostBitTest02", HostBitTest02); + UtRegisterTest("HostBitTest03", HostBitTest03); + UtRegisterTest("HostBitTest04", HostBitTest04); + UtRegisterTest("HostBitTest05", HostBitTest05); + UtRegisterTest("HostBitTest06", HostBitTest06); + UtRegisterTest("HostBitTest07", HostBitTest07); + UtRegisterTest("HostBitTest08", HostBitTest08); + UtRegisterTest("HostBitTest09", HostBitTest09); + UtRegisterTest("HostBitTest10", HostBitTest10); + UtRegisterTest("HostBitTest11", HostBitTest11); +#endif /* UNITTESTS */ +} |