From Mike Morrin:
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 26 Jan 2012 19:51:48 +0000 (19:51 +0000)
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 26 Jan 2012 19:51:48 +0000 (19:51 +0000)
Add dissectors for GSM and UMTS Cell Broadcast protocols.
( - the patch for gsmtap )

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

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@40735 f5534014-38df-0310-8fa8-9805f1628bb7

15 files changed:
asn1/gsm_map/gsm_map.cnf
asn1/gsm_map/packet-gsm_map-template.c
asn1/gsm_map/packet-gsm_map-template.h
asn1/sabp/packet-sabp-template.c
asn1/sabp/sabp.cnf
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-bmc.c
epan/dissectors/packet-cell_broadcast.c [new file with mode: 0644]
epan/dissectors/packet-cell_broadcast.h [new file with mode: 0644]
epan/dissectors/packet-gsm_cbch.c [new file with mode: 0644]
epan/dissectors/packet-gsm_map.c
epan/dissectors/packet-gsm_map.h
epan/dissectors/packet-rsl.c
epan/dissectors/packet-sabp.c

index c8e3629cdb07b65870988392632e7513bf08ce7b..dbff6fe57267317223510912d726099d7692fe03 100644 (file)
@@ -1,5 +1,5 @@
 
-#.OPT
+#.OPT 
 -b
 #-d satcom
 #-s packet-gsm_map-tmp
@@ -436,7 +436,7 @@ actx->pinfo->p2p_dir = P2P_DIR_RECV;
   if (!parameter_tvb)
      return offset;
   subtree = proto_item_add_subtree(actx->created_item, ett_gsm_map_cbs_data_coding);
-  dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree);
+  dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree, 0);
 
 #.FN_BODY USSD-String VAL_PTR = &parameter_tvb
 
index 2ae8f3b45d082bbbd2501cabe2560d2c177e52c7..a04a17987b343ad8cacbfa668b2db57e9f5f2e2a 100644 (file)
@@ -604,24 +604,24 @@ static const value_string gsm_map_cbs_coding_grp15_class_vals[] = {
 
 /* 3GPP TS 23.038 version 7.0.0 Release 7 */
 guint8
-dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint16 offset)
 {
        guint8 octet;
        guint8 coding_grp;
        guint8 character_set;
 
-       octet = tvb_get_guint8(tvb,0);
+       octet = tvb_get_guint8(tvb,offset);
        coding_grp = octet >>4;
-       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp, tvb, 0, 1, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp, tvb, offset, 1, ENC_BIG_ENDIAN);
 
        sms_encoding = SMS_ENCODING_NOT_SET;
        switch (coding_grp){
        case 0:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp0_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp0_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                sms_encoding = SMS_ENCODING_7BIT;
                break;
        case 1:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp1_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp1_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                if ((octet & 0x0f)== 0){
                        sms_encoding = SMS_ENCODING_7BIT_LANG;
                }else{
@@ -629,11 +629,11 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                }
                break;
        case 2:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp2_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp2_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                sms_encoding = SMS_ENCODING_7BIT;
                break;
        case 3:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp3_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp3_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                sms_encoding = SMS_ENCODING_7BIT;
                break;
                /* Coding_grp 01xx */
@@ -645,11 +645,11 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                  /* FALLTHRU */
        case 7:
                  /* FALLTHRU */
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_comp, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class_ind, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_comp, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, offset, 1, ENC_BIG_ENDIAN);
                if ((octet & 0x10)== 0x10){
-                       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, 0, 1, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, offset, 1, ENC_BIG_ENDIAN);
                }
                /* Bits 3 and 2 indicate the character set being used, */
                character_set = (octet&0x0c)>>2;
@@ -679,8 +679,8 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                break;
        case 9:
                /* Message with User Data Header (UDH) structure:*/
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, offset, 1, ENC_BIG_ENDIAN);
                character_set = (octet&0x0c)>>2;
                switch (character_set){
                case 0:
@@ -720,8 +720,8 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                break;
        case 15:
                /* Data coding / message handling */
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_mess_code, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_class, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_mess_code, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_class, tvb, offset, 1, ENC_BIG_ENDIAN);
                character_set = (octet&0x04)>>2;
                if (character_set == 0){
                        sms_encoding = SMS_ENCODING_7BIT;
index 6f167adeb8d3fdd4eae12cc4ace1b62efb1a670e..a57ce8f3f9fdb7cf57a1365f28194448bfdaabb9 100644 (file)
@@ -51,7 +51,7 @@ extern const value_string gsm_map_PDP_Type_Organisation_vals[];
 extern const value_string gsm_map_ietf_defined_pdp_vals[];
 extern const value_string gsm_map_etsi_defined_pdp_vals[];
 
-guint8 dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree);
+guint8 dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint16 offset);
 void dissect_gsm_map_msisdn(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree);
 
 #include "packet-gsm_map-exp.h"
index 7c735114fa3b6cc8f8735b274a4b203748581bcf..b8fb84e7625c88dccf4de374cab01bdd8975c16a 100644 (file)
@@ -40,6 +40,7 @@
 #include "packet-gsm_map.h"
 #include "packet-gsm_sms.h"
 #include <epan/sctpppids.h>
+#include "packet-cell_broadcast.h"
 
 #define PNAME  "UTRAN IuBC interface SABP signaling"
 #define PSNAME "SABP"
@@ -58,6 +59,8 @@ static int ett_sabp = -1;
 static int ett_sabp_e212 = -1;
 static int ett_sabp_cbs_data_coding = -1;
 static int ett_sabp_bcast_msg = -1;
+static int ett_sabp_cbs_serial_number = -1;
+static int ett_sabp_cbs_new_serial_number = -1;
 
 #include "packet-sabp-ett.c"
 
@@ -182,6 +185,8 @@ void proto_register_sabp(void) {
                  &ett_sabp_e212,
                  &ett_sabp_cbs_data_coding,
                  &ett_sabp_bcast_msg,
+          &ett_sabp_cbs_serial_number,
+          &ett_sabp_cbs_new_serial_number,
 #include "packet-sabp-ettarr.c"
   };
 
index cb6a2d64dba2e15d732ab5e48929889d2c34b51c..c3f3738cc7b240db8118b2770cc81756fdd70300 100644 (file)
@@ -178,6 +178,40 @@ Error-Indication                       N sabp.proc.imsg id-Error-Indication
        if (!parameter_tvb)
                return offset;
        subtree = proto_item_add_subtree(actx->created_item, ett_sabp_cbs_data_coding);
-       sms_encoding = dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree);
+       sms_encoding = dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree, 0);
 
+#.FN_BODY Message-Identifier VAL_PTR = &parameter_tvb
+ tvbuff_t *parameter_tvb=NULL;
+
+%(DEFAULT_BODY)s
+       if (!parameter_tvb)
+               return offset;
+        dissect_cbs_message_identifier(parameter_tvb, tree, 0);
+
+#.FN_BODY Serial-Number VAL_PTR = &parameter_tvb
+ tvbuff_t *parameter_tvb=NULL;
+ proto_tree *subtree;
+
+%(DEFAULT_BODY)s
+       if (!parameter_tvb)
+               return offset;
+       subtree = proto_item_add_subtree(actx->created_item, ett_sabp_cbs_serial_number);
+        dissect_cbs_serial_number(parameter_tvb, subtree, 0);
 
