Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gsm_rlp.c
blob35b6d55a407aaa5f2cd86c4def518e050fa1c13d
1 /* packet-gsm_rlp.c
2 * Routines for GSM RLP (3GPP TS 24.022) frame dissection
3 * (C) 2023 Harald Welte <laforge@osmocom.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/prefs.h>
16 #include <epan/expert.h>
17 #include <epan/reassemble.h>
18 #include <epan/conversation.h>
20 void proto_register_gsmrlp(void);
22 static int proto_gsmrlp;
24 static int hf_gsmrlp_cr;
25 static int hf_gsmrlp_pf;
26 static int hf_gsmrlp_n_r;
27 static int hf_gsmrlp_n_s;
28 static int hf_gsmrlp_ftype;
29 static int hf_gsmrlp_s_ftype;
30 static int hf_gsmrlp_u_ftype;
31 static int hf_gsmrlp_fcs;
32 static int hf_gsmrlp_fcs_status;
34 static int hf_gsmrlp_xid_p_type;
35 static int hf_gsmrlp_xid_p_len;
36 static int hf_gsmrlp_xid_p_val;
38 static int ett_gsmrlp;
39 static int ett_gsmrlp_xid;
41 static expert_field ei_gsmrlp_fcs_bad;
43 static dissector_handle_t l2rcop_handle;
44 static bool decode_as_l2rcop = true;
46 /* 3GPP TS 24.002 Section 5.2.1 */
47 enum rlp_ftype {
48 RLP_FT_U,
49 RLP_FT_S,
50 RLP_FT_IS,
53 static const value_string rlp_ftype_vals[] = {
54 { RLP_FT_U, "U" },
55 { RLP_FT_S, "S" },
56 { RLP_FT_IS, "IS" },
57 { 0, NULL }
60 /* 3GPP TS 24.002 Section 5.2.1 */
61 enum rlp_u_ftype {
62 RLP_U_FT_SABM = 0x07,
63 RLP_U_FT_UA = 0x0c,
64 RLP_U_FT_DISC = 0x08,
65 RLP_U_FT_DM = 0x03,
66 RLP_U_FT_NULL = 0x0f,
67 RLP_U_FT_UI = 0x00,
68 RLP_U_FT_XID = 0x17,
69 RLP_U_FT_TEST = 0x1c,
70 RLP_U_FT_REMAP = 0x11,
72 static const value_string rlp_ftype_u_vals[] = {
73 { RLP_U_FT_SABM, "SABM" },
74 { RLP_U_FT_UA, "UA" },
75 { RLP_U_FT_DISC, "DISC" },
76 { RLP_U_FT_DM, "DM" },
77 { RLP_U_FT_NULL, "NULL" },
78 { RLP_U_FT_UI, "UI" },
79 { RLP_U_FT_XID, "XID" },
80 { RLP_U_FT_TEST, "TEST" },
81 { RLP_U_FT_REMAP, "REMAP" },
82 { 0, NULL }
85 /* 3GPP TS 24.002 Section 5.2.1 */
86 enum rlp_s_ftype {
87 RLP_S_FT_RR = 0,
88 RLP_S_FT_REJ = 2,
89 RLP_S_FT_RNR = 1,
90 RLP_S_FT_SREJ = 3,
92 static const value_string rlp_ftype_s_vals[] = {
93 { RLP_S_FT_RR, "RR" },
94 { RLP_S_FT_REJ, "REJ" },
95 { RLP_S_FT_RNR, "RNR" },
96 { RLP_S_FT_SREJ, "SREJ" },
97 { 0, NULL }
100 /* 3GPP TS 24.002 Section 5.2.2.6 */
101 enum rlp_xid_param_type {
102 XID_P_DELIMITER = 0,
103 XID_P_RLP_VERSION = 1,
104 XID_P_IWF_TO_UE_WIN_SIZE = 2,
105 XID_P_UE_TO_IWF_WIN_SIZE = 3,
106 XID_P_ACK_TIMER_T1 = 4,
107 XID_P_RETRANS_ATTEMPTS_N2 = 5,
108 XID_P_REPLY_DELAY_T2 = 6,
109 XID_P_COMPRESSION_PT = 7,
110 XID_P_RESEQUENCING_T4 = 8,
111 XID_P_OPTIONAL_FEATURES = 9,
114 static const value_string rlp_xid_param_vals[] = {
115 { XID_P_DELIMITER, "Delimiter (end of parameters)" },
116 { XID_P_RLP_VERSION, "RLP version number" },
117 { XID_P_IWF_TO_UE_WIN_SIZE, "IWF to UE window size" },
118 { XID_P_UE_TO_IWF_WIN_SIZE, "UE to IWF window size" },
119 { XID_P_ACK_TIMER_T1, "Acknowledgement Timer (T1)" },
120 { XID_P_RETRANS_ATTEMPTS_N2, "Retransmission attempts (N2)" },
121 { XID_P_REPLY_DELAY_T2, "Reply delay (T2)" },
122 { XID_P_COMPRESSION_PT, "Compression PT" },
123 { XID_P_RESEQUENCING_T4, "Re-sequencing timer (T4)" },
124 { XID_P_OPTIONAL_FEATURES, "Optional Features" },
125 { 0, NULL }
128 static const uint32_t rlp_fcs_table[256] = {
129 0x00B29D2D, 0x00643A5B, 0x0044D87A, 0x00927F0C, 0x00051C38, 0x00D3BB4E, 0x00F3596F, 0x0025FE19,
130 0x008694BC, 0x005033CA, 0x0070D1EB, 0x00A6769D, 0x003115A9, 0x00E7B2DF, 0x00C750FE, 0x0011F788,
131 0x00DA8E0F, 0x000C2979, 0x002CCB58, 0x00FA6C2E, 0x006D0F1A, 0x00BBA86C, 0x009B4A4D, 0x004DED3B,
132 0x00EE879E, 0x003820E8, 0x0018C2C9, 0x00CE65BF, 0x0059068B, 0x008FA1FD, 0x00AF43DC, 0x0079E4AA,
133 0x0062BB69, 0x00B41C1F, 0x0094FE3E, 0x00425948, 0x00D53A7C, 0x00039D0A, 0x00237F2B, 0x00F5D85D,
134 0x0056B2F8, 0x0080158E, 0x00A0F7AF, 0x007650D9, 0x00E133ED, 0x0037949B, 0x001776BA, 0x00C1D1CC,
135 0x000AA84B, 0x00DC0F3D, 0x00FCED1C, 0x002A4A6A, 0x00BD295E, 0x006B8E28, 0x004B6C09, 0x009DCB7F,
136 0x003EA1DA, 0x00E806AC, 0x00C8E48D, 0x001E43FB, 0x008920CF, 0x005F87B9, 0x007F6598, 0x00A9C2EE,
137 0x0049DA1E, 0x009F7D68, 0x00BF9F49, 0x0069383F, 0x00FE5B0B, 0x0028FC7D, 0x00081E5C, 0x00DEB92A,
138 0x007DD38F, 0x00AB74F9, 0x008B96D8, 0x005D31AE, 0x00CA529A, 0x001CF5EC, 0x003C17CD, 0x00EAB0BB,
139 0x0021C93C, 0x00F76E4A, 0x00D78C6B, 0x00012B1D, 0x00964829, 0x0040EF5F, 0x00600D7E, 0x00B6AA08,
140 0x0015C0AD, 0x00C367DB, 0x00E385FA, 0x0035228C, 0x00A241B8, 0x0074E6CE, 0x005404EF, 0x0082A399,
141 0x0099FC5A, 0x004F5B2C, 0x006FB90D, 0x00B91E7B, 0x002E7D4F, 0x00F8DA39, 0x00D83818, 0x000E9F6E,
142 0x00ADF5CB, 0x007B52BD, 0x005BB09C, 0x008D17EA, 0x001A74DE, 0x00CCD3A8, 0x00EC3189, 0x003A96FF,
143 0x00F1EF78, 0x0027480E, 0x0007AA2F, 0x00D10D59, 0x00466E6D, 0x0090C91B, 0x00B02B3A, 0x00668C4C,
144 0x00C5E6E9, 0x0013419F, 0x0033A3BE, 0x00E504C8, 0x007267FC, 0x00A4C08A, 0x008422AB, 0x005285DD,
145 0x001F18F0, 0x00C9BF86, 0x00E95DA7, 0x003FFAD1, 0x00A899E5, 0x007E3E93, 0x005EDCB2, 0x00887BC4,
146 0x002B1161, 0x00FDB617, 0x00DD5436, 0x000BF340, 0x009C9074, 0x004A3702, 0x006AD523, 0x00BC7255,
147 0x00770BD2, 0x00A1ACA4, 0x00814E85, 0x0057E9F3, 0x00C08AC7, 0x00162DB1, 0x0036CF90, 0x00E068E6,
148 0x00430243, 0x0095A535, 0x00B54714, 0x0063E062, 0x00F48356, 0x00222420, 0x0002C601, 0x00D46177,
149 0x00CF3EB4, 0x001999C2, 0x00397BE3, 0x00EFDC95, 0x0078BFA1, 0x00AE18D7, 0x008EFAF6, 0x00585D80,
150 0x00FB3725, 0x002D9053, 0x000D7272, 0x00DBD504, 0x004CB630, 0x009A1146, 0x00BAF367, 0x006C5411,
151 0x00A72D96, 0x00718AE0, 0x005168C1, 0x0087CFB7, 0x0010AC83, 0x00C60BF5, 0x00E6E9D4, 0x00304EA2,
152 0x00932407, 0x00458371, 0x00656150, 0x00B3C626, 0x0024A512, 0x00F20264, 0x00D2E045, 0x00044733,
153 0x00E45FC3, 0x0032F8B5, 0x00121A94, 0x00C4BDE2, 0x0053DED6, 0x008579A0, 0x00A59B81, 0x00733CF7,
154 0x00D05652, 0x0006F124, 0x00261305, 0x00F0B473, 0x0067D747, 0x00B17031, 0x00919210, 0x00473566,
155 0x008C4CE1, 0x005AEB97, 0x007A09B6, 0x00ACAEC0, 0x003BCDF4, 0x00ED6A82, 0x00CD88A3, 0x001B2FD5,
156 0x00B84570, 0x006EE206, 0x004E0027, 0x0098A751, 0x000FC465, 0x00D96313, 0x00F98132, 0x002F2644,
157 0x00347987, 0x00E2DEF1, 0x00C23CD0, 0x00149BA6, 0x0083F892, 0x00555FE4, 0x0075BDC5, 0x00A31AB3,
158 0x00007016, 0x00D6D760, 0x00F63541, 0x00209237, 0x00B7F103, 0x00615675, 0x0041B454, 0x00971322,
159 0x005C6AA5, 0x008ACDD3, 0x00AA2FF2, 0x007C8884, 0x00EBEBB0, 0x003D4CC6, 0x001DAEE7, 0x00CB0991,
160 0x00686334, 0x00BEC442, 0x009E2663, 0x00488115, 0x00DFE221, 0x00094557, 0x0029A776, 0x00FF0000
163 /*! compute RLP FCS according to 3GPP TS 24.022 Section 4.4 */
164 static uint32_t rlp_fcs_compute(const unsigned char *in, size_t in_len)
166 uint32_t divider = 0;
167 size_t i;
169 for (i = 0; i < in_len; i++) {
170 unsigned char input = in[i] ^ (divider & 0xff);
171 divider = (divider >> 8) ^ rlp_fcs_table[input];
174 return ((divider & 0xff) << 16) | (divider & 0xff00) | ((divider & 0xff0000) >> 16);
177 static int
178 dissect_gsmrlp_xid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
180 int cur;
182 for (cur = offset; cur < (int) tvb_reported_length(tvb);) {
183 uint8_t len = tvb_get_uint8(tvb, cur) & 0x0f;
184 uint8_t type = tvb_get_uint8(tvb, cur) >> 4;
185 proto_tree *xid_tree;
187 proto_tree_add_subtree_format(tree, tvb, cur, 1 + len, ett_gsmrlp_xid, &xid_tree, "XID Parameter: %s",
188 val_to_str_const(type, rlp_xid_param_vals, "Unknown"));
189 proto_tree_add_item(xid_tree, hf_gsmrlp_xid_p_type, tvb, cur, 1, ENC_BIG_ENDIAN);
190 proto_tree_add_item(xid_tree, hf_gsmrlp_xid_p_len, tvb, cur, 1, ENC_BIG_ENDIAN);
191 if (len)
192 proto_tree_add_item(xid_tree, hf_gsmrlp_xid_p_val, tvb, cur + 1, len, ENC_BIG_ENDIAN);
193 cur += 1 + len;
194 if (type == XID_P_DELIMITER)
195 break;
198 return cur - offset;
202 /* Dissect a RLP v0/v1 message as described in TS 24.022 section 5.2 */
203 static int
204 dissect_gsmrlp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
206 int reported_len = tvb_reported_length(tvb);
207 proto_tree *rlp_tree;
208 proto_item *ti;
209 uint8_t n_s, n_r;
211 /* we currently support the 16bit header of RLP v0 + v1 */
213 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM-RLP");
215 n_s = (tvb_get_uint8(tvb, 0)) >> 3 | ((tvb_get_uint8(tvb, 1) & 1) << 5);
216 n_r = (tvb_get_uint8(tvb, 1) >> 2);
218 ti = proto_tree_add_protocol_format(tree, proto_gsmrlp, tvb, 0, reported_len,
219 "GSM RLP");
220 rlp_tree = proto_item_add_subtree(ti, ett_gsmrlp);
222 proto_tree_add_item(rlp_tree, hf_gsmrlp_cr, tvb, 0, 1, ENC_BIG_ENDIAN);
223 proto_tree_add_item(rlp_tree, hf_gsmrlp_pf, tvb, 1, 1, ENC_BIG_ENDIAN);
224 if (n_s == 0x3f) { /* U frame */
225 unsigned u_ftype;
226 proto_tree_add_uint(rlp_tree, hf_gsmrlp_ftype, tvb, 0, 1, RLP_FT_U);
227 proto_tree_add_item_ret_uint(rlp_tree, hf_gsmrlp_u_ftype, tvb, 1, 1, ENC_BIG_ENDIAN, &u_ftype);
228 if ((n_r & 0x1f) == RLP_U_FT_XID)
229 dissect_gsmrlp_xid(tvb, 2, pinfo, rlp_tree);
230 proto_item_append_text(ti, " U-Frame: %s", val_to_str(u_ftype, rlp_ftype_u_vals, "Unknown 0x%02x"));
231 } else if (n_s == 0x3e) { /* S Frame */
232 unsigned s_ftype;
233 proto_tree_add_uint(rlp_tree, hf_gsmrlp_ftype, tvb, 0, 1, RLP_FT_S);
234 proto_tree_add_item_ret_uint(rlp_tree, hf_gsmrlp_s_ftype, tvb, 0, 1, ENC_BIG_ENDIAN, &s_ftype);
235 proto_tree_add_uint(rlp_tree, hf_gsmrlp_n_r, tvb, 1, 1, n_r);
236 proto_item_append_text(ti, " S-Frame: %s, N(S): %u, N(R): %u",
237 val_to_str(s_ftype, rlp_ftype_s_vals, "Unknown 0x%02x"), n_s, n_r);
238 } else { /* IS Frame */
239 tvbuff_t *next_tvb;
240 unsigned s_ftype;
241 int data_len;
243 proto_tree_add_uint(rlp_tree, hf_gsmrlp_ftype, tvb, 0, 1, RLP_FT_IS);
244 proto_tree_add_item_ret_uint(rlp_tree, hf_gsmrlp_s_ftype, tvb, 0, 1, ENC_BIG_ENDIAN, &s_ftype);
245 proto_tree_add_uint(rlp_tree, hf_gsmrlp_n_s, tvb, 0, 2, n_s);
246 proto_tree_add_uint(rlp_tree, hf_gsmrlp_n_r, tvb, 1, 1, n_r);
247 proto_item_append_text(ti, " IS-Frame: %s, N(S): %u, N(R): %u",
248 val_to_str(s_ftype, rlp_ftype_s_vals, "Unknown 0x%02x"), n_s, n_r);
250 /* dispatch user data */
251 data_len = reported_len - 2 /* header */ - 3 /* FCS */;
252 next_tvb = tvb_new_subset_length(tvb, 2, data_len);
253 if (decode_as_l2rcop && l2rcop_handle)
254 call_dissector(l2rcop_handle, next_tvb, pinfo, rlp_tree);
255 else
256 call_data_dissector(next_tvb, pinfo, rlp_tree);
259 /* FCS is always the last 3 bytes of the message */
260 tvb_ensure_bytes_exist(tvb, 0, reported_len - 3);
261 uint32_t fcs_computed = rlp_fcs_compute(tvb_get_ptr(tvb, 0, reported_len - 3), reported_len - 3);
262 proto_tree_add_checksum(rlp_tree, tvb, reported_len - 3, hf_gsmrlp_fcs, hf_gsmrlp_fcs_status,
263 &ei_gsmrlp_fcs_bad, pinfo, fcs_computed, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
265 return tvb_reported_length(tvb);
268 void
269 proto_register_gsmrlp(void)
271 static hf_register_info hf[] = {
272 { &hf_gsmrlp_cr,
273 { "C/R", "gsm_rlp.cr", FT_UINT8, BASE_DEC, NULL, 0x01,
274 "Command/Response bit", HFILL }},
275 { &hf_gsmrlp_pf,
276 { "P/F", "gsm_rlp.pf", FT_UINT8, BASE_DEC, NULL, 0x02,
277 "Poll/Final bit", HFILL }},
278 { &hf_gsmrlp_n_r,
279 { "N(R)", "gsm_rlp.n_r", FT_UINT8, BASE_DEC, NULL, 0,
280 "Receive Sequence Number", HFILL }},
281 { &hf_gsmrlp_n_s,
282 { "N(S)", "gsm_rlp.n_s", FT_UINT8, BASE_DEC, NULL, 0,
283 "Send Sequence Number", HFILL }},
284 { &hf_gsmrlp_ftype,
285 { "Frame type", "gsm_rlp.ftype", FT_UINT8, BASE_HEX,
286 VALS(rlp_ftype_vals), 0, NULL, HFILL }},
287 { &hf_gsmrlp_u_ftype,
288 { "U Frame type", "gsm_rlp.u_ftype", FT_UINT8, BASE_HEX,
289 VALS(rlp_ftype_u_vals), 0x7c, NULL, HFILL }},
290 { &hf_gsmrlp_s_ftype,
291 { "S frame type", "gsm_rlp.s_ftype", FT_UINT8, BASE_HEX,
292 VALS(rlp_ftype_s_vals), 0x06, NULL, HFILL }},
293 { &hf_gsmrlp_fcs,
294 { "Frame Check Sequence", "gsm_rlp.fcs", FT_UINT24, BASE_HEX,
295 NULL, 0, NULL, HFILL }},
296 { &hf_gsmrlp_fcs_status,
297 { "FCS Status", "gsm_rlp.fcs.status", FT_UINT8, BASE_NONE,
298 VALS(proto_checksum_vals), 0, NULL, HFILL }},
300 { &hf_gsmrlp_xid_p_type,
301 { "XID Parameter Type", "gsm_rlp.xid.param_type", FT_UINT8, BASE_HEX,
302 VALS(rlp_xid_param_vals), 0xf0, NULL, HFILL }},
303 { &hf_gsmrlp_xid_p_len,
304 { "XID Parameter Length", "gsm_rlp.xid.param_len", FT_UINT8, BASE_DEC,
305 NULL, 0x0f, NULL, HFILL }},
306 { &hf_gsmrlp_xid_p_val,
307 { "XID Parameter Value", "gsm_rlp.xid.param_value", FT_UINT8, BASE_DEC,
308 NULL, 0, NULL, HFILL }},
310 static int *ett[] = {
311 &ett_gsmrlp,
312 &ett_gsmrlp_xid,
314 static ei_register_info ei[] = {
315 { &ei_gsmrlp_fcs_bad, { "gsm_rlp.fcs_bad", PI_CHECKSUM, PI_ERROR, "Bad checksum" , EXPFILL }},
317 module_t *rlp_module;
318 expert_module_t *expert_gsmrlp;
320 proto_gsmrlp = proto_register_protocol("GSM Radio Link Protocol (RLP)", "GSM-RLP", "gsm_rlp");
321 proto_register_field_array(proto_gsmrlp, hf, array_length(hf));
322 proto_register_subtree_array(ett, array_length(ett));
323 expert_gsmrlp = expert_register_protocol(proto_gsmrlp);
324 expert_register_field_array(expert_gsmrlp, ei, array_length(ei));
326 register_dissector("gsm_rlp", dissect_gsmrlp, proto_gsmrlp);
328 rlp_module = prefs_register_protocol(proto_gsmrlp, NULL);
329 prefs_register_bool_preference(rlp_module, "decode_as_l2rcop", "Decode payload as L2RCOP",
330 NULL, &decode_as_l2rcop);
332 void
333 proto_reg_handoff_gsmrlp(void)
335 l2rcop_handle = find_dissector_add_dependency("gsm_l2rcop", proto_gsmrlp);
339 * Editor modelines - https://www.wireshark.org/tools/modelines.html
341 * Local variables:
342 * c-basic-offset: 4
343 * tab-width: 8
344 * indent-tabs-mode: nil
345 * End:
347 * vi: set shiftwidth=4 tabstop=8 expandtab:
348 * :indentSize=4:tabSize=8:noTabs=true: