summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien Tandel <sebastien@tandel.be>2009-05-29 21:10:40 +0000
committerSebastien Tandel <sebastien@tandel.be>2009-05-29 21:10:40 +0000
commit52cc5fb1e86ac8007eabe1291bf543d3803f7148 (patch)
tree0ee2757e438e9d9db9dd0ddab19f0e84f3f29f03
parentcb4f0a40c23a3247fbb74a74dc117cbef4f83bf4 (diff)
downloadwireshark-52cc5fb1e86ac8007eabe1291bf543d3803f7148.tar.gz
python binding for wireshark (first commit)
* ability to write dissectors with python for wireshark. documentation (http://wiki.wireshark.org/Python) svn path=/trunk/; revision=28529
-rw-r--r--Makefile.am25
-rw-r--r--acinclude.m455
-rw-r--r--configure.in28
-rw-r--r--epan/Makefile.am21
-rw-r--r--epan/filesystem.c96
-rw-r--r--epan/filesystem.h7
-rw-r--r--epan/proto.c11
-rw-r--r--epan/wspython/Makefile.am56
-rw-r--r--epan/wspython/Makefile.common32
-rw-r--r--epan/wspython/register-dissector.py76
-rw-r--r--epan/wspython/wspy_dissector.py392
-rw-r--r--epan/wspython/wspy_dissectors/homeplug.py.sample90
-rw-r--r--epan/wspython/wspy_libws.py48
-rw-r--r--epan/wspython/wspy_proto.c92
-rw-r--r--epan/wspython/wspy_proto.h46
-rw-r--r--epan/wspython/wspy_register.c270
-rw-r--r--epan/wspython/wspy_register.h42
17 files changed, 1372 insertions, 15 deletions
diff --git a/Makefile.am b/Makefile.am
index 93bfb2bbff..fadf580e4a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 \
diff --git a/acinclude.m4 b/acinclude.m4
index 3f3aa32812..5136b73de0 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -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
+# ])
+])
diff --git a/configure.in b/configure.in
index 8a0a395691..8d3c3a1326 100644
--- a/configure.in
+++ b/configure.in
@@ -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"
diff --git a/epan/Makefile.am b/epan/Makefile.am
index 8e93076d8f..aa1d448552 100644
--- a/epan/Makefile.am
+++ b/epan/Makefile.am
@@ -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
diff --git a/epan/filesystem.c b/epan/filesystem.c
index 8b899eda0a..010bddc53a 100644
--- a/epan/filesystem.c
+++ b/epan/filesystem.c
@@ -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.
diff --git a/epan/filesystem.h b/epan/filesystem.h
index 895f956be7..792209af2e 100644
--- a/epan/filesystem.h
+++ b/epan/filesystem.h
@@ -51,6 +51,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.
*/
diff --git a/epan/proto.c b/epan/proto.c
index 632a4e3d40..5b077987ec 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -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
index 0000000000..f181dab5f7
--- /dev/null
+++ b/epan/wspython/Makefile.am
@@ -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
index 0000000000..d743d4a937
--- /dev/null
+++ b/epan/wspython/Makefile.common
@@ -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
index 0000000000..e05bfbcc37
--- /dev/null
+++ b/epan/wspython/register-dissector.py
@@ -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
index 0000000000..e44f529cfe
--- /dev/null
+++ b/epan/wspython/wspy_dissector.py
@@ -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
index 0000000000..d12a29c139
--- /dev/null
+++ b/epan/wspython/wspy_dissectors/homeplug.py.sample
@@ -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
index 0000000000..fb9bcf9916
--- /dev/null
+++ b/epan/wspython/wspy_libws.py
@@ -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
index 0000000000..5bf673e9ce
--- /dev/null
+++ b/epan/wspython/wspy_proto.c
@@ -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
index 0000000000..4fafdbca20
--- /dev/null
+++ b/epan/wspython/wspy_proto.h
@@ -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
index 0000000000..a6a9b0701b
--- /dev/null
+++ b/epan/wspython/wspy_register.c
@@ -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
index 0000000000..c52d59ac67
--- /dev/null
+++ b/epan/wspython/wspy_register.h
@@ -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__ */