TODO netlogon_user_flags_ntlmv2_enabled
[wireshark-sm.git] / epan / wslua / wslua_frame_info.c
blob9a6fbeed62575655b66a848e075e883e53d4abc9
1 /*
2 * wslua_frame_info.c
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
15 #include "config.h"
16 #define WS_LOG_DOMAIN LOG_DOMAIN_WSLUA
18 #include "wslua_file_common.h"
19 #include <lua.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));
45 f->rec = rec;
46 f->expired = false;
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);
54 if (!fi) {
55 lua_pushstring(L,"FrameInfo pointer is NULL!");
56 } else {
57 if (fi->rec)
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);
60 else
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);
75 int err = 0;
76 char *err_info = NULL;
78 if (!fh->file) {
79 luaL_error(L, "FrameInfo read_data() got null file pointer internally");
80 return 0;
83 if (!wtap_read_bytes_buffer(fh->file, &fi->rec->data, len, &err, &err_info)) {
84 lua_pushboolean(L, false);
85 if (err_info) {
86 lua_pushstring(L, err_info);
87 g_free(err_info); /* is this right? */
89 else lua_pushnil(L);
90 lua_pushinteger(L, err);
91 return 3;
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);
102 g_free(fi);
103 return 0;
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;
112 unsigned i = 0;
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++) {
120 comment = NULL;
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);
126 else {
127 lua_pushnil(L);
129 lua_settable(L, FRAMEINFO_COMMENTS_TABLE);
132 return 1;
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
139 size_t len = 0;
140 char *comment = NULL;
141 wtap_block_t block = NULL;
142 unsigned i = 0;
143 unsigned n_comments = 0;
145 if(fi->rec->block != NULL) {
146 block = fi->rec->block;
148 else {
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");
168 lua_pop(L, 1);
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);
175 else {
176 return luaL_error(L,"comment must be either a string or an array of strings");
179 return 0;
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;
195 return 0;
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.
214 [NOTE]
215 ====
216 This cannot be cleared once set.
217 ====
219 static int FrameInfo_set_data (lua_State* L) {
220 FrameInfo fi = checkFrameInfo(L,1);
222 if (!fi->rec) {
223 ws_warning("Error in FrameInfo set data: NULL pointer");
224 return 0;
227 if (lua_isstring(L,2)) {
228 size_t len = 0;
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;
236 else
237 luaL_error(L, "FrameInfo's attribute 'data' must be a Lua string");
239 return 0;
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),
291 { NULL, NULL, NULL }
294 WSLUA_METHODS FrameInfo_methods[] = {
295 WSLUA_CLASS_FNREG(FrameInfo,read_data),
296 { NULL, NULL }
299 WSLUA_META FrameInfo_meta[] = {
300 WSLUA_CLASS_MTREG(FrameInfo,tostring),
301 { NULL, NULL }
304 int FrameInfo_register(lua_State* L) {
305 WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfo);
306 return 0;
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));
318 f->rec = rec;
319 f->pd = pd;
320 f->expired = false;
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);
328 if (!fi) {
329 lua_pushstring(L,"FrameInfo pointer is NULL!");
330 } else {
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);
334 else
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);
349 int err = 0;
351 if (!fi->pd || !fi->rec || !fh->wdh) {
352 luaL_error(L, "FrameInfoConst write_data() got null buffer or file pointer internally");
353 return 0;
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);
363 return 3;
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);
374 g_free(fi);
375 return 0;
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;
385 unsigned i = 0;
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++) {
393 comment = NULL;
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);
399 else {
400 lua_pushnil(L);
402 lua_settable(L, FRAMEINFOCONST_COMMENTS_TABLE);
405 return 1;
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);
431 return 1;
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),
460 { NULL, NULL, NULL }
463 WSLUA_METHODS FrameInfoConst_methods[] = {
464 WSLUA_CLASS_FNREG(FrameInfoConst,write_data),
465 { NULL, NULL }
468 WSLUA_META FrameInfoConst_meta[] = {
469 WSLUA_CLASS_MTREG(FrameInfoConst,tostring),
470 { NULL, NULL }
473 int FrameInfoConst_register(lua_State* L) {
474 WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfoConst);
475 return 0;
480 * Editor modelines - https://www.wireshark.org/tools/modelines.html
482 * Local variables:
483 * c-basic-offset: 4
484 * tab-width: 8
485 * indent-tabs-mode: nil
486 * End:
488 * vi: set shiftwidth=4 tabstop=8 expandtab:
489 * :indentSize=4:tabSize=8:noTabs=true: