summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHadriel Kaplan <hadrielk@yahoo.com>2015-07-07 11:30:44 -0400
committerHadriel Kaplan <hadrielk@yahoo.com>2015-07-12 02:08:24 +0000
commit0caf0616ba53282cf4ef5587e13989a7aacc9588 (patch)
tree298c5cb80751accd9076a6da6c2cd89ac31e9d87
parentec1e099dc0b1a1307df1c7f002905e7d38a5f2c7 (diff)
downloadwireshark-0caf0616ba53282cf4ef5587e13989a7aacc9588.tar.gz
Lua: split up wslua files into class-based files
The size of some of the wslua source files has grown large, and it's hard to quickly find things. So split them up based on class name, as much as seems reasonable. Also have the make-wsluarm.pl Perl script handle this. Change-Id: Ib495ec5c2a4df90495c0a05504856288a0b09213 Reviewed-on: https://code.wireshark.org/review/9579 Petri-Dish: Hadriel Kaplan <hadrielk@yahoo.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Hadriel Kaplan <hadrielk@yahoo.com>
-rw-r--r--doc/README.wslua10
-rw-r--r--docbook/CMakeLists.txt14
-rw-r--r--docbook/Makefile.common14
-rwxr-xr-xdocbook/make-wsluarm.pl57
-rw-r--r--epan/wslua/CMakeLists.txt34
-rw-r--r--epan/wslua/Makefile.am55
-rw-r--r--epan/wslua/Makefile.nmake68
-rw-r--r--epan/wslua/wslua.h1
-rw-r--r--epan/wslua/wslua_address.c275
-rw-r--r--epan/wslua/wslua_byte_array.c410
-rw-r--r--epan/wslua/wslua_capture_info.c513
-rw-r--r--epan/wslua/wslua_column.c393
-rw-r--r--epan/wslua/wslua_dissector.c692
-rw-r--r--epan/wslua/wslua_file.c1966
-rw-r--r--epan/wslua/wslua_file_common.c205
-rw-r--r--epan/wslua/wslua_file_common.h86
-rw-r--r--epan/wslua/wslua_file_handler.c997
-rw-r--r--epan/wslua/wslua_frame_info.c415
-rw-r--r--epan/wslua/wslua_nstime.c210
-rw-r--r--epan/wslua/wslua_pinfo.c730
-rw-r--r--epan/wslua/wslua_pinfo_common.h35
-rw-r--r--epan/wslua/wslua_pref.c463
-rw-r--r--epan/wslua/wslua_proto.c2146
-rw-r--r--epan/wslua/wslua_proto_expert.c145
-rw-r--r--epan/wslua/wslua_proto_field.c997
-rw-r--r--epan/wslua/wslua_tvb.c555
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;