aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis Ontanon <luis.ontanon@gmail.com>2006-09-25 01:09:00 +0000
committerLuis Ontanon <luis.ontanon@gmail.com>2006-09-25 01:09:00 +0000
commit6462d05044d74e475253518912c0635222bd7fc2 (patch)
tree32834c107cb9baab32f865999d3d69d877452e71
parent299469d48d57337e6381f2d5363ece52c9a36d37 (diff)
Move the Lua interface into epan... (not a plugin anymore).
- Rename Tap into Listener - add a mechanism to pass protocols' tap data to the Listener svn path=/trunk/; revision=19319
-rw-r--r--Makefile.am14
-rw-r--r--configure.in2
-rw-r--r--epan/Makefile.am19
-rw-r--r--epan/epan.c8
-rw-r--r--epan/wslua/Makefile.am121
-rw-r--r--epan/wslua/Makefile.nmake69
-rw-r--r--epan/wslua/init_wslua.c323
-rwxr-xr-xepan/wslua/make-doc.pl385
-rwxr-xr-xepan/wslua/make-init-lua.pl121
-rwxr-xr-xepan/wslua/make-reg.pl62
-rw-r--r--epan/wslua/make-taps.pl206
-rw-r--r--epan/wslua/taps81
-rw-r--r--epan/wslua/template-init.lua61
-rw-r--r--epan/wslua/wslua.h338
-rw-r--r--epan/wslua/wslua_dumper.c389
-rw-r--r--epan/wslua/wslua_field.c445
-rw-r--r--epan/wslua/wslua_gui.c508
-rw-r--r--epan/wslua/wslua_listener.c332
-rw-r--r--epan/wslua/wslua_pinfo.c888
-rw-r--r--epan/wslua/wslua_proto.c1350
-rw-r--r--epan/wslua/wslua_tree.c290
-rw-r--r--epan/wslua/wslua_tvb.c738
-rw-r--r--epan/wslua/wslua_util.c129
-rw-r--r--plugins/Makefile.am8
24 files changed, 6860 insertions, 27 deletions
diff --git a/Makefile.am b/Makefile.am
index 3f789a9332..106333c569 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -187,12 +187,6 @@ include Makefile.common
if HAVE_PLUGINS
-if HAVE_LIBLUA
-lua_lib = plugins/lua/lua.la
-else # HAVE_LIBLUA
-lua_lib =
-endif # HAVE_LIBLUA
-
plugin_libs = \
plugins/acn/acn.la \
plugins/agentx/agentx.la \
@@ -205,7 +199,6 @@ plugin_libs = \
plugins/giop/coseventcomm.la \
plugins/gryphon/gryphon.la \
plugins/irda/irda.la \
- $(lua_lib) \
plugins/lwres/lwres.la \
plugins/mate/mate.la \
plugins/megaco/megaco.la \
@@ -226,12 +219,6 @@ plugin_ldadd = $(plugin_libs)
else # ENABLE_STATIC
-if HAVE_LIBLUA
-lua_ldadd = "-dlopen" plugins/lua/lua.la
-else # HAVE_LIBLUA
-lua_ldadd =
-endif # HAVE_LIBLUA
-
plugin_ldadd = \
"-dlopen" self \
"-dlopen" plugins/acn/acn.la \
@@ -246,7 +233,6 @@ plugin_ldadd = \
"-dlopen" plugins/gryphon/gryphon.la \
"-dlopen" plugins/h223/h223.la \
"-dlopen" plugins/irda/irda.la \
- $(lua_ldadd) \
"-dlopen" plugins/lwres/lwres.la \
"-dlopen" plugins/mate/mate.la \
"-dlopen" plugins/megaco/megaco.la \
diff --git a/configure.in b/configure.in
index 293f2b3bcd..ba5825eacd 100644
--- a/configure.in
+++ b/configure.in
@@ -1347,6 +1347,7 @@ AC_OUTPUT(
epan/dfilter/Makefile
epan/dissectors/Makefile
epan/ftypes/Makefile
+ epan/wslua/Makefile
codecs/Makefile
gtk/Makefile
gtk/doxygen.cfg
@@ -1371,7 +1372,6 @@ AC_OUTPUT(
plugins/gryphon/Makefile
plugins/h223/Makefile
plugins/irda/Makefile
- plugins/lua/Makefile
plugins/lwres/Makefile
plugins/mate/Makefile
plugins/megaco/Makefile
diff --git a/epan/Makefile.am b/epan/Makefile.am
index 50c7edec44..735845b5a9 100644
--- a/epan/Makefile.am
+++ b/epan/Makefile.am
@@ -22,7 +22,17 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-SUBDIRS = ftypes dfilter dissectors
+
+if HAVE_LIBLUA
+wslua_lib = wslua/libwslua.la
+wslua_dir = wslua
+else # HAVE_LIBLUA
+wslua_lib =
+wslua_dir =
+endif # HAVE_LIBLUA
+
+
+SUBDIRS = ftypes dfilter dissectors $(wslua_dir)
# EPAN will eventually be a shared library. While I move source code around,
# however, it is an archive library.
@@ -34,7 +44,7 @@ libwireshark_la_LDFLAGS = -version-info 0:1:0
include Makefile.common
-INCLUDES = -I$(srcdir)/.. -I$(srcdir)/$(LEMON) \
+INCLUDES = -I$(srcdir)/.. -I$(srcdir)/$(LEMON) @LUA_INCLUDES@ \
$(LIBGNUTLS_CFLAGS) $(LIBGCRYPT_CFLAGS)
libwireshark_la_SOURCES = \
@@ -82,11 +92,12 @@ MAINTAINERCLEANFILES = \
Makefile.in \
sminmpec.c
+
#
# Add the object files for missing routines, if any.
#
-libwireshark_la_LIBADD = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la @ADNS_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @KRB5_LIBS@ @SNMP_LIBS@ @SSL_LIBS@ -lm
-libwireshark_la_DEPENDENCIES = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la
+libwireshark_la_LIBADD = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la $(wslua_lib) @ADNS_LIBS@ @LIBGNUTLS_LIBS@ @LIBICONV@ @KRB5_LIBS@ @SNMP_LIBS@ @SSL_LIBS@ -lm
+libwireshark_la_DEPENDENCIES = @G_ASCII_STRTOULL_LO@ @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ dfilter/libdfilter.la ftypes/libftypes.la dissectors/libdissectors.la $(wslua_lib)
tvbtest: tvbtest.o tvbuff.o except.o strutil.o
$(LINK) $^ $(GLIB_LIBS) -lz
diff --git a/epan/epan.c b/epan/epan.c
index 05e274e85b..fe68db2378 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -38,6 +38,10 @@
#include "emem.h"
#include "expert.h"
+#ifdef HAVE_LUA_5_1
+#include <epan/wslua/wslua.h>
+#endif
+
static void (*report_failure_func)(const char *, va_list);
static void (*report_open_failure_func)(const char *, int, gboolean);
static void (*report_read_failure_func)(const char *, int);
@@ -93,6 +97,10 @@ epan_init(const char *plugin_dir, void (*register_all_protocols)(void),
final_registration_all_protocols();
host_name_lookup_init();
expert_init();
+#ifdef HAVE_LUA_5_1
+ wslua_init(NULL);
+#endif
+
}
void
diff --git a/epan/wslua/Makefile.am b/epan/wslua/Makefile.am
new file mode 100644
index 0000000000..ecc39ff5f3
--- /dev/null
+++ b/epan/wslua/Makefile.am
@@ -0,0 +1,121 @@
+# Makefile.am
+#
+# $Id$
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+INCLUDES = -I$(top_srcdir) @LUA_INCLUDES@
+
+noinst_LTLIBRARIES = libwslua.la
+
+wslua_modules = \
+ wslua_tvb.c \
+ wslua_proto.c \
+ wslua_tree.c \
+ wslua_pinfo.c \
+ wslua_listener.c \
+ wslua_gui.c \
+ wslua_util.c \
+ wslua_field.c \
+ wslua_dumper.c
+
+libwslua_la_SOURCES = \
+ $(wslua_modules) \
+ init_wslua.c \
+ wslua.h
+
+libwslua_la_LIBADD = @LUA_LIBS@
+
+BUILT_SOURCES = \
+ wslua_register.h
+
+pkgdata_DATA = init.lua
+
+CLEANFILES = \
+ *~
+
+DISTCLEANFILES = \
+ dummy
+
+MAINTAINERCLEANFILES = \
+ Makefile.in \
+ doc/*.pod \
+ wslua_register.h \
+ taps.c-inc \
+ taps.txt \
+ init.lua
+
+EXTRA_DIST = \
+ wslua_register.h \
+ taps \
+ make-reg.pl \
+ make-doc.pl \
+ template-init.lua \
+ make-init-lua.pl \
+ make-taps.pl \
+ Makefile.nmake
+
+taps_used = \
+ ../dissectors/packet-http.h \
+ ../dissectors/packet-ip.h \
+ ../dissectors/packet-udp.h \
+ ../dissectors/packet-h225.h
+
+taps: $(taps_used)
+ touch taps
+
+taps.c-inc: make-taps.pl taps
+ $(PERL) make-taps.pl taps taps.c-inc taps.txt
+
+taps.txt: taps.c-inc
+
+wslua.h: wslua_register.h
+
+# do not do not unnecessarilly modify the old file in order avoid recompiling every module every time
+wslua_register.h: make-reg.pl $(lua_modules) taps.c-inc
+ $(PERL) make-reg.pl \
+ wslua_tvb.c \
+ wslua_proto.c \
+ wslua_tree.c \
+ wslua_pinfo.c \
+ wslua_listener.c \
+ wslua_gui.c \
+ wslua_util.c \
+ wslua_field.c \
+ wslua_dumper.c > wslua_register.h.new ;\
+ if diff wslua_register.h.new wslua_register.h >/dev/null; then rm wslua_register.h.new; else mv wslua_register.h.new wslua_register.h; fi
+
+doc: make-doc.pl $(lua_modules)
+ $(PERL) make-doc.pl \
+ wslua_tvb.c \
+ wslua_proto.c \
+ wslua_tree.c \
+ wslua_pinfo.c \
+ wslua_listener.c \
+ wslua_gui.c \
+ wslua_util.c \
+ wslua_field.c \
+ wslua_dumper.c
+
+dummy:
+ touch dummy
+
+init.lua: template-init.lua make-init-lua.pl ../ftypes/ftypes.h ../../wiretap/wtap.h ../proto.h
+ $(PERL) make-init-lua.pl template-init.lua > init.lua
diff --git a/epan/wslua/Makefile.nmake b/epan/wslua/Makefile.nmake
new file mode 100644
index 0000000000..497ab2eebe
--- /dev/null
+++ b/epan/wslua/Makefile.nmake
@@ -0,0 +1,69 @@
+#
+# $Id$
+#
+
+include ..\..\config.nmake
+
+############### no need to modify below this line #########
+
+CFLAGS=/DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) $(LUA_CFLAGS)\
+ /I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS)
+
+LDFLAGS = /NOLOGO /INCREMENTAL:no /MACHINE:I386 $(LOCAL_LDFLAGS)
+
+!IFDEF LUA_DIR
+!IFDEF ENABLE_LIBWIRESHARK
+LINK_PLUGIN_WITH=..\..\epan\libwireshark.lib
+CFLAGS=/DHAVE_WIN32_LIBWIRESHARK_LIB /D_NEED_VAR_IMPORT_ $(CFLAGS)
+
+MODULES= \
+ elua_dumper.c \
+ elua_field.c \
+ elua_gui.c \
+ elua_pinfo.c \
+ elua_proto.c \
+ elua_tap.c \
+ elua_tree.c \
+ elua_tvb.c \
+ elua_util.c
+
+OBJECTS= \
+ elua.obj \
+ elua_dumper.obj \
+ elua_field.obj \
+ elua_gui.obj \
+ elua_pinfo.obj \
+ elua_plugin.obj \
+ elua_proto.obj \
+ elua_tap.obj \
+ elua_tree.obj \
+ elua_tvb.obj \
+ elua_util.obj
+
+lua.dll lua.exp lua.lib : $(OBJECTS) $(LINK_PLUGIN_WITH)
+ link -dll /out:lua.dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \
+ $(GLIB_LIBS) $(LUA_LIBS) ..\..\wiretap\wiretap-$(WTAP_VERSION).lib
+
+
+elua_register.h: elua_makereg.pl $(MODULES)
+ $(PERL) elua_makereg.pl $(MODULES) > elua_register.h
+
+elua.c: elua_register.h
+
+doc: $(MODULES)
+ $(PERL) elua_makedoc.pl $(MODULES)
+
+#elua.c: $(LUA_LIBS)
+
+init.lua: template-init.lua make-init-lua.pl ../../epan/ftypes/ftypes.h ../../wiretap/wtap.h ../../epan/proto.h
+ $(PERL) make-init-lua.pl template-init.lua > init.lua
+
+!ENDIF
+!ENDIF
+
+clean:
+ rm -f $(OBJECTS) lua.dll lua.exp lua.lib *.pdb init.lua
+
+distclean: clean
+
+maintainer-clean: distclean
diff --git a/epan/wslua/init_wslua.c b/epan/wslua/init_wslua.c
new file mode 100644
index 0000000000..9e7132190d
--- /dev/null
+++ b/epan/wslua/init_wslua.c
@@ -0,0 +1,323 @@
+/*
+ * packet-lua.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id$
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+#include <epan/nstime.h>
+#include <math.h>
+#include <epan/expert.h>
+#include <epan/ex-opt.h>
+#include <epan/privileges.h>
+
+static lua_State* L = NULL;
+
+packet_info* lua_pinfo;
+struct _wslua_treeitem* lua_tree;
+tvbuff_t* lua_tvb;
+int lua_malformed;
+int lua_dissectors_table_ref;
+
+dissector_handle_t lua_data_handle;
+
+
+static int wslua_not_register_menu(lua_State* LS) {
+ luaL_error(LS,"too late to register a menu");
+ return 0;
+}
+
+void dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) {
+ lua_pinfo = pinfo;
+ lua_tvb = tvb;
+
+ lua_tree = ep_alloc(sizeof(struct _wslua_treeitem));
+ lua_tree->tree = tree;
+ lua_tree->item = proto_tree_add_text(tree,tvb,0,0,"lua fake item");
+ PROTO_ITEM_SET_HIDDEN(lua_tree->item);
+
+ /*
+ * almost equivalent to Lua:
+ * dissectors[current_proto](tvb,pinfo,tree)
+ */
+
+ lua_settop(L,0);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
+
+ lua_pushstring(L, pinfo->current_proto);
+ lua_gettable(L, -2);
+
+ lua_remove(L,1);
+
+
+ if (lua_isfunction(L,1)) {
+
+ push_Tvb(L,tvb);
+ push_Pinfo(L,pinfo);
+ push_TreeItem(L,lua_tree);
+
+ if ( lua_pcall(L,3,0,0) ) {
+ const gchar* error = lua_tostring(L,-1);
+
+ proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Lua Error: %s",error);
+ expert_add_info_format(pinfo, pi, PI_DEBUG, PI_ERROR ,"Lua Error");
+ }
+ } else {
+ proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Lua Error: did not find the %s dissector"
+ " in the dissectors table",pinfo->current_proto);
+
+ expert_add_info_format(pinfo, pi, PI_DEBUG, PI_ERROR ,"Lua Error");
+ }
+
+ clear_outstanding_tvbs();
+ clear_outstanding_pinfos();
+ clear_outstanding_trees();
+
+
+ lua_pinfo = NULL;
+ lua_tree = NULL;
+ lua_tvb = NULL;
+
+}
+
+static void iter_table_and_call(lua_State* LS, int env, const gchar* table_name, lua_CFunction error_handler) {
+ lua_settop(LS,0);
+
+ lua_pushcfunction(LS,error_handler);
+ lua_pushstring(LS, table_name);
+ lua_gettable(LS, env);
+
+ if (!lua_istable(LS, 2)) {
+ report_failure("Lua: either `%s' does not exist or it is not a table!\n",table_name);
+ lua_close(LS);
+ L = NULL;
+ return;
+ }
+
+ lua_pushnil(LS);
+
+ while (lua_next(LS, 2)) {
+ const gchar* name = lua_tostring(L,-2);
+
+ if (lua_isfunction(LS,-1)) {
+
+ if ( lua_pcall(LS,0,0,1) ) {
+ lua_pop(LS,1);
+ }
+
+ } else {
+ report_failure("Lua: Something not a function got its way into the %s.%s",table_name,name);
+ lua_close(LS);
+ L = NULL;
+ return;
+ }
+ }
+
+ lua_settop(LS,0);
+}
+
+
+static int init_error_handler(lua_State* LS) {
+ const gchar* error = lua_tostring(LS,1);
+ report_failure("Lua: Error During execution of Initialization:\n %s",error);
+ return 0;
+}
+
+
+static void wslua_init_routine(void) {
+ static gboolean initialized = FALSE;
+
+ if ( ! initialized ) {
+ lua_prime_all_fields(NULL);
+ initialized = TRUE;
+ }
+
+ if (L) {
+ iter_table_and_call(L, LUA_GLOBALSINDEX, WSLUA_INIT_ROUTINES,init_error_handler);
+ }
+
+}
+
+
+static const char *getF(lua_State *L _U_, void *ud, size_t *size)
+{
+ FILE *f=(FILE *)ud;
+ static char buff[512];
+ if (feof(f)) return NULL;
+ *size=fread(buff,1,sizeof(buff),f);
+ return (*size>0) ? buff : NULL;
+}
+
+static int lua_main_error_handler(lua_State* LS) {
+ const gchar* error = lua_tostring(LS,1);
+ report_failure("Lua: Error during loading:\n %s",error);
+ return 0;
+}
+
+void lua_load_script(const gchar* filename) {
+ FILE* file;
+
+ if (! ( file = fopen(filename,"r")) ) {
+ report_open_failure(filename,errno,FALSE);
+ return;
+ }
+
+ lua_settop(L,0);
+
+ lua_pushcfunction(L,lua_main_error_handler);
+
+ switch (lua_load(L,getF,file,filename)) {
+ case 0:
+ lua_pcall(L,0,0,1);
+ fclose(file);
+ return;
+ case LUA_ERRSYNTAX: {
+ report_failure("Lua: syntax error during precompilation of `%s':\n%s",filename,lua_tostring(L,-1));
+ fclose(file);
+ return;
+ }
+ case LUA_ERRMEM:
+ report_failure("Lua: memory allocation error during execution of %s",filename);
+ fclose(file);
+ return;
+ }
+
+}
+
+static void basic_logger(const gchar *log_domain _U_,
+ GLogLevelFlags log_level _U_,
+ const gchar *message,
+ gpointer user_data _U_) {
+ fputs(message,stderr);
+}
+
+static int wslua_panic(lua_State* LS) {
+ g_error("LUA PANIC: %s",lua_tostring(LS,-1));
+ return 0;
+}
+
+int wslua_init(lua_State* LS) {
+ const gchar* filename;
+ const funnel_ops_t* ops = funnel_get_funnel_ops();
+ gboolean run_anyway = FALSE;
+
+ /* set up the logger */
+ g_log_set_handler(LOG_DOMAIN_LUA, G_LOG_LEVEL_CRITICAL|
+ G_LOG_LEVEL_WARNING|
+ G_LOG_LEVEL_MESSAGE|
+ G_LOG_LEVEL_INFO|
+ G_LOG_LEVEL_DEBUG,
+ ops ? ops->logger : basic_logger, NULL);
+
+ if (!L) {
+ if (LS)
+ L = LS;
+ else
+ L = luaL_newstate();
+ }
+
+ WSLUA_INIT(L);
+
+ lua_atpanic(L,wslua_panic);
+
+ /* the init_routines table (accessible by the user) */
+ lua_pushstring(L, WSLUA_INIT_ROUTINES);
+ lua_newtable (L);
+ lua_settable(L, LUA_GLOBALSINDEX);
+
+ /* the dissectors table goes in the registry (not accessible) */
+ lua_newtable (L);
+ lua_dissectors_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* set running_superuser variable to it's propper value */
+ WSLUA_REG_GLOBAL_BOOL(L,"running_superuser",started_with_special_privs());
+
+ /* load system's init.lua */
+ filename = get_datafile_path("init.lua");
+
+ if (( file_exists(filename))) {
+ lua_load_script(filename);
+ }
+
+ /* check if lua is to be disabled */
+ lua_pushstring(L,"lua_disabled");
+ lua_gettable(L, LUA_GLOBALSINDEX);
+
+ if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) {
+ /* disable lua */
+ lua_close(L);
+ L = NULL;
+ return;
+ }
+
+ /* check whether we should run other scripts even if running superuser */
+ lua_pushstring(L,"run_user_scripts_when_superuser");
+ lua_gettable(L, LUA_GLOBALSINDEX);
+
+ if (lua_isboolean(L,-1) && lua_toboolean(L,-1)) {
+ run_anyway = TRUE;
+ }
+
+
+ /* if we are indeed superuser run user scripts only if told to do so */
+ if ( (!started_with_special_privs()) || run_anyway ) {
+ filename = get_persconffile_path("init.lua", FALSE);
+
+ if (( file_exists(filename))) {
+ lua_load_script(filename);
+ }
+
+ while((filename = ex_opt_get_next("lua_script"))) {
+ lua_load_script(filename);
+ }
+ }
+
+ /* at this point we're set up so register the init routine */
+ register_init_routine(wslua_init_routine);
+
+ /*
+ * after this point it is too late to register a menu
+ * disable the function to avoid weirdness
+ */
+ lua_pushstring(L, "register_menu");
+ lua_pushcfunction(L, wslua_not_register_menu);
+ lua_settable(L, LUA_GLOBALSINDEX);
+
+ /* set up some essential globals */
+ lua_pinfo = NULL;
+ lua_tree = NULL;
+ lua_tvb = NULL;
+
+ lua_data_handle = find_dissector("data");
+ lua_malformed = proto_get_id_by_filter_name("malformed");
+
+ Proto_commit(L);
+
+ return 0;
+}
+
+lua_State* wslua_state() { return L; }
+
diff --git a/epan/wslua/make-doc.pl b/epan/wslua/make-doc.pl
new file mode 100755
index 0000000000..47d2b1cf1f
--- /dev/null
+++ b/epan/wslua/make-doc.pl
@@ -0,0 +1,385 @@
+#!/usr/bin/perl
+#
+# make-doc.pl
+# WSLUA's Reference Manual Generator
+#
+# (c) 2006, Luis E. Garcia Onatnon <luis.ontanon@gmail.com>
+#
+# $Id$
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# (-: I don't even think writing this in Lua :-)
+
+use strict;
+#use V2P;
+
+sub deb {
+# warn $_[0];
+}
+
+sub gorolla {
+# a gorilla stays to a chimp like ... stays to chomp
+# but this one returns the shrugged string.
+ my $s = shift;
+ $s =~ s/^([\n]|\s)*//ms;
+ $s =~ s/([\n]|\s)*$//ms;
+ $s;
+}
+
+my $class;
+my %classes;
+my $function;
+my @functions;
+
+my %template = %{{
+ class_header => "= %s =\n",
+ class_desc => "%s\n",
+ class_constructors_header => "== %s constructors ==\n",
+ class_methods_header => "== %s methods ==\n",
+ class_attributes_header => "== %s Attributes ==\n",
+ class_attr_header => "=== %s ===\n",
+ class_attr_descr => "%s\n",
+ function_header => "=== %s ===\n",
+ function_descr => "%s\n",
+ function_arg_header => "==== %s ====\n",
+ function_arg_descr => "%s\n",
+ function_argerrors_header => "'''Errors:'''\n",
+ function_argerror => " * %s\n",
+ function_returns_header => "==== returns ====\n",
+ function_returns => " * %s\n",
+ function_errors_header => "==== errors ====\n",
+ function_errors => " * %s\n",
+ non_method_functions_header => "= Non method functions =\n",
+}};
+
+
+my %metamethods = %{{
+ __tostring => "tostring(__)",
+ __index => "__[]",
+ __newindex => "__[] = ",
+ __add => "__ + __",
+ __sub => "__ - __",
+ __mul => "__ * __",
+ __div => "__ / __",
+ __mod => "__ % __",
+ __pow => "__ ^ __",
+ __unm => "-___",
+ __concat => "__ .. __",
+ __len => "#__",
+ __call => "()",
+ __eq => "__ == __",
+ __lt => "__ < __",
+ __le => "__ <= __",
+}};
+
+# It's said that only perl can parse perl... my editor isn't perl...
+# if unencoded this causes my editor's autoindent to bail out so I encoded in octal
+# XXX: support \" within ""
+my $QUOTED_RE = "\042\050\133^\042\135*\051\042";
+
+my $TRAILING_COMMENT_RE = '((\s*|[\n\r]*)/\*(.*?)\*/)?';
+
+my @control =
+(
+# This will be scanned in order trying to match the re if it matches
+# the body will be executed immediatelly after.
+
+ [ 'WSLUA_CLASS_DEFINE\050\s*([A-Z][a-zA-Z]+)\s*,.*?\051' . $TRAILING_COMMENT_RE,
+sub {
+ deb ">c=$1=$2=$3=$4=$5=$6=$7=\n";
+ $class = {
+ name => $1,
+ descr=> gorolla($4),
+ constructors => [],
+ methods => [],
+ metamethods => [],
+ attributes => []
+ };
+ $classes{$1} = $class;
+}],
+
+[ 'WSLUA_FUNCTION\s+wslua_([a-z_]+)[^\173]*\173' . $TRAILING_COMMENT_RE,
+sub {
+ deb ">f=$1=$2=$3=$4=$5=$6=$7=\n";
+ $function = {
+ returns => [],
+ arglist => [],
+ args => {},
+ name => $1,
+ descr => gorolla($4),
+ type => 'standalone'
+ };
+ push @functions, $function;
+} ] ,
+
+[ 'WSLUA_CONSTRUCTOR\s+([A-Za-z]+)_([a-z_]+).*?\173' . $TRAILING_COMMENT_RE,
+sub {
+ deb ">cc=$1=$2=$3=$4=$5=$6=$7=\n";
+ $function = {
+ returns => [],
+ arglist => [],
+ args => {},
+ name => "$1.$2",
+ descr => gorolla($5),
+ type => 'constructor'
+ };
+ push @{${$class}{constructors}}, $function;
+} ] ,
+
+[ 'WSLUA_METHOD\s+([A-Za-z]+)_([a-z_]+)[^\173]*\173' . $TRAILING_COMMENT_RE,
+ sub {
+ deb ">cm=$1=$2=$3=$4=$5=$6=$7=\n";
+ $function = {
+ returns => [],
+ arglist => [],
+ args => {},
+ name => "$1:$2",
+ descr => gorolla($5),
+ type => 'method'
+ };
+ push @{${$class}{methods}}, $function;
+ } ] ,
+
+[ 'WSLUA_METAMETHOD\s+([A-Za-z]+)(__[a-z]+)[^\173]*\173' . $TRAILING_COMMENT_RE,
+ sub {
+ deb ">cm=$1=$2=$3=$4=$5=$6=$7=\n";
+ my $name = $metamethods{$2};
+ my ($c,$d) = ($1,$5);
+ $name =~ s/__/$c/g;
+ $function = {
+ returns => [],
+ arglist => [],
+ args => {},
+ name => $name,
+ descr => gorolla($d),
+ type => 'metamethod'
+ };
+ push @{${$class}{metamethods}}, $function;
+ } ] ,
+
+[ '#define WSLUA_(OPT)?ARG_([a-z_]+)_([A-Z0-9]+)\s+\d+' . $TRAILING_COMMENT_RE,
+sub {
+ deb ">a=$1=$2=$3=$4=$5=$6=$7=\n";
+ push @{${$function}{arglist}} , $3;
+ ${${$function}{args}}{$3} = {descr=>$6}
+} ],
+
+[ '#define WSLUA_(OPT)?ARG_([A-Za-z]+)_([a-z_]+)_([A-Z0-9]+)\s+\d+' . $TRAILING_COMMENT_RE,
+sub {
+ deb ">ca=$1=$2=$3=$4=$5=$6=$7=\n";
+ push @{${$function}{arglist}} , $4;
+ ${${$function}{args}}{$4} = {descr=>$7}
+} ],
+
+[ '/\052\s+WSLUA_ATTRIBUTE\s+([A-Za-z]+)_([a-z_]+)\s+([A-Z]*)\s*(.*?)\052/',
+ sub {
+ deb ">at=$1=$2=$3=$4=$5=$6=$7=\n";
+ push @{${$class}{attributes}}, { name => $2, descr => gorolla($4), mode=>$3 };
+ } ],
+
+[ '/\052\s+WSLUA_MOREARGS\s+([A-Za-z_]+)\s+(.*?)\052/',
+ sub {
+ deb ">ma=$1=$2=$3=$4=$5=$6=$7=\n";
+ push @{${$function}{arglist}} , "...";
+ ${${$function}{args}}{"..."} = {descr=>gorolla($2)}
+ } ],
+
+[ 'WSLUA_(FINAL_)?RETURN\050\s*.*?\s*\051\s*;' . $TRAILING_COMMENT_RE,
+sub {
+ deb ">fr=$1=$2=$3=$4=$5=$6=$7=\n";
+ push @{${$function}{returns}} , gorolla($4) if $4 ne '';
+} ],
+
+[ 'WSLUA_ERROR\s*\050\s*(([A-Z][A-Za-z]+)_)?([a-z_]+),' . $QUOTED_RE ,
+ sub {
+ deb ">e=$1=$2=$3=$4=$5=$6=$7=\n";
+ my $errors;
+ unless (exists ${$function}{errors}) {
+ $errors = ${$function}{errors} = [];
+ } else {
+ $errors = ${$function}{errors};
+ }
+
+ push @{$errors}, gorolla($4);
+ } ],
+
+[ 'WSLUA_(OPT)?ARG_ERROR\s*\050\s*(([A-Z][A-Za-z]+)_)?([a-z_]+)\s*,\s*([A-Z0-9]+)\s*,\s*' . $QUOTED_RE,
+ sub {
+ deb ">ae=$1=$2=$3=$4=$5=$6=$7=\n";
+ my $errors;
+ unless (exists ${${${$function}{args}}{$5}}{errors}) {
+ $errors = ${${${$function}{args}}{$5}}{errors} = [];
+ } else {
+ $errors = ${${${$function}{args}}{$5}}{errors};
+ }
+
+ push @{$errors}, gorolla($6);
+ } ] ,
+);
+
+my $anymatch = '(^ThIsWiLlNeVeRmAtCh$';
+for (@control) {
+ $anymatch .= "|${$_}[0]";
+}
+$anymatch .= ')';
+
+# for each file given in the command line args
+my $file;
+while ( $file = shift) {
+
+ next unless -f $file;
+
+ my $docfile = $file;
+ $docfile =~ s/\.c$/.pod/;
+
+ open C, "< $file";
+ open D, "> doc/$docfile";
+
+ my $b = '';
+ $b .= $_ while (<C>);
+
+ while ($b =~ /$anymatch/ms ) {
+ my $match = $1;
+# print "\n-----\n$match\n-----\n";
+ for (@control) {
+ my ($re,$f) = @{$_};
+ if ( $match =~ /$re/ms) {
+ &{$f}();
+ $b =~ s/.*?$re//ms;
+ last;
+ }
+ }
+ }
+
+ for my $cname (sort keys %classes) {
+ my $cl = $classes{$cname};
+ printf D $template{class_header}, $cname;
+ printf D $template{class_desc} , ${$cl}{descr} if ${$cl}{descr};
+
+ if ( $#{${$cl}{constructors}} >= 0) {
+ printf D $template{class_constructors_header}, $cname;
+
+ for my $c (@{${$cl}{constructors}}) {
+ function_descr($c);
+ }
+
+ printf D $template{class_constructors_footer}, $cname;
+ }
+
+ if ( $#{${$cl}{methods}} >= 0) {
+ printf D $template{class_methods_header}, $cname;
+
+ for my $m (@{${$cl}{methods}}) {
+ function_descr($m);
+ }
+
+ printf D $template{class_methods_footer}, $cname;
+ }
+
+ if ( $#{${$cl}{metamethods}} >= 0) {
+ printf D $template{class_metamethods_header}, $cname;
+
+ for my $m (@{${$cl}{metamethods}}) {
+ function_descr($m,${$m}{name});
+ }
+
+ printf D $template{class_metamethods_footer}, $cname;
+ }
+
+ if ( $#{${$cl}{attributes}} >= 0) {
+ printf D $template{class_attributes_header}, $cname;
+
+ for my $a (@{${$cl}{attributes}}) {
+ printf D $template{class_attr_header}, ${$a}{name};
+ printf D $template{class_attr_descr}, ${$a}{descr} if ${$a}{descr};
+ printf D $template{class_attr_footer}, ${$a}{name};
+
+ }
+
+ printf D $template{class_attributes_footer}, $cname;
+ }
+ }
+
+ if ($#functions >= 0) {
+ print D $template{non_method_functions_header};
+
+ for my $f (@functions) {
+ function_descr($f);
+ }
+ }
+
+ %classes = ();
+ $class = undef;
+ $function = undef;
+ @functions = ();
+ close C;
+ close D;
+}
+
+sub function_descr {
+ my $f = $_[0];
+ my $label = $_[1];
+
+ if (defined $label ) {
+ printf D $template{function_header}, $label;
+ } else {
+ my $arglist = '';
+
+ for (@{ ${$f}{arglist} }) {
+ my $a = $_;
+ $a =~ tr/A-Z/a-z/;
+ $arglist .= "$a, ";
+ }
+
+ $arglist =~ s/, $//;
+
+ printf D $template{function_header}, "${$f}{name}($arglist)";
+ }
+
+ printf D $template{function_descr}, ${$f}{descr} if ${$f}{descr};
+
+ for my $argname (@{${$f}{arglist}}) {
+ my $arg = ${${$f}{args}}{$argname};
+ $argname =~ tr/A-Z/a-z/;
+
+ printf D $template{function_arg_header}, $argname;
+ printf D $template{function_arg_descr}, ${$arg}{descr} if ${$arg}{descr};
+
+ if ( $#{${$arg}{errors}} >= 0) {
+ printf D $template{function_argerrors_header}, $argname;
+ printf D $template{function_argerror}, $_ for @{${$arg}{errors}};
+ printf D $template{function_argerrors_footer}, $argname;
+ }
+
+ }
+
+ if ( $#{${$f}{returns}} >= 0) {
+ printf D $template{function_returns_header}, ${$f}{name};
+ printf D $template{function_returns}, $_ for @{${$f}{returns}};
+ printf D $template{function_returns_footer}, ${$f}{name};
+ }
+
+ if ( $#{${$f}{errors}} >= 0) {
+ printf D $template{function_errors_header}, ${$f}{name};
+ printf D $template{function_errors}, $_ for @{${$f}{errors}};
+ printf D $template{function_errors_footer}, ${$f}{name};
+ }
+
+}
diff --git a/epan/wslua/make-init-lua.pl b/epan/wslua/make-init-lua.pl
new file mode 100755
index 0000000000..23fbe3601b
--- /dev/null
+++ b/epan/wslua/make-init-lua.pl
@@ -0,0 +1,121 @@
+#!/usr/bin/perl
+#
+# make-init-lua.pl
+#
+# create the init.lua file based on a template (stdin)
+#
+# (c) 2006, Luis E. Garcia Onatnon <luis.ontanon@gmail.com>
+#
+# $Id$
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+use strict;
+
+my $WSROOT = "../..";
+
+my $wtap_encaps_table = '';
+my $ft_types_table = '';
+my $bases_table = '';
+my $expert_pi = '';
+
+my %replacements = %{{
+ WTAP_ENCAPS => \$wtap_encaps_table,
+ FT_TYPES => \$ft_types_table,
+ BASES => \$bases_table,
+ EXPERT => \$expert_pi,
+}};
+
+
+#
+# load template
+#
+my $template = '';
+$template .= $_ while(<>);
+
+
+#
+# make wiretap encapusulation table
+#
+
+$wtap_encaps_table = "-- Wiretap encapsulations\nwtap = {\n";
+
+open WTAP_H, "< $WSROOT/wiretap/wtap.h";
+
+while(<WTAP_H>) {
+ if ( /^#define WTAP_ENCAP_([A-Z0-9_]+)\s+(\d+)/ ) {
+ $wtap_encaps_table .= "\t[\"$1\"] = $2,\n";
+ }
+}
+
+$wtap_encaps_table =~ s/,\n$/\n}\n/msi;
+
+#
+# enum fttype
+#
+
+$ft_types_table = " -- Field Types\nftypes = {\n";
+
+my $ftype_num = 0;
+
+open FTYPES_H, "< $WSROOT/epan/ftypes/ftypes.h";
+while(<FTYPES_H>) {
+ if ( /^\s+FT_([A-Z0-9a-z_]+)\s*,/ ) {
+ $ft_types_table .= "\t[\"$1\"] = $ftype_num,\n";
+ $ftype_num++;
+ }
+}
+close FTYPES_H;
+
+$ft_types_table =~ s/,\n$/\n}\n/msi;
+
+
+
+#
+# enum base
+#
+
+$bases_table = "-- Display Bases\n base = {\n";
+$expert_pi = "-- Expert flags and facilities\n";
+
+my $base_num = 0;
+
+open PROTO_H, "< $WSROOT/epan/proto.h";
+while(<PROTO_H>) {
+ if (/^\s+BASE_([A-Z_]+),/ ) {
+ $bases_table .= "\t[\"$1\"] = $base_num,\n";
+ $base_num++;
+ }
+
+ if ( /^.define\s+(PI_[A-Z_]+)\s+((0x)?[0-9A-Fa-f]+)/ ) {
+ my ($name, $value) = ($1, hex($2));
+ $expert_pi .= "$name = $value\n";
+ }
+}
+close PROTO_H;
+
+$bases_table .= "}\n\n";
+$expert_pi .= "\n\n";
+
+for my $key (keys %replacements) {
+ $template =~ s/%$key%/${$replacements{$key}}/msig;
+}
+
+
+print $template;
diff --git a/epan/wslua/make-reg.pl b/epan/wslua/make-reg.pl
new file mode 100755
index 0000000000..78d989954c
--- /dev/null
+++ b/epan/wslua/make-reg.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+#
+# make-reg.pl
+# Registration Macros Generator
+#
+# (c) 2006, Luis E. Garcia Onatnon <luis.ontanon@gmail.com>
+#
+# $Id$
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+use strict;
+
+my @classes = ();
+my @functions = ();
+
+while (<>) {
+ push @classes, $1 if /WSLUA_CLASS_DEFINE\050\s*([A-Za-z]+)/;
+ push @functions, $1 if /WSLUA_FUNCTION\s+wslua_([a-z_]+)/;
+}
+
+print "/* This file is automatically genrated by elua_makereg.pl do not edit */\n\n";
+
+print "#define WSLUA_DECLARE_CLASSES() \\\n";
+for (@classes) {
+ print "\tWSLUA_CLASS_DECLARE($_);\\\n"
+}
+print "\n\n";
+
+print "#define WSLUA_REGISTER_CLASSES() { \\\n";
+for (@classes) {
+ print "\t${_}_register(L);\\\n"
+}
+print "}\n\n";
+
+print "#define WSLUA_DECLARE_FUNCTIONS() \\\n";
+for (@functions) {
+ print "\tWSLUA_FUNCTION wslua_$_(lua_State* L);\\\n"
+}
+print "\n\n";
+
+print "#define WSLUA_REGISTER_FUNCTIONS() {\\\n";
+for (@functions) {
+ print "\t WSLUA_REGISTER_FUNCTION($_); \\\n"
+}
+print "}\n\n";
diff --git a/epan/wslua/make-taps.pl b/epan/wslua/make-taps.pl
new file mode 100644
index 0000000000..f287907ffb
--- /dev/null
+++ b/epan/wslua/make-taps.pl
@@ -0,0 +1,206 @@
+#!/usr/bin/perl
+#
+# make-taps.pl
+# Extract structs from C headers to generate a function that
+# pushes a lua table into the stack containing the elements of
+# the struct.
+#
+# (c) 2006 Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+#
+# $Id$
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+use strict;
+
+my %types = %{{
+ 'gchar[]' => 'lua_pushstring(L,(char*)v->%s);',
+ 'gchar*' => 'lua_pushstring(L,(char*)v->%s);',
+ 'guint' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'guint8' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'guint16' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'guint32' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'gint' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'gint8' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'gint16' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'gint32' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'gboolean' => 'lua_pushboolean(L,(int)v->%s);',
+ 'address' => '{ Address a = g_malloc(sizeof(address)); COPY_ADDRESS(a, &(v->%s)); pushAddress(L,a); }',
+ 'address*' => '{ Address a = g_malloc(sizeof(address)); COPY_ADDRESS(a, v->%s); pushAddress(L,a); }',
+ 'int' => 'lua_pushnumber(L,(lua_Number)v->%s);',
+ 'nstime_t' => '{lua_Number t = v->%s.secs; t += v->%s.nsecs * 1e-9; lua_pushnumber(L,t); }',
+ 'nstime_t*' => '{lua_Number t = v->%s->secs; t += v->%s->nsecs * 1e-9; lua_pushnumber(L,t); }',
+}};
+
+my %comments = %{{
+ 'gchar[]' => 'string',
+ 'gchar*' => 'string',
+ 'guint' => 'number',
+ 'guint8' => 'number',
+ 'guint16' => 'number',
+ 'guint32' => 'number',
+ 'gint' => 'number',
+ 'gint8' => 'number',
+ 'gint16' => 'number',
+ 'gint32' => 'number',
+ 'gboolean' => 'boolean',
+ 'address' => 'Address',
+ 'address*' => 'Address',
+ 'int' => 'number',
+ 'nstime_t' => 'number (seconds, since 1-1-1970 if absolute)',
+ 'nstime_t*' => 'number (seconds, since 1-1-1970 if absolute)',
+}};
+
+
+my %functs = ();
+
+my %enums = ();
+
+sub dotap {
+ my ($tname,$fname,$sname,@enums) = @_;
+ my $buf = '';
+
+ open FILE, "< $fname";
+ while(<FILE>) {
+ $buf .= $_;
+ }
+ close FILE;
+
+ $buf =~ s@/\*.*?\*/@@;
+
+ for my $ename (@enums) {
+ $enums{$ename} = [];
+ my $a = $enums{$ename};
+
+ my $enumre = "typedef\\s+enum[^{]*{([^}]*)}[\\s\\n]*${ename}[\\s\\n]*;";
+ if ($buf =~ s/$enumre//ms ) {
+ $types{$ename} = "/*$ename*/ lua_pushnumber(L,(lua_Number)v->%s);";
+ my $ebody = $1;
+ $ebody =~ s/\s+//msg;
+ $comments{$ename} = "$ename: { $ebody }";
+ $comments{$ename} =~ s/,/|/g;
+ for (split /,/, $ebody) {
+ push @{$a}, $_;
+ }
+ }
+ }
+
+ my $re = "typedef\\s+struct.*?{([^}]*)}[\\s\\n]*($sname)[\\s\\n]*;";
+ my $body;
+
+ while ($buf =~ s/$re//ms) {
+ $body = $1;
+ }
+
+ die "could not find typedef $sname in $fname" if not defined $body and $sname ne "void";
+
+ my %elems = ();
+
+ while($body =~ s/\s*(.*?)([\w\d_]+)\s*\[\s*\d+\s*\]\s*;//) {
+ my ($k,$v) = ($2,$1 . "[]");
+ $v =~ s/\s+//g;
+ $elems{$k} = $v;
+ }
+
+ while($body =~ s/\s*(.*?)([\w\d_]+)\s*;//) {
+ my ($k,$v) = ($2,$1);
+ $v =~ s/\s+//g;
+ $elems{$k} = $v;
+ }
+
+ my $code = "void wslua_${tname}_to_table(lua_State* L, const void* p) { $sname* v = (void*)p; lua_newtable(L);\n";
+ my $doc = "Tap: $tname\n";
+
+ for my $n (sort keys %elems) {
+ my $fmt = $types{$elems{$n}};
+
+ if ($fmt) {
+ $code .= "\tlua_pushstring(L,\"$n\"); ";
+ $code .= sprintf($fmt,$n,$n) . " lua_settable(L,-3);\n";
+ $doc .= "\t$n: $comments{$elems{$n}}\n";
+ }
+
+ }
+
+ $code .= "}\n\n";
+ $doc .= "\n";
+
+ $functs{$tname} = "wslua_${tname}_to_table";
+
+ return ($code,$doc);
+}
+
+
+open TAPSFILE, "< $ARGV[0]";
+open CFILE, "> $ARGV[1]";
+open DOCFILE, "> $ARGV[2]";
+
+print CFILE <<"HEADER";
+/* This file is autogenerated from ./taps by ./make-taps.pl */
+/* DO NOT EDIT! */
+
+HEADER
+
+print DOCFILE "\n";
+
+while (<TAPSFILE>) {
+ s@#.*@@;
+ next if /^\s*$/;
+ my ($tname,$fname,$sname,@enums) = split /\s+/;
+ my ($c,$doc) = dotap($tname,$fname,$sname,@enums);
+ print CFILE "#include \"$fname\"\n";
+ print CFILE $c;
+ print DOCFILE $doc;
+}
+
+print CFILE <<"TBLHDR";
+tappable_t tappables[] = {
+TBLHDR
+
+ for my $tname (sort keys %functs) {
+ print CFILE <<"TBLELEM";
+ {"$tname", $functs{$tname} },
+TBLELEM
+ }
+
+print CFILE <<"TBLFTR";
+ {"frame",NULL},
+ {NULL,NULL}
+};
+
+void set_enums(lua_State* L) {
+TBLFTR
+
+
+for my $ename (sort keys %enums) {
+ print CFILE "\n\t/*\n\t * $ename\n\t */\n\tlua_pushstring(L,\"$ename\"); lua_newtable(L);\n";
+ for my $a (@{$enums{$ename}}) {
+ print CFILE <<"ENUMELEM";
+ lua_pushstring(L,"$a"); lua_pushnumber(L,(lua_Number)$a); lua_settable(L,LUA_GLOBALSINDEX);
+ lua_pushnumber(L,(lua_Number)$a); lua_pushstring(L,"$a"); lua_settable(L,-3);
+ENUMELEM
+ }
+ print CFILE "\tlua_settable(L,LUA_GLOBALSINDEX);\n";
+}
+
+print CFILE "};\n";
+exit 0;
+
+
+
diff --git a/epan/wslua/taps b/epan/wslua/taps
new file mode 100644
index 0000000000..a35d61ccf1
--- /dev/null
+++ b/epan/wslua/taps
@@ -0,0 +1,81 @@
+# taps
+# instructions for make-taps.pl to generate the taps.c file
+#
+# (c) 2006 Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+#
+# $Id$
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Each line is a tap type (the data structure passed by dissectors).
+# Elements are separated by whitespace.
+# tapname source_file_for_struct typedef_name_of_struct an_enum_name another_enum_name ...
+#
+# Note: Make sure you update the taps_used variable in Makefile.am
+# every time you add a new file to the list
+
+#frame ../dissectors/packet_frame.h void
+
+ip ../dissectors/packet-ip.h e_ip
+udp ../dissectors/packet-udp.h e_udphdr
+http ../dissectors/packet-http.h http_info_value_t
+h225 ../dissectors/packet-h225.h h225_packet_info h225_msg_type h225_cs_type
+
+#actrace
+#afp
+#ansi_a
+#ansi_map
+#bootp
+#dcerpc
+#dccp
+#dtls
+#epl
+#eth
+#fc
+#fddi
+#gsm_a
+#gsm_map
+#h245
+#h245dg
+#wlan
+#ipx
+#isup
+#jxta
+#ldap
+#mtp3
+#ncp_srt
+#ncp_hdr
+#ntlmssp
+#q931
+#rpc
+#rsvp
+#rtpevent
+#rtp
+#scsi
+#sctp
+#sdp
+#sip
+#smb
+#smb2
+#ssl
+#t38
+#tcp
+#teredo
+#tr
+#wsp
diff --git a/epan/wslua/template-init.lua b/epan/wslua/template-init.lua
new file mode 100644
index 0000000000..d1b139f4af
--- /dev/null
+++ b/epan/wslua/template-init.lua
@@ -0,0 +1,61 @@
+-- init.lua
+--
+-- initilaize ethereal's lua
+--
+-- This file is going to be executed before any other lua script.
+-- It can be used to load libraries, disable functions and more.
+--
+-- $Id$
+--
+-- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+-- If lua is to be disabled even if it was installed uncomment the following
+-- line.
+-- disable_lua = true; do return end;
+
+
+-- If set and we are running with special privileges this setting
+-- tells whether scripts other than this one are to be run.
+run_user_scripts_when_superuser = false
+
+-- disable potentialy harmful lua functions when running superuser
+if running_superuser then
+ dofile = function() error("dofile has been disabled") end
+ loadfile = function() error("loadfile has been disabled") end
+ loadlib = function() error("loadlib has been disabled") end
+ require = function() error("require has been disabled") end
+ os = {}
+ io = {}
+ file = {}
+end
+
+-- to avoid output to stdout which can caause problems lua's print ()
+-- has been suppresed so that it yields an error.
+-- have print() call info() instead.
+print = info
+
+-- %WTAP_ENCAPS%
+
+-- %FT_TYPES%
+
+-- %BASES%
+
+-- %EXPERT%
+
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
new file mode 100644
index 0000000000..6b87bb490d
--- /dev/null
+++ b/epan/wslua/wslua.h
@@ -0,0 +1,338 @@
+/*
+ * wslua.h
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua.h 18231 2006-05-28 16:32:49Z etxrab $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_LUA_H
+#define _PACKET_LUA_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <errno.h>
+#include <string.h>
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+#include <wiretap/wtap.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/prefs.h>
+#include <epan/proto.h>
+#include <epan/epan_dissect.h>
+#include <epan/tap.h>
+#include <epan/filesystem.h>
+#include <epan/report_err.h>
+#include <epan/emem.h>
+#include <epan/funnel.h>
+#include <epan/tvbparse.h>
+#include <epan/epan.h>
+
+#include "wslua_register.h"
+
+#define WSLUA_INIT_ROUTINES "init_routines"
+#define LOG_DOMAIN_LUA "wslua"
+
+struct _wslua_tvbrange {
+ tvbuff_t* tvb;
+ int offset;
+ int len;
+};
+
+typedef struct _wslua_field_t {
+ int hfid;
+ int ett;
+ char* name;
+ char* abbr;
+ char* blob;
+ enum ftenum type;
+ base_display_e base;
+ value_string* vs;
+ guint32 mask;
+} wslua_field_t;
+
+typedef enum {PREF_NONE,PREF_BOOL,PREF_UINT,PREF_STRING} pref_type_t;
+
+typedef struct _wslua_pref_t {
+ gchar* name;
+ gchar* label;
+ gchar* desc;
+ pref_type_t type;
+ union {
+ gboolean b;
+ guint u;
+ const gchar* s;
+ void* p;
+ } value;
+
+ struct _wslua_pref_t* next;
+ struct _wslua_proto_t* proto;
+} wslua_pref_t;
+
+typedef struct _wslua_proto_t {
+ gchar* name;
+ gchar* desc;
+ int hfid;
+ int ett;
+ wslua_pref_t prefs;
+ int fields;
+ module_t *prefs_module;
+ dissector_handle_t handle;
+ gboolean is_postdissector;
+} wslua_proto_t;
+
+struct _wslua_distbl_t {
+ dissector_table_t table;
+ gchar* name;
+};
+
+struct _wslua_col_info {
+ column_info* cinfo;
+ gint col;
+};
+
+struct _wslua_treeitem {
+ proto_item* item;
+ proto_tree* tree;
+};
+
+#if 0
+struct _wslua_main {
+ capture_options capture_opts;
+};
+#endif
+
+typedef void (*tap_extractor_t)(lua_State*,const void*);
+
+typedef struct { const char* name; tap_extractor_t extractor; } tappable_t;
+
+typedef struct {const gchar* str; enum ftenum id; } wslua_ft_types_t;
+
+typedef wslua_pref_t* Pref;
+typedef wslua_pref_t* Prefs;
+typedef struct _wslua_field_t* ProtoField;
+typedef struct _wslua_proto_t* Proto;
+typedef struct _wslua_distbl_t* DissectorTable;
+typedef dissector_handle_t Dissector;
+typedef GByteArray* ByteArray;
+typedef tvbuff_t* Tvb;
+typedef struct _wslua_tvbrange* TvbRange;
+typedef struct _wslua_col_info* Column;
+typedef column_info* Columns;
+typedef packet_info* Pinfo;
+typedef struct _wslua_treeitem* TreeItem;
+typedef address* Address;
+typedef header_field_info** Field;
+typedef field_info* FieldInfo;
+typedef struct _wslua_tap* Listener;
+typedef funnel_text_window_t* TextWindow;
+typedef wtap_dumper* Dumper;
+typedef struct lua_pseudo_header* PseudoHeader;
+typedef tvbparse_t* Parser;
+typedef tvbparse_wanted_t* Rule;
+typedef tvbparse_elem_t* Node;
+typedef tvbparse_action_t* Shortcut;
+typedef struct _wslua_main* WireShark;
+
+/*
+ * toXxx(L,idx) gets a Xxx from an index (Lua Error if fails)
+ * checkXxx(L,idx) gets a Xxx from an index after calling check_code (No Lua Error if it fails)
+ * pushXxx(L,xxx) pushes an Xxx into the stack
+ * isXxx(L,idx) tests whether we have an Xxx at idx
+ *
+ * LUA_CLASS_DEFINE must be used without trailing ';'
+ */
+#define WSLUA_CLASS_DEFINE(C,check_code,push_code) \
+C to##C(lua_State* L, int index) { \
+ C* v = (C*)lua_touserdata (L, index); \
+ if (!v) luaL_typerror(L,index,#C); \
+ return *v; \
+} \
+C check##C(lua_State* L, int index) { \
+ C* p; \
+ luaL_checktype(L,index,LUA_TUSERDATA); \
+ p = (C*)luaL_checkudata(L, index, #C); \
+ check_code; \
+ return p ? *p : NULL; \
+} \
+C* push##C(lua_State* L, C v) { \
+ C* p = lua_newuserdata(L,sizeof(C)); *p = v; \
+ luaL_getmetatable(L, #C); lua_setmetatable(L, -2); \
+ push_code; \
+ return p; \
+}\
+gboolean is##C(lua_State* L,int i) { \
+ void *p; \
+ if(!lua_isuserdata(L,i)) return FALSE; \
+ p = lua_touserdata(L, i); \
+ lua_getfield(L, LUA_REGISTRYINDEX, #C); \
+ if (p == NULL || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -2)) p=NULL; \
+ lua_pop(L, 2); \
+ return p ? TRUE : FALSE; \
+} \
+C shift##C(lua_State* L,int i) { \
+ C* p; \
+ if(!lua_isuserdata(L,i)) return NULL; \
+ p = lua_touserdata(L, i); \
+ lua_getfield(L, LUA_REGISTRYINDEX, #C); \
+ if (p == NULL || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -2)) p=NULL; \
+ lua_pop(L, 2); \
+ if (p) { lua_remove(L,i); return *p; }\
+ else return NULL;\
+} \
+int dummy##C
+
+#ifdef HAVE_LUA_5_1
+
+#define WSLUA_REGISTER_CLASS(C) { \
+ luaL_register (L, #C, C ## _methods); \
+ luaL_newmetatable (L, #C); \
+ luaL_register (L, NULL, C ## _meta); \
+ lua_pushliteral(L, "__index"); \
+ lua_pushvalue(L, -3); \
+ lua_rawset(L, -3); \
+ lua_pushliteral(L, "__metatable"); \
+ lua_pushvalue(L, -3); \
+ lua_rawset(L, -3); \
+ lua_pop(L, 1); \
+}
+
+#define WSLUA_REGISTER_META(C) luaL_newmetatable (L, #C); luaL_register (L, NULL, C ## _meta);
+
+#define WSLUA_INIT(L) \
+ L = luaL_newstate(); \
+ luaL_openlibs(L); \
+ WSLUA_REGISTER_CLASSES(); \
+ WSLUA_REGISTER_FUNCTIONS();
+
+
+#else /* Lua 5.0 */
+
+#define WSLUA_REGISTER_CLASS(C) { \
+ luaL_openlib(L, #C, C ## _methods, 0); \
+ luaL_newmetatable(L, #C); \
+ luaL_openlib(L, 0, C ## _meta, 0); \
+ lua_pushliteral(L, "__index"); \
+ lua_pushvalue(L, -3); \
+ lua_rawset(L, -3); \
+ lua_pushliteral(L, "__metatable"); \
+ lua_pushvalue(L, -3); \
+ lua_rawset(L, -3); \
+ lua_pop(L, 1); \
+}
+
+#define WSLUA_REGISTER_META(C) luaL_newmetatable (L, #C); luaL_openlib (L, NULL, C ## _meta, 0);
+
+#define WSLUA_INIT(L) \
+ if ( ! L) L = lua_open(); \
+ luaopen_base(L); \
+ luaopen_table(L); \
+ luaopen_io(L); \
+ luaopen_string(L); \
+ WSLUA_REGISTER_CLASSES(); \
+ WSLUA_REGISTER_FUNCTIONS();
+
+#endif
+
+#define WSLUA_FUNCTION extern int
+#define WSLUA_REGISTER_FUNCTION(name) { lua_pushstring(L, #name); lua_pushcfunction(L, wslua_## name); lua_settable(L, LUA_GLOBALSINDEX); }
+#define WSLUA_REGISTER extern int
+
+#define WSLUA_METHOD static int
+#define WSLUA_CONSTRUCTOR static int
+#define WSLUA_ATTR_SET static int
+#define WSLUA_ATTR_GET static int
+#define WSLUA_METAMETHOD static int
+
+#define WSLUA_METHODS static const luaL_reg
+#define WSLUA_META static const luaL_reg
+#define WSLUA_CLASS_FNREG(class,name) { #name, class##_##name }
+
+#define WSLUA_ERROR(name,error) { luaL_error(L, #name ": " error); return 0; }
+#define WSLUA_ARG_ERROR(name,attr,error) { luaL_argerror(L,WSLUA_ARG_ ## name ## _ ## attr, #name ": " error); return 0; }
+#define WSLUA_OPTARG_ERROR(name,attr,error) { luaL_argerror(L,WSLUA_OPTARG_##name##_ ##attr, #name ": " error); return 0; }
+
+#define WSLUA_REG_GLOBAL_BOOL(L,n,v) { lua_pushstring(L,n); lua_pushboolean(L,v); lua_settable(L, LUA_GLOBALSINDEX); }
+#define WSLUA_REG_GLOBAL_STRING(n,v) { lua_pushstring(L,n); lua_pushstring(L,v); lua_settable(L, LUA_GLOBALSINDEX); }
+#define WSLUA_REG_GLOBAL_NUMBER(n,v) { lua_pushstring(L,n); lua_pushnumber(L,v); lua_settable(L, LUA_GLOBALSINDEX); }
+
+#define WSLUA_RETURN(i) return (i);
+
+#define WSLUA_API extern
+
+#define NOP
+#define FAIL_ON_NULL(s) if (! *p) luaL_argerror(L,index,s)
+
+
+
+#define WSLUA_CLASS_DECLARE(C) \
+extern C to##C(lua_State* L, int index); \
+extern C check##C(lua_State* L, int index); \
+extern C* push##C(lua_State* L, C v); \
+extern int C##_register(lua_State* L); \
+extern gboolean is##C(lua_State* L,int i); \
+extern C shift##C(lua_State* L,int i)
+
+
+extern packet_info* lua_pinfo;
+extern TreeItem lua_tree;
+extern tvbuff_t* lua_tvb;
+extern int lua_malformed;
+extern dissector_handle_t lua_data_handle;
+extern gboolean lua_initialized;
+extern int lua_dissectors_table_ref;
+
+WSLUA_DECLARE_CLASSES()
+WSLUA_DECLARE_FUNCTIONS()
+
+extern lua_State* wslua_state(void);
+
+extern const gchar* lua_shiftstring(lua_State* L,int idx);
+extern void dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree);
+
+extern void proto_register_lua(void);
+extern GString* lua_register_all_taps(void);
+extern void lua_prime_all_fields(proto_tree* tree);
+
+extern int Proto_commit(lua_State* L);
+
+extern void* push_Tvb(lua_State* L, Tvb tvb);
+extern void clear_outstanding_tvbs(void);
+
+extern void* push_Pinfo(lua_State* L, Pinfo p);
+extern void clear_outstanding_pinfos(void);
+
+extern void* push_TreeItem(lua_State* L, TreeItem ti);
+extern void clear_outstanding_trees(void);
+
+extern void wslua_print_stack(char* s, lua_State* L);
+
+extern int wslua_init(lua_State* L);
+
+extern int luaopen_libwireshark(lua_State* L);
+#endif
diff --git a/epan/wslua/wslua_dumper.c b/epan/wslua/wslua_dumper.c
new file mode 100644
index 0000000000..539e60d982
--- /dev/null
+++ b/epan/wslua/wslua_dumper.c
@@ -0,0 +1,389 @@
+/*
+ * lua_dumper.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_dumper.c 18231 2006-05-28 16:32:49Z etxrab $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+#include <math.h>
+
+WSLUA_CLASS_DEFINE(PseudoHeader,NOP,NOP);
+/*
+ A pseudoheader to be used to save captured frames.
+ */
+
+enum lua_pseudoheader_type {
+ PHDR_NONE,
+ PHDR_ETH,
+ PHDR_X25,
+ PHDR_ISDN,
+ PHDR_ATM,
+ PHDR_ASCEND,
+ PHDR_P2P,
+ PHDR_WIFI,
+ PHDR_COSINE,
+ PHDR_IRDA,
+ PHDR_NETTL,
+ PHDR_MTP2,
+ PHDR_K12
+};
+
+struct lua_pseudo_header {
+ enum lua_pseudoheader_type type;
+ union wtap_pseudo_header* wph;
+};
+
+WSLUA_CONSTRUCTOR PseudoHeader_none(lua_State* L) {
+ /*
+ Creates a "no" pseudoheader.
+
+ */
+ PseudoHeader ph = g_malloc(sizeof(struct lua_pseudo_header));
+ ph->type = PHDR_NONE;
+ ph->wph = NULL;
+
+ pushPseudoHeader(L,ph);
+
+ WSLUA_RETURN(1);
+ /* A null pseudoheader */
+}
+
+WSLUA_CONSTRUCTOR PseudoHeader_eth(lua_State* L) {
+ /*
+ Creates an ethernet pseudoheader
+ */
+
+#define WSLUA_OPTARG_PseudoHeader_eth_FCSLEN 1 /* the fcs lenght */
+
+ PseudoHeader ph = g_malloc(sizeof(struct lua_pseudo_header));
+ ph->type = PHDR_ETH;
+ ph->wph = g_malloc(sizeof(union wtap_pseudo_header));
+ ph->wph->eth.fcs_len = luaL_optint(L,1,-1);
+
+ pushPseudoHeader(L,ph);
+
+ WSLUA_RETURN(1); /* The ethernet pseudoheader */
+}
+
+WSLUA_CONSTRUCTOR PseudoHeader_atm(lua_State* L) {
+ /*
+ Creates an ATM pseudoheader
+ */
+#define WSLUA_OPTARG_PseudoHeader_atm_AAL 1 /* AAL number */
+#define WSLUA_OPTARG_PseudoHeader_atm_VPI 2 /* VPI */
+#define WSLUA_OPTARG_PseudoHeader_atm_VCI 3 /* VCI */
+#define WSLUA_OPTARG_PseudoHeader_atm_CHANNEL 4 /* Channel */
+#define WSLUA_OPTARG_PseudoHeader_atm_CELLS 5 /* Number of cells in the PDU */
+#define WSLUA_OPTARG_PseudoHeader_atm_AAL5U2U 6 /* AAL5 User to User indicator */
+#define WSLUA_OPTARG_PseudoHeader_atm_AAL5LEN 7 /* AAL5 Len */
+
+ PseudoHeader ph = g_malloc(sizeof(struct lua_pseudo_header));
+ ph->type = PHDR_ATM;
+ ph->wph = g_malloc(sizeof(union wtap_pseudo_header));
+ ph->wph->atm.aal = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_AAL,5);
+ ph->wph->atm.vpi = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_VPI,1);
+ ph->wph->atm.vci = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_VCI,1);
+ ph->wph->atm.channel = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_CHANNEL,0);
+ ph->wph->atm.cells = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_CELLS,1);
+ ph->wph->atm.aal5t_u2u = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_AAL5U2U,1);
+ ph->wph->atm.aal5t_len = luaL_optint(L,WSLUA_OPTARG_PseudoHeader_atm_AAL5LEN,0);
+
+ pushPseudoHeader(L,ph);
+ WSLUA_RETURN(1);
+ /* The ATM pseudoheader */
+}
+
+WSLUA_CONSTRUCTOR PseudoHeader_mtp2(lua_State* L) {
+ /* Creates an MTP2 PseudoHeader */
+#define WSLUA_OPTARG_PseudoHeader_mtp2_SENT 1 /* True if the packet is sent, False if received. */
+#define WSLUA_OPTARG_PseudoHeader_mtp2_ANNEXA 2 /* True if annex A is used */
+#define WSLUA_OPTARG_PseudoHeader_mtp2_LINKNUM 3 /* Link Number */
+ PseudoHeader ph = g_malloc(sizeof(struct lua_pseudo_header));
+ ph->type = PHDR_MTP2;
+ ph->wph = g_malloc(sizeof(union wtap_pseudo_header));
+ ph->wph->mtp2.sent = luaL_optint(L,1,0);
+ ph->wph->mtp2.annex_a_used = luaL_optint(L,2,0);
+ ph->wph->mtp2.link_number = luaL_optint(L,3,0);
+
+ pushPseudoHeader(L,ph);
+ WSLUA_RETURN(1); /* The MTP2 pseudoheader */
+}
+
+#if 0
+static int PseudoHeader_x25(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_isdn(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_ascend(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_wifi(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_cosine(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_irda(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_nettl(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+static int PseudoHeader_k12(lua_State* L) { luaL_error(L,"not implemented"); return 0; }
+#endif
+
+WSLUA_METHODS PseudoHeader_methods[] = {
+ WSLUA_CLASS_FNREG(PseudoHeader,mtp2),
+ WSLUA_CLASS_FNREG(PseudoHeader,atm),
+ WSLUA_CLASS_FNREG(PseudoHeader,eth),
+ WSLUA_CLASS_FNREG(PseudoHeader,none),
+ {0,0}
+};
+
+WSLUA_META PseudoHeader_meta[] = {
+ {0,0}
+};
+
+int PseudoHeader_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(PseudoHeader)
+ return 0;
+}
+
+
+WSLUA_CLASS_DEFINE(Dumper,FAIL_ON_NULL("Dumper already closed"),NOP);
+
+static GHashTable* dumper_encaps = NULL;
+#define DUMPER_ENCAP(d) GPOINTER_TO_INT(g_hash_table_lookup(dumper_encaps,d))
+
+WSLUA_CONSTRUCTOR Dumper_new(lua_State* L) {
+ /*
+ Creates a file to write packets.
+ Dumper:new_for_current() will probably be a better choice.
+ */
+#define WSLUA_ARG_Dumper_new_FILENAME 1 /* The name of the capture file to be created */
+#define WSLUA_OPTARG_Dumper_new_FILETYPE 2 /* The type of the file to be created */
+#define WSLUA_OPTARG_Dumper_new_ENCAP 3 /* The encapsulation to be used in the file to be created */
+ Dumper d;
+ const char* filename = luaL_checkstring(L,1);
+ int filetype = luaL_optint(L,2,WTAP_FILE_PCAP);
+ int encap = luaL_optint(L,3,WTAP_ENCAP_ETHERNET);
+ int err = 0;
+
+ if (! filename) return 0;
+
+ if (!wtap_dump_can_write_encap(filetype, encap))
+ WSLUA_ERROR(Dumper_new,"not every filetype handles every encap");
+
+ d = wtap_dump_open(filename, filetype, encap,0 , FALSE, &err);
+
+ if (! d ) {
+ /* WSLUA_ERROR("error while opening file for writing"); */
+ luaL_error(L,"error while opening `%s': %s",
+ filename,
+ wtap_strerror(err));
+ return 0;
+ }
+
+ g_hash_table_insert(dumper_encaps,d,GINT_TO_POINTER(encap));
+
+ pushDumper(L,d);
+ WSLUA_RETURN(1);
+ /* The newly created Dumper object */
+}
+
+WSLUA_METHOD Dumper_close(lua_State* L) {
+ /* Closes a dumper */
+ Dumper* dp = (Dumper*)luaL_checkudata(L, 1, "Dumper");
+ int err;
+
+ if (! *dp)
+ WSLUA_ERROR(Dumper_close,"Cannot operate on a closed dumper");
+
+ g_hash_table_remove(dumper_encaps,*dp);
+
+ if (!wtap_dump_close(*dp, &err)) {
+ luaL_error(L,"error closing: %s",
+ wtap_strerror(err));
+ }
+
+ /* this way if we close a dumper any attempt to use it (for everything but GC) will yield an error */
+ dp = NULL;
+
+ return 0;
+}
+
+WSLUA_METHOD Dumper_flush(lua_State* L) {
+ /*
+ Writes all unsaved data of a dumper to the disk.
+ */
+ Dumper d = checkDumper(L,1);
+
+ if (!d) return 0;
+
+ wtap_dump_flush(d);
+
+ return 0;
+}
+
+WSLUA_METHOD Dumper_dump(lua_State* L) {
+ /*
+ Dumps an arbitrary packet.
+ Note: Dumper:dump_current() will fit best in most cases.
+ */
+#define WSLUA_ARG_Dumper_dump_TIMESTAMP 2 /* The absolute timestamp the packet will have */
+#define WSLUA_ARG_Dumper_dump_PSEUDOHEADER 3 /* The Pseudoheader to use. */
+#define WSLUA_ARG_Dumper_dump_BYTEARRAY 4 /* the data to be saved */
+
+ Dumper d = checkDumper(L,1);
+ PseudoHeader ph;
+ ByteArray ba;
+ struct wtap_pkthdr pkthdr;
+ double ts;
+ int err;
+
+ if (!d) return 0;
+
+ ts = luaL_checknumber(L,WSLUA_ARG_Dumper_dump_TIMESTAMP);
+ ph = checkPseudoHeader(L,WSLUA_ARG_Dumper_dump_PSEUDOHEADER);
+
+ if (!ph) WSLUA_ARG_ERROR(Dumper_dump,TIMESTAMP,"need a PseudoHeader");
+
+ ba = checkByteArray(L,WSLUA_ARG_Dumper_dump_BYTEARRAY);
+
+ if (! ba) WSLUA_ARG_ERROR(Dumper_dump,BYTEARRAY,"must be a ByteArray");
+
+ pkthdr.ts.secs = (int)floor(ts);
+ pkthdr.ts.nsecs = (int)floor(ts - pkthdr.ts.secs) * 1000000000;
+ pkthdr.len = ba->len;
+ pkthdr.caplen = ba->len;
+ pkthdr.pkt_encap = DUMPER_ENCAP(d);
+
+ if (! wtap_dump(d, &pkthdr, ph->wph, ba->data, &err)) {
+ luaL_error(L,"error while dumping: %s",
+ wtap_strerror(err));
+ }
+
+ return 0;
+
+}
+
+WSLUA_METHOD Dumper_new_for_current(lua_State* L) {
+ /*
+ Creates a capture file using the same encapsulation as the one of the cuurrent packet
+ */
+#define WSLUA_OPTARG_Dumper_new_for_current_FILETYPE 2 /* The file type. Defaults to pcap. */
+ Dumper d;
+ const char* filename = luaL_checkstring(L,1);
+ int filetype = luaL_optint(L,2,WTAP_FILE_PCAP);
+ int encap;
+ int err = 0;
+
+ if (! lua_pinfo )
+ WSLUA_ERROR(Dumper_new_for_current,"cannot be used outside a tap or a dissector");
+
+ encap = lua_pinfo->fd->lnk_t;
+
+ if (!wtap_dump_can_write_encap(filetype, encap)) {
+ luaL_error(L,"Cannot write encap %s in filetype %s",
+ wtap_encap_short_string(encap),
+ wtap_file_type_string(filetype));
+ return 0;
+ }
+
+ d = wtap_dump_open(filename, filetype, encap, 0 , FALSE, &err);
+
+ if (! d ) {
+ luaL_error(L,"error while opening `%s': %s",
+ filename,
+ wtap_strerror(err));
+ return 0;
+ }
+
+ pushDumper(L,d);
+ WSLUA_RETURN(1); /* The newly created Dumper Object */
+
+}
+
+WSLUA_METHOD Dumper_dump_current(lua_State* L) {
+ /*
+ Dumps the current packet as it is.
+ */
+ Dumper d = checkDumper(L,1);
+ struct wtap_pkthdr pkthdr;
+ const guchar* data;
+ tvbuff_t* data_src;
+ int err = 0;
+
+ if (!d) return 0;
+
+ if (! lua_pinfo ) WSLUA_ERROR(Dumper_new_for_current,"cannot be used outside a tap or a dissector");
+
+ data_src = ((data_source*)(lua_pinfo->data_src->data))->tvb;
+
+ pkthdr.ts.secs = lua_pinfo->fd->abs_ts.secs;
+ pkthdr.ts.nsecs = lua_pinfo->fd->abs_ts.nsecs;
+ pkthdr.len = tvb_reported_length(data_src);
+ pkthdr.caplen = tvb_length(data_src);
+ pkthdr.pkt_encap = lua_pinfo->fd->lnk_t;
+
+ data = ep_tvb_memdup(data_src,0,pkthdr.caplen);
+
+ if (! wtap_dump(d, &pkthdr, lua_pinfo->pseudo_header, data, &err)) {
+ luaL_error(L,"error while dumping: %s",
+ wtap_strerror(err));
+ }
+
+ return 0;
+}
+
+static int Dumper__gc(lua_State* L) {
+ Dumper* dp = (Dumper*)luaL_checkudata(L, 1, "Dumper");
+ int err;
+
+ /* If we are Garbage Collected it means the Dumper is no longer usable. Close it */
+
+ if (! *dp)
+ return 0; /* already closed, nothing to do! */
+
+ g_hash_table_remove(dumper_encaps,*dp);
+
+ if (!wtap_dump_close(*dp, &err)) {
+ luaL_error(L,"error closing: %s",
+ wtap_strerror(err));
+ }
+
+ return 0;
+}
+
+
+WSLUA_METHODS Dumper_methods[] = {
+ {"new", Dumper_new},
+ {"new_for_current", Dumper_new_for_current},
+ {"close", Dumper_close},
+ {"flush", Dumper_flush},
+ {"dump", Dumper_dump},
+ {"dump_current", Dumper_dump_current},
+ {0, 0}
+};
+
+WSLUA_META Dumper_meta[] = {
+ {"__gc", Dumper__gc},
+ {0, 0}
+};
+
+int Dumper_register(lua_State* L) {
+ dumper_encaps = g_hash_table_new(g_direct_hash,g_direct_equal);
+ WSLUA_REGISTER_CLASS(Dumper);
+ return 1;
+}
+
diff --git a/epan/wslua/wslua_field.c b/epan/wslua/wslua_field.c
new file mode 100644
index 0000000000..c440ce6bc2
--- /dev/null
+++ b/epan/wslua/wslua_field.c
@@ -0,0 +1,445 @@
+/*
+ * wslua_field.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_field.c 18231 2006-05-28 16:32:49Z etxrab $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+
+WSLUA_CLASS_DEFINE(FieldInfo,NOP,NOP);
+/*
+ An extracted Field
+ */
+
+WSLUA_METAMETHOD FieldInfo__len(lua_State* L) {
+ /*
+ The Length of the field
+ */
+ FieldInfo fi = checkFieldInfo(L,1);
+ lua_pushnumber(L,fi->length);
+ return 1;
+}
+
+WSLUA_METAMETHOD FieldInfo__unm(lua_State* L) {
+ /*
+ The Offset of the field
+ */
+ FieldInfo fi = checkFieldInfo(L,1);
+ lua_pushnumber(L,fi->start);
+ return 1;
+}
+
+WSLUA_METAMETHOD FieldInfo__call(lua_State* L) {
+ /*
+ The Value of the field
+ */
+ FieldInfo fi = checkFieldInfo(L,1);
+
+ switch(fi->hfinfo->type) {
+ case FT_NONE:
+ lua_pushnil(L);
+ return 1;
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ case FT_FRAMENUM:
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ lua_pushnumber(L,(lua_Number)fvalue_get_integer(&(fi->value)));
+ return 1;
+ case FT_FLOAT:
+ case FT_DOUBLE:
+ lua_pushnumber(L,(lua_Number)fvalue_get_floating(&(fi->value)));
+ return 1;
+ case FT_INT64:
+ case FT_UINT64:
+ /*
+ * XXX: double has 53 bits integer precision, n > 2^22 will cause a loss in precision
+ */
+ lua_pushnumber(L,(lua_Number)(gint64)fvalue_get_integer64(&(fi->value)));
+ return 1;
+ case FT_ETHER: {
+ Address eth = g_malloc(sizeof(address));
+ eth->type = AT_ETHER;
+ eth->len = fi->length;
+ eth->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
+ pushAddress(L,eth);
+ return 1;
+ }
+ case FT_IPv4:{
+ Address ipv4 = g_malloc(sizeof(address));
+ ipv4->type = AT_IPv4;
+ ipv4->len = fi->length;
+ ipv4->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
+ pushAddress(L,ipv4);
+ return 1;
+ }
+ case FT_IPv6: {
+ Address ipv6 = g_malloc(sizeof(address));
+ ipv6->type = AT_IPv6;
+ ipv6->len = fi->length;
+ ipv6->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
+ pushAddress(L,ipv6);
+ return 1;
+ }
+ case FT_IPXNET:{
+ Address ipx = g_malloc(sizeof(address));
+ ipx->type = AT_IPX;
+ ipx->len = fi->length;
+ ipx->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
+ pushAddress(L,ipx);
+ return 1;
+ }
+ case FT_STRING:
+ case FT_STRINGZ:
+ lua_pushstring(L,fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL));
+ return 1;
+ case FT_BYTES:
+ case FT_UINT_BYTES:
+ case FT_GUID:
+ case FT_OID: {
+ ByteArray ba = g_byte_array_new();
+ g_byte_array_append(ba, ep_tvb_memdup(fi->ds_tvb,fi->start,fi->length),fi->length);
+ pushByteArray(L,ba);
+ return 1;
+ }
+ default:
+ luaL_error(L,"FT_ not yet supported");
+ return 1;
+ }
+}
+
+WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) {
+ FieldInfo fi = checkFieldInfo(L,1);
+ if (fi) {
+ lua_pushstring(L,fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL));
+ }
+ return 1;
+}
+
+WSLUA_ATTR_GET FieldInfo_get_data_source(lua_State* L) {
+ FieldInfo fi = checkFieldInfo(L,1);
+ pushTvb(L,fi->ds_tvb);
+ return 1;
+}
+
+WSLUA_ATTR_GET FieldInfo_get_range(lua_State* L) {
+ FieldInfo fi = checkFieldInfo(L,1);
+ TvbRange r = ep_alloc(sizeof(struct _wslua_tvbrange));
+
+ r->tvb = fi->ds_tvb;
+ r->offset = fi->start;
+ r->len = fi->length;
+
+ pushTvbRange(L,r);
+ return 1;
+}
+
+
+WSLUA_ATTR_GET FieldInfo_get_hidden(lua_State* L) {
+ FieldInfo fi = checkFieldInfo(L,1);
+ lua_pushboolean(L,FI_GET_FLAG(fi, FI_HIDDEN));
+ return 1;
+}
+
+WSLUA_ATTR_GET FieldInfo_get_generated(lua_State* L) {
+ FieldInfo fi = checkFieldInfo(L,1);
+ lua_pushboolean(L,FI_GET_FLAG(fi, FI_GENERATED));
+ return 1;
+}
+
+WSLUA_ATTR_GET FieldInfo_get_name(lua_State* L) {
+ FieldInfo fi = checkFieldInfo(L,1);
+ lua_pushstring(L,fi->hfinfo->abbrev);
+ return 1;
+}
+
+static const luaL_reg FieldInfo_get[] = {
+ {"data_source", FieldInfo_get_data_source },
+ {"range", FieldInfo_get_range},
+ {"hidden", FieldInfo_get_hidden},
+ {"generated", FieldInfo_get_generated},
+ {"name", FieldInfo_get_name},
+ {"label", FieldInfo__tostring},
+ {"value", FieldInfo__call},
+ {"len", FieldInfo__len},
+ {"offset", FieldInfo__unm},
+ {0, 0}
+};
+
+WSLUA_METAMETHOD FieldInfo__index(lua_State* L) {
+ /*
+ Other attributes:
+ */
+ const gchar* index = luaL_checkstring(L,2);
+ const luaL_reg* r;
+
+ checkFieldInfo(L,1);
+
+ for (r = FieldInfo_get; r->name; r++) {
+ if (g_str_equal(r->name, index)) {
+ return r->func(L);
+ }
+ }
+
+ return 0;
+}
+
+WSLUA_METAMETHOD FieldInfo__eq(lua_State* L) {
+ FieldInfo l = checkFieldInfo(L,1);
+ FieldInfo r = checkFieldInfo(L,2);
+
+ if (l->ds_tvb != r->ds_tvb)
+ WSLUA_ERROR(FieldInfo__eq,"data source must be the same for both fields");
+
+ if (l->start <= r->start && r->start + r->length <= l->start + r->length) {
+ lua_pushboolean(L,1);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+WSLUA_METAMETHOD FieldInfo__le(lua_State* L) {
+ FieldInfo l = checkFieldInfo(L,1);
+ FieldInfo r = checkFieldInfo(L,2);
+
+ if (l->ds_tvb != r->ds_tvb)
+ WSLUA_ERROR(FieldInfo__eq,"data source must be the same for both fields");
+
+ if (r->start + r->length <= l->start + r->length) {
+ lua_pushboolean(L,1);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+WSLUA_METAMETHOD FieldInfo__lt(lua_State* L) {
+ FieldInfo l = checkFieldInfo(L,1);
+ FieldInfo r = checkFieldInfo(L,2);
+
+ if (l->ds_tvb != r->ds_tvb)
+ WSLUA_ERROR(FieldInfo__eq,"data source must be the same for both fields");
+
+ if ( r->start + r->length < l->start ) {
+ lua_pushboolean(L,1);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+static const luaL_reg FieldInfo_meta[] = {
+ {"__tostring", FieldInfo__tostring},
+ {"__call", FieldInfo__call},
+ {"__index", FieldInfo__index},
+ {"__len", FieldInfo__len},
+ {"__unm", FieldInfo__unm},
+ {"__eq", FieldInfo__eq},
+ {"__le", FieldInfo__le},
+ {"__lt", FieldInfo__lt},
+ {0, 0}
+};
+
+int FieldInfo_register(lua_State* L) {
+ WSLUA_REGISTER_META(FieldInfo);
+ return 1;
+}
+
+
+WSLUA_FUNCTION wslua_all_field_infos(lua_State* L) {
+ GPtrArray* found = lua_tree->tree ? proto_all_finfos(lua_tree->tree) : NULL;
+ int items_found = 0;
+ guint i;
+
+ if (found) {
+ for (i=0; i<found->len; i++) {
+ pushFieldInfo(L,g_ptr_array_index(found,i));
+ items_found++;
+ }
+
+ g_ptr_array_free(found,TRUE);
+ }
+
+ return items_found;
+}
+
+WSLUA_CLASS_DEFINE(Field,NOP,NOP);
+/*
+ A Field extractor to to obtain field values.
+ */
+
+static GPtrArray* wanted_fields = NULL;
+
+/*
+ * field extractor registartion is tricky, In order to allow
+ * the user to define them in the body of the script we will
+ * populate the Field value with a pointer of the abbrev of it
+ * to later replace it with the hfi.
+ *
+ * This will be added to the wanted_fields array that will
+ * exists only while they can be defined, and be cleared right
+ * after the fields are primed.
+ */
+
+void lua_prime_all_fields(proto_tree* tree _U_) {
+ GString* fake_tap_filter = g_string_new("frame");
+ guint i;
+ static gboolean fake_tap = FALSE;
+
+ for(i=0; i < wanted_fields->len; i++) {
+ Field f = g_ptr_array_index(wanted_fields,i);
+ gchar* name = *((gchar**)f);
+
+ *f = proto_registrar_get_byname(name);
+
+ if (!*f) {
+ report_failure("Could not find field `%s'",name);
+ *f = NULL;
+ g_free(name);
+ continue;
+ }
+
+ g_free(name);
+
+ g_string_sprintfa(fake_tap_filter," || %s",(*f)->abbrev);
+ fake_tap = TRUE;
+ }
+
+ g_ptr_array_free(wanted_fields,TRUE);
+ wanted_fields = NULL;
+
+ if (fake_tap) {
+ /* a boring tap :-) */
+ GString* error = register_tap_listener("frame",
+ &fake_tap,
+ fake_tap_filter->str,
+ NULL, NULL, NULL);
+
+ if (error) {
+ report_failure("while registering lua_fake_tap:\n%s",error->str);
+ g_string_free(error,TRUE);
+ }
+ }
+
+}
+
+WSLUA_CONSTRUCTOR Field_new(lua_State *L) {
+ /*
+ Create a Field extractor
+ */
+#define WSLUA_ARG_Field_new_FIELDNAME 1 /* The filter name of the field (e.g. ip.addr) */
+ const gchar* name = luaL_checkstring(L,WSLUA_ARG_Field_new_FIELDNAME);
+ Field f;
+
+ if (!name) return 0;
+
+ if (!proto_registrar_get_byname(name))
+ WSLUA_ARG_ERROR(Field_new,FIELDNAME,"a field with this name must exist");
+
+ if (!wanted_fields)
+ WSLUA_ERROR(Field_get,"a Field extractor must be defined before Taps or Dissectors get called");
+
+ f = g_malloc(sizeof(void*));
+ *f = (header_field_info*)g_strdup(name); /* cheating */
+
+ g_ptr_array_add(wanted_fields,f);
+
+ pushField(L,f);
+ WSLUA_RETURN(1); /* The field extractor */
+}
+
+WSLUA_METAMETHOD Field__call (lua_State* L) {
+ Field f = checkField(L,1);
+ header_field_info* in = *f;
+ int items_found = 0;
+
+ if (! in) {
+ luaL_error(L,"invalid field");
+ return 0;
+ }
+
+ if (! lua_pinfo ) {
+ WSLUA_ERROR(Field__call,"fields cannot be used outside dissectors or taps");
+ return 0;
+ }
+
+ for (;in;in = in->same_name_next) {
+ GPtrArray* found = proto_get_finfo_ptr_array(lua_tree->tree, in->id);
+ guint i;
+ if (found) {
+ for (i=0; i<found->len; i++) {
+ pushFieldInfo(L,g_ptr_array_index(found,i));
+ items_found++;
+ }
+ }
+ }
+
+ WSLUA_RETURN(items_found); /* All the values of this field */
+}
+
+static int Field_tostring(lua_State* L) {
+ Field f = checkField(L,1);
+
+ if ( !(f && *f) ) {
+ luaL_error(L,"invalid Field");
+ return 0;
+ }
+
+ if (wanted_fields) {
+ lua_pushstring(L,*((gchar**)f));
+ } else {
+ lua_pushstring(L,(*f)->abbrev);
+ }
+
+ return 1;
+}
+
+static const luaL_reg Field_methods[] = {
+ {"new", Field_new},
+ {0, 0}
+};
+
+static const luaL_reg Field_meta[] = {
+ {"__tostring", Field_tostring},
+ {"__call", Field__call},
+ {0, 0}
+};
+
+int Field_register(lua_State* L) {
+
+ wanted_fields = g_ptr_array_new();
+
+ WSLUA_REGISTER_CLASS(Field);
+
+ return 1;
+}
+
+
diff --git a/epan/wslua/wslua_gui.c b/epan/wslua/wslua_gui.c
new file mode 100644
index 0000000000..9c7c563913
--- /dev/null
+++ b/epan/wslua/wslua_gui.c
@@ -0,0 +1,508 @@
+/*
+ * lua_gui.c
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_gui.c 18611 2006-06-29 13:49:56Z lego $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+
+static const funnel_ops_t* ops = NULL;
+
+struct _lua_menu_data {
+ lua_State* L;
+ int cb_ref;
+ int data_ref;
+};
+
+static int menu_cb_error_handler(lua_State* L) {
+ const gchar* error = lua_tostring(L,1);
+ report_failure("Lua: Error During execution of Menu Callback:\n %s",error);
+ return 0;
+}
+
+WSLUA_FUNCTION wslua_gui_enabled(lua_State* L) { /* Checks whether the GUI facility is enabled. */
+ lua_pushboolean(L,GPOINTER_TO_INT(ops));
+ WSLUA_RETURN(1); /* A boolean: true if it is enabled, false if it isn't. */
+}
+
+void lua_menu_callback(gpointer data) {
+ struct _lua_menu_data* md = data;
+
+ lua_pushcfunction(md->L,menu_cb_error_handler);
+ lua_rawgeti(md->L, LUA_REGISTRYINDEX, md->cb_ref);
+ lua_rawgeti(md->L, LUA_REGISTRYINDEX, md->data_ref);
+
+ lua_pcall(md->L,1,0,1);
+
+ return;
+}
+
+WSLUA_FUNCTION wslua_register_menu(lua_State* L) { /* Register a menu item in the Statistics menu. */
+#define WSLUA_ARG_register_menu_NAME 1 /* The name of the menu item. */
+#define WSLUA_ARG_register_menu_ACTION 2 /* The function to be called when the menu item is invoked. */
+#define WSLUA_OPTARG_register_menu_USERDATA 3 /* To be passed to the action. */
+
+ const gchar* name = luaL_checkstring(L,WSLUA_ARG_register_menu_NAME);
+ struct _lua_menu_data* md;
+ gboolean retap = FALSE;
+
+ if(!name)
+ WSLUA_ARG_ERROR(register_menu,NAME,"must be a string");
+
+ if (!lua_isfunction(L,WSLUA_ARG_register_menu_ACTION))
+ WSLUA_ARG_ERROR(register_menu,ACTION,"must be a function");
+
+ md = g_malloc(sizeof(struct _lua_menu_data));
+ md->L = L;
+
+ lua_pushvalue(L, 2);
+ md->cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ if ( lua_gettop(L) > 2) {
+ lua_pushvalue(L, WSLUA_OPTARG_register_menu_USERDATA);
+ md->data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ } else {
+ md->data_ref = LUA_NOREF;
+ }
+
+ funnel_register_menu(name,
+ REGISTER_STAT_GROUP_GENERIC,
+ lua_menu_callback,
+ md,
+ retap);
+
+ WSLUA_RETURN(0);
+}
+
+
+
+
+struct _dlg_cb_data {
+ lua_State* L;
+ int func_ref;
+ int data_ref;
+};
+
+static int dlg_cb_error_handler(lua_State* L) {
+ const gchar* error = lua_tostring(L,1);
+ report_failure("Lua: Error During execution of dialog callback:\n %s",error);
+ return 0;
+}
+
+static void lua_dialog_cb(gchar** user_input, void* data) {
+ struct _dlg_cb_data* dcbd = data;
+ int i = 0;
+ gchar* input;
+ lua_State* L = dcbd->L;
+
+ lua_settop(L,0);
+ lua_pushcfunction(L,dlg_cb_error_handler);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, dcbd->func_ref);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, dcbd->data_ref);
+
+ for (i = 0; (input = user_input[i]) ; i++) {
+ lua_pushstring(L,input);
+ g_free(input);
+ }
+
+ g_free(user_input);
+
+ switch ( lua_pcall(L,i+1,0,1) ) {
+ case 0:
+ break;
+ case LUA_ERRRUN:
+ g_warning("Runtime error while calling dialog callback");
+ break;
+ case LUA_ERRMEM:
+ g_warning("Memory alloc error while calling dialog callback");
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+}
+
+WSLUA_FUNCTION wslua_new_dialog(lua_State* L) { /* Pops up a new dialog */
+#define WSLUA_ARG_new_dialog_TITLE 1 /* Title of the dialog's window. */
+#define WSLUA_ARG_new_dialog_ACTION 2 /* Action to be performed when OKd. */
+/* WSLUA_MOREARGS new_dialog A series of strings to be used as labels of the dialog's fields */
+
+ const gchar* title;
+ int top = lua_gettop(L);
+ int i;
+ GPtrArray* labels;
+ struct _dlg_cb_data* dcbd;
+
+ if (! ops) {
+ luaL_error(L,"the GUI facility has to be enabled");
+ return 0;
+ }
+
+ if (! (title = luaL_checkstring(L,WSLUA_ARG_new_dialog_TITLE)) ) {
+ WSLUA_ARG_ERROR(new_dialog,TITLE,"must be a string");
+ return 0;
+ }
+
+ if (! lua_isfunction(L,WSLUA_ARG_new_dialog_ACTION)) {
+ WSLUA_ARG_ERROR(new_dialog,ACTION,"must be a function");
+ return 0;
+ }
+
+ if (top < 3) {
+ WSLUA_ERROR(new_dialog,"at least one field required");
+ return 0;
+ }
+
+
+ dcbd = g_malloc(sizeof(struct _dlg_cb_data));
+ dcbd->L = L;
+
+ lua_remove(L,1);
+
+ lua_pushvalue(L, 1);
+ dcbd->func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_remove(L,1);
+
+ lua_pushvalue(L, 1);
+ dcbd->data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_remove(L,1);
+
+ labels = g_ptr_array_new();
+
+ top -= 3;
+
+ for (i = 1; i <= top; i++) {
+ gchar* label = (void*)luaL_checkstring(L,i);
+
+ /* XXX leaks labels on error */
+ if (! label)
+ WSLUA_ERROR(new_dialog,"all fields must be strings");
+
+ g_ptr_array_add(labels,label);
+ }
+
+ g_ptr_array_add(labels,NULL);
+
+ ops->new_dialog(title, (const gchar**)labels->pdata, lua_dialog_cb, dcbd);
+
+ g_ptr_array_free(labels,TRUE);
+
+ WSLUA_RETURN(0);
+}
+
+
+
+WSLUA_CLASS_DEFINE(TextWindow,NOP,NOP); /* Manages a text window. */
+
+WSLUA_CONSTRUCTOR TextWindow_new(lua_State* L) { /* Creates a new TextWindow. */
+#define WSLUA_OPTARG_TextWindow_new_TITLE 1 /* Title of the new window. */
+
+ const gchar* title;
+ TextWindow tw;
+
+ title = luaL_optstring(L,WSLUA_OPTARG_TextWindow_new_TITLE,"Untitled Window");
+ tw = ops->new_text_window(title);
+ pushTextWindow(L,tw);
+
+ WSLUA_RETURN(1); /* The newly created TextWindow object. */
+}
+
+struct _close_cb_data {
+ lua_State* L;
+ int func_ref;
+ int data_ref;
+};
+
+int text_win_close_cb_error_handler(lua_State* L) {
+ const gchar* error = lua_tostring(L,1);
+ report_failure("Lua: Error During execution of TextWindow close callback:\n %s",error);
+ return 0;
+}
+
+static void text_win_close_cb(void* data) {
+ struct _close_cb_data* cbd = data;
+ lua_State* L = cbd->L;
+
+ lua_pushcfunction(L,text_win_close_cb_error_handler);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->func_ref);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->data_ref);
+
+ switch ( lua_pcall(L,1,0,1) ) {
+ case 0:
+ break;
+ case LUA_ERRRUN:
+ g_warning("Runtime error during execution of TextWindow close callback");
+ break;
+ case LUA_ERRMEM:
+ g_warning("Memory alloc error during execution of TextWindow close callback");
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+WSLUA_METHOD TextWindow_set_atclose(lua_State* L) { /* Set the function that will be called when the window closes */
+#define WSLUA_ARG_TextWindow_at_close_ACTION 2 /* A function to be executed when the user closes the window */
+
+ TextWindow tw = checkTextWindow(L,1);
+ struct _close_cb_data* cbd;
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_at_close,"cannot be called for something not a TextWindow");
+
+ lua_settop(L,3);
+
+ if (! lua_isfunction(L,2))
+ WSLUA_ARG_ERROR(TextWindow_at_close,ACTION,"must be a function");
+
+ cbd = g_malloc(sizeof(struct _close_cb_data));
+
+ cbd->L = L;
+ cbd->data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ cbd->func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ ops->set_close_cb(tw,text_win_close_cb,cbd);
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+WSLUA_METHOD TextWindow_set(lua_State* L) { /* Sets the text. */
+#define WSLUA_ARG_TextWindow_set_TEXT 2 /* The text to be used. */
+
+ TextWindow tw = checkTextWindow(L,1);
+ const gchar* text = luaL_checkstring(L,2);
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_set,"cannot be called for something not a TextWindow");
+
+ if (!text)
+ WSLUA_ARG_ERROR(TextWindow_set,TEXT,"must be a string");
+
+ ops->set_text(tw,text);
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+WSLUA_METHOD TextWindow_append(lua_State* L) { /* Appends text */
+#define WSLUA_ARG_TextWindow_append_TEXT 2 /* The text to be appended */
+ TextWindow tw = checkTextWindow(L,1);
+ const gchar* text = luaL_checkstring(L,2);
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_append,"cannot be called for something not a TextWindow");
+
+ if (!text)
+ WSLUA_ARG_ERROR(TextWindow_append,TEXT,"must be a string");
+
+ ops->append_text(tw,text);
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+WSLUA_METHOD TextWindow_prepend(lua_State* L) { /* Prepends text */
+#define WSLUA_ARG_TextWindow_prepend_TEXT 2 /* The text to be appended */
+ TextWindow tw = checkTextWindow(L,1);
+ const gchar* text = luaL_checkstring(L,2);
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_prepend,"cannot be called for something not a TextWindow");
+
+ if (!text)
+ WSLUA_ARG_ERROR(TextWindow_prepend,TEXT,"must be a string");
+
+ ops->prepend_text(tw,text);
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+WSLUA_METHOD TextWindow_clear(lua_State* L) { /* Errases all text in the window. */
+ TextWindow tw = checkTextWindow(L,1);
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_clear,"cannot be called for something not a TextWindow");
+
+ ops->clear_text(tw);
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+WSLUA_METHOD TextWindow_get_text(lua_State* L) { /* Get the text of the window */
+ TextWindow tw = checkTextWindow(L,1);
+ const gchar* text;
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_get_text,"cannot be called for something not a TextWindow");
+
+ text = ops->get_text(tw);
+
+ lua_pushstring(L,text);
+ WSLUA_RETURN(1); /* The TextWindow's text. */
+}
+
+static int TextWindow__gc(lua_State* L) {
+ TextWindow tw = checkTextWindow(L,1);
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_gc,"cannot be called for something not a TextWindow");
+
+ ops->destroy_text_window(tw);
+ return 1;
+}
+
+WSLUA_METHOD TextWindow_set_editable(lua_State* L) { /* Set the function that will be called when the window closes */
+#define WSLUA_OPTARG_TextWindow_at_close_EDITABLE 2 /* A boolean flag, defaults to true */
+
+ TextWindow tw = checkTextWindow(L,1);
+ gboolean editable = luaL_optint(L,2,1);
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_at_close,"cannot be called for something not a TextWindow");
+
+ if (ops->set_editable)
+ ops->set_editable(tw,editable);
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+typedef struct _wslua_bt_cb_t {
+ lua_State* L;
+ int func_ref;
+ int data_ref;
+} wslua_bt_cb_t;
+
+static gboolean wslua_button_callback(funnel_text_window_t* tw, void* data) {
+ wslua_bt_cb_t* cbd = data;
+ lua_State* L = cbd->L;
+
+ lua_settop(L,0);
+ lua_pushcfunction(L,dlg_cb_error_handler);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->func_ref);
+ pushTextWindow(L,tw);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, cbd->data_ref);
+
+ switch ( lua_pcall(L,2,0,1) ) {
+ case 0:
+ break;
+ case LUA_ERRRUN:
+ g_warning("Runtime error while calling button callback");
+ break;
+ case LUA_ERRMEM:
+ g_warning("Memory alloc error while calling button callback");
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ return TRUE;
+}
+
+WSLUA_METHOD TextWindow_add_button(lua_State* L) {
+#define WSLUA_ARG_TextWindow_add_button_LABEL 2 /* The label of the button */
+#define WSLUA_ARG_TextWindow_add_button_FUNCTION 3 /* The function to be called when clicked */
+#define WSLUA_ARG_TextWindow_add_button_DATA 4 /* The data to be passed to the function (other than the window) */
+ TextWindow tw = checkTextWindow(L,1);
+ const gchar* label = luaL_checkstring(L,WSLUA_ARG_TextWindow_add_button_LABEL);
+
+ funnel_bt_t* fbt;
+ wslua_bt_cb_t* cbd;
+
+ if (!tw)
+ WSLUA_ERROR(TextWindow_at_close,"cannot be called for something not a TextWindow");
+
+ if (! lua_isfunction(L,WSLUA_ARG_TextWindow_add_button_FUNCTION) )
+ WSLUA_ARG_ERROR(TextWindow_add_button,FUNCTION,"must be a function");
+
+ lua_settop(L,4);
+
+ if (ops->add_button) {
+ fbt = ep_alloc(sizeof(funnel_bt_t));
+ cbd = ep_alloc(sizeof(wslua_bt_cb_t));
+
+ fbt->tw = tw;
+ fbt->func = wslua_button_callback;
+ fbt->data = cbd;
+
+ cbd->L = L;
+ cbd->data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ cbd->func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ ops->add_button(tw,fbt,label);
+ }
+
+ pushTextWindow(L,tw);
+ WSLUA_RETURN(1); /* The TextWindow object. */
+}
+
+WSLUA_METHODS TextWindow_methods[] = {
+ WSLUA_CLASS_FNREG(TextWindow,new),
+ WSLUA_CLASS_FNREG(TextWindow,set),
+ WSLUA_CLASS_FNREG(TextWindow,new),
+ WSLUA_CLASS_FNREG(TextWindow,append),
+ WSLUA_CLASS_FNREG(TextWindow,prepend),
+ WSLUA_CLASS_FNREG(TextWindow,clear),
+ WSLUA_CLASS_FNREG(TextWindow,set_atclose),
+ WSLUA_CLASS_FNREG(TextWindow,set_editable),
+ WSLUA_CLASS_FNREG(TextWindow,get_text),
+ WSLUA_CLASS_FNREG(TextWindow,add_button),
+ {0, 0}
+};
+
+WSLUA_META TextWindow_meta[] = {
+ {"__tostring", TextWindow_get_text},
+ {"__gc", TextWindow__gc},
+ {0, 0}
+};
+
+int TextWindow_register(lua_State* L) {
+
+ ops = funnel_get_funnel_ops();
+
+ WSLUA_REGISTER_CLASS(TextWindow);
+
+ return 1;
+}
+
+
+WSLUA_FUNCTION wslua_retap_packets(lua_State* L) {
+ /*
+ Rescan all packets and just run taps - don't reconstruct the display.
+ */
+ if ( ops->retap_packets ) {
+ ops->retap_packets();
+ } else {
+ WSLUA_ERROR(wslua_retap_packets, "does not work on TShark");
+ }
+
+ return 0;
+}
+
+
diff --git a/epan/wslua/wslua_listener.c b/epan/wslua/wslua_listener.c
new file mode 100644
index 0000000000..e7b9dd73ff
--- /dev/null
+++ b/epan/wslua/wslua_listener.c
@@ -0,0 +1,332 @@
+/*
+ * wslua_tap.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_tap.c 18268 2006-05-31 17:38:42Z gerald $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+
+/* generated file gets included */
+#include "taps.c-inc"
+
+WSLUA_CLASS_DEFINE(Listener,NOP,NOP);
+/*
+ A Listener, is called once for every packet that matches a certain filter or has a certain tap.
+ It can read the tree, the packet's Tvb eventually the tapped data but it cannot
+ add elements to the tree.
+ */
+struct _wslua_tap {
+ gchar* name;
+ gchar* filter;
+ tap_extractor_t extractor;
+ lua_State* L;
+ int packet_ref;
+ int draw_ref;
+ int init_ref;
+};
+
+tap_extractor_t get_extractor(const gchar* name) {
+ tappable_t* t;
+ for(t = tappables; t->name; t++ ) {
+ if (g_str_equal(t->name,name)) return t->extractor;
+ }
+
+ return NULL;
+}
+
+int tap_packet_cb_error_handler(lua_State* L) {
+ const gchar* error = lua_tostring(L,1);
+ static gchar* last_error = NULL;
+ static int repeated = 0;
+ static int next = 2;
+ const gchar* where = (lua_pinfo) ?
+ ep_strdup_printf("Lua: on packet %i Error During execution of Listener Packet Callback",lua_pinfo->fd->num) :
+ ep_strdup_printf("Lua: Error During execution of Listener Packet Callback") ;
+
+ /* show the error the 1st, 3rd, 5th, 9th, 17th, 33th... time it appears to avoid window flooding */
+ /* XXX the last series of identical errors won't be shown (the user however gets at least one message) */
+
+ if (! last_error) {
+ report_failure("%s:\n%s",where,error);
+ last_error = g_strdup(error);
+ repeated = 0;
+ next = 2;
+ return 0;
+ }
+
+ if (g_str_equal(last_error,error) ) {
+ repeated++;
+ if ( repeated == next ) {
+ report_failure("%s happened %i times:\n %s",where,repeated,error);
+ next *= 2;
+ }
+ } else {
+ report_failure("%s happened %i times:\n %s",where,repeated,last_error);
+ g_free(last_error);
+ last_error = g_strdup(error);
+ repeated = 0;
+ next = 2;
+ report_failure("%s:\n %s",where,error);
+ }
+
+ return 0;
+}
+
+
+int lua_tap_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *data) {
+ Listener tap = tapdata;
+ int retval = 0;
+
+ if (tap->packet_ref == LUA_NOREF) return 0;
+
+ lua_settop(tap->L,0);
+
+ lua_pushcfunction(tap->L,tap_packet_cb_error_handler);
+ lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->packet_ref);
+
+ push_Pinfo(tap->L, pinfo);
+ push_Tvb(tap->L, edt->tvb);
+
+ if (tap->extractor) {
+ tap->extractor(tap->L,data);
+ } else {
+ lua_pushnil(tap->L);
+ }
+
+ lua_pinfo = pinfo;
+ lua_tvb = edt->tvb;
+ lua_tree = ep_alloc(sizeof(struct _wslua_treeitem));
+ lua_tree->tree = edt->tree;
+ lua_tree->item = NULL;
+
+ switch ( lua_pcall(tap->L,3,1,1) ) {
+ case 0:
+
+ if (lua_gettop(tap->L) == 1)
+ retval = luaL_checkint(tap->L,1);
+ else
+ retval = 1;
+
+ break;
+ case LUA_ERRRUN:
+ break;
+ case LUA_ERRMEM:
+ g_warning("Memory alloc error while calling listenet tap callback packet");
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ clear_outstanding_pinfos();
+ clear_outstanding_tvbs();
+
+ lua_pinfo = NULL;
+ lua_tvb = NULL;
+ lua_tree = NULL;
+
+ return retval;
+}
+
+int tap_reset_cb_error_handler(lua_State* L) {
+ const gchar* error = lua_tostring(L,1);
+ report_failure("Lua: Error During execution of Listener init Callback:\n %s",error);
+ return 1;
+}
+
+void lua_tap_reset(void *tapdata) {
+ Listener tap = tapdata;
+
+ if (tap->init_ref == LUA_NOREF) return;
+
+ lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
+ lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->init_ref);
+
+ switch ( lua_pcall(tap->L,0,0,1) ) {
+ case 0:
+ break;
+ case LUA_ERRRUN:
+ g_warning("Runtime error while calling a listener's init()");
+ break;
+ case LUA_ERRMEM:
+ g_warning("Memory alloc error while calling a listener's init()");
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+int tap_draw_cb_error_handler(lua_State* L) {
+ const gchar* error = lua_tostring(L,1);
+ report_failure("Lua: Error During execution of Listener Draw Callback:\n %s",error);
+ return 1;
+}
+
+void lua_tap_draw(void *tapdata) {
+ Listener tap = tapdata;
+ const gchar* error;
+ if (tap->draw_ref == LUA_NOREF) return;
+
+ lua_pushcfunction(tap->L,tap_reset_cb_error_handler);
+ lua_rawgeti(tap->L, LUA_REGISTRYINDEX, tap->draw_ref);
+
+ switch ( lua_pcall(tap->L,0,0,1) ) {
+ case 0:
+ /* OK */
+ break;
+ case LUA_ERRRUN:
+ error = lua_tostring(tap->L,-1);
+ g_warning("Runtime error while calling a listener's draw(): %s",error);
+ break;
+ case LUA_ERRMEM:
+ g_warning("Memory alloc error while calling a listener's draw()");
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+}
+
+WSLUA_CONSTRUCTOR Listener_new(lua_State* L) {
+ /* Creates a new Listener listener */
+#define WSLUA_OPTARG_Listener_new_TAP 1 /* the name of this tap */
+#define WSLUA_OPTARG_Listener_new_FILTER 2 /* a filter that when matches the tap.packet function gets called (use nil to be called for every packet) */
+
+ const gchar* tap_type = luaL_optstring(L,WSLUA_OPTARG_Listener_new_TAP,"frame");
+ const gchar* filter = luaL_optstring(L,WSLUA_OPTARG_Listener_new_FILTER,NULL);
+ Listener tap;
+ GString* error;
+
+ tap = g_malloc(sizeof(struct _wslua_tap));
+
+ tap->name = g_strdup(tap_type);
+ tap->filter = filter ? g_strdup(filter) : NULL;
+ tap->extractor = get_extractor(tap_type);
+ tap->L = L;
+ tap->packet_ref = LUA_NOREF;
+ tap->draw_ref = LUA_NOREF;
+ tap->init_ref = LUA_NOREF;
+
+ error = register_tap_listener(tap_type, tap, tap->filter, lua_tap_reset, lua_tap_packet, lua_tap_draw);
+
+ if (error) {
+ if (tap->filter) g_free(tap->filter);
+ g_free(tap->name);
+ g_free(tap);
+ /* WSLUA_ERROR(new_tap,"tap registration error"); */
+ luaL_error(L,"Error while registering tap:\n%s",error->str);
+ g_string_free(error,TRUE); /* XXX LEAK? */
+ }
+
+ pushListener(L,tap);
+ WSLUA_RETURN(1); /* The newly created Listener listener object */
+}
+
+WSLUA_METHOD Listener_remove(lua_State* L) {
+ /* Removes a tap listener */
+ Listener tap = checkListener(L,1);
+
+ if (!tap) return 0;
+
+ remove_tap_listener(tap);
+
+ return 0;
+}
+
+static int Listener_tostring(lua_State* L) {
+ Listener tap = checkListener(L,1);
+ gchar* str;
+
+ if (!tap) return 0;
+
+ str = g_strdup_printf("Listener(%s) filter: %s",tap->name, tap->filter ? tap->filter : "NONE");
+ lua_pushstring(L,str);
+ g_free(str);
+
+ return 1;
+}
+
+
+static int Listener_newindex(lua_State* L) {
+ /* WSLUA_ATTRIBUTE Listener_packet WO A function that will be called once every packet matches the Listener listener filter.
+
+ function tap.packet(pinfo,tvb,userdata) ... end
+ */
+ /* WSLUA_ATTRIBUTE Listener_draw WO A function that will be called once every few seconds to redraw the gui objects
+ in tshark this funtion is called oly at the very end of the capture file.
+
+ function tap.draw(userdata) ... end
+ */
+ /* WSLUA_ATTRIBUTE Listener_reset WO A function that will be called at the end of the capture run.
+
+ function tap.reset(userdata) ... end
+ */
+ Listener tap = shiftListener(L,1);
+ const gchar* index = lua_shiftstring(L,1);
+ int* refp = NULL;
+
+ if (!index) return 0;
+
+ if (g_str_equal(index,"packet")) {
+ refp = &(tap->packet_ref);
+ } else if (g_str_equal(index,"draw")) {
+ refp = &(tap->draw_ref);
+ } else if (g_str_equal(index,"reset")) {
+ refp = &(tap->init_ref);
+ } else {
+ luaL_error(L,"No such attribute `%s' for a tap",index);
+ return 0;
+ }
+
+ if (! lua_isfunction(L,1)) {
+ luaL_error(L,"Listener's attribute `%s' must be a function");
+ return 0;
+ }
+
+ lua_pushvalue(L, 1);
+ *refp = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ return 0;
+}
+
+
+static const luaL_reg Listener_methods[] = {
+ {"new", Listener_new},
+ {"remove", Listener_remove},
+ {0, 0}
+};
+
+static const luaL_reg Listener_meta[] = {
+ {"__tostring", Listener_tostring},
+ {"__newindex", Listener_newindex},
+ {0, 0}
+};
+
+int Listener_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(Listener);
+ return 1;
+}
+
diff --git a/epan/wslua/wslua_pinfo.c b/epan/wslua/wslua_pinfo.c
new file mode 100644
index 0000000000..9037505857
--- /dev/null
+++ b/epan/wslua/wslua_pinfo.c
@@ -0,0 +1,888 @@
+/*
+ * wslua_pinfo.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_pinfo.c 18231 2006-05-28 16:32:49Z etxrab $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+
+#include <epan/addr_resolv.h>
+#include <string.h>
+
+
+/*
+ * NULLify lua userdata to avoid crashing when trying to
+ * access saved copies of invalid stuff.
+ *
+ * see comment on lua_tvb.c
+ */
+
+static GPtrArray* outstanding_stuff = NULL;
+
+void clear_outstanding_pinfos(void) {
+ while (outstanding_stuff->len) {
+ void** p = (void**)g_ptr_array_remove_index_fast(outstanding_stuff,0);
+ *p = NULL;
+ }
+}
+
+void* push_Pinfo(lua_State* L, Pinfo pinfo) {
+ void** p = (void**)pushPinfo(L,pinfo);
+ g_ptr_array_add(outstanding_stuff,p);
+ return p;
+}
+
+#define PUSH_COLUMN(L,c) g_ptr_array_add(outstanding_stuff,pushColumn(L,c))
+#define PUSH_COLUMNS(L,c) g_ptr_array_add(outstanding_stuff,pushColumns(L,c))
+
+WSLUA_CLASS_DEFINE(Address,NOP,NOP);
+
+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 = g_malloc(sizeof(address));
+ guint32* ip_addr = 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[] = {
+ {"ip", Address_ip },
+ {"ipv4", Address_ip },
+#if 0
+ {"ipv6", Address_ipv6 },
+ {"ss7pc", Address_ss7 },
+ {"eth", Address_eth },
+ {"sna", Address_sna },
+ {"atalk", Address_atalk },
+ {"vines", Address_vines },
+ {"osi", Address_osi },
+ {"arcnet", Address_arcnet },
+ {"fc", Address_fc },
+ {"string", Address_string },
+ {"eui64", Address_eui64 },
+ {"uri", Address_uri },
+ {"tipc", Address_tipc },
+#endif
+ {0,0}
+};
+
+WSLUA_METAMETHOD Address__tostring(lua_State* L) {
+ Address addr = checkAddress(L,1);
+
+ lua_pushstring(L,get_addr_name(addr));
+
+ WSLUA_RETURN(1); /* The string representing the address. */
+}
+
+static int Address__gc(lua_State* L) {
+ Address addr = checkAddress(L,1);
+
+ if (addr) {
+ if (addr->data) 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[] = {
+ {"__gc", Address__gc },
+ {"__tostring", Address__tostring },
+ {"__eq",Address__eq},
+ {"__le",Address__le},
+ {"__lt",Address__lt},
+ {0,0}
+};
+
+
+int Address_register(lua_State *L) {
+ WSLUA_REGISTER_CLASS(Address);
+ return 1;
+}
+
+
+WSLUA_CLASS_DEFINE(Column,FAIL_ON_NULL("expired 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},
+ {"cls_time",COL_CLS_TIME},
+ {"rel_time",COL_REL_TIME},
+ {"date",COL_ABS_DATE_TIME},
+ {"delta_time",COL_DELTA_TIME},
+ {"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},
+ {"oxid",COL_OXID},
+ {"rxid",COL_RXID},
+ {"direction",COL_IF_DIR},
+ {"circuit_id",COL_CIRCUIT_ID},
+ {"src_idx",COL_SRCIDX},
+ {"dst_idx",COL_DSTIDX},
+ {"vsan",COL_VSAN},
+ {"tx_rate",COL_TX_RATE},
+ {"rssi",COL_RSSI},
+ {"hpux_subsys",COL_HPUX_SUBSYS},
+ {"hpux_devid",COL_HPUX_DEVID},
+ {"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* name;
+
+ if (!(c)) {
+ return 0;
+ }
+
+ /* XXX: should return the column's text ! */
+ name = col_id_to_name(c->col);
+ lua_pushstring(L,name ? name : "Unknown Column");
+
+ WSLUA_RETURN(1); /* A string representing the column */
+}
+
+WSLUA_METHOD Column_clear(lua_State *L) {
+ /* Clears a Column */
+ Column c = checkColumn(L,1);
+
+ if (!(c && c->cinfo)) return 0;
+
+ if (check_col(c->cinfo, c->col))
+ 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 && c->cinfo))
+ return 0;
+
+ if (!s) WSLUA_ARG_ERROR(Column_set,TEXT,"must be a string");
+
+ if (check_col(c->cinfo, c->col))
+ col_set_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 && c->cinfo))
+ return 0;
+
+ if (!s) WSLUA_ARG_ERROR(Column_append,TEXT,"must be a string");
+
+
+ if (check_col(c->cinfo, c->col))
+ col_append_str(c->cinfo, c->col, s);
+
+ return 0;
+}
+
+WSLUA_METHOD Column_preppend(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 && c->cinfo))
+ return 0;
+
+ if (!s) WSLUA_ARG_ERROR(Column_prepend,TEXT,"must be a string");
+
+ if (check_col(c->cinfo, c->col))
+ col_prepend_fstr(c->cinfo, c->col, "%s",s);
+
+ return 0;
+}
+
+WSLUA_METHODS Column_methods[] = {
+ {"clear", Column_clear },
+ {"set", Column_set },
+ {"append", Column_append },
+ {"preppend", Column_preppend },
+ {0,0}
+};
+
+
+WSLUA_META Column_meta[] = {
+ {"__tostring", Column__tostring },
+ {0,0}
+};
+
+
+int Column_register(lua_State *L) {
+ WSLUA_REGISTER_CLASS(Column);
+ return 1;
+}
+
+
+
+
+
+
+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. */
+}
+
+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;
+
+ 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) ) {
+ if (check_col(cols, cn->id))
+ col_set_str(cols, 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) {
+ Columns cols = checkColumns(L,1);
+ const struct col_names_t* cn;
+ const char* colname = luaL_checkstring(L,2);
+
+ if (!cols) {
+ Column c = ep_alloc(sizeof(struct _wslua_col_info));
+ c->cinfo = NULL;
+ c->col = col_name_to_id(colname);
+
+ PUSH_COLUMN(L,c);
+ return 1;
+ }
+
+
+
+ if (!colname) return 0;
+
+ for(cn = colnames; cn->name; cn++) {
+ if( g_str_equal(cn->name,colname) ) {
+ Column c = ep_alloc(sizeof(struct _wslua_col_info));
+ c->cinfo = cols;
+ c->col = col_name_to_id(colname);
+
+ PUSH_COLUMN(L,c);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static const luaL_reg Columns_meta[] = {
+ {"__tostring", Columns__tostring },
+ {"__newindex", Columns__newindex },
+ {"__index", Columns_index},
+ {0,0}
+};
+
+
+int Columns_register(lua_State *L) {
+ WSLUA_REGISTER_META(Columns);
+ return 1;
+}
+
+
+WSLUA_CLASS_DEFINE(Pinfo,FAIL_ON_NULL("expired pinfo"),NOP);
+/* Packet information */
+
+static int Pinfo_tostring(lua_State *L) { lua_pushstring(L,"a Pinfo"); return 1; }
+
+#define PINFO_GET_NUMBER(name,val) static int name(lua_State *L) { \
+ Pinfo pinfo = checkPinfo(L,1); \
+ if (!pinfo) return 0;\
+ lua_pushnumber(L,(lua_Number)(val));\
+ return 1;\
+}
+
+#define PINFO_GET_STRING(name,val) static int name(lua_State *L) { \
+ Pinfo pinfo = checkPinfo(L,1); \
+ const gchar* value; \
+ if (!pinfo) return 0; \
+ value = val; \
+ if (value) lua_pushstring(L,(const char*)(value)); else lua_pushnil(L); \
+ return 1; \
+}
+
+#define PINFO_GET_ADDRESS(name,role) static int name(lua_State *L) { \
+ Pinfo pinfo = checkPinfo(L,1); \
+ Address addr = g_malloc(sizeof(address)); \
+ if (!pinfo) return 0; \
+ COPY_ADDRESS(addr, &(pinfo->role)); \
+ pushAddress(L,addr); \
+ return 1; \
+}
+
+PINFO_GET_NUMBER(Pinfo_number,pinfo->fd->num)
+PINFO_GET_NUMBER(Pinfo_len,pinfo->fd->pkt_len)
+PINFO_GET_NUMBER(Pinfo_caplen,pinfo->fd->cap_len)
+PINFO_GET_NUMBER(Pinfo_abs_ts,(((double)pinfo->fd->abs_ts.secs) + (((double)pinfo->fd->abs_ts.nsecs) / 1000000000.0) ))
+PINFO_GET_NUMBER(Pinfo_rel_ts,(((double)pinfo->fd->rel_ts.secs) + (((double)pinfo->fd->rel_ts.nsecs) / 1000000000.0) ))
+PINFO_GET_NUMBER(Pinfo_delta_ts,(((double)pinfo->fd->del_ts.secs) + (((double)pinfo->fd->del_ts.nsecs) / 1000000000.0) ))
+PINFO_GET_NUMBER(Pinfo_ipproto,pinfo->ipproto)
+PINFO_GET_NUMBER(Pinfo_circuit_id,pinfo->circuit_id)
+PINFO_GET_NUMBER(Pinfo_ptype,pinfo->ptype)
+PINFO_GET_NUMBER(Pinfo_src_port,pinfo->srcport)
+PINFO_GET_NUMBER(Pinfo_dst_port,pinfo->destport)
+
+PINFO_GET_STRING(Pinfo_curr_proto,pinfo->current_proto)
+
+PINFO_GET_ADDRESS(Pinfo_net_src,net_src)
+PINFO_GET_ADDRESS(Pinfo_net_dst,net_dst)
+PINFO_GET_ADDRESS(Pinfo_dl_src,dl_src)
+PINFO_GET_ADDRESS(Pinfo_dl_dst,dl_dst)
+PINFO_GET_ADDRESS(Pinfo_src,src)
+PINFO_GET_ADDRESS(Pinfo_dst,dst)
+
+static int Pinfo_visited(lua_State *L) {
+ Pinfo pinfo = checkPinfo(L,1);
+ if (!pinfo) return 0;
+ lua_pushboolean(L,pinfo->fd->flags.visited);
+ return 1;
+}
+
+
+static int Pinfo_match(lua_State *L) {
+ Pinfo pinfo = checkPinfo(L,1);
+
+ if (!pinfo) return 0;
+
+ if (pinfo->match_string) {
+ lua_pushstring(L,pinfo->match_string);
+ } else {
+ lua_pushnumber(L,(lua_Number)(pinfo->match_port));
+ }
+
+ return 1;
+}
+
+static int Pinfo_columns(lua_State *L) {
+ Pinfo pinfo = checkPinfo(L,1);
+ const gchar* colname = luaL_optstring(L,2,NULL);
+
+ if (!colname) {
+ PUSH_COLUMNS(L,pinfo->cinfo);
+ } else {
+ lua_settop(L,0);
+ PUSH_COLUMNS(L,pinfo->cinfo);
+ lua_pushstring(L,colname);
+ return Columns_index(L);
+ }
+ return 1;
+}
+
+
+typedef enum {
+ PARAM_NONE,
+ PARAM_ADDR_SRC,
+ PARAM_ADDR_DST,
+ PARAM_ADDR_DL_SRC,
+ PARAM_ADDR_DL_DST,
+ PARAM_ADDR_NET_SRC,
+ PARAM_ADDR_NET_DST,
+ PARAM_PORT_SRC,
+ PARAM_PORT_DST,
+ PARAM_CIRCUIT_ID,
+ PARAM_PORT_TYPE,
+} pinfo_param_type_t;
+
+static int pushnil_param(lua_State* L, packet_info* pinfo _U_, pinfo_param_type_t pt _U_ ) {
+ lua_pushnil(L);
+ return 1;
+}
+
+int Pinfo_set_addr(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt) {
+ const address* from = checkAddress(L,1);
+ address* to;
+
+ if (! from ) {
+ luaL_error(L,"Not an OK address");
+ return 0;
+ }
+
+ switch(pt) {
+ case PARAM_ADDR_SRC:
+ to = &(pinfo->src);
+ break;
+ case PARAM_ADDR_DST:
+ to = &(pinfo->dst);
+ break;
+ case PARAM_ADDR_DL_SRC:
+ to = &(pinfo->dl_src);
+ break;
+ case PARAM_ADDR_DL_DST:
+ to = &(pinfo->dl_dst);
+ break;
+ case PARAM_ADDR_NET_SRC:
+ to = &(pinfo->net_src);
+ break;
+ case PARAM_ADDR_NET_DST:
+ to = &(pinfo->net_dst);
+ break;
+ default:
+ g_assert(!"BUG: A bad parameter");
+ }
+
+ COPY_ADDRESS(to,from);
+ return 0;
+}
+
+int Pinfo_set_int(lua_State* L, packet_info* pinfo, pinfo_param_type_t pt) {
+ guint v = luaL_checkint(L,1);
+
+ switch(pt) {
+ case PARAM_PORT_SRC:
+ pinfo->srcport = v;
+ return 0;
+ case PARAM_PORT_DST:
+ pinfo->destport = v;
+ return 0;
+ case PARAM_CIRCUIT_ID:
+ pinfo->circuit_id = v;
+ return 0;
+ default:
+ g_assert(!"BUG: A bad parameter");
+ }
+
+ return 0;
+}
+
+typedef struct _pinfo_method_t {
+ const gchar* name;
+ lua_CFunction get;
+ int (*set)(lua_State*, packet_info*, pinfo_param_type_t);
+ pinfo_param_type_t param;
+} pinfo_method_t;
+
+static int Pinfo_hi(lua_State *L) {
+ Pinfo pinfo = checkPinfo(L,1);
+ Address addr = g_malloc(sizeof(address));
+
+ if (!pinfo) return 0;
+
+ if (CMP_ADDRESS(&(pinfo->src), &(pinfo->dst) ) >= 0) {
+ COPY_ADDRESS(addr, &(pinfo->src));
+ } else {
+ COPY_ADDRESS(addr, &(pinfo->dst));
+ }
+
+ pushAddress(L,addr);
+ return 1;
+}
+
+static int Pinfo_lo(lua_State *L) {
+ Pinfo pinfo = checkPinfo(L,1);
+ Address addr = g_malloc(sizeof(address));
+
+ if (!pinfo) return 0;
+
+ if (CMP_ADDRESS(&(pinfo->src), &(pinfo->dst) ) < 0) {
+ COPY_ADDRESS(addr, &(pinfo->src));
+ } else {
+ COPY_ADDRESS(addr, &(pinfo->dst));
+ }
+
+ pushAddress(L,addr);
+ return 1;
+}
+
+
+static const pinfo_method_t Pinfo_methods[] = {
+
+ /* WSLUA_ATTRIBUTE Pinfo_number RO The number of this packet in the current file */
+ {"number", Pinfo_number, pushnil_param, PARAM_NONE},
+
+ /* WSLUA_ATTRIBUTE Pinfo_len RO The length of the frame */
+ {"len", Pinfo_len, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_caplen RO The captured length of the frame */
+ {"caplen", Pinfo_caplen, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_abs_ts RO When the packet was captured */
+ {"abs_ts",Pinfo_abs_ts, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_rel_ts RO Number of seconds passed since beginning of capture */
+ {"rel_ts",Pinfo_rel_ts, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_delta_ts RO Number of seconds passed since the last packet */
+ {"delta_ts",Pinfo_delta_ts, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_visited RO Whether this packet hass been already visited */
+ {"visited",Pinfo_visited, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_src RW Source Address of this Packet */
+ {"src", Pinfo_src, Pinfo_set_addr, PARAM_ADDR_SRC },
+
+ /* WSLUA_ATTRIBUTE Pinfo_dst RW Destination Address of this Packet */
+ {"dst", Pinfo_dst, Pinfo_set_addr, PARAM_ADDR_DST },
+
+ /* WSLUA_ATTRIBUTE Pinfo_lo RO lower Address of this Packet */
+ {"lo", Pinfo_lo, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_hi RW higher Address of this Packet */
+ {"hi", Pinfo_hi, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_dl_src RW Data Link Source Address of this Packet */
+ {"dl_src", Pinfo_dl_src, Pinfo_set_addr, PARAM_ADDR_DL_SRC },
+
+ /* WSLUA_ATTRIBUTE Pinfo_dl_dst RW Data Link Destination Address of this Packet */
+ {"dl_dst", Pinfo_dl_dst, Pinfo_set_addr, PARAM_ADDR_DL_DST },
+
+ /* WSLUA_ATTRIBUTE Pinfo_net_src RW Network Layer Source Address of this Packet */
+ {"net_src", Pinfo_net_src, Pinfo_set_addr, PARAM_ADDR_NET_SRC },
+
+ /* WSLUA_ATTRIBUTE Pinfo_net_dst RW Network Layer Destination Address of this Packet */
+ {"net_dst", Pinfo_net_dst, Pinfo_set_addr, PARAM_ADDR_NET_DST },
+
+ /* WSLUA_ATTRIBUTE Pinfo_ptype RW Type of Port of .src_port and .dst_port */
+ {"port_type", Pinfo_ptype, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_src_port RW Source Port of this Packet */
+ {"src_port", Pinfo_src_port, Pinfo_set_int, PARAM_PORT_SRC },
+
+ /* WSLUA_ATTRIBUTE Pinfo_dst_port RW Source Address of this Packet */
+ {"dst_port", Pinfo_dst_port, Pinfo_set_int, PARAM_PORT_SRC },
+
+ /* WSLUA_ATTRIBUTE Pinfo_ipproto RO IP Protocol id */
+ {"ipproto", Pinfo_ipproto, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_circuit_id RO For circuit based protocols */
+ {"circuit_id", Pinfo_circuit_id, Pinfo_set_int, PARAM_CIRCUIT_ID },
+
+ /* WSLUA_ATTRIBUTE Pinfo_match RO Port/Data we are matching */
+ {"match", Pinfo_match, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_match RO Which Protocol are we dissecting */
+ {"curr_proto", Pinfo_curr_proto, pushnil_param, PARAM_NONE },
+
+ /* WSLUA_ATTRIBUTE Pinfo_columns RO Accesss to the packet list columns */
+ {"cols", Pinfo_columns, pushnil_param, PARAM_NONE },
+
+ {NULL,NULL,NULL,PARAM_NONE}
+};
+
+
+static int pushnil(lua_State* L) {
+ lua_pushnil(L);
+ return 1;
+}
+
+static int Pinfo_index(lua_State* L) {
+ Pinfo pinfo = checkPinfo(L,1);
+ const gchar* name = luaL_checkstring(L,2);
+ lua_CFunction method = pushnil;
+ const pinfo_method_t* curr;
+
+ if (! (pinfo && name) ) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ for (curr = Pinfo_methods ; curr->name ; curr++) {
+ if (g_str_equal(curr->name,name)) {
+ method = curr->get;
+ break;
+ }
+ }
+
+ lua_settop(L,1);
+ return method(L);
+}
+
+static int Pinfo_setindex(lua_State* L) {
+ Pinfo pinfo = checkPinfo(L,1);
+ const gchar* name = luaL_checkstring(L,2);
+ int (*method)(lua_State*, packet_info* pinfo, pinfo_param_type_t) = pushnil_param;
+ const pinfo_method_t* curr;
+ pinfo_param_type_t param_type = PARAM_NONE;
+
+ if (! (pinfo && name) ) {
+ return 0;
+ }
+
+ for (curr = Pinfo_methods ; curr->name ; curr++) {
+ if (g_str_equal(curr->name,name)) {
+ method = curr->set;
+ param_type = curr->param;
+ break;
+ }
+ }
+
+ lua_remove(L,1);
+ lua_remove(L,1);
+ return method(L,pinfo,param_type);
+}
+
+static const luaL_reg Pinfo_meta[] = {
+ {"__index", Pinfo_index},
+ {"__newindex",Pinfo_setindex},
+ {"__tostring", Pinfo_tostring},
+ {0, 0}
+};
+
+int Pinfo_register(lua_State* L) {
+ WSLUA_REGISTER_META(Pinfo);
+ outstanding_stuff = g_ptr_array_new();
+ return 1;
+}
+
diff --git a/epan/wslua/wslua_proto.c b/epan/wslua/wslua_proto.c
new file mode 100644
index 0000000000..0a30f93d6f
--- /dev/null
+++ b/epan/wslua/wslua_proto.c
@@ -0,0 +1,1350 @@
+/*
+ * lua_proto.c
+ *
+ * wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_proto.c 18611 2006-06-29 13:49:56Z lego $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+
+WSLUA_CLASS_DEFINE(Pref,NOP,NOP); /* A preference of a Protocol. */
+
+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 = 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 = lua_toboolean(L,2);
+ pref->value.b = def;
+ break;
+ }
+ case PREF_UINT: {
+ guint32 def = (guint32)luaL_optnumber(L,2,0);
+ pref->value.u = def;
+ break;
+ }
+ case PREF_STRING: {
+ gchar* def = g_strdup(luaL_optstring(L,2,""));
+ pref->value.s = def;
+ 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 Protocol's prefs table.
+ */
+#define WSLUA_ATTR_Pref_bool_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
+#define WSLUA_ATTR_Pref_bool_DEFAULT 2 /* The default value for this preference */
+#define WSLUA_ATTR_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 Protocol's prefs table.
+ */
+#define WSLUA_ATTR_Pref_uint_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
+#define WSLUA_ATTR_Pref_uint_DEFAULT 2 /* The default value for this preference */
+#define WSLUA_ATTR_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 Protocol's prefs table.
+ */
+#define WSLUA_ATTR_Pref_string_LABEL 1 /* The Label (text in the right side of the preference input) for this preference */
+#define WSLUA_ATTR_Pref_string_DEFAULT 2 /* The default value for this preference */
+#define WSLUA_ATTR_Pref_string_DESCR 3 /* A description of what this preference is */
+ return new_pref(L,PREF_STRING);
+}
+
+static int Pref_gc(lua_State* L) {
+ Pref pref = checkPref(L,1);
+
+ if (pref && ! pref->name) {
+ if (pref->label) g_free(pref->label);
+ if (pref->desc) g_free(pref->desc);
+ if (pref->type == PREF_STRING) g_free((void*)pref->value.s);
+ g_free(pref);
+ }
+
+ return 0;
+}
+
+WSLUA_METHODS Pref_methods[] = {
+ {"bool", Pref_bool},
+ {"uint", Pref_uint},
+ {"string", Pref_string},
+ {0,0}
+};
+
+WSLUA_META Pref_meta[] = {
+ {"__gc", Pref_gc},
+ {0,0}
+};
+
+
+WSLUA_REGISTER Pref_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(Pref);
+ return 1;
+}
+
+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 still unassigned Pref object */
+
+ Pref prefs = 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;
+
+ if (! prefs ) return 0;
+
+ if (! name )
+ WSLUA_ARG_ERROR(Prefs__newindex,NAME,"must be a string");
+
+ if (! pref )
+ WSLUA_ARG_ERROR(Prefs__newindex,PREF,"must be a valid Pref");
+
+ if (pref->name)
+ WSLUA_ARG_ERROR(Prefs__newindex,NAME,"cannot change existing preference");
+
+ if (pref->proto)
+ WSLUA_ARG_ERROR(Prefs__newindex,PREF,"cannot be added to more than one protocol");
+
+ p = prefs;
+
+ do {
+ if ( p->name && g_str_equal(p->name,name) ) {
+ luaL_error(L,"a preference named %s exists already",name);
+ return 0;
+ }
+
+ if ( ! p->next) {
+ p->next = pref;
+
+ pref->name = g_strdup(name);
+
+ if (!pref->label)
+ pref->label = g_strdup(name);
+
+ if (!prefs->proto->prefs_module) {
+ prefs->proto->prefs_module = prefs_register_protocol(prefs->proto->hfid, NULL);
+
+ }
+
+ switch(pref->type) {
+ case PREF_BOOL:
+ prefs_register_bool_preference(prefs->proto->prefs_module,
+ pref->name,
+ pref->label,
+ pref->desc,
+ &(pref->value.b));
+ break;
+ case PREF_UINT:
+ prefs_register_uint_preference(prefs->proto->prefs_module,
+ pref->name,
+ pref->label,
+ pref->desc,
+ 10,
+ &(pref->value.u));
+ break;
+ case PREF_STRING:
+ prefs_register_string_preference(prefs->proto->prefs_module,
+ pref->name,
+ pref->label,
+ pref->desc,
+ &(pref->value.s));
+ break;
+ default:
+ WSLUA_ERROR(Prefs__newindex,"unknow Pref type");
+ }
+
+ 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 = checkPrefs(L,1);
+ const gchar* name = luaL_checkstring(L,2);
+
+ if (! ( name && prefs ) ) return 0;
+
+ prefs = prefs->next;
+
+ do {
+ if ( g_str_equal(prefs->name,name) ) {
+ switch (prefs->type) {
+ case PREF_BOOL: lua_pushboolean(L, prefs->value.b); break;
+ case PREF_UINT: lua_pushnumber(L,(lua_Number)prefs->value.u); break;
+ case PREF_STRING: lua_pushstring(L,prefs->value.s); break;
+ default: WSLUA_ERROR(Prefs__index,"unknow Pref type");
+ }
+ WSLUA_RETURN(1); /* the current value of the preference */
+ }
+ } while (( prefs = prefs->next ));
+
+ WSLUA_ARG_ERROR(Prefs__index,NAME,"no preference named like this");
+ WSLUA_RETURN(0);
+}
+
+WSLUA_META Prefs_meta[] = {
+ {"__newindex", Prefs__newindex},
+ {"__index", Prefs__index},
+ {0,0}
+};
+
+WSLUA_REGISTER Prefs_register(lua_State* L) {
+ WSLUA_REGISTER_META(Prefs);
+ return 1;
+}
+
+
+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[] = {
+{"FT_BOOLEAN",FT_BOOLEAN},
+{"FT_UINT8",FT_UINT8},
+{"FT_UINT16",FT_UINT16},
+{"FT_UINT24",FT_UINT24},
+{"FT_UINT32",FT_UINT32},
+{"FT_UINT64",FT_UINT64},
+{"FT_INT8",FT_INT8},
+{"FT_INT16",FT_INT16},
+{"FT_INT24",FT_INT24},
+{"FT_INT32",FT_INT32},
+{"FT_INT64",FT_INT64},
+{"FT_FLOAT",FT_FLOAT},
+{"FT_DOUBLE",FT_DOUBLE},
+{"FT_STRING",FT_STRING},
+{"FT_STRINGZ",FT_STRINGZ},
+{"FT_ETHER",FT_ETHER},
+{"FT_BYTES",FT_BYTES},
+{"FT_UINT_BYTES",FT_UINT_BYTES},
+{"FT_IPv4",FT_IPv4},
+{"FT_IPv6",FT_IPv6},
+{"FT_IPXNET",FT_IPXNET},
+{"FT_FRAMENUM",FT_FRAMENUM},
+{"FT_GUID",FT_GUID},
+{"FT_OID",FT_OID},
+{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 base_display_string_t {
+ const gchar* str;
+ base_display_e base;
+};
+
+static const struct base_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},
+ {NULL,0}
+};
+
+static const gchar* base_to_string(base_display_e base) {
+ const struct base_display_string_t* b;
+ for (b=base_displays;b->str;b++) {
+ if ( base == b->base)
+ return b->str;
+ }
+ return NULL;
+}
+
+static base_display_e string_to_base(const gchar* str) {
+ const struct base_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 vaalue_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 vaalue_string must be strings");
+ g_array_free(vs,TRUE);
+ return NULL;
+ }
+
+ v.value = (guint32)lua_tonumber(L,-2);
+ v.strptr = g_strdup(lua_tostring(L,-1));
+
+ g_array_append_val(vs,v);
+
+ lua_pop(L, 1);
+ }
+
+ lua_pop(L, 1);
+
+ ret = (value_string*)vs->data;
+
+ g_array_free(vs,FALSE);
+
+ return ret;
+
+}
+
+WSLUA_CONSTRUCTOR ProtoField_new(lua_State* L) { /* Creates a new field to be used in a protocol. */
+#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 (FT_*). */
+#define WSLUA_OPTARG_ProtoField_new_VALUESTRING 4 /* a ValueString object. */
+#define WSLUA_OPTARG_ProtoField_new_BASE 5 /* The representation BASE_*. */
+#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 = g_malloc(sizeof(wslua_field_t));
+ value_string* vs;
+
+ /* will be using -2 as far as the field has not been added to an array then it will turn -1 */
+ f->hfid = -2;
+ f->ett = -1;
+ f->name = g_strdup(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_NAME));
+ f->abbr = g_strdup(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_ABBR));
+ f->type = get_ftenum(luaL_checkstring(L,WSLUA_ARG_ProtoField_new_TYPE));
+
+ /*XXX do it better*/
+ if (f->type == FT_NONE) {
+ WSLUA_ARG_ERROR(ProtoField_new,TYPE,"invalid FT_type");
+ return 0;
+ }
+
+ if (! lua_isnil(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING) ) {
+ vs = value_string_from_table(L,WSLUA_OPTARG_ProtoField_new_VALUESTRING);
+
+ if (vs) {
+ f->vs = vs;
+ } else {
+ g_free(f);
+ return 0;
+ }
+
+
+ } else {
+ f->vs = NULL;
+ }
+
+ /* XXX: need BASE_ERROR */
+ f->base = string_to_base(luaL_optstring(L, WSLUA_OPTARG_ProtoField_new_BASE, "BASE_NONE"));
+ f->mask = luaL_optint(L, WSLUA_OPTARG_ProtoField_new_MASK, 0x0);
+ f->blob = g_strdup(luaL_optstring(L,WSLUA_OPTARG_ProtoField_new_DESCR,""));
+
+ pushProtoField(L,f);
+
+ WSLUA_RETURN(1); /* The newly created ProtoField object */
+}
+
+
+static int ProtoField_integer(lua_State* L, enum ftenum type) {
+ ProtoField f = g_malloc(sizeof(wslua_field_t));
+ const gchar* abbr = luaL_checkstring(L,1);
+ const gchar* name = luaL_optstring(L,2,abbr);
+ base_display_e base = luaL_optint(L, 3, BASE_DEC);
+ value_string* vs = (lua_gettop(L) > 3) ? value_string_from_table(L,4) : NULL;
+ int mask = luaL_optint(L, 5, 0x0);
+ const gchar* blob = luaL_optstring(L,6,"");
+
+ if (base < BASE_DEC || base > BASE_HEX_DEC) {
+ luaL_argerror(L,2,"Base must be either BASE_DEC, BASE_HEX, BASE_OCT,"
+ " BASE_DEC_HEX, BASE_DEC_HEX or BASE_HEX_DEC");
+ return 0;
+ }
+
+ f->hfid = -2;
+ f->ett = -1;
+ f->name = g_strdup(name);
+ f->abbr = g_strdup(abbr);
+ f->type = type;
+ f->vs = vs;
+ f->base = base;
+ f->mask = mask;
+ f->blob = g_strdup(blob);
+
+
+ pushProtoField(L,f);
+
+ return 1;
+}
+
+#define PROTOFIELD_INTEGER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_integer(L,FT); }
+/* WSLUA_SECTION Protofield integer constructors */
+/* WSLUA_TEXT integer type ProtoField constructors use the following arguments */
+/* WSLUA_ARG_DESC Protofield_integer ABBR abbreviated name of the field (the string used in filters) */
+/* WSLUA_OPTARG_DESC Protofield_integer NAME Actual name of the field (the string that appears in the tree) */
+/* WSLUA_ARGDESC Protofield_integer DESC description of the field */
+/* _WSLUA_RETURNS_ Protofield_integer a protofiled item to be added to a ProtoFieldArray */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_uint8 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_uint16 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_uint24 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_uint32 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_uint64 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_int8 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_int16 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_int24 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_int32 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_int64 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_framenum */
+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_INT8)
+PROTOFIELD_INTEGER(int24,FT_INT8)
+PROTOFIELD_INTEGER(int32,FT_INT8)
+PROTOFIELD_INTEGER(int64,FT_INT8)
+PROTOFIELD_INTEGER(framenum,FT_FRAMENUM)
+
+static int ProtoField_other(lua_State* L,enum ftenum type) {
+ ProtoField f = g_malloc(sizeof(wslua_field_t));
+ const gchar* abbr = luaL_checkstring(L,1);
+ const gchar* name = luaL_optstring(L,2,abbr);
+ const gchar* blob = luaL_optstring(L,3,"");
+
+ f->hfid = -2;
+ f->ett = -1;
+ f->name = g_strdup(name);
+ f->abbr = g_strdup(abbr);
+ f->type = type;
+ f->vs = NULL;
+ f->base = ( type == FT_FLOAT || type == FT_DOUBLE) ? BASE_DEC : BASE_NONE;
+ f->mask = 0;
+ f->blob = g_strdup(blob);
+
+ pushProtoField(L,f);
+
+ return 1;
+}
+
+#define PROTOFIELD_OTHER(lower,FT) static int ProtoField_##lower(lua_State* L) { return ProtoField_other(L,FT); }
+/* WSLUA_SECTION Protofield integer constructors */
+/* WSLUA_TEXT integer type ProtoField constructors use the following arguments */
+/* WSLUA_ARG_DESC Protofield_integer ABBR abbreviated name of the field (the string used in filters) */
+/* WSLUA_OPTARG_DESC Protofield_integer NAME Actual name of the field (the string that appears in the tree) */
+/* WSLUA_ARGDESC Protofield_integer DESC : description of the field */
+/* _WSLUA_RETURNS_ Protofield non integer : a protofiled item to be added to a ProtoFieldArray */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_ipv4 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_ipv6 */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_ether */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_float */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_double */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_string */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_strigz */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_bytes */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_ubytes */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_guid */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_oid */
+/* _WSLUA_CONSTRUCTOR_ ProtoField_bool */
+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(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)
+
+/* XXX: T/F strings */
+PROTOFIELD_OTHER(bool,FT_BOOLEAN)
+
+
+static int ProtoField_tostring(lua_State* L) {
+ ProtoField f = checkProtoField(L,1);
+ gchar* s = g_strdup_printf("ProtoField(%i): %s %s %s %s %p %.8x %s",f->hfid,f->name,f->abbr,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 = checkProtoField(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->abbr);
+ g_free(f->blob);
+ g_free(f);
+ }
+
+ return 0;
+}
+
+
+static const luaL_reg ProtoField_methods[] = {
+ {"new", ProtoField_new},
+ {"uint8",ProtoField_uint8},
+ {"uint16",ProtoField_uint16},
+ {"uint24",ProtoField_uint24},
+ {"uint32",ProtoField_uint32},
+ {"uint64",ProtoField_uint64},
+ {"int8",ProtoField_int8},
+ {"int16",ProtoField_int16},
+ {"int24",ProtoField_int24},
+ {"int32",ProtoField_int32},
+ {"int64",ProtoField_int64},
+ {"framenum",ProtoField_framenum},
+ {"ipv4",ProtoField_ipv4},
+ {"ipv6",ProtoField_ipv6},
+ {"ipx",ProtoField_ipx},
+ {"ether",ProtoField_ether},
+ {"bool",ProtoField_bool},
+ {"float",ProtoField_float},
+ {"double",ProtoField_double},
+ {"string",ProtoField_string},
+ {"stringz",ProtoField_stringz},
+ {"bytes",ProtoField_bytes},
+ {"ubytes",ProtoField_ubytes},
+ {"guid",ProtoField_guid},
+ {"oid",ProtoField_oid},
+ {0,0}
+};
+
+static const luaL_reg ProtoField_meta[] = {
+ {"__gc", ProtoField_gc },
+ {"__tostring", ProtoField_tostring },
+ {0, 0}
+};
+
+int ProtoField_register(lua_State* L) {
+
+ WSLUA_REGISTER_CLASS(ProtoField);
+
+ return 1;
+}
+
+WSLUA_CLASS_DEFINE(Proto,NOP,NOP);
+/*
+ A new protocol in wireshark. Protocols have more uses, the main one is to dissect
+ a protocol. But they can be just dummies used to register preferences for
+ other purposes.
+ */
+
+static int protocols_table_ref = LUA_NOREF;
+
+WSLUA_CONSTRUCTOR Proto_new(lua_State* L) {
+#define WSLUA_ARG_Proto_new_NAME 1 /* The name of the protocol */
+#define WSLUA_ARG_Proto_new_DESC 1 /* A Long Text description of the protocol (usually lowercase) */
+ const gchar* name = luaL_checkstring(L,1);
+ const gchar* desc = luaL_checkstring(L,2);
+
+ if ( name ) {
+ gchar* loname = ep_strdup(name);
+ g_strdown(loname);
+ if ( proto_get_id_by_filter_name(loname) > 0 ) {
+ WSLUA_ARG_ERROR(Proto_new,NAME,"there cannot be two protocols with the same name");
+ } else {
+ Proto proto = g_malloc(sizeof(wslua_proto_t));
+ gchar* loname = g_strdup(name);
+ gchar* hiname = g_strdup(name);
+
+ g_strdown(loname);
+ g_strup(hiname);
+
+ proto->name = hiname;
+ proto->desc = g_strdup(desc);
+ proto->hfid = proto_register_protocol(proto->desc,hiname,loname);
+ proto->ett = -1;
+ proto->is_postdissector = FALSE;
+
+ lua_newtable (L);
+ proto->fields = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ proto->prefs.name = NULL;
+ proto->prefs.label = NULL;
+ proto->prefs.desc = NULL;
+ proto->prefs.value.u = 0;
+ proto->prefs.next = NULL;
+ proto->prefs.proto = proto;
+
+ proto->prefs_module = NULL;
+ proto->handle = NULL;
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
+
+ lua_pushstring(L,loname);
+ pushProto(L,proto);
+
+ lua_settable(L, -3);
+
+ pushProto(L,proto);
+
+ WSLUA_RETURN(1); /* The newly created protocol */
+ }
+ } else {
+ WSLUA_ARG_ERROR(Proto_new,NAME,"must be a string");
+ }
+
+ return 0;
+}
+
+
+
+static int Proto_tostring(lua_State* L) {
+ Proto proto = checkProto(L,1);
+ gchar* s;
+
+ if (!proto) return 0;
+
+ s = g_strdup_printf("Proto: %s",proto->name);
+ lua_pushstring(L,s);
+ g_free(s);
+
+ return 1;
+}
+
+WSLUA_FUNCTION wslua_register_postdissector(lua_State* L) {
+ Proto proto = checkProto(L,1);
+ if (!proto) return 0;
+
+ if(!proto->is_postdissector) {
+ if (! proto->handle) {
+ proto->handle = create_dissector_handle(dissect_lua, proto->hfid);
+ }
+
+ register_postdissector(proto->handle);
+ } else {
+ luaL_argerror(L,1,"this protocol is already registered as postdissector");
+ }
+
+ return 0;
+}
+
+
+static int Proto_get_dissector(lua_State* L) {
+ Proto proto = toProto(L,1);
+
+ if (proto->handle) {
+ pushDissector(L,proto->handle);
+ return 1;
+ } else {
+ luaL_error(L,"The protocol hasn't been registered yet");
+ return 0;
+ }
+}
+
+
+static int Proto_set_dissector(lua_State* L) {
+ Proto proto = toProto(L,1);
+
+ if (lua_isfunction(L,3)) {
+ /* insert the dissector into the dissectors table */
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);
+ lua_replace(L, 1);
+ lua_pushstring(L,proto->name);
+ lua_replace(L, 2);
+ lua_settable(L,1);
+
+ proto->handle = create_dissector_handle(dissect_lua, proto->hfid);
+
+ return 0;
+ } else {
+ luaL_argerror(L,3,"The dissector of a protocol must be a function");
+ return 0;
+ }
+}
+
+static int Proto_get_prefs(lua_State* L) {
+ Proto proto = toProto(L,1);
+
+ pushPrefs(L,&proto->prefs);
+ return 1;
+}
+
+static int Proto_set_init(lua_State* L) {
+ Proto proto = toProto(L,1);
+
+ if (lua_isfunction(L,3)) {
+ /* insert the dissector into the dissectors table */
+ lua_pushstring(L, WSLUA_INIT_ROUTINES);
+ lua_gettable(L, LUA_GLOBALSINDEX);
+ lua_replace(L, 1);
+ lua_pushstring(L,proto->name);
+ lua_replace(L, 2);
+ lua_settable(L,1);
+
+ return 0;
+ } else {
+ luaL_argerror(L,3,"The initializer of a protocol must be a function");
+ return 0;
+ }
+}
+
+static int Proto_get_name(lua_State* L) {
+ Proto proto = toProto(L,1);
+
+ lua_pushstring(L,proto->name);
+ return 1;
+}
+
+
+static int Proto_get_fields(lua_State* L) {
+ Proto proto = toProto(L,1);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
+ return 1;
+}
+
+void wslua_print_stack(char* s, lua_State* L) {
+ int i;
+
+ for (i=1;i<=lua_gettop(L);i++) {
+ printf("%s-%i: %s\n",s,i,lua_typename (L,lua_type(L, i)));
+ }
+ printf("\n");
+}
+
+static int Proto_set_fields(lua_State* L) {
+ Proto proto = toProto(L,1);
+#define FIELDS_TABLE 2
+#define NEW_TABLE 3
+#define NEW_FIELD 3
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
+ lua_replace(L,FIELDS_TABLE);
+
+
+ if( lua_istable(L,NEW_TABLE)) {
+ for (lua_pushnil(L); lua_next(L, NEW_TABLE); ) {
+ if (isProtoField(L,5)) {
+ luaL_ref(L,FIELDS_TABLE);
+ } else if (! lua_isnil(L,5) ) {
+ return luaL_error(L,"only ProtoFields should be in the table");
+ }
+ }
+ } else if (isProtoField(L,NEW_FIELD)){
+ lua_pushvalue(L, NEW_FIELD);
+ luaL_ref(L,FIELDS_TABLE);
+
+ } else {
+ return luaL_error(L,"either a ProtoField or an array of protofields");
+ }
+
+ lua_pushvalue(L, 3);
+
+ return 1;
+}
+
+
+
+typedef struct {
+ gchar* name;
+ lua_CFunction get;
+ lua_CFunction set;
+} proto_actions_t;
+
+static const proto_actions_t proto_actions[] = {
+ /* WSLUA_ATTRIBUTE Pinfo_dissector RW the protocol's dissector, a function you define */
+ {"dissector",Proto_get_dissector, Proto_set_dissector},
+
+ /* WSLUA_ATTRIBUTE Pinfo_fields RO the Fields Table of this dissector */
+ {"fields" ,Proto_get_fields, Proto_set_fields},
+
+ /* WSLUA_ATTRIBUTE Proto_get_prefs RO the preferences of this dissector */
+ {"prefs",Proto_get_prefs,NULL},
+
+ /* WSLUA_ATTRIBUTE Proto_init WO the init routine of this dissector, a function you define */
+ {"init",NULL,Proto_set_init},
+
+ /* WSLUA_ATTRIBUTE Proto_init RO the name given to this dissector */
+ {"name",Proto_get_name,NULL},
+ {NULL,NULL,NULL}
+};
+
+static int Proto_index(lua_State* L) {
+ Proto proto = checkProto(L,1);
+ const gchar* name = luaL_checkstring(L,2);
+ const proto_actions_t* pa;
+
+ if (! (proto && name) ) return 0;
+
+ for (pa = proto_actions; pa->name; pa++) {
+ if ( g_str_equal(name,pa->name) ) {
+ if (pa->get) {
+ return pa->get(L);
+ } else {
+ luaL_error(L,"You cannot get the `%s' attribute of a protocol",name);
+ return 0;
+ }
+ }
+ }
+
+ luaL_error(L,"A protocol doesn't have a `%s' attribute",name);
+ return 0;
+}
+
+
+static int Proto_newindex(lua_State* L) {
+ Proto proto = checkProto(L,1);
+ const gchar* name = luaL_checkstring(L,2);
+ const proto_actions_t* pa;
+
+ if (! (proto && name) ) return 0;
+
+ for (pa = proto_actions; pa->name; pa++) {
+ if ( g_str_equal(name,pa->name) ) {
+ if (pa->set) {
+ return pa->set(L);
+ } else {
+ luaL_error(L,"You cannot set the `%s' attribute of a protocol",name);
+ return 0;
+ }
+ }
+ }
+
+ luaL_error(L,"A protocol doesn't have a `%s' attribute",name);
+ return 0;
+}
+
+static const luaL_reg Proto_meta[] = {
+ {"__tostring", Proto_tostring},
+ {"__index", Proto_index},
+ {"__newindex", Proto_newindex},
+ {0, 0}
+};
+
+int Proto_register(lua_State* L) {
+
+ WSLUA_REGISTER_META(Proto);
+
+ lua_newtable(L);
+ protocols_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ lua_pushstring(L, "Proto");
+ lua_pushcfunction(L, Proto_new);
+ lua_settable(L, LUA_GLOBALSINDEX);
+
+ Pref_register(L);
+ Prefs_register(L);
+
+ return 1;
+}
+
+int Proto_commit(lua_State* L) {
+ lua_settop(L,0);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, protocols_table_ref);
+
+ for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 2)) {
+ GArray* hfa = g_array_new(TRUE,TRUE,sizeof(hf_register_info));
+ GArray* etta = g_array_new(TRUE,TRUE,sizeof(gint*));
+ Proto proto;
+ const gchar* proto_name;
+ proto_name = lua_tostring(L,2);
+ proto = checkProto(L,3);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, proto->fields);
+
+ for (lua_pushnil(L); lua_next(L, 4); lua_pop(L, 1)) {
+ ProtoField f = checkProtoField(L,6);
+ hf_register_info hfri = { &(f->hfid), {f->name,f->abbr,f->type,f->base,VALS(f->vs),f->mask,f->blob,HFILL}};
+ gint* ettp = &(f->ett);
+
+ if (f->hfid != -2) {
+ return luaL_error(L,"fields can be registered only once");
+ }
+
+ f->hfid = -1;
+ g_array_append_val(hfa,hfri);
+ g_array_append_val(etta,ettp);
+ }
+
+ proto_register_field_array(proto->hfid,(hf_register_info*)hfa->data,hfa->len);
+ proto_register_subtree_array((gint**)etta->data,etta->len);
+
+ g_array_free(hfa,FALSE);
+ g_array_free(etta,FALSE);
+ }
+
+ return 0;
+}
+
+
+
+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,1);
+ Dissector d;
+
+ if (!name)
+ WSLUA_ARG_ERROR(Dissector_get,NAME,"must be a string");
+
+ if ((d = find_dissector(name))) {
+ pushDissector(L, d);
+ WSLUA_RETURN(1); /* The Dissector reference */
+ } else
+ WSLUA_ARG_ERROR(Dissector_get,NAME,"No such dissector");
+
+}
+
+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 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);
+
+ if (! ( d && tvb && pinfo) ) return 0;
+
+ TRY {
+ call_dissector(d, tvb, pinfo, ti->tree);
+ /* XXX Are we sure about this??? is this the right/only thing to catch */
+ } CATCH(ReportedBoundsError) {
+ proto_tree_add_protocol_format(lua_tree->tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
+ WSLUA_ERROR(Dissector_call,"malformed frame");
+ return 0;
+ } ENDTRY;
+
+ return 0;
+}
+
+
+static int Dissector_tostring(lua_State* L) {
+ Dissector d = checkDissector(L,1);
+ if (!d) return 0;
+ lua_pushstring(L,dissector_handle_get_short_name(d));
+ return 1;
+}
+
+static const luaL_reg Dissector_methods[] = {
+ {"get", Dissector_get },
+ {"call", Dissector_call },
+ {0,0}
+};
+
+static const luaL_reg Dissector_meta[] = {
+ {"__tostring", Dissector_tostring},
+ {0, 0}
+};
+
+int Dissector_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(Dissector);
+ return 1;
+}
+
+
+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 FT_UINT* or FT_STRING (defaults to FT_UINT32) */
+ gchar* name = (void*)luaL_checkstring(L,WSLUA_ARG_DissectorTable_new_TABLENAME);
+ gchar* ui_name = (void*)luaL_optstring(L,WSLUA_OPTARG_DissectorTable_new_UINAME,name);
+ enum ftenum type = luaL_optint(L,WSLUA_OPTARG_DissectorTable_new_TYPE,FT_UINT32);
+ base_display_e base = luaL_optint(L,4,BASE_DEC);
+
+ if(!(name && ui_name)) return 0;
+
+ name = g_strdup(name);
+ ui_name = g_strdup(ui_name);
+
+ switch(type) {
+ case FT_STRING:
+ base = BASE_NONE;
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ {
+ DissectorTable dt = g_malloc(sizeof(struct _wslua_distbl_t));
+
+ 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 FTUINT* or FT_STRING");
+ }
+ return 0;
+}
+
+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;
+
+ if(!name) return 0;
+
+ table = find_dissector_table(name);
+
+ if (table) {
+ DissectorTable dt = g_malloc(sizeof(struct _wslua_distbl_t));
+ dt->table = table;
+ dt->name = g_strdup(name);
+
+ pushDissectorTable(L, dt);
+
+ WSLUA_RETURN(1); /* The DissectorTable */
+ } else
+ WSLUA_ARG_ERROR(DissectorTable_get,TABLENAME,"no such dissector_table");
+
+}
+
+
+WSLUA_METHOD DissectorTable_add (lua_State *L) {
+ /*
+ Add a dissector to a table.
+ */
+#define WSLUA_ARG_DissectorTable_add_PATTERN 2 /* The pattern to match (either an integer or a string depending on the table's type). */
+#define WSLUA_ARG_DissectorTable_add_DISSECTOR 3 /* The dissector to add (either an 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 = toProto(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");
+
+ } 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");
+
+ 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);
+ } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
+ int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_add_PATTERN);
+ dissector_add(dt->name, port, handle);
+ } else {
+ luaL_error(L,"Strange type %d for a DissectorTable",type);
+ }
+
+ return 0;
+}
+
+WSLUA_METHOD DissectorTable_remove (lua_State *L) {
+ /*
+ Remove a dissector from a table
+ */
+#define WSLUA_ARG_DissectorTable_remove_PATTERN 2 /* The pattern to match (either an integer or a string depending on the table's type). */
+#define WSLUA_ARG_DissectorTable_remove_DISSECTOR 3 /* The dissector to add (either an 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 = toProto(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_add,DISSECTOR,"must be either Proto or Dissector");
+
+ type = get_dissector_table_selector_type(dt->name);
+
+ if (type == FT_STRING) {
+ gchar* pattern = g_strdup(luaL_checkstring(L,2));
+ dissector_delete_string(dt->name, pattern,handle);
+ } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
+ int port = luaL_checkint(L, 2);
+ dissector_delete(dt->name, port, 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 dt = checkDissectorTable(L,1);
+ Tvb tvb = checkTvb(L,3);
+ Pinfo pinfo = checkPinfo(L,4);
+ TreeItem ti = checkTreeItem(L,5);
+ ftenum_t type;
+
+ if (! (dt && tvb && pinfo && ti) ) return 0;
+
+ type = get_dissector_table_selector_type(dt->name);
+
+ TRY {
+
+ if (type == FT_STRING) {
+ const gchar* pattern = luaL_checkstring(L,2);
+
+ if (!pattern) return 0;
+
+ if (dissector_try_string(dt->table,pattern,tvb,pinfo,ti->tree))
+ return 0;
+
+ } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
+ int port = luaL_checkint(L, 2);
+
+ if (dissector_try_port(dt->table,port,tvb,pinfo,ti->tree))
+ return 0;
+
+ } else {
+ luaL_error(L,"No such type of dissector_table");
+ }
+
+ call_dissector(lua_data_handle,tvb,pinfo,ti->tree);
+
+ /* XXX Are we sure about this??? is this the right/only thing to catch */
+ } CATCH(ReportedBoundsError) {
+ proto_tree_add_protocol_format(lua_tree->tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
+ WSLUA_ERROR(DissectorTable_try,"malformed frame");
+ } ENDTRY;
+
+ return 0;
+
+}
+
+WSLUA_METHOD DissectorTable_get_dissector (lua_State *L) {
+ /*
+ Try to obtain 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). */
+
+ 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_try_PATTERN);
+
+ if (!pattern) WSLUA_ARG_ERROR(DissectorTable_try,PATTERN,"must be a string");
+
+ handle = dissector_get_string_handle(dt->table,pattern);
+ } else if ( type == FT_UINT32 || type == FT_UINT16 || type == FT_UINT8 || type == FT_UINT24 ) {
+ int port = luaL_checkint(L, WSLUA_ARG_DissectorTable_try_PATTERN);
+ handle = dissector_get_port_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 */
+ }
+}
+
+
+static int DissectorTable_tostring(lua_State* L) {
+ /* XXX It would be nice to iterate and print which dissectors it has */
+ 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_sprintfa(s,"%s String:\n",dt->name);
+ break;
+ }
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ {
+ int base = get_dissector_table_base(dt->name);
+ g_string_sprintfa(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);
+ return 1;
+}
+
+static const luaL_reg DissectorTable_methods[] = {
+ {"new", DissectorTable_new },
+ {"get", DissectorTable_get },
+ {"add", DissectorTable_add },
+ {"remove", DissectorTable_remove },
+ {"try", DissectorTable_try },
+ {"get_dissector", DissectorTable_get_dissector },
+ {0,0}
+};
+
+static const luaL_reg DissectorTable_meta[] = {
+ {"__tostring", DissectorTable_tostring},
+ {0, 0}
+};
+
+int DissectorTable_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(DissectorTable);
+ return 1;
+}
+
+
+
diff --git a/epan/wslua/wslua_tree.c b/epan/wslua/wslua_tree.c
new file mode 100644
index 0000000000..b4f2c97de9
--- /dev/null
+++ b/epan/wslua/wslua_tree.c
@@ -0,0 +1,290 @@
+/*
+ * wslua_tree.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_tree.c 18231 2006-05-28 16:32:49Z etxrab $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+#include <epan/expert.h>
+
+static gint wslua_ett = -1;
+
+static GPtrArray* outstanding_stuff = NULL;
+
+#define PUSH_TREEITEM(L,i) g_ptr_array_add(outstanding_stuff,push_TreeItem(L,i))
+
+void* push_TreeItem(lua_State*L, TreeItem t) {
+ void** p = (void**)pushTreeItem(L,t);
+ g_ptr_array_add(outstanding_stuff,p);
+ return p;
+}
+
+void clear_outstanding_trees(void) {
+ while (outstanding_stuff->len) {
+ void** p = (void**)g_ptr_array_remove_index_fast(outstanding_stuff,0);
+ *p = NULL;
+ }
+}
+
+WSLUA_CLASS_DEFINE(TreeItem,NOP,NOP);
+
+/* ProtoTree class */
+static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
+ TvbRange tvbr;
+ Proto proto;
+ ProtoField field;
+ int hfid = -1;
+ int ett = -1;
+ ftenum_t type = FT_NONE;
+ TreeItem tree_item = shiftTreeItem(L,1);
+ proto_item* item = NULL;
+
+ if (!tree_item) {
+ return luaL_error(L,"not a TreeItem!");
+ }
+ if (! ( field = shiftProtoField(L,1) ) ) {
+ if (( proto = shiftProto(L,1) )) {
+ hfid = proto->hfid;
+ type = FT_PROTOCOL;
+ ett = proto->ett;
+ }
+ } else {
+ hfid = field->hfid;
+ type = field->type;
+ ett = field->ett;
+ }
+
+ tvbr = shiftTvbRange(L,1);
+
+ if (!tvbr) {
+ tvbr = ep_alloc(sizeof(struct _wslua_tvbrange));
+ tvbr->tvb = lua_tvb;
+ tvbr->offset = 0;
+ tvbr->len = 0;
+ }
+
+ if (hfid > 0 ) {
+ if (lua_gettop(L)) {
+ switch(type) {
+ case FT_PROTOCOL:
+ item = proto_tree_add_item(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,FALSE);
+ lua_pushnumber(L,0);
+ lua_insert(L,1);
+ break;
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ case FT_FRAMENUM:
+ item = proto_tree_add_uint(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(guint32)luaL_checknumber(L,1));
+ break;
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ item = proto_tree_add_int(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(gint32)luaL_checknumber(L,1));
+ break;
+ case FT_FLOAT:
+ item = proto_tree_add_float(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(float)luaL_checknumber(L,1));
+ break;
+ case FT_DOUBLE:
+ item = proto_tree_add_double(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(double)luaL_checknumber(L,1));
+ break;
+ case FT_STRING:
+ case FT_STRINGZ:
+ item = proto_tree_add_string(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,luaL_checkstring(L,1));
+ break;
+ case FT_UINT64:
+ case FT_INT64:
+ case FT_ETHER:
+ case FT_BYTES:
+ case FT_UINT_BYTES:
+ case FT_IPv4:
+ case FT_IPv6:
+ case FT_IPXNET:
+ case FT_GUID:
+ case FT_OID:
+ default:
+ luaL_error(L,"FT_ not yet supported");
+ return 0;
+ }
+
+ lua_remove(L,1);
+
+ } else {
+ item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb, tvbr->offset, tvbr->len, little_endian);
+ }
+
+ if ( lua_gettop(L) ) {
+ const gchar* s = lua_tostring(L,1);
+
+ if (s) proto_item_set_text(item,"%s",s);
+
+ lua_remove(L,1);
+
+ }
+
+ } else if (tvbr) {
+ if (lua_gettop(L)) {
+ const gchar* s = lua_tostring(L,1);
+
+ item = proto_tree_add_text(tree_item->tree, tvbr->tvb, tvbr->offset, tvbr->len,"%s",s);
+ lua_remove(L,1);
+ }
+ } else {
+ if (lua_gettop(L)) {
+ const gchar* s = lua_tostring(L,1);
+ item = proto_tree_add_text(tree_item->tree, lua_tvb, 0, 0,"%s",s);
+ lua_remove(L,1);
+ }
+ }
+
+ while(lua_gettop(L)) {
+ const gchar* s = lua_tostring(L,1);
+
+ if (s) proto_item_append_text(item, " %s", s);
+
+ lua_remove(L,1);
+
+ }
+
+
+ tree_item = ep_alloc(sizeof(struct _wslua_treeitem));
+ tree_item->item = item;
+ tree_item->tree = proto_item_add_subtree(item,ett > 0 ? ett : wslua_ett);
+
+ PUSH_TREEITEM(L,tree_item);
+
+ return 1;
+}
+
+
+WSLUA_METHOD TreeItem_add(lua_State *L) { return TreeItem_add_item_any(L,FALSE); }
+WSLUA_METHOD TreeItem_add_le(lua_State *L) { return TreeItem_add_item_any(L,TRUE); }
+
+WSLUA_METHOD TreeItem_set_text(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+
+ if (ti) {
+ const gchar* s = luaL_checkstring(L,2);
+ proto_item_set_text(ti->item,"%s",s);
+ }
+
+ return 0;
+}
+
+WSLUA_METHOD TreeItem_append_text(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+ const gchar* s;
+
+ if (ti) {
+ s = luaL_checkstring(L,2);
+ proto_item_append_text(ti->item,"%s",s);
+ }
+ return 0;
+}
+
+WSLUA_METHOD TreeItem_set_len(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+ int len;
+
+ if (ti) {
+ len = luaL_checkint(L,2);
+ proto_item_set_len(ti->item,len);
+ }
+
+ return 0;
+}
+
+WSLUA_METHOD TreeItem_set_expert_flags(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+ int group = luaL_checkint(L,2);
+ int severity = luaL_checkint(L,3);
+
+ if ( ti && ti->item ) {
+ proto_item_set_expert_flags(ti->item,group,severity);
+ }
+
+ return 0;
+}
+
+WSLUA_METHOD TreeItem_add_expert_info(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+ int group = luaL_checkint(L,2);
+ int severity = luaL_checkint(L,3);
+ const gchar* str = luaL_optstring(L,4,"Expert Info");
+
+ if ( ti && ti->item ) {
+ expert_add_info_format(lua_pinfo, ti->item, group, severity, "%s", str);
+ }
+
+ return 0;
+}
+
+WSLUA_METHOD TreeItem_set_generated(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+ if (ti) {
+ PROTO_ITEM_SET_GENERATED(ti->item);
+ }
+ return 0;
+}
+
+
+WSLUA_METHOD TreeItem_set_hidden(lua_State *L) {
+ TreeItem ti = checkTreeItem(L,1);
+ if (ti) {
+ PROTO_ITEM_SET_HIDDEN(ti->item);
+ }
+ return 0;
+}
+
+static const luaL_reg TreeItem_methods[] = {
+ {"add", TreeItem_add},
+ {"add_le", TreeItem_add_le},
+ {"set_text", TreeItem_set_text},
+ {"append_text", TreeItem_append_text},
+ {"set_len", TreeItem_set_len},
+ {"set_expert_flags", TreeItem_set_expert_flags},
+ {"add_expert_info", TreeItem_add_expert_info},
+ {"set_generated", TreeItem_set_generated},
+ {"set_hidden", TreeItem_set_hidden},
+ {0, 0}
+};
+static const luaL_reg TreeItem_meta[] = {
+ {0, 0}
+};
+
+
+
+int TreeItem_register(lua_State *L) {
+ gint* etts[] = { &wslua_ett };
+
+ WSLUA_REGISTER_CLASS(TreeItem);
+ outstanding_stuff = g_ptr_array_new();
+
+ proto_register_subtree_array(etts,1);
+
+ return 1;
+}
diff --git a/epan/wslua/wslua_tvb.c b/epan/wslua/wslua_tvb.c
new file mode 100644
index 0000000000..01c8437188
--- /dev/null
+++ b/epan/wslua/wslua_tvb.c
@@ -0,0 +1,738 @@
+/*
+ * wslua_tvb.c
+ *
+ * Wireshark's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_tvb.c 18231 2006-05-28 16:32:49Z etxrab $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+
+WSLUA_CLASS_DEFINE(ByteArray,FAIL_ON_NULL("null bytearray"),NOP);
+
+WSLUA_CONSTRUCTOR ByteArray_new(lua_State* L) { /* creates a ByteArray Object */
+#define WSLUA_OPTARG_ByteArray_new_HEXBYTES 1 /* A string consisting of hexadecimal bytes like "00 B1 A2" or "1a2b3c4d" */
+ GByteArray* ba = g_byte_array_new();
+ const gchar* s;
+ int nibble[2];
+ int i = 0;
+ gchar c;
+
+ if (lua_gettop(L) == 1) {
+ s = luaL_checkstring(L,WSLUA_OPTARG_ByteArray_new_HEXBYTES);
+
+ if (!s) {
+ WSLUA_OPTARG_ERROR(ByteArray_new,HEXBYTES,"must be a string");
+ return 0;
+ }
+
+ /* XXX: slow! */
+ for (; (c = *s); s++) {
+ switch(c) {
+ case '0': case '1': case '2': case '3': case '4': case '5' : case '6' : case '7': case '8' : case '9' :
+ nibble[(i++)%2] = c - '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f' :
+ nibble[(i++)%2] = c - 'a' + 0xa;
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F' :
+ nibble[(i++)%2] = c - 'A' + 0xa;
+ break;
+ default:
+ break;
+ }
+
+ if ( i == 2 ) {
+ guint8 b = (guint8)(nibble[0] * 16 + nibble[1]);
+ g_byte_array_append(ba,&b,1);
+ i = 0;
+ }
+ }
+ }
+
+ pushByteArray(L,ba);
+
+ WSLUA_RETURN(1); /* The new ByteArray object. */
+}
+
+static int ByteArray_gc(lua_State* L) {
+ ByteArray ba = checkByteArray(L,1);
+
+ if (!ba) return 0;
+
+ g_byte_array_free(ba,TRUE);
+ return 0;
+}
+
+WSLUA_METAMETHOD ByteArray__concat(lua_State* L) {
+#define WSLUA_ARG_ByteArray__cat_FIRST 1
+#define WSLUA_ARG_ByteArray__cat_SECOND 1
+
+ ByteArray ba = checkByteArray(L,1);
+ ByteArray ba2 = checkByteArray(L,2);
+
+ if (! (ba && ba2) )
+ WSLUA_ERROR(ByteArray__cat,"both arguments must be ByteArrays");
+
+ g_byte_array_append(ba,ba2->data,ba2->len);
+
+ pushByteArray(L,ba);
+ WSLUA_RETURN(1); /* The new composite ByteArray. */
+}
+
+WSLUA_METHOD ByteArray_prepend(lua_State* L) {
+#define WSLUA_ARG_ByteArray_prepend_BYTES 1
+ ByteArray ba = checkByteArray(L,1);
+ ByteArray ba2 = checkByteArray(L,2);
+
+ if (! (ba && ba2) )
+ WSLUA_ERROR(ByteArray_prepend,"both arguments must be ByteArrays");
+
+ g_byte_array_prepend(ba,ba2->data,ba2->len);
+
+ pushByteArray(L,ba);
+ return 1;
+}
+
+WSLUA_METHOD ByteArray_append(lua_State* L) {
+ ByteArray ba = checkByteArray(L,1);
+ ByteArray ba2 = checkByteArray(L,2);
+
+ if (! (ba && ba2) )
+ WSLUA_ERROR(ByteArray_prepend,"both arguments must be ByteArrays");
+
+ g_byte_array_prepend(ba,ba2->data,ba2->len);
+
+ pushByteArray(L,ba);
+ return 1;
+}
+
+WSLUA_METHOD ByteArray_set_size(lua_State* L) {
+ ByteArray ba = checkByteArray(L,1);
+ int siz = luaL_checkint(L,2);
+
+ if (!ba) return 0;
+
+ g_byte_array_set_size(ba,siz);
+ return 0;
+}
+
+WSLUA_METHOD ByteArray_set_index(lua_State* L) {
+ ByteArray ba = checkByteArray(L,1);
+ int idx = luaL_checkint(L,2);
+ int v = luaL_checkint(L,3);
+
+ if (!ba) return 0;
+
+ 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) {
+ ByteArray ba = checkByteArray(L,1);
+ int idx = luaL_checkint(L,2);
+
+ if (!ba) return 0;
+
+ 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]);
+
+ return 1;
+}
+
+WSLUA_METHOD ByteArray_len(lua_State* L) {
+ ByteArray ba = checkByteArray(L,1);
+
+ if (!ba) return 0;
+
+ lua_pushnumber(L,(lua_Number)ba->len);
+
+ return 1;
+}
+
+WSLUA_METHOD ByteArray_subset(lua_State* L) {
+ ByteArray ba = checkByteArray(L,1);
+ int offset = luaL_checkint(L,2);
+ int len = luaL_checkint(L,3);
+ ByteArray sub;
+
+ if (!ba) return 0;
+
+ 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);
+
+ return 1;
+}
+
+static int ByteArray_tostring(lua_State* L) {
+ static const gchar* byte_to_str[] = {
+ "00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
+ "10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
+ "20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
+ "30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
+ "40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
+ "50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
+ "60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
+ "70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
+ "80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
+ "90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
+ "A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
+ "B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
+ "C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
+ "D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
+ "E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
+ "F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
+ };
+ ByteArray ba = checkByteArray(L,1);
+ int i;
+ GString* s;
+
+ if (!ba) return 0;
+
+ s = g_string_new("");
+
+ for (i = 0; i < (int)ba->len; i++) {
+ g_string_append(s,byte_to_str[(ba->data)[i]]);
+ }
+
+ lua_pushstring(L,s->str);
+ g_string_free(s,TRUE);
+
+ return 1;
+}
+
+static int Tvb_new_real (lua_State *L);
+
+static const luaL_reg ByteArray_methods[] = {
+ {"new", ByteArray_new},
+ {"len", ByteArray_len},
+ {"prepend", ByteArray_prepend},
+ {"append", ByteArray_append},
+ {"subset", ByteArray_subset},
+ {"set_size", ByteArray_set_size},
+ {"tvb", Tvb_new_real},
+ {"get_index", ByteArray_get_index},
+ {"set_index", ByteArray_set_index},
+ {0,0}
+};
+
+static const luaL_reg ByteArray_meta[] = {
+ {"__tostring", ByteArray_tostring},
+ {"__gc", ByteArray_gc},
+ {"__concat", ByteArray__concat},
+ {"__call",ByteArray_subset},
+ {0, 0}
+};
+
+int ByteArray_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(ByteArray);
+ return 1;
+}
+
+
+/*
+ * Tvb & TvbRange
+ *
+ * a Tvb represents a tvbuff_t in Lua.
+ * a TvbRange represents a range in a tvb (tvb,offset,lenght) it's main purpose is to do bounds checking,
+ * it helps too simplifing argument passing to Tree. In wireshark terms this is worthless nothing
+ * not already done by the TVB itself. In lua's terms is necessary to avoid abusing TRY{}CATCH(){}
+ * via preemptive bounds checking.
+ *
+ * These lua objects have to be "NULLified after use", that is, we cannot leave pointers in the
+ * lua machine to a tvb or a tvbr that might exist anymore.
+ *
+ * To do so we are going to keep a pointer to every "box" in which lua has placed a pointer to our object
+ * and then NULLify the object lua points to.
+ *
+ * Other than that we are going to check every instance of a potentialy NULLified object before using it
+ * and report an error to the lua machine if it happens to be NULLified.
+ */
+
+WSLUA_CLASS_DEFINE(Tvb,FAIL_ON_NULL("expired tvb"),NOP);
+
+static GPtrArray* outstanding_stuff = NULL;
+
+#define PUSH_TVB(L,t) g_ptr_array_add(outstanding_stuff,pushTvb(L,t))
+#define PUSH_TVBRANGE(L,t) g_ptr_array_add(outstanding_stuff,pushTvbRange(L,t))
+
+void clear_outstanding_tvbs(void) {
+ while (outstanding_stuff->len) {
+ void** p = (void**)g_ptr_array_remove_index_fast(outstanding_stuff,0);
+ *p = NULL;
+ }
+}
+
+void* push_Tvb(lua_State* L, Tvb tvb) {
+ void** p = (void**)pushTvb(L,tvb);
+ g_ptr_array_add(outstanding_stuff,p);
+ return p;
+}
+
+
+
+/*
+ * Tvb_new_real(bytearray,name)
+ * Creates a new Tvb from a bytearray (adds it to the frame too)
+ */
+static int Tvb_new_real (lua_State *L) {
+ ByteArray ba = checkByteArray(L,1);
+ const gchar* name = luaL_optstring(L,2,"Unnamed") ;
+ guint8* data;
+ Tvb tvb;
+
+ if (!ba) return 0;
+
+ if (!lua_tvb) {
+ luaL_error(L,"Tvbs can only be created and used in dissectors");
+ return 0;
+ }
+
+ data = g_memdup(ba->data, ba->len);
+
+ tvb = tvb_new_real_data(data, ba->len,ba->len);
+ tvb_set_free_cb(tvb, g_free);
+
+ add_new_data_source(lua_pinfo, tvb, name);
+ PUSH_TVB(L,tvb);
+ return 1;
+}
+
+/*
+ * creates a subtvb from a tvbrange
+ *
+ */
+static int Tvb_new_subset (lua_State *L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+
+ if (! tvbr) return 0;
+
+ if (tvb_offset_exists(tvbr->tvb, tvbr->offset + tvbr->len -1 )) {
+ PUSH_TVB(L, tvb_new_subset(tvbr->tvb,tvbr->offset,tvbr->len, tvbr->len) );
+ return 1;
+ } else {
+ luaL_error(L,"Out Of Bounds");
+ return 0;
+ }
+}
+
+/*
+ * convert the bytes to string, mainly for debugging purposes (mind the ...)
+ */
+static int Tvb_tostring(lua_State* L) {
+ Tvb tvb = checkTvb(L,1);
+ int len;
+ gchar* str;
+
+ if (!tvb) return 0;
+
+ len = tvb_length(tvb);
+ str = ep_strdup_printf("TVB(%i) : %s",len,tvb_bytes_to_str(tvb,0,len));
+ lua_pushstring(L,str);
+ return 1;
+}
+
+
+/*
+ * returns the length of a TVB
+ */
+static int Tvb_len(lua_State* L) {
+ Tvb tvb = checkTvb(L,1);
+
+ if (!tvb) return 0;
+
+ lua_pushnumber(L,tvb_length(tvb));
+ return 1;
+}
+
+/*
+ * returns the raw offset of a sub TVB
+ */
+static int Tvb_offset(lua_State* L) {
+ Tvb tvb = checkTvb(L,1);
+
+ if (!tvb) return 0;
+
+ lua_pushnumber(L,TVB_RAW_OFFSET(tvb));
+ return 1;
+}
+
+
+static const luaL_reg Tvb_methods[] = {
+ {"len", Tvb_len},
+ {"offset", Tvb_offset},
+ {0,0}
+};
+
+static int Tvb_range(lua_State* L);
+
+static const luaL_reg Tvb_meta[] = {
+ {"__call", Tvb_range},
+ {"__tostring", Tvb_tostring},
+ {0, 0}
+};
+
+int Tvb_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(Tvb);
+ return 1;
+}
+
+/*
+ * TVB RAnge helper class
+ *
+ */
+
+TvbRange new_TvbRange(lua_State* L, tvbuff_t* tvb, int offset, int len) {
+ TvbRange tvbr;
+
+ if (len == -1) {
+ len = tvb_length_remaining(tvb,offset);
+ if (len < 0) {
+ luaL_error(L,"out of bounds");
+ return 0;
+ }
+ } else if ( (guint)(len + offset) > tvb_length(tvb)) {
+ luaL_error(L,"Range is out of bounds");
+ return NULL;
+ }
+
+ tvbr = ep_alloc(sizeof(struct _wslua_tvbrange));
+ tvbr->tvb = tvb;
+ tvbr->offset = offset;
+ tvbr->len = len;
+
+ return tvbr;
+}
+
+/*
+ * creates a tvbr given the triplet (tvb,offset,len)
+ */
+static int Tvb_range(lua_State* L) {
+ Tvb tvb = checkTvb(L,1);
+ int offset = luaL_optint(L,2,0);
+ int len = luaL_optint(L,3,-1);
+ TvbRange tvbr;
+
+ if (!tvb) return 0;
+
+ if ((tvbr = new_TvbRange(L,tvb,offset,len))) {
+ PUSH_TVBRANGE(L,tvbr);
+ return 1;
+ }
+
+ return 0;
+
+}
+
+WSLUA_CLASS_DEFINE(TvbRange,FAIL_ON_NULL("expired tvbrange"),NOP);
+
+/*
+ * read access to tvbr's data
+ */
+static int TvbRange_get_index(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ const gchar* index = luaL_checkstring(L,2);
+
+ if (!(tvbr && index)) return 0;
+
+ if (g_str_equal(index,"offset")) {
+ lua_pushnumber(L,(lua_Number)tvbr->offset);
+ return 1;
+ } else if (g_str_equal(index,"len")) {
+ lua_pushnumber(L,(lua_Number)tvbr->len);
+ return 1;
+ } else if (g_str_equal(index,"tvb")) {
+ PUSH_TVB(L,tvbr->tvb);
+ return 1;
+ } else {
+ luaL_error(L,"TvbRange has no `%s' attribute",index);
+ }
+
+ return 0;
+}
+
+/*
+ * write access to tvbr's data
+ */
+static int TvbRange_set_index(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ const gchar* index = luaL_checkstring(L,2);
+
+ if (!tvbr) return 0;
+
+ if (g_str_equal(index,"offset")) {
+ int offset = (int)lua_tonumber(L,3);
+
+ if ( (guint)(tvbr->len + offset) > tvb_length(tvbr->tvb)) {
+ luaL_error(L,"out of bounds");
+ return 0;
+ } else {
+ tvbr->offset = offset;
+ PUSH_TVBRANGE(L,tvbr);
+ return 1;
+ }
+ } else if (g_str_equal(index,"len")) {
+ int len = (int)lua_tonumber(L,3);
+
+ if ( (guint)(tvbr->offset + len) > tvb_length(tvbr->tvb)) {
+ luaL_error(L,"out of bounds");
+ return 0;
+ } else {
+ tvbr->len = len;
+ PUSH_TVBRANGE(L,tvbr);
+ return 1;
+ }
+ } else {
+ luaL_error(L,"cannot set `%s' attribute on TvbRange",index);
+ return 0;
+ }
+
+ return 0;
+}
+
+/*
+ * get a Blefuscuoan unsigned integer from a tvb
+ */
+static int TvbRange_get_uint(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ if (!tvbr) return 0;
+
+ switch (tvbr->len) {
+ case 1:
+ lua_pushnumber(L,tvb_get_guint8(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 2:
+ lua_pushnumber(L,tvb_get_ntohs(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 3:
+ lua_pushnumber(L,tvb_get_ntoh24(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 4:
+ lua_pushnumber(L,tvb_get_ntohl(tvbr->tvb,tvbr->offset));
+ return 1;
+ /*
+ * XXX:
+ * lua uses double so we have 52 bits to play with
+ * we are missing 5 and 6 byte integers within lua's range
+ * and 64 bit integers are not supported (there's a lib for
+ * lua that does).
+ */
+ default:
+ luaL_error(L,"TvbRange:get_uint() does not handle %d byte integers",tvbr->len);
+ return 0;
+ }
+}
+
+/*
+ * get a Lilliputian unsigned integer from a tvb
+ */
+static int TvbRange_get_le_uint(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ if (!tvbr) return 0;
+
+ switch (tvbr->len) {
+ case 1:
+ /* XXX unsigned anyway */
+ lua_pushnumber(L,(lua_Number)tvb_get_guint8(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 2:
+ lua_pushnumber(L,tvb_get_letohs(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 3:
+ lua_pushnumber(L,tvb_get_letoh24(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 4:
+ lua_pushnumber(L,tvb_get_letohl(tvbr->tvb,tvbr->offset));
+ return 1;
+ default:
+ luaL_error(L,"TvbRange:get_le_uint() does not handle %d byte integers",tvbr->len);
+ return 0;
+ }
+}
+
+/*
+ * get a Blefuscuoan float
+ */
+static int TvbRange_get_float(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ if (!tvbr) return 0;
+
+ switch (tvbr->len) {
+ case 4:
+ lua_pushnumber(L,(double)tvb_get_ntohieee_float(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 8:
+ lua_pushnumber(L,tvb_get_ntohieee_double(tvbr->tvb,tvbr->offset));
+ return 1;
+ default:
+ luaL_error(L,"TvbRange:get_float() does not handle %d byte floating numbers",tvbr->len);
+ return 0;
+ }
+}
+
+/*
+ * get a Lilliputian float
+ */
+static int TvbRange_get_le_float(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ if (!tvbr) return 0;
+
+ switch (tvbr->len) {
+ case 4:
+ lua_pushnumber(L,tvb_get_letohieee_float(tvbr->tvb,tvbr->offset));
+ return 1;
+ case 8:
+ lua_pushnumber(L,tvb_get_letohieee_double(tvbr->tvb,tvbr->offset));
+ return 1;
+ default:
+ luaL_error(L,"TvbRange:get_float() does not handle %d byte floating numbers",tvbr->len);
+ return 0;
+ }
+}
+
+static int TvbRange_get_ipv4(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ Address addr;
+ guint32* ip_addr;
+
+ if ( !tvbr ) return 0;
+
+ addr = g_malloc(sizeof(address));
+
+ ip_addr = g_malloc(sizeof(guint32));
+ *ip_addr = tvb_get_ntohl(tvbr->tvb,tvbr->offset);
+
+ SET_ADDRESS(addr, AT_IPv4, 4, ip_addr);
+ pushAddress(L,addr);
+
+ return 1;
+}
+
+static int TvbRange_get_ether(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ Address addr;
+ guint8* buff;
+
+ if ( !tvbr ) return 0;
+
+ addr = g_malloc(sizeof(address));
+
+ buff = tvb_memdup(tvbr->tvb,tvbr->offset,tvbr->len);
+
+ SET_ADDRESS(addr, AT_ETHER, 6, buff);
+ pushAddress(L,addr);
+
+ return 1;
+}
+
+
+static int TvbRange_get_string(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+
+ if ( !tvbr ) return 0;
+
+ lua_pushstring(L, (gchar*)tvb_get_ephemeral_string(tvbr->tvb,tvbr->offset,tvbr->len) );
+
+ return 1;
+}
+
+static int TvbRange_get_bytes(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+ GByteArray* ba;
+
+ if ( !tvbr ) return 0;
+
+ ba = g_byte_array_new();
+ g_byte_array_append(ba,ep_tvb_memdup(tvbr->tvb,tvbr->offset,tvbr->len),tvbr->len);
+
+ pushByteArray(L,ba);
+
+ return 1;
+}
+
+static int TvbRange_tostring(lua_State* L) {
+ TvbRange tvbr = checkTvbRange(L,1);
+
+ if (!tvbr) return 0;
+
+ lua_pushstring(L,tvb_bytes_to_str(tvbr->tvb,tvbr->offset,tvbr->len));
+ return 1;
+}
+
+static const luaL_reg TvbRange_methods[] = {
+ {"uint", TvbRange_get_uint},
+ {"le_uint", TvbRange_get_le_uint},
+ {"float", TvbRange_get_float},
+ {"le_float", TvbRange_get_le_float},
+ {"ether", TvbRange_get_ether},
+ {"ipv4", TvbRange_get_ipv4},
+ {"string", TvbRange_get_string},
+ {"bytes", TvbRange_get_bytes},
+ {"tvb", Tvb_new_subset},
+ {0, 0}
+};
+
+static const luaL_reg TvbRange_meta[] = {
+ {"__index", TvbRange_get_index},
+ {"__newindex", TvbRange_set_index},
+ {"__tostring", TvbRange_tostring},
+ {0, 0}
+};
+
+int TvbRange_register(lua_State* L) {
+ outstanding_stuff = g_ptr_array_new();
+ WSLUA_REGISTER_CLASS(TvbRange);
+ return 1;
+}
diff --git a/epan/wslua/wslua_util.c b/epan/wslua/wslua_util.c
new file mode 100644
index 0000000000..a2b5329c03
--- /dev/null
+++ b/epan/wslua/wslua_util.c
@@ -0,0 +1,129 @@
+/*
+ * wslua_util.c
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id: wslua_util.c 18197 2006-05-21 05:12:17Z sahlberg $
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "wslua.h"
+#include <math.h>
+
+WSLUA_API const gchar* lua_shiftstring(lua_State* L, int i) {
+ const gchar* p = luaL_checkstring(L, i);
+
+ if (p) {
+ lua_remove(L,i);
+ return p;
+ } else {
+ return NULL;
+ }
+}
+
+WSLUA_FUNCTION wslua_format_date(lua_State* LS) { /* Formats an absolute timestamp into a human readable date */
+#define WSLUA_ARG_format_date_TIMESTAMP 1 /* A timestamp value to convert. */
+ lua_Number time = luaL_checknumber(LS,WSLUA_ARG_format_date_TIMESTAMP);
+ nstime_t then;
+ gchar* str;
+
+ then.secs = (guint32)floor(time);
+ then.nsecs = (guint32) ( (time-(double)(then.secs))*1000000000);
+ str = abs_time_to_str(&then);
+ lua_pushstring(LS,str);
+
+ WSLUA_RETURN(1); /* a string with the formated date */
+}
+
+WSLUA_FUNCTION wslua_format_time(lua_State* LS) { /* Formats an absolute timestamp in a human readable form */
+#define WSLUA_ARG_format_time_TIMESTAMP 1 /* a timestamp value to convert */
+ lua_Number time = luaL_checknumber(LS,WSLUA_ARG_format_time_TIMESTAMP);
+ nstime_t then;
+ gchar* str;
+
+ then.secs = (guint32)floor(time);
+ then.nsecs = (guint32) ( (time-(double)(then.secs))*1000000000);
+ str = rel_time_to_str(&then);
+ lua_pushstring(LS,str);
+
+ WSLUA_RETURN(1); /* a string with the formated time */
+}
+
+WSLUA_FUNCTION wslua_report_failure(lua_State* LS) { /* reports a failure to the user */
+#define WSLUA_ARG_report_failure_TEXT 1 /* message */
+ const gchar* s = luaL_checkstring(LS,WSLUA_ARG_report_failure_TEXT);
+ report_failure("%s",s);
+ return 0;
+}
+
+static int wslua_log(lua_State* L, GLogLevelFlags log_level) {
+ GString* str = g_string_new("");
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+
+ lua_getglobal(L, "tostring");
+ for (i=1; i<=n; i++) {
+ const char *s;
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ s = lua_tostring(L, -1); /* get result */
+ if (s == NULL)
+ return luaL_error(L, "`tostring' must return a string");
+
+ if (i>1) g_string_append(str,"\t");
+ g_string_append(str,s);
+
+ lua_pop(L, 1); /* pop result */
+ }
+
+ g_log(LOG_DOMAIN_LUA, log_level, "%s\n", str->str);
+ g_string_free(str,TRUE);
+
+ return 0;
+}
+
+WSLUA_FUNCTION wslua_critical( lua_State* L ) { /* Will add a log entry with critical severity*/
+/* WSLUA_MOREARGS critical objects to be printed */
+ wslua_log(L,G_LOG_LEVEL_CRITICAL);
+ return 0;
+}
+WSLUA_FUNCTION wslua_warn( lua_State* L ) { /* Will add a log entry with warn severity */
+/* WSLUA_MOREARGS warn objects to be printed */
+ wslua_log(L,G_LOG_LEVEL_WARNING);
+ return 0;
+}
+WSLUA_FUNCTION wslua_message( lua_State* L ) { /* Will add a log entry with message severity */
+/* WSLUA_MOREARGS message objects to be printed */
+ wslua_log(L,G_LOG_LEVEL_MESSAGE);
+ return 0;
+}
+WSLUA_FUNCTION wslua_info( lua_State* L ) { /* Will add a log entry with info severity */
+/* WSLUA_MOREARGS info objects to be printed */
+ wslua_log(L,G_LOG_LEVEL_INFO);
+ return 0;
+}
+WSLUA_FUNCTION wslua_debug( lua_State* L ) { /* Will add a log entry with debug severity */
+/* WSLUA_MOREARGS debug objects to be printed */
+ wslua_log(L,G_LOG_LEVEL_DEBUG);
+ return 0;
+}
+
+
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index aaf93fd9a2..da0b6d3043 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -21,13 +21,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-if HAVE_LIBLUA
-lua_dir = \
- lua
-else # HAVE_LIBLUA
-lua_dir =
-endif # HAVE_LIBLUA
-
SUBDIRS = \
acn \
agentx \
@@ -40,7 +33,6 @@ SUBDIRS = \
gryphon \
h223 \
irda \
- $(lua_dir) \
lwres \
mate \
megaco \