MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-mpeg-sect.c
blobd79292628b5d2e3c58cb730e891bd5f14abf0031
1 /* packet-mpeg-sect.c
2 * Routines for MPEG2 (ISO/ISO 13818-1) Section dissection
3 * Copyright 2012, Guy Martin <gmsoft@tuxicoman.be>
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.
26 #include "config.h"
28 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/crc32-tvb.h>
33 #include <epan/expert.h>
34 #include <epan/dissectors/packet-mpeg-sect.h>
36 static int proto_mpeg_sect = -1;
37 static int hf_mpeg_sect_table_id = -1;
38 static int hf_mpeg_sect_syntax_indicator = -1;
39 static int hf_mpeg_sect_reserved = -1;
40 static int hf_mpeg_sect_length = -1;
41 static int hf_mpeg_sect_crc = -1;
43 static gint ett_mpeg_sect = -1;
45 static expert_field ei_mpeg_sect_crc = EI_INIT;
47 static dissector_table_t mpeg_sect_tid_dissector_table;
49 static gboolean mpeg_sect_check_crc = FALSE;
51 #define MPEG_SECT_SYNTAX_INDICATOR_MASK 0x8000
52 #define MPEG_SECT_RESERVED_MASK 0x7000
53 #define MPEG_SECT_LENGTH_MASK 0x0FFF
55 /* From ISO/IEC 13818-1 */
56 enum {
57 TID_PAT,
58 TID_CA,
59 TID_PMT,
60 TID_TS_DESC,
61 TID_SCENE_DESC,
62 TID_OBJECT_DESC,
63 TID_FORBIDEN = 0xFF
66 /* From ETSI EN 300 468 */
67 enum {
68 TID_NIT = 0x40,
69 TID_NIT_OTHER,
70 TID_SDT,
71 TID_SDT_OTHER = 0x46,
72 TID_BAT = 0x4A,
73 TID_EIT = 0x4E,
74 TID_EIT_OTHER,
75 TID_TDT = 0x70,
76 TID_RST,
77 TID_ST,
78 TID_TOT
81 /* From ETSI EN 301 790 */
82 enum {
83 TID_RMT = 0x41, /* Conflict with TID_NIT_OTHER */
84 TID_SCT = 0xA0,
85 TID_FCT,
86 TID_TCT,
87 TID_SPT,
88 TID_CMT,
89 TID_TBTP,
90 TID_PCR,
91 TID_TIM = 0xB0
94 /* From ESTI EN 301 192 */
95 enum {
96 TID_DVB_MPE = 0x3E
99 /* From OC-SP-ETV-AM 1.0-IO5 */
100 enum {
101 TID_ETV_EISS = 0xE0,
102 TID_ETV_DII = 0xE3,
103 TID_ETV_DDB = 0xE4
106 /* From ETSI TS 102 899 */
107 enum {
108 TID_AIT = 0x74
112 static const value_string mpeg_sect_table_id_vals[] = {
114 { TID_PAT, "Program Association Table (PAT)" },
115 { TID_CA, "Conditional Access (CA)" },
116 { TID_PMT, "Program Map Table (PMT)" },
117 { TID_TS_DESC, "Transport Stream Description" },
118 { TID_SCENE_DESC, "ISO/IEC 14496 Scene Description" },
119 { TID_OBJECT_DESC, "ISO/IEC 14496 Object Description" },
120 { TID_NIT, "Network Information Table (NIT), current network" },
121 { TID_NIT_OTHER, "Network Information Table (NIT), other network" },
122 { TID_SDT, "Service Description Table (SDT), current network" },
123 { TID_SDT_OTHER, "Service Description (SDT), other network" },
124 { TID_BAT, "Bouquet Associatoin Table (BAT)" },
125 { TID_EIT, "Event Information Table (EIT), actual TS" },
126 { TID_EIT_OTHER, "Event Information Table (EIT), other TS" },
127 { TID_TDT, "Time and Date Table (TDT)" },
128 { TID_RST, "Running Status Table (RST)" },
129 { TID_ST, "Stuffing Table (ST)" },
130 { TID_TOT, "Time Offset Table (TOT)" },
131 { TID_AIT, "Application Information Table (AIT)" },
132 { TID_SCT, "Superframe Composition Table (SCT)" },
133 { TID_FCT, "Frame Composition Table (FCT)" },
134 { TID_TCT, "Time-Slot Composition Table (TCT)" },
135 { TID_SPT, "Satellite Position Table (SPT)" },
136 { TID_CMT, "Correction Message Table (CMT)" },
137 { TID_TBTP, "Terminal Burst Time Plan (TBTP)" },
138 { TID_TIM, "Terminal Information Message (TIM)" },
139 { TID_DVB_MPE, "DVB MultiProtocol Encapsulation (MPE)" },
140 { TID_ETV_EISS, "ETV Integrated Signaling Stream (EISS)" },
141 { TID_ETV_DII, "ETV Download Info Indication" },
142 { TID_ETV_DDB, "ETV Download Data Block" },
143 { TID_FORBIDEN, "Forbidden" },
144 { 0, NULL }
147 /* From packet-dvbci.c
148 read a utc_time field in an apdu and write it to utc_time
149 the encoding of the field is according to DVB-SI specification, section 5.2.5
150 16bit modified julian day (MJD), 24bit 6*4bit BCD digits hhmmss
151 return the length in bytes or -1 for error */
152 gint
153 packet_mpeg_sect_mjd_to_utc_time(tvbuff_t *tvb, gint offset, nstime_t *utc_time)
155 gint bcd_time_offset; /* start offset of the bcd time in the tvbuff */
156 guint8 hour, min, sec;
158 if (!utc_time)
159 return -1;
161 nstime_set_zero(utc_time);
162 utc_time->secs = (tvb_get_ntohs(tvb, offset) - 40587) * 86400;
163 bcd_time_offset = offset+2;
164 hour = MPEG_SECT_BCD44_TO_DEC(tvb_get_guint8(tvb, bcd_time_offset));
165 min = MPEG_SECT_BCD44_TO_DEC(tvb_get_guint8(tvb, bcd_time_offset+1));
166 sec = MPEG_SECT_BCD44_TO_DEC(tvb_get_guint8(tvb, bcd_time_offset+2));
167 if (hour>23 || min>59 || sec>59)
168 return -1;
170 utc_time->secs += hour*3600 + min*60 + sec;
171 return 5;
174 guint
175 packet_mpeg_sect_header(tvbuff_t *tvb, guint offset,
176 proto_tree *tree, guint *sect_len, gboolean *ssi)
178 return packet_mpeg_sect_header_extra(tvb, offset, tree, sect_len,
179 NULL, ssi, NULL);
182 guint
183 packet_mpeg_sect_header_extra(tvbuff_t *tvb, guint offset, proto_tree *tree,
184 guint *sect_len, guint *reserved, gboolean *ssi,
185 proto_item **items)
187 guint tmp;
188 guint len = 0;
189 proto_item *pi[PACKET_MPEG_SECT_PI__SIZE];
190 gint i;
192 for (i = 0; i < PACKET_MPEG_SECT_PI__SIZE; i++) {
193 pi[i] = NULL;
196 if (tree) {
197 pi[PACKET_MPEG_SECT_PI__TABLE_ID] =
198 proto_tree_add_item(tree, hf_mpeg_sect_table_id,
199 tvb, offset + len, 1, ENC_BIG_ENDIAN);
202 len++;
204 if (tree) {
205 pi[PACKET_MPEG_SECT_PI__SSI] =
206 proto_tree_add_item(tree, hf_mpeg_sect_syntax_indicator,
207 tvb, offset + len, 2, ENC_BIG_ENDIAN);
209 pi[PACKET_MPEG_SECT_PI__RESERVED] =
210 proto_tree_add_item(tree, hf_mpeg_sect_reserved, tvb,
211 offset + len, 2, ENC_BIG_ENDIAN);
213 pi[PACKET_MPEG_SECT_PI__LENGTH] =
214 proto_tree_add_item(tree, hf_mpeg_sect_length, tvb,
215 offset + len, 2, ENC_BIG_ENDIAN);
218 tmp = tvb_get_ntohs(tvb, offset + len);
220 if (sect_len)
221 *sect_len = MPEG_SECT_LENGTH_MASK & tmp;
223 if (reserved)
224 *reserved = (MPEG_SECT_RESERVED_MASK & tmp) >> 12;
226 if (ssi)
227 *ssi = (MPEG_SECT_SYNTAX_INDICATOR_MASK & tmp);
229 if (items) {
230 for (i = 0; i < PACKET_MPEG_SECT_PI__SIZE; i++) {
231 items[i] = pi[i];
235 len += 2;
237 return len;
241 guint
242 packet_mpeg_sect_crc(tvbuff_t *tvb, packet_info *pinfo,
243 proto_tree *tree, guint start, guint end)
245 guint32 crc, calculated_crc;
246 const char *label;
248 crc = tvb_get_ntohl(tvb, end);
250 calculated_crc = crc;
251 label = "Unverified";
252 if (mpeg_sect_check_crc) {
253 label = "Verified";
254 calculated_crc = crc32_mpeg2_tvb_offset(tvb, start, end);
257 if (calculated_crc == crc) {
258 proto_tree_add_uint_format( tree, hf_mpeg_sect_crc, tvb,
259 end, 4, crc, "CRC: 0x%08x [%s]", crc, label);
260 } else {
261 proto_item *msg_error;
263 msg_error = proto_tree_add_uint_format( tree, hf_mpeg_sect_crc, tvb,
264 end, 4, crc,
265 "CRC: 0x%08x [Failed Verification (Calculated: 0x%08x)]",
266 crc, calculated_crc );
267 PROTO_ITEM_SET_GENERATED(msg_error);
268 expert_add_info( pinfo, msg_error, &ei_mpeg_sect_crc);
271 return 4;
275 static void
276 dissect_mpeg_sect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
278 gint offset = 0;
279 guint section_length = 0;
280 gboolean syntax_indicator = FALSE;
281 guint8 table_id;
283 proto_item *ti;
284 proto_tree *mpeg_sect_tree;
286 table_id = tvb_get_guint8(tvb, offset);
288 /* Check if a dissector can parse the current table */
289 if (dissector_try_uint(mpeg_sect_tid_dissector_table, table_id, tvb, pinfo, tree))
290 return;
292 /* If no dissector is registered, use the common one */
293 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPEG SECT");
294 col_add_fstr(pinfo->cinfo, COL_INFO, "Table ID 0x%02x", table_id);
296 ti = proto_tree_add_item(tree, proto_mpeg_sect, tvb, offset, -1, ENC_NA);
297 mpeg_sect_tree = proto_item_add_subtree(ti, ett_mpeg_sect);
299 proto_item_append_text(ti, " Table_ID=0x%02x", table_id);
301 packet_mpeg_sect_header(tvb, offset, mpeg_sect_tree,
302 &section_length, &syntax_indicator);
304 if (syntax_indicator)
305 packet_mpeg_sect_crc(tvb, pinfo, mpeg_sect_tree, 0, (section_length-1));
309 void
310 proto_register_mpeg_sect(void)
312 static hf_register_info hf[] = {
313 { &hf_mpeg_sect_table_id, {
314 "Table ID", "mpeg_sect.tid",
315 FT_UINT8, BASE_HEX, VALS(mpeg_sect_table_id_vals), 0, NULL, HFILL
316 } },
318 { &hf_mpeg_sect_syntax_indicator, {
319 "Syntax indicator", "mpeg_sect.syntax_indicator",
320 FT_UINT16, BASE_DEC, NULL, MPEG_SECT_SYNTAX_INDICATOR_MASK, NULL, HFILL
321 } },
323 { &hf_mpeg_sect_reserved, {
324 "Reserved", "mpeg_sect.reserved",
325 FT_UINT16, BASE_HEX, NULL, MPEG_SECT_RESERVED_MASK, NULL, HFILL
326 } },
328 { &hf_mpeg_sect_length, {
329 "Length", "mpeg_sect.len",
330 FT_UINT16, BASE_DEC, NULL, MPEG_SECT_LENGTH_MASK, NULL, HFILL
331 } },
333 { &hf_mpeg_sect_crc, {
334 "CRC 32", "mpeg_sect.crc",
335 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
339 static gint *ett[] = {
340 &ett_mpeg_sect
343 static ei_register_info ei[] = {
344 { &ei_mpeg_sect_crc, { "mpeg_sect.crc.invalid", PI_CHECKSUM, PI_WARN, "Invalid CRC", EXPFILL }},
347 module_t *mpeg_sect_module;
348 expert_module_t* expert_mpeg_sect;
350 proto_mpeg_sect = proto_register_protocol("MPEG2 Section", "MPEG SECT", "mpeg_sect");
351 register_dissector("mpeg_sect", dissect_mpeg_sect, proto_mpeg_sect);
353 proto_register_field_array(proto_mpeg_sect, hf, array_length(hf));
354 proto_register_subtree_array(ett, array_length(ett));
355 expert_mpeg_sect = expert_register_protocol(proto_mpeg_sect);
356 expert_register_field_array(expert_mpeg_sect, ei, array_length(ei));
358 mpeg_sect_module = prefs_register_protocol(proto_mpeg_sect, NULL);
360 prefs_register_bool_preference(mpeg_sect_module,
361 "verify_crc",
362 "Verify the section CRC",
363 "Whether the section dissector should verify the CRC",
364 &mpeg_sect_check_crc);
366 mpeg_sect_tid_dissector_table = register_dissector_table("mpeg_sect.tid",
367 "MPEG SECT Table ID",
368 FT_UINT8, BASE_HEX);
373 * Editor modelines - http://www.wireshark.org/tools/modelines.html
375 * Local variables:
376 * c-basic-offset: 4
377 * tab-width: 8
378 * indent-tabs-mode: nil
379 * End:
381 * vi: set shiftwidth=4 tabstop=8 expandtab:
382 * :indentSize=4:tabSize=8:noTabs=true: