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  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 
67 static 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 
82 static 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 
98 static 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 
112 static 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 
137 static 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 
162 static const luaL_Reg flowvarlib[] = {
163  // clang-format off
164  { "register", LuaFlowintRegister, },
165  { "get", LuaFlowintGet },
166  { NULL, NULL, },
167  // clang-format on
168 };
169 
170 static 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 }
DetectLuaData
Definition: detect-lua.h:39
util-lua-common.h
util-lua.h
LuaCallbackError
int LuaCallbackError(lua_State *luastate, const char *msg)
Definition: util-lua-common.c:59
Flow_
Flow data structure.
Definition: flow.h:356
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:523
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:59
VarNameStoreLookupByName
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time.
Definition: util-var-name.c:315
util-debug.h
DetectLuaData::flowints
uint16_t flowints
Definition: detect-lua.h:46
DetectLuaData::flowint
uint32_t flowint[DETECT_LUA_MAX_FLOWINTS]
Definition: detect-lua.h:45
name
const char * name
Definition: tm-threads.c:2123
FlowVarTypeInt_::value
uint32_t value
Definition: flow-var.h:45
detect-lua-extensions.h
suricata-common.h
util-lua-flowintlib.h
luaext_key_ld
const char luaext_key_ld[]
Definition: detect-lua-extensions.c:47
FlowVarAddInt
void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:157
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:78
flow-var.h
FlowVar_
Definition: flow-var.h:49
LuaLoadFlowintLib
int LuaLoadFlowintLib(lua_State *L)
Definition: util-lua-flowintlib.c:180
FlowVar_::data
union FlowVar_::@113 data