diff options
author | Sebastien Tandel <sebastien@tandel.be> | 2009-05-29 21:10:40 +0000 |
---|---|---|
committer | Sebastien Tandel <sebastien@tandel.be> | 2009-05-29 21:10:40 +0000 |
commit | 52cc5fb1e86ac8007eabe1291bf543d3803f7148 (patch) | |
tree | 0ee2757e438e9d9db9dd0ddab19f0e84f3f29f03 /epan/wspython | |
parent | cb4f0a40c23a3247fbb74a74dc117cbef4f83bf4 (diff) |
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
Diffstat (limited to 'epan/wspython')
-rw-r--r-- | epan/wspython/Makefile.am | 56 | ||||
-rw-r--r-- | epan/wspython/Makefile.common | 32 | ||||
-rw-r--r-- | epan/wspython/register-dissector.py | 76 | ||||
-rw-r--r-- | epan/wspython/wspy_dissector.py | 392 | ||||
-rw-r--r-- | epan/wspython/wspy_dissectors/homeplug.py.sample | 90 | ||||
-rw-r--r-- | epan/wspython/wspy_libws.py | 48 | ||||
-rw-r--r-- | epan/wspython/wspy_proto.c | 92 | ||||
-rw-r--r-- | epan/wspython/wspy_proto.h | 46 | ||||
-rw-r--r-- | epan/wspython/wspy_register.c | 270 | ||||
-rw-r--r-- | epan/wspython/wspy_register.h | 42 |
10 files changed, 1144 insertions, 0 deletions
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__ */ |