python binding for wireshark (first commit)
authorstandel <standel@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 29 May 2009 21:10:40 +0000 (21:10 +0000)
committerstandel <standel@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 29 May 2009 21:10:40 +0000 (21:10 +0000)
      * ability to write dissectors with python for wireshark.
        documentation (http://wiki.wireshark.org/Python)

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@28529 f5534014-38df-0310-8fa8-9805f1628bb7

17 files changed:
Makefile.am
acinclude.m4
configure.in
epan/Makefile.am
epan/filesystem.c
epan/filesystem.h
epan/proto.c
epan/wspython/Makefile.am [new file with mode: 0644]
epan/wspython/Makefile.common [new file with mode: 0644]
epan/wspython/register-dissector.py [new file with mode: 0644]
epan/wspython/wspy_dissector.py [new file with mode: 0644]
epan/wspython/wspy_dissectors/homeplug.py.sample [new file with mode: 0644]
epan/wspython/wspy_libws.py [new file with mode: 0644]
epan/wspython/wspy_proto.c [new file with mode: 0644]
epan/wspython/wspy_proto.h [new file with mode: 0644]
epan/wspython/wspy_register.c [new file with mode: 0644]
epan/wspython/wspy_register.h [new file with mode: 0644]

index 93bfb2bbffd2573d306b33de6bde0457489c613b..fadf580e4afeaab99ee0e78718cb489c29047a3d 100644 (file)
@@ -25,6 +25,13 @@ ACLOCAL_AMFLAGS = `./aclocal-flags`
 
 INCLUDES= @LUA_INCLUDES@
 
+if HAVE_LIBPY
+py_dissectors_dir = -DPYTHON_DIR=\"@pythondir@\"
+else
+py_dissectors_dir = -DPYTHONDIR=
+endif
+
+
 if HAVE_WARNINGS_AS_ERRORS
 AM_CLEAN_CFLAGS = -Werror
 endif
@@ -319,7 +326,7 @@ wireshark_LDADD = \
        @LIBGNUTLS_LIBS@                \
        @LIBSMI_LDFLAGS@                \
        @PORTAUDIO_LIBS@
-wireshark_CFLAGS = $(AM_CLEAN_CFLAGS)
+wireshark_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 if ENABLE_STATIC
 tshark_LDFLAGS = -Wl,-static -all-static
@@ -349,7 +356,7 @@ tshark_LDADD = \
        @LIBGCRYPT_LIBS@                \
        @LIBGNUTLS_LIBS@                \
        @LIBSMI_LDFLAGS@
-tshark_CFLAGS = $(AM_CLEAN_CFLAGS)
+tshark_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 if ENABLE_STATIC
 rawshark_LDFLAGS = -Wl,-static -all-static
@@ -379,7 +386,7 @@ rawshark_LDADD = \
        @LIBGCRYPT_LIBS@                \
        @LIBGNUTLS_LIBS@                \
        @LIBSMI_LDFLAGS@
-rawshark_CFLAGS = $(AM_CLEAN_CFLAGS)
+rawshark_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Optional objects that I know how to build, and that are needed by
 # text2pcap.
@@ -402,21 +409,21 @@ mergecap_LDADD = \
        wiretap/libwiretap.la           \
        wsutil/libwsutil.la             \
        @GLIB_LIBS@
-mergecap_CFLAGS = $(AM_CLEAN_CFLAGS)
+mergecap_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Libraries with which to link capinfos.
 capinfos_LDADD = \
        wiretap/libwiretap.la           \
        wsutil/libwsutil.la             \
        @GLIB_LIBS@
-capinfos_CFLAGS = $(AM_CLEAN_CFLAGS)
+capinfos_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Libraries with which to link editcap.
 editcap_LDADD = \
        wiretap/libwiretap.la           \
        wsutil/libwsutil.la             \
        @GLIB_LIBS@
-editcap_CFLAGS = $(AM_CLEAN_CFLAGS)
+editcap_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Libraries with which to link randpkt.
 randpkt_LDADD = \
@@ -428,7 +435,7 @@ randpkt_LDADD = \
        @NSL_LIBS@                      \
        @C_ARES_LIBS@                   \
        @ADNS_LIBS@
-randpkt_CFLAGS = $(AM_CLEAN_CFLAGS)
+randpkt_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Libraries and plugin flags with which to link dftest.
 dftest_LDADD = \
@@ -449,7 +456,7 @@ dftest_LDADD = \
        @LIBGCRYPT_LIBS@                \
        @LIBGNUTLS_LIBS@                \
        @LIBSMI_LDFLAGS@
-dftest_CFLAGS = $(AM_CLEAN_CFLAGS)
+dftest_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Libraries with which to link dumpcap.
 dumpcap_LDADD = \
@@ -464,7 +471,7 @@ dumpcap_LDADD = \
        @LIBGCRYPT_LIBS@                \
        @LIBGNUTLS_LIBS@                \
        @LIBCAP_LIBS@
-dumpcap_CFLAGS = $(AM_CLEAN_CFLAGS)
+dumpcap_CFLAGS = $(AM_CLEAN_CFLAGS) $(py_dissectors_dir)
 
 # Common headers
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/wiretap \
index 3f3aa32812781f5b1088b9d7337762c208dab1fb..5136b73de00d3d11a97533e465afdc372989b949 100644 (file)
@@ -1597,4 +1597,57 @@ AC_DEFUN([AC_WIRESHARK_IGE_MAC_INTEGRATION_CHECK],
        LIBS="$ac_save_LIBS"
 ])
 
