From 198149f1480b743048ad69471ce54b32fd76c434 Mon Sep 17 00:00:00 2001 From: Anders Broman Date: Fri, 5 Apr 2013 05:09:31 +0000 Subject: [PATCH] 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 --- epan/dissectors/packet-lapd.c | 88 +++++++++++++++++++++++++--------- epan/dissectors/packet-tdmoe.c | 81 ++++++++++++++++++------------- ui/gtk/voip_calls.c | 4 +- 3 files changed, 116 insertions(+), 57 deletions(-) diff --git a/epan/dissectors/packet-lapd.c b/epan/dissectors/packet-lapd.c index 8e05a03a56..23ce852aa5 100644 --- a/epan/dissectors/packet-lapd.c +++ b/epan/dissectors/packet-lapd.c @@ -47,6 +47,7 @@ #include #include #include +#include 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)) diff --git a/epan/dissectors/packet-tdmoe.c b/epan/dissectors/packet-tdmoe.c index 4c5670b31d..c473341133 100644 --- a/epan/dissectors/packet-tdmoe.c +++ b/epan/dissectors/packet-tdmoe.c @@ -29,6 +29,7 @@ #include #include +#include /* 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"); } diff --git a/ui/gtk/voip_calls.c b/ui/gtk/voip_calls.c index 073aeae775..849179ef35 100644 --- a/ui/gtk/voip_calls.c +++ b/ui/gtk/voip_calls.c @@ -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;