static int LuaGetFlowvar(lua_State *luastate) { uint16_t idx; int id; Flow *f; FlowVar *fv; DetectLuaData *ld; /* need lua data for id -> idx conversion */ lua_pushlightuserdata(luastate, (void *)&luaext_key_ld); lua_gettable(luastate, LUA_REGISTRYINDEX); ld = lua_touserdata(luastate, -1); SCLogDebug("ld %p", ld); if (ld == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "internal error: no ld"); return 2; } /* need flow and lock hint */ f = LuaStateGetFlow(luastate); if (f == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "no flow"); return 2; } /* need flowvar idx */ if (!lua_isnumber(luastate, 1)) { lua_pushnil(luastate); lua_pushstring(luastate, "1st arg not a number"); return 2; } id = lua_tonumber(luastate, 1); if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) { lua_pushnil(luastate); lua_pushstring(luastate, "flowvar id out of range"); return 2; } idx = ld->flowvar[id]; if (idx == 0) { lua_pushnil(luastate); lua_pushstring(luastate, "flowvar id uninitialized"); return 2; } fv = FlowVarGet(f, idx); if (fv == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "no flow var"); return 2; } LuaPushStringBuffer(luastate, (const uint8_t *)fv->data.fv_str.value, (size_t)fv->data.fv_str.value_len); return 1; }
/* add a flowvar to the flow, or update it */ void FlowVarAddIntNoLock(Flow *f, uint16_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); } }
int DetectFlowvarMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { int ret = 0; DetectFlowvarData *fd = (DetectFlowvarData *)ctx; /* we need a lock */ FLOWLOCK_RDLOCK(p->flow); FlowVar *fv = FlowVarGet(p->flow, fd->idx); if (fv != NULL) { uint8_t *ptr = SpmSearch(fv->data.fv_str.value, fv->data.fv_str.value_len, fd->content, fd->content_len); if (ptr != NULL) ret = 1; } FLOWLOCK_UNLOCK(p->flow); return ret; }
/* add a flowvar to the flow, or update it */ void FlowVarAddStrNoLock(Flow *f, uint16_t idx, uint8_t *value, uint16_t size) { 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_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); } }
int DetectFlowvarMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { int ret = 0; DetectFlowvarData *fd = (DetectFlowvarData *)m->ctx; /* we need a lock */ SCMutexLock(&p->flow->m); FlowVar *fv = FlowVarGet(p->flow, fd->idx); if (fv != NULL) { uint8_t *ptr = SpmSearch(fv->data.fv_str.value, fv->data.fv_str.value_len, fd->content, fd->content_len); if (ptr != NULL) ret = 1; } SCMutexUnlock(&p->flow->m); return ret; }
static int LuaDecrFlowint(lua_State *luastate) { uint16_t idx; int id; Flow *f; FlowVar *fv; DetectLuaData *ld; int flow_lock = 0; uint32_t number; /* need luajit data for id -> idx conversion */ lua_pushlightuserdata(luastate, (void *)&luaext_key_ld); lua_gettable(luastate, LUA_REGISTRYINDEX); ld = lua_touserdata(luastate, -1); SCLogDebug("ld %p", ld); if (ld == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "internal error: no ld"); return 2; } /* need flow and lock hint */ f = LuaStateGetFlow(luastate, &flow_lock); if (f == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "no flow"); return 2; } /* need flowint idx */ if (!lua_isnumber(luastate, 1)) { SCLogDebug("1st arg not a number"); lua_pushnil(luastate); lua_pushstring(luastate, "1st arg not a number"); return 2; } id = lua_tonumber(luastate, 1); if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWINTS) { SCLogDebug("id %d", id); lua_pushnil(luastate); lua_pushstring(luastate, "flowint id out of range"); return 2; } idx = ld->flowint[id]; if (idx == 0) { SCLogDebug("idx %u", idx); lua_pushnil(luastate); lua_pushstring(luastate, "flowint id uninitialized"); return 2; } /* lookup var */ if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT) FLOWLOCK_RDLOCK(f); fv = FlowVarGet(f, idx); if (fv == NULL) { number = 0; } else { number = fv->data.fv_int.value; if (number > 0) number--; } FlowVarAddIntNoLock(f, idx, number); if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT) FLOWLOCK_UNLOCK(f); /* return value through luastate, as a luanumber */ lua_pushnumber(luastate, (lua_Number)number); SCLogDebug("decremented flow:%p idx:%u value:%u", f, idx, number); return 1; }
static int LuaGetFlowint(lua_State *luastate) { uint16_t idx; int id; Flow *f; FlowVar *fv; DetectLuaData *ld; uint32_t number; /* need lua data for id -> idx conversion */ lua_pushlightuserdata(luastate, (void *)&luaext_key_ld); lua_gettable(luastate, LUA_REGISTRYINDEX); ld = lua_touserdata(luastate, -1); SCLogDebug("ld %p", ld); if (ld == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "internal error: no ld"); return 2; } /* need flow and lock hint */ f = LuaStateGetFlow(luastate); if (f == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "no flow"); return 2; } /* need flowint idx */ if (!lua_isnumber(luastate, 1)) { SCLogDebug("1st arg not a number"); lua_pushnil(luastate); lua_pushstring(luastate, "1st arg not a number"); return 2; } id = lua_tonumber(luastate, 1); if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWINTS) { SCLogDebug("id %d", id); lua_pushnil(luastate); lua_pushstring(luastate, "flowint id out of range"); return 2; } idx = ld->flowint[id]; if (idx == 0) { SCLogDebug("idx %u", idx); lua_pushnil(luastate); lua_pushstring(luastate, "flowint id uninitialized"); return 2; } /* lookup var */ fv = FlowVarGet(f, idx); if (fv == NULL) { SCLogDebug("fv NULL"); lua_pushnil(luastate); lua_pushstring(luastate, "no flow var"); return 2; } number = fv->data.fv_int.value; /* return value through luastate, as a luanumber */ lua_pushnumber(luastate, (lua_Number)number); SCLogDebug("retrieved flow:%p idx:%u value:%u", f, idx, number); return 1; }
/** * \brief This function is used to create a flowint, add/substract values, * compare it with other flowints, etc * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param s pointer to the current Signature * \param m pointer to the sigmatch that we will cast into DetectFlowintData * * \retval 0 no match, when a var doesn't exist * \retval 1 match, when a var is initialized well, add/substracted, or a true * condition */ int DetectFlowintMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { const DetectFlowintData *sfd = (const DetectFlowintData *)ctx; FlowVar *fv; FlowVar *fvt; uint32_t targetval; int ret = 0; /** ATM If we are going to compare the current var with another * that doesn't exist, the default value will be zero; * if you don't want this behaviour, you can use the keyword * "isset" to make it match or not before using the default * value of zero; * But it is mandatory that the current var exist, otherwise, it will * return zero(not match). */ if (sfd->targettype == FLOWINT_TARGET_VAR) { uint16_t tvar_idx = VariableNameGetIdx(det_ctx->de_ctx, sfd->target.tvar.name, VAR_TYPE_FLOW_INT); fvt = FlowVarGet(p->flow, tvar_idx); /* We don't have that variable initialized yet */ if (fvt == NULL) targetval = 0; else targetval = fvt->data.fv_int.value; } else { targetval = sfd->target.value; } SCLogDebug("Our var %s is at idx: %"PRIu16"", sfd->name, sfd->idx); if (sfd->modifier == FLOWINT_MODIFIER_SET) { FlowVarAddIntNoLock(p->flow, sfd->idx, targetval); SCLogDebug("Setting %s = %u", sfd->name, targetval); ret = 1; goto end; } fv = FlowVarGet(p->flow, sfd->idx); if (sfd->modifier == FLOWINT_MODIFIER_ISSET) { SCLogDebug(" Isset %s? = %u", sfd->name,(fv) ? 1 : 0); if (fv != NULL) ret = 1; goto end; } if (sfd->modifier == FLOWINT_MODIFIER_NOTSET) { SCLogDebug(" Not set %s? = %u", sfd->name,(fv) ? 0 : 1); if (fv == NULL) ret = 1; goto end; } if (fv != NULL && fv->datatype == FLOWVAR_TYPE_INT) { if (sfd->modifier == FLOWINT_MODIFIER_ADD) { SCLogDebug("Adding %u to %s", targetval, sfd->name); FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value + targetval); ret = 1; goto end; } if (sfd->modifier == FLOWINT_MODIFIER_SUB) { SCLogDebug("Substracting %u to %s", targetval, sfd->name); FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value - targetval); ret = 1; goto end; } switch(sfd->modifier) { case FLOWINT_MODIFIER_EQ: SCLogDebug("( %u EQ %u )", fv->data.fv_int.value, targetval); ret = (fv->data.fv_int.value == targetval); break; case FLOWINT_MODIFIER_NE: SCLogDebug("( %u NE %u )", fv->data.fv_int.value, targetval); ret = (fv->data.fv_int.value != targetval); break; case FLOWINT_MODIFIER_LT: SCLogDebug("( %u LT %u )", fv->data.fv_int.value, targetval); ret = (fv->data.fv_int.value < targetval); break; case FLOWINT_MODIFIER_LE: SCLogDebug("( %u LE %u )", fv->data.fv_int.value, targetval); ret = (fv->data.fv_int.value <= targetval); break; case FLOWINT_MODIFIER_GT: SCLogDebug("( %u GT %u )", fv->data.fv_int.value, targetval); ret = (fv->data.fv_int.value > targetval); break; case FLOWINT_MODIFIER_GE: SCLogDebug("( %u GE %u )", fv->data.fv_int.value, targetval); ret = (fv->data.fv_int.value >= targetval); break; default: SCLogDebug("Unknown Modifier!"); #ifdef DEBUG BUG_ON(1); #endif } } else { /* allow a add on a non-existing var, it will init to the "add" value, * so implying a 0 set. */ if (sfd->modifier == FLOWINT_MODIFIER_ADD) { SCLogDebug("Adding %u to %s (new var)", targetval, sfd->name); FlowVarAddIntNoLock(p->flow, sfd->idx, targetval); ret = 1; } else { SCLogDebug("Var not found!"); /* It doesn't exist because it wasn't set * or it is a string var, that we don't compare here */ ret = 0; } } end: return ret; }