HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-mp2t.c
blob42896b07a907f29ff0c7466f9864ed4943666ed5
1 /* packet-mp2t.c
3 * Routines for RFC 2250 MPEG2 (ISO/IEC 13818-1) Transport Stream dissection
5 * $Id$
7 * Copyright 2006, Erwin Rol <erwin@erwinrol.com>
8 * Copyright 2012, Guy Martin <gmsoft@tuxicoman.be>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "config.h"
31 #include <glib.h>
32 #include <epan/packet.h>
34 #include <epan/rtp_pt.h>
36 #include <epan/wmem/wmem.h>
37 #include <epan/conversation.h>
38 #include <epan/expert.h>
39 #include <epan/reassemble.h>
41 #include <epan/tvbuff-int.h> /* XXX, for tvb_new_proxy() */
43 /* The MPEG2 TS packet size */
44 #define MP2T_PACKET_SIZE 188
45 #define MP2T_SYNC_BYTE 0x47
47 #define MP2T_PID_DOCSIS 0x1FFE
48 #define MP2T_PID_NULL 0x1FFF
50 static dissector_handle_t mp2t_handle;
52 static dissector_handle_t docsis_handle;
53 static dissector_handle_t mpeg_pes_handle;
54 static dissector_handle_t mpeg_sect_handle;
55 static dissector_handle_t data_handle;
57 static heur_dissector_list_t heur_subdissector_list;
59 static int proto_mp2t = -1;
60 static gint ett_mp2t = -1;
61 static gint ett_mp2t_header = -1;
62 static gint ett_mp2t_af = -1;
63 static gint ett_mp2t_analysis = -1;
64 static gint ett_stuff = -1;
66 static int hf_mp2t_header = -1;
67 static int hf_mp2t_sync_byte = -1;
68 static int hf_mp2t_tei = -1;
69 static int hf_mp2t_pusi = -1;
70 static int hf_mp2t_tp = -1;
71 static int hf_mp2t_pid = -1;
72 static int hf_mp2t_tsc = -1;
73 static int hf_mp2t_afc = -1;
74 static int hf_mp2t_cc = -1;
76 /* static int hf_mp2t_analysis_flags = -1; */
77 static int hf_mp2t_analysis_skips = -1;
78 static int hf_mp2t_analysis_drops = -1;
80 #define MP2T_SYNC_BYTE_MASK 0xFF000000
81 #define MP2T_TEI_MASK 0x00800000
82 #define MP2T_PUSI_MASK 0x00400000
83 #define MP2T_TP_MASK 0x00200000
84 #define MP2T_PID_MASK 0x001FFF00
85 #define MP2T_TSC_MASK 0x000000C0
86 #define MP2T_AFC_MASK 0x00000030
87 #define MP2T_CC_MASK 0x0000000F
89 #define MP2T_SYNC_BYTE_SHIFT 24
90 #define MP2T_TEI_SHIFT 23
91 #define MP2T_PUSI_SHIFT 22
92 #define MP2T_TP_SHIFT 21
93 #define MP2T_PID_SHIFT 8
94 #define MP2T_TSC_SHIFT 6
95 #define MP2T_AFC_SHIFT 4
96 #define MP2T_CC_SHIFT 0
98 static int hf_mp2t_af = -1;
99 static int hf_mp2t_af_length = -1;
100 static int hf_mp2t_af_di = -1;
101 static int hf_mp2t_af_rai = -1;
102 static int hf_mp2t_af_espi = -1;
103 static int hf_mp2t_af_pcr_flag = -1;
104 static int hf_mp2t_af_opcr_flag = -1;
105 static int hf_mp2t_af_sp_flag = -1;
106 static int hf_mp2t_af_tpd_flag = -1;
107 static int hf_mp2t_af_afe_flag = -1;
109 #define MP2T_AF_DI_MASK 0x80
110 #define MP2T_AF_RAI_MASK 0x40
111 #define MP2T_AF_ESPI_MASK 0x20
112 #define MP2T_AF_PCR_MASK 0x10
113 #define MP2T_AF_OPCR_MASK 0x08
114 #define MP2T_AF_SP_MASK 0x04
115 #define MP2T_AF_TPD_MASK 0x02
116 #define MP2T_AF_AFE_MASK 0x01
118 #define MP2T_AF_DI_SHIFT 7
119 #define MP2T_AF_RAI_SHIFT 6
120 #define MP2T_AF_ESPI_SHIFT 5
121 #define MP2T_AF_PCR_SHIFT 4
122 #define MP2T_AF_OPCR_SHIFT 3
123 #define MP2T_AF_SP_SHIFT 2
124 #define MP2T_AF_TPD_SHIFT 1
125 #define MP2T_AF_AFE_SHIFT 0
127 static int hf_mp2t_af_pcr = -1;
128 static int hf_mp2t_af_opcr = -1;
130 static int hf_mp2t_af_sc = -1;
132 static int hf_mp2t_af_tpd_length = -1;
133 static int hf_mp2t_af_tpd = -1;
135 static int hf_mp2t_af_e_length = -1;
136 static int hf_mp2t_af_e_ltw_flag = -1;
137 static int hf_mp2t_af_e_pr_flag = -1;
138 static int hf_mp2t_af_e_ss_flag = -1;
139 static int hf_mp2t_af_e_reserved = -1;
141 #define MP2T_AF_E_LTW_FLAG_MASK 0x80
142 #define MP2T_AF_E_PR_FLAG_MASK 0x40
143 #define MP2T_AF_E_SS_FLAG_MASK 0x20
145 static int hf_mp2t_af_e_reserved_bytes = -1;
146 static int hf_mp2t_af_stuffing_bytes = -1;
148 static int hf_mp2t_af_e_ltwv_flag = -1;
149 static int hf_mp2t_af_e_ltwo = -1;
151 static int hf_mp2t_af_e_pr_reserved = -1;
152 static int hf_mp2t_af_e_pr = -1;
154 static int hf_mp2t_af_e_st = -1;
155 static int hf_mp2t_af_e_dnau_32_30 = -1;
156 static int hf_mp2t_af_e_m_1 = -1;
157 static int hf_mp2t_af_e_dnau_29_15 = -1;
158 static int hf_mp2t_af_e_m_2 = -1;
159 static int hf_mp2t_af_e_dnau_14_0 = -1;
160 static int hf_mp2t_af_e_m_3 = -1;
162 /* static int hf_mp2t_payload = -1; */
163 static int hf_mp2t_stuff_bytes = -1;
164 static int hf_mp2t_pointer = -1;
167 static const value_string mp2t_sync_byte_vals[] = {
168 { MP2T_SYNC_BYTE, "Correct" },
169 { 0, NULL }
172 static const value_string mp2t_pid_vals[] = {
173 { 0x0000, "Program Association Table" },
174 { 0x0001, "Conditional Access Table" },
175 { 0x0002, "Transport Stream Description Table" },
176 { 0x0003, "Reserved" },
177 { 0x0004, "Reserved" },
178 { 0x0005, "Reserved" },
179 { 0x0006, "Reserved" },
180 { 0x0007, "Reserved" },
181 { 0x0008, "Reserved" },
182 { 0x0009, "Reserved" },
183 { 0x000A, "Reserved" },
184 { 0x000B, "Reserved" },
185 { 0x000C, "Reserved" },
186 { 0x000D, "Reserved" },
187 { 0x000E, "Reserved" },
188 { 0x000F, "Reserved" },
189 { 0x1FFE, "DOCSIS Data-over-cable well-known PID" },
190 { 0x1FFF, "Null packet" },
191 { 0, NULL }
195 /* Values below according ETSI ETR 289 */
196 static const value_string mp2t_tsc_vals[] = {
197 { 0, "Not scrambled" },
198 { 1, "Reserved" },
199 { 2, "Packet scrambled with Even Key" },
200 { 3, "Packet scrambled with Odd Key" },
201 { 0, NULL }
204 static const value_string mp2t_afc_vals[] = {
205 { 0, "Reserved" },
206 { 1, "Payload only" },
207 { 2, "Adaptation Field only" },
208 { 3, "Adaptation Field and Payload" },
209 { 0, NULL }
212 static gint ett_msg_fragment = -1;
213 static gint ett_msg_fragments = -1;
214 static int hf_msg_fragments = -1;
215 static int hf_msg_fragment = -1;
216 static int hf_msg_fragment_overlap = -1;
217 static int hf_msg_fragment_overlap_conflicts = -1;
218 static int hf_msg_fragment_multiple_tails = -1;
219 static int hf_msg_fragment_too_long_fragment = -1;
220 static int hf_msg_fragment_error = -1;
221 static int hf_msg_fragment_count = -1;
222 static int hf_msg_reassembled_in = -1;
223 static int hf_msg_reassembled_length = -1;
225 static expert_field ei_mp2t_pointer = EI_INIT;
226 static expert_field ei_mp2t_cc_drop = EI_INIT;
228 static const fragment_items mp2t_msg_frag_items = {
229 /* Fragment subtrees */
230 &ett_msg_fragment,
231 &ett_msg_fragments,
232 /* Fragment fields */
233 &hf_msg_fragments,
234 &hf_msg_fragment,
235 &hf_msg_fragment_overlap,
236 &hf_msg_fragment_overlap_conflicts,
237 &hf_msg_fragment_multiple_tails,
238 &hf_msg_fragment_too_long_fragment,
239 &hf_msg_fragment_error,
240 &hf_msg_fragment_count,
241 /* Reassembled in field */
242 &hf_msg_reassembled_in,
243 /* Reassembled length field */
244 &hf_msg_reassembled_length,
245 /* Reassembled data field */
246 NULL,
247 /* Tag */
248 "Message fragments"
252 /* Data structure used for detecting CC drops
254 * conversation
256 * +-> mp2t_analysis_data
258 * +-> pid_table (RB tree) (key: pid)
259 * | |
260 * | +-> pid_analysis_data (per pid)
261 * | +-> pid_analysis_data
262 * | +-> pid_analysis_data
264 * +-> frame_table (RB tree) (key: pinfo->fd->num)
266 * +-> frame_analysis_data (only created if drop detected)
268 * +-> ts_table (RB tree)
270 * +-> ts_analysis_data (per TS subframe)
271 * +-> ts_analysis_data
272 * +-> ts_analysis_data
275 typedef struct mp2t_analysis_data {
277 /* This structure contains a tree containing data for the
278 * individual pid's, this is only used when packets are
279 * processed sequencially.
281 wmem_tree_t *pid_table;
283 /* When detecting a CC drop, store that information for the
284 * given frame. This info is needed, when clicking around in
285 * wireshark, as the pid table data only makes sense during
286 * sequential processing. The flag pinfo->fd->flags.visited is
287 * used to tell the difference.
290 wmem_tree_t *frame_table;
292 /* Total counters per conversation / multicast stream */
293 guint32 total_skips;
294 guint32 total_discontinuity;
296 } mp2t_analysis_data_t;
298 enum pid_payload_type {
299 pid_pload_unknown,
300 pid_pload_docsis,
301 pid_pload_pes,
302 pid_pload_sect,
303 pid_pload_null
306 typedef struct subpacket_analysis_data {
307 guint32 frag_cur_pos;
308 guint32 frag_tot_len;
309 gboolean fragmentation;
310 guint32 frag_id;
311 } subpacket_analysis_data_t;
313 typedef struct packet_analysis_data {
315 /* Contain information for each MPEG2-TS packet in the current big packet */
316 wmem_tree_t *subpacket_table;
317 } packet_analysis_data_t;
319 /* Analysis TS frame info needed during sequential processing */
320 typedef struct pid_analysis_data {
321 guint16 pid;
322 gint8 cc_prev; /* Previous CC number */
323 enum pid_payload_type pload_type;
325 /* Fragments information used for first pass */
326 gboolean fragmentation;
327 guint32 frag_cur_pos;
328 guint32 frag_tot_len;
329 guint32 frag_id;
330 } pid_analysis_data_t;
332 /* Analysis info stored for a TS frame */
333 typedef struct ts_analysis_data {
334 guint16 pid;
335 gint8 cc_prev; /* Previous CC number */
336 guint8 skips; /* Skips between CCs max 14 */
337 } ts_analysis_data_t;
340 typedef struct frame_analysis_data {
342 /* As each frame has several pid's, thus need a pid data
343 * structure per TS frame.
345 wmem_tree_t *ts_table;
347 } frame_analysis_data_t;
349 static mp2t_analysis_data_t *
350 init_mp2t_conversation_data(void)
352 mp2t_analysis_data_t *mp2t_data = NULL;
354 mp2t_data = wmem_new0(wmem_file_scope(), struct mp2t_analysis_data);
356 mp2t_data->pid_table = wmem_tree_new(wmem_file_scope());
358 mp2t_data->frame_table = wmem_tree_new(wmem_file_scope());
360 mp2t_data->total_skips = 0;
361 mp2t_data->total_discontinuity = 0;
363 return mp2t_data;
366 static mp2t_analysis_data_t *
367 get_mp2t_conversation_data(conversation_t *conv)
369 mp2t_analysis_data_t *mp2t_data = NULL;
371 mp2t_data = (mp2t_analysis_data_t *)conversation_get_proto_data(conv, proto_mp2t);
372 if (!mp2t_data) {
373 mp2t_data = init_mp2t_conversation_data();
374 conversation_add_proto_data(conv, proto_mp2t, mp2t_data);
377 return mp2t_data;
380 static frame_analysis_data_t *
381 init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
383 frame_analysis_data_t *frame_analysis_data_p = NULL;
385 frame_analysis_data_p = wmem_new0(wmem_file_scope(), struct frame_analysis_data);
386 frame_analysis_data_p->ts_table = wmem_tree_new(wmem_file_scope());
387 /* Insert into mp2t tree */
388 wmem_tree_insert32(mp2t_data->frame_table, pinfo->fd->num,
389 (void *)frame_analysis_data_p);
391 return frame_analysis_data_p;
395 static frame_analysis_data_t *
396 get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
398 frame_analysis_data_t *frame_analysis_data_p = NULL;
399 frame_analysis_data_p = (frame_analysis_data_t *)wmem_tree_lookup32(mp2t_data->frame_table, pinfo->fd->num);
400 return frame_analysis_data_p;
403 static pid_analysis_data_t *
404 get_pid_analysis(guint32 pid, conversation_t *conv)
406 pid_analysis_data_t *pid_data = NULL;
407 mp2t_analysis_data_t *mp2t_data = NULL;
409 mp2t_data = get_mp2t_conversation_data(conv);
411 pid_data = (pid_analysis_data_t *)wmem_tree_lookup32(mp2t_data->pid_table, pid);
412 if (!pid_data) {
413 pid_data = wmem_new0(wmem_file_scope(), struct pid_analysis_data);
414 pid_data->cc_prev = -1;
415 pid_data->pid = pid;
416 pid_data->frag_id = (pid << (32 - 13)) | 0x1;
418 wmem_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data);
420 return pid_data;
423 /* Structure to handle packets, spanned across
424 * multiple MPEG packets
426 static reassembly_table mp2t_reassembly_table;
428 static void
429 mp2t_dissect_packet(tvbuff_t *tvb, enum pid_payload_type pload_type,
430 packet_info *pinfo, proto_tree *tree)
432 dissector_handle_t handle = NULL;
434 switch (pload_type) {
435 case pid_pload_docsis:
436 handle = docsis_handle;
437 break;
438 case pid_pload_pes:
439 handle = mpeg_pes_handle;
440 break;
441 case pid_pload_sect:
442 handle = mpeg_sect_handle;
443 break;
444 default:
445 /* Should not happen */
446 break;
449 if (handle)
450 call_dissector(handle, tvb, pinfo, tree);
451 else
452 call_dissector(data_handle, tvb, pinfo, tree);
455 guint
456 mp2t_get_packet_length(tvbuff_t *tvb, guint offset, packet_info *pinfo,
457 guint32 frag_id, enum pid_payload_type pload_type)
459 fragment_head *frag = NULL;
460 tvbuff_t *len_tvb = NULL, *frag_tvb = NULL, *data_tvb = NULL;
461 gint pkt_len = 0;
462 guint remaining_len;
464 remaining_len = tvb_length_remaining(tvb, offset);
465 frag = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, NULL);
466 if (frag)
467 frag = frag->next;
469 if (!frag) { /* First frame */
470 if ( (pload_type == pid_pload_docsis && remaining_len < 4) ||
471 (pload_type == pid_pload_sect && remaining_len < 3) ||
472 (pload_type == pid_pload_pes && remaining_len < 5) ) {
473 /* Not enough info to determine the size of the encapulated packet */
474 /* Just add the fragment and we'll check out the length later */
475 return -1;
478 len_tvb = tvb;
479 } else {
480 /* Create a composite tvb out of the two */
481 frag_tvb = tvb_new_proxy(frag->tvb_data);
482 len_tvb = tvb_new_composite();
483 tvb_composite_append(len_tvb, frag_tvb);
485 data_tvb = tvb_new_subset_remaining(tvb, offset);
486 tvb_composite_append(len_tvb, data_tvb);
487 tvb_composite_finalize(len_tvb);
489 offset = frag->offset;
492 /* Get the next packet's size if possible */
493 switch (pload_type) {
494 case pid_pload_docsis:
495 pkt_len = tvb_get_ntohs(len_tvb, offset + 2) + 6;
496 break;
497 case pid_pload_pes:
498 pkt_len = tvb_get_ntohs(len_tvb, offset + 4);
499 if (pkt_len) /* A size of 0 means size not bounded */
500 pkt_len += 6;
501 break;
502 case pid_pload_sect:
503 pkt_len = (tvb_get_ntohs(len_tvb, offset + 1) & 0xFFF) + 3;
504 break;
505 default:
506 /* Should not happen */
507 break;
510 if (frag_tvb)
511 tvb_free(frag_tvb);
513 return pkt_len;
516 static void
517 mp2t_fragment_handle(tvbuff_t *tvb, guint offset, packet_info *pinfo,
518 proto_tree *tree, guint32 frag_id,
519 guint frag_offset, guint frag_len,
520 gboolean fragment_last, enum pid_payload_type pload_type)
522 /* proto_item *ti; */
523 fragment_head *frag_msg = NULL;
524 tvbuff_t *new_tvb = NULL;
525 gboolean save_fragmented;
527 save_fragmented = pinfo->fragmented;
528 pinfo->fragmented = TRUE;
530 /* check length; send frame for reassembly */
531 frag_msg = fragment_add_check(&mp2t_reassembly_table,
532 tvb, offset, pinfo, frag_id, NULL,
533 frag_offset,
534 frag_len,
535 !fragment_last);
537 new_tvb = process_reassembled_data(tvb, offset, pinfo,
538 "Reassembled MP2T",
539 frag_msg, &mp2t_msg_frag_items,
540 NULL, tree);
542 if (new_tvb) {
543 /* ti = */ proto_tree_add_text(tree, tvb, 0, 0, "MPEG TS Packet (reassembled)");
544 mp2t_dissect_packet(new_tvb, pload_type, pinfo, tree);
547 pinfo->fragmented = save_fragmented;
551 /* Decoding of DOCSIS MAC frames within MPEG packets. MAC frames may begin anywhere
552 * within an MPEG packet or span multiple MPEG packets.
553 * payload_unit_start_indicator bit in MPEG header, and pointer field are used to
554 * decode fragmented DOCSIS frames within MPEG packet.
555 *-------------------------------------------------------------------------------
556 *MPEG Header | pointer_field | stuff_bytes | Start of MAC Frame #1 |
557 *(PUSI = 1) | (= 0) | (0 or more) |(up to 183 bytes) |
558 *-------------------------------------------------------------------------------
559 *-------------------------------------------------------------------------------
560 *MPEG Header | Continuation of MAC Frame #1 |
561 *(PUSI = 0) | (up to 183 bytes) |
562 *-------------------------------------------------------------------------------
563 *-------------------------------------------------------------------------------
564 *MPEG Header | pointer_field |Tail of MAC Frame| stuff_bytes |Start of MAC Frame|
565 *(PUSI = 1) | (= M) | #1 (M bytes) | (0 or more) |# 2 (N bytes) |
566 *-------------------------------------------------------------------------------
567 * Source - Data-Over-Cable Service Interface Specifications
568 * CM-SP-DRFI-I07-081209
570 static void
571 mp2t_process_fragmented_payload(tvbuff_t *tvb, gint offset, guint remaining_len, packet_info *pinfo,
572 proto_tree *tree, proto_tree *header_tree, guint32 pusi_flag,
573 pid_analysis_data_t *pid_analysis)
575 tvbuff_t *next_tvb;
576 guint8 pointer = 0;
577 proto_item *pi;
578 guint stuff_len = 0;
579 proto_item *si;
580 proto_tree *stuff_tree;
581 packet_analysis_data_t *pdata = NULL;
582 subpacket_analysis_data_t *spdata = NULL;
583 guint32 frag_cur_pos = 0, frag_tot_len = 0;
584 gboolean fragmentation = FALSE;
585 guint32 frag_id = 0;
587 if (pusi_flag && pid_analysis->pload_type == pid_pload_unknown
588 && remaining_len > 3) {
589 /* We should already have identified if it was a DOCSIS packet
590 * Remaining possibility is PES or SECT */
591 if (tvb_get_ntoh24(tvb, offset) == 0x000001) {
592 /* Looks like a PES packet to me ... */
593 pid_analysis->pload_type = pid_pload_pes;
594 } else {
595 /* Most probably a SECT packet */
596 pid_analysis->pload_type = pid_pload_sect;
600 /* Unable to determine the payload type, do nothing */
601 if (pid_analysis->pload_type == pid_pload_unknown)
602 return;
604 /* PES packet don't have pointer fields, others do */
605 if (pusi_flag && pid_analysis->pload_type != pid_pload_pes) {
606 pointer = tvb_get_guint8(tvb, offset);
607 pi = proto_tree_add_item(header_tree, hf_mp2t_pointer, tvb, offset, 1, ENC_BIG_ENDIAN);
608 offset++;
609 remaining_len--;
610 if (pointer > remaining_len) {
611 /* Bogus pointer */
612 expert_add_info_format(pinfo, pi, &ei_mp2t_pointer,
613 "Pointer value is too large (> remaining data length %u)",
614 remaining_len);
618 if (!pinfo->fd->flags.visited) {
619 /* Get values from our current PID analysis */
620 frag_cur_pos = pid_analysis->frag_cur_pos;
621 frag_tot_len = pid_analysis->frag_tot_len;
622 fragmentation = pid_analysis->fragmentation;
623 frag_id = pid_analysis->frag_id;
624 pdata = (packet_analysis_data_t *)p_get_proto_data(pinfo->fd, proto_mp2t, 0);
625 if (!pdata) {
626 pdata = wmem_new0(wmem_file_scope(), packet_analysis_data_t);
627 pdata->subpacket_table = wmem_tree_new(wmem_file_scope());
628 p_add_proto_data(pinfo->fd, proto_mp2t, 0, pdata);
630 } else {
631 spdata = (subpacket_analysis_data_t *)wmem_tree_lookup32(pdata->subpacket_table, offset);
634 if (!spdata) {
635 spdata = wmem_new0(wmem_file_scope(), subpacket_analysis_data_t);
636 /* Save the info into pdata from pid_analysis */
637 spdata->frag_cur_pos = frag_cur_pos;
638 spdata->frag_tot_len = frag_tot_len;
639 spdata->fragmentation = fragmentation;
640 spdata->frag_id = frag_id;
641 wmem_tree_insert32(pdata->subpacket_table, offset, (void *)spdata);
643 } else {
644 /* Get saved values */
645 pdata = (packet_analysis_data_t *)p_get_proto_data(pinfo->fd, proto_mp2t, 0);
646 if (!pdata) {
647 /* Occurs for the first packets in the capture which cannot be reassembled */
648 return;
651 spdata = (subpacket_analysis_data_t *)wmem_tree_lookup32(pdata->subpacket_table, offset);
652 if (!spdata) {
653 /* Occurs for the first sub packets in the capture which cannot be reassembled */
654 return;
657 frag_cur_pos = spdata->frag_cur_pos;
658 frag_tot_len = spdata->frag_tot_len;
659 fragmentation = spdata->fragmentation;
660 frag_id = spdata->frag_id;
663 if (frag_tot_len == (guint)-1) {
664 frag_tot_len = mp2t_get_packet_length(tvb, offset, pinfo, frag_id, pid_analysis->pload_type);
666 if (frag_tot_len == (guint)-1) {
667 return;
672 /* The beginning of a new packet is present */
673 if (pusi_flag) {
674 if (pointer > remaining_len) {
676 * Quit, so we don't use the bogus pointer value;
677 * that could cause remaining_len to become
678 * "negative", meaning it becomes a very large
679 * positive value.
681 return;
684 /* "pointer" contains the number of bytes until the
685 * start of the new section
686 * if the new section does not start immediately after the
687 * pointer field (i.e. pointer>0), the remaining bytes before the
688 * start of the section are another fragment of the
689 * current packet */
690 if (pointer>0 && fragmentation) {
691 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos,
692 pointer, TRUE, pid_analysis->pload_type);
693 frag_id++;
696 offset += pointer;
697 remaining_len -= pointer;
698 fragmentation = FALSE;
699 frag_cur_pos = 0;
700 frag_tot_len = 0;
702 if (!remaining_len) {
703 /* Shouldn't happen */
704 goto save_state;
707 while (remaining_len > 0) {
708 /* Skip stuff bytes */
709 stuff_len = 0;
710 while ((tvb_get_guint8(tvb, offset + stuff_len) == 0xFF)) {
711 stuff_len++;
712 if (stuff_len >= remaining_len) {
713 remaining_len = 0;
714 break;
718 if (stuff_len) {
719 si = proto_tree_add_text(tree, tvb, offset, stuff_len, "Stuffing");
720 stuff_tree = proto_item_add_subtree(si, ett_stuff);
721 proto_tree_add_item(stuff_tree, hf_mp2t_stuff_bytes, tvb, offset, stuff_len, ENC_NA);
722 offset += stuff_len;
723 if (stuff_len >= remaining_len) {
724 goto save_state;
726 remaining_len -= stuff_len;
729 /* Get the next packet's size if possible */
730 frag_tot_len = mp2t_get_packet_length(tvb, offset, pinfo, frag_id, pid_analysis->pload_type);
731 if (frag_tot_len == (guint)-1 || !frag_tot_len) {
732 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, 0, remaining_len, FALSE, pid_analysis->pload_type);
733 fragmentation = TRUE;
734 /*offset += remaining_len;*/
735 frag_cur_pos += remaining_len;
736 goto save_state;
739 /* Check for full packets within this TS frame */
740 if (frag_tot_len &&
741 frag_tot_len <= remaining_len) {
742 next_tvb = tvb_new_subset(tvb, offset, frag_tot_len, frag_tot_len);
743 mp2t_dissect_packet(next_tvb, pid_analysis->pload_type, pinfo, tree);
744 remaining_len -= frag_tot_len;
745 offset += frag_tot_len;
746 frag_tot_len = 0;
747 } else {
748 break;
752 if (remaining_len == 0) {
753 pid_analysis->frag_cur_pos = 0;
754 pid_analysis->frag_tot_len = 0;
755 goto save_state;
761 /* There are remaining bytes. Add them to the fragment list */
763 if ((frag_tot_len && frag_cur_pos + remaining_len >= frag_tot_len) || (!frag_tot_len && pusi_flag)) {
764 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len, TRUE, pid_analysis->pload_type);
765 frag_id++;
766 fragmentation = FALSE;
767 frag_cur_pos = 0;
768 frag_tot_len = 0;
769 } else {
770 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len, FALSE, pid_analysis->pload_type);
771 fragmentation = TRUE;
772 frag_cur_pos += remaining_len;
775 save_state:
776 pid_analysis->fragmentation = fragmentation;
777 pid_analysis->frag_cur_pos = frag_cur_pos;
778 pid_analysis->frag_tot_len = frag_tot_len;
779 pid_analysis->frag_id = frag_id;
784 /* Calc the number of skipped CC numbers. Note that this can easy
785 * overflow, and a value above 7 indicate several network packets
786 * could be lost.
788 static guint32
789 calc_skips(gint32 curr, gint32 prev)
791 int res = 0;
793 /* Only count the missing TS frames in between prev and curr.
794 * The "prev" frame CC number seen is confirmed received, it's
795 * the next frames CC counter which is the first known missing
796 * TS frame
798 prev += 1;
800 /* Calc missing TS frame 'skips' */
801 res = curr - prev;
803 /* Handle wrap around */
804 if (res < 0)
805 res += 16;
807 return res;
810 #define KEY(pid, cc) ((pid << 4)|cc)
812 static guint32
813 detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
814 guint32 pid, gint32 cc_curr, conversation_t *conv)
816 gint32 cc_prev = -1;
817 pid_analysis_data_t *pid_data = NULL;
818 ts_analysis_data_t *ts_data = NULL;
819 mp2t_analysis_data_t *mp2t_data = NULL;
820 frame_analysis_data_t *frame_analysis_data_p = NULL;
821 proto_item *flags_item;
823 guint32 detected_drop = 0;
824 guint32 skips = 0;
826 mp2t_data = get_mp2t_conversation_data(conv);
828 /* The initial sequencial processing stage */
829 if (!pinfo->fd->flags.visited) {
830 /* This is the sequencial processing stage */
831 pid_data = get_pid_analysis(pid, conv);
833 cc_prev = pid_data->cc_prev;
834 pid_data->cc_prev = cc_curr;
836 /* Null packet always have a CC value equal 0 */
837 if (pid == 0x1fff)
838 return 0;
840 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
841 if (cc_prev == cc_curr)
842 return 0;
844 /* Have not seen this pid before */
845 if (cc_prev == -1)
846 return 0;
848 /* Detect if CC is not increasing by one all the time */
849 if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) {
850 detected_drop = 1;
852 skips = calc_skips(cc_curr, cc_prev);
854 mp2t_data->total_skips += skips;
855 mp2t_data->total_discontinuity++;
856 /* TODO: if (skips > 7) signal_loss++; ??? */
860 /* Save the info about the dropped packet */
861 if (detected_drop && !pinfo->fd->flags.visited) {
862 /* Lookup frame data, contains TS pid data objects */
863 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
864 if (!frame_analysis_data_p)
865 frame_analysis_data_p = init_frame_analysis_data(mp2t_data, pinfo);
867 /* Create and store a new TS frame pid_data object.
868 This indicate that we have a drop
870 ts_data = wmem_new0(wmem_file_scope(), struct ts_analysis_data);
871 ts_data->cc_prev = cc_prev;
872 ts_data->pid = pid;
873 ts_data->skips = skips;
874 wmem_tree_insert32(frame_analysis_data_p->ts_table, KEY(pid, cc_curr),
875 (void *)ts_data);
878 /* See if we stored info about drops */
879 if (pinfo->fd->flags.visited) {
881 /* Lookup frame data, contains TS pid data objects */
882 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
883 if (!frame_analysis_data_p)
884 return 0; /* No stored frame data -> no drops*/
885 else {
886 ts_data = (struct ts_analysis_data *)wmem_tree_lookup32(frame_analysis_data_p->ts_table,
887 KEY(pid, cc_curr));
889 if (ts_data) {
890 if (ts_data->skips > 0) {
891 detected_drop = 1;
892 cc_prev = ts_data->cc_prev;
893 skips = ts_data->skips;
899 /* Add info to the proto tree about drops */
900 if (detected_drop) {
901 expert_add_info_format(pinfo, tree, &ei_mp2t_cc_drop,
902 "Detected %d missing TS frames before this (last_cc:%d total skips:%d discontinuity:%d)",
903 skips, cc_prev,
904 mp2t_data->total_skips,
905 mp2t_data->total_discontinuity
908 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_skips,
909 tvb, 0, 0, skips);
910 PROTO_ITEM_SET_GENERATED(flags_item);
912 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_drops,
913 tvb, 0, 0, 1);
914 PROTO_ITEM_SET_GENERATED(flags_item);
916 return skips;
919 static gint
920 dissect_mp2t_adaptation_field(tvbuff_t *tvb, gint offset, guint8 af_length,
921 packet_info *pinfo _U_, proto_tree *tree)
923 gint af_start_offset;
924 proto_item *hi;
925 proto_tree *mp2t_af_tree;
926 guint8 af_flags;
927 gint stuffing_len;
930 af_start_offset = offset;
932 hi = proto_tree_add_item( tree, hf_mp2t_af, tvb, offset, af_length, ENC_NA);
933 mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af );
935 af_flags = tvb_get_guint8(tvb, offset);
936 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, ENC_BIG_ENDIAN);
937 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, ENC_BIG_ENDIAN);
938 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, ENC_BIG_ENDIAN);
939 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
940 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
941 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
942 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
943 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
944 offset += 1;
946 if (af_flags & MP2T_AF_PCR_MASK) {
947 guint64 pcr_base = 0;
948 guint32 pcr_ext = 0;
949 guint8 tmp;
951 tmp = tvb_get_guint8(tvb, offset);
952 pcr_base = (pcr_base << 8) | tmp;
953 offset += 1;
955 tmp = tvb_get_guint8(tvb, offset);
956 pcr_base = (pcr_base << 8) | tmp;
957 offset += 1;
959 tmp = tvb_get_guint8(tvb, offset);
960 pcr_base = (pcr_base << 8) | tmp;
961 offset += 1;
963 tmp = tvb_get_guint8(tvb, offset);
964 pcr_base = (pcr_base << 8) | tmp;
965 offset += 1;
967 tmp = tvb_get_guint8(tvb, offset);
968 pcr_base = (pcr_base << 1) | ((tmp >> 7) & 0x01);
969 pcr_ext = (tmp & 0x01);
970 offset += 1;
972 tmp = tvb_get_guint8(tvb, offset);
973 pcr_ext = (pcr_ext << 8) | tmp;
974 offset += 1;
976 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset - 6, 6,
977 "Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
978 pcr_base, pcr_ext, pcr_base * 300 + pcr_ext);
981 if (af_flags & MP2T_AF_OPCR_MASK) {
982 guint64 opcr_base = 0;
983 guint32 opcr_ext = 0;
984 guint8 tmp = 0;
986 tmp = tvb_get_guint8(tvb, offset);
987 opcr_base = (opcr_base << 8) | tmp;
988 offset += 1;
990 tmp = tvb_get_guint8(tvb, offset);
991 opcr_base = (opcr_base << 8) | tmp;
992 offset += 1;
994 tmp = tvb_get_guint8(tvb, offset);
995 opcr_base = (opcr_base << 8) | tmp;
996 offset += 1;
998 tmp = tvb_get_guint8(tvb, offset);
999 opcr_base = (opcr_base << 8) | tmp;
1000 offset += 1;
1002 tmp = tvb_get_guint8(tvb, offset);
1003 opcr_base = (opcr_base << 1) | ((tmp >> 7) & 0x01);
1004 opcr_ext = (tmp & 0x01);
1005 offset += 1;
1007 tmp = tvb_get_guint8(tvb, offset);
1008 opcr_ext = (opcr_ext << 8) | tmp;
1009 offset += 1;
1011 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset - 6, 6,
1012 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
1013 opcr_base, opcr_ext, opcr_base * 300 + opcr_ext);
1015 offset += 6;
1018 if (af_flags & MP2T_AF_SP_MASK) {
1019 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, ENC_BIG_ENDIAN);
1020 offset += 1;
1023 if (af_flags & MP2T_AF_TPD_MASK) {
1024 guint8 tpd_len;
1026 tpd_len = tvb_get_guint8(tvb, offset);
1027 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1028 offset += 1;
1030 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, ENC_NA);
1031 offset += tpd_len;
1034 if (af_flags & MP2T_AF_AFE_MASK) {
1035 guint8 e_len;
1036 guint8 e_flags;
1037 gint e_start_offset = offset;
1038 gint reserved_len = 0;
1040 e_len = tvb_get_guint8(tvb, offset);
1041 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1042 offset += 1;
1044 e_flags = tvb_get_guint8(tvb, offset);
1045 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1046 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1047 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1048 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1049 offset += 1;
1051 if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) {
1052 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, ENC_BIG_ENDIAN);
1053 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, ENC_BIG_ENDIAN);
1054 offset += 2;
1057 if (e_flags & MP2T_AF_E_PR_FLAG_MASK) {
1058 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, ENC_BIG_ENDIAN);
1059 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, ENC_BIG_ENDIAN);
1060 offset += 3;
1063 if (e_flags & MP2T_AF_E_SS_FLAG_MASK) {
1064 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, ENC_BIG_ENDIAN);
1065 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, ENC_BIG_ENDIAN);
1066 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1067 offset += 1;
1068 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, ENC_BIG_ENDIAN);
1069 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, ENC_BIG_ENDIAN);
1070 offset += 2;
1071 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, ENC_BIG_ENDIAN);
1072 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, ENC_BIG_ENDIAN);
1073 offset += 2;
1076 reserved_len = (e_len + 1) - (offset - e_start_offset);
1077 if (reserved_len > 0) {
1078 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, ENC_NA);
1079 offset += reserved_len;
1083 stuffing_len = af_length - (offset - af_start_offset);
1084 if (stuffing_len > 0) {
1085 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, ENC_NA);
1086 offset += stuffing_len;
1089 return offset-af_start_offset;
1092 static void
1093 dissect_tsp(tvbuff_t *tvb, volatile gint offset, packet_info *pinfo,
1094 proto_tree *tree, conversation_t *conv)
1096 guint32 header;
1097 guint afc;
1098 guint8 af_length;
1099 gint start_offset = offset;
1100 volatile gint payload_len;
1101 pid_analysis_data_t *pid_analysis;
1103 guint32 skips;
1104 guint32 pid;
1105 guint32 cc;
1106 guint32 pusi_flag;
1108 guint32 tsc;
1110 proto_item *ti = NULL;
1111 proto_item *hi = NULL;
1112 proto_item *item = NULL;
1113 proto_tree *mp2t_tree = NULL;
1114 proto_tree *mp2t_header_tree = NULL;
1115 proto_tree *mp2t_analysis_tree = NULL;
1116 proto_item *afci = NULL;
1118 ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, ENC_NA );
1119 mp2t_tree = proto_item_add_subtree( ti, ett_mp2t );
1121 header = tvb_get_ntohl(tvb, offset);
1123 pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT;
1124 cc = (header & MP2T_CC_MASK) >> MP2T_CC_SHIFT;
1125 tsc = (header & MP2T_TSC_MASK);
1126 pusi_flag = (header & 0x00400000);
1127 proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc);
1128 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPEG TS");
1130 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, ENC_BIG_ENDIAN);
1131 mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header );
1133 proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, ENC_BIG_ENDIAN);
1134 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, ENC_BIG_ENDIAN);
1135 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, ENC_BIG_ENDIAN);
1136 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, ENC_BIG_ENDIAN);
1137 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
1138 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, ENC_BIG_ENDIAN);
1139 afci = proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, ENC_BIG_ENDIAN);
1140 proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, ENC_BIG_ENDIAN);
1142 afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT;
1144 pid_analysis = get_pid_analysis(pid, conv);
1146 /* Find out the payload type based on the payload */
1147 if (pid_analysis->pload_type == pid_pload_unknown) {
1148 if (pid == MP2T_PID_NULL) {
1149 pid_analysis->pload_type = pid_pload_null;
1150 } else if (pid == MP2T_PID_DOCSIS) {
1151 pid_analysis->pload_type = pid_pload_docsis;
1155 if (pid_analysis->pload_type == pid_pload_docsis && afc) {
1156 /* DOCSIS packets should not have an adaptation field */
1157 proto_item_append_text(afci, " (Invalid for DOCSIS packets, should be 0)");
1160 if (pid_analysis->pload_type == pid_pload_null) {
1161 /* Nothing more to do */
1162 col_set_str(pinfo->cinfo, COL_INFO, "NULL packet");
1163 proto_item_append_text(afci, " (Should be 0 for NULL packets)");
1164 return;
1167 offset += 4;
1169 /* Create a subtree for analysis stuff */
1170 item = proto_tree_add_text(mp2t_tree, tvb, offset, 0, "MPEG2 PCR Analysis");
1171 PROTO_ITEM_SET_GENERATED(item);
1172 mp2t_analysis_tree = proto_item_add_subtree(item, ett_mp2t_analysis);
1174 skips = detect_cc_drops(tvb, mp2t_analysis_tree, pinfo, pid, cc, conv);
1175 if (skips > 0)
1176 proto_item_append_text(ti, " skips=%d", skips);
1178 if (afc == 2 || afc == 3) {
1179 af_length = tvb_get_guint8(tvb, offset);
1180 proto_tree_add_item( mp2t_tree, hf_mp2t_af_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1181 offset += 1;
1182 /* fix issues where afc==3 but af_length==0
1183 * Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single
1184 * stuffing byte in a Transport Stream packet. When the adaptation_field_control
1185 * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
1187 if (af_length>0)
1188 offset += dissect_mp2t_adaptation_field(tvb, offset, af_length, pinfo, mp2t_tree);
1191 if ((offset - start_offset) < MP2T_PACKET_SIZE)
1192 payload_len = MP2T_PACKET_SIZE - (offset - start_offset);
1193 else
1194 payload_len = 0;
1196 if (!payload_len)
1197 return;
1199 if (afc == 2) {
1200 col_set_str(pinfo->cinfo, COL_INFO, "Adaptation field only");
1201 /* The rest of the packet is stuffing bytes */
1202 proto_tree_add_item( mp2t_tree, hf_mp2t_stuff_bytes, tvb, offset, payload_len, ENC_NA);
1203 offset += payload_len;
1206 if (!tsc) {
1207 mp2t_process_fragmented_payload(tvb, offset, payload_len, pinfo, tree, mp2t_tree, pusi_flag, pid_analysis);
1208 } else {
1209 /* Payload is scrambled */
1210 col_set_str(pinfo->cinfo, COL_INFO, "Scrambled TS payload");
1215 static void
1216 dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1218 guint offset = 0;
1219 conversation_t *conv;
1221 conv = find_or_create_conversation(pinfo);
1223 for (; tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE; offset += MP2T_PACKET_SIZE) {
1224 dissect_tsp(tvb, offset, pinfo, tree, conv);
1229 static gboolean
1230 heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
1232 gint length;
1233 guint offset = 0;
1235 length = tvb_length_remaining(tvb, offset);
1236 if (length == 0) {
1237 /* Nothing to check for */
1238 return FALSE;
1240 if ((length % MP2T_PACKET_SIZE) != 0) {
1241 /* Not a multiple of the MPEG-2 transport packet size */
1242 return FALSE;
1243 } else {
1244 while (tvb_offset_exists(tvb, offset)) {
1245 if (tvb_get_guint8(tvb, offset) != MP2T_SYNC_BYTE) {
1246 /* No sync byte at the appropriate offset */
1247 return FALSE;
1249 offset += MP2T_PACKET_SIZE;
1253 dissect_mp2t(tvb, pinfo, tree);
1254 return TRUE;
1258 static void
1259 mp2t_init(void) {
1260 reassembly_table_init(&mp2t_reassembly_table,
1261 &addresses_reassembly_table_functions);
1264 void
1265 proto_register_mp2t(void)
1267 static hf_register_info hf[] = {
1268 { &hf_mp2t_header, {
1269 "Header", "mp2t.header",
1270 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
1271 } } ,
1272 { &hf_mp2t_sync_byte, {
1273 "Sync Byte", "mp2t.sync_byte",
1274 FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL
1275 } } ,
1276 { &hf_mp2t_tei, {
1277 "Transport Error Indicator", "mp2t.tei",
1278 FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL
1279 } } ,
1280 { &hf_mp2t_pusi, {
1281 "Payload Unit Start Indicator", "mp2t.pusi",
1282 FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL
1283 } } ,
1284 { &hf_mp2t_tp, {
1285 "Transport Priority", "mp2t.tp",
1286 FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL
1287 } } ,
1288 { &hf_mp2t_pid, {
1289 "PID", "mp2t.pid",
1290 FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL
1291 } } ,
1292 { &hf_mp2t_tsc, {
1293 "Transport Scrambling Control", "mp2t.tsc",
1294 FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL
1295 } } ,
1296 { &hf_mp2t_afc, {
1297 "Adaptation Field Control", "mp2t.afc",
1298 FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL
1299 } } ,
1300 { &hf_mp2t_cc, {
1301 "Continuity Counter", "mp2t.cc",
1302 FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL
1303 } } ,
1304 #if 0
1305 { &hf_mp2t_analysis_flags, {
1306 "MPEG2-TS Analysis Flags", "mp2t.analysis.flags",
1307 FT_NONE, BASE_NONE, NULL, 0x0,
1308 "This frame has some of the MPEG2 analysis flags set", HFILL
1309 } } ,
1310 #endif
1311 { &hf_mp2t_analysis_skips, {
1312 "TS Continuity Counter Skips", "mp2t.analysis.skips",
1313 FT_UINT8, BASE_DEC, NULL, 0x0,
1314 "Missing TS frames according to CC counter values", HFILL
1315 } } ,
1316 { &hf_mp2t_analysis_drops, {
1317 "Some frames dropped", "mp2t.analysis.drops",
1318 FT_UINT8, BASE_DEC, NULL, 0x0,
1319 "Discontinuity: A number of TS frames were dropped", HFILL
1320 } } ,
1321 { &hf_mp2t_af, {
1322 "Adaptation Field", "mp2t.af",
1323 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1324 } } ,
1325 { &hf_mp2t_af_length, {
1326 "Adaptation Field Length", "mp2t.af.length",
1327 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
1328 } } ,
1329 { &hf_mp2t_af_di, {
1330 "Discontinuity Indicator", "mp2t.af.di",
1331 FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL
1332 } } ,
1333 { &hf_mp2t_af_rai, {
1334 "Random Access Indicator", "mp2t.af.rai",
1335 FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL
1336 } } ,
1337 { &hf_mp2t_af_espi, {
1338 "Elementary Stream Priority Indicator", "mp2t.af.espi",
1339 FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL
1340 } } ,
1341 { &hf_mp2t_af_pcr_flag, {
1342 "PCR Flag", "mp2t.af.pcr_flag",
1343 FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL
1344 } } ,
1345 { &hf_mp2t_af_opcr_flag, {
1346 "OPCR Flag", "mp2t.af.opcr_flag",
1347 FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL
1348 } } ,
1349 { &hf_mp2t_af_sp_flag, {
1350 "Splicing Point Flag", "mp2t.af.sp_flag",
1351 FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL
1352 } } ,
1353 { &hf_mp2t_af_tpd_flag, {
1354 "Transport Private Data Flag", "mp2t.af.tpd_flag",
1355 FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL
1356 } } ,
1357 { &hf_mp2t_af_afe_flag, {
1358 "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
1359 FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL
1360 } } ,
1361 { &hf_mp2t_af_pcr, {
1362 "Program Clock Reference", "mp2t.af.pcr",
1363 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1364 } } ,
1365 { &hf_mp2t_af_opcr, {
1366 "Original Program Clock Reference", "mp2t.af.opcr",
1367 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1368 } } ,
1369 { &hf_mp2t_af_sc, {
1370 "Splice Countdown", "mp2t.af.sc",
1371 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1372 } } ,
1373 { &hf_mp2t_af_tpd_length, {
1374 "Transport Private Data Length", "mp2t.af.tpd_length",
1375 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1376 } } ,
1377 { &hf_mp2t_af_tpd, {
1378 "Transport Private Data", "mp2t.af.tpd",
1379 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL
1380 } } ,
1381 { &hf_mp2t_af_e_length, {
1382 "Adaptation Field Extension Length", "mp2t.af.e_length",
1383 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1384 } } ,
1385 { &hf_mp2t_af_e_ltw_flag, {
1386 "LTW Flag", "mp2t.af.e.ltw_flag",
1387 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL
1388 } } ,
1389 { &hf_mp2t_af_e_pr_flag, {
1390 "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
1391 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL
1392 } } ,
1393 { &hf_mp2t_af_e_ss_flag, {
1394 "Seamless Splice Flag", "mp2t.af.e.ss_flag",
1395 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL
1396 } } ,
1397 { &hf_mp2t_af_e_reserved, {
1398 "Reserved", "mp2t.af.e.reserved",
1399 FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL
1400 } } ,
1401 { &hf_mp2t_af_e_reserved_bytes, {
1402 "Reserved", "mp2t.af.e.reserved_bytes",
1403 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1404 } } ,
1405 { &hf_mp2t_af_stuffing_bytes, {
1406 "Stuffing", "mp2t.af.stuffing_bytes",
1407 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1408 } } ,
1409 { &hf_mp2t_af_e_ltwv_flag, {
1410 "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
1411 FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL
1412 } } ,
1413 { &hf_mp2t_af_e_ltwo, {
1414 "LTW Offset", "mp2t.af.e.ltwo",
1415 FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL
1416 } } ,
1417 { &hf_mp2t_af_e_pr_reserved, {
1418 "Reserved", "mp2t.af.e.pr_reserved",
1419 FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL
1420 } } ,
1421 { &hf_mp2t_af_e_pr, {
1422 "Piecewise Rate", "mp2t.af.e.pr",
1423 FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL
1424 } } ,
1425 { &hf_mp2t_af_e_st, {
1426 "Splice Type", "mp2t.af.e.st",
1427 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
1428 } } ,
1429 { &hf_mp2t_af_e_dnau_32_30, {
1430 "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
1431 FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL
1432 } } ,
1433 { &hf_mp2t_af_e_m_1, {
1434 "Marker Bit", "mp2t.af.e.m_1",
1435 FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
1436 } } ,
1437 { &hf_mp2t_af_e_dnau_29_15, {
1438 "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
1439 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1440 } } ,
1441 { &hf_mp2t_af_e_m_2, {
1442 "Marker Bit", "mp2t.af.e.m_2",
1443 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1444 } } ,
1445 { &hf_mp2t_af_e_dnau_14_0, {
1446 "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
1447 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1448 } } ,
1449 { &hf_mp2t_af_e_m_3, {
1450 "Marker Bit", "mp2t.af.e.m_3",
1451 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1452 } } ,
1453 #if 0
1454 { &hf_mp2t_payload, {
1455 "Payload", "mp2t.payload",
1456 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1457 } } ,
1458 #endif
1459 { &hf_mp2t_stuff_bytes, {
1460 "Stuffing", "mp2t.stuff_bytes",
1461 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1462 } },
1463 { &hf_mp2t_pointer, {
1464 "Pointer", "mp2t.pointer",
1465 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
1466 } },
1467 { &hf_msg_fragments, {
1468 "Message fragments", "mp2t.msg.fragments",
1469 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL
1470 } },
1471 { &hf_msg_fragment, {
1472 "Message fragment", "mp2t.msg.fragment",
1473 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1474 } },
1475 { &hf_msg_fragment_overlap, {
1476 "Message fragment overlap", "mp2t.msg.fragment.overlap",
1477 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1478 } },
1479 { &hf_msg_fragment_overlap_conflicts, {
1480 "Message fragment overlapping with conflicting data",
1481 "mp2t.msg.fragment.overlap.conflicts",
1482 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1483 } },
1484 { &hf_msg_fragment_multiple_tails, {
1485 "Message has multiple tail fragments",
1486 "mp2t.msg.fragment.multiple_tails",
1487 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1488 } },
1489 { &hf_msg_fragment_too_long_fragment, {
1490 "Message fragment too long", "mp2t.msg.fragment.too_long_fragment",
1491 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1492 } },
1493 { &hf_msg_fragment_error, {
1494 "Message defragmentation error", "mp2t.msg.fragment.error",
1495 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1496 } },
1497 { &hf_msg_fragment_count, {
1498 "Message fragment count", "mp2t.msg.fragment.count",
1499 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1500 } },
1501 { &hf_msg_reassembled_in, {
1502 "Reassembled in", "mp2t.msg.reassembled.in",
1503 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1504 } },
1505 { &hf_msg_reassembled_length, {
1506 "Reassembled MP2T length", "mp2t.msg.reassembled.length",
1507 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1511 static gint *ett[] =
1513 &ett_mp2t,
1514 &ett_mp2t_header,
1515 &ett_mp2t_af,
1516 &ett_mp2t_analysis,
1517 &ett_stuff,
1518 &ett_msg_fragment,
1519 &ett_msg_fragments
1522 static ei_register_info ei[] = {
1523 { &ei_mp2t_pointer, { "mp2t.pointer", PI_MALFORMED, PI_ERROR, "Pointer value is too large", EXPFILL }},
1524 { &ei_mp2t_cc_drop, { "mp2t.cc.drop", PI_MALFORMED, PI_ERROR, "Detected missing TS frames", EXPFILL }},
1527 expert_module_t* expert_mp2t;
1529 proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
1531 mp2t_handle = register_dissector("mp2t", dissect_mp2t, proto_mp2t);
1533 proto_register_field_array(proto_mp2t, hf, array_length(hf));
1534 proto_register_subtree_array(ett, array_length(ett));
1535 expert_mp2t = expert_register_protocol(proto_mp2t);
1536 expert_register_field_array(expert_mp2t, ei, array_length(ei));
1538 register_heur_dissector_list("mp2t.pid", &heur_subdissector_list);
1539 /* Register init of processing of fragmented DEPI packets */
1540 register_init_routine(mp2t_init);
1545 void
1546 proto_reg_handoff_mp2t(void)
1548 heur_dissector_add("udp", heur_dissect_mp2t, proto_mp2t);
1550 dissector_add_uint("rtp.pt", PT_MP2T, mp2t_handle);
1551 dissector_add_handle("udp.port", mp2t_handle); /* for decode-as */
1552 heur_dissector_add("usb.bulk", heur_dissect_mp2t, proto_mp2t);
1553 dissector_add_uint("wtap_encap", WTAP_ENCAP_MPEG_2_TS, mp2t_handle);
1555 docsis_handle = find_dissector("docsis");
1556 mpeg_pes_handle = find_dissector("mpeg-pes");
1557 mpeg_sect_handle = find_dissector("mpeg_sect");
1558 data_handle = find_dissector("data");
1562 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1564 * Local variables:
1565 * c-basic-offset: 4
1566 * tab-width: 8
1567 * indent-tabs-mode: nil
1568 * End:
1570 * vi: set shiftwidth=4 tabstop=8 expandtab:
1571 * :indentSize=4:tabSize=8:noTabs=true: