From 8879b125d26e8db1a5633de5a9c692eb2d1c4f83 Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Wed, 9 Sep 2015 22:21:41 -0700 Subject: suricata checkin based on commit id a4bce14770beee46a537eda3c3f6e8e8565d5d0a Change-Id: I9a214fa0ee95e58fc640e50bd604dac7f42db48f --- framework/src/suricata/src/flow-bit.c | 483 ++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 framework/src/suricata/src/flow-bit.c (limited to 'framework/src/suricata/src/flow-bit.c') diff --git a/framework/src/suricata/src/flow-bit.c b/framework/src/suricata/src/flow-bit.c new file mode 100644 index 00000000..2e52b9ef --- /dev/null +++ b/framework/src/suricata/src/flow-bit.c @@ -0,0 +1,483 @@ +/* Copyright (C) 2007-2013 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 + * + * Implements per flow 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. + * \todo have more than one instance of the same var, and be able to match on a + * specific one, or one all at a time. So if a certain capture matches + * multiple times, we can operate on all of them. + */ + +#include "suricata-common.h" +#include "threads.h" +#include "flow-bit.h" +#include "flow.h" +#include "flow-util.h" +#include "flow-private.h" +#include "detect.h" +#include "util-var.h" +#include "util-debug.h" +#include "util-unittest.h" + +/* get the flowbit with idx from the flow */ +static FlowBit *FlowBitGet(Flow *f, uint16_t idx) +{ + GenericVar *gv = f->flowvar; + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_FLOWBITS && gv->idx == idx) { + return (FlowBit *)gv; + } + } + + return NULL; +} + +/* add a flowbit to the flow */ +static void FlowBitAdd(Flow *f, uint16_t idx) +{ + FlowBit *fb = FlowBitGet(f, idx); + if (fb == NULL) { + fb = SCMalloc(sizeof(FlowBit)); + if (unlikely(fb == NULL)) + return; + + fb->type = DETECT_FLOWBITS; + fb->idx = idx; + fb->next = NULL; + GenericVarAppend(&f->flowvar, (GenericVar *)fb); + + //printf("FlowBitAdd: adding flowbit with idx %" PRIu32 "\n", idx); +#ifdef FLOWBITS_STATS + SCMutexLock(&flowbits_mutex); + flowbits_added++; + flowbits_memuse += sizeof(FlowBit); + if (flowbits_memuse > flowbits_memuse_max) + flowbits_memuse_max = flowbits_memuse; + SCMutexUnlock(&flowbits_mutex); +#endif /* FLOWBITS_STATS */ + } +} + +static void FlowBitRemove(Flow *f, uint16_t idx) +{ + FlowBit *fb = FlowBitGet(f, idx); + if (fb == NULL) + return; + + GenericVarRemove(&f->flowvar, (GenericVar *)fb); + + //printf("FlowBitRemove: remove flowbit with idx %" PRIu32 "\n", idx); +#ifdef FLOWBITS_STATS + SCMutexLock(&flowbits_mutex); + flowbits_removed++; + if (flowbits_memuse >= sizeof(FlowBit)) + flowbits_memuse -= sizeof(FlowBit); + else { + printf("ERROR: flowbits memory usage going below 0!\n"); + flowbits_memuse = 0; + } + SCMutexUnlock(&flowbits_mutex); +#endif /* FLOWBITS_STATS */ +} + +void FlowBitSetNoLock(Flow *f, uint16_t idx) +{ + FlowBit *fb = FlowBitGet(f, idx); + if (fb == NULL) { + FlowBitAdd(f, idx); + } +} + +void FlowBitSet(Flow *f, uint16_t idx) +{ + FLOWLOCK_WRLOCK(f); + FlowBitSetNoLock(f, idx); + FLOWLOCK_UNLOCK(f); +} + +void FlowBitUnsetNoLock(Flow *f, uint16_t idx) +{ + FlowBit *fb = FlowBitGet(f, idx); + if (fb != NULL) { + FlowBitRemove(f, idx); + } +} + +void FlowBitUnset(Flow *f, uint16_t idx) +{ + FLOWLOCK_WRLOCK(f); + FlowBitUnsetNoLock(f, idx); + FLOWLOCK_UNLOCK(f); +} + +void FlowBitToggleNoLock(Flow *f, uint16_t idx) +{ + FlowBit *fb = FlowBitGet(f, idx); + if (fb != NULL) { + FlowBitRemove(f, idx); + } else { + FlowBitAdd(f, idx); + } +} + +void FlowBitToggle(Flow *f, uint16_t idx) +{ + FLOWLOCK_WRLOCK(f); + FlowBitToggleNoLock(f, idx); + FLOWLOCK_UNLOCK(f); +} + +int FlowBitIsset(Flow *f, uint16_t idx) +{ + int r = 0; + FLOWLOCK_RDLOCK(f); + + FlowBit *fb = FlowBitGet(f, idx); + if (fb != NULL) { + r = 1; + } + + FLOWLOCK_UNLOCK(f); + return r; +} + +int FlowBitIsnotset(Flow *f, uint16_t idx) +{ + int r = 0; + FLOWLOCK_RDLOCK(f); + + FlowBit *fb = FlowBitGet(f, idx); + if (fb == NULL) { + r = 1; + } + + FLOWLOCK_UNLOCK(f); + return r; +} + +void FlowBitFree(FlowBit *fb) +{ + if (fb == NULL) + return; + + SCFree(fb); + +#ifdef FLOWBITS_STATS + SCMutexLock(&flowbits_mutex); + flowbits_removed++; + if (flowbits_memuse >= sizeof(FlowBit)) + flowbits_memuse -= sizeof(FlowBit); + else { + printf("ERROR: flowbits memory usage going below 0!\n"); + flowbits_memuse = 0; + } + SCMutexUnlock(&flowbits_mutex); +#endif /* FLOWBITS_STATS */ +} + + +/* TESTS */ +#ifdef UNITTESTS +static int FlowBitTest01 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + + FlowBit *fb = FlowBitGet(&f,0); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest02 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBit *fb = FlowBitGet(&f,0); + if (fb == NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest03 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + + FlowBit *fb = FlowBitGet(&f,0); + if (fb == NULL) { + printf("fb == NULL although it was just added: "); + goto end; + } + + FlowBitRemove(&f, 0); + + fb = FlowBitGet(&f,0); + if (fb != NULL) { + printf("fb != NULL although it was just removed: "); + goto end; + } else { + ret = 1; + } +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest04 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,0); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest05 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,1); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest06 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,2); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest07 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,3); + if (fb != NULL) + ret = 1; + + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest08 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,0); + if (fb == NULL) + goto end; + + FlowBitRemove(&f,0); + + fb = FlowBitGet(&f,0); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest09 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,1); + if (fb == NULL) + goto end; + + FlowBitRemove(&f,1); + + fb = FlowBitGet(&f,1); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest10 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,2); + if (fb == NULL) + goto end; + + FlowBitRemove(&f,2); + + fb = FlowBitGet(&f,2); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +static int FlowBitTest11 (void) +{ + int ret = 0; + + Flow f; + memset(&f, 0, sizeof(Flow)); + + FlowBitAdd(&f, 0); + FlowBitAdd(&f, 1); + FlowBitAdd(&f, 2); + FlowBitAdd(&f, 3); + + FlowBit *fb = FlowBitGet(&f,3); + if (fb == NULL) + goto end; + + FlowBitRemove(&f,3); + + fb = FlowBitGet(&f,3); + if (fb != NULL) { + printf("fb != NULL even though it was removed: "); + goto end; + } + + ret = 1; +end: + GenericVarFree(f.flowvar); + return ret; +} + +#endif /* UNITTESTS */ + +void FlowBitRegisterTests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("FlowBitTest01", FlowBitTest01, 1); + UtRegisterTest("FlowBitTest02", FlowBitTest02, 1); + UtRegisterTest("FlowBitTest03", FlowBitTest03, 1); + UtRegisterTest("FlowBitTest04", FlowBitTest04, 1); + UtRegisterTest("FlowBitTest05", FlowBitTest05, 1); + UtRegisterTest("FlowBitTest06", FlowBitTest06, 1); + UtRegisterTest("FlowBitTest07", FlowBitTest07, 1); + UtRegisterTest("FlowBitTest08", FlowBitTest08, 1); + UtRegisterTest("FlowBitTest09", FlowBitTest09, 1); + UtRegisterTest("FlowBitTest10", FlowBitTest10, 1); + UtRegisterTest("FlowBitTest11", FlowBitTest11, 1); +#endif /* UNITTESTS */ +} + -- cgit 1.2.3-korg