Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-li5g.c
blobf3718d6d5fc938592402c60322b1e8c77a7f9fc4
1 /* packet-li5g.c
2 * Routines for ETSI TS 103 221-2 V1.6.1 (2022-06), Internal Network Interface X2/X3 for Lawful Interception
3 * Roy Zhang <roy.zhang@nokia-sbell.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
11 #include "config.h"
12 #include <epan/packet.h>
13 #include <epan/ipproto.h>
14 #include <epan/unit_strings.h>
15 #include "packet-tls.h"
17 void proto_reg_handoff_li5g(void);
18 void proto_register_li5g(void);
20 static int proto_li5g;
21 static int hf_li5g_version;
22 static int hf_li5g_pduType;
23 static int hf_li5g_headerLen;
24 static int hf_li5g_payloadLen;
25 static int hf_li5g_payloadFormat;
26 static int hf_li5g_payloadDirection;
27 static int hf_li5g_xid;
28 static int hf_li5g_cid;
29 static int hf_li5g_attrType;
30 static int hf_li5g_attrLen;
31 static int hf_li5g_pld;
33 /* the min Attribute Type is 1 */
34 #define LI_5G_ATTR_TYPE_MAX 23
35 /* the min header length */
36 #define LI_5G_HEADER_LEN_MIN 40
38 static int ett_li5g;
39 static int ett_attrContents[LI_5G_ATTR_TYPE_MAX];
40 static int hf_li5g_attrContents[LI_5G_ATTR_TYPE_MAX];
41 static dissector_handle_t li5g_handle;
43 static dissector_table_t li5g_subdissector_table;
45 static const value_string pdu_type_vals[] = {
46 {1, "X2 xIRI"},
47 {2, "X3 xCC"},
48 {3, "Keepalive"},
49 {4, "Keepalive Acknowledgement"},
50 {0, NULL}
53 static const value_string payload_format_vals[] = {
54 { 0, "Reserved for Keepalive"},
55 { 1, "ETSI TS 102 232-1 Defined Payload"},
56 { 2, "3GPP TS 33.128 Defined Payload"},
57 { 3, "3GPP TS 33.108 Defined Payload"},
58 { 4, "Proprietary Payload"},
59 { 5, "IPv4 Packet"},
60 { 6, "IPv6 Packet"},
61 { 7, "Ethernet Frame"},
62 { 8, "RTP Packet"},
63 { 9, "SIP Message"},
64 {10, "DHCP Message"},
65 {11, "RADIUS Packet"},
66 {12, "GTP-U Message"},
67 {13, "MSRP Message"},
68 {14, "3GPP TS 33.108 EpsIRIContent"},
69 {15, "MIME Message"},
70 {16, "3GPP Unstructured PDU"},
71 { 0, NULL}
74 static const value_string payload_dir_vals[] = {
75 {0, "Reserved for Keepalive"},
76 {1, "The direction of the intercepted data or event is not known to the POI"},
77 {2, "The intercepted data or event was sent to (i.e. received by) the target"},
78 {3, "The intercepted data or event was sent from the target"},
79 {4, "The intercepted data or event is a result of intercepted data or events in more than one direction"},
80 {5, "The concept of direction is not applicable to this intercepted data or event"},
81 {0, NULL}
84 static const value_string attribute_type_vals[] = {
85 { 1, "ETSI TS 102 232-1 Defined Attribute"},
86 { 2, "3GPP TS 33.128 Defined Attribute"},
87 { 3, "3GPP TS 33.108 Defined Attribute"},
88 { 4, "Proprietary Attribute"},
89 { 5, "Domain ID (DID)"},
90 { 6, "Network Function ID (NFID)"},
91 { 7, "Interception Point ID (IPID)"},
92 { 8, "Sequence Number"},
93 { 9, "Timestamp"},
94 {10, "Source IPv4 Address"},
95 {11, "Destination IPv4 Address"},
96 {12, "Source IPv6 Address"},
97 {13, "Destination IPv6 Address"},
98 {14, "Source Port"},
99 {15, "Destination Port"},
100 {16, "IP Protocol"},
101 {17, "Matched Target Identifier"},
102 {18, "Other Target Identifier"},
103 {19, "MIME Content Type"},
104 {20, "MIME Content Transfer Encoding"},
105 {21, "Additional XID Related Information"},
106 {22, "SDP Session Description"},
107 {0, NULL}
110 static int
111 // NOLINTNEXTLINE(misc-no-recursion)
112 dissect_li5g(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
114 proto_tree *li5g_tree, *attr_tree, *parent=NULL;
115 proto_item *ti, *attr_ti;
116 tvbuff_t *payload_tvb;
117 int offset = LI_5G_HEADER_LEN_MIN, hf_attr = -1;
118 uint32_t headerLen, payloadLen, pduType;
119 uint16_t payloadFormat, attrType, attrLen;
120 const char* info;
122 address src_addr;
123 address dst_addr;
124 uint32_t src_port;
125 uint32_t dst_port;
127 headerLen = tvb_get_ntohl(tvb, 4);
128 payloadLen = tvb_get_ntohl(tvb, 8);
129 payloadFormat = tvb_get_ntohs(tvb, 12);
131 ti = proto_tree_add_item(tree, proto_li5g, tvb, 0, headerLen+payloadLen, ENC_NA);
132 li5g_tree = proto_item_add_subtree(ti, ett_li5g);
133 proto_tree_add_item(li5g_tree, hf_li5g_version, tvb, 0, 2, ENC_BIG_ENDIAN);
134 proto_tree_add_item_ret_uint(li5g_tree, hf_li5g_pduType, tvb, 2, 2, ENC_BIG_ENDIAN, &pduType);
135 proto_tree_add_item(li5g_tree, hf_li5g_headerLen, tvb, 4, 4, ENC_BIG_ENDIAN);
136 proto_tree_add_item(li5g_tree, hf_li5g_payloadLen, tvb, 8, 4, ENC_BIG_ENDIAN);
137 proto_tree_add_item(li5g_tree, hf_li5g_payloadFormat, tvb, 12, 2, ENC_BIG_ENDIAN);
138 proto_tree_add_item(li5g_tree, hf_li5g_payloadDirection, tvb, 14, 2, ENC_BIG_ENDIAN);
139 proto_tree_add_item(li5g_tree, hf_li5g_xid, tvb, 16, 16, ENC_NA);
140 proto_tree_add_item(li5g_tree, hf_li5g_cid, tvb, 32, 8, ENC_NA);
142 /* Get the Conditional Attribute */
143 while(headerLen - offset > 0){
144 attrType = tvb_get_ntohs(tvb, offset);
145 attrLen = tvb_get_ntohs(tvb, offset+2);
146 if (attrType < LI_5G_ATTR_TYPE_MAX){
147 hf_attr = hf_li5g_attrContents[attrType];
149 attr_ti = proto_tree_add_item(li5g_tree, hf_attr, tvb, offset+4, attrLen, ENC_NA);
150 attr_tree = proto_item_add_subtree(attr_ti, ett_attrContents[attrType]);
151 proto_tree_add_item(attr_tree, hf_li5g_attrType, tvb, offset, 2, ENC_BIG_ENDIAN);
152 proto_tree_add_item(attr_tree, hf_li5g_attrLen, tvb, offset+2, 2, ENC_BIG_ENDIAN);
153 if (attrType == 17 || attrType == 18) {
154 proto_tree_add_item(attr_tree, hf_attr, tvb, offset+4, attrLen, ENC_UTF_8 | ENC_NA);
155 } else {
156 proto_tree_add_item(attr_tree, hf_attr, tvb, offset+4, attrLen, ENC_BIG_ENDIAN);
160 offset = offset + 4 + attrLen;
163 proto_tree_add_item(li5g_tree, hf_li5g_pld, tvb, headerLen, payloadLen, ENC_NA);
165 /* the key is address+port+frame_num for reassemble list, the address/port can be changed in pinfo because of the inner TCP protocol */
166 copy_address_shallow(&src_addr, &pinfo->src);
167 copy_address_shallow(&dst_addr, &pinfo->dst);
168 src_port = pinfo->srcport;
169 dst_port = pinfo->destport;
171 /* to make all the sub protocol(such as DNS) under li5g*/
172 if (li5g_tree && li5g_tree->parent){
173 parent=li5g_tree->parent;
174 li5g_tree->parent=NULL;
177 payload_tvb = tvb_new_subset_length(tvb, offset, payloadLen);
178 if (!dissector_try_uint(li5g_subdissector_table, payloadFormat, payload_tvb, pinfo, li5g_tree)) {
179 call_data_dissector(payload_tvb, pinfo, li5g_tree);
182 if (parent)
183 li5g_tree->parent=parent;
185 /* have another li5g in the same packet? */
186 if (tvb_captured_length(tvb)>offset+payloadLen) {
187 increment_dissection_depth(pinfo);
188 dissect_li5g(tvb_new_subset_remaining(tvb, offset+payloadLen), pinfo, tree, NULL);
189 decrement_dissection_depth(pinfo);
192 /* set these info at the end*/
193 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LI5G");
194 col_clear_fence(pinfo->cinfo, COL_INFO);
195 col_clear(pinfo->cinfo, COL_INFO);
196 info = try_val_to_str(pduType, pdu_type_vals);
197 if (info != NULL) {
198 col_set_str(pinfo->cinfo, COL_INFO, info);
201 /* copy back to the original value when return from innner protocol */
202 copy_address_shallow(&pinfo->src, &src_addr);
203 copy_address_shallow(&pinfo->dst, &dst_addr);
204 pinfo->srcport = src_port;
205 pinfo->destport = dst_port;
207 return tvb_captured_length(tvb);
210 static bool
211 dissect_li5g_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
213 struct tlsinfo* tlsinfo = (struct tlsinfo*)data;
214 if (tvb_captured_length(tvb) < LI_5G_HEADER_LEN_MIN)
215 return false;
216 /* the version should be 1 */
217 if (tvb_get_ntohs(tvb, 0) != 1)
218 return false;
219 /* only 4 types supported*/
220 if(tvb_get_ntohs(tvb, 2) < 1 || tvb_get_ntohs(tvb, 2) > 4)
221 return false;
223 /* TLS can hold it, no need to find the dissector every time */
224 *(tlsinfo->app_handle) = li5g_handle;
225 dissect_li5g(tvb, pinfo, tree, data);
227 return true;
230 void
231 proto_register_li5g(void)
233 static hf_register_info hf[] = {
234 { &hf_li5g_version, { "Version", "li5g.ver", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
235 { &hf_li5g_pduType, { "PDU Type", "li5g.type", FT_UINT16, BASE_DEC, VALS(pdu_type_vals), 0x0, NULL, HFILL }},
236 { &hf_li5g_headerLen, { "Header Length", "li5g.hl", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_octet_octets), 0x0, NULL, HFILL }},
237 { &hf_li5g_payloadLen, { "Payload Length", "li5g.pl", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_octet_octets), 0x0, NULL, HFILL }},
238 { &hf_li5g_payloadFormat, { "Payload Format", "li5g.pf", FT_UINT16, BASE_DEC, VALS(payload_format_vals), 0x0, NULL, HFILL }},
239 { &hf_li5g_payloadDirection, { "Payload Direction", "li5g.pd", FT_UINT16, BASE_DEC, VALS(payload_dir_vals), 0x0, NULL, HFILL }},
240 { &hf_li5g_xid, { "XID", "li5g.xid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
241 { &hf_li5g_cid, { "Correlation ID", "li5g.cid", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
243 { &hf_li5g_attrType, { "Attribute Type", "li5g.attrType", FT_UINT16, BASE_DEC, VALS(attribute_type_vals), 0x0, NULL, HFILL }},
244 { &hf_li5g_attrLen, { "Attribute Length", "li5g.attrLen", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_octet_octets), 0x0, NULL, HFILL }},
245 { &hf_li5g_attrContents[1], { "ETSI TS 102 232-1 Defined Attribute", "li5g.102_232_1_attr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
246 { &hf_li5g_attrContents[2], { "3GPP TS 33.128 Defined Attribute", "li5g.33_128_attr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
247 { &hf_li5g_attrContents[3], { "3GPP TS 33.108 Defined Attribute", "li5g.33_108_attr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
248 { &hf_li5g_attrContents[4], { "Proprietary Attribute", "li5g.proprietary_attr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
249 { &hf_li5g_attrContents[5], { "Domain ID", "li5g.did", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
250 { &hf_li5g_attrContents[6], { "Network Function ID", "li5g.nfid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
251 { &hf_li5g_attrContents[7], { "Interception Point ID", "li5g.ipid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
252 { &hf_li5g_attrContents[8], { "Sequence Number", "li5g.sq", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
253 { &hf_li5g_attrContents[9], { "Timestamp", "li5g.ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL }},
254 { &hf_li5g_attrContents[10], { "Source IPv4 address", "li5g.srcip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
255 { &hf_li5g_attrContents[11], { "Destination IPv4 address", "li5g.dstip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
256 { &hf_li5g_attrContents[12], { "Source IPv6 address", "li5g.srcipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
257 { &hf_li5g_attrContents[13], { "Destination IPv6 address", "li5g.dstipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
258 { &hf_li5g_attrContents[14], { "Source Port", "li5g.srcport", FT_UINT16, BASE_PT_TCP, NULL, 0x0, NULL, HFILL }},
259 { &hf_li5g_attrContents[15], { "Destination Port", "li5g.dstport", FT_UINT16, BASE_PT_TCP, NULL, 0x0, NULL, HFILL }},
260 { &hf_li5g_attrContents[16], { "IP Protocol", "li5g.ipproto", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ipproto_val_ext, 0x0, NULL, HFILL }},
261 { &hf_li5g_attrContents[17], { "Matched Target Identifier", "li5g.mti", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
262 { &hf_li5g_attrContents[18], { "Other Target Identifier", "li5g.oti", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
263 { &hf_li5g_attrContents[19], { "MIME Content Type", "li5g.mime_content_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
264 { &hf_li5g_attrContents[20], { "MIME Content Transfer Encoding", "li5g.mime_transfer_type_encoding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
265 { &hf_li5g_attrContents[21], { "Additional XID Related Information", "li5g.additional_xid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
266 { &hf_li5g_attrContents[22], { "SDP Session Description", "li5g.sdp", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
268 { &hf_li5g_pld, { "Payload", "li5g.pld", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
271 static int *ett[] = {
272 &ett_li5g,
273 &ett_attrContents[1],
274 &ett_attrContents[2],
275 &ett_attrContents[3],
276 &ett_attrContents[4],
277 &ett_attrContents[5],
278 &ett_attrContents[6],
279 &ett_attrContents[7],
280 &ett_attrContents[8],
281 &ett_attrContents[9],
282 &ett_attrContents[10],
283 &ett_attrContents[11],
284 &ett_attrContents[12],
285 &ett_attrContents[13],
286 &ett_attrContents[14],
287 &ett_attrContents[15],
288 &ett_attrContents[16],
289 &ett_attrContents[17],
290 &ett_attrContents[18],
291 &ett_attrContents[19],
292 &ett_attrContents[20],
293 &ett_attrContents[21],
294 &ett_attrContents[22],
297 proto_li5g = proto_register_protocol("Lawful Interception 5G", "LI5G", "li5g");
299 li5g_handle = register_dissector("li5g", dissect_li5g, proto_li5g);
301 li5g_subdissector_table = register_dissector_table("li5g.payload", "LI5G Payload Format", proto_li5g, FT_UINT16, BASE_DEC);
303 proto_register_field_array(proto_li5g, hf, array_length(hf));
304 proto_register_subtree_array(ett, array_length(ett));
307 void
308 proto_reg_handoff_li5g(void)
310 dissector_add_uint("li5g.payload", 2, find_dissector_add_dependency("xiri", proto_li5g));
311 dissector_add_uint("li5g.payload", 5, find_dissector("ip"));
312 dissector_add_uint("li5g.payload", 6, find_dissector("ipv6"));
313 dissector_add_uint("li5g.payload", 7, find_dissector("eth_maybefcs"));
314 dissector_add_uint("li5g.payload", 8, find_dissector("rtp"));
315 dissector_add_uint("li5g.payload", 9, find_dissector("sip"));
316 dissector_add_uint("li5g.payload", 10, find_dissector("dhcp"));
317 dissector_add_uint("li5g.payload", 11, find_dissector("radius"));
318 dissector_add_uint("li5g.payload", 12, find_dissector("gtp"));
319 dissector_add_uint("li5g.payload", 13, find_dissector("msrp"));
320 dissector_add_uint("li5g.payload", 14, find_dissector("HI2Operations"));
322 dissector_add_uint_range_with_preference("tcp.port", "", li5g_handle);
323 dissector_add_uint_range_with_preference("udp.port", "", li5g_handle);
324 heur_dissector_add("tls", dissect_li5g_heur, "5G LI over TLS", "li5g_tls", proto_li5g, HEURISTIC_ENABLE);