2 * Routines for clique reliable multicast dissector
3 * Copyright 2007, Collabora Ltd.
4 * @author: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
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.
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;
73 /* Unreliable packets */
74 PACKET_TYPE_WHOIS_REQUEST
= 0,
75 PACKET_TYPE_WHOIS_REPLY
,
76 PACKET_TYPE_REPAIR_REQUEST
,
78 /* Reliable packets */
79 FIRST_RELIABLE_PACKET
= 0xf,
80 PACKET_TYPE_DATA
= FIRST_RELIABLE_PACKET
,
81 /* No data just acknowledgement */
83 /* Some nodes failed */
85 /* Start a joining attempt */
86 PACKET_TYPE_ATTEMPT_JOIN
,
89 /* Leaving now, bye */
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" },
109 { PACKET_TYPE_JOIN
, "Join" },
110 /* Leaving now, bye */
111 { PACKET_TYPE_BYE
, "Bye" },
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
)
126 count
= tvb_get_guint8(tvb
, offset
);
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
);
133 for (i
= 0; i
< count
; i
++, offset
+= 4)
134 proto_tree_add_item(tree
, hf_header_sender
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
138 dissect_data_packet(proto_tree
*clique_rm_tree
, tvbuff_t
*tvb
, int offset
)
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
);
149 proto_tree_add_item(tree
, hf_clique_rm_data_stream_id
, tvb
, offset
, 2,
153 proto_tree_add_item(tree
, hf_clique_rm_data_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
157 proto_tree_add_item(tree
, hf_clique_rm_data_data
, tvb
, offset
,
158 tvb_length_remaining(tvb
, offset
), ENC_NA
);
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
;
169 count
= tvb_get_guint8(tvb
, offset
);
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
);
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
);
193 /* Code to actually dissect the packets */
195 dissect_reliable_packet(proto_tree
*clique_rm_tree
, guint8 type
, tvbuff_t
*tvb
, int offset
)
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,
204 offset
+= dissect_depends(clique_rm_tree
, tvb
, offset
);
208 case PACKET_TYPE_DATA
:
209 dissect_data_packet(clique_rm_tree
, tvb
, offset
);
211 case PACKET_TYPE_NO_DATA
:
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
);
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
);
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
);
225 case PACKET_TYPE_BYE
:
233 dissect_unreliable_packet(proto_tree
*clique_rm_tree
, guint8 type
, tvbuff_t
*tvb
, int offset
)
238 return; /* no col_..() or expert...() calls in following */
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
);
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
);
251 proto_tree_add_item(clique_rm_tree
,
252 hf_clique_rm_whois_reply_name
, tvb
, offset
, len
, ENC_ASCII
|ENC_NA
);
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
);
259 proto_tree_add_item(clique_rm_tree
,
260 hf_clique_rm_repair_request_packet_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
262 case PACKET_TYPE_SESSION
:
263 dissect_depends(clique_rm_tree
, tvb
, offset
);
272 dissect_clique_rm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
275 proto_tree
*clique_rm_tree
;
281 if (tvb_length(tvb
) < 12)
284 qword
= tvb_get_ntoh48(tvb
,0);
285 /* ASCII str for 'Clique' = 0x436c69717565 */
286 if(qword
!= G_GINT64_CONSTANT (0x436c69717565U
))
290 version
= tvb_get_guint8(tvb
, offset
);
295 type
= tvb_get_guint8(tvb
, 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 */
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,
312 proto_tree_add_item(clique_rm_tree
, hf_clique_rm_type
, tvb
, offset
, 1,
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
,
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
);
329 dissect_unreliable_packet(clique_rm_tree
, type
, tvb
, offset
);
336 /* Register the protocol with Wireshark */
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,
349 { &hf_clique_rm_type
,
350 { "Type", "clique_rm.type",
351 FT_UINT8
, BASE_HEX
, VALS(packet_type_vals
), 0x0,
354 { &hf_clique_rm_sender
,
355 { "Sender", "clique_rm.sender",
356 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
359 { &hf_clique_rm_packet_id
,
360 { "Packet id", "clique_rm.packet_id",
361 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
364 { &hf_clique_rm_depends
,
365 { "Depends", "clique_rm.depends",
366 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
369 { &hf_clique_rm_depend_sender
,
370 { "Sender", "clique_rm.depends.sender",
371 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
374 { &hf_clique_rm_depend_packet_id
,
375 { "Packet id", "clique_rm.depends.packet_id",
376 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
379 { &hf_clique_rm_failures
,
380 { "Failures", "clique_rm.failures",
381 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
384 { &hf_clique_rm_failures_senders
,
385 { "Sender", "clique_rm.failures.sender",
386 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
389 { &hf_clique_rm_attempt_join
,
390 { "New attempt join senders", "clique_rm.attempt_join",
391 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
394 { &hf_clique_rm_attempt_join_senders
,
395 { "Sender", "clique_rm.attempt_join.sender",
396 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
399 { &hf_clique_rm_join_failures
,
400 { "Join failures", "clique_rm.join_failures",
401 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
404 { &hf_clique_rm_join_failures_senders
,
405 { "Sender", "clique_rm.join_failures.sender",
406 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
409 { &hf_clique_rm_data_flags
,
410 { "Data flags", "clique_rm.data.flags",
411 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
414 { &hf_clique_rm_data_size
,
415 { "Data total size", "clique_rm.data.size",
416 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
419 { &hf_clique_rm_data_stream_id
,
420 { "Data stream id", "clique_rm.data.stream_id",
421 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
424 { &hf_clique_rm_data_data
,
425 { "Raw data", "clique_rm.data.data",
426 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
429 { &hf_clique_rm_whois_request_id
,
430 { "Whois request id", "clique_rm.whois_request.id",
431 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
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,
439 { &hf_clique_rm_whois_reply_name
,
440 { "Whois reply name", "clique_rm.whois_reply.name",
441 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
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,
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,
458 /* Setup protocol subtree array */
459 static gint
*ett
[] = {
461 &ett_clique_rm_depends
,
462 &ett_clique_rm_depends_item
,
464 &ett_clique_rm_failures
,
465 &ett_clique_rm_join_failures
,
466 &ett_clique_rm_attempt_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
));
481 proto_reg_handoff_clique_rm(void)
483 heur_dissector_add("udp", dissect_clique_rm
, proto_clique_rm
);