2 * Routines for MBMS synchronisation protocol dissection
3 * Copyright 2012, David Wei <davidwei@lavabit.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/expert.h>
18 #include <epan/crc6-tvb.h>
19 #include <epan/unit_strings.h>
21 #include <wsutil/array.h>
28 void proto_register_sync(void);
29 void proto_reg_handoff_sync(void);
31 /* Initialize the protocol and registered fields */
32 static int proto_sync
;
33 static int hf_sync_type
;
34 static int hf_sync_spare4
;
35 static int hf_sync_timestamp
;
36 static int hf_sync_packet_nr
;
37 static int hf_sync_elapsed_octet_ctr
;
38 static int hf_sync_total_nr_of_packet
;
39 static int hf_sync_total_nr_of_octet
;
40 static int hf_sync_header_crc
;
41 static int hf_sync_payload_crc
;
42 static int hf_sync_length_of_packet
;
44 /* Initialize the subtree pointers */
47 static expert_field ei_sync_pdu_type2
;
48 static expert_field ei_sync_type
;
50 static dissector_handle_t sync_handle
;
51 static dissector_handle_t ip_handle
;
53 static const value_string sync_type_vals
[] = {
54 { 0, "Synchronisation frame without payload" },
55 { 1, "User data with synchronisation frame for uncompressed headers" },
56 { 2, "User data with synchronisation frame for compressed headers" },
57 { 3, "Synchronisation frame with Length of Packets" },
58 /* 4-15 reserved for future PDU type extensions */
63 dissect_sync(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
65 proto_item
*ti
, *item
, *type_item
;
66 proto_tree
*sync_tree
;
68 uint16_t packet_nr
, packet_len1
, packet_len2
;
69 uint32_t timestamp
, total_nr_of_packet
;
73 type
= tvb_get_uint8(tvb
, offset
) >> 4;
74 spare
= tvb_get_uint8(tvb
, offset
) & 0x0F;
76 /* Heuristics to check if packet is really MBMS sync */
81 if ( type
== 0 && tvb_captured_length(tvb
) < 18) {
83 } else if ( type
== 1 && tvb_captured_length(tvb
) < 11 ) {
85 } else if ( type
== 3 && tvb_captured_length(tvb
) < 19 ) {
89 if ( (type
!= 2) && (spare
!= 0) )
93 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SYNC");
94 col_set_str(pinfo
->cinfo
, COL_INFO
, "MBMS synchronisation protocol");
96 /* Ugly, but necessary to get the correct length for type 3 */
97 packet_nr
= tvb_get_ntohs(tvb
, offset
+3) + 1;
99 /* The length varies depending on PDU type */
102 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, TYPE_0_LEN
, ENC_NA
);
105 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, TYPE_1_LEN
, ENC_NA
);
108 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, TYPE_2_LEN
+ (spare
& 0x01 ? 40 : 20), ENC_NA
);
111 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0,
112 TYPE_3_LEN
+ (int16_t)(packet_nr
% 2 == 0 ?
113 1.5*packet_nr
: 1.5*(packet_nr
-1)+2),
117 ti
= proto_tree_add_item(tree
, proto_sync
, tvb
, 0, -1, ENC_NA
);
121 sync_tree
= proto_item_add_subtree(ti
, ett_sync
);
123 /* Octet 1 - PDU Type */
124 type_item
= proto_tree_add_item(sync_tree
, hf_sync_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
125 proto_tree_add_item(sync_tree
, hf_sync_spare4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
128 /* Octet 2 - Time Stamp */
129 timestamp
= tvb_get_ntohs(tvb
, offset
) * 10;
130 proto_tree_add_uint(sync_tree
, hf_sync_timestamp
, tvb
, offset
, 2, timestamp
);
133 /* Octet 4 - Packet Number */
134 proto_tree_add_uint(sync_tree
, hf_sync_packet_nr
, tvb
, offset
, 2, packet_nr
);
137 /* Octet 6 - Elapsed Octet Counter */
138 proto_tree_add_item(sync_tree
, hf_sync_elapsed_octet_ctr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
143 /* SYNC PDU Type 0 */
144 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_packet
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
146 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_octet
, tvb
, offset
, 5, ENC_BIG_ENDIAN
);
148 proto_tree_add_item(sync_tree
, hf_sync_header_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
152 /* SYNC PDU Type 1 */
153 /* XXX - Calculate the CRC and check against this value? */
154 item
= proto_tree_add_item(sync_tree
, hf_sync_header_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
155 proto_tree_add_item(sync_tree
, hf_sync_payload_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
156 proto_item_append_text(item
, " [Calculated CRC 0x%x]",
157 crc6_compute_tvb(tvb
, offset
));
160 /* XXX - The payload may not always be present? */
161 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
162 /* XXX - The payload may not always be IP? */
163 call_dissector(ip_handle
, next_tvb
, pinfo
, tree
);
166 /* SYNC PDU Type 2 */
167 expert_add_info(pinfo
, ti
, &ei_sync_pdu_type2
);
170 /* SYNC PDU Type 3 */
171 total_nr_of_packet
= tvb_get_ntoh24(tvb
, offset
);
172 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_packet
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
174 proto_tree_add_item(sync_tree
, hf_sync_total_nr_of_octet
, tvb
, offset
, 5, ENC_BIG_ENDIAN
);
176 proto_tree_add_item(sync_tree
, hf_sync_header_crc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
177 proto_tree_add_item(sync_tree
, hf_sync_payload_crc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
180 if (offset
< (int)tvb_reported_length(tvb
)) {
183 if (total_nr_of_packet
!= 0 && packet_nr
% 2 == 0) {
184 /* Even number of packets */
185 for (i
= 1; i
< packet_nr
; i
+=2, offset
+=3) {
186 packet_len1
= tvb_get_bits16(tvb
, offset
*8, 12, ENC_BIG_ENDIAN
);
187 packet_len2
= tvb_get_bits16(tvb
, offset
*8+12, 12, ENC_BIG_ENDIAN
);
188 proto_tree_add_uint_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
, 2, packet_len1
, "Length of Packet %u : %hu", i
, packet_len1
);
189 proto_tree_add_uint_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
+1, 2, packet_len2
, "Length of Packet %u : %hu", i
+1, packet_len2
);
192 /* Odd 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_uint_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
, 2, packet_len1
, "Length of Packet %u : %hu", i
, packet_len1
);
197 proto_tree_add_uint_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
+1, 2, packet_len2
, "Length of Packet %u : %hu", i
+1, packet_len2
);
199 packet_len1
= tvb_get_bits16(tvb
, offset
*8, 12, ENC_BIG_ENDIAN
);
200 proto_tree_add_uint_format(sync_tree
, hf_sync_length_of_packet
, tvb
, offset
, 2, packet_len1
, "Length of Packet %u : %hu", packet_nr
, packet_len1
);
202 proto_tree_add_item(sync_tree
, hf_sync_spare4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
208 expert_add_info(pinfo
, type_item
, &ei_sync_type
);
212 return tvb_captured_length(tvb
);
217 proto_register_sync(void)
219 static hf_register_info hf_sync
[] = {
221 { "PDU Type", "sync.type",
222 FT_UINT8
, BASE_DEC
, VALS(sync_type_vals
), 0xF0,
226 { "Spare", "sync.spare",
227 FT_UINT8
, BASE_DEC
, NULL
, 0x0F,
230 { &hf_sync_timestamp
,
231 { "Timestamp", "sync.timestamp",
232 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_milliseconds
), 0x0,
233 "Relative time value for the starting time of a synchronisation sequence within the synchronisation period.", HFILL
}
235 { &hf_sync_packet_nr
,
236 { "Packet Number", "sync.packet_nr",
237 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
238 "Number of elapsed SYNC PDUs cumulatively within the synchronisation sequence.", HFILL
}
240 { &hf_sync_elapsed_octet_ctr
,
241 { "Elapsed Octet Counter", "sync.elapsed_octet_ctr",
242 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
243 "Number of elapsed cumulative octets cumulatively within one synchronisation sequence.", HFILL
}
245 { &hf_sync_total_nr_of_packet
,
246 { "Total Number of Packet", "sync.total_nr_of_packet",
247 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
248 "Cumulatively the number of the packets for the MBMS service within one synchronisation period.", HFILL
}
250 { &hf_sync_total_nr_of_octet
,
251 { "Total Number of Octet", "sync.total_nr_of_octet",
252 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
253 "Cumulatively the number of the octets for the MBMS service within one synchronisation period.", HFILL
}
255 { &hf_sync_header_crc
,
256 { "Header CRC", "sync.header_crc",
257 FT_UINT8
, BASE_HEX
, NULL
, 0xFC,
260 { &hf_sync_payload_crc
,
261 { "Payload CRC", "sync.payload_crc",
262 FT_UINT16
, BASE_HEX
, NULL
, 0x03FF,
265 { &hf_sync_length_of_packet
,
266 { "Length of Packet", "sync.length_of_packet",
267 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
272 static int *ett_sync_array
[] = {
276 static ei_register_info ei
[] = {
277 { &ei_sync_pdu_type2
, { "sync.pdu_type2", PI_UNDECODED
, PI_WARN
, "SYNC PDU type 2 unsupported", EXPFILL
}},
278 { &ei_sync_type
, { "sync.type.unknown", PI_PROTOCOL
, PI_WARN
, "Unknown SYNC PDU type", EXPFILL
}},
281 expert_module_t
* expert_sync
;
283 proto_sync
= proto_register_protocol("MBMS synchronisation protocol", "SYNC", "sync");
285 proto_register_field_array(proto_sync
, hf_sync
, array_length(hf_sync
));
286 proto_register_subtree_array(ett_sync_array
, array_length(ett_sync_array
));
287 expert_sync
= expert_register_protocol(proto_sync
);
288 expert_register_field_array(expert_sync
, ei
, array_length(ei
));
290 sync_handle
= register_dissector("sync", dissect_sync
, proto_sync
);
294 proto_reg_handoff_sync(void)
296 ip_handle
= find_dissector_add_dependency("ip", proto_sync
);
298 dissector_add_for_decode_as_with_preference("udp.port", sync_handle
);
302 * Editor modelines - https://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: