728183c27e
Since v2.9.1rc0-528-g31aba351e2, it is clear that wtap file formats should free earlier comments before writing a new one. Do so. Fixes leaks reported by ASAN for test_wslua_file_acme_reader. Change-Id: Iafb643f01f5973f2d3b88f244ee70e8c0c451080 Reviewed-on: https://code.wireshark.org/review/31738 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
404 lines
15 KiB
C
404 lines
15 KiB
C
/*
|
|
* wslua_frame_info.c
|
|
*
|
|
* Wireshark's interface to the Lua Programming Language
|
|
* for frame data and meta-data from a capture file.
|
|
*
|
|
* (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "wslua_file_common.h"
|
|
|
|
|
|
/* WSLUA_CONTINUE_MODULE File */
|
|
|
|
|
|
WSLUA_CLASS_DEFINE(FrameInfo,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"));
|
|
/*
|
|
A FrameInfo object, passed into Lua as an argument by FileHandler callback
|
|
functions (e.g., `read`, `seek_read`, etc.).
|
|
|
|
This object represents frame data and meta-data (data about the frame/packet)
|
|
for a given `read`/`seek_read`/`write`'s frame.
|
|
|
|
This object's fields are written-to/set when used by read function callbacks, and
|
|
read-from/get when used by file write function callbacks. In other words, when
|
|
the Lua plugin's FileHandler `read`/`seek_read`/etc. functions are invoked, a
|
|
FrameInfo object will be passed in as one of the arguments, and its fields
|
|
should be written-to/set based on the frame information read from the file;
|
|
whereas when the Lua plugin's `FileHandler.write()` function is invoked, the
|
|
`FrameInfo` object passed in should have its fields read-from/get, to write that
|
|
frame information to the file.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
|
|
FrameInfo* push_FrameInfo(lua_State* L, wtap_rec *rec, Buffer* buf) {
|
|
FrameInfo f = (FrameInfo) g_malloc0(sizeof(struct _wslua_phdr));
|
|
f->rec = rec;
|
|
f->buf = buf;
|
|
f->expired = FALSE;
|
|
return pushFrameInfo(L,f);
|
|
}
|
|
|
|
WSLUA_METAMETHOD FrameInfo__tostring(lua_State* L) {
|
|
/* Generates a string of debug info for the FrameInfo */
|
|
FrameInfo fi = toFrameInfo(L,1);
|
|
|
|
if (!fi) {
|
|
lua_pushstring(L,"FrameInfo pointer is NULL!");
|
|
} else {
|
|
if (fi->rec)
|
|
lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'",
|
|
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->opt_comment);
|
|
else
|
|
lua_pushstring(L, "FrameInfo rec pointer is NULL!");
|
|
}
|
|
|
|
WSLUA_RETURN(1); /* String of debug information. */
|
|
}
|
|
|
|
/* XXX: should this function be a method of File instead? */
|
|
WSLUA_METHOD FrameInfo_read_data(lua_State* L) {
|
|
/* Tells Wireshark to read directly from given file into frame data buffer, for length bytes. Returns true if succeeded, else false. */
|
|
#define WSLUA_ARG_FrameInfo_read_data_FILE 2 /* The File object userdata, provided by Wireshark previously in a reading-based callback. */
|
|
#define WSLUA_ARG_FrameInfo_read_data_LENGTH 3 /* The number of bytes to read from the file at the current cursor position. */
|
|
FrameInfo fi = checkFrameInfo(L,1);
|
|
File fh = checkFile(L,WSLUA_ARG_FrameInfo_read_data_FILE);
|
|
guint32 len = wslua_checkguint32(L, WSLUA_ARG_FrameInfo_read_data_LENGTH);
|
|
int err = 0;
|
|
gchar *err_info = NULL;
|
|
|
|
if (!fi->buf || !fh->file) {
|
|
luaL_error(L, "FrameInfo read_data() got null buffer or file pointer internally");
|
|
return 0;
|
|
}
|
|
|
|
if (!wtap_read_packet_bytes(fh->file, fi->buf, len, &err, &err_info)) {
|
|
lua_pushboolean(L, FALSE);
|
|
if (err_info) {
|
|
lua_pushstring(L, err_info);
|
|
g_free(err_info); /* is this right? */
|
|
}
|
|
else lua_pushnil(L);
|
|
lua_pushnumber(L, err);
|
|
return 3;
|
|
}
|
|
|
|
lua_pushboolean(L, TRUE);
|
|
|
|
WSLUA_RETURN(1); /* True if succeeded, else returns false along with the error number and string error description. */
|
|
}
|
|
|
|
/* free the struct we created, but not the rec/buf it points to */
|
|
static int FrameInfo__gc(lua_State* L) {
|
|
FrameInfo fi = toFrameInfo(L,1);
|
|
g_free(fi);
|
|
return 0;
|
|
}
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_time RW The packet timestamp as an NSTime object.
|
|
|
|
Note: Set the `FileHandler.time_precision` to the appropriate `wtap_file_tsprec` value as well.
|
|
*/
|
|
static int FrameInfo_set_time (lua_State* L) {
|
|
FrameInfo fi = checkFrameInfo(L,1);
|
|
NSTime nstime = checkNSTime(L,2);
|
|
|
|
if (!fi->rec) return 0;
|
|
|
|
fi->rec->ts.secs = nstime->secs;
|
|
fi->rec->ts.nsecs = nstime->nsecs;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int FrameInfo_get_time (lua_State* L) {
|
|
FrameInfo fi = checkFrameInfo(L,1);
|
|
NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));
|
|
|
|
if (!nstime) return 0;
|
|
|
|
nstime->secs = fi->rec->ts.secs;
|
|
nstime->nsecs = fi->rec->ts.nsecs;
|
|
|
|
pushNSTime(L,nstime);
|
|
|
|
return 1; /* An NSTime object of the frame's timestamp. */
|
|
}
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_data RW The data buffer containing the packet.
|
|
|
|
[NOTE]
|
|
====
|
|
This cannot be cleared once set.
|
|
====
|
|
*/
|
|
static int FrameInfo_set_data (lua_State* L) {
|
|
FrameInfo fi = checkFrameInfo(L,1);
|
|
|
|
if (!fi->rec) {
|
|
g_warning("Error in FrameInfo set data: NULL pointer");
|
|
return 0;
|
|
}
|
|
|
|
if (!fi->buf) {
|
|
g_warning("Error in FrameInfo set data: NULL frame_buffer pointer");
|
|
return 0;
|
|
}
|
|
|
|
if (lua_isstring(L,2)) {
|
|
size_t len = 0;
|
|
const gchar* s = luaL_checklstring(L,2,&len);
|
|
|
|
/* Make sure we have enough room for the packet */
|
|
ws_buffer_assure_space(fi->buf, len);
|
|
memcpy(ws_buffer_start_ptr(fi->buf), s, len);
|
|
fi->rec->rec_header.packet_header.caplen = (guint32) len;
|
|
fi->rec->rec_header.packet_header.len = (guint32) len;
|
|
}
|
|
else
|
|
luaL_error(L, "FrameInfo's attribute 'data' must be a Lua string");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int FrameInfo_get_data (lua_State* L) {
|
|
FrameInfo fi = checkFrameInfo(L,1);
|
|
|
|
if (!fi->buf) return 0;
|
|
|
|
lua_pushlstring(L, ws_buffer_start_ptr(fi->buf), ws_buffer_length(fi->buf));
|
|
|
|
WSLUA_RETURN(1); /* A Lua string of the frame buffer's data. */
|
|
}
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_rec_type RW The record type of the packet frame
|
|
|
|
See `wtap_rec_types` in `init.lua` for values. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,rec_type,rec->rec_type);
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,rec_type,rec->rec_type,guint);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_flags RW The presence flags of the packet frame.
|
|
|
|
See `wtap_presence_flags` in `init.lua` for bit values. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,flags,rec->presence_flags);
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,flags,rec->presence_flags,guint32);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_captured_length RW The captured packet length,
|
|
and thus the length of the buffer passed to the `FrameInfo.data` field. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,captured_length,rec->rec_header.packet_header.caplen);
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,captured_length,rec->rec_header.packet_header.caplen,guint32);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_original_length RW The on-the-wire packet length,
|
|
which may be longer than the `captured_length`. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,original_length,rec->rec_header.packet_header.len);
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,original_length,rec->rec_header.packet_header.len,guint32);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfo_encap RW The packet encapsulation type for the frame/packet,
|
|
if the file supports per-packet types. See `wtap_encaps` in `init.lua` for possible
|
|
packet encapsulation types to use as the value for this field. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,encap,rec->rec_header.packet_header.pkt_encap);
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,encap,rec->rec_header.packet_header.pkt_encap,int);
|
|
|
|
// rec->opt_comment will be freed by wtap_sequential_close -> wtap_rec_cleanup.
|
|
/* WSLUA_ATTRIBUTE FrameInfo_comment RW A string comment for the packet, if the
|
|
`wtap_presence_flags.COMMENTS` was set in the presence flags; nil if there is no comment. */
|
|
WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FrameInfo,comment,rec->opt_comment);
|
|
WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(FrameInfo,comment,rec->opt_comment,TRUE);
|
|
|
|
/* This table is ultimately registered as a sub-table of the class' metatable,
|
|
* and if __index/__newindex is invoked then it calls the appropriate function
|
|
* from this table for getting/setting the members.
|
|
*/
|
|
WSLUA_ATTRIBUTES FrameInfo_attributes[] = {
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,rec_type),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,flags),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,captured_length),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,original_length),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,comment),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,encap),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,time),
|
|
WSLUA_ATTRIBUTE_RWREG(FrameInfo,data),
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
WSLUA_METHODS FrameInfo_methods[] = {
|
|
WSLUA_CLASS_FNREG(FrameInfo,read_data),
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
WSLUA_META FrameInfo_meta[] = {
|
|
WSLUA_CLASS_MTREG(FrameInfo,tostring),
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
int FrameInfo_register(lua_State* L) {
|
|
WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfo);
|
|
return 0;
|
|
}
|
|
|
|
WSLUA_CLASS_DEFINE(FrameInfoConst,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"));
|
|
/*
|
|
A constant FrameInfo object, passed into Lua as an argument by the FileHandler write
|
|
callback function. This has similar attributes/properties as FrameInfo, but the fields can
|
|
only be read from, not written to.
|
|
|
|
@since 1.11.3
|
|
*/
|
|
|
|
FrameInfoConst* push_FrameInfoConst(lua_State* L, const wtap_rec *rec, const guint8 *pd) {
|
|
FrameInfoConst f = (FrameInfoConst) g_malloc(sizeof(struct _wslua_const_phdr));
|
|
f->rec = rec;
|
|
f->pd = pd;
|
|
f->expired = FALSE;
|
|
return pushFrameInfoConst(L,f);
|
|
}
|
|
|
|
WSLUA_METAMETHOD FrameInfoConst__tostring(lua_State* L) {
|
|
/* Generates a string of debug info for the FrameInfo */
|
|
FrameInfoConst fi = toFrameInfoConst(L,1);
|
|
|
|
if (!fi) {
|
|
lua_pushstring(L,"FrameInfo pointer is NULL!");
|
|
} else {
|
|
if (fi->rec && !fi->expired)
|
|
lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'",
|
|
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->opt_comment);
|
|
else
|
|
lua_pushfstring(L, "FrameInfo has %s", fi->rec?"expired":"null rec pointer");
|
|
}
|
|
|
|
WSLUA_RETURN(1); /* String of debug information. */
|
|
}
|
|
|
|
/* XXX: should this function be a method of File instead? */
|
|
WSLUA_METHOD FrameInfoConst_write_data(lua_State* L) {
|
|
/* Tells Wireshark to write directly to given file from the frame data buffer, for length bytes. Returns true if succeeded, else false. */
|
|
#define WSLUA_ARG_FrameInfoConst_write_data_FILE 2 /* The File object userdata, provided by Wireshark previously in a writing-based callback. */
|
|
#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. */
|
|
FrameInfoConst fi = checkFrameInfoConst(L,1);
|
|
File fh = checkFile(L,WSLUA_ARG_FrameInfoConst_write_data_FILE);
|
|
guint32 len = wslua_optguint32(L, WSLUA_OPTARG_FrameInfoConst_write_data_LENGTH, fi->rec ? fi->rec->rec_header.packet_header.caplen:0);
|
|
int err = 0;
|
|
|
|
if (!fi->pd || !fi->rec || !fh->wdh) {
|
|
luaL_error(L, "FrameInfoConst write_data() got null buffer or file pointer internally");
|
|
return 0;
|
|
}
|
|
|
|
if (len > fi->rec->rec_header.packet_header.caplen)
|
|
len = fi->rec->rec_header.packet_header.caplen;
|
|
|
|
if (!wtap_dump_file_write(fh->wdh, fi->pd, (size_t)(len), &err)) {
|
|
lua_pushboolean(L, FALSE);
|
|
lua_pushfstring(L, "FrameInfoConst write_data() error: %s", g_strerror(err));
|
|
lua_pushnumber(L, err);
|
|
return 3;
|
|
}
|
|
|
|
lua_pushboolean(L, TRUE);
|
|
|
|
WSLUA_RETURN(1); /* True if succeeded, else returns false along with the error number and string error description. */
|
|
}
|
|
|
|
/* free the struct we created, but not the wtap_rec it points to */
|
|
static int FrameInfoConst__gc(lua_State* L) {
|
|
FrameInfoConst fi = toFrameInfoConst(L,1);
|
|
g_free(fi);
|
|
return 0;
|
|
}
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_time RO The packet timestamp as an NSTime object. */
|
|
static int FrameInfoConst_get_time (lua_State* L) {
|
|
FrameInfoConst fi = checkFrameInfoConst(L,1);
|
|
NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));
|
|
|
|
if (!nstime) return 0;
|
|
|
|
nstime->secs = fi->rec->ts.secs;
|
|
nstime->nsecs = fi->rec->ts.nsecs;
|
|
|
|
pushNSTime(L,nstime);
|
|
|
|
return 1; /* An NSTime object of the frame's timestamp. */
|
|
}
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_data RO The data buffer containing the packet. */
|
|
static int FrameInfoConst_get_data (lua_State* L) {
|
|
FrameInfoConst fi = checkFrameInfoConst(L,1);
|
|
|
|
if (!fi->pd || !fi->rec) return 0;
|
|
|
|
lua_pushlstring(L, fi->pd, fi->rec->rec_header.packet_header.caplen);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_rec_type RO The record type of the packet frame - see `wtap_presence_flags` in `init.lua` for values. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,rec_type,rec->rec_type);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_flags RO The presence flags of the packet frame - see `wtap_presence_flags` in `init.lua` for bits. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,flags,rec->presence_flags);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_captured_length RO The captured packet length, and thus the length of the buffer in the FrameInfoConst.data field. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,captured_length,rec->rec_header.packet_header.caplen);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_original_length RO The on-the-wire packet length, which may be longer than the `captured_length`. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,original_length,rec->rec_header.packet_header.len);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_encap RO The packet encapsulation type, if the file supports per-packet types.
|
|
|
|
See `wtap_encaps` in `init.lua` for possible packet encapsulation types to use as the value for this field. */
|
|
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,encap,rec->rec_header.packet_header.pkt_encap);
|
|
|
|
/* WSLUA_ATTRIBUTE FrameInfoConst_comment RO A comment for the packet; nil if there is none. */
|
|
WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FrameInfoConst,comment,rec->opt_comment);
|
|
|
|
WSLUA_ATTRIBUTES FrameInfoConst_attributes[] = {
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,rec_type),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,flags),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,captured_length),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,original_length),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,encap),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,comment),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,time),
|
|
WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,data),
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
WSLUA_METHODS FrameInfoConst_methods[] = {
|
|
WSLUA_CLASS_FNREG(FrameInfoConst,write_data),
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
WSLUA_META FrameInfoConst_meta[] = {
|
|
WSLUA_CLASS_MTREG(FrameInfoConst,tostring),
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
int FrameInfoConst_register(lua_State* L) {
|
|
WSLUA_REGISTER_CLASS_WITH_ATTRS(FrameInfoConst);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 4
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
*/
|