Wireshark patch for SMSCB dissection support in LAPDm Create a new gsm_smscb dissector module for SMSCB as defined in GSM TS 04.12. Call it from packet-lapdm when the Link Protocol Discriminator has the value "0 1". Signed-off-by: Alex Badea --- epan/dissectors/Makefile.common | 1 + epan/dissectors/packet-gsm_smscb.c | 642 ++++++++++++++++++++++++++++++++++++ epan/dissectors/packet-lapdm.c | 18 +- 3 files changed, 658 insertions(+), 3 deletions(-) diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 9f9a602..5684579 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -500,6 +500,7 @@ DISSECTOR_SRC = \ packet-gsm_bssmap_le.c \ packet-gsm_sms.c \ packet-gsm_sms_ud.c \ + packet-gsm_smscb.c \ packet-gsm_um.c \ packet-gsmtap.c \ packet-gssapi.c \ diff --git a/epan/dissectors/packet-gsm_smscb.c b/epan/dissectors/packet-gsm_smscb.c new file mode 100644 index 0000000..a2f8bee --- /dev/null +++ b/epan/dissectors/packet-gsm_smscb.c @@ -0,0 +1,642 @@ +/* packet-gsm_smscb.c + * Routines for GSM SMSCB (GSM 04.12) dissection + * Copyright 2010, Alex Badea + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include "packet-gsm_map.h" +#include "packet-gsm_sms.h" + +static gint proto_gsm_smscb = -1; +static gint hf_smscb_addr = -1; +static gint hf_smscb_addr_lb = -1; +static gint hf_smscb_addr_seq = -1; +static gint hf_smscb_serial_gs = -1; +static gint hf_smscb_serial_mcode = -1; +static gint hf_smscb_serial_updnum = -1; +static gint hf_smscb_page_num = -1; +static gint hf_smscb_page_cnt = -1; +static gint hf_smscb_msgid = -1; +static gint hf_smscb_content = -1; +static gint hf_smscb_fragments = -1; +static gint hf_smscb_fragment = -1; +static gint hf_smscb_fragment_overlap = -1; +static gint hf_smscb_fragment_overlap_conflicts = -1; +static gint hf_smscb_fragment_multiple_tails = -1; +static gint hf_smscb_fragment_too_long_fragment = -1; +static gint hf_smscb_fragment_error = -1; +static gint hf_smscb_reassembled_in = -1; +static gint hf_smscb_reassembled_length = -1; +static gint hf_smscb_sched_type = -1; +static gint hf_smscb_sched_spare = -1; +static gint hf_smscb_sched_begin_slot = -1; +static gint hf_smscb_sched_end_slot = -1; +static gint hf_smscb_sched_mdt1 = -1; +static gint hf_smscb_sched_mdt2 = -1; +static gint hf_smscb_sched_mdt8 = -1; +static gint hf_smscb_sched_msgid = -1; +static gint hf_smscb_sched_repslot = -1; + +static gint ett_smscb = -1; +static gint ett_smscb_addr = -1; +static gint ett_smscb_dcs = -1; +static gint ett_smscb_fragment = -1; +static gint ett_smscb_fragments = -1; +static gint ett_smscb_sched_new = -1; +static gint ett_smscb_sched_other = -1; +static gint ett_smscb_sched_slot = -1; + +static GHashTable *smscb_fragment_table = NULL; +static GHashTable *smscb_reassembled_table = NULL; + +static gboolean reassemble_smscb = TRUE; + +static dissector_handle_t data_handle; + +#define SMSCB_HDR_MINLEN 1 + +/* + * Bits in the address field. + */ +#define SMSCB_ADDR_LB 0x10 /* Address Last Bit */ +#define SMSCB_ADDR_SEQ 0x0f /* Address sequence number */ +#define SMSCB_SERIAL_GS 0xc000 /* CBS Serial Number - Geographical Scope */ +#define SMSCB_SERIAL_MCODE 0x3ff0 /* CBS Serial Number - Message Code */ +#define SMSCB_SERIAL_UPDNUM 0x000f /* CBS Serial Number - Update Number */ +#define SMSCB_PAGE_NUM 0xf0 /* Page number */ +#define SMSCB_PAGE_CNT 0x0f /* Page total count */ + +/* + * Bits in the Schedule message + */ +#define SMSCB_SCHED_TYPE 0xc0 /* Type */ +#define SMSCB_SCHED_SLOT 0x3f /* Begin/End Slot Number */ +#define SMSCB_SCHED_SPARE 0xc0 /* Spare */ +#define SMSCB_SCHED_MDT1 0x8000 /* MDT (1 bit)*/ +#define SMSCB_SCHED_MSGID 0x7fff /* Message ID */ +#define SMSCB_SCHED_MDT2 0xc0 /* MDT (2 bits) */ +#define SMSCB_SCHED_REPSLOT 0x3f /* Repeated Slot Number */ + +#define SMSCB_SEQ_LAST 3 +#define SMSCB_SEQ_1ST 0 +#define SMSCB_SEQ_1ST_SCHED 8 + +#define SMSCB_SCHED_SLOT_MAX 48 + +/* 04.12 section 3.3.1 */ +static const value_string smscb_addr_lb_vals[] = { + { 0, "More blocks" }, + { 1, "Last block" }, + { 0, NULL } +}; + +/* 04.12 section 3.3.1 */ +static const value_string smscb_addr_seq_vals[] = { + { 0, "First block" }, + { 1, "Second block" }, + { 2, "Third block" }, + { 3, "Fourth block" }, + { 8, "First schedule block" }, + { 15, "Null message" }, + { 0, NULL } +}; + +/* 03.41 section 9.3.2.1 */ +static const value_string smscb_serial_gs_vals[] = { + { 0, "Cell wide (immediate)" }, + { 1, "PLMN wide" }, + { 2, "Location Area wide" }, + { 3, "Cell wide" }, + { 0, NULL } +}; + +/* 04.14 section 3.5.5 */ +static const value_string smscb_sched_mdt8_vals[] = { + { 0x00, "Retransmission indication" }, + { 0x80, "First transmission of an SMSCB within the Schedule Period" }, + { 0x40, "Free Message Slot, optional reading" }, + { 0x41, "Free Message Slot, reading advised" }, + { 0, NULL } +}; + +static const fragment_items smscb_frag_items = { + /* Fragment subtrees */ + &ett_smscb_fragment, + &ett_smscb_fragments, + /* Fragment fields */ + &hf_smscb_fragments, + &hf_smscb_fragment, + &hf_smscb_fragment_overlap, + &hf_smscb_fragment_overlap_conflicts, + &hf_smscb_fragment_multiple_tails, + &hf_smscb_fragment_too_long_fragment, + &hf_smscb_fragment_error, + /* Reassembled in field */ + &hf_smscb_reassembled_in, + /* Reassembled length field */ + &hf_smscb_reassembled_length, + /* Tag */ + "fragments" +}; + +static void smscb_defragment_init(void) +{ + fragment_table_init(&smscb_fragment_table); + reassembled_table_init(&smscb_reassembled_table); +} + +/* [3GPP TS 03.41 section 9.3] */ +static int dissect_smscb_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + gint offset = 0; + gint length, out_len, textlen; + guint8 encoding; + gchar msgbuf[88 + 1]; + gchar *utf8_text, *p; + + proto_tree_add_item(tree, hf_smscb_serial_gs, tvb, offset, 1, ENC_NA); + proto_tree_add_item(tree, hf_smscb_serial_mcode, tvb, offset, 2, ENC_NA); + offset++; + proto_tree_add_item(tree, hf_smscb_serial_updnum, tvb, offset, 1, ENC_NA); + offset++; + proto_tree_add_item(tree, hf_smscb_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + col_append_fstr(pinfo->cinfo, COL_INFO, " - Message ID %d", tvb_get_ntohs(tvb, offset)); + offset += 2; + ti = proto_tree_add_text(tree, tvb, offset, 1, "Data Coding Scheme"); + encoding = dissect_cbs_data_coding_scheme( + tvb_new_subset(tvb, offset, 1, -1), pinfo, + proto_item_add_subtree(ti, ett_smscb_dcs)); + offset++; + proto_tree_add_item(tree, hf_smscb_page_num, tvb, offset, 1, ENC_NA); + proto_tree_add_item(tree, hf_smscb_page_cnt, tvb, offset, 1, ENC_NA); + offset++; + + length = tvb_length(tvb) - offset; + switch (encoding) { + case SMS_ENCODING_7BIT: + case SMS_ENCODING_7BIT_LANG: + out_len = gsm_sms_char_7bit_unpack(0, length, sizeof(msgbuf) - 1, + tvb_get_ptr(tvb, offset, length), msgbuf); + msgbuf[out_len] = '\0'; + utf8_text = gsm_sms_chars_to_utf8(msgbuf, out_len); + textlen = strlen(utf8_text); + break; + /* TODO: UCS2? */ + case SMS_ENCODING_8BIT: + default: + utf8_text = tvb_get_ephemeral_string(tvb, offset, length); + textlen = length; + break; + } + + proto_tree_add_string(tree, hf_smscb_content, tvb, offset, length, utf8_text); + + /* strip padding */ + if ((p = strchr( utf8_text, '\r'))) + *p = 0; + col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", utf8_text); + + return tvb_length(tvb); +} + +/* [3GPP TS 04.14 section 3.5.5] */ +static int dissect_sched_msg_desc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, + gint *slot_list, gint slot_count) +{ + gint offset = 0; + gint k; + proto_item *ti; + proto_tree *subtree; + guint8 mdt; + + for (k = 0; k < slot_count; k++) { + mdt = tvb_get_guint8(tvb, offset); + + if (mdt & 0x80) + mdt = 0x80; + else if (!(mdt & 0x40)) + mdt = 0; + + ti = proto_tree_add_text(tree, tvb, offset, 1, "Slot %d - %s", + slot_list[k], + val_to_str(mdt, smscb_sched_mdt8_vals, "Unknown (0x%02x)")); + subtree = proto_item_add_subtree(ti, ett_smscb_sched_slot); + + if (mdt & 0x80) { + guint16 msgid = tvb_get_ntohs(tvb, offset) & SMSCB_SCHED_MSGID; + proto_item_append_text(ti, " (message ID %d)", msgid); + proto_item_set_len(ti, 2); + proto_tree_add_item(subtree, hf_smscb_sched_mdt1, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_smscb_sched_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + } else if (!(mdt & 0xc0)) { + guint8 slot = tvb_get_guint8(tvb, offset) & SMSCB_SCHED_SLOT; + proto_item_append_text(ti, " (slot %d)", slot); + proto_tree_add_item(subtree, hf_smscb_sched_mdt2, tvb, offset, 1, ENC_NA); + proto_tree_add_item(subtree, hf_smscb_sched_repslot, tvb, offset, 1, ENC_NA); + offset++; + } else { + proto_tree_add_item(subtree, hf_smscb_sched_mdt8, tvb, offset, 1, ENC_NA); + offset++; + } + } + return offset; +} + +/* [3GPP TS 04.14 section 3.5] */ +static int dissect_sched_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + gint offset = 0; + gint first, last, nm, len; + gint new_count = 0; + gint other_count = 0; + gint new_list[SMSCB_SCHED_SLOT_MAX]; + gint other_list[SMSCB_SCHED_SLOT_MAX]; + + col_append_str(pinfo->cinfo, COL_INFO, " - Schedule message"); + + proto_tree_add_item(tree, hf_smscb_sched_type, tvb, offset, 1, ENC_NA); + proto_tree_add_item(tree, hf_smscb_sched_begin_slot, tvb, offset, 1, ENC_NA); + offset++; + proto_tree_add_item(tree, hf_smscb_sched_spare, tvb, offset, 1, ENC_NA); + proto_tree_add_item(tree, hf_smscb_sched_end_slot, tvb, offset, 1, ENC_NA); + offset++; + + first = tvb_get_guint8(tvb, 0) & SMSCB_SCHED_SLOT; + last = tvb_get_guint8(tvb, 1) & SMSCB_SCHED_SLOT; + last = MIN(last, SMSCB_SCHED_SLOT_MAX); + + ti = proto_tree_add_text(tree, tvb, offset, 6, "List of new message slots ="); + for (nm = first; nm <= last; nm++) { + if (tvb_get_bits8(tvb, offset * 8 + nm - first, 1)) { + proto_item_append_text(ti, " %d", nm); + new_list[new_count++] = nm; + } else { + other_list[other_count++] = nm; + } + } + offset += 6; + + ti = proto_tree_add_text(tree, tvb, offset, 0, "New Message Descriptions"); + len = dissect_sched_msg_desc(tvb_new_subset(tvb, offset, -1, -1), pinfo, + proto_item_add_subtree(ti, ett_smscb_sched_new), + new_list, new_count); + offset += len; + proto_item_set_len(ti, len); + + ti = proto_tree_add_text(tree, tvb, offset, 0, "Other Message Descriptions"); + len = dissect_sched_msg_desc(tvb_new_subset(tvb, offset, -1, -1), pinfo, + proto_item_add_subtree(ti, ett_smscb_sched_other), + other_list, other_count); + offset += len; + proto_item_set_len(ti, len); + + return offset; +} + +static inline int seq_any_frags(guint8 seq) +{ + return seq <= SMSCB_SEQ_LAST || seq == SMSCB_SEQ_1ST_SCHED; +} + +static inline int seq_more_frags(guint8 seq) +{ + return seq < SMSCB_SEQ_LAST || seq == SMSCB_SEQ_1ST_SCHED; +} + +static inline int seq_first(guint8 seq) +{ + return seq == SMSCB_SEQ_1ST || seq == SMSCB_SEQ_1ST_SCHED; +} + +static inline int seq_bits(guint8 seq) +{ + return seq & 3; +} + +/* + * Do the reassembly thing. + * + * SMSCB fragmentation doesn't really fit in with the wireshark + * reassembler. There are only two valid fragment sequences: + * i) 0,1,2,3 for a SMSCB message + * ii) 8,1,2,3 for a schedule message + * + * We can't use different fragment-IDs for each content type, + * since the last 3 blocks have identical sequence numbers. + * + * We can't just mask the lower 2 bits, because when reassembly + * completes (which is on the last block, sequence #3) we won't + * know which content type we've reassembled. + * + * We also can't munge e.g. the schedule sequence to 8,9,10,11, + * since the reassembler will think we're missing the first 8 + * blocks and not do anything. + * + * Also, according to TS 03.41 section 8 we must discard + * non-consecutive sequences. + * + * So the approach here is to include the address header byte + * in the first fragment. This way after reassembly we can peek + * at it and dissect accordingly. + * + * A clean implementation would likely be to add a FD_* reassembler + * flag to special-case this behaviour. + */ +static tvbuff_t *smscb_try_reassembly(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + guint8 *seq_p, guint8 more) +{ + guint8 seq = *seq_p; + fragment_data *frag; + guint32 frag_id = 0x42; + guchar expected_seq = 0; + tvbuff_t *reassembled = NULL; + gboolean save_fragmented = pinfo->fragmented; + + if (!reassemble_smscb || !seq_any_frags(seq)) + return tvb; + + frag = fragment_get(pinfo, frag_id, smscb_fragment_table); + if (frag) { + while (frag->next) + frag = frag->next; + expected_seq = frag->offset + 1; + } + + if (seq != expected_seq) + g_free(fragment_delete(pinfo, frag_id, smscb_fragment_table)); + + if (!seq_first(seq)) + tvb = tvb_new_subset(tvb, 1, -1, -1); + + pinfo->fragmented = more; + frag = fragment_add_seq_check(tvb, 0, pinfo, frag_id, + smscb_fragment_table, + smscb_reassembled_table, seq_bits(seq), + tvb_length(tvb), + more); + + reassembled = process_reassembled_data(tvb, 0, pinfo, + "Reassembled SMSCB", frag, &smscb_frag_items, NULL, tree); + + if (frag && pinfo->fd->num == frag->reassembled_in) { + *seq_p = tvb_get_guint8(reassembled, 0) & SMSCB_ADDR_SEQ; + reassembled = tvb_new_subset(reassembled, 1, -1, -1); + } else { + col_append_str(pinfo->cinfo, COL_INFO, " (Fragment)"); + proto_tree_add_text(tree, tvb, 0, -1, "Fragment Data"); + reassembled = NULL; + } + + pinfo->fragmented = save_fragmented; + return reassembled; +} + +static int dissect_gsm_smscb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *gsm_smscb_tree = NULL; + proto_tree *subtree = NULL; + guint8 addr, seq, more; + tvbuff_t *payload; + + if (tvb_length(tvb) < SMSCB_HDR_MINLEN) + return 0; + + addr = tvb_get_guint8(tvb, 0); + seq = addr & SMSCB_ADDR_SEQ; + more = !(addr & SMSCB_ADDR_LB) && seq_more_frags(seq); + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMSCB"); + + col_clear(pinfo->cinfo, COL_INFO); + col_append_str(pinfo->cinfo, COL_INFO, + val_to_str(seq, smscb_addr_seq_vals, "Unknown block #%d")); + + if (tree) { + ti = proto_tree_add_item(tree, proto_gsm_smscb, tvb, 0, -1, ENC_NA); + gsm_smscb_tree = proto_item_add_subtree(ti, ett_smscb); + + ti = proto_tree_add_item(gsm_smscb_tree, hf_smscb_addr, tvb, 0, 1, ENC_NA); + subtree = proto_item_add_subtree(ti, ett_smscb_addr); + proto_tree_add_item(subtree, hf_smscb_addr_lb, tvb, 0, 1, ENC_NA); + proto_tree_add_item(subtree, hf_smscb_addr_seq, tvb, 0, 1, ENC_NA); + } + + payload = smscb_try_reassembly(tvb, pinfo, gsm_smscb_tree, &seq, more); + if (payload) { + switch (seq) { + case SMSCB_SEQ_1ST: + dissect_smscb_message(payload, pinfo, gsm_smscb_tree); + break; + case SMSCB_SEQ_1ST_SCHED: + dissect_sched_message(payload, pinfo, gsm_smscb_tree); + break; + } + } + + return tvb_length(tvb); +} + +static hf_register_info hf[] = { + { &hf_smscb_addr, { + "Address Field", "smscb.addr", FT_UINT8, BASE_HEX, + NULL, 0x0, + "Address", HFILL, + }}, + { &hf_smscb_addr_lb, { + "LB", "smscb.addr.lb", FT_UINT8, BASE_DEC, + VALS(smscb_addr_lb_vals), SMSCB_ADDR_LB, + "Last Block bit", HFILL, + }}, + { &hf_smscb_addr_seq, { + "SEQ", "smscb.addr.seq", FT_UINT8, BASE_DEC, + VALS(smscb_addr_seq_vals), SMSCB_ADDR_SEQ, + "Sequence Number", HFILL, + }}, + + { &hf_smscb_serial_gs, { + "Geographic Scope", "smscb.serial.gs", FT_UINT16, BASE_DEC, + VALS(smscb_serial_gs_vals), SMSCB_SERIAL_GS, NULL, HFILL, + }}, + { &hf_smscb_serial_mcode, { + "Message Code", "smscb.serial.mcode", FT_UINT16, BASE_DEC, + NULL, SMSCB_SERIAL_MCODE, NULL, HFILL, + }}, + { &hf_smscb_serial_updnum, { + "Update Number", "smscb.serial.updnum", FT_UINT16, BASE_DEC, + NULL, SMSCB_SERIAL_UPDNUM, NULL, HFILL, + }}, + + { &hf_smscb_msgid, { + "Message Identifier", "smscb.msgid", FT_UINT16, BASE_DEC, + NULL, 0, NULL, HFILL, + }}, + + { &hf_smscb_page_num, { + "Page number", "smscb.page.num", FT_UINT8, BASE_DEC, + NULL, SMSCB_PAGE_NUM, NULL, HFILL, + }}, + { &hf_smscb_page_cnt, { + "Total pages", "smscb.page.cnt", FT_UINT8, BASE_DEC, + NULL, SMSCB_PAGE_CNT, NULL, HFILL, + }}, + { &hf_smscb_content, { + "Content of Message", "smscb.content", FT_STRING, BASE_NONE, + NULL, 0x00, NULL, HFILL, + }}, + + /* Schedule message */ + { &hf_smscb_sched_type, { + "Type", "smscb.sched.type", FT_UINT8, BASE_HEX, + NULL, SMSCB_SCHED_TYPE, + "Type", HFILL, + }}, + { &hf_smscb_sched_spare, { + "Spare", "smscb.sched.spare", FT_UINT8, BASE_DEC, + NULL, SMSCB_SCHED_TYPE, + "Spare", HFILL, + }}, + { &hf_smscb_sched_begin_slot, { + "Begin slot", "smscb.sched.begin_slot", FT_UINT8, BASE_DEC, + NULL, SMSCB_SCHED_SLOT, + "Begin slot", HFILL, + }}, + { &hf_smscb_sched_end_slot, { + "End slot", "smscb.sched.end_slot", FT_UINT8, BASE_DEC, + NULL, SMSCB_SCHED_SLOT, + "End slot", HFILL, + }}, + { &hf_smscb_sched_mdt1, { + "MDT", "smscb.sched.mdt1", FT_UINT16, BASE_DEC, + NULL, SMSCB_SCHED_MDT1, + "Message Description Type", HFILL, + }}, + { &hf_smscb_sched_msgid, { + "Message ID", "smscb.sched.msg_id", FT_UINT16, BASE_DEC, + NULL, SMSCB_SCHED_MSGID, + "Message ID", HFILL, + }}, + { &hf_smscb_sched_mdt2, { + "MDT", "smscb.sched.mdt2", FT_UINT8, BASE_DEC, + NULL, SMSCB_SCHED_MDT2, + "Message Description Type", HFILL, + }}, + { &hf_smscb_sched_repslot, { + "Repeated Slot Number", "smscb.sched.repslot", FT_UINT8, BASE_DEC, + NULL, SMSCB_SCHED_REPSLOT, + "Repeated Slot Number", HFILL, + }}, + { &hf_smscb_sched_mdt8, { + "MDT", "smscb.sched.mdt8", FT_UINT8, BASE_HEX, + VALS(smscb_sched_mdt8_vals), 0x00, + "Message Description Type", HFILL, + }}, + + /* Fragment reassembly */ + { &hf_smscb_fragments, { + "Message fragments", "smscb.fragments", + FT_NONE, BASE_NONE, NULL, 0x00, + "SMSCB Message fragments", HFILL, + }}, + { &hf_smscb_fragment, { + "Message fragment", "smscb.fragment", + FT_FRAMENUM, BASE_NONE, NULL, 0x00, + "SMSCB Message fragment", HFILL, + }}, + { &hf_smscb_fragment_overlap, { + "Message fragment overlap", "smscb.fragment.overlap", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "SMSCB Message fragment overlaps with other fragment(s)", HFILL, + }}, + { &hf_smscb_fragment_overlap_conflicts, { + "Message fragment overlapping with conflicting data", "smscb.fragment.overlap.conflicts", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "SMSCB Message fragment overlaps with conflicting data", HFILL, + }}, + { &hf_smscb_fragment_multiple_tails, { + "Message has multiple tail fragments", "smscb.fragment.multiple_tails", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "SMSCB Message fragment has multiple tail fragments", HFILL, + }}, + { &hf_smscb_fragment_too_long_fragment, { + "Message fragment too long", "smscb.fragment.too_long_fragment", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "SMSCB Message fragment data goes beyond the packet end", HFILL, + }}, + { &hf_smscb_fragment_error, { + "Message defragmentation error", "smscb.fragment.error", + FT_FRAMENUM, BASE_NONE, NULL, 0x00, + "SMSCB Message defragmentation error due to illegal fragments", HFILL, + }}, + { &hf_smscb_reassembled_in, { + "Reassembled in", "smscb.reassembled.in", + FT_FRAMENUM, BASE_NONE, NULL, 0x00, + "SMSCB Message has been reassembled in this packet.", HFILL, + }}, + { &hf_smscb_reassembled_length, { + "Reassembled SMSCB length", "smscb.reassembled.length", + FT_UINT32, BASE_DEC, NULL, 0x00, + "The total length of the reassembled payload", HFILL, + }}, +}; + +static gint *ett[] = { + &ett_smscb, + &ett_smscb_addr, + &ett_smscb_dcs, + &ett_smscb_fragment, + &ett_smscb_fragments, + &ett_smscb_sched_new, + &ett_smscb_sched_other, + &ett_smscb_sched_slot, +}; + +void proto_reg_handoff_gsm_smscb(void) +{ + data_handle = find_dissector("data"); +} + +void proto_register_gsm_smscb(void) +{ + proto_gsm_smscb = proto_register_protocol( + "Short Message Service Cell Broadcast", + "SMSCB", "gsm_smscb"); + + proto_register_field_array(proto_gsm_smscb, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + new_register_dissector("gsm_smscb", dissect_gsm_smscb, proto_gsm_smscb); + register_init_routine(smscb_defragment_init); +} diff --git a/epan/dissectors/packet-lapdm.c b/epan/dissectors/packet-lapdm.c index dbeac85..add859d 100644 --- a/epan/dissectors/packet-lapdm.c +++ b/epan/dissectors/packet-lapdm.c @@ -110,6 +110,7 @@ static GHashTable *lapdm_reassembled_table = NULL; static dissector_table_t lapdm_sapi_dissector_table; static dissector_handle_t data_handle; +static dissector_handle_t smscb_handle; static gboolean reassemble_lapdm = TRUE; @@ -121,6 +122,7 @@ static gboolean reassemble_lapdm = TRUE; #define LAPDM_CR 0x02 /* Command/Response bit */ #define LAPDM_EA 0x01 /* First Address Extension bit */ #define LAPDM_LPD 0x60 /* Link Protocol Discriminator */ +#define LAPDM_LPD_CB 0x20 /* Cell Broadcast LPD */ /* * Bits in the length field. @@ -219,6 +221,7 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) tvbuff_t *payload; int available_length; gboolean is_response = FALSE; + gboolean is_cbs = FALSE; /* Check that there's enough data */ if (tvb_length(tvb) < LAPDM_HEADER_LEN) @@ -229,6 +232,7 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) addr = tvb_get_guint8(tvb, 0); length = tvb_get_guint8(tvb, 2); + is_cbs = (addr & LAPDM_LPD) == LAPDM_LPD_CB; cr = addr & LAPDM_CR; if (pinfo->p2p_dir == P2P_DIR_RECV) { is_response = cr ? FALSE : TRUE; @@ -245,15 +249,22 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) addr_tree = proto_item_add_subtree(addr_ti, ett_lapdm_address); proto_tree_add_uint(addr_tree, hf_lapdm_lpd, tvb, 0, 1, addr); - proto_tree_add_uint(addr_tree, hf_lapdm_sapi, tvb, 0, 1, addr); - proto_tree_add_uint(addr_tree, hf_lapdm_cr, tvb, 0, 1, addr); - proto_tree_add_uint(addr_tree, hf_lapdm_ea, tvb, 0, 1, addr); + if (!is_cbs) { + proto_tree_add_uint(addr_tree, hf_lapdm_sapi, tvb, 0, 1, addr); + proto_tree_add_uint(addr_tree, hf_lapdm_cr, tvb, 0, 1, addr); + proto_tree_add_uint(addr_tree, hf_lapdm_ea, tvb, 0, 1, addr); + } } else { lapdm_ti = NULL; lapdm_tree = NULL; } + if (is_cbs) { + call_dissector(smscb_handle, tvb, pinfo, tree); + return; + } + control = dissect_xdlc_control(tvb, 1, pinfo, lapdm_tree, hf_lapdm_control, ett_lapdm_control, &lapdm_cf_items, NULL /* LAPDm doesnt support extended */, NULL, NULL, is_response, FALSE, FALSE); @@ -486,5 +497,6 @@ void proto_reg_handoff_lapdm(void) { data_handle = find_dissector("data"); + smscb_handle = find_dissector("gsm_smscb"); } +