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 :)
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(a)redhat.com>
+ */
+
+#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