suricata
util-lua-flowintlib.c
Go to the documentation of this file.
1/* Copyright (C) 2025 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "suricata-common.h"
19#include "app-layer-protos.h"
20#include "flow-var.h"
21#include "lauxlib.h"
22#include "util-debug.h"
23#include "util-lua-common.h"
24#include "util-lua-flowintlib.h"
25#include "util-lua.h"
26#include "util-var-name.h"
27#include "detect-lua.h"
29
30static const char suricata_flowint_mt[] = "suricata:flowint:mt";
31
32static DetectLuaData *GetLuaData(lua_State *luastate)
33{
34 DetectLuaData *ld;
35 lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
36 lua_gettable(luastate, LUA_REGISTRYINDEX);
37 ld = lua_touserdata(luastate, -1);
38 return ld;
39}
40
41/**
42 * \brief Register a flowvar.
43 *
44 * Ensures that a flowvar exists for the provided name, will be
45 * created if needed.
46 *
47 * The flowvar ID is returned, however as this is most likely to be
48 * used in the scripts "init" method, this ID is unlikely to be used.
49 */
50static int LuaFlowintRegister(lua_State *L)
51{
52 DetectLuaData *ld = GetLuaData(L);
53 const char *name = luaL_checkstring(L, 1);
54 uint32_t *flowvar_id = lua_newuserdata(L, sizeof(*flowvar_id));
56 if (*flowvar_id == 0) {
57 return luaL_error(L, "failed to register flowvar");
58 }
59 ld->flowint[ld->flowints++] = *flowvar_id;
60
61 luaL_getmetatable(L, suricata_flowint_mt);
62 lua_setmetatable(L, -2);
63
64 return 1;
65}
66
67static int LuaFlowintGet(lua_State *L)
68{
69 const char *name = luaL_checkstring(L, 1);
70 uint32_t *flowvar_id = lua_newuserdata(L, sizeof(*flowvar_id));
72 if (*flowvar_id == 0) {
73 return luaL_error(L, "flowvar does not exist");
74 }
75
76 luaL_getmetatable(L, suricata_flowint_mt);
77 lua_setmetatable(L, -2);
78
79 return 1;
80}
81
82static int LuaFlowintValue(lua_State *L)
83{
84 uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
85 Flow *f = LuaStateGetFlow(L);
86 if (f == NULL) {
87 return LuaCallbackError(L, "flow is NULL");
88 }
89 FlowVar *fv = FlowVarGet(f, *flowvar_id);
90 if (fv == NULL) {
91 lua_pushnil(L);
92 } else {
93 lua_pushnumber(L, (lua_Number)fv->data.fv_int.value);
94 }
95 return 1;
96}
97
98static int LuaFlowintSet(lua_State *L)
99{
100 const int value = (int)luaL_checkinteger(L, 2);
101 uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
102 Flow *f = LuaStateGetFlow(L);
103 if (f == NULL) {
104 return luaL_error(L, "no flow");
105 }
106
107 FlowVarAddInt(f, *flowvar_id, value);
108
109 return 1;
110}
111
112static int LuaFlowintIncr(lua_State *L)
113{
114 uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
115 Flow *f = LuaStateGetFlow(L);
116 if (f == NULL) {
117 return luaL_error(L, "no flow");
118 }
119
120 FlowVar *fv = FlowVarGet(f, *flowvar_id);
121 uint32_t value;
122 if (fv == NULL) {
123 value = 1;
124 } else {
125 value = fv->data.fv_int.value;
126 if (value < UINT32_MAX) {
127 value++;
128 }
129 }
130
131 FlowVarAddInt(f, *flowvar_id, value);
132 lua_pushnumber(L, (lua_Number)value);
133
134 return 1;
135}
136
137static int LuaFlowintDecr(lua_State *L)
138{
139 uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
140 Flow *f = LuaStateGetFlow(L);
141 if (f == NULL) {
142 return luaL_error(L, "no flow");
143 }
144
145 FlowVar *fv = FlowVarGet(f, *flowvar_id);
146 uint32_t value;
147 if (fv == NULL) {
148 value = 0;
149 } else {
150 value = fv->data.fv_int.value;
151 if (value > 0) {
152 value--;
153 }
154 }
155
156 FlowVarAddInt(f, *flowvar_id, value);
157 lua_pushnumber(L, (lua_Number)value);
158
159 return 1;
160}
161
162static const luaL_Reg flowvarlib[] = {
163 // clang-format off
164 { "register", LuaFlowintRegister, },
165 { "get", LuaFlowintGet },
166 { NULL, NULL, },
167 // clang-format on
168};
169
170static const luaL_Reg flowvarmt[] = {
171 // clang-format off
172 { "value", LuaFlowintValue, },
173 { "set", LuaFlowintSet, },
174 { "incr", LuaFlowintIncr, },
175 { "decr", LuaFlowintDecr, },
176 { NULL, NULL, },
177 // clang-format on
178};
179
181{
182 luaL_newmetatable(L, suricata_flowint_mt);
183 lua_pushvalue(L, -1);
184 lua_setfield(L, -2, "__index");
185 luaL_setfuncs(L, flowvarmt, 0);
186
187 luaL_newlib(L, flowvarlib);
188 return 1;
189}
const char luaext_key_ld[]
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition flow-var.c:84
void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
Definition flow-var.c:183
uint32_t flowint[DETECT_LUA_MAX_FLOWINTS]
Definition detect-lua.h:50
uint16_t flowints
Definition detect-lua.h:51
uint32_t value
Definition flow-var.h:46
FlowVarTypeInt fv_int
Definition flow-var.h:65
union FlowVar_::@124 data
Flow data structure.
Definition flow.h:356
struct lua_State lua_State
const char * name
int LuaCallbackError(lua_State *luastate, const char *msg)
int LuaLoadFlowintLib(lua_State *L)
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition util-lua.c:161
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time. As the active store won't be modified, we don't need locks.
@ VAR_TYPE_FLOW_INT
Definition util-var.h:37