3 * Routines for RFC 2250 MPEG2 (ISO/IEC 13818-1) Transport Stream dissection
7 * Copyright 2006, Erwin Rol <erwin@erwinrol.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <epan/packet.h>
35 #include <epan/rtp_pt.h>
36 #include "packet-frame.h"
38 #include <epan/emem.h>
39 #include <epan/conversation.h>
40 #include <epan/expert.h>
41 #include <epan/reassemble.h>
43 /* The MPEG2 TS packet size */
44 #define MP2T_PACKET_SIZE 188
45 #define MP2T_SYNC_BYTE 0x47
47 static dissector_handle_t pes_handle;
48 static dissector_handle_t docsis_handle;
49 static dissector_handle_t data_handle;
51 static int proto_mp2t = -1;
52 static gint ett_mp2t = -1;
53 static gint ett_mp2t_header = -1;
54 static gint ett_mp2t_af = -1;
55 static gint ett_mp2t_analysis = -1;
56 static gint ett_dmpt = -1;
58 static int hf_mp2t_header = -1;
59 static int hf_mp2t_sync_byte = -1;
60 static int hf_mp2t_tei = -1;
61 static int hf_mp2t_pusi = -1;
62 static int hf_mp2t_tp = -1;
63 static int hf_mp2t_pid = -1;
64 static int hf_mp2t_tsc = -1;
65 static int hf_mp2t_afc = -1;
66 static int hf_mp2t_cc = -1;
67 static int hf_mp2t_cc_drop = -1;
69 static int hf_mp2t_analysis_flags = -1;
70 static int hf_mp2t_analysis_skips = -1;
71 static int hf_mp2t_analysis_drops = -1;
73 #define MP2T_SYNC_BYTE_MASK 0xFF000000
74 #define MP2T_TEI_MASK 0x00800000
75 #define MP2T_PUSI_MASK 0x00400000
76 #define MP2T_TP_MASK 0x00200000
77 #define MP2T_PID_MASK 0x001FFF00
78 #define MP2T_TSC_MASK 0x000000C0
79 #define MP2T_AFC_MASK 0x00000030
80 #define MP2T_CC_MASK 0x0000000F
82 #define MP2T_SYNC_BYTE_SHIFT 24
83 #define MP2T_TEI_SHIFT 23
84 #define MP2T_PUSI_SHIFT 22
85 #define MP2T_TP_SHIFT 21
86 #define MP2T_PID_SHIFT 8
87 #define MP2T_TSC_SHIFT 6
88 #define MP2T_AFC_SHIFT 4
89 #define MP2T_CC_SHIFT 0
91 static int hf_mp2t_af = -1;
92 static int hf_mp2t_af_length = -1;
93 static int hf_mp2t_af_di = -1;
94 static int hf_mp2t_af_rai = -1;
95 static int hf_mp2t_af_espi = -1;
96 static int hf_mp2t_af_pcr_flag = -1;
97 static int hf_mp2t_af_opcr_flag = -1;
98 static int hf_mp2t_af_sp_flag = -1;
99 static int hf_mp2t_af_tpd_flag = -1;
100 static int hf_mp2t_af_afe_flag = -1;
102 #define MP2T_AF_DI_MASK 0x80
103 #define MP2T_AF_RAI_MASK 0x40
104 #define MP2T_AF_ESPI_MASK 0x20
105 #define MP2T_AF_PCR_MASK 0x10
106 #define MP2T_AF_OPCR_MASK 0x08
107 #define MP2T_AF_SP_MASK 0x04
108 #define MP2T_AF_TPD_MASK 0x02
109 #define MP2T_AF_AFE_MASK 0x01
111 #define MP2T_AF_DI_SHIFT 7
112 #define MP2T_AF_RAI_SHIFT 6
113 #define MP2T_AF_ESPI_SHIFT 5
114 #define MP2T_AF_PCR_SHIFT 4
115 #define MP2T_AF_OPCR_SHIFT 3
116 #define MP2T_AF_SP_SHIFT 2
117 #define MP2T_AF_TPD_SHIFT 1
118 #define MP2T_AF_AFE_SHIFT 0
120 static int hf_mp2t_af_pcr = -1;
121 static int hf_mp2t_af_opcr = -1;
123 static int hf_mp2t_af_sc = -1;
125 static int hf_mp2t_af_tpd_length = -1;
126 static int hf_mp2t_af_tpd = -1;
128 static int hf_mp2t_af_e_length = -1;
129 static int hf_mp2t_af_e_ltw_flag = -1;
130 static int hf_mp2t_af_e_pr_flag = -1;
131 static int hf_mp2t_af_e_ss_flag = -1;
132 static int hf_mp2t_af_e_reserved = -1;
134 #define MP2T_AF_E_LTW_FLAG_MASK 0x80
135 #define MP2T_AF_E_PR_FLAG_MASK 0x40
136 #define MP2T_AF_E_SS_FLAG_MASK 0x20
138 static int hf_mp2t_af_e_reserved_bytes = -1;
139 static int hf_mp2t_af_stuffing_bytes = -1;
141 static int hf_mp2t_af_e_ltwv_flag = -1;
142 static int hf_mp2t_af_e_ltwo = -1;
144 static int hf_mp2t_af_e_pr_reserved = -1;
145 static int hf_mp2t_af_e_pr = -1;
147 static int hf_mp2t_af_e_st = -1;
148 static int hf_mp2t_af_e_dnau_32_30 = -1;
149 static int hf_mp2t_af_e_m_1 = -1;
150 static int hf_mp2t_af_e_dnau_29_15 = -1;
151 static int hf_mp2t_af_e_m_2 = -1;
152 static int hf_mp2t_af_e_dnau_14_0 = -1;
153 static int hf_mp2t_af_e_m_3 = -1;
155 static int hf_mp2t_payload = -1;
156 static int hf_mp2t_malformed_payload = -1;
159 static const value_string mp2t_sync_byte_vals[] = {
160 { MP2T_SYNC_BYTE, "Correct" },
164 static const value_string mp2t_pid_vals[] = {
165 { 0x0000, "Program Association Table" },
166 { 0x0001, "Conditional Access Table" },
167 { 0x0002, "Transport Stream Description Table" },
168 { 0x0003, "Reserved" },
169 { 0x0004, "Reserved" },
170 { 0x0005, "Reserved" },
171 { 0x0006, "Reserved" },
172 { 0x0007, "Reserved" },
173 { 0x0008, "Reserved" },
174 { 0x0009, "Reserved" },
175 { 0x000A, "Reserved" },
176 { 0x000B, "Reserved" },
177 { 0x000C, "Reserved" },
178 { 0x000D, "Reserved" },
179 { 0x000E, "Reserved" },
180 { 0x000F, "Reserved" },
181 { 0x1FFE, "DOCSIS Data-over-cable well-known PID" },
182 { 0x1FFF, "Null packet" },
186 static const value_string mp2t_tsc_vals[] = {
187 { 0, "Not scrambled" },
188 { 1, "User-defined" },
189 { 2, "User-defined" },
190 { 3, "User-defined" },
194 static const value_string mp2t_afc_vals[] = {
196 { 1, "Payload only" },
197 { 2, "Adaptation Field only" },
198 { 3, "Adaptation Field and Payload" },
202 static gint ett_depi_msg_fragment = -1;
203 static gint ett_depi_msg_fragments = -1;
204 static int hf_depi_msg_fragments = -1;
205 static int hf_depi_msg_fragment = -1;
206 static int hf_depi_msg_fragment_overlap = -1;
207 static int hf_depi_msg_fragment_overlap_conflicts = -1;
208 static int hf_depi_msg_fragment_multiple_tails = -1;
209 static int hf_depi_msg_fragment_too_long_fragment = -1;
210 static int hf_depi_msg_fragment_error = -1;
211 static int hf_depi_msg_reassembled_in = -1;
212 static int hf_depi_msg_reassembled_length = -1;
214 static const fragment_items depi_msg_frag_items = {
215 /* Fragment subtrees */
216 &ett_depi_msg_fragment,
217 &ett_depi_msg_fragments,
218 /* Fragment fields */
219 &hf_depi_msg_fragments,
220 &hf_depi_msg_fragment,
221 &hf_depi_msg_fragment_overlap,
222 &hf_depi_msg_fragment_overlap_conflicts,
223 &hf_depi_msg_fragment_multiple_tails,
224 &hf_depi_msg_fragment_too_long_fragment,
225 &hf_depi_msg_fragment_error,
226 /* Reassembled in field */
227 &hf_depi_msg_reassembled_in,
228 /* Reassembled length field */
229 &hf_depi_msg_reassembled_length,
234 /* Structures to handle DOCSIS-DEPI packets, spanned across
235 * multiple MPEG packets
237 static GHashTable *mp2t_depi_fragment_table = NULL;
238 static GHashTable *mp2t_depi_reassembled_table = NULL;
240 /***************** DOCSIS defragmentation support *******************/
241 /* definitions of DOCSIS payload type - from plugins/docsis/packet-docsis.c */
242 #define DOCSIS_FC_TYPE_DATA 0x00
243 #define DOCSIS_FC_TYPE_ATM 0x01
244 #define DOCSIS_FC_TYPE_RESERVED 0x02
245 #define DOCSIS_FC_TYPE_MAC 0x03
248 get_docsis_packet_length(tvbuff_t * tvb, gint offset)
254 /* Extract FC_TYPE and FC_PARM */
255 fc = tvb_get_guint8 (tvb, offset); /* Frame Control Byte */
256 fctype = (fc >> 6) & 0x03; /* Frame Control Type: 2 MSB Bits */
258 if((fctype == DOCSIS_FC_TYPE_ATM) ||
259 (fctype == DOCSIS_FC_TYPE_RESERVED)) {
260 /* add text - this FC type is not supported */
264 /* The only case when this field is used for SID is for
265 * request frames, but they are in upstream direction.
267 len = tvb_get_ntohs(tvb, offset + 2) + 6;
273 mp2t_depi_docsis_fragmentation_handle(tvbuff_t *tvb, guint offset,
274 packet_info *pinfo, proto_tree *tree,
275 guint frag_offset, guint frag_len,
276 gboolean fragment_last)
278 fragment_data *frag_msg = NULL;
279 tvbuff_t *new_tvb = NULL;
280 tvbuff_t *next_tvb = NULL;
282 proto_tree *dmpt_tree;
284 pinfo->fragmented = TRUE;
286 /* check length; send frame for reassembly */
287 frag_msg = fragment_add_check(tvb, offset, pinfo,
288 0, mp2t_depi_fragment_table,
289 mp2t_depi_reassembled_table,
294 new_tvb = process_reassembled_data(tvb, offset, pinfo,
296 frag_msg, &depi_msg_frag_items,
299 if (frag_msg) { /* Reassembled */
300 col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)");
301 } else { /* Not last packet of reassembled Short Message */
302 col_append_fstr(pinfo->cinfo, COL_INFO," (Message fragment %u)", 0);
305 /* put DOCSIS handler here */
306 if (new_tvb) { /* take it all */
309 ti = proto_tree_add_text(tree, tvb, offset, 0, "DOCSIS MAC Frame (reassembled)");
310 dmpt_tree = proto_item_add_subtree(ti, ett_dmpt);
313 call_dissector(docsis_handle, next_tvb, pinfo, dmpt_tree);
315 call_dissector(data_handle, next_tvb, pinfo, dmpt_tree);
316 } else { /* make a new subset */
317 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
323 /* Decoding of DOCSIS MAC frames within MPEG packets. MAC frames may begin anywhere
324 * within an MPEG packet or span multiple MPEG packets.
325 * payload_unit_start_indicator bit in MPEG header, and pointer field are used to
326 * decode fragmented DOCSIS frames within MPEG packet.
327 *-------------------------------------------------------------------------------
328 *MPEG Header | pointer_field | stuff_bytes | Start of MAC Frame #1 |
329 *(PUSI = 1) | (= 0) | (0 or more) |(up to 183 bytes) |
330 *-------------------------------------------------------------------------------
331 *-------------------------------------------------------------------------------
332 *MPEG Header | Continuation of MAC Frame #1 |
333 *(PUSI = 0) | (up to 183 bytes) |
334 *-------------------------------------------------------------------------------
335 *-------------------------------------------------------------------------------
336 *MPEG Header | pointer_field |Tail of MAC Frame| stuff_bytes |Start of MAC Frame|
337 *(PUSI = 1) | (= M) | #1 (M bytes) | (0 or more) |# 2 (N bytes) |
338 *-------------------------------------------------------------------------------
339 * Source - Data-Over-Cable Service Interface Specifications
340 * CM-SP-DRFI-I07-081209
343 mp2t_depi_docsis_process_payload(tvbuff_t *tvb, gint offset, packet_info *pinfo,
344 proto_tree *tree, proto_tree *header_tree)
350 proto_tree *dmpt_tree;
351 static gboolean fragmentation = FALSE;
352 static guint32 mac_frame_len, cumulative_len;
354 pusi_flag = (tvb_get_ntohl(tvb, offset) & 0x00400000);
359 pointer = tvb_get_guint8(tvb, offset);
360 proto_tree_add_text(header_tree, tvb, offset, 1,
361 "Pointer: %u", tvb_get_guint8(tvb, offset));
365 /* get tail of MAC frame */
366 if (pusi_flag && fragmentation) {
367 fragmentation = FALSE;
369 /* check length; send frame for reassembly */
370 mp2t_depi_docsis_fragmentation_handle(tvb, offset, pinfo,
375 cumulative_len += pointer;
377 if (cumulative_len != mac_frame_len) {
378 proto_tree_add_text(tree, tvb, offset, mac_frame_len,
379 "Invalid cumulative length %u",
385 /* Get start of MAC frame or get complete frame */
386 if (pusi_flag && !fragmentation) {
387 guint16 remaining_length;
389 remaining_length = 183 - pointer;
392 while (remaining_length > 0) {
393 while ((tvb_get_guint8(tvb, offset) == 0xFF)) {
395 if (remaining_length == 0)
400 /* Here, we start DOCSIS frame */
401 mac_frame_len = get_docsis_packet_length(tvb, offset);
404 if (!mac_frame_len) {
405 proto_tree_add_text(tree, tvb, offset, mac_frame_len,
406 "Invalid DOCSIS length %u", mac_frame_len);
410 if (mac_frame_len <= remaining_length) {
411 fragmentation = FALSE;
412 /* send for processing */
413 ti = proto_tree_add_text(tree, tvb, offset,
415 "DOCSIS MAC Frame: %u bytes", mac_frame_len);
416 dmpt_tree = proto_item_add_subtree(ti, ett_dmpt);
417 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
418 call_dissector(docsis_handle, next_tvb, pinfo, dmpt_tree);
420 offset += mac_frame_len;
421 remaining_length -= mac_frame_len;
423 fragmentation = TRUE;
425 mp2t_depi_docsis_fragmentation_handle(tvb, offset, pinfo,
426 tree, 0, remaining_length, FALSE);
427 cumulative_len = remaining_length;
433 /* if PUSI flag == 0 - check fragmentation flag */
435 gboolean last_fragment = FALSE;
437 if (fragmentation == FALSE) {
438 /* Error - fragmentation should be TRUE */
439 proto_tree_add_text(tree, tvb, offset, mac_frame_len,
440 "Error - PUSI is 0 in unfragmented DOCSIS packet");
444 /* If packet length is consistent with MAC frame length -
445 * call function to handle all fragments
447 if ((cumulative_len + 184) == mac_frame_len) {
448 last_fragment = TRUE;
449 fragmentation = FALSE;
452 mp2t_depi_docsis_fragmentation_handle(tvb, offset, pinfo,
453 tree, cumulative_len, 184, last_fragment);
454 cumulative_len += 184;
461 /* Data structure used for detecting CC drops
465 * +-> mp2t_analysis_data
467 * +-> pid_table (RB tree) (key: pid)
469 * | +-> pid_analysis_data (per pid)
470 * | +-> pid_analysis_data
471 * | +-> pid_analysis_data
473 * +-> frame_table (RB tree) (key: pinfo->fd->num)
475 * +-> frame_analysis_data (only created if drop detected)
477 * +-> ts_table (RB tree)
479 * +-> ts_analysis_data (per TS subframe)
480 * +-> ts_analysis_data
481 * +-> ts_analysis_data
484 typedef struct mp2t_analysis_data {
486 /* This structure contains a tree containing data for the
487 * individual pid's, this is only used when packets are
488 * processed sequencially.
490 emem_tree_t *pid_table;
492 /* When detecting a CC drop, store that information for the
493 * given frame. This info is needed, when clicking around in
494 * wireshark, as the pid table data only makes sence during
495 * sequencial processing. The flag pinfo->fd->flags.visited is
496 * used to tell the difference.
499 emem_tree_t *frame_table;
501 /* Total counters per conversation / multicast stream */
503 guint32 total_discontinuity;
505 } mp2t_analysis_data_t;
507 /* Analysis TS frame info needed during sequential processing */
508 typedef struct pid_analysis_data {
510 gint8 cc_prev; /* Previous CC number */
511 } pid_analysis_data_t;
513 /* Analysis info stored for a TS frame */
514 typedef struct ts_analysis_data {
516 gint8 cc_prev; /* Previous CC number */
517 guint8 skips; /* Skips between CCs max 14 */
518 } ts_analysis_data_t;
521 typedef struct frame_analysis_data {
523 /* As each frame has several pid's, thus need a pid data
524 * structure per TS frame.
526 emem_tree_t *ts_table;
528 } frame_analysis_data_t;
530 static mp2t_analysis_data_t *
531 init_mp2t_conversation_data(void)
533 mp2t_analysis_data_t *mp2t_data = NULL;
535 mp2t_data = se_alloc0(sizeof(struct mp2t_analysis_data));
537 mp2t_data->pid_table =
538 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
540 mp2t_data->frame_table =
541 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
544 mp2t_data->total_skips = 0;
545 mp2t_data->total_discontinuity = 0;
550 static mp2t_analysis_data_t *
551 get_mp2t_conversation_data(conversation_t *conv)
553 mp2t_analysis_data_t *mp2t_data = NULL;
555 mp2t_data = conversation_get_proto_data(conv, proto_mp2t);
557 mp2t_data = init_mp2t_conversation_data();
558 conversation_add_proto_data(conv, proto_mp2t, mp2t_data);
564 static frame_analysis_data_t *
565 init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
567 frame_analysis_data_t *frame_analysis_data_p = NULL;
569 frame_analysis_data_p = se_alloc0(sizeof(struct frame_analysis_data));
570 frame_analysis_data_p->ts_table =
571 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
572 "mp2t_frame_pid_table");
573 /* Insert into mp2t tree */
574 se_tree_insert32(mp2t_data->frame_table, pinfo->fd->num,
575 (void *)frame_analysis_data_p);
577 return frame_analysis_data_p;
581 static frame_analysis_data_t *
582 get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
584 frame_analysis_data_t *frame_analysis_data_p = NULL;
585 frame_analysis_data_p = se_tree_lookup32(mp2t_data->frame_table, pinfo->fd->num);
586 return frame_analysis_data_p;
589 static pid_analysis_data_t *
590 get_pid_analysis(guint32 pid, conversation_t *conv)
593 pid_analysis_data_t *pid_data = NULL;
594 mp2t_analysis_data_t *mp2t_data = NULL;
595 mp2t_data = get_mp2t_conversation_data(conv);
597 pid_data = se_tree_lookup32(mp2t_data->pid_table, pid);
599 pid_data = se_alloc0(sizeof(struct pid_analysis_data));
600 pid_data->cc_prev = -1;
603 se_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data);
608 /* Calc the number of skipped CC numbers. Note that this can easy
609 * overflow, and a value above 7 indicate several network packets
613 calc_skips(gint32 curr, gint32 prev)
617 /* Only count the missing TS frames in between prev and curr.
618 * The "prev" frame CC number seen is confirmed received, its
619 * the next frames CC counter which is the first known missing
624 /* Calc missing TS frame 'skips' */
627 /* Handle wrap around */
634 #define KEY(pid, cc) ((pid << 4)|cc)
637 detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
638 guint32 pid, gint32 cc_curr, conversation_t *conv)
641 pid_analysis_data_t *pid_data = NULL;
642 ts_analysis_data_t *ts_data = NULL;
643 mp2t_analysis_data_t *mp2t_data = NULL;
644 frame_analysis_data_t *frame_analysis_data_p = NULL;
645 proto_item *flags_item;
647 guint32 detected_drop = 0;
650 mp2t_data = get_mp2t_conversation_data(conv);
652 /* The initial sequencial processing stage */
653 if (!pinfo->fd->flags.visited) {
655 /* This is the sequencial processing stage */
656 pid_data = get_pid_analysis(pid, conv);
658 cc_prev = pid_data->cc_prev;
659 pid_data->cc_prev = cc_curr;
661 /* Null packet always have a CC value equal 0 */
665 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
666 if (cc_prev == cc_curr)
669 /* Have not seen this pid before */
673 /* Detect if CC is not increasing by one all the time */
674 if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) {
677 skips = calc_skips(cc_curr, cc_prev);
679 mp2t_data->total_skips += skips;
680 mp2t_data->total_discontinuity++;
681 /* TODO: if (skips > 7) signal_loss++; ??? */
685 /* Save the info about the dropped packet */
686 if (detected_drop && !pinfo->fd->flags.visited) {
688 /* Lookup frame data, contains TS pid data objects */
689 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
690 if (!frame_analysis_data_p)
691 frame_analysis_data_p = init_frame_analysis_data(mp2t_data, pinfo);
693 /* Create and store a new TS frame pid_data object.
694 This indicate that we have a drop
696 ts_data = se_alloc0(sizeof(struct ts_analysis_data));
697 ts_data->cc_prev = cc_prev;
699 ts_data->skips = skips;
700 se_tree_insert32(frame_analysis_data_p->ts_table, KEY(pid, cc_curr),
704 /* See if we stored info about drops */
705 if (pinfo->fd->flags.visited) {
707 /* Lookup frame data, contains TS pid data objects */
708 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
709 if (!frame_analysis_data_p)
710 return 0; /* No stored frame data -> no drops*/
712 ts_data = se_tree_lookup32(frame_analysis_data_p->ts_table,
716 if (ts_data->skips > 0) {
718 cc_prev = ts_data->cc_prev;
719 skips = ts_data->skips;
726 /* Add info to the proto tree about drops */
730 proto_tree_add_none_format(
731 tree, hf_mp2t_cc_drop, tvb, 0, 0,
732 "Detected %d missing TS frames before this"
733 " (last_cc:%d total skips:%d discontinuity:%d)",
735 mp2t_data->total_skips,
736 mp2t_data->total_discontinuity
739 PROTO_ITEM_SET_GENERATED(flags_item);
740 expert_add_info_format(pinfo, flags_item, PI_MALFORMED,
741 PI_ERROR, "Detected TS frame loss");
743 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_skips,
745 PROTO_ITEM_SET_GENERATED(flags_item);
747 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_drops,
749 PROTO_ITEM_SET_GENERATED(flags_item);
757 dissect_tsp(tvbuff_t *tvb, volatile gint offset, packet_info *pinfo,
758 proto_tree *tree, conversation_t *conv)
762 gint start_offset = offset;
763 volatile gint payload_len;
769 proto_item *ti = NULL;
770 proto_item *hi = NULL;
771 proto_item *item = NULL;
772 proto_tree *mp2t_tree = NULL;
773 proto_tree *mp2t_header_tree = NULL;
774 proto_tree *mp2t_af_tree = NULL;
775 proto_tree *mp2t_analysis_tree = NULL;
777 ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, FALSE );
778 mp2t_tree = proto_item_add_subtree( ti, ett_mp2t );
780 header = tvb_get_ntohl(tvb, offset);
782 pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT;
783 cc = (header & MP2T_CC_MASK) >> MP2T_CC_SHIFT;
784 proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc);
786 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, FALSE);
787 mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header );
789 proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, FALSE);
790 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, FALSE);
791 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, FALSE);
792 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, FALSE);
793 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, FALSE);
794 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, FALSE);
795 proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, FALSE);
796 proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, FALSE);
798 /* If this is a DOCSIS packet - reassemble MPEG frames and call DOCSIS dissector */
799 if (((header & MP2T_PID_MASK) >> MP2T_PID_SHIFT) == 0x1FFE) {
800 mp2t_depi_docsis_process_payload(tvb, offset, pinfo, tree, mp2t_tree);
805 /* Create a subtree for analysis stuff */
806 item = proto_tree_add_text(mp2t_tree, tvb, 0, 0, "MPEG2 PCR Analysis");
807 PROTO_ITEM_SET_GENERATED(item);
808 mp2t_analysis_tree = proto_item_add_subtree(item, ett_mp2t_analysis);
810 skips = detect_cc_drops(tvb, mp2t_analysis_tree, pinfo, pid, cc, conv);
812 proto_item_append_text(ti, " skips=%d", skips);
815 afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT;
817 if (afc == 2 || afc == 3)
819 gint af_start_offset = offset;
826 af_length = tvb_get_guint8(tvb, offset);
828 proto_tree_add_item( mp2t_tree, hf_mp2t_af_length, tvb, offset, 1, FALSE);
830 /* fix issues where afc==3 but af_length==0
831 * Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single
832 * stuffing byte in a Transport Stream packet. When the adaptation_field_control
833 * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
835 if (af_length > 0 ) {
836 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_af, tvb, offset, af_length, FALSE);
837 mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af );
839 af_flags = tvb_get_guint8(tvb, offset);
841 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, FALSE);
842 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, FALSE);
843 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, FALSE);
844 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, FALSE);
845 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, FALSE);
846 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, FALSE);
847 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, FALSE);
848 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, FALSE);
852 if (af_flags & MP2T_AF_PCR_MASK) {
853 guint64 pcr_base = 0;
857 tmp = tvb_get_guint8(tvb, offset);
858 pcr_base = (pcr_base << 8) | tmp;
861 tmp = tvb_get_guint8(tvb, offset);
862 pcr_base = (pcr_base << 8) | tmp;
865 tmp = tvb_get_guint8(tvb, offset);
866 pcr_base = (pcr_base << 8) | tmp;
869 tmp = tvb_get_guint8(tvb, offset);
870 pcr_base = (pcr_base << 8) | tmp;
873 tmp = tvb_get_guint8(tvb, offset);
874 pcr_base = (pcr_base << 1) | ((tmp >> 7) & 0x01);
875 pcr_ext = (tmp & 0x01);
878 tmp = tvb_get_guint8(tvb, offset);
879 pcr_ext = (pcr_ext << 8) | tmp;
882 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset - 6, 6,
883 "Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
884 pcr_base, pcr_ext, pcr_base * 300 + pcr_ext);
887 if (af_flags & MP2T_AF_OPCR_MASK) {
888 guint64 opcr_base = 0;
889 guint32 opcr_ext = 0;
892 tmp = tvb_get_guint8(tvb, offset);
893 opcr_base = (opcr_base << 8) | tmp;
896 tmp = tvb_get_guint8(tvb, offset);
897 opcr_base = (opcr_base << 8) | tmp;
900 tmp = tvb_get_guint8(tvb, offset);
901 opcr_base = (opcr_base << 8) | tmp;
904 tmp = tvb_get_guint8(tvb, offset);
905 opcr_base = (opcr_base << 8) | tmp;
908 tmp = tvb_get_guint8(tvb, offset);
909 opcr_base = (opcr_base << 1) | ((tmp >> 7) & 0x01);
910 opcr_ext = (tmp & 0x01);
913 tmp = tvb_get_guint8(tvb, offset);
914 opcr_ext = (opcr_ext << 8) | tmp;
917 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset - 6, 6,
918 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
919 opcr_base, opcr_ext, opcr_base * 300 + opcr_ext);
924 if (af_flags & MP2T_AF_SP_MASK) {
925 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, FALSE);
929 if (af_flags & MP2T_AF_TPD_MASK) {
932 tpd_len = tvb_get_guint8(tvb, offset);
933 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, FALSE);
936 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, FALSE);
940 if (af_flags & MP2T_AF_AFE_MASK) {
943 gint e_start_offset = offset;
944 gint reserved_len = 0;
946 e_len = tvb_get_guint8(tvb, offset);
947 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, FALSE);
950 e_flags = tvb_get_guint8(tvb, offset);
951 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, FALSE);
952 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, FALSE);
953 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, FALSE);
954 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, FALSE);
957 if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) {
958 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, FALSE);
959 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, FALSE);
963 if (e_flags & MP2T_AF_E_PR_FLAG_MASK) {
964 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, FALSE);
965 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, FALSE);
969 if (e_flags & MP2T_AF_E_SS_FLAG_MASK) {
970 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, FALSE);
971 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, FALSE);
972 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, FALSE);
974 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, FALSE);
975 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, FALSE);
977 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, FALSE);
978 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, FALSE);
982 reserved_len = (e_len + 1) - (offset - e_start_offset);
983 if (reserved_len > 0) {
984 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, FALSE);
985 offset += reserved_len;
989 stuffing_len = (af_length + 1) - (offset - af_start_offset);
990 if (stuffing_len > 0) {
991 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, FALSE);
992 offset += stuffing_len;
997 payload_len = MP2T_PACKET_SIZE - (offset - start_offset);
998 if (payload_len > 0) {
999 if (afc == 2) { /* AF only */
1000 /* Packet is malformed */
1001 proto_tree_add_item( mp2t_tree, hf_mp2t_malformed_payload, tvb, offset, payload_len, FALSE);
1002 offset += payload_len;
1004 /* Check to make sure if we are not at end of payload, if we have less than 3 bytes, the tvb_get_ntoh24 fails. */
1005 if (payload_len >=3 ) {
1006 if (tvb_get_ntoh24(tvb, offset) == 0x000001) {
1007 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, payload_len, payload_len);
1008 const char *saved_proto = pinfo->current_proto;
1009 void *pd_save = pinfo->private_data;
1012 call_dissector(pes_handle, next_tvb, pinfo, mp2t_tree);
1016 Don't stop processing TS packets if somebody threw
1017 BoundsError, which means that dissecting the payload found
1018 that the packet was cut off by before the end of the
1019 payload. This is very likely as this protocol splits the
1020 media stream up into chunks of MP2T_PACKET_SIZE.
1022 CATCH2(BoundsError, ReportedBoundsError) {
1023 /* Restore the private_data structure in case one of the
1024 * called dissectors modified it (and, due to the exception,
1025 * was unable to restore it).
1027 pinfo->private_data = pd_save;
1028 show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1029 pinfo->current_proto = saved_proto;
1034 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, FALSE);
1037 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, FALSE);
1039 offset += payload_len;
1048 dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1051 conversation_t *conv;
1052 conv = find_or_create_conversation(pinfo);
1054 while ( tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE ) {
1055 offset = dissect_tsp(tvb, offset, pinfo, tree, conv);
1060 heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1064 if (tvb_length_remaining(tvb, offset) % MP2T_PACKET_SIZE) {
1067 while (tvb_length_remaining(tvb, offset)) {
1068 if (tvb_get_guint8(tvb, offset) != MP2T_SYNC_BYTE)
1070 offset += MP2T_PACKET_SIZE;
1074 dissect_mp2t(tvb, pinfo, tree);
1079 proto_register_mp2t(void)
1081 static hf_register_info hf[] = {
1082 { &hf_mp2t_header, {
1083 "Header", "mp2t.header",
1084 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
1086 { &hf_mp2t_sync_byte, {
1087 "Sync Byte", "mp2t.sync_byte",
1088 FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL
1091 "Transport Error Indicator", "mp2t.tei",
1092 FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL
1095 "Payload Unit Start Indicator", "mp2t.pusi",
1096 FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL
1099 "Transport Priority", "mp2t.tp",
1100 FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL
1104 FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL
1107 "Transport Scrambling Control", "mp2t.tsc",
1108 FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL
1111 "Adaption Field Control", "mp2t.afc",
1112 FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL
1115 "Continuity Counter", "mp2t.cc",
1116 FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL
1118 { &hf_mp2t_cc_drop, {
1119 "Continuity Counter Drops", "mp2t.cc.drop",
1120 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL
1122 { &hf_mp2t_analysis_flags, {
1123 "MPEG2-TS Analysis Flags", "mp2t.analysis.flags",
1124 FT_NONE, BASE_NONE, NULL, 0x0,
1125 "This frame has some of the MPEG2 analysis flags set", HFILL
1127 { &hf_mp2t_analysis_skips, {
1128 "TS Continuity Counter Skips", "mp2t.analysis.skips",
1129 FT_UINT8, BASE_DEC, NULL, 0x0,
1130 "Missing TS frames accoding to CC counter values", HFILL
1132 { &hf_mp2t_analysis_drops, {
1133 "Some frames dropped", "mp2t.analysis.drops",
1134 FT_UINT8, BASE_DEC, NULL, 0x0,
1135 "Discontinuity: A number of TS frames were dropped", HFILL
1138 "Adaption field", "mp2t.af",
1139 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1141 { &hf_mp2t_af_length, {
1142 "Adaptation Field Length", "mp2t.af.length",
1143 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
1146 "Discontinuity Indicator", "mp2t.af.di",
1147 FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL
1149 { &hf_mp2t_af_rai, {
1150 "Random Access Indicator", "mp2t.af.rai",
1151 FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL
1153 { &hf_mp2t_af_espi, {
1154 "Elementary Stream Priority Indicator", "mp2t.af.espi",
1155 FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL
1157 { &hf_mp2t_af_pcr_flag, {
1158 "PCR Flag", "mp2t.af.pcr_flag",
1159 FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL
1161 { &hf_mp2t_af_opcr_flag, {
1162 "OPCR Flag", "mp2t.af.opcr_flag",
1163 FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL
1165 { &hf_mp2t_af_sp_flag, {
1166 "Splicing Point Flag", "mp2t.af.sp_flag",
1167 FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL
1169 { &hf_mp2t_af_tpd_flag, {
1170 "Transport Private Data Flag", "mp2t.af.tpd_flag",
1171 FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL
1173 { &hf_mp2t_af_afe_flag, {
1174 "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
1175 FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL
1177 { &hf_mp2t_af_pcr, {
1178 "Program Clock Reference", "mp2t.af.pcr",
1179 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1181 { &hf_mp2t_af_opcr, {
1182 "Original Program Clock Reference", "mp2t.af.opcr",
1183 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1186 "Splice Countdown", "mp2t.af.sc",
1187 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1189 { &hf_mp2t_af_tpd_length, {
1190 "Transport Private Data Length", "mp2t.af.tpd_length",
1191 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1193 { &hf_mp2t_af_tpd, {
1194 "Transport Private Data", "mp2t.af.tpd",
1195 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL
1197 { &hf_mp2t_af_e_length, {
1198 "Adaptation Field Extension Length", "mp2t.af.e_length",
1199 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1201 { &hf_mp2t_af_e_ltw_flag, {
1202 "LTW Flag", "mp2t.af.e.ltw_flag",
1203 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL
1205 { &hf_mp2t_af_e_pr_flag, {
1206 "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
1207 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL
1209 { &hf_mp2t_af_e_ss_flag, {
1210 "Seamless Splice Flag", "mp2t.af.e.ss_flag",
1211 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL
1213 { &hf_mp2t_af_e_reserved, {
1214 "Reserved", "mp2t.af.e.reserved",
1215 FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL
1217 { &hf_mp2t_af_e_reserved_bytes, {
1218 "Reserved", "mp2t.af.e.reserved_bytes",
1219 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1221 { &hf_mp2t_af_stuffing_bytes, {
1222 "Stuffing", "mp2t.af.stuffing_bytes",
1223 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1225 { &hf_mp2t_af_e_ltwv_flag, {
1226 "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
1227 FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL
1229 { &hf_mp2t_af_e_ltwo, {
1230 "LTW Offset", "mp2t.af.e.ltwo",
1231 FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL
1233 { &hf_mp2t_af_e_pr_reserved, {
1234 "Reserved", "mp2t.af.e.pr_reserved",
1235 FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL
1237 { &hf_mp2t_af_e_pr, {
1238 "Piecewise Rate", "mp2t.af.e.pr",
1239 FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL
1241 { &hf_mp2t_af_e_st, {
1242 "Splice Type", "mp2t.af.e.st",
1243 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
1245 { &hf_mp2t_af_e_dnau_32_30, {
1246 "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
1247 FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL
1249 { &hf_mp2t_af_e_m_1, {
1250 "Marker Bit", "mp2t.af.e.m_1",
1251 FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
1253 { &hf_mp2t_af_e_dnau_29_15, {
1254 "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
1255 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1257 { &hf_mp2t_af_e_m_2, {
1258 "Marker Bit", "mp2t.af.e.m_2",
1259 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1261 { &hf_mp2t_af_e_dnau_14_0, {
1262 "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
1263 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1265 { &hf_mp2t_af_e_m_3, {
1266 "Marker Bit", "mp2t.af.e.m_3",
1267 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1269 { &hf_mp2t_payload, {
1270 "Payload", "mp2t.payload",
1271 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1273 { &hf_mp2t_malformed_payload, {
1274 "Malformed Payload", "mp2t.malformed_payload",
1275 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1277 { &hf_depi_msg_fragments, {
1278 "Message fragments", "mp2t.depi_msg.fragments",
1279 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL
1281 { &hf_depi_msg_fragment, {
1282 "Message fragment", "mp2t.depi_msg.fragment",
1283 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1285 { &hf_depi_msg_fragment_overlap, {
1286 "Message fragment overlap", "mp2t.depi_msg.fragment.overlap",
1287 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1289 { &hf_depi_msg_fragment_overlap_conflicts, {
1290 "Message fragment overlapping with conflicting data",
1291 "mp2t.depi_msg.fragment.overlap.conflicts",
1292 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1294 { &hf_depi_msg_fragment_multiple_tails, {
1295 "Message has multiple tail fragments",
1296 "mp2t.depi_msg.fragment.multiple_tails",
1297 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1299 { &hf_depi_msg_fragment_too_long_fragment, {
1300 "Message fragment too long", "mp2t.depi_msg.fragment.too_long_fragment",
1301 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1303 { &hf_depi_msg_fragment_error, {
1304 "Message defragmentation error", "mp2t.depi_msg.fragment.error",
1305 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1307 { &hf_depi_msg_reassembled_in, {
1308 "Reassembled in", "mp2t.depi_msg.reassembled.in",
1309 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1311 { &hf_depi_msg_reassembled_length, {
1312 "Reassembled MP2T length", "mp2t.depi_msg.reassembled.length",
1313 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1317 static gint *ett[] =
1324 &ett_depi_msg_fragment,
1325 &ett_depi_msg_fragments
1328 proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
1329 register_dissector("mp2t", dissect_mp2t, proto_mp2t);
1330 proto_register_field_array(proto_mp2t, hf, array_length(hf));
1331 proto_register_subtree_array(ett, array_length(ett));
1332 /* Register processing of fragmented DEPI packets */
1333 fragment_table_init(&mp2t_depi_fragment_table);
1334 reassembled_table_init(&mp2t_depi_reassembled_table);
1340 proto_reg_handoff_mp2t(void)
1342 dissector_handle_t mp2t_handle;
1344 heur_dissector_add("udp", heur_dissect_mp2t, proto_mp2t);
1346 mp2t_handle = create_dissector_handle(dissect_mp2t, proto_mp2t);
1347 dissector_add("rtp.pt", PT_MP2T, mp2t_handle);
1348 dissector_add_handle("udp.port", mp2t_handle); /* for decode-as */
1350 pes_handle = find_dissector("mpeg-pes");
1351 docsis_handle = find_dissector("docsis");
1352 data_handle = find_dissector("data");