-
+#
+# AC_WIRESHARK_PYTHON_CHECK
+#
+# Check whether python devel package is present
+#
+AC_DEFUN([AC_WIRESHARK_PYTHON_CHECK],
+  [
+    #
+    # Checking whether we have a python devel environment available
+    #
+#  AC_CACHE_CHECK([checking python devel package], ac_cv_wireshark_python_devel,
+#    [
+    AC_CHECK_PROG([ac_ws_python_config], [python-config], "yes", "no")
+    if test ac_ws_python_config = "no"; then
+      ac_cv_wireshark_python_devel = "no"
+    else
+      AC_MSG_CHECKING([python devel])
+      ac_save_ws_cflags=$CFLAGS
+      ac_save_ws_libs=$LIBS
+      CFLAGS=$(python-config --includes)
+      LIBS=$(python-config --ldflags)
+      AC_COMPILE_IFELSE(
+        [
+          AC_LANG_PROGRAM(
+            [[#include <Python.h>]],
+            [[Py_Initialiaze();]]
+          )
+        ],
+        [
+          #
+          # Compilation successful, we have python devel available
+          #
+          ac_cv_wireshark_python_devel=yes
+          PY_LIBS=$LIBS
+          PY_CFLAGS=$CFLAGS
+          AC_SUBST(PY_LIBS)
+          AC_SUBST(PY_CFLAGS)
+          CFLAGS="$ac_save_ws_cflags"
+          LIBS="$ac_save_ws_libs"
+          AC_DEFINE(HAVE_PYTHON, 1, [Define if python devel package available])
+          AC_MSG_RESULT([yes])
+        ],
+        [
+          #
+          # Compilation unsuccessful, python devel not available
+          #
+          ac_cv_wireshark_python_devel=no
+          CFLAGS=$ac_save_ws_cflags
+          LIBS=$ac_save_ws_libs
+          AC_MSG_RESULT([no])
+        ])
+    fi
+#    ])
+])
index 8a0a395691f810f879ab75a0a9e3bd54b8a19204..8d3c3a132633df6b3d7e5e508fa1f61985a7fffa 100644 (file)
@@ -1353,6 +1353,26 @@ else
 fi
 AC_SUBST(GEOIP_LIBS)
 
+dnl Python devel Check
+AC_ARG_WITH(python,
+    AC_HELP_STRING( [--with-python@<:@=DIR@:>@],
+                    [use python interpretor (installed in DIR, if supplied). @<:@default=no@:>@ (EXPERIMENTAL)]),
+[
+pythondir='${libdir}/wireshark/python/${VERSION}'
+if test "x$withval" = "xno"; then
+  want_python=no
+elif test "x$withval" != "xyes"; then
+  pythondir="$withval"
+  want_python=yes
+  AC_WIRESHARK_PYTHON_CHECK
+else
+  want_python=yes
+  AC_WIRESHARK_PYTHON_CHECK
+fi
+])
+AM_CONDITIONAL(HAVE_LIBPY, test x$want_python = xyes)
+AC_SUBST(pythondir)
+
 #
 # Define WS_VAR_IMPORT appropriately for declarations of external
 # variables exported from dynamically-linked libraries.
@@ -1698,6 +1718,7 @@ AC_OUTPUT(
   epan/dissectors/Makefile
   epan/ftypes/Makefile
   epan/wslua/Makefile
+  epan/wspython/Makefile
   codecs/Makefile
   gtk/Makefile
   gtk/doxygen.cfg
@@ -1764,6 +1785,12 @@ else
        lua_message="no"
 fi
 
+if test "x$want_python" = "xyes"; then
+        python_message="yes"
+else
+        python_message="no"
+fi
+
 if test "x$want_portaudio" = "xyes" ; then
        portaudio_message="yes"
 else
@@ -1823,6 +1850,7 @@ echo ""
 echo "             Install dumpcap setuid : $setuid_message"
 echo "                        Use plugins : $have_plugins"
 echo "                    Use lua library : $lua_message"
+echo "                     python binding : $python_message"
 echo "                   Build rtp_player : $portaudio_message"
 echo "                        Use threads : $enable_threads"
 echo "             Build profile binaries : $enable_profile_build"
index 8e93076d8fa99e5b5bac0593561717112199a44c..aa1d448552eda289b5a9ca1ff5646874432efd8f 100644 (file)
@@ -34,10 +34,21 @@ wslua_dir =
 wslua_dist_dir = wslua
 endif           # HAVE_LIBLUA
 
+if HAVE_LIBPY
+wspython_lib = wspython/libwspython.la
+wspython_dir = wspython
+wspython_dist_dir =
+py_dissectors_dir = -DPYTHON_DIR=\"@pythondir@\"
+else
+wspython_lib =
+wspython_dir =
+wspython_dist_dir = wspython
+py_dissectors_dir = -DPYTHONDIR=
+endif
 
-SUBDIRS = crc crypt ftypes dfilter dissectors $(wslua_dir)
+SUBDIRS = crc crypt ftypes dfilter dissectors $(wslua_dir) $(wspython_dir)
 
-DIST_SUBDIRS = $(SUBDIRS) $(wslua_dist_dir)
+DIST_SUBDIRS = $(SUBDIRS) $(wslua_dist_dir) $(wspython_dist_dir)
 
 ACLOCAL_AMFLAGS = `../aclocal-flags`
 
@@ -63,7 +74,7 @@ endif
 libwireshark_la_SOURCES = \
        $(LIBWIRESHARK_SRC)     \
        $(LIBWIRESHARK_INCLUDES)
-libwireshark_la_CFLAGS = $(AM_NON_GENERATED_CFLAGS)
+libwireshark_la_CFLAGS = $(AM_NON_GENERATED_CFLAGS) $(py_dissectors_dir)
 
 libwireshark_generated_la_SOURCES = \
        $(LIBWIRESHARK_GENERATED_SRC) \
@@ -127,7 +138,7 @@ libwireshark_la_LIBADD = \
        @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ libwireshark_generated.la \
        libwireshark_asmopt.la crc/libcrc.la crypt/libairpdcap.la \
        ftypes/libftypes.la dfilter/libdfilter.la dissectors/libdissectors.la \
-       dissectors/libdirtydissectors.la $(wslua_lib) @SOCKET_LIBS@ @NSL_LIBS@ \
+       dissectors/libdirtydissectors.la $(wslua_lib) $(wspython_lib) @SOCKET_LIBS@ @NSL_LIBS@ \
        @C_ARES_LIBS@ @ADNS_LIBS@ @LIBGCRYPT_LIBS@ @LIBGNUTLS_LIBS@ \
        @KRB5_LIBS@ @SSL_LIBS@ @LIBSMI_LDFLAGS@ @GEOIP_LIBS@ \
        ${top_builddir}/wsutil/libwsutil.la -lm
@@ -136,7 +147,7 @@ libwireshark_la_DEPENDENCIES = \
        @INET_ATON_LO@ @INET_PTON_LO@ @INET_NTOP_LO@ libwireshark_generated.la \
        libwireshark_asmopt.la crc/libcrc.la crypt/libairpdcap.la \
        ftypes/libftypes.la dfilter/libdfilter.la dissectors/libdissectors.la \
-       dissectors/libdirtydissectors.la $(wslua_lib) \
+       dissectors/libdirtydissectors.la $(wslua_lib) $(wspython_lib) \
        ${top_builddir}/wsutil/libwsutil.la
 
 #EXTRA_PROGRAMS = reassemble_test
index 8b899eda0a04dbbd3caf6a69da3d868bba423687..010bddc53aa5875ed9a4939197bd4a2e839e1d5b 100644 (file)
@@ -669,6 +669,102 @@ get_datafile_dir(void)
        return datafile_dir;
 }
 
+#ifdef HAVE_PYTHON
+/*
+ * Find the directory where the python dissectors are stored.
+ *
+ * On Windows, we use the "py_dissector" subdirectory of the datafile directory.
+ *
+ * On UN*X, we use the PLUGIN_DIR value supplied by the configure
+ * script, unless we think we're being run from the build directory,
+ * in which case we use the "py_dissector" subdirectory of the datafile directory.
+ *
+ * In both cases, we then use the subdirectory of that directory whose
+ * name is the version number.
+ *
+ * XXX - if we think we're being run from the build directory, perhaps we
+ * should have the plugin code not look in the version subdirectory
+ * of the plugin directory, but look in all of the subdirectories
+ * of the plugin directory, so it can just fetch the plugins built
+ * as part of the build process.
+ */
+static const char *wspython_dir = NULL;
+
+static void
+init_wspython_dir(void)
+{
+#ifdef _WIN32
+       /*
+        * On Windows, the data file directory is the installation
+        * directory; the python dissectors are stored under it.
+        *
+        * Assume we're running the installed version of Wireshark;
+        * on Windows, the data file directory is the directory
+        * in which the Wireshark binary resides.
+        */
+        wspython_dir = g_strdup_printf("%s\\python\\%s", get_datafile_dir(),
+                                        VERSION);
+
+       /*
+        * Make sure that pathname refers to a directory.
+        */
+       if (test_for_directory(wspython_dir) != EISDIR) {
+               /*
+                * Either it doesn't refer to a directory or it
+                * refers to something that doesn't exist.
+                *
+                * Assume that means we're running a version of
+                * Wireshark we've built in a build directory,
+                * in which case {datafile dir}\python is the
+                * top-level plugins source directory, and use
+                * that directory and set the "we're running in
+                * a build directory" flag, so the plugin
+                * scanner will check all subdirectories of that
+                * directory for python dissectors.
+                */
+               g_free( (gpointer) wspython_dir);
+               wspython_dir = g_strdup_printf("%s\\python", get_datafile_dir());
+               running_in_build_directory_flag = TRUE;
+       }
+#else
+       if (running_in_build_directory_flag) {
+               /*
+                * We're (probably) being run from the build directory and
+                * weren't started with special privileges, so we'll use
+                * the "python" subdirectory of the datafile directory
+                * (the datafile directory is the build directory).
+                */
+               wspython_dir = g_strdup_printf("%s/epan/wspython/", get_datafile_dir());
+       } else {
+               if (getenv("WIRESHARK_PYTHON_DIR") && !started_with_special_privs()) {
+                       /*
+                        * The user specified a different directory for plugins
+                        * and we aren't running with special privileges.
+                        */
+                       wspython_dir = g_strdup(getenv("WIRESHARK_PYTHON_DIR"));
+               } else {
+                       wspython_dir = PYTHON_DIR;
+               }
+       }
+#endif
+}
+#endif /* HAVE_PYTHON */
+
+/*
+ * Get the directory in which the python dissectors are stored.
+ */
+const char *
+get_wspython_dir(void)
+{
+#ifdef HAVE_PYTHON
+       if (!wspython_dir) init_wspython_dir();
+       return wspython_dir;
+#else
+       return NULL;
+#endif
+}
+
+
 #ifdef HAVE_PLUGINS
 /*
  * Find the directory where the plugins are stored.
index 895f956be7bcbb3639460365d21960b80d9d0af2..792209af2e8771f1f6b95ac0708ef466cd9e470a 100644 (file)
@@ -50,6 +50,13 @@ extern const char *get_progfile_dir(void);
  */
 extern const char *get_plugin_dir(void);
 
+/*
+ * Get the directory in which python plugins are stored; this must not be
+ * called before init_progfile_dir() is called, as they might be stored in a
+ * subdirectory of the program file directory.
+ */
+extern const char *get_wspython_dir(void);
+
 /*
  * Get the flag indicating whether we're running from a build
  * directory.
index 632a4e3d40c1166c3227c9c7a5c16a1d38863bef..5b077987ec51b9d3ff0b779265cb895b1eb9d8d3 100644 (file)
@@ -47,6 +47,8 @@
 #include "asm_utils.h"
 #include "column-utils.h"
 
+#include "wspython/wspy_register.h"
+
 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
 #define SUBTREE_MAX_LEVELS 256
 
@@ -357,6 +359,10 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
           handle, and do whatever one-time initialization it needs to
           do. */
        register_all_protocols_func(cb, client_data);
+#ifdef HAVE_PYTHON
+        /* Now scan for python protocols */
+        register_all_py_protocols_func(cb, client_data);
+#endif
 
 #ifdef HAVE_PLUGINS
        /* Now scan for plugins and load all the ones we find, calling
@@ -373,6 +379,11 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
           they need. */
        register_all_handoffs_func(cb, client_data);
 
+#ifdef HAVE_PYTHON
+        /* Now do the same with python dissectors */
+        register_all_py_handoffs_func(cb, client_data);
+#endif
+
 #ifdef HAVE_PLUGINS
        /* Now do the same with plugins. */
        if(cb)
diff --git a/epan/wspython/Makefile.am b/epan/wspython/Makefile.am
new file mode 100644 (file)
index 0000000..f181dab
--- /dev/null
@@ -0,0 +1,56 @@
+# 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.
+
+if HAVE_WARNINGS_AS_ERRORS
+AM_CFLAGS = -Werror
+endif
+
+include Makefile.common
+
+noinst_LTLIBRARIES = libwspython.la
+
+CLEANFILES = \
+       libwspython.a   \
+       libwspython.la  \
+       *~
+
+MAINTAINERCLEANFILES = \
+       Makefile.in
+
+INCLUDES = -I$(srcdir)/../.. -I$(srcdir)/..
+
+libwspython_la_SOURCES = $(LIBWSPYTHON_SRC) $(LIBWSPYTHON_INCLUDES)
+
+libwspython_la_LIBADD = @PY_LIBS@
+libwspython_la_CFLAGS = @PY_CFLAGS@
+
+wspythondir=@pythondir@
+
+wspython_DATA= \
+  register-dissector.py \
+  wspy_dissector.py \
+  wspy_libws.py
+
+
+EXTRA_DIST = \
+       Makefile.common         \
+       Makefile.nmake
diff --git a/epan/wspython/Makefile.common b/epan/wspython/Makefile.common
new file mode 100644 (file)
index 0000000..d743d4a
--- /dev/null
@@ -0,0 +1,32 @@
+# Makefile.common
+#     Contains the stuff from Makefile.am and Makefile.nmake that is
+#     a) common to both files and
+#     b) portable between both files
+#
+# $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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+LIBWSPYTHON_SRC =              \
+       wspy_register.c         \
+       wspy_proto.c
+
+LIBWSPYTHON_INCLUDES =         \
+       wspy_register.h         \
+       wspy_proto.h
diff --git a/epan/wspython/register-dissector.py b/epan/wspython/register-dissector.py
new file mode 100644 (file)
index 0000000..e05bfbc
--- /dev/null
@@ -0,0 +1,76 @@
+# register-dissector.py
+#
+# $Id: $
+#
+# Wireshark Protocol Python Binding
+#
+# Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+# Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+#
+# 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.
+import sys
+import re
+import os
+import imp
+
+#
+# Build a list of files belonging to a directory and matching a regexp (f.e.
+# '(?P<plugin>.*)\.py$' )
+#
+def get_plugin_list(dir, regexp):
+  lDir = os.listdir(dir)
+
+  lPlugins=[]
+  for sDir in lDir:
+    MatchedObject = re.match(regexp, sDir)
+    if (MatchedObject != None):
+      lPlugins.append(MatchedObject.group("plugin"))
+  return lPlugins
+
+#Import the module "name"
+def plugin_import(name):
+  #if the module was already loaded
+  try:
+    return sys.modules[name]
+  except KeyError:
+    pass
+
+  return __import__(name)
+
+def register_dissectors(dir):
+  #append dir to be able to import py_lib
+  sys.path.append(dir)
+  from wspy_libws import get_libws_handle
+  libws = get_libws_handle()
+
+  dissectors_dir = os.path.join(dir, "wspy_dissectors")
+  #append dir to be able to import python dissectors
+  sys.path.append(dissectors_dir)
+
+  registered_protocols = []
+  #Read all python dissectors
+  try:
+    dissectors = get_plugin_list(dissectors_dir, "(?P<plugin>.*)\.py$")
+  #For each dissector, register it and put it in the list of registered
+  #protocols
+    for dissector in dissectors:
+      d = plugin_import(dissector)
+      registered_protocol = d.register_protocol()
+      if registered_protocol:
+        registered_protocols.append(registered_protocol)
+  except Exception, e:
+    print e
+
+  return registered_protocols
diff --git a/epan/wspython/wspy_dissector.py b/epan/wspython/wspy_dissector.py
new file mode 100644 (file)
index 0000000..e44f529
--- /dev/null
@@ -0,0 +1,392 @@
+# wspy_dissector.py
+#
+# $Id: $
+#
+# Wireshark Protocol Python Binding
+#
+# Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+# Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+#
+# 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.
+
+from ctypes import c_int, pointer, POINTER, py_object
+from wspy_libws import get_libws_handle
+
+# From epan/proto.h
+# ? STA ? : is there a better way to include/define these constants?
+# (duplicating definition is not a good thing)
+(BASE_NONE,
+BASE_DEC,
+BASE_HEX,
+BASE_OCT,
+BASE_DEC_HEX,
+BASE_HEX_DEC,
+BASE_CUSTOM) = map(int, xrange(7))
+
+# field types, see epan/ftypes/ftypes.h
+(FT_NONE,
+FT_PROTOCOL,
+FT_BOOLEAN,
+FT_UINT8,
+FT_UINT16,
+FT_UINT24,
+FT_UINT32,
+FT_UINT64,
+FT_INT8,
+FT_INT16,
+FT_INT24,
+FT_INT32,
+FT_INT64,
+FT_FLOAT,
+FT_DOUBLE,
+FT_ABSOLUTE_TIME,
+FT_RELATIVE_TIME,
+FT_STRING,
+FT_STRINGZ,
+FT_EBCDIC,
+FT_UINT_STRING,
+FT_ETHER,
+FT_BYTES,
+FT_UINT_BYTES,
+FT_IPv4,
+FT_IPv6,
+FT_IPXNET,
+FT_FRAMENUM,
+FT_PCRE,
+FT_GUID,
+FT_OID) = map(int, xrange(31))
+
+# hf_register_info from usual dissectors
+class register_info(object):
+  def __init__(self, wsl):
+    self.__protocol = None
+    self.__wsl = wsl
+    self.__hf_register = None
+    self.__registers = []
+
+  def add(self, name, short_desc, \
+          type=FT_UINT32, display=BASE_DEC, \
+          strings=None, bitmask=0x0, desc=None):
+    if not desc:
+      desc = name
+    self.__registers.append( (name, short_desc, \
+          type, display, strings, bitmask, desc) )
+
+  def register(self, protocol):
+    self.__protocol = protocol
+    hf = self.__registers
+    lr = len(hf)
+    if not lr:
+      return None
+
+    self.__hf_register = self.__wsl.hf_register_info_create(lr)
+    chf = self.__hf_register
+    if not self.__hf_register:
+      return None
+
+    for i in xrange(lr):
+      n, sd, t, d, st, bm, ld = hf[i]
+      sdn = sd.replace('.', '_')
+      self.__dict__[sdn] = c_int(-1)
+      p_id = pointer(self.__dict__[sdn])
+      self.__wsl.hf_register_info_add(chf, i, p_id, n , sd, t, d, st, bm, ld)
+
+    self.__wsl.proto_register_field_array(self.__protocol, chf, lr)
+
+  def display(self):
+    self.__wsl.hf_register_info_print(self.__hf_register, \
+                                    len(self.__registers))
+
+  def get(self):
+    return self.__hf_register, len(self.__registers)
+
+  def __del__(self):
+    self.__wsl.hf_register_info_destroy(self.__hf_register)
+
+#Subtrees definition
+#Every subtree added can be accesses as an attribute after having been
+#registered
+class Subtree(object):
+  def __init__(self, wsl, protocol):
+    self.__wsl = wsl
+    self.__protocol = protocol
+    self.__st = {}
+    self.__user_defined_protocol_tree = False
+
+  def add(self, name):
+    if name == self.__protocol:
+      self.__user_defined_protocol_tree = True
+
+    self.__st[name] = c_int(-1)
+
+  def has_user_defined_protocol_tree(self):
+    return self.__user_defined_protocol_tree
+
+  def register(self):
+    if not self.__user_defined_protocol_tree:
+      self.__st[self.__protocol] = c_int(-1)
+
+    ls = len(self.__st)
+    if not ls:
+      return
+
+    CSubtrees = POINTER(c_int) * ls
+    p_sts = CSubtrees()
+    k = self.__st.keys()
+    for i in xrange(ls):
+      p_sts[i] = pointer(self.__st[k[i]])
+
+    self.__wsl.proto_register_subtree_array(p_sts, ls)
+
+  def __getattr__(self, name):
+    if self.__st.has_key(name):
+      return self.__st[name]
+    #raise KeyError
+
+#Dissector class : base class to write a dissector in python
+class Dissector(object):
+  def __init__(self, protocol_name, short_desc, short):
+    self.__protocol_name = protocol_name
+    self.__short_desc = short_desc
+    self.__short = short
+
+    self.__tvb = None
+    self.__pinfo = None
+    self.__tree = None
+
+    self.__Tree = None
+
+    self.__offset = 0
+
+    self.__wsl = get_libws_handle()
+    self.__hf = None
+    self.__subtree = None
+
+  def fields(self):
+    if not self.__hf:
+      self.__hf = register_info(self.__wsl)
+    return self.__hf
+
+  def subtrees(self):
+    if not self.__subtree:
+      self.__subtree = Subtree(self.__wsl, self.__short)
+    return self.__subtree
+
+  def tree(self):
+    if not self.__Tree:
+      self.__Tree = Tree(self.__tree, self)
+    return self.__Tree
+
+  def display(self):
+    print self.__short
+
+  def __str__(self):
+    # STA TODO : keep with short_desc because used in the hash table of
+    # dissectors in C code. If it is modified, it won't work anymore
+    return self.__short_desc
+
+  def __unicode__(self):
+    return self.__short
+
+  def __hash__(self):
+    return hash(self.__short)
+
+  def protocol(self):
+    return self.__protocol
+
+  def register_protocol(self):
+    self.__protocol = \
+      self.__wsl.proto_register_protocol( \
+        self.__protocol_name, self.__short_desc, \
+        self.__short)
+    self.__hf.register(self.__protocol)
+    #self.__hf.display()
+    self.__subtree.register()
+
+  def dissect(self):
+    pass
+
+  def pre_dissect(self):
+    self.__tvb = self.__wsl.py_tvbuff()
+    self.__pinfo = self.__wsl.py_pinfo()
+    self.__tree = self.__wsl.py_tree()
+
+    #self.__wsl.print_current_proto(py_object(pinfo))
+    subt = self.subtrees()
+    try:
+      if not subt.has_user_defined_protocol_tree():
+        tree = self.tree()
+        p_tree = tree.add_item(self.protocol())
+        self.__Tree = p_tree.add_subtree(subt.homeplug)
+    except:
+      print e
+    self.dissect()
+
+  def protocol_ids(self):
+    return [ (None, 0, None) ]
+
+  def create_dissector_handle(self, protocol=None):
+    gdissector = self.__wsl.py_generic_dissector()
+    if not protocol:
+      protocol = self.__protocol
+    return self.__wsl.create_dissector_handle(gdissector, protocol)
+
+  def find_dissector(self, protocol):
+    return self.__wsl.find_dissector(protocol)
+
+  def register_handoff(self):
+    #TODO STA : think how we would use dissector_add in an easy way *and* with
+    #the possibility to add the same dissector for TCP and UDP (extend
+    #py_generic_dissector)
+    private_handle = None
+    try:
+      ids = self.protocol_ids()
+      for type, protocol_id, handle in self.protocol_ids():
+        if not type:
+          continue
+        if not handle:
+          if not private_handle:
+            handle = \
+              self.create_dissector_handle(self.__protocol)
+          else:
+            handle = private_handle
+        self.__wsl.dissector_add(type, protocol_id, handle)
+    except Exception, e:
+      print "creating dissector failed", e
+      raise
+
+  def advance(self, step):
+    self.__offset += step
+
+  def offset(self):
+    return self.__offset
+
+  def _wsl(self):
+    return self.__wsl
+
+  def _tvb(self):
+    return self.__tvb
+
+#Tree class implementation
+#see proto.h
+class Tree(object):
+  def __init__(self, tree, dissector):
+    self.__dissector = dissector
+    self.__tree = tree
+    self.__wsl = dissector._wsl()
+    self.__tvb = dissector._tvb()
+
+  def add_item(self, field, offset=0, length=-1, little_endian=False, adv=True):
+    '''add an item to the tree'''
+    try:
+      tree = self.__wsl.proto_tree_add_item(self.__tree, \
+        field, self.__tvb, self.__dissector.offset(), length, \
+        little_endian)
+    except Exception, e:
+      print e
+    else:
+      if length > 0 and adv:
+        self.__dissector.advance(length)
+      return Tree(tree, self.__dissector)
+
+  def add_uint(self, field, value, offset=0, length=4, adv=True):
+    '''add unsigned integer to the tree'''
+    try:
+      tree = self.__wsl.proto_tree_add_uint(self.__tree, field, self.__tvb, self.__dissector.offset(), length, value)
+    except Exception, e:
+      print e
+    else:
+      if adv:
+        self.__dissector.advance(length)
+      return Tree(tree, self.__dissector)
+
+  def add_text(self, string, offset=0, length=-1, adv=True):
+    '''add text to the tree'''
+    try:
+      tree = self.__wsl.proto_tree_add_text(self.__tree, self.__tvb, self.__dissector.offset(), length, string)
+    except Exception, e:
+      print e
+    else:
+      if length > 0 and adv:
+        self.__dissector.advance(length)
+      return Tree(tree, self.__dissector)
+
+  def add_subtree(self, subtree):
+    '''add a subtree to the tree'''
+    try:
+      tree = self.__wsl.proto_item_add_subtree(self.__tree, subtree)
+    except Exception, e:
+      print e
+    else:
+      return Tree(tree, self.__dissector)
+
+#tvb class implementation
+#see proto.h
+class TVB(object):
+  def __init__(self, wsl, tvb, dissector):
+    self.__tvb = tvb
+    self.__wsl = wsl
+    self.__dissector = dissector
+
+  def length(self):
+    return self.__wsl.length(self.__wsl)
+
+  def length_remaining(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_length_remaining(self.__tvb, offset)
+
+  def reported_length(self):
+    return self.__wsl.tvb_reported_length(self.__tvb)
+
+  def reported_length_remaining(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_length_remaining(self.__tvb, offset)
+
+  def get_guint8(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_get_guint8(self.__tvb)
+
+  def get_ntohs(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_get_ntohs(self.__tvb, offset)
+
+  def get_ntohl(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_get_ntohl(self.__tvb, offset)
+
+  def get_letohl(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_get_letohl(self.__tvb, offset)
+
+  def get_letohs(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_get_letohs(self.__tvb, offset)
+
+  #STA TODO : check that we can do that
+  def get_ptr(self, offset=-1):
+    if offset < 0:
+      offset = self.__dissector.offset()
+    return self.__wsl.tvb_get_ptr(self.__tvb, offset)
+
+  #how to get this working ??? check how application uses this!
+  #def new_subset(self, offset=0):
+  #  return self.__wsl.tvb_get_new_subset(self.tvb, offset)
diff --git a/epan/wspython/wspy_dissectors/homeplug.py.sample b/epan/wspython/wspy_dissectors/homeplug.py.sample
new file mode 100644 (file)
index 0000000..d12a29c
--- /dev/null
@@ -0,0 +1,90 @@
+from wspy_dissector import Dissector
+from wspy_dissector import FT_UINT8, FT_NONE
+from wspy_dissector import BASE_NONE, BASE_HEX
+
+class homeplug(Dissector):
+  # return the two first parameters of dissector_add as a tuple
+  def protocol_ids(self):
+    #you could use self.find_dissector() or self.create_dissector_handle() as
+    #defined in proto.h and pass the result in the third element of the tuple
+    #returned
+    return [ ("ethertype", 0x887B, None) ]
+
+  #Main default entry point of dissection
+  def dissect(self):
+    self.dissect_mctrl()
+    self.dissect_mehdr()
+    self.dissect_melen()
+
+  def dissect_mctrl(self):
+    self.hf = self.fields()
+    self.subt = self.subtrees()
+    self.c_tree = self.tree()
+    try:
+      tree = self.c_tree.add_item(self.hf.homeplug_mctrl, length=1, adv=False)
+      mctrl_tree = tree.add_subtree(self.subt.mctrl)
+
+      mctrl_tree.add_item(self.hf.homeplug_mctrl_rsvd, length=1, adv=False)
+      mctrl_tree.add_item(self.hf.homeplug_mctrl_ne, length=1)
+    except Exception, e:
+      print e
+
+  def dissect_mehdr(self):
+    try:
+      tree = self.c_tree.add_item(self.hf.homeplug_mehdr, length=1, adv=False)
+      mehdr_tree = tree.add_subtree(self.subt.mehdr)
+
+      mehdr_tree.add_item(self.hf.homeplug_mehdr_mev, length=1, adv=False)
+      mehdr_tree.add_item(self.hf.homeplug_mehdr_metype, length=1)
+    except Exception, e:
+      print e
+
+  def dissect_melen(self):
+    try:
+      self.c_tree.add_item(self.hf.homeplug_melen, length=1)
+    except Exception, e:
+      print e
+
+  def dissect_mme(self):
+    try:
+      self.c_tree.add_item(self.hf.homeplug_mme, length=1)
+    except Exception, e:
+      print e
+
+
+HOMEPLUG_MCTRL_RSVD   = 0x80
+HOMEPLUG_MCTRL_NE     = 0x7F
+HOMEPLUG_MEHDR_MEV    = 0xE0
+HOMEPLUG_MEHDR_METYPE = 0x1F
+
+def register_protocol():
+  tp = homeplug("HomePlug protocol", "HomePlug", "homeplug")
+
+  #
+  # Register Protocol Fields
+  #
+  hf = tp.fields()
+  # MAC Control Field
+  hf.add("Mac Control Field", "homeplug.mctrl", FT_NONE, BASE_NONE)
+  hf.add("Reserved", "homeplug.mctrl.rsvd", FT_UINT8, bitmask=HOMEPLUG_MCTRL_RSVD)
+  hf.add("Number of MAC Data Entries", "homeplug.mctrl.ne", FT_UINT8, bitmask=HOMEPLUG_MCTRL_NE)
+
+  # MAC Entry Header
+  hf.add("MAC Management Entry Header", "homeplug.mehdr", FT_NONE, BASE_NONE)
+  hf.add("MAC Entry Version", "homeplug.mehdr.mev", FT_UINT8, bitmask=HOMEPLUG_MEHDR_MEV)
+  hf.add("MAC Entry Type", "homeplug.mehdr.metype", FT_UINT8, BASE_HEX, bitmask=HOMEPLUG_MEHDR_METYPE)
+
+  # MAC Entry Len
+  hf.add("MAC Management Entry Length", "homeplug.melen", FT_UINT8)
+
+  # MAC Management Entry
+  hf.add("MAC Management Entry Data", "homeplug.mmentry", FT_UINT8)
+
+  #
+  # Register Subtrees
+  #
+  subt = tp.subtrees()
+  #subt.add("homeplug") => we let Dissector output the main tree of this protocol
+  subt.add("mctrl")
+  subt.add("mehdr")
+  return tp
diff --git a/epan/wspython/wspy_libws.py b/epan/wspython/wspy_libws.py
new file mode 100644 (file)
index 0000000..fb9bcf9
--- /dev/null
@@ -0,0 +1,48 @@
+# wspy_libws.py
+#
+# $Id: $
+#
+# Wireshark Protocol Python Binding
+#
+# Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+# Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+#
+# 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.
+
+
+from ctypes import cdll
+import platform
+
+__libwireshark = None
+
+def get_libws_libname():
+  system = platform.system()
+  if system == "Darwin":
+    return 'libwireshark.dylib'
+  elif system == "Windows":
+    return 'libwireshark.dll'
+  else:
+    return 'libwireshark.so'
+
+def get_libws_handle():
+  global __libwireshark
+  try:
+    if not __libwireshark:
+      libname = get_libws_libname()
+      __libwireshark = cdll.LoadLibrary(libname)
+    return __libwireshark
+  except Exception, e:
+    print e
+    return None
diff --git a/epan/wspython/wspy_proto.c b/epan/wspython/wspy_proto.c
new file mode 100644 (file)
index 0000000..5bf673e
--- /dev/null
@@ -0,0 +1,92 @@
+/* wspy_proto.c
+ *
+ * $Id: $
+ *
+ * Wireshark Protocol Python Binding
+ *
+ * Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+ * Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+ *
+ * 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
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+
+#include <glib.h>
+
+#include <stdio.h>
+
+#include "proto.h"
+
+
+hf_register_info *hf_register_info_create(const guint8 size)
+{
+  hf_register_info *hf = g_malloc0(sizeof(hf_register_info) * size);
+
+  /**STA TODO :
+   * if (!hf_register_info)
+   *  raise exception
+   */
+
+  return hf;
+}
+
+void hf_register_info_destroy(hf_register_info *hf)
+{
+  if (hf) {
+    g_free(hf);
+  }
+}
+
+void hf_register_info_add(hf_register_info *hf, guint8 index,
+          int *p_id, const char *name, const char *abbrev,
+          enum ftenum type, int display, const void *strings,
+          guint32 bitmask, const char *blurb)
+{
+  hf[index].p_id = p_id;
+  hf[index].hfinfo.name = name;
+  hf[index].hfinfo.abbrev = abbrev;
+  hf[index].hfinfo.type = type;
+  hf[index].hfinfo.display = display;
+  hf[index].hfinfo.strings = strings;
+  hf[index].hfinfo.bitmask = bitmask;
+  hf[index].hfinfo.blurb = blurb;
+  hf[index].hfinfo.id = 0;
+  hf[index].hfinfo.parent = 0;
+  hf[index].hfinfo.ref_count = 0;
+  hf[index].hfinfo.bitshift = 0;
+  hf[index].hfinfo.same_name_next = NULL;
+  hf[index].hfinfo.same_name_prev = NULL;
+}
+
+void hf_register_info_print(hf_register_info *hf, guint8 size)
+{
+  guint8 c;
+  if (!hf)
+    return;
+
+  for (c = 0; c < size; c++) {
+    printf("%s : %s : %s\n", hf[c].hfinfo.name,
+                             hf[c].hfinfo.abbrev,
+                             hf[c].hfinfo.blurb);
+  }
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/epan/wspython/wspy_proto.h b/epan/wspython/wspy_proto.h
new file mode 100644 (file)
index 0000000..4fafdbc
--- /dev/null
@@ -0,0 +1,46 @@
+/* wspy_proto.h
+ *
+ * $Id: $
+ *
+ * Wireshark Protocol Python Binding
+ *
+ * Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+ * Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+ *
+ * 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 __WS_PY_PROTO_H__
+#define __WS_PY_PROTO_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "config.h"
+
+#ifdef HAVE_PYTHON
+hf_register_info *hf_register_info_create(const guint8 size);
+void hf_register_info_destroy(hf_register_info *hf);
+void hf_register_info_add(hf_register_info *hf, guint8 index,
+          int *p_id, const char *name, const char *abbrev,
+          enum ftenum type, int display, const void *strings,
+          guint32 bitmask, const char *blurb);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WS_PY_PROTO_H__ */
diff --git a/epan/wspython/wspy_register.c b/epan/wspython/wspy_register.c
new file mode 100644 (file)
index 0000000..a6a9b07
--- /dev/null
@@ -0,0 +1,270 @@
+/* wspy_register.c
+ *
+ * $Id: $
+ *
+ * Wireshark Protocol Python Binding
+ *
+ * Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+ * Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+ *
+ * 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
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+
+#include <glib.h>
+
+#include <stdio.h>
+
+#include "epan.h"
+#include "proto.h"
+#include "packet.h"
+#include "tvbuff.h"
+#include "filesystem.h"
+
+/* hash table containing all the registered python dissectors */
+GHashTable * g_py_dissectors=NULL;
+
+/**
+ * Global objects that python method dissect() will get. Avoid to write a
+ * function for each proto_tree*.
+ * Is it the only way to do that? I can't believe it ... think about it
+ */
+tvbuff_t * g_tvb = NULL;
+packet_info * g_pinfo = NULL;
+proto_tree * g_tree = NULL;
+
+
+/* Initialization of the Python Interpreter */
+inline
+void wspy_init()
+{
+  Py_Initialize();
+}
+
+/* Finalization of the Python Interpreter */
+inline
+void wspy_finalize()
+{
+  Py_Finalize();
+}
+
+/*const char * py_dissector_short_desc(PyObject * py_dissector)
+{
+}*/
+
+/**
+ * Returns the __str__ of the python object
+ */
+char * py_dissector_name(PyObject * py_dissector)
+{
+  PyObject * py_object_name;
+
+  assert(py_dissector);
+  py_object_name = PyObject_Str(py_dissector);
+
+  return PyString_AS_STRING(py_object_name);
+}
+
+/**
+ * Register the dissector
+ */
+void py_dissector_register(PyObject * py_dissector, char * py_name, register_cb cb, gpointer client_data)
+{
+//  const char * py_name;
+
+  /* Get the name of the dissector */
+//  py_name = py_dissector_name(py_dissector);
+
+  /* Register dissector in register_cb */
+  if (cb)
+    (*cb)(RA_REGISTER, py_name, client_data);
+
+  /**
+   * Register protocol, fields, subtrees
+   *
+   * Done by calling register method of the object
+   */
+  PyObject_CallMethod(py_dissector, "register_protocol", NULL);
+
+}
+
+const char *get_py_register_file()
+{
+  static const char * wspython_register_file = NULL;
+
+  if (!wspython_register_file) {
+#ifdef _WIN32
+      wspython_register_file = g_strdup_printf("%s\\register-dissector.py", get_wspython_dir());
+#else
+      wspython_register_file = g_strdup_printf("%s/register-dissector.py", get_wspython_dir());
+#endif /* _WIN32 */
+  }
+  return wspython_register_file;
+}
+
+/**
+ * Finds out all the python dissectors and register them
+ */
+void register_all_py_protocols_func(register_cb cb, gpointer client_data)
+{
+  FILE * py_reg;
+  PyObject * global_dict, * main_module, * register_fn;
+  PyObject * py_dissectors, * py_dissector;
+  PyObject * py_args;
+  Py_ssize_t index;
+  void * nothing;
+  char * name;
+  nothing = cb;
+  nothing = client_data;
+
+  /* STA TODO : init only if prefs is enabled */
+  wspy_init();
+
+  /* load the python register module */
+  py_reg = fopen(get_py_register_file(), "r");
+  PyRun_SimpleFile(py_reg, get_py_register_file());
+
+  /* Getting the global symbols from the python register module */
+  main_module = PyImport_AddModule("__main__");
+  global_dict = PyModule_GetDict(main_module);
+
+  /* Get the python register function */
+  register_fn = PyDict_GetItemString(global_dict, "register_dissectors");
+
+  /* Execute the python register function */
+  /* This function returns a sequence of python dissectors objects */
+  py_args = Py_BuildValue("(s)", get_wspython_dir());
+  py_dissectors = PyObject_CallObject(register_fn, py_args);
+  //py_dissectors = PyObject_CallObject(register_fn, NULL);
+
+  /* Check that the py_dissectors is really a sequence */
+  if (!PySequence_Check(py_dissectors)) {
+    printf("not registered ...\n");
+    return;
+  }
+
+  /* intialize the hash table where all the python dissectors are kept */
+  g_py_dissectors = g_hash_table_new(g_str_hash, g_str_equal);
+
+  /**
+   * For each dissector, register it in cb and registers all fields, subtrees,
+   * protocol name, etc ...
+   */
+  for (index = 0; ; index++) {
+    py_dissector = PySequence_GetItem(py_dissectors, index);
+    if (!py_dissector)
+      break;
+    assert(py_dissector);
+
+    name = py_dissector_name(py_dissector);
+    py_dissector_register(py_dissector, name, cb, client_data);
+    g_hash_table_insert(g_py_dissectors, (gpointer*)name, py_dissector);
+  }
+}
+
+tvbuff_t *py_tvbuff()
+{
+  return g_tvb;
+}
+
+packet_info * py_pinfo()
+{
+  return g_pinfo;
+}
+
+proto_tree * py_tree()
+{
+  return g_tree;
+}
+
+/*
+ * Generic Python Dissector
+ *
+ * Search the correct PyObject dissector based on
+ * pinfo->current_proto in the hash table py_dissectors.
+ *
+ * We then call the method "dissect" of this PyObject.
+ */
+void py_dissect(tvbuff_t * tvb, packet_info * pinfo,
+    proto_tree * tree)
+{
+  PyObject * py_dissector;
+
+  //printf("pinfo->current_proto : %s\n", pinfo->current_proto);
+  //NOTE => pinfo->current_proto == "HomePlug"
+
+  g_tree = tree;
+  g_pinfo = pinfo;
+  g_tvb = tvb;
+
+  py_dissector = g_hash_table_lookup(g_py_dissectors, pinfo->current_proto);
+  assert(py_dissector);
+
+  PyObject_CallMethod(py_dissector, "pre_dissect", NULL);
+}
+
+/*
+ * Return the pointer to the generic python dissector
+ *
+ * One could think that it could be a PyCObject but it is a
+ * workaround because ctypes is used and it complains later -not
+ * knowing how to conver the parameter - in the Python code when
+ * calling back a C function with a PyCObject as parameter
+ */
+dissector_t py_generic_dissector()
+{
+  return py_dissect;
+}
+
+struct SRegisterHandoffsForeach {
+  register_cb cb;
+  gpointer client_data;
+};
+
+void register_all_py_handoffs_foreach(gpointer key _U_, gpointer value, gpointer user_data)
+{
+  PyObject * py_dissector = (PyObject *)value;
+  struct SRegisterHandoffsForeach *rhf = (struct SRegisterHandoffsForeach*)user_data;
+
+  /* STA TODO : it's the short_desc field ... not really the filter field! */
+  char * handoff_name = g_strdup_printf("handoff_%s", py_dissector_name(py_dissector));
+
+  if (rhf->cb)
+    (*(rhf->cb))(RA_HANDOFF, handoff_name, rhf->client_data);
+
+  PyObject_CallMethod(py_dissector, "register_handoff", NULL);
+}
+
+/**
+ * Finalize the registration of the python protocol dissectors
+ */
+void
+register_all_py_handoffs_func(register_cb cb, gpointer client_data)
+{
+  struct SRegisterHandoffsForeach rhf;
+
+  rhf.cb = cb;
+  rhf.client_data = client_data;
+
+  g_hash_table_foreach(g_py_dissectors, register_all_py_handoffs_foreach, &rhf);
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/epan/wspython/wspy_register.h b/epan/wspython/wspy_register.h
new file mode 100644 (file)
index 0000000..c52d59a
--- /dev/null
@@ -0,0 +1,42 @@
+/* wspy_register.h
+ *
+ * $Id: $
+ *
+ * Wireshark Protocol Python Binding
+ *
+ * Copyright (c) 2009 by Sebastien Tandel <sebastien [AT] tandel [dot] be>
+ * Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
+ *
+ * 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 __WS_PY_REGISTER_H__
+#define __WS_PY_REGISTER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "config.h"
+
+#ifdef HAVE_PYTHON
+void register_all_py_protocols_func(register_cb cb, gpointer client_data);
+void register_all_py_handoffs_func(register_cb cb, gpointer client_data);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WS_PY_REGISTER_H__ */