4 * Wireshark's interface to the Lua Programming Language
5 * for frame data and meta-data from a capture file.
7 * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 #define WS_LOG_DOMAIN LOG_DOMAIN_WSLUA
18 #include "wslua_file_common.h"
22 /* WSLUA_CONTINUE_MODULE File */
25 WSLUA_CLASS_DEFINE(FrameInfo
,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"));
27 A FrameInfo object, passed into Lua as an argument by FileHandler callback
28 functions (e.g., `read`, `seek_read`, etc.).
30 This object represents frame data and meta-data (data about the frame/packet)
31 for a given `read`/`seek_read`/`write`++'++s frame.
33 This object's fields are written-to/set when used by read function callbacks, and
34 read-from/get when used by file write function callbacks. In other words, when
35 the Lua plugin's FileHandler `read`/`seek_read`/etc. functions are invoked, a
36 FrameInfo object will be passed in as one of the arguments, and its fields
37 should be written-to/set based on the frame information read from the file;
38 whereas when the Lua plugin's `FileHandler.write()` function is invoked, the
39 `FrameInfo` object passed in should have its fields read-from/get, to write that
40 frame information to the file.
43 FrameInfo
* push_FrameInfo(lua_State
* L
, wtap_rec
*rec
) {
44 FrameInfo f
= (FrameInfo
) g_malloc0(sizeof(struct _wslua_rec
));
47 return pushFrameInfo(L
,f
);
50 WSLUA_METAMETHOD
FrameInfo__tostring(lua_State
* L
) {
51 /* Generates a string of debug info for the FrameInfo */
52 FrameInfo fi
= toFrameInfo(L
,1);
55 lua_pushstring(L
,"FrameInfo pointer is NULL!");
58 lua_pushfstring(L
, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, block='%p'",
59 fi
->rec
->rec_type
, fi
->rec
->presence_flags
, fi
->rec
->rec_header
.packet_header
.caplen
, fi
->rec
->rec_header
.packet_header
.len
, fi
->rec
->rec_header
.packet_header
.pkt_encap
, fi
->rec
->block
);
61 lua_pushstring(L
, "FrameInfo rec pointer is NULL!");
64 WSLUA_RETURN(1); /* String of debug information. */
67 /* XXX: should this function be a method of File instead? */
68 WSLUA_METHOD
FrameInfo_read_data(lua_State
* L
) {
69 /* Tells Wireshark to read directly from given file into frame data buffer, for length bytes. Returns true if succeeded, else false. */
70 #define WSLUA_ARG_FrameInfo_read_data_FILE 2 /* The File object userdata, provided by Wireshark previously in a reading-based callback. */
71 #define WSLUA_ARG_FrameInfo_read_data_LENGTH 3 /* The number of bytes to read from the file at the current cursor position. */
72 FrameInfo fi
= checkFrameInfo(L
,1);
73 File fh
= checkFile(L
,WSLUA_ARG_FrameInfo_read_data_FILE
);
74 uint32_t len
= wslua_checkuint32(L
, WSLUA_ARG_FrameInfo_read_data_LENGTH
);
76 char *err_info
= NULL
;
79 luaL_error(L
, "FrameInfo read_data() got null file pointer internally");
83 if (!wtap_read_bytes_buffer(fh
->file
, &fi
->rec
->data
, len
, &err
, &err_info
)) {
84 lua_pushboolean(L
, false);
86 lua_pushstring(L
, err_info
);
87 g_free(err_info
); /* is this right? */
90 lua_pushinteger(L
, err
);
94 lua_pushboolean(L
, true);
96 WSLUA_RETURN(1); /* True if succeeded, else returns false along with the error number and string error description. */
99 /* free the struct we created, but not the rec/buf it points to */
100 static int FrameInfo__gc(lua_State
* L
) {
101 FrameInfo fi
= toFrameInfo(L
,1);
106 /* WSLUA_ATTRIBUTE FrameInfo_comment RW Table of comments in this frame. */
107 static int FrameInfo_get_comment (lua_State
* L
) {
108 FrameInfo fi
= checkFrameInfo(L
,1);
109 #define FRAMEINFO_COMMENTS_TABLE 2
110 char *comment
= NULL
;
111 wtap_block_t block
= NULL
;
113 unsigned n_comments
= 0;
115 block
= fi
->rec
->block
;
116 // XXX - how to get the user-edited block, if any?
117 n_comments
= wtap_block_count_option(block
, OPT_COMMENT
);
118 lua_createtable(L
, n_comments
, 0);
119 for (i
= 0; i
< n_comments
; i
++) {
121 lua_pushinteger(L
, i
+1);
122 if (WTAP_OPTTYPE_SUCCESS
==
123 wtap_block_get_nth_string_option_value(block
, OPT_COMMENT
, i
, &comment
)) {
124 lua_pushstring(L
, comment
);
129 lua_settable(L
, FRAMEINFO_COMMENTS_TABLE
);
135 static int FrameInfo_set_comment (lua_State
* L
) {
136 FrameInfo fi
= checkFrameInfo(L
,1);
137 #define FRAMEINFO_COMMENTS_NEWTABLE 2
138 #define FRAMEINFO_COMMENTS_NEWCOMMENT 2
140 char *comment
= NULL
;
141 wtap_block_t block
= NULL
;
143 unsigned n_comments
= 0;
145 if(fi
->rec
->block
!= NULL
) {
146 block
= fi
->rec
->block
;
149 block
= wtap_block_create(WTAP_BLOCK_PACKET
);
150 fi
->rec
->block
= block
;
153 /* Strip off old comments */
154 n_comments
= wtap_block_count_option(block
, OPT_COMMENT
);
155 for (i
= 0; i
< n_comments
; i
++) {
156 wtap_block_remove_nth_option_instance(block
, OPT_COMMENT
, 0);
159 /* Add new comment(s) */
160 if (lua_istable(L
, FRAMEINFO_COMMENTS_NEWTABLE
)) {
161 for (lua_pushnil(L
); lua_next(L
, FRAMEINFO_COMMENTS_NEWTABLE
); ) {
162 if (lua_isstring(L
,-1)) {
163 comment
= (char *)luaL_checklstring(L
,-1,&len
);
164 wtap_block_add_string_option(block
, OPT_COMMENT
, comment
, len
);
165 } else if (! lua_isnil(L
,-1) ) {
166 return luaL_error(L
,"only strings should be in the table");
171 else if (lua_isstring(L
, FRAMEINFO_COMMENTS_NEWCOMMENT
)) {
172 comment
= (char *)luaL_checklstring(L
,FRAMEINFO_COMMENTS_NEWCOMMENT
,&len
);
173 wtap_block_add_string_option(block
, OPT_COMMENT
, comment
, len
);
176 return luaL_error(L
,"comment must be either a string or an array of strings");
182 /* WSLUA_ATTRIBUTE FrameInfo_time RW The packet timestamp as an NSTime object.
184 Note: Set the `FileHandler.time_precision` to the appropriate `wtap_file_tsprec` value as well.
186 static int FrameInfo_set_time (lua_State
* L
) {
187 FrameInfo fi
= checkFrameInfo(L
,1);
188 NSTime nstime
= checkNSTime(L
,2);
190 if (!fi
->rec
) return 0;
192 fi
->rec
->ts
.secs
= nstime
->secs
;
193 fi
->rec
->ts
.nsecs
= nstime
->nsecs
;
198 static int FrameInfo_get_time (lua_State
* L
) {
199 FrameInfo fi
= checkFrameInfo(L
,1);
200 NSTime nstime
= (NSTime
)g_malloc(sizeof(nstime_t
));
202 if (!nstime
) return 0;
204 nstime
->secs
= fi
->rec
->ts
.secs
;
205 nstime
->nsecs
= fi
->rec
->ts
.nsecs
;
207 pushNSTime(L
,nstime
);
209 return 1; /* An NSTime object of the frame's timestamp. */
212 /* WSLUA_ATTRIBUTE FrameInfo_data RW The data buffer containing the packet.
216 This cannot be cleared once set.
219 static int FrameInfo_set_data (lua_State
* L
) {
220 FrameInfo fi
= checkFrameInfo(L
,1);
223 ws_warning("Error in FrameInfo set data: NULL pointer");
227 if (lua_isstring(L
,2)) {
229 const char* s
= luaL_checklstring(L
,2,&len
);
231 /* Make sure we have enough room for the packet */
232 ws_buffer_append(&fi
->rec
->data
, s
, len
);
233 fi
->rec
->rec_header
.packet_header
.caplen
= (uint32_t) len
;
234 fi
->rec
->rec_header
.packet_header
.len
= (uint32_t) len
;
237 luaL_error(L
, "FrameInfo's attribute 'data' must be a Lua string");
242 static int FrameInfo_get_data (lua_State
* L
) {
243 FrameInfo fi
= checkFrameInfo(L
,1);
245 lua_pushlstring(L
, ws_buffer_start_ptr(&fi
->rec
->data
), ws_buffer_length(&fi
->rec
->data
));
247 WSLUA_RETURN(1); /* A Lua string of the frame record's data. */
250 /* WSLUA_ATTRIBUTE FrameInfo_rec_type RW The record type of the packet frame
252 See `wtap_rec_types` for values. */
253 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfo
,rec_type
,rec
->rec_type
);
254 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(FrameInfo
,rec_type
,rec
->rec_type
,unsigned);
256 /* WSLUA_ATTRIBUTE FrameInfo_flags RW The presence flags of the packet frame.
258 See `wtap_presence_flags` for bit values. */
259 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfo
,flags
,rec
->presence_flags
);
260 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(FrameInfo
,flags
,rec
->presence_flags
,uint32_t);
262 /* WSLUA_ATTRIBUTE FrameInfo_captured_length RW The captured packet length,
263 and thus the length of the buffer passed to the `FrameInfo.data` field. */
264 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfo
,captured_length
,rec
->rec_header
.packet_header
.caplen
);
265 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(FrameInfo
,captured_length
,rec
->rec_header
.packet_header
.caplen
,uint32_t);
267 /* WSLUA_ATTRIBUTE FrameInfo_original_length RW The on-the-wire packet length,
268 which may be longer than the `captured_length`. */
269 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfo
,original_length
,rec
->rec_header
.packet_header
.len
);
270 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(FrameInfo
,original_length
,rec
->rec_header
.packet_header
.len
,uint32_t);
272 /* WSLUA_ATTRIBUTE FrameInfo_encap RW The packet encapsulation type for the frame/packet,
273 if the file supports per-packet types. See `wtap_encaps` for possible
274 packet encapsulation types to use as the value for this field. */
275 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfo
,encap
,rec
->rec_header
.packet_header
.pkt_encap
);
276 WSLUA_ATTRIBUTE_NAMED_INTEGER_SETTER(FrameInfo
,encap
,rec
->rec_header
.packet_header
.pkt_encap
,int);
278 /* This table is ultimately registered as a sub-table of the class' metatable,
279 * and if __index/__newindex is invoked then it calls the appropriate function
280 * from this table for getting/setting the members.
282 WSLUA_ATTRIBUTES FrameInfo_attributes
[] = {
283 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,rec_type
),
284 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,flags
),
285 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,captured_length
),
286 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,original_length
),
287 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,comment
),
288 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,encap
),
289 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,time
),
290 WSLUA_ATTRIBUTE_RWREG(FrameInfo
,data
),
294 WSLUA_METHODS FrameInfo_methods
[] = {
295 WSLUA_CLASS_FNREG(FrameInfo
,read_data
),
299 WSLUA_META FrameInfo_meta
[] = {
300 WSLUA_CLASS_MTREG(FrameInfo
,tostring
),
304 int FrameInfo_register(lua_State
* L
) {
305 WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfo
);
309 WSLUA_CLASS_DEFINE(FrameInfoConst
,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"));
311 A constant FrameInfo object, passed into Lua as an argument by the FileHandler write
312 callback function. This has similar attributes/properties as FrameInfo, but the fields can
313 only be read from, not written to.
316 FrameInfoConst
* push_FrameInfoConst(lua_State
* L
, const wtap_rec
*rec
, const uint8_t *pd
) {
317 FrameInfoConst f
= (FrameInfoConst
) g_malloc(sizeof(struct _wslua_const_rec
));
321 return pushFrameInfoConst(L
,f
);
324 WSLUA_METAMETHOD
FrameInfoConst__tostring(lua_State
* L
) {
325 /* Generates a string of debug info for the FrameInfo */
326 FrameInfoConst fi
= toFrameInfoConst(L
,1);
329 lua_pushstring(L
,"FrameInfo pointer is NULL!");
331 if (fi
->rec
&& !fi
->expired
)
332 lua_pushfstring(L
, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, block='%p'",
333 fi
->rec
->rec_type
, fi
->rec
->presence_flags
, fi
->rec
->rec_header
.packet_header
.caplen
, fi
->rec
->rec_header
.packet_header
.len
, fi
->rec
->rec_header
.packet_header
.pkt_encap
, fi
->rec
->block
);
335 lua_pushfstring(L
, "FrameInfo has %s", fi
->rec
?"expired":"null rec pointer");
338 WSLUA_RETURN(1); /* String of debug information. */
341 /* XXX: should this function be a method of File instead? */
342 WSLUA_METHOD
FrameInfoConst_write_data(lua_State
* L
) {
343 /* Tells Wireshark to write directly to given file from the frame data buffer, for length bytes. Returns true if succeeded, else false. */
344 #define WSLUA_ARG_FrameInfoConst_write_data_FILE 2 /* The File object userdata, provided by Wireshark previously in a writing-based callback. */
345 #define WSLUA_OPTARG_FrameInfoConst_write_data_LENGTH 3 /* The number of bytes to write to the file at the current cursor position, or all if not supplied. */
346 FrameInfoConst fi
= checkFrameInfoConst(L
,1);
347 File fh
= checkFile(L
,WSLUA_ARG_FrameInfoConst_write_data_FILE
);
348 uint32_t len
= wslua_optuint32(L
, WSLUA_OPTARG_FrameInfoConst_write_data_LENGTH
, fi
->rec
? fi
->rec
->rec_header
.packet_header
.caplen
:0);
351 if (!fi
->pd
|| !fi
->rec
|| !fh
->wdh
) {
352 luaL_error(L
, "FrameInfoConst write_data() got null buffer or file pointer internally");
356 if (len
> fi
->rec
->rec_header
.packet_header
.caplen
)
357 len
= fi
->rec
->rec_header
.packet_header
.caplen
;
359 if (!wtap_dump_file_write(fh
->wdh
, fi
->pd
, (size_t)(len
), &err
)) {
360 lua_pushboolean(L
, false);
361 lua_pushfstring(L
, "FrameInfoConst write_data() error: %s", g_strerror(err
));
362 lua_pushinteger(L
, err
);
366 lua_pushboolean(L
, true);
368 WSLUA_RETURN(1); /* True if succeeded, else returns false along with the error number and string error description. */
371 /* free the struct we created, but not the wtap_rec it points to */
372 static int FrameInfoConst__gc(lua_State
* L
) {
373 FrameInfoConst fi
= toFrameInfoConst(L
,1);
378 /* WSLUA_ATTRIBUTE FrameInfoConst_comment RO The first string comment for the packet, if any;
379 nil if there is no comment. */
380 static int FrameInfoConst_get_comment (lua_State
* L
) {
381 FrameInfoConst fi
= checkFrameInfoConst(L
,1);
382 #define FRAMEINFOCONST_COMMENTS_TABLE 2
383 char *comment
= NULL
;
384 wtap_block_t block
= NULL
;
386 unsigned n_comments
= 0;
388 block
= fi
->rec
->block
;
389 // XXX - how to get the user-edited block, if any?
390 n_comments
= wtap_block_count_option(block
, OPT_COMMENT
);
391 lua_createtable(L
, n_comments
, 0);
392 for (i
= 0; i
< n_comments
; i
++) {
394 lua_pushinteger(L
, i
+1);
395 if (WTAP_OPTTYPE_SUCCESS
==
396 wtap_block_get_nth_string_option_value(block
, OPT_COMMENT
, i
, &comment
)) {
397 lua_pushstring(L
, comment
);
402 lua_settable(L
, FRAMEINFOCONST_COMMENTS_TABLE
);
408 /* WSLUA_ATTRIBUTE FrameInfoConst_time RO The packet timestamp as an NSTime object. */
409 static int FrameInfoConst_get_time (lua_State
* L
) {
410 FrameInfoConst fi
= checkFrameInfoConst(L
,1);
411 NSTime nstime
= (NSTime
)g_malloc(sizeof(nstime_t
));
413 if (!nstime
) return 0;
415 nstime
->secs
= fi
->rec
->ts
.secs
;
416 nstime
->nsecs
= fi
->rec
->ts
.nsecs
;
418 pushNSTime(L
,nstime
);
420 return 1; /* An NSTime object of the frame's timestamp. */
423 /* WSLUA_ATTRIBUTE FrameInfoConst_data RO The data buffer containing the packet. */
424 static int FrameInfoConst_get_data (lua_State
* L
) {
425 FrameInfoConst fi
= checkFrameInfoConst(L
,1);
427 if (!fi
->pd
|| !fi
->rec
) return 0;
429 lua_pushlstring(L
, fi
->pd
, fi
->rec
->rec_header
.packet_header
.caplen
);
434 /* WSLUA_ATTRIBUTE FrameInfoConst_rec_type RO The record type of the packet frame - see `wtap_presence_flags` for values. */
435 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfoConst
,rec_type
,rec
->rec_type
);
437 /* WSLUA_ATTRIBUTE FrameInfoConst_flags RO The presence flags of the packet frame - see `wtap_presence_flags` for bits. */
438 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfoConst
,flags
,rec
->presence_flags
);
440 /* WSLUA_ATTRIBUTE FrameInfoConst_captured_length RO The captured packet length, and thus the length of the buffer in the FrameInfoConst.data field. */
441 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfoConst
,captured_length
,rec
->rec_header
.packet_header
.caplen
);
443 /* WSLUA_ATTRIBUTE FrameInfoConst_original_length RO The on-the-wire packet length, which may be longer than the `captured_length`. */
444 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfoConst
,original_length
,rec
->rec_header
.packet_header
.len
);
446 /* WSLUA_ATTRIBUTE FrameInfoConst_encap RO The packet encapsulation type, if the file supports per-packet types.
448 See `wtap_encaps` for possible packet encapsulation types to use as the value for this field. */
449 WSLUA_ATTRIBUTE_NAMED_INTEGER_GETTER(FrameInfoConst
,encap
,rec
->rec_header
.packet_header
.pkt_encap
);
451 WSLUA_ATTRIBUTES FrameInfoConst_attributes
[] = {
452 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,rec_type
),
453 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,flags
),
454 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,captured_length
),
455 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,original_length
),
456 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,encap
),
457 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,comment
),
458 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,time
),
459 WSLUA_ATTRIBUTE_ROREG(FrameInfoConst
,data
),
463 WSLUA_METHODS FrameInfoConst_methods
[] = {
464 WSLUA_CLASS_FNREG(FrameInfoConst
,write_data
),
468 WSLUA_META FrameInfoConst_meta
[] = {
469 WSLUA_CLASS_MTREG(FrameInfoConst
,tostring
),
473 int FrameInfoConst_register(lua_State
* L
) {
474 WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfoConst
);
480 * Editor modelines - https://www.wireshark.org/tools/modelines.html
485 * indent-tabs-mode: nil
488 * vi: set shiftwidth=4 tabstop=8 expandtab:
489 * :indentSize=4:tabSize=8:noTabs=true: