diff options
Diffstat (limited to 'src/flow-var.c')
-rw-r--r-- | src/flow-var.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/flow-var.c b/src/flow-var.c new file mode 100644 index 0000000..a92358f --- /dev/null +++ b/src/flow-var.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2007-2010 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> + * \author Pablo Rincon <pablo.rincon.crespo@gmail.com> + * + * Flow level variable support for complex detection rules + * Supported types atm are String and Integers + */ + +#include "suricata-common.h" +#include "threads.h" +#include "flow-var.h" +#include "flow.h" +#include "detect.h" +#include "util-debug.h" + +/* puts a new value into a flowvar */ +static void FlowVarUpdateStr(FlowVar *fv, uint8_t *value, uint16_t size) +{ + if (fv->data.fv_str.value) + SCFree(fv->data.fv_str.value); + fv->data.fv_str.value = value; + fv->data.fv_str.value_len = size; +} + +/* puts a new value into a flowvar */ +static void FlowVarUpdateInt(FlowVar *fv, uint32_t value) +{ + fv->data.fv_int.value = value; +} + +/** \brief get the flowvar with index 'idx' from the flow + * \note flow is not locked by this function, caller is + * responsible + */ +FlowVar *FlowVarGetByKey(Flow *f, const uint8_t *key, uint16_t keylen) +{ + if (f == NULL) + return NULL; + + GenericVar *gv = f->flowvar; + + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_FLOWVAR && gv->idx == 0) { + + FlowVar *fv = (FlowVar *)gv; + if (fv->keylen == keylen && memcmp(key, fv->key, keylen) == 0) { + return fv; + } + } + } + + return NULL; +} + +/** \brief get the flowvar with index 'idx' from the flow + * \note flow is not locked by this function, caller is + * responsible + */ +FlowVar *FlowVarGet(Flow *f, uint32_t idx) +{ + if (f == NULL) + return NULL; + + GenericVar *gv = f->flowvar; + + for ( ; gv != NULL; gv = gv->next) { + if (gv->type == DETECT_FLOWVAR && gv->idx == idx) + return (FlowVar *)gv; + } + + return NULL; +} + +/* add a flowvar to the flow, or update it */ +void FlowVarAddKeyValue(Flow *f, uint8_t *key, uint16_t keysize, uint8_t *value, uint16_t size) +{ + FlowVar *fv = SCCalloc(1, sizeof(FlowVar)); + if (unlikely(fv == NULL)) + return; + + fv->type = DETECT_FLOWVAR; + fv->datatype = FLOWVAR_TYPE_STR; + fv->idx = 0; + fv->data.fv_str.value = value; + fv->data.fv_str.value_len = size; + fv->key = key; + fv->keylen = keysize; + fv->next = NULL; + + GenericVarAppend(&f->flowvar, (GenericVar *)fv); +} + +/* add a flowvar to the flow, or update it */ +void FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size) +{ + FlowVar *fv = FlowVarGet(f, idx); + if (fv == NULL) { + fv = SCCalloc(1, sizeof(FlowVar)); + if (unlikely(fv == NULL)) + return; + + fv->type = DETECT_FLOWVAR; + fv->datatype = FLOWVAR_TYPE_STR; + fv->idx = idx; + fv->data.fv_str.value = value; + fv->data.fv_str.value_len = size; + fv->next = NULL; + + GenericVarAppend(&f->flowvar, (GenericVar *)fv); + } else { + FlowVarUpdateStr(fv, value, size); + } +} + +/* add a flowvar to the flow, or update it */ +void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value) +{ + FlowVar *fv = FlowVarGet(f, idx); + if (fv == NULL) { + fv = SCMalloc(sizeof(FlowVar)); + if (unlikely(fv == NULL)) + return; + + fv->type = DETECT_FLOWVAR; + fv->datatype = FLOWVAR_TYPE_INT; + fv->idx = idx; + fv->data.fv_int.value= value; + fv->next = NULL; + + GenericVarAppend(&f->flowvar, (GenericVar *)fv); + } else { + FlowVarUpdateInt(fv, value); + } +} + +/* add a flowvar to the flow, or update it */ +void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value) +{ + FlowVarAddIntNoLock(f, idx, value); +} + +void FlowVarFree(FlowVar *fv) +{ + if (fv == NULL) + return; + + if (fv->datatype == FLOWVAR_TYPE_STR) { + if (fv->data.fv_str.value != NULL) + SCFree(fv->data.fv_str.value); + } + SCFree(fv); +} + +void FlowVarPrint(GenericVar *gv) +{ + uint16_t u; + + if (!SCLogDebugEnabled()) + return; + + if (gv == NULL) + return; + + if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) { + FlowVar *fv = (FlowVar *)gv; + + if (fv->datatype == FLOWVAR_TYPE_STR) { + SCLogDebug("Name idx \"%" PRIu32 "\", Value \"", fv->idx); + for (u = 0; u < fv->data.fv_str.value_len; u++) { + if (isprint(fv->data.fv_str.value[u])) + SCLogDebug("%c", fv->data.fv_str.value[u]); + else + SCLogDebug("\\%02X", fv->data.fv_str.value[u]); + } + SCLogDebug("\", Len \"%" PRIu16 "\"\n", fv->data.fv_str.value_len); + } else if (fv->datatype == FLOWVAR_TYPE_INT) { + SCLogDebug("Name idx \"%" PRIu32 "\", Value \"%" PRIu32 "\"", fv->idx, + fv->data.fv_int.value); + } else { + SCLogDebug("Unknown data type at flowvars\n"); + } + } + FlowVarPrint(gv->next); +} + |