]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
wireshar/ceph/packet-ceph.c: fix eol
authorYehuda Sadeh <yehuda@inktank.com>
Tue, 17 Jul 2012 17:15:27 +0000 (10:15 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Tue, 24 Jul 2012 17:09:27 +0000 (10:09 -0700)
Removing extra char from dos eol format.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
wireshark/ceph/packet-ceph.c

index 754478db0d5d48c2c3ea66516401d05793a2c501..b552ffc4fff772e92f3413dcc628d10acc48a29f 100644 (file)
-/* packet-ceph.c\r
-* This program is free software; you can redistribute it and/or\r
-* modify it under the terms of the GNU General Public License\r
-* as published by the Free Software Foundation; either version 2\r
-* of the License, or (at your option) any later version.\r
-*\r
-* This program is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with this program; if not, write to the Free Software\r
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
-*/\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <glib.h>\r
-#include <epan/packet.h>\r
-#include <epan/dissectors/packet-tcp.h>\r
-\r
-#include "types.h"\r
-\r
-#include "crc32c.h"\r
-\r
-#include <string.h>\r
-\r
-#define PROTO_TAG_CEPH "CEPH"\r
-\r
-/* Wireshark ID of the CEPH protocol */\r
-static int proto_ceph = -1;\r
-\r
-\r
-\r
-/* These are the handles of our subdissectors */\r
-static dissector_handle_t data_handle=NULL;\r
-\r
-static dissector_handle_t ceph_handle;\r
-static void dissect_ceph(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);\r
-\r
-static guint32 global_ceph_min_port = 6789;\r
-static guint32 global_ceph_max_port = 6810;\r
-\r
-static guint32 global_ceph_min_mon_port = 6789;\r
-static guint32 global_ceph_max_mon_port = 6799;\r
-\r
-#define DEST_PORT_CEPH ((pinfo->destport >= global_ceph_min_port) && (pinfo->destport <= global_ceph_max_port))\r
-\r
-#define PORT_IS_MON(port) ((port >= global_ceph_min_mon_port) && (port <= global_ceph_max_mon_port))\r
-#define PORT_IS_MDS(port) ((port >= global_ceph_min_mds_port) && (port <= global_ceph_max_mds_port))\r
-#define PORT_IS_OSD(port) ((port >= global_ceph_min_osd_port) && (port <= global_ceph_max_osd_port))\r
-\r
-#define IS_ENTITY(cmp, port1, port2) (cmp(port1) || cmp(port2))\r
-\r
-#define IS_MON(pinfo) IS_ENTITY(PORT_IS_MON, pinfo->srcport, pinfo->destport)\r
-#define IS_MDS(pinfo) IS_ENTITY(PORT_IS_MDS, pinfo->srcport, pinfo->destport)\r
-#define IS_OSD(pinfo) IS_ENTITY(PORT_IS_OSD, pinfo->srcport, pinfo->destport)\r
-\r
-#define MON_STR "mon"\r
-#define MDS_STR "mds"\r
-#define OSD_STR "osd"\r
-\r
-#define FMT_INO        "0x%.16llx"\r
-\r
-#define PROTO_ADD_TEXT(type, s, field, modifier)\\r
-       proto_tree_add_text(tree, tvb, offset + offsetof(type, field), sizeof(s->field), "" #field ": " modifier, s->field);\r
-\r
-#define PROTO_ADD_ITEM(tree, type, hf, s, field) \\r
-       proto_tree_add_item(tree, hf, tvb, offset + offsetof(type, field), sizeof(s->field), TRUE);\r
-\r
-#define CTIME_BUF_LEN  128\r
-\r
-#define PROTO_ADD_TIME(tvb, tree, type, offset, head, field, name) \\r
-       do { \\r
-               time_t time;                    \\r
-               time = head->field.tv_sec;      \\r
-               proto_tree_add_text(tree, tvb, offset + offsetof(type, field), \\r
-                       sizeof(head->field), "" #name ": %s (%d ns)", ctime(&time), head->field.tv_nsec); \\r
-       } while (0)\r
-\r
-static const value_string packettypenames[] = {\r
-       { 1, "Shutdown" },\r
-       { 2, "Ping" },\r
-       { 4, "Mon Map" },\r
-       { 5, "Mon Get Map" },\r
-       { 10, "Client Mount" },\r
-       { 11, "Client Mount Ack" },\r
-       { 12, "Client Unmount" },\r
-       { 13, "Statfs" },\r
-       { 20, "MDS Get Map" },\r
-       { 21, "MDS Map" },\r
-       { 22, "Client Session" },\r
-       { 23, "Client Reconnect" },\r
-       { 24, "Client Request" },\r
-       { 25, "Client Request Forward" },\r
-       { 26, "Client Reply" },\r
-       { 0x310, "Client Caps" },\r
-       { 0x311, "Client Lease" },\r
-       { 0x312, "Client Snap" },\r
-       { 40, "OSD Get Map" },\r
-       { 41, "OSD Map" },\r
-       { 42, "OSD Op" },\r
-       { 43, "OSD Op Reply" },\r
-       { 0, NULL }\r
-};     \r
-\r
-#define ACK_MSG_SIZE                   9\r
-#define TVB_MSG_HEADER_POS(x) (1 + offsetof(struct ceph_msg_header, x))\r
-#define TVB_IS_ACK(ofs) (tvb_get_guint8(tvb, ofs) == CEPH_MSGR_TAG_ACK)\r
-#define TVB_MSG_FIELD(func, tvb, ofs, field) func(tvb, ofs + (TVB_IS_ACK(ofs) ? ACK_MSG_SIZE : 0) + TVB_MSG_HEADER_POS(field))\r
-\r
-/* The following hf_* variables are used to hold the Wireshark IDs of\r
-* our header fields; they are filled out when we call\r
-* proto_register_field_array() in proto_register_ceph()\r
-*/\r
-/** Kts attempt at defining the protocol */\r
-static gint hf_ceph = -1;\r
-static gint hf_ceph_mds_op = -1;\r
-static gint hf_ceph_header = -1;\r
-static gint hf_ceph_banner = -1;\r
-static gint hf_ceph_entity_addr = -1;\r
-static gint hf_ceph_entity_type = -1;\r
-static gint hf_ceph_entity_num = -1;\r
-static gint hf_ceph_fsid = -1;\r
-static gint hf_ceph_banner_magic = -1;\r
-static gint hf_ceph_banner_version = -1;\r
-static gint hf_ceph_connect_erank = -1;\r
-static gint hf_ceph_connect_nonce = -1;\r
-static gint hf_ceph_sockaddr_in = -1;\r
-static gint hf_ceph_connect_host_type = -1;\r
-static gint hf_ceph_connect_tag = -1;\r
-static gint hf_ceph_connect_global_seq = -1;\r
-static gint hf_ceph_connect_connect_seq = -1;\r
-static gint hf_ceph_connect_flags = -1;\r
-static gint hf_ceph_length = -1;\r
-static gint hf_ceph_type = -1;\r
-static gint hf_ceph_text = -1;\r
-static gint hf_ceph_path = -1;\r
-static gint hf_sin_family = -1;\r
-static gint hf_sin_port = -1;\r
-static gint hf_sin_addr = -1;\r
-static gint hf_ceph_hdr_tag = -1;\r
-static gint hf_ceph_hdr_seq_ack = -1;\r
-static gint hf_ceph_hdr_seq = -1;\r
-static gint hf_ceph_hdr_type = -1;\r
-static gint hf_ceph_hdr_priority = -1;\r
-static gint hf_ceph_hdr_version = -1;\r
-static gint hf_ceph_hdr_mon_protocol = -1;\r
-static gint hf_ceph_hdr_osd_protocol = -1;\r
-static gint hf_ceph_hdr_mds_protocol = -1;\r
-static gint hf_ceph_hdr_client_protocol = -1;\r
-static gint hf_ceph_hdr_front_len = -1;\r
-static gint hf_ceph_hdr_middle_len = -1;\r
-static gint hf_ceph_hdr_data_off = -1;\r
-static gint hf_ceph_hdr_data_len = -1;\r
-static gint hf_ceph_data = -1;\r
-static gint hf_ceph_front = -1;\r
-static gint hf_ceph_hdr_src = -1;\r
-static gint hf_ceph_hdr_orig_src = -1;\r
-static gint hf_ceph_hdr_dst = -1;\r
-static gint hf_ceph_hdr_crc = -1;\r
-static gint hf_ceph_footer = -1;\r
-static gint hf_ceph_footer_flags = -1;\r
-static gint hf_ceph_footer_front_crc = -1;\r
-static gint hf_ceph_footer_middle_crc = -1;\r
-static gint hf_ceph_footer_data_crc = -1;\r
-\r
-\r
-/* These are the ids of the subtrees that we may be creating */\r
-static gint ett_ceph = -1;\r
-static gint ett_ceph_header = -1;\r
-static gint ett_ceph_banner = -1;\r
-static gint ett_ceph_entity_addr = -1;\r
-static gint ett_ceph_length = -1;\r
-static gint ett_ceph_type = -1;\r
-static gint ett_ceph_text = -1;\r
-static gint ett_ceph_front = -1;\r
-static gint ett_ceph_data = -1;\r
-static gint ett_ceph_footer = -1;\r
-\r
-\r
-void proto_reg_handoff_ceph(void)\r
-{\r
-       static gboolean initialized=FALSE;\r
-       static guint32 port;\r
-\r
-       if (!initialized) {\r
-               data_handle = find_dissector("data");\r
-               ceph_handle = create_dissector_handle(dissect_ceph, proto_ceph);\r
-               for (port = global_ceph_min_port; port <= global_ceph_max_port; port++)\r
-                       dissector_add("tcp.port", port, ceph_handle);\r
-       }\r
-\r
-}\r
-\r
-void proto_register_ceph (void)\r
-{\r
-       /* A header field is something you can search/filter on.\r
-       * \r
-       * We create a structure to register our fields. It consists of an\r
-       * array of hf_register_info structures, each of which are of the format\r
-       * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.\r
-       */\r
-       static hf_register_info hf[] = {\r
-               { &hf_ceph,\r
-                       { "Data", "ceph.data", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "CEPH PDU", HFILL }},\r
-               { &hf_ceph_header,\r
-                       { "Header", "ceph.header", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "CEPH Header", HFILL }},\r
-               { &hf_ceph_banner,\r
-                       { "Ceph Banner", "ceph.connect.banner", FT_STRING, BASE_NONE, NULL, 0x0,\r
-                       "Ceph Banner", HFILL }},\r
-               { &hf_ceph_entity_type,\r
-                       { "Ceph Entity Type", "ceph.entity.type", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "Ceph Entity Type", HFILL }},\r
-               { &hf_ceph_entity_num,\r
-                       { "Ceph Entity Num", "ceph.entity.num", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "Ceph Entity Num", HFILL }},\r
-               { &hf_ceph_entity_addr,\r
-                       { "Ceph Entity Addr", "ceph.entity.addr", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "Ceph Entity Addr", HFILL }},\r
-               { &hf_ceph_fsid,\r
-                       { "Ceph FSID", "ceph.fsid", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "Ceph FSID", HFILL }},\r
-               { &hf_ceph_banner_magic,\r
-                       { "Ceph Banner Magic", "ceph.connect.banner.magic", FT_STRING, BASE_NONE, NULL, 0x0,\r
-                       "Ceph Banner Magic", HFILL }},\r
-               { &hf_ceph_banner_version,\r
-                       { "Ceph Banner Version", "ceph.connect.banner.ver", FT_STRING, BASE_NONE, NULL, 0x0,\r
-                       "Ceph Banner", HFILL }},\r
-               { &hf_ceph_connect_erank,\r
-                       { "erank", "ceph.connect.erank", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "connect: erank", HFILL }},\r
-               { &hf_ceph_connect_nonce,\r
-                       { "nonce", "ceph.connect.nonce", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "connect: nonce", HFILL }},\r
-               { &hf_ceph_sockaddr_in,\r
-                       { "sockaddr_in", "ceph.sockaddr_in", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "sockaddr_in", HFILL }},\r
-               { &hf_sin_family,\r
-                       { "sin_family", "ceph.sin_family", FT_UINT16, BASE_HEX, NULL, 0x0,\r
-                       "sockaddr_in: sin_family", HFILL }},\r
-               { &hf_sin_port,\r
-                       { "sin_port", "ceph.sin_port", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "sockaddr_in: sin_port", HFILL }},\r
-               { &hf_sin_addr,\r
-                       { "ip addr", "ceph.addr", FT_IPv4, BASE_NONE, NULL, 0x0,\r
-                       "sockaddr_in: ip addr", HFILL }},\r
-               { &hf_ceph_connect_host_type,\r
-                       { "host_type", "ceph.connect.host_type", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "connect: host_type", HFILL }},\r
-               { &hf_ceph_connect_tag,\r
-                       { "tag", "ceph.connect.tag", FT_UINT8, BASE_DEC, NULL, 0x0,\r
-                       "connect: tag", HFILL }},\r
-               { &hf_ceph_mds_op,\r
-                       { "mds op", "ceph.mds.op", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "ceph: mds op", HFILL }},\r
-               { &hf_ceph_connect_global_seq,\r
-                       { "global_seq", "ceph.connect.global_seq", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "connect: global_seq", HFILL }},\r
-               { &hf_ceph_connect_connect_seq,\r
-                       { "connect_seq", "ceph.connect.connect_seq", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "connect: connect_seq", HFILL }},\r
-               { &hf_ceph_connect_flags,\r
-                       { "flags", "ceph.connect.flags", FT_UINT8, BASE_HEX, NULL, 0x0,\r
-                       "connect: flags", HFILL }},\r
-               { &hf_ceph_length,\r
-                       { "Package Length", "ceph.len", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "Package Length", HFILL }},\r
-               { &hf_ceph_type,\r
-                       { "Type", "ceph.type", FT_UINT8, BASE_DEC, VALS(packettypenames), 0x0,\r
-                       "Package Type", HFILL }},\r
-               { &hf_ceph_text,\r
-                       { "Text", "ceph.text", FT_STRING, BASE_NONE, NULL, 0x0,\r
-                       "Text", HFILL }},\r
-               { &hf_ceph_path,\r
-                       { "path", "ceph.path", FT_STRING, BASE_NONE, NULL, 0x0,\r
-                       "path", HFILL }},\r
-               { &hf_ceph_hdr_tag,\r
-                       { "tag", "ceph.tag", FT_UINT8, BASE_DEC, NULL, 0x0,\r
-                       "hdr: tag", HFILL }},\r
-               { &hf_ceph_hdr_seq_ack,\r
-                       { "ack seq", "ceph.ack.seq", FT_UINT64, BASE_DEC, NULL, 0x0,\r
-                       "ack: seq", HFILL }},\r
-               { &hf_ceph_hdr_seq,\r
-                       { "seq", "ceph.seq", FT_UINT64, BASE_DEC, NULL, 0x0,\r
-                       "hdr: seq", HFILL }},\r
-               { &hf_ceph_hdr_type,\r
-                       { "type", "ceph.type", FT_UINT16, BASE_HEX, NULL, 0x0,\r
-                       "hdr: type", HFILL }},\r
-               { &hf_ceph_hdr_priority,\r
-                       { "priority", "ceph.priority", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "hdr: priority", HFILL }},\r
-               { &hf_ceph_hdr_version,\r
-                       { "version", "ceph.version", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "hdr: version", HFILL }},\r
-               { &hf_ceph_hdr_mon_protocol,\r
-                       { "mon_protocol", "ceph.mon_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "hdr: mon_protocol", HFILL }},\r
-               { &hf_ceph_hdr_osd_protocol,\r
-                       { "osd_protocol", "ceph.osd_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "hdr: osd_protocol", HFILL }},\r
-               { &hf_ceph_hdr_mds_protocol,\r
-                       { "mds_protocol", "ceph.mds_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "hdr: mds_protocol", HFILL }},\r
-               { &hf_ceph_hdr_client_protocol,\r
-                       { "client_protocol", "ceph.client_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,\r
-                       "hdr: client_protocol", HFILL }},\r
-               { &hf_ceph_hdr_front_len,\r
-                       { "front_len", "ceph.front_len", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "hdr: front_len", HFILL }},\r
-               { &hf_ceph_hdr_middle_len,\r
-                       { "middle_len", "ceph.middle_len", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "hdr: middle_len", HFILL }},\r
-               { &hf_ceph_hdr_data_off,\r
-                       { "data_off", "ceph.data_off", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "hdr: data_off", HFILL }},\r
-               { &hf_ceph_hdr_data_len,\r
-                       { "data_len", "ceph.data_len", FT_UINT32, BASE_DEC, NULL, 0x0,\r
-                       "hdr: data_len", HFILL }},\r
-               { &hf_ceph_hdr_src,\r
-                       { "src", "ceph.src", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "hdr: src", HFILL }},\r
-               { &hf_ceph_hdr_orig_src,\r
-                       { "orig_src", "ceph.orig_src", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "hdr: orig_src", HFILL }},\r
-               { &hf_ceph_hdr_dst,\r
-                       { "dst", "ceph.dst", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "hdr: dst", HFILL }},\r
-               { &hf_ceph_hdr_crc,\r
-                       { "crc", "ceph.crc", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "hdr: crc", HFILL }},\r
-               { &hf_ceph_front,\r
-                       { "Front", "ceph.front", FT_NONE, BASE_NONE, NULL, 0x0,\r
-                       "Ceph Front", HFILL }},\r
-               { &hf_ceph_data,\r
-                       { "Data", "ceph.data", FT_NONE, BASE_HEX, NULL, 0x0,\r
-                       "Ceph Data", HFILL }},\r
-               { &hf_ceph_footer,\r
-                       { "Footer", "ceph.footer", FT_NONE, BASE_HEX, NULL, 0x0,\r
-                       "Ceph Footer", HFILL }},\r
-               { &hf_ceph_footer_flags,\r
-                       { "flags", "ceph.footer.flags", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "footer: flags", HFILL }},\r
-               { &hf_ceph_footer_front_crc,\r
-                       { "front_crc", "ceph.footer.front_crc", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "footer: front_crc", HFILL }},\r
-               { &hf_ceph_footer_middle_crc,\r
-                       { "middle_crc", "ceph.footer.middle_crc", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "footer: middle_crc", HFILL }},\r
-               { &hf_ceph_footer_data_crc,\r
-                       { "data_crc", "ceph.footer.data_crc", FT_UINT32, BASE_HEX, NULL, 0x0,\r
-                       "footer: data_crc", HFILL }},\r
-       };\r
-       static gint *ett[] = {\r
-               &ett_ceph,\r
-               &ett_ceph_header,\r
-               &ett_ceph_banner,\r
-               &ett_ceph_length,\r
-               &ett_ceph_entity_addr,\r
-               &ett_ceph_type,\r
-               &ett_ceph_text,\r
-               &ett_ceph_data,\r
-               &ett_ceph_front,\r
-               &ett_ceph_footer\r
-       };\r
-       //if (proto_ceph == -1) { /* execute protocol initialization only once */\r
-       proto_ceph = proto_register_protocol ("CEPH Protocol", "CEPH", "ceph");\r
-\r
-       proto_register_field_array (proto_ceph, hf, array_length (hf));\r
-       proto_register_subtree_array (ett, array_length (ett));\r
-       register_dissector("ceph", dissect_ceph, proto_ceph);\r
-       //}\r
-}\r
-       \r
-static guint32 dissect_sockaddr_in(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_sockaddr_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-       proto_item *ceph_item = proto_tree_get_parent(tree);\r
-\r
-       ceph_sockaddr_tree = proto_item_add_subtree(ceph_item, ett_ceph);\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_sockaddr_in, tvb, offset, 16, TRUE );\r
-       ceph_sockaddr_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-\r
-       proto_tree_add_item(ceph_sockaddr_tree, hf_sin_family, tvb, offset, 2, TRUE);\r
-       proto_tree_add_item(ceph_sockaddr_tree, hf_sin_port, tvb, offset+2, 2, TRUE);\r
-       proto_tree_add_item(ceph_sockaddr_tree, hf_sin_addr, tvb, offset+4, 4, FALSE);\r
-       offset += 16;\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_banner(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_banner_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_banner, tvb, offset, 9, TRUE );\r
-       ceph_banner_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-\r
-       proto_tree_add_item(ceph_banner_tree, hf_ceph_banner_magic, tvb, offset, 4, TRUE);\r
-       proto_tree_add_item(ceph_banner_tree, hf_ceph_banner_version, tvb, offset+5, 4, TRUE);\r
-\r
-       return offset+9;\r
-}\r
-\r
-static guint32 dissect_ceph_entity_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_entity_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_entity_addr, tvb, offset, sizeof(struct ceph_entity_addr), TRUE );\r
-       ceph_entity_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_erank, tvb, offset, 4, TRUE);\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_nonce, tvb, offset+4, 4, TRUE);\r
-       dissect_sockaddr_in(tvb, ceph_entity_tree, offset+8);\r
-#if 0\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_host_type, tvb, offset, 4, TRUE);\r
-       offset += 4;\r
-#endif\r
-\r
-       return offset + sizeof(struct ceph_entity_addr);\r
-}\r
-\r
-static guint32 dissect_ceph_fsid(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_entity_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-       struct ceph_fsid *fsid;\r
-\r
-       fsid = (struct ceph_fsid *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_fsid));\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_fsid, tvb, offset, sizeof(struct ceph_entity_addr), TRUE );\r
-       ceph_entity_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_erank, tvb, offset, 4, TRUE);\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_nonce, tvb, offset+4, 4, TRUE);\r
-\r
-       proto_tree_add_text(tree, tvb, 0, \r
-                               sizeof(struct ceph_fsid), "fsid: " FMT_INO "." FMT_INO, ((unsigned long long *)fsid->fsid)[0], ((unsigned long long *)fsid->fsid)[1]);\r
-       \r
-       offset += sizeof(struct ceph_fsid);\r
-\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_entity_inst(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_entity_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_entity_addr, tvb, offset, sizeof(struct ceph_entity_addr), TRUE );\r
-       ceph_entity_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_entity_type, tvb, offset, 4, TRUE);\r
-       proto_tree_add_item(ceph_entity_tree, hf_ceph_entity_num, tvb, offset+4, 4, TRUE);\r
-       offset += 8;\r
-       offset = dissect_ceph_entity_addr(tvb, ceph_entity_tree, offset);\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_footer(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 data_crc)\r
-{\r
-       proto_tree *ceph_footer_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-       proto_item *data_crc_item = NULL;\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_footer, tvb, offset, sizeof(struct ceph_msg_footer), TRUE );\r
-       ceph_footer_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-       proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_flags, tvb, offset, 4, TRUE);\r
-       proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_front_crc, tvb, offset+4, 4, TRUE);\r
-       proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_middle_crc, tvb, offset+8, 4, TRUE);\r
-       data_crc_item = proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_data_crc, tvb, offset+12, 4, TRUE);\r
-       proto_item_append_text(data_crc_item, " (calculated %x)", data_crc);\r
-\r
-       offset += 12;\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_client_connect(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_header_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-       proto_item *ceph_item = proto_tree_get_parent(tree);\r
-       struct ceph_msg_connect *msg;\r
-\r
-       offset = dissect_ceph_banner(tvb, tree, offset);\r
-\r
-       ceph_header_tree = proto_item_add_subtree(ceph_item, ett_ceph);\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_header, tvb, offset, -1, TRUE );\r
-       ceph_header_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-\r
-       offset = dissect_ceph_entity_addr(tvb, ceph_header_tree, offset);\r
-#if 0\r
-       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_host_type, tvb, offset, 4, TRUE);\r
-       offset += 4;\r
-       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_global_seq, tvb, offset, 4, TRUE);\r
-       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_connect_seq, tvb, offset+4, 4, TRUE);\r
-       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_flags, tvb, offset+8, 1, TRUE);\r
-       offset += 8;\r
-#endif\r
-\r
-       msg = (struct ceph_msg_connect *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_msg_connect));\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, host_type, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, global_seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, connect_seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, protocol_version, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, flags, "%x");\r
-\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_server_connect(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_header_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-       proto_item *ceph_item = proto_tree_get_parent(tree);\r
-       struct ceph_msg_connect_reply *msg;\r
-\r
-       offset = dissect_ceph_banner(tvb, tree, offset);\r
-\r
-       ceph_header_tree = proto_item_add_subtree(ceph_item, ett_ceph);\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_header, tvb, offset, -1, TRUE );\r
-       ceph_header_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-\r
-       offset = dissect_ceph_entity_addr(tvb, ceph_header_tree, offset);\r
-       offset = dissect_ceph_entity_addr(tvb, ceph_header_tree, offset);\r
-       msg = (struct ceph_msg_connect_reply *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_msg_connect_reply));\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, tag, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, global_seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, connect_seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, protocol_version, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, flags, "%x");\r
-\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_file_layout(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       guint32 orig_ofs = offset;\r
-       struct ceph_file_layout *lo;\r
-\r
-       lo = (struct ceph_file_layout *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_file_layout));\r
-       \r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_stripe_unit, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_stripe_count, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_object_size, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_cas_hash, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_object_stripe_unit, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_pg_preferred, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_pg_pool, "%u");\r
-\r
-       return orig_ofs + sizeof(struct ceph_mds_reply_head);\r
-}\r
-#if 0\r
-static int dissect_ceph_filepath(tvbuff_t *tvb, proto_tree *tree, guint32 offset, char **path, guint64 *ino)\r
-{\r
-       guint32 len;\r
-       const char *p = NULL;\r
-\r
-       *ino = tvb_get_letoh64(tvb, offset);\r
-       proto_tree_add_text(tree, tvb, offset, sizeof(*ino), "inode: " FMT_INO, *ino);\r
-       offset += sizeof(*ino);\r
-       len = tvb_get_letohl(tvb, offset);\r
-       proto_tree_add_text(tree, tvb, offset, sizeof(len), "len: %d", len);\r
-       offset += sizeof(len);\r
-\r
-       if (len) {\r
-               p = tvb_get_ptr(tvb, offset, len);\r
-               *path = malloc(len+1);\r
-               if (*path) {\r
-                       memcpy(*path, p, len);\r
-                       (*path)[len] = '\0';\r
-                       proto_tree_add_item(tree, hf_ceph_path, tvb, offset, len, TRUE);\r
-               }\r
-       }\r
-\r
-       offset += len;\r
-\r
-       return offset;\r
-}\r
-#endif\r
-static guint32 dissect_ceph_mon_statfs(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       struct ceph_mon_statfs *req;\r
-\r
-       req = (struct ceph_mon_statfs *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mon_statfs));\r
-       \r
-       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_mon_statfs, fsid));\r
-       PROTO_ADD_TEXT(struct ceph_mon_statfs, req, tid, "%lld");\r
-\r
-       return offset + sizeof(struct ceph_mon_statfs);\r
-}\r
-\r
-static guint32 dissect_ceph_mon_statfs_reply(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       struct ceph_mon_statfs_reply *req;\r
-\r
-       req = (struct ceph_mon_statfs_reply *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mon_statfs_reply));\r
-       \r
-       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_mon_statfs_reply, fsid));\r
-       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, tid, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.kb, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.kb_used, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.kb_avail, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.num_objects, "%lld");\r
-\r
-       return offset + sizeof(struct ceph_mon_statfs_reply);\r
-}\r
-#if 0\r
-static guint32 dissect_ceph_client_osd_getmap(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       struct ceph_osd_getmap *req;\r
-\r
-       req = (struct ceph_osd_getmap *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_osd_getmap));\r
-       \r
-       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_osd_getmap, fsid));\r
-       PROTO_ADD_TEXT(struct ceph_osd_getmap, req, start, "%d");\r
-\r
-       return offset + sizeof(struct ceph_osd_getmap);\r
-}\r
-\r
-static guint32 dissect_ceph_client_mds_getmap(tvbuff_t *tvb, proto_tree *tree, guint32 offset)\r
-{\r
-       struct ceph_mds_getmap *req;\r
-\r
-       req = (struct ceph_mds_getmap *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_getmap));\r
-       \r
-       PROTO_ADD_TEXT(struct ceph_mds_getmap, req, monhdr.have_version, "%lld");\r
-       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_mds_getmap, fsid));\r
-\r
-       return offset + sizeof(struct ceph_mds_getmap);\r
-}\r
-#endif\r
-static guint32 dissect_ceph_client_mds_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)\r
-{\r
-       struct ceph_mds_request_head *head;\r
-       proto_item *item;\r
-\r
-       head = (struct ceph_mds_request_head *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_request_head));\r
-       \r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, tid, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, oldest_client_tid, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, mdsmap_epoch, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, num_retry, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, num_fwd, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, num_releases, "%d");\r
-\r
-       item = proto_tree_add_item(tree, hf_ceph_mds_op, tvb, offset+offsetof(struct ceph_mds_request_head, op), sizeof(head->op), TRUE);\r
-       proto_item_append_text(item, " (%s)", ceph_mds_op_name(head->op));\r
-\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, caller_uid, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, caller_gid, "%d");\r
-\r
-       if (check_col(pinfo->cinfo, COL_INFO)) {\r
-               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ceph_mds_op_name(head->op));\r
-       }\r
-       \r
-       /* FIXME */\r
-       switch (head->op) {\r
-       case CEPH_MDS_OP_LOOKUP:\r
-//             PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.lookup.mask, "0x%.4x");\r
-               break;\r
-       case CEPH_MDS_OP_SETXATTR:\r
-               break;\r
-       case CEPH_MDS_OP_SETLAYOUT:\r
-               dissect_ceph_file_layout(tvb, tree, offset + offsetof(struct ceph_mds_request_head, args.setlayout.layout));\r
-               break;\r
-       case CEPH_MDS_OP_SETATTR:\r
-               break;\r
-       case CEPH_MDS_OP_MKNOD:\r
-               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.mknod.mode, "0%.5o");\r
-               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.mknod.rdev, "%d");\r
-               break;\r
-       case CEPH_MDS_OP_OPEN:\r
-               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.open.flags, "%x");\r
-               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.open.mode, "0%.5o");\r
-               break;\r
-       case CEPH_MDS_OP_MKDIR:\r
-               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.mkdir.mode, "0%.5o");\r
-               break;\r
-       case CEPH_MDS_OP_RMXATTR:\r
-       case CEPH_MDS_OP_LINK:\r
-       case CEPH_MDS_OP_UNLINK:\r
-       case CEPH_MDS_OP_RENAME:\r
-       case CEPH_MDS_OP_RMDIR:\r
-       case CEPH_MDS_OP_SYMLINK:\r
-       case CEPH_MDS_OP_LSSNAP:\r
-       case CEPH_MDS_OP_MKSNAP:\r
-       case CEPH_MDS_OP_RMSNAP:\r
-               break;\r
-       }\r
-\r
-       offset += sizeof(struct ceph_mds_request_head);\r
-#if 0\r
-       if (head->op == CEPH_MDS_OP_FINDINODE) {\r
-       \r
-       } else {\r
-               guint64 ino1, ino2;\r
-               char *s1 = NULL, *s2 = NULL;\r
-\r
-               offset = dissect_ceph_filepath(tvb, tree, offset, &s1, &ino1);\r
-               offset = dissect_ceph_filepath(tvb, tree, offset, &s2, &ino2);\r
-\r
-               if (check_col(pinfo->cinfo, COL_INFO)) {\r
-                       if (s1)\r
-                               col_append_fstr(pinfo->cinfo, COL_INFO, " %s", s1);\r
-                       if (s2)\r
-                               col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", s2);\r
-               }\r
-\r
-\r
-               \r
-       }\r
-#endif\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_client_mds_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)\r
-{\r
-       guint32 orig_ofs = offset;\r
-       struct ceph_mds_reply_head *head;\r
-\r
-       head = (struct ceph_mds_reply_head *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_reply_head));\r
-       \r
-       PROTO_ADD_TEXT(struct ceph_mds_reply_head, head, tid, "%lld");\r
-\r
-       proto_tree_add_text(tree, tvb, offsetof(struct ceph_mds_reply_head, op), \r
-                               sizeof(head->op), "op: %d (%s)", head->op, ceph_mds_op_name(head->op));\r
-\r
-       PROTO_ADD_TEXT(struct ceph_mds_reply_head, head, result, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_reply_head, head, mdsmap_epoch, "%d");\r
-\r
-\r
-       if (check_col(pinfo->cinfo, COL_INFO)) {\r
-               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ceph_mds_op_name(head->op));\r
-       }\r
-\r
-       return orig_ofs + sizeof(struct ceph_mds_reply_head);\r
-}\r
-\r
-static guint32 dissect_ceph_client_mds_lease_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)\r
-{\r
-       guint32 orig_ofs = offset;\r
-       struct ceph_mds_lease *head;\r
-       static char *lease_action[] = { "", "revoke", "release", "renew" };\r
-\r
-       head = (struct ceph_mds_lease *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_lease));\r
-       \r
-       PROTO_ADD_TEXT(struct ceph_mds_lease, head, action, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_lease, head, mask, "%.4x");\r
-       PROTO_ADD_TEXT(struct ceph_mds_lease, head, ino, FMT_INO);\r
-       PROTO_ADD_TEXT(struct ceph_mds_lease, head, first, "%lld");\r
-       PROTO_ADD_TEXT(struct ceph_mds_lease, head, last, "%lld");\r
-\r
-       if (check_col(pinfo->cinfo, COL_INFO)) {\r
-               if (head->action < 4) {\r
-                       col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", lease_action[head->action]);\r
-               }\r
-       }\r
-\r
-       return orig_ofs + sizeof(struct ceph_mds_lease);\r
-}\r
-\r
-static guint32 dissect_ceph_client_mds_caps_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)\r
-{\r
-       guint32 orig_ofs = offset;\r
-       struct ceph_mds_caps *head;\r
-\r
-       head = (struct ceph_mds_caps *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_caps));\r
-       \r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, op, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, ino, FMT_INO);\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, caps, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, wanted, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, size, "%llu");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, max_size, "%llu");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, truncate_seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, migrate_seq, "%d");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, time_warp_seq, "%u");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, snap_follows, "%llu");\r
-       PROTO_ADD_TEXT(struct ceph_mds_caps, head, snap_trace_len, "%d");\r
-\r
-#define CAPS_REQ_ADD_TIME(field) PROTO_ADD_TIME(tvb, tree, struct ceph_mds_caps, offset, head, field, field) \r
-       CAPS_REQ_ADD_TIME(mtime);\r
-       CAPS_REQ_ADD_TIME(atime);\r
-       CAPS_REQ_ADD_TIME(ctime);\r
-\r
-       if (check_col(pinfo->cinfo, COL_INFO)) {\r
-               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ceph_cap_op_name(head->op));\r
-       }\r
-\r
-       return orig_ofs + sizeof(struct ceph_mds_caps);\r
-}\r
-\r
-static guint32 dissect_ceph_client_front(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint16 type)\r
-{\r
-       switch (type) {\r
-       case CEPH_MSG_STATFS:\r
-               offset = dissect_ceph_mon_statfs(tvb, tree, offset);\r
-               break;\r
-       case CEPH_MSG_STATFS_REPLY:\r
-               offset = dissect_ceph_mon_statfs_reply(tvb, tree, offset);\r
-               break;\r
-       case CEPH_MSG_CLIENT_REQUEST: /* mds request */\r
-               offset = dissect_ceph_client_mds_request(tvb, pinfo, tree, offset);\r
-               break;\r
-       case CEPH_MSG_CLIENT_REPLY:\r
-               offset = dissect_ceph_client_mds_reply(tvb, pinfo, tree, offset);\r
-               break;\r
-       case CEPH_MSG_CLIENT_LEASE:\r
-               offset = dissect_ceph_client_mds_lease_request(tvb, pinfo, tree, offset);\r
-               break;\r
-       case CEPH_MSG_CLIENT_CAPS:\r
-               offset = dissect_ceph_client_mds_caps_request(tvb, pinfo, tree, offset);\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-       return offset;\r
-}\r
-\r
-static guint32 dissect_ceph_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)\r
-{\r
-       proto_tree *ceph_header_tree = NULL;\r
-       proto_item *ceph_sub_item = NULL;\r
-       proto_item *ceph_item = proto_tree_get_parent(tree);\r
-       guint32 front_len, middle_len, data_len;\r
-       guint8 tag;\r
-       guint32 orig_ofs = offset;\r
-       guint16 type;\r
-       guint64 seq;\r
-       struct ceph_msg_header *header;\r
-    unsigned int data_crc = 0;\r
-\r
-       ceph_header_tree = proto_item_add_subtree(ceph_item, ett_ceph);\r
-\r
-       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_header, tvb, offset, -1, TRUE );\r
-       ceph_header_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);\r
-\r
-       tag = tvb_get_guint8(tvb, offset);\r
-\r
-       if (tag == CEPH_MSGR_TAG_ACK) {\r
-               proto_tree_add_item(ceph_header_tree, hf_ceph_hdr_tag, tvb, offset, 1, TRUE);\r
-               proto_tree_add_item(ceph_header_tree, hf_ceph_hdr_seq_ack, tvb, offset+1, 8, TRUE);\r
-               offset += ACK_MSG_SIZE;\r
-       }\r
-\r
-       proto_tree_add_item(ceph_header_tree, hf_ceph_hdr_tag, tvb, offset, 1, TRUE);\r
-       offset++;\r
-\r
-       header = (struct ceph_msg_header *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_msg_header));\r
-\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_seq, header, seq);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_type, header, type);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_priority, header, priority);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_version, header, version);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_front_len, header, front_len);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_middle_len, header, middle_len);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_data_off, header, data_off);\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_data_len, header, data_len);\r
-       dissect_ceph_entity_inst(tvb, ceph_header_tree, offset + offsetof(struct ceph_msg_header, src));\r
-       dissect_ceph_entity_inst(tvb, ceph_header_tree, offset + offsetof(struct ceph_msg_header, orig_src));\r
-       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_crc, header, crc);\r
-       \r
-       offset += sizeof(struct ceph_msg_header);\r
-       \r
-       type = TVB_MSG_FIELD(tvb_get_letohl, tvb, orig_ofs, type);\r
-       seq = TVB_MSG_FIELD(tvb_get_letoh64, tvb, orig_ofs, seq);\r
-       front_len = TVB_MSG_FIELD(tvb_get_letohs, tvb, orig_ofs, front_len);\r
-       middle_len = TVB_MSG_FIELD(tvb_get_letohs, tvb, orig_ofs, middle_len);\r
-       data_len = TVB_MSG_FIELD(tvb_get_letohl, tvb, orig_ofs, data_len);\r
-\r
-       if (front_len) {\r
-       /*      ceph_sub_item = proto_tree_add_item( tree, hf_ceph_front, tvb, offset, front_len, TRUE );\r
-               offset += front_len; */\r
-\r
-               dissect_ceph_client_front(tvb, pinfo, tree, offset, type);\r
-               offset += front_len;\r
-       }\r
-\r
-       if (middle_len) {\r
-                offset += middle_len;\r
-       }\r
-\r
-       if (data_len) {\r
-               char *data;\r
-               ceph_sub_item = proto_tree_add_item( tree, hf_ceph_data, tvb, offset, data_len, TRUE );\r
-           data = (char *)tvb_get_ptr(tvb, offset, data_len);\r
-\r
-               data_crc = crc32c_le(0, data, data_len);\r
-\r
-               offset += data_len;\r
-       }\r
-\r
-       offset = dissect_ceph_footer(tvb, tree, offset, data_crc);\r
-\r
-       return offset;\r
-}\r
-\r
-static const char *entity_name_by_type(int type)\r
-{\r
-       if (type < 4)\r
-               return "???";\r
-\r
-       if (type < 20)\r
-               return "mon";\r
-\r
-       if (type < 30)\r
-               return "mds";\r
-\r
-       if (type < 50)\r
-               return "osd";\r
-\r
-       if (type < 0x300)\r
-               return "???";\r
-\r
-       if (type < 0x400)\r
-               return "mds";\r
-\r
-       return "???";\r
-}\r
-\r
-static void\r
-dissect_ceph_client(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\r
-{\r
-\r
-       proto_item *ceph_item = NULL;\r
-       proto_tree *ceph_tree = NULL;\r
-       guint16 type = 0;\r
-       const guchar *ptr;\r
-       guint32 pos = 0;\r
-       int have_banner = 0;\r
-       \r
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))\r
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CEPH);\r
-       /* Clear out stuff in the info column */\r
-       if(check_col(pinfo->cinfo,COL_INFO)){\r
-               col_clear(pinfo->cinfo,COL_INFO);\r
-       }\r
-\r
-       ptr = tvb_get_ptr(tvb, pos, 9);\r
-       if (ptr && memcmp(ptr, "ceph", 4) == 0) {\r
-               have_banner = 1;\r
-               pos += 9;\r
-       }\r
-\r
-       // This is not a good way of dissecting packets.  The tvb length should\r
-       // be sanity checked so we aren't going past the actual size of the buffer.\r
-       type = tvb_get_guint8( tvb, 4 ); // Get the type byte\r
-\r
-       if (check_col(pinfo->cinfo, COL_INFO)) {\r
-               const char *entity_str = NULL;\r
-                       \r
-               if (have_banner) {\r
-                       if (IS_MON(pinfo))\r
-                               entity_str = MON_STR;\r
-                       else \r
-                               entity_str = "???";\r
-\r
-                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] Connect Request", entity_str);\r
-               } else {\r
-                       type = TVB_MSG_FIELD(tvb_get_letohl, tvb, 0, type);\r
-                       entity_str = entity_name_by_type(type);\r
-                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] %s",\r
-                       entity_str,\r
-                       val_to_str(type, packettypenames, "Unknown Type:0x%02x"));\r
-               }\r
-       }\r
-\r
-       if (tree) { /* we are being asked for details */\r
-               guint32 offset = 0;\r
-\r
-               ceph_item = proto_tree_add_item(tree, proto_ceph, tvb, 0, -1, TRUE);\r
-               ceph_tree = proto_item_add_subtree(ceph_item, ett_ceph);\r
-               if (have_banner) { /* this is a connect message */\r
-                       offset = dissect_ceph_client_connect(tvb, ceph_tree, offset);\r
-               } else {\r
-                       offset = dissect_ceph_generic(tvb, pinfo, ceph_tree, offset);\r
-               }\r
-       }\r
-}\r
-\r
-static void\r
-dissect_ceph_server(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\r
-{\r
-\r
-       proto_item *ceph_item = NULL;\r
-       proto_tree *ceph_tree = NULL;\r
-       guint16 type = 0;\r
-       const guchar *ptr;\r
-       guint32 pos = 0;\r
-       int have_banner = 0;\r
-\r
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))\r
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CEPH);\r
-       /* Clear out stuff in the info column */\r
-       if(check_col(pinfo->cinfo,COL_INFO)){\r
-               col_clear(pinfo->cinfo,COL_INFO);\r
-       }\r
-\r
-       ptr = tvb_get_ptr(tvb, pos, 9);\r
-       if (ptr && memcmp(ptr, "ceph", 4) == 0) {\r
-               have_banner = 1;\r
-               pos += 9;\r
-       }\r
-\r
-       // This is not a good way of dissecting packets.  The tvb length should\r
-       // be sanity checked so we aren't going past the actual size of the buffer.\r
-       type = tvb_get_guint8( tvb, 4 ); // Get the type byte\r
-\r
-       if (check_col(pinfo->cinfo, COL_INFO)) {\r
-               const char *entity_str;\r
-                       if (IS_MON(pinfo))\r
-                               entity_str = MON_STR;\r
-                       else \r
-                               entity_str = "???";\r
-               if (have_banner) {\r
-                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] Connect Response", entity_str);\r
-               } else {\r
-                       type = TVB_MSG_FIELD(tvb_get_letohl, tvb, 0, type);\r
-                       entity_str = entity_name_by_type(type);\r
-                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] %s",\r
-                       entity_str,\r
-                       val_to_str(type, packettypenames, "Unknown Type:0x%02x"));\r
-               }\r
-       }\r
-\r
-       if (tree) { /* we are being asked for details */\r
-               guint32 offset = 0;\r
-\r
-               ceph_item = proto_tree_add_item(tree, proto_ceph, tvb, 0, -1, TRUE);\r
-               ceph_tree = proto_item_add_subtree(ceph_item, ett_ceph);\r
-\r
-               if (have_banner) {\r
-                       offset = dissect_ceph_server_connect(tvb, ceph_tree, offset);\r
-               } else {\r
-                       offset = dissect_ceph_generic(tvb, pinfo, ceph_tree, offset);\r
-               }\r
-       }\r
-}\r
-\r
-static void\r
-dissect_ceph_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\r
-{\r
-       if (DEST_PORT_CEPH)\r
-               dissect_ceph_client(tvb, pinfo, tree);\r
-       else\r
-               dissect_ceph_server(tvb, pinfo, tree);\r
-}              \r
-\r
-static guint dissect_ceph_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\r
-{\r
-       guint32 offset = 0;\r
-\r
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))\r
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CEPH);\r
-       /* Clear out stuff in the info column */\r
-       if(check_col(pinfo->cinfo,COL_INFO)){\r
-               col_clear(pinfo->cinfo,COL_INFO);\r
-               col_add_fstr(pinfo->cinfo, COL_INFO, "Ack");\r
-       }\r
-       if (tree) {\r
-               proto_tree_add_item(tree, proto_ceph, tvb, 0, 5, TRUE);\r
-               proto_tree_add_item(tree, hf_ceph_hdr_tag, tvb, offset, 1, TRUE);\r
-               proto_tree_add_item(tree, hf_ceph_hdr_seq_ack, tvb, offset+1, 8, TRUE);\r
-               offset += 9;\r
-       }\r
-\r
-       return offset;\r
-}\r
-\r
-/* determine PDU length of protocol ceph */\r
-static guint get_ceph_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)\r
-{\r
-       const char *ptr;\r
-       guint32 len;\r
-       guint32 pos = 0;\r
-\r
-       ptr = tvb_get_ptr(tvb, offset, /* sizeof(CEPH_BANNER) */tvb->length-offset);\r
-       if (ptr && memcmp(ptr, "ceph", 4) == 0) {\r
-               if (DEST_PORT_CEPH) {\r
-                       len = sizeof(CEPH_BANNER) - 1 +\r
-                               sizeof(struct ceph_entity_addr) +\r
-                               sizeof(struct ceph_msg_connect);\r
-               } else\r
-                       len = sizeof(CEPH_BANNER) - 1 +\r
-                               sizeof(struct ceph_entity_addr) +\r
-                               sizeof(struct ceph_entity_addr) +\r
-                               sizeof(struct ceph_msg_connect_reply);\r
-\r
-               return len;\r
-       }\r
-\r
-       if (*ptr == CEPH_MSGR_TAG_ACK)\r
-               pos = ACK_MSG_SIZE;\r
-\r
-       len = pos + (guint)1 + sizeof(struct ceph_msg_header) +\r
-               TVB_MSG_FIELD(tvb_get_letohl, tvb, offset, front_len) + \r
-               TVB_MSG_FIELD(tvb_get_letohl, tvb, offset, data_len) + \r
-               sizeof(struct ceph_msg_footer);\r
-       \r
-       if (!*ptr)\r
-               return 0;\r
-       return len;\r
-}\r
-\r
-\r
-static void dissect_ceph(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\r
-{\r
-       const char *ptr;\r
-\r
-       ptr = tvb_get_ptr(tvb, 0, 6);\r
-\r
-       if ((*ptr == CEPH_MSGR_TAG_MSG) || \r
-            (memcmp(ptr, CEPH_BANNER, 4) == 0) || \r
-          ((ptr[0] == CEPH_MSGR_TAG_ACK) && (ptr[5] == CEPH_MSGR_TAG_MSG))\r
-       )  {\r
-               tcp_dissect_pdus(tvb, pinfo, tree, TRUE, TVB_MSG_HEADER_POS(src),\r
-                       get_ceph_message_len, dissect_ceph_message);\r
-       } else {\r
-               dissect_ceph_acks(tvb, pinfo, tree);\r
-       }\r
-}\r
-\r
+/* packet-ceph.c
+* 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
+
+#include <stdio.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/dissectors/packet-tcp.h>
+
+#include "types.h"
+
+#include "crc32c.h"
+
+#include <string.h>
+
+#define PROTO_TAG_CEPH "CEPH"
+
+/* Wireshark ID of the CEPH protocol */
+static int proto_ceph = -1;
+
+
+
+/* These are the handles of our subdissectors */
+static dissector_handle_t data_handle=NULL;
+
+static dissector_handle_t ceph_handle;
+static void dissect_ceph(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static guint32 global_ceph_min_port = 6789;
+static guint32 global_ceph_max_port = 6810;
+
+static guint32 global_ceph_min_mon_port = 6789;
+static guint32 global_ceph_max_mon_port = 6799;
+
+#define DEST_PORT_CEPH ((pinfo->destport >= global_ceph_min_port) && (pinfo->destport <= global_ceph_max_port))
+
+#define PORT_IS_MON(port) ((port >= global_ceph_min_mon_port) && (port <= global_ceph_max_mon_port))
+#define PORT_IS_MDS(port) ((port >= global_ceph_min_mds_port) && (port <= global_ceph_max_mds_port))
+#define PORT_IS_OSD(port) ((port >= global_ceph_min_osd_port) && (port <= global_ceph_max_osd_port))
+
+#define IS_ENTITY(cmp, port1, port2) (cmp(port1) || cmp(port2))
+
+#define IS_MON(pinfo) IS_ENTITY(PORT_IS_MON, pinfo->srcport, pinfo->destport)
+#define IS_MDS(pinfo) IS_ENTITY(PORT_IS_MDS, pinfo->srcport, pinfo->destport)
+#define IS_OSD(pinfo) IS_ENTITY(PORT_IS_OSD, pinfo->srcport, pinfo->destport)
+
+#define MON_STR "mon"
+#define MDS_STR "mds"
+#define OSD_STR "osd"
+
+#define FMT_INO        "0x%.16llx"
+
+#define PROTO_ADD_TEXT(type, s, field, modifier)\
+       proto_tree_add_text(tree, tvb, offset + offsetof(type, field), sizeof(s->field), "" #field ": " modifier, s->field);
+
+#define PROTO_ADD_ITEM(tree, type, hf, s, field) \
+       proto_tree_add_item(tree, hf, tvb, offset + offsetof(type, field), sizeof(s->field), TRUE);
+
+#define CTIME_BUF_LEN  128
+
+#define PROTO_ADD_TIME(tvb, tree, type, offset, head, field, name) \
+       do { \
+               time_t time;                    \
+               time = head->field.tv_sec;      \
+               proto_tree_add_text(tree, tvb, offset + offsetof(type, field), \
+                       sizeof(head->field), "" #name ": %s (%d ns)", ctime(&time), head->field.tv_nsec); \
+       } while (0)
+
+static const value_string packettypenames[] = {
+       { 1, "Shutdown" },
+       { 2, "Ping" },
+       { 4, "Mon Map" },
+       { 5, "Mon Get Map" },
+       { 10, "Client Mount" },
+       { 11, "Client Mount Ack" },
+       { 12, "Client Unmount" },
+       { 13, "Statfs" },
+       { 20, "MDS Get Map" },
+       { 21, "MDS Map" },
+       { 22, "Client Session" },
+       { 23, "Client Reconnect" },
+       { 24, "Client Request" },
+       { 25, "Client Request Forward" },
+       { 26, "Client Reply" },
+       { 0x310, "Client Caps" },
+       { 0x311, "Client Lease" },
+       { 0x312, "Client Snap" },
+       { 40, "OSD Get Map" },
+       { 41, "OSD Map" },
+       { 42, "OSD Op" },
+       { 43, "OSD Op Reply" },
+       { 0, NULL }
+};     
+
+#define ACK_MSG_SIZE                   9
+#define TVB_MSG_HEADER_POS(x) (1 + offsetof(struct ceph_msg_header, x))
+#define TVB_IS_ACK(ofs) (tvb_get_guint8(tvb, ofs) == CEPH_MSGR_TAG_ACK)
+#define TVB_MSG_FIELD(func, tvb, ofs, field) func(tvb, ofs + (TVB_IS_ACK(ofs) ? ACK_MSG_SIZE : 0) + TVB_MSG_HEADER_POS(field))
+
+/* The following hf_* variables are used to hold the Wireshark IDs of
+* our header fields; they are filled out when we call
+* proto_register_field_array() in proto_register_ceph()
+*/
+/** Kts attempt at defining the protocol */
+static gint hf_ceph = -1;
+static gint hf_ceph_mds_op = -1;
+static gint hf_ceph_header = -1;
+static gint hf_ceph_banner = -1;
+static gint hf_ceph_entity_addr = -1;
+static gint hf_ceph_entity_type = -1;
+static gint hf_ceph_entity_num = -1;
+static gint hf_ceph_fsid = -1;
+static gint hf_ceph_banner_magic = -1;
+static gint hf_ceph_banner_version = -1;
+static gint hf_ceph_connect_erank = -1;
+static gint hf_ceph_connect_nonce = -1;
+static gint hf_ceph_sockaddr_in = -1;
+static gint hf_ceph_connect_host_type = -1;
+static gint hf_ceph_connect_tag = -1;
+static gint hf_ceph_connect_global_seq = -1;
+static gint hf_ceph_connect_connect_seq = -1;
+static gint hf_ceph_connect_flags = -1;
+static gint hf_ceph_length = -1;
+static gint hf_ceph_type = -1;
+static gint hf_ceph_text = -1;
+static gint hf_ceph_path = -1;
+static gint hf_sin_family = -1;
+static gint hf_sin_port = -1;
+static gint hf_sin_addr = -1;
+static gint hf_ceph_hdr_tag = -1;
+static gint hf_ceph_hdr_seq_ack = -1;
+static gint hf_ceph_hdr_seq = -1;
+static gint hf_ceph_hdr_type = -1;
+static gint hf_ceph_hdr_priority = -1;
+static gint hf_ceph_hdr_version = -1;
+static gint hf_ceph_hdr_mon_protocol = -1;
+static gint hf_ceph_hdr_osd_protocol = -1;
+static gint hf_ceph_hdr_mds_protocol = -1;
+static gint hf_ceph_hdr_client_protocol = -1;
+static gint hf_ceph_hdr_front_len = -1;
+static gint hf_ceph_hdr_middle_len = -1;
+static gint hf_ceph_hdr_data_off = -1;
+static gint hf_ceph_hdr_data_len = -1;
+static gint hf_ceph_data = -1;
+static gint hf_ceph_front = -1;
+static gint hf_ceph_hdr_src = -1;
+static gint hf_ceph_hdr_orig_src = -1;
+static gint hf_ceph_hdr_dst = -1;
+static gint hf_ceph_hdr_crc = -1;
+static gint hf_ceph_footer = -1;
+static gint hf_ceph_footer_flags = -1;
+static gint hf_ceph_footer_front_crc = -1;
+static gint hf_ceph_footer_middle_crc = -1;
+static gint hf_ceph_footer_data_crc = -1;
+
+
+/* These are the ids of the subtrees that we may be creating */
+static gint ett_ceph = -1;
+static gint ett_ceph_header = -1;
+static gint ett_ceph_banner = -1;
+static gint ett_ceph_entity_addr = -1;
+static gint ett_ceph_length = -1;
+static gint ett_ceph_type = -1;
+static gint ett_ceph_text = -1;
+static gint ett_ceph_front = -1;
+static gint ett_ceph_data = -1;
+static gint ett_ceph_footer = -1;
+
+
+void proto_reg_handoff_ceph(void)
+{
+       static gboolean initialized=FALSE;
+       static guint32 port;
+
+       if (!initialized) {
+               data_handle = find_dissector("data");
+               ceph_handle = create_dissector_handle(dissect_ceph, proto_ceph);
+               for (port = global_ceph_min_port; port <= global_ceph_max_port; port++)
+                       dissector_add("tcp.port", port, ceph_handle);
+       }
+
+}
+
+void proto_register_ceph (void)
+{
+       /* A header field is something you can search/filter on.
+       * 
+       * We create a structure to register our fields. It consists of an
+       * array of hf_register_info structures, each of which are of the format
+       * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
+       */
+       static hf_register_info hf[] = {
+               { &hf_ceph,
+                       { "Data", "ceph.data", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "CEPH PDU", HFILL }},
+               { &hf_ceph_header,
+                       { "Header", "ceph.header", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "CEPH Header", HFILL }},
+               { &hf_ceph_banner,
+                       { "Ceph Banner", "ceph.connect.banner", FT_STRING, BASE_NONE, NULL, 0x0,
+                       "Ceph Banner", HFILL }},
+               { &hf_ceph_entity_type,
+                       { "Ceph Entity Type", "ceph.entity.type", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "Ceph Entity Type", HFILL }},
+               { &hf_ceph_entity_num,
+                       { "Ceph Entity Num", "ceph.entity.num", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "Ceph Entity Num", HFILL }},
+               { &hf_ceph_entity_addr,
+                       { "Ceph Entity Addr", "ceph.entity.addr", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "Ceph Entity Addr", HFILL }},
+               { &hf_ceph_fsid,
+                       { "Ceph FSID", "ceph.fsid", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "Ceph FSID", HFILL }},
+               { &hf_ceph_banner_magic,
+                       { "Ceph Banner Magic", "ceph.connect.banner.magic", FT_STRING, BASE_NONE, NULL, 0x0,
+                       "Ceph Banner Magic", HFILL }},
+               { &hf_ceph_banner_version,
+                       { "Ceph Banner Version", "ceph.connect.banner.ver", FT_STRING, BASE_NONE, NULL, 0x0,
+                       "Ceph Banner", HFILL }},
+               { &hf_ceph_connect_erank,
+                       { "erank", "ceph.connect.erank", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "connect: erank", HFILL }},
+               { &hf_ceph_connect_nonce,
+                       { "nonce", "ceph.connect.nonce", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "connect: nonce", HFILL }},
+               { &hf_ceph_sockaddr_in,
+                       { "sockaddr_in", "ceph.sockaddr_in", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "sockaddr_in", HFILL }},
+               { &hf_sin_family,
+                       { "sin_family", "ceph.sin_family", FT_UINT16, BASE_HEX, NULL, 0x0,
+                       "sockaddr_in: sin_family", HFILL }},
+               { &hf_sin_port,
+                       { "sin_port", "ceph.sin_port", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "sockaddr_in: sin_port", HFILL }},
+               { &hf_sin_addr,
+                       { "ip addr", "ceph.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
+                       "sockaddr_in: ip addr", HFILL }},
+               { &hf_ceph_connect_host_type,
+                       { "host_type", "ceph.connect.host_type", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "connect: host_type", HFILL }},
+               { &hf_ceph_connect_tag,
+                       { "tag", "ceph.connect.tag", FT_UINT8, BASE_DEC, NULL, 0x0,
+                       "connect: tag", HFILL }},
+               { &hf_ceph_mds_op,
+                       { "mds op", "ceph.mds.op", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "ceph: mds op", HFILL }},
+               { &hf_ceph_connect_global_seq,
+                       { "global_seq", "ceph.connect.global_seq", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "connect: global_seq", HFILL }},
+               { &hf_ceph_connect_connect_seq,
+                       { "connect_seq", "ceph.connect.connect_seq", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "connect: connect_seq", HFILL }},
+               { &hf_ceph_connect_flags,
+                       { "flags", "ceph.connect.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+                       "connect: flags", HFILL }},
+               { &hf_ceph_length,
+                       { "Package Length", "ceph.len", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "Package Length", HFILL }},
+               { &hf_ceph_type,
+                       { "Type", "ceph.type", FT_UINT8, BASE_DEC, VALS(packettypenames), 0x0,
+                       "Package Type", HFILL }},
+               { &hf_ceph_text,
+                       { "Text", "ceph.text", FT_STRING, BASE_NONE, NULL, 0x0,
+                       "Text", HFILL }},
+               { &hf_ceph_path,
+                       { "path", "ceph.path", FT_STRING, BASE_NONE, NULL, 0x0,
+                       "path", HFILL }},
+               { &hf_ceph_hdr_tag,
+                       { "tag", "ceph.tag", FT_UINT8, BASE_DEC, NULL, 0x0,
+                       "hdr: tag", HFILL }},
+               { &hf_ceph_hdr_seq_ack,
+                       { "ack seq", "ceph.ack.seq", FT_UINT64, BASE_DEC, NULL, 0x0,
+                       "ack: seq", HFILL }},
+               { &hf_ceph_hdr_seq,
+                       { "seq", "ceph.seq", FT_UINT64, BASE_DEC, NULL, 0x0,
+                       "hdr: seq", HFILL }},
+               { &hf_ceph_hdr_type,
+                       { "type", "ceph.type", FT_UINT16, BASE_HEX, NULL, 0x0,
+                       "hdr: type", HFILL }},
+               { &hf_ceph_hdr_priority,
+                       { "priority", "ceph.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "hdr: priority", HFILL }},
+               { &hf_ceph_hdr_version,
+                       { "version", "ceph.version", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "hdr: version", HFILL }},
+               { &hf_ceph_hdr_mon_protocol,
+                       { "mon_protocol", "ceph.mon_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "hdr: mon_protocol", HFILL }},
+               { &hf_ceph_hdr_osd_protocol,
+                       { "osd_protocol", "ceph.osd_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "hdr: osd_protocol", HFILL }},
+               { &hf_ceph_hdr_mds_protocol,
+                       { "mds_protocol", "ceph.mds_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "hdr: mds_protocol", HFILL }},
+               { &hf_ceph_hdr_client_protocol,
+                       { "client_protocol", "ceph.client_protocol", FT_UINT16, BASE_DEC, NULL, 0x0,
+                       "hdr: client_protocol", HFILL }},
+               { &hf_ceph_hdr_front_len,
+                       { "front_len", "ceph.front_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "hdr: front_len", HFILL }},
+               { &hf_ceph_hdr_middle_len,
+                       { "middle_len", "ceph.middle_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "hdr: middle_len", HFILL }},
+               { &hf_ceph_hdr_data_off,
+                       { "data_off", "ceph.data_off", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "hdr: data_off", HFILL }},
+               { &hf_ceph_hdr_data_len,
+                       { "data_len", "ceph.data_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "hdr: data_len", HFILL }},
+               { &hf_ceph_hdr_src,
+                       { "src", "ceph.src", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "hdr: src", HFILL }},
+               { &hf_ceph_hdr_orig_src,
+                       { "orig_src", "ceph.orig_src", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "hdr: orig_src", HFILL }},
+               { &hf_ceph_hdr_dst,
+                       { "dst", "ceph.dst", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "hdr: dst", HFILL }},
+               { &hf_ceph_hdr_crc,
+                       { "crc", "ceph.crc", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "hdr: crc", HFILL }},
+               { &hf_ceph_front,
+                       { "Front", "ceph.front", FT_NONE, BASE_NONE, NULL, 0x0,
+                       "Ceph Front", HFILL }},
+               { &hf_ceph_data,
+                       { "Data", "ceph.data", FT_NONE, BASE_HEX, NULL, 0x0,
+                       "Ceph Data", HFILL }},
+               { &hf_ceph_footer,
+                       { "Footer", "ceph.footer", FT_NONE, BASE_HEX, NULL, 0x0,
+                       "Ceph Footer", HFILL }},
+               { &hf_ceph_footer_flags,
+                       { "flags", "ceph.footer.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "footer: flags", HFILL }},
+               { &hf_ceph_footer_front_crc,
+                       { "front_crc", "ceph.footer.front_crc", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "footer: front_crc", HFILL }},
+               { &hf_ceph_footer_middle_crc,
+                       { "middle_crc", "ceph.footer.middle_crc", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "footer: middle_crc", HFILL }},
+               { &hf_ceph_footer_data_crc,
+                       { "data_crc", "ceph.footer.data_crc", FT_UINT32, BASE_HEX, NULL, 0x0,
+                       "footer: data_crc", HFILL }},
+       };
+       static gint *ett[] = {
+               &ett_ceph,
+               &ett_ceph_header,
+               &ett_ceph_banner,
+               &ett_ceph_length,
+               &ett_ceph_entity_addr,
+               &ett_ceph_type,
+               &ett_ceph_text,
+               &ett_ceph_data,
+               &ett_ceph_front,
+               &ett_ceph_footer
+       };
+       //if (proto_ceph == -1) { /* execute protocol initialization only once */
+       proto_ceph = proto_register_protocol ("CEPH Protocol", "CEPH", "ceph");
+
+       proto_register_field_array (proto_ceph, hf, array_length (hf));
+       proto_register_subtree_array (ett, array_length (ett));
+       register_dissector("ceph", dissect_ceph, proto_ceph);
+       //}
+}
+       
+static guint32 dissect_sockaddr_in(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_sockaddr_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+       proto_item *ceph_item = proto_tree_get_parent(tree);
+
+       ceph_sockaddr_tree = proto_item_add_subtree(ceph_item, ett_ceph);
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_sockaddr_in, tvb, offset, 16, TRUE );
+       ceph_sockaddr_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+
+       proto_tree_add_item(ceph_sockaddr_tree, hf_sin_family, tvb, offset, 2, TRUE);
+       proto_tree_add_item(ceph_sockaddr_tree, hf_sin_port, tvb, offset+2, 2, TRUE);
+       proto_tree_add_item(ceph_sockaddr_tree, hf_sin_addr, tvb, offset+4, 4, FALSE);
+       offset += 16;
+       return offset;
+}
+
+static guint32 dissect_ceph_banner(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_banner_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_banner, tvb, offset, 9, TRUE );
+       ceph_banner_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+
+       proto_tree_add_item(ceph_banner_tree, hf_ceph_banner_magic, tvb, offset, 4, TRUE);
+       proto_tree_add_item(ceph_banner_tree, hf_ceph_banner_version, tvb, offset+5, 4, TRUE);
+
+       return offset+9;
+}
+
+static guint32 dissect_ceph_entity_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_entity_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_entity_addr, tvb, offset, sizeof(struct ceph_entity_addr), TRUE );
+       ceph_entity_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_erank, tvb, offset, 4, TRUE);
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_nonce, tvb, offset+4, 4, TRUE);
+       dissect_sockaddr_in(tvb, ceph_entity_tree, offset+8);
+#if 0
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_host_type, tvb, offset, 4, TRUE);
+       offset += 4;
+#endif
+
+       return offset + sizeof(struct ceph_entity_addr);
+}
+
+static guint32 dissect_ceph_fsid(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_entity_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+       struct ceph_fsid *fsid;
+
+       fsid = (struct ceph_fsid *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_fsid));
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_fsid, tvb, offset, sizeof(struct ceph_entity_addr), TRUE );
+       ceph_entity_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_erank, tvb, offset, 4, TRUE);
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_connect_nonce, tvb, offset+4, 4, TRUE);
+
+       proto_tree_add_text(tree, tvb, 0, 
+                               sizeof(struct ceph_fsid), "fsid: " FMT_INO "." FMT_INO, ((unsigned long long *)fsid->fsid)[0], ((unsigned long long *)fsid->fsid)[1]);
+       
+       offset += sizeof(struct ceph_fsid);
+
+       return offset;
+}
+
+static guint32 dissect_ceph_entity_inst(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_entity_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_entity_addr, tvb, offset, sizeof(struct ceph_entity_addr), TRUE );
+       ceph_entity_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_entity_type, tvb, offset, 4, TRUE);
+       proto_tree_add_item(ceph_entity_tree, hf_ceph_entity_num, tvb, offset+4, 4, TRUE);
+       offset += 8;
+       offset = dissect_ceph_entity_addr(tvb, ceph_entity_tree, offset);
+       return offset;
+}
+
+static guint32 dissect_ceph_footer(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 data_crc)
+{
+       proto_tree *ceph_footer_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+       proto_item *data_crc_item = NULL;
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_footer, tvb, offset, sizeof(struct ceph_msg_footer), TRUE );
+       ceph_footer_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+       proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_flags, tvb, offset, 4, TRUE);
+       proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_front_crc, tvb, offset+4, 4, TRUE);
+       proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_middle_crc, tvb, offset+8, 4, TRUE);
+       data_crc_item = proto_tree_add_item(ceph_footer_tree, hf_ceph_footer_data_crc, tvb, offset+12, 4, TRUE);
+       proto_item_append_text(data_crc_item, " (calculated %x)", data_crc);
+
+       offset += 12;
+       return offset;
+}
+
+static guint32 dissect_ceph_client_connect(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_header_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+       proto_item *ceph_item = proto_tree_get_parent(tree);
+       struct ceph_msg_connect *msg;
+
+       offset = dissect_ceph_banner(tvb, tree, offset);
+
+       ceph_header_tree = proto_item_add_subtree(ceph_item, ett_ceph);
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_header, tvb, offset, -1, TRUE );
+       ceph_header_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+
+       offset = dissect_ceph_entity_addr(tvb, ceph_header_tree, offset);
+#if 0
+       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_host_type, tvb, offset, 4, TRUE);
+       offset += 4;
+       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_global_seq, tvb, offset, 4, TRUE);
+       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_connect_seq, tvb, offset+4, 4, TRUE);
+       proto_tree_add_item(ceph_header_tree, hf_ceph_connect_flags, tvb, offset+8, 1, TRUE);
+       offset += 8;
+#endif
+
+       msg = (struct ceph_msg_connect *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_msg_connect));
+       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, host_type, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, global_seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, connect_seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, protocol_version, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect, msg, flags, "%x");
+
+       return offset;
+}
+
+static guint32 dissect_ceph_server_connect(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_header_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+       proto_item *ceph_item = proto_tree_get_parent(tree);
+       struct ceph_msg_connect_reply *msg;
+
+       offset = dissect_ceph_banner(tvb, tree, offset);
+
+       ceph_header_tree = proto_item_add_subtree(ceph_item, ett_ceph);
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_header, tvb, offset, -1, TRUE );
+       ceph_header_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+
+       offset = dissect_ceph_entity_addr(tvb, ceph_header_tree, offset);
+       offset = dissect_ceph_entity_addr(tvb, ceph_header_tree, offset);
+       msg = (struct ceph_msg_connect_reply *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_msg_connect_reply));
+       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, tag, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, global_seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, connect_seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, protocol_version, "%d");
+       PROTO_ADD_TEXT(struct ceph_msg_connect_reply, msg, flags, "%x");
+
+       return offset;
+}
+
+static guint32 dissect_ceph_file_layout(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       guint32 orig_ofs = offset;
+       struct ceph_file_layout *lo;
+
+       lo = (struct ceph_file_layout *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_file_layout));
+       
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_stripe_unit, "%d");
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_stripe_count, "%d");
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_object_size, "%d");
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_cas_hash, "%d");
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_object_stripe_unit, "%d");
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_pg_preferred, "%d");
+       PROTO_ADD_TEXT(struct ceph_file_layout, lo, fl_pg_pool, "%u");
+
+       return orig_ofs + sizeof(struct ceph_mds_reply_head);
+}
+#if 0
+static int dissect_ceph_filepath(tvbuff_t *tvb, proto_tree *tree, guint32 offset, char **path, guint64 *ino)
+{
+       guint32 len;
+       const char *p = NULL;
+
+       *ino = tvb_get_letoh64(tvb, offset);
+       proto_tree_add_text(tree, tvb, offset, sizeof(*ino), "inode: " FMT_INO, *ino);
+       offset += sizeof(*ino);
+       len = tvb_get_letohl(tvb, offset);
+       proto_tree_add_text(tree, tvb, offset, sizeof(len), "len: %d", len);
+       offset += sizeof(len);
+
+       if (len) {
+               p = tvb_get_ptr(tvb, offset, len);
+               *path = malloc(len+1);
+               if (*path) {
+                       memcpy(*path, p, len);
+                       (*path)[len] = '\0';
+                       proto_tree_add_item(tree, hf_ceph_path, tvb, offset, len, TRUE);
+               }
+       }
+
+       offset += len;
+
+       return offset;
+}
+#endif
+static guint32 dissect_ceph_mon_statfs(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       struct ceph_mon_statfs *req;
+
+       req = (struct ceph_mon_statfs *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mon_statfs));
+       
+       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_mon_statfs, fsid));
+       PROTO_ADD_TEXT(struct ceph_mon_statfs, req, tid, "%lld");
+
+       return offset + sizeof(struct ceph_mon_statfs);
+}
+
+static guint32 dissect_ceph_mon_statfs_reply(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       struct ceph_mon_statfs_reply *req;
+
+       req = (struct ceph_mon_statfs_reply *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mon_statfs_reply));
+       
+       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_mon_statfs_reply, fsid));
+       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, tid, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.kb, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.kb_used, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.kb_avail, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mon_statfs_reply, req, st.num_objects, "%lld");
+
+       return offset + sizeof(struct ceph_mon_statfs_reply);
+}
+#if 0
+static guint32 dissect_ceph_client_osd_getmap(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       struct ceph_osd_getmap *req;
+
+       req = (struct ceph_osd_getmap *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_osd_getmap));
+       
+       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_osd_getmap, fsid));
+       PROTO_ADD_TEXT(struct ceph_osd_getmap, req, start, "%d");
+
+       return offset + sizeof(struct ceph_osd_getmap);
+}
+
+static guint32 dissect_ceph_client_mds_getmap(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+       struct ceph_mds_getmap *req;
+
+       req = (struct ceph_mds_getmap *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_getmap));
+       
+       PROTO_ADD_TEXT(struct ceph_mds_getmap, req, monhdr.have_version, "%lld");
+       dissect_ceph_fsid(tvb, tree, offset + offsetof(struct ceph_mds_getmap, fsid));
+
+       return offset + sizeof(struct ceph_mds_getmap);
+}
+#endif
+static guint32 dissect_ceph_client_mds_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
+{
+       struct ceph_mds_request_head *head;
+       proto_item *item;
+
+       head = (struct ceph_mds_request_head *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_request_head));
+       
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, tid, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, oldest_client_tid, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, mdsmap_epoch, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, num_retry, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, num_fwd, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, num_releases, "%d");
+
+       item = proto_tree_add_item(tree, hf_ceph_mds_op, tvb, offset+offsetof(struct ceph_mds_request_head, op), sizeof(head->op), TRUE);
+       proto_item_append_text(item, " (%s)", ceph_mds_op_name(head->op));
+
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, caller_uid, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_request_head, head, caller_gid, "%d");
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ceph_mds_op_name(head->op));
+       }
+       
+       /* FIXME */
+       switch (head->op) {
+       case CEPH_MDS_OP_LOOKUP:
+//             PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.lookup.mask, "0x%.4x");
+               break;
+       case CEPH_MDS_OP_SETXATTR:
+               break;
+       case CEPH_MDS_OP_SETLAYOUT:
+               dissect_ceph_file_layout(tvb, tree, offset + offsetof(struct ceph_mds_request_head, args.setlayout.layout));
+               break;
+       case CEPH_MDS_OP_SETATTR:
+               break;
+       case CEPH_MDS_OP_MKNOD:
+               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.mknod.mode, "0%.5o");
+               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.mknod.rdev, "%d");
+               break;
+       case CEPH_MDS_OP_OPEN:
+               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.open.flags, "%x");
+               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.open.mode, "0%.5o");
+               break;
+       case CEPH_MDS_OP_MKDIR:
+               PROTO_ADD_TEXT(struct ceph_mds_request_head, head, args.mkdir.mode, "0%.5o");
+               break;
+       case CEPH_MDS_OP_RMXATTR:
+       case CEPH_MDS_OP_LINK:
+       case CEPH_MDS_OP_UNLINK:
+       case CEPH_MDS_OP_RENAME:
+       case CEPH_MDS_OP_RMDIR:
+       case CEPH_MDS_OP_SYMLINK:
+       case CEPH_MDS_OP_LSSNAP:
+       case CEPH_MDS_OP_MKSNAP:
+       case CEPH_MDS_OP_RMSNAP:
+               break;
+       }
+
+       offset += sizeof(struct ceph_mds_request_head);
+#if 0
+       if (head->op == CEPH_MDS_OP_FINDINODE) {
+       
+       } else {
+               guint64 ino1, ino2;
+               char *s1 = NULL, *s2 = NULL;
+
+               offset = dissect_ceph_filepath(tvb, tree, offset, &s1, &ino1);
+               offset = dissect_ceph_filepath(tvb, tree, offset, &s2, &ino2);
+
+               if (check_col(pinfo->cinfo, COL_INFO)) {
+                       if (s1)
+                               col_append_fstr(pinfo->cinfo, COL_INFO, " %s", s1);
+                       if (s2)
+                               col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", s2);
+               }
+
+
+               
+       }
+#endif
+       return offset;
+}
+
+static guint32 dissect_ceph_client_mds_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
+{
+       guint32 orig_ofs = offset;
+       struct ceph_mds_reply_head *head;
+
+       head = (struct ceph_mds_reply_head *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_reply_head));
+       
+       PROTO_ADD_TEXT(struct ceph_mds_reply_head, head, tid, "%lld");
+
+       proto_tree_add_text(tree, tvb, offsetof(struct ceph_mds_reply_head, op), 
+                               sizeof(head->op), "op: %d (%s)", head->op, ceph_mds_op_name(head->op));
+
+       PROTO_ADD_TEXT(struct ceph_mds_reply_head, head, result, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_reply_head, head, mdsmap_epoch, "%d");
+
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ceph_mds_op_name(head->op));
+       }
+
+       return orig_ofs + sizeof(struct ceph_mds_reply_head);
+}
+
+static guint32 dissect_ceph_client_mds_lease_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
+{
+       guint32 orig_ofs = offset;
+       struct ceph_mds_lease *head;
+       static char *lease_action[] = { "", "revoke", "release", "renew" };
+
+       head = (struct ceph_mds_lease *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_lease));
+       
+       PROTO_ADD_TEXT(struct ceph_mds_lease, head, action, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_lease, head, mask, "%.4x");
+       PROTO_ADD_TEXT(struct ceph_mds_lease, head, ino, FMT_INO);
+       PROTO_ADD_TEXT(struct ceph_mds_lease, head, first, "%lld");
+       PROTO_ADD_TEXT(struct ceph_mds_lease, head, last, "%lld");
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               if (head->action < 4) {
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", lease_action[head->action]);
+               }
+       }
+
+       return orig_ofs + sizeof(struct ceph_mds_lease);
+}
+
+static guint32 dissect_ceph_client_mds_caps_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
+{
+       guint32 orig_ofs = offset;
+       struct ceph_mds_caps *head;
+
+       head = (struct ceph_mds_caps *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_mds_caps));
+       
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, op, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, ino, FMT_INO);
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, caps, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, wanted, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, size, "%llu");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, max_size, "%llu");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, truncate_seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, migrate_seq, "%d");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, time_warp_seq, "%u");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, snap_follows, "%llu");
+       PROTO_ADD_TEXT(struct ceph_mds_caps, head, snap_trace_len, "%d");
+
+#define CAPS_REQ_ADD_TIME(field) PROTO_ADD_TIME(tvb, tree, struct ceph_mds_caps, offset, head, field, field) 
+       CAPS_REQ_ADD_TIME(mtime);
+       CAPS_REQ_ADD_TIME(atime);
+       CAPS_REQ_ADD_TIME(ctime);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", ceph_cap_op_name(head->op));
+       }
+
+       return orig_ofs + sizeof(struct ceph_mds_caps);
+}
+
+static guint32 dissect_ceph_client_front(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint16 type)
+{
+       switch (type) {
+       case CEPH_MSG_STATFS:
+               offset = dissect_ceph_mon_statfs(tvb, tree, offset);
+               break;
+       case CEPH_MSG_STATFS_REPLY:
+               offset = dissect_ceph_mon_statfs_reply(tvb, tree, offset);
+               break;
+       case CEPH_MSG_CLIENT_REQUEST: /* mds request */
+               offset = dissect_ceph_client_mds_request(tvb, pinfo, tree, offset);
+               break;
+       case CEPH_MSG_CLIENT_REPLY:
+               offset = dissect_ceph_client_mds_reply(tvb, pinfo, tree, offset);
+               break;
+       case CEPH_MSG_CLIENT_LEASE:
+               offset = dissect_ceph_client_mds_lease_request(tvb, pinfo, tree, offset);
+               break;
+       case CEPH_MSG_CLIENT_CAPS:
+               offset = dissect_ceph_client_mds_caps_request(tvb, pinfo, tree, offset);
+               break;
+       default:
+               break;
+       }
+       return offset;
+}
+
+static guint32 dissect_ceph_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
+{
+       proto_tree *ceph_header_tree = NULL;
+       proto_item *ceph_sub_item = NULL;
+       proto_item *ceph_item = proto_tree_get_parent(tree);
+       guint32 front_len, middle_len, data_len;
+       guint8 tag;
+       guint32 orig_ofs = offset;
+       guint16 type;
+       guint64 seq;
+       struct ceph_msg_header *header;
+    unsigned int data_crc = 0;
+
+       ceph_header_tree = proto_item_add_subtree(ceph_item, ett_ceph);
+
+       ceph_sub_item = proto_tree_add_item( tree, hf_ceph_header, tvb, offset, -1, TRUE );
+       ceph_header_tree = proto_item_add_subtree(ceph_sub_item, ett_ceph);
+
+       tag = tvb_get_guint8(tvb, offset);
+
+       if (tag == CEPH_MSGR_TAG_ACK) {
+               proto_tree_add_item(ceph_header_tree, hf_ceph_hdr_tag, tvb, offset, 1, TRUE);
+               proto_tree_add_item(ceph_header_tree, hf_ceph_hdr_seq_ack, tvb, offset+1, 8, TRUE);
+               offset += ACK_MSG_SIZE;
+       }
+
+       proto_tree_add_item(ceph_header_tree, hf_ceph_hdr_tag, tvb, offset, 1, TRUE);
+       offset++;
+
+       header = (struct ceph_msg_header *)tvb_get_ptr(tvb, offset, sizeof(struct ceph_msg_header));
+
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_seq, header, seq);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_type, header, type);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_priority, header, priority);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_version, header, version);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_front_len, header, front_len);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_middle_len, header, middle_len);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_data_off, header, data_off);
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_data_len, header, data_len);
+       dissect_ceph_entity_inst(tvb, ceph_header_tree, offset + offsetof(struct ceph_msg_header, src));
+       dissect_ceph_entity_inst(tvb, ceph_header_tree, offset + offsetof(struct ceph_msg_header, orig_src));
+       PROTO_ADD_ITEM(ceph_header_tree, struct ceph_msg_header, hf_ceph_hdr_crc, header, crc);
+       
+       offset += sizeof(struct ceph_msg_header);
+       
+       type = TVB_MSG_FIELD(tvb_get_letohl, tvb, orig_ofs, type);
+       seq = TVB_MSG_FIELD(tvb_get_letoh64, tvb, orig_ofs, seq);
+       front_len = TVB_MSG_FIELD(tvb_get_letohs, tvb, orig_ofs, front_len);
+       middle_len = TVB_MSG_FIELD(tvb_get_letohs, tvb, orig_ofs, middle_len);
+       data_len = TVB_MSG_FIELD(tvb_get_letohl, tvb, orig_ofs, data_len);
+
+       if (front_len) {
+       /*      ceph_sub_item = proto_tree_add_item( tree, hf_ceph_front, tvb, offset, front_len, TRUE );
+               offset += front_len; */
+
+               dissect_ceph_client_front(tvb, pinfo, tree, offset, type);
+               offset += front_len;
+       }
+
+       if (middle_len) {
+                offset += middle_len;
+       }
+
+       if (data_len) {
+               char *data;
+               ceph_sub_item = proto_tree_add_item( tree, hf_ceph_data, tvb, offset, data_len, TRUE );
+           data = (char *)tvb_get_ptr(tvb, offset, data_len);
+
+               data_crc = crc32c_le(0, data, data_len);
+
+               offset += data_len;
+       }
+
+       offset = dissect_ceph_footer(tvb, tree, offset, data_crc);
+
+       return offset;
+}
+
+static const char *entity_name_by_type(int type)
+{
+       if (type < 4)
+               return "???";
+
+       if (type < 20)
+               return "mon";
+
+       if (type < 30)
+               return "mds";
+
+       if (type < 50)
+               return "osd";
+
+       if (type < 0x300)
+               return "???";
+
+       if (type < 0x400)
+               return "mds";
+
+       return "???";
+}
+
+static void
+dissect_ceph_client(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+       proto_item *ceph_item = NULL;
+       proto_tree *ceph_tree = NULL;
+       guint16 type = 0;
+       const guchar *ptr;
+       guint32 pos = 0;
+       int have_banner = 0;
+       
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CEPH);
+       /* Clear out stuff in the info column */
+       if(check_col(pinfo->cinfo,COL_INFO)){
+               col_clear(pinfo->cinfo,COL_INFO);
+       }
+
+       ptr = tvb_get_ptr(tvb, pos, 9);
+       if (ptr && memcmp(ptr, "ceph", 4) == 0) {
+               have_banner = 1;
+               pos += 9;
+       }
+
+       // This is not a good way of dissecting packets.  The tvb length should
+       // be sanity checked so we aren't going past the actual size of the buffer.
+       type = tvb_get_guint8( tvb, 4 ); // Get the type byte
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               const char *entity_str = NULL;
+                       
+               if (have_banner) {
+                       if (IS_MON(pinfo))
+                               entity_str = MON_STR;
+                       else 
+                               entity_str = "???";
+
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] Connect Request", entity_str);
+               } else {
+                       type = TVB_MSG_FIELD(tvb_get_letohl, tvb, 0, type);
+                       entity_str = entity_name_by_type(type);
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] %s",
+                       entity_str,
+                       val_to_str(type, packettypenames, "Unknown Type:0x%02x"));
+               }
+       }
+
+       if (tree) { /* we are being asked for details */
+               guint32 offset = 0;
+
+               ceph_item = proto_tree_add_item(tree, proto_ceph, tvb, 0, -1, TRUE);
+               ceph_tree = proto_item_add_subtree(ceph_item, ett_ceph);
+               if (have_banner) { /* this is a connect message */
+                       offset = dissect_ceph_client_connect(tvb, ceph_tree, offset);
+               } else {
+                       offset = dissect_ceph_generic(tvb, pinfo, ceph_tree, offset);
+               }
+       }
+}
+
+static void
+dissect_ceph_server(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+       proto_item *ceph_item = NULL;
+       proto_tree *ceph_tree = NULL;
+       guint16 type = 0;
+       const guchar *ptr;
+       guint32 pos = 0;
+       int have_banner = 0;
+
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CEPH);
+       /* Clear out stuff in the info column */
+       if(check_col(pinfo->cinfo,COL_INFO)){
+               col_clear(pinfo->cinfo,COL_INFO);
+       }
+
+       ptr = tvb_get_ptr(tvb, pos, 9);
+       if (ptr && memcmp(ptr, "ceph", 4) == 0) {
+               have_banner = 1;
+               pos += 9;
+       }
+
+       // This is not a good way of dissecting packets.  The tvb length should
+       // be sanity checked so we aren't going past the actual size of the buffer.
+       type = tvb_get_guint8( tvb, 4 ); // Get the type byte
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               const char *entity_str;
+                       if (IS_MON(pinfo))
+                               entity_str = MON_STR;
+                       else 
+                               entity_str = "???";
+               if (have_banner) {
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] Connect Response", entity_str);
+               } else {
+                       type = TVB_MSG_FIELD(tvb_get_letohl, tvb, 0, type);
+                       entity_str = entity_name_by_type(type);
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] %s",
+                       entity_str,
+                       val_to_str(type, packettypenames, "Unknown Type:0x%02x"));
+               }
+       }
+
+       if (tree) { /* we are being asked for details */
+               guint32 offset = 0;
+
+               ceph_item = proto_tree_add_item(tree, proto_ceph, tvb, 0, -1, TRUE);
+               ceph_tree = proto_item_add_subtree(ceph_item, ett_ceph);
+
+               if (have_banner) {
+                       offset = dissect_ceph_server_connect(tvb, ceph_tree, offset);
+               } else {
+                       offset = dissect_ceph_generic(tvb, pinfo, ceph_tree, offset);
+               }
+       }
+}
+
+static void
+dissect_ceph_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       if (DEST_PORT_CEPH)
+               dissect_ceph_client(tvb, pinfo, tree);
+       else
+               dissect_ceph_server(tvb, pinfo, tree);
+}              
+
+static guint dissect_ceph_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       guint32 offset = 0;
+
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CEPH);
+       /* Clear out stuff in the info column */
+       if(check_col(pinfo->cinfo,COL_INFO)){
+               col_clear(pinfo->cinfo,COL_INFO);
+               col_add_fstr(pinfo->cinfo, COL_INFO, "Ack");
+       }
+       if (tree) {
+               proto_tree_add_item(tree, proto_ceph, tvb, 0, 5, TRUE);
+               proto_tree_add_item(tree, hf_ceph_hdr_tag, tvb, offset, 1, TRUE);
+               proto_tree_add_item(tree, hf_ceph_hdr_seq_ack, tvb, offset+1, 8, TRUE);
+               offset += 9;
+       }
+
+       return offset;
+}
+
+/* determine PDU length of protocol ceph */
+static guint get_ceph_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
+{
+       const char *ptr;
+       guint32 len;
+       guint32 pos = 0;
+
+       ptr = tvb_get_ptr(tvb, offset, /* sizeof(CEPH_BANNER) */tvb->length-offset);
+       if (ptr && memcmp(ptr, "ceph", 4) == 0) {
+               if (DEST_PORT_CEPH) {
+                       len = sizeof(CEPH_BANNER) - 1 +
+                               sizeof(struct ceph_entity_addr) +
+                               sizeof(struct ceph_msg_connect);
+               } else
+                       len = sizeof(CEPH_BANNER) - 1 +
+                               sizeof(struct ceph_entity_addr) +
+                               sizeof(struct ceph_entity_addr) +
+                               sizeof(struct ceph_msg_connect_reply);
+
+               return len;
+       }
+
+       if (*ptr == CEPH_MSGR_TAG_ACK)
+               pos = ACK_MSG_SIZE;
+
+       len = pos + (guint)1 + sizeof(struct ceph_msg_header) +
+               TVB_MSG_FIELD(tvb_get_letohl, tvb, offset, front_len) + 
+               TVB_MSG_FIELD(tvb_get_letohl, tvb, offset, data_len) + 
+               sizeof(struct ceph_msg_footer);
+       
+       if (!*ptr)
+               return 0;
+       return len;
+}
+
+
+static void dissect_ceph(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       const char *ptr;
+
+       ptr = tvb_get_ptr(tvb, 0, 6);
+
+       if ((*ptr == CEPH_MSGR_TAG_MSG) || 
+            (memcmp(ptr, CEPH_BANNER, 4) == 0) || 
+          ((ptr[0] == CEPH_MSGR_TAG_ACK) && (ptr[5] == CEPH_MSGR_TAG_MSG))
+       )  {
+               tcp_dissect_pdus(tvb, pinfo, tree, TRUE, TVB_MSG_HEADER_POS(src),
+                       get_ceph_message_len, dissect_ceph_message);
+       } else {
+               dissect_ceph_acks(tvb, pinfo, tree);
+       }
+}
+