/* packet-db-lsp.c * Routines for Dropbox LAN sync Protocol * * Copyright 2010, Stig Bjorlykke * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include "packet-tcp.h" #include "packet-x509af.h" #define PNAME "Dropbox LAN sync Protocol" #define PSNAME "DB-LSP" #define PFNAME "db-lsp" #define PNAME_DISC "Dropbox LAN sync Discovery Protocol" #define PSNAME_DISC "DB-LSP-DISC" #define PFNAME_DISC "db-lsp-disc" #define DB_LSP_PORT 17500 void proto_register_db_lsp(void); void proto_reg_handoff_db_lsp(void); static int proto_db_lsp = -1; static int proto_db_lsp_disc = -1; static int hf_type = -1; static int hf_magic = -1; static int hf_length = -1; static int hf_opvalue = -1; static int hf_data = -1; static int hf_value = -1; static int hf_text = -1; static gint ett_db_lsp = -1; static heur_dissector_list_t heur_subdissector_list; static dissector_handle_t db_lsp_tcp_handle; static dissector_handle_t db_lsp_udp_handle; /* Use heuristic */ static gboolean try_heuristic = TRUE; /* desegmentation of tcp payload */ static gboolean db_lsp_desegment = TRUE; #define TYPE_CONFIG 0x16 #define TYPE_DATA 0x17 static const value_string type_vals[] = { { TYPE_CONFIG, "Configuration" }, { TYPE_DATA, "Data" }, { 0, NULL } }; #define OP_CERT 0x0B static const value_string op_vals[] = { { OP_CERT, "Certificate" }, { 0, NULL } }; static int dissect_db_lsp_pdu (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_tree *db_lsp_tree; proto_item *db_lsp_item; gint offset = 0; guint8 type, opvalue; guint16 magic, length; col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME); col_set_str (pinfo->cinfo, COL_INFO, PNAME); db_lsp_item = proto_tree_add_item (tree, proto_db_lsp, tvb, offset, -1, ENC_NA); db_lsp_tree = proto_item_add_subtree (db_lsp_item, ett_db_lsp); type = tvb_get_guint8 (tvb, offset); proto_tree_add_item (db_lsp_tree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (type == 0x80) { /* Two unknown bytes */ offset += 2; } magic = tvb_get_ntohs (tvb, offset); proto_tree_add_item (db_lsp_tree, hf_magic, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; length = tvb_get_ntohs (tvb, offset); proto_tree_add_item (db_lsp_tree, hf_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (magic != 0x0301 || length > tvb_reported_length_remaining (tvb, offset)) { /* Probably an unknown packet */ /* expert_add_info_format (pinfo, db_lsp_item, PI_UNDECODED, PI_WARN, "Unknown packet"); */ return 0; } if (type == TYPE_CONFIG) { opvalue = tvb_get_guint8 (tvb, offset); proto_tree_add_item (db_lsp_tree, hf_opvalue, tvb, offset, 1, ENC_BIG_ENDIAN); if (opvalue == OP_CERT) { /* X509 Certificate */ tvbuff_t *cert_tvb = tvb_new_subset_length (tvb, offset+10, length-10); dissect_x509af_Certificate_PDU (cert_tvb, pinfo, db_lsp_tree, NULL); } else { proto_tree_add_item (db_lsp_tree, hf_value, tvb, offset, length, ENC_NA); } } else if (type == TYPE_DATA) { proto_tree_add_item (db_lsp_tree, hf_data, tvb, offset, length, ENC_NA); } else { proto_tree_add_item (db_lsp_tree, hf_value, tvb, offset, length, ENC_NA); } /*offset += length;*/ proto_item_append_text (db_lsp_item, ", Type: %d, Length: %d", type, length); proto_item_set_len (db_lsp_item, length + 5); return tvb_reported_length(tvb); } static guint get_db_lsp_pdu_len (packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { if (tvb_get_ntohs (tvb, offset + 1) != 0x0301) { /* Unknown data, eat remaining data for this frame */ return tvb_reported_length_remaining (tvb, offset); } return tvb_get_ntohs (tvb, offset + 3) + 5; } static int dissect_db_lsp_tcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { tcp_dissect_pdus (tvb, pinfo, tree, db_lsp_desegment, 5, get_db_lsp_pdu_len, dissect_db_lsp_pdu, data); return tvb_reported_length(tvb); } static int dissect_db_lsp_disc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_tree *db_lsp_tree; proto_item *db_lsp_item; gint offset = 0; heur_dtbl_entry_t *hdtbl_entry; proto_tree *data_subtree; col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME_DISC); col_set_str (pinfo->cinfo, COL_INFO, PNAME_DISC); db_lsp_item = proto_tree_add_item (tree, proto_db_lsp_disc, tvb, offset, -1, ENC_NA); db_lsp_tree = proto_item_add_subtree (db_lsp_item, ett_db_lsp); /* try the heuristic dissectors */ if (try_heuristic) { data_subtree = proto_item_add_subtree(db_lsp_item, ett_db_lsp); if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, data_subtree, &hdtbl_entry, NULL)) { return tvb_captured_length(tvb); } } /* heuristic failed. Print remaining bytes as text */ proto_tree_add_item (db_lsp_tree, hf_text, tvb, offset, -1, ENC_ASCII|ENC_NA); return tvb_captured_length(tvb); } void proto_register_db_lsp (void) { static hf_register_info hf[] = { { &hf_type, { "Type", "db-lsp.type", FT_UINT8, BASE_DEC_HEX, VALS(type_vals), 0x0, NULL, HFILL } }, { &hf_magic, { "Magic", "db-lsp.magic", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, "Magic number", HFILL } }, { &hf_length, { "Length", "db-lsp.length", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, "Length in bytes", HFILL } }, { &hf_opvalue, { "OP Value", "db-lsp.op", FT_UINT8, BASE_DEC_HEX, VALS(op_vals), 0x0, NULL, HFILL } }, { &hf_value, { "Value", "db-lsp.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_data, { "Data", "db-lsp.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_text, { "Text", "db-lsp.text", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, }; static gint *ett[] = { &ett_db_lsp, }; module_t *db_lsp_module; proto_db_lsp = proto_register_protocol (PNAME, PSNAME, PFNAME); proto_db_lsp_disc = proto_register_protocol (PNAME_DISC, PSNAME_DISC, PFNAME_DISC); db_lsp_tcp_handle = register_dissector ("db-lsp.tcp", dissect_db_lsp_tcp, proto_db_lsp); db_lsp_udp_handle = register_dissector ("db-lsp.udp", dissect_db_lsp_disc, proto_db_lsp_disc); heur_subdissector_list = register_heur_dissector_list("db-lsp", proto_db_lsp); proto_register_field_array (proto_db_lsp, hf, array_length (hf)); proto_register_subtree_array (ett, array_length (ett)); /* Register our configuration options */ db_lsp_module = prefs_register_protocol (proto_db_lsp, NULL); prefs_register_bool_preference (db_lsp_module, "desegment_pdus", "Reassemble PDUs spanning multiple TCP segments", "Whether the LAN sync dissector should reassemble PDUs" " spanning multiple TCP segments." " To use this option, you must also enable \"Allow subdissectors" " to reassemble TCP streams\" in the TCP protocol settings.", &db_lsp_desegment); prefs_register_bool_preference(db_lsp_module, "try_heuristic", "Try heuristic sub-dissectors", "Try to decode the payload using an heuristic sub-dissector", &try_heuristic); } void proto_reg_handoff_db_lsp (void) { dissector_add_uint_with_preference("tcp.port", DB_LSP_PORT, db_lsp_tcp_handle); dissector_add_uint_with_preference("udp.port", DB_LSP_PORT, db_lsp_udp_handle); } /* * Editor modelines * * Local Variables: * c-basic-offset: 2 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=2 tabstop=8 expandtab: * :indentSize=2:tabSize=8:noTabs=true: */