HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-clique-rm.c
blobcba3d0cc820c999fb95184cccb0520ec84e5e473
1 /* packet-clique_rm.c
2 * Routines for clique reliable multicast dissector
3 * Copyright 2007, Collabora Ltd.
4 * @author: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <glib.h>
30 #include <epan/packet.h>
32 void proto_register_clique_rm(void);
33 void proto_reg_handoff_clique_rm(void);
35 /* Initialize the protocol and registered fields */
36 static int proto_clique_rm = -1;
38 static int hf_clique_rm_version = -1;
39 static int hf_clique_rm_type = -1;
40 static int hf_clique_rm_sender = -1;
41 static int hf_clique_rm_packet_id = -1;
42 static int hf_clique_rm_depends = -1;
43 static int hf_clique_rm_depend_sender = -1;
44 static int hf_clique_rm_depend_packet_id = -1;
45 static int hf_clique_rm_failures = -1;
46 static int hf_clique_rm_failures_senders = -1;
47 static int hf_clique_rm_attempt_join = -1;
48 static int hf_clique_rm_attempt_join_senders = -1;
49 static int hf_clique_rm_join_failures = -1;
50 static int hf_clique_rm_join_failures_senders = -1;
51 static int hf_clique_rm_data_flags = -1;
52 static int hf_clique_rm_data_size = -1;
53 static int hf_clique_rm_data_stream_id = -1;
54 static int hf_clique_rm_data_data = -1;
55 static int hf_clique_rm_whois_request_id = -1;
56 static int hf_clique_rm_whois_reply_name = -1;
57 static int hf_clique_rm_whois_reply_name_length = -1;
58 static int hf_clique_rm_repair_request_sender_id = -1;
59 static int hf_clique_rm_repair_request_packet_id = -1;
61 /* Initialize the subtree pointers */
62 static gint ett_clique_rm = -1;
63 static gint ett_clique_rm_data = -1;
64 static gint ett_clique_rm_depends = -1;
65 static gint ett_clique_rm_depends_item = -1;
66 static gint ett_clique_rm_failures = -1;
67 static gint ett_clique_rm_join_failures = -1;
68 static gint ett_clique_rm_attempt_join = -1;
69 static gint ett_clique_rm_join = -1;
71 /* Packet types */
72 typedef enum {
73 /* Unreliable packets */
74 PACKET_TYPE_WHOIS_REQUEST = 0,
75 PACKET_TYPE_WHOIS_REPLY,
76 PACKET_TYPE_REPAIR_REQUEST,
77 PACKET_TYPE_SESSION,
78 /* Reliable packets */
79 FIRST_RELIABLE_PACKET = 0xf,
80 PACKET_TYPE_DATA = FIRST_RELIABLE_PACKET,
81 /* No data just acknowledgement */
82 PACKET_TYPE_NO_DATA,
83 /* Some nodes failed */
84 PACKET_TYPE_FAILURE,
85 /* Start a joining attempt */
86 PACKET_TYPE_ATTEMPT_JOIN,
87 /* The real join */
88 PACKET_TYPE_JOIN,
89 /* Leaving now, bye */
90 PACKET_TYPE_BYE,
91 PACKET_TYPE_INVALID
92 } GibberRMulticastPacketType;
94 #define IS_RELIABLE(type) (type >= FIRST_RELIABLE_PACKET)
96 static const value_string packet_type_vals[] = {
97 { PACKET_TYPE_WHOIS_REQUEST, "Whois request" },
98 { PACKET_TYPE_WHOIS_REPLY, "Whois reply" },
99 { PACKET_TYPE_REPAIR_REQUEST, "Repair request"},
100 { PACKET_TYPE_SESSION, "Session" },
101 { PACKET_TYPE_DATA, "Data" },
102 /* No data just acknowledgement */
103 { PACKET_TYPE_NO_DATA, "No data" },
104 /* Some nodes failed */
105 { PACKET_TYPE_FAILURE, "Failure" },
106 /* Start a joining attempt */
107 { PACKET_TYPE_ATTEMPT_JOIN, "Attempt join" },
108 /* The real join */
109 { PACKET_TYPE_JOIN, "Join" },
110 /* Leaving now, bye */
111 { PACKET_TYPE_BYE, "Bye" },
113 { 0, NULL }
116 static void
117 dissect_sender_array(proto_tree *clique_rm_tree, int hf_header, gint ett_header,
118 int hf_header_sender, tvbuff_t *tvb, int offset)
120 guint i, count;
121 int len;
122 proto_item *ti;
123 proto_tree *tree;
126 count = tvb_get_guint8(tvb, offset);
127 len = 1 + 4 * count;
128 ti = proto_tree_add_item(clique_rm_tree, hf_header, tvb, offset, 1, ENC_BIG_ENDIAN);
129 proto_item_set_len(ti, len);
130 tree = proto_item_add_subtree(ti, ett_header);
131 offset++;
133 for (i = 0; i < count; i++, offset += 4)
134 proto_tree_add_item(tree, hf_header_sender, tvb, offset, 4, ENC_BIG_ENDIAN);
137 static void
138 dissect_data_packet(proto_tree *clique_rm_tree, tvbuff_t *tvb, int offset)
140 proto_item *ti;
141 proto_tree *tree;
143 ti = proto_tree_add_text(clique_rm_tree, tvb, offset, -1, "Data");
144 tree = proto_item_add_subtree(ti, ett_clique_rm_data);
146 proto_tree_add_item(tree, hf_clique_rm_data_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
147 offset += 1;
149 proto_tree_add_item(tree, hf_clique_rm_data_stream_id, tvb, offset, 2,
150 ENC_BIG_ENDIAN);
151 offset += 2;
153 proto_tree_add_item(tree, hf_clique_rm_data_size, tvb, offset, 4, ENC_BIG_ENDIAN);
154 offset += 4;
157 proto_tree_add_item(tree, hf_clique_rm_data_data, tvb, offset,
158 tvb_length_remaining(tvb, offset), ENC_NA);
161 static int
162 dissect_depends(proto_tree *clique_rm_tree, tvbuff_t *tvb, int offset)
164 proto_item *ti, *depend_item;
165 proto_tree *tree, *depend_tree;
166 guint ii, count;
167 int len;
169 count = tvb_get_guint8(tvb, offset);
170 len = 1 + count * 8;
172 ti = proto_tree_add_item(clique_rm_tree,
173 hf_clique_rm_depends, tvb, offset, 1, ENC_BIG_ENDIAN);
174 proto_item_set_len(ti, len);
175 offset += 1;
177 tree = proto_item_add_subtree(ti, ett_clique_rm_depends);
178 for (ii = 0; ii < count; ii++)
180 depend_item = proto_tree_add_text(tree, tvb, offset, 8, "Depend item %d", ii+1);
181 depend_tree = proto_item_add_subtree(depend_item, ett_clique_rm_depends_item);
183 proto_tree_add_item(depend_tree, hf_clique_rm_depend_sender,
184 tvb, offset, 4, ENC_BIG_ENDIAN);
185 proto_tree_add_item(depend_tree, hf_clique_rm_depend_packet_id,
186 tvb, offset+4, 4, ENC_BIG_ENDIAN);
187 offset += 8;
190 return len;
193 /* Code to actually dissect the packets */
194 static void
195 dissect_reliable_packet(proto_tree *clique_rm_tree, guint8 type, tvbuff_t *tvb, int offset)
197 if (!clique_rm_tree)
198 return; /* no col_..() or expert...() calls in following */
200 proto_tree_add_item(clique_rm_tree, hf_clique_rm_packet_id, tvb, offset, 4,
201 ENC_BIG_ENDIAN);
202 offset += 4;
204 offset += dissect_depends(clique_rm_tree, tvb, offset);
206 switch (type)
208 case PACKET_TYPE_DATA:
209 dissect_data_packet(clique_rm_tree, tvb, offset);
210 break;
211 case PACKET_TYPE_NO_DATA:
212 break;
213 case PACKET_TYPE_FAILURE:
214 dissect_sender_array(clique_rm_tree, hf_clique_rm_failures,
215 ett_clique_rm_failures, hf_clique_rm_failures_senders, tvb, offset);
216 break;
217 case PACKET_TYPE_ATTEMPT_JOIN:
218 dissect_sender_array(clique_rm_tree, hf_clique_rm_attempt_join,
219 ett_clique_rm_attempt_join, hf_clique_rm_attempt_join_senders, tvb, offset);
220 break;
221 case PACKET_TYPE_JOIN:
222 dissect_sender_array(clique_rm_tree, hf_clique_rm_join_failures,
223 ett_clique_rm_join_failures, hf_clique_rm_join_failures_senders, tvb, offset);
224 break;
225 case PACKET_TYPE_BYE:
226 break;
227 default:
228 break;
232 static void
233 dissect_unreliable_packet(proto_tree *clique_rm_tree, guint8 type, tvbuff_t *tvb, int offset)
235 guint len;
237 if (!clique_rm_tree)
238 return; /* no col_..() or expert...() calls in following */
240 switch (type)
242 case PACKET_TYPE_WHOIS_REQUEST:
243 proto_tree_add_item(clique_rm_tree,
244 hf_clique_rm_whois_request_id, tvb, offset, 4, ENC_BIG_ENDIAN);
245 break;
246 case PACKET_TYPE_WHOIS_REPLY:
247 len = tvb_get_guint8(tvb, offset);
248 proto_tree_add_item(clique_rm_tree,
249 hf_clique_rm_whois_reply_name_length, tvb, offset, 1, ENC_BIG_ENDIAN);
250 offset += 1;
251 proto_tree_add_item(clique_rm_tree,
252 hf_clique_rm_whois_reply_name, tvb, offset, len, ENC_ASCII|ENC_NA);
253 break;
254 case PACKET_TYPE_REPAIR_REQUEST:
255 proto_tree_add_item(clique_rm_tree,
256 hf_clique_rm_repair_request_sender_id, tvb, offset, 4, ENC_BIG_ENDIAN);
257 offset += 4;
259 proto_tree_add_item(clique_rm_tree,
260 hf_clique_rm_repair_request_packet_id, tvb, offset, 4, ENC_BIG_ENDIAN);
261 break;
262 case PACKET_TYPE_SESSION:
263 dissect_depends(clique_rm_tree, tvb, offset);
264 break;
265 default:
266 break;
271 static gboolean
272 dissect_clique_rm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
274 proto_item *ti;
275 proto_tree *clique_rm_tree;
276 guint8 version;
277 guint8 type;
278 int offset = 0;
279 guint64 qword;
281 if (tvb_length(tvb) < 12)
282 return FALSE;
284 qword = tvb_get_ntoh48(tvb,0);
285 /* ASCII str for 'Clique' = 0x436c69717565 */
286 if(qword != G_GINT64_CONSTANT (0x436c69717565U))
287 return FALSE;
288 offset += 6;
290 version = tvb_get_guint8(tvb, offset);
291 if (version != 1)
292 return FALSE;
293 offset++;
295 type = tvb_get_guint8(tvb, offset);
296 offset++;
298 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Clique-rm");
299 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
300 val_to_str(type, packet_type_vals, "Unknown (0x%02x)"));
302 /* rewind back to just behind the prefix */
303 offset = 6;
305 ti = proto_tree_add_item(tree, proto_clique_rm, tvb, 0, -1, ENC_NA);
306 clique_rm_tree = proto_item_add_subtree(ti, ett_clique_rm);
308 proto_tree_add_item(clique_rm_tree, hf_clique_rm_version, tvb, offset, 1,
309 ENC_BIG_ENDIAN);
310 offset++;
312 proto_tree_add_item(clique_rm_tree, hf_clique_rm_type, tvb, offset, 1,
313 ENC_BIG_ENDIAN);
314 offset++;
316 col_append_fstr(pinfo->cinfo, COL_INFO, ", sender: 0x%x",
317 tvb_get_ntohl(tvb, offset));
319 proto_tree_add_item(clique_rm_tree, hf_clique_rm_sender, tvb, offset,
320 4, ENC_BIG_ENDIAN);
321 offset += 4;
323 if (IS_RELIABLE(type)) {
324 col_append_fstr(pinfo->cinfo, COL_INFO, ", id: 0x%x",
325 tvb_get_ntohl(tvb, offset));
327 dissect_reliable_packet(clique_rm_tree, type, tvb, offset);
328 } else {
329 dissect_unreliable_packet(clique_rm_tree, type, tvb, offset);
332 return TRUE;
336 /* Register the protocol with Wireshark */
338 void
339 proto_register_clique_rm(void)
342 /* Setup list of header fields See Section 1.6.1 for details*/
343 static hf_register_info hf[] = {
344 { &hf_clique_rm_version,
345 { "Version", "clique_rm.version",
346 FT_UINT8, BASE_DEC, NULL, 0x0,
347 NULL, HFILL }
349 { &hf_clique_rm_type,
350 { "Type", "clique_rm.type",
351 FT_UINT8, BASE_HEX, VALS(packet_type_vals), 0x0,
352 NULL, HFILL }
354 { &hf_clique_rm_sender,
355 { "Sender", "clique_rm.sender",
356 FT_UINT32, BASE_HEX, NULL, 0x0,
357 NULL, HFILL }
359 { &hf_clique_rm_packet_id,
360 { "Packet id", "clique_rm.packet_id",
361 FT_UINT32, BASE_HEX, NULL, 0x0,
362 NULL, HFILL }
364 { &hf_clique_rm_depends,
365 { "Depends", "clique_rm.depends",
366 FT_UINT8, BASE_HEX, NULL, 0x0,
367 NULL, HFILL }
369 { &hf_clique_rm_depend_sender,
370 { "Sender", "clique_rm.depends.sender",
371 FT_UINT32, BASE_HEX, NULL, 0x0,
372 NULL, HFILL }
374 { &hf_clique_rm_depend_packet_id,
375 { "Packet id", "clique_rm.depends.packet_id",
376 FT_UINT32, BASE_HEX, NULL, 0x0,
377 NULL, HFILL }
379 { &hf_clique_rm_failures,
380 { "Failures", "clique_rm.failures",
381 FT_UINT8, BASE_HEX, NULL, 0x0,
382 NULL, HFILL }
384 { &hf_clique_rm_failures_senders,
385 { "Sender", "clique_rm.failures.sender",
386 FT_UINT32, BASE_HEX, NULL, 0x0,
387 NULL, HFILL }
389 { &hf_clique_rm_attempt_join,
390 { "New attempt join senders", "clique_rm.attempt_join",
391 FT_UINT8, BASE_HEX, NULL, 0x0,
392 NULL, HFILL }
394 { &hf_clique_rm_attempt_join_senders,
395 { "Sender", "clique_rm.attempt_join.sender",
396 FT_UINT32, BASE_HEX, NULL, 0x0,
397 NULL, HFILL }
399 { &hf_clique_rm_join_failures,
400 { "Join failures", "clique_rm.join_failures",
401 FT_UINT8, BASE_HEX, NULL, 0x0,
402 NULL, HFILL }
404 { &hf_clique_rm_join_failures_senders,
405 { "Sender", "clique_rm.join_failures.sender",
406 FT_UINT32, BASE_HEX, NULL, 0x0,
407 NULL, HFILL }
409 { &hf_clique_rm_data_flags,
410 { "Data flags", "clique_rm.data.flags",
411 FT_UINT8, BASE_HEX, NULL, 0x0,
412 NULL, HFILL }
414 { &hf_clique_rm_data_size,
415 { "Data total size", "clique_rm.data.size",
416 FT_UINT32, BASE_DEC, NULL, 0x0,
417 NULL, HFILL }
419 { &hf_clique_rm_data_stream_id,
420 { "Data stream id", "clique_rm.data.stream_id",
421 FT_UINT16, BASE_HEX, NULL, 0x0,
422 NULL, HFILL }
424 { &hf_clique_rm_data_data,
425 { "Raw data", "clique_rm.data.data",
426 FT_BYTES, BASE_NONE, NULL, 0x0,
427 NULL, HFILL }
429 { &hf_clique_rm_whois_request_id,
430 { "Whois request id", "clique_rm.whois_request.id",
431 FT_UINT32, BASE_HEX, NULL, 0x0,
432 NULL, HFILL }
434 { &hf_clique_rm_whois_reply_name_length,
435 { "Whois reply name length", "clique_rm.whois_reply.length",
436 FT_UINT8, BASE_DEC, NULL, 0x0,
437 NULL, HFILL }
439 { &hf_clique_rm_whois_reply_name,
440 { "Whois reply name", "clique_rm.whois_reply.name",
441 FT_STRINGZ, BASE_NONE, NULL, 0x0,
442 NULL, HFILL }
444 { &hf_clique_rm_repair_request_sender_id,
445 { "Repair request for sender",
446 "clique_rm.repair_request.sender_id",
447 FT_UINT32, BASE_HEX, NULL, 0x0,
448 NULL, HFILL }
450 { &hf_clique_rm_repair_request_packet_id,
451 { "Repair request for packet",
452 "clique_rm.repair_request.packet_id",
453 FT_UINT32, BASE_HEX, NULL, 0x0,
454 NULL, HFILL }
458 /* Setup protocol subtree array */
459 static gint *ett[] = {
460 &ett_clique_rm,
461 &ett_clique_rm_depends,
462 &ett_clique_rm_depends_item,
463 &ett_clique_rm_data,
464 &ett_clique_rm_failures,
465 &ett_clique_rm_join_failures,
466 &ett_clique_rm_attempt_join,
467 &ett_clique_rm_join,
470 /* Register the protocol name and description */
471 proto_clique_rm = proto_register_protocol(
472 "Clique Reliable Multicast Protocol", "Clique-rm", "clique-rm");
474 /* Required function calls to register the header fields and subtrees used */
475 proto_register_field_array(proto_clique_rm, hf, array_length(hf));
476 proto_register_subtree_array(ett, array_length(ett));
480 void
481 proto_reg_handoff_clique_rm(void)
483 heur_dissector_add("udp", dissect_clique_rm, proto_clique_rm);