diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/CMakeLists.txt | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-gsm_l2rcop.c | 167 | ||||
-rw-r--r-- | epan/dissectors/packet-gsm_rlp.c | 17 |
3 files changed, 184 insertions, 1 deletions
diff --git a/epan/dissectors/CMakeLists.txt b/epan/dissectors/CMakeLists.txt index 810563546b..55d7c043f5 100644 --- a/epan/dissectors/CMakeLists.txt +++ b/epan/dissectors/CMakeLists.txt @@ -1191,6 +1191,7 @@ set(DISSECTOR_SRC ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_cbsp.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_gsup.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_ipa.c + ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_l2rcop.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_osmux.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_r_uus1.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_rlcmac.c diff --git a/epan/dissectors/packet-gsm_l2rcop.c b/epan/dissectors/packet-gsm_l2rcop.c new file mode 100644 index 0000000000..b9c6fcce3b --- /dev/null +++ b/epan/dissectors/packet-gsm_l2rcop.c @@ -0,0 +1,167 @@ +/* packet-gsm_l2rcop.c + * Routines for GSM L2RCOP (3GPP TS 27.002) dissection + * (C) 2023 Harald Welte <laforge@osmocom.org> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/xdlc.h> +#include <epan/reassemble.h> +#include <epan/conversation.h> + +void proto_register_gsm_l2rcop(void); + +static int proto_l2rcop = -1; + +static int hf_l2rcop_sa = -1; +static int hf_l2rcop_sb = -1; +static int hf_l2rcop_x = -1; +static int hf_l2rcop_addr = -1; +static int hf_l2rcop_break = -1; +static int hf_l2rcop_break_ack = -1; + +static int ett_l2rcop = -1; + +static const value_string addr_vals[] = { + { 31, "last status change, remainder empty" }, + { 30, "last status change, remainder full of characters" }, + { 29, "destructive break signal, remainder empty" }, + { 28, "destructive break acknowledge, remainder empty" }, + { 27, "extended address in ext octet" }, + { 0, NULL } +}; + +static void +add_characters(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint len) +{ + tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, len); + call_data_dissector(next_tvb, pinfo, tree); +} + +/* Dissect a L2RCOP message as described in 3GPP TS 27.002 */ +static int +dissect_l2rcop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int reported_len = tvb_reported_length(tvb); + guint cur; + + /* we currently support RLP v0 + v1 (first octet is always status octet) */ + + for (cur = 0; cur < (guint)reported_len; ) { + guint8 oct = tvb_get_guint8(tvb, cur); + guint8 addr = oct & 0x1f; + proto_tree *l2rcop_tree; + proto_item *ti; + const gchar *addr_str = val_to_str(addr, addr_vals, "%u characters"); + + ti = proto_tree_add_protocol_format(tree, proto_l2rcop, tvb, 0, reported_len, + "GSM L2RCOP Chunk Status=0x%02x (Addr: %s)", oct, addr_str); + l2rcop_tree = proto_item_add_subtree(ti, ett_l2rcop); + + proto_tree_add_item(l2rcop_tree, hf_l2rcop_sa, tvb, cur, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(l2rcop_tree, hf_l2rcop_sb, tvb, cur, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(l2rcop_tree, hf_l2rcop_x, tvb, cur, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(l2rcop_tree, hf_l2rcop_addr, tvb, cur, 1, ENC_BIG_ENDIAN); + + switch (addr) { + case 31: /* last status change, remainder empty */ + return reported_len; + case 30: /* last status change, remainder full of characters */ + add_characters(l2rcop_tree, pinfo, tvb, cur+1, reported_len-cur-1); + return reported_len; + case 29: /* destructive break signal, remainder empty */ + proto_tree_add_item(l2rcop_tree, hf_l2rcop_break, tvb, cur, 1, ENC_BIG_ENDIAN); + return reported_len; + case 28: /* destructive break acknowledge, remainder empty */ + proto_tree_add_item(l2rcop_tree, hf_l2rcop_break_ack, tvb, cur, 1, ENC_BIG_ENDIAN); + return reported_len; + case 27: /* extended address in ext octet */ + cur++; + addr = tvb_get_guint8(tvb, cur) & 0x3f; + /* This "cannot happen"; let's abort processing right now. */ + if (addr == 0) + return reported_len; + proto_tree_add_uint(l2rcop_tree, hf_l2rcop_addr, tvb, cur, 1, addr); + add_characters(l2rcop_tree, pinfo, tvb, cur+1, addr); + cur += 1 + addr; + break; + case 0: + /* This "cannot happen"; let's abort processing right now. */ + return reported_len; + default: + /* This "cannot happen"; let's abort processing right now. */ + if (addr == 0) + return reported_len; + add_characters(l2rcop_tree, pinfo, tvb, cur+1, addr); + cur += 1 + addr; + break; + } + } + + return reported_len; +} + +static const true_false_string x_vals = { + "flow control ACTIVE", "flow control inactive" +}; + +static const true_false_string sab_vals = { + "OFF", "ON" +}; + + +void +proto_register_gsm_l2rcop(void) +{ + static hf_register_info hf[] = { + { &hf_l2rcop_sa, + { "SA", "gsm_l2rcop.sa", FT_BOOLEAN, 8, TFS(&sab_vals), 0x80, + NULL, HFILL }}, + { &hf_l2rcop_sb, + { "SB", "gsm_l2rcop.sb", FT_BOOLEAN, 8, TFS(&sab_vals), 0x40, + NULL, HFILL }}, + { &hf_l2rcop_x, + { "X", "gsm_l2rcop.x", FT_BOOLEAN, 8, TFS(&x_vals), 0x20, + NULL, HFILL }}, + { &hf_l2rcop_addr, + { "Address", "gsm_l2rcop.addr", FT_UINT8, BASE_DEC|BASE_SPECIAL_VALS, VALS(addr_vals), 0x1f, + NULL, HFILL }}, + { &hf_l2rcop_break, + { "Break", "gsm_l2rcop.break", FT_UINT8, BASE_DEC, NULL, 0x00, + NULL, HFILL }}, + { &hf_l2rcop_break_ack, + { "Break Ack", "gsm_l2rcop.break_ack", FT_UINT8, BASE_DEC, NULL, 0x00, + NULL, HFILL }}, + }; + static gint *ett[] = { + &ett_l2rcop, + }; + + proto_l2rcop = proto_register_protocol("GSM L2R Character Oriented Protocol (L2RCOP)", "GSM-L2RCOP", + "gsm_l2rcop"); + proto_register_field_array(proto_l2rcop, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + register_dissector("gsm_l2rcop", dissect_l2rcop, proto_l2rcop); +} + + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/epan/dissectors/packet-gsm_rlp.c b/epan/dissectors/packet-gsm_rlp.c index f4c9a4f3ed..2f0fd7b9ce 100644 --- a/epan/dissectors/packet-gsm_rlp.c +++ b/epan/dissectors/packet-gsm_rlp.c @@ -40,6 +40,9 @@ static int ett_gsmrlp_xid = -1; static expert_field ei_gsmrlp_fcs_bad = EI_INIT; +static dissector_handle_t l2rcop_handle; +static gboolean decode_as_l2rcop = true; + /* 3GPP TS 24.002 Section 5.2.1 */ enum rlp_ftype { RLP_FT_U, @@ -247,7 +250,10 @@ dissect_gsmrlp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _ /* dispatch user data */ data_len = reported_len - 2 /* header */ - 3 /* FCS */; next_tvb = tvb_new_subset_length(tvb, 2, data_len); - call_data_dissector(next_tvb, pinfo, rlp_tree); + if (decode_as_l2rcop && l2rcop_handle) + call_dissector(l2rcop_handle, next_tvb, pinfo, rlp_tree); + else + call_data_dissector(next_tvb, pinfo, rlp_tree); } /* FCS is always the last 3 bytes of the message */ @@ -317,6 +323,15 @@ proto_register_gsmrlp(void) expert_register_field_array(expert_gsmrlp, ei, array_length(ei)); register_dissector("gsm_rlp", dissect_gsmrlp, proto_gsmrlp); + + rlp_module = prefs_register_protocol(proto_gsmrlp, NULL); + prefs_register_bool_preference(rlp_module, "decode_as_l2rcop", "Decode payload as L2RCOP", + NULL, &decode_as_l2rcop); +} +void +proto_reg_handoff_gsmrlp(void) +{ + l2rcop_handle = find_dissector_add_dependency("gsm_l2rcop", proto_gsmrlp); } /* |