2 * Routines for ALP dissection
3 * Copyright 2020, Nick Kelsey <nickk@silicondust.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * ATSC Link-Layer Protocol (A/330)
14 * https://www.atsc.org/atsc-30-standard/a3302016-link-layer-protocol/
18 #include <epan/packet.h>
19 #include <epan/to_str.h>
20 #include <epan/unit_strings.h>
21 #include <wsutil/array.h>
22 #include <wiretap/wtap.h>
24 void proto_reg_handoff_alp(void);
25 void proto_register_alp(void);
29 static int ett_alp_si
;
30 static int ett_alp_he
;
31 static int ett_alp_sig_info
;
32 static int ett_alp_lmt
;
33 static int ett_alp_lmt_plp
;
34 static int ett_alp_lmt_plp_mc
;
36 static dissector_handle_t alp_handle
;
37 static dissector_handle_t ip_handle
;
38 static dissector_handle_t ts_handle
;
40 static int hf_alp_packet_type
;
41 #define ALP_PACKET_TYPE_MASK 0xE0
42 #define ALP_PACKET_TYPE_IPV4 0
43 #define ALP_PACKET_TYPE_SIGNALLING 4
44 #define ALP_PACKET_TYPE_MPEG_TS 7
45 static const value_string alp_packet_type_vals
[] = {
48 { 2, "Compressed IPv4 packet" },
50 { 4, "Link layer signalling packet" },
52 { 6, "Packet type extension" },
53 { 7, "MPEG-2 transport stream" },
57 static int hf_alp_mpegts_numts
;
58 static int hf_alp_mpegts_ahf
;
59 static int hf_alp_mpegts_hdm
;
60 static int hf_alp_mpegts_dnp
;
61 #define ALP_MPEGTS_NUMTS_MASK 0x1E
62 #define ALP_MPEGTS_AHF_MASK 0x01
63 #define ALP_MPEGTS_HDM_MASK 0x80
64 #define ALP_MPEGTS_DNP_MASK 0x7F
66 static int hf_alp_payload_configuration
;
67 static int hf_alp_header_mode
;
68 static int hf_alp_segmentation_concatenation
;
69 #define ALP_PAYLOAD_CONFIGURATION_MASK 0x10
70 #define ALP_HEADER_MODE_MASK 0x08
71 #define ALP_SEGMENTATION_CONCATENATION_MASK 0x08
72 static const value_string alp_segmentation_concatenation_vals
[] = {
73 { 0, "Packet segment" },
74 { 1, "Concatenated packets" },
78 static int hf_alp_length
;
79 #define ALP_LENGTH_MASK 0x07FF
81 static int hf_alp_single_length
;
82 static int hf_alp_single_sif
;
83 static int hf_alp_single_hef
;
84 #define ALP_SINGLE_LENGTH_MASK 0x07FFF8
85 #define ALP_SINGLE_SIF_MASK 0x02
86 #define ALP_SINGLE_HEF_MASK 0x01
88 static int hf_alp_segment_sequence_number
;
89 static int hf_alp_segment_last_indicator
;
90 static int hf_alp_segment_sif
;
91 static int hf_alp_segment_hef
;
92 #define ALP_SEGMENT_SEQUENCE_NUMBER_MASK 0xF8
93 #define ALP_SEGMENT_LAST_INDICATOR_MASK 0x04
94 #define ALP_SEGMENT_SIF_MASK 0x02
95 #define ALP_SEGMENT_HEF_MASK 0x01
97 static int hf_alp_concat_length
;
98 static int hf_alp_concat_count
;
99 static int hf_alp_concat_sif
;
100 #define ALP_CONCAT_LENGTH_MASK 0x07FFF0
101 #define ALP_CONCAT_COUNT_MASK 0x0E
102 #define ALP_CONCAT_SIF_MASK 0x01
104 static int hf_alp_si
;
105 static int hf_alp_sid
;
107 static int hf_alp_header_extension
;
108 static int hf_alp_header_extension_type
;
109 static int hf_alp_header_extension_length
;
111 static int hf_alp_header_extension_sony_l1d_timeinfo
;
112 static int hf_alp_header_extension_sony_l1d_timeinfo_flag
;
113 static int hf_alp_header_extension_sony_l1d_timeinfo_sec
;
114 static int hf_alp_header_extension_sony_l1d_timeinfo_ms
;
115 static int hf_alp_header_extension_sony_l1d_timeinfo_us
;
116 static int hf_alp_header_extension_sony_l1d_timeinfo_ns
;
117 static int hf_alp_header_extension_sony_l1d_timeinfo_time
;
118 static int hf_alp_header_extension_sony_l1d_timeinfo_time_ns
;
119 static int hf_alp_header_extension_sony_plp_id
;
120 static int hf_alp_header_extension_sony_plp_unk
;
121 #define ALP_HE_SONY_L1D_TIME_FLAG_MASK 0xC000000000000000
122 #define ALP_HE_SONY_L1D_TIME_SEC_MASK 0x3FFFFFFFC0000000
123 #define ALP_HE_SONY_L1D_TIME_MS_MASK 0x000000003FF00000
124 #define ALP_HE_SONY_L1D_TIME_US_MASK 0x00000000000FFC00
125 #define ALP_HE_SONY_L1D_TIME_NS_MASK 0x00000000000003FF
126 #define ALP_HE_SONY_PLP_NUM_MASK 0xFC
127 #define ALP_HE_SONY_PLP_UNK_MASK 0x03
129 static int hf_alp_sig_info
;
130 static int hf_alp_sig_info_type
;
131 static int hf_alp_sig_info_type_extension
;
132 static int hf_alp_sig_info_version
;
133 static int hf_alp_sig_info_format
;
134 static int hf_alp_sig_info_encoding
;
135 #define ALP_SIG_INFO_FORMAT_MASK 0xC0
136 #define ALP_SIG_INFO_ENCODING_MASK 0x30
137 #define ALP_SIG_INFO_TYPE_LMT 0x01
138 static const value_string alp_sig_info_type_vals
[] = {
139 { 0x01, "Link Mapping Table" },
140 { 0x02, "ROHC-U Description Table" },
143 static const value_string alp_sig_info_format_vals
[] = {
150 static const value_string alp_sig_info_encoding_vals
[] = {
151 { 0, "No Compression" },
158 static int hf_alp_lmt
;
159 static int hf_alp_lmt_numplp
;
160 static int hf_alp_lmt_reserved
;
161 static int hf_alp_lmt_plp
;
162 static int hf_alp_lmt_plp_id
;
163 static int hf_alp_lmt_plp_reserved
;
164 static int hf_alp_lmt_plp_nummc
;
165 static int hf_alp_lmt_plp_mc
;
166 static int hf_alp_lmt_plp_mc_src_ip
;
167 static int hf_alp_lmt_plp_mc_dst_ip
;
168 static int hf_alp_lmt_plp_mc_src_port
;
169 static int hf_alp_lmt_plp_mc_dst_port
;
170 static int hf_alp_lmt_plp_mc_sid_flag
;
171 static int hf_alp_lmt_plp_mc_comp_flag
;
172 static int hf_alp_lmt_plp_mc_reserved
;
173 static int hf_alp_lmt_plp_mc_sid
;
174 static int hf_alp_lmt_plp_mc_context_id
;
176 #define ALP_LMT_NUMPLP_MASK 0xFC
177 #define ALP_LMT_RESERVED_MASK 0x03
178 #define ALP_LMT_PLP_ID_MASK 0xFC
179 #define ALP_LMT_PLP_RESERVED_MASK 0x03
180 #define ALP_LMT_PLP_MC_SID_MASK 0x80
181 #define ALP_LMT_PLP_MC_COMP_MASK 0x40
182 #define ALP_LMT_PLP_MC_RESERVED_MASK 0x3F
184 static int hf_alp_junk
;
187 dissect_alp_mpegts(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, proto_tree
*alp_tree
)
189 uint8_t header0
= tvb_get_uint8(tvb
, offset
);
190 uint8_t ahf
= header0
& ALP_MPEGTS_AHF_MASK
;
191 uint8_t numts
= (header0
& ALP_MPEGTS_NUMTS_MASK
) >> 1;
196 PROTO_ITEM_SET_GENERATED(
197 proto_tree_add_uint(alp_tree
, hf_alp_mpegts_numts
, tvb
, offset
, 1, numts
)
199 proto_tree_add_item(alp_tree
, hf_alp_mpegts_ahf
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
206 uint8_t header1
= tvb_get_uint8(tvb
, offset
);
207 hdm
= header1
& ALP_MPEGTS_HDM_MASK
;
208 dnp
= header1
& ALP_MPEGTS_DNP_MASK
;
209 if ((hdm
== 0) && (dnp
== 0)) {
213 proto_tree_add_item(alp_tree
, hf_alp_mpegts_hdm
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
214 PROTO_ITEM_SET_GENERATED(
215 proto_tree_add_uint(alp_tree
, hf_alp_mpegts_dnp
, tvb
, offset
, 1, dnp
)
221 unsigned char *ts_frame
= (unsigned char*)wmem_alloc(pinfo
->pool
, 188);
228 memset(ts_frame
+ 5, 0xFF, 183);
230 tvbuff_t
*ts_frame_tvb
= tvb_new_child_real_data(tvb
, ts_frame
, 188, 188);
231 call_dissector(ts_handle
, ts_frame_tvb
, pinfo
, tree
);
234 unsigned char *ts_frame
= (unsigned char*)wmem_alloc(pinfo
->pool
, 188);
237 tvb_memcpy(tvb
, ts_frame
+ 1, offset
, 187);
240 unsigned char header
[4];
241 memcpy(header
, ts_frame
, 4);
243 tvbuff_t
*ts_frame_tvb
= tvb_new_child_real_data(tvb
, ts_frame
, 188, 188);
244 call_dissector(ts_handle
, ts_frame_tvb
, pinfo
, tree
);
247 ts_frame
= (unsigned char*)wmem_alloc(pinfo
->pool
, 188);
250 header
[3] = (header
[3] & 0xF0) | ((header
[3] + 1) & 0x0F);
251 memcpy(ts_frame
, header
, 4);
252 tvb_memcpy(tvb
, ts_frame
+ 4, offset
, 184);
256 tvb_memcpy(tvb
, ts_frame
+ 1, offset
, 187);
260 ts_frame_tvb
= tvb_new_child_real_data(tvb
, ts_frame
, 188, 188);
261 call_dissector(ts_handle
, ts_frame_tvb
, pinfo
, tree
);
264 if (offset
< (int)tvb_captured_length(tvb
)) {
265 int junk_length
= tvb_captured_length(tvb
) - offset
;
266 proto_tree_add_bytes_format(alp_tree
, hf_alp_junk
, tvb
, offset
, -1, NULL
, "Junk at end (%u byte%s)", junk_length
, (junk_length
== 1) ? "" : "s");
269 return tvb_captured_length(tvb
);
273 dissect_alp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
275 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ALP");
276 col_clear(pinfo
->cinfo
, COL_INFO
);
278 proto_item
*ti
= proto_tree_add_item(tree
, proto_alp
, tvb
, 0, -1, ENC_NA
);
279 proto_tree
*alp_tree
= proto_item_add_subtree(ti
, ett_alp
);
282 uint8_t packet_type
= tvb_get_uint8(tvb
, offset
) >> 5;
283 proto_tree_add_item(alp_tree
, hf_alp_packet_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
285 if (packet_type
== ALP_PACKET_TYPE_MPEG_TS
) {
286 return dissect_alp_mpegts(tvb
, offset
, pinfo
, tree
, alp_tree
);
289 bool payload_configuration
= (tvb_get_uint8(tvb
, offset
) & ALP_PAYLOAD_CONFIGURATION_MASK
) != 0;
290 proto_tree_add_item(alp_tree
, hf_alp_payload_configuration
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
294 uint16_t payload_length
= 0;
296 if (payload_configuration
== 0) {
297 bool header_mode
= (tvb_get_uint8(tvb
, offset
) & ALP_HEADER_MODE_MASK
) != 0;
298 proto_tree_add_item(alp_tree
, hf_alp_header_mode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
300 if (header_mode
== 0) {
301 payload_length
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
) & ALP_LENGTH_MASK
;
302 proto_tree_add_item(alp_tree
, hf_alp_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
305 payload_length
= (tvb_get_uint24(tvb
, offset
, ENC_BIG_ENDIAN
) & ALP_SINGLE_LENGTH_MASK
) >> 3;
306 proto_tree_add_item(alp_tree
, hf_alp_single_length
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
309 sif
= (tvb_get_uint8(tvb
, offset
) & ALP_SINGLE_SIF_MASK
) != 0;
310 hef
= (tvb_get_uint8(tvb
, offset
) & ALP_SINGLE_HEF_MASK
) != 0;
311 proto_tree_add_item(alp_tree
, hf_alp_single_sif
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
312 proto_tree_add_item(alp_tree
, hf_alp_single_hef
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
316 bool segmentation_concatenation
= (tvb_get_uint8(tvb
, offset
) & ALP_SEGMENTATION_CONCATENATION_MASK
) != 0;
317 proto_tree_add_item(alp_tree
, hf_alp_segmentation_concatenation
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
319 if (segmentation_concatenation
== 0) {
320 payload_length
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
) & ALP_LENGTH_MASK
;
321 proto_tree_add_item(alp_tree
, hf_alp_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
324 sif
= (tvb_get_uint8(tvb
, offset
) & ALP_SEGMENT_SIF_MASK
) != 0;
325 hef
= (tvb_get_uint8(tvb
, offset
) & ALP_SEGMENT_HEF_MASK
) != 0;
326 proto_tree_add_item(alp_tree
, hf_alp_segment_sequence_number
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
327 proto_tree_add_item(alp_tree
, hf_alp_segment_last_indicator
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
328 proto_tree_add_item(alp_tree
, hf_alp_segment_sif
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
329 proto_tree_add_item(alp_tree
, hf_alp_segment_hef
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
332 payload_length
= (tvb_get_uint24(tvb
, offset
, ENC_BIG_ENDIAN
) & ALP_CONCAT_LENGTH_MASK
) >> 4;
333 proto_tree_add_item(alp_tree
, hf_alp_concat_length
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
336 uint8_t count
= (tvb_get_uint8(tvb
, offset
) & ALP_CONCAT_COUNT_MASK
) >> 1;
337 sif
= (tvb_get_uint8(tvb
, offset
) & ALP_CONCAT_SIF_MASK
) != 0;
338 proto_tree_add_item(alp_tree
, hf_alp_concat_count
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
339 proto_tree_add_item(alp_tree
, hf_alp_concat_sif
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
342 uint32_t skip
= (uint32_t)count
* 12;
351 proto_item
*si_item
= proto_tree_add_item(alp_tree
, hf_alp_si
, tvb
, offset
, 1, ENC_NA
);
352 proto_tree
*si_tree
= proto_item_add_subtree(si_item
, ett_alp_si
);
354 proto_tree_add_item(si_tree
, hf_alp_sid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
359 uint8_t he_length_m1
= tvb_get_uint8(tvb
, offset
+ 1);
360 uint16_t he_length
= (uint16_t)he_length_m1
+ 1;
361 proto_item
*he_item
= proto_tree_add_item(alp_tree
, hf_alp_header_extension
, tvb
, offset
, 2 + he_length
, ENC_NA
);
362 proto_tree
*he_tree
= proto_item_add_subtree(he_item
, ett_alp_he
);
364 uint8_t he_type
= tvb_get_uint8(tvb
, offset
);
366 proto_tree_add_item(he_tree
, hf_alp_header_extension_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
369 PROTO_ITEM_SET_GENERATED(
370 proto_tree_add_uint(he_tree
, hf_alp_header_extension_length
, tvb
, offset
, 1, he_length
)
374 if (he_type
== 0xF0 && he_length
== 8) {
375 /* Sony L1D Time Info Extension */
376 uint64_t sony_time
= tvb_get_uint64(tvb
, offset
, ENC_BIG_ENDIAN
);
377 uint64_t sony_sec
= (sony_time
& ALP_HE_SONY_L1D_TIME_SEC_MASK
) >> 30;
378 uint64_t sony_ms
= (sony_time
& ALP_HE_SONY_L1D_TIME_MS_MASK
) >> 20;
379 uint64_t sony_us
= (sony_time
& ALP_HE_SONY_L1D_TIME_US_MASK
) >> 10;
380 uint64_t sony_ns
= sony_time
& ALP_HE_SONY_L1D_TIME_NS_MASK
;
381 uint64_t ns_part
= sony_ns
+ sony_us
* 1000 + sony_ms
* 1000000;
382 uint64_t ns_full
= ns_part
+ sony_sec
* 1000000000;
383 nstime_t abs_time
= {
384 .secs
= (time_t) sony_sec
,
385 .nsecs
= (int) ns_part
387 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Sony L1D TAI Time: %s (%" PRIu64
")",
388 abs_time_to_str(pinfo
->pool
, &abs_time
, ABSOLUTE_TIME_UTC
, false), ns_full
);
390 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
391 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_flag
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
392 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_sec
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
393 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_ms
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
394 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_us
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
395 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_ns
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
396 PROTO_ITEM_SET_GENERATED(
397 proto_tree_add_time(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_time
, tvb
, offset
, 8, &abs_time
)
399 PROTO_ITEM_SET_GENERATED(
400 proto_tree_add_uint64(he_tree
, hf_alp_header_extension_sony_l1d_timeinfo_time_ns
, tvb
, offset
, 8, ns_full
)
403 } else if (he_type
== 0xF1 && he_length
== 1) {
404 /* Sony PLP Extension */
405 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Sony PLP Extension: PLP %u", (tvb_get_uint8(tvb
, offset
) & ALP_HE_SONY_PLP_NUM_MASK
) >> 2);
406 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_plp_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
407 proto_tree_add_item(he_tree
, hf_alp_header_extension_sony_plp_unk
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
410 tvbuff_t
*he_data_tvb
= tvb_new_subset_length(tvb
, offset
, he_length
);
411 call_data_dissector(he_data_tvb
, pinfo
, he_tree
);
416 if (packet_type
== ALP_PACKET_TYPE_SIGNALLING
) {
417 proto_item
*sig_info_item
= proto_tree_add_item(alp_tree
, hf_alp_sig_info
, tvb
, offset
, 5, ENC_NA
);
418 proto_tree
*sig_info_tree
= proto_item_add_subtree(sig_info_item
, ett_alp_sig_info
);
420 uint8_t sig_info_type
= tvb_get_uint8(tvb
, offset
);
421 proto_tree_add_item(sig_info_tree
, hf_alp_sig_info_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
424 proto_tree_add_item(sig_info_tree
, hf_alp_sig_info_type_extension
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
427 proto_tree_add_item(sig_info_tree
, hf_alp_sig_info_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
430 proto_tree_add_item(sig_info_tree
, hf_alp_sig_info_format
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
431 proto_tree_add_item(sig_info_tree
, hf_alp_sig_info_encoding
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
434 if (sig_info_type
== ALP_SIG_INFO_TYPE_LMT
) {
435 proto_item
*lmt_item
= proto_tree_add_item(alp_tree
, hf_alp_lmt
, tvb
, offset
, payload_length
, ENC_NA
);
436 proto_tree
*lmt_tree
= proto_item_add_subtree(lmt_item
, ett_alp_lmt
);
438 uint8_t lmt_numplp
= ((tvb_get_uint8(tvb
, offset
) & ALP_LMT_NUMPLP_MASK
) >> 2) + 1;
439 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Link Mapping Table, number of PLPs: %u", lmt_numplp
);
440 PROTO_ITEM_SET_GENERATED(
441 proto_tree_add_uint(lmt_tree
, hf_alp_lmt_numplp
, tvb
, offset
, 1, lmt_numplp
)
443 proto_tree_add_item(lmt_tree
, hf_alp_lmt_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
446 for(uint8_t i
= 0; i
< lmt_numplp
; i
++) {
447 /* Fist pass. Calculate PLP entry length */
448 int lmt_plp_length
= 2;
449 uint8_t lmt_mc_nummc
= tvb_get_uint8(tvb
, offset
+ 1);
451 for(uint8_t j
= 0; j
< lmt_mc_nummc
; j
++) {
452 uint8_t lmt_mc_plp_flags
= tvb_get_uint8(tvb
, offset
+ 2 + plp_mc_len
+ 12);
454 uint8_t lmt_mc_plp_sid_flag
= lmt_mc_plp_flags
& ALP_LMT_PLP_MC_SID_MASK
;
455 uint8_t lmt_mc_plp_comp_flag
= lmt_mc_plp_flags
& ALP_LMT_PLP_MC_COMP_MASK
;
456 if (lmt_mc_plp_sid_flag
) {
459 if (lmt_mc_plp_comp_flag
) {
463 lmt_plp_length
+= plp_mc_len
;
465 /* Second pass. Add PLP to the tree */
466 proto_item
*lmt_plp_item
= proto_tree_add_item(lmt_tree
, hf_alp_lmt_plp
, tvb
, offset
, lmt_plp_length
, ENC_NA
);
467 proto_tree
*lmt_plp_tree
= proto_item_add_subtree(lmt_plp_item
, ett_alp_lmt_plp
);
469 uint8_t lmt_plp_id
= (tvb_get_uint8(tvb
, offset
) & ALP_LMT_PLP_ID_MASK
) >> 2;
470 proto_item_append_text(lmt_plp_item
, " ID=%u", lmt_plp_id
);
472 proto_tree_add_item(lmt_plp_tree
, hf_alp_lmt_plp_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
473 proto_tree_add_item(lmt_plp_tree
, hf_alp_lmt_plp_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
476 proto_tree_add_item(lmt_plp_tree
, hf_alp_lmt_plp_nummc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
479 for(uint8_t j
= 0; j
< lmt_mc_nummc
; j
++) {
481 uint8_t lmt_mc_plp_flags
= tvb_get_uint8(tvb
, offset
+ 12);
482 uint8_t lmt_mc_plp_sid_flag
= lmt_mc_plp_flags
& ALP_LMT_PLP_MC_SID_MASK
;
483 uint8_t lmt_mc_plp_comp_flag
= lmt_mc_plp_flags
& ALP_LMT_PLP_MC_COMP_MASK
;
484 if (lmt_mc_plp_sid_flag
) {
487 if (lmt_mc_plp_comp_flag
) {
491 proto_item
*lmt_plp_mc_item
= proto_tree_add_item(lmt_plp_tree
, hf_alp_lmt_plp_mc
, tvb
, offset
, mc_len
, ENC_NA
);
492 proto_item_append_text(lmt_plp_mc_item
, " (%u) Dst=%s:%u", j
, tvb_ip_to_str(pinfo
->pool
, tvb
, offset
+ 4), tvb_get_uint16(tvb
, offset
+ 10, ENC_BIG_ENDIAN
));
493 proto_tree
*lmt_plp_mc_tree
= proto_item_add_subtree(lmt_plp_mc_item
, ett_alp_lmt_plp_mc
);
495 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_src_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
498 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_dst_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
501 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_src_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
504 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_dst_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
507 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_sid_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
508 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_comp_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
509 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
512 if (lmt_mc_plp_sid_flag
) {
513 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_sid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
516 if (lmt_mc_plp_comp_flag
) {
517 proto_tree_add_item(lmt_plp_mc_tree
, hf_alp_lmt_plp_mc_context_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
525 if (payload_length
> 0) {
526 tvbuff_t
*payload_tvb
= tvb_new_subset_length(tvb
, offset
, payload_length
);
527 offset
+= payload_length
;
529 if ((packet_type
== ALP_PACKET_TYPE_IPV4
) && (payload_configuration
== 0)) {
530 call_dissector(ip_handle
, payload_tvb
, pinfo
, tree
);
532 call_data_dissector(payload_tvb
, pinfo
, tree
);
536 if (offset
< (int)tvb_captured_length(tvb
)) {
537 int junk_length
= tvb_captured_length(tvb
) - offset
;
538 proto_tree_add_bytes_format(alp_tree
, hf_alp_junk
, tvb
, offset
, -1, NULL
, "Junk at end (%u byte%s)", junk_length
, (junk_length
== 1) ? "" : "s");
541 return tvb_captured_length(tvb
);
545 proto_register_alp(void)
547 static hf_register_info hf
[] = {
548 { &hf_alp_packet_type
, {
549 "Packet Type", "alp.type",
550 FT_UINT8
, BASE_DEC
, VALS(alp_packet_type_vals
), ALP_PACKET_TYPE_MASK
, NULL
, HFILL
553 { &hf_alp_mpegts_numts
, {
554 "Number of TS packets", "alp.numts",
555 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
557 { &hf_alp_mpegts_ahf
, {
558 "Additional Header Flag", "alp.ahf",
559 FT_UINT8
, BASE_DEC
, NULL
, ALP_MPEGTS_AHF_MASK
, NULL
, HFILL
561 { &hf_alp_mpegts_hdm
, {
562 "Header Deletion Mode", "alp.hdm",
563 FT_UINT8
, BASE_DEC
, NULL
, ALP_MPEGTS_HDM_MASK
, NULL
, HFILL
565 { &hf_alp_mpegts_dnp
, {
566 "Deleted Null Packets", "alp.dnp",
567 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
570 { &hf_alp_payload_configuration
, {
571 "Payload Configuration", "alp.pc",
572 FT_UINT8
, BASE_DEC
, NULL
, ALP_PAYLOAD_CONFIGURATION_MASK
, NULL
, HFILL
574 { &hf_alp_header_mode
, {
575 "Header Mode", "alp.hm",
576 FT_UINT8
, BASE_DEC
, NULL
, ALP_HEADER_MODE_MASK
, NULL
, HFILL
578 { &hf_alp_segmentation_concatenation
, {
579 "Segmentation Concatenation", "alp.sc",
580 FT_UINT8
, BASE_DEC
, VALS(alp_segmentation_concatenation_vals
), ALP_SEGMENTATION_CONCATENATION_MASK
, NULL
, HFILL
584 "Length", "alp.length",
585 FT_UINT16
, BASE_DEC
, NULL
, ALP_LENGTH_MASK
, NULL
, HFILL
588 { &hf_alp_single_length
, {
589 "Length", "alp.length",
590 FT_UINT24
, BASE_DEC
, NULL
, ALP_SINGLE_LENGTH_MASK
, NULL
, HFILL
592 { &hf_alp_single_sif
, {
593 "Sub-stream Identifier Flag", "alp.sif",
594 FT_UINT8
, BASE_DEC
, NULL
, ALP_SINGLE_SIF_MASK
, NULL
, HFILL
596 { &hf_alp_single_hef
, {
597 "Header Extension Flag", "alp.hef",
598 FT_UINT8
, BASE_DEC
, NULL
, ALP_SINGLE_HEF_MASK
, NULL
, HFILL
601 { &hf_alp_segment_sequence_number
, {
602 "Segment Sequence Number", "alp.ssn",
603 FT_UINT8
, BASE_DEC
, NULL
, ALP_SEGMENT_SEQUENCE_NUMBER_MASK
, NULL
, HFILL
605 { &hf_alp_segment_last_indicator
, {
606 "Last Segment Indicator", "alp.lsi",
607 FT_UINT8
, BASE_DEC
, NULL
, ALP_SEGMENT_LAST_INDICATOR_MASK
, NULL
, HFILL
609 { &hf_alp_segment_sif
, {
610 "Sub-stream Identifier Flag", "alp.sif",
611 FT_UINT8
, BASE_DEC
, NULL
, ALP_SEGMENT_SIF_MASK
, NULL
, HFILL
613 { &hf_alp_segment_hef
, {
614 "Header Extension Flag", "alp.hef",
615 FT_UINT8
, BASE_DEC
, NULL
, ALP_SEGMENT_HEF_MASK
, NULL
, HFILL
618 { &hf_alp_concat_length
, {
619 "Length", "alp.length",
620 FT_UINT24
, BASE_DEC
, NULL
, ALP_CONCAT_LENGTH_MASK
, NULL
, HFILL
622 { &hf_alp_concat_count
, {
623 "Concatenation Count", "alp.cc",
624 FT_UINT8
, BASE_DEC
, NULL
, ALP_CONCAT_COUNT_MASK
, NULL
, HFILL
626 { &hf_alp_concat_sif
, {
627 "Sub-stream Identifier Flag", "alp.sif",
628 FT_UINT8
, BASE_DEC
, NULL
, ALP_CONCAT_SIF_MASK
, NULL
, HFILL
632 "Sub-stream Identification", "alp.si",
633 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
636 "Sub-stream Identifier", "alp.si_sid",
637 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
640 { &hf_alp_header_extension
, {
641 "Header Extension", "alp.he",
642 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
644 { &hf_alp_header_extension_type
, {
645 "Header Extension Type", "alp.he.type",
646 FT_UINT8
, BASE_HEX
, NULL
, 0, NULL
, HFILL
648 { &hf_alp_header_extension_length
, {
649 "Header Extension Length", "alp.he.length",
650 FT_UINT8
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0, NULL
, HFILL
653 { &hf_alp_header_extension_sony_l1d_timeinfo
, {
654 "Sony L1D Time Info Extension Raw", "alp.he.sony_l1d_timeinfo",
655 FT_UINT64
, BASE_HEX
, NULL
, 0, NULL
, HFILL
657 { &hf_alp_header_extension_sony_l1d_timeinfo_flag
, {
658 "Sony L1D Time Info Flag", "alp.he.sony_l1d_timeinfo.flag",
659 FT_UINT64
, BASE_HEX
, NULL
, ALP_HE_SONY_L1D_TIME_FLAG_MASK
, NULL
, HFILL
661 { &hf_alp_header_extension_sony_l1d_timeinfo_sec
, {
662 "Sony L1D Time Info Seconds", "alp.he.sony_l1d_timeinfo.sec",
663 FT_UINT64
, BASE_DEC
, NULL
, ALP_HE_SONY_L1D_TIME_SEC_MASK
, NULL
, HFILL
665 { &hf_alp_header_extension_sony_l1d_timeinfo_ms
, {
666 "Sony L1D Time Info Milliseconds", "alp.he.sony_l1d_timeinfo.ms",
667 FT_UINT64
, BASE_DEC
, NULL
, ALP_HE_SONY_L1D_TIME_MS_MASK
, NULL
, HFILL
669 { &hf_alp_header_extension_sony_l1d_timeinfo_us
, {
670 "Sony L1D Time Info Microseconds", "alp.he.sony_l1d_timeinfo.us",
671 FT_UINT64
, BASE_DEC
, NULL
, ALP_HE_SONY_L1D_TIME_US_MASK
, NULL
, HFILL
673 { &hf_alp_header_extension_sony_l1d_timeinfo_ns
, {
674 "Sony L1D Time Info Nanoseconds", "alp.he.sony_l1d_timeinfo.ns",
675 FT_UINT64
, BASE_DEC
, NULL
, ALP_HE_SONY_L1D_TIME_NS_MASK
, NULL
, HFILL
677 { &hf_alp_header_extension_sony_l1d_timeinfo_time
, {
678 "Sony L1D Time Info TAI Time", "alp.he.sony_l1d_timeinfo.time",
679 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0, NULL
, HFILL
681 { &hf_alp_header_extension_sony_l1d_timeinfo_time_ns
, {
682 "Sony L1D Time Info TAI Time (ns)", "alp.he.sony_l1d_timeinfo.time_ns",
683 FT_UINT64
, BASE_DEC
, NULL
, 0, NULL
, HFILL
686 { &hf_alp_header_extension_sony_plp_id
, {
687 "Sony PLP Extension PLP ID", "alp.he.sony_plp.id",
688 FT_UINT8
, BASE_DEC
, NULL
, ALP_HE_SONY_PLP_NUM_MASK
, NULL
, HFILL
690 { &hf_alp_header_extension_sony_plp_unk
, {
691 "Sony PLP Extension Unknown Bits", "alp.he.sony_plp.unknown",
692 FT_UINT8
, BASE_HEX
, NULL
, ALP_HE_SONY_PLP_UNK_MASK
, NULL
, HFILL
695 { &hf_alp_sig_info
, {
696 "Signalling Information Header", "alp.sih",
697 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
699 { &hf_alp_sig_info_type
, {
700 "Signalling Type", "alp.sih_type",
701 FT_UINT8
, BASE_HEX
, VALS(alp_sig_info_type_vals
), 0, NULL
, HFILL
703 { &hf_alp_sig_info_type_extension
, {
704 "Signalling Type Extension", "alp.sih_type_ext",
705 FT_UINT16
, BASE_HEX
, NULL
, 0, NULL
, HFILL
707 { &hf_alp_sig_info_version
, {
708 "Signalling Version", "alp.sih_version",
709 FT_UINT8
, BASE_HEX
, NULL
, 0, NULL
, HFILL
711 { &hf_alp_sig_info_format
, {
712 "Signalling Format", "alp.sih_format",
713 FT_UINT8
, BASE_DEC
, VALS(alp_sig_info_format_vals
), ALP_SIG_INFO_FORMAT_MASK
, NULL
, HFILL
715 { &hf_alp_sig_info_encoding
, {
716 "Signalling Encoding", "alp.sih_encoding",
717 FT_UINT8
, BASE_DEC
, VALS(alp_sig_info_encoding_vals
), ALP_SIG_INFO_ENCODING_MASK
, NULL
, HFILL
721 "Link Mapping Table", "alp.lmt",
722 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
724 { &hf_alp_lmt_numplp
, {
725 "Number of PLPs", "alp.lmt.numplp",
726 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
728 { &hf_alp_lmt_reserved
, {
729 "Reserved", "alp.lmt.reserved",
730 FT_UINT8
, BASE_HEX
, NULL
, ALP_LMT_RESERVED_MASK
, NULL
, HFILL
735 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
737 { &hf_alp_lmt_plp_id
, {
738 "PLP ID", "alp.plp.id",
739 FT_UINT8
, BASE_DEC
, NULL
, ALP_LMT_PLP_ID_MASK
, NULL
, HFILL
741 { &hf_alp_lmt_plp_reserved
, {
742 "Reserved", "alp.plp.reserved",
743 FT_UINT8
, BASE_HEX
, NULL
, ALP_LMT_PLP_RESERVED_MASK
, NULL
, HFILL
745 { &hf_alp_lmt_plp_nummc
, {
746 "Number of Multicast Entries", "alp.plp.nummc",
747 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
749 { &hf_alp_lmt_plp_mc
, {
750 "Multicast Entry", "alp.plp.mc",
751 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
753 { &hf_alp_lmt_plp_mc_src_ip
, {
754 "Source IP", "alp.plp.mc.src_ip",
755 FT_IPv4
, BASE_NONE
, NULL
, 0, NULL
, HFILL
757 { &hf_alp_lmt_plp_mc_dst_ip
, {
758 "Destination IP", "alp.plp.mc.dst_ip",
759 FT_IPv4
, BASE_NONE
, NULL
, 0, NULL
, HFILL
761 { &hf_alp_lmt_plp_mc_src_port
, {
762 "Source Port", "alp.plp.mc.src_port",
763 FT_UINT16
, BASE_DEC
, NULL
, 0, NULL
, HFILL
765 { &hf_alp_lmt_plp_mc_dst_port
, {
766 "Destination IP", "alp.plp.mc.dst_port",
767 FT_UINT16
, BASE_DEC
, NULL
, 0, NULL
, HFILL
769 { &hf_alp_lmt_plp_mc_sid_flag
, {
770 "SID Flag", "alp.plp.mc.sid_flag",
771 FT_UINT8
, BASE_DEC
, NULL
, ALP_LMT_PLP_MC_SID_MASK
, NULL
, HFILL
773 { &hf_alp_lmt_plp_mc_comp_flag
, {
774 "Compressed Flag", "alp.plp.mc.comp_flag",
775 FT_UINT8
, BASE_DEC
, NULL
, ALP_LMT_PLP_MC_COMP_MASK
, NULL
, HFILL
777 { &hf_alp_lmt_plp_mc_reserved
, {
778 "Reserved", "alp.plp.mc.reserved",
779 FT_UINT8
, BASE_HEX
, NULL
, ALP_LMT_PLP_MC_RESERVED_MASK
, NULL
, HFILL
781 { &hf_alp_lmt_plp_mc_sid
, {
782 "Reserved", "alp.plp.mc.sid",
783 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
785 { &hf_alp_lmt_plp_mc_context_id
, {
786 "Reserved", "alp.plp.mc.context_id",
787 FT_UINT8
, BASE_HEX
, NULL
, 0, NULL
, HFILL
792 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
796 static int *ett
[] = {
806 proto_alp
= proto_register_protocol("ATSC Link-Layer Protocol", "ALP", "alp");
807 proto_register_field_array(proto_alp
, hf
, array_length(hf
));
808 proto_register_subtree_array(ett
, array_length(ett
));
812 proto_reg_handoff_alp(void)
814 alp_handle
= create_dissector_handle(dissect_alp
, proto_alp
);
815 dissector_add_uint("wtap_encap", WTAP_ENCAP_ATSC_ALP
, alp_handle
);
817 ip_handle
= find_dissector("ip");
818 ts_handle
= find_dissector("mp2t");
822 * Editor modelines - https://www.wireshark.org/tools/modelines.html
827 * indent-tabs-mode: nil
830 * vi: set shiftwidth=4 tabstop=8 expandtab:
831 * :indentSize=4:tabSize=8:noTabs=true: