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:
Harald Welte 2017-05-26 21:44:08 +02:00 committed by Michael Mann
parent 2023f419f4
commit 9097d1b07c
4 changed files with 102 additions and 12 deletions

View File

@ -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 \

View File

@ -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;

View File

@ -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
*/

View File

@ -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