On Mon, Oct 10, 2011 at 11:54:16AM +0200, Michal Privoznik wrote: > This patch creates basic dissector for Libvirt RPC. The protocol > description can be found here: > > http://libvirt.org/internals/rpc.html > > Currently, only packet head dissecting is written. To fully dissect > packet payloads a more effort is needed, as each function has > different arguments (in general). However, this can be good > stepping stone for later expansion. Ideally, a script that > will generate this dissector from libvirt RPC file would be written. > --- > > Okay, this patch obviously belongs to wireshark mailing list, > but before I'll send it there, I guess we should decide if we > want it there. I mean there are 2 modes/ways for wireshark > dissectors: > 1) Place it into wireshark repo as many others. > Advantage: wireshark will be shipped with support for libvirt RPC > Disadvantage: wireshark will be shipped with support for libvirt RPC > > In other words, if you look at wireshark releases, they are not > as often as ours, so in the end, this dissector will be always one > or more step behind current libvirt. But many users will be able > to use it right after box open. > > 2) Dissector as plugin > Advantage: we can update it as often as we want > Disadvantage: users needs to install a plugin > > Personally, I prefer 2) as libvirt RPC is expanded pretty often, > and I expect this dissector to be used by libvirt developer mainly, > for who installing a plugin into wireshark can't be a real problem :) Do we have to choose one approach or the other? If wireshark accepts the plugin, could we not also ship a newer version? That would give the best of both worlds. Dave > The table of string for labeling procedures, has been generated by > hand, but I intend to write script for that. > > Currently, only message header is dissected, no payload. Yeah, script > will generate structures for that too. > > More on this: > http://www.wireshark.org/docs/wsdg_html_chunked/ChapterDissection.html > > > epan/CMakeLists.txt | 1 + > epan/dissectors/Makefile.common | 1 + > epan/dissectors/packet-libvirt.c | 466 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 468 insertions(+), 0 deletions(-) > create mode 100644 epan/dissectors/packet-libvirt.c > > diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt > index 5d32e80..330cc9b 100644 > --- a/epan/CMakeLists.txt > +++ b/epan/CMakeLists.txt > @@ -724,6 +724,7 @@ set(DISSECTOR_SRC > dissectors/packet-ldp.c > dissectors/packet-ldss.c > dissectors/packet-lge_monitor.c > + dissectors/packet-libvirt.c > dissectors/packet-linx.c > dissectors/packet-lisp-data.c > dissectors/packet-lisp.c > diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common > index 080001a..c1d4043 100644 > --- a/epan/dissectors/Makefile.common > +++ b/epan/dissectors/Makefile.common > @@ -644,6 +644,7 @@ DISSECTOR_SRC = \ > packet-ldp.c \ > packet-ldss.c \ > packet-lge_monitor.c \ > + packet-libvirt.c \ > packet-linx.c \ > packet-lisp-data.c \ > packet-lisp.c \ > diff --git a/epan/dissectors/packet-libvirt.c b/epan/dissectors/packet-libvirt.c > new file mode 100644 > index 0000000..f3735f0 > --- /dev/null > +++ b/epan/dissectors/packet-libvirt.c > @@ -0,0 +1,466 @@ > +/* packet-libvirt.c > + * Routines for libvirt RPC packet disassembly > + * > + * 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. > + * > + * Author: Michal Privoznik <mprivozn@xxxxxxxxxx> > + */ > + > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > + > +#include <string.h> > +#include <glib.h> > +#include <epan/packet.h> > +#include <epan/prefs.h> > +#include <epan/addr_resolv.h> > +#include <epan/packet.h> > +#include <epan/prefs.h> > +#include "packet-tcp.h" > + > +#define LIBVIRT_PORT 16509 > +#define REMOTE_PROGRAM 0x20008086 > +#define QEMU_PROGRAM 0x20008087 > + > +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_qemu_procedure = -1; > +static gint ett_libvirt = -1; > + > +static const value_string program_strings[] = { > + { REMOTE_PROGRAM, "REMOTE" }, > + { QEMU_PROGRAM, "QEMU" }, > + { 0, NULL } > +}; > + > +static const value_string type_strings[] = { > + { 0, "CALL" }, > + { 1, "REPLY" }, > + { 2, "MESSAGE" }, > + { 3, "STREAM" }, > + {-1, NULL} > +}; > + > +static const value_string status_strings[] = { > + { 0, "OK" }, > + { 1, "ERROR" }, > + { 2, "CONTINUE" }, > + {-1, NULL} > +}; > + > +static const value_string remote_procedure_strings [] = { > + { 1, "OPEN" }, > + { 2, "CLOSE" }, > + { 3, "GET_TYPE" }, > + { 4, "GET_VERSION" }, > + { 5, "GET_MAX_VCPUS" }, > + { 6, "NODE_GET_INFO" }, > + { 7, "GET_CAPABILITIES" }, > + { 8, "DOMAIN_ATTACH_DEVICE" }, > + { 9, "DOMAIN_CREATE" }, > + { 10, "DOMAIN_CREATE_XML" }, > + { 11, "DOMAIN_DEFINE_XML" }, > + { 12, "DOMAIN_DESTROY" }, > + { 13, "DOMAIN_DETACH_DEVICE" }, > + { 14, "DOMAIN_GET_XML_DESC" }, > + { 15, "DOMAIN_GET_AUTOSTART" }, > + { 16, "DOMAIN_GET_INFO" }, > + { 17, "DOMAIN_GET_MAX_MEMORY" }, > + { 18, "DOMAIN_GET_MAX_VCPUS" }, > + { 19, "DOMAIN_GET_OS_TYPE" }, > + { 20, "DOMAIN_GET_VCPUS" }, > + { 21, "LIST_DEFINED_DOMAINS" }, > + { 22, "DOMAIN_LOOKUP_BY_ID" }, > + { 23, "DOMAIN_LOOKUP_BY_NAME" }, > + { 24, "DOMAIN_LOOKUP_BY_UUID" }, > + { 25, "NUM_OF_DEFINED_DOMAINS" }, > + { 26, "DOMAIN_PIN_VCPU" }, > + { 27, "DOMAIN_REBOOT" }, > + { 28, "DOMAIN_RESUME" }, > + { 29, "DOMAIN_SET_AUTOSTART" }, > + { 30, "DOMAIN_SET_MAX_MEMORY" }, > + { 31, "DOMAIN_SET_MEMORY" }, > + { 32, "DOMAIN_SET_VCPUS" }, > + { 33, "DOMAIN_SHUTDOWN" }, > + { 34, "DOMAIN_SUSPEND" }, > + { 35, "DOMAIN_UNDEFINE" }, > + { 36, "LIST_DEFINED_NETWORKS" }, > + { 37, "LIST_DOMAINS" }, > + { 38, "LIST_NETWORKS" }, > + { 39, "NETWORK_CREATE" }, > + { 40, "NETWORK_CREATE_XML" }, > + { 41, "NETWORK_DEFINE_XML" }, > + { 42, "NETWORK_DESTROY" }, > + { 43, "NETWORK_GET_XML_DESC" }, > + { 44, "NETWORK_GET_AUTOSTART" }, > + { 45, "NETWORK_GET_BRIDGE_NAME" }, > + { 46, "NETWORK_LOOKUP_BY_NAME" }, > + { 47, "NETWORK_LOOKUP_BY_UUID" }, > + { 48, "NETWORK_SET_AUTOSTART" }, > + { 49, "NETWORK_UNDEFINE" }, > + { 50, "NUM_OF_DEFINED_NETWORKS" }, > + { 51, "NUM_OF_DOMAINS" }, > + { 52, "NUM_OF_NETWORKS" }, > + { 53, "DOMAIN_CORE_DUMP" }, > + { 54, "DOMAIN_RESTORE" }, > + { 55, "DOMAIN_SAVE" }, > + { 56, "DOMAIN_GET_SCHEDULER_TYPE" }, > + { 57, "DOMAIN_GET_SCHEDULER_PARAMETERS" }, > + { 58, "DOMAIN_SET_SCHEDULER_PARAMETERS" }, > + { 59, "GET_HOSTNAME" }, > + { 60, "SUPPORTS_FEATURE" }, > + { 61, "DOMAIN_MIGRATE_PREPARE" }, > + { 62, "DOMAIN_MIGRATE_PERFORM" }, > + { 63, "DOMAIN_MIGRATE_FINISH" }, > + { 64, "DOMAIN_BLOCK_STATS" }, > + { 65, "DOMAIN_INTERFACE_STATS" }, > + { 66, "AUTH_LIST" }, > + { 67, "AUTH_SASL_INIT" }, > + { 68, "AUTH_SASL_START" }, > + { 69, "AUTH_SASL_STEP" }, > + { 70, "AUTH_POLKIT" }, > + { 71, "NUM_OF_STORAGE_POOLS" }, > + { 72, "LIST_STORAGE_POOLS" }, > + { 73, "NUM_OF_DEFINED_STORAGE_POOLS" }, > + { 74, "LIST_DEFINED_STORAGE_POOLS" }, > + { 75, "FIND_STORAGE_POOL_SOURCES" }, > + { 76, "STORAGE_POOL_CREATE_XML" }, > + { 77, "STORAGE_POOL_DEFINE_XML" }, > + { 78, "STORAGE_POOL_CREATE" }, > + { 79, "STORAGE_POOL_BUILD" }, > + { 80, "STORAGE_POOL_DESTROY" }, > + { 81, "STORAGE_POOL_DELETE" }, > + { 82, "STORAGE_POOL_UNDEFINE" }, > + { 83, "STORAGE_POOL_REFRESH" }, > + { 84, "STORAGE_POOL_LOOKUP_BY_NAME" }, > + { 85, "STORAGE_POOL_LOOKUP_BY_UUID" }, > + { 86, "STORAGE_POOL_LOOKUP_BY_VOLUME" }, > + { 87, "STORAGE_POOL_GET_INFO" }, > + { 88, "STORAGE_POOL_GET_XML_DESC" }, > + { 89, "STORAGE_POOL_GET_AUTOSTART" }, > + { 90, "STORAGE_POOL_SET_AUTOSTART" }, > + { 91, "STORAGE_POOL_NUM_OF_VOLUMES" }, > + { 92, "STORAGE_POOL_LIST_VOLUMES" }, > + { 93, "STORAGE_VOL_CREATE_XML" }, > + { 94, "STORAGE_VOL_DELETE" }, > + { 95, "STORAGE_VOL_LOOKUP_BY_NAME" }, > + { 96, "STORAGE_VOL_LOOKUP_BY_KEY" }, > + { 97, "STORAGE_VOL_LOOKUP_BY_PATH" }, > + { 98, "STORAGE_VOL_GET_INFO" }, > + { 99, "STORAGE_VOL_GET_XML_DESC" }, > + { 100, "STORAGE_VOL_GET_PATH" }, > + { 101, "NODE_GET_CELLS_FREE_MEMORY" }, > + { 102, "NODE_GET_FREE_MEMORY" }, > + { 103, "DOMAIN_BLOCK_PEEK" }, > + { 104, "DOMAIN_MEMORY_PEEK" }, > + { 105, "DOMAIN_EVENTS_REGISTER" }, > + { 106, "DOMAIN_EVENTS_DEREGISTER" }, > + { 107, "DOMAIN_EVENT_LIFECYCLE" }, > + { 108, "DOMAIN_MIGRATE_PREPARE2" }, > + { 109, "DOMAIN_MIGRATE_FINISH2" }, > + { 110, "GET_URI" }, > + { 111, "NODE_NUM_OF_DEVICES" }, > + { 112, "NODE_LIST_DEVICES" }, > + { 113, "NODE_DEVICE_LOOKUP_BY_NAME" }, > + { 114, "NODE_DEVICE_GET_XML_DESC" }, > + { 115, "NODE_DEVICE_GET_PARENT" }, > + { 116, "NODE_DEVICE_NUM_OF_CAPS" }, > + { 117, "NODE_DEVICE_LIST_CAPS" }, > + { 118, "NODE_DEVICE_DETTACH" }, > + { 119, "NODE_DEVICE_RE_ATTACH" }, > + { 120, "NODE_DEVICE_RESET" }, > + { 121, "DOMAIN_GET_SECURITY_LABEL" }, > + { 122, "NODE_GET_SECURITY_MODEL" }, > + { 123, "NODE_DEVICE_CREATE_XML" }, > + { 124, "NODE_DEVICE_DESTROY" }, > + { 125, "STORAGE_VOL_CREATE_XML_FROM" }, > + { 126, "NUM_OF_INTERFACES" }, > + { 127, "LIST_INTERFACES" }, > + { 128, "INTERFACE_LOOKUP_BY_NAME" }, > + { 129, "INTERFACE_LOOKUP_BY_MAC_STRING" }, > + { 130, "INTERFACE_GET_XML_DESC" }, > + { 131, "INTERFACE_DEFINE_XML" }, > + { 132, "INTERFACE_UNDEFINE" }, > + { 133, "INTERFACE_CREATE" }, > + { 134, "INTERFACE_DESTROY" }, > + { 135, "DOMAIN_XML_FROM_NATIVE" }, > + { 136, "DOMAIN_XML_TO_NATIVE" }, > + { 137, "NUM_OF_DEFINED_INTERFACES" }, > + { 138, "LIST_DEFINED_INTERFACES" }, > + { 139, "NUM_OF_SECRETS" }, > + { 140, "LIST_SECRETS" }, > + { 141, "SECRET_LOOKUP_BY_UUID" }, > + { 142, "SECRET_DEFINE_XML" }, > + { 143, "SECRET_GET_XML_DESC" }, > + { 144, "SECRET_SET_VALUE" }, > + { 145, "SECRET_GET_VALUE" }, > + { 146, "SECRET_UNDEFINE" }, > + { 147, "SECRET_LOOKUP_BY_USAGE" }, > + { 148, "DOMAIN_MIGRATE_PREPARE_TUNNEL" }, > + { 149, "IS_SECURE" }, > + { 150, "DOMAIN_IS_ACTIVE" }, > + { 151, "DOMAIN_IS_PERSISTENT" }, > + { 152, "NETWORK_IS_ACTIVE" }, > + { 153, "NETWORK_IS_PERSISTENT" }, > + { 154, "STORAGE_POOL_IS_ACTIVE" }, > + { 155, "STORAGE_POOL_IS_PERSISTENT" }, > + { 156, "INTERFACE_IS_ACTIVE" }, > + { 157, "GET_LIB_VERSION" }, > + { 158, "CPU_COMPARE" }, > + { 159, "DOMAIN_MEMORY_STATS" }, > + { 160, "DOMAIN_ATTACH_DEVICE_FLAGS" }, > + { 161, "DOMAIN_DETACH_DEVICE_FLAGS" }, > + { 162, "CPU_BASELINE" }, > + { 163, "DOMAIN_GET_JOB_INFO" }, > + { 164, "DOMAIN_ABORT_JOB" }, > + { 165, "STORAGE_VOL_WIPE" }, > + { 166, "DOMAIN_MIGRATE_SET_MAX_DOWNTIME" }, > + { 167, "DOMAIN_EVENTS_REGISTER_ANY" }, > + { 168, "DOMAIN_EVENTS_DEREGISTER_ANY" }, > + { 169, "DOMAIN_EVENT_REBOOT" }, > + { 170, "DOMAIN_EVENT_RTC_CHANGE" }, > + { 171, "DOMAIN_EVENT_WATCHDOG" }, > + { 172, "DOMAIN_EVENT_IO_ERROR" }, > + { 173, "DOMAIN_EVENT_GRAPHICS" }, > + { 174, "DOMAIN_UPDATE_DEVICE_FLAGS" }, > + { 175, "NWFILTER_LOOKUP_BY_NAME" }, > + { 176, "NWFILTER_LOOKUP_BY_UUID" }, > + { 177, "NWFILTER_GET_XML_DESC" }, > + { 178, "NUM_OF_NWFILTERS" }, > + { 179, "LIST_NWFILTERS" }, > + { 180, "NWFILTER_DEFINE_XML" }, > + { 181, "NWFILTER_UNDEFINE" }, > + { 182, "DOMAIN_MANAGED_SAVE" }, > + { 183, "DOMAIN_HAS_MANAGED_SAVE_IMAGE" }, > + { 184, "DOMAIN_MANAGED_SAVE_REMOVE" }, > + { 185, "DOMAIN_SNAPSHOT_CREATE_XML" }, > + { 186, "DOMAIN_SNAPSHOT_GET_XML_DESC" }, > + { 187, "DOMAIN_SNAPSHOT_NUM" }, > + { 188, "DOMAIN_SNAPSHOT_LIST_NAMES" }, > + { 189, "DOMAIN_SNAPSHOT_LOOKUP_BY_NAME" }, > + { 190, "DOMAIN_HAS_CURRENT_SNAPSHOT" }, > + { 191, "DOMAIN_SNAPSHOT_CURRENT" }, > + { 192, "DOMAIN_REVERT_TO_SNAPSHOT" }, > + { 193, "DOMAIN_SNAPSHOT_DELETE" }, > + { 194, "DOMAIN_GET_BLOCK_INFO" }, > + { 195, "DOMAIN_EVENT_IO_ERROR_REASON" }, > + { 196, "DOMAIN_CREATE_WITH_FLAGS" }, > + { 197, "DOMAIN_SET_MEMORY_PARAMETERS" }, > + { 198, "DOMAIN_GET_MEMORY_PARAMETERS" }, > + { 199, "DOMAIN_SET_VCPUS_FLAGS" }, > + { 200, "DOMAIN_GET_VCPUS_FLAGS" }, > + { 201, "DOMAIN_OPEN_CONSOLE" }, > + { 202, "DOMAIN_IS_UPDATED" }, > + { 203, "GET_SYSINFO" }, > + { 204, "DOMAIN_SET_MEMORY_FLAGS" }, > + { 205, "DOMAIN_SET_BLKIO_PARAMETERS" }, > + { 206, "DOMAIN_GET_BLKIO_PARAMETERS" }, > + { 207, "DOMAIN_MIGRATE_SET_MAX_SPEED" }, > + { 208, "STORAGE_VOL_UPLOAD" }, > + { 209, "STORAGE_VOL_DOWNLOAD" }, > + { 210, "DOMAIN_INJECT_NMI" }, > + { 211, "DOMAIN_SCREENSHOT" }, > + { 212, "DOMAIN_GET_STATE" }, > + { 213, "DOMAIN_MIGRATE_BEGIN3" }, > + { 214, "DOMAIN_MIGRATE_PREPARE3" }, > + { 215, "DOMAIN_MIGRATE_PREPARE_TUNNEL3" }, > + { 216, "DOMAIN_MIGRATE_PERFORM3" }, > + { 217, "DOMAIN_MIGRATE_FINISH3" }, > + { 218, "DOMAIN_MIGRATE_CONFIRM3" }, > + { 219, "DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS" }, > + { 220, "INTERFACE_CHANGE_BEGIN" }, > + { 221, "INTERFACE_CHANGE_COMMIT" }, > + { 222, "INTERFACE_CHANGE_ROLLBACK" }, > + { 223, "DOMAIN_GET_SCHEDULER_PARAMETERS_FLAGS" }, > + { 224, "DOMAIN_EVENT_CONTROL_ERROR" }, > + { 225, "DOMAIN_PIN_VCPU_FLAGS" }, > + { 226, "DOMAIN_SEND_KEY" }, > + { 227, "NODE_GET_CPU_STATS" }, > + { 228, "NODE_GET_MEMORY_STATS" }, > + { 229, "DOMAIN_GET_CONTROL_INFO" }, > + { 230, "DOMAIN_GET_VCPU_PIN_INFO" }, > + { 231, "DOMAIN_UNDEFINE_FLAGS" }, > + { 232, "DOMAIN_SAVE_FLAGS" }, > + { 233, "DOMAIN_RESTORE_FLAGS" }, > + { 234, "DOMAIN_DESTROY_FLAGS" }, > + { 235, "DOMAIN_SAVE_IMAGE_GET_XML_DESC" }, > + { 236, "DOMAIN_SAVE_IMAGE_DEFINE_XML" }, > + { 237, "DOMAIN_BLOCK_JOB_ABORT" }, > + { 238, "DOMAIN_GET_BLOCK_JOB_INFO" }, > + { 239, "DOMAIN_BLOCK_JOB_SET_SPEED" }, > + { 240, "DOMAIN_BLOCK_PULL" }, > + { 241, "DOMAIN_EVENT_BLOCK_JOB" }, > + { 242, "DOMAIN_MIGRATE_GET_MAX_SPEED" }, > + { 243, "DOMAIN_BLOCK_STATS_FLAGS" }, > + { 244, "DOMAIN_SNAPSHOT_GET_PARENT" }, > + { 245, "DOMAIN_RESET" }, > + { 0, NULL} > +}; > + > +static const value_string qemu_procedure_strings[] = { > + { 1, "MONITOR_COMMAND" }, > + { 2, "DOMAIN_ATTACH" }, > + { 0, NULL} > +}; > + > +static void > +dissect_libvirt_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) > +{ > + gint offset = 0; > + /* Okay, these are magic constants, but > + * they are just offsets where requested > + * info is to be found */ > + guint32 prog = tvb_get_ntohl(tvb, 4); > + guint32 proc = tvb_get_ntohl(tvb, 12); > + guint32 type = tvb_get_ntohl(tvb, 16); > + guint32 serial = tvb_get_ntohl(tvb, 20); > + guint32 status = tvb_get_ntohl(tvb, 24); > + > + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Libvirt"); > + col_clear(pinfo->cinfo,COL_INFO); > + if (prog == REMOTE_PROGRAM) > + col_add_fstr(pinfo->cinfo, COL_INFO, "Proc=%s ", val_to_str(proc, remote_procedure_strings, "%d")); > + else if (prog == QEMU_PROGRAM) > + col_add_fstr(pinfo->cinfo, COL_INFO, "Proc=%s ", val_to_str(proc, qemu_procedure_strings, "%d")); > + else > + /* unhandeld program */ > + col_add_fstr(pinfo->cinfo, COL_INFO, "Proc=%u ", proc); > + > + col_append_fstr(pinfo->cinfo, COL_INFO, "Type=%s Status=%s Prog=%s Serial=%u", > + val_to_str(type, type_strings, "%d"), > + val_to_str(status, status_strings, "%d"), > + val_to_str(prog, program_strings, "%x"), > + serial); > + > + if (tree) { > + proto_item *ti = NULL; > + proto_tree *libvirt_tree = NULL; > + > + ti = proto_tree_add_item(tree, proto_libvirt, tvb, 0, -1, FALSE); > + libvirt_tree = proto_item_add_subtree(ti, ett_libvirt); > + proto_tree_add_item(libvirt_tree, hf_libvirt_length, tvb, offset, 4, FALSE); offset += 4; > + proto_tree_add_item(libvirt_tree, hf_libvirt_program, tvb, offset, 4, FALSE); offset += 4; > + proto_tree_add_item(libvirt_tree, hf_libvirt_version, tvb, offset, 4, FALSE); offset += 4; > + if (prog == REMOTE_PROGRAM) > + proto_tree_add_item(libvirt_tree, hf_libvirt_procedure, tvb, offset, 4, FALSE); > + else if (prog == QEMU_PROGRAM) > + proto_tree_add_item(libvirt_tree, hf_qemu_procedure, tvb, offset, 4, FALSE); > + else > + /* unhandeld program */ > + proto_tree_add_none_format(libvirt_tree, -1, tvb, offset, 4, "Unknown proc: %u", proc); > + offset += 4; > + proto_tree_add_item(libvirt_tree, hf_libvirt_type, tvb, offset, 4, FALSE); offset += 4; > + proto_tree_add_item(libvirt_tree, hf_libvirt_serial, tvb, offset, 4, FALSE); offset += 4; > + proto_tree_add_item(libvirt_tree, hf_libvirt_status, tvb, offset, 4, FALSE); offset += 4; > + } > +} > + > +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, > + VALS(remote_procedure_strings), 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} > + }, > + { &hf_qemu_procedure, > + { "procedure", "libvirt.procedure", > + FT_INT32, BASE_DEC, > + VALS(qemu_procedure_strings), 0x0, > + NULL, HFILL} > + } > + }; > + > + static gint *ett[] = { > + &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_foo(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); > +} > -- > 1.7.3.4 > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list