Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gsm_l2rcop.c
blob7f2a752d267481cb671a0978abbd972f96a0698c
1 /* packet-gsm_l2rcop.c
2 * Routines for GSM L2RCOP (3GPP TS 27.002) 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/tfs.h>
17 void proto_register_gsm_l2rcop(void);
19 static int proto_l2rcop;
21 static int hf_l2rcop_sa;
22 static int hf_l2rcop_sb;
23 static int hf_l2rcop_x;
24 static int hf_l2rcop_addr;
25 static int hf_l2rcop_break;
26 static int hf_l2rcop_break_ack;
28 static int ett_l2rcop;
30 static const value_string addr_vals[] = {
31 { 31, "last status change, remainder empty" },
32 { 30, "last status change, remainder full of characters" },
33 { 29, "destructive break signal, remainder empty" },
34 { 28, "destructive break acknowledge, remainder empty" },
35 { 27, "extended address in ext octet" },
36 { 0, NULL }
39 static void
40 add_characters(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset, unsigned len)
42 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, len);
43 call_data_dissector(next_tvb, pinfo, tree);
46 /* Dissect a L2RCOP message as described in 3GPP TS 27.002 */
47 static int
48 dissect_l2rcop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
50 int reported_len = tvb_reported_length(tvb);
51 unsigned cur;
53 /* we currently support RLP v0 + v1 (first octet is always status octet) */
55 for (cur = 0; cur < (unsigned)reported_len; ) {
56 uint8_t oct = tvb_get_uint8(tvb, cur);
57 uint8_t addr = oct & 0x1f;
58 proto_tree *l2rcop_tree;
59 proto_item *ti;
60 const char *addr_str = val_to_str(addr, addr_vals, "%u characters");
62 ti = proto_tree_add_protocol_format(tree, proto_l2rcop, tvb, 0, reported_len,
63 "GSM L2RCOP Chunk Status=0x%02x (Addr: %s)", oct, addr_str);
64 l2rcop_tree = proto_item_add_subtree(ti, ett_l2rcop);
66 proto_tree_add_item(l2rcop_tree, hf_l2rcop_sa, tvb, cur, 1, ENC_BIG_ENDIAN);
67 proto_tree_add_item(l2rcop_tree, hf_l2rcop_sb, tvb, cur, 1, ENC_BIG_ENDIAN);
68 proto_tree_add_item(l2rcop_tree, hf_l2rcop_x, tvb, cur, 1, ENC_BIG_ENDIAN);
69 proto_tree_add_item(l2rcop_tree, hf_l2rcop_addr, tvb, cur, 1, ENC_BIG_ENDIAN);
71 switch (addr) {
72 case 31: /* last status change, remainder empty */
73 return reported_len;
74 case 30: /* last status change, remainder full of characters */
75 add_characters(l2rcop_tree, pinfo, tvb, cur+1, reported_len-cur-1);
76 return reported_len;
77 case 29: /* destructive break signal, remainder empty */
78 proto_tree_add_item(l2rcop_tree, hf_l2rcop_break, tvb, cur, 1, ENC_BIG_ENDIAN);
79 return reported_len;
80 case 28: /* destructive break acknowledge, remainder empty */
81 proto_tree_add_item(l2rcop_tree, hf_l2rcop_break_ack, tvb, cur, 1, ENC_BIG_ENDIAN);
82 return reported_len;
83 case 27: /* extended address in ext octet */
84 cur++;
85 addr = tvb_get_uint8(tvb, cur) & 0x3f;
86 /* This "cannot happen"; let's abort processing right now. */
87 if (addr == 0)
88 return reported_len;
89 proto_tree_add_uint(l2rcop_tree, hf_l2rcop_addr, tvb, cur, 1, addr);
90 add_characters(l2rcop_tree, pinfo, tvb, cur+1, addr);
91 cur += 1 + addr;
92 break;
93 case 0:
94 /* This "cannot happen"; let's abort processing right now. */
95 return reported_len;
96 default:
97 /* This "cannot happen"; let's abort processing right now. */
98 if (addr == 0)
99 return reported_len;
100 add_characters(l2rcop_tree, pinfo, tvb, cur+1, addr);
101 cur += 1 + addr;
102 break;
106 return reported_len;
109 static const true_false_string x_vals = {
110 "flow control ACTIVE", "flow control inactive"
114 void
115 proto_register_gsm_l2rcop(void)
117 static hf_register_info hf[] = {
118 { &hf_l2rcop_sa,
119 { "SA", "gsm_l2rcop.sa", FT_BOOLEAN, 8, TFS(&tfs_off_on), 0x80,
120 NULL, HFILL }},
121 { &hf_l2rcop_sb,
122 { "SB", "gsm_l2rcop.sb", FT_BOOLEAN, 8, TFS(&tfs_off_on), 0x40,
123 NULL, HFILL }},
124 { &hf_l2rcop_x,
125 { "X", "gsm_l2rcop.x", FT_BOOLEAN, 8, TFS(&x_vals), 0x20,
126 NULL, HFILL }},
127 { &hf_l2rcop_addr,
128 { "Address", "gsm_l2rcop.addr", FT_UINT8, BASE_DEC|BASE_SPECIAL_VALS, VALS(addr_vals), 0x1f,
129 NULL, HFILL }},
130 { &hf_l2rcop_break,
131 { "Break", "gsm_l2rcop.break", FT_UINT8, BASE_DEC, NULL, 0x00,
132 NULL, HFILL }},
133 { &hf_l2rcop_break_ack,
134 { "Break Ack", "gsm_l2rcop.break_ack", FT_UINT8, BASE_DEC, NULL, 0x00,
135 NULL, HFILL }},
137 static int *ett[] = {
138 &ett_l2rcop,
141 proto_l2rcop = proto_register_protocol("GSM L2R Character Oriented Protocol (L2RCOP)", "GSM-L2RCOP",
142 "gsm_l2rcop");
143 proto_register_field_array(proto_l2rcop, hf, array_length(hf));
144 proto_register_subtree_array(ett, array_length(ett));
145 register_dissector("gsm_l2rcop", dissect_l2rcop, proto_l2rcop);
150 * Editor modelines - https://www.wireshark.org/tools/modelines.html
152 * Local variables:
153 * c-basic-offset: 4
154 * tab-width: 8
155 * indent-tabs-mode: nil
156 * End:
158 * vi: set shiftwidth=4 tabstop=8 expandtab:
159 * :indentSize=4:tabSize=8:noTabs=true: