From f152eda1d3f15cfdfef7829265d972e7caf09315 Mon Sep 17 00:00:00 2001 From: Alex Badea Date: Sat, 27 Nov 2010 18:31:49 +0200 Subject: [PATCH] wireshark: update SMSCB dissector patch Now factored out to its own dissector module, and supporting message block reassembly. Signed-off-by: Alex Badea --- src/wireshark/smscb.patch | 681 ++++++++++++++++++++++++++------------ 1 file changed, 470 insertions(+), 211 deletions(-) diff --git a/src/wireshark/smscb.patch b/src/wireshark/smscb.patch index 4ac0952..6929c71 100644 --- a/src/wireshark/smscb.patch +++ b/src/wireshark/smscb.patch @@ -1,248 +1,507 @@ -From 8ab33ab3f2de22f83df1cd45ae9a38254dc76400 Mon Sep 17 00:00:00 2001 -From: Alex Badea -Date: Sun, 21 Nov 2010 22:19:58 +0200 -Subject: [RFC][PATCH wireshark] packet-lapdm: dissect CBS payloads +Wireshark patch for SMSCB dissection support in LAPDm -Hack dissection of Cell Broadcast Service into LAPDm. First-Block payloads -are also dissected directly. ---- - packet-lapdm.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 163 insertions(+), 1 deletion(-) +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". -diff --git a/epan/dissectors/packet-lapdm.c b/epan/dissectors/packet-lapdm.c -index dbeac85..e1d67b4 100644 ---- a/epan/dissectors/packet-lapdm.c -+++ b/epan/dissectors/packet-lapdm.c -@@ -61,12 +61,25 @@ - #include - #include - +The dissector supports reassembly of SMSCB Message blocks. Schedule +block reassmebly or dissection is not yet implemented. + +Signed-off-by: Alex Badea + + Makefile.common | 1 + packet-gsm_smscb.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + packet-lapdm.c | 18 +- + 3 files changed, 420 insertions(+), 3 deletions(-) + +diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common +index 1c1e60b..86bc856 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..12b98f9 +--- /dev/null ++++ b/epan/dissectors/packet-gsm_smscb.c +@@ -0,0 +1,404 @@ ++/* 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 ++ * ++ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED" ++ * is a dissector file; if you just copied this from README.developer, ++ * don't bother with the "Copied from" - you don't even need to put ++ * in a "Copied from" if you copied an existing dissector, especially ++ * if the bulk of the code in the new dissector is your code) ++ * ++ * 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 int proto_lapdm = -1; - static int hf_lapdm_address = -1; - static int hf_lapdm_ea = -1; - static int hf_lapdm_cr = -1; - static int hf_lapdm_sapi = -1; - static int hf_lapdm_lpd = -1; -+static int hf_lapdm_cb_lb = -1; -+static int hf_lapdm_cb_seq = -1; -+static int hf_lapdm_cbs_serial_gs = -1; -+static int hf_lapdm_cbs_serial_mcode = -1; -+static int hf_lapdm_cbs_serial_updnum = -1; -+static int hf_lapdm_cbs_msgid = -1; -+static int hf_lapdm_cbs_page_num = -1; -+static int hf_lapdm_cbs_page_cnt = -1; -+static int hf_lapdm_cbs_content = -1; - - static int hf_lapdm_control = -1; - static int hf_lapdm_n_r = -1; -@@ -103,6 +116,8 @@ static gint ett_lapdm_control = -1; - static gint ett_lapdm_length = -1; - static gint ett_lapdm_fragment = -1; - static gint ett_lapdm_fragments = -1; -+static gint ett_lapdm_cbs_serial = -1; -+static gint ett_lapdm_cbs_dcs = -1; - - static GHashTable *lapdm_fragment_table = NULL; - static GHashTable *lapdm_reassembled_table = NULL; -@@ -121,6 +136,12 @@ 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 */ -+#define LAPDM_CB_LB 0x10 /* Cell Broadcast Last Bit */ -+#define LAPDM_CB_SEQ 0x0f /* Cell Broadcast sequence number */ -+#define LAPDM_CBS_SERIAL_GS 0xc0 /* CBS Serial Number - Geographical Scope */ -+#define LAPDM_CBS_SERIAL_MCODE 0x3ffc /* CBS Serial Number - Message Code */ -+#define LAPDM_CBS_SERIAL_UPDNUM 0x03 /* CBS Serial Number - Update Number */ - - /* - * Bits in the length field. -@@ -132,6 +153,7 @@ static gboolean reassemble_lapdm = TRUE; - #define LAPDM_LEN_SHIFT 2 - - #define LAPDM_HEADER_LEN 3 -+#define LAPDM_CB_HEADER_LEN 1 - - #define LAPDM_SAPI_RR_CC_MM 0 - #define LAPDM_SAPI_SMS 3 -@@ -179,6 +201,33 @@ static const value_string lapdm_el_vals[] = { - { 0, NULL } - }; - ++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 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 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 0xc0 /* CBS Serial Number - Geographical Scope */ ++#define SMSCB_SERIAL_MCODE 0x3ffc /* CBS Serial Number - Message Code */ ++#define SMSCB_SERIAL_UPDNUM 0x03 /* CBS Serial Number - Update Number */ ++#define SMSCB_PAGE_NUM 0xf0 /* Page number */ ++#define SMSCB_PAGE_CNT 0x0f /* Page total count */ ++ ++#define SMSCB_SEQ_LAST 3 ++ +/* 04.12 section 3.3.1 */ -+static const value_string lapdm_lb_vals[] = { -+ { 0, "More blocks" }, -+ { 1, "Last block" }, -+ { 0, NULL } ++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 lapdm_seq_vals[] = { -+ { 0, "First block" }, -+ { 1, "Second block" }, -+ { 2, "Third block" }, -+ { 3, "Fourth block" }, -+ { 8, "First schedule block" }, -+ { 15, "Null message" }, -+ { 0, NULL } ++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 lapdm_serial_gs_vals[] = { -+ { 0, "Cell wide (immediate)" }, -+ { 1, "PLMN wide" }, -+ { 2, "Location Area wide" }, -+ { 3, "Cell wide" }, -+ { 0, NULL } ++static const value_string smscb_serial_gs_vals[] = { ++ { 0, "Cell wide (immediate)" }, ++ { 1, "PLMN wide" }, ++ { 2, "Location Area wide" }, ++ { 3, "Cell wide" }, ++ { 0, NULL } +}; + - - static const fragment_items lapdm_frag_items = { - /* Fragment subtrees */ -@@ -209,6 +258,79 @@ lapdm_defragment_init (void) - - - static void -+dissect_lapdm_cb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) ++ ++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) +{ -+ proto_tree *lapdm_tree, *addr_tree; -+ proto_item *lapdm_ti, *addr_ti; -+ guint8 addr, seq; -+ tvbuff_t *payload; -+ int offset; -+ int length, out_len; -+ gchar msgbuf[88]; -+ -+ addr = tvb_get_guint8(tvb, 0); -+ if (tree) { -+ lapdm_ti = proto_tree_add_item(tree, proto_lapdm, tvb, 0, LAPDM_CB_HEADER_LEN, FALSE); -+ 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); -+ 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_cb_lb, tvb, 0, 1, addr); -+ proto_tree_add_uint(addr_tree, hf_lapdm_cb_seq, tvb, 0, 1, addr); -+ } else { -+ lapdm_ti = NULL; -+ lapdm_tree = NULL; -+ } ++ fragment_table_init(&smscb_fragment_table); ++ reassembled_table_init(&smscb_reassembled_table); ++} + -+ col_append_str(pinfo->cinfo, COL_INFO, "CBS "); ++/* [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; + -+ offset = 1; ++ 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, 1, ENC_BIG_ENDIAN); ++ 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++; + -+ /* TODO: reassemble blocks 1-3 */ -+ seq = addr & LAPDM_CB_SEQ; -+ if (seq == 0) { -+ proto_item *ti; -+ proto_tree *subtree; ++ 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; ++ } + -+ ti = proto_tree_add_text(lapdm_tree, tvb, offset, 2, "Serial Number"); -+ subtree = proto_item_add_subtree(ti, ett_lapdm_cbs_serial); ++ proto_tree_add_string(tree, hf_smscb_content, tvb, offset, length, utf8_text); + -+ proto_tree_add_item(subtree, hf_lapdm_cbs_serial_gs, tvb, offset, 1, FALSE); -+ proto_tree_add_item(subtree, hf_lapdm_cbs_serial_mcode, tvb, offset, 2, FALSE); -+ offset++; -+ proto_tree_add_item(subtree, hf_lapdm_cbs_serial_updnum, tvb, offset, 1, FALSE); -+ offset++; ++ /* strip padding */ ++ if ((p = strchr( utf8_text, '\r'))) ++ *p = 0; ++ col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", utf8_text); + -+ proto_tree_add_item(lapdm_tree, hf_lapdm_cbs_msgid, tvb, offset, 2, FALSE); -+ offset += 2; ++ return tvb_length(tvb); ++} + -+ ti = proto_tree_add_text(lapdm_tree, tvb, offset, 1, "Data Coding Scheme"); -+ subtree = proto_item_add_subtree(ti, ett_lapdm_cbs_dcs); -+ dissect_cbs_data_coding_scheme(tvb_new_subset(tvb, offset, 1, -1), pinfo, subtree); -+ offset++; ++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; + -+ proto_tree_add_item(lapdm_tree, hf_lapdm_cbs_page_num, tvb, offset, 1, FALSE); -+ proto_tree_add_item(lapdm_tree, hf_lapdm_cbs_page_cnt, tvb, offset, 1, FALSE); -+ offset++; ++ if (tvb_length(tvb) < SMSCB_HDR_MINLEN) ++ return 0; + -+ length = tvb_length(tvb) - offset; -+ out_len = gsm_sms_char_7bit_unpack(0, length, sizeof(msgbuf) - 1, -+ tvb_get_ptr(tvb, offset, length), msgbuf); -+ msgbuf[out_len] = '\0'; -+ proto_tree_add_string(lapdm_tree, hf_lapdm_cbs_content, tvb, offset, length, -+ gsm_sms_chars_to_utf8(msgbuf, out_len)); ++ addr = tvb_get_guint8(tvb, 0); ++ seq = addr & SMSCB_ADDR_SEQ; ++ more = !(addr & SMSCB_ADDR_LB) && seq < SMSCB_SEQ_LAST; + -+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", gsm_sms_chars_to_utf8(msgbuf, out_len)); -+ } ++ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMSCB"); ++ ++ col_clear(pinfo->cinfo, COL_INFO); ++ col_append_fstr(pinfo->cinfo, COL_INFO, "seq=%d", seq); ++ ++ 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 = tvb_new_subset_remaining(tvb, offset); -+ call_dissector(data_handle, payload, pinfo, tree); ++ payload = tvb_new_subset(tvb, 1, -1, -1); ++ ++ if (reassemble_smscb && seq <= SMSCB_SEQ_LAST) { ++ fragment_data *frag; ++ guint32 frag_id = 0x42; ++ guchar expected_seq = 0; ++ tvbuff_t *reassembled = NULL; ++ gboolean save_fragmented = pinfo->fragmented; ++ ++ frag = fragment_get(pinfo, frag_id, smscb_fragment_table); ++ if (frag) { ++ while (frag->next) ++ frag = frag->next; ++ expected_seq = frag->offset + 1; ++ } ++ ++ /* ++ * TS 03.41 section 8 says we should discard sequences ++ * which do not consist of consecutive blocks ++ */ ++ if (seq != expected_seq) ++ g_free(fragment_delete(pinfo, frag_id, smscb_fragment_table)); ++ ++ pinfo->fragmented = more; ++ frag = fragment_add_seq_check(payload, 0, pinfo, frag_id, ++ smscb_fragment_table, ++ smscb_reassembled_table, seq, ++ tvb_length(payload), ++ more); ++ ++ reassembled = process_reassembled_data(payload, 0, pinfo, ++ "Reassembled SMSCB", frag, &smscb_frag_items, NULL, ++ gsm_smscb_tree); ++ ++ if (frag && pinfo->fd->num == frag->reassembled_in) { ++ dissect_smscb_message(reassembled, pinfo, gsm_smscb_tree); ++ } else { ++ col_append_str(pinfo->cinfo, COL_INFO, " (Fragment)"); ++ proto_tree_add_text(gsm_smscb_tree, payload, 0, -1, "Fragment Data"); ++ } ++ ++ pinfo->fragmented = save_fragmented; ++ } else if (seq == 0) { ++ dissect_smscb_message(payload, pinfo, gsm_smscb_tree); ++ } else { ++ /* TODO: reassemble & dissect Schedule messages */ ++ call_dissector(data_handle, payload, pinfo, tree); ++ } ++ ++ 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, ++ }}, + -+static void - dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) - { - proto_tree *lapdm_tree, *addr_tree, *length_tree; -@@ -227,6 +349,11 @@ dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPDm"); ++ { &hf_smscb_serial_gs, { ++ "Geographic Scope", "smscb.serial.gs", FT_UINT8, 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_UINT8, BASE_DEC, ++ NULL, SMSCB_SERIAL_MCODE, 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, ++ }}, ++ ++ /* 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, ++}; ++ ++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); -+ if ((addr & LAPDM_LPD) == LAPDM_LPD_CB) { -+ dissect_lapdm_cb(tvb, pinfo, tree); -+ return; -+ } -+ length = tvb_get_guint8(tvb, 2); ++ is_cbs = (addr & LAPDM_LPD) == LAPDM_LPD_CB; cr = addr & LAPDM_CR; -@@ -360,6 +487,39 @@ proto_register_lapdm(void) - { "SAPI", "lapdm.sapi", FT_UINT8, BASE_DEC, VALS(lapdm_sapi_vals), LAPDM_SAPI, - "Service access point identifier", HFILL }}, + 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); -+ { &hf_lapdm_cb_lb, -+ { "LB", "lapdm.cb.lb", FT_UINT8, BASE_DEC, -+ VALS(lapdm_lb_vals), LAPDM_CB_LB, "Last Block bit", HFILL }}, -+ -+ { &hf_lapdm_cb_seq, -+ { "SEQ", "lapdm.cb.seq", FT_UINT8, BASE_DEC, -+ VALS(lapdm_seq_vals), LAPDM_CB_SEQ, "Sequence Number", HFILL }}, -+ -+ { &hf_lapdm_cbs_serial_gs, -+ { "GS", "lapdm.cbs.serial.gs", FT_UINT8, BASE_DEC, -+ VALS(lapdm_serial_gs_vals), LAPDM_CBS_SERIAL_GS, "Geographic Scope", HFILL }}, -+ { &hf_lapdm_cbs_serial_mcode, -+ { "Message Code", "lapdm.cbs.serial.mcode", FT_UINT16, BASE_DEC, -+ NULL, LAPDM_CBS_SERIAL_MCODE, NULL, HFILL }}, -+ { &hf_lapdm_cbs_serial_updnum, -+ { "Update Number", "lapdm.cbs.serial.updnum", FT_UINT8, BASE_DEC, -+ NULL, LAPDM_CBS_SERIAL_MCODE, NULL, HFILL }}, -+ -+ { &hf_lapdm_cbs_msgid, -+ { "Message Identifier", "lapdm.cbs.msgid", FT_UINT16, BASE_DEC, -+ NULL, 0, NULL, HFILL }}, -+ -+ { &hf_lapdm_cbs_page_num, -+ { "Page number", "lapdm.cbs.page.num", FT_UINT8, BASE_DEC, -+ NULL, 0xf0, NULL, HFILL }}, -+ { &hf_lapdm_cbs_page_cnt, -+ { "Total pages", "lapdm.cbs.page.cnt", FT_UINT8, BASE_DEC, -+ NULL, 0x0f, NULL, HFILL }}, -+ -+ { &hf_lapdm_cbs_content, -+ { "Content of Message", "lapdm.cbs.content", FT_STRING, BASE_NONE, -+ NULL, 0x00, NULL, HFILL }}, -+ - { &hf_lapdm_control, - { "Control Field", "lapdm.control_field", FT_UINT8, BASE_HEX, NULL, 0x0, - NULL, HFILL }}, -@@ -461,7 +621,9 @@ proto_register_lapdm(void) - &ett_lapdm_control, - &ett_lapdm_length, - &ett_lapdm_fragment, -- &ett_lapdm_fragments -+ &ett_lapdm_fragments, -+ &ett_lapdm_cbs_serial, -+ &ett_lapdm_cbs_dcs, - }; + 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"); + } - module_t *lapdm_module; -- 2.20.1