mirror of
https://github.com/OISF/suricata.git
synced 2026-10-12 02:07:10 +00:00
lua: convert lua flowint functions to lib: suricata.flowintlib
Ticket: #7487
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
Flowint Library
|
||||
###############
|
||||
|
||||
The ``suricata.flowint`` library exposes ``flowint`` variables to Lua
|
||||
scripts.
|
||||
|
||||
Initialization
|
||||
**************
|
||||
|
||||
First, the ``flowint`` module must be loaded::
|
||||
|
||||
local flowintlib = require("suricata.flowint")
|
||||
|
||||
Then in the ``init`` method, any flow integers used in the script
|
||||
should be registered. This is optional and could be skipped if you
|
||||
know for sure the flow integers will be registered by some other
|
||||
means.
|
||||
|
||||
Example::
|
||||
|
||||
local flowintlib = require("suricata.flowint")
|
||||
|
||||
function init ()
|
||||
flowintlib.register("count")
|
||||
return {}
|
||||
end
|
||||
|
||||
Finally, in the ``thread_init`` function a handle is acquired for the
|
||||
flow integers and stored as a global::
|
||||
|
||||
function thread_init ()
|
||||
count_flow_int = flowintlib.get("count")
|
||||
end
|
||||
|
||||
Flow Integer Methods
|
||||
********************
|
||||
|
||||
``decr()``
|
||||
==========
|
||||
|
||||
Decrement the value of the ``flowint`` by 1. The new value is
|
||||
returned. If the value is 0, it will remain 0.
|
||||
|
||||
``incr()``
|
||||
==========
|
||||
|
||||
Increment the value of the ``flowint`` by 1. The new value is
|
||||
returned.
|
||||
|
||||
``value()``
|
||||
===========
|
||||
|
||||
Get the current value of the flow integer. Note that ``nil`` may be
|
||||
returned if the flow integer does not have a value.
|
||||
|
||||
``set(value)``
|
||||
===================
|
||||
|
||||
Set the value of the flowint to the value provided.
|
||||
@@ -11,6 +11,7 @@ environment without access to additional modules.
|
||||
base64
|
||||
dns
|
||||
flowlib
|
||||
flowint
|
||||
flowvar
|
||||
hashlib
|
||||
http
|
||||
|
||||
@@ -533,6 +533,7 @@ noinst_HEADERS = \
|
||||
util-lua-dnp3.h \
|
||||
util-lua-dnp3-objects.h \
|
||||
util-lua-dns.h \
|
||||
util-lua-flowintlib.h \
|
||||
util-lua-flowlib.h \
|
||||
util-lua-flowvarlib.h \
|
||||
util-lua.h \
|
||||
@@ -1102,6 +1103,7 @@ libsuricata_c_a_SOURCES = \
|
||||
util-lua-dnp3.c \
|
||||
util-lua-dnp3-objects.c \
|
||||
util-lua-dns.c \
|
||||
util-lua-flowintlib.c \
|
||||
util-lua-flowlib.c \
|
||||
util-lua-flowvarlib.c \
|
||||
util-lua-hashlib.c \
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "detect.h"
|
||||
|
||||
#include "flow.h"
|
||||
#include "flow-var.h"
|
||||
|
||||
#include "util-debug.h"
|
||||
|
||||
@@ -39,7 +38,6 @@
|
||||
|
||||
#include "util-lua.h"
|
||||
#include "util-lua-common.h"
|
||||
#include "util-lua-http.h"
|
||||
#include "util-lua-ja3.h"
|
||||
#include "util-lua-tls.h"
|
||||
#include "util-lua-smtp.h"
|
||||
@@ -64,183 +62,6 @@ static int GetLuaData(lua_State *luastate, DetectLuaData **ret_ld)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetFlow(lua_State *luastate, Flow **ret_f)
|
||||
{
|
||||
Flow *f = LuaStateGetFlow(luastate);
|
||||
if (f == NULL) {
|
||||
LUA_ERROR("no flow");
|
||||
}
|
||||
*ret_f = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetFlowIntById(lua_State *luastate, Flow *f,
|
||||
FlowVar **ret_fv, bool fv_may_be_null, uint32_t *ret_idx)
|
||||
{
|
||||
DetectLuaData *ld = NULL;
|
||||
if (ret_idx)
|
||||
*ret_idx = 0;
|
||||
*ret_fv = NULL;
|
||||
|
||||
/* need lua data for id -> idx conversion */
|
||||
int ret = GetLuaData(luastate, &ld);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (!lua_isnumber(luastate, 1)) {
|
||||
LUA_ERROR("flowvar id not a number");
|
||||
}
|
||||
int id = lua_tonumber(luastate, 1);
|
||||
if (id < 0 || id >= DETECT_LUA_MAX_FLOWVARS) {
|
||||
LUA_ERROR("flowvar id out of range");
|
||||
}
|
||||
uint32_t idx = ld->flowint[id];
|
||||
if (idx == 0) {
|
||||
LUA_ERROR("flowvar id uninitialized");
|
||||
}
|
||||
FlowVar *fv = FlowVarGet(f, idx);
|
||||
if (!fv_may_be_null && fv == NULL) {
|
||||
LUA_ERROR("no flow var");
|
||||
}
|
||||
*ret_fv = fv;
|
||||
if (ret_idx)
|
||||
*ret_idx = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaGetFlowint(lua_State *luastate)
|
||||
{
|
||||
Flow *f;
|
||||
FlowVar *fv;
|
||||
uint32_t number;
|
||||
|
||||
/* need flow */
|
||||
int ret = GetFlow(luastate, &f);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = GetFlowIntById(luastate, f, &fv, false, NULL);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
number = fv->data.fv_int.value;
|
||||
|
||||
/* return value through luastate, as a luanumber */
|
||||
lua_pushnumber(luastate, (lua_Number)number);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int LuaSetFlowint(lua_State *luastate)
|
||||
{
|
||||
uint32_t idx;
|
||||
Flow *f;
|
||||
DetectLuaData *ld;
|
||||
|
||||
/* need lua data for id -> idx conversion */
|
||||
int ret = GetLuaData(luastate, &ld);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* need flow */
|
||||
ret = GetFlow(luastate, &f);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* need flowint idx */
|
||||
if (!lua_isnumber(luastate, 1)) {
|
||||
LUA_ERROR("1st arg not a number");
|
||||
}
|
||||
int id = lua_tonumber(luastate, 1);
|
||||
if (id < 0 || id >= DETECT_LUA_MAX_FLOWVARS) {
|
||||
LUA_ERROR("flowint id out of range");
|
||||
}
|
||||
|
||||
if (!lua_isnumber(luastate, 2)) {
|
||||
LUA_ERROR("2nd arg not a number");
|
||||
}
|
||||
lua_Number luanumber = lua_tonumber(luastate, 2);
|
||||
if (luanumber < 0 || id > (double)UINT_MAX) {
|
||||
LUA_ERROR("value out of range, "
|
||||
"value must be unsigned 32bit int");
|
||||
}
|
||||
uint32_t number = (uint32_t)luanumber;
|
||||
|
||||
idx = ld->flowint[id];
|
||||
if (idx == 0) {
|
||||
LUA_ERROR("flowint id uninitialized");
|
||||
}
|
||||
|
||||
FlowVarAddInt(f, idx, number);
|
||||
|
||||
SCLogDebug("stored flow:%p idx:%u value:%u", f, idx, number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LuaIncrFlowint(lua_State *luastate)
|
||||
{
|
||||
uint32_t idx;
|
||||
Flow *f;
|
||||
FlowVar *fv;
|
||||
uint32_t number;
|
||||
|
||||
/* need flow */
|
||||
int ret = GetFlow(luastate, &f);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = GetFlowIntById(luastate, f, &fv, true, &idx);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (fv == NULL) {
|
||||
number = 1;
|
||||
} else {
|
||||
number = fv->data.fv_int.value;
|
||||
if (number < UINT_MAX)
|
||||
number++;
|
||||
}
|
||||
FlowVarAddIntNoLock(f, idx, number);
|
||||
|
||||
/* return value through luastate, as a luanumber */
|
||||
lua_pushnumber(luastate, (lua_Number)number);
|
||||
SCLogDebug("incremented flow:%p idx:%u value:%u", f, idx, number);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int LuaDecrFlowint(lua_State *luastate)
|
||||
{
|
||||
uint32_t idx;
|
||||
Flow *f;
|
||||
FlowVar *fv;
|
||||
uint32_t number;
|
||||
|
||||
/* need flow */
|
||||
int ret = GetFlow(luastate, &f);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = GetFlowIntById(luastate, f, &fv, true, &idx);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (fv == NULL) {
|
||||
number = 0;
|
||||
} else {
|
||||
number = fv->data.fv_int.value;
|
||||
if (number > 0)
|
||||
number--;
|
||||
}
|
||||
FlowVarAddIntNoLock(f, idx, number);
|
||||
|
||||
/* 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 LuaGetByteVar(lua_State *luastate)
|
||||
{
|
||||
DetectLuaData *ld = NULL;
|
||||
@@ -296,30 +117,6 @@ void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld,
|
||||
*/
|
||||
int LuaRegisterExtensions(lua_State *lua_state)
|
||||
{
|
||||
lua_pushcfunction(lua_state, LuaGetFlowint);
|
||||
lua_setglobal(lua_state, "ScFlowintGet");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaGetFlowint);
|
||||
lua_setglobal(lua_state, "SCFlowintGet");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaSetFlowint);
|
||||
lua_setglobal(lua_state, "ScFlowintSet");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaSetFlowint);
|
||||
lua_setglobal(lua_state, "SCFlowintSet");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaIncrFlowint);
|
||||
lua_setglobal(lua_state, "ScFlowintIncr");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaIncrFlowint);
|
||||
lua_setglobal(lua_state, "SCFlowintIncr");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaDecrFlowint);
|
||||
lua_setglobal(lua_state, "ScFlowintDecr");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaDecrFlowint);
|
||||
lua_setglobal(lua_state, "SCFlowintDecr");
|
||||
|
||||
lua_pushcfunction(lua_state, LuaGetByteVar);
|
||||
lua_setglobal(lua_state, "SCByteVarGet");
|
||||
|
||||
|
||||
+64
-40
@@ -1505,22 +1505,26 @@ static int LuaMatchTest03a(void)
|
||||
/** \test http buffer, flowints */
|
||||
static int LuaMatchTest04(void)
|
||||
{
|
||||
const char script[] = "function init (args)\n"
|
||||
" local needs = {}\n"
|
||||
" needs[\"flowint\"] = {\"cnt\"}\n"
|
||||
" return needs\n"
|
||||
const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
|
||||
"function init (args)\n"
|
||||
" flowintlib.register(\"cnt\")\n"
|
||||
" return {}\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function thread_init (args)\n"
|
||||
" cnt = flowintlib.get(\"cnt\")\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function match(args)\n"
|
||||
" print \"inspecting\""
|
||||
" a = ScFlowintGet(0)\n"
|
||||
" a = cnt:value()\n"
|
||||
" if a then\n"
|
||||
" ScFlowintSet(0, a + 1)\n"
|
||||
" cnt:set(a + 1)\n"
|
||||
" else\n"
|
||||
" ScFlowintSet(0, 1)\n"
|
||||
" cnt:set(1)\n"
|
||||
" end\n"
|
||||
" \n"
|
||||
" a = ScFlowintGet(0)\n"
|
||||
" a = cnt:value()\n"
|
||||
" if a == 2 then\n"
|
||||
" print \"match\"\n"
|
||||
" return 1\n"
|
||||
@@ -1621,22 +1625,26 @@ static int LuaMatchTest04(void)
|
||||
/** \test http buffer, flowints */
|
||||
static int LuaMatchTest04a(void)
|
||||
{
|
||||
const char script[] = "function init (args)\n"
|
||||
" local needs = {}\n"
|
||||
" needs[\"flowint\"] = {\"cnt\"}\n"
|
||||
" return needs\n"
|
||||
const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
|
||||
"function init (args)\n"
|
||||
" flowintlib.register(\"cnt\")\n"
|
||||
" return {}\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function thread_init (args)\n"
|
||||
" cnt = flowintlib.get(\"cnt\")\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function match(args)\n"
|
||||
" print \"inspecting\""
|
||||
" a = SCFlowintGet(0)\n"
|
||||
" a = cnt:value()\n"
|
||||
" if a then\n"
|
||||
" SCFlowintSet(0, a + 1)\n"
|
||||
" cnt:set(a + 1)\n"
|
||||
" else\n"
|
||||
" SCFlowintSet(0, 1)\n"
|
||||
" cnt:set(1)\n"
|
||||
" end\n"
|
||||
" \n"
|
||||
" a = SCFlowintGet(0)\n"
|
||||
" a = cnt:value()\n"
|
||||
" if a == 2 then\n"
|
||||
" print \"match\"\n"
|
||||
" return 1\n"
|
||||
@@ -1739,15 +1747,19 @@ static int LuaMatchTest04a(void)
|
||||
/** \test http buffer, flowints */
|
||||
static int LuaMatchTest05(void)
|
||||
{
|
||||
const char script[] = "function init (args)\n"
|
||||
" local needs = {}\n"
|
||||
" needs[\"flowint\"] = {\"cnt\"}\n"
|
||||
" return needs\n"
|
||||
const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
|
||||
"function init (args)\n"
|
||||
" flowintlib.register(\"cnt\")\n"
|
||||
" return {}\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function thread_init (args)\n"
|
||||
" cnt = flowintlib.get(\"cnt\")\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function match(args)\n"
|
||||
" print \"inspecting\""
|
||||
" a = ScFlowintIncr(0)\n"
|
||||
" a = cnt:incr()\n"
|
||||
" if a == 2 then\n"
|
||||
" print \"match\"\n"
|
||||
" return 1\n"
|
||||
@@ -1850,15 +1862,19 @@ static int LuaMatchTest05(void)
|
||||
/** \test http buffer, flowints */
|
||||
static int LuaMatchTest05a(void)
|
||||
{
|
||||
const char script[] = "function init (args)\n"
|
||||
" local needs = {}\n"
|
||||
" needs[\"flowint\"] = {\"cnt\"}\n"
|
||||
" return needs\n"
|
||||
const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
|
||||
"function init (args)\n"
|
||||
" flowintlib.register(\"cnt\")\n"
|
||||
" return {}\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function thread_init (args)\n"
|
||||
" cnt = flowintlib.get(\"cnt\")\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function match(args)\n"
|
||||
" print \"inspecting\""
|
||||
" a = SCFlowintIncr(0)\n"
|
||||
" a = cnt:incr()\n"
|
||||
" if a == 2 then\n"
|
||||
" print \"match\"\n"
|
||||
" return 1\n"
|
||||
@@ -1961,20 +1977,24 @@ static int LuaMatchTest05a(void)
|
||||
/** \test http buffer, flowints */
|
||||
static int LuaMatchTest06(void)
|
||||
{
|
||||
const char script[] = "function init (args)\n"
|
||||
" local needs = {}\n"
|
||||
" needs[\"flowint\"] = {\"cnt\"}\n"
|
||||
" return needs\n"
|
||||
const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
|
||||
"function init (args)\n"
|
||||
" flowintlib.register(\"cnt\")\n"
|
||||
" return {}\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function thread_init (args)\n"
|
||||
" cnt = flowintlib.get(\"cnt\")\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function match(args)\n"
|
||||
" print \"inspecting\""
|
||||
" a = ScFlowintGet(0)\n"
|
||||
" a = cnt:value()\n"
|
||||
" if a == nil then\n"
|
||||
" print \"new var set to 2\""
|
||||
" ScFlowintSet(0, 2)\n"
|
||||
" cnt:set(2)\n"
|
||||
" end\n"
|
||||
" a = ScFlowintDecr(0)\n"
|
||||
" a = cnt:decr()\n"
|
||||
" if a == 0 then\n"
|
||||
" print \"match\"\n"
|
||||
" return 1\n"
|
||||
@@ -2077,20 +2097,24 @@ static int LuaMatchTest06(void)
|
||||
/** \test http buffer, flowints */
|
||||
static int LuaMatchTest06a(void)
|
||||
{
|
||||
const char script[] = "function init (args)\n"
|
||||
" local needs = {}\n"
|
||||
" needs[\"flowint\"] = {\"cnt\"}\n"
|
||||
" return needs\n"
|
||||
const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
|
||||
"function init (args)\n"
|
||||
" flowintlib.register(\"cnt\")\n"
|
||||
" return {}\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function thread_init (args)\n"
|
||||
" cnt = flowintlib.get(\"cnt\")\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"function match(args)\n"
|
||||
" print \"inspecting\""
|
||||
" a = SCFlowintGet(0)\n"
|
||||
" a = cnt:value()\n"
|
||||
" if a == nil then\n"
|
||||
" print \"new var set to 2\""
|
||||
" SCFlowintSet(0, 2)\n"
|
||||
" cnt:set(2)\n"
|
||||
" end\n"
|
||||
" a = SCFlowintDecr(0)\n"
|
||||
" a = cnt:decr()\n"
|
||||
" if a == 0 then\n"
|
||||
" print \"match\"\n"
|
||||
" return 1\n"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "util-lua-base64lib.h"
|
||||
#include "util-lua-dataset.h"
|
||||
#include "util-lua-dnp3.h"
|
||||
#include "util-lua-flowintlib.h"
|
||||
#include "util-lua-flowvarlib.h"
|
||||
#include "util-lua-http.h"
|
||||
#include "util-lua-dns.h"
|
||||
@@ -37,6 +38,7 @@ static const luaL_Reg builtins[] = {
|
||||
{ "suricata.dnp3", SCLuaLoadDnp3Lib },
|
||||
{ "suricata.dns", SCLuaLoadDnsLib },
|
||||
{ "suricata.flow", LuaLoadFlowLib },
|
||||
{ "suricata.flowint", LuaLoadFlowintLib },
|
||||
{ "suricata.flowvar", LuaLoadFlowvarLib },
|
||||
{ "suricata.hashlib", SCLuaLoadHashlib },
|
||||
{ "suricata.http", SCLuaLoadHttpLib },
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "app-layer-protos.h"
|
||||
#include "flow-var.h"
|
||||
#include "lauxlib.h"
|
||||
#include "util-debug.h"
|
||||
#include "util-lua-common.h"
|
||||
#include "util-lua-flowintlib.h"
|
||||
#include "util-lua.h"
|
||||
#include "util-var-name.h"
|
||||
#include "detect-lua.h"
|
||||
#include "detect-lua-extensions.h"
|
||||
|
||||
static const char suricata_flowint_mt[] = "suricata:flowint:mt";
|
||||
|
||||
static DetectLuaData *GetLuaData(lua_State *luastate)
|
||||
{
|
||||
DetectLuaData *ld;
|
||||
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
|
||||
lua_gettable(luastate, LUA_REGISTRYINDEX);
|
||||
ld = lua_touserdata(luastate, -1);
|
||||
return ld;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Register a flowvar.
|
||||
*
|
||||
* Ensures that a flowvar exists for the provided name, will be
|
||||
* created if needed.
|
||||
*
|
||||
* The flowvar ID is returned, however as this is most likely to be
|
||||
* used in the scripts "init" method, this ID is unlikely to be used.
|
||||
*/
|
||||
static int LuaFlowintRegister(lua_State *L)
|
||||
{
|
||||
DetectLuaData *ld = GetLuaData(L);
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
uint32_t *flowvar_id = lua_newuserdata(L, sizeof(*flowvar_id));
|
||||
*flowvar_id = VarNameStoreRegister(name, VAR_TYPE_FLOW_INT);
|
||||
if (*flowvar_id == 0) {
|
||||
return luaL_error(L, "failed to register flowvar");
|
||||
}
|
||||
ld->flowint[ld->flowints++] = *flowvar_id;
|
||||
|
||||
luaL_getmetatable(L, suricata_flowint_mt);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaFlowintGet(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
uint32_t *flowvar_id = lua_newuserdata(L, sizeof(*flowvar_id));
|
||||
*flowvar_id = VarNameStoreLookupByName(name, VAR_TYPE_FLOW_INT);
|
||||
if (*flowvar_id == 0) {
|
||||
return luaL_error(L, "flowvar does not exist");
|
||||
}
|
||||
|
||||
luaL_getmetatable(L, suricata_flowint_mt);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaFlowintValue(lua_State *L)
|
||||
{
|
||||
uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
|
||||
Flow *f = LuaStateGetFlow(L);
|
||||
if (f == NULL) {
|
||||
return LuaCallbackError(L, "flow is NULL");
|
||||
}
|
||||
FlowVar *fv = FlowVarGet(f, *flowvar_id);
|
||||
if (fv == NULL) {
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
lua_pushnumber(L, (lua_Number)fv->data.fv_int.value);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaFlowintSet(lua_State *L)
|
||||
{
|
||||
const int value = luaL_checkinteger(L, 2);
|
||||
uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
|
||||
Flow *f = LuaStateGetFlow(L);
|
||||
if (f == NULL) {
|
||||
return luaL_error(L, "no flow");
|
||||
}
|
||||
|
||||
FlowVarAddInt(f, *flowvar_id, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaFlowintIncr(lua_State *L)
|
||||
{
|
||||
uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
|
||||
Flow *f = LuaStateGetFlow(L);
|
||||
if (f == NULL) {
|
||||
return luaL_error(L, "no flow");
|
||||
}
|
||||
|
||||
FlowVar *fv = FlowVarGet(f, *flowvar_id);
|
||||
uint32_t value;
|
||||
if (fv == NULL) {
|
||||
value = 1;
|
||||
} else {
|
||||
value = fv->data.fv_int.value;
|
||||
if (value < UINT32_MAX) {
|
||||
value++;
|
||||
}
|
||||
}
|
||||
|
||||
FlowVarAddInt(f, *flowvar_id, value);
|
||||
lua_pushnumber(L, (lua_Number)value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LuaFlowintDecr(lua_State *L)
|
||||
{
|
||||
uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
|
||||
Flow *f = LuaStateGetFlow(L);
|
||||
if (f == NULL) {
|
||||
return luaL_error(L, "no flow");
|
||||
}
|
||||
|
||||
FlowVar *fv = FlowVarGet(f, *flowvar_id);
|
||||
uint32_t value;
|
||||
if (fv == NULL) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = fv->data.fv_int.value;
|
||||
if (value > 0) {
|
||||
value--;
|
||||
}
|
||||
}
|
||||
|
||||
FlowVarAddInt(f, *flowvar_id, value);
|
||||
lua_pushnumber(L, (lua_Number)value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg flowvarlib[] = {
|
||||
// clang-format off
|
||||
{ "register", LuaFlowintRegister, },
|
||||
{ "get", LuaFlowintGet },
|
||||
{ NULL, NULL, },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const luaL_Reg flowvarmt[] = {
|
||||
// clang-format off
|
||||
{ "value", LuaFlowintValue, },
|
||||
{ "set", LuaFlowintSet, },
|
||||
{ "incr", LuaFlowintIncr, },
|
||||
{ "decr", LuaFlowintDecr, },
|
||||
{ NULL, NULL, },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
int LuaLoadFlowintLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, suricata_flowint_mt);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
luaL_setfuncs(L, flowvarmt, 0);
|
||||
|
||||
luaL_newlib(L, flowvarlib);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Copyright (C) 2025 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.
|
||||
*/
|
||||
|
||||
#ifndef SURICATA_UTIL_LUA_FLOWINTLIB_H
|
||||
#define SURICATA_UTIL_LUA_FLOWINTLIB_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
int LuaLoadFlowintLib(lua_State *L);
|
||||
|
||||
#endif /* SURICATA_UTIL_LUA_FLOWINTLIB_H */
|
||||
Reference in New Issue
Block a user