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"
28 #include "detect-lua-extensions.h"
29 
30 static const char suricata_flowint_mt[] = "suricata:flowint:mt";
31 
32 static 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  */
50 static 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  if (ld->flowints >= DETECT_LUA_MAX_FLOWINTS) {
60  return luaL_error(L, "too many flowints registered");
61  }
62  ld->flowint[ld->flowints++] = *flowvar_id;
63 
64  luaL_getmetatable(L, suricata_flowint_mt);
65  lua_setmetatable(L, -2);
66 
67  return 1;
68 }
69 
70 static int LuaFlowintGet(lua_State *L)
71 {
72  const char *name = luaL_checkstring(L, 1);
73  uint32_t *flowvar_id = lua_newuserdata(L, sizeof(*flowvar_id));
75  if (*flowvar_id == 0) {
76  return luaL_error(L, "flowvar does not exist");
77  }
78 
79  luaL_getmetatable(L, suricata_flowint_mt);
80  lua_setmetatable(L, -2);
81 
82  return 1;
83 }
84 
85 static int LuaFlowintValue(lua_State *L)
86 {
87  uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
88  Flow *f = LuaStateGetFlow(L);
89  if (f == NULL) {
90  return LuaCallbackError(L, "flow is NULL");
91  }
92  FlowVar *fv = FlowVarGet(f, *flowvar_id);
93  if (fv == NULL) {
94  lua_pushnil(L);
95  } else {
96  lua_pushnumber(L, (lua_Number)fv->data.fv_int.value);
97  }
98  return 1;
99 }
100 
101 static int LuaFlowintSet(lua_State *L)
102 {
103  const int value = (int)luaL_checkinteger(L, 2);
104  uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
105  Flow *f = LuaStateGetFlow(L);
106  if (f == NULL) {
107  return luaL_error(L, "no flow");
108  }
109 
110  FlowVarAddInt(f, *flowvar_id, value);
111 
112  return 1;
113 }
114 
115 static int LuaFlowintIncr(lua_State *L)
116 {
117  uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
118  Flow *f = LuaStateGetFlow(L);
119  if (f == NULL) {
120  return luaL_error(L, "no flow");
121  }
122 
123  FlowVar *fv = FlowVarGet(f, *flowvar_id);
124  uint32_t value;
125  if (fv == NULL) {
126  value = 1;
127  } else {
128  value = fv->data.fv_int.value;
129  if (value < UINT32_MAX) {
130  value++;
131  }
132  }
133 
134  FlowVarAddInt(f, *flowvar_id, value);
135  lua_pushnumber(L, (lua_Number)value);
136 
137  return 1;
138 }
139 
140 static int LuaFlowintDecr(lua_State *L)
141 {
142  uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowint_mt);
143  Flow *f = LuaStateGetFlow(L);
144  if (f == NULL) {
145  return luaL_error(L, "no flow");
146  }
147 
148  FlowVar *fv = FlowVarGet(f, *flowvar_id);
149  uint32_t value;
150  if (fv == NULL) {
151  value = 0;
152  } else {
153  value = fv->data.fv_int.value;
154  if (value > 0) {
155  value--;
156  }
157  }
158 
159  FlowVarAddInt(f, *flowvar_id, value);
160  lua_pushnumber(L, (lua_Number)value);
161 
162  return 1;
163 }
164 
165 static const luaL_Reg flowvarlib[] = {
166  // clang-format off
167  { "register", LuaFlowintRegister, },
168  { "get", LuaFlowintGet },
169  { NULL, NULL, },
170  // clang-format on
171 };
172 
173 static const luaL_Reg flowvarmt[] = {
174  // clang-format off
175  { "value", LuaFlowintValue, },
176  { "set", LuaFlowintSet, },
177  { "incr", LuaFlowintIncr, },
178  { "decr", LuaFlowintDecr, },
179  { NULL, NULL, },
180  // clang-format on
181 };
182 
184 {
185  luaL_newmetatable(L, suricata_flowint_mt);
186  lua_pushvalue(L, -1);
187  lua_setfield(L, -2, "__index");
188  luaL_setfuncs(L, flowvarmt, 0);
189 
190  luaL_newlib(L, flowvarlib);
191  return 1;
192 }
DetectLuaData
Definition: detect-lua.h:44
util-lua-common.h
name
const char * name
Definition: detect-engine-proto.c:48
util-lua.h
LuaCallbackError
int LuaCallbackError(lua_State *luastate, const char *msg)
Definition: util-lua-common.c:39
Flow_
Flow data structure.
Definition: flow.h:349
detect-lua.h
util-var-name.h
VarNameStoreRegister
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
Definition: util-var-name.c:155
lua_State
struct lua_State lua_State
Definition: suricata-common.h:528
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:65
VarNameStoreLookupByName
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.
Definition: util-var-name.c:326
util-debug.h
DETECT_LUA_MAX_FLOWINTS
#define DETECT_LUA_MAX_FLOWINTS
Definition: detect-lua.h:36
DetectLuaData::flowints
uint16_t flowints
Definition: detect-lua.h:51
DetectLuaData::flowint
uint32_t flowint[DETECT_LUA_MAX_FLOWINTS]
Definition: detect-lua.h:50
FlowVarTypeInt_::value
uint32_t value
Definition: flow-var.h:46
detect-lua-extensions.h
suricata-common.h
util-lua-flowintlib.h
FlowVar_::data
union FlowVar_::@116 data
luaext_key_ld
const char luaext_key_ld[]
Definition: detect-lua-extensions.c:45
FlowVarAddInt
void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:183
LuaStateGetFlow
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition: util-lua.c:161
VAR_TYPE_FLOW_INT
@ VAR_TYPE_FLOW_INT
Definition: util-var.h:37
app-layer-protos.h
FlowVarGet
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition: flow-var.c:84
flow-var.h
FlowVar_
Definition: flow-var.h:55
LuaLoadFlowintLib
int LuaLoadFlowintLib(lua_State *L)
Definition: util-lua-flowintlib.c:183