From 52f51a24e23be5a10b3d831f49ee2a1983ec7ff5 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 17 Jul 2012 10:15:27 -0700 Subject: [PATCH] wireshar/ceph/packet-ceph.c: fix eol Removing extra char from dos eol format. Signed-off-by: Yehuda Sadeh --- wireshark/ceph/packet-ceph.c | 2266 +++++++++++++++++----------------- 1 file changed, 1133 insertions(+), 1133 deletions(-) diff --git a/wireshark/ceph/packet-ceph.c b/wireshark/ceph/packet-ceph.c index 754478db0d5..b552ffc4fff 100644 --- a/wireshark/ceph/packet-ceph.c +++ b/wireshark/ceph/packet-ceph.c @@ -1,1133 +1,1133 @@ -/* 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 -#include -#include -#include - -#include "types.h" - -#include "crc32c.h" - -#include - -#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); - } -} - +/* 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 +#include +#include +#include + +#include "types.h" + +#include "crc32c.h" + +#include + +#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); + } +} + -- 2.47.3