+#.FN_BODY New-Serial-Number VAL_PTR = &parameter_tvb
+ tvbuff_t *parameter_tvb=NULL;
+ proto_tree *subtree;
+
+%(DEFAULT_BODY)s
+       if (!parameter_tvb)
+               return offset;
+       subtree = proto_item_add_subtree(actx->created_item, ett_sabp_cbs_new_serial_number);
+        dissect_cbs_serial_number(parameter_tvb, subtree, 0);
+
+#.FN_BODY Broadcast-Message-Content VAL_PTR = &parameter_tvb
+ tvbuff_t *parameter_tvb=NULL;
+
+%(DEFAULT_BODY)s
+       if (!parameter_tvb)
+               return offset;
+        dissect_umts_cell_broadcast_message(parameter_tvb, actx->pinfo, proto_tree_get_root(tree));
index cae7cb84fb9bd3a1312f509390b876b800062fc4..364abc28951b69827ff6e2dc006020f7b2d735c5 100644 (file)
@@ -397,6 +397,7 @@ set(DISSECTOR_SRC
        dissectors/packet-catapult-dct2000.c
        dissectors/packet-ccsds.c
        dissectors/packet-cdp.c
+       dissectors/packet-cell_broadcast.c
        dissectors/packet-cfm.c
        dissectors/packet-cgmp.c
        dissectors/packet-chdlc.c
@@ -608,8 +609,9 @@ set(DISSECTOR_SRC
        dissectors/packet-gsm_a_rr.c
        dissectors/packet-gsm_bsslap.c
        dissectors/packet-gsm_bssmap_le.c
-       dissectors/packet-gsm_rlcmac.c
+       dissectors/packet-gsm_cbch.c
        dissectors/packet-gsm_ipa.c
+       dissectors/packet-gsm_rlcmac.c
        dissectors/packet-gsm_sms.c
        dissectors/packet-gsm_sms_ud.c
        dissectors/packet-gsm_um.c
index f4f4d0249ea54d327a3f2df356172badb7f6d46d..1924075981dd7d1bac92b49c5e7b578f175c9c96 100644 (file)
@@ -315,6 +315,7 @@ DISSECTOR_SRC = \
        packet-catapult-dct2000.c \
        packet-ccsds.c          \
        packet-cdp.c            \
+       packet-cell_broadcast.c \
        packet-cfm.c            \
        packet-cgmp.c           \
        packet-chdlc.c          \
@@ -526,6 +527,7 @@ DISSECTOR_SRC = \
        packet-gsm_a_rr.c       \
        packet-gsm_bsslap.c     \
        packet-gsm_bssmap_le.c  \
+       packet-gsm_cbch.c       \
        packet-gsm_ipa.c        \
        packet-gsm_rlcmac.c     \
        packet-gsm_sms.c        \
@@ -1116,6 +1118,7 @@ DISSECTOR_INCLUDES =      \
        packet-c1222.h  \
        packet-camel.h  \
        packet-cdt.h    \
+       packet-cell_broadcast.h \
        packet-charging_ase.h   \
        packet-chdlc.h  \
        packet-cimd.h   \
index bcc704abe3609d9b1ce64fd68765761b554c1d3b..af18efb19c512c114ff322ac9bf49b25db29fbb7 100644 (file)
 
 #include <epan/bitswap.h>
 #include <epan/packet.h>
+#include <epan/asn1.h> /* needed for packet-gsm_map.h */
+
+#include "packet-cell_broadcast.h"
+#include "packet-gsm_map.h"
 
 static int dissect_bmc_cbs_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 static int dissect_bmc_schedule_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
@@ -138,19 +142,21 @@ dissect_bmc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 static int
 dissect_bmc_cbs_message(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
+    tvbuff_t *cell_broadcast_tvb;
     gint offset=1;
 
-    proto_tree_add_item(tree, hf_bmc_message_id, tvb, offset, 2, ENC_BIG_ENDIAN);
+    dissect_cbs_message_identifier(tvb, tree, offset);
     offset += 2;
 
-    proto_tree_add_item(tree, hf_bmc_serial_number, tvb, offset, 2, ENC_BIG_ENDIAN);
+    dissect_cbs_serial_number(tvb, tree, offset);
     offset += 2;
 
-    proto_tree_add_item(tree, hf_bmc_data_coding_scheme, tvb, offset, 1, ENC_BIG_ENDIAN);
+    dissect_cbs_data_coding_scheme(tvb, pinfo, tree, offset);
     offset += 1;
 
-    proto_tree_add_item(tree, hf_bmc_cb_data, tvb, offset, tvb_length_remaining(tvb,offset), ENC_NA);
-    offset = tvb_length(tvb);
+    cell_broadcast_tvb = tvb_new_subset(tvb, offset, -1, -1);
+    dissect_umts_cell_broadcast_message(cell_broadcast_tvb, pinfo, tree);
+    offset = tvb_length(cell_broadcast_tvb);
 
     return offset;
 }
diff --git a/epan/dissectors/packet-cell_broadcast.c b/epan/dissectors/packet-cell_broadcast.c
new file mode 100644 (file)
index 0000000..1ef524c
--- /dev/null
@@ -0,0 +1,570 @@
+/* packet-gsm_cell_broadcast.c
+ * Routines for GSM Cell Broadcast Service dissection - A.K.A. 3GPP 23.041 (GSM 03.41) section 9.4
+ *
+ * Copyright 2011, Mike Morrin <mike.morrin [AT] ipaccess.com>
+ *
+ * $Id$
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <epan/emem.h>
+#include <epan/strutil.h>
+#include <epan/asn1.h>
+
+#include <epan/packet.h>
+#include <epan/reassemble.h>
+
+#include "packet-gsm_map.h"
+#include "packet-gsm_sms.h"
+
+#define GSM_CBS_PAGE_SIZE 88
+
+const value_string message_id_values[] = {
+    { 0, "Index"},
+    { 10, "Flashes"},
+    { 20, "Hospitals"},
+    { 22, "Doctors"},
+    { 24, "Pharmacy"},
+    { 30, "Long Distance Road Reports"},
+    { 32, "Local Road Reports"},
+    { 34, "Taxis"},
+    { 40, "Weather"},
+    { 50, "Regional Services (local phone prefixes) / District (Base Station Identity)"},
+    { 52, "Network Information"},
+    { 54, "Operator Service"},
+    { 56, "Directory Enquiries (national)"},
+    { 57, "Directory Enquiries (international)"},
+    { 58, "Customer Care (national)"},
+    { 59, "Customer Care (international)"},
+    { 60, "Local Date/Time Group incl. Time Zone"},
+    { 100, "Regional Services (local phone prefixes)"},
+    { 101, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 102, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 103, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 104, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 105, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 106, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 107, "planned for news, events, whether, traffic, TV station and News of the day"},
+    { 123, "Mobile Auction"},
+    { 140, "Handelsblatt (latest info from stock exchange)"},
+    { 666, "PASSO Traffic Alert (brief teaser information for IVR)"},
+    { 1000, "LCS CBS Message Identifier for E-OTD Assistance Data message"},
+    { 1001, "LCS CBS Message Identifier for DGPS Correction Data message"},
+    { 1002, "LCS CBS Message Identifier for GPS Ephemeris and Clock Correction Data message"},
+    { 1003, "LCS CBS Message Identifier for GPS Almanac and Other Data message"},
+    { 4352, "ETWS CBS Message Identifier for earthquake warning message"},
+    { 4353, "ETWS CBS Message Identifier for tsunami warning message"},
+    { 4354, "ETWS CBS Message Identifier for earthquake and tsunami combined warning message"},
+    { 4355, "ETWS CBS Message Identifier for test message"},
+    { 4356, "ETWS CBS Message Identifier for messages related to other emergency types"},
+    { 4370, "CMAS CBS Message Identifier for CMAS Presidential Level Alerts"},
+    { 4371, "CMAS CBS Message Identifier for CMAS Extreme Alerts with Severity of Extreme, Urgency of Immediate, and Certainty of Observed"},
+    { 4372, "CMAS CBS Message Identifier for CMAS Extreme Alerts with Severity of Extreme, Urgency of Immediate, and Certainty of Likely"},
+    { 4373, "CMAS CBS Message Identifier for CMAS Severe Alerts with Severity of Extreme, Urgency of Expected, and Certainty of Observed"},
+    { 4374, "CMAS CBS Message Identifier for CMAS Severe Alerts with Severity of Extreme, Urgency of Expected, and Certainty of Likely"},
+    { 4375, "CMAS CBS Message Identifier for CMAS Severe Alerts with Severity of Severe, Urgency of Immediate, and Certainty of Observed"},
+    { 4376, "CMAS CBS Message Identifier for CMAS Severe Alerts with Severity of Severe, Urgency of Immediate, and Certainty of Likely"},
+    { 4377, "CMAS CBS Message Identifier for CMAS Severe Alerts with Severity of Severe, Urgency of Expected, and Certainty of Observed"},
+    { 4378, "CMAS CBS Message Identifier for CMAS Severe Alerts with Severity of Severe, Urgency of Expected, and Certainty of Likely"},
+    { 4379, "CMAS CBS Message Identifier for Child Abduction Emergency (or Amber Alert)"},
+    { 4380, "CMAS CBS Message Identifier for the Required Monthly Test"},
+    { 4381, "CMAS CBS Message Identifier for CMAS Exercise"},
+    { 4382, "CMAS CBS Message Identifier for operator defined use"},
+    { 65535, "Message Identifier Reserved, and should not be used for new services"},
+    {    0, NULL }
+};
+
+const value_string geographic_scope_values[] = {
+    { 0x00, "Cell-wide (immediate display)" },
+    { 0x01, "PLMN-wide" },
+    { 0x02, "Location Area-wide (GSM) or Service Area-wide (UMTS)" },
+    { 0x03, "Cell-wide (normal display)" },
+    {    0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_cell_broadcast = -1;
+
+static int hf_gsm_cbs_serial_number    = -1;
+static int hf_gsm_cbs_geographic_scope = -1;
+static int hf_gsm_cbs_message_code     = -1;
+static int hf_gsm_cbs_update_number    = -1;
+static int hf_gsm_cbs_message_identifier       = -1;
+static int hf_gsm_cbs_total_pages      = -1;
+static int hf_gsm_cbs_current_page     = -1;
+
+/* These fields are used when reassembling multi-page gsm cbs messages */
+static int hf_gsm_cbs_pages                    = -1;
+static int hf_gsm_cbs_page_num                 = -1;
+static int hf_gsm_cbs_page_overlap             = -1;
+static int hf_gsm_cbs_page_overlap_conflict    = -1;
+static int hf_gsm_cbs_page_multiple_tails      = -1;
+static int hf_gsm_cbs_page_too_long_fragment   = -1;
+static int hf_gsm_cbs_page_error               = -1;
+static int hf_gsm_cbs_page_count               = -1;
+static int hf_gsm_cbs_message_reassembled_in           = -1;
+static int hf_gsm_cbs_message_reassembled_length               = -1;
+static int hf_gsm_cbs_page_content             = -1;
+static int hf_gsm_cbs_message_content          = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_cbs_msg = -1;
+static gint ett_cbs_serial_no = -1;
+static gint ett_cbs_coding = -1;
+static gint ett_gsm_cbs_page           = -1;
+static gint ett_gsm_cbs_page_content         = -1;
+static gint ett_gsm_cbs_pages          = -1;
+
+/* reassembly of GSM multi-page messages */
+static GHashTable      *gsm_cbs_page_table = NULL;
+static GHashTable      *gsm_cbs_message_table = NULL;
+
+/* Structure needed for the fragmentation routines in reassemble.c */
+static const fragment_items gsm_page_items = {
+    &ett_gsm_cbs_page,
+    &ett_gsm_cbs_pages,
+    &hf_gsm_cbs_pages,
+    &hf_gsm_cbs_page_num,
+    &hf_gsm_cbs_page_overlap,
+    &hf_gsm_cbs_page_overlap_conflict,
+    &hf_gsm_cbs_page_multiple_tails,
+    &hf_gsm_cbs_page_too_long_fragment,
+    &hf_gsm_cbs_page_error,
+    &hf_gsm_cbs_page_count,
+    &hf_gsm_cbs_message_reassembled_in,
+    &hf_gsm_cbs_message_reassembled_length,
+    "pages"
+};
+
+
+static void gsm_cbs_message_reassembly_init(void)
+{
+  fragment_table_init(&gsm_cbs_page_table);
+  reassembled_table_init(&gsm_cbs_message_table);
+}
+
+guint16 dissect_cbs_serial_number(tvbuff_t *tvb, proto_tree *tree, guint16 offset)
+{
+   guint16 serial_number = tvb_get_ntohs(tvb, offset) ;
+   proto_item *item;
+   proto_tree *subtree;
+
+   item = proto_tree_add_item(tree, hf_gsm_cbs_serial_number, tvb, offset, 2, ENC_BIG_ENDIAN);
+   proto_item_append_text(item, ", Message Code: %d, Update Number: %d", (serial_number & 0x3FF) >> 4, serial_number & 0x0F);
+   subtree = proto_item_add_subtree(item, ett_cbs_serial_no);
+   proto_tree_add_item(subtree, hf_gsm_cbs_geographic_scope, tvb, offset, 2, ENC_BIG_ENDIAN);
+   proto_tree_add_item(subtree, hf_gsm_cbs_message_code, tvb, offset, 2, ENC_BIG_ENDIAN);
+   proto_tree_add_item(subtree, hf_gsm_cbs_update_number, tvb, offset, 2, ENC_BIG_ENDIAN);
+   offset +=2;
+   return offset;
+}
+
+guint16 dissect_cbs_message_identifier(tvbuff_t *tvb, proto_tree *tree, guint16 offset)
+{
+   guint16 msg_id;
+   const char *msg_id_string = NULL;
+
+   msg_id = tvb_get_ntohs(tvb, offset);
+   msg_id_string = match_strval(msg_id, message_id_values);
+   if (msg_id_string == NULL)
+   {
+      if (msg_id < 1000)
+      {
+         msg_id_string = "Message ID to be allocated by GSMA";
+      }
+      else if (msg_id < 4096)
+      {
+         msg_id_string = "Message ID intended for standardization in future versions of 3GPP TS 23.041";
+      }
+      else if (msg_id < 4224)
+      {
+         msg_id_string = "Message ID reserved for Cell Broadcast Data Download (unsecured) to the SIM ";
+      }
+      else if (msg_id < 4352)
+      {
+         msg_id_string = "Message ID reserved for Cell Broadcast Data Download (secured) to the SIM ";
+      }
+      else if (msg_id < 4360)
+      {
+         msg_id_string = "ETWS CBS Message Identifier for future extension";
+      }
+      else if (msg_id < 4400)
+      {
+         msg_id_string = "CMAS CBS Message Identifier for future extension";
+      }
+      else if (msg_id < 6400)
+      {
+         msg_id_string = "CBS Message Identifier for future PWS use";
+      }
+      else if (msg_id < 40960)
+      {
+         msg_id_string = "Intended for standardization in future versions of 3GPP TS 23.041";
+      }
+      else if (msg_id < 43500)
+      {
+         msg_id_string = "Message ID in PLMN operator specific range";
+      }
+      else if (msg_id < 43530)
+      {
+         msg_id_string = "Traffic Information Traffic Master UK";
+      }
+      else if (msg_id < 43585)
+      {
+         msg_id_string = "Traffic information Mannesmann Telecommerce";
+      }
+      else if (msg_id < 45056)
+      {
+         msg_id_string = "Message ID in PLMN operator specific range";
+      }
+      else
+      {
+         msg_id_string = "Message ID intended as PLMN operator specific range in future versions of 3GPP TS 23.041";
+      }
+   }
+   proto_tree_add_uint_format_value(tree, hf_gsm_cbs_message_identifier, tvb, offset, 2, msg_id, "%s (%d)", msg_id_string, msg_id);
+   return 2;
+}
+
+static tvbuff_t * dissect_cbs_data(guint8 sms_encoding, tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint16 offset )
+{
+   tvbuff_t * tvb_out = NULL;
+   guint8              out_len;
+   int                 length = tvb_length(tvb) - offset;
+   gchar *utf8_text = NULL;
+   static unsigned char msgbuf[1024];
+   guint8 * input_string = tvb_get_ephemeral_string(tvb, offset, length);
+   GIConv cd;
+   GError *l_conv_error = NULL;
+
+   switch(sms_encoding){
+     case SMS_ENCODING_7BIT:
+     case SMS_ENCODING_7BIT_LANG:
+     out_len = gsm_sms_char_7bit_unpack(0, length, sizeof(msgbuf),
+                                        input_string,
+                                        msgbuf);
+     msgbuf[out_len] = '\0';
+     utf8_text = gsm_sms_chars_to_utf8(msgbuf, out_len);
+     tvb_out = tvb_new_child_real_data(tvb, utf8_text, out_len, out_len);
+     add_new_data_source(pinfo, tvb_out, "unpacked 7 bit data");
+     break;
+
+     case SMS_ENCODING_8BIT:
+     tvb_out = tvb_new_subset(tvb, offset, length, length);
+     break;
+
+     case SMS_ENCODING_UCS2:
+     case SMS_ENCODING_UCS2_LANG:
+     if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv) -1)
+     {
+         utf8_text = g_convert_with_iconv(input_string, length, cd, NULL, NULL, &l_conv_error);
+         if(!l_conv_error)
+         {
+            tvb_out = tvb_new_subset(tvb, offset, length, length);
+         }
+         else
+         proto_tree_add_text(tree, tvb, offset, length, "CBS String: g_convert_with_iconv FAILED");
+
+         g_free(utf8_text);
+         g_iconv_close(cd);
+     }
+     else
+     {
+            proto_tree_add_text(tree, tvb, offset, length, "CBS String: g_iconv_open FAILED contact wireshark");
+     }
+     break;
+
+      default:
+         proto_tree_add_text(tree, tvb, offset, length, "Unhandled encoding %d of CBS String", sms_encoding);
+     break;
+   }
+   return tvb_out;
+}
+
+static void
+dissect_gsm_cell_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+   guint8 sms_encoding, total_pages, current_page;
+   guint32       offset = 0;
+   guint32       len, msg_key;
+   proto_item     *cbs_page_item = NULL, *cbs_page_item2 = NULL;
+   proto_tree    *cbs_page_tree = NULL, *cbs_page_subtree = NULL;
+   guint16 serial_number, message_id;
+   tvbuff_t *cbs_page_tvb = NULL;
+   tvbuff_t *cbs_msg_tvb = NULL;
+   fragment_data * frag_data = NULL;
+
+   len = tvb_length(tvb);
+
+   col_append_str(pinfo->cinfo, COL_PROTOCOL, " Cell Broadcast");
+   col_append_str(pinfo->cinfo, COL_INFO, " (CBS Page)");
+
+   cbs_page_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, tvb, 0, len, "GSM Cell Broadcast");
+   cbs_page_tree = proto_item_add_subtree(cbs_page_item, ett_gsm_cbs_page);
+
+   serial_number = tvb_get_ntohs(tvb, offset);
+   offset += dissect_cbs_serial_number(tvb, cbs_page_tree, offset);
+   message_id = tvb_get_ntohs(tvb, offset);
+   offset += dissect_cbs_message_identifier(tvb, cbs_page_tree, offset);
+   sms_encoding = dissect_cbs_data_coding_scheme(tvb, pinfo, cbs_page_tree, offset++);
+   total_pages = tvb_get_guint8(tvb, offset);
+   current_page = (total_pages & 0xF0) >> 4;
+   total_pages &= 0x0F;
+   proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_current_page, tvb, offset, 1, ENC_BIG_ENDIAN);
+   proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_total_pages, tvb, offset++, 1, ENC_BIG_ENDIAN);
+   cbs_page_tvb = dissect_cbs_data(sms_encoding, tvb, cbs_page_tree, pinfo, offset );
+
+   if (cbs_page_tvb != NULL)
+   {
+     if (tree != NULL)
+     {
+        proto_item *item = proto_tree_add_text(cbs_page_tree, tvb, offset, -1, "Cell Broadcast Page Contents");
+        proto_tree *cbs_page_subtree = proto_item_add_subtree(item, ett_gsm_cbs_page_content);
+        gint len = tvb_length(cbs_page_tvb);
+        proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content, cbs_page_tvb, 0, len, tvb_get_ephemeral_string(cbs_page_tvb, 0, len));
+     }
+     if (total_pages == 1)
+     {
+        /* no need for reassembly */
+        cbs_msg_tvb = cbs_page_tvb;
+     }
+     else
+     {
+         /* now we have a complete page, try to concatenate the full message */
+        /* we can use the serial number and message ID as keys, as they are the same for all pages of a message */
+        msg_key = (serial_number << 16) + message_id;
+        frag_data = fragment_add_check(cbs_page_tvb, 0, pinfo, msg_key,
+                                       gsm_cbs_page_table, gsm_cbs_message_table,
+                                       ((current_page -1) * GSM_CBS_PAGE_SIZE),
+                                       GSM_CBS_PAGE_SIZE, (current_page!=total_pages));
+        cbs_msg_tvb = process_reassembled_data(cbs_page_tvb, 0, pinfo, "Reassembled Cell Broadcast message",
+                                            frag_data, &gsm_page_items, NULL, cbs_page_tree);
+     }
+   }
+   if ((tree != NULL) && (cbs_msg_tvb != NULL))
+   {
+      guint16 len;
+      proto_item     *cbs_msg_item = NULL;
+      proto_tree    *cbs_msg_tree = NULL;
+
+      len = tvb_length(cbs_msg_tvb);
+      col_append_str(pinfo->cinfo, COL_INFO, " (CBS Message)");
+
+      cbs_msg_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, cbs_msg_tvb, 0, len, "GSM Cell Broadcast Message");
+      cbs_msg_tree = proto_item_add_subtree(cbs_msg_item, ett_cbs_msg);
+
+      proto_tree_add_string(cbs_msg_tree, hf_gsm_cbs_message_content, cbs_msg_tvb, 0, len, tvb_get_ephemeral_string(cbs_msg_tvb, 0, len));
+   }
+}
+
+void dissect_umts_cell_broadcast_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+   guint8 sms_encoding;
+   guint32       offset = 0;
+   guint32       len;
+   proto_item    *cbs_item = NULL, *cbs_item2 = NULL;
+   proto_tree    *cbs_tree = NULL, *cbs_subtree = NULL;
+   guint16  msg_len;
+   tvbuff_t * cbs_msg_tvb = NULL;
+
+   len = tvb_length(tvb);
+
+   col_append_str(pinfo->cinfo, COL_PROTOCOL, " Cell Broadcast");
+   col_append_str(pinfo->cinfo, COL_INFO, " (CBS Message)");
+
+   cbs_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, tvb, 0, len, "Cell Broadcast");
+   cbs_tree = proto_item_add_subtree(cbs_item, ett_cbs_msg);
+
+   sms_encoding = dissect_cbs_data_coding_scheme(tvb, pinfo, cbs_tree, 0);
+   offset++;
+   cbs_msg_tvb = dissect_cbs_data(sms_encoding, tvb, cbs_tree, pinfo, offset );
+
+   msg_len = tvb_length(cbs_msg_tvb);
+   cbs_item2 = proto_tree_add_text(cbs_tree, tvb, offset, -1, "Cell Broadcast Message Contents (length: %d)", msg_len);
+   cbs_subtree = proto_item_add_subtree(cbs_item2, ett_cbs_msg);
+   proto_tree_add_text(cbs_subtree, cbs_msg_tvb , 0, tvb_length(cbs_msg_tvb), tvb_get_ephemeral_string(cbs_msg_tvb, 0, msg_len));
+}
+
+/* Register the protocol with Wireshark */
+void
+proto_register_cbs(void)
+{
+    /* Setup list of header fields */
+    static hf_register_info hf_cbs[] =
+        {
+           { &hf_gsm_cbs_serial_number,
+             { "GSM CBS Serial Number",        "gsm_cbs.serial_number",
+       FT_UINT16, BASE_HEX_DEC, NULL, 0x00,
+       NULL, HFILL }
+           },
+            { &hf_gsm_cbs_message_code,
+              { "GSM CBS Message Code",        "gsm_cbs.message_code",
+               FT_UINT16, BASE_DEC_HEX, NULL, 0x3FF0,
+               NULL, HFILL }
+            },
+            { &hf_gsm_cbs_geographic_scope,
+              { "GSM CBS Geographic Scope",    "gsm_cbs.geographic_scope",
+               FT_UINT16, BASE_DEC, VALS(geographic_scope_values), 0xC000,
+               NULL, HFILL }
+            },
+            { &hf_gsm_cbs_update_number,
+              { "GSM CBS Update Number",       "gsm_cbs.update_number",
+               FT_UINT16, BASE_DEC, NULL, 0x000F,
+               NULL, HFILL }
+            },
+            { &hf_gsm_cbs_message_identifier,
+              { "GSM CBS Message Identifier",  "gsm_cbs.message-identifier",
+               FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
+               NULL, HFILL }
+            },
+            { &hf_gsm_cbs_total_pages,
+              { "GSM CBS Total Pages", "gsm_cbs.total_pages",
+               FT_UINT8, BASE_DEC, NULL, 0x0F,
+               NULL, HFILL }
+            },
+            { &hf_gsm_cbs_current_page,
+              { "GSM CBS Current Page",        "gsm_cbs.current_page",
+               FT_UINT8, BASE_DEC, NULL, 0xF0,
+               NULL, HFILL }
+            },
+            /* Fragment fields
+             */
+            { &hf_gsm_cbs_page_overlap,
+              {        "page overlap",
+            "gsm_cbs.page.overlap",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "GSM CBS page overlaps with other fragments", HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_overlap_conflict,
+              {        "Conflicting data in page overlap",
+            "gsm_cbs.page.overlap.conflict",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Overlapping pages contained conflicting data", HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_multiple_tails,
+              {        "Multiple final pages found",
+            "gsm_cbs.page.multipletails",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Several copies of the final page were found when reassembling the message", HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_too_long_fragment,
+              {        "Page too long",
+            "gsm_cbs.page.toolongfragment",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Page contained data past end of packet", HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_error,
+              {        "Reassembly error",
+            "gsm_cbs.fragment.error",
+            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+            "Reassembly error due to illegal fragments", HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_count,
+              {        "Fragment count",
+            "gsm_cbs.fragment.count",
+            FT_UINT32, BASE_DEC, NULL, 0x0,
+            "Count of Page Fragment", HFILL
+              }
+            },
+            { &hf_gsm_cbs_message_reassembled_in,
+              {        "Reassembled in",
+            "gsm_cbs.reassembled.in",
+            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+            "CBS pages are reassembled in the given packet", HFILL
+              }
+            },
+            { &hf_gsm_cbs_message_reassembled_length,
+              {        "Reassembled message length",
+            "gsm_cbs.reassembled.length",
+            FT_UINT32, BASE_DEC, NULL, 0x0,
+            "The total length of the reassembled message", HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_num,
+              {        "CBS Page Number",
+            "gsm_cbs.page_number",
+            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+            NULL, HFILL
+              }
+            },
+            { &hf_gsm_cbs_pages,
+              {        "CBS Pages",
+            "gsm_cbs.pages",
+            FT_NONE, BASE_NONE, NULL, 0x0,
+            NULL, HFILL
+              }
+            },
+            { &hf_gsm_cbs_page_content,
+              {        "CBS Page Content",
+            "gsm_cbs.page_content",
+            FT_STRING, BASE_NONE, NULL, 0x0,
+            NULL, HFILL
+              }
+            },
+            { &hf_gsm_cbs_message_content,
+              {        "CBS Message Content",
+            "gsm_cbs.message_content",
+            FT_STRING, BASE_NONE, NULL, 0x0,
+            NULL, HFILL
+              }
+            }
+            };
+
+    /* Setup protocol subtree array */
+    static gint *ett[] = {
+       &ett_cbs_msg,
+       &ett_cbs_serial_no,
+       &ett_cbs_coding,
+       &ett_gsm_cbs_page,
+       &ett_gsm_cbs_page_content,
+       &ett_gsm_cbs_pages,
+    };
+
+    /* Register the protocol name and description */
+    proto_cell_broadcast = proto_register_protocol("GSM Cell Broadcast Service", "GSM Cell Broadcast Service", "gsm_cell_broadcast");
+
+    proto_register_field_array(proto_cell_broadcast, hf_cbs, array_length(hf_cbs));
+    register_init_routine(gsm_cbs_message_reassembly_init);
+
+    /* subdissector code */
+    register_dissector("gsm_cell_broadcast", dissect_gsm_cell_broadcast, proto_cell_broadcast);
+    register_dissector("umts_cell_broadcast", dissect_umts_cell_broadcast_message, proto_cell_broadcast);
+
+    /* subtree array */
+    proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_gsm_cbs(void)
+{
+}
diff --git a/epan/dissectors/packet-cell_broadcast.h b/epan/dissectors/packet-cell_broadcast.h
new file mode 100644 (file)
index 0000000..6892360
--- /dev/null
@@ -0,0 +1,59 @@
+/* packet-cell_broadcast.h
+ *
+ * $Id$
+ *
+ * Copyright 2011, Mike Morrin <mike.morrin [AT] ipaccess.com>,
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_CELL_BROADCAST_H
+#define PACKET_CELL_BROADCAST_H
+
+
+/**
+ * Dissects the GSM/UMTS/SABP Message Identifier
+ * 
+ * @param tvb
+ * @param tree
+ * @param offset
+ */
+void dissect_cbs_message_identifier(tvbuff_t *tvb, proto_tree *tree, guint16 offset);
+
+
+/**
+ * Decodes the GSM/UMTS/SABP message Serial Number
+ * 
+ * @param tvb
+ * @param tree
+ * @param offset
+ */
+void dissect_cbs_serial_number(tvbuff_t *tvb, proto_tree *tree, guint16 offset);
+
+
+/**
+ * Dissects UMTS/SABP Cell Broadcast Message
+ * 
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ */
+guint16 dissect_umts_cell_broadcast_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+#endif /* PACKET_CELL_BROADCAST_H */
diff --git a/epan/dissectors/packet-gsm_cbch.c b/epan/dissectors/packet-gsm_cbch.c
new file mode 100644 (file)
index 0000000..26c47df
--- /dev/null
@@ -0,0 +1,585 @@
+/* packet-gsm_cbch.c
+ * Routines for GSM CBCH dissection - A.K.A. 3GPP 44.012 (GSM 04.12)
+ *
+ * Copyright 2011, Mike Morrin <mike.morrin [AT] ipaccess.com>
+ *
+ * $Id$
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+   #include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include <string.h>
+
+#include <epan/packet.h>
+#include <epan/reassemble.h>
+#include "packet-cell_broadcast.h"
+
+#define CBCH_FRAGMENT_SIZE 22
+
+const value_string block_type_lpd_strings[] = {
+   { 0x00, "NOT Cell Broadcast"},
+   { 0x01, "Cell Broadcast"},
+   { 0x02, "NOT Cell Broadcast"},
+   { 0x03, "NOT Cell Broadcast"},
+   {    0, NULL}
+};
+
+const value_string block_type_seq_num_values[] = {
+   { 0x00, "First Block"},
+   { 0x01, "Second Block"},
+   { 0x02, "Third Block"},
+   { 0x03, "Fourth Block"},
+   { 0x08, "First Schedule Block"},
+   { 0xFF, "Null message"},
+   {    0, NULL}
+};
+
+const value_string sched_type_values[] = {
+   { 0x00, "messages formatted as specified in subclause 3.5 of 3GPP 44.012"},
+   { 0xFF, "Unknown schedule message format"},
+   {    0, NULL}
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_cbch = -1;
+
+static int hf_gsm_cbch_spare_bit = -1;
+static int hf_gsm_cbch_lpd = -1;
+static int hf_gsm_cbch_lb  = -1;
+static int hf_gsm_cbch_seq_num   = -1;
+static int hf_gsm_cbch_sched_type   = -1;
+static int hf_gsm_cbch_sched_begin_slot   = -1;
+static int hf_gsm_cbch_sched_spare  = -1;
+static int hf_gsm_cbch_sched_end_slot  = -1;
+static int hf_gsm_cbch_sched_msg_id = -1;
+
+/* These fields are used when reassembling cbch fragments
+*/
+static int hf_cbch_fragments        = -1;
+static int hf_cbch_fragment         = -1;
+static int hf_cbch_fragment_overlap    = -1;
+static int hf_cbch_fragment_overlap_conflict = -1;
+static int hf_cbch_fragment_multiple_tails   = -1;
+static int hf_cbch_fragment_too_long_fragment   = -1;
+static int hf_cbch_fragment_error      = -1;
+static int hf_cbch_fragment_count      = -1;
+static int hf_cbch_reassembled_in      = -1;
+static int hf_cbch_reassembled_length     = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_cbch_msg = -1;
+static gint ett_schedule_msg = -1;
+static gint ett_schedule_new_msg = -1;
+static gint ett_cbch_fragment           = -1;
+static gint ett_cbch_fragments          = -1;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t cbs_handle;
+
+/* reassembly of CHCH blocks */
+static GHashTable *fragment_block_table = NULL;
+static GHashTable *reassembled_message_table = NULL;
+
+/* Structure needed for the fragmentation routines in reassemble.c
+*/
+static const fragment_items cbch_frag_items = {
+   &ett_cbch_fragment,
+   &ett_cbch_fragments,
+   &hf_cbch_fragments,
+   &hf_cbch_fragment,
+   &hf_cbch_fragment_overlap,
+   &hf_cbch_fragment_overlap_conflict,
+   &hf_cbch_fragment_multiple_tails,
+   &hf_cbch_fragment_too_long_fragment,
+   &hf_cbch_fragment_error,
+   &hf_cbch_fragment_count,
+   &hf_cbch_reassembled_in,
+   &hf_cbch_reassembled_length,
+   "blocks"
+};
+
+static void cbch_defragment_init(void)
+{
+   fragment_table_init(&fragment_block_table);
+   reassembled_table_init(&reassembled_message_table);
+}
+
+static void dissect_schedule_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree)
+{
+   guint8 octet1, i, j, k=0, len, sched_begin, sched_end, new_slots[48] , offset = 0;
+   gboolean valid_message = TRUE;
+   guint16 other_slots[48];
+   proto_item *item = NULL, *schedule_item = NULL;
+   proto_tree *sched_tree = NULL, *sched_subtree = NULL;
+
+   len = tvb_length(tvb);
+
+   col_append_str(pinfo->cinfo, COL_INFO, " CBCH Schedule Message ");
+
+   schedule_item = proto_tree_add_protocol_format(top_tree, proto_cbch, tvb, 0, len,
+                                                  "GSM CBCH Schedule Message");
+
+   sched_tree = proto_item_add_subtree(schedule_item, ett_schedule_msg);
+
+   proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+   octet1 = tvb_get_guint8(tvb, offset);
+   if (0 == (octet1 & 0xC0))
+   {
+      sched_begin = octet1 & 0x3F;
+      proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_begin_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
+      if (1 == sched_begin)
+      {
+         proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "(apparently) Scheduled Scheduling Message");
+      }
+      else if ((2 <= sched_begin) && (48 >= sched_begin))
+      {
+         proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "(apparently) Unscheduled Scheduling Message");
+      }
+      else
+      {
+         proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "Begin Slot Number out of range: ignoring message");
+         valid_message = FALSE;
+      }
+      proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_spare, tvb, offset, 1, ENC_BIG_ENDIAN);
+      sched_end = tvb_get_guint8(tvb, offset);
+      proto_tree_add_item(sched_tree, hf_gsm_cbch_sched_end_slot, tvb, offset++, 1, ENC_BIG_ENDIAN);
+      if (sched_end < sched_begin)
+      {
+         proto_tree_add_text(sched_tree, tvb, offset - 1, 1, "End Slot Number less than Begin Slot Number: ignoring message");
+         valid_message = FALSE;
+      }
+
+      if (valid_message)
+      {
+         /* build an array of new messages */
+         memset(&new_slots, 0xFF, sizeof(new_slots));
+         memset(&other_slots, 0xFF, sizeof(other_slots));
+
+         /* iterate over the octets */
+         for (i=0; i<6; i++)
+         {
+            octet1 = tvb_get_guint8(tvb, offset++);
+
+            /* iterate over the bits */
+            for (j=0; j<8; j++)
+            {
+               if (octet1 & (0x80>>j))
+               {
+                  new_slots[k++] = (i<<3) + j + 1;
+               }
+            }
+         }
+         /* print the array of new messages */
+         item = proto_tree_add_text(sched_tree, tvb, offset-6, 6, "This schedule contains %d slots with new messages", k);
+         sched_subtree = proto_item_add_subtree(item, ett_schedule_new_msg);
+         for (i=0; i<k; i++)
+         {
+            DISSECTOR_ASSERT(new_slots[i] < 48);
+            octet1 = tvb_get_guint8(tvb, offset);
+            if ((octet1 & 0x80) == 0x80)
+            {
+               /* MDT 1 */
+               guint8 octet2;
+               guint16 msg_id;
+
+               octet2 = tvb_get_guint8(tvb, offset + 1);
+               msg_id = ((octet1 &0x7F) << 8) + octet2;
+               proto_tree_add_text(sched_subtree, tvb, offset, 2,
+                                   "Slot: %d, Message ID: %d, First transmission of an SMSCB within the Schedule Period",
+                                   new_slots[i], msg_id);
+               offset +=2;
+               other_slots[new_slots[i] - 1] = msg_id;
+            }
+            else if ((octet1 & 0xC0) == 0)
+            {
+               /* MDT 00 */
+               if (octet1 < new_slots[i])
+               {
+                  proto_tree_add_text(sched_subtree, tvb, offset++, 1,
+                                      "Slot: %d, Message ID: %d, Repeat of Slot %d",
+                                      new_slots[i], other_slots[octet1 - 1], octet1);
+                  other_slots[new_slots[i] - 1] = other_slots[octet1 - 1];
+               }
+               else
+               {
+                  proto_tree_add_text(sched_subtree, tvb, offset++, 1,
+                                      "Slot: %d, Apparent forward reference to slot %d",
+                                      new_slots[i], octet1);
+               }
+            }
+            else if ((octet1 == 0x40))
+            {
+               /* MDT 010000000 */
+               proto_tree_add_text(sched_subtree, tvb, offset++, 1, "Slot: %d Free Message Slot, optional reading", new_slots[k]);
+               other_slots[new_slots[i] - 1] = 0xFFFE;
+            }
+            else if ((octet1 == 0x41))
+            {
+               /* MDT 010000001 */
+               proto_tree_add_text(sched_subtree, tvb, offset++, 1, "Slot: %d Free Message Slot, reading advised", new_slots[k]);
+               other_slots[new_slots[i] - 1] = 0xFFFE;
+            }
+            else
+            {
+               /* reserved MDT */
+               proto_tree_add_text(sched_subtree, tvb, offset, 1, "Slot: %d reseved MDT: %x", new_slots[k], octet1);
+               other_slots[new_slots[i] - 1] = 0xFFFE;
+            }
+         }
+         proto_item_set_end(item, tvb, offset);    
+
+         /* print schedule of other messages */
+         item = proto_tree_add_text(sched_tree, tvb, offset, 0, "Other message slots in this schedule");
+         sched_subtree = proto_item_add_subtree(item, ett_schedule_new_msg);
+         for (k=0; offset<len; j++)
+         {
+            while ((other_slots[k]!=0xFFFF) && (k<sched_end))
+            {
+               k++;
+            }
+            if (k >= sched_end)
+               break;
+
+            octet1 = tvb_get_guint8(tvb, offset);
+            if ((octet1 & 0x80) == 0x80)
+            {
+               if ((offset+1)<len)
+               {
+                  /* MDT 1 */
+                  guint8 octet2;
+                  guint16 msg_id;
+
+                  octet2 = tvb_get_guint8(tvb, offset + 1);
+                  msg_id = ((octet1 &0x7F) << 8) + octet2;
+                  other_slots[k] = msg_id;
+                  proto_tree_add_text(sched_subtree, tvb, offset, 2,
+                                      "Slot: %d, Message: %d, First transmission of an SMSCB within the Schedule Period",
+                                      ++k, msg_id);
+                  offset +=2;
+               }
+            }
+            else if ((octet1 & 0xC0) == 0)
+            {
+               /* MDT 00 */
+               if (octet1 < k)
+               {
+                  other_slots[k] = other_slots[octet1 - 1];
+                  proto_tree_add_text(sched_subtree, tvb, offset++, 1,
+                                      "Slot: %d, Message ID: %d, Repeat of Slot %d",
+                                      ++k, other_slots[octet1 - 1], octet1);
+               }
+               else
+               {
+                  proto_tree_add_text(sched_subtree, tvb, offset++, 1,
+                                      "Slot: %d, Apparent forward reference to slot %d",
+                                      ++k, octet1);
+               }
+            }
+            else if ((octet1 == 0x40))
+            {
+               /* MDT 010000000 */
+               proto_tree_add_text(sched_subtree, tvb, offset++, 1, "Slot: %d Free Message Slot, optional reading", ++k);
+            }
+            else if ((octet1 == 0x41))
+            {
+               /* MDT 010000001 */
+               proto_tree_add_text(sched_subtree, tvb, offset++, 1, "Slot: %d Free Message Slot, reading advised", ++k);
+            }
+            else
+            {
+               /* reserved MDT */
+               proto_tree_add_text(sched_subtree, tvb, offset, 1, "Slot: %d reserved MDT: %x", ++k, octet1);
+            }
+         }
+         proto_item_set_end(item, tvb, offset);    
+         proto_tree_add_text(sched_tree, tvb, offset, -1, "Padding");
+      }
+   }
+}
+
+static void
+dissect_cbch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+   fragment_data * frag_data = NULL;
+   guint8          octet, lb, lpd, seq_num;
+   guint32         offset;
+   guint32         len;
+   proto_item      *cbch_item = NULL;
+   proto_tree      *cbch_tree = NULL;
+   tvbuff_t        *reass_tvb = NULL, *msg_tvb = NULL;
+
+   len = tvb_length(tvb);
+   offset = 0;
+   octet = tvb_get_guint8(tvb, offset);
+
+   /*
+    * create the protocol tree
+    */
+   cbch_item = proto_tree_add_protocol_format(tree, proto_cbch, tvb, 0, len,
+                                              "GSM CBCH - Block (0x%02x)", octet&3);
+
+   col_append_str(pinfo->cinfo, COL_PROTOCOL, " CBCH");
+
+   cbch_tree = proto_item_add_subtree(cbch_item, ett_cbch_msg);
+
+   proto_tree_add_text(cbch_tree, tvb, offset, 1,
+                       "CBCH Block");
+
+   proto_tree_add_uint(cbch_tree, hf_gsm_cbch_spare_bit, tvb, offset, 1, octet);
+   proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lpd, tvb, offset, 1, octet);
+   proto_tree_add_uint(cbch_tree, hf_gsm_cbch_lb, tvb, offset, 1, octet);
+   proto_tree_add_uint(cbch_tree, hf_gsm_cbch_seq_num, tvb, offset, 1, octet);
+   seq_num = octet & 0x0F;
+   lpd = (octet & 0x60) >> 5;
+   lb = (octet & 0x10) >> 4;
+
+   if (lpd == 1)
+   {
+      switch (seq_num)
+      {
+         case 0x00:
+         case 0x08:
+            pinfo->fragmented = TRUE;
+            /* we should have a unique ID for the reassembled page, but we don't really have anything from the protocol...
+               The GSM frame number div 4 might be used for this, but it has not been passed to this layer and does not 
+               exist at all if the message is being passed over the RSL interface.
+               So we just use 0... */
+
+            /* after reassembly we will need to know if this is a scheduling message,
+               this information is carried in the initial sequence number, not the payload,
+               so we prepend the reassembly with the octet containing the initial sequence number
+               to allow later dissection of the payload */
+            frag_data = fragment_add_seq_check(tvb, offset, pinfo, 0,
+                                               fragment_block_table, reassembled_message_table,
+                                               seq_num & 0x03, CBCH_FRAGMENT_SIZE + 1, !lb);
+            reass_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CBCH message",
+                                                 frag_data, &cbch_frag_items, NULL, cbch_tree);
+            break;
+
+         case 0x01:
+         case 0x02:
+         case 0x03:
+            pinfo->fragmented = TRUE;
+            offset++; /* step to beginning of payload */
+            frag_data = fragment_add_seq_check(tvb, offset, pinfo, 0,
+                                               fragment_block_table, reassembled_message_table, seq_num,
+                                               CBCH_FRAGMENT_SIZE, !lb);
+            reass_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CBCH message",
+                                                 frag_data, &cbch_frag_items, NULL, cbch_tree);
+            break;
+
+         case 0x0F:
+            proto_tree_add_text(cbch_tree, tvb, offset, 1, "NULL message");
+            call_dissector(data_handle, tvb, pinfo, cbch_tree);
+            break;
+
+         default:
+            proto_tree_add_text(cbch_tree, tvb, offset, 1, "reserved Sequence Number");
+            call_dissector(data_handle, tvb, pinfo, cbch_tree);
+            break;
+      }
+      if (reass_tvb)
+      {
+         /* Reassembled */
+
+         /* the tvb contains the reassmbled message prepended with the sequence number octet from the first block
+            We use this to determine whether this is a normal message or a scheduling message */
+         offset = 0;
+
+         octet = tvb_get_guint8(reass_tvb, offset++);
+         msg_tvb = tvb_new_subset_remaining(reass_tvb, offset);
+
+         if (octet & 0x08)
+         {
+            dissect_schedule_message(msg_tvb, pinfo, tree);
+         }
+         else
+         {
+            call_dissector(cbs_handle, msg_tvb, pinfo, tree);
+         }
+      }
+   }
+   else
+   {
+      proto_tree_add_text(cbch_tree, tvb, offset, 1, "invalid Link Protocol Discriminator");
+      call_dissector(data_handle, tvb, pinfo, cbch_tree);
+   }
+}
+
+/* Register the protocol with Wireshark */
+void
+proto_register_gsm_cbch(void)
+{
+   /* Setup list of header fields */
+   static hf_register_info hf_smscb[] =
+   {
+      { &hf_gsm_cbch_spare_bit,
+         { "GSM CBCH spare bit",  "gsm_cbch_block_type.spare",
+            FT_UINT8, BASE_HEX, NULL, 0x80,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_lpd,
+         { "GSM CBCH Link Protocol Discriminator",  "gsm_cbch_block_type.lpd",
+            FT_UINT8, BASE_DEC, VALS(block_type_lpd_strings), 0x60,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_lb,
+         { "GSM CBCH Last Block", "gsm_cbch_block_type.lb",
+            FT_UINT8, BASE_DEC, NULL, 0x10,
+            "Last Block", HFILL}
+      },
+      { &hf_gsm_cbch_seq_num,
+         { "GSM CBCH Sequence Number",  "gsm_cbch_block_type.seq_num",
+            FT_UINT8, BASE_DEC, VALS(block_type_seq_num_values), 0x0F,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_sched_type,
+         { "GSM CBCH Schedule Type", "gsm_cbch.sched_type",
+            FT_UINT8, BASE_DEC, VALS(sched_type_values), 0xC0,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_sched_begin_slot,
+         { "GSM CBCH Schedule Begin slot", "gsm_cbch.schedule_begin",
+            FT_UINT8, BASE_DEC, NULL, 0x3F,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_sched_spare,
+         { "GSM CBCH Schedule Spare Bits", "gsm_cbch.sched_spare",
+            FT_UINT8, BASE_DEC, NULL, 0xC0,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_sched_end_slot,
+         { "GSM CBCH Schedule End Slot",   "gsm_cbch.sched_end",
+            FT_UINT8, BASE_DEC, NULL, 0x3F,
+            NULL, HFILL}
+      },
+      { &hf_gsm_cbch_sched_msg_id,
+         { "GSM CBCH Schedule Message ID", "gsm_cbch.sched_msg_id",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            NULL, HFILL}
+      },
+      /* Fragment fields
+       */
+      { &hf_cbch_fragment_overlap,
+         {   "Fragment overlap",
+            "gsm_cbch.fragment.overlap",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Fragment overlaps with other fragments", HFILL
+         }
+      },
+      { &hf_cbch_fragment_overlap_conflict,
+         {   "Conflicting data in fragment overlap",
+            "gsm_cbch.fragment.overlap.conflict",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Overlapping fragments contained conflicting data", HFILL
+         }
+      },
+      { &hf_cbch_fragment_multiple_tails,
+         {   "Multiple tail fragments found",
+            "gsm_cbch.fragment.multipletails",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Several tails were found when defragmenting the packet", HFILL
+         }
+      },
+      { &hf_cbch_fragment_too_long_fragment,
+         {   "Fragment too long",
+            "gsm_cbch.fragment.toolongfragment",
+            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+            "Fragment contained data past end of packet", HFILL
+         }
+      },
+      { &hf_cbch_fragment_error,
+         {   "Defragmentation error",
+            "gsm_cbch.fragment.error",
+            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+            "Defragmentation error due to illegal fragments", HFILL
+         }
+      },
+      { &hf_cbch_fragment_count,
+         {   "Fragmentation count",
+            "gsm_cbch.fragment.count",
+            FT_UINT32, BASE_DEC, NULL, 0x0,
+            "Count of CBCH Fragments", HFILL
+         }
+      },
+      { &hf_cbch_reassembled_in,
+         {   "Reassembled in",
+            "gsm_cbch.reassembled.in",
+            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+            "CBCH fragments are reassembled in the given packet", HFILL
+         }
+      },
+      { &hf_cbch_reassembled_length,
+         {   "Reassembled message length is one less than indicated here",
+            "gsm_cbch.reassembled.length",
+            FT_UINT32, BASE_DEC, NULL, 0x0,
+            "The total length of the reassembled message", HFILL
+         }
+      },
+      { &hf_cbch_fragment,
+         {   "CBCH Fragment",
+            "gsm_cbch.fragment",
+            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+            NULL, HFILL
+         }
+      },
+      { &hf_cbch_fragments,
+         {   "CBCH Fragments",
+            "gsm_cbch.fragments",
+            FT_NONE, BASE_NONE, NULL, 0x0,
+            NULL, HFILL
+         }
+      }
+   };
+
+/* Setup protocol subtree array */
+   static gint *ett[] = {
+      &ett_cbch_msg,
+      &ett_schedule_msg,
+      &ett_schedule_new_msg,
+      &ett_cbch_fragment,
+      &ett_cbch_fragments,
+   };
+
+   /* Register the protocol name and description */
+   proto_cbch =
+   proto_register_protocol("GSM Cell Broadcast Channel", "GSM CBCH", "gsm_cbch");
+
+   proto_register_field_array(proto_cbch, hf_smscb, array_length(hf_smscb));
+
+   /* subdissector code */
+   register_dissector("gsm_cbch", dissect_cbch, proto_cbch);
+   register_init_routine(cbch_defragment_init);
+
+   /* subtree array */
+   proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_gsm_cbch(void)
+{
+   data_handle = find_dissector("data");
+   cbs_handle = find_dissector("gsm_cell_broadcast");
+}
index e013a57bfdf89c85f18922a7937a5a248053a25a..56f619aebe184ee9e8edaf603869d6ac7a821a7a 100644 (file)
@@ -2716,24 +2716,24 @@ static const value_string gsm_map_cbs_coding_grp15_class_vals[] = {
 
 /* 3GPP TS 23.038 version 7.0.0 Release 7 */
 guint8
-dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint16 offset)
 {
        guint8 octet;
        guint8 coding_grp;
        guint8 character_set;
 
-       octet = tvb_get_guint8(tvb,0);
+       octet = tvb_get_guint8(tvb,offset);
        coding_grp = octet >>4;
-       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp, tvb, 0, 1, ENC_BIG_ENDIAN);
+       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp, tvb, offset, 1, ENC_BIG_ENDIAN);
 
        sms_encoding = SMS_ENCODING_NOT_SET;
        switch (coding_grp){
        case 0:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp0_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp0_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                sms_encoding = SMS_ENCODING_7BIT;
                break;
        case 1:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp1_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp1_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                if ((octet & 0x0f)== 0){
                        sms_encoding = SMS_ENCODING_7BIT_LANG;
                }else{
@@ -2741,11 +2741,11 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                }
                break;
        case 2:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp2_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp2_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                sms_encoding = SMS_ENCODING_7BIT;
                break;
        case 3:
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp3_lang, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp3_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
                sms_encoding = SMS_ENCODING_7BIT;
                break;
                /* Coding_grp 01xx */
@@ -2757,11 +2757,11 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                  /* FALLTHRU */
        case 7:
                  /* FALLTHRU */
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_comp, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class_ind, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_comp, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, offset, 1, ENC_BIG_ENDIAN);
                if ((octet & 0x10)== 0x10){
-                       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, 0, 1, ENC_BIG_ENDIAN);
+                       proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, offset, 1, ENC_BIG_ENDIAN);
                }
                /* Bits 3 and 2 indicate the character set being used, */
                character_set = (octet&0x0c)>>2;
@@ -2791,8 +2791,8 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                break;
        case 9:
                /* Message with User Data Header (UDH) structure:*/
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_char_set, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp4_7_class, tvb, offset, 1, ENC_BIG_ENDIAN);
                character_set = (octet&0x0c)>>2;
                switch (character_set){
                case 0:
@@ -2832,8 +2832,8 @@ dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
                break;
        case 15:
                /* Data coding / message handling */
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_mess_code, tvb, 0, 1, ENC_BIG_ENDIAN);
-               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_class, tvb, 0, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_mess_code, tvb, offset, 1, ENC_BIG_ENDIAN);
+               proto_tree_add_item(tree, hf_gsm_map_cbs_coding_grp15_class, tvb, offset, 1, ENC_BIG_ENDIAN);
                character_set = (octet&0x04)>>2;
                if (character_set == 0){
                        sms_encoding = SMS_ENCODING_7BIT;
@@ -4501,7 +4501,7 @@ dissect_gsm_map_ss_USSD_DataCodingScheme(gboolean implicit_tag _U_, tvbuff_t *tv
   if (!parameter_tvb)
      return offset;
   subtree = proto_item_add_subtree(actx->created_item, ett_gsm_map_cbs_data_coding);
-  dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree);
+  dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree, 0);
 
 
 
index 179c59c976e60e6edcfbecf057d7132cb05a2fbb..bd808677622a852a02df01f70cbe435da0d64c04 100644 (file)
@@ -59,7 +59,7 @@ extern const value_string gsm_map_PDP_Type_Organisation_vals[];
 extern const value_string gsm_map_ietf_defined_pdp_vals[];
 extern const value_string gsm_map_etsi_defined_pdp_vals[];
 
-guint8 dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree);
+guint8 dissect_cbs_data_coding_scheme(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint16 offset);
 void dissect_gsm_map_msisdn(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree);
 
 
index 945734ffdcc6c19ce507ad4f8f3bd1f6258d2900..55fd77b80dfc3faaa2599fbdff9ea4f3fe6b2b6a 100644 (file)
@@ -171,6 +171,8 @@ static int ett_ie_message_id = -1;
 static int ett_ie_sys_info_type = -1;
 
 static proto_tree *top_tree;
+static dissector_handle_t gsm_cbch_handle;
+static dissector_handle_t gsm_cbs_handle;
 static dissector_handle_t gsm_a_ccch_handle;
 static dissector_handle_t gsm_a_dtap_handle;
 static dissector_handle_t gsm_a_sacch_handle;
@@ -1977,6 +1979,7 @@ dissect_rsl_ie_smscb_inf(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree
 {
     proto_item *ti;
     proto_tree *ie_tree;
+    tvbuff_t    *next_tvb;
 
     guint       length;
     guint8      ie_id;
@@ -2002,7 +2005,8 @@ dissect_rsl_ie_smscb_inf(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree
     /*
      * SMSCB frame
      */
-    proto_tree_add_text(ie_tree, tvb,offset,length,"SMSCB frame");
+    next_tvb = tvb_new_subset(tvb, offset, length, length);
+    call_dissector(gsm_cbch_handle, next_tvb, pinfo, top_tree);
 
     offset = offset + length;
 
@@ -2202,6 +2206,7 @@ dissect_rsl_ie_smscb_mess(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre
 {
     proto_item *ti;
     proto_tree *ie_tree;
+    tvbuff_t    *next_tvb;
     guint length;
     guint8 ie_id;
     int ie_offset;
@@ -2228,7 +2233,8 @@ dissect_rsl_ie_smscb_mess(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre
      * SMSCB Message
      */
 
-    proto_tree_add_text(ie_tree, tvb,offset,length ,"SMSCB Message");
+    next_tvb = tvb_new_subset(tvb, offset, length, length);
+    call_dissector(gsm_cbs_handle, next_tvb, pinfo, top_tree);
 
     offset = ie_offset + length;
 
@@ -3985,6 +3991,8 @@ proto_reg_handoff_rsl(void)
     rsl_handle = create_dissector_handle(dissect_rsl, proto_rsl);
     dissector_add_uint("lapd.gsm.sapi", LAPD_GSM_SAPI_RA_SIG_PROC, rsl_handle);
 
+    gsm_cbch_handle = find_dissector("gsm_cbch");
+    gsm_cbs_handle = find_dissector("gsm_cell_broadcast");
     gsm_a_ccch_handle = find_dissector("gsm_a_ccch");
     gsm_a_dtap_handle = find_dissector("gsm_a_dtap");
     gsm_a_sacch_handle = find_dissector("gsm_a_sacch");
index c8aaa4bf396ffef9ca830ae8669cf71ad9fa0667..8d1b17812d52c8ebd900ed742ee6d0c636410042 100644 (file)
@@ -48,6 +48,7 @@
 #include "packet-gsm_map.h"
 #include "packet-gsm_sms.h"
 #include <epan/sctpppids.h>
+#include "packet-cell_broadcast.h"
 
 #define PNAME  "UTRAN IuBC interface SABP signaling"
 #define PSNAME "SABP"
@@ -99,7 +100,7 @@ typedef enum _ProtocolIE_ID_enum {
 } ProtocolIE_ID_enum;
 
 /*--- End of included file: packet-sabp-val.h ---*/
-#line 49 "../../asn1/sabp/packet-sabp-template.c"
+#line 50 "../../asn1/sabp/packet-sabp-template.c"
 
 /* Initialize the protocol and registered fields */
 static int proto_sabp = -1;
@@ -189,13 +190,15 @@ static int hf_sabp_successfulOutcome_value = -1;  /* SuccessfulOutcome_value */
 static int hf_sabp_unsuccessfulOutcome_value = -1;  /* UnsuccessfulOutcome_value */
 
 /*--- End of included file: packet-sabp-hf.c ---*/
-#line 55 "../../asn1/sabp/packet-sabp-template.c"
+#line 56 "../../asn1/sabp/packet-sabp-template.c"
 
 /* Initialize the subtree pointers */
 static int ett_sabp = -1;
 static int ett_sabp_e212 = -1;
 static int ett_sabp_cbs_data_coding = -1;
 static int ett_sabp_bcast_msg = -1;
+static int ett_sabp_cbs_serial_number = -1;
+static int ett_sabp_cbs_new_serial_number = -1;
 
 
 /*--- Included file: packet-sabp-ett.c ---*/
@@ -241,7 +244,7 @@ static gint ett_sabp_SuccessfulOutcome = -1;
 static gint ett_sabp_UnsuccessfulOutcome = -1;
 
 /*--- End of included file: packet-sabp-ett.c ---*/
-#line 63 "../../asn1/sabp/packet-sabp-template.c"
+#line 66 "../../asn1/sabp/packet-sabp-template.c"
 
 /* Global variables */
 static guint32 ProcedureCode;
@@ -477,8 +480,16 @@ dissect_sabp_Available_Bandwidth(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *
 
 static int
 dissect_sabp_Broadcast_Message_Content(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 211 "../../asn1/sabp/sabp.cnf"
+ tvbuff_t *parameter_tvb=NULL;
+
   offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
-                                     1, 9968, FALSE, NULL);
+                                     1, 9968, FALSE, &parameter_tvb);
+
+       if (!parameter_tvb)
+               return offset;
+        dissect_umts_cell_broadcast_message(parameter_tvb, actx->pinfo, proto_tree_get_root(tree));
+
 
   return offset;
 }
@@ -660,12 +671,10 @@ dissect_sabp_Data_Coding_Scheme(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *a
   offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
                                      8, 8, FALSE, &parameter_tvb);
 
-
        if (!parameter_tvb)
                return offset;
        subtree = proto_item_add_subtree(actx->created_item, ett_sabp_cbs_data_coding);
-       sms_encoding = dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree);
-
+       sms_encoding = dissect_cbs_data_coding_scheme(parameter_tvb, actx->pinfo, subtree, 0);
 
 
 
@@ -753,8 +762,17 @@ dissect_sabp_Failure_List(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U
 
 static int
 dissect_sabp_Message_Identifier(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 183 "../../asn1/sabp/sabp.cnf"
+ tvbuff_t *parameter_tvb=NULL;
+
   offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
-                                     16, 16, FALSE, NULL);
+                                     16, 16, FALSE, &parameter_tvb);
+
+       if (!parameter_tvb)
+               return offset;
+        dissect_cbs_message_identifier(parameter_tvb, tree, 0);
+
+
 
   return offset;
 }
@@ -763,8 +781,19 @@ dissect_sabp_Message_Identifier(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *a
 
 static int
 dissect_sabp_Serial_Number(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 191 "../../asn1/sabp/sabp.cnf"
+ tvbuff_t *parameter_tvb=NULL;
+ proto_tree *subtree;
+
   offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
-                                     16, 16, FALSE, NULL);
+                                     16, 16, FALSE, &parameter_tvb);
+
+       if (!parameter_tvb)
+               return offset;
+       subtree = proto_item_add_subtree(actx->created_item, ett_sabp_cbs_serial_number);
+        dissect_cbs_serial_number(parameter_tvb, subtree, 0);
+
+
 
   return offset;
 }
@@ -773,8 +802,19 @@ dissect_sabp_Serial_Number(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _
 
 static int
 dissect_sabp_New_Serial_Number(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 201 "../../asn1/sabp/sabp.cnf"
+ tvbuff_t *parameter_tvb=NULL;
+ proto_tree *subtree;
+
   offset = dissect_sabp_Serial_Number(tvb, offset, actx, tree, hf_index);
 
+       if (!parameter_tvb)
+               return offset;
+       subtree = proto_item_add_subtree(actx->created_item, ett_sabp_cbs_new_serial_number);
+        dissect_cbs_serial_number(parameter_tvb, subtree, 0);
+
+
+
   return offset;
 }
 
@@ -1682,7 +1722,7 @@ static int dissect_SABP_PDU_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto
 
 
 /*--- End of included file: packet-sabp-fn.c ---*/
-#line 87 "../../asn1/sabp/packet-sabp-template.c"
+#line 90 "../../asn1/sabp/packet-sabp-template.c"
 
 static int dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -2093,7 +2133,7 @@ void proto_register_sabp(void) {
         "UnsuccessfulOutcome_value", HFILL }},
 
 /*--- End of included file: packet-sabp-hfarr.c ---*/
-#line 177 "../../asn1/sabp/packet-sabp-template.c"
+#line 180 "../../asn1/sabp/packet-sabp-template.c"
   };
 
   /* List of subtrees */
@@ -2102,6 +2142,8 @@ void proto_register_sabp(void) {
                  &ett_sabp_e212,
                  &ett_sabp_cbs_data_coding,
                  &ett_sabp_bcast_msg,
+          &ett_sabp_cbs_serial_number,
+          &ett_sabp_cbs_new_serial_number,
 
 /*--- Included file: packet-sabp-ettarr.c ---*/
 #line 1 "../../asn1/sabp/packet-sabp-ettarr.c"
@@ -2146,7 +2188,7 @@ void proto_register_sabp(void) {
     &ett_sabp_UnsuccessfulOutcome,
 
 /*--- End of included file: packet-sabp-ettarr.c ---*/
-#line 186 "../../asn1/sabp/packet-sabp-template.c"
+#line 191 "../../asn1/sabp/packet-sabp-template.c"
   };
 
 
@@ -2229,7 +2271,7 @@ proto_reg_handoff_sabp(void)
 
 
 /*--- End of included file: packet-sabp-dis-tab.c ---*/
-#line 223 "../../asn1/sabp/packet-sabp-template.c"
+#line 228 "../../asn1/sabp/packet-sabp-template.c"
 
 }