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