2 * Routines for MPEG2 (ISO/ISO 13818-1) Section dissection
3 * Copyright 2012, Guy Martin <gmsoft@tuxicoman.be>
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.
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 */
66 /* From ETSI EN 300 468 */
81 /* From ETSI EN 301 790 */
83 TID_RMT
= 0x41, /* Conflict with TID_NIT_OTHER */
94 /* From ESTI EN 301 192 */
99 /* From OC-SP-ETV-AM 1.0-IO5 */
106 /* From ETSI TS 102 899 */
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" },
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 */
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
;
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)
170 utc_time
->secs
+= hour
*3600 + min
*60 + sec
;
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
,
183 packet_mpeg_sect_header_extra(tvbuff_t
*tvb
, guint offset
, proto_tree
*tree
,
184 guint
*sect_len
, guint
*reserved
, gboolean
*ssi
,
189 proto_item
*pi
[PACKET_MPEG_SECT_PI__SIZE
];
192 for (i
= 0; i
< PACKET_MPEG_SECT_PI__SIZE
; i
++) {
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
);
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
);
221 *sect_len
= MPEG_SECT_LENGTH_MASK
& tmp
;
224 *reserved
= (MPEG_SECT_RESERVED_MASK
& tmp
) >> 12;
227 *ssi
= (MPEG_SECT_SYNTAX_INDICATOR_MASK
& tmp
);
230 for (i
= 0; i
< PACKET_MPEG_SECT_PI__SIZE
; i
++) {
242 packet_mpeg_sect_crc(tvbuff_t
*tvb
, packet_info
*pinfo
,
243 proto_tree
*tree
, guint start
, guint end
)
245 guint32 crc
, calculated_crc
;
248 crc
= tvb_get_ntohl(tvb
, end
);
250 calculated_crc
= crc
;
251 label
= "Unverified";
252 if (mpeg_sect_check_crc
) {
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
);
261 proto_item
*msg_error
;
263 msg_error
= proto_tree_add_uint_format( tree
, hf_mpeg_sect_crc
, tvb
,
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
);
276 dissect_mpeg_sect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
279 guint section_length
= 0;
280 gboolean syntax_indicator
= FALSE
;
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
))
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 §ion_length
, &syntax_indicator
);
304 if (syntax_indicator
)
305 packet_mpeg_sect_crc(tvb
, pinfo
, mpeg_sect_tree
, 0, (section_length
-1));
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
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
323 { &hf_mpeg_sect_reserved
, {
324 "Reserved", "mpeg_sect.reserved",
325 FT_UINT16
, BASE_HEX
, NULL
, MPEG_SECT_RESERVED_MASK
, NULL
, HFILL
328 { &hf_mpeg_sect_length
, {
329 "Length", "mpeg_sect.len",
330 FT_UINT16
, BASE_DEC
, NULL
, MPEG_SECT_LENGTH_MASK
, NULL
, HFILL
333 { &hf_mpeg_sect_crc
, {
334 "CRC 32", "mpeg_sect.crc",
335 FT_UINT32
, BASE_HEX
, NULL
, 0, NULL
, HFILL
339 static gint
*ett
[] = {
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
,
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",
373 * Editor modelines - http://www.wireshark.org/tools/modelines.html
378 * indent-tabs-mode: nil
381 * vi: set shiftwidth=4 tabstop=8 expandtab:
382 * :indentSize=4:tabSize=8:noTabs=true: