Starts to work so I check it in.
authorLuis Ontanon <luis.ontanon@gmail.com>
Fri, 20 Jan 2006 00:06:20 +0000 (00:06 -0000)
committerLuis Ontanon <luis.ontanon@gmail.com>
Fri, 20 Jan 2006 00:06:20 +0000 (00:06 -0000)
This is an interface to the Lua programming language.

http://www.lua.org

I've already wrote a simple dissector that calls another dissectors.

soon It will be able to register a tap and do something more.

I did not checkin changes to the Makefiles so in order to use it you must change the makefiles.

Other than that to get it to work you need to download lua-5.0.2.tar.gz into the plugin directory, uncompress it, cd to it and call make.

the interface is buggy and far from finished, time will help on this.

svn path=/trunk/; revision=17057

plugins/lua/Makefile.am [new file with mode: 0644]
plugins/lua/packet-lua.c [new file with mode: 0644]
plugins/lua/plugin.c [new file with mode: 0644]

diff --git a/plugins/lua/Makefile.am b/plugins/lua/Makefile.am
new file mode 100644 (file)
index 0000000..d55f1e4
--- /dev/null
@@ -0,0 +1,58 @@
+# Makefile.am
+#
+# $Id: $
+#
+# Ethereal - Network traffic analyzer
+# By Gerald Combs <gerald@ethereal.com>
+# 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) -I./lua-5.0.2/include
+
+plugindir = @plugindir@
+
+plugin_LTLIBRARIES = work.la
+
+work_la_SOURCES = \
+    packet-lua.c \
+       plugin.c
+
+work_la_LDFLAGS = -module -avoid-version
+work_la_LIBADD = @PLUGIN_LIBS@
+
+
+# Libs must be cleared, or else libtool won't create a shared module.
+# If your module needs to be linked against any particular libraries,
+# add them here.
+LIBS = -L./lua-5.0.2/lib -llua -llualib
+
+
+CLEANFILES = \
+       *~
+
+DISTCLEANFILES = \
+       dummy
+
+MAINTAINERCLEANFILES = \
+       Makefile.in
+
+EXTRA_DIST = \
+       dummy
+
+dummy:
+       touch dummy
+    
diff --git a/plugins/lua/packet-lua.c b/plugins/lua/packet-lua.c
new file mode 100644 (file)
index 0000000..1895bd4
--- /dev/null
@@ -0,0 +1,1977 @@
+/*
+ * packet-lua.c
+ *
+ * Ethereal's interface to the Lua Programming Language
+ *
+ * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ *
+ * $Id:  $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <errno.h>
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.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>
+
+#define VALUE_STRING "ValueString"
+typedef GArray* ValueString;
+
+#define FIELD "Field"
+typedef struct _eth_field_t* Field;
+
+#define FIELD_ARRAY "FieldArray"
+typedef GArray* FieldArray;
+
+#define ETT "Ett"
+typedef int* Ett;
+
+#define ETT_ARRAY "EttArray"
+typedef GArray* EttArray;
+
+#define PROTO "Proto"
+typedef struct _eth_proto_t* Proto;
+
+#define DISSECTOR_TABLE "DissectorTable"
+typedef struct _eth_distbl_t {
+    dissector_table_t table;
+    gchar* name;
+}* DissectorTable;
+
+#define DISSECTOR "Dissector"
+typedef dissector_handle_t Dissector;
+
+#define TVB "Tvb"
+typedef tvbuff_t* Tvb;
+
+#define COLUMN "Column"
+typedef struct _eth_col_info {
+    column_info* cinfo;
+    gint col;
+}* Column;
+
+#define PINFO "Pinfo"
+typedef packet_info* Pinfo;
+
+#define TREE "Tree"
+typedef proto_tree* Tree;
+
+#define ITEM "Item"
+typedef proto_item* Item;
+
+#define ADDRESS "Address"
+typedef address* Address;
+
+static lua_State* L = NULL;
+static dissector_handle_t data_handle = NULL;
+
+typedef struct _eth_field_t {
+    int hfid;
+    char* name;
+    char* abbr;
+    char* blob;
+    enum ftenum type;
+    base_display_e base;
+    value_string* vs;
+    guint32 mask;
+} eth_field_t;
+
+typedef enum {PREF_BOOL,PREF_UINT,PREF_STRING} pref_type_t;
+
+typedef struct _eth_pref_t {
+    gchar* name;
+    pref_type_t type;
+    union {
+        gboolean b;
+        guint32 u;
+        gint32 i;
+        const gchar* s;
+    } value;
+    struct _eth_pref_t* next;
+} eth_pref_t;
+
+typedef struct _eth_proto_t {
+    int hfid;
+    char* name;
+    char* filter;
+    char* desc;
+    hf_register_info* hfarray;
+    gboolean hf_registered;
+    module_t *prefs_module;
+    eth_pref_t* prefs;
+    dissector_handle_t handle;
+} eth_proto_t;
+
+typedef struct {const gchar* str; enum ftenum id; } eth_ft_types_t;
+
+#define NOP
+
+#define LUA_CLASS_OPS(C,CN,check_code) \
+static  C to##C(lua_State* L, int index) { \
+    C* v = (C*)lua_touserdata (L, index); \
+    if (!v) luaL_typerror(L,index,CN); \
+    return *v; \
+} \
+static  C check##C(lua_State* L, int index) { \
+    C* p; \
+    luaL_checktype(L,index,LUA_TUSERDATA); \
+    p = (C*)luaL_checkudata(L, index, CN); \
+    check_code; \
+    return *p; \
+} \
+static  C* push##C(lua_State* L, C v) { \
+    C* p = lua_newuserdata(L,sizeof(C)); *p = v; \
+    luaL_getmetatable(L, CN); lua_setmetatable(L, -2); \
+    return p; \
+}
+
+static int No_gc(lua_State *L _U_) { return 0; }
+
+/*
+ * ValueString class
+ */
+LUA_CLASS_OPS(ValueString,VALUE_STRING,if ( !p )  luaL_error(L,"null value_string"););
+
+static int ValueString_new(lua_State* L) {
+    ValueString vs = g_array_new(TRUE,TRUE,sizeof(value_string));
+    pushValueString(L,vs);
+    return 1;
+}
+
+
+static int ValueString_add(lua_State* L) {
+    ValueString vs = checkValueString(L,1);
+    value_string v = {0,NULL};
+    
+    v.value = luaL_checkint(L,2);
+    v.strptr = g_strdup(luaL_checkstring(L,3));
+    
+    g_array_append_val(vs,v);
+    
+    return 0;
+}
+
+static int ValueString_match(lua_State* L) {
+    ValueString vs = checkValueString(L,1);
+    guint32 val = (guint32)luaL_checkint(L,2);
+    const gchar* def = luaL_optstring(L,8,"Unknown");
+    
+    lua_pushstring(L,val_to_str(val, (value_string*)(vs->data), def));
+    
+    return 1;
+}
+
+static int ValueString_gc(lua_State* L) {
+    ValueString vs = checkValueString(L,1);
+    
+    g_array_free(vs,TRUE);
+    
+    return 0;
+}
+
+static int ValueString_tostring(lua_State* L) {
+    ValueString vs = checkValueString(L,1);
+    value_string* c = (value_string*)vs->data;
+    GString* s = g_string_new("");
+    
+    for(;c->strptr;c++) {
+        g_string_sprintfa(s,"\t%u\t%s\n",c->value,c->strptr);
+    }
+    
+    lua_pushstring(L,s->str);
+    
+    g_string_free(s,TRUE);
+    
+    return 1;
+}
+
+static const luaL_reg ValueString_methods[] = {
+    {"new",   ValueString_new},
+    {"add",   ValueString_add},
+    {"match", ValueString_match},
+    {0,0}
+};
+
+
+static const luaL_reg ValueString_meta[] = {
+    {"__gc",       ValueString_gc},
+    {"__tostring", ValueString_tostring},
+    {0, 0}
+};
+
+
+static  int ValueString_register(lua_State* L) {
+    luaL_openlib(L, VALUE_STRING, ValueString_methods, 0);
+    luaL_newmetatable(L, VALUE_STRING);
+    luaL_openlib(L, 0, ValueString_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);
+    
+    return 1;
+}
+
+
+
+
+/*
+ * Field class
+ */
+
+static const eth_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 eth_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 eth_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;
+}
+
+
+LUA_CLASS_OPS(Field,FIELD,if (! *p) luaL_error(L,"null Field"));
+
+static int Field_new(lua_State* L) {
+    Field f = g_malloc(sizeof(eth_field_t));
+    GArray* vs;
+    
+    f->hfid = -1;
+    f->name = g_strdup(luaL_checkstring(L,1));
+    f->abbr = g_strdup(luaL_checkstring(L,2));
+    f->type = get_ftenum(luaL_checkstring(L,3));
+    
+    if (f->type == FT_NONE) {
+        luaL_error(L,"invalid FT_type");
+        return 0;
+    }
+    
+    if (! lua_isnil(L,4) ) {
+        vs = checkValueString(L,4);
+        
+        if (vs) {
+            f->vs = (value_string*)vs->data;
+        }
+    } else {
+        f->vs = NULL;
+    }
+    
+    f->base = string_to_base(luaL_optstring(L, 5, "BASE_NONE"));
+    f->mask = luaL_optint(L, 6, 0x0);
+    f->blob = g_strdup(luaL_optstring(L,7,""));
+    
+    pushField(L,f);
+    
+    return 1;
+}
+
+static int Field_tostring(lua_State* L) {
+    Field f = checkField(L,1);
+    gchar* s = g_strdup_printf("Field: %s %s %s %s %p %.8x %s\n",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 const luaL_reg Field_methods[] = {
+    {"new",   Field_new},
+    {0,0}
+};
+
+static const luaL_reg Field_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Field_tostring},
+    {0, 0}
+};
+
+static int Field_register(lua_State* L) {
+    const eth_ft_types_t* ts;
+    const struct base_display_string_t* b;
+
+    luaL_openlib(L, FIELD, Field_methods, 0);
+    luaL_newmetatable(L, FIELD);
+    luaL_openlib(L, 0, Field_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);
+    
+    for (ts = ftenums; ts->str; ts++) {
+        lua_pushstring(L, ts->str);
+        lua_pushstring(L, ts->str);
+        lua_settable(L, LUA_GLOBALSINDEX);
+    }
+    
+    for (b=base_displays;b->str;b++) {
+        lua_pushstring(L, b->str);
+        lua_pushstring(L, b->str);
+        lua_settable(L, LUA_GLOBALSINDEX);
+    }
+    
+    return 1;
+}
+
+
+
+
+/*
+ * FieldArray class
+ */
+
+LUA_CLASS_OPS(FieldArray,FIELD_ARRAY,if (! *p) luaL_error(L,"null FieldArray"));
+
+static int FieldArray_new(lua_State* L) {
+    FieldArray fa = g_array_new(TRUE,TRUE,sizeof(hf_register_info));
+    pushFieldArray(L,fa);
+    return 1;
+}
+
+
+static int FieldArray_add(lua_State* L) {
+    FieldArray fa = checkFieldArray(L,1);
+    Field f = checkField(L,2);
+    hf_register_info hfri = { &(f->hfid), {f->name,f->abbr,f->type,f->base,VALS(f->vs),f->mask,f->blob,HFILL}};
+    
+    g_array_append_val(fa,hfri);
+    
+    return 0;
+}
+
+static int FieldArray_tostring(lua_State* L) {
+    GString* s = g_string_new("FieldArray:\n");
+    hf_register_info* f;
+    FieldArray fa = checkFieldArray(L,1);
+    unsigned i;
+    
+    for(i = 0; i< fa->len; i++) {
+        f = &(((hf_register_info*)(fa->data))[i]);
+        g_string_sprintfa(s,"%i %s %s %s %u %p %.8x %s\n",*(f->p_id),f->hfinfo.name,f->hfinfo.abbrev,ftenum_to_string(f->hfinfo.type),f->hfinfo.display,f->hfinfo.strings,f->hfinfo.bitmask,f->hfinfo.blurb);
+    };
+    
+    lua_pushstring(L,s->str);
+    g_string_free(s,TRUE);
+    
+    return 1;
+}
+
+static int FieldArray_gc(lua_State* L) {
+    FieldArray vs = checkValueString(L,1);
+    
+    g_array_free(vs,TRUE);
+    
+    return 0;
+}
+
+
+static const luaL_reg FieldArray_methods[] = {
+    {"new",   FieldArray_new},
+    {"add",   FieldArray_add},
+    {0,0}
+};
+
+static const luaL_reg FieldArray_meta[] = {
+    {"__gc",       FieldArray_gc},
+    {"__tostring", FieldArray_tostring},
+    {0, 0}
+};
+
+static int FieldArray_register(lua_State* L) {
+    luaL_openlib(L, FIELD_ARRAY, FieldArray_methods, 0);
+    luaL_newmetatable(L, FIELD_ARRAY);
+    luaL_openlib(L, 0, FieldArray_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);
+    
+    return 1;
+}
+
+
+
+
+/*
+ * Ett class
+ */
+
+LUA_CLASS_OPS(Ett,ETT,NOP);
+
+static int Ett_new(lua_State* L) {
+    Ett e = g_malloc(sizeof(int));
+    *e = -1;
+    pushEtt(L,e);
+    
+    return 1;
+}
+
+static int Ett_tostring(lua_State* L) {
+    Ett e = checkEtt(L,1);
+    gchar* s = g_strdup_printf("Ett: %i",*e);
+    
+    lua_pushstring(L,s);
+    g_free(s);
+    
+    return 1;
+}
+
+
+static const luaL_reg Ett_methods[] = {
+    {"new",   Ett_new},
+    {0,0}
+};
+
+static const luaL_reg Ett_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Ett_tostring},
+    {0, 0}
+};
+
+static int Ett_register(lua_State* L) {
+    luaL_openlib(L, ETT, Ett_methods, 0);
+    luaL_newmetatable(L, ETT);
+    luaL_openlib(L, 0, Ett_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);
+    
+    return 1;
+}
+
+
+
+
+
+/*
+ * EttArray class
+ */
+LUA_CLASS_OPS(EttArray,ETT_ARRAY,if (! *p) luaL_error(L,"null EttArray"));
+
+
+static int EttArray_new(lua_State* L) {
+    EttArray ea = g_array_new(TRUE,TRUE,sizeof(gint*));
+    pushEttArray(L,ea);
+    return 1;
+}
+
+
+static int EttArray_add(lua_State* L) {
+    EttArray ea = checkEttArray(L,1);
+    Ett e = checkEtt(L,2);
+    
+    g_array_append_val(ea,e);
+    
+    return 0;
+}
+
+static int EttArray_tostring(lua_State* L) {
+    GString* s = g_string_new("EttArray:\n");
+    EttArray ea = checkEttArray(L,1);
+    unsigned i;
+    
+    for(i = 0; i< ea->len; i++) {
+        gint ett = *(((gint**)(ea->data))[i]);
+        g_string_sprintfa(s,"%i\n",ett);
+    };
+    
+    lua_pushstring(L,s->str);
+    g_string_free(s,TRUE);
+    
+    return 1;
+}
+
+static int EttArray_register_to_ethereal(lua_State* L) {
+    EttArray ea = checkEttArray(L,1);
+    proto_register_subtree_array((gint *const *)ea->data, ea->len);
+    return 0;
+}
+
+static int EttArray_gc(lua_State* L) {
+    EttArray ea = checkEttArray(L,1);
+    
+    g_array_free(ea,FALSE);
+    
+    return 0;
+}
+
+
+static const luaL_reg EttArray_methods[] = {
+    {"new",   EttArray_new},
+    {"add",   EttArray_add},
+    {"register",   EttArray_register_to_ethereal},
+    {0,0}
+};
+
+static const luaL_reg EttArray_meta[] = {
+    {"__gc",       EttArray_gc},
+    {"__tostring", EttArray_tostring},
+    {0, 0}
+};
+
+static int EttArray_register(lua_State* L) {
+    luaL_openlib(L, ETT_ARRAY, EttArray_methods, 0);
+    luaL_newmetatable(L, ETT_ARRAY);
+    luaL_openlib(L, 0, EttArray_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);
+    
+    return 1;
+}
+
+
+/*
+ * Proto class
+ */
+LUA_CLASS_OPS(Proto,PROTO,if (! *p) luaL_error(L,"null Proto"));
+
+static void dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree);
+
+static int Proto_new(lua_State* L) {
+    Proto proto = g_malloc(sizeof(eth_proto_t));
+    
+    proto->hfid = -1;
+    proto->name = g_strdup(luaL_checkstring(L,1));
+    proto->filter = g_strdup(luaL_checkstring(L,2));
+    proto->desc = g_strdup(luaL_checkstring(L,3));
+    proto->hfarray = NULL;
+    proto->prefs_module = NULL;
+    proto->prefs = NULL;
+    proto->handle = NULL;
+    
+    if (proto->name && proto->filter && proto->desc) {
+        if ( proto_get_id_by_filter_name(proto->filter) > 0 ) { 
+            g_free(proto);
+            luaL_error(L,"Protocol exists already");
+            return 0;
+        } else {
+            proto->hfid = proto_register_protocol(proto->desc,proto->name,proto->filter);
+            proto->handle = create_dissector_handle(dissect_lua,proto->hfid);
+            pushProto(L,proto);
+            return 1;
+        }
+     } else {
+         g_free(proto);
+         luaL_error(L,"Missing Parameters");
+         return 0;
+     }
+
+}
+
+static int Proto_register_field_array(lua_State* L) {
+    Proto proto = checkProto(L,1);
+    FieldArray fa = checkFieldArray(L,2);
+    
+    if (proto && fa && fa->len) {
+        if (proto->hfarray) {
+            luaL_error(L,"field array already registered");
+        }
+        
+        proto->hfarray = (hf_register_info*)(fa->data);
+        proto_register_field_array(proto->hfid,proto->hfarray,fa->len);
+        
+    } else {
+        luaL_error(L,"not a good field array");
+    }
+    
+    return 0;
+}
+
+static int Proto_add_uint_pref(lua_State* L) {
+    Proto proto = checkProto(L,1);
+    gchar* abbr = g_strdup(luaL_checkstring(L,2));
+    guint def = (guint)luaL_optint(L,3,0);
+    guint base = (guint)luaL_optint(L,4,10);
+    gchar* name = g_strdup(luaL_optstring (L, 5, ""));
+    gchar* desc = g_strdup(luaL_optstring (L, 6, ""));
+    
+    if (proto && abbr) {
+        eth_pref_t* pref = g_malloc(sizeof(eth_pref_t));
+        pref->name = abbr;
+        pref->type = PREF_UINT;
+        pref->value.u = def;
+        pref->next = NULL;
+        
+        if (! proto->prefs_module)
+            proto->prefs_module = prefs_register_protocol(proto->hfid, NULL);
+        
+        if (! proto->prefs) {
+            proto->prefs = pref;
+        } else {
+            eth_pref_t* p;
+            for (p = proto->prefs; p->next; p = p->next) ;
+            p->next = pref;
+        }
+        
+        prefs_register_uint_preference(proto->prefs_module, abbr,name,
+                                       desc, base, &(pref->value.u));
+        
+    } else {
+        luaL_error(L,"missing a mandatory parameter");
+    }
+    
+    return 0;
+}
+
+static int Proto_add_bool_pref(lua_State* L) {
+    Proto proto = checkProto(L,1);
+    gchar* abbr = g_strdup(luaL_checkstring(L,2));
+    gboolean def = (gboolean)luaL_optint(L,3,FALSE);
+    gchar* name = g_strdup(luaL_optstring (L, 4, ""));
+    gchar* desc = g_strdup(luaL_optstring (L, 5, ""));
+    
+    if (proto && abbr) {
+        eth_pref_t* pref = g_malloc(sizeof(eth_pref_t));
+        pref->name = abbr;
+        pref->type = PREF_BOOL;
+        pref->value.b = def;
+        pref->next = NULL;
+        
+        if (! proto->prefs_module)
+            proto->prefs_module = prefs_register_protocol(proto->hfid, NULL);
+        
+        if (! proto->prefs) {
+            proto->prefs = pref;
+        } else {
+            eth_pref_t* p;
+            for (p = proto->prefs; p->next; p = p->next) ;
+            p->next = pref;
+        }
+        
+        prefs_register_bool_preference(proto->prefs_module, abbr,name,
+                                       desc, &(pref->value.b));
+        
+    } else {
+        luaL_error(L,"missing a mandatory parameter");
+    }
+    
+    return 0;
+}
+
+static int Proto_add_string_pref(lua_State* L) {
+    Proto proto = checkProto(L,1);
+    gchar* abbr = g_strdup(luaL_checkstring(L,2));
+    gchar* def = g_strdup(luaL_optstring (L, 3, ""));
+    gchar* name = g_strdup(luaL_optstring (L, 4, ""));
+    gchar* desc = g_strdup(luaL_optstring (L, 5, ""));
+    
+    if (proto && abbr) {
+        eth_pref_t* pref = g_malloc(sizeof(eth_pref_t));
+        pref->name = abbr;
+        pref->type = PREF_STRING;
+        pref->value.s = def;
+        pref->next = NULL;
+        
+        if (! proto->prefs_module)
+            proto->prefs_module = prefs_register_protocol(proto->hfid, NULL);
+        
+        if (! proto->prefs) {
+            proto->prefs = pref;
+        } else {
+            eth_pref_t* p;
+            for (p = proto->prefs; p->next; p = p->next) ;
+            p->next = pref;
+        }
+        
+        prefs_register_string_preference(proto->prefs_module, abbr,name,
+                                         desc, &(pref->value.s));
+        
+    } else {
+        luaL_error(L,"missing a mandatory parameter");
+    }
+    
+    return 0;
+}
+
+
+static int Proto_get_pref(lua_State* L) {
+    Proto proto = checkProto(L,1);
+    gchar* abbr = g_strdup(luaL_checkstring(L,2));
+    
+    if (! proto || ! abbr) {
+        return 0;
+    }
+    
+    if (proto->prefs) {
+        eth_pref_t* p;
+        for (p = proto->prefs; p; p = p->next) {
+            if (g_str_equal(p->name,abbr)) {
+                switch(p->type) {
+                    case PREF_BOOL:
+                        lua_pushboolean(L, p->value.b);
+                        break;
+                    case PREF_UINT:
+                        lua_pushnumber(L, (lua_Number)(p->value.u));
+                        break;
+                    case PREF_STRING:
+                        lua_pushstring(L, p->value.s);
+                        break;
+                }
+                return 1;
+            }
+        }
+        
+        luaL_error(L,"no such preference");
+        return 0;
+        
+    } else {
+        luaL_error(L,"no preferences");
+        return 0;
+    }
+}
+
+
+static int Proto_set_pref(lua_State* L) {
+    Proto proto = checkProto(L,1);
+    gchar* abbr = g_strdup(luaL_checkstring(L,2));
+    
+    if (! proto || ! abbr) {
+        return 0;
+    }
+    
+    if (proto->prefs) {
+        eth_pref_t* p;
+        for (p = proto->prefs; p; p = p->next) {
+            if (g_str_equal(p->name,abbr)) {
+                switch(p->type) {
+                    case PREF_BOOL:
+                        if (lua_isnumber(L, 3)) {
+                            p->value.b  = lua_toboolean(L, 3);
+                        } else {
+                            p->value.b = TRUE;
+                        }
+                        break;
+                    case PREF_UINT:
+                        p->value.u = (guint32)luaL_checkint(L, 3);
+                        break;
+                    case PREF_STRING:
+                        g_free((void*)p->value.s);
+                        p->value.s = lua_isstring(L, 3) ? g_strdup(lua_tostring(L,3)): g_strdup("");
+                        break;
+                }
+                return 0;
+            }
+        }
+        
+        luaL_error(L,"no such preference");
+        return 0;
+        
+    } else {
+        luaL_error(L,"no preferences");
+        return 0;
+    }
+}
+
+static int Proto_tostring(lua_State* L) { 
+    Proto proto = checkProto(L,1);
+    gchar* s = g_strdup_printf("a Proto: %s",proto->name);
+    lua_pushstring(L,s);
+    g_free(s);
+    
+    return 1;
+}
+
+static const luaL_reg Proto_methods[] = {
+    {"new",   Proto_new},
+    {"register_field_array",   Proto_register_field_array},
+    {"add_uint_pref",   Proto_add_uint_pref},
+    {"add_bool_pref",   Proto_add_bool_pref},
+    {"add_string_pref",   Proto_add_string_pref},
+    {"get_pref",   Proto_get_pref},
+    {"set_pref",   Proto_set_pref},
+    {0,0}
+};
+
+static const luaL_reg Proto_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Proto_tostring},
+    {0, 0}
+};
+
+static int Proto_register(lua_State* L) {
+    luaL_openlib(L, PROTO, Proto_methods, 0);
+    luaL_newmetatable(L, PROTO);
+    luaL_openlib(L, 0, Proto_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);
+    
+    return 1;
+}
+
+
+
+/*
+ * Tvb class
+ */
+
+
+LUA_CLASS_OPS(Tvb,TVB,if (! *p) luaL_error(L,"null tvb"));
+
+static int Tvb_new (lua_State *L) {
+    int len = luaL_optint(L, 3, -1);
+    pushTvb(L, tvb_new_subset( checkTvb(L,1),luaL_optint(L, 2, 0),len, len) );
+    return 1;
+}
+
+
+
+#define TVBGET_FN(type) Tvb_get_ ## type
+
+#define DEFINE_TVBGET(type,len)  static int TVBGET_FN(type) (lua_State *L) { \
+    tvbuff_t* tvb = checkTvb(L,1); \
+    int offset = luaL_checkint(L,2); \
+    if (tvb_offset_exists(tvb, offset+len)) { \
+        lua_pushnumber(L, (lua_Number) tvb_get_ ## type(tvb,offset)); \
+        return 1; \
+    } else { \
+        luaL_error(L,"Out Of Bounds"); \
+        return 0; \
+    } \
+}
+
+
+DEFINE_TVBGET(guint8,1);
+DEFINE_TVBGET(ntohs,2);
+DEFINE_TVBGET(ntoh24,3);
+DEFINE_TVBGET(ntohl,4);
+DEFINE_TVBGET(ntohieee_float,4);
+DEFINE_TVBGET(ntohieee_double,8);
+
+DEFINE_TVBGET(letohs,1);
+DEFINE_TVBGET(letoh24,2);
+DEFINE_TVBGET(letohl,3);
+DEFINE_TVBGET(letohieee_float,4);
+DEFINE_TVBGET(letohieee_double,8);
+
+
+static int Tvb_get_stringz(lua_State* L) {
+    lua_pushstring(L,(gchar*)tvb_get_ephemeral_stringz(checkTvb(L,1),luaL_checkint(L,2),NULL));
+    return 1;
+}
+
+static int Tvb_get_string(lua_State* L) {
+    lua_pushstring(L,(gchar*)tvb_get_ephemeral_string(checkTvb(L,1),luaL_checkint(L,2),luaL_checkint(L,3)));
+   return 1;
+}
+
+static int Tvb_tostring(lua_State* L) {
+    Tvb tvb = checkTvb(L,1);
+    int len = tvb_length(tvb);
+    gchar* str = g_strdup_printf("TVB(%i) : %s",len,tvb_bytes_to_str(tvb,0,len));
+    lua_pushstring(L,str);
+    return 1;
+}
+
+
+
+static int Tvb_len(lua_State* L) {
+    Tvb tvb = checkTvb(L,1);
+    lua_pushnumber(L,tvb_length(tvb));
+    return 1;
+}
+
+
+static const luaL_reg Tvb_methods[] = {
+    {"new",           Tvb_new},
+    {"get_char", TVBGET_FN(guint8)},
+    {"get_ntohs", TVBGET_FN(ntohs)},
+    {"get_ntoh24", TVBGET_FN(ntoh24)},
+    {"get_ntohl", TVBGET_FN(ntohl)},
+    {"get_ntohfloat", TVBGET_FN(ntohieee_float)},
+    {"get_ntohdouble", TVBGET_FN(ntohieee_double)},
+    {"get_letohs", TVBGET_FN(letohs)},
+    {"get_letoh24", TVBGET_FN(letoh24)},
+    {"get_letohl", TVBGET_FN(letohl)},
+    {"get_letohl", TVBGET_FN(letohl)},
+    {"get_letohfloat", TVBGET_FN(letohieee_float)},
+    {"get_letohdouble", TVBGET_FN(letohieee_double)},
+    {"get_stringz", Tvb_get_stringz },
+    {"get_string", Tvb_get_string },
+    {"len", Tvb_len},
+    {0,0}
+};
+
+static const luaL_reg Tvb_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Tvb_tostring},
+    {0, 0}
+};
+
+static int Tvb_register(lua_State* L) {
+    luaL_openlib(L, TVB, Tvb_methods, 0);
+    luaL_newmetatable(L, TVB);
+    luaL_openlib(L, 0, Tvb_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);
+    
+    return 1;
+};
+
+/* Address class */
+
+/* Column class */
+struct col_names_t {
+    const gchar* name;
+    int id;
+};
+
+static const struct col_names_t colnames[] = {
+    {"COL_NUMBER",COL_NUMBER},
+    {"COL_CLS_TIME",COL_CLS_TIME},
+    {"COL_REL_TIME",COL_REL_TIME},
+    {"COL_ABS_TIME",COL_ABS_TIME},
+    {"COL_ABS_DATE_TIME",COL_ABS_DATE_TIME},
+    {"COL_DELTA_TIME",COL_DELTA_TIME},
+    {"COL_DEF_SRC",COL_DEF_SRC},
+    {"COL_RES_SRC",COL_RES_SRC},
+    {"COL_UNRES_SRC",COL_UNRES_SRC},
+    {"COL_DEF_DL_SRC",COL_DEF_DL_SRC},
+    {"COL_RES_DL_SRC",COL_RES_DL_SRC},
+    {"COL_UNRES_DL_SRC",COL_UNRES_DL_SRC},
+    {"COL_DEF_NET_SRC",COL_DEF_NET_SRC},
+    {"COL_RES_NET_SRC",COL_RES_NET_SRC},
+    {"COL_UNRES_NET_SRC",COL_UNRES_NET_SRC},
+    {"COL_DEF_DST",COL_DEF_DST},
+    {"COL_RES_DST",COL_RES_DST},
+    {"COL_UNRES_DST",COL_UNRES_DST},
+    {"COL_DEF_DL_DST",COL_DEF_DL_DST},
+    {"COL_RES_DL_DST",COL_RES_DL_DST},
+    {"COL_UNRES_DL_DST",COL_UNRES_DL_DST},
+    {"COL_DEF_NET_DST",COL_DEF_NET_DST},
+    {"COL_RES_NET_DST",COL_RES_NET_DST},
+    {"COL_UNRES_NET_DST",COL_UNRES_NET_DST},
+    {"COL_DEF_SRC_PORT",COL_DEF_SRC_PORT},
+    {"COL_RES_SRC_PORT",COL_RES_SRC_PORT},
+    {"COL_UNRES_SRC_PORT",COL_UNRES_SRC_PORT},
+    {"COL_DEF_DST_PORT",COL_DEF_DST_PORT},
+    {"COL_RES_DST_PORT",COL_RES_DST_PORT},
+    {"COL_UNRES_DST_PORT",COL_UNRES_DST_PORT},
+    {"COL_PROTOCOL",COL_PROTOCOL},
+    {"COL_INFO",COL_INFO},
+    {"COL_PACKET_LENGTH",COL_PACKET_LENGTH},
+    {"COL_CUMULATIVE_BYTES",COL_CUMULATIVE_BYTES},
+    {"COL_OXID",COL_OXID},
+    {"COL_RXID",COL_RXID},
+    {"COL_IF_DIR",COL_IF_DIR},
+    {"COL_CIRCUIT_ID",COL_CIRCUIT_ID},
+    {"COL_SRCIDX",COL_SRCIDX},
+    {"COL_DSTIDX",COL_DSTIDX},
+    {"COL_VSAN",COL_VSAN},
+    {"COL_TX_RATE",COL_TX_RATE},
+    {"COL_RSSI",COL_RSSI},
+    {"COL_HPUX_SUBSYS",COL_HPUX_SUBSYS},
+    {"COL_HPUX_DEVID",COL_HPUX_DEVID},
+    {"COL_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;
+}
+
+LUA_CLASS_OPS(Column,COLUMN,if (! *p) luaL_error(L,"null column"));
+
+static int Column_tostring(lua_State *L) {
+    Column c = checkColumn(L,1);
+    const gchar* name = col_id_to_name(c->col);
+    lua_pushstring(L,name ? name : "Unknown Column");
+    return 1;
+}
+
+static int Column_clear(lua_State *L) {
+    Column c = checkColumn(L,1);
+    if (check_col(c->cinfo, c->col))
+        col_clear(c->cinfo, c->col);
+    return 0;
+}
+
+static int Column_set(lua_State *L) {
+    Column c = checkColumn(L,1);
+    const gchar* s = luaL_checkstring(L,2);
+    
+    if (check_col(c->cinfo, c->col))
+        col_set_str(c->cinfo, c->col, s);
+    
+    return 0;
+}
+
+static int Column_append(lua_State *L) {
+    Column c = checkColumn(L,1);
+    const gchar* s = luaL_checkstring(L,2);
+    
+    if (check_col(c->cinfo, c->col))
+        col_append_str(c->cinfo, c->col, s);
+    
+    return 0;
+}
+static int Column_preppend(lua_State *L) {
+    Column c = checkColumn(L,1);
+    const gchar* s = luaL_checkstring(L,2);
+    
+    if (check_col(c->cinfo, c->col))
+        col_prepend_fstr(c->cinfo, c->col, "%s",s);
+    
+    return 0;
+}
+
+static int Column_gc(lua_State *L) {
+    Column c = checkColumn(L,1);
+    g_free(c);
+    return 0;
+}
+
+static const luaL_reg Column_methods[] = {
+    {"clear", Column_clear },
+    {"set", Column_set },
+    {"append", Column_append },
+    {"preppend", Column_preppend },
+    {0,0}
+};
+
+
+static const luaL_reg Column_meta[] = {
+    {"__gc", Column_gc },
+    {"__tostring", Column_tostring },
+    {0,0}
+};
+
+
+static int Column_register(lua_State *L) {
+    const struct col_names_t* cn;    
+
+    luaL_openlib(L, COLUMN, Column_methods, 0);
+    luaL_newmetatable(L, COLUMN);
+    luaL_openlib(L, 0, Column_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);
+    
+    for(cn = colnames; cn->name; cn++) {
+        lua_pushstring(L, cn->name);
+        lua_pushstring(L, cn->name);
+        lua_settable(L, LUA_GLOBALSINDEX);
+    }
+
+    return 1;
+}
+
+/* Pinfo class */
+LUA_CLASS_OPS(Pinfo,PINFO,if (! *p) luaL_error(L,"null pinfo"));
+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); 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); if (val) lua_pushstring(L,(const char*)(val)); else lua_pushnil(L); 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_visited,pinfo->fd->flags.visited);
+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_match_port,pinfo->match_port);
+
+
+PINFO_GET_STRING(Pinfo_src,address_to_str(&(pinfo->src)));
+PINFO_GET_STRING(Pinfo_dst,address_to_str(&(pinfo->dst)));
+PINFO_GET_STRING(Pinfo_net_src,address_to_str(&(pinfo->net_src)));
+PINFO_GET_STRING(Pinfo_net_dst,address_to_str(&(pinfo->net_dst)));
+PINFO_GET_STRING(Pinfo_dl_src,address_to_str(&(pinfo->dl_src)));
+PINFO_GET_STRING(Pinfo_dl_dst,address_to_str(&(pinfo->dl_dst)));
+PINFO_GET_STRING(Pinfo_match_string,pinfo->match_string);
+PINFO_GET_STRING(Pinfo_curr_proto,pinfo->current_proto);
+
+static int Pinfo_column(lua_State *L) {
+    Pinfo pinfo = checkPinfo(L,1);
+    Column c = g_malloc(sizeof(*c));
+    
+    c->cinfo = pinfo->cinfo;
+    c->col = col_name_to_id(luaL_checkstring(L,2));
+    
+    pushColumn(L,c);
+    return 1;
+}
+
+static const luaL_reg Pinfo_methods[] = {
+    {"number", Pinfo_number },
+    {"len", Pinfo_len },
+    {"caplen", Pinfo_caplen },
+    {"abs_ts",Pinfo_abs_ts },
+    {"rel_ts",Pinfo_rel_ts },
+    {"delta_ts",Pinfo_delta_ts },
+    {"visited",Pinfo_visited },
+    {"src_address", Pinfo_src },
+    {"dst_address", Pinfo_dst },
+    {"dl_src", Pinfo_dl_src },
+    {"dl_dst", Pinfo_dl_dst },
+    {"net_src", Pinfo_net_src },
+    {"net_dst", Pinfo_net_dst },
+    {"ipproto", Pinfo_ipproto },
+    {"circuit_id", Pinfo_circuit_id },
+    {"ptype", Pinfo_ptype },
+    {"match_port", Pinfo_match_port },
+    {"match_string", Pinfo_match_string },
+    {"curr_proto", Pinfo_curr_proto },
+    {"col", Pinfo_column },
+    {0,0}
+};
+
+static const luaL_reg Pinfo_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Pinfo_tostring},
+    {0, 0}
+};
+
+static int Pinfo_register(lua_State* L) {
+    luaL_openlib(L, PINFO, Pinfo_methods, 0);
+    luaL_newmetatable(L, PINFO);
+    luaL_openlib(L, 0, Pinfo_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);
+    
+    return 1;
+};
+
+/* Tree class */
+LUA_CLASS_OPS(Tree,TREE,NOP);
+LUA_CLASS_OPS(Item,ITEM,NOP);
+
+static int Tree_add_item_any(lua_State *L, gboolean little_endian) {
+    /*
+     called with:
+     tree,field,tvb,offset,len,datum
+     tree,field,tvb,offset,len
+     tree,tvb,offset,len,text
+     tree,tvb,text
+     */
+    Tree tree = checkTree(L,1);
+    Field field;
+    Item item;
+    Tvb tvb;
+    int offset;
+    int len;
+    
+    if (!tree) {
+        pushItem(L,NULL);
+        return 1;
+    }
+    
+    if (( luaL_checkudata (L, 2, TVB) )) {
+        tvb = checkTvb(L,2);
+        const char* str;
+        
+        if (lua_isnumber(L,3)) {
+            offset = luaL_checkint(L,3);
+            len = luaL_checkint(L,4);
+            str = lua_tostring(L,5);
+        } else if (lua_isstring(L,3)) {
+            offset = 0;
+            len = 0;
+            str = lua_tostring(L,3);
+        } else {
+            luaL_error(L,"First arg must be either TVB or Field");
+            return 0;
+        }
+        
+        item = proto_tree_add_text(tree,tvb,offset,len,"%s",str);
+        
+    } else if (( luaL_checkudata (L, 2, FIELD) )) {
+        field = checkField(L,2);
+        tvb = checkTvb(L,3);
+        offset = luaL_checkint(L,4);
+        len = luaL_checkint(L,5);
+        
+        if ( lua_gettop(L) == 6 ) {
+            switch(field->type) {
+                case FT_UINT8:
+                case FT_UINT16:
+                case FT_UINT24:
+                case FT_UINT32:
+                case FT_FRAMENUM:
+                    item = proto_tree_add_uint(tree,field->hfid,tvb,offset,len,(guint32)luaL_checknumber(L,6));
+                    break;
+                case FT_INT8:
+                case FT_INT16:
+                case FT_INT24:
+                case FT_INT32:
+                    item = proto_tree_add_int(tree,field->hfid,tvb,offset,len,(gint32)luaL_checknumber(L,6));
+                    break;
+                case FT_FLOAT:
+                    item = proto_tree_add_float(tree,field->hfid,tvb,offset,len,(float)luaL_checknumber(L,6));
+                    break;
+                case FT_DOUBLE:
+                    item = proto_tree_add_double(tree,field->hfid,tvb,offset,len,(double)luaL_checknumber(L,6));
+                    break;
+                case FT_STRING:
+                case FT_STRINGZ:
+                    item = proto_tree_add_string(tree,field->hfid,tvb,offset,len,luaL_checkstring(L,6));
+                    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;
+            }
+        } else {
+            item = proto_tree_add_item(tree,field->hfid,tvb,offset,len,little_endian);
+        }
+    } else {
+        luaL_error(L,"First arg must be either TVB or Field");
+        return 0;
+    }
+    
+    pushItem(L,item);
+    return 1;
+}
+
+static int Tree_add_item(lua_State *L) { return Tree_add_item_any(L,FALSE); }
+static int Tree_add_item_le(lua_State *L) { return Tree_add_item_any(L,TRUE); }
+
+static int Tree_tostring(lua_State *L) {
+    Tree tree = checkTree(L,1);
+    lua_pushstring(L,ep_strdup_printf("a Tree %p",tree));
+    return 1;
+}
+
+
+static int Tree_get_parent(lua_State *L) {
+    Tree tree = checkTree(L,1);
+    proto_item* item = NULL;
+    
+    if (tree) {
+        item = proto_tree_get_parent(tree);
+    }
+    
+    pushItem(L,item);
+    
+    return 1;
+}
+
+static const luaL_reg Tree_methods[] = {
+    {"add_item",       Tree_add_item},
+    {"add_item_le",       Tree_add_item_le},
+    {"get_parent",       Tree_get_parent},
+    {0, 0}
+};
+
+static const luaL_reg Tree_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Tree_tostring},
+    {0, 0}
+};
+
+static int Tree_register(lua_State* L) {
+    luaL_openlib(L, TREE, Tree_methods, 0);
+    luaL_newmetatable(L, TREE);
+    luaL_openlib(L, 0, Tree_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);
+    
+    return 1;
+}
+
+/* Item class */
+static int Item_tostring(lua_State *L) {
+    Item item = checkItem(L,1);
+    lua_pushstring(L,ep_strdup_printf("an Item %p",item));
+    return 1;
+}
+
+static int Item_add_subtree(lua_State *L) {
+    Item item = checkItem(L,1);
+    Ett ett;
+    
+    if (!item) {
+        pushTree(L,NULL);
+        return 1;
+    }
+    
+    ett = checkEtt(L,2);
+    
+    Tree tree = proto_item_add_subtree(item,*ett);
+    
+    pushTree(L,tree);
+    return 1;
+}
+
+static int Item_set_text(lua_State *L) {
+    Item item = checkItem(L,1);
+    
+    if (!item) {
+        const gchar* s = luaL_checkstring(L,2);
+        proto_item_set_text(item,"%s",s);
+    }
+    
+    return 0;
+}
+
+static int Item_append_text(lua_State *L) {
+    Item item = checkItem(L,1);
+    const gchar* s;
+    
+    if (item) {
+        s = luaL_checkstring(L,2);
+        proto_item_append_text(item,"%s",s);
+    }
+    return 0;
+}
+
+static int Item_set_len(lua_State *L) {
+    Item item = checkItem(L,1);
+    int len;
+
+    if (item) {
+        len = luaL_checkint(L,2);
+        proto_item_set_len(item,len);
+    }
+    
+    return 0;
+}
+
+struct _expert_severity {
+    const gchar* str;
+    int val;
+};
+
+static const struct _expert_severity severities[] = {
+    {"PI_CHAT",PI_CHAT},
+    {"PI_NOTE",PI_NOTE},
+    {"PI_WARN",PI_WARN},
+    {"PI_ERROR",PI_ERROR},
+    {"PI_CHECKSUM",PI_CHECKSUM},
+    {"PI_SEQUENCE",PI_SEQUENCE},
+    {"PI_RESPONSE_CODE",PI_RESPONSE_CODE},
+    {"PI_UNDECODED",PI_UNDECODED},
+    {"PI_REASSEMBLE",PI_REASSEMBLE},
+    {"PI_MALFORMED",PI_MALFORMED},
+    {"PI_DEBUG",PI_DEBUG},
+    {NULL,0}
+};
+
+static int str_to_expert(const gchar* str) {
+    const struct _expert_severity* s;
+
+    if (!str) return 0;
+    
+    for(s = severities; s->str; s++) {
+        if (g_str_equal(str,s->str)) {
+            return s->val;
+        }
+    }
+    return 0;
+}
+
+#if 0
+static const gchar* expert_to_str(int val) {
+    const struct _expert_severity* s;
+    for(s = severities; s->str; s++) {
+        if (s->val == val) {
+            return s->str;
+        }
+    }
+    return NULL;
+}
+#endif
+
+static int Item_set_expert_flags(lua_State *L) {
+    Item item = checkItem(L,1);
+    int group;
+    int severity;
+
+    if (item) {
+        group = str_to_expert(luaL_checkstring(L,2));
+        severity = str_to_expert(luaL_checkstring(L,3));
+
+        if (group && severity) {
+            proto_item_set_expert_flags(item,group,severity);
+        }
+    }
+
+    return 0;
+}
+
+
+static int Item_set_generated(lua_State *L) {
+    Item item = checkItem(L,1);
+    if (item) {
+        PROTO_ITEM_SET_GENERATED(item);
+    }
+    return 0;
+}
+
+
+static int Item_set_hidden(lua_State *L) {
+    Item item = checkItem(L,1);
+    if (item) {
+        PROTO_ITEM_SET_HIDDEN(item);
+    }
+    return 0;
+}
+
+static const luaL_reg Item_methods[] = {
+    {"add_subtree",       Item_add_subtree},
+    {"set_text",       Item_set_text},
+    {"append_text",       Item_append_text},
+    {"set_len",       Item_set_len},
+    {"set_expert_flags",       Item_set_expert_flags},
+    {"set_generated",       Item_set_generated},
+    {"set_hidden",       Item_set_hidden},
+    {0, 0}
+};
+
+static const luaL_reg Item_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Item_tostring},
+    {0, 0}
+};
+
+
+
+static int Item_register(lua_State *L) {
+   const struct _expert_severity* s;
+    
+    luaL_openlib(L, ITEM, Item_methods, 0);
+    luaL_newmetatable(L, ITEM);
+    luaL_openlib(L, 0, Item_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);
+    
+    for(s = severities; s->str; s++) {
+        lua_pushstring(L, s->str);
+        lua_pushstring(L, s->str);
+        lua_settable(L, LUA_GLOBALSINDEX);
+    }
+    
+    return 1;
+}
+
+
+/*
+ * Dissector class
+ */
+LUA_CLASS_OPS(Dissector,DISSECTOR,NOP);
+
+static int Dissector_get (lua_State *L) {
+    const gchar* name = luaL_checkstring(L,1);
+    Dissector d = find_dissector(name);
+    
+    if (d) {
+        pushDissector(L, d);
+        return 1;
+    } else {
+        luaL_error(L,"No such dissector");
+        return 0;
+    }
+    
+}
+
+
+static int Dissector_call(lua_State* L) {
+    Dissector d = checkDissector(L,1);
+    Tvb tvb = checkTvb(L,2);
+    Pinfo pinfo = checkPinfo(L,3);
+    Tree tree = checkTree(L,4);
+    
+    call_dissector(d, tvb, pinfo, tree);
+    return 0;
+}
+
+
+static int Dissector_tostring(lua_State* L) {
+    Dissector d = checkDissector(L,1);
+    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[] = {
+    {"__gc",       No_gc},
+    {"__tostring", Dissector_tostring},
+    {0, 0}
+};
+
+static int Dissector_register(lua_State* L) {
+    luaL_openlib(L, DISSECTOR, Dissector_methods, 0);
+    luaL_newmetatable(L, DISSECTOR);
+    luaL_openlib(L, 0, Dissector_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);
+    
+    return 1;
+};
+
+
+
+
+
+
+/*
+ * DissectorTable class
+ */
+LUA_CLASS_OPS(DissectorTable,DISSECTOR_TABLE,NOP);
+
+static int DissectorTable_new (lua_State *L) {
+    gchar* name = g_strdup(luaL_checkstring(L,1));
+    gchar* ui_name = g_strdup(luaL_optstring(L,2,name));
+    enum ftenum type = get_ftenum(luaL_optstring(L,3,"FT_UINT32"));
+    int base = luaL_optint(L,3,10);
+    
+    switch(type) {
+        case FT_STRING:
+            base = 0;
+        case FT_UINT32:
+        {
+            DissectorTable dt = g_malloc(sizeof(struct _eth_distbl_t));
+
+            dt->table = register_dissector_table(name, ui_name, type, base);
+            dt->name = name;
+            pushDissectorTable(L, dt);
+        }
+            return 1;
+        default:
+            luaL_error(L,"Invalid ft_type");
+            return 0;
+    }
+    
+}
+
+static int DissectorTable_get (lua_State *L) {
+    const gchar* name = luaL_checkstring(L,1);
+    dissector_table_t table = find_dissector_table(name);
+        
+    if (table) {
+        DissectorTable dt = g_malloc(sizeof(struct _eth_distbl_t));
+        dt->table = table;
+        dt->name = g_strdup(name);
+        
+        pushDissectorTable(L, dt);
+        
+        return 1;
+    } else {
+        luaL_error(L,"No such dissector_table");
+        return 0;
+    }
+    
+}
+
+
+static int DissectorTable_add (lua_State *L) {
+    DissectorTable dt = checkDissectorTable(L,1);
+    Proto p = checkProto(L,3);
+    ftenum_t type = get_dissector_table_selector_type(dt->name);
+
+    if (type == FT_STRING) {
+        gchar* pattern = g_strdup(luaL_checkstring(L,2));
+        dissector_add_string(dt->name, pattern,p->handle);
+    } else if ( type == FT_UINT32 ) {
+        int port = luaL_checkint(L, 2);
+        dissector_add(dt->name, port, p->handle);
+    }
+    
+    return 0;
+}
+
+
+static int DissectorTable_try (lua_State *L) {
+    DissectorTable dt = checkDissectorTable(L,1);
+    Tvb tvb = checkTvb(L,3);
+    Pinfo pinfo = checkPinfo(L,4);
+    Tree tree = checkTree(L,5);
+    ftenum_t type = get_dissector_table_selector_type(dt->name);
+
+    if (type == FT_STRING) {
+        const gchar* pattern = luaL_checkstring(L,2);
+        if (dissector_try_string(dt->table,pattern,tvb,pinfo,tree))
+            return 0;
+    } else if ( type == FT_UINT32 ) {
+        int port = luaL_checkint(L, 2);
+        if (dissector_try_port(dt->table,port,tvb,pinfo,tree))
+            return 0;
+    } else {
+        luaL_error(L,"No such type of dissector_table");
+    }
+    
+    call_dissector(data_handle,tvb,pinfo,tree);
+    return 0;
+}
+
+
+static int DissectorTable_get_dissector (lua_State *L) {
+    DissectorTable dt = checkDissectorTable(L,1);
+    ftenum_t type = get_dissector_table_selector_type(dt->name);
+    dissector_handle_t handle = data_handle;
+    
+    if (type == FT_STRING) {
+        const gchar* pattern = luaL_checkstring(L,2);
+        handle = dissector_get_string_handle(dt->table,pattern);
+    } else if ( type == FT_UINT32 ) {
+        int port = luaL_checkint(L, 2);
+        handle = dissector_get_port_handle(dt->table,port);
+    }
+    
+    pushDissector(L,handle);
+
+    return 1;
+
+}
+
+
+static int DissectorTable_tostring(lua_State* L) {
+    DissectorTable dt = checkDissectorTable(L,1);
+    GString* s = g_string_new("DissectorTable ");
+    ftenum_t type =  get_dissector_table_selector_type(dt->name);
+    
+    switch(type) {
+        case FT_STRING:
+        {
+            g_string_sprintfa(s,"%s String:\n",dt->name);
+            break;
+        }
+        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 },
+    {"try", DissectorTable_try },
+    {"get_dissector", DissectorTable_get_dissector },
+    {0,0}
+};
+
+static const luaL_reg DissectorTable_meta[] = {
+    {"__gc",       No_gc},
+    {"__tostring", DissectorTable_tostring},
+    {0, 0}
+};
+
+static int DissectorTable_register(lua_State* L) {
+    luaL_openlib(L, DISSECTOR_TABLE, DissectorTable_methods, 0);
+    luaL_newmetatable(L, DISSECTOR_TABLE);
+    luaL_openlib(L, 0, DissectorTable_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);
+    
+    return 1;
+};
+
+
+
+/* ethereal uses lua */
+
+static void dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) {
+
+    lua_pushstring(L, "_ethereal_tvb");
+    pushTvb(L, tvb);
+    lua_settable(L, LUA_GLOBALSINDEX);
+
+    lua_pushstring(L, "_ethereal_pinfo");
+    pushPinfo(L, pinfo);
+    lua_settable(L, LUA_GLOBALSINDEX);
+
+    lua_pushstring(L, "_ethereal_tree");
+    pushTree(L, tree);
+    lua_settable(L, LUA_GLOBALSINDEX);
+    
+    lua_dostring(L,ep_strdup_printf("dissectors.%s(_ethereal_tvb,_ethereal_pinfo,_ethereal_tree);",pinfo->current_proto));
+    
+}
+
+static void init_lua(void) {
+    if (L)
+        lua_dostring(L, "for k in init_routines do init_routines[k]() end;");
+}
+
+void proto_reg_handoff_lua(void) {
+    data_handle = find_dissector("data");
+    
+    if (L)
+        lua_dostring(L, "for k in handoff_routines do handoff_routines[k]() end ;");
+}
+
+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 void functions_defined_but_unused(void) {
+    toValueString(L,1);
+    toField(L,1);
+    toFieldArray(L,1);
+    toEtt(L,1);
+    toEttArray(L,1);
+    toProto(L,1);
+    toTvb(L,1);
+    toColumn(L,1);
+    toPinfo(L,1);
+    toTree(L,1);
+    toItem(L,1);
+    toDissector(L,1);
+    toDissectorTable(L,1);
+}
+
+void proto_register_lua(void)
+{
+    FILE* file;
+    gchar* filename = getenv("ETHEREAL_LUA_INIT");
+    
+    if (!filename) filename = get_persconffile_path("init.lua", FALSE);
+
+    file = fopen(filename,"r");
+
+    if (! file) return;
+    
+    register_init_routine(init_lua);    
+    
+    L = lua_open();
+    luaopen_base(L);
+    luaopen_table(L);
+    luaopen_io(L);
+    luaopen_string(L);
+    ValueString_register(L);
+    Field_register(L);
+    FieldArray_register(L);
+    Ett_register(L);
+    EttArray_register(L);
+    Tvb_register(L);
+    Proto_register(L);
+    Column_register(L);
+    Pinfo_register(L);
+    Tree_register(L);
+    Item_register(L);
+    Dissector_register(L);
+    DissectorTable_register(L);
+    
+    lua_pushstring(L, "handoff_routines");
+    lua_newtable (L);
+    lua_settable(L, LUA_GLOBALSINDEX);
+    
+    lua_pushstring(L, "init_routines");
+    lua_newtable (L);
+    lua_settable(L, LUA_GLOBALSINDEX);
+    
+    lua_pushstring(L, "dissectors");
+    lua_newtable (L);
+    lua_settable(L, LUA_GLOBALSINDEX);
+    
+    if (lua_load(L,getF,file,filename) || lua_pcall(L,0,0,0))
+        fprintf(stderr,"%s\n",lua_tostring(L,-1));
+    
+    fclose(file);
+    
+}
+
diff --git a/plugins/lua/plugin.c b/plugins/lua/plugin.c
new file mode 100644 (file)
index 0000000..13b2774
--- /dev/null
@@ -0,0 +1,45 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef ENABLE_STATIC
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+
+/* Name of package */
+#define PACKAGE "lua_plugin"
+
+#ifdef VERSION
+#undef VERSION
+#endif
+
+/* Version number of package */
+#define VERSION "0.0.0"
+
+
+#include <gmodule.h>
+#endif
+
+void proto_register_lua(void);
+void proto_reg_handoff_lua(void);
+
+static gboolean initialized = FALSE;
+
+#ifndef ENABLE_STATIC
+G_MODULE_EXPORT const gchar version[] = VERSION;
+
+G_MODULE_EXPORT void plugin_register(void) {
+       
+       if (! initialized ) {
+        proto_register_lua();
+               initialized = 1;
+       }
+}
+
+G_MODULE_EXPORT void plugin_reg_handoff(void)
+{
+    proto_reg_handoff_lua();
+}
+#endif