Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lls.c
blob3600f085dca631c406a81b871b64f1840d103666
1 /* packet-lls.c
2 * Routines for ATSC3 LLS(Low Level Signalling) dissection
3 * Copyright 2023, Sergey V. Lobanov <sergey@lobanov.in>
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 * ATSC3 Signaling, Delivery, Synchronization, and Error Protection (A/331)
14 * https://www.atsc.org/atsc-documents/3312017-signaling-delivery-synchronization-error-protection/
16 * ATSC3 Security and Service Protection (A/360)
17 * https://www.atsc.org/atsc-documents/3602018-atsc-3-0-security-service-protection/
19 * ATSC Code Point Registry
20 * https://www.atsc.org/documents/code-point-registry/
23 #include <config.h>
24 #include <epan/expert.h>
25 #include <epan/packet.h>
27 #include "packet-lls.h"
29 #define LLS_PORT 4937 // IANA Registered (atsc-mh-ssc)
31 void proto_reg_handoff_lls(void);
32 void proto_register_lls(void);
34 static int proto_lls;
35 static int ett_lls;
36 static int ett_lls_smt_entry;
37 static int ett_lls_smt_signature;
38 static int ett_lls_table_payload;
39 static int ett_lls_table_payload_xml;
41 static dissector_handle_t lls_handle;
42 static dissector_handle_t xml_handle;
43 static dissector_handle_t cms_handle;
45 static expert_field ei_lls_table_decompression_failed;
47 static int hf_lls_table_id;
48 #define LLS_TABLE_TYPE_SIGNED_MULTI_TABLE 0xFE
49 #define LLS_TABLE_TYPE_SLT 0x01
50 static const value_string hf_lls_table_type_vals[] = {
51 { 0x01, "SLT (Service List Table)" },
52 { 0x02, "RRT (Rating Region Table)" },
53 { 0x03, "System Time" },
54 { 0x04, "AEAT (Advanced Emergency Information Table)" },
55 { 0x05, "On Screen Message Notification" },
56 { 0x06, "CDT (Certification Data Table)" },
57 { 0x07, "DRCT (Dedicated Return Channel Table)" },
58 { 0x80, "VIT (Version Information Table)" },
59 { 0x81, "CPT (Content Protection Table)" },
60 { 0x82, "CAP (Common Alerting Protocol)" },
61 { 0xFE, "Signed Multi Table" },
62 { 0xFF, "User Defined" },
63 { 0x00, NULL }
65 static const value_string hf_lls_table_type_short_vals[] = {
66 { 0x01, "SLT" },
67 { 0x02, "RRT" },
68 { 0x03, "ST" },
69 { 0x04, "AEAT" },
70 { 0x05, "OSMN" },
71 { 0x06, "CDT" },
72 { 0x07, "DRCT" },
73 { 0x80, "VIT" },
74 { 0x81, "CPT" },
75 { 0x82, "CAP" },
76 { 0xFE, "SMT" },
77 { 0xFF, "USD" },
78 { 0x00, NULL }
81 static int hf_lls_group_id;
82 static int hf_lls_group_count;
83 static int hf_lls_table_version;
84 static int hf_lls_table_payload;
85 static int hf_lls_table_payload_uncompressed;
87 static int hf_lls_smt_payload_count;
88 static int hf_lls_smt_entry;
89 static int hf_lls_smt_entry_payload_length;
90 static int hf_lls_smt_signature_length;
91 static int hf_lls_smt_signature;
94 static void
95 dissect_lls_table_payload(uint8_t lls_table_id, tvbuff_t *tvb, packet_info *pinfo, int offset, int len, proto_tree *tree)
97 proto_item *ti = proto_tree_add_item(tree, hf_lls_table_payload, tvb, offset, len, ENC_NA);
99 if (lls_table_id == LLS_TABLE_TYPE_SIGNED_MULTI_TABLE) {
100 /* Nested SignedMultiTable decoding is not specified in the standard */
101 return;
104 proto_tree *uncompress_tree = proto_item_add_subtree(ti, ett_lls_table_payload);
105 tvbuff_t *uncompress_tvb = tvb_uncompress_zlib(tvb, offset, len);
106 proto_tree *xml_tree = NULL;
107 if (uncompress_tvb) {
108 const char *table_type_short = val_to_str_const(lls_table_id, hf_lls_table_type_short_vals, "Unknown");
109 char *source_name = wmem_strdup_printf(pinfo->pool, "Table ID %u (%s)", lls_table_id, table_type_short);
110 add_new_data_source(pinfo, uncompress_tvb, source_name);
111 unsigned decomp_length = tvb_captured_length(uncompress_tvb);
113 proto_item *ti_uncomp = proto_tree_add_item(uncompress_tree, hf_lls_table_payload_uncompressed, uncompress_tvb, 0, decomp_length, ENC_ASCII);
114 proto_item_set_generated(ti_uncomp);
116 if (xml_handle) {
117 xml_tree = proto_item_add_subtree(ti_uncomp, ett_lls_table_payload_xml);
118 call_dissector(xml_handle, uncompress_tvb, pinfo, xml_tree);
120 } else {
121 expert_add_info(pinfo, ti, &ei_lls_table_decompression_failed);
124 if (lls_table_id == LLS_TABLE_TYPE_SLT && xml_tree != NULL) {
125 lls_extract_save_slt_table(pinfo, xml_handle);
130 static int
131 dissect_lls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
133 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLS");
135 proto_item *ti = proto_tree_add_item(tree, proto_lls, tvb, 0, -1, ENC_NA);
136 proto_tree *lls_tree = proto_item_add_subtree(ti, ett_lls);
138 int offset = 0;
140 uint8_t lls_table_id = tvb_get_uint8(tvb, offset);
141 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(lls_table_id, hf_lls_table_type_vals, "Unknown"));
142 proto_tree_add_item(lls_tree, hf_lls_table_id, tvb, offset, 1, ENC_BIG_ENDIAN);
143 offset++;
145 proto_tree_add_item(lls_tree, hf_lls_group_id, tvb, offset, 1, ENC_BIG_ENDIAN);
146 offset++;
148 uint16_t lls_group_count = tvb_get_uint8(tvb, offset) + 1;
149 PROTO_ITEM_SET_GENERATED(
150 proto_tree_add_uint(lls_tree, hf_lls_group_count, tvb, offset, 1, lls_group_count)
152 offset++;
154 proto_tree_add_item(lls_tree, hf_lls_table_version, tvb, offset, 1, ENC_BIG_ENDIAN);
155 offset++;
157 if (lls_table_id == LLS_TABLE_TYPE_SIGNED_MULTI_TABLE) {
158 uint8_t smt_payload_count = tvb_get_uint8(tvb, offset);
159 proto_tree_add_item(lls_tree, hf_lls_smt_payload_count, tvb, offset, 1, ENC_BIG_ENDIAN);
160 offset++;
162 for(uint8_t i = 0; i < smt_payload_count; i++) {
163 uint16_t smt_entry_payload_length = tvb_get_uint16(tvb, offset + 2, ENC_BIG_ENDIAN);
164 proto_item *smt_entry_item = proto_tree_add_item(lls_tree, hf_lls_smt_entry, tvb, offset, smt_entry_payload_length + 4, ENC_NA);
165 proto_tree *smt_entry_tree = proto_item_add_subtree(smt_entry_item, ett_lls_smt_entry);
167 uint8_t smt_entry_table_id = tvb_get_uint8(tvb, offset);
168 const char *table_type_short = val_to_str_const(smt_entry_table_id, hf_lls_table_type_short_vals, "Unknown");
169 proto_item_append_text(smt_entry_item, " (%u) Table ID=%u (%s)", i, smt_entry_table_id, table_type_short);
170 col_append_fstr(pinfo->cinfo, COL_INFO, "/%s", table_type_short);
171 proto_tree_add_item(smt_entry_tree, hf_lls_table_id, tvb, offset, 1, ENC_BIG_ENDIAN);
172 offset++;
174 proto_tree_add_item(smt_entry_tree, hf_lls_table_version, tvb, offset, 1, ENC_BIG_ENDIAN);
175 offset++;
177 proto_tree_add_item(smt_entry_tree, hf_lls_smt_entry_payload_length, tvb, offset, 2, ENC_BIG_ENDIAN);
178 offset += 2;
180 dissect_lls_table_payload(smt_entry_table_id, tvb, pinfo, offset, smt_entry_payload_length, smt_entry_tree);
181 offset += smt_entry_payload_length;
184 uint16_t smt_signature_length = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
185 proto_tree_add_item(lls_tree, hf_lls_smt_signature_length, tvb, offset, 2, ENC_BIG_ENDIAN);
186 offset += 2;
188 proto_item *smt_signature_item = proto_tree_add_item(lls_tree, hf_lls_smt_signature, tvb, offset, smt_signature_length, ENC_NA);
189 if (cms_handle) {
190 proto_tree *cms_tree = proto_item_add_subtree(smt_signature_item, ett_lls_smt_signature);
191 tvbuff_t *cms_tvb = tvb_new_subset_length(tvb, offset, smt_signature_length);
193 /* CMS dissector removes useful info from Protocol and Info columns so store it */
194 char *col_info_text = wmem_strdup(pinfo->pool, col_get_text(pinfo->cinfo, COL_INFO));
195 char *col_protocol_text = wmem_strdup(pinfo->pool, col_get_text(pinfo->cinfo, COL_PROTOCOL));
197 call_dissector(cms_handle, cms_tvb, pinfo, cms_tree);
199 /* Restore Protocol and Info columns */
200 col_set_str(pinfo->cinfo, COL_INFO, col_info_text);
201 col_set_str(pinfo->cinfo, COL_PROTOCOL, col_protocol_text);
203 } else {
204 int table_payload_length = tvb_captured_length(tvb) - 4;
205 dissect_lls_table_payload(lls_table_id, tvb, pinfo, offset, table_payload_length, lls_tree);
208 return tvb_captured_length(tvb);
211 void
212 proto_register_lls(void)
214 static hf_register_info hf[] = {
215 { &hf_lls_table_id, {
216 "Table ID", "lls.table.id",
217 FT_UINT8, BASE_DEC, VALS(hf_lls_table_type_vals), 0, NULL, HFILL
218 } },
219 { &hf_lls_group_id, {
220 "Group ID", "lls.group.id",
221 FT_UINT8, BASE_DEC, 0, 0, NULL, HFILL
222 } },
223 { &hf_lls_group_count, {
224 "Group Count", "lls.group.count",
225 FT_UINT16, BASE_DEC, 0, 0, NULL, HFILL
226 } },
227 { &hf_lls_table_version, {
228 "Table Version", "lls.table.version",
229 FT_UINT8, BASE_DEC, 0, 0, NULL, HFILL
230 } },
231 { &hf_lls_table_payload, {
232 "Table Payload", "lls.table.payload",
233 FT_NONE, BASE_NONE, 0, 0, NULL, HFILL
234 } },
235 { &hf_lls_table_payload_uncompressed, {
236 "Table Payload Uncompressed", "lls.table.payload.uncompressed",
237 FT_STRING, BASE_NONE, 0, 0, NULL, HFILL
238 } },
241 { &hf_lls_smt_payload_count, {
242 "Signed Multi Table Payload Count", "lls.smt.payload_count",
243 FT_UINT8, BASE_DEC, 0, 0, NULL, HFILL
244 } },
245 { &hf_lls_smt_entry, {
246 "Signed Multi Table Entry", "lls.smt.entry",
247 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
248 } },
250 { &hf_lls_smt_entry_payload_length, {
251 "Payload Length", "lls.smt.entry.payload_length",
252 FT_UINT16, BASE_DEC, 0, 0, NULL, HFILL
253 } },
255 { &hf_lls_smt_signature_length, {
256 "Signed Multi Table Signature Length", "lls.smt.signature_length",
257 FT_UINT16, BASE_DEC, 0, 0, NULL, HFILL
258 } },
259 { &hf_lls_smt_signature, {
260 "Signed Multi Table Signature", "lls.smt.signature",
261 FT_NONE, BASE_NONE, 0, 0, NULL, HFILL
262 } },
265 static int *ett[] = {
266 &ett_lls,
267 &ett_lls_smt_entry,
268 &ett_lls_table_payload,
269 &ett_lls_table_payload_xml,
270 &ett_lls_smt_signature,
273 static ei_register_info ei[] = {
274 { &ei_lls_table_decompression_failed,
275 { "lls.table.decompression.failed", PI_MALFORMED, PI_ERROR,
276 "LLS table payload decompression failed",
277 EXPFILL }
281 proto_lls = proto_register_protocol("ATSC3 Low Level Signalling", "LLS", "lls");
283 expert_module_t *expert_lls = expert_register_protocol(proto_lls);
284 expert_register_field_array(expert_lls, ei, array_length(ei));
286 proto_register_field_array(proto_lls, hf, array_length(hf));
287 proto_register_subtree_array(ett, array_length(ett));
290 void
291 proto_reg_handoff_lls(void)
293 lls_handle = create_dissector_handle(dissect_lls, proto_lls);
294 xml_handle = find_dissector_add_dependency("xml", proto_lls);
295 cms_handle = find_dissector_add_dependency("cms", proto_lls);
296 dissector_add_uint_with_preference("udp.port", LLS_PORT, lls_handle);
301 * Editor modelines - https://www.wireshark.org/tools/modelines.html
303 * Local variables:
304 * c-basic-offset: 4
305 * tab-width: 8
306 * indent-tabs-mode: nil
307 * End:
309 * vi: set shiftwidth=4 tabstop=8 expandtab:
310 * :indentSize=4:tabSize=8:noTabs=true: