2 * Routines for MBMS synchronisation protocol dissection
3 * Copyright 2012, David Wei <davidwei@lavabit.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
33 #include <wsutil/crc6.h>
40 /* Initialize the protocol and registered fields */
41 static int proto_sync
= -1;
42 static int hf_sync_type
= -1;
43 static int hf_sync_spare4
= -1;
44 static int hf_sync_timestamp
= -1;
45 static int hf_sync_packet_nr
= -1;
46 static int hf_sync_elapsed_octet_ctr
= -1;
47 static int hf_sync_total_nr_of_packet
= -1;
48 static int hf_sync_total_nr_of_octet
= -1;
49 static int hf_sync_header_crc
= -1;
50 static int hf_sync_payload_crc
= -1;
51 static int hf_sync_length_of_packet
= -1;
53 /* Initialize the subtree pointers */
54 static gint ett_sync
= -1;
56 static dissector_handle_t sync_handle
;
57 static dissector_handle_t ip_handle
;
59 static const value_string sync_type_vals
[] = {
60 { 0, "Synchronisation frame without payload" },
61 { 1, "User data with synchronisation frame for uncompressed headers" },
62 { 2, "User data with synchronisation frame for compressed headers" },
63 { 3, "Synchronisation frame with Length of Packets" },
64 /* 4-15 reserved for future PDU type extensions */
69 dissect_sync(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
71 proto_item
*ti
, *item
;
72 proto_tree
*sync_tree
;
74 guint16 packet_nr
, packet_len1
, packet_len2
;
75 guint32 timestamp
, total_nr_of_packet
;
79 type
= tvb_get_guint8(tvb
, offset
) >> 4;
80 spare
= tvb_get_guint8(tvb
, offset
) & 0x0F;
82 /* Heuristics to check if packet is really MBMS sync */
87 if ( type
== 0 && tvb_length(tvb
) < 18) {
89 } else if ( type
== 1 && tvb_length(tvb
) < 11 ) {
91 } else if ( type
== 3 && tvb_length(tvb
) < 19 ) {
95 if ( (type
!= 2) && (spare
!= 0) )
99 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SYNC");
100 col_set_str(pinfo
->cinfo
, COL_INFO
, "MBMS synchronisation protocol");
102 /* Ugly, but necessary to get the correct length for type 3 */
103 packet_nr
= tvb_get_ntohs(tvb
, offset
+3);
106 /* The length varies depending on PDU type */
109 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, TYPE_0_LEN
, ENC_NA
);
112 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, TYPE_1_LEN
, ENC_NA
);
115 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, TYPE_2_LEN
+ (spare
& 0x01 ? 40 : 20), ENC_NA
);
118 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0,
119 TYPE_3_LEN
+ (gint16
)(packet_nr
% 2 == 0 ?
120 1.5*packet_nr
: 1.5*(packet_nr
-1)+2),
124 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, -1, ENC_NA
);
128 sync_tree
= proto_item_add_subtree(ti
, ett_sync
);
130 /* Octet 1 - PDU Type */
131 proto_tree_add_item(sync_tree
, hf_sync_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
132 proto_tree_add_item(sync_tree
, hf_sync_spare4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
135 /* Octet 2 - Time Stamp */
136 timestamp
= tvb_get_ntohs(tvb
, offset
) * 10;
137 item
= proto_tree_add_uint(sync_tree
, hf_sync_timestamp
, tvb
, offset
, 2, timestamp
);
138 proto_item_append_text(item
, " ms");
141 /* Octet 4 - Packet Number */
142 proto_tree_add_uint(sync_tree
, hf_sync_packet_nr
, tvb
, offset
, 2, packet_nr
+1);
145 /* Octet 6 - Elapsed Octet Counter */
146 proto_tree_add_item(sync_tree
, hf_sync_elapsed_octet_ctr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
151 /* SYNC PDU Type 0 */
152 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_packet
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
154 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_octet
, tvb
, offset
, 5, ENC_BIG_ENDIAN
);
156 proto_tree_add_item(sync_tree
, hf_sync_header_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
160 /* SYNC PDU Type 1 */
161 /* XXX - Calculate the CRC and check against this value? */
162 item
= proto_tree_add_item(sync_tree
, hf_sync_header_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
163 proto_tree_add_item(sync_tree
, hf_sync_payload_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
164 proto_item_append_text(item
, " [Calculated CRC 0x%x]",
165 crc6_compute(tvb_get_ptr(tvb
, 0, offset
),offset
));
168 /* XXX - The payload may not always be present? */
169 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
170 /* XXX - The payload may not always be IP? */
171 call_dissector(ip_handle
, next_tvb
, pinfo
, tree
);
174 /* SYNC PDU Type 2 */
175 proto_tree_add_text(tree
, tvb
, offset
, -1, "SYNC PDU type 2 unsupported");
178 /* SYNC PDU Type 3 */
179 total_nr_of_packet
= tvb_get_ntoh24(tvb
, offset
);
180 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_packet
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
182 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_octet
, tvb
, offset
, 5, ENC_BIG_ENDIAN
);
184 proto_tree_add_item(sync_tree
, hf_sync_header_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
185 proto_tree_add_item(sync_tree
, hf_sync_payload_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
188 if (offset
< (gint
)tvb_reported_length(tvb
)) {
191 if (total_nr_of_packet
!= 0 && packet_nr
% 2 == 0) {
192 /* Even number of packets */
193 for (i
= 1; i
< packet_nr
; i
+=2, offset
+=3) {
194 packet_len1
= tvb_get_bits16(tvb
, offset
*8, 12, ENC_BIG_ENDIAN
);
195 packet_len2
= tvb_get_bits16(tvb
, offset
*8+12, 12, ENC_BIG_ENDIAN
);
196 proto_tree_add_string_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
, 2, "", "Length of Packet %u : %hu", i
, packet_len1
);
197 proto_tree_add_string_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
+1, 2, "", "Length of Packet %u : %hu", i
+1, packet_len2
);
200 /* Odd number of packets */
201 for (i
= 1; i
< packet_nr
; i
+=2, offset
+=3) {
202 packet_len1
= tvb_get_bits16(tvb
, offset
*8, 12, ENC_BIG_ENDIAN
);
203 packet_len2
= tvb_get_bits16(tvb
, offset
*8+12, 12, ENC_BIG_ENDIAN
);
204 proto_tree_add_string_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
, 2, "", "Length of Packet %u : %hu", i
, packet_len1
);
205 proto_tree_add_string_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
+1, 2, "", "Length of Packet %u : %hu", i
+1, packet_len2
);
207 packet_len1
= tvb_get_bits16(tvb
, offset
*8, 12, ENC_BIG_ENDIAN
);
208 proto_tree_add_string_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
, 2, "", "Length of Packet %u : %hu", packet_nr
, packet_len1
);
210 proto_tree_add_item(sync_tree
, hf_sync_spare4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
216 proto_tree_add_text(tree
, tvb
, offset
, -1, "Unknown SYNC PDU type");
221 return tvb_length(tvb
);
226 proto_register_sync(void)
228 static hf_register_info hf_sync
[] = {
230 { "PDU Type", "sync.type",
231 FT_UINT8
, BASE_DEC
, VALS(sync_type_vals
), 0xF0,
235 { "Spare", "sync.spare",
236 FT_UINT8
, BASE_DEC
, NULL
, 0x0F,
239 { &hf_sync_timestamp
,
240 { "Timestamp", "sync.timestamp",
241 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
242 "Relative time value for the starting time of a synchronisation sequence within the synchronisation period.", HFILL
}
244 { &hf_sync_packet_nr
,
245 { "Packet Number", "sync.packet_nr",
246 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
247 "Number of elapsed SYNC PDUs cumulatively within the synchronisation sequence.", HFILL
}
249 { &hf_sync_elapsed_octet_ctr
,
250 { "Elapsed Octet Counter", "sync.elapsed_octet_ctr",
251 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
252 "Number of elapsed cumulative octets cumulatively within one synchronisation sequence.", HFILL
}
254 { &hf_sync_total_nr_of_packet
,
255 { "Total Number of Packet", "sync.total_nr_of_packet",
256 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
257 "Cumulatively the number of the packets for the MBMS service within one synchronisation period.", HFILL
}
259 { &hf_sync_total_nr_of_octet
,
260 { "Total Number of Octet", "sync.total_nr_of_octet",
261 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
262 "Cumulatively the number of the octets for the MBMS service within one synchronisation period.", HFILL
}
264 { &hf_sync_header_crc
,
265 { "Header CRC", "sync.header_crc",
266 FT_UINT8
, BASE_HEX
, NULL
, 0xFC,
269 { &hf_sync_payload_crc
,
270 { "Payload CRC", "sync.payload_crc",
271 FT_UINT16
, BASE_HEX
, NULL
, 0x3FF,
274 { &hf_sync_length_of_packet
,
275 { "Length of Packet", "sync.length_of_packet",
276 FT_STRING
, BASE_NONE
, NULL
, 0x0,
281 static gint
*ett_sync_array
[] = {
285 proto_sync
= proto_register_protocol("MBMS synchronisation protocol", "SYNC", "sync");
287 proto_register_field_array(proto_sync
, hf_sync
, array_length(hf_sync
));
288 proto_register_subtree_array(ett_sync_array
, array_length(ett_sync_array
));
290 sync_handle
= new_register_dissector("sync", dissect_sync
, proto_sync
);
294 proto_reg_handoff_sync(void)
296 ip_handle
= find_dissector("ip");
298 dissector_add_handle("udp.port", sync_handle
);
302 * Editor modelines - http://www.wireshark.org/tools/modelines.html
307 * indent-tabs-mode: nil
310 * vi: set shiftwidth=4 tabstop=8 expandtab:
311 * :indentSize=4:tabSize=8:noTabs=true: