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; }
/* add a flowvar to the flow, or update it */ void FlowVarAddInt(Flow *f, uint16_t idx, uint32_t value) { FLOWLOCK_WRLOCK(f); FlowVarAddIntNoLock(f, idx, value); FLOWLOCK_UNLOCK(f); }
int LuaSetFlowint(lua_State *luastate) { uint16_t idx; int id; Flow *f; DetectEngineThreadCtx *det_ctx; DetectLuaData *ld; int flow_lock = 0; uint32_t number; lua_Number luanumber; /* 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 det_ctx */ lua_pushlightuserdata(luastate, (void *)&luaext_key_det_ctx); lua_gettable(luastate, LUA_REGISTRYINDEX); det_ctx = lua_touserdata(luastate, -1); SCLogDebug("det_ctx %p", det_ctx); if (det_ctx == NULL) { lua_pushnil(luastate); lua_pushstring(luastate, "internal error: no det_ctx"); 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)) { 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, "flowint id out of range"); return 2; } if (!lua_isnumber(luastate, 2)) { lua_pushnil(luastate); lua_pushstring(luastate, "2nd arg not a number"); return 2; } luanumber = lua_tonumber(luastate, 2); if (luanumber < 0 || id > (double)UINT_MAX) { lua_pushnil(luastate); lua_pushstring(luastate, "value out of range, value must be unsigned 32bit int"); return 2; } number = (uint32_t)luanumber; idx = ld->flowint[id]; if (idx == 0) { lua_pushnil(luastate); lua_pushstring(luastate, "flowint id uninitialized"); return 2; } if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT) FlowVarAddInt(f, idx, number); else FlowVarAddIntNoLock(f, idx, number); SCLogDebug("stored flow:%p idx:%u value:%u", f, idx, number); return 0; }
/** * \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; }