LAPDm: Support the LAPDm B4 Frame Format
The B4 Frame Format is used on the downlink SACCH and has no length field. While the comment on top of packet-lapdm.c claimed ever since its introduction in 2009 that B4 was a supported format, in fact it was not supported yet. This patch makes handling the length field conditional to a frame format that has a length field, and introduces lapdm_data_t that can be passed using call_dissector_with_data(). The GSMTAP dissector is updated to use this mechanism to specify the frame format based on the channel type. Change-Id: I52cb1cedbc8c7baf65e70d3e050e8932573647aa Reviewed-on: https://code.wireshark.org/review/21767 Reviewed-by: Jaap Keuter <jaap.keuter@xs4all.nl> Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
parent
2023f419f4
commit
9097d1b07c
|
@ -1621,6 +1621,7 @@ DISSECTOR_INCLUDES = \
|
|||
packet-kerberos.h \
|
||||
packet-klm.h \
|
||||
packet-l2tp.h \
|
||||
packet-lapdm.h \
|
||||
packet-lbm.h \
|
||||
packet-lbtrm.h \
|
||||
packet-lbtru.h \
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <epan/packet.h>
|
||||
|
||||
#include "packet-gsmtap.h"
|
||||
#include "packet-lapdm.h"
|
||||
#include "packet-tetra.h"
|
||||
|
||||
void proto_register_gsmtap(void);
|
||||
|
@ -318,6 +319,17 @@ dissect_sacch_l1h(tvbuff_t *tvb, proto_tree *tree)
|
|||
proto_tree_add_item(l1h_tree, hf_sacch_l1h_ta, tvb, 1, 1, ENC_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_lapdm(guint8 sub_type, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
lapdm_data_t ld;
|
||||
|
||||
ld.hdr_type = LAPDM_HDR_FMT_B;
|
||||
/* only downlink SACCH frames use B4 header format */
|
||||
if (sub_type & GSMTAP_CHANNEL_ACCH && pinfo->p2p_dir == P2P_DIR_RECV)
|
||||
ld.hdr_type = LAPDM_HDR_FMT_B4;
|
||||
call_dissector_with_data(sub_handles[GSMTAP_SUB_UM_LAPDM], tvb, pinfo, tree, &ld);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_tetra(int channel _U_, tvbuff_t *payload_tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
|
||||
|
@ -489,8 +501,8 @@ dissect_gsmtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _
|
|||
case GSMTAP_CHANNEL_SDCCH8:
|
||||
case GSMTAP_CHANNEL_TCH_F:
|
||||
case GSMTAP_CHANNEL_TCH_H:
|
||||
sub_handle = GSMTAP_SUB_UM_LAPDM;
|
||||
break;
|
||||
handle_lapdm(sub_type, payload_tvb, pinfo, tree);
|
||||
return tvb_captured_length(tvb);
|
||||
case GSMTAP_CHANNEL_PACCH:
|
||||
if (pinfo->p2p_dir == P2P_DIR_SENT) {
|
||||
sub_handle = GSMTAP_SUB_UM_RLC_MAC_UL;
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "packet-lapdm.h"
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
|
@ -130,6 +131,7 @@ static gboolean reassemble_lapdm = TRUE;
|
|||
#define LAPDM_LEN_SHIFT 2
|
||||
|
||||
#define LAPDM_HEADER_LEN 3
|
||||
#define LAPDM_HEADER_LEN_B4 2
|
||||
|
||||
#define LAPDM_SAPI_RR_CC_MM 0
|
||||
#define LAPDM_SAPI_SMS 3
|
||||
|
@ -201,27 +203,57 @@ static const fragment_items lapdm_frag_items = {
|
|||
"fragments"
|
||||
};
|
||||
|
||||
static gboolean hdr_has_length(enum lapdm_hdr_type hdr_type)
|
||||
{
|
||||
switch (hdr_type) {
|
||||
case LAPDM_HDR_FMT_A:
|
||||
case LAPDM_HDR_FMT_B:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
||||
dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
|
||||
{
|
||||
proto_tree *lapdm_tree, *addr_tree, *length_tree;
|
||||
proto_item *lapdm_ti, *addr_ti, *length_ti;
|
||||
guint8 addr, length, cr, sapi, len, n_s;
|
||||
guint8 addr, length, header_len, cr, sapi, len, n_s;
|
||||
int control;
|
||||
gboolean m;
|
||||
tvbuff_t *payload;
|
||||
int available_length;
|
||||
gboolean is_response = FALSE;
|
||||
enum lapdm_hdr_type hdr_type = LAPDM_HDR_FMT_B;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check that there's enough data */
|
||||
if (tvb_captured_length(tvb) < LAPDM_HEADER_LEN)
|
||||
if (tvb_captured_length(tvb) < header_len)
|
||||
return 0;
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPDm");
|
||||
|
||||
addr = tvb_get_guint8(tvb, 0);
|
||||
length = tvb_get_guint8(tvb, 2);
|
||||
|
||||
cr = addr & LAPDM_CR;
|
||||
if (pinfo->p2p_dir == P2P_DIR_RECV) {
|
||||
|
@ -232,7 +264,7 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U
|
|||
}
|
||||
|
||||
if (tree) {
|
||||
lapdm_ti = proto_tree_add_item(tree, proto_lapdm, tvb, 0, LAPDM_HEADER_LEN, ENC_NA);
|
||||
lapdm_ti = proto_tree_add_item(tree, proto_lapdm, tvb, 0, header_len, ENC_NA);
|
||||
lapdm_tree = proto_item_add_subtree(lapdm_ti, ett_lapdm);
|
||||
|
||||
addr_ti = proto_tree_add_uint(lapdm_tree, hf_lapdm_address, tvb, 0, 1, addr);
|
||||
|
@ -252,7 +284,8 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U
|
|||
ett_lapdm_control, &lapdm_cf_items, NULL /* LAPDm doesn't support extended */, NULL, NULL,
|
||||
is_response, FALSE, FALSE);
|
||||
|
||||
if (tree) {
|
||||
/* dissect length field (if present) */
|
||||
if (tree && hdr_has_length(hdr_type)) {
|
||||
length_ti = proto_tree_add_uint(lapdm_tree, hf_lapdm_length, tvb,
|
||||
2, 1, length);
|
||||
length_tree = proto_item_add_subtree(length_ti, ett_lapdm_length);
|
||||
|
@ -262,18 +295,24 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U
|
|||
proto_tree_add_uint(length_tree, hf_lapdm_el, tvb, 2, 1, length);
|
||||
}
|
||||
|
||||
if (hdr_has_length(hdr_type)) {
|
||||
len = (length & LAPDM_LEN) >> LAPDM_LEN_SHIFT;
|
||||
m = (length & LAPDM_M) >> LAPDM_M_SHIFT;
|
||||
} else {
|
||||
len = tvb_captured_length(tvb) - header_len;
|
||||
m = 0;
|
||||
}
|
||||
|
||||
sapi = (addr & LAPDM_SAPI) >> LAPDM_SAPI_SHIFT;
|
||||
len = (length & LAPDM_LEN) >> LAPDM_LEN_SHIFT;
|
||||
n_s = (control & XDLC_N_S_MASK) >> XDLC_N_S_SHIFT;
|
||||
m = (length & LAPDM_M) >> LAPDM_M_SHIFT;
|
||||
available_length = tvb_captured_length(tvb) - LAPDM_HEADER_LEN;
|
||||
available_length = tvb_captured_length(tvb) - header_len;
|
||||
|
||||
/* No point in doing anything if no payload
|
||||
*/
|
||||
if( !MIN(len, available_length) )
|
||||
return 2;
|
||||
|
||||
payload = tvb_new_subset_length_caplen(tvb, LAPDM_HEADER_LEN, MIN(len,available_length), len);
|
||||
payload = tvb_new_subset_length_caplen(tvb, header_len, MIN(len,available_length), len);
|
||||
|
||||
/* Potentially segmented I frame
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* packet-lapdm.h
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __PACKET_BTL2CAP_H__
|
||||
#define __PACKET_BTL2CAP_H__
|
||||
|
||||
/* See GSM TS 04.06 */
|
||||
enum lapdm_hdr_type {
|
||||
LAPDM_HDR_FMT_A,
|
||||
LAPDM_HDR_FMT_B,
|
||||
LAPDM_HDR_FMT_Bter,
|
||||
LAPDM_HDR_FMT_B4,
|
||||
LAPDM_HDR_FMT_C,
|
||||
};
|
||||
|
||||
typedef struct _lapdm_data_t {
|
||||
enum lapdm_hdr_type hdr_type;
|
||||
} lapdm_data_t;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue