suricata
util-lua-flowvarlib.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-flowvarlib.h"
25#include "util-lua.h"
26#include "util-var-name.h"
27#include "detect-lua.h"
29
30static const char suricata_flowvar_mt[] = "suricata:flowvar: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 LuaFlowvarRegister(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->flowvar[ld->flowvars++] = *flowvar_id;
60
61 luaL_getmetatable(L, suricata_flowvar_mt);
62 lua_setmetatable(L, -2);
63
64 return 1;
65}
66
67static int LuaFlowvarGet(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_flowvar_mt);
77 lua_setmetatable(L, -2);
78
79 return 1;
80}
81
82static int LuaFlowvarValue(lua_State *L)
83{
84 uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowvar_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 {
94 L, (const uint8_t *)fv->data.fv_str.value, (size_t)fv->data.fv_str.value_len);
95 }
96 return 1;
97}
98
99static int LuaFlowvarSet(lua_State *L)
100{
101 const char *value = luaL_checkstring(L, 2);
102 const int len = (int)luaL_checkinteger(L, 3);
103 uint32_t *flowvar_id = luaL_checkudata(L, 1, suricata_flowvar_mt);
104 Flow *f = LuaStateGetFlow(L);
105 if (f == NULL) {
106 return luaL_error(L, "no flow");
107 }
108
109 uint8_t *buf = SCMalloc(len + 1);
110 if (buf == NULL) {
111 return luaL_error(L, "alloc failure");
112 }
113 memcpy(buf, value, len);
114 buf[len] = '\0';
115 FlowVarAddIdValue(f, *flowvar_id, buf, (uint16_t)len);
116
117 return 1;
118}
119
120static const luaL_Reg flowvarlib[] = {
121 // clang-format off
122 { "register", LuaFlowvarRegister, },
123 { "get", LuaFlowvarGet },
124 { NULL, NULL, },
125 // clang-format on
126};
127
128static const luaL_Reg flowvarmt[] = {
129 // clang-format off
130 { "value", LuaFlowvarValue, },
131 { "set", LuaFlowvarSet, },
132 { NULL, NULL, },
133 // clang-format on
134};
135
137{
138 luaL_newmetatable(L, suricata_flowvar_mt);
139 lua_pushvalue(L, -1);
140 lua_setfield(L, -2, "__index");
141 luaL_setfuncs(L, flowvarmt, 0);
142
143 luaL_newlib(L, flowvarlib);
144 return 1;
145}
uint8_t len
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 FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
Definition flow-var.c:120
uint16_t flowvars
Definition detect-lua.h:52
uint32_t flowvar[DETECT_LUA_MAX_FLOWVARS]
Definition detect-lua.h:53
uint16_t value_len
Definition flow-var.h:41
uint8_t * value
Definition flow-var.h:40
FlowVarTypeStr fv_str
Definition flow-var.h:64
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 LuaLoadFlowvarLib(lua_State *L)
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition util-lua.c:319
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition util-lua.c:161
#define SCMalloc(sz)
Definition util-mem.h:47
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_VAR
Definition util-var.h:39