From Tim Ringenbach:

makes the TDMoE dissector call the LAPD bitstream dissector on the D-Channel. As a result, LAPD calls Q.931, and you can actually see call setup and tear down, instead of just a hex dump.

It adds a preference for which channel the D-Channel is.

It patches the LAPD code to fix a few bugs, not pass the checksum to Q.931 (who isn't expecting it), to register the lapd-bitstream dissector, and to mark packets with aborts or resets.

also storing more data on the lapd_byte_state_t.

https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8374

svn path=/trunk/; revision=48743
This commit is contained in:
Anders Broman 2013-04-05 05:09:31 +00:00
parent 9bd43d3c28
commit 198149f148
3 changed files with 116 additions and 57 deletions

View File

@ -47,6 +47,7 @@
#include <epan/crc16-tvb.h>
#include <epan/prefs.h>
#include <epan/lapd_sapi.h>
#include <epan/expert.h>
static int proto_lapd = -1;
static int hf_lapd_direction = -1;
@ -73,6 +74,7 @@ static int hf_lapd_ftype_s_u_ext = -1;
static int hf_lapd_checksum = -1;
static int hf_lapd_checksum_good = -1;
static int hf_lapd_checksum_bad = -1;
static int hf_lapd_abort = -1;
static gint ett_lapd = -1;
static gint ett_lapd_address = -1;
@ -148,6 +150,7 @@ static const xdlc_cf_items lapd_cf_items_ext = {
&hf_lapd_ftype_s_u_ext
};
#define MAX_LAPD_PACKET_LEN 1024
/* LAPD frame detection state */
enum lapd_bitstream_states {OUT_OF_SYNC, FLAGS, DATA};
@ -157,6 +160,8 @@ typedef struct lapd_byte_state {
char full_byte; /* part of a full byte */
char bit_offset; /* number of bits already got in the full byte */
int ones; /* number of consecutive ones since the last zero */
char data[MAX_LAPD_PACKET_LEN];
int data_len;
} lapd_byte_state_t;
typedef struct lapd_ppi {
@ -166,12 +171,15 @@ typedef struct lapd_ppi {
/* Fill values in lapd_byte_state struct */
static void
fill_lapd_byte_state(lapd_byte_state_t *ptr, enum lapd_bitstream_states state, char full_byte, char bit_offset, int ones)
fill_lapd_byte_state(lapd_byte_state_t *ptr, enum lapd_bitstream_states state, char full_byte, char bit_offset, int ones, char *data, int data_len)
{
ptr->state = state;
ptr->full_byte = full_byte;
ptr->bit_offset = bit_offset;
ptr->ones = ones;
memcpy(ptr->data, data, data_len);
ptr->data_len = data_len;
}
typedef struct lapd_convo_data {
@ -183,10 +191,11 @@ typedef struct lapd_convo_data {
lapd_byte_state_t *byte_state_b;
} lapd_convo_data_t;
#define MAX_LAPD_PACKET_LEN 1024
static void
dissect_lapd(tvbuff_t*, packet_info*, proto_tree*);
static void
dissect_lapd_full(tvbuff_t*, packet_info*, proto_tree*, gboolean);
/* got new LAPD frame byte */
static void new_byte(char full_byte, char data[], int *data_len) {
@ -198,6 +207,18 @@ static void new_byte(char full_byte, char data[], int *data_len) {
}
}
static void
lapd_log_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const char *msg)
{ proto_tree *lapd_tree;
proto_item *lapd_ti, *pi;
lapd_ti = proto_tree_add_item(tree, proto_lapd, tvb, offset, 1,
ENC_NA);
lapd_tree = proto_item_add_subtree(lapd_ti, ett_lapd);
pi = proto_tree_add_boolean(lapd_tree, hf_lapd_abort, tvb, offset, 1, TRUE);
expert_add_info_format(pinfo, pi, PI_PROTOCOL, PI_ERROR, "%s", msg);
}
static void
dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@ -217,8 +238,7 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
gboolean forward_stream = TRUE;
/* get remaining data from previous packets */
conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
conversation = find_or_create_conversation(pinfo);
lapd_ppi = (lapd_ppi_t*)p_get_proto_data(pinfo->fd, proto_lapd);
if (lapd_ppi) {
prev_byte_state = &lapd_ppi->start_byte_state;
@ -227,6 +247,8 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
full_byte = prev_byte_state->full_byte;
bit_offset = prev_byte_state->bit_offset;
ones = prev_byte_state->ones;
memcpy(data, prev_byte_state->data, prev_byte_state->data_len);
data_len = prev_byte_state->data_len;
}
} else if (conversation) {
@ -253,6 +275,9 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
full_byte = prev_byte_state->full_byte;
bit_offset = prev_byte_state->bit_offset;
ones = prev_byte_state->ones;
memcpy(data, prev_byte_state->data, prev_byte_state->data_len);
data_len = prev_byte_state->data_len;
}
}
@ -277,14 +302,23 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
new_tvb = tvb_new_child_real_data(tvb, buff, data_len, data_len);
tvb_set_free_cb(new_tvb, g_free);
add_new_data_source(pinfo, new_tvb, "Decoded LAPD bitstream");
dissect_lapd(new_tvb, pinfo, tree);
data_len = 0;
state = FLAGS;
bit_offset++;
if (full_byte != 0x7E) {
data_len = 0;
state = OUT_OF_SYNC;
lapd_log_abort(tvb, pinfo, tree, offset, "Abort! 6 ones that don't match 0x7e!");
}
dissect_lapd_full(new_tvb, pinfo, tree, TRUE);
} else if (ones >= 7) { /* frame reset or 11111111 flag byte */
data_len = 0;
state = OUT_OF_SYNC;
bit_offset++;
lapd_log_abort(tvb, pinfo, tree, offset, "Abort! 7 ones!");
} else {
bit_offset++;
}
@ -327,11 +361,7 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
if (state == DATA) { /* we are in the middle of an LAPD frame, we need more bytes */
pinfo->desegment_offset = 0;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return;
} else { /* finished processing LAPD frame(s) */
{
if (NULL == p_get_proto_data(pinfo->fd, proto_lapd)) {
/* Per packet information */
lapd_ppi = se_new(lapd_ppi_t);
@ -339,9 +369,9 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (prev_byte_state)
fill_lapd_byte_state(&lapd_ppi->start_byte_state, prev_byte_state->state,
prev_byte_state->full_byte, prev_byte_state->bit_offset,
prev_byte_state->ones);
prev_byte_state->ones, prev_byte_state->data, prev_byte_state->data_len);
else
fill_lapd_byte_state(&lapd_ppi->start_byte_state, OUT_OF_SYNC, 0x00, 0, 0);
fill_lapd_byte_state(&lapd_ppi->start_byte_state, OUT_OF_SYNC, 0x00, 0, 0, data, 0);
p_add_proto_data(pinfo->fd, proto_lapd, lapd_ppi);
@ -351,15 +381,15 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (conversation) {
if (convo_data) { /* already have lapd convo data */
if (forward_stream)
fill_lapd_byte_state(convo_data->byte_state_a, state, full_byte, bit_offset, ones);
fill_lapd_byte_state(convo_data->byte_state_a, state, full_byte, bit_offset, ones, data, data_len);
else {
if (!convo_data->byte_state_b)
convo_data->byte_state_b = se_new(lapd_byte_state_t);
fill_lapd_byte_state(convo_data->byte_state_b, state, full_byte, bit_offset, ones);
fill_lapd_byte_state(convo_data->byte_state_b, state, full_byte, bit_offset, ones, data, data_len);
}
} else { /* lapd convo data has to be created */
lapd_byte_state = se_new(lapd_byte_state_t);
fill_lapd_byte_state(lapd_byte_state, state, full_byte, bit_offset, ones);
fill_lapd_byte_state(lapd_byte_state, state, full_byte, bit_offset, ones, data, data_len);
convo_data = se_new(lapd_convo_data_t);
COPY_ADDRESS(&convo_data->addr_a, &pinfo->src);
COPY_ADDRESS(&convo_data->addr_b, &pinfo->dst);
@ -374,9 +404,14 @@ dissect_lapd_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
static void
dissect_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
dissect_lapd_full(tvb, pinfo, tree, FALSE);
}
static void
dissect_lapd_full(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean has_crc)
{
proto_tree *lapd_tree, *addr_tree, *checksum_tree;
proto_item *lapd_ti, *addr_ti, *checksum_ti;
@ -501,8 +536,7 @@ dissect_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (tree)
proto_item_set_len(lapd_ti, lapd_header_len);
if (NULL != p_get_proto_data(pinfo->fd, proto_lapd)
&& ((lapd_ppi_t*)p_get_proto_data(pinfo->fd, proto_lapd))->has_crc) {
if (has_crc) {
/* check checksum */
checksum_offset = tvb_length(tvb) - 2;
@ -518,13 +552,15 @@ dissect_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_boolean(checksum_tree, hf_lapd_checksum_good, tvb, checksum_offset, 2, TRUE);
proto_tree_add_boolean(checksum_tree, hf_lapd_checksum_bad, tvb, checksum_offset, 2, FALSE);
} else {
proto_item *pi;
checksum_ti = proto_tree_add_uint_format(lapd_tree, hf_lapd_checksum, tvb, checksum_offset, 2, 0,"Checksum: 0x%04x [incorrect, should be 0x%04x]", checksum, checksum_calculated);
checksum_tree = proto_item_add_subtree(checksum_ti, ett_lapd_checksum);
proto_tree_add_boolean(checksum_tree, hf_lapd_checksum_good, tvb, checksum_offset, 2, FALSE);
proto_tree_add_boolean(checksum_tree, hf_lapd_checksum_bad, tvb, checksum_offset, 2, TRUE);
pi = proto_tree_add_boolean(checksum_tree, hf_lapd_checksum_bad, tvb, checksum_offset, 2, TRUE);
expert_add_info_format(pinfo, pi, PI_CHECKSUM, PI_WARN, "Bad FCS");
}
next_tvb = tvb_new_subset(tvb, lapd_header_len, tvb_length_remaining(tvb,lapd_header_len) - 2, -1);
next_tvb = tvb_new_subset(tvb, lapd_header_len, tvb_length_remaining(tvb,lapd_header_len) - 2, tvb_length_remaining(tvb,lapd_header_len) - 2);
} else
next_tvb = tvb_new_subset_remaining(tvb, lapd_header_len);
@ -650,7 +686,12 @@ proto_register_lapd(void)
{ &hf_lapd_checksum_bad,
{ "Bad Checksum", "lapd.checksum_bad", FT_BOOLEAN, BASE_NONE,
NULL, 0x0, "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }}
NULL, 0x0, "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
{ &hf_lapd_abort,
{ "Abort", "lapd.abort", FT_BOOLEAN, BASE_NONE,
NULL, 0x0, "True: there is an Abort sequence, 7 ones in a row, or 6 ones in a row that aren't equal to 0x7e", HFILL }}
};
static gint *ett[] = {
@ -686,7 +727,6 @@ proto_register_lapd(void)
"RTP payload type for embedded LAPD. It must be one of the dynamic types "
"from 96 to 127. Set it to 0 to disable.",
10, &pref_lapd_rtp_payload_type);
}
void
@ -703,9 +743,11 @@ proto_reg_handoff_lapd(void)
dissector_add_uint("wtap_encap", WTAP_ENCAP_LINUX_LAPD, lapd_handle);
dissector_add_uint("wtap_encap", WTAP_ENCAP_LAPD, lapd_handle);
lapd_bitstream_handle = create_dissector_handle(dissect_lapd_bitstream, proto_lapd);
register_dissector("lapd-bitstream", dissect_lapd_bitstream, proto_lapd);
lapd_bitstream_handle = find_dissector("lapd-bitstream");
data_handle = find_dissector("data");
init = TRUE;
} else {
if ((lapd_rtp_payload_type > 95) && (lapd_rtp_payload_type < 128))

View File

@ -29,6 +29,7 @@
#include <epan/packet.h>
#include <epan/etypes.h>
#include <epan/prefs.h>
/* Bitmasks for the flags in the fourth byte of the packet */
#define TDMOE_YELLOW_ALARM_BITMASK 0x01
@ -49,8 +50,13 @@ static int hf_tdmoe_sig_bits = -1;
static gint ett_tdmoe = -1;
static gint ett_tdmoe_flags = -1;
static dissector_handle_t lapd_handle;
static dissector_handle_t data_handle;
static gint pref_tdmoe_d_channel = 24;
void proto_reg_handoff_tdmoe(void);
static int
dissect_tdmoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
@ -59,6 +65,9 @@ dissect_tdmoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U
tvbuff_t *next_client;
guint16 channels;
guint16 subaddress;
gint32 offset = 0;
static const gint *flags[] = { &hf_tdmoe_yellow_alarm, &hf_tdmoe_sig_bits_present, NULL };
int chan;
/* Check that there's enough data */
if (tvb_length(tvb) < 8)
@ -74,48 +83,49 @@ dissect_tdmoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U
(tvb_get_guint8(tvb, 3) & TDMOE_YELLOW_ALARM_BITMASK ? "[YELLOW ALARM]" : "")
);
if (tree) {
gint32 offset = 0;
static const gint *flags[] = { &hf_tdmoe_yellow_alarm, &hf_tdmoe_sig_bits_present, NULL };
/* create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_tdmoe, tvb, 0, -1, ENC_NA);
tdmoe_tree = proto_item_add_subtree(ti, ett_tdmoe);
/* create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_tdmoe, tvb, 0, -1, ENC_NA);
tdmoe_tree = proto_item_add_subtree(ti, ett_tdmoe);
/* Subaddress */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_subaddress, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
/* Subaddress */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_subaddress, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
/* Samples (1 byte) */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_samples, tvb, offset, 1, ENC_NA);
offset++;
/* Samples (1 byte) */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_samples, tvb, offset, 1, ENC_NA);
offset++;
/* Yellow alarm & "Sig bits present" bits (1 byte) */
proto_tree_add_bitmask(tdmoe_tree, tvb, offset, hf_tdmoe_flags, ett_tdmoe_flags, flags, ENC_BIG_ENDIAN);
offset++;
/* Yellow alarm & "Sig bits present" bits (1 byte) */
proto_tree_add_bitmask(tdmoe_tree, tvb, offset, hf_tdmoe_flags, ett_tdmoe_flags, flags, ENC_BIG_ENDIAN);
offset++;
/* Packet counter (2 bytes) */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_packet_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
/* Packet counter (2 bytes) */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_packet_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
/* Number of channels in packet (2 bytes) */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_channels, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
/* Number of channels in packet (2 bytes) */
proto_tree_add_item(tdmoe_tree, hf_tdmoe_channels, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
if (tvb_get_guint8(tvb, 3) & TDMOE_SIGBITS_BITMASK) {
/* 4 sigbits per channel. Might be different on other sub-protocols? */
guint16 length = (channels >> 1) + ((channels & 0x01) ? 1 : 0);
if (tvb_get_guint8(tvb, 3) & TDMOE_SIGBITS_BITMASK) {
/* 4 sigbits per channel. Might be different on other sub-protocols? */
guint16 length = (channels >> 1) + ((channels & 0x01) ? 1 : 0);
proto_tree_add_item(tdmoe_tree, hf_tdmoe_sig_bits, tvb, offset, length, ENC_NA);
offset += length;
}
/* The rest is SAMPLES * CHANNELS bytes of channel data */
next_client = tvb_new_subset_remaining(tvb, offset);
return call_dissector(data_handle, next_client, pinfo, tdmoe_tree);
proto_tree_add_item(tdmoe_tree, hf_tdmoe_sig_bits, tvb, offset, length, ENC_NA);
offset += length;
}
return tvb_reported_length(tvb);
/* The rest is SAMPLES * CHANNELS bytes of channel data */
for (chan = 1; chan <= channels; chan++) {
next_client = tvb_new_subset_length(tvb, offset + ((chan - 1) * 8), 8);
if (chan == pref_tdmoe_d_channel) {
call_dissector(lapd_handle, next_client, pinfo, tree);
} else {
call_dissector(data_handle, next_client, pinfo, tree);
}
}
return 1;
}
void
@ -152,10 +162,16 @@ proto_register_tdmoe(void)
&ett_tdmoe,
&ett_tdmoe_flags
};
module_t *tdmoe_module;
proto_tdmoe = proto_register_protocol("Digium TDMoE Protocol", "TDMoE", "tdmoe");
proto_register_field_array(proto_tdmoe, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
tdmoe_module = prefs_register_protocol(proto_tdmoe, proto_reg_handoff_tdmoe);
prefs_register_uint_preference(tdmoe_module, "d_channel",
"TDMoE D-Channel",
"The TDMoE channel that contains the D-Channel.",
10, &pref_tdmoe_d_channel);
}
void
@ -166,5 +182,6 @@ proto_reg_handoff_tdmoe(void)
tdmoe_handle = new_create_dissector_handle(dissect_tdmoe, proto_tdmoe);
dissector_add_uint("ethertype", ETHERTYPE_TDMOE, tdmoe_handle);
lapd_handle = find_dissector("lapd-bitstream");
data_handle = find_dissector("data");
}

View File

@ -1594,8 +1594,8 @@ q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
list = g_list_next (list);
}
/* add staff to ACTRACE */
} else if (actrace_frame_num == q931_frame_num) {
/* add stuff to ACTRACE */
} else {
address pstn_add;
comment = NULL;