Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-alp.c
blob050dd931ebfb395d959d9c8bd7c3ddf07a4fc1c5
1 /* packet-alp.c
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/
17 #include <config.h>
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);
27 static int proto_alp;
28 static int ett_alp;
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[] = {
46 { 0, "IPv4 packet" },
47 { 1, "Reserved" },
48 { 2, "Compressed IPv4 packet" },
49 { 3, "Reserved" },
50 { 4, "Link layer signalling packet" },
51 { 5, "Reserved" },
52 { 6, "Packet type extension" },
53 { 7, "MPEG-2 transport stream" },
54 { 0, NULL }
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" },
75 { 0, NULL }
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" },
141 { 0, NULL }
143 static const value_string alp_sig_info_format_vals[] = {
144 { 0, "Binary" },
145 { 1, "XML" },
146 { 2, "JSON" },
147 { 3, "Reserved" },
148 { 0, NULL }
150 static const value_string alp_sig_info_encoding_vals[] = {
151 { 0, "No Compression" },
152 { 1, "DEFLATE" },
153 { 2, "Reserved" },
154 { 3, "Reserved" },
155 { 0, NULL }
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;
186 static int
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;
192 if (numts == 0) {
193 numts = 16;
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);
200 offset++;
202 uint8_t hdm = 0;
203 uint8_t dnp = 0;
205 if (ahf) {
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)) {
210 dnp = 128;
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)
217 offset++;
220 while (dnp--) {
221 unsigned char *ts_frame = (unsigned char*)wmem_alloc(pinfo->pool, 188);
223 ts_frame[0] = 0x47;
224 ts_frame[1] = 0x1F;
225 ts_frame[2] = 0xFF;
226 ts_frame[3] = 0x10;
227 ts_frame[4] = 0x00;
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);
236 ts_frame[0] = 0x47;
237 tvb_memcpy(tvb, ts_frame + 1, offset, 187);
238 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);
246 while (--numts) {
247 ts_frame = (unsigned char*)wmem_alloc(pinfo->pool, 188);
249 if (hdm) {
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);
253 offset += 184;
254 } else {
255 ts_frame[0] = 0x47;
256 tvb_memcpy(tvb, ts_frame + 1, offset, 187);
257 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);
272 static int
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);
281 int offset = 0;
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);
292 bool sif = false;
293 bool hef = false;
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);
303 offset += 2;
304 } else {
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);
307 offset += 2;
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);
313 offset++;
315 } else {
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);
322 offset += 2;
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);
330 offset++;
331 } else {
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);
334 offset += 2;
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);
340 offset++;
342 uint32_t skip = (uint32_t)count * 12;
343 if (count & 0x01) {
344 skip += 4;
346 offset += skip / 8;
350 if (sif) {
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);
355 offset++;
358 if (hef) {
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);
367 offset++;
369 PROTO_ITEM_SET_GENERATED(
370 proto_tree_add_uint(he_tree, hf_alp_header_extension_length, tvb, offset, 1, he_length)
372 offset++;
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)
402 offset += 8;
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);
408 offset++;
409 } else {
410 tvbuff_t *he_data_tvb = tvb_new_subset_length(tvb, offset, he_length);
411 call_data_dissector(he_data_tvb, pinfo, he_tree);
412 offset += he_length;
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);
422 offset++;
424 proto_tree_add_item(sig_info_tree, hf_alp_sig_info_type_extension, tvb, offset, 2, ENC_BIG_ENDIAN);
425 offset += 2;
427 proto_tree_add_item(sig_info_tree, hf_alp_sig_info_version, tvb, offset, 1, ENC_BIG_ENDIAN);
428 offset++;
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);
432 offset++;
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);
444 offset++;
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);
450 int plp_mc_len = 0;
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);
453 plp_mc_len += 13;
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) {
457 plp_mc_len += 1;
459 if (lmt_mc_plp_comp_flag) {
460 plp_mc_len += 1;
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);
474 offset++;
476 proto_tree_add_item(lmt_plp_tree, hf_alp_lmt_plp_nummc, tvb, offset, 1, ENC_BIG_ENDIAN);
477 offset++;
479 for(uint8_t j = 0; j < lmt_mc_nummc; j++) {
480 int mc_len = 13;
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) {
485 mc_len += 1;
487 if (lmt_mc_plp_comp_flag) {
488 mc_len += 1;
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);
496 offset += 4;
498 proto_tree_add_item(lmt_plp_mc_tree, hf_alp_lmt_plp_mc_dst_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
499 offset += 4;
501 proto_tree_add_item(lmt_plp_mc_tree, hf_alp_lmt_plp_mc_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
502 offset += 2;
504 proto_tree_add_item(lmt_plp_mc_tree, hf_alp_lmt_plp_mc_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
505 offset += 2;
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);
510 offset += 1;
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);
514 offset += 1;
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);
518 offset += 1;
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);
531 } else {
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);
544 void
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
551 } },
553 { &hf_alp_mpegts_numts, {
554 "Number of TS packets", "alp.numts",
555 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
556 } },
557 { &hf_alp_mpegts_ahf, {
558 "Additional Header Flag", "alp.ahf",
559 FT_UINT8, BASE_DEC, NULL, ALP_MPEGTS_AHF_MASK, NULL, HFILL
560 } },
561 { &hf_alp_mpegts_hdm, {
562 "Header Deletion Mode", "alp.hdm",
563 FT_UINT8, BASE_DEC, NULL, ALP_MPEGTS_HDM_MASK, NULL, HFILL
564 } },
565 { &hf_alp_mpegts_dnp, {
566 "Deleted Null Packets", "alp.dnp",
567 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
568 } },
570 { &hf_alp_payload_configuration, {
571 "Payload Configuration", "alp.pc",
572 FT_UINT8, BASE_DEC, NULL, ALP_PAYLOAD_CONFIGURATION_MASK, NULL, HFILL
573 } },
574 { &hf_alp_header_mode, {
575 "Header Mode", "alp.hm",
576 FT_UINT8, BASE_DEC, NULL, ALP_HEADER_MODE_MASK, NULL, HFILL
577 } },
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
581 } },
583 { &hf_alp_length, {
584 "Length", "alp.length",
585 FT_UINT16, BASE_DEC, NULL, ALP_LENGTH_MASK, NULL, HFILL
586 } },
588 { &hf_alp_single_length, {
589 "Length", "alp.length",
590 FT_UINT24, BASE_DEC, NULL, ALP_SINGLE_LENGTH_MASK, NULL, HFILL
591 } },
592 { &hf_alp_single_sif, {
593 "Sub-stream Identifier Flag", "alp.sif",
594 FT_UINT8, BASE_DEC, NULL, ALP_SINGLE_SIF_MASK, NULL, HFILL
595 } },
596 { &hf_alp_single_hef, {
597 "Header Extension Flag", "alp.hef",
598 FT_UINT8, BASE_DEC, NULL, ALP_SINGLE_HEF_MASK, NULL, HFILL
599 } },
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
604 } },
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
608 } },
609 { &hf_alp_segment_sif, {
610 "Sub-stream Identifier Flag", "alp.sif",
611 FT_UINT8, BASE_DEC, NULL, ALP_SEGMENT_SIF_MASK, NULL, HFILL
612 } },
613 { &hf_alp_segment_hef, {
614 "Header Extension Flag", "alp.hef",
615 FT_UINT8, BASE_DEC, NULL, ALP_SEGMENT_HEF_MASK, NULL, HFILL
616 } },
618 { &hf_alp_concat_length, {
619 "Length", "alp.length",
620 FT_UINT24, BASE_DEC, NULL, ALP_CONCAT_LENGTH_MASK, NULL, HFILL
621 } },
622 { &hf_alp_concat_count, {
623 "Concatenation Count", "alp.cc",
624 FT_UINT8, BASE_DEC, NULL, ALP_CONCAT_COUNT_MASK, NULL, HFILL
625 } },
626 { &hf_alp_concat_sif, {
627 "Sub-stream Identifier Flag", "alp.sif",
628 FT_UINT8, BASE_DEC, NULL, ALP_CONCAT_SIF_MASK, NULL, HFILL
629 } },
631 { &hf_alp_si, {
632 "Sub-stream Identification", "alp.si",
633 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
634 } },
635 { &hf_alp_sid, {
636 "Sub-stream Identifier", "alp.si_sid",
637 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
638 } },
640 { &hf_alp_header_extension, {
641 "Header Extension", "alp.he",
642 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
643 } },
644 { &hf_alp_header_extension_type, {
645 "Header Extension Type", "alp.he.type",
646 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL
647 } },
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
651 } },
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
656 } },
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
660 } },
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
664 } },
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
668 } },
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
672 } },
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
676 } },
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
680 } },
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
684 } },
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
689 } },
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
693 } },
695 { &hf_alp_sig_info, {
696 "Signalling Information Header", "alp.sih",
697 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
698 } },
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
702 } },
703 { &hf_alp_sig_info_type_extension, {
704 "Signalling Type Extension", "alp.sih_type_ext",
705 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL
706 } },
707 { &hf_alp_sig_info_version, {
708 "Signalling Version", "alp.sih_version",
709 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL
710 } },
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
714 } },
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
718 } },
720 { &hf_alp_lmt, {
721 "Link Mapping Table", "alp.lmt",
722 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
723 } },
724 { &hf_alp_lmt_numplp, {
725 "Number of PLPs", "alp.lmt.numplp",
726 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
727 } },
728 { &hf_alp_lmt_reserved, {
729 "Reserved", "alp.lmt.reserved",
730 FT_UINT8, BASE_HEX, NULL, ALP_LMT_RESERVED_MASK, NULL, HFILL
731 } },
733 { &hf_alp_lmt_plp, {
734 "PLP", "alp.plp",
735 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
736 } },
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
740 } },
741 { &hf_alp_lmt_plp_reserved, {
742 "Reserved", "alp.plp.reserved",
743 FT_UINT8, BASE_HEX, NULL, ALP_LMT_PLP_RESERVED_MASK, NULL, HFILL
744 } },
745 { &hf_alp_lmt_plp_nummc, {
746 "Number of Multicast Entries", "alp.plp.nummc",
747 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
748 } },
749 { &hf_alp_lmt_plp_mc, {
750 "Multicast Entry", "alp.plp.mc",
751 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
752 } },
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
756 } },
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
760 } },
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
764 } },
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
768 } },
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
772 } },
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
776 } },
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
780 } },
781 { &hf_alp_lmt_plp_mc_sid, {
782 "Reserved", "alp.plp.mc.sid",
783 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
784 } },
785 { &hf_alp_lmt_plp_mc_context_id, {
786 "Reserved", "alp.plp.mc.context_id",
787 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL
788 } },
790 { &hf_alp_junk, {
791 "Junk", "alp.junk",
792 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL
793 } },
796 static int *ett[] = {
797 &ett_alp,
798 &ett_alp_si,
799 &ett_alp_he,
800 &ett_alp_sig_info,
801 &ett_alp_lmt,
802 &ett_alp_lmt_plp,
803 &ett_alp_lmt_plp_mc,
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));
811 void
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
824 * Local variables:
825 * c-basic-offset: 4
826 * tab-width: 8
827 * indent-tabs-mode: nil
828 * End:
830 * vi: set shiftwidth=4 tabstop=8 expandtab:
831 * :indentSize=4:tabSize=8:noTabs=true: