epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-sync.c
blob2d38c61a5082e582a62ffb2194c52a1f5b844647
1 /* packet-sync.c
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
11 * Ref 3GPP TS 25.446
14 #include "config.h"
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>
23 #define TYPE_0_LEN 17
24 #define TYPE_1_LEN 11
25 #define TYPE_2_LEN 12
26 #define TYPE_3_LEN 19
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 */
45 static int ett_sync;
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 */
59 { 0, NULL}
62 static int
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;
67 uint8_t type, spare;
68 uint16_t packet_nr, packet_len1, packet_len2;
69 uint32_t timestamp, total_nr_of_packet;
70 int offset = 0;
71 tvbuff_t *next_tvb;
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 */
77 #if 0
78 if ( type > 3 )
79 return 0;
81 if ( type == 0 && tvb_captured_length(tvb) < 18) {
82 return 0;
83 } else if ( type == 1 && tvb_captured_length(tvb) < 11 ) {
84 return 0;
85 } else if ( type == 3 && tvb_captured_length(tvb) < 19 ) {
86 return 0;
89 if ( (type != 2) && (spare != 0) )
90 return 0;
91 #endif
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 */
100 switch (type) {
101 case 0:
102 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, TYPE_0_LEN, ENC_NA);
103 break;
104 case 1:
105 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, TYPE_1_LEN, ENC_NA);
106 break;
107 case 2:
108 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, TYPE_2_LEN + (spare & 0x01 ? 40 : 20), ENC_NA);
109 break;
110 case 3:
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),
114 ENC_NA);
115 break;
116 default:
117 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, -1, ENC_NA);
118 break;
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);
126 offset++;
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);
131 offset += 2;
133 /* Octet 4 - Packet Number */
134 proto_tree_add_uint(sync_tree, hf_sync_packet_nr, tvb, offset, 2, packet_nr);
135 offset += 2;
137 /* Octet 6 - Elapsed Octet Counter */
138 proto_tree_add_item(sync_tree, hf_sync_elapsed_octet_ctr, tvb, offset, 4, ENC_BIG_ENDIAN);
139 offset += 4;
141 switch (type) {
142 case 0:
143 /* SYNC PDU Type 0 */
144 proto_tree_add_item(sync_tree, hf_sync_total_nr_of_packet, tvb, offset, 3, ENC_BIG_ENDIAN);
145 offset += 3;
146 proto_tree_add_item(sync_tree, hf_sync_total_nr_of_octet, tvb, offset, 5, ENC_BIG_ENDIAN);
147 offset += 5;
148 proto_tree_add_item(sync_tree, hf_sync_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
149 offset++;
150 break;
151 case 1:
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));
158 offset += 2;
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);
164 break;
165 case 2:
166 /* SYNC PDU Type 2 */
167 expert_add_info(pinfo, ti, &ei_sync_pdu_type2);
168 break;
169 case 3:
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);
173 offset += 3;
174 proto_tree_add_item(sync_tree, hf_sync_total_nr_of_octet, tvb, offset, 5, ENC_BIG_ENDIAN);
175 offset += 5;
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);
178 offset += 2;
180 if (offset < (int)tvb_reported_length(tvb)) {
181 int i;
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);
191 } else {
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);
201 offset++;
202 proto_tree_add_item(sync_tree, hf_sync_spare4, tvb, offset, 1, ENC_BIG_ENDIAN);
206 break;
207 default:
208 expert_add_info(pinfo, type_item, &ei_sync_type);
209 break;
212 return tvb_captured_length(tvb);
216 void
217 proto_register_sync(void)
219 static hf_register_info hf_sync[] = {
220 { &hf_sync_type,
221 { "PDU Type", "sync.type",
222 FT_UINT8, BASE_DEC, VALS(sync_type_vals), 0xF0,
223 NULL, HFILL }
225 { &hf_sync_spare4,
226 { "Spare", "sync.spare",
227 FT_UINT8, BASE_DEC, NULL, 0x0F,
228 NULL, HFILL }
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,
258 NULL, HFILL }
260 { &hf_sync_payload_crc,
261 { "Payload CRC", "sync.payload_crc",
262 FT_UINT16, BASE_HEX, NULL, 0x03FF,
263 NULL, HFILL }
265 { &hf_sync_length_of_packet,
266 { "Length of Packet", "sync.length_of_packet",
267 FT_UINT16, BASE_DEC, NULL, 0x0,
268 NULL, HFILL }
272 static int *ett_sync_array[] = {
273 &ett_sync
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);
293 void
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
304 * Local variables:
305 * c-basic-offset: 4
306 * tab-width: 8
307 * indent-tabs-mode: nil
308 * End:
310 * vi: set shiftwidth=4 tabstop=8 expandtab:
311 * :indentSize=4:tabSize=8:noTabs=true: