mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
Introduce Libvirt Wireshark dissector
Introduce Wireshark dissector plugin which adds support to Wireshark for dissecting libvirt RPC protocol. Added following files to build Wireshark dissector from libvirt source tree. * tools/wireshark/*: Source tree of Wireshark dissector plugin. Added followings to configure.ac or Makefile.am. configure.ac * --with-wireshark-dissector: Enable support for building Wireshark dissector. * --with-ws-plugindir: Specify wireshark plugin directory that dissector will installed. * Added tools/wireshark/{Makefile,src/Makefile} to AC_CONFIG_FILES. Makefile.am * Added tools/wireshark/ to SUBDIR.
This commit is contained in:
parent
a1cbe4b5a9
commit
4f32c5f793
2
.gitignore
vendored
2
.gitignore
vendored
@ -226,6 +226,8 @@
|
||||
/tools/virsh-*-edit.c
|
||||
/tools/virt-*-validate
|
||||
/tools/virt-sanlock-cleanup
|
||||
/tools/wireshark/src/plugin.c
|
||||
/tools/wireshark/src/libvirt
|
||||
/update.log
|
||||
GPATH
|
||||
GRTAGS
|
||||
|
@ -22,7 +22,8 @@ GENHTML = genhtml
|
||||
SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \
|
||||
tests po examples/object-events examples/hellolibvirt \
|
||||
examples/dominfo examples/domsuspend examples/apparmor \
|
||||
examples/xml/nwfilter examples/openauth examples/systemtap
|
||||
examples/xml/nwfilter examples/openauth examples/systemtap \
|
||||
tools/wireshark
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
|
8
cfg.mk
8
cfg.mk
@ -977,10 +977,10 @@ exclude_file_name_regexp--sc_prohibit_newline_at_end_of_diagnostic = \
|
||||
^src/rpc/gendispatch\.pl$$
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_nonreentrant = \
|
||||
^((po|tests)/|docs/.*(py|html\.in)|run.in$$)
|
||||
^((po|tests)/|docs/.*(py|html\.in)|run.in$$|tools/wireshark/util/genxdrstub\.pl$$)
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_raw_allocation = \
|
||||
^(docs/hacking\.html\.in)|(src/util/viralloc\.[ch]|examples/.*|tests/securityselinuxhelper\.c|tests/vircgroupmock\.c)$$
|
||||
^(docs/hacking\.html\.in)|(src/util/viralloc\.[ch]|examples/.*|tests/securityselinuxhelper\.c|tests/vircgroupmock\.c|tools/wireshark/src/packet-libvirt.c)$$
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_readlink = \
|
||||
^src/(util/virutil|lxc/lxc_container)\.c$$
|
||||
@ -988,7 +988,7 @@ exclude_file_name_regexp--sc_prohibit_readlink = \
|
||||
exclude_file_name_regexp--sc_prohibit_setuid = ^src/util/virutil\.c$$
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_sprintf = \
|
||||
^(docs/hacking\.html\.in)|(examples/systemtap/.*stp)|(src/dtrace2systemtap\.pl)|(src/rpc/gensystemtap\.pl)$$
|
||||
^(docs/hacking\.html\.in)|(examples/systemtap/.*stp)|(src/dtrace2systemtap\.pl)|(src/rpc/gensystemtap\.pl)|(tools/wireshark/util/genxdrstub\.pl)$$
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_strncpy = ^src/util/virstring\.c$$
|
||||
|
||||
@ -1021,7 +1021,7 @@ exclude_file_name_regexp--sc_correct_id_types = \
|
||||
exclude_file_name_regexp--sc_m4_quote_check = m4/virt-lib.m4
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_include_public_headers_quote = \
|
||||
^src/internal\.h$$
|
||||
^(src/internal\.h$$|tools/wireshark/src/packet-libvirt.h$$)
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_include_public_headers_brackets = \
|
||||
^(tools/|examples/|include/libvirt/(virterror|libvirt-(qemu|lxc))\.h$$)
|
||||
|
72
configure.ac
72
configure.ac
@ -2502,6 +2502,70 @@ AM_CONDITIONAL([HAVE_LIBNL], [test "$have_libnl" = "yes"])
|
||||
AC_SUBST([LIBNL_CFLAGS])
|
||||
AC_SUBST([LIBNL_LIBS])
|
||||
|
||||
dnl wireshark dissector
|
||||
|
||||
AC_ARG_WITH([wireshark-dissector],
|
||||
[AS_HELP_STRING([--with-wireshark-dissector],
|
||||
[enable wireshark dissector plugin support @<:@default=check@:>@])],
|
||||
[ with_wireshark_dissector=$withval ],
|
||||
[ with_wireshark_dissector=check ])
|
||||
|
||||
AC_DEFUN([LIBVIRT_WS_HANDLE_ERROR], [
|
||||
if test "$with_wireshark_dissector" = "yes"; then
|
||||
AC_MSG_ERROR([$1])
|
||||
else
|
||||
with_wireshark_dissector=no
|
||||
fi
|
||||
])
|
||||
if test "$with_wireshark_dissector" != "no"; then
|
||||
dnl Check for XDR headers existence
|
||||
AC_CHECK_HEADERS([rpc/types.h])
|
||||
|
||||
dnl Check for glib-2.0 existence
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0], [
|
||||
WS_DISSECTOR_CPPFLAGS="$WS_DISSECTOR_CPPFLAGS `$PKG_CONFIG --cflags glib-2.0`"
|
||||
], [
|
||||
LIBVIRT_WS_HANDLE_ERROR([pkg-config 'glib-2.0' is required for wireshark-dissector support])
|
||||
])
|
||||
|
||||
dnl Search for wireshark(or tshark) command
|
||||
AC_PATH_PROG([WIRESHARK], [wireshark])
|
||||
AC_PATH_PROG([WIRESHARK], [tshark])
|
||||
if test -z "$WIRESHARK"; then
|
||||
LIBVIRT_WS_HANDLE_ERROR([command not found wireshark or tshark])
|
||||
else
|
||||
dnl Check for wireshark headers
|
||||
save_CPPFLAGS="$CPPFLAGS"
|
||||
WS_DISSECTOR_CPPFLAGS="$WS_DISSECTOR_CPPFLAGS -I`dirname $WIRESHARK`/../include/wireshark"
|
||||
CPPFLAGS="$CPPFLAGS $WS_DISSECTOR_CPPFLAGS"
|
||||
AC_CHECK_HEADERS([wireshark/config.h],, [
|
||||
LIBVIRT_WS_HANDLE_ERROR([wireshark/config.h is required for wireshark-dissector support])
|
||||
])
|
||||
AC_CHECK_HEADERS([wireshark/epan/packet.h wireshark/epan/dissectors/packet-tcp.h],, [
|
||||
LIBVIRT_WS_HANDLE_ERROR([wireshark/epan/{packet,packet-tcp}.h are required for wireshark-dissector support])
|
||||
], [
|
||||
#include <wireshark/config.h>
|
||||
])
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
fi
|
||||
if test "$with_wireshark_dissector" != "no"; then
|
||||
with_wireshark_dissector=yes
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([WS_DISSECTOR_CPPFLAGS])
|
||||
AM_CONDITIONAL([WITH_WIRESHARK_DISSECTOR], [test "$with_wireshark_dissector" = "yes"])
|
||||
|
||||
AC_ARG_WITH([ws-plugindir],
|
||||
[AS_HELP_STRING([--with-ws-plugindir],
|
||||
[wireshark plugins directory that plugin will installed])],
|
||||
[ ws_plugindir=$withval ])
|
||||
|
||||
if test "$with_wireshark_dissector" != "no" && test -z "$ws_plugindir"; then
|
||||
ws_version=`$WIRESHARK -v | head -1 | cut -f 2 -d' '`
|
||||
ws_plugindir=`dirname $WIRESHARK`/../lib/wireshark/plugins/$ws_version
|
||||
fi
|
||||
AC_SUBST([ws_plugindir])
|
||||
|
||||
# Check for Linux vs. BSD ifreq members
|
||||
AC_CHECK_MEMBERS([struct ifreq.ifr_newname,
|
||||
struct ifreq.ifr_ifindex,
|
||||
@ -2585,7 +2649,9 @@ AC_CONFIG_FILES([\
|
||||
examples/openauth/Makefile \
|
||||
examples/hellolibvirt/Makefile \
|
||||
examples/systemtap/Makefile \
|
||||
examples/xml/nwfilter/Makefile])
|
||||
examples/xml/nwfilter/Makefile \
|
||||
tools/wireshark/Makefile \
|
||||
tools/wireshark/src/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE([])
|
||||
@ -2746,6 +2812,10 @@ AC_MSG_NOTICE([ XML Catalog: $XML_CATALOG_FILE])
|
||||
AC_MSG_NOTICE([ Init script: $with_init_script])
|
||||
AC_MSG_NOTICE([Char device locks: $with_chrdev_lock_files])
|
||||
AC_MSG_NOTICE([])
|
||||
AC_MSG_NOTICE([Developer Tools])
|
||||
AC_MSG_NOTICE([])
|
||||
AC_MSG_NOTICE([Wireshark dissector: $with_wireshark_dissector])
|
||||
AC_MSG_NOTICE([])
|
||||
AC_MSG_NOTICE([Privileges])
|
||||
AC_MSG_NOTICE([])
|
||||
AC_MSG_NOTICE([ QEMU: $QEMU_USER:$QEMU_GROUP])
|
||||
|
22
tools/wireshark/Makefile.am
Normal file
22
tools/wireshark/Makefile.am
Normal file
@ -0,0 +1,22 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
# Copyright (C) 2013 Yuto KAWAMURA(kawamuray) <kawamuray.dadada@gmail.com>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author: Yuto KAWAMURA(kawamuray)
|
||||
if WITH_WIRESHARK_DISSECTOR
|
||||
SUBDIRS = src
|
||||
endif WITH_WIRESHARK_DISSECTOR
|
31
tools/wireshark/README.md
Normal file
31
tools/wireshark/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
About
|
||||
=====
|
||||
This is the project of Google Summer of Code 2013 accepted by QEMU.org and
|
||||
libvirt community. The goal of this project is, provide Wireshark dissector for
|
||||
Libvirt RPC protocol. It will provide Libvirt packet overview/detail analysing
|
||||
in Wireshark. Furthermore, it will be able to build(generated) from RPC protocol
|
||||
definition placed in Libvirt source tree to support latest protocol
|
||||
specification.
|
||||
|
||||
See also:
|
||||
- http://www.google-melange.com/gsoc/project/google/gsoc2013/kawamuray/7001
|
||||
- http://wiki.qemu.org/Features/LibvirtWiresharkDissector
|
||||
|
||||
Installation
|
||||
=============
|
||||
Run ./configure with --with-wireshark-dissector option enabled.
|
||||
Then dissector will compiled with libvirt itself.
|
||||
|
||||
Add/Remove protocol from dissector's support
|
||||
--------------------------------------------
|
||||
Modify variable WS\_DISSECTOR\_PROTO\_FILES in tools/wireshark/src/Makefile.am.
|
||||
|
||||
Changing installation directory
|
||||
-------------------------------
|
||||
You can change installation directory of pluggable shared object(libvirt.so) by
|
||||
specifying --with-ws-plugindir=<path>.
|
||||
|
||||
You can install libvirt.so into your local wireshark plugin directory:
|
||||
|
||||
./configure --with-wireshark-dissector \
|
||||
--with-ws-plugindir=$HOME/.wireshark/plugins
|
42
tools/wireshark/src/Makefile.am
Normal file
42
tools/wireshark/src/Makefile.am
Normal file
@ -0,0 +1,42 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
# Copyright (C) 2013 Yuto KAWAMURA(kawamuray) <kawamuray.dadada@gmail.com>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Author: Yuto KAWAMURA(kawamuray)
|
||||
ws_plugin_LTLIBRARIES = libvirt.la
|
||||
libvirt_la_SOURCES = packet-libvirt.c plugin.c
|
||||
libvirt_la_CPPFLAGS = $(WS_DISSECTOR_CPPFLAGS)
|
||||
libvirt_la_LDFLAGS = -avoid-version -module
|
||||
|
||||
packet-libvirt.c: packet-libvirt.h libvirt/protocol.h
|
||||
|
||||
plugin.c: packet-libvirt.c
|
||||
$(srcdir)/../util/make-dissector-reg . plugin $<
|
||||
|
||||
WS_DISSECTOR_PROTO_FILES = \
|
||||
$(top_srcdir)/src/remote/remote_protocol.x \
|
||||
$(top_srcdir)/src/remote/qemu_protocol.x \
|
||||
$(top_srcdir)/src/remote/lxc_protocol.x \
|
||||
$(top_srcdir)/src/rpc/virkeepaliveprotocol.x
|
||||
|
||||
libvirt/protocol.h: $(srcdir)/../util/genxdrstub.pl $(WS_DISSECTOR_PROTO_FILES)
|
||||
$(MKDIR_P) libvirt
|
||||
LIBVIRT_VERSION=$(LIBVIRT_VERSION) \
|
||||
$(PERL) $(srcdir)/../util/genxdrstub.pl $(WS_DISSECTOR_PROTO_FILES)
|
||||
|
||||
clean-local:
|
||||
-rm -rf libvirt plugin.c
|
520
tools/wireshark/src/packet-libvirt.c
Normal file
520
tools/wireshark/src/packet-libvirt.c
Normal file
@ -0,0 +1,520 @@
|
||||
/* packet-libvirt.c --- Libvirt packet dissector routines.
|
||||
*
|
||||
* Copyright (C) 2013 Yuto KAWAMURA(kawamuray) <kawamuray.dadada@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Michal Privoznik <mprivozn redhat com>
|
||||
* Yuto KAWAMURA(kawamuray) <kawamuray.dadada gmail.com>
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <wireshark/config.h>
|
||||
#include <wireshark/epan/proto.h>
|
||||
#include <wireshark/epan/packet.h>
|
||||
#include <wireshark/epan/dissectors/packet-tcp.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#ifdef HAVE_RPC_TYPES_H
|
||||
# include <rpc/types.h>
|
||||
#endif
|
||||
#include <rpc/xdr.h>
|
||||
#include "packet-libvirt.h"
|
||||
|
||||
static int proto_libvirt = -1;
|
||||
static int hf_libvirt_length = -1;
|
||||
static int hf_libvirt_program = -1;
|
||||
static int hf_libvirt_version = -1;
|
||||
static int hf_libvirt_procedure = -1;
|
||||
static int hf_libvirt_type = -1;
|
||||
static int hf_libvirt_serial = -1;
|
||||
static int hf_libvirt_status = -1;
|
||||
static int hf_libvirt_stream = -1;
|
||||
static int hf_libvirt_num_of_fds = -1;
|
||||
static int hf_libvirt_unknown = -1;
|
||||
static gint ett_libvirt = -1;
|
||||
|
||||
#define XDR_PRIMITIVE_DISSECTOR(xtype, ctype, ftype) \
|
||||
static gboolean \
|
||||
dissect_xdr_##xtype(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf) \
|
||||
{ \
|
||||
goffset start; \
|
||||
ctype val; \
|
||||
start = xdr_getpos(xdrs); \
|
||||
if (xdr_##xtype(xdrs, &val)) { \
|
||||
proto_tree_add_##ftype(tree, hf, tvb, start, xdr_getpos(xdrs) - start, val); \
|
||||
return TRUE; \
|
||||
} else { \
|
||||
proto_tree_add_item(tree, hf_libvirt_unknown, tvb, start, -1, ENC_NA); \
|
||||
return FALSE; \
|
||||
} \
|
||||
}
|
||||
|
||||
XDR_PRIMITIVE_DISSECTOR(int, gint32, int)
|
||||
XDR_PRIMITIVE_DISSECTOR(u_int, guint32, uint)
|
||||
XDR_PRIMITIVE_DISSECTOR(short, gint16, int)
|
||||
XDR_PRIMITIVE_DISSECTOR(u_short, guint16, uint)
|
||||
XDR_PRIMITIVE_DISSECTOR(char, gchar, int)
|
||||
XDR_PRIMITIVE_DISSECTOR(u_char, guchar, uint)
|
||||
XDR_PRIMITIVE_DISSECTOR(hyper, gint64, int64)
|
||||
XDR_PRIMITIVE_DISSECTOR(u_hyper, guint64, uint64)
|
||||
XDR_PRIMITIVE_DISSECTOR(float, gfloat, float)
|
||||
XDR_PRIMITIVE_DISSECTOR(double, gdouble, double)
|
||||
XDR_PRIMITIVE_DISSECTOR(bool, bool_t, boolean)
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_string(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf,
|
||||
guint32 maxlen)
|
||||
{
|
||||
goffset start;
|
||||
gchar *val = NULL;
|
||||
|
||||
start = xdr_getpos(xdrs);
|
||||
if (xdr_string(xdrs, &val, maxlen)) {
|
||||
proto_tree_add_string(tree, hf, tvb, start, xdr_getpos(xdrs) - start, val);
|
||||
xdr_free((xdrproc_t)xdr_string, (char *)&val);
|
||||
return TRUE;
|
||||
} else {
|
||||
proto_tree_add_item(tree, hf_libvirt_unknown, tvb, start, -1, ENC_NA);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
format_xdr_bytes(guint8 *bytes, guint32 length)
|
||||
{
|
||||
gchar *buf;
|
||||
guint32 i;
|
||||
|
||||
if (length == 0)
|
||||
return "";
|
||||
buf = ep_alloc(length*2 + 1);
|
||||
for (i = 0; i < length; i++) {
|
||||
/* We know that buf has enough size to contain
|
||||
2 * length + '\0' characters. */
|
||||
g_sprintf(buf, "%02x", bytes[i]);
|
||||
buf += 2;
|
||||
}
|
||||
return buf - length*2;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_opaque(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf,
|
||||
guint32 size)
|
||||
{
|
||||
goffset start;
|
||||
gboolean rc;
|
||||
guint8 *val;
|
||||
|
||||
val = g_malloc(size);
|
||||
start = xdr_getpos(xdrs);
|
||||
if ((rc = xdr_opaque(xdrs, (caddr_t)val, size))) {
|
||||
proto_tree_add_bytes_format_value(tree, hf, tvb, start, xdr_getpos(xdrs) - start,
|
||||
NULL, "%s", format_xdr_bytes(val, size));
|
||||
} else {
|
||||
proto_tree_add_item(tree, hf_libvirt_unknown, tvb, start, -1, ENC_NA);
|
||||
}
|
||||
|
||||
g_free(val);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_bytes(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf,
|
||||
guint32 maxlen)
|
||||
{
|
||||
goffset start;
|
||||
guint8 *val = NULL;
|
||||
guint32 length;
|
||||
|
||||
start = xdr_getpos(xdrs);
|
||||
if (xdr_bytes(xdrs, (char **)&val, &length, maxlen)) {
|
||||
proto_tree_add_bytes_format_value(tree, hf, tvb, start, xdr_getpos(xdrs) - start,
|
||||
NULL, "%s", format_xdr_bytes(val, length));
|
||||
/* Seems I can't call xdr_free() for this case.
|
||||
It will raises SEGV by referencing out of bounds call stack */
|
||||
free(val);
|
||||
return TRUE;
|
||||
} else {
|
||||
proto_tree_add_item(tree, hf_libvirt_unknown, tvb, start, -1, ENC_NA);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_pointer(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf,
|
||||
vir_xdr_dissector_t dissect)
|
||||
{
|
||||
goffset start;
|
||||
bool_t not_null;
|
||||
|
||||
start = xdr_getpos(xdrs);
|
||||
if (!xdr_bool(xdrs, ¬_null)) {
|
||||
proto_tree_add_item(tree, hf_libvirt_unknown, tvb, start, -1, ENC_NA);
|
||||
return FALSE;
|
||||
}
|
||||
if (not_null) {
|
||||
return dissect(tvb, tree, xdrs, hf);
|
||||
} else {
|
||||
proto_item *ti;
|
||||
ti = proto_tree_add_item(tree, hf, tvb, start, xdr_getpos(xdrs) - start, ENC_NA);
|
||||
proto_item_append_text(ti, ": (null)");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_iterable(tvbuff_t *tvb, proto_item *ti, XDR *xdrs, gint ett, int rhf,
|
||||
guint32 length, vir_xdr_dissector_t dissect, goffset start)
|
||||
{
|
||||
proto_tree *tree;
|
||||
guint32 i;
|
||||
|
||||
tree = proto_item_add_subtree(ti, ett);
|
||||
for (i = 0; i < length; i++) {
|
||||
if (!dissect(tvb, tree, xdrs, rhf))
|
||||
return FALSE;
|
||||
}
|
||||
proto_item_set_len(ti, xdr_getpos(xdrs) - start);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_vector(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, gint ett,
|
||||
int rhf, gchar *rtype, guint32 size, vir_xdr_dissector_t dissect)
|
||||
{
|
||||
goffset start;
|
||||
proto_item *ti;
|
||||
|
||||
start = xdr_getpos(xdrs);
|
||||
ti = proto_tree_add_item(tree, hf, tvb, start, -1, ENC_NA);
|
||||
proto_item_append_text(ti, " :: %s[%u]", rtype, size);
|
||||
return dissect_xdr_iterable(tvb, ti, xdrs, ett, rhf, size, dissect, start);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dissect_xdr_array(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, gint ett,
|
||||
int rhf, gchar *rtype, guint32 maxlen, vir_xdr_dissector_t dissect)
|
||||
{
|
||||
goffset start;
|
||||
proto_item *ti;
|
||||
guint32 length;
|
||||
|
||||
start = xdr_getpos(xdrs);
|
||||
|
||||
if (!xdr_u_int(xdrs, &length))
|
||||
return FALSE;
|
||||
if (length > maxlen)
|
||||
return FALSE;
|
||||
|
||||
ti = proto_tree_add_item(tree, hf, tvb, start, -1, ENC_NA);
|
||||
proto_item_append_text(ti, " :: %s<%u>", rtype, length);
|
||||
return dissect_xdr_iterable(tvb, ti, xdrs, ett, rhf, length, dissect, start);
|
||||
}
|
||||
|
||||
static vir_xdr_dissector_t
|
||||
find_payload_dissector(guint32 proc, guint32 type,
|
||||
const vir_dissector_index_t *pds, gsize length)
|
||||
{
|
||||
const vir_dissector_index_t *pd;
|
||||
guint32 first, last, direction;
|
||||
|
||||
if (pds == NULL || length < 1)
|
||||
return NULL;
|
||||
|
||||
first = pds[0].proc;
|
||||
last = pds[length-1].proc;
|
||||
if (proc < first || proc > last) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pd = &pds[proc-first];
|
||||
/* There is no guarantee to proc numbers has no gap */
|
||||
if (pd->proc != proc) {
|
||||
direction = (pd->proc < proc) ? 1 : -1;
|
||||
while (pd->proc != proc) {
|
||||
if (pd->proc == first || pd->proc == last)
|
||||
return NULL;
|
||||
pd += direction;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case VIR_NET_CALL:
|
||||
case VIR_NET_CALL_WITH_FDS:
|
||||
return pd->args;
|
||||
case VIR_NET_REPLY:
|
||||
case VIR_NET_REPLY_WITH_FDS:
|
||||
return pd->ret;
|
||||
case VIR_NET_MESSAGE:
|
||||
return pd->msg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_libvirt_stream(tvbuff_t *tvb, proto_tree *tree, gint payload_length)
|
||||
{
|
||||
proto_tree_add_item(tree, hf_libvirt_stream, tvb, VIR_HEADER_LEN,
|
||||
payload_length - VIR_HEADER_LEN, ENC_NA);
|
||||
}
|
||||
|
||||
static gint32
|
||||
dissect_libvirt_num_of_fds(tvbuff_t *tvb, proto_tree *tree)
|
||||
{
|
||||
gint32 nfds;
|
||||
nfds = tvb_get_ntohl(tvb, VIR_HEADER_LEN);
|
||||
proto_tree_add_int(tree, hf_libvirt_num_of_fds, tvb, VIR_HEADER_LEN, 4, nfds);
|
||||
return nfds;
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_libvirt_fds(tvbuff_t *tvb, gint start, gint32 nfds)
|
||||
{
|
||||
/* TODO: NOP for now */
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_libvirt_payload_xdr_data(tvbuff_t *tvb, proto_tree *tree, gint payload_length,
|
||||
gint32 status, vir_xdr_dissector_t dissect)
|
||||
{
|
||||
gint32 nfds = 0;
|
||||
gint start = VIR_HEADER_LEN;
|
||||
tvbuff_t *payload_tvb;
|
||||
caddr_t payload_data;
|
||||
XDR xdrs;
|
||||
|
||||
if (status == VIR_NET_CALL_WITH_FDS ||
|
||||
status == VIR_NET_REPLY_WITH_FDS) {
|
||||
nfds = dissect_libvirt_num_of_fds(tvb, tree);
|
||||
start += 4;
|
||||
payload_length -= 4;
|
||||
}
|
||||
|
||||
payload_tvb = tvb_new_subset(tvb, start, -1, payload_length);
|
||||
payload_data = (caddr_t)tvb_memdup(payload_tvb, 0, payload_length);
|
||||
xdrmem_create(&xdrs, payload_data, payload_length, XDR_DECODE);
|
||||
|
||||
dissect(payload_tvb, tree, &xdrs, -1);
|
||||
|
||||
xdr_destroy(&xdrs);
|
||||
g_free(payload_data);
|
||||
|
||||
if (nfds != 0) {
|
||||
dissect_libvirt_fds(tvb, start + payload_length, nfds);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_libvirt_payload(tvbuff_t *tvb, proto_tree *tree,
|
||||
guint32 prog, guint32 proc, guint32 type, guint32 status)
|
||||
{
|
||||
gssize payload_length;
|
||||
|
||||
payload_length = tvb_length(tvb) - VIR_HEADER_LEN;
|
||||
if (payload_length <= 0)
|
||||
return; /* No payload */
|
||||
|
||||
if (status == VIR_NET_OK) {
|
||||
vir_xdr_dissector_t xd = find_payload_dissector(proc, type, get_program_data(prog, VIR_PROGRAM_DISSECTORS),
|
||||
*(gsize *)get_program_data(prog, VIR_PROGRAM_DISSECTORS_LEN));
|
||||
if (xd == NULL)
|
||||
goto unknown;
|
||||
dissect_libvirt_payload_xdr_data(tvb, tree, payload_length, status, xd);
|
||||
} else if (status == VIR_NET_ERROR) {
|
||||
dissect_libvirt_payload_xdr_data(tvb, tree, payload_length, status, VIR_ERROR_MESSAGE_DISSECTOR);
|
||||
} else if (type == VIR_NET_STREAM) { /* implicitly, status == VIR_NET_CONTINUE */
|
||||
dissect_libvirt_stream(tvb, tree, payload_length);
|
||||
} else {
|
||||
goto unknown;
|
||||
}
|
||||
return;
|
||||
|
||||
unknown:
|
||||
dbg("Cannot determine payload: Prog=%u, Proc=%u, Type=%u, Status=%u", prog, proc, type, status);
|
||||
proto_tree_add_item(tree, hf_libvirt_unknown, tvb, VIR_HEADER_LEN, -1, ENC_NA);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_libvirt_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
goffset offset;
|
||||
guint32 prog, proc, type, serial, status;
|
||||
const value_string *vs;
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Libvirt");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
offset = 4; /* End of length field */
|
||||
prog = tvb_get_ntohl(tvb, offset); offset += 4;
|
||||
offset += 4; /* Ignore version header field */
|
||||
proc = tvb_get_ntohl(tvb, offset); offset += 4;
|
||||
type = tvb_get_ntohl(tvb, offset); offset += 4;
|
||||
serial = tvb_get_ntohl(tvb, offset); offset += 4;
|
||||
status = tvb_get_ntohl(tvb, offset); offset += 4;
|
||||
|
||||
col_add_fstr(pinfo->cinfo, COL_INFO, "Prog=%s",
|
||||
val_to_str(prog, program_strings, "%x"));
|
||||
|
||||
vs = get_program_data(prog, VIR_PROGRAM_PROCSTRINGS);
|
||||
if (vs == NULL) {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, " Proc=%u", proc);
|
||||
} else {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, " Proc=%s", val_to_str(proc, vs, "%d"));
|
||||
}
|
||||
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, " Type=%s Serial=%u Status=%s",
|
||||
val_to_str(type, type_strings, "%d"), serial,
|
||||
val_to_str(status, status_strings, "%d"));
|
||||
|
||||
if (tree) {
|
||||
gint *hf_proc;
|
||||
proto_item *ti;
|
||||
proto_tree *libvirt_tree;
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_libvirt, tvb, 0, tvb_length(tvb), ENC_NA);
|
||||
libvirt_tree = proto_item_add_subtree(ti, ett_libvirt);
|
||||
|
||||
offset = 0;
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_length, tvb, offset, 4, ENC_NA); offset += 4;
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_program, tvb, offset, 4, ENC_NA); offset += 4;
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_version, tvb, offset, 4, ENC_NA); offset += 4;
|
||||
|
||||
hf_proc = (int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
|
||||
if (hf_proc != NULL && *hf_proc != -1) {
|
||||
proto_tree_add_item(libvirt_tree, *hf_proc, tvb, offset, 4, ENC_NA);
|
||||
} else {
|
||||
/* No string representation, but still useful displaying proc number */
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_procedure, tvb, offset, 4, ENC_NA);
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_type, tvb, offset, 4, ENC_NA); offset += 4;
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_serial, tvb, offset, 4, ENC_NA); offset += 4;
|
||||
proto_tree_add_item(libvirt_tree, hf_libvirt_status, tvb, offset, 4, ENC_NA); offset += 4;
|
||||
|
||||
/* Dissect payload remaining */
|
||||
dissect_libvirt_payload(tvb, libvirt_tree, prog, proc, type, status);
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_message_len(packet_info *pinfo __attribute__((unused)), tvbuff_t *tvb, int offset)
|
||||
{
|
||||
return tvb_get_ntohl(tvb, offset);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_libvirt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
/* Another magic const - 4; simply, how much bytes
|
||||
* is needed to tell the length of libvirt packet. */
|
||||
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4, get_message_len, dissect_libvirt_message);
|
||||
}
|
||||
|
||||
void
|
||||
proto_register_libvirt(void)
|
||||
{
|
||||
static hf_register_info hf[] = {
|
||||
{ &hf_libvirt_length,
|
||||
{ "length", "libvirt.length",
|
||||
FT_UINT32, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_program,
|
||||
{ "program", "libvirt.program",
|
||||
FT_UINT32, BASE_HEX,
|
||||
VALS(program_strings), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_version,
|
||||
{ "version", "libvirt.version",
|
||||
FT_UINT32, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_procedure,
|
||||
{ "procedure", "libvirt.procedure",
|
||||
FT_INT32, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_type,
|
||||
{ "type", "libvirt.type",
|
||||
FT_INT32, BASE_DEC,
|
||||
VALS(type_strings), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_serial,
|
||||
{ "serial", "libvirt.serial",
|
||||
FT_UINT32, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_status,
|
||||
{ "status", "libvirt.status",
|
||||
FT_INT32, BASE_DEC,
|
||||
VALS(status_strings), 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
|
||||
VIR_DYNAMIC_HFSET
|
||||
|
||||
{ &hf_libvirt_stream,
|
||||
{ "stream", "libvirt.stream",
|
||||
FT_BYTES, BASE_NONE,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_num_of_fds,
|
||||
{ "num_of_fds", "libvirt.num_of_fds",
|
||||
FT_INT32, BASE_DEC,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
{ &hf_libvirt_unknown,
|
||||
{ "unknown", "libvirt.unknown",
|
||||
FT_BYTES, BASE_NONE,
|
||||
NULL, 0x0,
|
||||
NULL, HFILL}
|
||||
},
|
||||
};
|
||||
|
||||
static gint *ett[] = {
|
||||
VIR_DYNAMIC_ETTSET
|
||||
&ett_libvirt
|
||||
};
|
||||
|
||||
proto_libvirt = proto_register_protocol(
|
||||
"Libvirt", /* name */
|
||||
"libvirt", /* short name */
|
||||
"libvirt" /* abbrev */
|
||||
);
|
||||
|
||||
proto_register_field_array(proto_libvirt, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
}
|
||||
|
||||
void
|
||||
proto_reg_handoff_libvirt(void)
|
||||
{
|
||||
static dissector_handle_t libvirt_handle;
|
||||
|
||||
libvirt_handle = create_dissector_handle(dissect_libvirt, proto_libvirt);
|
||||
dissector_add_uint("tcp.port", LIBVIRT_PORT, libvirt_handle);
|
||||
}
|
128
tools/wireshark/src/packet-libvirt.h
Normal file
128
tools/wireshark/src/packet-libvirt.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* packet-libvirt.h --- Libvirt packet dissector header file.
|
||||
*
|
||||
* Copyright (C) 2013 Yuto KAWAMURA(kawamuray) <kawamuray.dadada@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Yuto KAWAMURA(kawamuray)
|
||||
*/
|
||||
#ifndef _PACKET_LIBVIRT_H_
|
||||
# define _PACKET_LIBVIRT_H_
|
||||
|
||||
# ifndef LIBVIRT_PORT
|
||||
# define LIBVIRT_PORT 16509
|
||||
# endif
|
||||
|
||||
# define VIR_HEADER_LEN 28
|
||||
|
||||
# ifdef DEBUG
|
||||
# define dbg(fmt, ...) \
|
||||
g_print("[LIBVIRT] " fmt " at " __FILE__ " line %d\n", ##__VA_ARGS__, __LINE__)
|
||||
# else
|
||||
# define dbg(fmt, ...)
|
||||
# endif
|
||||
|
||||
typedef gboolean (*vir_xdr_dissector_t)(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
|
||||
typedef struct vir_dissector_index vir_dissector_index_t;
|
||||
struct vir_dissector_index {
|
||||
guint32 proc;
|
||||
vir_xdr_dissector_t args;
|
||||
vir_xdr_dissector_t ret;
|
||||
vir_xdr_dissector_t msg;
|
||||
};
|
||||
|
||||
enum vir_net_message_type {
|
||||
VIR_NET_CALL = 0,
|
||||
VIR_NET_REPLY = 1,
|
||||
VIR_NET_MESSAGE = 2,
|
||||
VIR_NET_STREAM = 3,
|
||||
VIR_NET_CALL_WITH_FDS = 4,
|
||||
VIR_NET_REPLY_WITH_FDS = 5,
|
||||
};
|
||||
|
||||
enum vir_net_message_status {
|
||||
VIR_NET_OK = 0,
|
||||
VIR_NET_ERROR = 1,
|
||||
VIR_NET_CONTINUE = 2,
|
||||
};
|
||||
|
||||
enum vir_program_data_index {
|
||||
VIR_PROGRAM_PROCHFVAR,
|
||||
VIR_PROGRAM_PROCSTRINGS,
|
||||
VIR_PROGRAM_DISSECTORS,
|
||||
VIR_PROGRAM_DISSECTORS_LEN,
|
||||
VIR_PROGRAM_LAST,
|
||||
};
|
||||
|
||||
static const value_string type_strings[] = {
|
||||
{ VIR_NET_CALL, "CALL" },
|
||||
{ VIR_NET_REPLY, "REPLY" },
|
||||
{ VIR_NET_MESSAGE, "MESSAGE" },
|
||||
{ VIR_NET_STREAM, "STREAM" },
|
||||
{ VIR_NET_CALL_WITH_FDS, "CALL_WITH_FDS" },
|
||||
{ VIR_NET_REPLY_WITH_FDS, "REPLY_WITH_FDS" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
static const value_string status_strings[] = {
|
||||
{ VIR_NET_OK, "OK" },
|
||||
{ VIR_NET_ERROR, "ERROR" },
|
||||
{ VIR_NET_CONTINUE, "CONTINUE" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
/* TODO: These symbols will automatically included in generated headers in the feature */
|
||||
# define VIR_SECURITY_MODEL_BUFLEN (256 + 1)
|
||||
# define VIR_SECURITY_LABEL_BUFLEN (4096 + 1)
|
||||
# define VIR_SECURITY_DOI_BUFLEN (256 + 1)
|
||||
# define VIR_UUID_BUFLEN (16)
|
||||
enum {
|
||||
VIR_TYPED_PARAM_INT = 1, /* integer case */
|
||||
VIR_TYPED_PARAM_UINT = 2, /* unsigned integer case */
|
||||
VIR_TYPED_PARAM_LLONG = 3, /* long long case */
|
||||
VIR_TYPED_PARAM_ULLONG = 4, /* unsigned long long case */
|
||||
VIR_TYPED_PARAM_DOUBLE = 5, /* double case */
|
||||
VIR_TYPED_PARAM_BOOLEAN = 6, /* boolean(character) case */
|
||||
VIR_TYPED_PARAM_STRING = 7, /* string case */
|
||||
};
|
||||
/* / */
|
||||
|
||||
# define VIR_ERROR_MESSAGE_DISSECTOR dissect_xdr_remote_error
|
||||
|
||||
static gboolean dissect_xdr_int(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_u_int(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_short(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_u_short(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_char(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_u_char(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_hyper(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_u_hyper(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_float(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_double(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_bool(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf);
|
||||
static gboolean dissect_xdr_string(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, guint32 maxlen);
|
||||
static gboolean dissect_xdr_opaque(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, guint32 size);
|
||||
static gboolean dissect_xdr_bytes(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, guint32 maxlen);
|
||||
static gboolean dissect_xdr_pointer(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf,
|
||||
vir_xdr_dissector_t dp);
|
||||
static gboolean dissect_xdr_vector(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, gint ett,
|
||||
int rhf, gchar *rtype, guint32 size, vir_xdr_dissector_t dp);
|
||||
static gboolean dissect_xdr_array(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, gint ett,
|
||||
int rhf, gchar *rtype, guint32 maxlen, vir_xdr_dissector_t dp);
|
||||
|
||||
# include "libvirt/protocol.h"
|
||||
|
||||
#endif /* _PACKET_LIBVIRT_H_ */
|
1011
tools/wireshark/util/genxdrstub.pl
Executable file
1011
tools/wireshark/util/genxdrstub.pl
Executable file
File diff suppressed because it is too large
Load Diff
198
tools/wireshark/util/make-dissector-reg
Executable file
198
tools/wireshark/util/make-dissector-reg
Executable file
@ -0,0 +1,198 @@
|
||||
#! /bin/sh
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Copied from Wireshark(http://www.wireshark.org/)
|
||||
|
||||
#
|
||||
# The first argument is the directory in which the source files live.
|
||||
#
|
||||
srcdir="$1"
|
||||
shift
|
||||
|
||||
#
|
||||
# The second argument is either "plugin" or "dissectors"; if it's
|
||||
# "plugin", we build a plugin.c for a plugin, and if it's
|
||||
# "dissectors", we build a register.c for libwireshark.
|
||||
#
|
||||
registertype="$1"
|
||||
shift
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
outfile="plugin.c"
|
||||
elif [ "$registertype" = dissectors ]
|
||||
then
|
||||
outfile="register.c"
|
||||
else
|
||||
echo "Unknown output type '$registertype'" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# All subsequent arguments are the files to scan.
|
||||
#
|
||||
rm -f ${outfile}-tmp
|
||||
echo '/* Do not modify this file. */' >${outfile}-tmp
|
||||
echo '/* It is created automatically by the Makefile. */'>>${outfile}-tmp
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
#include "config.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
/* plugins are DLLs */
|
||||
#define WS_BUILD_DLL
|
||||
#include "ws_symbol_export.h"
|
||||
|
||||
#ifndef ENABLE_STATIC
|
||||
WS_DLL_PUBLIC_NOEXTERN const gchar version[] = VERSION;
|
||||
|
||||
/* Start the functions we need for the plugin stuff */
|
||||
|
||||
WS_DLL_PUBLIC_NOEXTERN void
|
||||
plugin_register (void)
|
||||
{
|
||||
EOF
|
||||
#
|
||||
# Build code to call all the protocol registration routines.
|
||||
#
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
#include "register.h"
|
||||
void
|
||||
register_all_protocols(register_cb cb, gpointer client_data)
|
||||
{
|
||||
EOF
|
||||
#
|
||||
# Build code to call all the protocol registration routines.
|
||||
#
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_REGISTER, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
|
||||
fi
|
||||
echo '}' >>${outfile}-tmp
|
||||
|
||||
|
||||
#
|
||||
# Build code to call all the protocol handoff registration routines.
|
||||
#
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
WS_DLL_PUBLIC_NOEXTERN void
|
||||
plugin_reg_handoff(void)
|
||||
{
|
||||
EOF
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
void
|
||||
register_all_protocol_handoffs(register_cb cb, gpointer client_data)
|
||||
{
|
||||
EOF
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
for f in "$@"
|
||||
do
|
||||
if [ -f $f ]
|
||||
then
|
||||
srcfile=$f
|
||||
else
|
||||
srcfile=$srcdir/$f
|
||||
fi
|
||||
grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
|
||||
done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); if(cb) (*cb)(RA_HANDOFF, \"\1\", client_data); \1 ();}/' >>${outfile}-tmp
|
||||
fi
|
||||
echo '}' >>${outfile}-tmp
|
||||
if [ "$registertype" = plugin ]
|
||||
then
|
||||
echo '#endif' >>${outfile}-tmp
|
||||
else
|
||||
cat <<"EOF" >>${outfile}-tmp
|
||||
gulong register_count(void)
|
||||
{
|
||||
EOF
|
||||
proto_regs=`grep RA_REGISTER ${outfile}-tmp | wc -l`
|
||||
handoff_regs=`grep RA_HANDOFF ${outfile}-tmp | wc -l`
|
||||
echo " return $proto_regs + $handoff_regs;" >>${outfile}-tmp
|
||||
echo '}' >>${outfile}-tmp
|
||||
fi
|
||||
|
||||
# Only overwrite outfile if it differs from newly generated file
|
||||
mv ${outfile}-tmp ${outfile}
|
Loading…
Reference in New Issue
Block a user