diff options
26 files changed, 6166 insertions, 5320 deletions
diff --git a/doc/README.wslua b/doc/README.wslua index 5bee84b090..74074904e3 100644 --- a/doc/README.wslua +++ b/doc/README.wslua @@ -289,6 +289,14 @@ to make new wslua files generate documentation, it is not sufficient to just add this macro to a new file and add the file to the CMakeLists.txt; you also have to add the module name into docbook/user-guide.xml, and docbook/wsluarm.xml. + +WSLUA_CONTINUE_MODULE - like WSLUA_MODULE, except used at the top of a .c file +to continue defining classes/functions/etc. within a previously declared module +in a previous file (i.e., one that used WSLUA_MODULE). The module name must match +the original one, and the .c file must be listed after the original one in the +CMakeLists.txt/Makefile.common lists in the docbook directory. + + WSLUA_ATTRIBUTE - this is another documentation-only "macro", only used within comments. It makes the API docs generate documentation for a member variable of a class, i.e. a key of a Lua table that is not called as a function in Lua, @@ -327,6 +335,7 @@ Example: WSLUA_RETURN(1); /* A boolean: true if it is enabled, false if it isn't. */ } + WSLUA_CLASS_DEFINE - this is used to define/create a new Lua class type (i.e., table with methods). A Class name must begin with an uppercase letter, followed by any upper or lower case letters but not underscores; in other @@ -338,6 +347,7 @@ Example: WSLUA_CLASS_DEFINE(ProgDlg,NOP,NOP); /* Manages a progress bar dialog. */ + WSLUA_CONSTRUCTOR - this is used to define a function of a class that is a static function rather than a per-object method; i.e., from a Lua perspective the function is called as 'myObj.func()' instead of 'myObj:func()'. From a diff --git a/docbook/CMakeLists.txt b/docbook/CMakeLists.txt index e218bbc259..5c3164516b 100644 --- a/docbook/CMakeLists.txt +++ b/docbook/CMakeLists.txt @@ -255,6 +255,9 @@ set(WSDG_SOURCE ${WSDG_GRAPHICS} ) +# Note: file order here MATTERS! +# new WSLUA_MODULE files must come right before any WSLUA_CONTINUE_MODULE +# files for the same module set(WSLUA_MODULES ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_dumper.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_field.c @@ -262,10 +265,21 @@ set(WSLUA_MODULES ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_int64.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_listener.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_pinfo.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_address.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_column.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_nstime.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_proto.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_dissector.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_pref.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_proto_expert.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_proto_field.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_tree.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_tvb.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_byte_array.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_file.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_file_handler.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_frame_info.c + ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_capture_info.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_dir.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_util.c ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_struct.c diff --git a/docbook/Makefile.common b/docbook/Makefile.common index 4c9e941334..a2edd2e393 100644 --- a/docbook/Makefile.common +++ b/docbook/Makefile.common @@ -253,18 +253,32 @@ CLEANDIRS = \ wsug_html_chunked \ wsluarm_src +# Note: file order here MATTERS! +# new WSLUA_MODULE files must come right before any WSLUA_CONTINUE_MODULE +# files for the same module WSLUA_MODULES = \ $(top_srcdir)/epan/wslua/wslua_dumper.c \ $(top_srcdir)/epan/wslua/wslua_field.c \ $(top_srcdir)/epan/wslua/wslua_gui.c \ $(top_srcdir)/epan/wslua/wslua_listener.c \ $(top_srcdir)/epan/wslua/wslua_pinfo.c \ + $(top_srcdir)/epan/wslua/wslua_address.c \ + $(top_srcdir)/epan/wslua/wslua_column.c \ + $(top_srcdir)/epan/wslua/wslua_nstime.c \ $(top_srcdir)/epan/wslua/wslua_proto.c \ + $(top_srcdir)/epan/wslua/wslua_dissector.c \ + $(top_srcdir)/epan/wslua/wslua_pref.c \ + $(top_srcdir)/epan/wslua/wslua_proto_expert.c \ + $(top_srcdir)/epan/wslua/wslua_proto_field.c \ $(top_srcdir)/epan/wslua/wslua_int64.c \ $(top_srcdir)/epan/wslua/wslua_struct.c \ $(top_srcdir)/epan/wslua/wslua_tree.c \ $(top_srcdir)/epan/wslua/wslua_tvb.c \ + $(top_srcdir)/epan/wslua/wslua_byte_array.c \ $(top_srcdir)/epan/wslua/wslua_file.c \ + $(top_srcdir)/epan/wslua/wslua_file_handler.c \ + $(top_srcdir)/epan/wslua/wslua_frame_info.c \ + $(top_srcdir)/epan/wslua/wslua_capture_info.c \ $(top_srcdir)/epan/wslua/wslua_dir.c \ $(top_srcdir)/epan/wslua/wslua_util.c diff --git a/docbook/make-wsluarm.pl b/docbook/make-wsluarm.pl index 35f92a8644..4bba10b9c0 100755 --- a/docbook/make-wsluarm.pl +++ b/docbook/make-wsluarm.pl @@ -545,16 +545,19 @@ for (@control) { $anymatch .= ')'; # for each file given in the command line args -my $file; -while ( $file = shift) { +my $file = shift; +my $docfile = 0; - next unless -f $file; +while ( $file ) { - %module = (); + # continue to next loop if the file is not plain text + next unless -f $file; - my $docfile = $file; - $docfile =~ s#.*/##; - $docfile =~ s/\.c$/.$out_extension/; + if (!$docfile) { + $docfile = $file; + $docfile =~ s#.*/##; + $docfile =~ s/\.c$/.$out_extension/; + } open C, "< $file" or die "Can't open input file $file: $!"; open D, "> wsluarm_src/$docfile" or die "Can't open output file wsluarm_src/$docfile: $!"; @@ -562,6 +565,8 @@ while ( $file = shift) { my $b = ''; $b .= $_ while (<C>); + close C; + while ($b =~ /$anymatch/ms ) { my $match = $1; # print "\n-----\n$match\n-----\n"; @@ -575,6 +580,34 @@ while ( $file = shift) { } } + # peek at next file to see if it's continuing this module + $file = shift; + # make sure we get the next plain text file + while ($file and !(-f $file)) { + $file = shift; + } + + if ($file) { + # we have another file - check it out + + open C, "< $file" or die "Can't open input file $file: $!"; + + my $peek_for_continue = ''; + $peek_for_continue .= $_ while (<C>); + + close C; + + if ($peek_for_continue =~ /WSLUA_CONTINUE_MODULE\s*([A-Z][a-zA-Z0-9]+)/) { + if ($module{name} ne $1) { + die "Input file $file continues a different module: $1 (previous module is $module{name})!"; + } + # ok, we're continuing the same module + next; + } + } + + # if we got here, we're not continuing the module + $modules{$module{name}} = $docfile; print "Generating source XML for: $module{name}\n"; @@ -640,15 +673,17 @@ while ( $file = shift) { print D ${$template_ref}{global_functions_footer}; } + printf D ${$template_ref}{module_footer}, $module{name}; + + close D; + + %module = (); %classes = (); $class = undef; $function = undef; @functions = (); - close C; + $docfile = 0; - printf D ${$template_ref}{module_footer}, $module{name}; - - close D; } sub function_descr { diff --git a/epan/wslua/CMakeLists.txt b/epan/wslua/CMakeLists.txt index e3c2b75a2b..8669e101bb 100644 --- a/epan/wslua/CMakeLists.txt +++ b/epan/wslua/CMakeLists.txt @@ -20,24 +20,36 @@ # set(WSLUA_MODULES - ${CMAKE_CURRENT_SOURCE_DIR}/lua_bitop.c ${CMAKE_CURRENT_SOURCE_DIR}/lrexlib.c ${CMAKE_CURRENT_SOURCE_DIR}/lrexlib_glib.c ${CMAKE_CURRENT_SOURCE_DIR}/lrexlib_glib_f.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_int64.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_tvb.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_proto.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_tree.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_pinfo.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_listener.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_gui.c + ${CMAKE_CURRENT_SOURCE_DIR}/lua_bitop.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_address.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_byte_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_capture_info.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_column.c ${CMAKE_CURRENT_SOURCE_DIR}/wslua_dir.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_util.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_dissector.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_dumper.c ${CMAKE_CURRENT_SOURCE_DIR}/wslua_field.c ${CMAKE_CURRENT_SOURCE_DIR}/wslua_file.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_struct.c - ${CMAKE_CURRENT_SOURCE_DIR}/wslua_dumper.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_file_common.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_file_handler.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_frame_info.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_gui.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_int64.c ${CMAKE_CURRENT_SOURCE_DIR}/wslua_internals.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_nstime.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_pinfo.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_pref.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_proto.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_proto_expert.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_proto_field.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_struct.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_tree.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_tvb.c + ${CMAKE_CURRENT_SOURCE_DIR}/wslua_util.c ) set (WSLUA_MODULES ${WSLUA_MODULES} PARENT_SCOPE) diff --git a/epan/wslua/Makefile.am b/epan/wslua/Makefile.am index 9dd866f33f..fcc15450d2 100644 --- a/epan/wslua/Makefile.am +++ b/epan/wslua/Makefile.am @@ -27,25 +27,37 @@ AM_CPPFLAGS = -I$(top_srcdir) @LUA_CFLAGS@ noinst_LTLIBRARIES = libwslua.la -wslua_modules = \ - lua_bitop.c \ - lrexlib.c \ - lrexlib_glib.c \ - lrexlib_glib_f.c \ - wslua_tvb.c \ - wslua_proto.c \ - wslua_int64.c \ - wslua_tree.c \ - wslua_pinfo.c \ - wslua_listener.c \ - wslua_gui.c \ - wslua_dir.c \ - wslua_util.c \ - wslua_field.c \ - wslua_file.c \ - wslua_struct.c \ - wslua_dumper.c \ - wslua_internals.c +wslua_modules = \ + lrexlib.c \ + lrexlib_glib.c \ + lrexlib_glib_f.c \ + lua_bitop.c \ + wslua_address.c \ + wslua_byte_array.c \ + wslua_capture_info.c \ + wslua_column.c \ + wslua_dir.c \ + wslua_dissector.c \ + wslua_dumper.c \ + wslua_field.c \ + wslua_file.c \ + wslua_file_common.c \ + wslua_file_handler.c \ + wslua_frame_info.c \ + wslua_gui.c \ + wslua_int64.c \ + wslua_internals.c \ + wslua_listener.c \ + wslua_nstime.c \ + wslua_pinfo.c \ + wslua_pref.c \ + wslua_proto.c \ + wslua_proto_expert.c \ + wslua_proto_field.c \ + wslua_struct.c \ + wslua_tree.c \ + wslua_tvb.c \ + wslua_util.c libwslua_la_SOURCES = \ $(wslua_modules) \ @@ -86,7 +98,10 @@ MAINTAINERCLEANFILES = \ EXTRA_DIST = \ declare_wslua.h \ lua_bitop.h \ - lrexlib.h \ + lrexlib.h \ + lrexlib_algo.h \ + wslua_file_common.h \ + wslua_pinfo_common.h \ lrexlib_algo.h \ register_wslua.c \ taps \ diff --git a/epan/wslua/Makefile.nmake b/epan/wslua/Makefile.nmake index 9a8e9e344a..9ad3ac5c88 100644 --- a/epan/wslua/Makefile.nmake +++ b/epan/wslua/Makefile.nmake @@ -13,47 +13,71 @@ CFLAGS=$(WARNINGS_ARE_ERRORS) $(STANDARD_CFLAGS) \ $(CC) $(CFLAGS) -Fd.\ -c $< MODULES = \ - lua_bitop.c \ lrexlib.c \ lrexlib_glib.c \ lrexlib_glib_f.c \ - wslua_tvb.c \ - wslua_proto.c \ - wslua_int64.c \ - wslua_tree.c \ - wslua_pinfo.c \ - wslua_listener.c \ - wslua_gui.c \ + lua_bitop.c \ + wslua_address.c \ + wslua_byte_array.c \ + wslua_capture_info.c \ + wslua_column.c \ wslua_dir.c \ - wslua_util.c \ + wslua_dissector.c \ + wslua_dumper.c \ wslua_field.c \ wslua_file.c \ + wslua_file_common.c \ + wslua_file_handler.c \ + wslua_frame_info.c \ + wslua_gui.c \ + wslua_int64.c \ + wslua_internals.c \ + wslua_listener.c \ + wslua_nstime.c \ + wslua_pinfo.c \ + wslua_pref.c \ + wslua_proto.c \ + wslua_proto_expert.c \ + wslua_proto_field.c \ wslua_struct.c \ - wslua_dumper.c \ - wslua_internals.c + wslua_tree.c \ + wslua_tvb.c \ + wslua_util.c OBJECTS= \ init_wslua.obj \ register_wslua.obj \ taps_wslua.obj \ - lua_bitop.obj \ lrexlib.obj \ lrexlib_glib.obj \ lrexlib_glib_f.obj \ - wslua_tvb.obj \ - wslua_proto.obj \ - wslua_int64.obj \ - wslua_tree.obj \ - wslua_pinfo.obj \ - wslua_listener.obj \ - wslua_gui.obj \ + lua_bitop.obj \ + wslua_address.obj \ + wslua_byte_array.obj \ + wslua_capture_info.obj \ + wslua_column.obj \ wslua_dir.obj \ - wslua_util.obj \ + wslua_dissector.obj \ + wslua_dumper.obj \ wslua_field.obj \ wslua_file.obj \ + wslua_file_common.obj \ + wslua_file_handler.obj \ + wslua_frame_info.obj \ + wslua_gui.obj \ + wslua_int64.obj \ + wslua_internals.obj \ + wslua_listener.obj \ + wslua_nstime.obj \ + wslua_pinfo.obj \ + wslua_pref.obj \ + wslua_proto.obj \ + wslua_proto_expert.obj \ + wslua_proto_field.obj \ wslua_struct.obj \ - wslua_dumper.obj \ - wslua_internals.obj + wslua_tree.obj \ + wslua_tvb.obj \ + wslua_util.obj wslua.lib : $(OBJECTS) init.lua link /lib /NODEFAULTLIB /out:wslua.lib $(OBJECTS) diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h index 18ea9d3019..268d498dd2 100644 --- a/epan/wslua/wslua.h +++ b/epan/wslua/wslua.h @@ -696,6 +696,7 @@ extern void UInt64_pack(lua_State* L, luaL_Buffer *b, gint idx, gboolean asLittl extern int UInt64_unpack(lua_State* L, const gchar *buff, gboolean asLittleEndian); extern Tvb* push_Tvb(lua_State* L, tvbuff_t* tvb); +extern int push_wsluaTvb(lua_State* L, Tvb t); extern gboolean push_TvbRange(lua_State* L, tvbuff_t* tvb, int offset, int len); extern void clear_outstanding_Tvb(void); extern void clear_outstanding_TvbRange(void); diff --git a/epan/wslua/wslua_address.c b/epan/wslua/wslua_address.c new file mode 100644 index 0000000000..eff8ddb488 --- /dev/null +++ b/epan/wslua/wslua_address.c @@ -0,0 +1,275 @@ +/* + * wslua_address.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + +#include <epan/addr_resolv.h> + +/* WSLUA_CONTINUE_MODULE Pinfo */ + + +WSLUA_CLASS_DEFINE(Address,FAIL_ON_NULL("Address"),NOP); /* Represents an address. */ + +WSLUA_CONSTRUCTOR Address_ip(lua_State* L) { + /* Creates an Address Object representing an IP address. */ + +#define WSLUA_ARG_Address_ip_HOSTNAME 1 /* The address or name of the IP host. */ + Address addr = (Address)g_malloc(sizeof(address)); + guint32* ip_addr = (guint32 *)g_malloc(sizeof(guint32)); + const gchar* name = luaL_checkstring(L,WSLUA_ARG_Address_ip_HOSTNAME); + + if (! get_host_ipaddr(name, (guint32*)ip_addr)) { + *ip_addr = 0; + } + + SET_ADDRESS(addr, AT_IPv4, 4, ip_addr); + pushAddress(L,addr); + WSLUA_RETURN(1); /* The Address object. */ +} + +#if 0 +/* TODO */ +static int Address_ipv6(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_ss7(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_eth(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_sna(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_atalk(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_vines(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_osi(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_arcnet(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_fc(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_string(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_eui64(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_uri(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +static int Address_tipc(lua_State* L) { + Address addr = g_malloc(sizeof(address)); + + SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); + + pushAddress(L,addr); + return 1; +} +#endif + +WSLUA_METHODS Address_methods[] = { + WSLUA_CLASS_FNREG(Address,ip), + WSLUA_CLASS_FNREG_ALIAS(Address,ipv4,ip), +#if 0 + WSLUA_CLASS_FNREG(Address,ipv6), + WSLUA_CLASS_FNREG_ALIAS(Address,ss7pc,ss7), + WSLUA_CLASS_FNREG(Address,eth), + WSLUA_CLASS_FNREG(Address,sna}, + WSLUA_CLASS_FNREG(Address,atalk), + WSLUA_CLASS_FNREG(Address,vines), + WSLUA_CLASS_FNREG(Address,osi), + WSLUA_CLASS_FNREG(Address,arcnet), + WSLUA_CLASS_FNREG(Address,fc), + WSLUA_CLASS_FNREG(Address,string), + WSLUA_CLASS_FNREG(Address,eui64), + WSLUA_CLASS_FNREG(Address,uri), + WSLUA_CLASS_FNREG(Address,tipc), +#endif + { NULL, NULL } +}; + +WSLUA_METAMETHOD Address__tostring(lua_State* L) { + Address addr = checkAddress(L,1); + const gchar *str = address_to_display(NULL, addr); + + lua_pushstring(L, str); + + wmem_free(NULL, (void*) str); + + WSLUA_RETURN(1); /* The string representing the address. */ +} + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int Address__gc(lua_State* L) { + Address addr = toAddress(L,1); + + if (addr) { + g_free((void*)(addr->data)); + g_free((void*)(addr)); + } + + return 0; +} + +WSLUA_METAMETHOD Address__eq(lua_State* L) { /* Compares two Addresses. */ + Address addr1 = checkAddress(L,1); + Address addr2 = checkAddress(L,2); + gboolean result = FALSE; + + if (ADDRESSES_EQUAL(addr1, addr2)) + result = TRUE; + + lua_pushboolean(L,result); + + return 1; +} + +WSLUA_METAMETHOD Address__le(lua_State* L) { /* Compares two Addresses. */ + Address addr1 = checkAddress(L,1); + Address addr2 = checkAddress(L,2); + gboolean result = FALSE; + + if (CMP_ADDRESS(addr1, addr2) <= 0) + result = TRUE; + + lua_pushboolean(L,result); + + return 1; +} + +WSLUA_METAMETHOD Address__lt(lua_State* L) { /* Compares two Addresses. */ + Address addr1 = checkAddress(L,1); + Address addr2 = checkAddress(L,2); + gboolean result = FALSE; + + if (CMP_ADDRESS(addr1, addr2) < 0) + result = TRUE; + + lua_pushboolean(L,result); + + return 1; +} + +WSLUA_META Address_meta[] = { + WSLUA_CLASS_MTREG(Address,tostring), + WSLUA_CLASS_MTREG(Address,eq), + WSLUA_CLASS_MTREG(Address,le), + WSLUA_CLASS_MTREG(Address,lt), + { NULL, NULL } +}; + + +int Address_register(lua_State *L) { + WSLUA_REGISTER_CLASS(Address); + 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: + */ diff --git a/epan/wslua/wslua_byte_array.c b/epan/wslua/wslua_byte_array.c new file mode 100644 index 0000000000..53843f9407 --- /dev/null +++ b/epan/wslua/wslua_byte_array.c @@ -0,0 +1,410 @@ +/* + * wslua_byte_array.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" +#include "wsutil/base64.h" + + +/* WSLUA_CONTINUE_MODULE Tvb */ + + +WSLUA_CLASS_DEFINE(ByteArray,FAIL_ON_NULL("ByteArray"),NOP); + +WSLUA_CONSTRUCTOR ByteArray_new(lua_State* L) { + /* Creates a `ByteArray` object. + + Starting in version 1.11.3, if the second argument is a boolean `true`, + then the first argyument is treated as a raw Lua string of bytes to use, + instead of a hexadecimal string. + */ +#define WSLUA_OPTARG_ByteArray_new_HEXBYTES 1 /* A string consisting of hexadecimal bytes like "00 B1 A2" or "1a2b3c4d". */ +#define WSLUA_OPTARG_ByteArray_new_SEPARATOR 2 /* A string separator between hex bytes/words (default=" "), + or if the boolean value `true` is used, then the first argument + is treated as raw binary data */ + GByteArray* ba = g_byte_array_new(); + const gchar* s; + size_t len = 0; + const gchar* sep = " "; + gboolean ishex = TRUE; + + if (lua_gettop(L) >= 1) { + s = luaL_checklstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES,&len); + + if (lua_gettop(L) >= 2) { + if (lua_type(L,2) == LUA_TBOOLEAN && lua_toboolean(L,2)) { + ishex = FALSE; + } else { + sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_new_SEPARATOR," "); + } + } + + if (ishex) { + wslua_hex2bin(L, s, (guint)len, sep); /* this pushes a new string on top of stack */ + s = luaL_checklstring(L, -1, &len); /* get the new binary string */ + g_byte_array_append(ba,s,(guint)len); /* copy it into ByteArray */ + lua_pop(L,1); /* pop the newly created string */ + } else { + g_byte_array_append(ba,s,(guint)len); + } + } + + pushByteArray(L,ba); + + WSLUA_RETURN(1); /* The new ByteArray object. */ +} + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int ByteArray__gc(lua_State* L) { + ByteArray ba = toByteArray(L,1); + + if (!ba) return 0; + + g_byte_array_free(ba,TRUE); + return 0; +} + +WSLUA_METAMETHOD ByteArray__concat(lua_State* L) { + /* Concatenate two `ByteArrays`. */ +#define WSLUA_ARG_ByteArray__cat_FIRST 1 /* First array. */ +#define WSLUA_ARG_ByteArray__cat_SECOND 2 /* Second array. */ + + ByteArray ba1 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_FIRST); + ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_SECOND); + ByteArray ba; + + ba = g_byte_array_new(); + g_byte_array_append(ba,ba1->data,ba1->len); + g_byte_array_append(ba,ba2->data,ba2->len); + + pushByteArray(L,ba); + WSLUA_RETURN(1); /* The new composite `ByteArray`. */ +} + +WSLUA_METAMETHOD ByteArray__eq(lua_State* L) { + /* Compares two ByteArray values. + + @since 1.11.4 + */ +#define WSLUA_ARG_ByteArray__eq_FIRST 1 /* First array. */ +#define WSLUA_ARG_ByteArray__eq_SECOND 2 /* Second array. */ + ByteArray ba1 = checkByteArray(L,WSLUA_ARG_ByteArray__eq_FIRST); + ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__eq_SECOND); + gboolean result = FALSE; + + if (ba1->len == ba2->len) { + if (memcmp(ba1->data, ba2->data, ba1->len) == 0) + result = TRUE; + } + + lua_pushboolean(L,result); + + return 1; +} + +WSLUA_METHOD ByteArray_prepend(lua_State* L) { + /* Prepend a `ByteArray` to this `ByteArray`. */ +#define WSLUA_ARG_ByteArray_prepend_PREPENDED 2 /* `ByteArray` to be prepended. */ + ByteArray ba = checkByteArray(L,1); + ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_prepend_PREPENDED); + + g_byte_array_prepend(ba,ba2->data,ba2->len); + + return 0; +} + +WSLUA_METHOD ByteArray_append(lua_State* L) { + /* Append a `ByteArray` to this `ByteArray`. */ +#define WSLUA_ARG_ByteArray_append_APPENDED 2 /* `ByteArray` to be appended. */ + ByteArray ba = checkByteArray(L,1); + ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_append_APPENDED); + + g_byte_array_append(ba,ba2->data,ba2->len); + + return 0; +} + +WSLUA_METHOD ByteArray_set_size(lua_State* L) { + /* Sets the size of a `ByteArray`, either truncating it or filling it with zeros. */ +#define WSLUA_ARG_ByteArray_set_size_SIZE 2 /* New size of the array. */ + + ByteArray ba = checkByteArray(L,1); + int siz = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_size_SIZE); + guint8* padding; + + if (siz < 0) { + WSLUA_ERROR(ByteArray_set_size,"ByteArray size must be non-negative"); + return 0; + } + + if (ba->len >= (guint)siz) { /* truncate */ + g_byte_array_set_size(ba,siz); + } else { /* fill */ + padding = (guint8 *)g_malloc0(sizeof(guint8)*(siz - ba->len)); + g_byte_array_append(ba,padding,siz - ba->len); + g_free(padding); + } + return 0; +} + +WSLUA_METHOD ByteArray_set_index(lua_State* L) { + /* Sets the value of an index of a `ByteArray`. */ +#define WSLUA_ARG_ByteArray_set_index_INDEX 2 /* The position of the byte to be set. */ +#define WSLUA_ARG_ByteArray_set_index_VALUE 3 /* The char value to set [0-255]. */ + ByteArray ba = checkByteArray(L,1); + int idx = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_INDEX); + int v = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_VALUE); + + if (idx == 0 && ! g_str_equal(luaL_optstring(L,2,""),"0") ) { + luaL_argerror(L,2,"bad index"); + return 0; + } + + if (idx < 0 || (guint)idx >= ba->len) { + luaL_argerror(L,2,"index out of range"); + return 0; + } + + if (v < 0 || v > 255) { + luaL_argerror(L,3,"Byte out of range"); + return 0; + } + + ba->data[idx] = (guint8)v; + + return 0; +} + + +WSLUA_METHOD ByteArray_get_index(lua_State* L) { + /* Get the value of a byte in a `ByteArray`. */ +#define WSLUA_ARG_ByteArray_get_index_INDEX 2 /* The position of the byte to get. */ + ByteArray ba = checkByteArray(L,1); + int idx = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_get_index_INDEX); + + if (idx == 0 && ! g_str_equal(luaL_optstring(L,2,""),"0") ) { + luaL_argerror(L,2,"bad index"); + return 0; + } + + if (idx < 0 || (guint)idx >= ba->len) { + luaL_argerror(L,2,"index out of range"); + return 0; + } + lua_pushnumber(L,ba->data[idx]); + + WSLUA_RETURN(1); /* The value [0-255] of the byte. */ +} + +WSLUA_METHOD ByteArray_len(lua_State* L) { + /* Obtain the length of a `ByteArray`. */ + ByteArray ba = checkByteArray(L,1); + + lua_pushnumber(L,(lua_Number)ba->len); + + WSLUA_RETURN(1); /* The length of the `ByteArray`. */ +} + +WSLUA_METHOD ByteArray_subset(lua_State* L) { + /* Obtain a segment of a `ByteArray`, as a new `ByteArray`. */ +#define WSLUA_ARG_ByteArray_set_index_OFFSET 2 /* The position of the first byte (0=first). */ +#define WSLUA_ARG_ByteArray_set_index_LENGTH 3 /* The length of the segment. */ + ByteArray ba = checkByteArray(L,1); + int offset = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_OFFSET); + int len = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_LENGTH); + ByteArray sub; + + if ((offset + len) > (int)ba->len || offset < 0 || len < 1) { + luaL_error(L,"Out Of Bounds"); + return 0; + } + + sub = g_byte_array_new(); + g_byte_array_append(sub,ba->data + offset,len); + + pushByteArray(L,sub); + + WSLUA_RETURN(1); /* A `ByteArray` containing the requested segment. */ +} + +WSLUA_METHOD ByteArray_base64_decode(lua_State* L) { + /* Obtain a base64 decoded `ByteArray`. + + @since 1.11.3 + */ + ByteArray ba = checkByteArray(L,1); + ByteArray ba2; + gchar *data; + size_t len; + + ba2 = g_byte_array_new(); + data = (gchar*)g_malloc (ba->len + 1); + memcpy(data, ba->data, ba->len); + data[ba->len] = '\0'; + + len = ws_base64_decode_inplace(data); + g_byte_array_append(ba2,data,(int)len); + g_free(data); + + pushByteArray(L,ba2); + WSLUA_RETURN(1); /* The created `ByteArray`. */ +} + +WSLUA_METHOD ByteArray_raw(lua_State* L) { + /* Obtain a Lua string of the binary bytes in a `ByteArray`. + + @since 1.11.3 + */ +#define WSLUA_OPTARG_ByteArray_raw_OFFSET 2 /* The position of the first byte (default=0/first). */ +#define WSLUA_OPTARG_ByteArray_raw_LENGTH 3 /* The length of the segment to get (default=all). */ + ByteArray ba = checkByteArray(L,1); + guint offset = (guint) luaL_optinteger(L,WSLUA_OPTARG_ByteArray_raw_OFFSET,0); + int len; + + if (!ba) return 0; + if (offset > ba->len) { + WSLUA_OPTARG_ERROR(ByteArray_raw,OFFSET,"offset beyond end of byte array"); + return 0; + } + + len = (int) luaL_optinteger(L,WSLUA_OPTARG_ByteArray_raw_LENGTH, ba->len - offset); + if ((len < 0) || ((guint)len > (ba->len - offset))) + len = ba->len - offset; + + lua_pushlstring(L, &(ba->data[offset]), len); + + WSLUA_RETURN(1); /* A Lua string of the binary bytes in the ByteArray. */ +} + +WSLUA_METHOD ByteArray_tohex(lua_State* L) { + /* Obtain a Lua string of the bytes in a `ByteArray` as hex-ascii, with given separator + + @since 1.11.3 + */ +#define WSLUA_OPTARG_ByteArray_tohex_LOWERCASE 2 /* True to use lower-case hex characters (default=false). */ +#define WSLUA_OPTARG_ByteArray_tohex_SEPARATOR 3 /* A string separator to insert between hex bytes (default=nil). */ + ByteArray ba = checkByteArray(L,1); + gboolean lowercase = FALSE; + const gchar* sep = NULL; + + if (!ba) return 0; + + lowercase = wslua_optbool(L,WSLUA_OPTARG_ByteArray_tohex_LOWERCASE,FALSE); + sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_tohex_SEPARATOR,NULL); + + wslua_bin2hex(L, ba->data, ba->len, lowercase, sep); + + WSLUA_RETURN(1); /* A hex-ascii string representation of the `ByteArray`. */ +} + +WSLUA_METAMETHOD ByteArray__tostring(lua_State* L) { + /* Obtain a Lua string containing the bytes in a `ByteArray` so that it can be used in + display filters (e.g. "01FE456789AB"). */ + ByteArray ba = checkByteArray(L,1); + + if (!ba) return 0; + + wslua_bin2hex(L, ba->data, ba->len, FALSE, NULL); + + WSLUA_RETURN(1); /* A hex-ascii string representation of the `ByteArray`. */ +} + +/* + * ByteArray_tvb(name) + */ +WSLUA_CONSTRUCTOR ByteArray_tvb (lua_State *L) { + /* Creates a new `Tvb` from a `ByteArray` (it gets added to the current frame too). */ +#define WSLUA_ARG_ByteArray_tvb_NAME 2 /* The name to be given to the new data-source. */ + ByteArray ba = checkByteArray(L,1); + const gchar* name = luaL_optstring(L,WSLUA_ARG_ByteArray_tvb_NAME,"Unnamed") ; + guint8* data; + Tvb tvb; + + if (!lua_tvb) { + luaL_error(L,"Tvbs can only be created and used in dissectors"); + return 0; + } + + data = (guint8 *)g_memdup(ba->data, ba->len); + + tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); + tvb->ws_tvb = tvb_new_real_data(data, ba->len,ba->len); + tvb->expired = FALSE; + tvb->need_free = TRUE; + tvb_set_free_cb(tvb->ws_tvb, g_free); + + add_new_data_source(lua_pinfo, tvb->ws_tvb, name); + push_wsluaTvb(L,tvb); + WSLUA_RETURN(1); /* The created `Tvb`. */ +} + + +WSLUA_METHODS ByteArray_methods[] = { + WSLUA_CLASS_FNREG(ByteArray,new), + WSLUA_CLASS_FNREG(ByteArray,len), + WSLUA_CLASS_FNREG(ByteArray,prepend), + WSLUA_CLASS_FNREG(ByteArray,append), + WSLUA_CLASS_FNREG(ByteArray,subset), + WSLUA_CLASS_FNREG(ByteArray,set_size), + WSLUA_CLASS_FNREG(ByteArray,tvb), + WSLUA_CLASS_FNREG(ByteArray,base64_decode), + WSLUA_CLASS_FNREG(ByteArray,get_index), + WSLUA_CLASS_FNREG(ByteArray,set_index), + WSLUA_CLASS_FNREG(ByteArray,tohex), + WSLUA_CLASS_FNREG(ByteArray,raw), + { NULL, NULL } +}; + +WSLUA_META ByteArray_meta[] = { + WSLUA_CLASS_MTREG(ByteArray,tostring), + WSLUA_CLASS_MTREG(ByteArray,concat), + WSLUA_CLASS_MTREG(ByteArray,eq), + {"__call",ByteArray_subset}, + { NULL, NULL } +}; + +int ByteArray_register(lua_State* L) { + WSLUA_REGISTER_CLASS(ByteArray); + 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: + */ diff --git a/epan/wslua/wslua_capture_info.c b/epan/wslua/wslua_capture_info.c new file mode 100644 index 0000000000..eb83a94089 --- /dev/null +++ b/epan/wslua/wslua_capture_info.c @@ -0,0 +1,513 @@ +/* + * wslua_capture_info.c + * + * Wireshark's interface to the Lua Programming Language + * for capture file data and meta-data. + * + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "wslua_file_common.h" + +#include <epan/addr_resolv.h> + + +/* WSLUA_CONTINUE_MODULE File */ + + +WSLUA_CLASS_DEFINE(CaptureInfo,FAIL_ON_NULL_MEMBER_OR_EXPIRED("CaptureInfo",wth),NOP); +/* + A `CaptureInfo` object, passed into Lua as an argument by `FileHandler` callback + function `read_open()`, `read()`, `seek_read()`, `seq_read_close()`, and `read_close()`. + This object represents capture file data and meta-data (data about the + capture file) being read into Wireshark/Tshark. + + This object's fields can be written-to by Lua during the read-based function callbacks. + In other words, when the Lua plugin's `FileHandler.read_open()` function is invoked, a + `CaptureInfo` object will be passed in as one of the arguments, and its fields + should be written to by your Lua code to tell Wireshark about the capture. + + @since 1.11.3 + */ + +CaptureInfo* push_CaptureInfo(lua_State* L, wtap *wth, const gboolean first_time) { + CaptureInfo f = (CaptureInfo) g_malloc0(sizeof(struct _wslua_captureinfo)); + f->wth = wth; + f->wdh = NULL; + f->expired = FALSE; + + if (first_time) { + /* XXX: need to do this? */ + wth->file_encap = WTAP_ENCAP_UNKNOWN; + wth->file_tsprec = WTAP_TSPREC_UNKNOWN; + wth->snapshot_length = 0; + } + + return pushCaptureInfo(L,f); +} + +WSLUA_METAMETHOD CaptureInfo__tostring(lua_State* L) { + /* Generates a string of debug info for the CaptureInfo */ + CaptureInfo fi = toCaptureInfo(L,1); + + if (!fi || !fi->wth) { + lua_pushstring(L,"CaptureInfo pointer is NULL!"); + } else { + wtap *wth = fi->wth; + lua_pushfstring(L, "CaptureInfo: file_type_subtype=%d, snapshot_length=%d, pkt_encap=%d, file_tsprec='%s'", + wth->file_type_subtype, wth->snapshot_length, wth->phdr.pkt_encap, wth->file_tsprec); + } + + WSLUA_RETURN(1); /* String of debug information. */ +} + + +static int CaptureInfo__gc(lua_State* L _U_) { + CaptureInfo fc = toCaptureInfo(L,1); + if (fc) + g_free(fc); + return 0; +} + +/* WSLUA_ATTRIBUTE CaptureInfo_encap RW The packet encapsulation type for the whole file. + + See `wtap_encaps` in `init.lua` for available types. Set to `wtap_encaps.PER_PACKET` if packets can + have different types, then later set `FrameInfo.encap` for each packet during `read()`/`seek_read()`. + */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfo,encap,wth->file_encap); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,encap,wth->file_encap,int); + +/* WSLUA_ATTRIBUTE CaptureInfo_time_precision RW The precision of the packet timestamps in the file. + + See `wtap_file_tsprec` in `init.lua` for available precisions. + */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfo,time_precision,wth->file_tsprec); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,time_precision,wth->file_tsprec,int); + +/* WSLUA_ATTRIBUTE CaptureInfo_snapshot_length RW The maximum packet length that could be recorded. + + Setting it to `0` means unknown. Wireshark cannot handle anything bigger than 65535 bytes. + */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfo,snapshot_length,wth->snapshot_length); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,snapshot_length,wth->snapshot_length,guint); + +/* WSLUA_ATTRIBUTE CaptureInfo_comment RW A string comment for the whole capture file, + or nil if there is no `comment`. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,comment,wth->shb_hdr.opt_comment); +WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,comment,wth->shb_hdr.opt_comment,TRUE); + +/* WSLUA_ATTRIBUTE CaptureInfo_hardware RW A string containing the description of + the hardware used to create the capture, or nil if there is no `hardware` string. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,hardware,wth->shb_hdr.shb_hardware); +WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,hardware,wth->shb_hdr.shb_hardware,TRUE); + +/* WSLUA_ATTRIBUTE CaptureInfo_os RW A string containing the name of + the operating system used to create the capture, or nil if there is no `os` string. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,os,wth->shb_hdr.shb_os); +WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,os,wth->shb_hdr.shb_os,TRUE); + +/* WSLUA_ATTRIBUTE CaptureInfo_user_app RW A string containing the name of + the application used to create the capture, or nil if there is no `user_app` string. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,user_app,wth->shb_hdr.shb_user_appl); +WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,user_app,wth->shb_hdr.shb_user_appl,TRUE); + +/* WSLUA_ATTRIBUTE CaptureInfo_hosts WO Sets resolved ip-to-hostname information. + + The value set must be a Lua table of two key-ed names: `ipv4_addresses` and `ipv6_addresses`. + The value of each of these names are themselves array tables, of key-ed tables, such that the inner table has a key + `addr` set to the raw 4-byte or 16-byte IP address Lua string and a `name` set to the resolved name. + + For example, if the capture file identifies one resolved IPv4 address of 1.2.3.4 to `foo.com`, then you must set + `CaptureInfo.hosts` to a table of: + @code { ipv4_addresses = { { addr = "\01\02\03\04", name = "foo.com" } } } @endcode + + Note that either the `ipv4_addresses` or the `ipv6_addresses` table, or both, may be empty or nil. + */ +static int CaptureInfo_set_hosts(lua_State* L) { + CaptureInfo fi = checkCaptureInfo(L,1); + wtap *wth = fi->wth; + const char *addr = NULL; + const char *name = NULL; + size_t addr_len = 0; + size_t name_len = 0; + guint32 v4_addr = 0; + struct e_in6_addr v6_addr = { {0} }; + + if (!wth->add_new_ipv4 || !wth->add_new_ipv6) { + return luaL_error(L, "CaptureInfo wtap has no IPv4 or IPv6 name resolution"); + } + + if (!lua_istable(L,-1)) { + return luaL_error(L, "CaptureInfo.host must be set to a table"); + } + + /* get the ipv4_addresses table */ + lua_getfield(L, -1, "ipv4_addresses"); + + if (lua_istable(L,-1)) { + /* now walk the table */ + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + /* 'key' (at index -2) and 'value' (at index -1) */ + if (!lua_istable(L,-1)) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv4_addresses table does not contain a table"); + } + + lua_getfield(L, -1, "addr"); + if (!lua_isstring(L,-1)) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv4_addresses table's table does not contain an 'addr' field"); + } + addr = luaL_checklstring(L,-1,&addr_len); + if (addr_len != 4) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv4_addresses 'addr' value is not 4 bytes long"); + } + memcpy(&v4_addr, addr, 4); + + lua_getfield(L, -1, "name"); + if (!lua_isstring(L,-1)) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv4_addresses table's table does not contain an 'addr' field"); + } + name = luaL_checklstring(L,-1,&name_len); + + wth->add_new_ipv4(v4_addr, name); + + /* removes 'value'; keeps 'key' for next iteration */ + lua_pop(L, 1); + } + } + + /* wasn't a table, or it was and we walked it; either way pop it */ + lua_pop(L,1); + + + /* get the ipv6_addresses table */ + lua_getfield(L, -1, "ip6_addresses"); + + if (lua_istable(L,-1)) { + /* now walk the table */ + lua_pushnil(L); /* first key */ + while (lua_next(L, -2) != 0) { + /* 'key' (at index -2) and 'value' (at index -1) */ + if (!lua_istable(L,-1)) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv6_addresses table does not contain a table"); + } + + lua_getfield(L, -1, "addr"); + if (!lua_isstring(L,-1)) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv6_addresses table's table does not contain an 'addr' field"); + } + addr = luaL_checklstring(L,-1,&addr_len); + if (addr_len != 16) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv6_addresses 'addr' value is not 16 bytes long"); + } + memcpy(&v6_addr, addr, 16); + + lua_getfield(L, -1, "name"); + if (!lua_isstring(L,-1)) { + lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ + return luaL_error(L, "CaptureInfo.host ipv6_addresses table's table does not contain an 'addr' field"); + } + name = luaL_checklstring(L,-1,&name_len); + + wth->add_new_ipv6((const void *)(&v6_addr), name); + + /* removes 'value'; keeps 'key' for next iteration */ + lua_pop(L, 1); + } + } + + /* wasn't a table, or it was and we walked it; either way pop it */ + lua_pop(L,1); + + return 0; +} + + +/* WSLUA_ATTRIBUTE CaptureInfo_private_table RW A private Lua value unique to this file. + + The `private_table` is a field you set/get with your own Lua table. + This is provided so that a Lua script can save per-file reading/writing + state, because multiple files can be opened and read at the same time. + + For example, if the user issued a reload-file command, or Lua called the + `reload()` function, then the current capture file is still open while a new one + is being opened, and thus Wireshark will invoke `read_open()` while the previous + capture file has not caused `read_close()` to be called; and if the `read_open()` + succeeds then `read_close()` will be called right after that for the previous + file, rather than the one just opened. Thus the Lua script can use this + `private_table` to store a table of values specific to each file, by setting + this `private_table` in the `read_open()` function, which it can then later get back + inside its `read()`, `seek_read()`, and `read_close()` functions. +*/ +static int CaptureInfo_get_private_table(lua_State* L) { + CaptureInfo fi = checkCaptureInfo(L,1); + return get_wth_priv_table_ref(L, fi->wth); +} + +static int CaptureInfo_set_private_table(lua_State* L) { + CaptureInfo fi = checkCaptureInfo(L,1); + return set_wth_priv_table_ref(L, fi->wth); +} + +WSLUA_ATTRIBUTES CaptureInfo_attributes[] = { + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,encap), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,time_precision), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,snapshot_length), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,comment), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,hardware), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,os), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,user_app), + WSLUA_ATTRIBUTE_WOREG(CaptureInfo,hosts), + WSLUA_ATTRIBUTE_RWREG(CaptureInfo,private_table), + { NULL, NULL, NULL } +}; + +WSLUA_META CaptureInfo_meta[] = { + WSLUA_CLASS_MTREG(CaptureInfo,tostring), + { NULL, NULL } +}; + +int CaptureInfo_register(lua_State* L) { + WSLUA_REGISTER_META(CaptureInfo); + WSLUA_REGISTER_ATTRIBUTES(CaptureInfo); + return 0; +} + + +WSLUA_CLASS_DEFINE(CaptureInfoConst,FAIL_ON_NULL_MEMBER_OR_EXPIRED("CaptureInfoConst",wdh),NOP); +/* + A `CaptureInfoConst` object, passed into Lua as an argument to the `FileHandler` callback + function `write_open()`. + + This object represents capture file data and meta-data (data about the + capture file) for the current capture in Wireshark/Tshark. + + This object's fields are read-from when used by `write_open` function callback. + In other words, when the Lua plugin's FileHandler `write_open` function is invoked, a + `CaptureInfoConst` object will be passed in as one of the arguments, and its fields + should be read from by your Lua code to get data about the capture that needs to be written. + + @since 1.11.3 + */ + +CaptureInfoConst* push_CaptureInfoConst(lua_State* L, wtap_dumper *wdh) { + CaptureInfoConst f = (CaptureInfoConst) g_malloc0(sizeof(struct _wslua_captureinfo)); + f->wth = NULL; + f->wdh = wdh; + f->expired = FALSE; + return pushCaptureInfoConst(L,f); +} + +WSLUA_METAMETHOD CaptureInfoConst__tostring(lua_State* L) { + /* Generates a string of debug info for the CaptureInfoConst */ + CaptureInfoConst fi = toCaptureInfoConst(L,1); + + if (!fi || !fi->wdh) { + lua_pushstring(L,"CaptureInfoConst pointer is NULL!"); + } else { + wtap_dumper *wdh = fi->wdh; + lua_pushfstring(L, "CaptureInfoConst: file_type_subtype=%d, snaplen=%d, encap=%d, compressed=%d, file_tsprec='%s'", + wdh->file_type_subtype, wdh->snaplen, wdh->encap, wdh->compressed, wdh->tsprecision); + } + + WSLUA_RETURN(1); /* String of debug information. */ +} + +/* WSLUA_ATTRIBUTE CaptureInfoConst_type RO The file type. */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfoConst,type,wdh->file_type_subtype); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_snapshot_length RO The maximum packet length that is actually recorded (vs. the original + length of any given packet on-the-wire). A value of `0` means the snapshot length is unknown or there is no one + such length for the whole file. */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfoConst,snapshot_length,wdh->snaplen); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_encap RO The packet encapsulation type for the whole file. + + See `wtap_encaps` in init.lua for available types. It is set to `wtap_encaps.PER_PACKET` if packets can + have different types, in which case each Frame identifies its type, in `FrameInfo.packet_encap`. */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfoConst,encap,wdh->encap); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_comment RW A comment for the whole capture file, if the + `wtap_presence_flags.COMMENTS` was set in the presence flags; nil if there is no comment. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,comment,wth->shb_hdr.opt_comment); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_hardware RO A string containing the description of + the hardware used to create the capture, or nil if there is no hardware string. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,hardware,wth->shb_hdr.shb_hardware); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_os RO A string containing the name of + the operating system used to create the capture, or nil if there is no os string. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,os,wth->shb_hdr.shb_os); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_user_app RO A string containing the name of + the application used to create the capture, or nil if there is no user_app string. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,user_app,wth->shb_hdr.shb_user_appl); + +/* WSLUA_ATTRIBUTE CaptureInfoConst_hosts RO A ip-to-hostname Lua table of two key-ed names: `ipv4_addresses` and `ipv6_addresses`. + The value of each of these names are themselves array tables, of key-ed tables, such that the inner table has a key + `addr` set to the raw 4-byte or 16-byte IP address Lua string and a `name` set to the resolved name. + + For example, if the current capture has one resolved IPv4 address of 1.2.3.4 to `foo.com`, then getting + `CaptureInfoConst.hosts` will get a table of: + @code { ipv4_addresses = { { addr = "\01\02\03\04", name = "foo.com" } }, ipv6_addresses = { } } @endcode + + Note that either the `ipv4_addresses` or the `ipv6_addresses` table, or both, may be empty, however they will not + be nil. */ +static int CaptureInfoConst_get_hosts(lua_State* L) { + CaptureInfoConst fi = checkCaptureInfoConst(L,1); + wtap_dumper *wdh = fi->wdh; + + /* create the main table to return */ + lua_newtable(L); + + /* create the ipv4_addresses table */ + lua_newtable(L); + + if (wdh->addrinfo_lists && wdh->addrinfo_lists->ipv4_addr_list) { + hashipv4_t *ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, 0); + int i, j; + for (i=1, j=1; ipv4_hash_list_entry != NULL; i++) { + if ((ipv4_hash_list_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) { + lua_pushnumber(L, j); /* push numeric index key starting at 1, so it will be an array table */ + /* create the entry table */ + lua_newtable(L); + /* addr is in network order already */ + lua_pushlstring(L, (char*)(&ipv4_hash_list_entry->ip), 4); + lua_setfield(L, -2, "addr"); + lua_pushstring(L, ipv4_hash_list_entry->name); + lua_setfield(L, -2, "name"); + /* now our ipv4_addresses table is at -3, key number is -2, and entry table at -2, so we're good */ + lua_settable(L, -3); + j++; + } + ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i); + } + } + + /* set the (possibly empty) ipv4_addresses table into the main table */ + lua_setfield(L, -2, "ipv4_addresses"); + + /* create the ipv6_addresses table */ + lua_newtable(L); + + if (wdh->addrinfo_lists && wdh->addrinfo_lists->ipv6_addr_list) { + hashipv6_t *ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, 0); + int i, j; + for (i=1, j=1; ipv6_hash_list_entry != NULL; i++) { + if ((ipv6_hash_list_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) { + lua_pushnumber(L, j); /* push numeric index key starting at 1, so it will be an array table */ + /* create the entry table */ + lua_newtable(L); + /* addr is in network order already */ + lua_pushlstring(L, (char*)(&ipv6_hash_list_entry->addr.bytes[0]), 16); + lua_setfield(L, -2, "addr"); + lua_pushstring(L, ipv6_hash_list_entry->name); + lua_setfield(L, -2, "name"); + /* now our ipv6_addresses table is at -3, key number is -2, and entry table at -2, so we're good */ + lua_settable(L, -3); + j++; + } + ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i); + } + } + + /* set the (possibly empty) ipv6_addresses table into the main table */ + lua_setfield(L, -2, "ip6_addresses"); + + /* return the main table */ + return 1; +} + +/* WSLUA_ATTRIBUTE CaptureInfoConst_private_table RW A private Lua value unique to this file. + + The `private_table` is a field you set/get with your own Lua table. + This is provided so that a Lua script can save per-file reading/writing + state, because multiple files can be opened and read at the same time. + + For example, if two Lua scripts issue a `Dumper:new_for_current()` call and the + current file happens to use your script's writer, then the Wireshark will invoke + `write_open()` while the previous capture file has not had `write_close()` called. + Thus the Lua script can use this `private_table` to store a table of values + specific to each file, by setting this `private_table` in the write_open() + function, which it can then later get back inside its `write()`, and `write_close()` + functions. +*/ +static int CaptureInfoConst_get_private_table(lua_State* L) { + CaptureInfoConst fi = checkCaptureInfoConst(L,1); + return get_wdh_priv_table_ref(L, fi->wdh); +} + +static int CaptureInfoConst_set_private_table(lua_State* L) { + CaptureInfoConst fi = checkCaptureInfoConst(L,1); + return set_wdh_priv_table_ref(L, fi->wdh); +} + +static int CaptureInfoConst__gc(lua_State* L _U_) { + CaptureInfoConst fi = toCaptureInfoConst(L,1); + if (fi) + g_free(fi); + return 0; +} + +WSLUA_ATTRIBUTES CaptureInfoConst_attributes[] = { + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,encap), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,type), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,snapshot_length), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,comment), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,hardware), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,os), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,user_app), + WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,hosts), + WSLUA_ATTRIBUTE_RWREG(CaptureInfoConst,private_table), + { NULL, NULL, NULL } +}; + +WSLUA_META CaptureInfoConst_meta[] = { + WSLUA_CLASS_MTREG(CaptureInfoConst,tostring), + { NULL, NULL } +}; + +int CaptureInfoConst_register(lua_State* L) { + WSLUA_REGISTER_META(CaptureInfoConst); + WSLUA_REGISTER_ATTRIBUTES(CaptureInfoConst); + 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: + */ diff --git a/epan/wslua/wslua_column.c b/epan/wslua/wslua_column.c new file mode 100644 index 0000000000..2a1e781c3d --- /dev/null +++ b/epan/wslua/wslua_column.c @@ -0,0 +1,393 @@ +/* + * wslua_column.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "wslua_pinfo_common.h" + + +/* WSLUA_CONTINUE_MODULE Pinfo */ + + +static GPtrArray* outstanding_Column = NULL; +static GPtrArray* outstanding_Columns = NULL; + +CLEAR_OUTSTANDING(Column,expired, TRUE) +CLEAR_OUTSTANDING(Columns,expired, TRUE) + +#define PUSH_COLUMN(L,c) {g_ptr_array_add(outstanding_Column,c);pushColumn(L,c);} + +void Push_Columns(lua_State *L, Columns c) +{ + g_ptr_array_add(outstanding_Columns, c); + pushColumns(L, c); +} + + +WSLUA_CLASS_DEFINE(Column,FAIL_ON_NULL("Column"),NOP); /* A Column in the packet list. */ + +struct col_names_t { + const gchar* name; + int id; +}; + +static const struct col_names_t colnames[] = { + {"number",COL_NUMBER}, + {"abs_time",COL_ABS_TIME}, + {"utc_time",COL_UTC_TIME}, + {"cls_time",COL_CLS_TIME}, + {"rel_time",COL_REL_TIME}, + {"date",COL_ABS_YMD_TIME}, + {"date_doy",COL_ABS_YDOY_TIME}, + {"utc_date",COL_UTC_YMD_TIME}, + {"utc_date_doy",COL_UTC_YDOY_TIME}, + {"delta_time",COL_DELTA_TIME}, + {"delta_time_displayed",COL_DELTA_TIME_DIS}, + {"src",COL_DEF_SRC}, + {"src_res",COL_RES_SRC}, + {"src_unres",COL_UNRES_SRC}, + {"dl_src",COL_DEF_DL_SRC}, + {"dl_src_res",COL_RES_DL_SRC}, + {"dl_src_unres",COL_UNRES_DL_SRC}, + {"net_src",COL_DEF_NET_SRC}, + {"net_src_res",COL_RES_NET_SRC}, + {"net_src_unres",COL_UNRES_NET_SRC}, + {"dst",COL_DEF_DST}, + {"dst_res",COL_RES_DST}, + {"dst_unres",COL_UNRES_DST}, + {"dl_dst",COL_DEF_DL_DST}, + {"dl_dst_res",COL_RES_DL_DST}, + {"dl_dst_unres",COL_UNRES_DL_DST}, + {"net_dst",COL_DEF_NET_DST}, + {"net_dst_res",COL_RES_NET_DST}, + {"net_dst_unres",COL_UNRES_NET_DST}, + {"src_port",COL_DEF_SRC_PORT}, + {"src_port_res",COL_RES_SRC_PORT}, + {"src_port_unres",COL_UNRES_SRC_PORT}, + {"dst_port",COL_DEF_DST_PORT}, + {"dst_port_res",COL_RES_DST_PORT}, + {"dst_port_unres",COL_UNRES_DST_PORT}, + {"protocol",COL_PROTOCOL}, + {"info",COL_INFO}, + {"packet_len",COL_PACKET_LENGTH}, + {"cumulative_bytes",COL_CUMULATIVE_BYTES}, + {"direction",COL_IF_DIR}, + {"vsan",COL_VSAN}, + {"tx_rate",COL_TX_RATE}, + {"rssi",COL_RSSI}, + {"dce_call",COL_DCE_CALL}, + {NULL,0} +}; + +static gint col_name_to_id(const gchar* name) { + const struct col_names_t* cn; + for(cn = colnames; cn->name; cn++) { + if (g_str_equal(cn->name,name)) { + return cn->id; + } + } + + return 0; +} + +static const gchar* col_id_to_name(gint id) { + const struct col_names_t* cn; + for(cn = colnames; cn->name; cn++) { + if ( cn->id == id ) { + return cn->name; + } + } + return NULL; +} + + +WSLUA_METAMETHOD Column__tostring(lua_State *L) { + Column c = checkColumn(L,1); + const gchar* text; + + if (!c->cinfo) { + text = col_id_to_name(c->col); + lua_pushfstring(L, "(%s)", text ? text : "unknown"); + } + else { + text = col_get_text(c->cinfo, c->col); + lua_pushstring(L, text ? text : "(nil)"); + } + + WSLUA_RETURN(1); /* The column's string text (in parenthesis if not available). */ +} + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS */ +static int Column__gc(lua_State* L) { + Column col = toColumn(L,1); + + if (!col) return 0; + + if (!col->expired) + col->expired = TRUE; + else + g_free(col); + + return 0; + +} + +WSLUA_METHOD Column_clear(lua_State *L) { + /* Clears a Column. */ + Column c = checkColumn(L,1); + + if (!(c->cinfo)) return 0; + + col_clear(c->cinfo, c->col); + + return 0; +} + +WSLUA_METHOD Column_set(lua_State *L) { + /* Sets the text of a Column. */ +#define WSLUA_ARG_Column_set_TEXT 2 /* The text to which to set the Column. */ + Column c = checkColumn(L,1); + const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_set_TEXT); + + if (!(c->cinfo)) + return 0; + + col_add_str(c->cinfo, c->col, s); + + return 0; +} + +WSLUA_METHOD Column_append(lua_State *L) { + /* Appends text to a Column. */ +#define WSLUA_ARG_Column_append_TEXT 2 /* The text to append to the Column. */ + Column c = checkColumn(L,1); + const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_append_TEXT); + + if (!(c->cinfo)) + return 0; + + col_append_str(c->cinfo, c->col, s); + + return 0; +} + +WSLUA_METHOD Column_prepend(lua_State *L) { + /* Prepends text to a Column. */ +#define WSLUA_ARG_Column_prepend_TEXT 2 /* The text to prepend to the Column. */ + Column c = checkColumn(L,1); + const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_prepend_TEXT); + + if (!(c->cinfo)) + return 0; + + col_prepend_fstr(c->cinfo, c->col, "%s",s); + + return 0; +} + +WSLUA_METHOD Column_fence(lua_State *L) { + /* Sets Column text fence, to prevent overwriting. + + @since 1.10.6 + */ + Column c = checkColumn(L,1); + + if (c->cinfo) + col_set_fence(c->cinfo, c->col); + + return 0; +} + +WSLUA_METHOD Column_clear_fence(lua_State *L) { + /* Clear Column text fence. + + @since 1.11.3 + */ + Column c = checkColumn(L,1); + + if (c->cinfo) + col_clear_fence(c->cinfo, c->col); + + return 0; +} + + +WSLUA_METHODS Column_methods[] = { + WSLUA_CLASS_FNREG(Column,clear), + WSLUA_CLASS_FNREG(Column,set), + WSLUA_CLASS_FNREG(Column,append), + WSLUA_CLASS_FNREG(Column,prepend), + WSLUA_CLASS_FNREG_ALIAS(Column,preppend,prepend), + WSLUA_CLASS_FNREG(Column,fence), + WSLUA_CLASS_FNREG(Column,clear_fence), + { NULL, NULL } +}; + + +WSLUA_META Column_meta[] = { + WSLUA_CLASS_MTREG(Column,tostring), + { NULL, NULL } +}; + + +int Column_register(lua_State *L) { + WSLUA_REGISTER_CLASS(Column); + outstanding_Column = g_ptr_array_new(); + return 0; +} + + +WSLUA_CLASS_DEFINE(Columns,NOP,NOP); +/* The Columns of the packet list. */ + +WSLUA_METAMETHOD Columns__tostring(lua_State *L) { + lua_pushstring(L,"Columns"); + WSLUA_RETURN(1); + /* The string "Columns", no real use, just for debugging purposes. */ +} + +/* + * To document this is very odd - it won't make sense to a person reading the + * API docs to see this metamethod as a method, but oh well. + */ +WSLUA_METAMETHOD Columns__newindex(lua_State *L) { + /* Sets the text of a specific column. */ +#define WSLUA_ARG_Columns__newindex_COLUMN 2 /* The name of the column to set. */ +#define WSLUA_ARG_Columns__newindex_TEXT 3 /* The text for the column. */ + Columns cols = checkColumns(L,1); + const struct col_names_t* cn; + const char* colname; + const char* text; + + if (!cols) return 0; + if (cols->expired) { + luaL_error(L,"expired column"); + return 0; + } + + colname = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_COLUMN); + text = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_TEXT); + + for(cn = colnames; cn->name; cn++) { + if( g_str_equal(cn->name,colname) ) { + col_add_str(cols->cinfo, cn->id, text); + return 0; + } + } + + WSLUA_ARG_ERROR(Columns__newindex,COLUMN,"the column name must be a valid column"); + return 0; +} + +WSLUA_METAMETHOD Columns__index(lua_State *L) { + /* Gets a specific Column. */ + Columns cols = checkColumns(L,1); + const struct col_names_t* cn; + const char* colname = luaL_checkstring(L,2); + + if (!cols) { + Column c = (Column)g_malloc(sizeof(struct _wslua_col_info)); + c->cinfo = NULL; + c->col = col_name_to_id(colname); + c->expired = FALSE; + + PUSH_COLUMN(L,c); + return 1; + } + + + if (cols->expired) { + luaL_error(L,"expired column"); + return 0; + } + + for(cn = colnames; cn->name; cn++) { + if( g_str_equal(cn->name,colname) ) { + Column c = (Column)g_malloc(sizeof(struct _wslua_col_info)); + c->cinfo = cols->cinfo; + c->col = col_name_to_id(colname); + c->expired = FALSE; + + PUSH_COLUMN(L,c); + return 1; + } + } + + return 0; +} + +/* for internal use - used by Pinfo */ +int get_Columns_index(lua_State *L) +{ + return Columns__index(L); +} + + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_META */ +static int Columns__gc(lua_State* L) { + Columns cols = toColumns(L,1); + + if (!cols) return 0; + + if (!cols->expired) + cols->expired = TRUE; + else + g_free(cols); + + return 0; + +} + + +WSLUA_META Columns_meta[] = { + WSLUA_CLASS_MTREG(Columns,tostring), + WSLUA_CLASS_MTREG(Columns,newindex), + WSLUA_CLASS_MTREG(Columns,index), + { NULL, NULL } +}; + + +int Columns_register(lua_State *L) { + WSLUA_REGISTER_META(Columns); + outstanding_Columns = g_ptr_array_new(); + 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: + */ diff --git a/epan/wslua/wslua_dissector.c b/epan/wslua/wslua_dissector.c new file mode 100644 index 0000000000..d3ccc0413f --- /dev/null +++ b/epan/wslua/wslua_dissector.c @@ -0,0 +1,692 @@ +/* + * wslua_dissector.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + +#include <epan/exceptions.h> +#include <epan/show_exception.h> + + +/* WSLUA_CONTINUE_MODULE Proto */ + + +WSLUA_CLASS_DEFINE(Dissector,NOP,NOP); +/* + A refererence to a dissector, used to call a dissector against a packet or a part of it. + */ + +WSLUA_CONSTRUCTOR Dissector_get (lua_State *L) { + /* Obtains a dissector reference by name. */ +#define WSLUA_ARG_Dissector_get_NAME 1 /* The name of the dissector. */ + const gchar* name = luaL_checkstring(L,WSLUA_ARG_Dissector_get_NAME); + Dissector d; + + if ((d = find_dissector(name))) { + pushDissector(L, d); + WSLUA_RETURN(1); /* The Dissector reference. */ + } + + WSLUA_ARG_ERROR(Dissector_get,NAME,"No such dissector"); + return 0; +} + +/* Allow dissector key names to be sorted alphabetically. */ +static gint +compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b) +{ + return strcmp((const char*)dissector_a, (const char*)dissector_b); +} + +WSLUA_CONSTRUCTOR Dissector_list (lua_State *L) { + /* Gets a Lua array table of all registered Dissector names. + + Note: this is an expensive operation, and should only be used for troubleshooting. + + @since 1.11.3 + */ + GList* list = get_dissector_names(); + GList* elist = NULL; + int i = 1; + + if (!list) return luaL_error(L,"Cannot retrieve Dissector name list"); + + list = g_list_sort(list, (GCompareFunc)compare_dissector_key_name); + elist = g_list_first(list); + + lua_newtable(L); + for (i=1; elist; i++, elist = g_list_next(elist)) { + lua_pushstring(L,(const char *) elist->data); + lua_rawseti(L,1,i); + } + + g_list_free(list); + WSLUA_RETURN(1); /* The array table of registered dissector names. */ +} + +WSLUA_METHOD Dissector_call(lua_State* L) { + /* Calls a dissector against a given packet (or part of it). */ +#define WSLUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect. */ +#define WSLUA_ARG_Dissector_call_PINFO 3 /* The packet info. */ +#define WSLUA_ARG_Dissector_call_TREE 4 /* The tree on which to add the protocol items. */ + + Dissector volatile d = checkDissector(L,1); + Tvb tvb = checkTvb(L,WSLUA_ARG_Dissector_call_TVB); + Pinfo pinfo = checkPinfo(L,WSLUA_ARG_Dissector_call_PINFO); + TreeItem ti = checkTreeItem(L,WSLUA_ARG_Dissector_call_TREE); + const char *volatile error = NULL; + int len = 0; + + if (! ( d && tvb && pinfo) ) return 0; + + TRY { + len = call_dissector(d, tvb->ws_tvb, pinfo->ws_pinfo, ti->tree); + /* XXX Are we sure about this??? is this the right/only thing to catch */ + } CATCH_NONFATAL_ERRORS { + show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE); + error = "Malformed frame"; + } ENDTRY; + + if (error) { WSLUA_ERROR(Dissector_call,error); } + + lua_pushnumber(L,(lua_Number)len); + WSLUA_RETURN(1); /* Number of bytes dissected. Note that some dissectors always return number of bytes in incoming buffer, so be aware. */ +} + +WSLUA_METAMETHOD Dissector__call(lua_State* L) { + /* Calls a dissector against a given packet (or part of it). */ +#define WSLUA_ARG_Dissector__call_TVB 2 /* The buffer to dissect. */ +#define WSLUA_ARG_Dissector__call_PINFO 3 /* The packet info. */ +#define WSLUA_ARG_Dissector__call_TREE 4 /* The tree on which to add the protocol items. */ + return Dissector_call(L); +} + +WSLUA_METAMETHOD Dissector__tostring(lua_State* L) { + /* Gets the Dissector's protocol short name. */ + Dissector d = checkDissector(L,1); + if (!d) return 0; + lua_pushstring(L,dissector_handle_get_short_name(d)); + WSLUA_RETURN(1); /* A string of the protocol's short name. */ +} + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int Dissector__gc(lua_State* L _U_) { + /* do NOT free Dissector */ + return 0; +} + +WSLUA_METHODS Dissector_methods[] = { + WSLUA_CLASS_FNREG(Dissector,get), + WSLUA_CLASS_FNREG(Dissector,call), + WSLUA_CLASS_FNREG(Dissector,list), + { NULL, NULL } +}; + +WSLUA_META Dissector_meta[] = { + WSLUA_CLASS_MTREG(Dissector,tostring), + WSLUA_CLASS_MTREG(Dissector,call), + { NULL, NULL } +}; + +int Dissector_register(lua_State* L) { + WSLUA_REGISTER_CLASS(Dissector); + return 0; +} + +WSLUA_CLASS_DEFINE(DissectorTable,NOP,NOP); +/* + A table of subdissectors of a particular protocol (e.g. TCP subdissectors like http, smtp, + sip are added to table "tcp.port"). + + Useful to add more dissectors to a table so that they appear in the Decode As... dialog. + */ + +WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) { + /* Creates a new DissectorTable for your dissector's use. */ +#define WSLUA_ARG_DissectorTable_new_TABLENAME 1 /* The short name of the table. */ +#define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the User Interface + (defaults to the name given). */ +#define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* Either `ftypes.UINT8`, `ftypes.UINT16`, + `ftypes.UINT24`, `ftypes.UINT32`, or + `ftypes.STRING` + (defaults to `ftypes.UINT32`). */ +#define WSLUA_OPTARG_DissectorTable_new_BASE 4 /* Either `base.NONE`, `base.DEC`, `base.HEX`, + `base.OCT`, `base.DEC_HEX` or `base.HEX_DEC` + (defaults to `base.DEC`). */ + const gchar* name = (const gchar*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_new_TABLENAME); + const gchar* ui_name = (const gchar*)luaL_optstring(L,WSLUA_OPTARG_DissectorTable_new_UINAME,name); + enum ftenum type = (enum ftenum)luaL_optinteger(L,WSLUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32); + unsigned base = (unsigned)luaL_optinteger(L,WSLUA_OPTARG_DissectorTable_new_BASE,BASE_DEC); + + switch(type) { + case FT_STRING: + base = BASE_NONE; + /* fallthrough */ + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + { + DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t)); + + name = g_strdup(name); + ui_name = g_strdup(ui_name); + + dt->table = register_dissector_table(name, ui_name, type, base); + dt->name = name; + pushDissectorTable(L, dt); + } + WSLUA_RETURN(1); /* The newly created DissectorTable. */ + default: + WSLUA_OPTARG_ERROR(DissectorTable_new,TYPE,"must be ftypes.UINT{8,16,24,32} or ftypes.STRING"); + break; + } + return 0; +} + +/* this struct is used for passing ourselves user_data through dissector_all_tables_foreach_table(). */ +typedef struct dissector_tables_foreach_table_info { + int num; + lua_State *L; +} dissector_tables_foreach_table_info_t; + +/* this is the DATFunc_table function used for dissector_all_tables_foreach_table() + so we can get all dissector_table names. This pushes the name into a table at stack index 1 */ +static void +dissector_tables_list_func(const gchar *table_name, const gchar *ui_name _U_, gpointer user_data) { + dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data; + lua_pushstring(data->L, table_name); + lua_rawseti(data->L, 1, data->num); + data->num = data->num + 1; +} + +WSLUA_CONSTRUCTOR DissectorTable_list (lua_State *L) { + /* Gets a Lua array table of all DissectorTable names - i.e., the string names you can + use for the first argument to DissectorTable.get(). + + Note: this is an expensive operation, and should only be used for troubleshooting. + + @since 1.11.3 + */ + dissector_tables_foreach_table_info_t data = { 1, L }; + + lua_newtable(L); + + dissector_all_tables_foreach_table(dissector_tables_list_func, (gpointer)&data, + (GCompareFunc)compare_dissector_key_name); + + WSLUA_RETURN(1); /* The array table of registered DissectorTable names. */ +} + +/* this is the DATFunc_heur_table function used for dissector_all_heur_tables_foreach_table() + so we can get all heuristic dissector list names. This pushes the name into a table at stack index 1 */ +static void +heur_dissector_tables_list_func(const gchar *table_name, heur_dissector_list_t *table _U_, gpointer user_data) { + dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data; + lua_pushstring(data->L, table_name); + lua_rawseti(data->L, 1, data->num); + data->num = data->num + 1; +} + +WSLUA_CONSTRUCTOR DissectorTable_heuristic_list (lua_State *L) { + /* Gets a Lua array table of all heuristic list names - i.e., the string names you can + use for the first argument in Proto:register_heuristic(). + + Note: this is an expensive operation, and should only be used for troubleshooting. + + @since 1.11.3 + */ + dissector_tables_foreach_table_info_t data = { 1, L }; + + lua_newtable(L); + + dissector_all_heur_tables_foreach_table(heur_dissector_tables_list_func, (gpointer)&data, NULL); + + WSLUA_RETURN(1); /* The array table of registered heuristic list names */ +} + +WSLUA_CONSTRUCTOR DissectorTable_get (lua_State *L) { + /* + Obtain a reference to an existing dissector table. + */ +#define WSLUA_ARG_DissectorTable_get_TABLENAME 1 /* The short name of the table. */ + const gchar* name = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_TABLENAME); + dissector_table_t table = find_dissector_table(name); + + if (table) { + DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t)); + dt->table = table; + dt->name = g_strdup(name); + + pushDissectorTable(L, dt); + + WSLUA_RETURN(1); /* The DissectorTable. */ + } + + WSLUA_ARG_ERROR(DissectorTable_get,TABLENAME,"no such dissector_table"); + return 0; +} + +WSLUA_METHOD DissectorTable_add (lua_State *L) { + /* + Add a `Proto` with a dissector function, or a `Dissector` object, to the dissector table. + */ +#define WSLUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer, a + integer range or a string depending on the table's type). */ +#define WSLUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either a `Proto` or a `Dissector`). */ + + DissectorTable dt = checkDissectorTable(L,1); + ftenum_t type; + Dissector handle; + + if (!dt) return 0; + + if( isProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) { + Proto p; + p = checkProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR); + handle = p->handle; + + if (! handle) { + WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"a Protocol that does not have a dissector cannot be added to a table"); + return 0; + } + + } else if ( isDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) { + handle = toDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR); + } else { + WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector"); + return 0; + } + + type = get_dissector_table_selector_type(dt->name); + + if (type == FT_STRING) { + gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN)); + dissector_add_string(dt->name, pattern,handle); + g_free (pattern); + } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { + if (lua_isnumber(L, WSLUA_ARG_DissectorTable_add_PATTERN)) { + int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_add_PATTERN); + dissector_add_uint(dt->name, port, handle); + } else { + /* Not a number, try as range */ + const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN); + range_t *range = NULL; + if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) { + dissector_add_uint_range(dt->name, range, handle); + } else { + g_free (range); + WSLUA_ARG_ERROR(DissectorTable_add,PATTERN,"invalid integer or range"); + return 0; + } + g_free (range); + } + } else { + luaL_error(L,"Strange type %d for a DissectorTable",type); + } + + return 0; +} + +WSLUA_METHOD DissectorTable_set (lua_State *L) { + /* + Remove existing dissectors from a table and add a new or a range of new dissectors. + + @since 1.11.3 + */ +#define WSLUA_ARG_DissectorTable_set_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */ +#define WSLUA_ARG_DissectorTable_set_DISSECTOR 3 /* The dissector to add (either a `Proto` or a `Dissector`). */ + + DissectorTable dt = checkDissectorTable(L,1); + ftenum_t type; + Dissector handle; + + if (!dt) return 0; + + if( isProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) { + Proto p; + p = checkProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR); + handle = p->handle; + + if (! handle) { + WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"a Protocol that does not have a dissector cannot be set to a table"); + return 0; + } + + } else if ( isDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) { + handle = toDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR); + } else { + WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"must be either Proto or Dissector"); + return 0; + } + + type = get_dissector_table_selector_type(dt->name); + + if (type == FT_STRING) { + const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN); + dissector_delete_all(dt->name, handle); + dissector_add_string(dt->name, pattern,handle); + } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { + if (lua_isnumber(L, WSLUA_ARG_DissectorTable_set_PATTERN)) { + int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_set_PATTERN); + dissector_delete_all(dt->name, handle); + dissector_add_uint(dt->name, port, handle); + } else { + /* Not a number, try as range */ + const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN); + range_t *range = NULL; + if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) { + dissector_delete_all(dt->name, handle); + dissector_add_uint_range(dt->name, range, handle); + } else { + g_free (range); + WSLUA_ARG_ERROR(DissectorTable_set,PATTERN,"invalid integer or range"); + return 0; + } + g_free (range); + } + } else { + luaL_error(L,"Strange type %d for a DissectorTable",type); + } + + return 0; +} + +WSLUA_METHOD DissectorTable_remove (lua_State *L) { + /* + Remove a dissector or a range of dissectors from a table + */ +#define WSLUA_ARG_DissectorTable_remove_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */ +#define WSLUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to remove (either a `Proto` or a `Dissector`). */ + DissectorTable dt = checkDissectorTable(L,1); + ftenum_t type; + Dissector handle; + + if (!dt) return 0; + + if( isProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) { + Proto p; + p = checkProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR); + handle = p->handle; + + } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) { + handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR); + } else { + WSLUA_ARG_ERROR(DissectorTable_remove,DISSECTOR,"must be either Proto or Dissector"); + return 0; + } + + type = get_dissector_table_selector_type(dt->name); + + if (type == FT_STRING) { + gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN)); + dissector_delete_string(dt->name, pattern,handle); + g_free (pattern); + } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { + if (lua_isnumber(L, WSLUA_ARG_DissectorTable_remove_PATTERN)) { + int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_remove_PATTERN); + dissector_delete_uint(dt->name, port, handle); + } else { + /* Not a number, try as range */ + const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN); + range_t *range = NULL; + if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) + dissector_delete_uint_range(dt->name, range, handle); + else { + g_free (range); + WSLUA_ARG_ERROR(DissectorTable_remove,PATTERN,"invalid integer or range"); + return 0; + } + g_free (range); + } + } + + return 0; +} + +WSLUA_METHOD DissectorTable_remove_all (lua_State *L) { + /* + Remove all dissectors from a table. + + @since 1.11.3 + */ +#define WSLUA_ARG_DissectorTable_remove_all_DISSECTOR 2 /* The dissector to remove (either a `Proto` or a `Dissector`). */ + DissectorTable dt = checkDissectorTable(L,1); + Dissector handle; + + if (!dt) return 0; + + if( isProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) { + Proto p; + p = checkProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR); + handle = p->handle; + + } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) { + handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR); + } else { + WSLUA_ARG_ERROR(DissectorTable_remove_all,DISSECTOR,"must be either Proto or Dissector"); + return 0; + } + + dissector_delete_all (dt->name, handle); + + return 0; +} + +WSLUA_METHOD DissectorTable_try (lua_State *L) { + /* + Try to call a dissector from a table + */ +#define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */ +#define WSLUA_ARG_DissectorTable_try_TVB 3 /* The buffer to dissect. */ +#define WSLUA_ARG_DissectorTable_try_PINFO 4 /* The packet info. */ +#define WSLUA_ARG_DissectorTable_try_TREE 5 /* The tree on which to add the protocol items. */ + DissectorTable volatile dt = checkDissectorTable(L,1); + Tvb tvb = checkTvb(L,WSLUA_ARG_DissectorTable_try_TVB); + Pinfo pinfo = checkPinfo(L,WSLUA_ARG_DissectorTable_try_PINFO); + TreeItem ti = checkTreeItem(L,WSLUA_ARG_DissectorTable_try_TREE); + ftenum_t type; + gboolean handled = FALSE; + const gchar *volatile error = NULL; + int len = 0; + + if (! (dt && tvb && tvb->ws_tvb && pinfo && ti) ) return 0; + + type = get_dissector_table_selector_type(dt->name); + + TRY { + + if (type == FT_STRING) { + const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN); + + len = dissector_try_string(dt->table,pattern,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree, NULL); + if (len > 0) { + handled = TRUE; + } + } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { + int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_try_PATTERN); + + len = dissector_try_uint(dt->table,port,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree); + if (len > 0) { + handled = TRUE; + } + } else { + luaL_error(L,"No such type of dissector_table"); + } + + if (!handled) { + len = call_dissector(lua_data_handle,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree); + } + /* XXX Are we sure about this??? is this the right/only thing to catch */ + } CATCH_NONFATAL_ERRORS { + show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE); + error = "Malformed frame"; + } ENDTRY; + + if (error) { WSLUA_ERROR(DissectorTable_try,error); } + + lua_pushnumber(L,(lua_Number)len); + WSLUA_RETURN(1); /* Number of bytes dissected. Note that some dissectors always return number of bytes in incoming buffer, so be aware. */ +} + +WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) { + /* + Try to obtain a dissector from a table. + */ +#define WSLUA_ARG_DissectorTable_get_dissector_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */ + + DissectorTable dt = checkDissectorTable(L,1); + ftenum_t type; + dissector_handle_t handle = lua_data_handle; + + if (!dt) return 0; + + type = get_dissector_table_selector_type(dt->name); + + if (type == FT_STRING) { + const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN); + handle = dissector_get_string_handle(dt->table,pattern); + } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { + int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_get_dissector_PATTERN); + handle = dissector_get_uint_handle(dt->table,port); + } + + if (handle) { + pushDissector(L,handle); + WSLUA_RETURN(1); /* The dissector handle if found. */ + } else { + lua_pushnil(L); + WSLUA_RETURN(1); /* nil if not found. */ + } +} + +WSLUA_METHOD DissectorTable_add_for_decode_as (lua_State *L) { + /* + Add the given `Proto` to the "Decode as..." list for this DissectorTable. + The passed-in `Proto` object's `dissector()` function is used for dissecting. + + @since 1.99.1 + */ +#define WSLUA_ARG_DissectorTable_add_for_decode_as_PROTO 2 /* The `Proto` to add. */ + DissectorTable dt = checkDissectorTable(L,1); + Proto proto = checkProto(L, WSLUA_ARG_DissectorTable_add_for_decode_as_PROTO); + dissector_handle_t handle = NULL; + + if (! proto->handle) { + proto->handle = new_register_dissector(proto->loname, dissect_lua, proto->hfid); + } + + handle = proto->handle; + + dissector_add_for_decode_as(dt->name, handle); + + return 0; +} + +/* XXX It would be nice to iterate and print which dissectors it has */ +WSLUA_METAMETHOD DissectorTable__tostring(lua_State* L) { + /* Gets some debug information about the DissectorTable. */ + DissectorTable dt = checkDissectorTable(L,1); + GString* s; + ftenum_t type; + + if (!dt) return 0; + + type = get_dissector_table_selector_type(dt->name); + s = g_string_new("DissectorTable "); + + switch(type) { + case FT_STRING: + { + g_string_append_printf(s,"%s String:\n",dt->name); + break; + } + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + { + int base = get_dissector_table_param(dt->name); + g_string_append_printf(s,"%s Integer(%i):\n",dt->name,base); + break; + } + default: + luaL_error(L,"Strange table type"); + } + + lua_pushstring(L,s->str); + g_string_free(s,TRUE); + WSLUA_RETURN(1); /* A string of debug information about the DissectorTable. */ +} + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int DissectorTable__gc(lua_State* L _U_) { + /* do NOT free DissectorTable */ + return 0; +} + +WSLUA_METHODS DissectorTable_methods[] = { + WSLUA_CLASS_FNREG(DissectorTable,new), + WSLUA_CLASS_FNREG(DissectorTable,get), + WSLUA_CLASS_FNREG(DissectorTable,list), + WSLUA_CLASS_FNREG(DissectorTable,heuristic_list), + WSLUA_CLASS_FNREG(DissectorTable,add), + WSLUA_CLASS_FNREG(DissectorTable,set), + WSLUA_CLASS_FNREG(DissectorTable,remove), + WSLUA_CLASS_FNREG(DissectorTable,remove_all), + WSLUA_CLASS_FNREG(DissectorTable,try), + WSLUA_CLASS_FNREG(DissectorTable,get_dissector), + WSLUA_CLASS_FNREG(DissectorTable,add_for_decode_as), + { NULL, NULL } +}; + +WSLUA_META DissectorTable_meta[] = { + WSLUA_CLASS_MTREG(DissectorTable,tostring), + { NULL, NULL } +}; + +int DissectorTable_register(lua_State* L) { + WSLUA_REGISTER_CLASS(DissectorTable); + 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: + */ diff --git a/epan/wslua/wslua_file.c b/epan/wslua/wslua_file.c index e344afe7ef..89a4c3d467 100644 --- a/epan/wslua/wslua_file.c +++ b/epan/wslua/wslua_file.c @@ -25,14 +25,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include "wslua_file_common.h" -#include "wslua.h" #include <errno.h> -#include <wiretap/wtap-int.h> #include <wiretap/file_wrappers.h> -#include <epan/addr_resolv.h> -#include <math.h> #define MAX_LINE_LENGTH 65536 @@ -100,7 +96,7 @@ WSLUA_CLASS_DEFINE(File,FAIL_ON_NULL_OR_EXPIRED("File"),NOP); can be a wtap_dumper struct during write operations. A wtap_dumper struct has a WFILE_T member, but we can't only store its pointer here because dump operations need the whole thing to write out with. Ugh. */ -static File* push_File(lua_State* L, FILE_T ft) { +File* push_File(lua_State* L, FILE_T ft) { File f = (File) g_malloc(sizeof(struct _wslua_file)); f->file = ft; f->wdh = NULL; @@ -108,7 +104,7 @@ static File* push_File(lua_State* L, FILE_T ft) { return pushFile(L,f); } -static File* push_Wdh(lua_State* L, wtap_dumper *wdh) { +File* push_Wdh(lua_State* L, wtap_dumper *wdh) { File f = (File) g_malloc(sizeof(struct _wslua_file)); f->file = (FILE_T)wdh->fh; f->wdh = wdh; @@ -512,1962 +508,6 @@ int File_register(lua_State* L) { } -/************ - * The following is for handling private data for the duration of the file - * read_open/read/close cycle, or write_open/write/write_close cycle. - * In other words it handles the "priv" member of wtap and wtap_dumper, - * but for the Lua script's use. A Lua script can set a Lua table - * to CaptureInfo/CaptureInfoConst and have it saved and retrievable this way. - * We need to offer that, because there needs to be a way for Lua scripts - * to save state for a given file's operations cycle. Since there can be - * two files opened at the same time for the same Lua script (due to reload - * and other such events), the script can't just have one file state. - */ - -/* this is way overkill for this one member, but in case we need to add - more in the future, the plumbing will be here */ -typedef struct _file_priv_t { - int table_ref; -} file_priv_t; - -/* create and set the wtap->priv private data for the file instance */ -static void create_wth_priv(lua_State* L, wtap *wth) { - file_priv_t *priv = (file_priv_t*)g_malloc(sizeof(file_priv_t)); - - if (wth->priv != NULL) { - luaL_error(L, "Cannot create wtap private data because there already is private data"); - return; - } - priv->table_ref = LUA_NOREF; - wth->priv = (void*) priv; -} - -/* gets the private data table from wtap */ -static int get_wth_priv_table_ref(lua_State* L, wtap *wth) { - file_priv_t *priv = (file_priv_t*) wth->priv; - - if (!priv) { - /* shouldn't be possible */ - luaL_error(L, "Cannot get wtap private data: it is null"); - return LUA_NOREF; - } - - /* the following might push a nil, but that's ok */ - lua_rawgeti(L, LUA_REGISTRYINDEX, priv->table_ref); - - return 1; -} - -/* sets the private data to wtap - the table is presumed on top of stack */ -static int set_wth_priv_table_ref(lua_State* L, wtap *wth) { - file_priv_t *priv = (file_priv_t*) wth->priv; - - if (!priv) { - /* shouldn't be possible */ - luaL_error(L, "Cannot get wtap private data: it is null"); - return 0; - } - - if (lua_isnil(L, -1)){ - /* user is setting it nil - ok, de-ref any previous one */ - luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); - priv->table_ref = LUA_NOREF; - return 0; - } - - if (!lua_istable(L, -1)) { - luaL_error(L, "The private_table member can only be set to a table or nil"); - return 0; - } - - /* if we had a table already referenced, de-ref it first */ - if (priv->table_ref != LUA_NOREF) { - luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); - } - - priv->table_ref = luaL_ref(L, LUA_REGISTRYINDEX); - - return 0; -} - -/* remove, deref, and free the wtap->priv data */ -static void remove_wth_priv(lua_State* L, wtap *wth) { - file_priv_t *priv = (file_priv_t*) wth->priv; - - if (!priv) { - /* shouldn't be possible */ - luaL_error(L, "Cannot remove wtap private data: it is null"); - return; - } - - luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); - - g_free(wth->priv); - wth->priv = NULL; -} - -/* create and set the wtap_dumper->priv private data for the file instance */ -static void create_wdh_priv(lua_State* L, wtap_dumper *wdh) { - file_priv_t *priv = (file_priv_t*)g_malloc(sizeof(file_priv_t)); - - if (wdh->priv != NULL) { - luaL_error(L, "Cannot create wtap_dumper private data because there already is private data"); - return; - } - priv->table_ref = LUA_NOREF; - wdh->priv = (void*) priv; -} - -/* get the private data from wtap_dumper */ -static int get_wdh_priv_table_ref(lua_State* L, wtap_dumper *wdh) { - file_priv_t *priv = (file_priv_t*) wdh->priv; - - if (!priv) { - /* shouldn't be possible */ - luaL_error(L, "Cannot get wtap_dumper private data: it is null"); - return LUA_NOREF; - } - - /* the following might push a nil, but that's ok */ - lua_rawgeti(L, LUA_REGISTRYINDEX, priv->table_ref); - - return 1; -} - -/* sets the private data to wtap - the table is presumed on top of stack */ -static int set_wdh_priv_table_ref(lua_State* L, wtap_dumper *wdh) { - file_priv_t *priv = (file_priv_t*) wdh->priv; - - if (!priv) { - /* shouldn't be possible */ - luaL_error(L, "Cannot get wtap private data: it is null"); - return 0; - } - - if (lua_isnil(L, -1)){ - /* user is setting it nil - ok, de-ref any previous one */ - luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); - priv->table_ref = LUA_NOREF; - return 0; - } - - if (!lua_istable(L, -1)) { - luaL_error(L, "The private_table member can only be set to a table or nil"); - return 0; - } - - /* if we had a table already referenced, de-ref it first */ - if (priv->table_ref != LUA_NOREF) { - luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); - } - - priv->table_ref = luaL_ref(L, LUA_REGISTRYINDEX); - - return 0; -} - -/* remove and deref the wtap_dumper->priv data */ -static void remove_wdh_priv(lua_State* L, wtap_dumper *wdh) { - file_priv_t *priv = (file_priv_t*) wdh->priv; - - if (!priv) { - /* shouldn't be possible */ - luaL_error(L, "Cannot remove wtap_dumper private data: it is null"); - return; - } - - luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); - /* we do NOT free wtap_dumper's priv member - wtap_dump_close() free's it */ -} - - -WSLUA_CLASS_DEFINE(CaptureInfo,FAIL_ON_NULL_MEMBER_OR_EXPIRED("CaptureInfo",wth),NOP); -/* - A `CaptureInfo` object, passed into Lua as an argument by `FileHandler` callback - function `read_open()`, `read()`, `seek_read()`, `seq_read_close()`, and `read_close()`. - This object represents capture file data and meta-data (data about the - capture file) being read into Wireshark/Tshark. - - This object's fields can be written-to by Lua during the read-based function callbacks. - In other words, when the Lua plugin's `FileHandler.read_open()` function is invoked, a - `CaptureInfo` object will be passed in as one of the arguments, and its fields - should be written to by your Lua code to tell Wireshark about the capture. - - @since 1.11.3 - */ - -static CaptureInfo* push_CaptureInfo(lua_State* L, wtap *wth, const gboolean first_time) { - CaptureInfo f = (CaptureInfo) g_malloc0(sizeof(struct _wslua_captureinfo)); - f->wth = wth; - f->wdh = NULL; - f->expired = FALSE; - - if (first_time) { - /* XXX: need to do this? */ - wth->file_encap = WTAP_ENCAP_UNKNOWN; - wth->file_tsprec = WTAP_TSPREC_UNKNOWN; - wth->snapshot_length = 0; - } - - return pushCaptureInfo(L,f); -} - -WSLUA_METAMETHOD CaptureInfo__tostring(lua_State* L) { - /* Generates a string of debug info for the CaptureInfo */ - CaptureInfo fi = toCaptureInfo(L,1); - - if (!fi || !fi->wth) { - lua_pushstring(L,"CaptureInfo pointer is NULL!"); - } else { - wtap *wth = fi->wth; - lua_pushfstring(L, "CaptureInfo: file_type_subtype=%d, snapshot_length=%d, pkt_encap=%d, file_tsprec='%s'", - wth->file_type_subtype, wth->snapshot_length, wth->phdr.pkt_encap, wth->file_tsprec); - } - - WSLUA_RETURN(1); /* String of debug information. */ -} - - -static int CaptureInfo__gc(lua_State* L _U_) { - CaptureInfo fc = toCaptureInfo(L,1); - if (fc) - g_free(fc); - return 0; -} - -/* WSLUA_ATTRIBUTE CaptureInfo_encap RW The packet encapsulation type for the whole file. - - See `wtap_encaps` in `init.lua` for available types. Set to `wtap_encaps.PER_PACKET` if packets can - have different types, then later set `FrameInfo.encap` for each packet during `read()`/`seek_read()`. - */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfo,encap,wth->file_encap); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,encap,wth->file_encap,int); - -/* WSLUA_ATTRIBUTE CaptureInfo_time_precision RW The precision of the packet timestamps in the file. - - See `wtap_file_tsprec` in `init.lua` for available precisions. - */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfo,time_precision,wth->file_tsprec); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,time_precision,wth->file_tsprec,int); - -/* WSLUA_ATTRIBUTE CaptureInfo_snapshot_length RW The maximum packet length that could be recorded. - - Setting it to `0` means unknown. Wireshark cannot handle anything bigger than 65535 bytes. - */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfo,snapshot_length,wth->snapshot_length); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,snapshot_length,wth->snapshot_length,guint); - -/* WSLUA_ATTRIBUTE CaptureInfo_comment RW A string comment for the whole capture file, - or nil if there is no `comment`. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,comment,wth->shb_hdr.opt_comment); -WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,comment,wth->shb_hdr.opt_comment,TRUE); - -/* WSLUA_ATTRIBUTE CaptureInfo_hardware RW A string containing the description of - the hardware used to create the capture, or nil if there is no `hardware` string. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,hardware,wth->shb_hdr.shb_hardware); -WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,hardware,wth->shb_hdr.shb_hardware,TRUE); - -/* WSLUA_ATTRIBUTE CaptureInfo_os RW A string containing the name of - the operating system used to create the capture, or nil if there is no `os` string. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,os,wth->shb_hdr.shb_os); -WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,os,wth->shb_hdr.shb_os,TRUE); - -/* WSLUA_ATTRIBUTE CaptureInfo_user_app RW A string containing the name of - the application used to create the capture, or nil if there is no `user_app` string. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfo,user_app,wth->shb_hdr.shb_user_appl); -WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(CaptureInfo,user_app,wth->shb_hdr.shb_user_appl,TRUE); - -/* WSLUA_ATTRIBUTE CaptureInfo_hosts WO Sets resolved ip-to-hostname information. - - The value set must be a Lua table of two key-ed names: `ipv4_addresses` and `ipv6_addresses`. - The value of each of these names are themselves array tables, of key-ed tables, such that the inner table has a key - `addr` set to the raw 4-byte or 16-byte IP address Lua string and a `name` set to the resolved name. - - For example, if the capture file identifies one resolved IPv4 address of 1.2.3.4 to `foo.com`, then you must set - `CaptureInfo.hosts` to a table of: - @code { ipv4_addresses = { { addr = "\01\02\03\04", name = "foo.com" } } } @endcode - - Note that either the `ipv4_addresses` or the `ipv6_addresses` table, or both, may be empty or nil. - */ -static int CaptureInfo_set_hosts(lua_State* L) { - CaptureInfo fi = checkCaptureInfo(L,1); - wtap *wth = fi->wth; - const char *addr = NULL; - const char *name = NULL; - size_t addr_len = 0; - size_t name_len = 0; - guint32 v4_addr = 0; - struct e_in6_addr v6_addr = { {0} }; - - if (!wth->add_new_ipv4 || !wth->add_new_ipv6) { - return luaL_error(L, "CaptureInfo wtap has no IPv4 or IPv6 name resolution"); - } - - if (!lua_istable(L,-1)) { - return luaL_error(L, "CaptureInfo.host must be set to a table"); - } - - /* get the ipv4_addresses table */ - lua_getfield(L, -1, "ipv4_addresses"); - - if (lua_istable(L,-1)) { - /* now walk the table */ - lua_pushnil(L); /* first key */ - while (lua_next(L, -2) != 0) { - /* 'key' (at index -2) and 'value' (at index -1) */ - if (!lua_istable(L,-1)) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv4_addresses table does not contain a table"); - } - - lua_getfield(L, -1, "addr"); - if (!lua_isstring(L,-1)) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv4_addresses table's table does not contain an 'addr' field"); - } - addr = luaL_checklstring(L,-1,&addr_len); - if (addr_len != 4) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv4_addresses 'addr' value is not 4 bytes long"); - } - memcpy(&v4_addr, addr, 4); - - lua_getfield(L, -1, "name"); - if (!lua_isstring(L,-1)) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv4_addresses table's table does not contain an 'addr' field"); - } - name = luaL_checklstring(L,-1,&name_len); - - wth->add_new_ipv4(v4_addr, name); - - /* removes 'value'; keeps 'key' for next iteration */ - lua_pop(L, 1); - } - } - - /* wasn't a table, or it was and we walked it; either way pop it */ - lua_pop(L,1); - - - /* get the ipv6_addresses table */ - lua_getfield(L, -1, "ip6_addresses"); - - if (lua_istable(L,-1)) { - /* now walk the table */ - lua_pushnil(L); /* first key */ - while (lua_next(L, -2) != 0) { - /* 'key' (at index -2) and 'value' (at index -1) */ - if (!lua_istable(L,-1)) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv6_addresses table does not contain a table"); - } - - lua_getfield(L, -1, "addr"); - if (!lua_isstring(L,-1)) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv6_addresses table's table does not contain an 'addr' field"); - } - addr = luaL_checklstring(L,-1,&addr_len); - if (addr_len != 16) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv6_addresses 'addr' value is not 16 bytes long"); - } - memcpy(&v6_addr, addr, 16); - - lua_getfield(L, -1, "name"); - if (!lua_isstring(L,-1)) { - lua_pop(L, 3); /* remove whatever it is, the key, and the ipv4_addreses table */ - return luaL_error(L, "CaptureInfo.host ipv6_addresses table's table does not contain an 'addr' field"); - } - name = luaL_checklstring(L,-1,&name_len); - - wth->add_new_ipv6((const void *)(&v6_addr), name); - - /* removes 'value'; keeps 'key' for next iteration */ - lua_pop(L, 1); - } - } - - /* wasn't a table, or it was and we walked it; either way pop it */ - lua_pop(L,1); - - return 0; -} - - -/* WSLUA_ATTRIBUTE CaptureInfo_private_table RW A private Lua value unique to this file. - - The `private_table` is a field you set/get with your own Lua table. - This is provided so that a Lua script can save per-file reading/writing - state, because multiple files can be opened and read at the same time. - - For example, if the user issued a reload-file command, or Lua called the - `reload()` function, then the current capture file is still open while a new one - is being opened, and thus Wireshark will invoke `read_open()` while the previous - capture file has not caused `read_close()` to be called; and if the `read_open()` - succeeds then `read_close()` will be called right after that for the previous - file, rather than the one just opened. Thus the Lua script can use this - `private_table` to store a table of values specific to each file, by setting - this `private_table` in the `read_open()` function, which it can then later get back - inside its `read()`, `seek_read()`, and `read_close()` functions. -*/ -static int CaptureInfo_get_private_table(lua_State* L) { - CaptureInfo fi = checkCaptureInfo(L,1); - return get_wth_priv_table_ref(L, fi->wth); -} - -static int CaptureInfo_set_private_table(lua_State* L) { - CaptureInfo fi = checkCaptureInfo(L,1); - return set_wth_priv_table_ref(L, fi->wth); -} - -WSLUA_ATTRIBUTES CaptureInfo_attributes[] = { - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,encap), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,time_precision), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,snapshot_length), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,comment), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,hardware), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,os), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,user_app), - WSLUA_ATTRIBUTE_WOREG(CaptureInfo,hosts), - WSLUA_ATTRIBUTE_RWREG(CaptureInfo,private_table), - { NULL, NULL, NULL } -}; - -WSLUA_META CaptureInfo_meta[] = { - WSLUA_CLASS_MTREG(CaptureInfo,tostring), - { NULL, NULL } -}; - -int CaptureInfo_register(lua_State* L) { - WSLUA_REGISTER_META(CaptureInfo); - WSLUA_REGISTER_ATTRIBUTES(CaptureInfo); - return 0; -} - - -WSLUA_CLASS_DEFINE(CaptureInfoConst,FAIL_ON_NULL_MEMBER_OR_EXPIRED("CaptureInfoConst",wdh),NOP); -/* - A `CaptureInfoConst` object, passed into Lua as an argument to the `FileHandler` callback - function `write_open()`. - - This object represents capture file data and meta-data (data about the - capture file) for the current capture in Wireshark/Tshark. - - This object's fields are read-from when used by `write_open` function callback. - In other words, when the Lua plugin's FileHandler `write_open` function is invoked, a - `CaptureInfoConst` object will be passed in as one of the arguments, and its fields - should be read from by your Lua code to get data about the capture that needs to be written. - - @since 1.11.3 - */ - -static CaptureInfoConst* push_CaptureInfoConst(lua_State* L, wtap_dumper *wdh) { - CaptureInfoConst f = (CaptureInfoConst) g_malloc0(sizeof(struct _wslua_captureinfo)); - f->wth = NULL; - f->wdh = wdh; - f->expired = FALSE; - return pushCaptureInfoConst(L,f); -} - -WSLUA_METAMETHOD CaptureInfoConst__tostring(lua_State* L) { - /* Generates a string of debug info for the CaptureInfoConst */ - CaptureInfoConst fi = toCaptureInfoConst(L,1); - - if (!fi || !fi->wdh) { - lua_pushstring(L,"CaptureInfoConst pointer is NULL!"); - } else { - wtap_dumper *wdh = fi->wdh; - lua_pushfstring(L, "CaptureInfoConst: file_type_subtype=%d, snaplen=%d, encap=%d, compressed=%d, file_tsprec='%s'", - wdh->file_type_subtype, wdh->snaplen, wdh->encap, wdh->compressed, wdh->tsprecision); - } - - WSLUA_RETURN(1); /* String of debug information. */ -} - -/* WSLUA_ATTRIBUTE CaptureInfoConst_type RO The file type. */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfoConst,type,wdh->file_type_subtype); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_snapshot_length RO The maximum packet length that is actually recorded (vs. the original - length of any given packet on-the-wire). A value of `0` means the snapshot length is unknown or there is no one - such length for the whole file. */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfoConst,snapshot_length,wdh->snaplen); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_encap RO The packet encapsulation type for the whole file. - - See `wtap_encaps` in init.lua for available types. It is set to `wtap_encaps.PER_PACKET` if packets can - have different types, in which case each Frame identifies its type, in `FrameInfo.packet_encap`. */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(CaptureInfoConst,encap,wdh->encap); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_comment RW A comment for the whole capture file, if the - `wtap_presence_flags.COMMENTS` was set in the presence flags; nil if there is no comment. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,comment,wth->shb_hdr.opt_comment); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_hardware RO A string containing the description of - the hardware used to create the capture, or nil if there is no hardware string. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,hardware,wth->shb_hdr.shb_hardware); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_os RO A string containing the name of - the operating system used to create the capture, or nil if there is no os string. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,os,wth->shb_hdr.shb_os); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_user_app RO A string containing the name of - the application used to create the capture, or nil if there is no user_app string. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(CaptureInfoConst,user_app,wth->shb_hdr.shb_user_appl); - -/* WSLUA_ATTRIBUTE CaptureInfoConst_hosts RO A ip-to-hostname Lua table of two key-ed names: `ipv4_addresses` and `ipv6_addresses`. - The value of each of these names are themselves array tables, of key-ed tables, such that the inner table has a key - `addr` set to the raw 4-byte or 16-byte IP address Lua string and a `name` set to the resolved name. - - For example, if the current capture has one resolved IPv4 address of 1.2.3.4 to `foo.com`, then getting - `CaptureInfoConst.hosts` will get a table of: - @code { ipv4_addresses = { { addr = "\01\02\03\04", name = "foo.com" } }, ipv6_addresses = { } } @endcode - - Note that either the `ipv4_addresses` or the `ipv6_addresses` table, or both, may be empty, however they will not - be nil. */ -static int CaptureInfoConst_get_hosts(lua_State* L) { - CaptureInfoConst fi = checkCaptureInfoConst(L,1); - wtap_dumper *wdh = fi->wdh; - - /* create the main table to return */ - lua_newtable(L); - - /* create the ipv4_addresses table */ - lua_newtable(L); - - if (wdh->addrinfo_lists && wdh->addrinfo_lists->ipv4_addr_list) { - hashipv4_t *ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, 0); - int i, j; - for (i=1, j=1; ipv4_hash_list_entry != NULL; i++) { - if ((ipv4_hash_list_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) { - lua_pushnumber(L, j); /* push numeric index key starting at 1, so it will be an array table */ - /* create the entry table */ - lua_newtable(L); - /* addr is in network order already */ - lua_pushlstring(L, (char*)(&ipv4_hash_list_entry->ip), 4); - lua_setfield(L, -2, "addr"); - lua_pushstring(L, ipv4_hash_list_entry->name); - lua_setfield(L, -2, "name"); - /* now our ipv4_addresses table is at -3, key number is -2, and entry table at -2, so we're good */ - lua_settable(L, -3); - j++; - } - ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i); - } - } - - /* set the (possibly empty) ipv4_addresses table into the main table */ - lua_setfield(L, -2, "ipv4_addresses"); - - /* create the ipv6_addresses table */ - lua_newtable(L); - - if (wdh->addrinfo_lists && wdh->addrinfo_lists->ipv6_addr_list) { - hashipv6_t *ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, 0); - int i, j; - for (i=1, j=1; ipv6_hash_list_entry != NULL; i++) { - if ((ipv6_hash_list_entry->flags & USED_AND_RESOLVED_MASK) == RESOLVED_ADDRESS_USED) { - lua_pushnumber(L, j); /* push numeric index key starting at 1, so it will be an array table */ - /* create the entry table */ - lua_newtable(L); - /* addr is in network order already */ - lua_pushlstring(L, (char*)(&ipv6_hash_list_entry->addr.bytes[0]), 16); - lua_setfield(L, -2, "addr"); - lua_pushstring(L, ipv6_hash_list_entry->name); - lua_setfield(L, -2, "name"); - /* now our ipv6_addresses table is at -3, key number is -2, and entry table at -2, so we're good */ - lua_settable(L, -3); - j++; - } - ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i); - } - } - - /* set the (possibly empty) ipv6_addresses table into the main table */ - lua_setfield(L, -2, "ip6_addresses"); - - /* return the main table */ - return 1; -} - -/* WSLUA_ATTRIBUTE CaptureInfoConst_private_table RW A private Lua value unique to this file. - - The `private_table` is a field you set/get with your own Lua table. - This is provided so that a Lua script can save per-file reading/writing - state, because multiple files can be opened and read at the same time. - - For example, if two Lua scripts issue a `Dumper:new_for_current()` call and the - current file happens to use your script's writer, then the Wireshark will invoke - `write_open()` while the previous capture file has not had `write_close()` called. - Thus the Lua script can use this `private_table` to store a table of values - specific to each file, by setting this `private_table` in the write_open() - function, which it can then later get back inside its `write()`, and `write_close()` - functions. -*/ -static int CaptureInfoConst_get_private_table(lua_State* L) { - CaptureInfoConst fi = checkCaptureInfoConst(L,1); - return get_wdh_priv_table_ref(L, fi->wdh); -} - -static int CaptureInfoConst_set_private_table(lua_State* L) { - CaptureInfoConst fi = checkCaptureInfoConst(L,1); - return set_wdh_priv_table_ref(L, fi->wdh); -} - -static int CaptureInfoConst__gc(lua_State* L _U_) { - CaptureInfoConst fi = toCaptureInfoConst(L,1); - if (fi) - g_free(fi); - return 0; -} - -WSLUA_ATTRIBUTES CaptureInfoConst_attributes[] = { - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,encap), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,type), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,snapshot_length), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,comment), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,hardware), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,os), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,user_app), - WSLUA_ATTRIBUTE_ROREG(CaptureInfoConst,hosts), - WSLUA_ATTRIBUTE_RWREG(CaptureInfoConst,private_table), - { NULL, NULL, NULL } -}; - -WSLUA_META CaptureInfoConst_meta[] = { - WSLUA_CLASS_MTREG(CaptureInfoConst,tostring), - { NULL, NULL } -}; - -int CaptureInfoConst_register(lua_State* L) { - WSLUA_REGISTER_META(CaptureInfoConst); - WSLUA_REGISTER_ATTRIBUTES(CaptureInfoConst); - return 0; -} - - -WSLUA_CLASS_DEFINE(FrameInfo,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"),NOP); -/* - 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 - */ - -static FrameInfo* push_FrameInfo(lua_State* L, struct wtap_pkthdr *phdr, Buffer* buf) { - FrameInfo f = (FrameInfo) g_malloc0(sizeof(struct _wslua_phdr)); - f->phdr = phdr; - 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->phdr) - lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'", - fi->phdr->rec_type, fi->phdr->presence_flags, fi->phdr->caplen, fi->phdr->len, fi->phdr->pkt_encap, fi->phdr->opt_comment); - else - lua_pushstring(L, "FrameInfo phdr 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 phdr/buf it points to */ -static int FrameInfo__gc(lua_State* L _U_) { - FrameInfo fi = toFrameInfo(L,1); - if (fi) - 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->phdr) return 0; - - fi->phdr->ts.secs = nstime->secs; - fi->phdr->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->phdr->ts.secs; - nstime->nsecs = fi->phdr->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->phdr) { - 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->phdr->caplen = (guint32) len; - fi->phdr->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,phdr->rec_type); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,rec_type,phdr->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,phdr->presence_flags); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,flags,phdr->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,phdr->caplen); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,captured_length,phdr->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,phdr->len); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,original_length,phdr->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,phdr->pkt_encap); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,encap,phdr->pkt_encap,int); - -/* 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,phdr->opt_comment); -WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(FrameInfo,comment,phdr->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(FrameInfo); - WSLUA_REGISTER_ATTRIBUTES(FrameInfo); - return 0; -} - -WSLUA_CLASS_DEFINE(FrameInfoConst,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"),NOP); -/* - 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 - */ - -static FrameInfoConst* push_FrameInfoConst(lua_State* L, const struct wtap_pkthdr *phdr, const guint8 *pd) { - FrameInfoConst f = (FrameInfoConst) g_malloc(sizeof(struct _wslua_const_phdr)); - f->phdr = phdr; - 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->phdr && !fi->expired) - lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'", - fi->phdr->rec_type, fi->phdr->presence_flags, fi->phdr->caplen, fi->phdr->len, fi->phdr->pkt_encap, fi->phdr->opt_comment); - else - lua_pushfstring(L, "FrameInfo has %s", fi->phdr?"expired":"null phdr 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->phdr ? fi->phdr->caplen:0); - int err = 0; - - if (!fi->pd || !fi->phdr || !fh->wdh) { - luaL_error(L, "FrameInfoConst write_data() got null buffer or file pointer internally"); - return 0; - } - - if (len > fi->phdr->caplen) - len = fi->phdr->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_pkthdr it points to */ -static int FrameInfoConst__gc(lua_State* L _U_) { - FrameInfoConst fi = toFrameInfoConst(L,1); - if (fi) - 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->phdr->ts.secs; - nstime->nsecs = fi->phdr->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->phdr) return 0; - - lua_pushlstring(L, fi->pd, fi->phdr->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,phdr->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,phdr->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,phdr->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,phdr->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,phdr->pkt_encap); - -/* WSLUA_ATTRIBUTE FrameInfoConst_comment RO A comment for the packet; nil if there is none. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FrameInfoConst,comment,phdr->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(FrameInfoConst); - WSLUA_REGISTER_ATTRIBUTES(FrameInfoConst); - return 0; -} - - -WSLUA_CLASS_DEFINE(FileHandler,NOP,NOP); -/* - A FileHandler object, created by a call to FileHandler.new(arg1, arg2, ...). - The FileHandler object lets you create a file-format reader, or writer, or - both, by setting your own read_open/read or write_open/write functions. - - @since 1.11.3 - */ - -static int filehandler_cb_error_handler(lua_State* L) { - const gchar* error = lua_tostring(L,1); - const gchar* functype = luaL_optstring(L, lua_upvalueindex(1), "UNKNOWN"); - report_failure("Lua: Error During execution of FileHandler %s callback:\n %s",functype,error); - lua_pop(L, 1); - return 0; -} - -static int push_error_handler(lua_State* L, const gchar* funcname) { - lua_pushstring(L, funcname); - lua_pushcclosure(L, filehandler_cb_error_handler, 1); - return 1; -} - - -/* During file routines, we cannot allow the FileHandler to get de-registered, since - that would change the GArray's in file_access.c and hilarity would ensue. So we - set this to true right before pcall(), and back to false afterwards */ -static gboolean in_routine = FALSE; - -/* This does the verification and setup common to all open/read/seek_read/close routines */ -#define INIT_FILEHANDLER_ROUTINE(name,retval) \ - if (!fh) { \ - g_warning("Error in file %s: no Lua FileHandler object", #name); \ - return retval; \ - } \ - if (!fh->registered) { \ - g_warning("Error in file %s: Lua FileHandler is not registered", #name); \ - return retval; \ - } \ - if (!fh->L) { \ - g_warning("Error in file %s: no FileHandler Lua state", #name); \ - return retval; \ - } \ - if (fh->name##_ref == LUA_NOREF) { \ - g_warning("Error in file %s: no FileHandler %s routine reference", #name, #name); \ - return retval; \ - } \ - L = fh->L; \ - lua_settop(L,0); \ - push_error_handler(L, #name " routine"); \ - lua_rawgeti(L, LUA_REGISTRYINDEX, fh->name##_ref); \ - if (!lua_isfunction(L, -1)) { \ - g_warning("Error in file %s: no FileHandler %s routine function in Lua", #name, #name); \ - return retval; \ - } \ - /* now guard against de-registering during pcall() */ \ - in_routine = TRUE; - -#define END_FILEHANDLER_ROUTINE() \ - /* now allow de-registering again */ \ - in_routine = TRUE; - - -/* LUA_ERRGCMM is in Lua 5.2 only - making it 9 disables it */ -#ifndef LUA_ERRGCMM -#define LUA_ERRGCMM 9 -#endif - -#define CASE_ERROR(name) \ - case LUA_ERRRUN: \ - g_warning("Run-time error while calling FileHandler %s routine", name); \ - break; \ - case LUA_ERRMEM: \ - g_warning("Memory alloc error while calling FileHandler %s routine", name); \ - break; \ - case LUA_ERRERR: \ - g_warning("Error in error handling while calling FileHandler %s routine", name); \ - break; \ - case LUA_ERRGCMM: \ - g_warning("Error in garbage collector while calling FileHandler %s routine", name); \ - break; \ - default: \ - g_assert_not_reached(); \ - break; - -#define CASE_ERROR_ERRINFO(name) \ - case LUA_ERRRUN: \ - g_warning("Run-time error while calling FileHandler %s routine", name); \ - *err_info = g_strdup_printf("Run-time error while calling FileHandler %s routine", name); \ - break; \ - case LUA_ERRMEM: \ - g_warning("Memory alloc error while calling FileHandler %s routine", name); \ - *err_info = g_strdup_printf("Memory alloc error while calling FileHandler %s routine", name); \ - break; \ - case LUA_ERRERR: \ - g_warning("Error in error handling while calling FileHandler %s routine", name); \ - *err_info = g_strdup_printf("Error in error handling while calling FileHandler %s routine", name); \ - break; \ - case LUA_ERRGCMM: \ - g_warning("Error in garbage collector while calling FileHandler %s routine", name); \ - *err_info = g_strdup_printf("Error in garbage collector while calling FileHandler %s routine", name); \ - break; \ - default: \ - g_assert_not_reached(); \ - break; - - -/* some declarations */ -static gboolean -wslua_filehandler_read(wtap *wth, int *err, gchar **err_info, - gint64 *data_offset); -static gboolean -wslua_filehandler_seek_read(wtap *wth, gint64 seek_off, - struct wtap_pkthdr *phdr, Buffer *buf, - int *err, gchar **err_info); -static void -wslua_filehandler_close(wtap *wth); -static void -wslua_filehandler_sequential_close(wtap *wth); - - -/* This is our one-and-only open routine for file handling. When called by - * file_access.c, the wtap wth argument has a void* wslua_data that holds the specific - * FileHandler for the specific registered file format reader. It has this because - * we passed it in when we registered the open routine. - * The open_file_* routines should return: - * -1 on an I/O error; - * 1 if the file they're reading is one of the types it handles; - * 0 if the file they're reading isn't the type they're checking for. - * If the routine handles this type of file, it should set the "file_type" - * field in the "struct wtap" to the type of the file. - */ -static wtap_open_return_val -wslua_filehandler_open(wtap *wth, int *err, gchar **err_info) -{ - FileHandler fh = (FileHandler)(wth->wslua_data); - wtap_open_return_val retval = WTAP_OPEN_NOT_MINE; - lua_State* L = NULL; - File *fp = NULL; - CaptureInfo *fc = NULL; - - INIT_FILEHANDLER_ROUTINE(read_open,WTAP_OPEN_NOT_MINE); - - create_wth_priv(L, wth); - - fp = push_File(L, wth->fh); - fc = push_CaptureInfo(L, wth, TRUE); - - errno = WTAP_ERR_CANT_OPEN; - switch ( lua_pcall(L,2,1,1) ) { - case 0: - retval = (wtap_open_return_val)wslua_optboolint(L,-1,0); - break; - CASE_ERROR_ERRINFO("read_open") - } - - END_FILEHANDLER_ROUTINE(); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - - if (retval == WTAP_OPEN_MINE) { - /* this is our file type - set the routines and settings into wtap */ - - if (fh->read_ref != LUA_NOREF) { - wth->subtype_read = wslua_filehandler_read; - } - else { - g_warning("Lua file format module lacks a read routine"); - return WTAP_OPEN_NOT_MINE; - } - - if (fh->seek_read_ref != LUA_NOREF) { - wth->subtype_seek_read = wslua_filehandler_seek_read; - } - else { - g_warning("Lua file format module lacks a seek-read routine"); - return WTAP_OPEN_NOT_MINE; - } - - /* it's ok to not have a close routine */ - if (fh->read_close_ref != LUA_NOREF) - wth->subtype_close = wslua_filehandler_close; - else - wth->subtype_close = NULL; - - /* it's ok to not have a sequential close routine */ - if (fh->seq_read_close_ref != LUA_NOREF) - wth->subtype_sequential_close = wslua_filehandler_sequential_close; - else - wth->subtype_sequential_close = NULL; - - wth->file_type_subtype = fh->file_type; - } - else if (retval == WTAP_OPEN_ERROR) { - /* open error - we *must* return an error code! */ - if (err) { - *err = WTAP_ERR_CANT_OPEN; - } - } - else if (retval == WTAP_OPEN_NOT_MINE) { - /* not our file type */ - remove_wth_priv(L, wth); - } - else { - /* not a valid return type */ - g_warning("FileHandler read_open routine returned %d", retval); - if (err) { - *err = WTAP_ERR_INTERNAL; - } - retval = WTAP_OPEN_ERROR; - } - - lua_settop(L,0); - return retval; -} - -/* The classic wtap read routine. This returns TRUE if it found the next packet, - * else FALSE. - * If it finds a frame/packet, it should set the pseudo-header info (ie, let Lua set it). - * Also Lua needs to set data_offset to the beginning of the line we're returning. - * This will be the seek_off parameter when this frame is re-read. -*/ -static gboolean -wslua_filehandler_read(wtap *wth, int *err, gchar **err_info, - gint64 *data_offset) -{ - FileHandler fh = (FileHandler)(wth->wslua_data); - int retval = -1; - lua_State* L = NULL; - File *fp = NULL; - CaptureInfo *fc = NULL; - FrameInfo *fi = NULL; - - INIT_FILEHANDLER_ROUTINE(read,FALSE); - - /* Reset errno */ - if (err) { - *err = errno = 0; - } - - wth->phdr.opt_comment = NULL; - - fp = push_File(L, wth->fh); - fc = push_CaptureInfo(L, wth, FALSE); - fi = push_FrameInfo(L, &wth->phdr, wth->frame_buffer); - - switch ( lua_pcall(L,3,1,1) ) { - case 0: - if (lua_isnumber(L,-1)) { - *data_offset = wslua_togint64(L, -1); - retval = 1; - break; - } - retval = wslua_optboolint(L,-1,0); - break; - CASE_ERROR_ERRINFO("read") - } - - END_FILEHANDLER_ROUTINE(); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - (*fi)->expired = TRUE; - lua_settop(L,0); - - return (retval == 1); -} - -/* Classic wtap seek_read function, called by wtap core. This must return TRUE on - * success, FALSE on error. - */ -static gboolean -wslua_filehandler_seek_read(wtap *wth, gint64 seek_off, - struct wtap_pkthdr *phdr, Buffer *buf, - int *err, gchar **err_info) -{ - FileHandler fh = (FileHandler)(wth->wslua_data); - int retval = -1; - lua_State* L = NULL; - File *fp = NULL; - CaptureInfo *fc = NULL; - FrameInfo *fi = NULL; - - INIT_FILEHANDLER_ROUTINE(seek_read,FALSE); - - /* Reset errno */ - if (err) { - *err = errno = 0; - } - phdr->opt_comment = NULL; - - fp = push_File(L, wth->random_fh); - fc = push_CaptureInfo(L, wth, FALSE); - fi = push_FrameInfo(L, phdr, buf); - lua_pushnumber(L, (lua_Number)seek_off); - - switch ( lua_pcall(L,4,1,1) ) { - case 0: - if (lua_isstring(L,-1)) { - size_t len = 0; - const gchar* fd = lua_tolstring(L, -1, &len); - if (len < WTAP_MAX_PACKET_SIZE) - memcpy(ws_buffer_start_ptr(buf), fd, len); - retval = 1; - break; - } - retval = wslua_optboolint(L,-1,0); - break; - CASE_ERROR_ERRINFO("seek_read") - } - - END_FILEHANDLER_ROUTINE(); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - (*fi)->expired = TRUE; - lua_settop(L,0); - - return (retval == 1); -} - -/* Classic wtap close function, called by wtap core. - */ -static void -wslua_filehandler_close(wtap *wth) -{ - FileHandler fh = (FileHandler)(wth->wslua_data); - lua_State* L = NULL; - File *fp = NULL; - CaptureInfo *fc = NULL; - - INIT_FILEHANDLER_ROUTINE(read_close,); - - fp = push_File(L, wth->fh); - fc = push_CaptureInfo(L, wth, FALSE); - - switch ( lua_pcall(L,2,1,1) ) { - case 0: - break; - CASE_ERROR("read_close") - } - - END_FILEHANDLER_ROUTINE(); - - remove_wth_priv(L, wth); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - lua_settop(L,0); - - return; -} - -/* Classic wtap sequential close function, called by wtap core. - */ -static void -wslua_filehandler_sequential_close(wtap *wth) -{ - FileHandler fh = (FileHandler)(wth->wslua_data); - lua_State* L = NULL; - File *fp = NULL; - CaptureInfo *fc = NULL; - - INIT_FILEHANDLER_ROUTINE(seq_read_close,); - - fp = push_File(L, wth->fh); - fc = push_CaptureInfo(L, wth, FALSE); - - switch ( lua_pcall(L,2,1,1) ) { - case 0: - break; - CASE_ERROR("seq_read_close") - } - - END_FILEHANDLER_ROUTINE(); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - lua_settop(L,0); - - return; -} - - -/* basically a dummy function to use for can_write_encap so that the caller calls - * wslua_can_write_encap instead (which will be wslua_filehandler_can_write_encap) - */ -static int -wslua_dummy_can_write_encap(int encap _U_) -{ - return WTAP_ERR_CHECK_WSLUA; -} - -/* Similar to the classic wtap can_write_encap function. - * This returns 0 if the encap is ok for this file type. - */ -static int -wslua_filehandler_can_write_encap(int encap, void* data) -{ - FileHandler fh = (FileHandler)(data); - int retval = WTAP_ERR_UNWRITABLE_ENCAP; - lua_State* L = NULL; - - INIT_FILEHANDLER_ROUTINE(can_write_encap,WTAP_ERR_INTERNAL); - - lua_pushnumber(L, encap); - - switch ( lua_pcall(L,1,1,1) ) { - case 0: - retval = wslua_optboolint(L,-1,WTAP_ERR_UNWRITABLE_ENCAP); - break; - CASE_ERROR("can_write_encap") - } - - END_FILEHANDLER_ROUTINE(); - - /* the retval we got was either a 1 for true, 0 for false, or WTAP_ERR_UNWRITABLE_ENCAP; - but can_write_encap() expects 0 to be true/yes */ - if (retval == 1) { - retval = 0; - } else if (retval == 0) { - retval = WTAP_ERR_UNWRITABLE_ENCAP; - } - - return retval; -} - -/* some declarations */ -static gboolean -wslua_filehandler_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, - const guint8 *pd, int *err, gchar **err_info); -static gboolean -wslua_filehandler_dump_close(wtap_dumper *wdh, int *err); - - -/* The classic wtap dump_open function. - * This returns 1 (TRUE) on success. - */ -static int -wslua_filehandler_dump_open(wtap_dumper *wdh, int *err) -{ - FileHandler fh = (FileHandler)(wdh->wslua_data); - int retval = 0; - lua_State* L = NULL; - File *fp = NULL; - CaptureInfoConst *fc = NULL; - - INIT_FILEHANDLER_ROUTINE(write_open,0); - - create_wdh_priv(L, wdh); - - fp = push_Wdh(L, wdh); - fc = push_CaptureInfoConst(L,wdh); - - /* Reset err */ - if (err) { - *err = 0; - } - - switch ( lua_pcall(L,2,1,1) ) { - case 0: - retval = wslua_optboolint(L,-1,0); - break; - CASE_ERROR("write_open") - } - - END_FILEHANDLER_ROUTINE(); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - - if (retval == 1) { - /* this is our file type - set the routines and settings into wtap */ - - if (fh->write_ref != LUA_NOREF) { - wdh->subtype_write = wslua_filehandler_dump; - } - else { - g_warning("FileHandler was not set with a write function, even though write_open() returned true"); - return 0; - } - - /* it's ok to not have a close routine */ - if (fh->write_close_ref != LUA_NOREF) - wdh->subtype_close = wslua_filehandler_dump_close; - else - wdh->subtype_close = NULL; - } - else { - /* not our file type? */ - remove_wdh_priv(L, wdh); - } - - return retval; -} - -/* The classic wtap dump routine. This returns TRUE if it writes the current packet, - * else FALSE. -*/ -static gboolean -wslua_filehandler_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, - const guint8 *pd, int *err, gchar **err_info _U_) -{ - FileHandler fh = (FileHandler)(wdh->wslua_data); - int retval = -1; - lua_State* L = NULL; - File *fp = NULL; - CaptureInfoConst *fc = NULL; - FrameInfoConst *fi = NULL; - - INIT_FILEHANDLER_ROUTINE(write,FALSE); - - /* Reset errno */ - if (err) { - *err = errno = 0; - } - - fp = push_Wdh(L, wdh); - fc = push_CaptureInfoConst(L,wdh); - fi = push_FrameInfoConst(L, phdr, pd); - - errno = WTAP_ERR_CANT_WRITE; - switch ( lua_pcall(L,3,1,1) ) { - case 0: - retval = wslua_optboolint(L,-1,0); - break; - CASE_ERROR("write") - } - - END_FILEHANDLER_ROUTINE(); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - (*fi)->expired = TRUE; - - return (retval == 1); -} - -/* The classic wtap dump_close routine. This returns TRUE if it closes cleanly, - * else FALSE. -*/ -static gboolean -wslua_filehandler_dump_close(wtap_dumper *wdh, int *err) -{ - FileHandler fh = (FileHandler)(wdh->wslua_data); - int retval = -1; - lua_State* L = NULL; - File *fp = NULL; - CaptureInfoConst *fc = NULL; - - INIT_FILEHANDLER_ROUTINE(write_close,FALSE); - - /* Reset errno */ - if (err) { - *err = errno = 0; - } - - fp = push_Wdh(L, wdh); - fc = push_CaptureInfoConst(L,wdh); - - errno = WTAP_ERR_CANT_CLOSE; - switch ( lua_pcall(L,2,1,1) ) { - case 0: - retval = wslua_optboolint(L,-1,0); - break; - CASE_ERROR("write_close") - } - - END_FILEHANDLER_ROUTINE(); - - remove_wdh_priv(L, wdh); - - (*fp)->expired = TRUE; - (*fc)->expired = TRUE; - - return (retval == 1); -} - - -WSLUA_CONSTRUCTOR FileHandler_new(lua_State* L) { - /* Creates a new FileHandler */ -#define WSLUA_ARG_FileHandler_new_NAME 1 /* The name of the file type, for display purposes only. E.g., "Wireshark - pcapng" */ -#define WSLUA_ARG_FileHandler_new_SHORTNAME 2 /* the file type short name, used as a shortcut in various places. E.g., "pcapng". Note: the name cannot already be in use. */ -#define WSLUA_ARG_FileHandler_new_DESCRIPTION 3 /* Descriptive text about this file format, for display purposes only */ -#define WSLUA_ARG_FileHandler_new_TYPE 4 /* The type of FileHandler, "r"/"w"/"rw" for reader/writer/both, include "m" for magic, "s" for strong heuristic */ - - const gchar* name = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_NAME); - const gchar* short_name = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_SHORTNAME); - const gchar* desc = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_DESCRIPTION); - const gchar* type = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_TYPE); - FileHandler fh = (FileHandler) g_malloc0(sizeof(struct _wslua_filehandler)); - - fh->is_reader = (strchr(type,'r') != NULL) ? TRUE : FALSE; - fh->is_writer = (strchr(type,'w') != NULL) ? TRUE : FALSE; - - if (fh->is_reader && wtap_has_open_info(short_name)) { - return luaL_error(L, "FileHandler.new: '%s' short name already exists for a reader!", short_name); - } - - if (fh->is_writer && wtap_short_string_to_file_type_subtype(short_name) > -1) { - return luaL_error(L, "FileHandler.new: '%s' short name already exists for a writer!", short_name); - } - - fh->type = g_strdup(type); - fh->finfo.name = g_strdup(name); - fh->finfo.short_name = g_strdup(short_name); - fh->finfo.default_file_extension = NULL; - fh->finfo.additional_file_extensions = NULL; - fh->finfo.writing_must_seek = FALSE; - fh->finfo.has_name_resolution = FALSE; - fh->finfo.can_write_encap = NULL; - fh->finfo.dump_open = NULL; - /* this will be set to a new file_type when registered */ - fh->file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; - - fh->description = g_strdup(desc); - fh->L = L; - fh->read_open_ref = LUA_NOREF; - fh->read_ref = LUA_NOREF; - fh->seek_read_ref = LUA_NOREF; - fh->read_close_ref = LUA_NOREF; - fh->seq_read_close_ref = LUA_NOREF; - fh->write_open_ref = LUA_NOREF; - fh->write_ref = LUA_NOREF; - fh->write_close_ref = LUA_NOREF; - fh->can_write_encap_ref = LUA_NOREF; - - fh->registered = FALSE; - - pushFileHandler(L,fh); - WSLUA_RETURN(1); /* The newly created FileHandler object */ -} - -WSLUA_METAMETHOD FileHandler__tostring(lua_State* L) { - /* Generates a string of debug info for the FileHandler */ - FileHandler fh = toFileHandler(L,1); - - if (!fh) { - lua_pushstring(L,"FileHandler pointer is NULL!"); - } else { - lua_pushfstring(L, "FileHandler(%s): short-name='%s', description='%s', read_open=%d, read=%d, write=%d", - fh->finfo.name, fh->finfo.short_name, fh->description, fh->read_open_ref, fh->read_ref, fh->write_ref); - } - - WSLUA_RETURN(1); /* String of debug information. */ -} - -static int FileHandler__gc(lua_State* L _U_) { - /* do NOT free FileHandler, it's never free'd */ - /* TODO: handle this and other Lua things that should be free'd on exit, in a better way */ - return 0; -} - -/* A Lua File handler must not be expired, and must be either a reader or writer, and - * a *reader* one MUST at least define read_open, read, and seek_read funcs; and - * a *writer* one MUST at least define can_write_encap, write_open, and write funcs - */ -static gboolean verify_filehandler_complete(FileHandler fh) { - return ((fh->is_reader || fh->is_writer) && - (!fh->is_reader || - (fh->is_reader && - fh->read_open_ref != LUA_NOREF && - fh->read_ref != LUA_NOREF && - fh->seek_read_ref != LUA_NOREF)) && - (!fh->is_writer || - (fh->is_writer && - fh->can_write_encap_ref != LUA_NOREF && - fh->write_open_ref != LUA_NOREF && - fh->write_ref != LUA_NOREF)) ); -} - - -WSLUA_FUNCTION wslua_register_filehandler(lua_State* L) { - /* Register the FileHandler into Wireshark/tshark, so they can read/write this new format. - All functions and settings must be complete before calling this registration function. - This function cannot be called inside the reading/writing callback functions. */ -#define WSLUA_ARG_register_filehandler_FILEHANDLER 1 /* the FileHandler object to be registered */ - FileHandler fh = checkFileHandler(L,WSLUA_ARG_register_filehandler_FILEHANDLER); - - if (in_routine) - return luaL_error(L,"a FileHAndler cannot be registered during reading/writing callback functions"); - - if (fh->registered) - return luaL_error(L,"this FileHandler is already registered"); - - if (!verify_filehandler_complete(fh)) - return luaL_error(L,"this FileHandler is not complete enough to register"); - - if (fh->is_writer) { - fh->finfo.can_write_encap = wslua_dummy_can_write_encap; - fh->finfo.wslua_info = (wtap_wslua_file_info_t*) g_malloc0(sizeof(wtap_wslua_file_info_t)); - fh->finfo.wslua_info->wslua_can_write_encap = wslua_filehandler_can_write_encap; - fh->finfo.wslua_info->wslua_data = (void*)(fh); - fh->finfo.dump_open = wslua_filehandler_dump_open; - } - - fh->file_type = wtap_register_file_type_subtypes(&(fh->finfo),fh->file_type); - - if (fh->is_reader) { - struct open_info oi = { NULL, OPEN_INFO_HEURISTIC, NULL, NULL, NULL, NULL }; - oi.name = fh->finfo.short_name; - oi.open_routine = wslua_filehandler_open; - oi.extensions = fh->finfo.additional_file_extensions; - oi.wslua_data = (void*)(fh); - if (strchr(fh->type,'m') != NULL) { - oi.type = OPEN_INFO_MAGIC; - } else { - oi.type = OPEN_INFO_HEURISTIC; - } - wtap_register_open_info(&oi, (strchr(fh->type,'s') != NULL)); - } - - fh->registered = TRUE; - - lua_pushnumber(L, fh->file_type); - - WSLUA_RETURN(1); /* the new type number for this file reader/write */ -} - -WSLUA_FUNCTION wslua_deregister_filehandler(lua_State* L) { - /* De-register the FileHandler from Wireshark/tshark, so it no longer gets used for reading/writing/display. - This function cannot be called inside the reading/writing callback functions. */ -#define WSLUA_ARG_register_filehandler_FILEHANDLER 1 /* the FileHandler object to be de-registered */ - FileHandler fh = checkFileHandler(L,WSLUA_ARG_register_filehandler_FILEHANDLER); - - if (in_routine) - return luaL_error(L,"A FileHAndler cannot be de-registered during reading/writing callback functions"); - - if (!fh->registered) - return 0; - - /* undo writing stuff, even if it wasn't a writer */ - fh->finfo.can_write_encap = NULL; - if (fh->finfo.wslua_info) { - fh->finfo.wslua_info->wslua_can_write_encap = NULL; - fh->finfo.wslua_info->wslua_data = NULL; - g_free(fh->finfo.wslua_info); - fh->finfo.wslua_info = NULL; - } - fh->finfo.dump_open = NULL; - - if (fh->file_type != WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) - wtap_deregister_file_type_subtype(fh->file_type); - - if (fh->is_reader && wtap_has_open_info(fh->finfo.short_name)) { - wtap_deregister_open_info(fh->finfo.short_name); - } - - fh->registered = FALSE; - - return 0; -} - -/* The folllowing macros generate setter functions for Lua, for the following Lua - function references in _wslua_filehandler struct: - int read_open_ref; - int read_ref; - int seek_read_ref; - int read_close_ref; - int seq_read_close_ref; - int can_write_encap_ref; - int write_open_ref; - int write_ref; - int write_close_ref; -*/ - -/* WSLUA_ATTRIBUTE FileHandler_read_open WO The Lua function to be called when Wireshark opens a file for reading. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfo` object - - The purpose of the Lua function set to this `read_open` field is to check if the file Wireshark is opening is of its type, - for example by checking for magic numbers or trying to parse records in the file, etc. The more can be verified - the better, because Wireshark tries all file readers until it finds one that accepts the file, so accepting an - incorrect file prevents other file readers from reading their files. - - The called Lua function should return true if the file is its type (it accepts it), false if not. The Lua - function must also set the File offset position (using `file:seek()`) to where it wants it to be for its first - `read()` call. - */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,read_open); - -/* WSLUA_ATTRIBUTE FileHandler_read WO The Lua function to be called when Wireshark wants to read a packet from the file. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfo` object - 3. A `FrameInfo` object - - The purpose of the Lua function set to this `read` field is to read the next packet from the file, and setting the parsed/read - packet into the frame buffer using `FrameInfo.data = foo` or `FrameInfo:read_data()`. - - The called Lua function should return the file offset/position number where the packet begins, or false if it hit an - error. The file offset will be saved by Wireshark and passed into the set `seek_read()` Lua function later. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,read); - -/* WSLUA_ATTRIBUTE FileHandler_seek_read WO The Lua function to be called when Wireshark wants to read a packet from the file at the given offset. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfo` object - 3. A `FrameInfo` object - 4. The file offset number previously set by the `read()` function call - */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,seek_read); - -/* WSLUA_ATTRIBUTE FileHandler_read_close WO The Lua function to be called when Wireshark wants to close the read file completely. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfo` object - - It is not necessary to set this field to a Lua function - FileHandler can be registered without doing so - it - is available in case there is memory/state to clear in your script when the file is closed. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,read_close); - -/* WSLUA_ATTRIBUTE FileHandler_seq_read_close WO The Lua function to be called when Wireshark wants to close the sequentially-read file. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfo` object - - It is not necessary to set this field to a Lua - function - FileHandler can be registered without doing so - it is available in case there is memory/state to clear in your script - when the file is closed for the sequential reading portion. After this point, there will be no more calls to `read()`, only `seek_read()`. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,seq_read_close); - - -/* WSLUA_ATTRIBUTE FileHandler_can_write_encap WO The Lua function to be called when Wireshark wants to write a file, - by checking if this file writer can handle the wtap packet encapsulation(s). - - When later called by Wireshark, the Lua function will be given a Lua number, which matches one of the encapsulations - in the Lua `wtap_encaps` table. This might be the `wtap_encap.PER_PACKET` number, meaning the capture contains multiple - encapsulation types, and the file reader should only return true if it can handle multiple encap types in one file. The - function will then be called again, once for each encap type in the file, to make sure it can write each one. - - If the Lua file writer can write the given type of encapsulation into a file, then it returns the boolean true, else false. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,can_write_encap); - -/* WSLUA_ATTRIBUTE FileHandler_write_open WO The Lua function to be called when Wireshark opens a file for writing. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfoConst` object - - The purpose of the Lua function set to this `write_open` field is similar to the read_open callback function: - to initialize things necessary for writing the capture to a file. For example, if the output file format has a - file header, then the file header should be written within this write_open function. - - The called Lua function should return true on success, or false if it hit an error. - - Also make sure to set the `FileHandler.write` (and potentially `FileHandler.write_close`) functions before - returning true from this function. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,write_open); - -/* WSLUA_ATTRIBUTE FileHandler_write WO The Lua function to be called when Wireshark wants to write a packet to the file. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfoConst` object - 3. A `FrameInfoConst` object of the current frame/packet to be written - - The purpose of the Lua function set to this `write` field is to write the next packet to the file. - - The called Lua function should return true on success, or false if it hit an error. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,write); - -/* WSLUA_ATTRIBUTE FileHandler_write_close WO The Lua function to be called when Wireshark wants to close the written file. - - When later called by Wireshark, the Lua function will be given: - 1. A `File` object - 2. A `CaptureInfoConst` object - - It is not necessary to set this field to a Lua function - `FileHandler` can be registered without doing so - it is available - in case there is memory/state to clear in your script when the file is closed. */ -WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,write_close); - -/* generate other member accessors setters/getters */ - -/* WSLUA_ATTRIBUTE FileHandler_type RO The internal file type. This is automatically set with a new - number when the FileHandler is registered. */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FileHandler,type,file_type); - -/* WSLUA_ATTRIBUTE FileHandler_extensions RW One or more file extensions that this file type usually uses. - - For readers using heuristics to determine file type, Wireshark will try the readers of the file's - extension first, before trying other readers. But ultimately Wireshark tries all file readers - for any file extension, until it finds one that accepts the file. */ -WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FileHandler,extensions,finfo.additional_file_extensions); -WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(FileHandler,extensions,finfo.additional_file_extensions,TRUE); - -/* WSLUA_ATTRIBUTE FileHandler_writing_must_seek RW true if the ability to seek is required when writing - this file format, else false. - - This will be checked by Wireshark when writing out to compressed - file formats, because seeking is not possible with compressed files. Usually a file writer only - needs to be able to seek if it needs to go back in the file to change something, such as a block or - file length value earlier in the file. */ -WSLUA_ATTRIBUTE_NAMED_BOOLEAN_GETTER(FileHandler,writing_must_seek,finfo.writing_must_seek); -WSLUA_ATTRIBUTE_NAMED_BOOLEAN_SETTER(FileHandler,writing_must_seek,finfo.writing_must_seek); - -/* WSLUA_ATTRIBUTE FileHandler_writes_name_resolution RW true if the file format supports name resolution - records, else false. */ -WSLUA_ATTRIBUTE_NAMED_BOOLEAN_GETTER(FileHandler,writes_name_resolution,finfo.has_name_resolution); -WSLUA_ATTRIBUTE_NAMED_BOOLEAN_SETTER(FileHandler,writes_name_resolution,finfo.has_name_resolution); - -/* WSLUA_ATTRIBUTE FileHandler_supported_comment_types RW set to the bit-wise OR'ed number representing - the type of comments the file writer supports writing, based on the numbers in the `wtap_comments` table. */ -WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FileHandler,supported_comment_types,finfo.supported_comment_types); -WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FileHandler,supported_comment_types,finfo.supported_comment_types,guint32); - -/* 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 FileHandler_attributes[] = { - WSLUA_ATTRIBUTE_WOREG(FileHandler,read_open), - WSLUA_ATTRIBUTE_WOREG(FileHandler,read), - WSLUA_ATTRIBUTE_WOREG(FileHandler,seek_read), - WSLUA_ATTRIBUTE_WOREG(FileHandler,read_close), - WSLUA_ATTRIBUTE_WOREG(FileHandler,seq_read_close), - WSLUA_ATTRIBUTE_WOREG(FileHandler,can_write_encap), - WSLUA_ATTRIBUTE_WOREG(FileHandler,write_open), - WSLUA_ATTRIBUTE_WOREG(FileHandler,write), - WSLUA_ATTRIBUTE_WOREG(FileHandler,write_close), - WSLUA_ATTRIBUTE_ROREG(FileHandler,type), - WSLUA_ATTRIBUTE_RWREG(FileHandler,extensions), - WSLUA_ATTRIBUTE_RWREG(FileHandler,writing_must_seek), - WSLUA_ATTRIBUTE_RWREG(FileHandler,writes_name_resolution), - WSLUA_ATTRIBUTE_RWREG(FileHandler,supported_comment_types), - { NULL, NULL, NULL } -}; - -WSLUA_METHODS FileHandler_methods[] = { - WSLUA_CLASS_FNREG(FileHandler,new), - { NULL, NULL } -}; - -WSLUA_META FileHandler_meta[] = { - WSLUA_CLASS_MTREG(FileHandler,tostring), - { NULL, NULL } -}; - -int FileHandler_register(lua_State* L) { - WSLUA_REGISTER_CLASS(FileHandler); - WSLUA_REGISTER_ATTRIBUTES(FileHandler); - return 0; -} - /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * diff --git a/epan/wslua/wslua_file_common.c b/epan/wslua/wslua_file_common.c new file mode 100644 index 0000000000..8b3bb99a4a --- /dev/null +++ b/epan/wslua/wslua_file_common.c @@ -0,0 +1,205 @@ +/* + * wslua_file_common.c + * + * Wireshark's interface to the Lua Programming Language + * for file handling related source file internal functions. + * + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/************ + * The following is for handling private data for the duration of the file + * read_open/read/close cycle, or write_open/write/write_close cycle. + * In other words it handles the "priv" member of wtap and wtap_dumper, + * but for the Lua script's use. A Lua script can set a Lua table + * to CaptureInfo/CaptureInfoConst and have it saved and retrievable this way. + * We need to offer that, because there needs to be a way for Lua scripts + * to save state for a given file's operations cycle. Since there can be + * two files opened at the same time for the same Lua script (due to reload + * and other such events), the script can't just have one file state. + */ + +#include "wslua_file_common.h" + + +/* create and set the wtap->priv private data for the file instance */ +void create_wth_priv(lua_State* L, wtap *wth) { + file_priv_t *priv = (file_priv_t*)g_malloc(sizeof(file_priv_t)); + + if (wth->priv != NULL) { + luaL_error(L, "Cannot create wtap private data because there already is private data"); + return; + } + priv->table_ref = LUA_NOREF; + wth->priv = (void*) priv; +} + +/* gets the private data table from wtap */ +int get_wth_priv_table_ref(lua_State* L, wtap *wth) { + file_priv_t *priv = (file_priv_t*) wth->priv; + + if (!priv) { + /* shouldn't be possible */ + luaL_error(L, "Cannot get wtap private data: it is null"); + return LUA_NOREF; + } + + /* the following might push a nil, but that's ok */ + lua_rawgeti(L, LUA_REGISTRYINDEX, priv->table_ref); + + return 1; +} + +/* sets the private data to wtap - the table is presumed on top of stack */ +int set_wth_priv_table_ref(lua_State* L, wtap *wth) { + file_priv_t *priv = (file_priv_t*) wth->priv; + + if (!priv) { + /* shouldn't be possible */ + luaL_error(L, "Cannot get wtap private data: it is null"); + return 0; + } + + if (lua_isnil(L, -1)){ + /* user is setting it nil - ok, de-ref any previous one */ + luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); + priv->table_ref = LUA_NOREF; + return 0; + } + + if (!lua_istable(L, -1)) { + luaL_error(L, "The private_table member can only be set to a table or nil"); + return 0; + } + + /* if we had a table already referenced, de-ref it first */ + if (priv->table_ref != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); + } + + priv->table_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; +} + +/* remove, deref, and free the wtap->priv data */ +void remove_wth_priv(lua_State* L, wtap *wth) { + file_priv_t *priv = (file_priv_t*) wth->priv; + + if (!priv) { + /* shouldn't be possible */ + luaL_error(L, "Cannot remove wtap private data: it is null"); + return; + } + + luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); + + g_free(wth->priv); + wth->priv = NULL; +} + +/* create and set the wtap_dumper->priv private data for the file instance */ +void create_wdh_priv(lua_State* L, wtap_dumper *wdh) { + file_priv_t *priv = (file_priv_t*)g_malloc(sizeof(file_priv_t)); + + if (wdh->priv != NULL) { + luaL_error(L, "Cannot create wtap_dumper private data because there already is private data"); + return; + } + priv->table_ref = LUA_NOREF; + wdh->priv = (void*) priv; +} + +/* get the private data from wtap_dumper */ +int get_wdh_priv_table_ref(lua_State* L, wtap_dumper *wdh) { + file_priv_t *priv = (file_priv_t*) wdh->priv; + + if (!priv) { + /* shouldn't be possible */ + luaL_error(L, "Cannot get wtap_dumper private data: it is null"); + return LUA_NOREF; + } + + /* the following might push a nil, but that's ok */ + lua_rawgeti(L, LUA_REGISTRYINDEX, priv->table_ref); + + return 1; +} + +/* sets the private data to wtap - the table is presumed on top of stack */ +int set_wdh_priv_table_ref(lua_State* L, wtap_dumper *wdh) { + file_priv_t *priv = (file_priv_t*) wdh->priv; + + if (!priv) { + /* shouldn't be possible */ + luaL_error(L, "Cannot get wtap private data: it is null"); + return 0; + } + + if (lua_isnil(L, -1)){ + /* user is setting it nil - ok, de-ref any previous one */ + luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); + priv->table_ref = LUA_NOREF; + return 0; + } + + if (!lua_istable(L, -1)) { + luaL_error(L, "The private_table member can only be set to a table or nil"); + return 0; + } + + /* if we had a table already referenced, de-ref it first */ + if (priv->table_ref != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); + } + + priv->table_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; +} + +/* remove and deref the wtap_dumper->priv data */ +void remove_wdh_priv(lua_State* L, wtap_dumper *wdh) { + file_priv_t *priv = (file_priv_t*) wdh->priv; + + if (!priv) { + /* shouldn't be possible */ + luaL_error(L, "Cannot remove wtap_dumper private data: it is null"); + return; + } + + luaL_unref(L, LUA_REGISTRYINDEX, priv->table_ref); + /* we do NOT free wtap_dumper's priv member - wtap_dump_close() free's it */ +} + + +/* + * 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: + */ diff --git a/epan/wslua/wslua_file_common.h b/epan/wslua/wslua_file_common.h new file mode 100644 index 0000000000..f581e8dc2b --- /dev/null +++ b/epan/wslua/wslua_file_common.h @@ -0,0 +1,86 @@ +/* + * wslua_file_common.h + * + * Wireshark's interface to the Lua Programming Language + * for file handling related source files. + * + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +/* See wslua_file_common.c for details */ + +#include "config.h" + +#include "wslua.h" +#include <wiretap/wtap-int.h> + +/* this is way overkill for this one member, but in case we need to add + more in the future, the plumbing will be here */ +typedef struct _file_priv_t { + int table_ref; +} file_priv_t; + +/* create and set the wtap->priv private data for the file instance */ +extern void create_wth_priv(lua_State* L, wtap *wth); + +/* gets the private data table from wtap */ +extern int get_wth_priv_table_ref(lua_State* L, wtap *wth); + +/* sets the private data to wtap - the table is presumed on top of stack */ +extern int set_wth_priv_table_ref(lua_State* L, wtap *wth); + +/* remove, deref, and free the wtap->priv data */ +extern void remove_wth_priv(lua_State* L, wtap *wth); + +/* create and set the wtap_dumper->priv private data for the file instance */ +extern void create_wdh_priv(lua_State* L, wtap_dumper *wdh); + +/* get the private data from wtap_dumper */ +extern int get_wdh_priv_table_ref(lua_State* L, wtap_dumper *wdh); + +/* sets the private data to wtap - the table is presumed on top of stack */ +extern int set_wdh_priv_table_ref(lua_State* L, wtap_dumper *wdh); + +/* remove and deref the wtap_dumper->priv data */ +extern void remove_wdh_priv(lua_State* L, wtap_dumper *wdh); + +/* implemented in other c files than wslua_file_common.c */ +extern CaptureInfo* push_CaptureInfo(lua_State* L, wtap *wth, const gboolean first_time); +extern CaptureInfoConst* push_CaptureInfoConst(lua_State* L, wtap_dumper *wdh); +extern File* push_File(lua_State* L, FILE_T ft); +extern File* push_Wdh(lua_State* L, wtap_dumper *wdh); +extern FrameInfo* push_FrameInfo(lua_State* L, struct wtap_pkthdr *phdr, Buffer* buf); +extern FrameInfoConst* push_FrameInfoConst(lua_State* L, const struct wtap_pkthdr *phdr, const guint8 *pd); + + +/* + * 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: + */ diff --git a/epan/wslua/wslua_file_handler.c b/epan/wslua/wslua_file_handler.c new file mode 100644 index 0000000000..1ea8cb4555 --- /dev/null +++ b/epan/wslua/wslua_file_handler.c @@ -0,0 +1,997 @@ +/* + * wslua_file_handler.c + * + * Wireshark's interface to the Lua Programming Language + * for custom file reading/writing. + * + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "wslua_file_common.h" + + +/* WSLUA_CONTINUE_MODULE File */ + + +WSLUA_CLASS_DEFINE(FileHandler,NOP,NOP); +/* + A FileHandler object, created by a call to FileHandler.new(arg1, arg2, ...). + The FileHandler object lets you create a file-format reader, or writer, or + both, by setting your own read_open/read or write_open/write functions. + + @since 1.11.3 + */ + +static int filehandler_cb_error_handler(lua_State* L) { + const gchar* error = lua_tostring(L,1); + const gchar* functype = luaL_optstring(L, lua_upvalueindex(1), "UNKNOWN"); + report_failure("Lua: Error During execution of FileHandler %s callback:\n %s",functype,error); + lua_pop(L, 1); + return 0; +} + +static int push_error_handler(lua_State* L, const gchar* funcname) { + lua_pushstring(L, funcname); + lua_pushcclosure(L, filehandler_cb_error_handler, 1); + return 1; +} + + +/* During file routines, we cannot allow the FileHandler to get de-registered, since + that would change the GArray's in file_access.c and hilarity would ensue. So we + set this to true right before pcall(), and back to false afterwards */ +static gboolean in_routine = FALSE; + +/* This does the verification and setup common to all open/read/seek_read/close routines */ +#define INIT_FILEHANDLER_ROUTINE(name,retval) \ + if (!fh) { \ + g_warning("Error in file %s: no Lua FileHandler object", #name); \ + return retval; \ + } \ + if (!fh->registered) { \ + g_warning("Error in file %s: Lua FileHandler is not registered", #name); \ + return retval; \ + } \ + if (!fh->L) { \ + g_warning("Error in file %s: no FileHandler Lua state", #name); \ + return retval; \ + } \ + if (fh->name##_ref == LUA_NOREF) { \ + g_warning("Error in file %s: no FileHandler %s routine reference", #name, #name); \ + return retval; \ + } \ + L = fh->L; \ + lua_settop(L,0); \ + push_error_handler(L, #name " routine"); \ + lua_rawgeti(L, LUA_REGISTRYINDEX, fh->name##_ref); \ + if (!lua_isfunction(L, -1)) { \ + g_warning("Error in file %s: no FileHandler %s routine function in Lua", #name, #name); \ + return retval; \ + } \ + /* now guard against de-registering during pcall() */ \ + in_routine = TRUE; + +#define END_FILEHANDLER_ROUTINE() \ + /* now allow de-registering again */ \ + in_routine = TRUE; + + +/* LUA_ERRGCMM is in Lua 5.2 only - making it 9 disables it */ +#ifndef LUA_ERRGCMM +#define LUA_ERRGCMM 9 +#endif + +#define CASE_ERROR(name) \ + case LUA_ERRRUN: \ + g_warning("Run-time error while calling FileHandler %s routine", name); \ + break; \ + case LUA_ERRMEM: \ + g_warning("Memory alloc error while calling FileHandler %s routine", name); \ + break; \ + case LUA_ERRERR: \ + g_warning("Error in error handling while calling FileHandler %s routine", name); \ + break; \ + case LUA_ERRGCMM: \ + g_warning("Error in garbage collector while calling FileHandler %s routine", name); \ + break; \ + default: \ + g_assert_not_reached(); \ + break; + +#define CASE_ERROR_ERRINFO(name) \ + case LUA_ERRRUN: \ + g_warning("Run-time error while calling FileHandler %s routine", name); \ + *err_info = g_strdup_printf("Run-time error while calling FileHandler %s routine", name); \ + break; \ + case LUA_ERRMEM: \ + g_warning("Memory alloc error while calling FileHandler %s routine", name); \ + *err_info = g_strdup_printf("Memory alloc error while calling FileHandler %s routine", name); \ + break; \ + case LUA_ERRERR: \ + g_warning("Error in error handling while calling FileHandler %s routine", name); \ + *err_info = g_strdup_printf("Error in error handling while calling FileHandler %s routine", name); \ + break; \ + case LUA_ERRGCMM: \ + g_warning("Error in garbage collector while calling FileHandler %s routine", name); \ + *err_info = g_strdup_printf("Error in garbage collector while calling FileHandler %s routine", name); \ + break; \ + default: \ + g_assert_not_reached(); \ + break; + + +/* some declarations */ +static gboolean +wslua_filehandler_read(wtap *wth, int *err, gchar **err_info, + gint64 *data_offset); +static gboolean +wslua_filehandler_seek_read(wtap *wth, gint64 seek_off, + struct wtap_pkthdr *phdr, Buffer *buf, + int *err, gchar **err_info); +static void +wslua_filehandler_close(wtap *wth); +static void +wslua_filehandler_sequential_close(wtap *wth); + + +/* This is our one-and-only open routine for file handling. When called by + * file_access.c, the wtap wth argument has a void* wslua_data that holds the specific + * FileHandler for the specific registered file format reader. It has this because + * we passed it in when we registered the open routine. + * The open_file_* routines should return: + * -1 on an I/O error; + * 1 if the file they're reading is one of the types it handles; + * 0 if the file they're reading isn't the type they're checking for. + * If the routine handles this type of file, it should set the "file_type" + * field in the "struct wtap" to the type of the file. + */ +static wtap_open_return_val +wslua_filehandler_open(wtap *wth, int *err, gchar **err_info) +{ + FileHandler fh = (FileHandler)(wth->wslua_data); + wtap_open_return_val retval = WTAP_OPEN_NOT_MINE; + lua_State* L = NULL; + File *fp = NULL; + CaptureInfo *fc = NULL; + + INIT_FILEHANDLER_ROUTINE(read_open,WTAP_OPEN_NOT_MINE); + + create_wth_priv(L, wth); + + fp = push_File(L, wth->fh); + fc = push_CaptureInfo(L, wth, TRUE); + + errno = WTAP_ERR_CANT_OPEN; + switch ( lua_pcall(L,2,1,1) ) { + case 0: + retval = (wtap_open_return_val)wslua_optboolint(L,-1,0); + break; + CASE_ERROR_ERRINFO("read_open") + } + + END_FILEHANDLER_ROUTINE(); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + + if (retval == WTAP_OPEN_MINE) { + /* this is our file type - set the routines and settings into wtap */ + + if (fh->read_ref != LUA_NOREF) { + wth->subtype_read = wslua_filehandler_read; + } + else { + g_warning("Lua file format module lacks a read routine"); + return WTAP_OPEN_NOT_MINE; + } + + if (fh->seek_read_ref != LUA_NOREF) { + wth->subtype_seek_read = wslua_filehandler_seek_read; + } + else { + g_warning("Lua file format module lacks a seek-read routine"); + return WTAP_OPEN_NOT_MINE; + } + + /* it's ok to not have a close routine */ + if (fh->read_close_ref != LUA_NOREF) + wth->subtype_close = wslua_filehandler_close; + else + wth->subtype_close = NULL; + + /* it's ok to not have a sequential close routine */ + if (fh->seq_read_close_ref != LUA_NOREF) + wth->subtype_sequential_close = wslua_filehandler_sequential_close; + else + wth->subtype_sequential_close = NULL; + + wth->file_type_subtype = fh->file_type; + } + else if (retval == WTAP_OPEN_ERROR) { + /* open error - we *must* return an error code! */ + if (err) { + *err = WTAP_ERR_CANT_OPEN; + } + } + else if (retval == WTAP_OPEN_NOT_MINE) { + /* not our file type */ + remove_wth_priv(L, wth); + } + else { + /* not a valid return type */ + g_warning("FileHandler read_open routine returned %d", retval); + if (err) { + *err = WTAP_ERR_INTERNAL; + } + retval = WTAP_OPEN_ERROR; + } + + lua_settop(L,0); + return retval; +} + +/* The classic wtap read routine. This returns TRUE if it found the next packet, + * else FALSE. + * If it finds a frame/packet, it should set the pseudo-header info (ie, let Lua set it). + * Also Lua needs to set data_offset to the beginning of the line we're returning. + * This will be the seek_off parameter when this frame is re-read. +*/ +static gboolean +wslua_filehandler_read(wtap *wth, int *err, gchar **err_info, + gint64 *data_offset) +{ + FileHandler fh = (FileHandler)(wth->wslua_data); + int retval = -1; + lua_State* L = NULL; + File *fp = NULL; + CaptureInfo *fc = NULL; + FrameInfo *fi = NULL; + + INIT_FILEHANDLER_ROUTINE(read,FALSE); + + /* Reset errno */ + if (err) { + *err = errno = 0; + } + + wth->phdr.opt_comment = NULL; + + fp = push_File(L, wth->fh); + fc = push_CaptureInfo(L, wth, FALSE); + fi = push_FrameInfo(L, &wth->phdr, wth->frame_buffer); + + switch ( lua_pcall(L,3,1,1) ) { + case 0: + if (lua_isnumber(L,-1)) { + *data_offset = wslua_togint64(L, -1); + retval = 1; + break; + } + retval = wslua_optboolint(L,-1,0); + break; + CASE_ERROR_ERRINFO("read") + } + + END_FILEHANDLER_ROUTINE(); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + (*fi)->expired = TRUE; + lua_settop(L,0); + + return (retval == 1); +} + +/* Classic wtap seek_read function, called by wtap core. This must return TRUE on + * success, FALSE on error. + */ +static gboolean +wslua_filehandler_seek_read(wtap *wth, gint64 seek_off, + struct wtap_pkthdr *phdr, Buffer *buf, + int *err, gchar **err_info) +{ + FileHandler fh = (FileHandler)(wth->wslua_data); + int retval = -1; + lua_State* L = NULL; + File *fp = NULL; + CaptureInfo *fc = NULL; + FrameInfo *fi = NULL; + + INIT_FILEHANDLER_ROUTINE(seek_read,FALSE); + + /* Reset errno */ + if (err) { + *err = errno = 0; + } + phdr->opt_comment = NULL; + + fp = push_File(L, wth->random_fh); + fc = push_CaptureInfo(L, wth, FALSE); + fi = push_FrameInfo(L, phdr, buf); + lua_pushnumber(L, (lua_Number)seek_off); + + switch ( lua_pcall(L,4,1,1) ) { + case 0: + if (lua_isstring(L,-1)) { + size_t len = 0; + const gchar* fd = lua_tolstring(L, -1, &len); + if (len < WTAP_MAX_PACKET_SIZE) + memcpy(ws_buffer_start_ptr(buf), fd, len); + retval = 1; + break; + } + retval = wslua_optboolint(L,-1,0); + break; + CASE_ERROR_ERRINFO("seek_read") + } + + END_FILEHANDLER_ROUTINE(); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + (*fi)->expired = TRUE; + lua_settop(L,0); + + return (retval == 1); +} + +/* Classic wtap close function, called by wtap core. + */ +static void +wslua_filehandler_close(wtap *wth) +{ + FileHandler fh = (FileHandler)(wth->wslua_data); + lua_State* L = NULL; + File *fp = NULL; + CaptureInfo *fc = NULL; + + INIT_FILEHANDLER_ROUTINE(read_close,); + + fp = push_File(L, wth->fh); + fc = push_CaptureInfo(L, wth, FALSE); + + switch ( lua_pcall(L,2,1,1) ) { + case 0: + break; + CASE_ERROR("read_close") + } + + END_FILEHANDLER_ROUTINE(); + + remove_wth_priv(L, wth); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + lua_settop(L,0); + + return; +} + +/* Classic wtap sequential close function, called by wtap core. + */ +static void +wslua_filehandler_sequential_close(wtap *wth) +{ + FileHandler fh = (FileHandler)(wth->wslua_data); + lua_State* L = NULL; + File *fp = NULL; + CaptureInfo *fc = NULL; + + INIT_FILEHANDLER_ROUTINE(seq_read_close,); + + fp = push_File(L, wth->fh); + fc = push_CaptureInfo(L, wth, FALSE); + + switch ( lua_pcall(L,2,1,1) ) { + case 0: + break; + CASE_ERROR("seq_read_close") + } + + END_FILEHANDLER_ROUTINE(); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + lua_settop(L,0); + + return; +} + + +/* basically a dummy function to use for can_write_encap so that the caller calls + * wslua_can_write_encap instead (which will be wslua_filehandler_can_write_encap) + */ +static int +wslua_dummy_can_write_encap(int encap _U_) +{ + return WTAP_ERR_CHECK_WSLUA; +} + +/* Similar to the classic wtap can_write_encap function. + * This returns 0 if the encap is ok for this file type. + */ +static int +wslua_filehandler_can_write_encap(int encap, void* data) +{ + FileHandler fh = (FileHandler)(data); + int retval = WTAP_ERR_UNWRITABLE_ENCAP; + lua_State* L = NULL; + + INIT_FILEHANDLER_ROUTINE(can_write_encap,WTAP_ERR_INTERNAL); + + lua_pushnumber(L, encap); + + switch ( lua_pcall(L,1,1,1) ) { + case 0: + retval = wslua_optboolint(L,-1,WTAP_ERR_UNWRITABLE_ENCAP); + break; + CASE_ERROR("can_write_encap") + } + + END_FILEHANDLER_ROUTINE(); + + /* the retval we got was either a 1 for true, 0 for false, or WTAP_ERR_UNWRITABLE_ENCAP; + but can_write_encap() expects 0 to be true/yes */ + if (retval == 1) { + retval = 0; + } else if (retval == 0) { + retval = WTAP_ERR_UNWRITABLE_ENCAP; + } + + return retval; +} + +/* some declarations */ +static gboolean +wslua_filehandler_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, + const guint8 *pd, int *err, gchar **err_info); +static gboolean +wslua_filehandler_dump_close(wtap_dumper *wdh, int *err); + + +/* The classic wtap dump_open function. + * This returns 1 (TRUE) on success. + */ +static int +wslua_filehandler_dump_open(wtap_dumper *wdh, int *err) +{ + FileHandler fh = (FileHandler)(wdh->wslua_data); + int retval = 0; + lua_State* L = NULL; + File *fp = NULL; + CaptureInfoConst *fc = NULL; + + INIT_FILEHANDLER_ROUTINE(write_open,0); + + create_wdh_priv(L, wdh); + + fp = push_Wdh(L, wdh); + fc = push_CaptureInfoConst(L,wdh); + + /* Reset err */ + if (err) { + *err = 0; + } + + switch ( lua_pcall(L,2,1,1) ) { + case 0: + retval = wslua_optboolint(L,-1,0); + break; + CASE_ERROR("write_open") + } + + END_FILEHANDLER_ROUTINE(); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + + if (retval == 1) { + /* this is our file type - set the routines and settings into wtap */ + + if (fh->write_ref != LUA_NOREF) { + wdh->subtype_write = wslua_filehandler_dump; + } + else { + g_warning("FileHandler was not set with a write function, even though write_open() returned true"); + return 0; + } + + /* it's ok to not have a close routine */ + if (fh->write_close_ref != LUA_NOREF) + wdh->subtype_close = wslua_filehandler_dump_close; + else + wdh->subtype_close = NULL; + } + else { + /* not our file type? */ + remove_wdh_priv(L, wdh); + } + + return retval; +} + +/* The classic wtap dump routine. This returns TRUE if it writes the current packet, + * else FALSE. +*/ +static gboolean +wslua_filehandler_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, + const guint8 *pd, int *err, gchar **err_info _U_) +{ + FileHandler fh = (FileHandler)(wdh->wslua_data); + int retval = -1; + lua_State* L = NULL; + File *fp = NULL; + CaptureInfoConst *fc = NULL; + FrameInfoConst *fi = NULL; + + INIT_FILEHANDLER_ROUTINE(write,FALSE); + + /* Reset errno */ + if (err) { + *err = errno = 0; + } + + fp = push_Wdh(L, wdh); + fc = push_CaptureInfoConst(L,wdh); + fi = push_FrameInfoConst(L, phdr, pd); + + errno = WTAP_ERR_CANT_WRITE; + switch ( lua_pcall(L,3,1,1) ) { + case 0: + retval = wslua_optboolint(L,-1,0); + break; + CASE_ERROR("write") + } + + END_FILEHANDLER_ROUTINE(); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + (*fi)->expired = TRUE; + + return (retval == 1); +} + +/* The classic wtap dump_close routine. This returns TRUE if it closes cleanly, + * else FALSE. +*/ +static gboolean +wslua_filehandler_dump_close(wtap_dumper *wdh, int *err) +{ + FileHandler fh = (FileHandler)(wdh->wslua_data); + int retval = -1; + lua_State* L = NULL; + File *fp = NULL; + CaptureInfoConst *fc = NULL; + + INIT_FILEHANDLER_ROUTINE(write_close,FALSE); + + /* Reset errno */ + if (err) { + *err = errno = 0; + } + + fp = push_Wdh(L, wdh); + fc = push_CaptureInfoConst(L,wdh); + + errno = WTAP_ERR_CANT_CLOSE; + switch ( lua_pcall(L,2,1,1) ) { + case 0: + retval = wslua_optboolint(L,-1,0); + break; + CASE_ERROR("write_close") + } + + END_FILEHANDLER_ROUTINE(); + + remove_wdh_priv(L, wdh); + + (*fp)->expired = TRUE; + (*fc)->expired = TRUE; + + return (retval == 1); +} + + +WSLUA_CONSTRUCTOR FileHandler_new(lua_State* L) { + /* Creates a new FileHandler */ +#define WSLUA_ARG_FileHandler_new_NAME 1 /* The name of the file type, for display purposes only. E.g., "Wireshark - pcapng" */ +#define WSLUA_ARG_FileHandler_new_SHORTNAME 2 /* the file type short name, used as a shortcut in various places. E.g., "pcapng". Note: the name cannot already be in use. */ +#define WSLUA_ARG_FileHandler_new_DESCRIPTION 3 /* Descriptive text about this file format, for display purposes only */ +#define WSLUA_ARG_FileHandler_new_TYPE 4 /* The type of FileHandler, "r"/"w"/"rw" for reader/writer/both, include "m" for magic, "s" for strong heuristic */ + + const gchar* name = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_NAME); + const gchar* short_name = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_SHORTNAME); + const gchar* desc = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_DESCRIPTION); + const gchar* type = luaL_checkstring(L,WSLUA_ARG_FileHandler_new_TYPE); + FileHandler fh = (FileHandler) g_malloc0(sizeof(struct _wslua_filehandler)); + + fh->is_reader = (strchr(type,'r') != NULL) ? TRUE : FALSE; + fh->is_writer = (strchr(type,'w') != NULL) ? TRUE : FALSE; + + if (fh->is_reader && wtap_has_open_info(short_name)) { + return luaL_error(L, "FileHandler.new: '%s' short name already exists for a reader!", short_name); + } + + if (fh->is_writer && wtap_short_string_to_file_type_subtype(short_name) > -1) { + return luaL_error(L, "FileHandler.new: '%s' short name already exists for a writer!", short_name); + } + + fh->type = g_strdup(type); + fh->finfo.name = g_strdup(name); + fh->finfo.short_name = g_strdup(short_name); + fh->finfo.default_file_extension = NULL; + fh->finfo.additional_file_extensions = NULL; + fh->finfo.writing_must_seek = FALSE; + fh->finfo.has_name_resolution = FALSE; + fh->finfo.can_write_encap = NULL; + fh->finfo.dump_open = NULL; + /* this will be set to a new file_type when registered */ + fh->file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; + + fh->description = g_strdup(desc); + fh->L = L; + fh->read_open_ref = LUA_NOREF; + fh->read_ref = LUA_NOREF; + fh->seek_read_ref = LUA_NOREF; + fh->read_close_ref = LUA_NOREF; + fh->seq_read_close_ref = LUA_NOREF; + fh->write_open_ref = LUA_NOREF; + fh->write_ref = LUA_NOREF; + fh->write_close_ref = LUA_NOREF; + fh->can_write_encap_ref = LUA_NOREF; + + fh->registered = FALSE; + + pushFileHandler(L,fh); + WSLUA_RETURN(1); /* The newly created FileHandler object */ +} + +WSLUA_METAMETHOD FileHandler__tostring(lua_State* L) { + /* Generates a string of debug info for the FileHandler */ + FileHandler fh = toFileHandler(L,1); + + if (!fh) { + lua_pushstring(L,"FileHandler pointer is NULL!"); + } else { + lua_pushfstring(L, "FileHandler(%s): short-name='%s', description='%s', read_open=%d, read=%d, write=%d", + fh->finfo.name, fh->finfo.short_name, fh->description, fh->read_open_ref, fh->read_ref, fh->write_ref); + } + + WSLUA_RETURN(1); /* String of debug information. */ +} + +static int FileHandler__gc(lua_State* L _U_) { + /* do NOT free FileHandler, it's never free'd */ + /* TODO: handle this and other Lua things that should be free'd on exit, in a better way */ + return 0; +} + +/* A Lua File handler must not be expired, and must be either a reader or writer, and + * a *reader* one MUST at least define read_open, read, and seek_read funcs; and + * a *writer* one MUST at least define can_write_encap, write_open, and write funcs + */ +static gboolean verify_filehandler_complete(FileHandler fh) { + return ((fh->is_reader || fh->is_writer) && + (!fh->is_reader || + (fh->is_reader && + fh->read_open_ref != LUA_NOREF && + fh->read_ref != LUA_NOREF && + fh->seek_read_ref != LUA_NOREF)) && + (!fh->is_writer || + (fh->is_writer && + fh->can_write_encap_ref != LUA_NOREF && + fh->write_open_ref != LUA_NOREF && + fh->write_ref != LUA_NOREF)) ); +} + + +WSLUA_FUNCTION wslua_register_filehandler(lua_State* L) { + /* Register the FileHandler into Wireshark/tshark, so they can read/write this new format. + All functions and settings must be complete before calling this registration function. + This function cannot be called inside the reading/writing callback functions. */ +#define WSLUA_ARG_register_filehandler_FILEHANDLER 1 /* the FileHandler object to be registered */ + FileHandler fh = checkFileHandler(L,WSLUA_ARG_register_filehandler_FILEHANDLER); + + if (in_routine) + return luaL_error(L,"a FileHAndler cannot be registered during reading/writing callback functions"); + + if (fh->registered) + return luaL_error(L,"this FileHandler is already registered"); + + if (!verify_filehandler_complete(fh)) + return luaL_error(L,"this FileHandler is not complete enough to register"); + + if (fh->is_writer) { + fh->finfo.can_write_encap = wslua_dummy_can_write_encap; + fh->finfo.wslua_info = (wtap_wslua_file_info_t*) g_malloc0(sizeof(wtap_wslua_file_info_t)); + fh->finfo.wslua_info->wslua_can_write_encap = wslua_filehandler_can_write_encap; + fh->finfo.wslua_info->wslua_data = (void*)(fh); + fh->finfo.dump_open = wslua_filehandler_dump_open; + } + + fh->file_type = wtap_register_file_type_subtypes(&(fh->finfo),fh->file_type); + + if (fh->is_reader) { + struct open_info oi = { NULL, OPEN_INFO_HEURISTIC, NULL, NULL, NULL, NULL }; + oi.name = fh->finfo.short_name; + oi.open_routine = wslua_filehandler_open; + oi.extensions = fh->finfo.additional_file_extensions; + oi.wslua_data = (void*)(fh); + if (strchr(fh->type,'m') != NULL) { + oi.type = OPEN_INFO_MAGIC; + } else { + oi.type = OPEN_INFO_HEURISTIC; + } + wtap_register_open_info(&oi, (strchr(fh->type,'s') != NULL)); + } + + fh->registered = TRUE; + + lua_pushnumber(L, fh->file_type); + + WSLUA_RETURN(1); /* the new type number for this file reader/write */ +} + +WSLUA_FUNCTION wslua_deregister_filehandler(lua_State* L) { + /* De-register the FileHandler from Wireshark/tshark, so it no longer gets used for reading/writing/display. + This function cannot be called inside the reading/writing callback functions. */ +#define WSLUA_ARG_register_filehandler_FILEHANDLER 1 /* the FileHandler object to be de-registered */ + FileHandler fh = checkFileHandler(L,WSLUA_ARG_register_filehandler_FILEHANDLER); + + if (in_routine) + return luaL_error(L,"A FileHAndler cannot be de-registered during reading/writing callback functions"); + + if (!fh->registered) + return 0; + + /* undo writing stuff, even if it wasn't a writer */ + fh->finfo.can_write_encap = NULL; + if (fh->finfo.wslua_info) { + fh->finfo.wslua_info->wslua_can_write_encap = NULL; + fh->finfo.wslua_info->wslua_data = NULL; + g_free(fh->finfo.wslua_info); + fh->finfo.wslua_info = NULL; + } + fh->finfo.dump_open = NULL; + + if (fh->file_type != WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) + wtap_deregister_file_type_subtype(fh->file_type); + + if (fh->is_reader && wtap_has_open_info(fh->finfo.short_name)) { + wtap_deregister_open_info(fh->finfo.short_name); + } + + fh->registered = FALSE; + + return 0; +} + +/* The folllowing macros generate setter functions for Lua, for the following Lua + function references in _wslua_filehandler struct: + int read_open_ref; + int read_ref; + int seek_read_ref; + int read_close_ref; + int seq_read_close_ref; + int can_write_encap_ref; + int write_open_ref; + int write_ref; + int write_close_ref; +*/ + +/* WSLUA_ATTRIBUTE FileHandler_read_open WO The Lua function to be called when Wireshark opens a file for reading. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfo` object + + The purpose of the Lua function set to this `read_open` field is to check if the file Wireshark is opening is of its type, + for example by checking for magic numbers or trying to parse records in the file, etc. The more can be verified + the better, because Wireshark tries all file readers until it finds one that accepts the file, so accepting an + incorrect file prevents other file readers from reading their files. + + The called Lua function should return true if the file is its type (it accepts it), false if not. The Lua + function must also set the File offset position (using `file:seek()`) to where it wants it to be for its first + `read()` call. + */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,read_open); + +/* WSLUA_ATTRIBUTE FileHandler_read WO The Lua function to be called when Wireshark wants to read a packet from the file. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfo` object + 3. A `FrameInfo` object + + The purpose of the Lua function set to this `read` field is to read the next packet from the file, and setting the parsed/read + packet into the frame buffer using `FrameInfo.data = foo` or `FrameInfo:read_data()`. + + The called Lua function should return the file offset/position number where the packet begins, or false if it hit an + error. The file offset will be saved by Wireshark and passed into the set `seek_read()` Lua function later. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,read); + +/* WSLUA_ATTRIBUTE FileHandler_seek_read WO The Lua function to be called when Wireshark wants to read a packet from the file at the given offset. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfo` object + 3. A `FrameInfo` object + 4. The file offset number previously set by the `read()` function call + */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,seek_read); + +/* WSLUA_ATTRIBUTE FileHandler_read_close WO The Lua function to be called when Wireshark wants to close the read file completely. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfo` object + + It is not necessary to set this field to a Lua function - FileHandler can be registered without doing so - it + is available in case there is memory/state to clear in your script when the file is closed. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,read_close); + +/* WSLUA_ATTRIBUTE FileHandler_seq_read_close WO The Lua function to be called when Wireshark wants to close the sequentially-read file. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfo` object + + It is not necessary to set this field to a Lua + function - FileHandler can be registered without doing so - it is available in case there is memory/state to clear in your script + when the file is closed for the sequential reading portion. After this point, there will be no more calls to `read()`, only `seek_read()`. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,seq_read_close); + + +/* WSLUA_ATTRIBUTE FileHandler_can_write_encap WO The Lua function to be called when Wireshark wants to write a file, + by checking if this file writer can handle the wtap packet encapsulation(s). + + When later called by Wireshark, the Lua function will be given a Lua number, which matches one of the encapsulations + in the Lua `wtap_encaps` table. This might be the `wtap_encap.PER_PACKET` number, meaning the capture contains multiple + encapsulation types, and the file reader should only return true if it can handle multiple encap types in one file. The + function will then be called again, once for each encap type in the file, to make sure it can write each one. + + If the Lua file writer can write the given type of encapsulation into a file, then it returns the boolean true, else false. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,can_write_encap); + +/* WSLUA_ATTRIBUTE FileHandler_write_open WO The Lua function to be called when Wireshark opens a file for writing. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfoConst` object + + The purpose of the Lua function set to this `write_open` field is similar to the read_open callback function: + to initialize things necessary for writing the capture to a file. For example, if the output file format has a + file header, then the file header should be written within this write_open function. + + The called Lua function should return true on success, or false if it hit an error. + + Also make sure to set the `FileHandler.write` (and potentially `FileHandler.write_close`) functions before + returning true from this function. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,write_open); + +/* WSLUA_ATTRIBUTE FileHandler_write WO The Lua function to be called when Wireshark wants to write a packet to the file. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfoConst` object + 3. A `FrameInfoConst` object of the current frame/packet to be written + + The purpose of the Lua function set to this `write` field is to write the next packet to the file. + + The called Lua function should return true on success, or false if it hit an error. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,write); + +/* WSLUA_ATTRIBUTE FileHandler_write_close WO The Lua function to be called when Wireshark wants to close the written file. + + When later called by Wireshark, the Lua function will be given: + 1. A `File` object + 2. A `CaptureInfoConst` object + + It is not necessary to set this field to a Lua function - `FileHandler` can be registered without doing so - it is available + in case there is memory/state to clear in your script when the file is closed. */ +WSLUA_ATTRIBUTE_FUNC_SETTER(FileHandler,write_close); + +/* generate other member accessors setters/getters */ + +/* WSLUA_ATTRIBUTE FileHandler_type RO The internal file type. This is automatically set with a new + number when the FileHandler is registered. */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FileHandler,type,file_type); + +/* WSLUA_ATTRIBUTE FileHandler_extensions RW One or more file extensions that this file type usually uses. + + For readers using heuristics to determine file type, Wireshark will try the readers of the file's + extension first, before trying other readers. But ultimately Wireshark tries all file readers + for any file extension, until it finds one that accepts the file. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FileHandler,extensions,finfo.additional_file_extensions); +WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(FileHandler,extensions,finfo.additional_file_extensions,TRUE); + +/* WSLUA_ATTRIBUTE FileHandler_writing_must_seek RW true if the ability to seek is required when writing + this file format, else false. + + This will be checked by Wireshark when writing out to compressed + file formats, because seeking is not possible with compressed files. Usually a file writer only + needs to be able to seek if it needs to go back in the file to change something, such as a block or + file length value earlier in the file. */ +WSLUA_ATTRIBUTE_NAMED_BOOLEAN_GETTER(FileHandler,writing_must_seek,finfo.writing_must_seek); +WSLUA_ATTRIBUTE_NAMED_BOOLEAN_SETTER(FileHandler,writing_must_seek,finfo.writing_must_seek); + +/* WSLUA_ATTRIBUTE FileHandler_writes_name_resolution RW true if the file format supports name resolution + records, else false. */ +WSLUA_ATTRIBUTE_NAMED_BOOLEAN_GETTER(FileHandler,writes_name_resolution,finfo.has_name_resolution); +WSLUA_ATTRIBUTE_NAMED_BOOLEAN_SETTER(FileHandler,writes_name_resolution,finfo.has_name_resolution); + +/* WSLUA_ATTRIBUTE FileHandler_supported_comment_types RW set to the bit-wise OR'ed number representing + the type of comments the file writer supports writing, based on the numbers in the `wtap_comments` table. */ +WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FileHandler,supported_comment_types,finfo.supported_comment_types); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FileHandler,supported_comment_types,finfo.supported_comment_types,guint32); + +/* 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 FileHandler_attributes[] = { + WSLUA_ATTRIBUTE_WOREG(FileHandler,read_open), + WSLUA_ATTRIBUTE_WOREG(FileHandler,read), + WSLUA_ATTRIBUTE_WOREG(FileHandler,seek_read), + WSLUA_ATTRIBUTE_WOREG(FileHandler,read_close), + WSLUA_ATTRIBUTE_WOREG(FileHandler,seq_read_close), + WSLUA_ATTRIBUTE_WOREG(FileHandler,can_write_encap), + WSLUA_ATTRIBUTE_WOREG(FileHandler,write_open), + WSLUA_ATTRIBUTE_WOREG(FileHandler,write), + WSLUA_ATTRIBUTE_WOREG(FileHandler,write_close), + WSLUA_ATTRIBUTE_ROREG(FileHandler,type), + WSLUA_ATTRIBUTE_RWREG(FileHandler,extensions), + WSLUA_ATTRIBUTE_RWREG(FileHandler,writing_must_seek), + WSLUA_ATTRIBUTE_RWREG(FileHandler,writes_name_resolution), + WSLUA_ATTRIBUTE_RWREG(FileHandler,supported_comment_types), + { NULL, NULL, NULL } +}; + +WSLUA_METHODS FileHandler_methods[] = { + WSLUA_CLASS_FNREG(FileHandler,new), + { NULL, NULL } +}; + +WSLUA_META FileHandler_meta[] = { + WSLUA_CLASS_MTREG(FileHandler,tostring), + { NULL, NULL } +}; + +int FileHandler_register(lua_State* L) { + WSLUA_REGISTER_CLASS(FileHandler); + WSLUA_REGISTER_ATTRIBUTES(FileHandler); + 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: + */ diff --git a/epan/wslua/wslua_frame_info.c b/epan/wslua/wslua_frame_info.c new file mode 100644 index 0000000000..95f77844e5 --- /dev/null +++ b/epan/wslua/wslua_frame_info.c @@ -0,0 +1,415 @@ +/* + * 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 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "wslua_file_common.h" + + +/* WSLUA_CONTINUE_MODULE File */ + + +WSLUA_CLASS_DEFINE(FrameInfo,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"),NOP); +/* + 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, struct wtap_pkthdr *phdr, Buffer* buf) { + FrameInfo f = (FrameInfo) g_malloc0(sizeof(struct _wslua_phdr)); + f->phdr = phdr; + 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->phdr) + lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'", + fi->phdr->rec_type, fi->phdr->presence_flags, fi->phdr->caplen, fi->phdr->len, fi->phdr->pkt_encap, fi->phdr->opt_comment); + else + lua_pushstring(L, "FrameInfo phdr 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 phdr/buf it points to */ +static int FrameInfo__gc(lua_State* L _U_) { + FrameInfo fi = toFrameInfo(L,1); + if (fi) + 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->phdr) return 0; + + fi->phdr->ts.secs = nstime->secs; + fi->phdr->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->phdr->ts.secs; + nstime->nsecs = fi->phdr->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->phdr) { + 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->phdr->caplen = (guint32) len; + fi->phdr->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,phdr->rec_type); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,rec_type,phdr->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,phdr->presence_flags); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,flags,phdr->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,phdr->caplen); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,captured_length,phdr->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,phdr->len); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,original_length,phdr->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,phdr->pkt_encap); +WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,encap,phdr->pkt_encap,int); + +/* 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,phdr->opt_comment); +WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(FrameInfo,comment,phdr->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(FrameInfo); + WSLUA_REGISTER_ATTRIBUTES(FrameInfo); + return 0; +} + +WSLUA_CLASS_DEFINE(FrameInfoConst,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"),NOP); +/* + 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 struct wtap_pkthdr *phdr, const guint8 *pd) { + FrameInfoConst f = (FrameInfoConst) g_malloc(sizeof(struct _wslua_const_phdr)); + f->phdr = phdr; + 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->phdr && !fi->expired) + lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'", + fi->phdr->rec_type, fi->phdr->presence_flags, fi->phdr->caplen, fi->phdr->len, fi->phdr->pkt_encap, fi->phdr->opt_comment); + else + lua_pushfstring(L, "FrameInfo has %s", fi->phdr?"expired":"null phdr 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->phdr ? fi->phdr->caplen:0); + int err = 0; + + if (!fi->pd || !fi->phdr || !fh->wdh) { + luaL_error(L, "FrameInfoConst write_data() got null buffer or file pointer internally"); + return 0; + } + + if (len > fi->phdr->caplen) + len = fi->phdr->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_pkthdr it points to */ +static int FrameInfoConst__gc(lua_State* L _U_) { + FrameInfoConst fi = toFrameInfoConst(L,1); + if (fi) + 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->phdr->ts.secs; + nstime->nsecs = fi->phdr->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->phdr) return 0; + + lua_pushlstring(L, fi->pd, fi->phdr->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,phdr->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,phdr->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,phdr->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,phdr->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,phdr->pkt_encap); + +/* WSLUA_ATTRIBUTE FrameInfoConst_comment RO A comment for the packet; nil if there is none. */ +WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FrameInfoConst,comment,phdr->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(FrameInfoConst); + WSLUA_REGISTER_ATTRIBUTES(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: + */ diff --git a/epan/wslua/wslua_nstime.c b/epan/wslua/wslua_nstime.c new file mode 100644 index 0000000000..0c9abdb677 --- /dev/null +++ b/epan/wslua/wslua_nstime.c @@ -0,0 +1,210 @@ +/* + * wslua_nstime.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + + +/* WSLUA_CONTINUE_MODULE Pinfo */ + + +WSLUA_CLASS_DEFINE(NSTime,FAIL_ON_NULL("NSTime"),NOP); +/* NSTime represents a nstime_t. This is an object with seconds and nanoseconds. */ + +WSLUA_CONSTRUCTOR NSTime_new(lua_State *L) { + /* Creates a new NSTime object. */ +#define WSLUA_OPTARG_NSTime_new_SECONDS 1 /* Seconds. */ +#define WSLUA_OPTARG_NSTime_new_NSECONDS 2 /* Nano seconds. */ + NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t)); + + if (!nstime) return 0; + + nstime->secs = (time_t) luaL_optinteger(L,WSLUA_OPTARG_NSTime_new_SECONDS,0); + nstime->nsecs = (int) luaL_optinteger(L,WSLUA_OPTARG_NSTime_new_NSECONDS,0); + + pushNSTime(L,nstime); + + WSLUA_RETURN(1); /* The new NSTime object. */ +} + +WSLUA_METAMETHOD NSTime__call(lua_State* L) { /* Creates a NSTime object. */ +#define WSLUA_OPTARG_NSTime__call_SECONDS 1 /* Seconds. */ +#define WSLUA_OPTARG_NSTime__call_NSECONDS 2 /* Nanoseconds. */ + lua_remove(L,1); /* remove the table */ + WSLUA_RETURN(NSTime_new(L)); /* The new NSTime object. */ +} + +WSLUA_METAMETHOD NSTime__tostring(lua_State* L) { + NSTime nstime = checkNSTime(L,1); + gchar *str; + + str = wmem_strdup_printf(NULL, "%ld.%09d", (long)nstime->secs, nstime->nsecs); + lua_pushstring(L, str); + wmem_free(NULL, str); + + WSLUA_RETURN(1); /* The string representing the nstime. */ +} +WSLUA_METAMETHOD NSTime__add(lua_State* L) { /* Calculates the sum of two NSTimes. */ + NSTime time1 = checkNSTime(L,1); + NSTime time2 = checkNSTime(L,2); + NSTime time3 = (NSTime)g_malloc (sizeof (nstime_t)); + + nstime_sum (time3, time1, time2); + pushNSTime (L, time3); + + return 1; +} + +WSLUA_METAMETHOD NSTime__sub(lua_State* L) { /* Calculates the diff of two NSTimes. */ + NSTime time1 = checkNSTime(L,1); + NSTime time2 = checkNSTime(L,2); + NSTime time3 = (NSTime)g_malloc (sizeof (nstime_t)); + + nstime_delta (time3, time1, time2); + pushNSTime (L, time3); + + return 1; +} + +WSLUA_METAMETHOD NSTime__unm(lua_State* L) { /* Calculates the negative NSTime. */ + NSTime time1 = checkNSTime(L,1); + NSTime time2 = (NSTime)g_malloc (sizeof (nstime_t)); + + nstime_set_zero (time2); + nstime_subtract (time2, time1); + pushNSTime (L, time2); + + return 1; +} + +WSLUA_METAMETHOD NSTime__eq(lua_State* L) { /* Compares two NSTimes. */ + NSTime time1 = checkNSTime(L,1); + NSTime time2 = checkNSTime(L,2); + gboolean result = FALSE; + + if (nstime_cmp(time1, time2) == 0) + result = TRUE; + + lua_pushboolean(L,result); + + return 1; +} + +WSLUA_METAMETHOD NSTime__le(lua_State* L) { /* Compares two NSTimes. */ + NSTime time1 = checkNSTime(L,1); + NSTime time2 = checkNSTime(L,2); + gboolean result = FALSE; + + if (nstime_cmp(time1, time2) <= 0) + result = TRUE; + + lua_pushboolean(L,result); + + return 1; +} + +WSLUA_METAMETHOD NSTime__lt(lua_State* L) { /* Compares two NSTimes. */ + NSTime time1 = checkNSTime(L,1); + NSTime time2 = checkNSTime(L,2); + gboolean result = FALSE; + + if (nstime_cmp(time1, time2) < 0) + result = TRUE; + + lua_pushboolean(L,result); + + return 1; +} + + +/* WSLUA_ATTRIBUTE NSTime_secs RW The NSTime seconds. */ +WSLUA_ATTRIBUTE_NUMBER_GETTER(NSTime,secs); +WSLUA_ATTRIBUTE_NUMBER_SETTER(NSTime,secs,time_t); + +/* WSLUA_ATTRIBUTE NSTime_nsecs RW The NSTime nano seconds. */ +WSLUA_ATTRIBUTE_NUMBER_GETTER(NSTime,nsecs); +WSLUA_ATTRIBUTE_NUMBER_SETTER(NSTime,nsecs,int); + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int NSTime__gc(lua_State* L) { + NSTime nstime = toNSTime(L,1); + + if (!nstime) return 0; + + g_free (nstime); + return 0; +} + +/* 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 NSTime_attributes[] = { + WSLUA_ATTRIBUTE_RWREG(NSTime,secs), + WSLUA_ATTRIBUTE_RWREG(NSTime,nsecs), + { NULL, NULL, NULL } +}; + +WSLUA_METHODS NSTime_methods[] = { + WSLUA_CLASS_FNREG(NSTime,new), + { NULL, NULL } +}; + +WSLUA_META NSTime_meta[] = { + WSLUA_CLASS_MTREG(NSTime,tostring), + WSLUA_CLASS_MTREG(NSTime,add), + WSLUA_CLASS_MTREG(NSTime,sub), + WSLUA_CLASS_MTREG(NSTime,unm), + WSLUA_CLASS_MTREG(NSTime,eq), + WSLUA_CLASS_MTREG(NSTime,le), + WSLUA_CLASS_MTREG(NSTime,lt), + WSLUA_CLASS_MTREG(NSTime,call), + { NULL, NULL } +}; + +int NSTime_register(lua_State* L) { + WSLUA_REGISTER_CLASS(NSTime); + WSLUA_REGISTER_ATTRIBUTES(NSTime); + 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: + */ diff --git a/epan/wslua/wslua_pinfo.c b/epan/wslua/wslua_pinfo.c index ae58c358ae..cf8d5b3922 100644 --- a/epan/wslua/wslua_pinfo.c +++ b/epan/wslua/wslua_pinfo.c @@ -26,33 +26,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include "wslua_pinfo_common.h" #include <epan/wmem/wmem.h> - -/* WSLUA_MODULE Pinfo Obtaining packet information */ - - -#include "wslua.h" - -#include <epan/addr_resolv.h> #include <epan/conversation.h> #include <string.h> +/* WSLUA_MODULE Pinfo Obtaining packet information */ + + /* * Track pointers to wireshark's structures. * see comment on wslua_tvb.c */ static GPtrArray* outstanding_Pinfo = NULL; -static GPtrArray* outstanding_Column = NULL; -static GPtrArray* outstanding_Columns = NULL; static GPtrArray* outstanding_PrivateTable = NULL; CLEAR_OUTSTANDING(Pinfo,expired, TRUE) -CLEAR_OUTSTANDING(Column,expired, TRUE) -CLEAR_OUTSTANDING(Columns,expired, TRUE) CLEAR_OUTSTANDING(PrivateTable,expired, TRUE) Pinfo* push_Pinfo(lua_State* L, packet_info* ws_pinfo) { @@ -66,714 +58,8 @@ Pinfo* push_Pinfo(lua_State* L, packet_info* ws_pinfo) { return pushPinfo(L,pinfo); } -#define PUSH_COLUMN(L,c) {g_ptr_array_add(outstanding_Column,c);pushColumn(L,c);} -#define PUSH_COLUMNS(L,c) {g_ptr_array_add(outstanding_Columns,c);pushColumns(L,c);} #define PUSH_PRIVATE_TABLE(L,c) {g_ptr_array_add(outstanding_PrivateTable,c);pushPrivateTable(L,c);} -WSLUA_CLASS_DEFINE(NSTime,FAIL_ON_NULL("NSTime"),NOP); -/* NSTime represents a nstime_t. This is an object with seconds and nanoseconds. */ - -WSLUA_CONSTRUCTOR NSTime_new(lua_State *L) { - /* Creates a new NSTime object. */ -#define WSLUA_OPTARG_NSTime_new_SECONDS 1 /* Seconds. */ -#define WSLUA_OPTARG_NSTime_new_NSECONDS 2 /* Nano seconds. */ - NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t)); - - if (!nstime) return 0; - - nstime->secs = (time_t) luaL_optinteger(L,WSLUA_OPTARG_NSTime_new_SECONDS,0); - nstime->nsecs = (int) luaL_optinteger(L,WSLUA_OPTARG_NSTime_new_NSECONDS,0); - - pushNSTime(L,nstime); - - WSLUA_RETURN(1); /* The new NSTime object. */ -} - -WSLUA_METAMETHOD NSTime__call(lua_State* L) { /* Creates a NSTime object. */ -#define WSLUA_OPTARG_NSTime__call_SECONDS 1 /* Seconds. */ -#define WSLUA_OPTARG_NSTime__call_NSECONDS 2 /* Nanoseconds. */ - lua_remove(L,1); /* remove the table */ - WSLUA_RETURN(NSTime_new(L)); /* The new NSTime object. */ -} - -WSLUA_METAMETHOD NSTime__tostring(lua_State* L) { - NSTime nstime = checkNSTime(L,1); - gchar *str; - - str = wmem_strdup_printf(NULL, "%ld.%09d", (long)nstime->secs, nstime->nsecs); - lua_pushstring(L, str); - wmem_free(NULL, str); - - WSLUA_RETURN(1); /* The string representing the nstime. */ -} -WSLUA_METAMETHOD NSTime__add(lua_State* L) { /* Calculates the sum of two NSTimes. */ - NSTime time1 = checkNSTime(L,1); - NSTime time2 = checkNSTime(L,2); - NSTime time3 = (NSTime)g_malloc (sizeof (nstime_t)); - - nstime_sum (time3, time1, time2); - pushNSTime (L, time3); - - return 1; -} - -WSLUA_METAMETHOD NSTime__sub(lua_State* L) { /* Calculates the diff of two NSTimes. */ - NSTime time1 = checkNSTime(L,1); - NSTime time2 = checkNSTime(L,2); - NSTime time3 = (NSTime)g_malloc (sizeof (nstime_t)); - - nstime_delta (time3, time1, time2); - pushNSTime (L, time3); - - return 1; -} - -WSLUA_METAMETHOD NSTime__unm(lua_State* L) { /* Calculates the negative NSTime. */ - NSTime time1 = checkNSTime(L,1); - NSTime time2 = (NSTime)g_malloc (sizeof (nstime_t)); - - nstime_set_zero (time2); - nstime_subtract (time2, time1); - pushNSTime (L, time2); - - return 1; -} - -WSLUA_METAMETHOD NSTime__eq(lua_State* L) { /* Compares two NSTimes. */ - NSTime time1 = checkNSTime(L,1); - NSTime time2 = checkNSTime(L,2); - gboolean result = FALSE; - - if (nstime_cmp(time1, time2) == 0) - result = TRUE; - - lua_pushboolean(L,result); - - return 1; -} - -WSLUA_METAMETHOD NSTime__le(lua_State* L) { /* Compares two NSTimes. */ - NSTime time1 = checkNSTime(L,1); - NSTime time2 = checkNSTime(L,2); - gboolean result = FALSE; - - if (nstime_cmp(time1, time2) <= 0) - result = TRUE; - - lua_pushboolean(L,result); - - return 1; -} - -WSLUA_METAMETHOD NSTime__lt(lua_State* L) { /* Compares two NSTimes. */ - NSTime time1 = checkNSTime(L,1); - NSTime time2 = checkNSTime(L,2); - gboolean result = FALSE; - - if (nstime_cmp(time1, time2) < 0) - result = TRUE; - - lua_pushboolean(L,result); - - return 1; -} - - -/* WSLUA_ATTRIBUTE NSTime_secs RW The NSTime seconds. */ -WSLUA_ATTRIBUTE_NUMBER_GETTER(NSTime,secs); -WSLUA_ATTRIBUTE_NUMBER_SETTER(NSTime,secs,time_t); - -/* WSLUA_ATTRIBUTE NSTime_nsecs RW The NSTime nano seconds. */ -WSLUA_ATTRIBUTE_NUMBER_GETTER(NSTime,nsecs); -WSLUA_ATTRIBUTE_NUMBER_SETTER(NSTime,nsecs,int); - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int NSTime__gc(lua_State* L) { - NSTime nstime = toNSTime(L,1); - - if (!nstime) return 0; - - g_free (nstime); - return 0; -} - -/* 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 NSTime_attributes[] = { - WSLUA_ATTRIBUTE_RWREG(NSTime,secs), - WSLUA_ATTRIBUTE_RWREG(NSTime,nsecs), - { NULL, NULL, NULL } -}; - -WSLUA_METHODS NSTime_methods[] = { - WSLUA_CLASS_FNREG(NSTime,new), - { NULL, NULL } -}; - -WSLUA_META NSTime_meta[] = { - WSLUA_CLASS_MTREG(NSTime,tostring), - WSLUA_CLASS_MTREG(NSTime,add), - WSLUA_CLASS_MTREG(NSTime,sub), - WSLUA_CLASS_MTREG(NSTime,unm), - WSLUA_CLASS_MTREG(NSTime,eq), - WSLUA_CLASS_MTREG(NSTime,le), - WSLUA_CLASS_MTREG(NSTime,lt), - WSLUA_CLASS_MTREG(NSTime,call), - { NULL, NULL } -}; - -int NSTime_register(lua_State* L) { - WSLUA_REGISTER_CLASS(NSTime); - WSLUA_REGISTER_ATTRIBUTES(NSTime); - return 0; -} - -WSLUA_CLASS_DEFINE(Address,FAIL_ON_NULL("Address"),NOP); /* Represents an address. */ - -WSLUA_CONSTRUCTOR Address_ip(lua_State* L) { - /* Creates an Address Object representing an IP address. */ - -#define WSLUA_ARG_Address_ip_HOSTNAME 1 /* The address or name of the IP host. */ - Address addr = (Address)g_malloc(sizeof(address)); - guint32* ip_addr = (guint32 *)g_malloc(sizeof(guint32)); - const gchar* name = luaL_checkstring(L,WSLUA_ARG_Address_ip_HOSTNAME); - - if (! get_host_ipaddr(name, (guint32*)ip_addr)) { - *ip_addr = 0; - } - - SET_ADDRESS(addr, AT_IPv4, 4, ip_addr); - pushAddress(L,addr); - WSLUA_RETURN(1); /* The Address object. */ -} - -#if 0 -/* TODO */ -static int Address_ipv6(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_ss7(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_eth(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_sna(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_atalk(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_vines(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_osi(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_arcnet(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_fc(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_string(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_eui64(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_uri(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -static int Address_tipc(lua_State* L) { - Address addr = g_malloc(sizeof(address)); - - SET_ADDRESS(addr, AT_NONE, 4, g_malloc(4)); - - pushAddress(L,addr); - return 1; -} -#endif - -WSLUA_METHODS Address_methods[] = { - WSLUA_CLASS_FNREG(Address,ip), - WSLUA_CLASS_FNREG_ALIAS(Address,ipv4,ip), -#if 0 - WSLUA_CLASS_FNREG(Address,ipv6), - WSLUA_CLASS_FNREG_ALIAS(Address,ss7pc,ss7), - WSLUA_CLASS_FNREG(Address,eth), - WSLUA_CLASS_FNREG(Address,sna}, - WSLUA_CLASS_FNREG(Address,atalk), - WSLUA_CLASS_FNREG(Address,vines), - WSLUA_CLASS_FNREG(Address,osi), - WSLUA_CLASS_FNREG(Address,arcnet), - WSLUA_CLASS_FNREG(Address,fc), - WSLUA_CLASS_FNREG(Address,string), - WSLUA_CLASS_FNREG(Address,eui64), - WSLUA_CLASS_FNREG(Address,uri), - WSLUA_CLASS_FNREG(Address,tipc), -#endif - { NULL, NULL } -}; - -WSLUA_METAMETHOD Address__tostring(lua_State* L) { - Address addr = checkAddress(L,1); - const gchar *str = address_to_display(NULL, addr); - - lua_pushstring(L, str); - - wmem_free(NULL, (void*) str); - - WSLUA_RETURN(1); /* The string representing the address. */ -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int Address__gc(lua_State* L) { - Address addr = toAddress(L,1); - - if (addr) { - g_free((void*)(addr->data)); - g_free((void*)(addr)); - } - - return 0; -} - -WSLUA_METAMETHOD Address__eq(lua_State* L) { /* Compares two Addresses. */ - Address addr1 = checkAddress(L,1); - Address addr2 = checkAddress(L,2); - gboolean result = FALSE; - - if (ADDRESSES_EQUAL(addr1, addr2)) - result = TRUE; - - lua_pushboolean(L,result); - - return 1; -} - -WSLUA_METAMETHOD Address__le(lua_State* L) { /* Compares two Addresses. */ - Address addr1 = checkAddress(L,1); - Address addr2 = checkAddress(L,2); - gboolean result = FALSE; - - if (CMP_ADDRESS(addr1, addr2) <= 0) - result = TRUE; - - lua_pushboolean(L,result); - - return 1; -} - -WSLUA_METAMETHOD Address__lt(lua_State* L) { /* Compares two Addresses. */ - Address addr1 = checkAddress(L,1); - Address addr2 = checkAddress(L,2); - gboolean result = FALSE; - - if (CMP_ADDRESS(addr1, addr2) < 0) - result = TRUE; - - lua_pushboolean(L,result); - - return 1; -} - -WSLUA_META Address_meta[] = { - WSLUA_CLASS_MTREG(Address,tostring), - WSLUA_CLASS_MTREG(Address,eq), - WSLUA_CLASS_MTREG(Address,le), - WSLUA_CLASS_MTREG(Address,lt), - { NULL, NULL } -}; - - -int Address_register(lua_State *L) { - WSLUA_REGISTER_CLASS(Address); - return 0; -} - - -WSLUA_CLASS_DEFINE(Column,FAIL_ON_NULL("Column"),NOP); /* A Column in the packet list. */ - -struct col_names_t { - const gchar* name; - int id; -}; - -static const struct col_names_t colnames[] = { - {"number",COL_NUMBER}, - {"abs_time",COL_ABS_TIME}, - {"utc_time",COL_UTC_TIME}, - {"cls_time",COL_CLS_TIME}, - {"rel_time",COL_REL_TIME}, - {"date",COL_ABS_YMD_TIME}, - {"date_doy",COL_ABS_YDOY_TIME}, - {"utc_date",COL_UTC_YMD_TIME}, - {"utc_date_doy",COL_UTC_YDOY_TIME}, - {"delta_time",COL_DELTA_TIME}, - {"delta_time_displayed",COL_DELTA_TIME_DIS}, - {"src",COL_DEF_SRC}, - {"src_res",COL_RES_SRC}, - {"src_unres",COL_UNRES_SRC}, - {"dl_src",COL_DEF_DL_SRC}, - {"dl_src_res",COL_RES_DL_SRC}, - {"dl_src_unres",COL_UNRES_DL_SRC}, - {"net_src",COL_DEF_NET_SRC}, - {"net_src_res",COL_RES_NET_SRC}, - {"net_src_unres",COL_UNRES_NET_SRC}, - {"dst",COL_DEF_DST}, - {"dst_res",COL_RES_DST}, - {"dst_unres",COL_UNRES_DST}, - {"dl_dst",COL_DEF_DL_DST}, - {"dl_dst_res",COL_RES_DL_DST}, - {"dl_dst_unres",COL_UNRES_DL_DST}, - {"net_dst",COL_DEF_NET_DST}, - {"net_dst_res",COL_RES_NET_DST}, - {"net_dst_unres",COL_UNRES_NET_DST}, - {"src_port",COL_DEF_SRC_PORT}, - {"src_port_res",COL_RES_SRC_PORT}, - {"src_port_unres",COL_UNRES_SRC_PORT}, - {"dst_port",COL_DEF_DST_PORT}, - {"dst_port_res",COL_RES_DST_PORT}, - {"dst_port_unres",COL_UNRES_DST_PORT}, - {"protocol",COL_PROTOCOL}, - {"info",COL_INFO}, - {"packet_len",COL_PACKET_LENGTH}, - {"cumulative_bytes",COL_CUMULATIVE_BYTES}, - {"direction",COL_IF_DIR}, - {"vsan",COL_VSAN}, - {"tx_rate",COL_TX_RATE}, - {"rssi",COL_RSSI}, - {"dce_call",COL_DCE_CALL}, - {NULL,0} -}; - -static gint col_name_to_id(const gchar* name) { - const struct col_names_t* cn; - for(cn = colnames; cn->name; cn++) { - if (g_str_equal(cn->name,name)) { - return cn->id; - } - } - - return 0; -} - -static const gchar* col_id_to_name(gint id) { - const struct col_names_t* cn; - for(cn = colnames; cn->name; cn++) { - if ( cn->id == id ) { - return cn->name; - } - } - return NULL; -} - - -WSLUA_METAMETHOD Column__tostring(lua_State *L) { - Column c = checkColumn(L,1); - const gchar* text; - - if (!c->cinfo) { - text = col_id_to_name(c->col); - lua_pushfstring(L, "(%s)", text ? text : "unknown"); - } - else { - text = col_get_text(c->cinfo, c->col); - lua_pushstring(L, text ? text : "(nil)"); - } - - WSLUA_RETURN(1); /* The column's string text (in parenthesis if not available). */ -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS */ -static int Column__gc(lua_State* L) { - Column col = toColumn(L,1); - - if (!col) return 0; - - if (!col->expired) - col->expired = TRUE; - else - g_free(col); - - return 0; - -} - -WSLUA_METHOD Column_clear(lua_State *L) { - /* Clears a Column. */ - Column c = checkColumn(L,1); - - if (!(c->cinfo)) return 0; - - col_clear(c->cinfo, c->col); - - return 0; -} - -WSLUA_METHOD Column_set(lua_State *L) { - /* Sets the text of a Column. */ -#define WSLUA_ARG_Column_set_TEXT 2 /* The text to which to set the Column. */ - Column c = checkColumn(L,1); - const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_set_TEXT); - - if (!(c->cinfo)) - return 0; - - col_add_str(c->cinfo, c->col, s); - - return 0; -} - -WSLUA_METHOD Column_append(lua_State *L) { - /* Appends text to a Column. */ -#define WSLUA_ARG_Column_append_TEXT 2 /* The text to append to the Column. */ - Column c = checkColumn(L,1); - const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_append_TEXT); - - if (!(c->cinfo)) - return 0; - - col_append_str(c->cinfo, c->col, s); - - return 0; -} - -WSLUA_METHOD Column_prepend(lua_State *L) { - /* Prepends text to a Column. */ -#define WSLUA_ARG_Column_prepend_TEXT 2 /* The text to prepend to the Column. */ - Column c = checkColumn(L,1); - const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_prepend_TEXT); - - if (!(c->cinfo)) - return 0; - - col_prepend_fstr(c->cinfo, c->col, "%s",s); - - return 0; -} - -WSLUA_METHOD Column_fence(lua_State *L) { - /* Sets Column text fence, to prevent overwriting. - - @since 1.10.6 - */ - Column c = checkColumn(L,1); - - if (c->cinfo) - col_set_fence(c->cinfo, c->col); - - return 0; -} - -WSLUA_METHOD Column_clear_fence(lua_State *L) { - /* Clear Column text fence. - - @since 1.11.3 - */ - Column c = checkColumn(L,1); - - if (c->cinfo) - col_clear_fence(c->cinfo, c->col); - - return 0; -} - - -WSLUA_METHODS Column_methods[] = { - WSLUA_CLASS_FNREG(Column,clear), - WSLUA_CLASS_FNREG(Column,set), - WSLUA_CLASS_FNREG(Column,append), - WSLUA_CLASS_FNREG(Column,prepend), - WSLUA_CLASS_FNREG_ALIAS(Column,preppend,prepend), - WSLUA_CLASS_FNREG(Column,fence), - WSLUA_CLASS_FNREG(Column,clear_fence), - { NULL, NULL } -}; - - -WSLUA_META Column_meta[] = { - WSLUA_CLASS_MTREG(Column,tostring), - { NULL, NULL } -}; - - -int Column_register(lua_State *L) { - WSLUA_REGISTER_CLASS(Column); - return 0; -} - - -WSLUA_CLASS_DEFINE(Columns,NOP,NOP); -/* The Columns of the packet list. */ - -WSLUA_METAMETHOD Columns__tostring(lua_State *L) { - lua_pushstring(L,"Columns"); - WSLUA_RETURN(1); - /* The string "Columns", no real use, just for debugging purposes. */ -} - -/* - * To document this is very odd - it won't make sense to a person reading the - * API docs to see this metamethod as a method, but oh well. - */ -WSLUA_METAMETHOD Columns__newindex(lua_State *L) { - /* Sets the text of a specific column. */ -#define WSLUA_ARG_Columns__newindex_COLUMN 2 /* The name of the column to set. */ -#define WSLUA_ARG_Columns__newindex_TEXT 3 /* The text for the column. */ - Columns cols = checkColumns(L,1); - const struct col_names_t* cn; - const char* colname; - const char* text; - - if (!cols) return 0; - if (cols->expired) { - luaL_error(L,"expired column"); - return 0; - } - - colname = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_COLUMN); - text = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_TEXT); - - for(cn = colnames; cn->name; cn++) { - if( g_str_equal(cn->name,colname) ) { - col_add_str(cols->cinfo, cn->id, text); - return 0; - } - } - - WSLUA_ARG_ERROR(Columns__newindex,COLUMN,"the column name must be a valid column"); - return 0; -} - -WSLUA_METAMETHOD Columns__index(lua_State *L) { - /* Gets a specific Column. */ - Columns cols = checkColumns(L,1); - const struct col_names_t* cn; - const char* colname = luaL_checkstring(L,2); - - if (!cols) { - Column c = (Column)g_malloc(sizeof(struct _wslua_col_info)); - c->cinfo = NULL; - c->col = col_name_to_id(colname); - c->expired = FALSE; - - PUSH_COLUMN(L,c); - return 1; - } - - - if (cols->expired) { - luaL_error(L,"expired column"); - return 0; - } - - for(cn = colnames; cn->name; cn++) { - if( g_str_equal(cn->name,colname) ) { - Column c = (Column)g_malloc(sizeof(struct _wslua_col_info)); - c->cinfo = cols->cinfo; - c->col = col_name_to_id(colname); - c->expired = FALSE; - - PUSH_COLUMN(L,c); - return 1; - } - } - - return 0; -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_META */ -static int Columns__gc(lua_State* L) { - Columns cols = toColumns(L,1); - - if (!cols) return 0; - - if (!cols->expired) - cols->expired = TRUE; - else - g_free(cols); - - return 0; - -} - - -WSLUA_META Columns_meta[] = { - WSLUA_CLASS_MTREG(Columns,tostring), - WSLUA_CLASS_MTREG(Columns,newindex), - WSLUA_CLASS_MTREG(Columns,index), - { NULL, NULL } -}; - - -int Columns_register(lua_State *L) { - WSLUA_REGISTER_META(Columns); - return 0; -} WSLUA_CLASS_DEFINE(PrivateTable,FAIL_ON_NULL_OR_EXPIRED("PrivateTable"),NOP); /* PrivateTable represents the pinfo->private_table. */ @@ -1044,12 +330,12 @@ static int Pinfo_get_columns(lua_State *L) { cols->expired = FALSE; if (!colname) { - PUSH_COLUMNS(L,cols); + Push_Columns(L,cols); } else { lua_settop(L,0); - PUSH_COLUMNS(L,cols); + Push_Columns(L,cols); lua_pushstring(L,colname); - return Columns__index(L); + return get_Columns_index(L); } return 1; } @@ -1197,8 +483,6 @@ int Pinfo_register(lua_State* L) { WSLUA_REGISTER_META(Pinfo); WSLUA_REGISTER_ATTRIBUTES(Pinfo); outstanding_Pinfo = g_ptr_array_new(); - outstanding_Column = g_ptr_array_new(); - outstanding_Columns = g_ptr_array_new(); outstanding_PrivateTable = g_ptr_array_new(); return 0; } diff --git a/epan/wslua/wslua_pinfo_common.h b/epan/wslua/wslua_pinfo_common.h new file mode 100644 index 0000000000..3a3fad3aec --- /dev/null +++ b/epan/wslua/wslua_pinfo_common.h @@ -0,0 +1,35 @@ +/* + * wslua_pinfo_common.h + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + +void Push_Columns(lua_State *L, Columns c); +int get_Columns_index(lua_State *L); diff --git a/epan/wslua/wslua_pref.c b/epan/wslua/wslua_pref.c new file mode 100644 index 0000000000..cdde74d0c8 --- /dev/null +++ b/epan/wslua/wslua_pref.c @@ -0,0 +1,463 @@ +/* + * wslua_pref.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + +/* WSLUA_CONTINUE_MODULE Proto */ + + +WSLUA_CLASS_DEFINE(Pref,NOP,NOP); /* A preference of a Protocol. */ + +static range_t* get_range(lua_State *L, int idx_r, int idx_m); + +static enum_val_t* get_enum(lua_State *L, int idx) +{ + double seq; + const gchar *str1, *str2; + enum_val_t *ret, last = {NULL, NULL, -1}; + GArray* es = g_array_new(TRUE,TRUE,sizeof(enum_val_t)); + + luaL_checktype(L, idx, LUA_TTABLE); + lua_pushnil(L); /* first key */ + + while (lua_next(L, idx)) { + enum_val_t e = {NULL, NULL, -1}; + + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnil(L); + lua_next(L, -2); + if (! lua_isstring(L,-1)) { + luaL_argerror(L,idx,"First value of an enum table must be string"); + g_array_free(es,TRUE); + return NULL; + } + str1 = lua_tostring(L, -1); + + lua_pop(L, 1); + lua_next(L, -2); + if (! lua_isstring(L,-1)) { + luaL_argerror(L,idx,"Second value of an enum table must be string"); + g_array_free(es,TRUE); + return NULL; + } + str2 = lua_tostring(L, -1); + + lua_pop(L, 1); + lua_next(L, -2); + if (! lua_isnumber(L,-1)) { + luaL_argerror(L,idx,"Third value of an enum table must be an integer"); + g_array_free(es,TRUE); + return NULL; + } + seq = lua_tonumber(L, -1); + + e.name = g_strdup(str1); + e.description = g_strdup(str2); + e.value = (guint32)seq; + + g_array_append_val(es,e); + + lua_pop(L, 3); /* removes 'value'; keeps 'key' for next iteration */ + } + + g_array_append_val(es,last); + + ret = (enum_val_t*)(void*)es->data; + + g_array_free(es,FALSE); + + return ret; +} + +static int new_pref(lua_State* L, pref_type_t type) { + const gchar* label = luaL_optstring(L,1,NULL); + const gchar* descr = luaL_optstring(L,3,""); + + Pref pref = (wslua_pref_t *)g_malloc(sizeof(wslua_pref_t)); + pref->name = NULL; + pref->label = label ? g_strdup(label) : NULL; + pref->desc = g_strdup(descr); + pref->type = type; + pref->next = NULL; + pref->proto = NULL; + + switch(type) { + case PREF_BOOL: { + gboolean def = wslua_toboolean(L,2); + pref->value.b = def; + break; + } + case PREF_UINT: { + guint32 def = wslua_optgint32(L,2,0); + pref->value.u = def; + break; + } + case PREF_STRING: { + gchar* def = g_strdup(luaL_optstring(L,2,"")); + pref->value.s = def; + break; + } + case PREF_ENUM: { + guint32 def = wslua_optgint32(L,2,0); + enum_val_t *enum_val = get_enum(L,4); + gboolean radio = wslua_toboolean(L,5); + pref->value.e = def; + pref->info.enum_info.enumvals = enum_val; + pref->info.enum_info.radio_buttons = radio; + break; + } + case PREF_RANGE: { + range_t *range = get_range(L,2,4); + guint32 max = wslua_optgint32(L,4,0); + pref->value.r = range; + pref->info.max_value = max; + break; + } + case PREF_STATIC_TEXT: { + /* This is just a static text. */ + break; + } + default: + g_assert_not_reached(); + break; + + } + + pushPref(L,pref); + return 1; +} + +WSLUA_CONSTRUCTOR Pref_bool(lua_State* L) { + /* Creates a boolean preference to be added to a `Proto.prefs` Lua table. */ +#define WSLUA_ARG_Pref_bool_LABEL 1 /* The Label (text in the right side of the + preference input) for this preference. */ +#define WSLUA_ARG_Pref_bool_DEFAULT 2 /* The default value for this preference. */ +#define WSLUA_ARG_Pref_bool_DESCR 3 /* A description of what this preference is. */ + return new_pref(L,PREF_BOOL); +} + +WSLUA_CONSTRUCTOR Pref_uint(lua_State* L) { + /* Creates an (unsigned) integer preference to be added to a `Proto.prefs` Lua table. */ +#define WSLUA_ARG_Pref_uint_LABEL 1 /* The Label (text in the right side of the + preference input) for this preference. */ +#define WSLUA_ARG_Pref_uint_DEFAULT 2 /* The default value for this preference. */ +#define WSLUA_ARG_Pref_uint_DESCR 3 /* A description of what this preference is. */ + return new_pref(L,PREF_UINT); +} + +WSLUA_CONSTRUCTOR Pref_string(lua_State* L) { + /* Creates a string preference to be added to a `Proto.prefs` Lua table. */ +#define WSLUA_ARG_Pref_string_LABEL 1 /* The Label (text in the right side of the + preference input) for this preference. */ +#define WSLUA_ARG_Pref_string_DEFAULT 2 /* The default value for this preference. */ +#define WSLUA_ARG_Pref_string_DESCR 3 /* A description of what this preference is. */ + return new_pref(L,PREF_STRING); +} + +WSLUA_CONSTRUCTOR Pref_enum(lua_State* L) { + /* Creates an enum preference to be added to a `Proto.prefs` Lua table. */ +#define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the + preference input) for this preference. */ +#define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference. */ +#define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is. */ +#define WSLUA_ARG_Pref_enum_ENUM 4 /* An enum Lua table. */ +#define WSLUA_ARG_Pref_enum_RADIO 5 /* Radio button (true) or Combobox (false). */ + return new_pref(L,PREF_ENUM); +} + +WSLUA_CONSTRUCTOR Pref_range(lua_State* L) { + /* Creates a range preference to be added to a `Proto.prefs` Lua table. */ +#define WSLUA_ARG_Pref_range_LABEL 1 /* The Label (text in the right side of the preference + input) for this preference. */ +#define WSLUA_ARG_Pref_range_DEFAULT 2 /* The default value for this preference, e.g., "53", + "10-30", or "10-30,53,55,100-120". */ +#define WSLUA_ARG_Pref_range_DESCR 3 /* A description of what this preference is. */ +#define WSLUA_ARG_Pref_range_MAX 4 /* The maximum value. */ + return new_pref(L,PREF_RANGE); +} + +WSLUA_CONSTRUCTOR Pref_statictext(lua_State* L) { + /* Creates a static text string to be added to a `Proto.prefs` Lua table. */ +#define WSLUA_ARG_Pref_statictext_LABEL 1 /* The static text. */ +#define WSLUA_ARG_Pref_statictext_DESCR 2 /* The static text description. */ + return new_pref(L,PREF_STATIC_TEXT); +} + +static range_t* get_range(lua_State *L, int idx_r, int idx_m) +{ + static range_t *ret = NULL; + const gchar *pattern = luaL_checkstring(L, idx_r); + + switch (range_convert_str(&ret, pattern, wslua_togint32(L, idx_m))) { + case CVT_NO_ERROR: + break; + case CVT_SYNTAX_ERROR: + WSLUA_ARG_ERROR(Pref_range,DEFAULT,"syntax error in default range"); + return 0; + case CVT_NUMBER_TOO_BIG: + WSLUA_ARG_ERROR(Pref_range,DEFAULT,"value too large in default range"); + return 0; + default: + WSLUA_ARG_ERROR(Pref_range,DEFAULT,"unknown error in default range"); + return 0; + } + + return ret; +} +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int Pref__gc(lua_State* L) { + Pref pref = checkPref(L,1); + + if (pref && ! pref->name) { + g_free(pref->label); + g_free(pref->desc); + if (pref->type == PREF_STRING) + g_free((void*)pref->value.s); + g_free(pref); + } + + return 0; +} + +WSLUA_METHODS Pref_methods[] = { + WSLUA_CLASS_FNREG(Pref,bool), + WSLUA_CLASS_FNREG(Pref,uint), + WSLUA_CLASS_FNREG(Pref,string), + WSLUA_CLASS_FNREG(Pref,enum), + WSLUA_CLASS_FNREG(Pref,range), + WSLUA_CLASS_FNREG(Pref,statictext), + { NULL, NULL } +}; + +WSLUA_META Pref_meta[] = { + { NULL, NULL } +}; + + +WSLUA_REGISTER Pref_register(lua_State* L) { + WSLUA_REGISTER_CLASS(Pref); + return 0; +} + +WSLUA_CLASS_DEFINE(Prefs,NOP,NOP); /* The table of preferences of a protocol. */ + +WSLUA_METAMETHOD Prefs__newindex(lua_State* L) { + /* Creates a new preference. */ +#define WSLUA_ARG_Prefs__newindex_NAME 2 /* The abbreviation of this preference. */ +#define WSLUA_ARG_Prefs__newindex_PREF 3 /* A valid but still unassigned Pref object. */ + + Pref prefs_p = checkPrefs(L,1); + const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__newindex_NAME); + Pref pref = checkPref(L,WSLUA_ARG_Prefs__newindex_PREF); + Pref p; + const gchar *c; + + if (! prefs_p ) return 0; + + if (! pref ) { + WSLUA_ARG_ERROR(Prefs__newindex,PREF,"must be a valid Pref"); + return 0; + } + + if (pref->name) { + WSLUA_ARG_ERROR(Prefs__newindex,NAME,"cannot change existing preference"); + return 0; + } + + if (pref->proto) { + WSLUA_ARG_ERROR(Prefs__newindex,PREF,"cannot be added to more than one protocol"); + return 0; + } + + p = prefs_p; + + do { + if ( p->name && g_str_equal(p->name,name) ) { + luaL_error(L,"a preference named %s exists already",name); + return 0; + } + /* + * Make sure that only lower-case ASCII letters, numbers, + * underscores, and dots appear in the preference name. + */ + for (c = name; *c != '\0'; c++) { + if (!g_ascii_islower(*c) && !g_ascii_isdigit(*c) && *c != '_' && *c != '.') + { + luaL_error(L,"illegal preference name \"%s\", only lower-case ASCII letters, " + "numbers, underscores and dots may be used", name); + return 0; + } + } + + if ( ! p->next) { + p->next = pref; + pref->name = g_strdup(name); + + if (!pref->label) + pref->label = g_strdup(name); + + if (!prefs_p->proto->prefs_module) { + prefs_p->proto->prefs_module = prefs_register_protocol(prefs_p->proto->hfid, + wslua_prefs_changed); + } + + switch(pref->type) { + case PREF_BOOL: + prefs_register_bool_preference(prefs_p->proto->prefs_module, + pref->name, + pref->label, + pref->desc, + &(pref->value.b)); + break; + case PREF_UINT: + prefs_register_uint_preference(prefs_p->proto->prefs_module, + pref->name, + pref->label, + pref->desc, + 10, + &(pref->value.u)); + break; + case PREF_STRING: + prefs_register_string_preference(prefs_p->proto->prefs_module, + pref->name, + pref->label, + pref->desc, + (const char **)(&(pref->value.s))); + break; + case PREF_ENUM: + prefs_register_enum_preference(prefs_p->proto->prefs_module, + pref->name, + pref->label, + pref->desc, + &(pref->value.e), + pref->info.enum_info.enumvals, + pref->info.enum_info.radio_buttons); + break; + case PREF_RANGE: + prefs_register_range_preference(prefs_p->proto->prefs_module, + pref->name, + pref->label, + pref->desc, + &(pref->value.r), + pref->info.max_value); + break; + case PREF_STATIC_TEXT: + prefs_register_static_text_preference(prefs_p->proto->prefs_module, + pref->name, + pref->label, + pref->desc); + break; + default: + WSLUA_ERROR(Prefs__newindex,"Unknow Pref type"); + break; + } + + pref->proto = p->proto; + + WSLUA_RETURN(0); + } + } while (( p = p->next )); + + luaL_error(L,"this should not happen!"); + + WSLUA_RETURN(0); +} + +WSLUA_METAMETHOD Prefs__index(lua_State* L) { + /* Get the value of a preference setting. */ +#define WSLUA_ARG_Prefs__index_NAME 2 /* The abbreviation of this preference. */ + + Pref prefs_p = checkPrefs(L,1); + const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__index_NAME); + + if (! prefs_p ) return 0; + + if (!prefs_p->next) { + luaL_error(L,"No preference is registered yet"); + return 0; + } + + prefs_p = prefs_p->next; + + do { + if ( g_str_equal(prefs_p->name,name) ) { + switch (prefs_p->type) { + case PREF_BOOL: lua_pushboolean(L, prefs_p->value.b); break; + case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs_p->value.u); break; + case PREF_STRING: lua_pushstring(L,prefs_p->value.s); break; + case PREF_ENUM: lua_pushnumber(L,(lua_Number)prefs_p->value.e); break; + case PREF_RANGE: + { + char *push_str = range_convert_range(NULL, prefs_p->value.r); + lua_pushstring(L, push_str); + wmem_free(NULL, push_str); + } + break; + default: WSLUA_ERROR(Prefs__index,"Unknow Pref type"); return 0; + } + WSLUA_RETURN(1); /* The current value of the preference. */ + } + } while (( prefs_p = prefs_p->next )); + + WSLUA_ARG_ERROR(Prefs__index,NAME,"no preference named like this"); + return 0; +} + +/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ +static int Prefs__gc(lua_State* L _U_) { + /* do NOT free Prefs, it's never free'd */ + return 0; +} + +WSLUA_META Prefs_meta[] = { + WSLUA_CLASS_MTREG(Prefs,newindex), + WSLUA_CLASS_MTREG(Prefs,index), + { NULL, NULL } +}; + +WSLUA_REGISTER Prefs_register(lua_State* L) { + WSLUA_REGISTER_META(Prefs); + 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: + */ diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c index e78b39d9de..67a0d9ee0c 100644 --- a/epan/wslua/wslua_proto.c +++ b/epan/wslua/wslua_proto.c @@ -1,5 +1,5 @@ /* - * lua_proto.c + * wslua_proto.c * * wireshark's interface to the Lua Programming Language * @@ -27,6 +27,9 @@ #include "config.h" +#include "wslua.h" +#include <epan/dissectors/packet-tcp.h> + /* WSLUA_MODULE Proto Functions for new protocols and dissectors The classes and functions in this chapter allow Lua scripts to create new @@ -42,1466 +45,33 @@ as a heuristic dissector. */ -#include "wslua.h" -#include <epan/dissectors/packet-tcp.h> - -#include <epan/exceptions.h> -#include <epan/show_exception.h> - -WSLUA_CLASS_DEFINE(Pref,NOP,NOP); /* A preference of a Protocol. */ - -static range_t* get_range(lua_State *L, int idx_r, int idx_m); - -static enum_val_t* get_enum(lua_State *L, int idx) -{ - double seq; - const gchar *str1, *str2; - enum_val_t *ret, last = {NULL, NULL, -1}; - GArray* es = g_array_new(TRUE,TRUE,sizeof(enum_val_t)); - - luaL_checktype(L, idx, LUA_TTABLE); - lua_pushnil(L); /* first key */ - - while (lua_next(L, idx)) { - enum_val_t e = {NULL, NULL, -1}; - - luaL_checktype(L, -1, LUA_TTABLE); - lua_pushnil(L); - lua_next(L, -2); - if (! lua_isstring(L,-1)) { - luaL_argerror(L,idx,"First value of an enum table must be string"); - g_array_free(es,TRUE); - return NULL; - } - str1 = lua_tostring(L, -1); - - lua_pop(L, 1); - lua_next(L, -2); - if (! lua_isstring(L,-1)) { - luaL_argerror(L,idx,"Second value of an enum table must be string"); - g_array_free(es,TRUE); - return NULL; - } - str2 = lua_tostring(L, -1); - - lua_pop(L, 1); - lua_next(L, -2); - if (! lua_isnumber(L,-1)) { - luaL_argerror(L,idx,"Third value of an enum table must be an integer"); - g_array_free(es,TRUE); - return NULL; - } - seq = lua_tonumber(L, -1); - - e.name = g_strdup(str1); - e.description = g_strdup(str2); - e.value = (guint32)seq; - - g_array_append_val(es,e); - - lua_pop(L, 3); /* removes 'value'; keeps 'key' for next iteration */ - } - - g_array_append_val(es,last); - - ret = (enum_val_t*)(void*)es->data; - - g_array_free(es,FALSE); - - return ret; -} - -static int new_pref(lua_State* L, pref_type_t type) { - const gchar* label = luaL_optstring(L,1,NULL); - const gchar* descr = luaL_optstring(L,3,""); - - Pref pref = (wslua_pref_t *)g_malloc(sizeof(wslua_pref_t)); - pref->name = NULL; - pref->label = label ? g_strdup(label) : NULL; - pref->desc = g_strdup(descr); - pref->type = type; - pref->next = NULL; - pref->proto = NULL; - - switch(type) { - case PREF_BOOL: { - gboolean def = wslua_toboolean(L,2); - pref->value.b = def; - break; - } - case PREF_UINT: { - guint32 def = wslua_optgint32(L,2,0); - pref->value.u = def; - break; - } - case PREF_STRING: { - gchar* def = g_strdup(luaL_optstring(L,2,"")); - pref->value.s = def; - break; - } - case PREF_ENUM: { - guint32 def = wslua_optgint32(L,2,0); - enum_val_t *enum_val = get_enum(L,4); - gboolean radio = wslua_toboolean(L,5); - pref->value.e = def; - pref->info.enum_info.enumvals = enum_val; - pref->info.enum_info.radio_buttons = radio; - break; - } - case PREF_RANGE: { - range_t *range = get_range(L,2,4); - guint32 max = wslua_optgint32(L,4,0); - pref->value.r = range; - pref->info.max_value = max; - break; - } - case PREF_STATIC_TEXT: { - /* This is just a static text. */ - break; - } - default: - g_assert_not_reached(); - break; - - } - - pushPref(L,pref); - return 1; -} - -WSLUA_CONSTRUCTOR Pref_bool(lua_State* L) { - /* Creates a boolean preference to be added to a `Proto.prefs` Lua table. */ -#define WSLUA_ARG_Pref_bool_LABEL 1 /* The Label (text in the right side of the - preference input) for this preference. */ -#define WSLUA_ARG_Pref_bool_DEFAULT 2 /* The default value for this preference. */ -#define WSLUA_ARG_Pref_bool_DESCR 3 /* A description of what this preference is. */ - return new_pref(L,PREF_BOOL); -} - -WSLUA_CONSTRUCTOR Pref_uint(lua_State* L) { - /* Creates an (unsigned) integer preference to be added to a `Proto.prefs` Lua table. */ -#define WSLUA_ARG_Pref_uint_LABEL 1 /* The Label (text in the right side of the - preference input) for this preference. */ -#define WSLUA_ARG_Pref_uint_DEFAULT 2 /* The default value for this preference. */ -#define WSLUA_ARG_Pref_uint_DESCR 3 /* A description of what this preference is. */ - return new_pref(L,PREF_UINT); -} - -WSLUA_CONSTRUCTOR Pref_string(lua_State* L) { - /* Creates a string preference to be added to a `Proto.prefs` Lua table. */ -#define WSLUA_ARG_Pref_string_LABEL 1 /* The Label (text in the right side of the - preference input) for this preference. */ -#define WSLUA_ARG_Pref_string_DEFAULT 2 /* The default value for this preference. */ -#define WSLUA_ARG_Pref_string_DESCR 3 /* A description of what this preference is. */ - return new_pref(L,PREF_STRING); -} - -WSLUA_CONSTRUCTOR Pref_enum(lua_State* L) { - /* Creates an enum preference to be added to a `Proto.prefs` Lua table. */ -#define WSLUA_ARG_Pref_enum_LABEL 1 /* The Label (text in the right side of the - preference input) for this preference. */ -#define WSLUA_ARG_Pref_enum_DEFAULT 2 /* The default value for this preference. */ -#define WSLUA_ARG_Pref_enum_DESCR 3 /* A description of what this preference is. */ -#define WSLUA_ARG_Pref_enum_ENUM 4 /* An enum Lua table. */ -#define WSLUA_ARG_Pref_enum_RADIO 5 /* Radio button (true) or Combobox (false). */ - return new_pref(L,PREF_ENUM); -} - -WSLUA_CONSTRUCTOR Pref_range(lua_State* L) { - /* Creates a range preference to be added to a `Proto.prefs` Lua table. */ -#define WSLUA_ARG_Pref_range_LABEL 1 /* The Label (text in the right side of the preference - input) for this preference. */ -#define WSLUA_ARG_Pref_range_DEFAULT 2 /* The default value for this preference, e.g., "53", - "10-30", or "10-30,53,55,100-120". */ -#define WSLUA_ARG_Pref_range_DESCR 3 /* A description of what this preference is. */ -#define WSLUA_ARG_Pref_range_MAX 4 /* The maximum value. */ - return new_pref(L,PREF_RANGE); -} - -WSLUA_CONSTRUCTOR Pref_statictext(lua_State* L) { - /* Creates a static text string to be added to a `Proto.prefs` Lua table. */ -#define WSLUA_ARG_Pref_statictext_LABEL 1 /* The static text. */ -#define WSLUA_ARG_Pref_statictext_DESCR 2 /* The static text description. */ - return new_pref(L,PREF_STATIC_TEXT); -} - -static range_t* get_range(lua_State *L, int idx_r, int idx_m) -{ - static range_t *ret = NULL; - const gchar *pattern = luaL_checkstring(L, idx_r); - - switch (range_convert_str(&ret, pattern, wslua_togint32(L, idx_m))) { - case CVT_NO_ERROR: - break; - case CVT_SYNTAX_ERROR: - WSLUA_ARG_ERROR(Pref_range,DEFAULT,"syntax error in default range"); - return 0; - case CVT_NUMBER_TOO_BIG: - WSLUA_ARG_ERROR(Pref_range,DEFAULT,"value too large in default range"); - return 0; - default: - WSLUA_ARG_ERROR(Pref_range,DEFAULT,"unknown error in default range"); - return 0; - } - - return ret; -} -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int Pref__gc(lua_State* L) { - Pref pref = checkPref(L,1); - - if (pref && ! pref->name) { - g_free(pref->label); - g_free(pref->desc); - if (pref->type == PREF_STRING) - g_free((void*)pref->value.s); - g_free(pref); - } - - return 0; -} - -WSLUA_METHODS Pref_methods[] = { - WSLUA_CLASS_FNREG(Pref,bool), - WSLUA_CLASS_FNREG(Pref,uint), - WSLUA_CLASS_FNREG(Pref,string), - WSLUA_CLASS_FNREG(Pref,enum), - WSLUA_CLASS_FNREG(Pref,range), - WSLUA_CLASS_FNREG(Pref,statictext), - { NULL, NULL } -}; - -WSLUA_META Pref_meta[] = { - { NULL, NULL } -}; - - -WSLUA_REGISTER Pref_register(lua_State* L) { - WSLUA_REGISTER_CLASS(Pref); - return 0; -} - -WSLUA_CLASS_DEFINE(Prefs,NOP,NOP); /* The table of preferences of a protocol. */ - -WSLUA_METAMETHOD Prefs__newindex(lua_State* L) { - /* Creates a new preference. */ -#define WSLUA_ARG_Prefs__newindex_NAME 2 /* The abbreviation of this preference. */ -#define WSLUA_ARG_Prefs__newindex_PREF 3 /* A valid but still unassigned Pref object. */ - - Pref prefs_p = checkPrefs(L,1); - const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__newindex_NAME); - Pref pref = checkPref(L,WSLUA_ARG_Prefs__newindex_PREF); - Pref p; - const gchar *c; - if (! prefs_p ) return 0; - - if (! pref ) { - WSLUA_ARG_ERROR(Prefs__newindex,PREF,"must be a valid Pref"); - return 0; - } - - if (pref->name) { - WSLUA_ARG_ERROR(Prefs__newindex,NAME,"cannot change existing preference"); - return 0; - } - - if (pref->proto) { - WSLUA_ARG_ERROR(Prefs__newindex,PREF,"cannot be added to more than one protocol"); - return 0; - } - - p = prefs_p; - - do { - if ( p->name && g_str_equal(p->name,name) ) { - luaL_error(L,"a preference named %s exists already",name); - return 0; - } - /* - * Make sure that only lower-case ASCII letters, numbers, - * underscores, and dots appear in the preference name. - */ - for (c = name; *c != '\0'; c++) { - if (!g_ascii_islower(*c) && !g_ascii_isdigit(*c) && *c != '_' && *c != '.') - { - luaL_error(L,"illegal preference name \"%s\", only lower-case ASCII letters, " - "numbers, underscores and dots may be used", name); - return 0; - } - } - - if ( ! p->next) { - p->next = pref; - pref->name = g_strdup(name); - - if (!pref->label) - pref->label = g_strdup(name); - - if (!prefs_p->proto->prefs_module) { - prefs_p->proto->prefs_module = prefs_register_protocol(prefs_p->proto->hfid, - wslua_prefs_changed); - } - - switch(pref->type) { - case PREF_BOOL: - prefs_register_bool_preference(prefs_p->proto->prefs_module, - pref->name, - pref->label, - pref->desc, - &(pref->value.b)); - break; - case PREF_UINT: - prefs_register_uint_preference(prefs_p->proto->prefs_module, - pref->name, - pref->label, - pref->desc, - 10, - &(pref->value.u)); - break; - case PREF_STRING: - prefs_register_string_preference(prefs_p->proto->prefs_module, - pref->name, - pref->label, - pref->desc, - (const char **)(&(pref->value.s))); - break; - case PREF_ENUM: - prefs_register_enum_preference(prefs_p->proto->prefs_module, - pref->name, - pref->label, - pref->desc, - &(pref->value.e), - pref->info.enum_info.enumvals, - pref->info.enum_info.radio_buttons); - break; - case PREF_RANGE: - prefs_register_range_preference(prefs_p->proto->prefs_module, - pref->name, - pref->label, - pref->desc, - &(pref->value.r), - pref->info.max_value); - break; - case PREF_STATIC_TEXT: - prefs_register_static_text_preference(prefs_p->proto->prefs_module, - pref->name, - pref->label, - pref->desc); - break; - default: - WSLUA_ERROR(Prefs__newindex,"Unknow Pref type"); - break; - } - - pref->proto = p->proto; - - WSLUA_RETURN(0); - } - } while (( p = p->next )); - - luaL_error(L,"this should not happen!"); - - WSLUA_RETURN(0); -} - -WSLUA_METAMETHOD Prefs__index(lua_State* L) { - /* Get the value of a preference setting. */ -#define WSLUA_ARG_Prefs__index_NAME 2 /* The abbreviation of this preference. */ - - Pref prefs_p = checkPrefs(L,1); - const gchar* name = luaL_checkstring(L,WSLUA_ARG_Prefs__index_NAME); - - if (! prefs_p ) return 0; +/* + * _func_saver stores function refs so that Lua won't garbage collect them prematurely. + * It is only used by tcp_dissect_pdus right now. + */ +typedef struct _func_saver { + lua_State* state; + int get_len_ref; + int dissect_ref; +} func_saver_t; - if (!prefs_p->next) { - luaL_error(L,"No preference is registered yet"); - return 0; - } +static GPtrArray* outstanding_FuncSavers = NULL; - prefs_p = prefs_p->next; - - do { - if ( g_str_equal(prefs_p->name,name) ) { - switch (prefs_p->type) { - case PREF_BOOL: lua_pushboolean(L, prefs_p->value.b); break; - case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs_p->value.u); break; - case PREF_STRING: lua_pushstring(L,prefs_p->value.s); break; - case PREF_ENUM: lua_pushnumber(L,(lua_Number)prefs_p->value.e); break; - case PREF_RANGE: - { - char *push_str = range_convert_range(NULL, prefs_p->value.r); - lua_pushstring(L, push_str); - wmem_free(NULL, push_str); - } - break; - default: WSLUA_ERROR(Prefs__index,"Unknow Pref type"); return 0; +void clear_outstanding_FuncSavers(void) { + while (outstanding_FuncSavers->len) { + func_saver_t* fs = (func_saver_t*)g_ptr_array_remove_index_fast(outstanding_FuncSavers,0); + if (fs->state) { + lua_State* L = fs->state; + if (fs->get_len_ref != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, fs->get_len_ref); } - WSLUA_RETURN(1); /* The current value of the preference. */ - } - } while (( prefs_p = prefs_p->next )); - - WSLUA_ARG_ERROR(Prefs__index,NAME,"no preference named like this"); - return 0; -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int Prefs__gc(lua_State* L _U_) { - /* do NOT free Prefs, it's never free'd */ - return 0; -} - -WSLUA_META Prefs_meta[] = { - WSLUA_CLASS_MTREG(Prefs,newindex), - WSLUA_CLASS_MTREG(Prefs,index), - { NULL, NULL } -}; - -WSLUA_REGISTER Prefs_register(lua_State* L) { - WSLUA_REGISTER_META(Prefs); - return 0; -} - -WSLUA_CLASS_DEFINE(ProtoField,FAIL_ON_NULL("null ProtoField"),NOP); - /* A Protocol field (to be used when adding items to the dissection tree). */ - -static const wslua_ft_types_t ftenums[] = { - {"ftypes.NONE", FT_NONE}, - {"ftypes.BOOLEAN", FT_BOOLEAN}, - {"ftypes.UINT8", FT_UINT8}, - {"ftypes.UINT16", FT_UINT16}, - {"ftypes.UINT24", FT_UINT24}, - {"ftypes.UINT32", FT_UINT32}, - {"ftypes.UINT64", FT_UINT64}, - {"ftypes.INT8", FT_INT8}, - {"ftypes.INT16", FT_INT16}, - {"ftypes.INT24", FT_INT24}, - {"ftypes.INT32", FT_INT32}, - {"ftypes.INT64", FT_INT64}, - {"ftypes.FLOAT", FT_FLOAT}, - {"ftypes.DOUBLE", FT_DOUBLE}, - {"ftypes.ABSOLUTE_TIME", FT_ABSOLUTE_TIME}, - {"ftypes.RELATIVE_TIME", FT_RELATIVE_TIME}, - {"ftypes.STRING", FT_STRING}, - {"ftypes.STRINGZ", FT_STRINGZ}, - {"ftypes.ETHER", FT_ETHER}, - {"ftypes.BYTES", FT_BYTES}, - {"ftypes.UINT_BYTES", FT_UINT_BYTES}, - {"ftypes.IPv4", FT_IPv4}, - {"ftypes.IPv6", FT_IPv6}, - {"ftypes.IPXNET", FT_IPXNET}, - {"ftypes.FRAMENUM", FT_FRAMENUM}, - {"ftypes.GUID", FT_GUID}, - {"ftypes.OID", FT_OID}, - {"ftypes.SYSTEM_ID", FT_SYSTEM_ID}, - {"ftypes.REL_OID", FT_REL_OID}, - {"ftypes.EUI64", FT_EUI64}, - {"ftypes.FCWWN", FT_FCWWN}, - {NULL, FT_NONE} -}; - -static enum ftenum get_ftenum(const gchar* type) { - const wslua_ft_types_t* ts; - for (ts = ftenums; ts->str; ts++) { - if ( g_str_equal(ts->str,type) ) { - return ts->id; - } - } - return FT_NONE; -} - -static const gchar* ftenum_to_string(enum ftenum ft) { - const wslua_ft_types_t* ts; - for (ts = ftenums; ts->str; ts++) { - if ( ts->id == ft ) { - return ts->str; - } - } - return NULL; -} - -struct field_display_string_t { - const gchar* str; - unsigned base; -}; - -static const struct field_display_string_t base_displays[] = { - {"base.NONE", BASE_NONE}, - {"base.DEC", BASE_DEC}, - {"base.HEX", BASE_HEX}, - {"base.OCT", BASE_OCT}, - {"base.DEC_HEX", BASE_DEC_HEX}, - {"base.HEX_DEC", BASE_HEX_DEC}, - /* for FT_BOOLEAN, how wide the parent bitfield is */ - {"8",8}, - {"16",16}, - {"24",24}, - {"32",32}, - /* for FT_ABSOLUTE_TIME use values in absolute_time_display_e */ - {"LOCAL", ABSOLUTE_TIME_LOCAL}, - {"UTC", ABSOLUTE_TIME_UTC}, - {"DOY_UTC", ABSOLUTE_TIME_DOY_UTC}, - {NULL,0} -}; - -static const gchar* base_to_string(unsigned base) { - const struct field_display_string_t* b; - for (b=base_displays;b->str;b++) { - if ( base == b->base) - return b->str; - } - return NULL; -} - -static unsigned string_to_base(const gchar* str) { - const struct field_display_string_t* b; - for (b=base_displays;b->str;b++) { - if ( g_str_equal(str,b->str)) - return b->base; - } - return BASE_NONE; -} - -static value_string* value_string_from_table(lua_State* L, int idx) { - GArray* vs = g_array_new(TRUE,TRUE,sizeof(value_string)); - value_string* ret; - - if(lua_isnil(L,idx)) { - return NULL; - } else if (!lua_istable(L,idx)) { - luaL_argerror(L,idx,"must be a table"); - g_array_free(vs,TRUE); - return NULL; - } - - lua_pushnil(L); - - while (lua_next(L, idx) != 0) { - value_string v = {0,NULL}; - - if (! lua_isnumber(L,-2)) { - luaL_argerror(L,idx,"All keys of a table used as value_string must be integers"); - g_array_free(vs,TRUE); - return NULL; - } - - if (! lua_isstring(L,-1)) { - luaL_argerror(L,idx,"All values of a table used as value_string must be strings"); - g_array_free(vs,TRUE); - return NULL; - } - - v.value = wslua_toguint32(L,-2); - v.strptr = g_strdup(lua_tostring(L,-1)); - - g_array_append_val(vs,v); - - lua_pop(L, 1); - } - - ret = (value_string*)(void*)vs->data; - - g_array_free(vs,FALSE); - - return ret; -} - -static val64_string* val64_string_from_table(lua_State* L, int idx) { - GArray* vs = g_array_new(TRUE,TRUE,sizeof(val64_string)); - val64_string* ret; - - if(lua_isnil(L,idx)) { - return NULL; - } else if (!lua_istable(L,idx)) { - luaL_argerror(L,idx,"must be a table"); - g_array_free(vs,TRUE); - return NULL; - } - - lua_pushnil(L); - - while (lua_next(L, idx) != 0) { - val64_string v = {0,NULL}; - - if (! lua_isnumber(L,-2)) { - luaL_argerror(L,idx,"All keys of a table used as value string must be integers"); - g_array_free(vs,TRUE); - return NULL; - } - - if (! lua_isstring(L,-1)) { - luaL_argerror(L,idx,"All values of a table used as value string must be strings"); - g_array_free(vs,TRUE); - return NULL; - } - - v.value = wslua_toguint64(L, -2); - v.strptr = g_strdup(lua_tostring(L,-1)); - - g_array_append_val(vs,v); - - lua_pop(L, 1); - } - - ret = (val64_string*)(void*)vs->data; - - g_array_free(vs,FALSE); - - return ret; -} - -static true_false_string* true_false_string_from_table(lua_State* L, int idx) { - GArray* tfs = g_array_new(TRUE,TRUE,sizeof(true_false_string)); - true_false_string* ret; - true_false_string tf = { "True", "False" }; - - if (lua_isnil(L,idx)) { - return NULL; - } else if (!lua_istable(L,idx)) { - luaL_argerror(L,idx,"must be a table"); - g_array_free(tfs,TRUE); - return NULL; - } - - lua_pushnil(L); - - while (lua_next(L, idx)) { - - if (! lua_isnumber(L,-2)) { - luaL_argerror(L,idx,"All keys of a table used as true_false_string must be integers"); - g_array_free(tfs,TRUE); - return NULL; - } - - if (! lua_isstring(L,-1)) { - luaL_argerror(L,idx,"All values of a table used as true_false_string must be strings"); - g_array_free(tfs,TRUE); - return NULL; - } - - /* arrays in LUA start with index number 1 */ - if (lua_tointeger(L,-2) == 1) - tf.true_string = g_strdup(lua_tostring(L,-1)); - - if (lua_tointeger(L,-2) == 2) - tf.false_string = g_strdup(lua_tostring(L,-1)); - - lua_pop(L, 1); - } - - g_array_append_val(tfs,tf); - - ret = (true_false_string*)(void*)tfs->data; - - g_array_free(tfs,FALSE); - - return ret; -} - -static const gchar* check_field_name(lua_State* L, const int abbr_idx, const enum ftenum type) { - const gchar* abbr = luaL_checkstring(L,abbr_idx); - const header_field_info* hfinfo = NULL; - - if (!abbr[0]) { - luaL_argerror(L, abbr_idx, "Empty field name abbreviation"); - return NULL; - } - - if (proto_check_field_name(abbr)) { - luaL_argerror(L, abbr_idx, "Invalid char in abbrev"); - return NULL; - } - - hfinfo = proto_registrar_get_byname(abbr); - - if (hfinfo && !ftype_similar_types(type, hfinfo->type)) { - luaL_argerror(L, abbr_idx, "A field of an incompatible ftype with this abbrev already exists"); - return NULL; - } - - return abbr; -} - -WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) { - /* Creates a new `ProtoField` object to be used for a protocol field. */ -#define WSLUA_ARG_ProtoField_new_NAME 1 /* Actual name of the field (the string that - appears in the tree). */ -#define WSLUA_ARG_ProtoField_new_ABBR 2 /* Filter name of the field (the string that - is used in filters). */ -#define WSLUA_ARG_ProtoField_new_TYPE 3 /* Field Type: one of: `ftypes.BOOLEAN`, `ftypes.UINT8`, - `ftypes.UINT16`, `ftypes.UINT24`, `ftypes.UINT32`, `ftypes.UINT64`, `ftypes.INT8`, - `ftypes.INT16`, `ftypes.INT24`, `ftypes.INT32`, `ftypes.INT64`, `ftypes.FLOAT`, - `ftypes.DOUBLE` , `ftypes.ABSOLUTE_TIME`, `ftypes.RELATIVE_TIME`, `ftypes.STRING`, - `ftypes.STRINGZ`, `ftypes.UINT_STRING`, `ftypes.ETHER`, `ftypes.BYTES`, - `ftypes.UINT_BYTES`, `ftypes.IPv4`, `ftypes.IPv6`, `ftypes.IPXNET`, `ftypes.FRAMENUM`, - `ftypes.PCRE`, `ftypes.GUID`, `ftypes.OID`, `ftypes.REL_OID`, `ftypes.SYSTEM_ID`, - `ftypes.EUI64` or `ftypes.NONE`. - */ -#define WSLUA_OPTARG_ProtoField_new_VALUESTRING 4 /* A table containing the text that - corresponds to the values. */ -#define WSLUA_OPTARG_ProtoField_new_BASE 5 /* The representation, one of: `base.NONE`, `base.DEC`, - `base.HEX`, `base.OCT`, `base.DEC_HEX`, or - `base.HEX_DEC`. */ -#define WSLUA_OPTARG_ProtoField_new_MASK 6 /* The bitmask to be used. */ -#define WSLUA_OPTARG_ProtoField_new_DESCR 7 /* The description of the field. */ - - ProtoField f; - int nargs = lua_gettop(L); - const gchar* name = luaL_checkstring(L,WSLUA_ARG_ProtoField_new_NAME); - const gchar* abbr = NULL; - enum ftenum type; - value_string *vs32 = NULL; - val64_string *vs64 = NULL; - true_false_string *tfs = NULL; - unsigned base; - guint32 mask = wslua_optguint32(L, WSLUA_OPTARG_ProtoField_new_MASK, 0x0); - const gchar *blob = luaL_optstring(L,WSLUA_OPTARG_ProtoField_new_DESCR,NULL); - - if (lua_isnumber(L,WSLUA_ARG_ProtoField_new_TYPE)) { - type = (enum ftenum)luaL_checkinteger(L,WSLUA_ARG_ProtoField_new_TYPE); - } else { - type = get_ftenum(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_TYPE)); - } - - abbr = check_field_name(L,WSLUA_ARG_ProtoField_new_ABBR,type); - - if (lua_isnumber(L, WSLUA_OPTARG_ProtoField_new_BASE)) { - base = (unsigned)luaL_optinteger(L, WSLUA_OPTARG_ProtoField_new_BASE, BASE_NONE); - } else { - base = string_to_base(luaL_optstring(L, WSLUA_OPTARG_ProtoField_new_BASE, "BASE_NONE")); - } - - switch (type) { - case FT_FRAMENUM: - if (base != BASE_NONE) { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"FRAMENUM must use base.NONE"); - return 0; - } - if (mask) { - WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"FRAMENUM can not have a bitmask"); - return 0; - } - break; - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - if (base == BASE_NONE) { - base = BASE_DEC; /* Default base for integer */ - } else if (base < BASE_DEC || base > BASE_HEX_DEC) { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be either base.DEC, base.HEX, base.OCT," - " base.DEC_HEX, base.DEC_HEX or base.HEX_DEC"); - return 0; - } - if ((base == BASE_HEX || base == BASE_OCT) && - (type == FT_INT8 || type == FT_INT16 || type == FT_INT24 || type == FT_INT32 || type == FT_INT64)) - { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"This type does not display as hexadecimal"); - return 0; - } - if (nargs >= WSLUA_OPTARG_ProtoField_new_VALUESTRING && !lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING)) { - if (type == FT_UINT64 || type == FT_INT64) { - vs64 = val64_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); - } else { - vs32 = value_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); + if (fs->dissect_ref != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, fs->dissect_ref); } } - break; - case FT_BOOLEAN: - if (mask == 0x0 && base != BASE_NONE) { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be base.NONE if bitmask is zero."); - return 0; - } - if (mask != 0x0 && (base < 1 || base > 64)) { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be between 1 and 64 if bitmask is non-zero."); - return 0; - } - if (nargs >= WSLUA_OPTARG_ProtoField_new_VALUESTRING && !lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING)) { - tfs = true_false_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); - } - break; - case FT_ABSOLUTE_TIME: - if (base == BASE_NONE) { - base = ABSOLUTE_TIME_LOCAL; /* Default base for FT_ABSOLUTE_TIME */ - } else if (base < ABSOLUTE_TIME_LOCAL || base > ABSOLUTE_TIME_DOY_UTC) { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be either LOCAL, UTC, or DOY_UTC"); - return 0; - } - if (mask) { - WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"ABSOLUTE_TIME can not have a bitmask"); - return 0; - } - break; - case FT_NONE: - case FT_IPv4: - case FT_IPv6: - case FT_IPXNET: - case FT_ETHER: - case FT_FLOAT: - case FT_DOUBLE: - case FT_RELATIVE_TIME: - case FT_STRING: - case FT_STRINGZ: - case FT_BYTES: - case FT_UINT_BYTES: - case FT_GUID: - case FT_OID: - case FT_SYSTEM_ID: - case FT_REL_OID: - case FT_EUI64: - case FT_VINES: - case FT_FCWWN: - if (base != BASE_NONE) { - WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be base.NONE"); - return 0; - } - if (mask) { - WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"This type can not have a bitmask"); - return 0; - } - break; - default: - WSLUA_ARG_ERROR(ProtoField_new,TYPE,"Invalid field type"); - break; - } - - f = g_new(wslua_field_t,1); - - f->hfid = -2; - f->ett = -1; - f->name = g_strdup(name); - f->abbrev = g_strdup(abbr); - f->type = type; - f->base = base; - if (tfs) { - f->vs = TFS(tfs); - } else if (vs32) { - f->vs = VALS(vs32); - } else if (vs64) { - /* Indicate that we are using val64_string */ - f->base |= BASE_VAL64_STRING; - f->vs = VALS(vs64); - } else { - f->vs = NULL; - } - f->mask = mask; - if (blob && strcmp(blob, f->name) != 0) { - f->blob = g_strdup(blob); - } else { - f->blob = NULL; - } - - pushProtoField(L,f); - - WSLUA_RETURN(1); /* The newly created `ProtoField` object. */ -} - -static int ProtoField_integer(lua_State* L, enum ftenum type) { - ProtoField f; - const gchar* abbr = check_field_name(L,1,type); - const gchar* name = luaL_optstring(L,2,abbr); - unsigned default_base = (type == FT_FRAMENUM) ? BASE_NONE : BASE_DEC; - unsigned base = (unsigned)luaL_optinteger(L, 3, default_base); - value_string* vs32 = NULL; - val64_string* vs64 = NULL; - guint32 mask = wslua_optguint32(L,5,0); - const gchar* blob = luaL_optstring(L,6,NULL); - - if (lua_gettop(L) > 3) { - if (type == FT_UINT64 || type == FT_INT64) { - vs64 = val64_string_from_table(L,4); - } else { - vs32 = value_string_from_table(L,4); - } - } - - if (type == FT_FRAMENUM) { - if (base != BASE_NONE) - luaL_argerror(L, 3, "ftypes.FRAMENUMs must use base.NONE"); - else if (mask) - luaL_argerror(L, 3, "ftypes.FRAMENUMs can not have a bitmask"); - } else if (base < BASE_DEC || base > BASE_HEX_DEC) { - luaL_argerror(L, 3, "Base must be either base.DEC, base.HEX, base.OCT," - " base.DEC_HEX, base.DEC_HEX or base.HEX_DEC"); - return 0; - } else if ((base == BASE_HEX || base == BASE_OCT) && - (type == FT_INT8 || type == FT_INT16 || type == FT_INT24 || type == FT_INT32 || type == FT_INT64)) { - luaL_argerror(L, 3, "This type does not display as hexadecimal"); - return 0; - } - - f = g_new(wslua_field_t,1); - - f->hfid = -2; - f->ett = -1; - f->name = g_strdup(name); - f->abbrev = g_strdup(abbr); - f->type = type; - f->base = base; - if (vs64) { - /* Indicate that we are using val64_string */ - f->base |= BASE_VAL64_STRING; - f->vs = VALS(vs64); - } else { - f->vs = VALS(vs32); - } - f->mask = mask; - if (blob && strcmp(blob, f->name) != 0) { - f->blob = g_strdup(blob); - } else { - f->blob = NULL; - } - - pushProtoField(L,f); - - return 1; -} - -#define PROTOFIELD_INTEGER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_integer(L,FT); } -/* _WSLUA_CONSTRUCTOR_ ProtoField_uint8 Creates a `ProtoField` of an unsigned 8-bit integer (i.e., a byte). */ -/* WSLUA_ARG_Protofield_uint8_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_uint8_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_uint8_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_uint8_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_uint8_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_uint16 Creates a `ProtoField` of an unsigned 16-bit integer. */ -/* WSLUA_ARG_Protofield_uint16_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_uint16_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_uint16_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_uint16_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_uint16_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_uint16_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_uint24 Creates a `ProtoField` of an unsigned 24-bit integer. */ -/* WSLUA_ARG_Protofield_uint24_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_uint24_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_uint24_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_uint24_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_uint24_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_uint24_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_uint32 Creates a `ProtoField` of an unsigned 32-bit integer. */ -/* WSLUA_ARG_Protofield_uint32_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_uint32_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_uint32_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_uint32_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_uint32_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_uint32_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_uint64 Creates a `ProtoField` of an unsigned 64-bit integer. */ -/* WSLUA_ARG_Protofield_uint64_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_uint64_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_uint64_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_uint64_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_uint64_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_uint64_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_int8 Creates a `ProtoField` of a signed 8-bit integer (i.e., a byte). */ -/* WSLUA_ARG_Protofield_int8_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_int8_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_int8_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_int8_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_int8_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_int8_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_int16 Creates a `ProtoField` of a signed 16-bit integer. */ -/* WSLUA_ARG_Protofield_int16_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_int16_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_int16_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_int16_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_int16_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_int16_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_int24 Creates a `ProtoField` of a signed 24-bit integer. */ -/* WSLUA_ARG_Protofield_int24_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_int24_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_int24_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_int24_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_int24_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_int24_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_int32 Creates a `ProtoField` of a signed 32-bit integer. */ -/* WSLUA_ARG_Protofield_int32_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_int32_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_int32_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_int32_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_int32_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_int32_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_int64 Creates a `ProtoField` of a signed 64-bit integer. */ -/* WSLUA_ARG_Protofield_int64_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_int64_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_int64_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ -/* WSLUA_OPTARG_Protofield_int64_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_int64_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_int64_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_framenum Creates a `ProtoField` for a frame number (for hyperlinks between frames). */ -/* WSLUA_ARG_Protofield_framenum_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_framenum_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_framenum_BASE Only `base.NONE` is supported for framenum. */ -/* WSLUA_OPTARG_Protofield_framenum_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_framenum_MASK Integer mask of this field, which must be 0 for framenum. */ -/* WSLUA_OPTARG_Protofield_framenum_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -PROTOFIELD_INTEGER(uint8,FT_UINT8) -PROTOFIELD_INTEGER(uint16,FT_UINT16) -PROTOFIELD_INTEGER(uint24,FT_UINT24) -PROTOFIELD_INTEGER(uint32,FT_UINT32) -PROTOFIELD_INTEGER(uint64,FT_UINT64) -PROTOFIELD_INTEGER(int8,FT_INT8) -PROTOFIELD_INTEGER(int16,FT_INT16) -PROTOFIELD_INTEGER(int24,FT_INT24) -PROTOFIELD_INTEGER(int32,FT_INT32) -PROTOFIELD_INTEGER(int64,FT_INT64) -PROTOFIELD_INTEGER(framenum,FT_FRAMENUM) - -static int ProtoField_boolean(lua_State* L, enum ftenum type) { - ProtoField f; - const gchar* abbr = check_field_name(L,1,type); - const gchar* name = luaL_optstring(L,2,abbr); - unsigned base = (unsigned)luaL_optinteger(L, 3, BASE_NONE); - true_false_string* tfs = NULL; - guint32 mask = wslua_optguint32(L,5,0); - const gchar* blob = luaL_optstring(L,6,NULL); - - if (mask == 0x0 && base != BASE_NONE) { - luaL_argerror(L,2,"Fieldbase (fielddisplay) must be base.NONE" - " if bitmask is zero."); - return 0; - } - - if (mask != 0x0 && (base < 1 || base > 64)) { - luaL_argerror(L,2,"Fieldbase (fielddisplay) must be between 1 and 64" - " if bitmask is non-zero."); - return 0; - } - - if (lua_gettop(L) > 3 && !lua_isnil(L,4)) { - tfs = true_false_string_from_table(L,4); - } - - f = g_new(wslua_field_t,1); - - f->hfid = -2; - f->ett = -1; - f->name = g_strdup(name); - f->abbrev = g_strdup(abbr); - f->type = type; - f->vs = TFS(tfs); - f->base = base; - f->mask = mask; - if (blob && strcmp(blob, f->name) != 0) { - f->blob = g_strdup(blob); - } else { - f->blob = NULL; - } - - pushProtoField(L,f); - - return 1; -} - -#define PROTOFIELD_BOOL(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_boolean(L,FT); } -/* _WSLUA_CONSTRUCTOR_ ProtoField_bool Creates a `ProtoField` for a boolean true/false value. */ -/* WSLUA_ARG_Protofield_bool_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_bool_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_bool_DISPLAY how wide the parent bitfield is (`base.NONE` is used for NULL-value). */ -/* WSLUA_OPTARG_Protofield_bool_VALUESTRING A table containing the text that corresponds to the values. */ -/* WSLUA_OPTARG_Protofield_bool_MASK Integer mask of this field. */ -/* WSLUA_OPTARG_Protofield_bool_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* XXX: T/F strings */ -PROTOFIELD_BOOL(bool,FT_BOOLEAN) - -static int ProtoField_time(lua_State* L,enum ftenum type) { - ProtoField f; - const gchar* abbr = NULL; - const gchar* name = luaL_optstring(L,2,abbr); - unsigned base = (unsigned)luaL_optinteger(L,3,ABSOLUTE_TIME_LOCAL); - const gchar* blob = NULL; - - if (type == FT_ABSOLUTE_TIME) { - abbr = check_field_name(L,1,type); - blob = luaL_optstring(L,4,NULL); - if (base < ABSOLUTE_TIME_LOCAL || base > ABSOLUTE_TIME_DOY_UTC) { - luaL_argerror(L, 3, "Base must be either LOCAL, UTC, or DOY_UTC"); - return 0; - } - } else { - abbr = check_field_name(L,1,type); - blob = luaL_optstring(L,3,NULL); - } - - f = g_new(wslua_field_t,1); - - f->hfid = -2; - f->ett = -1; - f->name = g_strdup(name); - f->abbrev = g_strdup(abbr); - f->type = type; - f->vs = NULL; - f->base = base; - f->mask = 0; - if (blob && strcmp(blob, f->name) != 0) { - f->blob = g_strdup(blob); - } else { - f->blob = NULL; - } - - pushProtoField(L,f); - - return 1; -} - -#define PROTOFIELD_TIME(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_time(L,FT); } -/* _WSLUA_CONSTRUCTOR_ ProtoField_absolute_time Creates a `ProtoField` of a time_t structure value. */ -/* WSLUA_ARG_Protofield_absolute_time_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_absolute_time_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_absolute_time_BASE One of `base.LOCAL`, `base.UTC` or `base.DOY_UTC`. */ -/* WSLUA_OPTARG_Protofield_absolute_time_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_relative_time Creates a `ProtoField` of a time_t structure value. */ -/* WSLUA_ARG_Protofield_relative_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_relative_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_relative_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - - -PROTOFIELD_TIME(absolute_time,FT_ABSOLUTE_TIME) - -static int ProtoField_other(lua_State* L,enum ftenum type) { - ProtoField f; - const gchar* abbr = check_field_name(L,1,type); - const gchar* name = luaL_optstring(L,2,abbr); - const gchar* blob = luaL_optstring(L,3,NULL); - - f = g_new(wslua_field_t,1); - - f->hfid = -2; - f->ett = -1; - f->name = g_strdup(name); - f->abbrev = g_strdup(abbr); - f->type = type; - f->vs = NULL; - f->base = BASE_NONE; - f->mask = 0; - if (blob && strcmp(blob, f->name) != 0) { - f->blob = g_strdup(blob); - } else { - f->blob = NULL; - } - - pushProtoField(L,f); - - return 1; -} - -#define PROTOFIELD_OTHER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_other(L,FT); } -/* _WSLUA_CONSTRUCTOR_ ProtoField_none Creates a `ProtoField` of an unstructured type. */ -/* WSLUA_ARG_Protofield_none_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_none_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_none_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_ipv4 Creates a `ProtoField` of an IPv4 address (4 bytes). */ -/* WSLUA_ARG_Protofield_ipv4_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_ipv4_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_ipv4_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_ipv6 Creates a `ProtoField` of an IPv6 address (16 bytes). */ -/* WSLUA_ARG_Protofield_ipv6_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_ipv6_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_ipv6_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_ether Creates a `ProtoField` of an Ethernet address (6 bytes). */ -/* WSLUA_ARG_Protofield_ether_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_ether_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_ether_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_float Creates a `ProtoField` of a floating point number (4 bytes). */ -/* WSLUA_ARG_Protofield_float_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_float_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_float_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_double Creates a `ProtoField` of a double-precision floating point (8 bytes). */ -/* WSLUA_ARG_Protofield_double_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_double_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_double_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_string Creates a `ProtoField` of a string value. */ -/* WSLUA_ARG_Protofield_string_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_string_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_string_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_stringz Creates a `ProtoField` of a zero-terminated string value. */ -/* WSLUA_ARG_Protofield_stringz_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_stringz_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_stringz_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_bytes Creates a `ProtoField` for an arbitrary number of bytes. */ -/* WSLUA_ARG_Protofield_bytes_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_bytes_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_bytes_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_ubytes Creates a `ProtoField` for an arbitrary number of unsigned bytes. */ -/* WSLUA_ARG_Protofield_ubytes_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_ubytes_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_ubytes_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_guid Creates a `ProtoField` for a Globally Unique IDentifier (GUID). */ -/* WSLUA_ARG_Protofield_guid_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_guid_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_guid_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_oid Creates a `ProtoField` for an ASN.1 Organizational IDentified (OID). */ -/* WSLUA_ARG_Protofield_oid_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_oid_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_oid_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_rel_oid Creates a `ProtoField` for an ASN.1 Relative-OID. */ -/* WSLUA_ARG_Protofield_rel_oid_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_rel_oid_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_rel_oid_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_systemid Creates a `ProtoField` for an OSI System ID. */ -/* WSLUA_ARG_Protofield_systemid_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_systemid_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_systemid_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -/* _WSLUA_CONSTRUCTOR_ ProtoField_eui64 Creates a `ProtoField` for an EUI64. */ -/* WSLUA_ARG_Protofield_eui64_ABBR Abbreviated name of the field (the string used in filters). */ -/* WSLUA_OPTARG_Protofield_eui64_NAME Actual name of the field (the string that appears in the tree). */ -/* WSLUA_OPTARG_Protofield_eui64_DESC Description of the field. */ -/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ - -PROTOFIELD_OTHER(none,FT_NONE) -PROTOFIELD_OTHER(ipv4,FT_IPv4) -PROTOFIELD_OTHER(ipv6,FT_IPv6) -PROTOFIELD_OTHER(ipx,FT_IPXNET) -PROTOFIELD_OTHER(ether,FT_ETHER) -PROTOFIELD_OTHER(float,FT_FLOAT) -PROTOFIELD_OTHER(double,FT_DOUBLE) -PROTOFIELD_OTHER(relative_time,FT_RELATIVE_TIME) -PROTOFIELD_OTHER(string,FT_STRING) -PROTOFIELD_OTHER(stringz,FT_STRINGZ) -PROTOFIELD_OTHER(bytes,FT_BYTES) -PROTOFIELD_OTHER(ubytes,FT_UINT_BYTES) -PROTOFIELD_OTHER(guid,FT_GUID) -PROTOFIELD_OTHER(oid,FT_OID) -PROTOFIELD_OTHER(rel_oid,FT_REL_OID) -PROTOFIELD_OTHER(systemid,FT_SYSTEM_ID) -PROTOFIELD_OTHER(eui64,FT_EUI64) - -WSLUA_METAMETHOD ProtoField__tostring(lua_State* L) { - /* Returns a string with info about a protofield (for debugging purposes). */ - ProtoField f = checkProtoField(L,1); - gchar* s = g_strdup_printf("ProtoField(%i): %s %s %s %s %p %.8x %s", - f->hfid,f->name,f->abbrev, - ftenum_to_string(f->type), - base_to_string(f->base), - f->vs,f->mask,f->blob); - lua_pushstring(L,s); - g_free(s); - return 1; -} - -static int ProtoField__gc(lua_State* L) { - ProtoField f = toProtoField(L,1); - - /* - * A garbage collector for ProtoFields makes little sense. - * Even if This cannot be used anymore because it has gone out of scope, - * we can destroy the ProtoField only if it is not part of a ProtoFieldArray, - * if it actualy belongs to one we need to preserve it as it is pointed by - * a field array that may be registered afterwards causing a crash or memory corruption. - */ - - if (!f) { - luaL_argerror(L,1,"BUG: ProtoField_gc called for something not ProtoField"); - /* g_assert() ?? */ - } else if (f->hfid == -2) { - g_free(f->name); - g_free(f->abbrev); - g_free(f->blob); - g_free(f); - } - - return 0; -} - -WSLUA_METHODS ProtoField_methods[] = { - WSLUA_CLASS_FNREG(ProtoField,new), - WSLUA_CLASS_FNREG(ProtoField,none), - WSLUA_CLASS_FNREG(ProtoField,uint8), - WSLUA_CLASS_FNREG(ProtoField,uint16), - WSLUA_CLASS_FNREG(ProtoField,uint24), - WSLUA_CLASS_FNREG(ProtoField,uint32), - WSLUA_CLASS_FNREG(ProtoField,uint64), - WSLUA_CLASS_FNREG(ProtoField,int8), - WSLUA_CLASS_FNREG(ProtoField,int16), - WSLUA_CLASS_FNREG(ProtoField,int24), - WSLUA_CLASS_FNREG(ProtoField,int32), - WSLUA_CLASS_FNREG(ProtoField,int64), - WSLUA_CLASS_FNREG(ProtoField,framenum), - WSLUA_CLASS_FNREG(ProtoField,ipv4), - WSLUA_CLASS_FNREG(ProtoField,ipv6), - WSLUA_CLASS_FNREG(ProtoField,ipx), - WSLUA_CLASS_FNREG(ProtoField,ether), - WSLUA_CLASS_FNREG(ProtoField,bool), - WSLUA_CLASS_FNREG(ProtoField,float), - WSLUA_CLASS_FNREG(ProtoField,double), - WSLUA_CLASS_FNREG(ProtoField,absolute_time), - WSLUA_CLASS_FNREG(ProtoField,relative_time), - WSLUA_CLASS_FNREG(ProtoField,string), - WSLUA_CLASS_FNREG(ProtoField,stringz), - WSLUA_CLASS_FNREG(ProtoField,bytes), - WSLUA_CLASS_FNREG(ProtoField,ubytes), - WSLUA_CLASS_FNREG(ProtoField,guid), - WSLUA_CLASS_FNREG(ProtoField,oid), - WSLUA_CLASS_FNREG(ProtoField,rel_oid), - WSLUA_CLASS_FNREG(ProtoField,systemid), - WSLUA_CLASS_FNREG(ProtoField,eui64), - { NULL, NULL } -}; - -WSLUA_META ProtoField_meta[] = { - WSLUA_CLASS_MTREG(ProtoField,tostring), - { NULL, NULL } -}; - -int ProtoField_register(lua_State* L) { - WSLUA_REGISTER_CLASS(ProtoField); - return 0; -} - -WSLUA_CLASS_DEFINE(ProtoExpert,FAIL_ON_NULL("null ProtoExpert"),NOP); - /* A Protocol expert info field, to be used when adding items to the dissection tree. - - @since 1.11.3 - */ - -WSLUA_CONSTRUCTOR ProtoExpert_new(lua_State* L) { - /* Creates a new `ProtoExpert` object to be used for a protocol's expert information notices. - - @since 1.11.3 - */ -#define WSLUA_ARG_ProtoExpert_new_ABBR 1 /* Filter name of the expert info field (the string that - is used in filters). */ -#define WSLUA_ARG_ProtoExpert_new_TEXT 2 /* The default text of the expert field. */ -#define WSLUA_ARG_ProtoExpert_new_GROUP 3 /* Expert group type: one of: `expert.group.CHECKSUM`, - `expert.group.SEQUENCE`, `expert.group.RESPONSE_CODE`, - `expert.group.REQUEST_CODE`, `expert.group.UNDECODED`, - `expert.group.REASSEMBLE`, `expert.group.MALFORMED`, - `expert.group.DEBUG`, `expert.group.PROTOCOL`, - `expert.group.SECURITY`, or `expert.group.COMMENTS_GROUP`. */ -#define WSLUA_ARG_ProtoExpert_new_SEVERITY 4 /* Expert severity type: one of: - `expert.severity.COMMENT`, `expert.severity.CHAT`, - `expert.severity.NOTE`, `expert.severity.WARN`, - or `expert.severity.ERROR`. */ - - ProtoExpert pe = NULL; - const gchar* abbr = wslua_checkstring_only(L,WSLUA_ARG_ProtoExpert_new_ABBR); - const gchar* text = wslua_checkstring_only(L,WSLUA_ARG_ProtoExpert_new_TEXT); - int group = (int)luaL_checkinteger(L, WSLUA_ARG_ProtoExpert_new_GROUP); - int severity = (int)luaL_checkinteger(L, WSLUA_ARG_ProtoExpert_new_SEVERITY); - - pe = g_new(wslua_expert_field_t,1); - - pe->ids.ei = EI_INIT_EI; - pe->ids.hf = EI_INIT_HF; - pe->abbrev = g_strdup(abbr); - pe->text = g_strdup(text); - pe->group = group; - pe->severity = severity; - - pushProtoExpert(L,pe); - - WSLUA_RETURN(1); /* The newly created `ProtoExpert` object. */ -} - -WSLUA_METAMETHOD ProtoExpert__tostring(lua_State* L) { - /* Returns a string with debugging information about a `ProtoExpert` object. - - @since 1.11.3 - */ - ProtoExpert pe = toProtoExpert(L,1); - - if (!pe) { - lua_pushstring(L,"ProtoExpert pointer is NULL!"); - } else { - lua_pushfstring(L, "ProtoExpert: ei=%d, hf=%d, abbr=%s, text=%s, group=%d, severity=%d", - pe->ids.ei, pe->ids.hf, pe->abbrev, pe->text, pe->group, pe->severity); - } - return 1; -} - -static int ProtoExpert__gc(lua_State* L) { - ProtoExpert pe = toProtoExpert(L,1); - - /* - * A garbage collector for ProtoExpert makes little sense. - * Even if this cannot be used anymore because it has gone out of scope, - * we can destroy the ProtoExpert only if it is not part of a registered Proto, - * if it actually belongs to one we need to preserve it as it is pointed by - * a expert code causing a crash or memory corruption. - */ - - if (pe) { - luaL_argerror(L,1,"BUG: ProtoExpert_gc called for something not ProtoExpert"); - /* g_assert() ?? */ + g_free(fs); } - - return 0; -} - -WSLUA_METHODS ProtoExpert_methods[] = { - WSLUA_CLASS_FNREG(ProtoExpert,new), - { NULL, NULL } -}; - -WSLUA_META ProtoExpert_meta[] = { - WSLUA_CLASS_MTREG(ProtoExpert,tostring), - { NULL, NULL } -}; - -int ProtoExpert_register(lua_State* L) { - WSLUA_REGISTER_CLASS(ProtoExpert); - return 0; } @@ -1944,6 +514,8 @@ int Proto_register(lua_State* L) { WSLUA_REGISTER_CLASS(Proto); WSLUA_REGISTER_ATTRIBUTES(Proto); + outstanding_FuncSavers = g_ptr_array_new(); + lua_newtable(L); protocols_table_ref = luaL_ref(L, LUA_REGISTRYINDEX); @@ -2071,30 +643,6 @@ int Proto_commit(lua_State* L) { return 0; } -typedef struct _func_saver { - lua_State* state; - int get_len_ref; - int dissect_ref; -} func_saver_t; - -static GPtrArray* outstanding_FuncSavers = NULL; - -void clear_outstanding_FuncSavers(void) { - while (outstanding_FuncSavers->len) { - func_saver_t* fs = (func_saver_t*)g_ptr_array_remove_index_fast(outstanding_FuncSavers,0); - if (fs->state) { - lua_State* L = fs->state; - if (fs->get_len_ref != LUA_NOREF) { - luaL_unref(L, LUA_REGISTRYINDEX, fs->get_len_ref); - } - if (fs->dissect_ref != LUA_NOREF) { - luaL_unref(L, LUA_REGISTRYINDEX, fs->dissect_ref); - } - } - g_free(fs); - } -} - static guint wslua_dissect_tcp_get_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data _U_) @@ -2228,6 +776,8 @@ WSLUA_FUNCTION wslua_dissect_tcp_pdus(lua_State* L) { fs->dissect_ref = luaL_ref(L, LUA_REGISTRYINDEX); fs->get_len_ref = luaL_ref(L, LUA_REGISTRYINDEX); + /* save the passed-in function refs, so Lua's garbage collector won't + destroy them before they get invoked */ g_ptr_array_add(outstanding_FuncSavers, fs); tcp_dissect_pdus(tvb->ws_tvb, lua_pinfo, ti->tree, proto_desegment, @@ -2240,646 +790,6 @@ WSLUA_FUNCTION wslua_dissect_tcp_pdus(lua_State* L) { } -WSLUA_CLASS_DEFINE(Dissector,NOP,NOP); -/* - A refererence to a dissector, used to call a dissector against a packet or a part of it. - */ - -WSLUA_CONSTRUCTOR Dissector_get (lua_State *L) { - /* Obtains a dissector reference by name. */ -#define WSLUA_ARG_Dissector_get_NAME 1 /* The name of the dissector. */ - const gchar* name = luaL_checkstring(L,WSLUA_ARG_Dissector_get_NAME); - Dissector d; - - if ((d = find_dissector(name))) { - pushDissector(L, d); - WSLUA_RETURN(1); /* The Dissector reference. */ - } - - WSLUA_ARG_ERROR(Dissector_get,NAME,"No such dissector"); - return 0; -} - -/* Allow dissector key names to be sorted alphabetically. */ -static gint -compare_dissector_key_name(gconstpointer dissector_a, gconstpointer dissector_b) -{ - return strcmp((const char*)dissector_a, (const char*)dissector_b); -} - -WSLUA_CONSTRUCTOR Dissector_list (lua_State *L) { - /* Gets a Lua array table of all registered Dissector names. - - Note: this is an expensive operation, and should only be used for troubleshooting. - - @since 1.11.3 - */ - GList* list = get_dissector_names(); - GList* elist = NULL; - int i = 1; - - if (!list) return luaL_error(L,"Cannot retrieve Dissector name list"); - - list = g_list_sort(list, (GCompareFunc)compare_dissector_key_name); - elist = g_list_first(list); - - lua_newtable(L); - for (i=1; elist; i++, elist = g_list_next(elist)) { - lua_pushstring(L,(const char *) elist->data); - lua_rawseti(L,1,i); - } - - g_list_free(list); - WSLUA_RETURN(1); /* The array table of registered dissector names. */ -} - -WSLUA_METHOD Dissector_call(lua_State* L) { - /* Calls a dissector against a given packet (or part of it). */ -#define WSLUA_ARG_Dissector_call_TVB 2 /* The buffer to dissect. */ -#define WSLUA_ARG_Dissector_call_PINFO 3 /* The packet info. */ -#define WSLUA_ARG_Dissector_call_TREE 4 /* The tree on which to add the protocol items. */ - - Dissector volatile d = checkDissector(L,1); - Tvb tvb = checkTvb(L,WSLUA_ARG_Dissector_call_TVB); - Pinfo pinfo = checkPinfo(L,WSLUA_ARG_Dissector_call_PINFO); - TreeItem ti = checkTreeItem(L,WSLUA_ARG_Dissector_call_TREE); - const char *volatile error = NULL; - int len = 0; - - if (! ( d && tvb && pinfo) ) return 0; - - TRY { - len = call_dissector(d, tvb->ws_tvb, pinfo->ws_pinfo, ti->tree); - /* XXX Are we sure about this??? is this the right/only thing to catch */ - } CATCH_NONFATAL_ERRORS { - show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE); - error = "Malformed frame"; - } ENDTRY; - - if (error) { WSLUA_ERROR(Dissector_call,error); } - - lua_pushnumber(L,(lua_Number)len); - WSLUA_RETURN(1); /* Number of bytes dissected. Note that some dissectors always return number of bytes in incoming buffer, so be aware. */ -} - -WSLUA_METAMETHOD Dissector__call(lua_State* L) { - /* Calls a dissector against a given packet (or part of it). */ -#define WSLUA_ARG_Dissector__call_TVB 2 /* The buffer to dissect. */ -#define WSLUA_ARG_Dissector__call_PINFO 3 /* The packet info. */ -#define WSLUA_ARG_Dissector__call_TREE 4 /* The tree on which to add the protocol items. */ - return Dissector_call(L); -} - -WSLUA_METAMETHOD Dissector__tostring(lua_State* L) { - /* Gets the Dissector's protocol short name. */ - Dissector d = checkDissector(L,1); - if (!d) return 0; - lua_pushstring(L,dissector_handle_get_short_name(d)); - WSLUA_RETURN(1); /* A string of the protocol's short name. */ -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int Dissector__gc(lua_State* L _U_) { - /* do NOT free Dissector */ - return 0; -} - -WSLUA_METHODS Dissector_methods[] = { - WSLUA_CLASS_FNREG(Dissector,get), - WSLUA_CLASS_FNREG(Dissector,call), - WSLUA_CLASS_FNREG(Dissector,list), - { NULL, NULL } -}; - -WSLUA_META Dissector_meta[] = { - WSLUA_CLASS_MTREG(Dissector,tostring), - WSLUA_CLASS_MTREG(Dissector,call), - { NULL, NULL } -}; - -int Dissector_register(lua_State* L) { - WSLUA_REGISTER_CLASS(Dissector); - outstanding_FuncSavers = g_ptr_array_new(); - return 0; -} - -WSLUA_CLASS_DEFINE(DissectorTable,NOP,NOP); -/* - A table of subdissectors of a particular protocol (e.g. TCP subdissectors like http, smtp, - sip are added to table "tcp.port"). - - Useful to add more dissectors to a table so that they appear in the Decode As... dialog. - */ - -WSLUA_CONSTRUCTOR DissectorTable_new (lua_State *L) { - /* Creates a new DissectorTable for your dissector's use. */ -#define WSLUA_ARG_DissectorTable_new_TABLENAME 1 /* The short name of the table. */ -#define WSLUA_OPTARG_DissectorTable_new_UINAME 2 /* The name of the table in the User Interface - (defaults to the name given). */ -#define WSLUA_OPTARG_DissectorTable_new_TYPE 3 /* Either `ftypes.UINT8`, `ftypes.UINT16`, - `ftypes.UINT24`, `ftypes.UINT32`, or - `ftypes.STRING` - (defaults to `ftypes.UINT32`). */ -#define WSLUA_OPTARG_DissectorTable_new_BASE 4 /* Either `base.NONE`, `base.DEC`, `base.HEX`, - `base.OCT`, `base.DEC_HEX` or `base.HEX_DEC` - (defaults to `base.DEC`). */ - const gchar* name = (const gchar*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_new_TABLENAME); - const gchar* ui_name = (const gchar*)luaL_optstring(L,WSLUA_OPTARG_DissectorTable_new_UINAME,name); - enum ftenum type = (enum ftenum)luaL_optinteger(L,WSLUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32); - unsigned base = (unsigned)luaL_optinteger(L,WSLUA_OPTARG_DissectorTable_new_BASE,BASE_DEC); - - switch(type) { - case FT_STRING: - base = BASE_NONE; - /* fallthrough */ - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - { - DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t)); - - name = g_strdup(name); - ui_name = g_strdup(ui_name); - - dt->table = register_dissector_table(name, ui_name, type, base); - dt->name = name; - pushDissectorTable(L, dt); - } - WSLUA_RETURN(1); /* The newly created DissectorTable. */ - default: - WSLUA_OPTARG_ERROR(DissectorTable_new,TYPE,"must be ftypes.UINT{8,16,24,32} or ftypes.STRING"); - break; - } - return 0; -} - -/* this struct is used for passing ourselves user_data through dissector_all_tables_foreach_table(). */ -typedef struct dissector_tables_foreach_table_info { - int num; - lua_State *L; -} dissector_tables_foreach_table_info_t; - -/* this is the DATFunc_table function used for dissector_all_tables_foreach_table() - so we can get all dissector_table names. This pushes the name into a table at stack index 1 */ -static void -dissector_tables_list_func(const gchar *table_name, const gchar *ui_name _U_, gpointer user_data) { - dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data; - lua_pushstring(data->L, table_name); - lua_rawseti(data->L, 1, data->num); - data->num = data->num + 1; -} - -WSLUA_CONSTRUCTOR DissectorTable_list (lua_State *L) { - /* Gets a Lua array table of all DissectorTable names - i.e., the string names you can - use for the first argument to DissectorTable.get(). - - Note: this is an expensive operation, and should only be used for troubleshooting. - - @since 1.11.3 - */ - dissector_tables_foreach_table_info_t data = { 1, L }; - - lua_newtable(L); - - dissector_all_tables_foreach_table(dissector_tables_list_func, (gpointer)&data, - (GCompareFunc)compare_dissector_key_name); - - WSLUA_RETURN(1); /* The array table of registered DissectorTable names. */ -} - -/* this is the DATFunc_heur_table function used for dissector_all_heur_tables_foreach_table() - so we can get all heuristic dissector list names. This pushes the name into a table at stack index 1 */ -static void -heur_dissector_tables_list_func(const gchar *table_name, heur_dissector_list_t *table _U_, gpointer user_data) { - dissector_tables_foreach_table_info_t *data = (dissector_tables_foreach_table_info_t*) user_data; - lua_pushstring(data->L, table_name); - lua_rawseti(data->L, 1, data->num); - data->num = data->num + 1; -} - -WSLUA_CONSTRUCTOR DissectorTable_heuristic_list (lua_State *L) { - /* Gets a Lua array table of all heuristic list names - i.e., the string names you can - use for the first argument in Proto:register_heuristic(). - - Note: this is an expensive operation, and should only be used for troubleshooting. - - @since 1.11.3 - */ - dissector_tables_foreach_table_info_t data = { 1, L }; - - lua_newtable(L); - - dissector_all_heur_tables_foreach_table(heur_dissector_tables_list_func, (gpointer)&data, NULL); - - WSLUA_RETURN(1); /* The array table of registered heuristic list names */ -} - -WSLUA_CONSTRUCTOR DissectorTable_get (lua_State *L) { - /* - Obtain a reference to an existing dissector table. - */ -#define WSLUA_ARG_DissectorTable_get_TABLENAME 1 /* The short name of the table. */ - const gchar* name = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_TABLENAME); - dissector_table_t table = find_dissector_table(name); - - if (table) { - DissectorTable dt = (DissectorTable)g_malloc(sizeof(struct _wslua_distbl_t)); - dt->table = table; - dt->name = g_strdup(name); - - pushDissectorTable(L, dt); - - WSLUA_RETURN(1); /* The DissectorTable. */ - } - - WSLUA_ARG_ERROR(DissectorTable_get,TABLENAME,"no such dissector_table"); - return 0; -} - -WSLUA_METHOD DissectorTable_add (lua_State *L) { - /* - Add a `Proto` with a dissector function, or a `Dissector` object, to the dissector table. - */ -#define WSLUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer, a - integer range or a string depending on the table's type). */ -#define WSLUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either a `Proto` or a `Dissector`). */ - - DissectorTable dt = checkDissectorTable(L,1); - ftenum_t type; - Dissector handle; - - if (!dt) return 0; - - if( isProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) { - Proto p; - p = checkProto(L,WSLUA_ARG_DissectorTable_add_DISSECTOR); - handle = p->handle; - - if (! handle) { - WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"a Protocol that does not have a dissector cannot be added to a table"); - return 0; - } - - } else if ( isDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR) ) { - handle = toDissector(L,WSLUA_ARG_DissectorTable_add_DISSECTOR); - } else { - WSLUA_ARG_ERROR(DissectorTable_add,DISSECTOR,"must be either Proto or Dissector"); - return 0; - } - - type = get_dissector_table_selector_type(dt->name); - - if (type == FT_STRING) { - gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN)); - dissector_add_string(dt->name, pattern,handle); - g_free (pattern); - } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { - if (lua_isnumber(L, WSLUA_ARG_DissectorTable_add_PATTERN)) { - int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_add_PATTERN); - dissector_add_uint(dt->name, port, handle); - } else { - /* Not a number, try as range */ - const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_add_PATTERN); - range_t *range = NULL; - if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) { - dissector_add_uint_range(dt->name, range, handle); - } else { - g_free (range); - WSLUA_ARG_ERROR(DissectorTable_add,PATTERN,"invalid integer or range"); - return 0; - } - g_free (range); - } - } else { - luaL_error(L,"Strange type %d for a DissectorTable",type); - } - - return 0; -} - -WSLUA_METHOD DissectorTable_set (lua_State *L) { - /* - Remove existing dissectors from a table and add a new or a range of new dissectors. - - @since 1.11.3 - */ -#define WSLUA_ARG_DissectorTable_set_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */ -#define WSLUA_ARG_DissectorTable_set_DISSECTOR 3 /* The dissector to add (either a `Proto` or a `Dissector`). */ - - DissectorTable dt = checkDissectorTable(L,1); - ftenum_t type; - Dissector handle; - - if (!dt) return 0; - - if( isProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) { - Proto p; - p = checkProto(L,WSLUA_ARG_DissectorTable_set_DISSECTOR); - handle = p->handle; - - if (! handle) { - WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"a Protocol that does not have a dissector cannot be set to a table"); - return 0; - } - - } else if ( isDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR) ) { - handle = toDissector(L,WSLUA_ARG_DissectorTable_set_DISSECTOR); - } else { - WSLUA_ARG_ERROR(DissectorTable_set,DISSECTOR,"must be either Proto or Dissector"); - return 0; - } - - type = get_dissector_table_selector_type(dt->name); - - if (type == FT_STRING) { - const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN); - dissector_delete_all(dt->name, handle); - dissector_add_string(dt->name, pattern,handle); - } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { - if (lua_isnumber(L, WSLUA_ARG_DissectorTable_set_PATTERN)) { - int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_set_PATTERN); - dissector_delete_all(dt->name, handle); - dissector_add_uint(dt->name, port, handle); - } else { - /* Not a number, try as range */ - const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_set_PATTERN); - range_t *range = NULL; - if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) { - dissector_delete_all(dt->name, handle); - dissector_add_uint_range(dt->name, range, handle); - } else { - g_free (range); - WSLUA_ARG_ERROR(DissectorTable_set,PATTERN,"invalid integer or range"); - return 0; - } - g_free (range); - } - } else { - luaL_error(L,"Strange type %d for a DissectorTable",type); - } - - return 0; -} - -WSLUA_METHOD DissectorTable_remove (lua_State *L) { - /* - Remove a dissector or a range of dissectors from a table - */ -#define WSLUA_ARG_DissectorTable_remove_PATTERN 2 /* The pattern to match (either an integer, a integer range or a string depending on the table's type). */ -#define WSLUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to remove (either a `Proto` or a `Dissector`). */ - DissectorTable dt = checkDissectorTable(L,1); - ftenum_t type; - Dissector handle; - - if (!dt) return 0; - - if( isProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) { - Proto p; - p = checkProto(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR); - handle = p->handle; - - } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR) ) { - handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_DISSECTOR); - } else { - WSLUA_ARG_ERROR(DissectorTable_remove,DISSECTOR,"must be either Proto or Dissector"); - return 0; - } - - type = get_dissector_table_selector_type(dt->name); - - if (type == FT_STRING) { - gchar* pattern = g_strdup(luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN)); - dissector_delete_string(dt->name, pattern,handle); - g_free (pattern); - } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { - if (lua_isnumber(L, WSLUA_ARG_DissectorTable_remove_PATTERN)) { - int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_remove_PATTERN); - dissector_delete_uint(dt->name, port, handle); - } else { - /* Not a number, try as range */ - const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_remove_PATTERN); - range_t *range = NULL; - if (range_convert_str(&range, pattern, G_MAXUINT32) == CVT_NO_ERROR) - dissector_delete_uint_range(dt->name, range, handle); - else { - g_free (range); - WSLUA_ARG_ERROR(DissectorTable_remove,PATTERN,"invalid integer or range"); - return 0; - } - g_free (range); - } - } - - return 0; -} - -WSLUA_METHOD DissectorTable_remove_all (lua_State *L) { - /* - Remove all dissectors from a table. - - @since 1.11.3 - */ -#define WSLUA_ARG_DissectorTable_remove_all_DISSECTOR 2 /* The dissector to remove (either a `Proto` or a `Dissector`). */ - DissectorTable dt = checkDissectorTable(L,1); - Dissector handle; - - if (!dt) return 0; - - if( isProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) { - Proto p; - p = checkProto(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR); - handle = p->handle; - - } else if ( isDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR) ) { - handle = toDissector(L,WSLUA_ARG_DissectorTable_remove_all_DISSECTOR); - } else { - WSLUA_ARG_ERROR(DissectorTable_remove_all,DISSECTOR,"must be either Proto or Dissector"); - return 0; - } - - dissector_delete_all (dt->name, handle); - - return 0; -} - -WSLUA_METHOD DissectorTable_try (lua_State *L) { - /* - Try to call a dissector from a table - */ -#define WSLUA_ARG_DissectorTable_try_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */ -#define WSLUA_ARG_DissectorTable_try_TVB 3 /* The buffer to dissect. */ -#define WSLUA_ARG_DissectorTable_try_PINFO 4 /* The packet info. */ -#define WSLUA_ARG_DissectorTable_try_TREE 5 /* The tree on which to add the protocol items. */ - DissectorTable volatile dt = checkDissectorTable(L,1); - Tvb tvb = checkTvb(L,WSLUA_ARG_DissectorTable_try_TVB); - Pinfo pinfo = checkPinfo(L,WSLUA_ARG_DissectorTable_try_PINFO); - TreeItem ti = checkTreeItem(L,WSLUA_ARG_DissectorTable_try_TREE); - ftenum_t type; - gboolean handled = FALSE; - const gchar *volatile error = NULL; - int len = 0; - - if (! (dt && tvb && tvb->ws_tvb && pinfo && ti) ) return 0; - - type = get_dissector_table_selector_type(dt->name); - - TRY { - - if (type == FT_STRING) { - const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_try_PATTERN); - - len = dissector_try_string(dt->table,pattern,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree, NULL); - if (len > 0) { - handled = TRUE; - } - } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { - int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_try_PATTERN); - - len = dissector_try_uint(dt->table,port,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree); - if (len > 0) { - handled = TRUE; - } - } else { - luaL_error(L,"No such type of dissector_table"); - } - - if (!handled) { - len = call_dissector(lua_data_handle,tvb->ws_tvb,pinfo->ws_pinfo,ti->tree); - } - /* XXX Are we sure about this??? is this the right/only thing to catch */ - } CATCH_NONFATAL_ERRORS { - show_exception(tvb->ws_tvb, pinfo->ws_pinfo, ti->tree, EXCEPT_CODE, GET_MESSAGE); - error = "Malformed frame"; - } ENDTRY; - - if (error) { WSLUA_ERROR(DissectorTable_try,error); } - - lua_pushnumber(L,(lua_Number)len); - WSLUA_RETURN(1); /* Number of bytes dissected. Note that some dissectors always return number of bytes in incoming buffer, so be aware. */ -} - -WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) { - /* - Try to obtain a dissector from a table. - */ -#define WSLUA_ARG_DissectorTable_get_dissector_PATTERN 2 /* The pattern to be matched (either an integer or a string depending on the table's type). */ - - DissectorTable dt = checkDissectorTable(L,1); - ftenum_t type; - dissector_handle_t handle = lua_data_handle; - - if (!dt) return 0; - - type = get_dissector_table_selector_type(dt->name); - - if (type == FT_STRING) { - const gchar* pattern = luaL_checkstring(L,WSLUA_ARG_DissectorTable_get_dissector_PATTERN); - handle = dissector_get_string_handle(dt->table,pattern); - } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) { - int port = (int)luaL_checkinteger(L, WSLUA_ARG_DissectorTable_get_dissector_PATTERN); - handle = dissector_get_uint_handle(dt->table,port); - } - - if (handle) { - pushDissector(L,handle); - WSLUA_RETURN(1); /* The dissector handle if found. */ - } else { - lua_pushnil(L); - WSLUA_RETURN(1); /* nil if not found. */ - } -} - -WSLUA_METHOD DissectorTable_add_for_decode_as (lua_State *L) { - /* - Add the given `Proto` to the "Decode as..." list for this DissectorTable. - The passed-in `Proto` object's `dissector()` function is used for dissecting. - - @since 1.99.1 - */ -#define WSLUA_ARG_DissectorTable_add_for_decode_as_PROTO 2 /* The `Proto` to add. */ - DissectorTable dt = checkDissectorTable(L,1); - Proto proto = checkProto(L, WSLUA_ARG_DissectorTable_add_for_decode_as_PROTO); - dissector_handle_t handle = NULL; - - if (! proto->handle) { - proto->handle = new_register_dissector(proto->loname, dissect_lua, proto->hfid); - } - - handle = proto->handle; - - dissector_add_for_decode_as(dt->name, handle); - - return 0; -} - -/* XXX It would be nice to iterate and print which dissectors it has */ -WSLUA_METAMETHOD DissectorTable__tostring(lua_State* L) { - /* Gets some debug information about the DissectorTable. */ - DissectorTable dt = checkDissectorTable(L,1); - GString* s; - ftenum_t type; - - if (!dt) return 0; - - type = get_dissector_table_selector_type(dt->name); - s = g_string_new("DissectorTable "); - - switch(type) { - case FT_STRING: - { - g_string_append_printf(s,"%s String:\n",dt->name); - break; - } - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - { - int base = get_dissector_table_param(dt->name); - g_string_append_printf(s,"%s Integer(%i):\n",dt->name,base); - break; - } - default: - luaL_error(L,"Strange table type"); - } - - lua_pushstring(L,s->str); - g_string_free(s,TRUE); - WSLUA_RETURN(1); /* A string of debug information about the DissectorTable. */ -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int DissectorTable__gc(lua_State* L _U_) { - /* do NOT free DissectorTable */ - return 0; -} - -WSLUA_METHODS DissectorTable_methods[] = { - WSLUA_CLASS_FNREG(DissectorTable,new), - WSLUA_CLASS_FNREG(DissectorTable,get), - WSLUA_CLASS_FNREG(DissectorTable,list), - WSLUA_CLASS_FNREG(DissectorTable,heuristic_list), - WSLUA_CLASS_FNREG(DissectorTable,add), - WSLUA_CLASS_FNREG(DissectorTable,set), - WSLUA_CLASS_FNREG(DissectorTable,remove), - WSLUA_CLASS_FNREG(DissectorTable,remove_all), - WSLUA_CLASS_FNREG(DissectorTable,try), - WSLUA_CLASS_FNREG(DissectorTable,get_dissector), - WSLUA_CLASS_FNREG(DissectorTable,add_for_decode_as), - { NULL, NULL } -}; - -WSLUA_META DissectorTable_meta[] = { - WSLUA_CLASS_MTREG(DissectorTable,tostring), - { NULL, NULL } -}; - -int DissectorTable_register(lua_State* L) { - WSLUA_REGISTER_CLASS(DissectorTable); - return 0; -} - /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * diff --git a/epan/wslua/wslua_proto_expert.c b/epan/wslua/wslua_proto_expert.c new file mode 100644 index 0000000000..f1a36c13e3 --- /dev/null +++ b/epan/wslua/wslua_proto_expert.c @@ -0,0 +1,145 @@ +/* + * wslua_proto_expert.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + + +/* WSLUA_CONTINUE_MODULE Proto */ + + +WSLUA_CLASS_DEFINE(ProtoExpert,FAIL_ON_NULL("null ProtoExpert"),NOP); + /* A Protocol expert info field, to be used when adding items to the dissection tree. + + @since 1.11.3 + */ + +WSLUA_CONSTRUCTOR ProtoExpert_new(lua_State* L) { + /* Creates a new `ProtoExpert` object to be used for a protocol's expert information notices. + + @since 1.11.3 + */ +#define WSLUA_ARG_ProtoExpert_new_ABBR 1 /* Filter name of the expert info field (the string that + is used in filters). */ +#define WSLUA_ARG_ProtoExpert_new_TEXT 2 /* The default text of the expert field. */ +#define WSLUA_ARG_ProtoExpert_new_GROUP 3 /* Expert group type: one of: `expert.group.CHECKSUM`, + `expert.group.SEQUENCE`, `expert.group.RESPONSE_CODE`, + `expert.group.REQUEST_CODE`, `expert.group.UNDECODED`, + `expert.group.REASSEMBLE`, `expert.group.MALFORMED`, + `expert.group.DEBUG`, `expert.group.PROTOCOL`, + `expert.group.SECURITY`, or `expert.group.COMMENTS_GROUP`. */ +#define WSLUA_ARG_ProtoExpert_new_SEVERITY 4 /* Expert severity type: one of: + `expert.severity.COMMENT`, `expert.severity.CHAT`, + `expert.severity.NOTE`, `expert.severity.WARN`, + or `expert.severity.ERROR`. */ + + ProtoExpert pe = NULL; + const gchar* abbr = wslua_checkstring_only(L,WSLUA_ARG_ProtoExpert_new_ABBR); + const gchar* text = wslua_checkstring_only(L,WSLUA_ARG_ProtoExpert_new_TEXT); + int group = (int)luaL_checkinteger(L, WSLUA_ARG_ProtoExpert_new_GROUP); + int severity = (int)luaL_checkinteger(L, WSLUA_ARG_ProtoExpert_new_SEVERITY); + + pe = g_new(wslua_expert_field_t,1); + + pe->ids.ei = EI_INIT_EI; + pe->ids.hf = EI_INIT_HF; + pe->abbrev = g_strdup(abbr); + pe->text = g_strdup(text); + pe->group = group; + pe->severity = severity; + + pushProtoExpert(L,pe); + + WSLUA_RETURN(1); /* The newly created `ProtoExpert` object. */ +} + +WSLUA_METAMETHOD ProtoExpert__tostring(lua_State* L) { + /* Returns a string with debugging information about a `ProtoExpert` object. + + @since 1.11.3 + */ + ProtoExpert pe = toProtoExpert(L,1); + + if (!pe) { + lua_pushstring(L,"ProtoExpert pointer is NULL!"); + } else { + lua_pushfstring(L, "ProtoExpert: ei=%d, hf=%d, abbr=%s, text=%s, group=%d, severity=%d", + pe->ids.ei, pe->ids.hf, pe->abbrev, pe->text, pe->group, pe->severity); + } + return 1; +} + +static int ProtoExpert__gc(lua_State* L) { + ProtoExpert pe = toProtoExpert(L,1); + + /* + * A garbage collector for ProtoExpert makes little sense. + * Even if this cannot be used anymore because it has gone out of scope, + * we can destroy the ProtoExpert only if it is not part of a registered Proto, + * if it actually belongs to one we need to preserve it as it is pointed by + * a expert code causing a crash or memory corruption. + */ + + if (pe) { + luaL_argerror(L,1,"BUG: ProtoExpert_gc called for something not ProtoExpert"); + /* g_assert() ?? */ + } + + return 0; +} + +WSLUA_METHODS ProtoExpert_methods[] = { + WSLUA_CLASS_FNREG(ProtoExpert,new), + { NULL, NULL } +}; + +WSLUA_META ProtoExpert_meta[] = { + WSLUA_CLASS_MTREG(ProtoExpert,tostring), + { NULL, NULL } +}; + +int ProtoExpert_register(lua_State* L) { + WSLUA_REGISTER_CLASS(ProtoExpert); + 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: + */ diff --git a/epan/wslua/wslua_proto_field.c b/epan/wslua/wslua_proto_field.c new file mode 100644 index 0000000000..bb91b6cbe8 --- /dev/null +++ b/epan/wslua/wslua_proto_field.c @@ -0,0 +1,997 @@ +/* + * wslua_proto_field.c + * + * Wireshark's interface to the Lua Programming Language + * + * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> + * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> + * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include "wslua.h" + + +/* WSLUA_CONTINUE_MODULE Proto */ + + +WSLUA_CLASS_DEFINE(ProtoField,FAIL_ON_NULL("null ProtoField"),NOP); + /* A Protocol field (to be used when adding items to the dissection tree). */ + +static const wslua_ft_types_t ftenums[] = { + {"ftypes.NONE", FT_NONE}, + {"ftypes.BOOLEAN", FT_BOOLEAN}, + {"ftypes.UINT8", FT_UINT8}, + {"ftypes.UINT16", FT_UINT16}, + {"ftypes.UINT24", FT_UINT24}, + {"ftypes.UINT32", FT_UINT32}, + {"ftypes.UINT64", FT_UINT64}, + {"ftypes.INT8", FT_INT8}, + {"ftypes.INT16", FT_INT16}, + {"ftypes.INT24", FT_INT24}, + {"ftypes.INT32", FT_INT32}, + {"ftypes.INT64", FT_INT64}, + {"ftypes.FLOAT", FT_FLOAT}, + {"ftypes.DOUBLE", FT_DOUBLE}, + {"ftypes.ABSOLUTE_TIME", FT_ABSOLUTE_TIME}, + {"ftypes.RELATIVE_TIME", FT_RELATIVE_TIME}, + {"ftypes.STRING", FT_STRING}, + {"ftypes.STRINGZ", FT_STRINGZ}, + {"ftypes.ETHER", FT_ETHER}, + {"ftypes.BYTES", FT_BYTES}, + {"ftypes.UINT_BYTES", FT_UINT_BYTES}, + {"ftypes.IPv4", FT_IPv4}, + {"ftypes.IPv6", FT_IPv6}, + {"ftypes.IPXNET", FT_IPXNET}, + {"ftypes.FRAMENUM", FT_FRAMENUM}, + {"ftypes.GUID", FT_GUID}, + {"ftypes.OID", FT_OID}, + {"ftypes.SYSTEM_ID", FT_SYSTEM_ID}, + {"ftypes.REL_OID", FT_REL_OID}, + {"ftypes.EUI64", FT_EUI64}, + {"ftypes.FCWWN", FT_FCWWN}, + {NULL, FT_NONE} +}; + +static enum ftenum get_ftenum(const gchar* type) { + const wslua_ft_types_t* ts; + for (ts = ftenums; ts->str; ts++) { + if ( g_str_equal(ts->str,type) ) { + return ts->id; + } + } + return FT_NONE; +} + +static const gchar* ftenum_to_string(enum ftenum ft) { + const wslua_ft_types_t* ts; + for (ts = ftenums; ts->str; ts++) { + if ( ts->id == ft ) { + return ts->str; + } + } + return NULL; +} + +struct field_display_string_t { + const gchar* str; + unsigned base; +}; + +static const struct field_display_string_t base_displays[] = { + {"base.NONE", BASE_NONE}, + {"base.DEC", BASE_DEC}, + {"base.HEX", BASE_HEX}, + {"base.OCT", BASE_OCT}, + {"base.DEC_HEX", BASE_DEC_HEX}, + {"base.HEX_DEC", BASE_HEX_DEC}, + /* for FT_BOOLEAN, how wide the parent bitfield is */ + {"8",8}, + {"16",16}, + {"24",24}, + {"32",32}, + /* for FT_ABSOLUTE_TIME use values in absolute_time_display_e */ + {"LOCAL", ABSOLUTE_TIME_LOCAL}, + {"UTC", ABSOLUTE_TIME_UTC}, + {"DOY_UTC", ABSOLUTE_TIME_DOY_UTC}, + {NULL,0} +}; + +static const gchar* base_to_string(unsigned base) { + const struct field_display_string_t* b; + for (b=base_displays;b->str;b++) { + if ( base == b->base) + return b->str; + } + return NULL; +} + +static unsigned string_to_base(const gchar* str) { + const struct field_display_string_t* b; + for (b=base_displays;b->str;b++) { + if ( g_str_equal(str,b->str)) + return b->base; + } + return BASE_NONE; +} + +static value_string* value_string_from_table(lua_State* L, int idx) { + GArray* vs = g_array_new(TRUE,TRUE,sizeof(value_string)); + value_string* ret; + + if(lua_isnil(L,idx)) { + return NULL; + } else if (!lua_istable(L,idx)) { + luaL_argerror(L,idx,"must be a table"); + g_array_free(vs,TRUE); + return NULL; + } + + lua_pushnil(L); + + while (lua_next(L, idx) != 0) { + value_string v = {0,NULL}; + + if (! lua_isnumber(L,-2)) { + luaL_argerror(L,idx,"All keys of a table used as value_string must be integers"); + g_array_free(vs,TRUE); + return NULL; + } + + if (! lua_isstring(L,-1)) { + luaL_argerror(L,idx,"All values of a table used as value_string must be strings"); + g_array_free(vs,TRUE); + return NULL; + } + + v.value = wslua_toguint32(L,-2); + v.strptr = g_strdup(lua_tostring(L,-1)); + + g_array_append_val(vs,v); + + lua_pop(L, 1); + } + + ret = (value_string*)(void*)vs->data; + + g_array_free(vs,FALSE); + + return ret; +} + +static val64_string* val64_string_from_table(lua_State* L, int idx) { + GArray* vs = g_array_new(TRUE,TRUE,sizeof(val64_string)); + val64_string* ret; + + if(lua_isnil(L,idx)) { + return NULL; + } else if (!lua_istable(L,idx)) { + luaL_argerror(L,idx,"must be a table"); + g_array_free(vs,TRUE); + return NULL; + } + + lua_pushnil(L); + + while (lua_next(L, idx) != 0) { + val64_string v = {0,NULL}; + + if (! lua_isnumber(L,-2)) { + luaL_argerror(L,idx,"All keys of a table used as value string must be integers"); + g_array_free(vs,TRUE); + return NULL; + } + + if (! lua_isstring(L,-1)) { + luaL_argerror(L,idx,"All values of a table used as value string must be strings"); + g_array_free(vs,TRUE); + return NULL; + } + + v.value = wslua_toguint64(L, -2); + v.strptr = g_strdup(lua_tostring(L,-1)); + + g_array_append_val(vs,v); + + lua_pop(L, 1); + } + + ret = (val64_string*)(void*)vs->data; + + g_array_free(vs,FALSE); + + return ret; +} + +static true_false_string* true_false_string_from_table(lua_State* L, int idx) { + GArray* tfs = g_array_new(TRUE,TRUE,sizeof(true_false_string)); + true_false_string* ret; + true_false_string tf = { "True", "False" }; + + if (lua_isnil(L,idx)) { + return NULL; + } else if (!lua_istable(L,idx)) { + luaL_argerror(L,idx,"must be a table"); + g_array_free(tfs,TRUE); + return NULL; + } + + lua_pushnil(L); + + while (lua_next(L, idx)) { + + if (! lua_isnumber(L,-2)) { + luaL_argerror(L,idx,"All keys of a table used as true_false_string must be integers"); + g_array_free(tfs,TRUE); + return NULL; + } + + if (! lua_isstring(L,-1)) { + luaL_argerror(L,idx,"All values of a table used as true_false_string must be strings"); + g_array_free(tfs,TRUE); + return NULL; + } + + /* arrays in LUA start with index number 1 */ + if (lua_tointeger(L,-2) == 1) + tf.true_string = g_strdup(lua_tostring(L,-1)); + + if (lua_tointeger(L,-2) == 2) + tf.false_string = g_strdup(lua_tostring(L,-1)); + + lua_pop(L, 1); + } + + g_array_append_val(tfs,tf); + + ret = (true_false_string*)(void*)tfs->data; + + g_array_free(tfs,FALSE); + + return ret; +} + +static const gchar* check_field_name(lua_State* L, const int abbr_idx, const enum ftenum type) { + const gchar* abbr = luaL_checkstring(L,abbr_idx); + const header_field_info* hfinfo = NULL; + + if (!abbr[0]) { + luaL_argerror(L, abbr_idx, "Empty field name abbreviation"); + return NULL; + } + + if (proto_check_field_name(abbr)) { + luaL_argerror(L, abbr_idx, "Invalid char in abbrev"); + return NULL; + } + + hfinfo = proto_registrar_get_byname(abbr); + + if (hfinfo && !ftype_similar_types(type, hfinfo->type)) { + luaL_argerror(L, abbr_idx, "A field of an incompatible ftype with this abbrev already exists"); + return NULL; + } + + return abbr; +} + +WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) { + /* Creates a new `ProtoField` object to be used for a protocol field. */ +#define WSLUA_ARG_ProtoField_new_NAME 1 /* Actual name of the field (the string that + appears in the tree). */ +#define WSLUA_ARG_ProtoField_new_ABBR 2 /* Filter name of the field (the string that + is used in filters). */ +#define WSLUA_ARG_ProtoField_new_TYPE 3 /* Field Type: one of: `ftypes.BOOLEAN`, `ftypes.UINT8`, + `ftypes.UINT16`, `ftypes.UINT24`, `ftypes.UINT32`, `ftypes.UINT64`, `ftypes.INT8`, + `ftypes.INT16`, `ftypes.INT24`, `ftypes.INT32`, `ftypes.INT64`, `ftypes.FLOAT`, + `ftypes.DOUBLE` , `ftypes.ABSOLUTE_TIME`, `ftypes.RELATIVE_TIME`, `ftypes.STRING`, + `ftypes.STRINGZ`, `ftypes.UINT_STRING`, `ftypes.ETHER`, `ftypes.BYTES`, + `ftypes.UINT_BYTES`, `ftypes.IPv4`, `ftypes.IPv6`, `ftypes.IPXNET`, `ftypes.FRAMENUM`, + `ftypes.PCRE`, `ftypes.GUID`, `ftypes.OID`, `ftypes.REL_OID`, `ftypes.SYSTEM_ID`, + `ftypes.EUI64` or `ftypes.NONE`. + */ +#define WSLUA_OPTARG_ProtoField_new_VALUESTRING 4 /* A table containing the text that + corresponds to the values. */ +#define WSLUA_OPTARG_ProtoField_new_BASE 5 /* The representation, one of: `base.NONE`, `base.DEC`, + `base.HEX`, `base.OCT`, `base.DEC_HEX`, or + `base.HEX_DEC`. */ +#define WSLUA_OPTARG_ProtoField_new_MASK 6 /* The bitmask to be used. */ +#define WSLUA_OPTARG_ProtoField_new_DESCR 7 /* The description of the field. */ + + ProtoField f; + int nargs = lua_gettop(L); + const gchar* name = luaL_checkstring(L,WSLUA_ARG_ProtoField_new_NAME); + const gchar* abbr = NULL; + enum ftenum type; + value_string *vs32 = NULL; + val64_string *vs64 = NULL; + true_false_string *tfs = NULL; + unsigned base; + guint32 mask = wslua_optguint32(L, WSLUA_OPTARG_ProtoField_new_MASK, 0x0); + const gchar *blob = luaL_optstring(L,WSLUA_OPTARG_ProtoField_new_DESCR,NULL); + + if (lua_isnumber(L,WSLUA_ARG_ProtoField_new_TYPE)) { + type = (enum ftenum)luaL_checkinteger(L,WSLUA_ARG_ProtoField_new_TYPE); + } else { + type = get_ftenum(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_TYPE)); + } + + abbr = check_field_name(L,WSLUA_ARG_ProtoField_new_ABBR,type); + + if (lua_isnumber(L, WSLUA_OPTARG_ProtoField_new_BASE)) { + base = (unsigned)luaL_optinteger(L, WSLUA_OPTARG_ProtoField_new_BASE, BASE_NONE); + } else { + base = string_to_base(luaL_optstring(L, WSLUA_OPTARG_ProtoField_new_BASE, "BASE_NONE")); + } + + switch (type) { + case FT_FRAMENUM: + if (base != BASE_NONE) { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"FRAMENUM must use base.NONE"); + return 0; + } + if (mask) { + WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"FRAMENUM can not have a bitmask"); + return 0; + } + break; + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + case FT_UINT64: + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + case FT_INT64: + if (base == BASE_NONE) { + base = BASE_DEC; /* Default base for integer */ + } else if (base < BASE_DEC || base > BASE_HEX_DEC) { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be either base.DEC, base.HEX, base.OCT," + " base.DEC_HEX, base.DEC_HEX or base.HEX_DEC"); + return 0; + } + if ((base == BASE_HEX || base == BASE_OCT) && + (type == FT_INT8 || type == FT_INT16 || type == FT_INT24 || type == FT_INT32 || type == FT_INT64)) + { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"This type does not display as hexadecimal"); + return 0; + } + if (nargs >= WSLUA_OPTARG_ProtoField_new_VALUESTRING && !lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING)) { + if (type == FT_UINT64 || type == FT_INT64) { + vs64 = val64_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); + } else { + vs32 = value_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); + } + } + break; + case FT_BOOLEAN: + if (mask == 0x0 && base != BASE_NONE) { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be base.NONE if bitmask is zero."); + return 0; + } + if (mask != 0x0 && (base < 1 || base > 64)) { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be between 1 and 64 if bitmask is non-zero."); + return 0; + } + if (nargs >= WSLUA_OPTARG_ProtoField_new_VALUESTRING && !lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING)) { + tfs = true_false_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING); + } + break; + case FT_ABSOLUTE_TIME: + if (base == BASE_NONE) { + base = ABSOLUTE_TIME_LOCAL; /* Default base for FT_ABSOLUTE_TIME */ + } else if (base < ABSOLUTE_TIME_LOCAL || base > ABSOLUTE_TIME_DOY_UTC) { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be either LOCAL, UTC, or DOY_UTC"); + return 0; + } + if (mask) { + WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"ABSOLUTE_TIME can not have a bitmask"); + return 0; + } + break; + case FT_NONE: + case FT_IPv4: + case FT_IPv6: + case FT_IPXNET: + case FT_ETHER: + case FT_FLOAT: + case FT_DOUBLE: + case FT_RELATIVE_TIME: + case FT_STRING: + case FT_STRINGZ: + case FT_BYTES: + case FT_UINT_BYTES: + case FT_GUID: + case FT_OID: + case FT_SYSTEM_ID: + case FT_REL_OID: + case FT_EUI64: + case FT_VINES: + case FT_FCWWN: + if (base != BASE_NONE) { + WSLUA_OPTARG_ERROR(ProtoField_new,BASE,"Base must be base.NONE"); + return 0; + } + if (mask) { + WSLUA_OPTARG_ERROR(ProtoField_new,MASK,"This type can not have a bitmask"); + return 0; + } + break; + default: + WSLUA_ARG_ERROR(ProtoField_new,TYPE,"Invalid field type"); + break; + } + + f = g_new(wslua_field_t,1); + + f->hfid = -2; + f->ett = -1; + f->name = g_strdup(name); + f->abbrev = g_strdup(abbr); + f->type = type; + f->base = base; + if (tfs) { + f->vs = TFS(tfs); + } else if (vs32) { + f->vs = VALS(vs32); + } else if (vs64) { + /* Indicate that we are using val64_string */ + f->base |= BASE_VAL64_STRING; + f->vs = VALS(vs64); + } else { + f->vs = NULL; + } + f->mask = mask; + if (blob && strcmp(blob, f->name) != 0) { + f->blob = g_strdup(blob); + } else { + f->blob = NULL; + } + + pushProtoField(L,f); + + WSLUA_RETURN(1); /* The newly created `ProtoField` object. */ +} + +static int ProtoField_integer(lua_State* L, enum ftenum type) { + ProtoField f; + const gchar* abbr = check_field_name(L,1,type); + const gchar* name = luaL_optstring(L,2,abbr); + unsigned default_base = (type == FT_FRAMENUM) ? BASE_NONE : BASE_DEC; + unsigned base = (unsigned)luaL_optinteger(L, 3, default_base); + value_string* vs32 = NULL; + val64_string* vs64 = NULL; + guint32 mask = wslua_optguint32(L,5,0); + const gchar* blob = luaL_optstring(L,6,NULL); + + if (lua_gettop(L) > 3) { + if (type == FT_UINT64 || type == FT_INT64) { + vs64 = val64_string_from_table(L,4); + } else { + vs32 = value_string_from_table(L,4); + } + } + + if (type == FT_FRAMENUM) { + if (base != BASE_NONE) + luaL_argerror(L, 3, "ftypes.FRAMENUMs must use base.NONE"); + else if (mask) + luaL_argerror(L, 3, "ftypes.FRAMENUMs can not have a bitmask"); + } else if (base < BASE_DEC || base > BASE_HEX_DEC) { + luaL_argerror(L, 3, "Base must be either base.DEC, base.HEX, base.OCT," + " base.DEC_HEX, base.DEC_HEX or base.HEX_DEC"); + return 0; + } else if ((base == BASE_HEX || base == BASE_OCT) && + (type == FT_INT8 || type == FT_INT16 || type == FT_INT24 || type == FT_INT32 || type == FT_INT64)) { + luaL_argerror(L, 3, "This type does not display as hexadecimal"); + return 0; + } + + f = g_new(wslua_field_t,1); + + f->hfid = -2; + f->ett = -1; + f->name = g_strdup(name); + f->abbrev = g_strdup(abbr); + f->type = type; + f->base = base; + if (vs64) { + /* Indicate that we are using val64_string */ + f->base |= BASE_VAL64_STRING; + f->vs = VALS(vs64); + } else { + f->vs = VALS(vs32); + } + f->mask = mask; + if (blob && strcmp(blob, f->name) != 0) { + f->blob = g_strdup(blob); + } else { + f->blob = NULL; + } + + pushProtoField(L,f); + + return 1; +} + +#define PROTOFIELD_INTEGER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_integer(L,FT); } +/* _WSLUA_CONSTRUCTOR_ ProtoField_uint8 Creates a `ProtoField` of an unsigned 8-bit integer (i.e., a byte). */ +/* WSLUA_ARG_Protofield_uint8_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_uint8_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_uint8_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_uint8_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_uint8_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_uint8_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_uint16 Creates a `ProtoField` of an unsigned 16-bit integer. */ +/* WSLUA_ARG_Protofield_uint16_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_uint16_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_uint16_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_uint16_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_uint16_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_uint16_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_uint24 Creates a `ProtoField` of an unsigned 24-bit integer. */ +/* WSLUA_ARG_Protofield_uint24_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_uint24_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_uint24_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_uint24_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_uint24_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_uint24_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_uint32 Creates a `ProtoField` of an unsigned 32-bit integer. */ +/* WSLUA_ARG_Protofield_uint32_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_uint32_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_uint32_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_uint32_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_uint32_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_uint32_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_uint64 Creates a `ProtoField` of an unsigned 64-bit integer. */ +/* WSLUA_ARG_Protofield_uint64_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_uint64_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_uint64_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_uint64_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_uint64_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_uint64_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_int8 Creates a `ProtoField` of a signed 8-bit integer (i.e., a byte). */ +/* WSLUA_ARG_Protofield_int8_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_int8_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_int8_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_int8_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_int8_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_int8_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_int16 Creates a `ProtoField` of a signed 16-bit integer. */ +/* WSLUA_ARG_Protofield_int16_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_int16_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_int16_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_int16_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_int16_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_int16_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_int24 Creates a `ProtoField` of a signed 24-bit integer. */ +/* WSLUA_ARG_Protofield_int24_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_int24_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_int24_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_int24_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_int24_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_int24_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_int32 Creates a `ProtoField` of a signed 32-bit integer. */ +/* WSLUA_ARG_Protofield_int32_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_int32_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_int32_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_int32_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_int32_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_int32_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_int64 Creates a `ProtoField` of a signed 64-bit integer. */ +/* WSLUA_ARG_Protofield_int64_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_int64_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_int64_BASE One of `base.DEC`, `base.HEX` or `base.OCT`. */ +/* WSLUA_OPTARG_Protofield_int64_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_int64_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_int64_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_framenum Creates a `ProtoField` for a frame number (for hyperlinks between frames). */ +/* WSLUA_ARG_Protofield_framenum_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_framenum_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_framenum_BASE Only `base.NONE` is supported for framenum. */ +/* WSLUA_OPTARG_Protofield_framenum_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_framenum_MASK Integer mask of this field, which must be 0 for framenum. */ +/* WSLUA_OPTARG_Protofield_framenum_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +PROTOFIELD_INTEGER(uint8,FT_UINT8) +PROTOFIELD_INTEGER(uint16,FT_UINT16) +PROTOFIELD_INTEGER(uint24,FT_UINT24) +PROTOFIELD_INTEGER(uint32,FT_UINT32) +PROTOFIELD_INTEGER(uint64,FT_UINT64) +PROTOFIELD_INTEGER(int8,FT_INT8) +PROTOFIELD_INTEGER(int16,FT_INT16) +PROTOFIELD_INTEGER(int24,FT_INT24) +PROTOFIELD_INTEGER(int32,FT_INT32) +PROTOFIELD_INTEGER(int64,FT_INT64) +PROTOFIELD_INTEGER(framenum,FT_FRAMENUM) + +static int ProtoField_boolean(lua_State* L, enum ftenum type) { + ProtoField f; + const gchar* abbr = check_field_name(L,1,type); + const gchar* name = luaL_optstring(L,2,abbr); + unsigned base = (unsigned)luaL_optinteger(L, 3, BASE_NONE); + true_false_string* tfs = NULL; + guint32 mask = wslua_optguint32(L,5,0); + const gchar* blob = luaL_optstring(L,6,NULL); + + if (mask == 0x0 && base != BASE_NONE) { + luaL_argerror(L,2,"Fieldbase (fielddisplay) must be base.NONE" + " if bitmask is zero."); + return 0; + } + + if (mask != 0x0 && (base < 1 || base > 64)) { + luaL_argerror(L,2,"Fieldbase (fielddisplay) must be between 1 and 64" + " if bitmask is non-zero."); + return 0; + } + + if (lua_gettop(L) > 3 && !lua_isnil(L,4)) { + tfs = true_false_string_from_table(L,4); + } + + f = g_new(wslua_field_t,1); + + f->hfid = -2; + f->ett = -1; + f->name = g_strdup(name); + f->abbrev = g_strdup(abbr); + f->type = type; + f->vs = TFS(tfs); + f->base = base; + f->mask = mask; + if (blob && strcmp(blob, f->name) != 0) { + f->blob = g_strdup(blob); + } else { + f->blob = NULL; + } + + pushProtoField(L,f); + + return 1; +} + +#define PROTOFIELD_BOOL(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_boolean(L,FT); } +/* _WSLUA_CONSTRUCTOR_ ProtoField_bool Creates a `ProtoField` for a boolean true/false value. */ +/* WSLUA_ARG_Protofield_bool_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_bool_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_bool_DISPLAY how wide the parent bitfield is (`base.NONE` is used for NULL-value). */ +/* WSLUA_OPTARG_Protofield_bool_VALUESTRING A table containing the text that corresponds to the values. */ +/* WSLUA_OPTARG_Protofield_bool_MASK Integer mask of this field. */ +/* WSLUA_OPTARG_Protofield_bool_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* XXX: T/F strings */ +PROTOFIELD_BOOL(bool,FT_BOOLEAN) + +static int ProtoField_time(lua_State* L,enum ftenum type) { + ProtoField f; + const gchar* abbr = NULL; + const gchar* name = luaL_optstring(L,2,abbr); + unsigned base = (unsigned)luaL_optinteger(L,3,ABSOLUTE_TIME_LOCAL); + const gchar* blob = NULL; + + if (type == FT_ABSOLUTE_TIME) { + abbr = check_field_name(L,1,type); + blob = luaL_optstring(L,4,NULL); + if (base < ABSOLUTE_TIME_LOCAL || base > ABSOLUTE_TIME_DOY_UTC) { + luaL_argerror(L, 3, "Base must be either LOCAL, UTC, or DOY_UTC"); + return 0; + } + } else { + abbr = check_field_name(L,1,type); + blob = luaL_optstring(L,3,NULL); + } + + f = g_new(wslua_field_t,1); + + f->hfid = -2; + f->ett = -1; + f->name = g_strdup(name); + f->abbrev = g_strdup(abbr); + f->type = type; + f->vs = NULL; + f->base = base; + f->mask = 0; + if (blob && strcmp(blob, f->name) != 0) { + f->blob = g_strdup(blob); + } else { + f->blob = NULL; + } + + pushProtoField(L,f); + + return 1; +} + +#define PROTOFIELD_TIME(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_time(L,FT); } +/* _WSLUA_CONSTRUCTOR_ ProtoField_absolute_time Creates a `ProtoField` of a time_t structure value. */ +/* WSLUA_ARG_Protofield_absolute_time_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_absolute_time_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_absolute_time_BASE One of `base.LOCAL`, `base.UTC` or `base.DOY_UTC`. */ +/* WSLUA_OPTARG_Protofield_absolute_time_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_relative_time Creates a `ProtoField` of a time_t structure value. */ +/* WSLUA_ARG_Protofield_relative_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_relative_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_relative_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + + +PROTOFIELD_TIME(absolute_time,FT_ABSOLUTE_TIME) + +static int ProtoField_other(lua_State* L,enum ftenum type) { + ProtoField f; + const gchar* abbr = check_field_name(L,1,type); + const gchar* name = luaL_optstring(L,2,abbr); + const gchar* blob = luaL_optstring(L,3,NULL); + + f = g_new(wslua_field_t,1); + + f->hfid = -2; + f->ett = -1; + f->name = g_strdup(name); + f->abbrev = g_strdup(abbr); + f->type = type; + f->vs = NULL; + f->base = BASE_NONE; + f->mask = 0; + if (blob && strcmp(blob, f->name) != 0) { + f->blob = g_strdup(blob); + } else { + f->blob = NULL; + } + + pushProtoField(L,f); + + return 1; +} + +#define PROTOFIELD_OTHER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_other(L,FT); } +/* _WSLUA_CONSTRUCTOR_ ProtoField_none Creates a `ProtoField` of an unstructured type. */ +/* WSLUA_ARG_Protofield_none_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_none_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_none_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_ipv4 Creates a `ProtoField` of an IPv4 address (4 bytes). */ +/* WSLUA_ARG_Protofield_ipv4_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_ipv4_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_ipv4_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_ipv6 Creates a `ProtoField` of an IPv6 address (16 bytes). */ +/* WSLUA_ARG_Protofield_ipv6_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_ipv6_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_ipv6_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_ether Creates a `ProtoField` of an Ethernet address (6 bytes). */ +/* WSLUA_ARG_Protofield_ether_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_ether_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_ether_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_float Creates a `ProtoField` of a floating point number (4 bytes). */ +/* WSLUA_ARG_Protofield_float_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_float_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_float_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_double Creates a `ProtoField` of a double-precision floating point (8 bytes). */ +/* WSLUA_ARG_Protofield_double_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_double_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_double_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_string Creates a `ProtoField` of a string value. */ +/* WSLUA_ARG_Protofield_string_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_string_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_string_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_stringz Creates a `ProtoField` of a zero-terminated string value. */ +/* WSLUA_ARG_Protofield_stringz_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_stringz_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_stringz_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_bytes Creates a `ProtoField` for an arbitrary number of bytes. */ +/* WSLUA_ARG_Protofield_bytes_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_bytes_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_bytes_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_ubytes Creates a `ProtoField` for an arbitrary number of unsigned bytes. */ +/* WSLUA_ARG_Protofield_ubytes_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_ubytes_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_ubytes_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_guid Creates a `ProtoField` for a Globally Unique IDentifier (GUID). */ +/* WSLUA_ARG_Protofield_guid_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_guid_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_guid_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_oid Creates a `ProtoField` for an ASN.1 Organizational IDentified (OID). */ +/* WSLUA_ARG_Protofield_oid_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_oid_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_oid_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_rel_oid Creates a `ProtoField` for an ASN.1 Relative-OID. */ +/* WSLUA_ARG_Protofield_rel_oid_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_rel_oid_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_rel_oid_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_systemid Creates a `ProtoField` for an OSI System ID. */ +/* WSLUA_ARG_Protofield_systemid_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_systemid_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_systemid_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +/* _WSLUA_CONSTRUCTOR_ ProtoField_eui64 Creates a `ProtoField` for an EUI64. */ +/* WSLUA_ARG_Protofield_eui64_ABBR Abbreviated name of the field (the string used in filters). */ +/* WSLUA_OPTARG_Protofield_eui64_NAME Actual name of the field (the string that appears in the tree). */ +/* WSLUA_OPTARG_Protofield_eui64_DESC Description of the field. */ +/* _WSLUA_RETURNS_ A `ProtoField` object to be added to a table set to the `Proto.fields` attribute. */ + +PROTOFIELD_OTHER(none,FT_NONE) +PROTOFIELD_OTHER(ipv4,FT_IPv4) +PROTOFIELD_OTHER(ipv6,FT_IPv6) +PROTOFIELD_OTHER(ipx,FT_IPXNET) +PROTOFIELD_OTHER(ether,FT_ETHER) +PROTOFIELD_OTHER(float,FT_FLOAT) +PROTOFIELD_OTHER(double,FT_DOUBLE) +PROTOFIELD_OTHER(relative_time,FT_RELATIVE_TIME) +PROTOFIELD_OTHER(string,FT_STRING) +PROTOFIELD_OTHER(stringz,FT_STRINGZ) +PROTOFIELD_OTHER(bytes,FT_BYTES) +PROTOFIELD_OTHER(ubytes,FT_UINT_BYTES) +PROTOFIELD_OTHER(guid,FT_GUID) +PROTOFIELD_OTHER(oid,FT_OID) +PROTOFIELD_OTHER(rel_oid,FT_REL_OID) +PROTOFIELD_OTHER(systemid,FT_SYSTEM_ID) +PROTOFIELD_OTHER(eui64,FT_EUI64) + +WSLUA_METAMETHOD ProtoField__tostring(lua_State* L) { + /* Returns a string with info about a protofield (for debugging purposes). */ + ProtoField f = checkProtoField(L,1); + gchar* s = g_strdup_printf("ProtoField(%i): %s %s %s %s %p %.8x %s", + f->hfid,f->name,f->abbrev, + ftenum_to_string(f->type), + base_to_string(f->base), + f->vs,f->mask,f->blob); + lua_pushstring(L,s); + g_free(s); + return 1; +} + +static int ProtoField__gc(lua_State* L) { + ProtoField f = toProtoField(L,1); + + /* + * A garbage collector for ProtoFields makes little sense. + * Even if This cannot be used anymore because it has gone out of scope, + * we can destroy the ProtoField only if it is not part of a ProtoFieldArray, + * if it actualy belongs to one we need to preserve it as it is pointed by + * a field array that may be registered afterwards causing a crash or memory corruption. + */ + + if (!f) { + luaL_argerror(L,1,"BUG: ProtoField_gc called for something not ProtoField"); + /* g_assert() ?? */ + } else if (f->hfid == -2) { + g_free(f->name); + g_free(f->abbrev); + g_free(f->blob); + g_free(f); + } + + return 0; +} + +WSLUA_METHODS ProtoField_methods[] = { + WSLUA_CLASS_FNREG(ProtoField,new), + WSLUA_CLASS_FNREG(ProtoField,none), + WSLUA_CLASS_FNREG(ProtoField,uint8), + WSLUA_CLASS_FNREG(ProtoField,uint16), + WSLUA_CLASS_FNREG(ProtoField,uint24), + WSLUA_CLASS_FNREG(ProtoField,uint32), + WSLUA_CLASS_FNREG(ProtoField,uint64), + WSLUA_CLASS_FNREG(ProtoField,int8), + WSLUA_CLASS_FNREG(ProtoField,int16), + WSLUA_CLASS_FNREG(ProtoField,int24), + WSLUA_CLASS_FNREG(ProtoField,int32), + WSLUA_CLASS_FNREG(ProtoField,int64), + WSLUA_CLASS_FNREG(ProtoField,framenum), + WSLUA_CLASS_FNREG(ProtoField,ipv4), + WSLUA_CLASS_FNREG(ProtoField,ipv6), + WSLUA_CLASS_FNREG(ProtoField,ipx), + WSLUA_CLASS_FNREG(ProtoField,ether), + WSLUA_CLASS_FNREG(ProtoField,bool), + WSLUA_CLASS_FNREG(ProtoField,float), + WSLUA_CLASS_FNREG(ProtoField,double), + WSLUA_CLASS_FNREG(ProtoField,absolute_time), + WSLUA_CLASS_FNREG(ProtoField,relative_time), + WSLUA_CLASS_FNREG(ProtoField,string), + WSLUA_CLASS_FNREG(ProtoField,stringz), + WSLUA_CLASS_FNREG(ProtoField,bytes), + WSLUA_CLASS_FNREG(ProtoField,ubytes), + WSLUA_CLASS_FNREG(ProtoField,guid), + WSLUA_CLASS_FNREG(ProtoField,oid), + WSLUA_CLASS_FNREG(ProtoField,rel_oid), + WSLUA_CLASS_FNREG(ProtoField,systemid), + WSLUA_CLASS_FNREG(ProtoField,eui64), + { NULL, NULL } +}; + +WSLUA_META ProtoField_meta[] = { + WSLUA_CLASS_MTREG(ProtoField,tostring), + { NULL, NULL } +}; + +int ProtoField_register(lua_State* L) { + WSLUA_REGISTER_CLASS(ProtoField); + 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: + */ diff --git a/epan/wslua/wslua_tvb.c b/epan/wslua/wslua_tvb.c index 5fad6ddbf5..e1d180442c 100644 --- a/epan/wslua/wslua_tvb.c +++ b/epan/wslua/wslua_tvb.c @@ -6,6 +6,7 @@ * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org> * (c) 2008, Balint Reczey <balint.reczey@ericsson.com> * (c) 2009, Stig Bjorlykke <stig@bjorlykke.org> + * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com> * * Wireshark - Network traffic analyzer * By Gerald Combs <gerald@wireshark.org> @@ -28,343 +29,11 @@ #include "config.h" -#include <epan/wmem/wmem.h> - -/* WSLUA_MODULE Tvb Functions for handling packet data */ - #include "wslua.h" -#include "wsutil/base64.h" - -WSLUA_CLASS_DEFINE(ByteArray,FAIL_ON_NULL("ByteArray"),NOP); - -WSLUA_CONSTRUCTOR ByteArray_new(lua_State* L) { - /* Creates a `ByteArray` object. - - Starting in version 1.11.3, if the second argument is a boolean `true`, - then the first argyument is treated as a raw Lua string of bytes to use, - instead of a hexadecimal string. - */ -#define WSLUA_OPTARG_ByteArray_new_HEXBYTES 1 /* A string consisting of hexadecimal bytes like "00 B1 A2" or "1a2b3c4d". */ -#define WSLUA_OPTARG_ByteArray_new_SEPARATOR 2 /* A string separator between hex bytes/words (default=" "), - or if the boolean value `true` is used, then the first argument - is treated as raw binary data */ - GByteArray* ba = g_byte_array_new(); - const gchar* s; - size_t len = 0; - const gchar* sep = " "; - gboolean ishex = TRUE; - - if (lua_gettop(L) >= 1) { - s = luaL_checklstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES,&len); - - if (lua_gettop(L) >= 2) { - if (lua_type(L,2) == LUA_TBOOLEAN && lua_toboolean(L,2)) { - ishex = FALSE; - } else { - sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_new_SEPARATOR," "); - } - } - - if (ishex) { - wslua_hex2bin(L, s, (guint)len, sep); /* this pushes a new string on top of stack */ - s = luaL_checklstring(L, -1, &len); /* get the new binary string */ - g_byte_array_append(ba,s,(guint)len); /* copy it into ByteArray */ - lua_pop(L,1); /* pop the newly created string */ - } else { - g_byte_array_append(ba,s,(guint)len); - } - } - - pushByteArray(L,ba); - - WSLUA_RETURN(1); /* The new ByteArray object. */ -} - -/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */ -static int ByteArray__gc(lua_State* L) { - ByteArray ba = toByteArray(L,1); - - if (!ba) return 0; - - g_byte_array_free(ba,TRUE); - return 0; -} - -WSLUA_METAMETHOD ByteArray__concat(lua_State* L) { - /* Concatenate two `ByteArrays`. */ -#define WSLUA_ARG_ByteArray__cat_FIRST 1 /* First array. */ -#define WSLUA_ARG_ByteArray__cat_SECOND 2 /* Second array. */ - - ByteArray ba1 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_FIRST); - ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__cat_SECOND); - ByteArray ba; - - ba = g_byte_array_new(); - g_byte_array_append(ba,ba1->data,ba1->len); - g_byte_array_append(ba,ba2->data,ba2->len); - - pushByteArray(L,ba); - WSLUA_RETURN(1); /* The new composite `ByteArray`. */ -} - -WSLUA_METAMETHOD ByteArray__eq(lua_State* L) { - /* Compares two ByteArray values. - - @since 1.11.4 - */ -#define WSLUA_ARG_ByteArray__eq_FIRST 1 /* First array. */ -#define WSLUA_ARG_ByteArray__eq_SECOND 2 /* Second array. */ - ByteArray ba1 = checkByteArray(L,WSLUA_ARG_ByteArray__eq_FIRST); - ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray__eq_SECOND); - gboolean result = FALSE; - - if (ba1->len == ba2->len) { - if (memcmp(ba1->data, ba2->data, ba1->len) == 0) - result = TRUE; - } - - lua_pushboolean(L,result); - - return 1; -} - -WSLUA_METHOD ByteArray_prepend(lua_State* L) { - /* Prepend a `ByteArray` to this `ByteArray`. */ -#define WSLUA_ARG_ByteArray_prepend_PREPENDED 2 /* `ByteArray` to be prepended. */ - ByteArray ba = checkByteArray(L,1); - ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_prepend_PREPENDED); - - g_byte_array_prepend(ba,ba2->data,ba2->len); - - return 0; -} - -WSLUA_METHOD ByteArray_append(lua_State* L) { - /* Append a `ByteArray` to this `ByteArray`. */ -#define WSLUA_ARG_ByteArray_append_APPENDED 2 /* `ByteArray` to be appended. */ - ByteArray ba = checkByteArray(L,1); - ByteArray ba2 = checkByteArray(L,WSLUA_ARG_ByteArray_append_APPENDED); - - g_byte_array_append(ba,ba2->data,ba2->len); - - return 0; -} - -WSLUA_METHOD ByteArray_set_size(lua_State* L) { - /* Sets the size of a `ByteArray`, either truncating it or filling it with zeros. */ -#define WSLUA_ARG_ByteArray_set_size_SIZE 2 /* New size of the array. */ - - ByteArray ba = checkByteArray(L,1); - int siz = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_size_SIZE); - guint8* padding; - - if (siz < 0) { - WSLUA_ERROR(ByteArray_set_size,"ByteArray size must be non-negative"); - return 0; - } - - if (ba->len >= (guint)siz) { /* truncate */ - g_byte_array_set_size(ba,siz); - } else { /* fill */ - padding = (guint8 *)g_malloc0(sizeof(guint8)*(siz - ba->len)); - g_byte_array_append(ba,padding,siz - ba->len); - g_free(padding); - } - return 0; -} - -WSLUA_METHOD ByteArray_set_index(lua_State* L) { - /* Sets the value of an index of a `ByteArray`. */ -#define WSLUA_ARG_ByteArray_set_index_INDEX 2 /* The position of the byte to be set. */ -#define WSLUA_ARG_ByteArray_set_index_VALUE 3 /* The char value to set [0-255]. */ - ByteArray ba = checkByteArray(L,1); - int idx = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_INDEX); - int v = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_VALUE); - - if (idx == 0 && ! g_str_equal(luaL_optstring(L,2,""),"0") ) { - luaL_argerror(L,2,"bad index"); - return 0; - } - - if (idx < 0 || (guint)idx >= ba->len) { - luaL_argerror(L,2,"index out of range"); - return 0; - } - - if (v < 0 || v > 255) { - luaL_argerror(L,3,"Byte out of range"); - return 0; - } - - ba->data[idx] = (guint8)v; - - return 0; -} - - -WSLUA_METHOD ByteArray_get_index(lua_State* L) { - /* Get the value of a byte in a `ByteArray`. */ -#define WSLUA_ARG_ByteArray_get_index_INDEX 2 /* The position of the byte to get. */ - ByteArray ba = checkByteArray(L,1); - int idx = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_get_index_INDEX); - - if (idx == 0 && ! g_str_equal(luaL_optstring(L,2,""),"0") ) { - luaL_argerror(L,2,"bad index"); - return 0; - } - - if (idx < 0 || (guint)idx >= ba->len) { - luaL_argerror(L,2,"index out of range"); - return 0; - } - lua_pushnumber(L,ba->data[idx]); - - WSLUA_RETURN(1); /* The value [0-255] of the byte. */ -} - -WSLUA_METHOD ByteArray_len(lua_State* L) { - /* Obtain the length of a `ByteArray`. */ - ByteArray ba = checkByteArray(L,1); - - lua_pushnumber(L,(lua_Number)ba->len); - - WSLUA_RETURN(1); /* The length of the `ByteArray`. */ -} - -WSLUA_METHOD ByteArray_subset(lua_State* L) { - /* Obtain a segment of a `ByteArray`, as a new `ByteArray`. */ -#define WSLUA_ARG_ByteArray_set_index_OFFSET 2 /* The position of the first byte (0=first). */ -#define WSLUA_ARG_ByteArray_set_index_LENGTH 3 /* The length of the segment. */ - ByteArray ba = checkByteArray(L,1); - int offset = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_OFFSET); - int len = (int)luaL_checkinteger(L,WSLUA_ARG_ByteArray_set_index_LENGTH); - ByteArray sub; - - if ((offset + len) > (int)ba->len || offset < 0 || len < 1) { - luaL_error(L,"Out Of Bounds"); - return 0; - } - - sub = g_byte_array_new(); - g_byte_array_append(sub,ba->data + offset,len); - - pushByteArray(L,sub); - - WSLUA_RETURN(1); /* A `ByteArray` containing the requested segment. */ -} - -WSLUA_METHOD ByteArray_base64_decode(lua_State* L) { - /* Obtain a base64 decoded `ByteArray`. - - @since 1.11.3 - */ - ByteArray ba = checkByteArray(L,1); - ByteArray ba2; - gchar *data; - size_t len; - - ba2 = g_byte_array_new(); - data = (gchar*)g_malloc (ba->len + 1); - memcpy(data, ba->data, ba->len); - data[ba->len] = '\0'; - - len = ws_base64_decode_inplace(data); - g_byte_array_append(ba2,data,(int)len); - g_free(data); - - pushByteArray(L,ba2); - WSLUA_RETURN(1); /* The created `ByteArray`. */ -} - -WSLUA_METHOD ByteArray_raw(lua_State* L) { - /* Obtain a Lua string of the binary bytes in a `ByteArray`. - - @since 1.11.3 - */ -#define WSLUA_OPTARG_ByteArray_raw_OFFSET 2 /* The position of the first byte (default=0/first). */ -#define WSLUA_OPTARG_ByteArray_raw_LENGTH 3 /* The length of the segment to get (default=all). */ - ByteArray ba = checkByteArray(L,1); - guint offset = (guint) luaL_optinteger(L,WSLUA_OPTARG_ByteArray_raw_OFFSET,0); - int len; - - if (!ba) return 0; - if (offset > ba->len) { - WSLUA_OPTARG_ERROR(ByteArray_raw,OFFSET,"offset beyond end of byte array"); - return 0; - } - - len = (int) luaL_optinteger(L,WSLUA_OPTARG_ByteArray_raw_LENGTH, ba->len - offset); - if ((len < 0) || ((guint)len > (ba->len - offset))) - len = ba->len - offset; - - lua_pushlstring(L, &(ba->data[offset]), len); - - WSLUA_RETURN(1); /* A Lua string of the binary bytes in the ByteArray. */ -} - -WSLUA_METHOD ByteArray_tohex(lua_State* L) { - /* Obtain a Lua string of the bytes in a `ByteArray` as hex-ascii, with given separator - - @since 1.11.3 - */ -#define WSLUA_OPTARG_ByteArray_tohex_LOWERCASE 2 /* True to use lower-case hex characters (default=false). */ -#define WSLUA_OPTARG_ByteArray_tohex_SEPARATOR 3 /* A string separator to insert between hex bytes (default=nil). */ - ByteArray ba = checkByteArray(L,1); - gboolean lowercase = FALSE; - const gchar* sep = NULL; - - if (!ba) return 0; - - lowercase = wslua_optbool(L,WSLUA_OPTARG_ByteArray_tohex_LOWERCASE,FALSE); - sep = luaL_optstring(L,WSLUA_OPTARG_ByteArray_tohex_SEPARATOR,NULL); - - wslua_bin2hex(L, ba->data, ba->len, lowercase, sep); - - WSLUA_RETURN(1); /* A hex-ascii string representation of the `ByteArray`. */ -} - -WSLUA_METAMETHOD ByteArray__tostring(lua_State* L) { - /* Obtain a Lua string containing the bytes in a `ByteArray` so that it can be used in - display filters (e.g. "01FE456789AB"). */ - ByteArray ba = checkByteArray(L,1); - - if (!ba) return 0; - - wslua_bin2hex(L, ba->data, ba->len, FALSE, NULL); - - WSLUA_RETURN(1); /* A hex-ascii string representation of the `ByteArray`. */ -} - -static int ByteArray_tvb (lua_State *L); - -WSLUA_METHODS ByteArray_methods[] = { - WSLUA_CLASS_FNREG(ByteArray,new), - WSLUA_CLASS_FNREG(ByteArray,len), - WSLUA_CLASS_FNREG(ByteArray,prepend), - WSLUA_CLASS_FNREG(ByteArray,append), - WSLUA_CLASS_FNREG(ByteArray,subset), - WSLUA_CLASS_FNREG(ByteArray,set_size), - WSLUA_CLASS_FNREG(ByteArray,tvb), - WSLUA_CLASS_FNREG(ByteArray,base64_decode), - WSLUA_CLASS_FNREG(ByteArray,get_index), - WSLUA_CLASS_FNREG(ByteArray,set_index), - WSLUA_CLASS_FNREG(ByteArray,tohex), - WSLUA_CLASS_FNREG(ByteArray,raw), - { NULL, NULL } -}; +#include <epan/wmem/wmem.h> -WSLUA_META ByteArray_meta[] = { - WSLUA_CLASS_MTREG(ByteArray,tostring), - WSLUA_CLASS_MTREG(ByteArray,concat), - WSLUA_CLASS_MTREG(ByteArray,eq), - {"__call",ByteArray_subset}, - { NULL, NULL } -}; -int ByteArray_register(lua_State* L) { - WSLUA_REGISTER_CLASS(ByteArray); - return 0; -} +/* WSLUA_MODULE Tvb Functions for handling packet data */ /* @@ -405,9 +74,16 @@ WSLUA_CLASS_DEFINE(Tvb,FAIL_ON_NULL_OR_EXPIRED("Tvb"),NOP); static GPtrArray* outstanding_Tvb = NULL; static GPtrArray* outstanding_TvbRange = NULL; -#define PUSH_TVB(L,t) {g_ptr_array_add(outstanding_Tvb,t);pushTvb(L,t);} +/* this is used to push Tvbs that were created brand new by wslua code */ +int push_wsluaTvb(lua_State* L, Tvb t) { + g_ptr_array_add(outstanding_Tvb,t); + pushTvb(L,t); + return 1; +} + #define PUSH_TVBRANGE(L,t) {g_ptr_array_add(outstanding_TvbRange,t);pushTvbRange(L,t);} + static void free_Tvb(Tvb tvb) { if (!tvb) return; @@ -427,25 +103,7 @@ void clear_outstanding_Tvb(void) { } } -static void free_TvbRange(TvbRange tvbr) { - if (!(tvbr && tvbr->tvb)) return; - - if (!tvbr->tvb->expired) { - tvbr->tvb->expired = TRUE; - } else { - free_Tvb(tvbr->tvb); - g_free(tvbr); - } -} - -void clear_outstanding_TvbRange(void) { - while (outstanding_TvbRange->len) { - TvbRange tvbr = (TvbRange)g_ptr_array_remove_index_fast(outstanding_TvbRange,0); - free_TvbRange(tvbr); - } -} - - +/* this is used to push Tvbs that just point to pre-existing C-code Tvbs */ Tvb* push_Tvb(lua_State* L, tvbuff_t* ws_tvb) { Tvb tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); tvb->ws_tvb = ws_tvb; @@ -456,62 +114,6 @@ Tvb* push_Tvb(lua_State* L, tvbuff_t* ws_tvb) { } - -/* - * ByteArray_tvb(name) - */ -WSLUA_CONSTRUCTOR ByteArray_tvb (lua_State *L) { - /* Creates a new `Tvb` from a `ByteArray` (it gets added to the current frame too). */ -#define WSLUA_ARG_ByteArray_tvb_NAME 2 /* The name to be given to the new data-source. */ - ByteArray ba = checkByteArray(L,1); - const gchar* name = luaL_optstring(L,WSLUA_ARG_ByteArray_tvb_NAME,"Unnamed") ; - guint8* data; - Tvb tvb; - - if (!lua_tvb) { - luaL_error(L,"Tvbs can only be created and used in dissectors"); - return 0; - } - - data = (guint8 *)g_memdup(ba->data, ba->len); - - tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); - tvb->ws_tvb = tvb_new_real_data(data, ba->len,ba->len); - tvb->expired = FALSE; - tvb->need_free = TRUE; - tvb_set_free_cb(tvb->ws_tvb, g_free); - - add_new_data_source(lua_pinfo, tvb->ws_tvb, name); - PUSH_TVB(L,tvb); - WSLUA_RETURN(1); /* The created `Tvb`. */ -} - -WSLUA_CONSTRUCTOR TvbRange_tvb (lua_State *L) { - /* Creates a (sub)`Tvb` from a `TvbRange`. */ -#define WSLUA_ARG_Tvb_new_subset_RANGE 1 /* The `TvbRange` from which to create the new `Tvb`. */ - - TvbRange tvbr = checkTvbRange(L,WSLUA_ARG_Tvb_new_subset_RANGE); - Tvb tvb; - - if (! (tvbr && tvbr->tvb)) return 0; - if (tvbr->tvb->expired) { - luaL_error(L,"expired tvb"); - return 0; - } - - if (tvb_offset_exists(tvbr->tvb->ws_tvb, tvbr->offset + tvbr->len -1 )) { - tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); - tvb->expired = FALSE; - tvb->need_free = FALSE; - tvb->ws_tvb = tvb_new_subset(tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len, tvbr->len); - PUSH_TVB(L, tvb); - return 1; - } else { - luaL_error(L,"Out Of Bounds"); - return 0; - } -} - WSLUA_METAMETHOD Tvb__tostring(lua_State* L) { /* Convert the bytes of a `Tvb` into a string, to be used for debugging purposes, as '...' will be appended if the string is too long. */ @@ -615,46 +217,6 @@ WSLUA_METAMETHOD Tvb__call(lua_State* L) { } #endif -WSLUA_CLASS_DEFINE(TvbRange,FAIL_ON_NULL("TvbRange"),NOP); -/* - A `TvbRange` represents a usable range of a `Tvb` and is used to extract data from the `Tvb` that generated it. - - `TvbRange`s are created by calling a `Tvb` (e.g. 'tvb(offset,length)'). If the `TvbRange` span is outside the - `Tvb`'s range the creation will cause a runtime error. - */ - -gboolean push_TvbRange(lua_State* L, tvbuff_t* ws_tvb, int offset, int len) { - TvbRange tvbr; - - if (!ws_tvb) { - luaL_error(L,"expired tvb"); - return FALSE; - } - - if (len == -1) { - len = tvb_captured_length_remaining(ws_tvb,offset); - if (len < 0) { - luaL_error(L,"out of bounds"); - return FALSE; - } - } else if ( (guint)(len + offset) > tvb_captured_length(ws_tvb)) { - luaL_error(L,"Range is out of bounds"); - return FALSE; - } - - tvbr = (TvbRange)g_malloc(sizeof(struct _wslua_tvbrange)); - tvbr->tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); - tvbr->tvb->ws_tvb = ws_tvb; - tvbr->tvb->expired = FALSE; - tvbr->tvb->need_free = FALSE; - tvbr->offset = offset; - tvbr->len = len; - - PUSH_TVBRANGE(L,tvbr); - - return TRUE; -} - WSLUA_METHOD Tvb_range(lua_State* L) { /* Creates a `TvbRange` from this `Tvb`. */ @@ -762,10 +324,100 @@ WSLUA_META Tvb_meta[] = { int Tvb_register(lua_State* L) { WSLUA_REGISTER_CLASS(Tvb); + outstanding_Tvb = g_ptr_array_new(); return 0; } + + +WSLUA_CLASS_DEFINE(TvbRange,FAIL_ON_NULL("TvbRange"),NOP); +/* + A `TvbRange` represents a usable range of a `Tvb` and is used to extract data from the `Tvb` that generated it. + + `TvbRange`s are created by calling a `Tvb` (e.g. 'tvb(offset,length)'). If the `TvbRange` span is outside the + `Tvb`'s range the creation will cause a runtime error. + */ + + +static void free_TvbRange(TvbRange tvbr) { + if (!(tvbr && tvbr->tvb)) return; + + if (!tvbr->tvb->expired) { + tvbr->tvb->expired = TRUE; + } else { + free_Tvb(tvbr->tvb); + g_free(tvbr); + } +} + +void clear_outstanding_TvbRange(void) { + while (outstanding_TvbRange->len) { + TvbRange tvbr = (TvbRange)g_ptr_array_remove_index_fast(outstanding_TvbRange,0); + free_TvbRange(tvbr); + } +} + + +gboolean push_TvbRange(lua_State* L, tvbuff_t* ws_tvb, int offset, int len) { + TvbRange tvbr; + + if (!ws_tvb) { + luaL_error(L,"expired tvb"); + return FALSE; + } + + if (len == -1) { + len = tvb_captured_length_remaining(ws_tvb,offset); + if (len < 0) { + luaL_error(L,"out of bounds"); + return FALSE; + } + } else if ( (guint)(len + offset) > tvb_captured_length(ws_tvb)) { + luaL_error(L,"Range is out of bounds"); + return FALSE; + } + + tvbr = (TvbRange)g_malloc(sizeof(struct _wslua_tvbrange)); + tvbr->tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); + tvbr->tvb->ws_tvb = ws_tvb; + tvbr->tvb->expired = FALSE; + tvbr->tvb->need_free = FALSE; + tvbr->offset = offset; + tvbr->len = len; + + PUSH_TVBRANGE(L,tvbr); + + return TRUE; +} + + +WSLUA_CONSTRUCTOR TvbRange_tvb (lua_State *L) { + /* Creates a (sub)`Tvb` from a `TvbRange`. */ +#define WSLUA_ARG_Tvb_new_subset_RANGE 1 /* The `TvbRange` from which to create the new `Tvb`. */ + + TvbRange tvbr = checkTvbRange(L,WSLUA_ARG_Tvb_new_subset_RANGE); + Tvb tvb; + + if (! (tvbr && tvbr->tvb)) return 0; + if (tvbr->tvb->expired) { + luaL_error(L,"expired tvb"); + return 0; + } + + if (tvb_offset_exists(tvbr->tvb->ws_tvb, tvbr->offset + tvbr->len -1 )) { + tvb = (Tvb)g_malloc(sizeof(struct _wslua_tvb)); + tvb->expired = FALSE; + tvb->need_free = FALSE; + tvb->ws_tvb = tvb_new_subset(tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len, tvbr->len); + return push_wsluaTvb(L, tvb); + } else { + luaL_error(L,"Out Of Bounds"); + return 0; + } +} + + /* * get a Blefuscuoan unsigned integer from a tvb */ @@ -1619,7 +1271,7 @@ WSLUA_METHOD TvbRange_raw(lua_State* L) { } if ((guint)offset > tvb_captured_length(tvbr->tvb->ws_tvb)) { - WSLUA_OPTARG_ERROR(Tvb_raw,OFFSET,"offset beyond end of Tvb"); + WSLUA_OPTARG_ERROR(TvbRange_raw,OFFSET,"offset beyond end of Tvb"); return 0; } @@ -1734,7 +1386,6 @@ WSLUA_META TvbRange_meta[] = { }; int TvbRange_register(lua_State* L) { - outstanding_Tvb = g_ptr_array_new(); outstanding_TvbRange = g_ptr_array_new(); WSLUA_REGISTER_CLASS(TvbRange); return 0; |