HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-sync.c
blobf0587291b1a1b72090a61bc7f89c7de71435addd
1 /* packet-sync.c
2 * Routines for MBMS synchronisation protocol dissection
3 * Copyright 2012, David Wei <davidwei@lavabit.com>
5 * $Id$
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.
25 * Ref 3GPP TS 25.446
28 #include "config.h"
30 #include <glib.h>
32 #include <epan/packet.h>
33 #include <wsutil/crc6.h>
35 #define TYPE_0_LEN 17
36 #define TYPE_1_LEN 11
37 #define TYPE_2_LEN 12
38 #define TYPE_3_LEN 19
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 */
65 { 0, NULL}
68 static int
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;
73 guint8 type, spare;
74 guint16 packet_nr, packet_len1, packet_len2;
75 guint32 timestamp, total_nr_of_packet;
76 int offset = 0;
77 tvbuff_t *next_tvb;
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 */
83 #if 0
84 if ( type > 3 )
85 return 0;
87 if ( type == 0 && tvb_length(tvb) < 18) {
88 return 0;
89 } else if ( type == 1 && tvb_length(tvb) < 11 ) {
90 return 0;
91 } else if ( type == 3 && tvb_length(tvb) < 19 ) {
92 return 0;
95 if ( (type != 2) && (spare != 0) )
96 return 0;
97 #endif
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);
105 if (tree) {
106 /* The length varies depending on PDU type */
107 switch (type) {
108 case 0:
109 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, TYPE_0_LEN, ENC_NA);
110 break;
111 case 1:
112 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, TYPE_1_LEN, ENC_NA);
113 break;
114 case 2:
115 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, TYPE_2_LEN + (spare & 0x01 ? 40 : 20), ENC_NA);
116 break;
117 case 3:
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),
121 ENC_NA);
122 break;
123 default:
124 ti = proto_tree_add_item(tree, proto_sync, tvb, 0, -1, ENC_NA);
125 break;
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);
133 offset++;
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");
139 offset += 2;
141 /* Octet 4 - Packet Number */
142 proto_tree_add_uint(sync_tree, hf_sync_packet_nr, tvb, offset, 2, packet_nr+1);
143 offset += 2;
145 /* Octet 6 - Elapsed Octet Counter */
146 proto_tree_add_item(sync_tree, hf_sync_elapsed_octet_ctr, tvb, offset, 4, ENC_BIG_ENDIAN);
147 offset += 4;
149 switch (type) {
150 case 0:
151 /* SYNC PDU Type 0 */
152 proto_tree_add_item(sync_tree, hf_sync_total_nr_of_packet, tvb, offset, 3, ENC_BIG_ENDIAN);
153 offset += 3;
154 proto_tree_add_item(sync_tree, hf_sync_total_nr_of_octet, tvb, offset, 5, ENC_BIG_ENDIAN);
155 offset += 5;
156 proto_tree_add_item(sync_tree, hf_sync_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN);
157 offset++;
158 break;
159 case 1:
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));
166 offset += 2;
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);
172 break;
173 case 2:
174 /* SYNC PDU Type 2 */
175 proto_tree_add_text(tree, tvb, offset, -1, "SYNC PDU type 2 unsupported");
176 break;
177 case 3:
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);
181 offset += 3;
182 proto_tree_add_item(sync_tree, hf_sync_total_nr_of_octet, tvb, offset, 5, ENC_BIG_ENDIAN);
183 offset += 5;
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);
186 offset += 2;
188 if (offset < (gint)tvb_reported_length(tvb)) {
189 int i;
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);
199 } else {
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);
209 offset++;
210 proto_tree_add_item(sync_tree, hf_sync_spare4, tvb, offset, 1, ENC_BIG_ENDIAN);
214 break;
215 default:
216 proto_tree_add_text(tree, tvb, offset, -1, "Unknown SYNC PDU type");
217 break;
221 return tvb_length(tvb);
225 void
226 proto_register_sync(void)
228 static hf_register_info hf_sync[] = {
229 { &hf_sync_type,
230 { "PDU Type", "sync.type",
231 FT_UINT8, BASE_DEC, VALS(sync_type_vals), 0xF0,
232 NULL, HFILL }
234 { &hf_sync_spare4,
235 { "Spare", "sync.spare",
236 FT_UINT8, BASE_DEC, NULL, 0x0F,
237 NULL, HFILL }
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,
267 NULL, HFILL }
269 { &hf_sync_payload_crc,
270 { "Payload CRC", "sync.payload_crc",
271 FT_UINT16, BASE_HEX, NULL, 0x3FF,
272 NULL, HFILL }
274 { &hf_sync_length_of_packet,
275 { "Length of Packet", "sync.length_of_packet",
276 FT_STRING, BASE_NONE, NULL, 0x0,
277 NULL, HFILL }
281 static gint *ett_sync_array[] = {
282 &ett_sync
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);
293 void
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
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: