/src/wireshark/epan/dissectors/packet-mp2t.c
Line | Count | Source |
1 | | /* packet-mp2t.c |
2 | | * |
3 | | * Routines for RFC 2250 MPEG2 (ISO/IEC 13818-1) Transport Stream dissection |
4 | | * |
5 | | * Copyright 2006, Erwin Rol <erwin@erwinrol.com> |
6 | | * Copyright 2012-2014, Guy Martin <gmsoft@tuxicoman.be> |
7 | | * |
8 | | * Wireshark - Network traffic analyzer |
9 | | * By Gerald Combs <gerald@wireshark.org> |
10 | | * Copyright 1998 Gerald Combs |
11 | | * |
12 | | * SPDX-License-Identifier: GPL-2.0-or-later |
13 | | */ |
14 | | |
15 | | #include "config.h" |
16 | | |
17 | | #include <epan/packet.h> |
18 | | #include <wiretap/wtap.h> |
19 | | |
20 | | #include <epan/conversation.h> |
21 | | #include <epan/expert.h> |
22 | | #include <epan/reassemble.h> |
23 | | #include <epan/proto_data.h> |
24 | | #include <epan/exported_pdu.h> |
25 | | #include <epan/tap.h> |
26 | | #include <epan/follow.h> |
27 | | #include <epan/exceptions.h> |
28 | | #include <epan/show_exception.h> |
29 | | #include <epan/addr_resolv.h> |
30 | | #include "packet-l2tp.h" |
31 | | #include "packet-udp.h" |
32 | | #include "packet-mp2t.h" |
33 | | #include "packet-rtp_pt.h" |
34 | | |
35 | | void proto_register_mp2t(void); |
36 | | void proto_reg_handoff_mp2t(void); |
37 | | |
38 | 126 | #define MP2T_PID_DOCSIS 0x1FFE |
39 | 164 | #define MP2T_PID_NULL 0x1FFF |
40 | | |
41 | | static dissector_handle_t mp2t_handle; |
42 | | |
43 | | static dissector_handle_t docsis_handle; |
44 | | static dissector_handle_t mpeg_pes_handle; |
45 | | static dissector_handle_t mpeg_sect_handle; |
46 | | |
47 | | static heur_dissector_list_t heur_subdissector_list; |
48 | | |
49 | | static int exported_pdu_tap; |
50 | | static int mp2t_follow_tap; |
51 | | |
52 | | static int proto_mp2t; |
53 | | static int ett_mp2t; |
54 | | static int ett_mp2t_header; |
55 | | static int ett_mp2t_af; |
56 | | static int ett_mp2t_analysis; |
57 | | static int ett_stuff; |
58 | | |
59 | | static int hf_mp2t_stream; |
60 | | static int hf_mp2t_header; |
61 | | static int hf_mp2t_sync_byte; |
62 | | static int hf_mp2t_tei; |
63 | | static int hf_mp2t_pusi; |
64 | | static int hf_mp2t_tp; |
65 | | static int hf_mp2t_pid; |
66 | | static int hf_mp2t_tsc; |
67 | | static int hf_mp2t_afc; |
68 | | static int hf_mp2t_cc; |
69 | | |
70 | | /* static int hf_mp2t_analysis_flags; */ |
71 | | static int hf_mp2t_analysis_skips; |
72 | | static int hf_mp2t_analysis_drops; |
73 | | |
74 | 15 | #define MP2T_SYNC_BYTE_MASK 0xFF000000 |
75 | 15 | #define MP2T_TEI_MASK 0x00800000 |
76 | 15 | #define MP2T_PUSI_MASK 0x00400000 |
77 | 15 | #define MP2T_TP_MASK 0x00200000 |
78 | 26.8k | #define MP2T_PID_MASK 0x001FFF00 |
79 | 26.8k | #define MP2T_TSC_MASK 0x000000C0 |
80 | 26.8k | #define MP2T_AFC_MASK 0x00000030 |
81 | 27.3k | #define MP2T_CC_MASK 0x0000000F |
82 | | |
83 | | #define MP2T_SYNC_BYTE_SHIFT 24 |
84 | | #define MP2T_TEI_SHIFT 23 |
85 | | #define MP2T_PUSI_SHIFT 22 |
86 | | #define MP2T_TP_SHIFT 21 |
87 | 26.8k | #define MP2T_PID_SHIFT 8 |
88 | | #define MP2T_TSC_SHIFT 6 |
89 | 26.8k | #define MP2T_AFC_SHIFT 4 |
90 | 26.8k | #define MP2T_CC_SHIFT 0 |
91 | | |
92 | | static int hf_mp2t_af; |
93 | | static int hf_mp2t_af_length; |
94 | | static int hf_mp2t_af_di; |
95 | | static int hf_mp2t_af_rai; |
96 | | static int hf_mp2t_af_espi; |
97 | | static int hf_mp2t_af_pcr_flag; |
98 | | static int hf_mp2t_af_opcr_flag; |
99 | | static int hf_mp2t_af_sp_flag; |
100 | | static int hf_mp2t_af_tpd_flag; |
101 | | static int hf_mp2t_af_afe_flag; |
102 | | |
103 | 15 | #define MP2T_AF_DI_MASK 0x80 |
104 | 15 | #define MP2T_AF_RAI_MASK 0x40 |
105 | 15 | #define MP2T_AF_ESPI_MASK 0x20 |
106 | 138 | #define MP2T_AF_PCR_MASK 0x10 |
107 | 138 | #define MP2T_AF_OPCR_MASK 0x08 |
108 | 138 | #define MP2T_AF_SP_MASK 0x04 |
109 | 138 | #define MP2T_AF_TPD_MASK 0x02 |
110 | 138 | #define MP2T_AF_AFE_MASK 0x01 |
111 | | |
112 | | #define MP2T_AF_DI_SHIFT 7 |
113 | | #define MP2T_AF_RAI_SHIFT 6 |
114 | | #define MP2T_AF_ESPI_SHIFT 5 |
115 | | #define MP2T_AF_PCR_SHIFT 4 |
116 | | #define MP2T_AF_OPCR_SHIFT 3 |
117 | | #define MP2T_AF_SP_SHIFT 2 |
118 | | #define MP2T_AF_TPD_SHIFT 1 |
119 | | #define MP2T_AF_AFE_SHIFT 0 |
120 | | |
121 | | static int hf_mp2t_af_pcr; |
122 | | static int hf_mp2t_af_opcr; |
123 | | |
124 | | static int hf_mp2t_af_sc; |
125 | | |
126 | | static int hf_mp2t_af_tpd_length; |
127 | | static int hf_mp2t_af_tpd; |
128 | | |
129 | | static int hf_mp2t_af_e_length; |
130 | | static int hf_mp2t_af_e_ltw_flag; |
131 | | static int hf_mp2t_af_e_pr_flag; |
132 | | static int hf_mp2t_af_e_ss_flag; |
133 | | static int hf_mp2t_af_e_reserved; |
134 | | |
135 | 74 | #define MP2T_AF_E_LTW_FLAG_MASK 0x80 |
136 | 74 | #define MP2T_AF_E_PR_FLAG_MASK 0x40 |
137 | 74 | #define MP2T_AF_E_SS_FLAG_MASK 0x20 |
138 | | |
139 | | static int hf_mp2t_af_e_reserved_bytes; |
140 | | static int hf_mp2t_af_stuffing_bytes; |
141 | | |
142 | | static int hf_mp2t_af_e_ltwv_flag; |
143 | | static int hf_mp2t_af_e_ltwo; |
144 | | |
145 | | static int hf_mp2t_af_e_pr_reserved; |
146 | | static int hf_mp2t_af_e_pr; |
147 | | |
148 | | static int hf_mp2t_af_e_st; |
149 | | static int hf_mp2t_af_e_dnau_32_30; |
150 | | static int hf_mp2t_af_e_m_1; |
151 | | static int hf_mp2t_af_e_dnau_29_15; |
152 | | static int hf_mp2t_af_e_m_2; |
153 | | static int hf_mp2t_af_e_dnau_14_0; |
154 | | static int hf_mp2t_af_e_m_3; |
155 | | |
156 | | /* static int hf_mp2t_payload; */ |
157 | | static int hf_mp2t_stuff_bytes; |
158 | | static int hf_mp2t_pointer; |
159 | | |
160 | | /* proto data keys. Note that the packet_analysis_data structure is stored |
161 | | * using the layer number, but since that is at wmem_file_scope() while |
162 | | * the stream information is at pinfo->pool, they don't actually clash. |
163 | | */ |
164 | 28.5k | #define MP2T_PROTO_DATA_STREAM 1 |
165 | 26.8k | #define MP2T_PROTO_DATA_PID 2 |
166 | | |
167 | | static const value_string mp2t_sync_byte_vals[] = { |
168 | | { MP2T_SYNC_BYTE, "Correct" }, |
169 | | { 0, NULL } |
170 | | }; |
171 | | |
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 | | { 0x0010, "Network Information or Stuffing Table" }, |
190 | | { 0x0011, "Service Description or Bouquet Association or Stuffing Table" }, |
191 | | { 0x0012, "Event Information or Stuffing or Content Identifier Table" }, |
192 | | { 0x0013, "Running Status or Stuffing Table" }, |
193 | | { 0x0014, "Time and Date or Time Offset or Stuffing Table" }, |
194 | | { 0x0015, "Network Synchronization" }, |
195 | | { 0x0016, "Resolution Authority Record Notification Table" }, |
196 | | { 0x0017, "Reserved For Future Use" }, |
197 | | { 0x0018, "Reserved For Future Use" }, |
198 | | { 0x0019, "Reserved For Future Use" }, |
199 | | { 0x001A, "Reserved For Future Use" }, |
200 | | { 0x001B, "Reserved For Future Use" }, |
201 | | { 0x001C, "Inband Signaling" }, |
202 | | { 0x001D, "Measurement" }, |
203 | | { 0x001E, "Discontinuity Information Table" }, |
204 | | { 0x001F, "Selection Information Table" }, |
205 | | { 0x1FFE, "DOCSIS Data-over-cable well-known PID" }, |
206 | | { 0x1FFF, "Null packet" }, |
207 | | { 0, NULL } |
208 | | }; |
209 | | |
210 | | |
211 | | /* Values below according ETSI ETR 289 */ |
212 | | static const value_string mp2t_tsc_vals[] = { |
213 | | { 0, "Not scrambled" }, |
214 | | { 1, "Reserved" }, |
215 | | { 2, "Packet scrambled with Even Key" }, |
216 | | { 3, "Packet scrambled with Odd Key" }, |
217 | | { 0, NULL } |
218 | | }; |
219 | | |
220 | | static const value_string mp2t_afc_vals[] = { |
221 | | { 0, "Reserved" }, |
222 | | { 1, "Payload only" }, |
223 | | { 2, "Adaptation Field only" }, |
224 | | { 3, "Adaptation Field and Payload" }, |
225 | | { 0, NULL } |
226 | | }; |
227 | | |
228 | | static int ett_msg_fragment; |
229 | | static int ett_msg_fragments; |
230 | | static int hf_msg_fragments; |
231 | | static int hf_msg_fragment; |
232 | | static int hf_msg_fragment_overlap; |
233 | | static int hf_msg_fragment_overlap_conflicts; |
234 | | static int hf_msg_fragment_multiple_tails; |
235 | | static int hf_msg_fragment_too_long_fragment; |
236 | | static int hf_msg_fragment_error; |
237 | | static int hf_msg_fragment_count; |
238 | | static int hf_msg_reassembled_in; |
239 | | static int hf_msg_reassembled_length; |
240 | | |
241 | | static int hf_msg_ts_packet_reassembled; |
242 | | |
243 | | static expert_field ei_mp2t_pointer; |
244 | | static expert_field ei_mp2t_cc_drop; |
245 | | static expert_field ei_mp2t_invalid_afc; |
246 | | |
247 | | static const fragment_items mp2t_msg_frag_items = { |
248 | | /* Fragment subtrees */ |
249 | | &ett_msg_fragment, |
250 | | &ett_msg_fragments, |
251 | | /* Fragment fields */ |
252 | | &hf_msg_fragments, |
253 | | &hf_msg_fragment, |
254 | | &hf_msg_fragment_overlap, |
255 | | &hf_msg_fragment_overlap_conflicts, |
256 | | &hf_msg_fragment_multiple_tails, |
257 | | &hf_msg_fragment_too_long_fragment, |
258 | | &hf_msg_fragment_error, |
259 | | &hf_msg_fragment_count, |
260 | | /* Reassembled in field */ |
261 | | &hf_msg_reassembled_in, |
262 | | /* Reassembled length field */ |
263 | | &hf_msg_reassembled_length, |
264 | | /* Reassembled data field */ |
265 | | NULL, |
266 | | /* Tag */ |
267 | | "Message fragments" |
268 | | }; |
269 | | |
270 | | |
271 | | /* Data structure used for detecting CC drops |
272 | | * |
273 | | * conversation + direction |
274 | | * | |
275 | | * +-> mp2t_analysis_data |
276 | | * | |
277 | | * +-> pid_table (RB tree) (key: pid) |
278 | | * | | |
279 | | * | +-> pid_analysis_data (per pid) |
280 | | * | +-> pid_analysis_data |
281 | | * | +-> pid_analysis_data |
282 | | * | |
283 | | * +-> frame_table (RB tree) (key: pinfo->num) |
284 | | * | |
285 | | * +-> frame_analysis_data (only created if drop detected) |
286 | | * | |
287 | | * +-> ts_table (RB tree) |
288 | | * | |
289 | | * +-> ts_analysis_data (per TS subframe) |
290 | | * +-> ts_analysis_data |
291 | | * +-> ts_analysis_data |
292 | | */ |
293 | | |
294 | | static wmem_map_t *mp2t_stream_hashtable; |
295 | | |
296 | | static uint32_t mp2t_stream_count; |
297 | | |
298 | | typedef struct { |
299 | | const conversation_t* conv; |
300 | | int dir; |
301 | | } mp2t_stream_key; |
302 | | |
303 | | /* Hash functions */ |
304 | | static int |
305 | | mp2t_stream_equal(const void *v, const void *w) |
306 | 26.8k | { |
307 | 26.8k | const mp2t_stream_key *v1 = (const mp2t_stream_key *)v; |
308 | 26.8k | const mp2t_stream_key *v2 = (const mp2t_stream_key *)w; |
309 | 26.8k | int result; |
310 | 26.8k | result = (v1->conv == v2->conv && v1->dir == v2->dir); |
311 | 26.8k | return result; |
312 | 26.8k | } |
313 | | |
314 | | static unsigned |
315 | | mp2t_stream_hash(const void *v) |
316 | 26.9k | { |
317 | 26.9k | const mp2t_stream_key *key = (const mp2t_stream_key *)v; |
318 | | /* Actually getting multiple streams in opposite directions is |
319 | | * quite unlikely, so to optimize don't include it in the hash */ |
320 | 26.9k | unsigned hash_val = GPOINTER_TO_UINT(key->conv); |
321 | 26.9k | return hash_val; |
322 | 26.9k | } |
323 | | |
324 | | typedef struct mp2t_analysis_data { |
325 | | |
326 | | /* This structure contains a tree containing data for the |
327 | | * individual pid's, this is only used when packets are |
328 | | * processed sequentially. |
329 | | */ |
330 | | wmem_tree_t *pid_table; |
331 | | |
332 | | /* When detecting a CC drop, store that information for the |
333 | | * given frame. This info is needed, when clicking around in |
334 | | * wireshark, as the pid table data only makes sense during |
335 | | * sequential processing. The flag pinfo->fd->visited is |
336 | | * used to tell the difference. |
337 | | * |
338 | | */ |
339 | | wmem_tree_t *frame_table; |
340 | | |
341 | | uint32_t stream; |
342 | | |
343 | | /* Total counters per conversation / multicast stream */ |
344 | | uint32_t total_skips; |
345 | | uint32_t total_discontinuity; |
346 | | |
347 | | } mp2t_analysis_data_t; |
348 | | |
349 | | enum pid_payload_type { |
350 | | pid_pload_unknown, |
351 | | pid_pload_docsis, |
352 | | pid_pload_pes, |
353 | | pid_pload_sect, |
354 | | pid_pload_null |
355 | | }; |
356 | | |
357 | | typedef struct subpacket_analysis_data { |
358 | | uint32_t frag_cur_pos; |
359 | | uint32_t frag_tot_len; |
360 | | bool fragmentation; |
361 | | uint32_t frag_id; |
362 | | } subpacket_analysis_data_t; |
363 | | |
364 | | typedef struct packet_analysis_data { |
365 | | |
366 | | /* Contain information for each MPEG2-TS packet in the current big packet */ |
367 | | wmem_tree_t *subpacket_table; |
368 | | } packet_analysis_data_t; |
369 | | |
370 | | /* Analysis TS frame info needed during sequential processing */ |
371 | | typedef struct pid_analysis_data { |
372 | | uint16_t pid; |
373 | | int8_t cc_prev; /* Previous CC number */ |
374 | | enum pid_payload_type pload_type; |
375 | | wmem_tree_t *stream_types; |
376 | | |
377 | | /* Fragments information used for first pass */ |
378 | | bool fragmentation; |
379 | | uint32_t frag_cur_pos; |
380 | | uint32_t frag_tot_len; |
381 | | uint32_t frag_id; |
382 | | } pid_analysis_data_t; |
383 | | |
384 | | /* Analysis info stored for a TS frame */ |
385 | | typedef struct ts_analysis_data { |
386 | | uint16_t pid; |
387 | | int8_t cc_prev; /* Previous CC number */ |
388 | | uint8_t skips; /* Skips between Ccs max 14 */ |
389 | | } ts_analysis_data_t; |
390 | | |
391 | | |
392 | | typedef struct frame_analysis_data { |
393 | | |
394 | | /* As each frame has several pid's, thus need a pid data |
395 | | * structure per TS frame. |
396 | | */ |
397 | | wmem_tree_t *ts_table; |
398 | | |
399 | | } frame_analysis_data_t; |
400 | | |
401 | | static mp2t_analysis_data_t * |
402 | | init_mp2t_conversation_data(void) |
403 | 44 | { |
404 | 44 | mp2t_analysis_data_t *mp2t_data; |
405 | | |
406 | 44 | mp2t_data = wmem_new0(wmem_file_scope(), struct mp2t_analysis_data); |
407 | | |
408 | 44 | mp2t_data->stream = mp2t_stream_count++; |
409 | 44 | mp2t_data->pid_table = wmem_tree_new(wmem_file_scope()); |
410 | | |
411 | 44 | mp2t_data->frame_table = wmem_tree_new(wmem_file_scope()); |
412 | | |
413 | 44 | mp2t_data->total_skips = 0; |
414 | 44 | mp2t_data->total_discontinuity = 0; |
415 | | |
416 | 44 | return mp2t_data; |
417 | 44 | } |
418 | | |
419 | | static mp2t_analysis_data_t * |
420 | | get_mp2t_conversation_data(mp2t_stream_key *key) |
421 | 26.9k | { |
422 | 26.9k | mp2t_stream_key *new_key; |
423 | 26.9k | mp2t_analysis_data_t *mp2t_data; |
424 | | |
425 | 26.9k | mp2t_data = (mp2t_analysis_data_t *)wmem_map_lookup(mp2t_stream_hashtable, key); |
426 | 26.9k | if (!mp2t_data) { |
427 | 44 | new_key = wmem_new(wmem_file_scope(), mp2t_stream_key); |
428 | 44 | *new_key = *key; |
429 | 44 | mp2t_data = init_mp2t_conversation_data(); |
430 | 44 | wmem_map_insert(mp2t_stream_hashtable, new_key, mp2t_data); |
431 | 44 | } |
432 | | |
433 | 26.9k | return mp2t_data; |
434 | 26.9k | } |
435 | | |
436 | | static frame_analysis_data_t * |
437 | | init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo) |
438 | 136 | { |
439 | 136 | frame_analysis_data_t *frame_analysis_data_p; |
440 | | |
441 | 136 | frame_analysis_data_p = wmem_new0(wmem_file_scope(), struct frame_analysis_data); |
442 | 136 | frame_analysis_data_p->ts_table = wmem_tree_new(wmem_file_scope()); |
443 | | /* Insert into mp2t tree */ |
444 | 136 | wmem_tree_insert32(mp2t_data->frame_table, pinfo->num, |
445 | 136 | (void *)frame_analysis_data_p); |
446 | | |
447 | 136 | return frame_analysis_data_p; |
448 | 136 | } |
449 | | |
450 | | |
451 | | static frame_analysis_data_t * |
452 | | get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo) |
453 | 137 | { |
454 | 137 | frame_analysis_data_t *frame_analysis_data_p; |
455 | 137 | frame_analysis_data_p = (frame_analysis_data_t *)wmem_tree_lookup32(mp2t_data->frame_table, pinfo->num); |
456 | 137 | return frame_analysis_data_p; |
457 | 137 | } |
458 | | |
459 | | static pid_analysis_data_t * |
460 | | get_pid_analysis(mp2t_analysis_data_t *mp2t_data, uint32_t pid) |
461 | 27.5k | { |
462 | 27.5k | pid_analysis_data_t *pid_data; |
463 | | |
464 | 27.5k | pid_data = (pid_analysis_data_t *)wmem_tree_lookup32(mp2t_data->pid_table, pid); |
465 | 27.5k | if (!pid_data) { |
466 | 133 | pid_data = wmem_new0(wmem_file_scope(), struct pid_analysis_data); |
467 | 133 | pid_data->cc_prev = -1; |
468 | 133 | pid_data->pid = pid; |
469 | 133 | pid_data->stream_types = wmem_tree_new(wmem_file_scope()); |
470 | 133 | pid_data->frag_id = (pid << (32 - 13)) | 0x1; |
471 | | |
472 | 133 | wmem_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data); |
473 | 133 | } |
474 | 27.5k | return pid_data; |
475 | 27.5k | } |
476 | | |
477 | | uint32_t |
478 | | mp2t_get_stream_count(void) |
479 | 0 | { |
480 | 0 | return mp2t_stream_count; |
481 | 0 | } |
482 | | |
483 | | static void |
484 | | mp2t_init(void) |
485 | 15 | { |
486 | 15 | mp2t_stream_count = 0; |
487 | 15 | } |
488 | | |
489 | | static gboolean |
490 | | mp2t_stream_find(void *key _U_, void *value, void *user_data) |
491 | 0 | { |
492 | 0 | uint32_t stream = GPOINTER_TO_UINT(user_data); |
493 | 0 | mp2t_analysis_data_t *mp2t_data = (mp2t_analysis_data_t*)value; |
494 | 0 | if (mp2t_data->stream == stream) { |
495 | 0 | return true; |
496 | 0 | } |
497 | 0 | return false; |
498 | 0 | } |
499 | | |
500 | | bool |
501 | | mp2t_get_sub_stream_id(unsigned stream, unsigned sub_stream, bool le, unsigned *sub_stream_out) |
502 | 0 | { |
503 | 0 | mp2t_analysis_data_t *mp2t_data = wmem_map_find(mp2t_stream_hashtable, mp2t_stream_find, GUINT_TO_POINTER(stream)); |
504 | 0 | pid_analysis_data_t *pid_data; |
505 | 0 | if (!mp2t_data) { |
506 | 0 | return false; |
507 | 0 | } |
508 | 0 | if (le) { |
509 | 0 | pid_data = wmem_tree_lookup32_le(mp2t_data->pid_table, sub_stream); |
510 | 0 | } else { |
511 | 0 | pid_data = wmem_tree_lookup32_ge(mp2t_data->pid_table, sub_stream); |
512 | 0 | } |
513 | 0 | if (!pid_data) { |
514 | 0 | return false; |
515 | 0 | } |
516 | | |
517 | 0 | *sub_stream_out = pid_data->pid; |
518 | 0 | return true; |
519 | 0 | } |
520 | | |
521 | | char *mp2t_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream) |
522 | 0 | { |
523 | 0 | char *filter = NULL; |
524 | 0 | mp2t_stream_key *stream_key; |
525 | 0 | unsigned pid; |
526 | |
|
527 | 0 | stream_key = (mp2t_stream_key *)p_get_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_STREAM); |
528 | 0 | if (stream_key) { |
529 | 0 | mp2t_analysis_data_t *mp2t_data = get_mp2t_conversation_data(stream_key); |
530 | 0 | pid = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_PID)); |
531 | 0 | *stream = mp2t_data->stream; |
532 | 0 | *sub_stream = pid; |
533 | 0 | filter = ws_strdup_printf("mp2t.stream == %u && mp2t.pid == 0x%04x", *stream, pid); |
534 | 0 | } |
535 | 0 | return filter; |
536 | 0 | } |
537 | | |
538 | | char *mp2t_follow_index_filter(unsigned stream, unsigned sub_stream) |
539 | 0 | { |
540 | 0 | return ws_strdup_printf("mp2t.stream == %u && mp2t.pid == 0x%04x", stream, sub_stream); |
541 | 0 | } |
542 | | |
543 | | /* Structure to handle packets, spanned across |
544 | | * multiple MPEG packets |
545 | | */ |
546 | | |
547 | | /* Reassembly functions */ |
548 | | typedef struct _mp2t_fragment_key { |
549 | | uint32_t conv_index; /* Just use the unique index */ |
550 | | int dir; |
551 | | uint32_t id; |
552 | | } mp2t_fragment_key; |
553 | | |
554 | | static unsigned |
555 | | mp2t_fragment_hash(const void *k) |
556 | 2.41k | { |
557 | 2.41k | const mp2t_fragment_key* key = (const mp2t_fragment_key*) k; |
558 | 2.41k | unsigned hash_val; |
559 | | |
560 | 2.41k | hash_val = 0; |
561 | | |
562 | | /* In most captures there is only one conversation so optimize on |
563 | | * only using the id for the hash. */ |
564 | | // hash_val += (key->conv_index << 2) + key->dir; |
565 | | |
566 | 2.41k | hash_val ^= key->id; |
567 | | |
568 | 2.41k | return hash_val; |
569 | 2.41k | } |
570 | | |
571 | | static int |
572 | | mp2t_fragment_equal(const void *k1, const void *k2) |
573 | 1.11k | { |
574 | 1.11k | const mp2t_fragment_key* key1 = (const mp2t_fragment_key*) k1; |
575 | 1.11k | const mp2t_fragment_key* key2 = (const mp2t_fragment_key*) k2; |
576 | | |
577 | | /* Compare the id first since it's the most likely to differ */ |
578 | 1.11k | return (key1->id == key2->id) && |
579 | 1.11k | (key1->conv_index == key2->conv_index) && |
580 | 740 | (key1->dir == key2->dir); |
581 | 1.11k | } |
582 | | |
583 | | /* |
584 | | * Create a fragment key for permanent use; we are only copying ints, |
585 | | * so our temporary keys are the same as permanent ones. |
586 | | */ |
587 | | static void * |
588 | | mp2t_fragment_persistent_key(const packet_info *pinfo _U_, const uint32_t id, const void *data) |
589 | 2.05k | { |
590 | 2.05k | mp2t_fragment_key *key = g_slice_new(mp2t_fragment_key); |
591 | 2.05k | DISSECTOR_ASSERT(data); |
592 | 2.05k | mp2t_stream_key *stream = (mp2t_stream_key *)data; |
593 | | |
594 | 2.05k | key->conv_index = stream->conv->conv_index; |
595 | 2.05k | key->dir = stream->dir; |
596 | 2.05k | key->id = id; |
597 | | |
598 | 2.05k | return (void *)key; |
599 | 2.05k | } |
600 | | |
601 | | static void |
602 | | mp2t_fragment_free_persistent_key(void *ptr) |
603 | 1.97k | { |
604 | 1.97k | mp2t_fragment_key *key = (mp2t_fragment_key *)ptr; |
605 | 1.97k | g_slice_free(mp2t_fragment_key, key); |
606 | 1.97k | } |
607 | | |
608 | | static const reassembly_table_functions |
609 | | mp2t_reassembly_table_functions = { |
610 | | mp2t_fragment_hash, |
611 | | mp2t_fragment_equal, |
612 | | mp2t_fragment_persistent_key, |
613 | | mp2t_fragment_persistent_key, |
614 | | mp2t_fragment_free_persistent_key, |
615 | | mp2t_fragment_free_persistent_key |
616 | | }; |
617 | | |
618 | | static reassembly_table mp2t_reassembly_table; |
619 | | |
620 | | void |
621 | | mp2t_add_stream_type(packet_info *pinfo, uint32_t pid, uint32_t stream_type) |
622 | 88 | { |
623 | 88 | mp2t_stream_key *stream; |
624 | | |
625 | 88 | stream = (mp2t_stream_key *)p_get_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_STREAM); |
626 | 88 | if (!stream) { |
627 | 0 | return; |
628 | 0 | } |
629 | | |
630 | 88 | mp2t_analysis_data_t *mp2t_data = get_mp2t_conversation_data(stream); |
631 | 88 | pid_analysis_data_t *pid_data = get_pid_analysis(mp2t_data, pid); |
632 | | |
633 | 88 | if (!pid_data->stream_types) { |
634 | 0 | pid_data->stream_types = wmem_tree_new(wmem_file_scope()); |
635 | 0 | } |
636 | | |
637 | 88 | wmem_tree_insert32(pid_data->stream_types, pinfo->num, GUINT_TO_POINTER(stream_type)); |
638 | 88 | } |
639 | | |
640 | | static void |
641 | | mp2t_dissect_packet(tvbuff_t *tvb, const pid_analysis_data_t *pid_analysis, |
642 | | packet_info *pinfo, proto_tree *tree) |
643 | 756 | { |
644 | 756 | if (have_tap_listener(mp2t_follow_tap)) { |
645 | 0 | tap_queue_packet(mp2t_follow_tap, pinfo, tvb); |
646 | 0 | } |
647 | | |
648 | 756 | switch (pid_analysis->pload_type) { |
649 | 293 | case pid_pload_docsis: |
650 | 293 | call_dissector(docsis_handle, tvb, pinfo, tree); |
651 | 293 | break; |
652 | 8 | case pid_pload_pes: |
653 | 8 | call_dissector_with_data(mpeg_pes_handle, tvb, pinfo, tree, wmem_tree_lookup32_le(pid_analysis->stream_types, pinfo->num)); |
654 | 8 | break; |
655 | 455 | case pid_pload_sect: |
656 | 455 | call_dissector(mpeg_sect_handle, tvb, pinfo, tree); |
657 | 455 | break; |
658 | 0 | default: |
659 | | /* Should not happen */ |
660 | 0 | call_data_dissector(tvb, pinfo, tree); |
661 | 0 | break; |
662 | 756 | } |
663 | 756 | } |
664 | | |
665 | | /* Determine the length of a payload packet. If there aren't enough |
666 | | * bytes to determine the length, returns -1. This will usually be |
667 | | * called on the first fragment of a packet, but will be called |
668 | | * on the second fragment if it returned -1 previously. (Returning |
669 | | * -1 a second time indicates issues with dropped packets, etc.) |
670 | | */ |
671 | | static unsigned |
672 | | mp2t_get_packet_length(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
673 | | uint32_t frag_id, enum pid_payload_type pload_type) |
674 | 815 | { |
675 | 815 | mp2t_stream_key *stream; |
676 | 815 | fragment_head *frag_head; |
677 | 815 | fragment_item *frag = NULL; |
678 | 815 | tvbuff_t *len_tvb = NULL, *frag_tvb = NULL, *data_tvb = NULL; |
679 | 815 | int pkt_len = 0; |
680 | 815 | unsigned remaining_len; |
681 | | |
682 | 815 | stream = (mp2t_stream_key *)p_get_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_STREAM); |
683 | 815 | if (pinfo->fd->visited) { |
684 | 0 | frag_head = fragment_get_reassembled_id(&mp2t_reassembly_table, pinfo, frag_id); |
685 | 0 | if (frag_head) { |
686 | 0 | len_tvb = frag_head->tvb_data; |
687 | 0 | offset = 0; |
688 | 0 | } else { |
689 | | /* Not reassembled on the first pass. There are two possibilities: |
690 | | * 1) An entire packet contained within a TSP, so it never was |
691 | | * put in the table. |
692 | | * 2) Dangling fragments at the end of the capture. |
693 | | */ |
694 | 0 | frag_head = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, stream); |
695 | 0 | if (!frag_head) { |
696 | | /* This is the entire packet */ |
697 | 0 | len_tvb = tvb; |
698 | 0 | } else { |
699 | | /* Dangling packets at the end that failed to reassemble the |
700 | | * first time around, so don't bother this time |
701 | | */ |
702 | 0 | return -1; |
703 | 0 | } |
704 | 0 | } |
705 | 815 | } else { |
706 | 815 | frag_head = fragment_get(&mp2t_reassembly_table, pinfo, frag_id, stream); |
707 | 815 | if (frag_head) { |
708 | 21 | frag = frag_head->next; |
709 | 21 | } |
710 | | |
711 | 815 | if (!frag) { /* First frame */ |
712 | 794 | len_tvb = tvb; |
713 | 794 | } else { |
714 | | /* Create a composite tvb out of the two */ |
715 | 21 | frag_tvb = tvb_new_subset_remaining(frag->tvb_data, 0); |
716 | 21 | len_tvb = tvb_new_composite(); |
717 | 21 | tvb_composite_append(len_tvb, frag_tvb); |
718 | | |
719 | 21 | data_tvb = tvb_new_subset_remaining(tvb, offset); |
720 | 21 | tvb_composite_append(len_tvb, data_tvb); |
721 | 21 | tvb_composite_finalize(len_tvb); |
722 | | |
723 | 21 | offset = frag->offset; |
724 | 21 | } |
725 | 815 | } |
726 | | |
727 | | /* Get the next packet's size if possible; if not, return -1 */ |
728 | 815 | remaining_len = tvb_reported_length_remaining(len_tvb, offset); |
729 | | /* Normally the only time we would not enough info to determine the size |
730 | | * of the encapsulated packet is when the first fragment is at the very end |
731 | | * of a TSP, but prevent exceptions in the case of dropped and OOO frames. |
732 | | */ |
733 | 815 | switch (pload_type) { |
734 | 309 | case pid_pload_docsis: |
735 | 309 | if (remaining_len < 4) |
736 | 10 | return -1; |
737 | 299 | pkt_len = tvb_get_ntohs(len_tvb, offset + 2) + 6; |
738 | 299 | break; |
739 | 10 | case pid_pload_pes: |
740 | 10 | if (remaining_len < 6) |
741 | 0 | return -1; |
742 | 10 | pkt_len = tvb_get_ntohs(len_tvb, offset + 4); |
743 | 10 | if (pkt_len) /* A size of 0 means size not bounded */ |
744 | 10 | pkt_len += 6; |
745 | 10 | break; |
746 | 496 | case pid_pload_sect: |
747 | 496 | if (remaining_len < 3) |
748 | 10 | return -1; |
749 | 486 | pkt_len = (tvb_get_ntohs(len_tvb, offset + 1) & 0xFFF) + 3; |
750 | 486 | break; |
751 | 0 | default: |
752 | | /* Should not happen */ |
753 | 0 | break; |
754 | 815 | } |
755 | | |
756 | 795 | return pkt_len; |
757 | 815 | } |
758 | | |
759 | | static void |
760 | | mp2t_fragment_handle(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
761 | | proto_tree *tree, uint32_t frag_id, |
762 | | unsigned frag_offset, unsigned frag_len, |
763 | | bool fragment_last, const pid_analysis_data_t *pid_analysis) |
764 | 803 | { |
765 | 803 | fragment_head *frag_msg; |
766 | 803 | proto_item *ti; |
767 | 803 | tvbuff_t *new_tvb; |
768 | 803 | const char *save_proto; |
769 | 803 | mp2t_stream_key *stream; |
770 | 803 | bool save_fragmented; |
771 | | |
772 | 803 | save_fragmented = pinfo->fragmented; |
773 | 803 | pinfo->fragmented = true; |
774 | | /* It's possible that a fragment in the same packet set an address already |
775 | | * (e.g., with MPE), which is why we use the conversation and direction not |
776 | | * the addresses in the packet_info to reassemble. |
777 | | */ |
778 | | |
779 | 803 | stream = (mp2t_stream_key *)p_get_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_STREAM); |
780 | | /* check length; send frame for reassembly */ |
781 | 803 | frag_msg = fragment_add_check(&mp2t_reassembly_table, |
782 | 803 | tvb, offset, pinfo, frag_id, stream, |
783 | 803 | frag_offset, |
784 | 803 | frag_len, |
785 | 803 | !fragment_last); |
786 | | |
787 | | /* We only want to call subdissectors on the last fragment. |
788 | | * processed_reassembled_data checks the frame number and layer number, |
789 | | * but when there is more than one TSP in a frame, the fragment at the |
790 | | * end of one TSP and the first fragment of the next have the same layer |
791 | | * number. So use our own information about whether this is the last |
792 | | * fragment to avoid calling subdissectors early and often. |
793 | | */ |
794 | 803 | if (fragment_last) { |
795 | 413 | new_tvb = process_reassembled_data(tvb, offset, pinfo, |
796 | 413 | "Reassembled MP2T", |
797 | 413 | frag_msg, &mp2t_msg_frag_items, |
798 | 413 | NULL, tree); |
799 | 413 | } else { |
800 | 390 | new_tvb = NULL; |
801 | 390 | if (frag_msg != NULL) { |
802 | 0 | ti = proto_tree_add_uint(tree, hf_msg_reassembled_in, tvb, 0, 0, frag_msg->reassembled_in); |
803 | 0 | proto_item_set_generated(ti); |
804 | 0 | } |
805 | 390 | } |
806 | | |
807 | 803 | if (new_tvb) { |
808 | 354 | proto_tree_add_item(tree, hf_msg_ts_packet_reassembled, tvb, 0, 0, ENC_NA); |
809 | 354 | save_proto = pinfo->current_proto; |
810 | | /* |
811 | | * Dissect the reassembled packet. |
812 | | * |
813 | | * Because there isn't an explicit fragment ID (other than one |
814 | | * we've made ourselves) if frames were dropped or out of order |
815 | | * it's quite likely that a subdissector throws an exception. |
816 | | * However, that doesn't mean we must stop dissecting, since we have |
817 | | * the pointer to where the next upper level packet begins in the |
818 | | * TSP begins. (Also, we want to make sure we increment our fragment |
819 | | * ID and store the packet analysis data, which happens after this |
820 | | * back in the calling function.) |
821 | | */ |
822 | 354 | TRY { |
823 | 354 | mp2t_dissect_packet(new_tvb, pid_analysis, pinfo, tree); |
824 | 354 | } |
825 | 354 | CATCH_NONFATAL_ERRORS { |
826 | 269 | show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
827 | | |
828 | 269 | pinfo->current_proto = save_proto; |
829 | 269 | } |
830 | 354 | ENDTRY; |
831 | 449 | } else { |
832 | 449 | col_set_str(pinfo->cinfo, COL_INFO, "[MP2T fragment of a reassembled packet]"); |
833 | 449 | } |
834 | | |
835 | 803 | pinfo->fragmented = save_fragmented; |
836 | 803 | } |
837 | | |
838 | | |
839 | | /* |
840 | | * Reassembly of various payload types. |
841 | | * |
842 | | * DOCSIS MAC frames, PES packets, etc. may begin anywhere within an MPEG-TS |
843 | | * packet or span multiple MPEG packets. |
844 | | * |
845 | | * The payload_unit_start_indicator bit in the MPEG-TS header, and the pointer |
846 | | * field, are used to reassemble fragmented frames from MPEG-TS packets. |
847 | | * |
848 | | * If that bit is set, a higher-level packet begins in this MPEG-TS |
849 | | * packet, and the MPEG-TS header is followed by a 1-octet pointer field. |
850 | | * The value of the pointer field indicates at which byte the higher- |
851 | | * level packet begins. If that bit is not set, the packet begun in |
852 | | * an earlier MPEG-TS packet continues in this packet, with the data |
853 | | * in the payload going after the data in the previous MPEG-TS packet |
854 | | * (there can be more than one continuing packet). |
855 | | * |
856 | | * If the pointer field is non-zero, this MPEG-TS packet contains |
857 | | * the conclusion of one higher-level packet and the beginning of |
858 | | * the next packet. |
859 | | * |
860 | | * As the MPEG-TS packets are of a fixed size, stuff bytes are used |
861 | | * as padding before the first byte of a higher-level packet as |
862 | | * necessary. |
863 | | * |
864 | | * This diagram is from Data-Over-Cable Service Interface Specifications, |
865 | | * Downstream RF Interface Specification, CM-SP-DRFI-I16-170111, section 7 |
866 | | * "DOWNSTREAM TRANSMISSION CONVERGENCE SUBLAYER", and shows how the |
867 | | * higher-level packets are transported over the MPEG Transport Stream: |
868 | | * |
869 | | *+--------------------------------------------------------------------------------+ |
870 | | *|MPEG Header | pointer_field | stuff_bytes | Start of Packet #1 | |
871 | | *|(PUSI = 1) | (= 0) | (0 or more) | (up to 183 bytes) | |
872 | | *+--------------------------------------------------------------------------------+ |
873 | | *+--------------------------------------------------------------------------------+ |
874 | | *|MPEG Header | Continuation of Packet #1 | |
875 | | *|(PUSI = 0) | (up to 183 bytes) | |
876 | | *+--------------------------------------------------------------------------------+ |
877 | | *+---------------------------------------------------------------------------------+ |
878 | | *|MPEG Header | pointer_field |Tail of Packet #1 | stuff_bytes |Start of Packet #2 | |
879 | | *|(PUSI = 1) | (= M) |(M bytes) | (0 or more) |(N bytes) | |
880 | | *+---------------------------------------------------------------------------------+ |
881 | | * |
882 | | * For PES and PSI, see ISO/IEC 13818-1 / ITU-T Rec. H.222.0 (05/2006), |
883 | | * section 2.4.3.3 "Semantic definition of fields in Transport Stream packet |
884 | | * layer", which says much the same thing. |
885 | | * |
886 | | * When the payload is PES packet data, note that there is no pointer_field; |
887 | | * if the PUSI is 1 then the TS payload "will commence with the first byte |
888 | | * of a PES packet" and "one and only one PES packet starts in this Transport |
889 | | * Stream packet". Furthermore, section 2.4.3.5 "Semantic definition of |
890 | | * fields in adaptation field" mentions that stuffing in an adaptation field |
891 | | * is "the only method of stuffing allowed for Transport Stream packets |
892 | | * carrying PES packets." Thus stuff_bytes is not relevant for MPEG-TS payloads |
893 | | * carrying PES. (It is possible to have stuffing *inside* the PES packet, |
894 | | * as seen in section 2.4.3.6 "PES packet" and 2.4.3.7 "Semantic definition |
895 | | * of fields in PES packet", which is handled in the MPEG PES dissector.) |
896 | | * |
897 | | * For MPEG-TS packets carrying PSI (which includes private data sections), an |
898 | | * alternative stuffing method is allowed. This method involves stuff bytes |
899 | | * at the end of a MPEG-TS packet after the last section contained within |
900 | | * (similar to the stuff_bytes that may appear after a continued section |
901 | | * before the byte referenced by pointer_field). According to Section 2.4.4 |
902 | | * "Program specific information", once a packet stuffing byte 0xFF appears, |
903 | | * "all bytes until the end of the Transport Stream packet shall also be |
904 | | * stuffing bytes of value 0xFF." In other words, as section C.3 "The Mapping |
905 | | * of Sections into Transport Stream Packets" elaborates, while multiple |
906 | | * entire sections are allowed within a TS packet, "no gaps between sections |
907 | | * within a Transport Stream packet are allowed by the syntax". |
908 | | * |
909 | | * However, this function is permissive in what it accepts to the extent |
910 | | * possible; it will allow multiple PES packets in the same TS packet and |
911 | | * stuffing bytes to follow PES packets (at least those that indicate their |
912 | | * length) and will allow stuffing bytes between complete PSI sections. |
913 | | */ |
914 | | static void |
915 | | mp2t_process_fragmented_payload(tvbuff_t *tvb, int offset, unsigned remaining_len, packet_info *pinfo, |
916 | | proto_tree *tree, proto_tree *header_tree, uint32_t pusi_flag, |
917 | | pid_analysis_data_t *pid_analysis) |
918 | 524 | { |
919 | 524 | tvbuff_t *next_tvb; |
920 | 524 | uint8_t pointer = 0; |
921 | 524 | proto_item *pi; |
922 | 524 | unsigned stuff_len = 0; |
923 | 524 | proto_tree *stuff_tree; |
924 | 524 | packet_analysis_data_t *pdata = NULL; |
925 | 524 | subpacket_analysis_data_t *spdata = NULL; |
926 | 524 | uint32_t frag_cur_pos = 0, frag_tot_len = 0; |
927 | 524 | bool fragmentation = false; |
928 | 524 | uint32_t frag_id = 0; |
929 | | |
930 | 524 | if (pusi_flag && pid_analysis->pload_type == pid_pload_unknown |
931 | 39 | && remaining_len > 3) { |
932 | | /* We should already have identified if it was a DOCSIS packet |
933 | | * Remaining possibility is PES or SECT */ |
934 | 39 | if (tvb_get_ntoh24(tvb, offset) == 0x000001) { |
935 | | /* Looks like a PES packet to me ... */ |
936 | 2 | pid_analysis->pload_type = pid_pload_pes; |
937 | 37 | } else { |
938 | | /* Most probably a SECT packet */ |
939 | 37 | pid_analysis->pload_type = pid_pload_sect; |
940 | 37 | } |
941 | 39 | } |
942 | | |
943 | | /* Unable to determine the payload type, do nothing */ |
944 | 524 | if (pid_analysis->pload_type == pid_pload_unknown) |
945 | 19 | return; |
946 | | |
947 | | /* PES packet don't have pointer fields, others do */ |
948 | 505 | if (pusi_flag && pid_analysis->pload_type != pid_pload_pes) { |
949 | 494 | pi = proto_tree_add_item_ret_uint8(header_tree, hf_mp2t_pointer, tvb, offset, 1, ENC_BIG_ENDIAN, &pointer); |
950 | 494 | offset++; |
951 | 494 | remaining_len--; |
952 | 494 | if (pointer > remaining_len) { |
953 | | /* Bogus pointer */ |
954 | 33 | expert_add_info_format(pinfo, pi, &ei_mp2t_pointer, |
955 | 33 | "Pointer value is too large (> remaining data length %u)", |
956 | 33 | remaining_len); |
957 | 33 | } |
958 | 494 | } |
959 | | |
960 | 505 | if (!pinfo->fd->visited) { |
961 | | /* Get values from our current PID analysis */ |
962 | 505 | frag_cur_pos = pid_analysis->frag_cur_pos; |
963 | 505 | frag_tot_len = pid_analysis->frag_tot_len; |
964 | 505 | fragmentation = pid_analysis->fragmentation; |
965 | 505 | frag_id = pid_analysis->frag_id; |
966 | 505 | pdata = (packet_analysis_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mp2t, pinfo->curr_layer_num); |
967 | 505 | if (!pdata) { |
968 | 505 | pdata = wmem_new0(wmem_file_scope(), packet_analysis_data_t); |
969 | 505 | pdata->subpacket_table = wmem_tree_new(wmem_file_scope()); |
970 | | /* Since the subpacket data is indexed by offset in the tvb, |
971 | | * lacking a fragment id transmitted in the protocol, |
972 | | * we need a different table for each mp2t layer. |
973 | | */ |
974 | 505 | p_add_proto_data(wmem_file_scope(), pinfo, proto_mp2t, pinfo->curr_layer_num, pdata); |
975 | | |
976 | 505 | } else { |
977 | 0 | spdata = (subpacket_analysis_data_t *)wmem_tree_lookup32(pdata->subpacket_table, offset); |
978 | 0 | } |
979 | | |
980 | 505 | if (!spdata) { |
981 | 505 | spdata = wmem_new0(wmem_file_scope(), subpacket_analysis_data_t); |
982 | | /* Save the info into pdata from pid_analysis */ |
983 | 505 | spdata->frag_cur_pos = frag_cur_pos; |
984 | 505 | spdata->frag_tot_len = frag_tot_len; |
985 | 505 | spdata->fragmentation = fragmentation; |
986 | 505 | spdata->frag_id = frag_id; |
987 | 505 | wmem_tree_insert32(pdata->subpacket_table, offset, (void *)spdata); |
988 | 505 | } |
989 | 505 | } else { |
990 | | /* Get saved values */ |
991 | 0 | pdata = (packet_analysis_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mp2t, pinfo->curr_layer_num); |
992 | 0 | if (!pdata) { |
993 | | /* Occurs for the first packets in the capture which cannot be reassembled */ |
994 | 0 | return; |
995 | 0 | } |
996 | | |
997 | 0 | spdata = (subpacket_analysis_data_t *)wmem_tree_lookup32(pdata->subpacket_table, offset); |
998 | 0 | if (!spdata) { |
999 | | /* Occurs for the first sub packets in the capture which cannot be reassembled */ |
1000 | 0 | return; |
1001 | 0 | } |
1002 | | |
1003 | 0 | frag_cur_pos = spdata->frag_cur_pos; |
1004 | 0 | frag_tot_len = spdata->frag_tot_len; |
1005 | 0 | fragmentation = spdata->fragmentation; |
1006 | 0 | frag_id = spdata->frag_id; |
1007 | 0 | } |
1008 | | |
1009 | 505 | if (frag_tot_len == (unsigned)-1) { |
1010 | | /* We couldn't determine the total length of the reassembly from |
1011 | | * the first fragment (too short), so get it now that we have the |
1012 | | * second fragment. |
1013 | | */ |
1014 | 25 | frag_tot_len = mp2t_get_packet_length(tvb, offset, pinfo, frag_id, pid_analysis->pload_type); |
1015 | | |
1016 | 25 | if (frag_tot_len == (unsigned)-1) { |
1017 | | /* We still don't have enough to determine the length; this can |
1018 | | * only happen with dropped or out of order packets. Bail out. |
1019 | | * XXX: This just skips the packet and tries the next one, but |
1020 | | * there are probably better ways to handle it, especially if |
1021 | | * the PUSI flag is set in this packet. |
1022 | | */ |
1023 | 0 | return; |
1024 | 0 | } |
1025 | 25 | } |
1026 | | |
1027 | | /* The beginning of a new packet is present */ |
1028 | 505 | if (pusi_flag) { |
1029 | 503 | if (pointer > remaining_len) { |
1030 | | /* |
1031 | | * Quit, so we don't use the bogus pointer value; |
1032 | | * that could cause remaining_len to become |
1033 | | * "negative", meaning it becomes a very large |
1034 | | * positive value. |
1035 | | */ |
1036 | 33 | return; |
1037 | 33 | } |
1038 | | |
1039 | | /* "pointer" contains the number of bytes until the |
1040 | | * start of the new section |
1041 | | * |
1042 | | * if the new section does not start immediately after the |
1043 | | * pointer field (i.e. pointer>0), the remaining bytes before the |
1044 | | * start of the section are another fragment of the |
1045 | | * current packet |
1046 | | * |
1047 | | * if pointer is 0, a new upper-layer packet starts at the |
1048 | | * beginning of this TS packet |
1049 | | * if we have pending fragments, the last TS packet contained the |
1050 | | * last fragment and at the time we processed it, we couldn't figure |
1051 | | * out that it is the last fragment |
1052 | | * this is the case e.g. for PES packets with a 0 length field |
1053 | | * ("unbounded length") |
1054 | | * to handle this case, we add an empty fragment (pointer==0) |
1055 | | * and reassemble, then we process the current TS packet as |
1056 | | * usual |
1057 | | */ |
1058 | 470 | if (fragmentation) { |
1059 | 413 | mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, |
1060 | 413 | pointer, true, pid_analysis); |
1061 | 413 | frag_id++; |
1062 | 413 | } |
1063 | | |
1064 | 470 | offset += pointer; |
1065 | 470 | remaining_len -= pointer; |
1066 | 470 | fragmentation = false; |
1067 | 470 | frag_cur_pos = 0; |
1068 | 470 | frag_tot_len = 0; |
1069 | | |
1070 | 470 | if (!remaining_len) { |
1071 | | /* Shouldn't happen */ |
1072 | 1 | goto save_state; |
1073 | 1 | } |
1074 | | |
1075 | 871 | while (remaining_len > 0) { |
1076 | | /* Don't let subsequent packets overwrite the Info column */ |
1077 | 791 | col_append_str(pinfo->cinfo, COL_INFO, " "); |
1078 | 791 | col_set_fence(pinfo->cinfo, COL_INFO); |
1079 | | |
1080 | | /* Skip stuff bytes */ |
1081 | 791 | stuff_len = 0; |
1082 | 1.26k | while ((tvb_get_uint8(tvb, offset + stuff_len) == 0xFF)) { |
1083 | 473 | stuff_len++; |
1084 | 473 | if (stuff_len >= remaining_len) { |
1085 | 1 | remaining_len = 0; |
1086 | 1 | break; |
1087 | 1 | } |
1088 | 473 | } |
1089 | | |
1090 | 791 | if (stuff_len) { |
1091 | 33 | stuff_tree = proto_tree_add_subtree_format(tree, tvb, offset, stuff_len, ett_stuff, NULL, "Stuffing"); |
1092 | 33 | proto_tree_add_item(stuff_tree, hf_mp2t_stuff_bytes, tvb, offset, stuff_len, ENC_NA); |
1093 | 33 | offset += stuff_len; |
1094 | 33 | if (stuff_len >= remaining_len) { |
1095 | 1 | goto save_state; |
1096 | 1 | } |
1097 | 32 | remaining_len -= stuff_len; |
1098 | 32 | } |
1099 | | |
1100 | | /* Get the next packet's size if possible */ |
1101 | 790 | frag_tot_len = mp2t_get_packet_length(tvb, offset, pinfo, frag_id, pid_analysis->pload_type); |
1102 | 790 | if (frag_tot_len == (unsigned)-1 || !frag_tot_len) { |
1103 | 20 | mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, 0, remaining_len, false, pid_analysis); |
1104 | 20 | fragmentation = true; |
1105 | | /*offset += remaining_len;*/ |
1106 | 20 | frag_cur_pos += remaining_len; |
1107 | 20 | goto save_state; |
1108 | 20 | } |
1109 | | |
1110 | | /* Check for full packets within this TS frame */ |
1111 | 770 | if (frag_tot_len <= remaining_len) { |
1112 | 402 | next_tvb = tvb_new_subset_length(tvb, offset, frag_tot_len); |
1113 | 402 | mp2t_dissect_packet(next_tvb, pid_analysis, pinfo, tree); |
1114 | 402 | remaining_len -= frag_tot_len; |
1115 | 402 | offset += frag_tot_len; |
1116 | 402 | frag_tot_len = 0; |
1117 | 402 | frag_id++; |
1118 | 402 | } else { |
1119 | 368 | break; |
1120 | 368 | } |
1121 | 770 | } |
1122 | | |
1123 | 448 | if (remaining_len == 0) { |
1124 | 1 | pid_analysis->frag_cur_pos = 0; |
1125 | 1 | pid_analysis->frag_tot_len = 0; |
1126 | 1 | goto save_state; |
1127 | | |
1128 | 1 | } |
1129 | | |
1130 | 448 | } |
1131 | | |
1132 | | /* There are remaining bytes. Add them to the fragment list */ |
1133 | | |
1134 | 449 | if (frag_tot_len && frag_cur_pos + remaining_len > frag_tot_len) { |
1135 | | /* The case where PUSI was 0, a continuing SECT ended, and stuff |
1136 | | * bytes follow. */ |
1137 | 0 | stuff_len = frag_cur_pos + remaining_len - frag_tot_len; |
1138 | 0 | mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len - stuff_len, true, pid_analysis); |
1139 | 0 | offset += remaining_len - stuff_len; |
1140 | 0 | frag_id++; |
1141 | 0 | fragmentation = false; |
1142 | 0 | frag_cur_pos = 0; |
1143 | 0 | frag_tot_len = 0; |
1144 | 0 | stuff_tree = proto_tree_add_subtree_format(tree, tvb, offset, stuff_len, ett_stuff, NULL, "Stuffing"); |
1145 | 0 | proto_tree_add_item(stuff_tree, hf_mp2t_stuff_bytes, tvb, offset, stuff_len, ENC_NA); |
1146 | 449 | } else if ((frag_tot_len && frag_cur_pos + remaining_len == frag_tot_len) || (!frag_tot_len && pusi_flag)) { |
1147 | 0 | mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len, true, pid_analysis); |
1148 | 0 | frag_id++; |
1149 | 0 | fragmentation = false; |
1150 | 0 | frag_cur_pos = 0; |
1151 | 0 | frag_tot_len = 0; |
1152 | 449 | } else { |
1153 | 449 | mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len, false, pid_analysis); |
1154 | 449 | fragmentation = true; |
1155 | 449 | frag_cur_pos += remaining_len; |
1156 | 449 | } |
1157 | | |
1158 | | /* XXX: Ideally this would be handled with a TRY...FINALLY or |
1159 | | * similar, with more care taken to keep things consistent even |
1160 | | * with fatal errors in subdissectors. |
1161 | | */ |
1162 | 449 | save_state: |
1163 | 393 | pid_analysis->fragmentation = fragmentation; |
1164 | 393 | pid_analysis->frag_cur_pos = frag_cur_pos; |
1165 | 393 | pid_analysis->frag_tot_len = frag_tot_len; |
1166 | 393 | pid_analysis->frag_id = frag_id; |
1167 | 393 | } |
1168 | | |
1169 | | |
1170 | | |
1171 | | /* Calc the number of skipped CC numbers. Note that this can easy |
1172 | | * overflow, and a value above 7 indicate several network packets |
1173 | | * could be lost. |
1174 | | */ |
1175 | | static uint32_t |
1176 | | calc_skips(int32_t curr, int32_t prev) |
1177 | 137 | { |
1178 | 137 | int res; |
1179 | | |
1180 | | /* Only count the missing TS frames in between prev and curr. |
1181 | | * The "prev" frame CC number seen is confirmed received, it's |
1182 | | * the next frames CC counter which is the first known missing |
1183 | | * TS frame |
1184 | | */ |
1185 | 137 | prev += 1; |
1186 | | |
1187 | | /* Calc missing TS frame 'skips' */ |
1188 | 137 | res = curr - prev; |
1189 | | |
1190 | | /* Handle wrap around */ |
1191 | 137 | if (res < 0) |
1192 | 121 | res += 16; |
1193 | | |
1194 | 137 | return res; |
1195 | 137 | } |
1196 | | |
1197 | 137 | #define KEY(pid, cc) ((pid << 4)|cc) |
1198 | | |
1199 | | static uint32_t |
1200 | | detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, |
1201 | | uint32_t pid, int32_t cc_curr, mp2t_analysis_data_t *mp2t_data) |
1202 | 603 | { |
1203 | 603 | int32_t cc_prev = -1; |
1204 | 603 | pid_analysis_data_t *pid_data = NULL; |
1205 | 603 | ts_analysis_data_t *ts_data = NULL; |
1206 | 603 | frame_analysis_data_t *frame_analysis_data_p = NULL; |
1207 | 603 | proto_item *flags_item; |
1208 | | |
1209 | 603 | bool detected_drop = false; |
1210 | 603 | uint32_t skips = 0; |
1211 | | |
1212 | | /* The initial sequential processing stage */ |
1213 | 603 | if (!pinfo->fd->visited) { |
1214 | | /* This is the sequential processing stage */ |
1215 | 603 | pid_data = get_pid_analysis(mp2t_data, pid); |
1216 | | |
1217 | 603 | cc_prev = pid_data->cc_prev; |
1218 | 603 | pid_data->cc_prev = cc_curr; |
1219 | | |
1220 | | /* Null packet always have a CC value equal 0 */ |
1221 | 603 | if (pid == 0x1fff) |
1222 | 0 | return 0; |
1223 | | |
1224 | | /* Its allowed that (cc_prev == cc_curr) if adaptation field */ |
1225 | 603 | if (cc_prev == cc_curr) |
1226 | 27 | return 0; |
1227 | | |
1228 | | /* Have not seen this pid before */ |
1229 | 576 | if (cc_prev == -1) |
1230 | 83 | return 0; |
1231 | | |
1232 | | /* Detect if CC is not increasing by one all the time */ |
1233 | 493 | if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) { |
1234 | 137 | detected_drop = true; |
1235 | | |
1236 | 137 | skips = calc_skips(cc_curr, cc_prev); |
1237 | | |
1238 | 137 | mp2t_data->total_skips += skips; |
1239 | 137 | mp2t_data->total_discontinuity++; |
1240 | | /* TODO: if (skips > 7) signal_loss++; ??? */ |
1241 | 137 | } |
1242 | 493 | } |
1243 | | |
1244 | | /* Save the info about the dropped packet */ |
1245 | 493 | if (detected_drop && !pinfo->fd->visited) { |
1246 | | /* Lookup frame data, contains TS pid data objects */ |
1247 | 137 | frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo); |
1248 | 137 | if (!frame_analysis_data_p) |
1249 | 136 | frame_analysis_data_p = init_frame_analysis_data(mp2t_data, pinfo); |
1250 | | |
1251 | | /* Create and store a new TS frame pid_data object. |
1252 | | This indicate that we have a drop |
1253 | | */ |
1254 | 137 | ts_data = wmem_new0(wmem_file_scope(), struct ts_analysis_data); |
1255 | 137 | ts_data->cc_prev = cc_prev; |
1256 | 137 | ts_data->pid = pid; |
1257 | 137 | ts_data->skips = skips; |
1258 | 137 | wmem_tree_insert32(frame_analysis_data_p->ts_table, KEY(pid, cc_curr), |
1259 | 137 | (void *)ts_data); |
1260 | 137 | } |
1261 | | |
1262 | | /* See if we stored info about drops */ |
1263 | 493 | if (pinfo->fd->visited) { |
1264 | | |
1265 | | /* Lookup frame data, contains TS pid data objects */ |
1266 | 0 | frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo); |
1267 | 0 | if (!frame_analysis_data_p) |
1268 | 0 | return 0; /* No stored frame data -> no drops*/ |
1269 | 0 | else { |
1270 | 0 | ts_data = (struct ts_analysis_data *)wmem_tree_lookup32(frame_analysis_data_p->ts_table, |
1271 | 0 | KEY(pid, cc_curr)); |
1272 | |
|
1273 | 0 | if (ts_data) { |
1274 | 0 | if (ts_data->skips > 0) { |
1275 | 0 | detected_drop = true; |
1276 | 0 | cc_prev = ts_data->cc_prev; |
1277 | 0 | skips = ts_data->skips; |
1278 | 0 | } |
1279 | 0 | } |
1280 | 0 | } |
1281 | 0 | } |
1282 | | |
1283 | | /* Add info to the proto tree about drops */ |
1284 | 493 | if (detected_drop) { |
1285 | 137 | expert_add_info_format(pinfo, tree, &ei_mp2t_cc_drop, |
1286 | 137 | "Detected %d missing TS frames before this (last_cc:%d total skips:%d discontinuity:%d)", |
1287 | 137 | skips, cc_prev, |
1288 | 137 | mp2t_data->total_skips, |
1289 | 137 | mp2t_data->total_discontinuity |
1290 | 137 | ); |
1291 | | |
1292 | 137 | flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_skips, |
1293 | 137 | tvb, 0, 0, skips); |
1294 | 137 | proto_item_set_generated(flags_item); |
1295 | | |
1296 | 137 | flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_drops, |
1297 | 137 | tvb, 0, 0, 1); |
1298 | 137 | proto_item_set_generated(flags_item); |
1299 | 137 | } |
1300 | 493 | return skips; |
1301 | 493 | } |
1302 | | |
1303 | | static int |
1304 | | dissect_mp2t_adaptation_field(tvbuff_t *tvb, int offset, proto_tree *tree) |
1305 | 149 | { |
1306 | 149 | int af_start_offset; |
1307 | 149 | proto_item *hi; |
1308 | 149 | proto_tree *mp2t_af_tree; |
1309 | 149 | uint8_t af_length; |
1310 | 149 | uint8_t af_flags; |
1311 | 149 | int stuffing_len; |
1312 | | |
1313 | 149 | proto_tree_add_item_ret_uint8(tree, hf_mp2t_af_length, tvb, offset, 1, ENC_BIG_ENDIAN, &af_length); |
1314 | 149 | offset += 1; |
1315 | | /* fix issues where afc==3 but af_length==0 |
1316 | | * Adaptation field...spec section 2.4.3.5: The value 0 is for inserting a single |
1317 | | * stuffing byte in a Transport Stream packet. When the adaptation_field_control |
1318 | | * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182. |
1319 | | */ |
1320 | 149 | if (af_length == 0) |
1321 | 26 | return offset; |
1322 | | |
1323 | 123 | af_start_offset = offset; |
1324 | | |
1325 | 123 | hi = proto_tree_add_item( tree, hf_mp2t_af, tvb, offset, af_length, ENC_NA); |
1326 | 123 | mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af ); |
1327 | | |
1328 | 123 | af_flags = tvb_get_uint8(tvb, offset); |
1329 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, ENC_BIG_ENDIAN); |
1330 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, ENC_BIG_ENDIAN); |
1331 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1332 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1333 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1334 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1335 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1336 | 123 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1337 | 123 | offset += 1; |
1338 | | |
1339 | 123 | if (af_flags & MP2T_AF_PCR_MASK) { |
1340 | 58 | uint64_t pcr_base; |
1341 | 58 | uint16_t pcr_ext; |
1342 | | |
1343 | | /* 33 bit PCR base, 6 bit reserved, 9 bit PCR ext */ |
1344 | 58 | pcr_base = tvb_get_ntoh48(tvb, offset) >> (48-33); |
1345 | 58 | pcr_ext = (uint16_t)(tvb_get_ntoh48(tvb, offset) & 0x1FF); |
1346 | | |
1347 | 58 | proto_tree_add_uint64(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset, 6, |
1348 | 58 | pcr_base*300 + pcr_ext); |
1349 | | |
1350 | 58 | offset += 6; |
1351 | 58 | } |
1352 | | |
1353 | 123 | if (af_flags & MP2T_AF_OPCR_MASK) { |
1354 | 53 | uint64_t opcr_base; |
1355 | 53 | uint16_t opcr_ext; |
1356 | | |
1357 | | /* the same format as PCR above */ |
1358 | 53 | opcr_base = tvb_get_ntoh48(tvb, offset) >> (48-33); |
1359 | 53 | opcr_ext = (uint16_t)(tvb_get_ntoh48(tvb, offset) & 0x1FF); |
1360 | | |
1361 | 53 | proto_tree_add_uint64(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset, 6, |
1362 | 53 | opcr_base*300 + opcr_ext); |
1363 | | |
1364 | 53 | offset += 6; |
1365 | 53 | } |
1366 | | |
1367 | 123 | if (af_flags & MP2T_AF_SP_MASK) { |
1368 | 53 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, ENC_BIG_ENDIAN); |
1369 | 53 | offset += 1; |
1370 | 53 | } |
1371 | | |
1372 | 123 | if (af_flags & MP2T_AF_TPD_MASK) { |
1373 | 53 | uint8_t tpd_len; |
1374 | | |
1375 | 53 | tpd_len = tvb_get_uint8(tvb, offset); |
1376 | 53 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
1377 | 53 | offset += 1; |
1378 | | |
1379 | 53 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, ENC_NA); |
1380 | 53 | offset += tpd_len; |
1381 | 53 | } |
1382 | | |
1383 | 123 | if (af_flags & MP2T_AF_AFE_MASK) { |
1384 | 59 | uint8_t e_len; |
1385 | 59 | uint8_t e_flags; |
1386 | 59 | int e_start_offset = offset; |
1387 | 59 | int reserved_len = 0; |
1388 | | |
1389 | 59 | e_len = tvb_get_uint8(tvb, offset); |
1390 | 59 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, ENC_BIG_ENDIAN); |
1391 | 59 | offset += 1; |
1392 | | |
1393 | 59 | e_flags = tvb_get_uint8(tvb, offset); |
1394 | 59 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1395 | 59 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1396 | 59 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
1397 | 59 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); |
1398 | 59 | offset += 1; |
1399 | | |
1400 | 59 | if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) { |
1401 | 22 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, ENC_BIG_ENDIAN); |
1402 | 22 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, ENC_BIG_ENDIAN); |
1403 | 22 | offset += 2; |
1404 | 22 | } |
1405 | | |
1406 | 59 | if (e_flags & MP2T_AF_E_PR_FLAG_MASK) { |
1407 | 23 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, ENC_BIG_ENDIAN); |
1408 | 23 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, ENC_BIG_ENDIAN); |
1409 | 23 | offset += 3; |
1410 | 23 | } |
1411 | | |
1412 | 59 | if (e_flags & MP2T_AF_E_SS_FLAG_MASK) { |
1413 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, ENC_BIG_ENDIAN); |
1414 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, ENC_BIG_ENDIAN); |
1415 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, ENC_BIG_ENDIAN); |
1416 | 31 | offset += 1; |
1417 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, ENC_BIG_ENDIAN); |
1418 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, ENC_BIG_ENDIAN); |
1419 | 31 | offset += 2; |
1420 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, ENC_BIG_ENDIAN); |
1421 | 31 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, ENC_BIG_ENDIAN); |
1422 | 31 | offset += 2; |
1423 | 31 | } |
1424 | | |
1425 | 59 | reserved_len = (e_len + 1) - (offset - e_start_offset); |
1426 | 59 | if (reserved_len > 0) { |
1427 | 45 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, ENC_NA); |
1428 | 45 | offset += reserved_len; |
1429 | 45 | } |
1430 | 59 | } |
1431 | | |
1432 | 123 | stuffing_len = af_length - (offset - af_start_offset); |
1433 | 123 | if (stuffing_len > 0) { |
1434 | 52 | proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, ENC_NA); |
1435 | 52 | offset += stuffing_len; |
1436 | 52 | } |
1437 | | |
1438 | 123 | return offset; |
1439 | 149 | } |
1440 | | |
1441 | | static void |
1442 | | dissect_tsp(tvbuff_t *tvb, int offset, packet_info *pinfo, |
1443 | | proto_tree *tree, mp2t_analysis_data_t *mp2t_data) |
1444 | 26.8k | { |
1445 | 26.8k | uint32_t header; |
1446 | 26.8k | unsigned afc; |
1447 | 26.8k | int start_offset = offset; |
1448 | 26.8k | int payload_len; |
1449 | 26.8k | pid_analysis_data_t *pid_analysis; |
1450 | | |
1451 | 26.8k | uint32_t skips; |
1452 | 26.8k | uint32_t pid; |
1453 | 26.8k | uint32_t cc; |
1454 | 26.8k | uint32_t pusi_flag; |
1455 | | |
1456 | 26.8k | uint32_t tsc; |
1457 | | |
1458 | 26.8k | proto_item *ti; |
1459 | 26.8k | proto_item *hi; |
1460 | 26.8k | proto_item *item = NULL; |
1461 | 26.8k | proto_tree *mp2t_tree; |
1462 | 26.8k | proto_tree *mp2t_header_tree; |
1463 | 26.8k | proto_tree *mp2t_analysis_tree; |
1464 | 26.8k | proto_item *afci; |
1465 | | |
1466 | 26.8k | ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, ENC_NA ); |
1467 | 26.8k | mp2t_tree = proto_item_add_subtree( ti, ett_mp2t ); |
1468 | | |
1469 | 26.8k | header = tvb_get_ntohl(tvb, offset); |
1470 | 26.8k | pusi_flag = (header & 0x00400000); |
1471 | 26.8k | pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT; |
1472 | 26.8k | tsc = (header & MP2T_TSC_MASK); |
1473 | 26.8k | afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT; |
1474 | 26.8k | cc = (header & MP2T_CC_MASK) >> MP2T_CC_SHIFT; |
1475 | | |
1476 | 26.8k | p_add_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_PID, GUINT_TO_POINTER(pid)); |
1477 | 26.8k | proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc); |
1478 | 26.8k | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPEG TS"); |
1479 | | |
1480 | 26.8k | hi = proto_tree_add_uint(mp2t_tree, hf_mp2t_stream, tvb, 0, 0, mp2t_data->stream); |
1481 | 26.8k | proto_item_set_generated(hi); |
1482 | | |
1483 | 26.8k | hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, ENC_BIG_ENDIAN); |
1484 | 26.8k | mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header ); |
1485 | | |
1486 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, ENC_BIG_ENDIAN); |
1487 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, ENC_BIG_ENDIAN); |
1488 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, ENC_BIG_ENDIAN); |
1489 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, ENC_BIG_ENDIAN); |
1490 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, ENC_BIG_ENDIAN); |
1491 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, ENC_BIG_ENDIAN); |
1492 | 26.8k | afci = proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, ENC_BIG_ENDIAN); |
1493 | 26.8k | proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, ENC_BIG_ENDIAN); |
1494 | | |
1495 | 26.8k | pid_analysis = get_pid_analysis(mp2t_data, pid); |
1496 | | |
1497 | 26.8k | if (pid_analysis->pload_type == pid_pload_unknown) { |
1498 | 164 | if (pid == MP2T_PID_NULL) { |
1499 | 38 | pid_analysis->pload_type = pid_pload_null; |
1500 | 126 | } else if (pid == MP2T_PID_DOCSIS) { |
1501 | 7 | pid_analysis->pload_type = pid_pload_docsis; |
1502 | 7 | } |
1503 | 164 | } |
1504 | | |
1505 | 26.8k | if (pid_analysis->pload_type == pid_pload_docsis && (afc != 1)) { |
1506 | | /* DOCSIS packets should not have an adaptation field */ |
1507 | 51 | expert_add_info_format(pinfo, afci, &ei_mp2t_invalid_afc, |
1508 | 51 | "Adaptation Field Control for DOCSIS packets must be 0x01"); |
1509 | 51 | } |
1510 | | |
1511 | 26.8k | if (pid_analysis->pload_type == pid_pload_null) { |
1512 | 26.2k | col_set_str(pinfo->cinfo, COL_INFO, "NULL packet"); |
1513 | 26.2k | if (afc != 1) { |
1514 | 12 | expert_add_info_format(pinfo, afci, &ei_mp2t_invalid_afc, |
1515 | 12 | "Adaptation Field Control for NULL packets must be 0x01"); |
1516 | 12 | } |
1517 | | /* Nothing more to do */ |
1518 | 26.2k | return; |
1519 | 26.2k | } |
1520 | | |
1521 | 603 | offset += 4; |
1522 | | |
1523 | | /* Create a subtree for analysis stuff */ |
1524 | 603 | mp2t_analysis_tree = proto_tree_add_subtree_format(mp2t_tree, tvb, offset, 0, ett_mp2t_analysis, &item, "MPEG2 PCR Analysis"); |
1525 | 603 | proto_item_set_generated(item); |
1526 | | |
1527 | 603 | skips = detect_cc_drops(tvb, mp2t_analysis_tree, pinfo, pid, cc, mp2t_data); |
1528 | | |
1529 | 603 | if (skips > 0) |
1530 | 137 | proto_item_append_text(ti, " skips=%d", skips); |
1531 | | |
1532 | 603 | if (afc == 2 || afc == 3) |
1533 | 149 | offset = dissect_mp2t_adaptation_field(tvb, offset, mp2t_tree); |
1534 | | |
1535 | 603 | if ((offset - start_offset) < MP2T_PACKET_SIZE) |
1536 | 558 | payload_len = MP2T_PACKET_SIZE - (offset - start_offset); |
1537 | 45 | else |
1538 | 45 | payload_len = 0; |
1539 | | |
1540 | 603 | if (!payload_len) |
1541 | 1 | return; |
1542 | | |
1543 | 602 | if (afc == 2) { |
1544 | 18 | col_set_str(pinfo->cinfo, COL_INFO, "Adaptation field only"); |
1545 | | /* The rest of the packet is stuffing bytes */ |
1546 | 18 | proto_tree_add_item( mp2t_tree, hf_mp2t_stuff_bytes, tvb, offset, payload_len, ENC_NA); |
1547 | 18 | offset += payload_len; |
1548 | 18 | } |
1549 | | |
1550 | 602 | if (!tsc) { |
1551 | 524 | mp2t_process_fragmented_payload(tvb, offset, payload_len, pinfo, tree, mp2t_tree, pusi_flag, pid_analysis); |
1552 | 524 | } else { |
1553 | | /* Payload is scrambled */ |
1554 | 78 | col_set_str(pinfo->cinfo, COL_INFO, "Scrambled TS payload"); |
1555 | 78 | } |
1556 | 602 | } |
1557 | | |
1558 | | static void |
1559 | | export_pdu(tvbuff_t *tvb, packet_info *pinfo) |
1560 | 26.8k | { |
1561 | 26.8k | if (have_tap_listener(exported_pdu_tap)) { |
1562 | 0 | exp_pdu_data_t *exp_pdu_data = wmem_new0(pinfo->pool, exp_pdu_data_t); |
1563 | |
|
1564 | 0 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
1565 | 0 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
1566 | 0 | exp_pdu_data->pdu_tvb = tvb; |
1567 | 0 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
1568 | 0 | } |
1569 | 26.8k | } |
1570 | | |
1571 | | static int |
1572 | | dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ ) |
1573 | 26.8k | { |
1574 | 26.8k | volatile unsigned offset = 0; |
1575 | 26.8k | conversation_t *conv; |
1576 | 26.8k | mp2t_stream_key *stream; |
1577 | 26.8k | mp2t_analysis_data_t *mp2t_data; |
1578 | 26.8k | const char *saved_proto; |
1579 | | |
1580 | 26.8k | conv = find_or_create_conversation(pinfo); |
1581 | 26.8k | stream = wmem_new(pinfo->pool, mp2t_stream_key); |
1582 | 26.8k | stream->conv = conv; |
1583 | | /* Conversations on UDP, etc. are bidirectional, but in the odd case |
1584 | | * that we have two MP2T streams in the opposite directions, we have to |
1585 | | * separately track their Continuity Counters, manage their fragmentation |
1586 | | * status information, etc. |
1587 | | */ |
1588 | 26.8k | if (addresses_equal(&pinfo->src, conversation_key_addr1(conv->key_ptr))) { |
1589 | 26.8k | stream->dir = P2P_DIR_SENT; |
1590 | 26.8k | } else if (addresses_equal(&pinfo->dst, conversation_key_addr1(conv->key_ptr))) { |
1591 | 0 | stream->dir = P2P_DIR_RECV; |
1592 | 0 | } else { |
1593 | | /* DVB Base Band Frames, or some other endpoint that doesn't set the |
1594 | | * address, presumably unidirectional. |
1595 | | */ |
1596 | 0 | stream->dir = P2P_DIR_SENT; |
1597 | 0 | } |
1598 | | |
1599 | 26.8k | p_add_proto_data(pinfo->pool, pinfo, proto_mp2t, MP2T_PROTO_DATA_STREAM, stream); |
1600 | | |
1601 | 53.6k | for (; tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE; offset += MP2T_PACKET_SIZE) { |
1602 | | /* |
1603 | | * Dissect the TSP. |
1604 | | * |
1605 | | * If it gets an error that means there's no point in |
1606 | | * dissecting any more TSPs, rethrow the exception in |
1607 | | * question. |
1608 | | * |
1609 | | * If it gets any other error, report it and continue, as that |
1610 | | * means that TSP got an error, but that doesn't mean we should |
1611 | | * stop dissecting TSPs within this frame or chunk of reassembled |
1612 | | * data. |
1613 | | */ |
1614 | 26.8k | saved_proto = pinfo->current_proto; |
1615 | 26.8k | export_pdu(tvb_new_subset_length(tvb, offset, MP2T_PACKET_SIZE), pinfo); |
1616 | 26.8k | TRY { |
1617 | 26.8k | mp2t_data = get_mp2t_conversation_data(stream); |
1618 | 26.8k | dissect_tsp(tvb, offset, pinfo, tree, mp2t_data); |
1619 | 26.8k | } |
1620 | 26.8k | CATCH_NONFATAL_ERRORS { |
1621 | 123 | show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
1622 | | |
1623 | | /* |
1624 | | * Restore the saved protocol as well; we do this after |
1625 | | * show_exception(), so that the "Malformed packet" indication |
1626 | | * shows the protocol for which dissection failed. |
1627 | | */ |
1628 | 123 | pinfo->current_proto = saved_proto; |
1629 | 123 | } |
1630 | 26.8k | ENDTRY; |
1631 | 26.8k | } |
1632 | 26.8k | return tvb_captured_length(tvb); |
1633 | 26.8k | } |
1634 | | |
1635 | | static bool |
1636 | | heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ ) |
1637 | 920 | { |
1638 | 920 | int length; |
1639 | 920 | unsigned offset = 0; |
1640 | | |
1641 | 920 | length = tvb_reported_length_remaining(tvb, offset); |
1642 | 920 | if (length == 0) { |
1643 | | /* Nothing to check for */ |
1644 | 0 | return false; |
1645 | 0 | } |
1646 | 920 | if ((length % MP2T_PACKET_SIZE) != 0) { |
1647 | | /* Not a multiple of the MPEG-2 transport packet size */ |
1648 | 914 | return false; |
1649 | 914 | } else { |
1650 | 10 | while (tvb_offset_exists(tvb, offset)) { |
1651 | 7 | if (tvb_get_uint8(tvb, offset) != MP2T_SYNC_BYTE) { |
1652 | | /* No sync byte at the appropriate offset */ |
1653 | 3 | return false; |
1654 | 3 | } |
1655 | 4 | offset += MP2T_PACKET_SIZE; |
1656 | 4 | } |
1657 | 6 | } |
1658 | | |
1659 | 3 | dissect_mp2t(tvb, pinfo, tree, data); |
1660 | 3 | return true; |
1661 | 920 | } |
1662 | | |
1663 | | |
1664 | | void |
1665 | | proto_register_mp2t(void) |
1666 | 15 | { |
1667 | 15 | static hf_register_info hf[] = { |
1668 | 15 | { &hf_mp2t_stream, { |
1669 | 15 | "Stream index", "mp2t.stream", |
1670 | 15 | FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL |
1671 | 15 | } } , |
1672 | 15 | { &hf_mp2t_header, { |
1673 | 15 | "Header", "mp2t.header", |
1674 | 15 | FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL |
1675 | 15 | } } , |
1676 | 15 | { &hf_mp2t_sync_byte, { |
1677 | 15 | "Sync Byte", "mp2t.sync_byte", |
1678 | 15 | FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL |
1679 | 15 | } } , |
1680 | 15 | { &hf_mp2t_tei, { |
1681 | 15 | "Transport Error Indicator", "mp2t.tei", |
1682 | 15 | FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL |
1683 | 15 | } } , |
1684 | 15 | { &hf_mp2t_pusi, { |
1685 | 15 | "Payload Unit Start Indicator", "mp2t.pusi", |
1686 | 15 | FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL |
1687 | 15 | } } , |
1688 | 15 | { &hf_mp2t_tp, { |
1689 | 15 | "Transport Priority", "mp2t.tp", |
1690 | 15 | FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL |
1691 | 15 | } } , |
1692 | 15 | { &hf_mp2t_pid, { |
1693 | 15 | "PID", "mp2t.pid", |
1694 | 15 | FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL |
1695 | 15 | } } , |
1696 | 15 | { &hf_mp2t_tsc, { |
1697 | 15 | "Transport Scrambling Control", "mp2t.tsc", |
1698 | 15 | FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL |
1699 | 15 | } } , |
1700 | 15 | { &hf_mp2t_afc, { |
1701 | 15 | "Adaptation Field Control", "mp2t.afc", |
1702 | 15 | FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL |
1703 | 15 | } } , |
1704 | 15 | { &hf_mp2t_cc, { |
1705 | 15 | "Continuity Counter", "mp2t.cc", |
1706 | 15 | FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL |
1707 | 15 | } } , |
1708 | | #if 0 |
1709 | | { &hf_mp2t_analysis_flags, { |
1710 | | "MPEG2-TS Analysis Flags", "mp2t.analysis.flags", |
1711 | | FT_NONE, BASE_NONE, NULL, 0x0, |
1712 | | "This frame has some of the MPEG2 analysis flags set", HFILL |
1713 | | } } , |
1714 | | #endif |
1715 | 15 | { &hf_mp2t_analysis_skips, { |
1716 | 15 | "TS Continuity Counter Skips", "mp2t.analysis.skips", |
1717 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1718 | 15 | "Missing TS frames according to CC counter values", HFILL |
1719 | 15 | } } , |
1720 | 15 | { &hf_mp2t_analysis_drops, { |
1721 | 15 | "Some frames dropped", "mp2t.analysis.drops", |
1722 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1723 | 15 | "Discontinuity: A number of TS frames were dropped", HFILL |
1724 | 15 | } } , |
1725 | 15 | { &hf_mp2t_af, { |
1726 | 15 | "Adaptation Field", "mp2t.af", |
1727 | 15 | FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL |
1728 | 15 | } } , |
1729 | 15 | { &hf_mp2t_af_length, { |
1730 | 15 | "Adaptation Field Length", "mp2t.af.length", |
1731 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL |
1732 | 15 | } } , |
1733 | 15 | { &hf_mp2t_af_di, { |
1734 | 15 | "Discontinuity Indicator", "mp2t.af.di", |
1735 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL |
1736 | 15 | } } , |
1737 | 15 | { &hf_mp2t_af_rai, { |
1738 | 15 | "Random Access Indicator", "mp2t.af.rai", |
1739 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL |
1740 | 15 | } } , |
1741 | 15 | { &hf_mp2t_af_espi, { |
1742 | 15 | "Elementary Stream Priority Indicator", "mp2t.af.espi", |
1743 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL |
1744 | 15 | } } , |
1745 | 15 | { &hf_mp2t_af_pcr_flag, { |
1746 | 15 | "PCR Flag", "mp2t.af.pcr_flag", |
1747 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL |
1748 | 15 | } } , |
1749 | 15 | { &hf_mp2t_af_opcr_flag, { |
1750 | 15 | "OPCR Flag", "mp2t.af.opcr_flag", |
1751 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL |
1752 | 15 | } } , |
1753 | 15 | { &hf_mp2t_af_sp_flag, { |
1754 | 15 | "Splicing Point Flag", "mp2t.af.sp_flag", |
1755 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL |
1756 | 15 | } } , |
1757 | 15 | { &hf_mp2t_af_tpd_flag, { |
1758 | 15 | "Transport Private Data Flag", "mp2t.af.tpd_flag", |
1759 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL |
1760 | 15 | } } , |
1761 | 15 | { &hf_mp2t_af_afe_flag, { |
1762 | 15 | "Adaptation Field Extension Flag", "mp2t.af.afe_flag", |
1763 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL |
1764 | 15 | } } , |
1765 | 15 | { &hf_mp2t_af_pcr, { |
1766 | 15 | "Program Clock Reference", "mp2t.af.pcr", |
1767 | 15 | FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL |
1768 | 15 | } } , |
1769 | 15 | { &hf_mp2t_af_opcr, { |
1770 | 15 | "Original Program Clock Reference", "mp2t.af.opcr", |
1771 | 15 | FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL |
1772 | 15 | } } , |
1773 | 15 | { &hf_mp2t_af_sc, { |
1774 | 15 | "Splice Countdown", "mp2t.af.sc", |
1775 | 15 | FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL |
1776 | 15 | } } , |
1777 | 15 | { &hf_mp2t_af_tpd_length, { |
1778 | 15 | "Transport Private Data Length", "mp2t.af.tpd_length", |
1779 | 15 | FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL |
1780 | 15 | } } , |
1781 | 15 | { &hf_mp2t_af_tpd, { |
1782 | 15 | "Transport Private Data", "mp2t.af.tpd", |
1783 | 15 | FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL |
1784 | 15 | } } , |
1785 | 15 | { &hf_mp2t_af_e_length, { |
1786 | 15 | "Adaptation Field Extension Length", "mp2t.af.e_length", |
1787 | 15 | FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL |
1788 | 15 | } } , |
1789 | 15 | { &hf_mp2t_af_e_ltw_flag, { |
1790 | 15 | "LTW Flag", "mp2t.af.e.ltw_flag", |
1791 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL |
1792 | 15 | } } , |
1793 | 15 | { &hf_mp2t_af_e_pr_flag, { |
1794 | 15 | "Piecewise Rate Flag", "mp2t.af.e.pr_flag", |
1795 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL |
1796 | 15 | } } , |
1797 | 15 | { &hf_mp2t_af_e_ss_flag, { |
1798 | 15 | "Seamless Splice Flag", "mp2t.af.e.ss_flag", |
1799 | 15 | FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL |
1800 | 15 | } } , |
1801 | 15 | { &hf_mp2t_af_e_reserved, { |
1802 | 15 | "Reserved", "mp2t.af.e.reserved", |
1803 | 15 | FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL |
1804 | 15 | } } , |
1805 | 15 | { &hf_mp2t_af_e_reserved_bytes, { |
1806 | 15 | "Reserved", "mp2t.af.e.reserved_bytes", |
1807 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL |
1808 | 15 | } } , |
1809 | 15 | { &hf_mp2t_af_stuffing_bytes, { |
1810 | 15 | "Stuffing", "mp2t.af.stuffing_bytes", |
1811 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL |
1812 | 15 | } } , |
1813 | 15 | { &hf_mp2t_af_e_ltwv_flag, { |
1814 | 15 | "LTW Valid Flag", "mp2t.af.e.ltwv_flag", |
1815 | 15 | FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL |
1816 | 15 | } } , |
1817 | 15 | { &hf_mp2t_af_e_ltwo, { |
1818 | 15 | "LTW Offset", "mp2t.af.e.ltwo", |
1819 | 15 | FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL |
1820 | 15 | } } , |
1821 | 15 | { &hf_mp2t_af_e_pr_reserved, { |
1822 | 15 | "Reserved", "mp2t.af.e.pr_reserved", |
1823 | 15 | FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL |
1824 | 15 | } } , |
1825 | 15 | { &hf_mp2t_af_e_pr, { |
1826 | 15 | "Piecewise Rate", "mp2t.af.e.pr", |
1827 | 15 | FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL |
1828 | 15 | } } , |
1829 | 15 | { &hf_mp2t_af_e_st, { |
1830 | 15 | "Splice Type", "mp2t.af.e.st", |
1831 | 15 | FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL |
1832 | 15 | } } , |
1833 | 15 | { &hf_mp2t_af_e_dnau_32_30, { |
1834 | 15 | "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30", |
1835 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL |
1836 | 15 | } } , |
1837 | 15 | { &hf_mp2t_af_e_m_1, { |
1838 | 15 | "Marker Bit", "mp2t.af.e.m_1", |
1839 | 15 | FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL |
1840 | 15 | } } , |
1841 | 15 | { &hf_mp2t_af_e_dnau_29_15, { |
1842 | 15 | "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15", |
1843 | 15 | FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL |
1844 | 15 | } } , |
1845 | 15 | { &hf_mp2t_af_e_m_2, { |
1846 | 15 | "Marker Bit", "mp2t.af.e.m_2", |
1847 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL |
1848 | 15 | } } , |
1849 | 15 | { &hf_mp2t_af_e_dnau_14_0, { |
1850 | 15 | "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0", |
1851 | 15 | FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL |
1852 | 15 | } } , |
1853 | 15 | { &hf_mp2t_af_e_m_3, { |
1854 | 15 | "Marker Bit", "mp2t.af.e.m_3", |
1855 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL |
1856 | 15 | } } , |
1857 | | #if 0 |
1858 | | { &hf_mp2t_payload, { |
1859 | | "Payload", "mp2t.payload", |
1860 | | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL |
1861 | | } } , |
1862 | | #endif |
1863 | 15 | { &hf_mp2t_stuff_bytes, { |
1864 | 15 | "Stuffing", "mp2t.stuff_bytes", |
1865 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL |
1866 | 15 | } }, |
1867 | 15 | { &hf_mp2t_pointer, { |
1868 | 15 | "Pointer", "mp2t.pointer", |
1869 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL |
1870 | 15 | } }, |
1871 | 15 | { &hf_msg_fragments, { |
1872 | 15 | "Message fragments", "mp2t.msg.fragments", |
1873 | 15 | FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL |
1874 | 15 | } }, |
1875 | 15 | { &hf_msg_fragment, { |
1876 | 15 | "Message fragment", "mp2t.msg.fragment", |
1877 | 15 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL |
1878 | 15 | } }, |
1879 | 15 | { &hf_msg_fragment_overlap, { |
1880 | 15 | "Message fragment overlap", "mp2t.msg.fragment.overlap", |
1881 | 15 | FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL |
1882 | 15 | } }, |
1883 | 15 | { &hf_msg_fragment_overlap_conflicts, { |
1884 | 15 | "Message fragment overlapping with conflicting data", |
1885 | 15 | "mp2t.msg.fragment.overlap.conflicts", |
1886 | 15 | FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL |
1887 | 15 | } }, |
1888 | 15 | { &hf_msg_fragment_multiple_tails, { |
1889 | 15 | "Message has multiple tail fragments", |
1890 | 15 | "mp2t.msg.fragment.multiple_tails", |
1891 | 15 | FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL |
1892 | 15 | } }, |
1893 | 15 | { &hf_msg_fragment_too_long_fragment, { |
1894 | 15 | "Message fragment too long", "mp2t.msg.fragment.too_long_fragment", |
1895 | 15 | FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL |
1896 | 15 | } }, |
1897 | 15 | { &hf_msg_fragment_error, { |
1898 | 15 | "Message defragmentation error", "mp2t.msg.fragment.error", |
1899 | 15 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL |
1900 | 15 | } }, |
1901 | 15 | { &hf_msg_fragment_count, { |
1902 | 15 | "Message fragment count", "mp2t.msg.fragment.count", |
1903 | 15 | FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL |
1904 | 15 | } }, |
1905 | 15 | { &hf_msg_reassembled_in, { |
1906 | 15 | "Reassembled in", "mp2t.msg.reassembled.in", |
1907 | 15 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL |
1908 | 15 | } }, |
1909 | 15 | { &hf_msg_reassembled_length, { |
1910 | 15 | "Reassembled MP2T length", "mp2t.msg.reassembled.length", |
1911 | 15 | FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL |
1912 | 15 | } }, |
1913 | 15 | { &hf_msg_ts_packet_reassembled, { |
1914 | 15 | "MPEG TS Packet (reassembled)", "mp2t.ts_packet_reassembled", |
1915 | 15 | FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL |
1916 | 15 | } }, |
1917 | 15 | }; |
1918 | | |
1919 | 15 | static int *ett[] = |
1920 | 15 | { |
1921 | 15 | &ett_mp2t, |
1922 | 15 | &ett_mp2t_header, |
1923 | 15 | &ett_mp2t_af, |
1924 | 15 | &ett_mp2t_analysis, |
1925 | 15 | &ett_stuff, |
1926 | 15 | &ett_msg_fragment, |
1927 | 15 | &ett_msg_fragments |
1928 | 15 | }; |
1929 | | |
1930 | 15 | static ei_register_info ei[] = { |
1931 | 15 | { &ei_mp2t_pointer, { "mp2t.pointer_too_large", PI_MALFORMED, PI_ERROR, "Pointer value is too large", EXPFILL }}, |
1932 | 15 | { &ei_mp2t_cc_drop, { "mp2t.cc.drop", PI_SEQUENCE, PI_ERROR, "Detected missing TS frames", EXPFILL }}, |
1933 | 15 | { &ei_mp2t_invalid_afc, { "mp2t.afc.invalid", PI_PROTOCOL, PI_WARN, |
1934 | 15 | "Adaptation Field Control contains an invalid value", EXPFILL }} |
1935 | 15 | }; |
1936 | | |
1937 | 15 | expert_module_t* expert_mp2t; |
1938 | | |
1939 | 15 | proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t"); |
1940 | | |
1941 | 15 | mp2t_handle = register_dissector("mp2t", dissect_mp2t, proto_mp2t); |
1942 | | |
1943 | 15 | proto_register_field_array(proto_mp2t, hf, array_length(hf)); |
1944 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
1945 | 15 | expert_mp2t = expert_register_protocol(proto_mp2t); |
1946 | 15 | expert_register_field_array(expert_mp2t, ei, array_length(ei)); |
1947 | | |
1948 | 15 | heur_subdissector_list = register_heur_dissector_list_with_description("mp2t.pid", "Unused", proto_mp2t); |
1949 | | /* Register init of processing of fragmented DEPI packets */ |
1950 | 15 | reassembly_table_register(&mp2t_reassembly_table, |
1951 | 15 | &mp2t_reassembly_table_functions); |
1952 | | |
1953 | 15 | mp2t_stream_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), mp2t_stream_hash, mp2t_stream_equal); |
1954 | | |
1955 | 15 | register_init_routine(mp2t_init); |
1956 | | |
1957 | 15 | exported_pdu_tap = register_export_pdu_tap_with_encap("MP2T", WTAP_ENCAP_MPEG_2_TS); |
1958 | 15 | mp2t_follow_tap = register_tap("mp2t_follow"); |
1959 | | |
1960 | | /* MPEG2 TS is sometimes carried on UDP or RTP over UDP so using the UDP |
1961 | | * address filter is better than nothing for tshark. */ |
1962 | 15 | register_follow_stream(proto_mp2t, "mp2t_follow", mp2t_follow_conv_filter, mp2t_follow_index_filter, udp_follow_address_filter, udp_port_to_display, follow_tvb_tap_listener, mp2t_get_stream_count, mp2t_get_sub_stream_id); |
1963 | 15 | } |
1964 | | |
1965 | | |
1966 | | |
1967 | | void |
1968 | | proto_reg_handoff_mp2t(void) |
1969 | 15 | { |
1970 | 15 | heur_dissector_add("udp", heur_dissect_mp2t, "MP2T over UDP", "mp2t_udp", proto_mp2t, HEURISTIC_ENABLE); |
1971 | | |
1972 | 15 | dissector_add_uint("rtp.pt", PT_MP2T, mp2t_handle); |
1973 | 15 | dissector_add_for_decode_as_with_preference("tcp.port", mp2t_handle); |
1974 | 15 | dissector_add_for_decode_as_with_preference("udp.port", mp2t_handle); |
1975 | 15 | heur_dissector_add("usb.bulk", heur_dissect_mp2t, "MP2T USB bulk endpoint", "mp2t_usb_bulk", proto_mp2t, HEURISTIC_ENABLE); |
1976 | 15 | dissector_add_uint("wtap_encap", WTAP_ENCAP_MPEG_2_TS, mp2t_handle); |
1977 | 15 | dissector_add_uint("l2tp.pw_type", L2TPv3_PW_DOCSIS_DMPT, mp2t_handle); |
1978 | 15 | dissector_add_string("media_type", "video/mp2t", mp2t_handle); |
1979 | | |
1980 | 15 | docsis_handle = find_dissector("docsis"); |
1981 | 15 | mpeg_pes_handle = find_dissector("mpeg-pes"); |
1982 | 15 | mpeg_sect_handle = find_dissector("mpeg_sect"); |
1983 | 15 | } |
1984 | | |
1985 | | /* |
1986 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1987 | | * |
1988 | | * Local variables: |
1989 | | * c-basic-offset: 4 |
1990 | | * tab-width: 8 |
1991 | | * indent-tabs-mode: nil |
1992 | | * End: |
1993 | | * |
1994 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
1995 | | * :indentSize=4:tabSize=8:noTabs=true: |
1996 | | */ |