suricata
util-lua-packetlib.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 /**
19  * \file
20  *
21  * Packet API for Lua.
22  *
23  * local packet = require("suricata.packet")
24  */
25 
26 #include "suricata-common.h"
27 
28 #include "util-lua-packetlib.h"
29 
30 #include "app-layer-protos.h" /* Required by util-lua-common. */
31 #include "util-lua-common.h"
32 #include "util-lua.h"
33 #include "util-debug.h"
34 #include "util-print.h"
35 
36 static const char suricata_packet[] = "suricata:packet";
37 
38 /* no stored pointer: the accessors act on the packet the state is
39  * running on (LuaStateGetPacket), so a retained handle can never
40  * dangle */
41 struct LuaPacket {
42 };
43 
44 static int LuaPacketPayload(lua_State *luastate)
45 {
46  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
47  Packet *p = LuaStateGetPacket(luastate);
48  if (p == NULL) {
49  LUA_ERROR("failed to get packet");
50  }
51 
52  LuaPushStringBuffer(luastate, (const uint8_t *)p->payload, (size_t)p->payload_len);
53  return 1;
54 }
55 
56 static int LuaPacketPacket(lua_State *luastate)
57 {
58  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
59  Packet *p = LuaStateGetPacket(luastate);
60  if (p == NULL) {
61  LUA_ERROR("failed to get packet");
62  }
63 
64  LuaPushStringBuffer(luastate, (const uint8_t *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p));
65  return 1;
66 }
67 
68 static int LuaPacketPcapCnt(lua_State *luastate)
69 {
70  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
71  Packet *p = LuaStateGetPacket(luastate);
72  if (p == NULL) {
73  LUA_ERROR("failed to get packet");
74  }
75 
76  lua_pushinteger(luastate, PcapPacketCntGet(p));
77  return 1;
78 }
79 
80 /** \internal
81  * \brief legacy format as used by fast.log, etc.
82  */
83 static int LuaPacketTimestringLegacy(lua_State *luastate)
84 {
85  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
86  Packet *p = LuaStateGetPacket(luastate);
87  if (p == NULL) {
88  LUA_ERROR("failed to get packet");
89  }
90 
91  char timebuf[64];
92  CreateTimeString(p->ts, timebuf, sizeof(timebuf));
93  lua_pushstring(luastate, timebuf);
94  return 1;
95 }
96 
97 static int LuaPacketTimestringIso8601(lua_State *luastate)
98 {
99  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
100  Packet *p = LuaStateGetPacket(luastate);
101  if (p == NULL) {
102  LUA_ERROR("failed to get packet");
103  }
104 
105  char timebuf[64];
106  CreateIsoTimeString(p->ts, timebuf, sizeof(timebuf));
107  lua_pushstring(luastate, timebuf);
108  return 1;
109 }
110 
111 static int LuaPacketTimestamp(lua_State *luastate)
112 {
113  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
114  Packet *p = LuaStateGetPacket(luastate);
115  if (p == NULL) {
116  LUA_ERROR("failed to get packet");
117  }
118 
119  lua_pushnumber(luastate, (double)SCTIME_SECS(p->ts));
120  lua_pushnumber(luastate, (double)SCTIME_USECS(p->ts));
121  return 2;
122 }
123 
124 /** \internal
125  * \brief fill lua stack with header info
126  * \param luastate the lua state
127  * \retval cnt number of data items placed on the stack
128  *
129  * Places: ipver (number), src ip (string), dst ip (string), protocol (number),
130  * sp or icmp type (number), dp or icmp code (number).
131  */
132 static int LuaPacketTuple(lua_State *luastate)
133 {
134  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
135  Packet *p = LuaStateGetPacket(luastate);
136  if (p == NULL) {
137  LUA_ERROR("failed to get packet");
138  }
139 
140  int ipver = 0;
141  if (PacketIsIPv4(p)) {
142  ipver = 4;
143  } else if (PacketIsIPv6(p)) {
144  ipver = 6;
145  }
146  lua_pushinteger(luastate, ipver);
147  if (ipver == 0)
148  return 1;
149 
150  char srcip[46] = "", dstip[46] = "";
151  if (PacketIsIPv4(p)) {
152  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
153  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
154  } else if (PacketIsIPv6(p)) {
155  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
156  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
157  }
158 
159  lua_pushstring(luastate, srcip);
160  lua_pushstring(luastate, dstip);
161 
162  /* proto and ports (or type/code) */
163  lua_pushinteger(luastate, p->proto);
164  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) {
165  lua_pushinteger(luastate, p->sp);
166  lua_pushinteger(luastate, p->dp);
167 
168  } else if (p->proto == IPPROTO_ICMP || p->proto == IPPROTO_ICMPV6) {
169  lua_pushinteger(luastate, p->icmp_s.type);
170  lua_pushinteger(luastate, p->icmp_s.code);
171  } else {
172  lua_pushinteger(luastate, 0);
173  lua_pushinteger(luastate, 0);
174  }
175 
176  return 6;
177 }
178 
179 /** \internal
180  * \brief get tcp/udp/sctp source port
181  * \param luastate the lua state
182  */
183 static int LuaPacketSport(lua_State *luastate)
184 {
185  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
186  Packet *p = LuaStateGetPacket(luastate);
187  if (p == NULL) {
188  LUA_ERROR("failed to get packet");
189  }
190 
191  switch (p->proto) {
192  case IPPROTO_TCP:
193  case IPPROTO_UDP:
194  case IPPROTO_SCTP:
195  lua_pushinteger(luastate, p->sp);
196  break;
197  default:
198  LUA_ERROR("sp only available for tcp, udp and sctp");
199  }
200 
201  return 1;
202 }
203 
204 /** \internal
205  * \brief get tcp/udp/sctp dest port
206  * \param luastate the lua state
207  */
208 static int LuaPacketDport(lua_State *luastate)
209 {
210  SCLuaCheckUserData(luastate, 1, suricata_packet, SCLUA_TUD_PACKET);
211  Packet *p = LuaStateGetPacket(luastate);
212  if (p == NULL) {
213  LUA_ERROR("failed to get packet");
214  }
215 
216  switch (p->proto) {
217  case IPPROTO_TCP:
218  case IPPROTO_UDP:
219  case IPPROTO_SCTP:
220  lua_pushinteger(luastate, p->dp);
221  break;
222  default:
223  LUA_ERROR("dp only available for tcp, udp and sctp");
224  }
225 
226  return 1;
227 }
228 
229 static int LuaPacketGet(lua_State *luastate)
230 {
231  Packet *p = LuaStateGetPacket(luastate);
232  if (p == NULL) {
233  LUA_ERROR("failed to get packet");
234  }
235 
236  struct LuaPacket *s = SCLuaNewUserData(luastate, SCLUA_TUD_PACKET, sizeof(*s));
237  if (s == NULL) {
238  LUA_ERROR("failed to get userdata");
239  }
240  luaL_getmetatable(luastate, suricata_packet);
241  lua_setmetatable(luastate, -2);
242  return 1;
243 }
244 
245 static const luaL_Reg packetlib[] = {
246  // clang-format off
247  { "get", LuaPacketGet },
248  { NULL, NULL }
249  // clang-format on
250 };
251 
252 static const luaL_Reg packetlib_meta[] = {
253  // clang-format off
254  { "packet", LuaPacketPacket },
255  { "payload", LuaPacketPayload },
256  { "pcap_cnt", LuaPacketPcapCnt },
257  { "timestring_legacy", LuaPacketTimestringLegacy },
258  { "timestring_iso8601", LuaPacketTimestringIso8601 },
259  { "timestamp", LuaPacketTimestamp },
260  { "tuple", LuaPacketTuple },
261  { "sp", LuaPacketSport },
262  { "dp", LuaPacketDport },
263  { NULL, NULL }
264  // clang-format on
265 };
266 
268 {
269  luaL_newmetatable(luastate, suricata_packet);
270  lua_pushvalue(luastate, -1);
271  lua_setfield(luastate, -2, "__index");
272  luaL_setfuncs(luastate, packetlib_meta, 0);
273 
274  luaL_newlib(luastate, packetlib);
275  return 1;
276 }
Packet_::proto
uint8_t proto
Definition: decode.h:540
LUA_ERROR
#define LUA_ERROR(msg)
Definition: util-lua-common.h:195
util-lua-common.h
CreateIsoTimeString
void CreateIsoTimeString(const SCTime_t ts, char *str, size_t size)
Definition: util-time.c:209
LuaLoadPacketLib
int LuaLoadPacketLib(lua_State *luastate)
Definition: util-lua-packetlib.c:267
PcapPacketCntGet
uint64_t PcapPacketCntGet(const Packet *p)
Definition: decode.c:1203
util-lua.h
Packet_::payload
uint8_t * payload
Definition: decode.h:622
LuaPacket
Definition: util-lua-packetlib.c:41
p
Packet * p
Definition: fuzz_dataset.c:30
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:623
GET_IPV6_DST_ADDR
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:205
lua_State
struct lua_State lua_State
Definition: suricata-common.h:527
Packet_::icmp_s
struct Packet_::@32::@39 icmp_s
util-debug.h
GET_IPV4_DST_ADDR_PTR
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:200
Packet_::ts
SCTime_t ts
Definition: decode.h:572
util-print.h
util-lua-packetlib.h
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:210
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:238
Packet_::sp
Port sp
Definition: decode.h:525
SCLuaCheckUserData
void * SCLuaCheckUserData(lua_State *L, int idx, const char *mt, uint32_t type_id)
Definition: util-lua-common.c:101
Packet_
Definition: decode.h:518
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:209
SCLuaNewUserData
void * SCLuaNewUserData(lua_State *L, uint32_t type_id, size_t size)
Definition: util-lua-common.c:42
GET_IPV4_SRC_ADDR_PTR
#define GET_IPV4_SRC_ADDR_PTR(p)
Definition: decode.h:199
suricata-common.h
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
GET_IPV6_SRC_ADDR
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:204
app-layer-protos.h
IPPROTO_SCTP
#define IPPROTO_SCTP
Definition: decode.h:1275
Packet_::dp
Port dp
Definition: decode.h:533
LuaStateGetPacket
Packet * LuaStateGetPacket(lua_State *luastate)
get packet pointer from the lua state
Definition: util-lua.c:223
CreateTimeString
void CreateTimeString(const SCTime_t ts, char *str, size_t size)
Definition: util-time.c:272
SCLUA_TUD_PACKET
@ SCLUA_TUD_PACKET
Definition: util-lua-common.h:60
LuaPushStringBuffer
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition: util-lua.c:380
SCTIME_USECS
#define SCTIME_USECS(t)
Definition: util-time.h:56