aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-lapdm.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-lapdm.c')
-rw-r--r--epan/dissectors/packet-lapdm.c130
1 files changed, 70 insertions, 60 deletions
diff --git a/epan/dissectors/packet-lapdm.c b/epan/dissectors/packet-lapdm.c
index 8c14d140b4..3aae536e89 100644
--- a/epan/dissectors/packet-lapdm.c
+++ b/epan/dissectors/packet-lapdm.c
@@ -50,50 +50,50 @@ void proto_register_lapdm(void);
static dissector_handle_t b4_info_handle;
-static int proto_lapdm = -1;
-static int hf_lapdm_address = -1;
-static int hf_lapdm_ea = -1;
-static int hf_lapdm_cr = -1;
-static int hf_lapdm_sapi = -1;
-static int hf_lapdm_lpd = -1;
-
-static int hf_lapdm_control = -1;
-static int hf_lapdm_n_r = -1;
-static int hf_lapdm_n_s = -1;
-static int hf_lapdm_p = -1;
-static int hf_lapdm_f = -1;
-static int hf_lapdm_s_ftype = -1;
-static int hf_lapdm_u_modifier_cmd = -1;
-static int hf_lapdm_u_modifier_resp = -1;
-static int hf_lapdm_ftype_i = -1;
-static int hf_lapdm_ftype_s_u = -1;
-
-static int hf_lapdm_length = -1;
-static int hf_lapdm_el = -1;
-static int hf_lapdm_m = -1;
-static int hf_lapdm_len = -1;
+static int proto_lapdm;
+static int hf_lapdm_address;
+static int hf_lapdm_ea;
+static int hf_lapdm_cr;
+static int hf_lapdm_sapi;
+static int hf_lapdm_lpd;
+
+static int hf_lapdm_control;
+static int hf_lapdm_n_r;
+static int hf_lapdm_n_s;
+static int hf_lapdm_p;
+static int hf_lapdm_f;
+static int hf_lapdm_s_ftype;
+static int hf_lapdm_u_modifier_cmd;
+static int hf_lapdm_u_modifier_resp;
+static int hf_lapdm_ftype_i;
+static int hf_lapdm_ftype_s_u;
+
+static int hf_lapdm_length;
+static int hf_lapdm_el;
+static int hf_lapdm_m;
+static int hf_lapdm_len;
/*
* LAPDm fragment handling
*/
-static int hf_lapdm_fragment_data = -1;
-static int hf_lapdm_fragments = -1;
-static int hf_lapdm_fragment = -1;
-static int hf_lapdm_fragment_overlap = -1;
-static int hf_lapdm_fragment_overlap_conflicts = -1;
-static int hf_lapdm_fragment_multiple_tails = -1;
-static int hf_lapdm_fragment_too_long_fragment = -1;
-static int hf_lapdm_fragment_error = -1;
-static int hf_lapdm_fragment_count = -1;
-static int hf_lapdm_reassembled_in = -1;
-static int hf_lapdm_reassembled_length = -1;
-
-static gint ett_lapdm = -1;
-static gint ett_lapdm_address = -1;
-static gint ett_lapdm_control = -1;
-static gint ett_lapdm_length = -1;
-static gint ett_lapdm_fragment = -1;
-static gint ett_lapdm_fragments = -1;
+static int hf_lapdm_fragment_data;
+static int hf_lapdm_fragments;
+static int hf_lapdm_fragment;
+static int hf_lapdm_fragment_overlap;
+static int hf_lapdm_fragment_overlap_conflicts;
+static int hf_lapdm_fragment_multiple_tails;
+static int hf_lapdm_fragment_too_long_fragment;
+static int hf_lapdm_fragment_error;
+static int hf_lapdm_fragment_count;
+static int hf_lapdm_reassembled_in;
+static int hf_lapdm_reassembled_length;
+
+static gint ett_lapdm;
+static gint ett_lapdm_address;
+static gint ett_lapdm_control;
+static gint ett_lapdm_length;
+static gint ett_lapdm_fragment;
+static gint ett_lapdm_fragments;
static reassembly_table lapdm_reassembly_table;
@@ -218,30 +218,35 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
int available_length;
gboolean is_response = FALSE;
enum lapdm_hdr_type hdr_type = LAPDM_HDR_FMT_B;
+ gboolean is_acch = FALSE, is_ui_frame = FALSE;
if (data) {
lapdm_data_t *ld = (lapdm_data_t *) data;
- hdr_type = ld->hdr_type;
- }
-
- switch (hdr_type) {
- case LAPDM_HDR_FMT_A:
- case LAPDM_HDR_FMT_B:
- length = tvb_get_guint8(tvb, 2);
- header_len = LAPDM_HEADER_LEN;
- break;
- case LAPDM_HDR_FMT_B4:
- length = 0;
- header_len = LAPDM_HEADER_LEN_B4;
- break;
- default:
- return 0;
+ is_acch = ld->is_acch;
}
/* Check that there's enough data */
- if (tvb_captured_length(tvb) < header_len)
+ if (tvb_captured_length(tvb) < LAPDM_HEADER_LEN_B4)
return 0;
+ control = tvb_get_guint8(tvb, 1);
+ is_ui_frame = (control & XDLC_S_U_MASK) == XDLC_U && (control & XDLC_U_MODIFIER_MASK) == XDLC_UI;
+
+ /* only downlink UI SACCH frames use B4 header format */
+ if (is_acch && is_ui_frame && pinfo->p2p_dir == P2P_DIR_RECV) {
+ hdr_type = LAPDM_HDR_FMT_B4;
+ header_len = LAPDM_HEADER_LEN_B4;
+ length = 0;
+ } else {
+ header_len = LAPDM_HEADER_LEN;
+
+ /* Check that there's enough data */
+ if (tvb_captured_length(tvb) < header_len)
+ return 0;
+
+ length = tvb_get_guint8(tvb, 2);
+ }
+
col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPDm");
addr = tvb_get_guint8(tvb, 0);
@@ -317,7 +322,7 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
pinfo->fragmented = m;
/* Rely on caller to provide a way to group fragments */
- fragment_id = (conversation_get_endpoint_by_id(pinfo, ENDPOINT_GSMTAP, USE_LAST_ENDPOINT) << 4) | (sapi << 1) | pinfo->p2p_dir;
+ fragment_id = (conversation_get_id_from_elements(pinfo, CONVERSATION_GSMTAP, USE_LAST_ENDPOINT) << 4) | (sapi << 1) | pinfo->p2p_dir;
if (!PINFO_FD_VISITED(pinfo)) {
/* Check if new N(S) is equal to previous N(S) (to avoid adding retransmissions in reassembly table)
@@ -356,6 +361,11 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
if (!dissector_try_uint(lapdm_sapi_dissector_table, sapi,
reassembled, pinfo, tree))
call_data_dissector(reassembled, pinfo, tree);
+
+ if (!PINFO_FD_VISITED(pinfo)) {
+ /* If reassembling is done, allow fragment_id reuse */
+ wmem_map_remove(lapdm_last_n_s_map, GUINT_TO_POINTER(fragment_id));
+ }
}
else {
col_append_str(pinfo->cinfo, COL_INFO, " (Fragment)");
@@ -377,7 +387,7 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
if (!PINFO_FD_VISITED(pinfo) && ((control & XDLC_S_U_MASK) == XDLC_U) && ((control & XDLC_U_MODIFIER_MASK) == XDLC_SABM)) {
/* SABM frame; reset the last N(S) to an invalid value */
- guint32 fragment_id = (conversation_get_endpoint_by_id(pinfo, ENDPOINT_GSMTAP, USE_LAST_ENDPOINT) << 4) | (sapi << 1) | pinfo->p2p_dir;
+ guint32 fragment_id = (conversation_get_id_from_elements(pinfo, CONVERSATION_GSMTAP, USE_LAST_ENDPOINT) << 4) | (sapi << 1) | pinfo->p2p_dir;
wmem_map_insert(lapdm_last_n_s_map, GUINT_TO_POINTER(fragment_id), GUINT_TO_POINTER(0));
}
@@ -430,11 +440,11 @@ proto_register_lapdm(void)
{ &hf_lapdm_p,
{ "Poll", "lapdm.control.p", FT_BOOLEAN, 8,
- TFS(&tfs_true_false), XDLC_P_F, NULL, HFILL }},
+ NULL, XDLC_P_F, NULL, HFILL }},
{ &hf_lapdm_f,
{ "Final", "lapdm.control.f", FT_BOOLEAN, 8,
- TFS(&tfs_true_false), XDLC_P_F, NULL, HFILL }},
+ NULL, XDLC_P_F, NULL, HFILL }},
{ &hf_lapdm_s_ftype,
{ "Supervisory frame type", "lapdm.control.s_ftype", FT_UINT8, BASE_HEX,