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