diff options
Diffstat (limited to 'epan/dissectors/packet-lapdm.c')
-rw-r--r-- | epan/dissectors/packet-lapdm.c | 130 |
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, |