Fix for bug 5422:
[obnox/wireshark/wip.git] / epan / dissectors / packet-db-lsp.c
1 /* packet-db-lsp.c
2  * Routines for Dropbox LAN sync Protocol
3  *
4  * Copyright 2010, Stig Bjorlykke <stig@bjorlykke.org>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <glib.h>
32
33 #include <epan/packet.h>
34 #include <epan/asn1.h>
35 #include <epan/prefs.h>
36 #include <epan/expert.h>
37
38 #include "packet-tcp.h"
39 #include "packet-x509af.h"
40
41 #define PNAME  "Dropbox LAN sync Protocol"
42 #define PSNAME "DB-LSP"
43 #define PFNAME "db-lsp"
44
45 #define PNAME_DISC  "Dropbox LAN sync Discovery Protocol"
46 #define PSNAME_DISC "DB-LSP-DISC"
47 #define PFNAME_DISC "db-lsp-disc"
48
49 #define DB_LSP_PORT  17500
50
51 static int proto_db_lsp = -1;
52 static int proto_db_lsp_disc = -1;
53
54 static int hf_type = -1;
55 static int hf_magic = -1;
56 static int hf_length = -1;
57 static int hf_opvalue = -1;
58 static int hf_data = -1;
59 static int hf_value = -1;
60 static int hf_text = -1;
61
62 static gint ett_db_lsp = -1;
63
64 /* desegmentation of tcp payload */
65 static gboolean db_lsp_desegment = TRUE;
66
67 #define TYPE_CONFIG   0x16
68 #define TYPE_DATA     0x17
69
70 static const value_string type_vals[] = {
71   { TYPE_CONFIG,    "Configuration" },
72   { TYPE_DATA,      "Data" },
73   { 0, NULL }
74 };
75
76 #define OP_CERT       0x0B
77
78 static const value_string op_vals[] = {
79   { OP_CERT,   "Certificate" },
80   { 0, NULL }
81 };
82
83 static void
84 dissect_db_lsp_pdu (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
85 {
86   proto_tree *db_lsp_tree;
87   proto_item *db_lsp_item;
88   gint        offset = 0;
89   guint8      type, opvalue;
90   guint16     magic, length;
91
92   col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME);
93   col_set_str (pinfo->cinfo, COL_INFO, PNAME);
94
95   db_lsp_item = proto_tree_add_item (tree, proto_db_lsp, tvb, offset, -1, FALSE);
96   db_lsp_tree = proto_item_add_subtree (db_lsp_item, ett_db_lsp);
97
98   type = tvb_get_guint8 (tvb, offset);
99   proto_tree_add_item (db_lsp_tree, hf_type, tvb, offset, 1, FALSE);
100   offset += 1;
101
102   if (type == 0x80) {
103     /* Two unknown bytes */
104     offset += 2;
105   }
106
107   magic = tvb_get_ntohs (tvb, offset);
108   proto_tree_add_item (db_lsp_tree, hf_magic, tvb, offset, 2, FALSE);
109   offset += 2;
110
111   length = tvb_get_ntohs (tvb, offset);
112   proto_tree_add_item (db_lsp_tree, hf_length, tvb, offset, 2, FALSE);
113   offset += 2;
114
115   if (magic != 0x0301 || length > tvb_length_remaining (tvb, offset)) {
116     /* Probably an unknown packet */
117     /* expert_add_info_format (pinfo, db_lsp_item, PI_UNDECODED, PI_WARN, "Unknown packet"); */
118     return;
119   }
120
121   if (type == TYPE_CONFIG) {
122     opvalue = tvb_get_guint8 (tvb, offset);
123     proto_tree_add_item (db_lsp_tree, hf_opvalue, tvb, offset, 1, FALSE);
124
125     if (opvalue == OP_CERT) {
126       /* X509 Certificate */
127       tvbuff_t *cert_tvb = tvb_new_subset (tvb, offset+10, length-10, length-10);
128       dissect_x509af_Certificate_PDU (cert_tvb, pinfo, db_lsp_tree);
129     } else {
130       proto_tree_add_item (db_lsp_tree, hf_value, tvb, offset, length, FALSE);
131     }
132   } else if (type == TYPE_DATA) {
133     proto_tree_add_item (db_lsp_tree, hf_data, tvb, offset, length, FALSE);
134   } else {
135     proto_tree_add_item (db_lsp_tree, hf_value, tvb, offset, length, FALSE);
136   }
137   offset += length;
138
139   proto_item_append_text (db_lsp_item, ", Type: %d, Length: %d", type, length);
140   proto_item_set_len (db_lsp_item, length + 5);
141 }
142
143 static guint
144 get_db_lsp_pdu_len (packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
145 {
146   if (tvb_get_ntohs (tvb, offset + 1) != 0x0301) {
147     /* Unknown data, eat remaining data for this frame */
148     return tvb_length_remaining (tvb, offset);
149   }
150
151   return tvb_get_ntohs (tvb, offset + 3) + 5;
152 }
153
154 static void
155 dissect_db_lsp_tcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
156 {
157   tcp_dissect_pdus (tvb, pinfo, tree, db_lsp_desegment, 5,
158                     get_db_lsp_pdu_len, dissect_db_lsp_pdu);
159 }
160
161 static void
162 dissect_db_lsp_disc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
163 {
164   proto_tree *db_lsp_tree;
165   proto_item *db_lsp_item;
166   gint        offset = 0;
167
168   col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME_DISC);
169   col_set_str (pinfo->cinfo, COL_INFO, PNAME_DISC);
170
171   db_lsp_item = proto_tree_add_item (tree, proto_db_lsp_disc, tvb, offset, -1, FALSE);
172   db_lsp_tree = proto_item_add_subtree (db_lsp_item, ett_db_lsp);
173
174   proto_tree_add_item (db_lsp_tree, hf_text, tvb, offset, -1, FALSE);
175 }
176
177 void
178 proto_register_db_lsp (void)
179 {
180   static hf_register_info hf[] = {
181     { &hf_type,
182       { "Type", "db-lsp.type",
183         FT_UINT8, BASE_DEC_HEX, VALS(type_vals), 0x0,
184         NULL, HFILL } },
185
186     { &hf_magic,
187       { "Magic", "db-lsp.magic",
188         FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
189         "Magic number", HFILL } },
190
191     { &hf_length,
192       { "Length", "db-lsp.length",
193         FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
194         "Length in bytes", HFILL } },
195
196     { &hf_opvalue,
197       { "OP Value", "db-lsp.op",
198         FT_UINT8, BASE_DEC_HEX, VALS(op_vals), 0x0,
199         NULL, HFILL } },
200
201     { &hf_value,
202       { "Value", "db-lsp.value",
203         FT_BYTES, BASE_NONE, NULL, 0x0,
204         NULL, HFILL } },
205
206     { &hf_data,
207       { "Data", "db-lsp.data",
208         FT_BYTES, BASE_NONE, NULL, 0x0,
209         NULL, HFILL } },
210
211     { &hf_text,
212       { "Text", "db-lsp.text",
213         FT_STRING, BASE_NONE, NULL, 0x0,
214         NULL, HFILL } },
215   };
216
217   static gint *ett[] = {
218     &ett_db_lsp,
219   };
220
221   module_t *db_lsp_module;
222
223   proto_db_lsp = proto_register_protocol (PNAME, PSNAME, PFNAME);
224   proto_db_lsp_disc = proto_register_protocol (PNAME_DISC, PSNAME_DISC, PFNAME_DISC);
225   register_dissector ("db-lsp.tcp", dissect_db_lsp_tcp, proto_db_lsp);
226   register_dissector ("db-lsp.udp", dissect_db_lsp_disc, proto_db_lsp_disc);
227
228   proto_register_field_array (proto_db_lsp, hf, array_length (hf));
229   proto_register_subtree_array (ett, array_length (ett));
230
231   /* Register our configuration options */
232   db_lsp_module = prefs_register_protocol (proto_db_lsp, NULL);
233
234   prefs_register_bool_preference (db_lsp_module, "desegment_pdus",
235                                   "Reassemble PDUs spanning multiple TCP segments",
236                                   "Whether the LAN sync dissector should reassemble PDUs"
237                                   " spanning multiple TCP segments."
238                                   " To use this option, you must also enable \"Allow subdissectors"
239                                   " to reassemble TCP streams\" in the TCP protocol settings.",
240                                   &db_lsp_desegment);
241 }
242
243 void
244 proto_reg_handoff_db_lsp (void)
245 {
246   dissector_handle_t db_lsp_tcp_handle;
247   dissector_handle_t db_lsp_udp_handle;
248
249   db_lsp_tcp_handle = find_dissector ("db-lsp.tcp");
250   db_lsp_udp_handle = find_dissector ("db-lsp.udp");
251
252   dissector_add ("tcp.port", DB_LSP_PORT, db_lsp_tcp_handle);
253   dissector_add ("udp.port", DB_LSP_PORT, db_lsp_udp_handle);
254 }
255
256 /*
257  * Editor modelines
258  *
259  * Local Variables:
260  * c-basic-offset: 2
261  * tab-width: 8
262  * indent-tabs-mode: nil
263  * End:
264  *
265  * ex: set shiftwidth=2 tabstop=8 expandtab
266  * :indentSize=2:tabSize=8:noTabs=true:
267  */