For proto_tree_add_item(..., proto_xxx, ...)use ENC_NA as the encoding arg.
[obnox/wireshark/wip.git] / epan / dissectors / packet-sccp.c
index 48bc917b8081e7acb37c6a7d051102243d973547..09dfec9ad7e4a0e57d30447bd0eee7e1985918e2 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for Signalling Connection Control Part (SCCP) dissection
  *
  * It is hopefully compliant to:
- *   ANSI T1.112.3-1996
+ *   ANSI T1.112.3-2001
  *   ITU-T Q.713 7/1996
  *   YDN 038-1997 (Chinese ITU variant)
  *   JT-Q713 and NTT-Q713 (Japan)
@@ -10,7 +10,7 @@
  *   Note that Japan-specific GTT is incomplete; in particular, the specific
  *   TTs that are defined in TTC and NTT are not decoded in detail.
  *
- * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
+ * Copyright 2002, Jeff Morriss <jeff.morriss.ws [AT] gmail.com>
  *
  * $Id$
  *
@@ -39,7 +39,6 @@
 # include "config.h"
 #endif
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "packet-e164.h"
 #include "packet-e212.h"
 #include "packet-frame.h"
-#include "tap.h"
+#include <epan/tap.h>
+#include <address.h>
+
+/* function prototypes */
+void proto_reg_handoff_sccp(void);
 
 static Standard_Type decode_mtp3_standard;
+
 #define SCCP_SI 3
 
 #define SCCP_MSG_TYPE_OFFSET 0
@@ -73,55 +77,55 @@ static Standard_Type decode_mtp3_standard;
 
 /* Same as below but with names typed out */
 static const value_string sccp_message_type_values[] = {
-  { SCCP_MSG_TYPE_CR,     "Connection Request" },
-  { SCCP_MSG_TYPE_CC,     "Connection Confirm" },
-  { SCCP_MSG_TYPE_CREF,   "Connection Refused" },
-  { SCCP_MSG_TYPE_RLSD,   "Released" },
-  { SCCP_MSG_TYPE_RLC,    "Release Complete" },
-  { SCCP_MSG_TYPE_DT1,    "Data Form 1" },
-  { SCCP_MSG_TYPE_DT2,    "Data Form 2" },
-  { SCCP_MSG_TYPE_AK,     "Data Acknowledgement" },
-  { SCCP_MSG_TYPE_UDT,    "Unitdata" },
-  { SCCP_MSG_TYPE_UDTS,   "Unitdata Service" },
-  { SCCP_MSG_TYPE_ED,     "Expedited Data" },
-  { SCCP_MSG_TYPE_EA,     "Expedited Data Acknowledgement" },
-  { SCCP_MSG_TYPE_RSR,    "Reset Request" },
-  { SCCP_MSG_TYPE_RSC,    "Reset Confirmation" },
-  { SCCP_MSG_TYPE_ERR,    "Error" },
-  { SCCP_MSG_TYPE_IT,     "Inactivity Timer" },
-  { SCCP_MSG_TYPE_XUDT,   "Extended Unitdata" },
-  { SCCP_MSG_TYPE_XUDTS,  "Extended Unitdata Service" },
-  { SCCP_MSG_TYPE_LUDT,   "Long Unitdata (ITU)" },
-  { SCCP_MSG_TYPE_LUDTS,  "Long Unitdata Service (ITU)" },
-  { 0,                  NULL } };
+  { SCCP_MSG_TYPE_CR,          "Connection Request" },
+  { SCCP_MSG_TYPE_CC,          "Connection Confirm" },
+  { SCCP_MSG_TYPE_CREF,                "Connection Refused" },
+  { SCCP_MSG_TYPE_RLSD,                "Released" },
+  { SCCP_MSG_TYPE_RLC,         "Release Complete" },
+  { SCCP_MSG_TYPE_DT1,         "Data Form 1" },
+  { SCCP_MSG_TYPE_DT2,         "Data Form 2" },
+  { SCCP_MSG_TYPE_AK,          "Data Acknowledgement" },
+  { SCCP_MSG_TYPE_UDT,         "Unitdata" },
+  { SCCP_MSG_TYPE_UDTS,                "Unitdata Service" },
+  { SCCP_MSG_TYPE_ED,          "Expedited Data" },
+  { SCCP_MSG_TYPE_EA,          "Expedited Data Acknowledgement" },
+  { SCCP_MSG_TYPE_RSR,         "Reset Request" },
+  { SCCP_MSG_TYPE_RSC,         "Reset Confirmation" },
+  { SCCP_MSG_TYPE_ERR,         "Error" },
+  { SCCP_MSG_TYPE_IT,          "Inactivity Timer" },
+  { SCCP_MSG_TYPE_XUDT,                "Extended Unitdata" },
+  { SCCP_MSG_TYPE_XUDTS,       "Extended Unitdata Service" },
+  { SCCP_MSG_TYPE_LUDT,                "Long Unitdata" },
+  { SCCP_MSG_TYPE_LUDTS,       "Long Unitdata Service" },
+  { 0,                         NULL } };
 
 /* Same as above but in acronym form (for the Info column) */
 const value_string sccp_message_type_acro_values[] = {
-  { SCCP_MSG_TYPE_CR,     "CR" },
-  { SCCP_MSG_TYPE_CC,     "CC" },
-  { SCCP_MSG_TYPE_CREF,   "CREF" },
-  { SCCP_MSG_TYPE_RLSD,   "RLSD" },
-  { SCCP_MSG_TYPE_RLC,    "RLC" },
-  { SCCP_MSG_TYPE_DT1,    "DT1" },
-  { SCCP_MSG_TYPE_DT2,    "DT2" },
-  { SCCP_MSG_TYPE_AK,     "AK" },
-  { SCCP_MSG_TYPE_UDT,    "UDT" },
-  { SCCP_MSG_TYPE_UDTS,   "UDTS" },
-  { SCCP_MSG_TYPE_ED,     "ED" },
-  { SCCP_MSG_TYPE_EA,     "EA" },
-  { SCCP_MSG_TYPE_RSR,    "RSR" },
-  { SCCP_MSG_TYPE_RSC,    "RSC" },
-  { SCCP_MSG_TYPE_ERR,    "ERR" },
-  { SCCP_MSG_TYPE_IT,     "IT" },
-  { SCCP_MSG_TYPE_XUDT,   "XUDT" },
-  { SCCP_MSG_TYPE_XUDTS,  "XUDTS" },
-  { SCCP_MSG_TYPE_LUDT,   "LUDT" },
-  { SCCP_MSG_TYPE_LUDTS,  "LUDTS" },
-  { 0,                  NULL } };
-
-#define PARAMETER_LENGTH_LENGTH 1
-#define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
-#define PARAMETER_TYPE_LENGTH 1
+  { SCCP_MSG_TYPE_CR,          "CR" },
+  { SCCP_MSG_TYPE_CC,          "CC" },
+  { SCCP_MSG_TYPE_CREF,                "CREF" },
+  { SCCP_MSG_TYPE_RLSD,                "RLSD" },
+  { SCCP_MSG_TYPE_RLC,         "RLC" },
+  { SCCP_MSG_TYPE_DT1,         "DT1" },
+  { SCCP_MSG_TYPE_DT2,         "DT2" },
+  { SCCP_MSG_TYPE_AK,          "AK" },
+  { SCCP_MSG_TYPE_UDT,         "UDT" },
+  { SCCP_MSG_TYPE_UDTS,                "UDTS" },
+  { SCCP_MSG_TYPE_ED,          "ED" },
+  { SCCP_MSG_TYPE_EA,          "EA" },
+  { SCCP_MSG_TYPE_RSR,         "RSR" },
+  { SCCP_MSG_TYPE_RSC,         "RSC" },
+  { SCCP_MSG_TYPE_ERR,         "ERR" },
+  { SCCP_MSG_TYPE_IT,          "IT" },
+  { SCCP_MSG_TYPE_XUDT,                "XUDT" },
+  { SCCP_MSG_TYPE_XUDTS,       "XUDTS" },
+  { SCCP_MSG_TYPE_LUDT,                "LUDT" },
+  { SCCP_MSG_TYPE_LUDTS,       "LUDTS" },
+  { 0,                         NULL } };
+
+#define PARAMETER_LENGTH_LENGTH                        1
+#define PARAMETER_LONG_DATA_LENGTH_LENGTH      2
+#define PARAMETER_TYPE_LENGTH                  1
 
 #define PARAMETER_END_OF_OPTIONAL_PARAMETERS   0x00
 #define PARAMETER_DESTINATION_LOCAL_REFERENCE  0x01
@@ -141,7 +145,7 @@ const value_string sccp_message_type_acro_values[] = {
 #define PARAMETER_DATA                         0x0f
 #define PARAMETER_SEGMENTATION                 0x10
 #define PARAMETER_HOP_COUNTER                  0x11
-/* The below 2 are ITU only */
+/* Importance is ITU only */
 #define PARAMETER_IMPORTANCE                   0x12
 #define PARAMETER_LONG_DATA                    0x13
 /* ISNI is ANSI only */
@@ -167,7 +171,7 @@ static const value_string sccp_parameter_values[] = {
   { PARAMETER_SEGMENTATION,                    "Segmentation" },
   { PARAMETER_HOP_COUNTER,                     "Hop Counter" },
   { PARAMETER_IMPORTANCE,                      "Importance (ITU)" },
-  { PARAMETER_LONG_DATA,                       "Long Data (ITU)" },
+  { PARAMETER_LONG_DATA,                       "Long Data" },
   { PARAMETER_ISNI,                            "Intermediate Signaling Network Identification (ANSI)" },
   { 0,                                          NULL } };
 
@@ -205,15 +209,18 @@ static const value_string sccp_national_indicator_values[] = {
   { 0x1,  "Address coded to National standard" },
   { 0,    NULL } };
 
+#define ROUTE_ON_GT            0x0
+#define ROUTE_ON_SSN           0x1
+#define ROUTING_INDICATOR_SHIFT        6
 static const value_string sccp_routing_indicator_values[] = {
-  { 0x0, "Route on GT" },
-  { 0x1, "Route on SSN" },
-  { 0,   NULL } };
-
-#define AI_GTI_NO_GT           0x0
-#define ITU_AI_GTI_NAI         0x1
-#define AI_GTI_TT              0x2
-#define ITU_AI_GTI_TT_NP_ES    0x3
+  { ROUTE_ON_GT,  "Route on GT" },
+  { ROUTE_ON_SSN, "Route on SSN" },
+  { 0,           NULL } };
+
+#define AI_GTI_NO_GT                   0x0
+#define ITU_AI_GTI_NAI                 0x1
+#define AI_GTI_TT                      0x2
+#define ITU_AI_GTI_TT_NP_ES            0x3
 #define ITU_AI_GTI_TT_NP_ES_NAI        0x4
 static const value_string sccp_itu_global_title_indicator_values[] = {
   { AI_GTI_NO_GT,              "No Global Title" },
@@ -242,8 +249,8 @@ static const value_string sccp_ai_ssni_values[] = {
   { 0x0,  "SSN not present" },
   { 0,    NULL } };
 
-#define ADDRESS_SSN_LENGTH    1
-#define INVALID_SSN 0xff
+#define ADDRESS_SSN_LENGTH     1
+#define INVALID_SSN            0xff
   /* Some values from 3GPP TS 23.003 */
   /*  Japan TTC and NTT define a lot of SSNs, some of which conflict with
    *  these.  They are not added for now.
@@ -341,9 +348,9 @@ const value_string sccp_address_signal_values[] = {
 /* * * * * * * * * * * * * * * * * * * * * * * * * *
  * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
  * * * * * * * * * * * * * * * * * * * * * * * * * */
-#define GT_NP_MASK 0xf0
-#define GT_NP_SHIFT 4
-#define GT_NP_ES_LENGTH 1
+#define GT_NP_MASK             0xf0
+#define GT_NP_SHIFT            4
+#define GT_NP_ES_LENGTH                1
 #define GT_NP_UNKNOWN          0x00
 #define GT_NP_ISDN             0x01
 #define GT_NP_GENERIC_RESERVED 0x02
@@ -393,8 +400,9 @@ static const value_string sccp_es_values[] = {
 /* Address signals above */
 
 
-#define CLASS_CLASS_MASK 0xf
-#define CLASS_SPARE_HANDLING_MASK 0xf0
+#define CLASS_CLASS_MASK               0xf
+#define CLASS_SPARE_HANDLING_MASK      0xf0
+#define CLASS_SPARE_HANDLING_SHIFT     4
 static const value_string sccp_class_handling_values [] = {
   { 0x0,  "No special options" },
   { 0x8,  "Return message on error" },
@@ -412,8 +420,8 @@ static const value_string sccp_segmenting_reassembling_values [] = {
   { 0,                 NULL } };
 
 
-#define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
-#define RSN_MASK                       0xfe
+#define RECEIVE_SEQUENCE_NUMBER_LENGTH         1
+#define RSN_MASK                               0xfe
 
 #define SEQUENCING_SEGMENTING_LENGTH           2
 #define SEQUENCING_SEGMENTING_SSN_LENGTH       1
@@ -585,6 +593,7 @@ static int hf_sccp_variable_pointer1 = -1;
 static int hf_sccp_variable_pointer2 = -1;
 static int hf_sccp_variable_pointer3 = -1;
 static int hf_sccp_optional_pointer = -1;
+static int hf_sccp_param_length = -1;
 static int hf_sccp_ssn = -1;
 static int hf_sccp_gt_digits = -1;
 
@@ -611,6 +620,7 @@ static int hf_sccp_called_gt_tt = -1;
 static int hf_sccp_called_gt_np = -1;
 static int hf_sccp_called_gt_es = -1;
 static int hf_sccp_called_gt_digits = -1;
+static int hf_sccp_called_gt_digits_length = -1;
 
 /* Calling party address */
 static int hf_sccp_calling_national_indicator = -1;
@@ -635,6 +645,7 @@ static int hf_sccp_calling_gt_tt = -1;
 static int hf_sccp_calling_gt_np = -1;
 static int hf_sccp_calling_gt_es = -1;
 static int hf_sccp_calling_gt_digits = -1;
+static int hf_sccp_calling_gt_digits_length = -1;
 
 /* Other parameter values */
 static int hf_sccp_dlr = -1;
@@ -664,6 +675,8 @@ static int hf_sccp_ansi_isni_iri = -1;
 static int hf_sccp_ansi_isni_ti = -1;
 static int hf_sccp_ansi_isni_netspec = -1;
 static int hf_sccp_ansi_isni_counter = -1;
+static int hf_sccp_ansi_isni_network = -1;
+static int hf_sccp_ansi_isni_cluster = -1;
 static int hf_sccp_xudt_msg_fragments = -1;
 static int hf_sccp_xudt_msg_fragment = -1;
 static int hf_sccp_xudt_msg_fragment_overlap = -1;
@@ -671,7 +684,9 @@ static int hf_sccp_xudt_msg_fragment_overlap_conflicts = -1;
 static int hf_sccp_xudt_msg_fragment_multiple_tails = -1;
 static int hf_sccp_xudt_msg_fragment_too_long_fragment = -1;
 static int hf_sccp_xudt_msg_fragment_error = -1;
+static int hf_sccp_xudt_msg_fragment_count = -1;
 static int hf_sccp_xudt_msg_reassembled_in = -1;
+static int hf_sccp_xudt_msg_reassembled_length = -1;
 static int hf_sccp_assoc_msg = -1;
 static int hf_sccp_assoc_id = -1;
 
@@ -681,22 +696,23 @@ static gint ett_sccp_called = -1;
 static gint ett_sccp_called_ai = -1;
 static gint ett_sccp_called_pc = -1;
 static gint ett_sccp_called_gt = -1;
+static gint ett_sccp_called_gt_digits = -1;
 static gint ett_sccp_calling = -1;
 static gint ett_sccp_calling_ai = -1;
 static gint ett_sccp_calling_pc = -1;
 static gint ett_sccp_calling_gt = -1;
+static gint ett_sccp_calling_gt_digits = -1;
 static gint ett_sccp_sequencing_segmenting = -1;
 static gint ett_sccp_segmentation = -1;
 static gint ett_sccp_ansi_isni_routing_control = -1;
 static gint ett_sccp_xudt_msg_fragment = -1;
 static gint ett_sccp_xudt_msg_fragments = -1;
 static gint ett_sccp_assoc = -1;
-static gint ett_sccp_digits = -1;
 
 /* Declarations to desegment XUDT Messages */
 static gboolean sccp_xudt_desegment = TRUE;
-
 static gboolean show_key_params = FALSE;
+static gboolean set_addresses = FALSE;
 
 static int sccp_tap = -1;
 
@@ -713,8 +729,11 @@ static const fragment_items sccp_xudt_msg_frag_items = {
        &hf_sccp_xudt_msg_fragment_multiple_tails,
        &hf_sccp_xudt_msg_fragment_too_long_fragment,
        &hf_sccp_xudt_msg_fragment_error,
+       &hf_sccp_xudt_msg_fragment_count,
        /* Reassembled in field */
        &hf_sccp_xudt_msg_reassembled_in,
+       /* Reassembled length field */
+       &hf_sccp_xudt_msg_reassembled_length,
        /* Tag */
        "SCCP XUDT Message fragments"
 };
@@ -750,15 +769,18 @@ static dissector_handle_t bssap_handle;
 static dissector_handle_t gsmmap_handle;
 static dissector_handle_t camel_handle;
 static dissector_handle_t inap_handle;
+static dissector_handle_t default_handle;
+
+static const char *default_payload=NULL;
 
 static const value_string sccp_users_vals[] = {
-       { SCCP_USER_DATA, "Data"},
-       { SCCP_USER_TCAP, "TCAP"},
-       { SCCP_USER_RANAP, "RANAP"},
-       { SCCP_USER_BSSAP, "BSSAP"},
-       { SCCP_USER_GSMMAP, "GSM MAP"},
-       { SCCP_USER_CAMEL, "CAMEL"},
-       { SCCP_USER_INAP, "INAP"},
+       { SCCP_USER_DATA,       "Data"},
+       { SCCP_USER_TCAP,       "TCAP"},
+       { SCCP_USER_RANAP,      "RANAP"},
+       { SCCP_USER_BSSAP,      "BSSAP"},
+       { SCCP_USER_GSMMAP,     "GSM MAP"},
+       { SCCP_USER_CAMEL,      "CAMEL"},
+       { SCCP_USER_INAP,       "INAP"},
        { 0, NULL }
 };
 
@@ -786,17 +808,19 @@ static dissector_table_t sccp_ssn_dissector_table;
 static emem_tree_t* assocs = NULL;
 static sccp_assoc_info_t* assoc;
 static sccp_msg_info_t* sccp_msg;
-static sccp_assoc_info_t no_assoc = {0,0,0,0,0,FALSE,FALSE,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL};
+static sccp_assoc_info_t no_assoc = {0,0,0,0,0,FALSE,FALSE,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL,0};
 static gboolean trace_sccp = FALSE;
 static guint32 next_assoc_id = 0;
 
 static const value_string assoc_protos[] = {
-       {  SCCP_PLOAD_BSSAP, "BSSAP" },
-       {  SCCP_PLOAD_RANAP, "RANAP" },
-       { 0 , NULL }
+       { SCCP_PLOAD_BSSAP,     "BSSAP" },
+       { SCCP_PLOAD_RANAP,     "RANAP" },
+       { 0,                    NULL }
 };
 
-static sccp_assoc_info_t* new_assoc(guint32 calling, guint32 called){
+static sccp_assoc_info_t *
+new_assoc(guint32 calling, guint32 called)
+{
        sccp_assoc_info_t* a = se_alloc0(sizeof(sccp_assoc_info_t));
 
        a->id = next_assoc_id++;
@@ -814,11 +838,15 @@ static sccp_assoc_info_t* new_assoc(guint32 calling, guint32 called){
        return a;
 }
 
-void reset_sccp_assoc(void) {
+void
+reset_sccp_assoc(void)
+{
        assoc = NULL;
 }
 
-sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint msg_type) {
+sccp_assoc_info_t *
+get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_lr, guint32 dst_lr, guint msg_type)
+{
     guint32 opck, dpck;
     address* opc = &(pinfo->src);
     address* dpc = &(pinfo->dst);
@@ -827,8 +855,8 @@ sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_
     if(assoc)
         return assoc;
 
-    opck = opc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(address_to_str(opc));
-    dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(address_to_str(dpc));
+    opck = opc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(ep_address_to_str(opc));
+    dpck = dpc->type == AT_SS7PC ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(ep_address_to_str(dpc));
 
 
     switch (msg_type) {
@@ -836,12 +864,15 @@ sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_
         {
             /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr  */
             emem_tree_key_t bw_key[] = {
-                {1, &dpck}, {1, &opck}, {1, &src_lr}, {0, NULL}
+                {1, &dpck},
+               {1, &opck},
+               {1, &src_lr},
+               {0, NULL}
             };
 
             if (! ( assoc = se_tree_lookup32_array(assocs,bw_key) ) && ! pinfo->fd->flags.visited ) {
-                assoc = new_assoc(opck,dpck);
-                se_tree_insert32_array(assocs,bw_key,assoc);
+                assoc = new_assoc(opck, dpck);
+                se_tree_insert32_array(assocs, bw_key, assoc);
                 assoc->has_bw_key = TRUE;
             }
 
@@ -858,11 +889,11 @@ sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_
                 {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
             };
 
-            if ( ( assoc = se_tree_lookup32_array(assocs,bw_key) ) ) {
+            if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) {
                 goto got_assoc;
             }
 
-            if ( (assoc = se_tree_lookup32_array(assocs,fw_key) ) ) {
+            if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) {
                 goto got_assoc;
             }
 
@@ -873,12 +904,12 @@ sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_
             pinfo->p2p_dir = P2P_DIR_RECV;
 
             if ( ! pinfo->fd->flags.visited && ! assoc->has_bw_key ) {
-                se_tree_insert32_array(assocs,bw_key,assoc);
+                se_tree_insert32_array(assocs, bw_key, assoc);
                 assoc->has_bw_key = TRUE;
             }
 
             if ( ! pinfo->fd->flags.visited && ! assoc->has_fw_key ) {
-                se_tree_insert32_array(assocs,fw_key,assoc);
+                se_tree_insert32_array(assocs, fw_key, assoc);
                 assoc->has_fw_key = TRUE;
             }
 
@@ -892,27 +923,27 @@ sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_
             emem_tree_key_t fw_key[] = {
                 {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
             };
-            if ( ( assoc = se_tree_lookup32_array(assocs,bw_key) ) ) {
+            if ( ( assoc = se_tree_lookup32_array(assocs, bw_key) ) ) {
                 goto got_assoc_rlc;
             }
 
-            if ( (assoc = se_tree_lookup32_array(assocs,fw_key) ) ) {
+            if ( (assoc = se_tree_lookup32_array(assocs, fw_key) ) ) {
                 goto got_assoc_rlc;
             }
 
-            assoc = new_assoc(dpck,opck);
+            assoc = new_assoc(dpck, opck);
 
      got_assoc_rlc:
 
             pinfo->p2p_dir = P2P_DIR_SENT;
 
             if ( ! pinfo->fd->flags.visited && ! assoc->has_bw_key ) {
-                se_tree_insert32_array(assocs,bw_key,assoc);
+                se_tree_insert32_array(assocs, bw_key, assoc);
                 assoc->has_bw_key = TRUE;
             }
 
             if ( ! pinfo->fd->flags.visited && ! assoc->has_fw_key ) {
-                se_tree_insert32_array(assocs,fw_key,assoc);
+                se_tree_insert32_array(assocs, fw_key, assoc);
                 assoc->has_fw_key = TRUE;
             }
             break;
@@ -923,7 +954,7 @@ sccp_assoc_info_t* get_sccp_assoc(packet_info* pinfo, guint offset, guint32 src_
                 {1, &opck}, {1, &dpck}, {1, &dst_lr}, {0, NULL}
             };
 
-            assoc = se_tree_lookup32_array(assocs,key);
+            assoc = se_tree_lookup32_array(assocs, key);
 
             if (assoc) {
                 if (assoc->calling_dpc == dpck) {
@@ -1011,7 +1042,7 @@ dissect_sccp_dlr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
   lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, dlr);
   PROTO_ITEM_SET_HIDDEN(lr_item);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "DLR=%d ", dlr);
 }
 
@@ -1032,7 +1063,7 @@ dissect_sccp_slr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
   lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, slr);
   PROTO_ITEM_SET_HIDDEN(lr_item);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "SLR=%d ", slr);
 }
 
@@ -1042,29 +1073,32 @@ dissect_sccp_slr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
         || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
         || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
 
-static proto_item *
-dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
-                                   guint length, gboolean even_length,
-                                   gboolean called)
+static proto_tree *
+dissect_sccp_gt_address_information(tvbuff_t *tvb, packet_info *pinfo,
+                                   proto_tree *tree, guint length,
+                                   gboolean even_length, gboolean called,
+                                   gboolean route_on_gt)
 {
   guint offset = 0;
   guint8 odd_signal, even_signal;
-  proto_item *digits_item, *hidden_item;
-  char gt_digits[GT_MAX_SIGNALS+1] = { 0 };
+  proto_item *digits_item;
+  proto_tree *digits_tree;
+  char *gt_digits;
 
-  while(offset < length)
-  {
+  gt_digits = ep_alloc0(GT_MAX_SIGNALS+1);
+
+  while(offset < length) {
     odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
     even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
     even_signal >>= GT_EVEN_SIGNAL_SHIFT;
 
     g_strlcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
-                                "Unknown"), GT_MAX_SIGNALS+1);
+                                "Unknown: %d"), GT_MAX_SIGNALS+1);
 
     /* If the last signal is NOT filler */
     if (offset != (length - 1) || even_length == TRUE)
       g_strlcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
-                                  "Unknown"), GT_MAX_SIGNALS+1);
+                                  "Unknown: %d"), GT_MAX_SIGNALS+1);
 
     offset += GT_SIGNAL_LENGTH;
   }
@@ -1075,31 +1109,38 @@ dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
        *gt_ptr  = (guint8 *)ep_strdup(gt_digits);
   }
 
-  digits_item = proto_tree_add_string_format(tree,
-                                            called ? hf_sccp_called_gt_digits
-                                                   : hf_sccp_calling_gt_digits,
-                                            tvb, 0, length, gt_digits,
-                                            "Address information (digits): %s",
-                                            gt_digits);
+  digits_item = proto_tree_add_string(tree, called ? hf_sccp_called_gt_digits
+                                                  : hf_sccp_calling_gt_digits,
+                                     tvb, 0, length, gt_digits);
+  digits_tree = proto_item_add_subtree(digits_item, called ? ett_sccp_called_gt_digits
+                                                          : ett_sccp_calling_gt_digits);
 
-  hidden_item = proto_tree_add_string(tree, hf_sccp_gt_digits, tvb, 0, length,
-                              gt_digits);
-  PROTO_ITEM_SET_HIDDEN(hidden_item);
+  if (set_addresses && route_on_gt) {
+    if (called) {
+      SET_ADDRESS(&pinfo->dst, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits);
+    } else {
+      SET_ADDRESS(&pinfo->src, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits);
+    }
+  }
 
-  return digits_item;
+  proto_tree_add_string(digits_tree, hf_sccp_gt_digits, tvb, 0, length, gt_digits);
+  proto_tree_add_uint(digits_tree, called ? hf_sccp_called_gt_digits_length
+                                         : hf_sccp_calling_gt_digits_length,
+                     tvb, 0, length, (guint32)strlen(gt_digits));
+
+  return digits_tree;
 }
 
 static void
-dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
-                         guint8 gti, gboolean called)
+dissect_sccp_global_title(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length,
+                         guint8 gti, gboolean route_on_gt, gboolean called)
 {
-  proto_item *gt_item = 0;
-  proto_item *digits_item = 0;
-  proto_tree *gt_tree = 0;
-  proto_tree *digits_tree = 0;
+  proto_item *gt_item;
+  proto_tree *gt_tree;
+  proto_tree *digits_tree;
   tvbuff_t *signals_tvb;
   guint offset = 0;
-  guint8 odd_even, nai = 0, tt, np = 0, es;
+  guint8 odd_even, nai = 0, np = 0, es;
   gboolean even = TRUE;
 
   /* Shift GTI to where we can work with it */
@@ -1117,10 +1158,9 @@ dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
          (gti == ITU_AI_GTI_TT_NP_ES || gti == ITU_AI_GTI_TT_NP_ES_NAI)) ||
       (decode_mtp3_standard == ANSI_STANDARD && gti == ANSI_AI_GTI_TT_NP_ES)) {
 
-    tt = tvb_get_guint8(tvb, offset);
-    proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
+    proto_tree_add_item(gt_tree, called ? hf_sccp_called_gt_tt
                                        : hf_sccp_calling_gt_tt,
-                       tvb, offset, GT_TT_LENGTH, tt);
+                       tvb, offset, GT_TT_LENGTH, ENC_NA);
     offset += GT_TT_LENGTH;
   }
 
@@ -1177,24 +1217,20 @@ dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
   signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
                               (length - offset));
 
-  digits_item = dissect_sccp_gt_address_information(signals_tvb, gt_tree,
+  digits_tree = dissect_sccp_gt_address_information(signals_tvb, pinfo, gt_tree,
                                                    (length - offset),
-                                                   even, called);
+                                                   even, called, route_on_gt);
 
   /* Display the country code (if we can) */
   switch(np >> GT_NP_SHIFT) {
        case GT_NP_ISDN:
        case GT_NP_ISDN_MOBILE:
                if(nai == GT_NAI_INTERNATIONAL_NUM) {
-                       digits_tree = proto_item_add_subtree(digits_item,
-                                                            ett_sccp_digits);
                        dissect_e164_cc(signals_tvb, digits_tree, 0, TRUE);
                }
        break;
        case GT_NP_LAND_MOBILE:
-               digits_tree = proto_item_add_subtree(digits_item,
-                                                    ett_sccp_digits);
-               dissect_e212_mcc_mnc(signals_tvb, digits_tree, 0);
+               dissect_e212_mcc_mnc_in_address(signals_tvb, pinfo, digits_tree, 0);
        break;
        default:
        break;
@@ -1205,25 +1241,25 @@ static int
 dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint offset,
                      gboolean called)
 {
-  int *hf_pc;
+  int hf_pc;
 
   if (decode_mtp3_standard == ANSI_STANDARD)
   {
     if (called)
-      hf_pc = &hf_sccp_called_ansi_pc;
+      hf_pc = hf_sccp_called_ansi_pc;
     else
-      hf_pc = &hf_sccp_calling_ansi_pc;
+      hf_pc = hf_sccp_calling_ansi_pc;
   } else /* CHINESE_ITU_STANDARD */ {
     if (called)
-      hf_pc = &hf_sccp_called_chinese_pc;
+      hf_pc = hf_sccp_called_chinese_pc;
     else
-      hf_pc = &hf_sccp_calling_chinese_pc;
+      hf_pc = hf_sccp_calling_chinese_pc;
   }
 
   /* create and fill the PC tree */
   dissect_mtp3_3byte_pc(tvb, offset, call_tree,
                        called ? ett_sccp_called_pc : ett_sccp_calling_pc,
-                       *hf_pc,
+                       hf_pc,
                        called ? hf_sccp_called_pc_network : hf_sccp_calling_pc_network,
                        called ? hf_sccp_called_pc_cluster : hf_sccp_calling_pc_cluster,
                        called ? hf_sccp_called_pc_member  : hf_sccp_calling_pc_member,
@@ -1260,15 +1296,15 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
   const char *tcap_ssn_dissector_short_name = NULL;
 
   call_item = proto_tree_add_text(tree, tvb, 0, length,
-                                   "%s Party address (%u byte%s)",
-                                   called ? "Called" : "Calling", length,
-                                   plurality(length, "", "s"));
+                                 "%s Party address (%u byte%s)",
+                                 called ? "Called" : "Calling", length,
+                                 plurality(length, "", "s"));
   call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
                                                       : ett_sccp_calling);
 
   call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
-                                      ADDRESS_INDICATOR_LENGTH,
-                                      "Address Indicator");
+                                    ADDRESS_INDICATOR_LENGTH,
+                                    "Address Indicator");
   call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
                                                             : ett_sccp_calling_ai);
 
@@ -1279,7 +1315,7 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
                                                           : hf_sccp_calling_national_indicator,
                                      tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
     if (national == 0)
-          expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_NOTE, "Address is coded to "
+          expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_WARN, "Address is coded to "
                                 "international standards.  This doesn't normally happen in ANSI "
                                 "networks.");
   }
@@ -1288,6 +1324,8 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
   proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
                                           : hf_sccp_calling_routing_indicator,
                      tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
+  /* Only shift off the other bits after adding the item */
+  routing_ind >>= ROUTING_INDICATOR_SHIFT;
 
   gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
 
@@ -1301,9 +1339,13 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
                        tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
 
     ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
-    proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
-                                            : hf_sccp_calling_itu_ssn_indicator,
-                       tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+    expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
+                                                          : hf_sccp_calling_itu_ssn_indicator,
+                                     tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+    if (routing_ind == ROUTE_ON_SSN && ssni == 0) {
+      expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+                            "Message is routed on SSN, but SSN is not present");
+    }
 
     pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
@@ -1323,10 +1365,10 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
         }
         proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc
                                               : hf_sccp_calling_itu_pc,
-                            tvb, offset, ITU_PC_LENGTH, TRUE);
+                            tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
         offset += ITU_PC_LENGTH;
 
-      }else if (decode_mtp3_standard == JAPAN_STANDARD) {
+      } else if (decode_mtp3_standard == JAPAN_STANDARD) {
 
         if (length < offset + JAPAN_PC_LENGTH){
           expert_item = proto_tree_add_text(call_tree, tvb, 0, -1, "Wrong length indicated (%u) should be at least %u, PC is %u octets", length, offset + JAPAN_PC_LENGTH, JAPAN_PC_LENGTH);
@@ -1336,7 +1378,7 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
         }
         proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc
                                               : hf_sccp_calling_japan_pc,
-                            tvb, offset, JAPAN_PC_LENGTH, TRUE);
+                            tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
 
         offset += JAPAN_PC_LENGTH;
 
@@ -1357,13 +1399,18 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
     if (ssni) {
       ssn = tvb_get_guint8(tvb, offset);
 
+      if (routing_ind == ROUTE_ON_SSN && ssn == 0) {
+       expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+                              "Message is routed on SSN, but SSN is zero (unspecified)");
+      }
+
       if (called && assoc)
        assoc->called_ssn = ssn;
       else if (assoc)
        assoc->calling_ssn = ssn;
 
       if (is_connectionless(message_type) && sccp_msg) {
-       guintssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
+       guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
 
        *ssn_ptr  = ssn;
       }
@@ -1380,30 +1427,27 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
       /* Get the dissector handle of the dissector registered for this ssn
        * And print it's name.
        */
-      ssn_dissector = dissector_get_port_handle(sccp_ssn_dissector_table, ssn);
+      ssn_dissector = dissector_get_uint_handle(sccp_ssn_dissector_table, ssn);
 
       if (ssn_dissector) {
-         ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector);
+       ssn_dissector_short_name = dissector_handle_get_short_name(ssn_dissector);
 
-         if(ssn_dissector_short_name) {
-             item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name);
-             PROTO_ITEM_SET_GENERATED(item);
+       if(ssn_dissector_short_name) {
+         item = proto_tree_add_text(call_tree, tvb, offset - 1, ADDRESS_SSN_LENGTH, "Linked to %s", ssn_dissector_short_name);
+         PROTO_ITEM_SET_GENERATED(item);
 
-             if (g_ascii_strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) {
-                     tcap_ssn_dissector = get_itu_tcap_subdissector(ssn);
+         if (g_ascii_strncasecmp("TCAP", ssn_dissector_short_name, 4)== 0) {
+           tcap_ssn_dissector = get_itu_tcap_subdissector(ssn);
 
-                     if(tcap_ssn_dissector){
-                         tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector);
-                         proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name);
-                     }
-             }
-         } /* short name */
+           if(tcap_ssn_dissector) {
+             tcap_ssn_dissector_short_name = dissector_handle_get_short_name(tcap_ssn_dissector);
+             proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_short_name);
+           }
+         }
+       } /* short name */
       } /* ssn_dissector */
     } /* ssni */
 
-    if (!tree)
-      return;  /* got SSN, that's all we need here... */
-
     /* Dissect GT (if present) */
     if (gti != AI_GTI_NO_GT) {
       if (length < offset)
@@ -1411,8 +1455,8 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
 
       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
                              (length - offset));
-      dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
-                               called);
+      dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti,
+                               (routing_ind == ROUTE_ON_GT), called);
     }
 
   } else if (decode_mtp3_standard == ANSI_STANDARD) {
@@ -1427,9 +1471,13 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
                        tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
 
     ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
-    proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
-                                            : hf_sccp_calling_ansi_ssn_indicator,
-                       tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+    expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
+                                                          : hf_sccp_calling_ansi_ssn_indicator,
+                                     tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+    if (routing_ind == ROUTE_ON_SSN && ssni == 0) {
+      expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+                            "Message is routed on SSN, but SSN is not present");
+    }
 
     offset = ADDRESS_INDICATOR_LENGTH;
 
@@ -1437,30 +1485,33 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
     if (ssni) {
       ssn = tvb_get_guint8(tvb, offset);
 
-      if (called && assoc)
+      if (routing_ind == ROUTE_ON_SSN && ssn == 0) {
+       expert_add_info_format(pinfo, expert_item, PI_PROTOCOL, PI_WARN,
+                              "Message is routed on SSN, but SSN is zero (unspecified)");
+      }
+
+      if (called && assoc) {
        assoc->called_ssn = ssn;
-      else if (assoc)
+      } else if (assoc) {
        assoc->calling_ssn = ssn;
+      }
 
-        if (is_connectionless(message_type) && sccp_msg) {
-               guint* ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
+      if (is_connectionless(message_type) && sccp_msg) {
+       guint *ssn_ptr = called ? &(sccp_msg->data.ud.called_ssn) : &(sccp_msg->data.ud.calling_ssn);
 
-               *ssn_ptr  = ssn;
-       }
+       *ssn_ptr  = ssn;
+      }
 
-       proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
+      proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
                                            : hf_sccp_calling_ssn,
                          tvb, offset, ADDRESS_SSN_LENGTH, ssn);
       hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset,
-                                ADDRESS_SSN_LENGTH, ssn);
+                                       ADDRESS_SSN_LENGTH, ssn);
       PROTO_ITEM_SET_HIDDEN(hidden_item);
 
       offset += ADDRESS_SSN_LENGTH;
     }
 
-    if (!tree)
-      return;  /* got SSN, that's all we need here... */
-
     /* Dissect PC (if present) */
     if (pci) {
       offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
@@ -1469,11 +1520,11 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *
     /* Dissect GT (if present) */
     if (gti != AI_GTI_NO_GT) {
       if (length < offset)
-       return;
+                 return;
       gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
                              (length - offset));
-      dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
-                               called);
+      dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti,
+                               (routing_ind == ROUTE_ON_GT), called);
     }
 
   }
@@ -1495,23 +1546,68 @@ dissect_sccp_calling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 static void
 dissect_sccp_class_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
 {
-  guint8 class, handling;
+  guint8 class;
+  proto_item *pi;
+  gboolean invalid_class = FALSE;
 
   if (length != 1) {
-    proto_item *expert_item;
-    expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
-    expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
-    PROTO_ITEM_SET_GENERATED(expert_item);
+    pi = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
+    expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", length);
+    PROTO_ITEM_SET_GENERATED(pi);
     return;
   }
 
   class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
-  handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
+  pi = proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
+
+  switch(message_type) {
+  case SCCP_MSG_TYPE_DT1:
+    if (class != 2)
+      invalid_class = TRUE;
+    break;
+  case SCCP_MSG_TYPE_DT2:
+  case SCCP_MSG_TYPE_AK:
+  case SCCP_MSG_TYPE_ED:
+  case SCCP_MSG_TYPE_EA:
+  case SCCP_MSG_TYPE_RSR:
+  case SCCP_MSG_TYPE_RSC:
+    if (class != 3)
+      invalid_class = TRUE;
+    break;
+  case SCCP_MSG_TYPE_CR:
+  case SCCP_MSG_TYPE_CC:
+  case SCCP_MSG_TYPE_CREF:
+  case SCCP_MSG_TYPE_RLSD:
+  case SCCP_MSG_TYPE_RLC:
+  case SCCP_MSG_TYPE_ERR:
+  case SCCP_MSG_TYPE_IT:
+    if (class != 2 && class != 3)
+      invalid_class = TRUE;
+    break;
+  case SCCP_MSG_TYPE_UDT:
+  case SCCP_MSG_TYPE_UDTS:
+  case SCCP_MSG_TYPE_XUDT:
+  case SCCP_MSG_TYPE_XUDTS:
+  case SCCP_MSG_TYPE_LUDT:
+  case SCCP_MSG_TYPE_LUDTS:
+    if (class != 0 && class != 1)
+      invalid_class = TRUE;
+    break;
+  }
+
+  if (invalid_class)
+    expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Unexpected message class for this message type");
 
-  proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
+  if (class == 0 || class == 1) {
+    guint8 handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
 
-  if (class == 0 || class == 1)
-    proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
+    pi = proto_tree_add_item(tree, hf_sccp_handling, tvb, 0, length, ENC_NA);
+    handling >>= CLASS_SPARE_HANDLING_SHIFT;
+
+    if (match_strval(handling, sccp_class_handling_values) == NULL) {
+      expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid message handling");
+    }
+  }
 }
 
 static void
@@ -1525,7 +1621,7 @@ dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, packet_info *pinfo, pr
     return;
   }
 
-  proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, FALSE);
+  proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, ENC_BIG_ENDIAN);
 }
 
 static void
@@ -1548,17 +1644,16 @@ dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, packet_info *pinfo, pr
 static void
 dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint length)
 {
-  guint8 rsn, ssn, more;
+  guint8 rsn, ssn;
   proto_item *param_item;
   proto_tree *param_tree;
 
   ssn = tvb_get_guint8(tvb, 0) >> 1;
   rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
-  more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
 
   param_item = proto_tree_add_text(tree, tvb, 0, length, "%s",
                                   val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
-                                             sccp_parameter_values, "Unknown"));
+                                             sccp_parameter_values, "Unknown: %d"));
   param_tree = proto_item_add_subtree(param_item,
                                      ett_sccp_sequencing_segmenting);
 
@@ -1567,16 +1662,14 @@ dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint
   proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
                      SEQUENCING_SEGMENTING_SSN_LENGTH,
                      SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
-  proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
+  proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
                      SEQUENCING_SEGMENTING_SSN_LENGTH,
-                     SEQUENCING_SEGMENTING_RSN_LENGTH, more);
+                     SEQUENCING_SEGMENTING_RSN_LENGTH, ENC_NA);
 }
 
 static void
 dissect_sccp_credit_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
 {
-  guint8 credit;
-
   if (length != 1) {
     proto_item *expert_item;
     expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
@@ -1585,8 +1678,7 @@ dissect_sccp_credit_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
     return;
   }
 
-  credit = tvb_get_guint8(tvb, 0);
-  proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
+  proto_tree_add_item(tree, hf_sccp_credit, tvb, 0, length, ENC_NA);
 }
 
 static void
@@ -1605,7 +1697,7 @@ dissect_sccp_release_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
   cause = tvb_get_guint8(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
 }
 
@@ -1625,7 +1717,7 @@ dissect_sccp_return_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
   cause = tvb_get_guint8(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
 }
 
@@ -1645,7 +1737,7 @@ dissect_sccp_reset_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr
   cause = tvb_get_guint8(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
 }
 
@@ -1665,7 +1757,7 @@ dissect_sccp_error_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr
   cause = tvb_get_guint8(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
 }
 
@@ -1685,7 +1777,7 @@ dissect_sccp_refusal_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
   cause = tvb_get_guint8(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
 
-  if (show_key_params && check_col(pinfo->cinfo, COL_INFO))
+  if (show_key_params)
     col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", cause);
 }
 
@@ -1735,43 +1827,49 @@ dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         gboolean uses_tcap = FALSE;
 
        for (i=0; i < num_sccp_users; i++) {
-               sccp_user_t* u = &(sccp_users[i]);
-
-               if (!dpc || dpc->ni != u->ni) continue;
-
-               if (value_is_in_range(u->called_ssn, ssn)  && value_is_in_range(u->called_pc, dpc->pc) ) {
-                       handle = *(u->handlep);
-                       uses_tcap = u->uses_tcap;
-                       break;
-               } else if (value_is_in_range(u->called_ssn, other_ssn) && opc && value_is_in_range(u->called_pc, opc->pc) ) {
-                       handle = *(u->handlep);
-                       uses_tcap = u->uses_tcap;
-                       break;
-               }
+           sccp_user_t* u = &(sccp_users[i]);
+
+           if (!dpc || dpc->ni != u->ni) continue;
+
+           if (value_is_in_range(u->called_ssn, ssn)  && value_is_in_range(u->called_pc, dpc->pc) ) {
+               handle = *(u->handlep);
+               uses_tcap = u->uses_tcap;
+               break;
+           } else if (value_is_in_range(u->called_ssn, other_ssn) && opc && value_is_in_range(u->called_pc, opc->pc) ) {
+               handle = *(u->handlep);
+               uses_tcap = u->uses_tcap;
+               break;
+           }
        }
 
        if (handle) {
-               if (uses_tcap) {
-                       call_tcap_dissector(handle, tvb, pinfo, tree);
-               } else {
-                       call_dissector(handle, tvb, pinfo, tree);
-               }
-               return;
+           if (uses_tcap) {
+               call_tcap_dissector(handle, tvb, pinfo, tree);
+           } else {
+               call_dissector(handle, tvb, pinfo, tree);
+           }
+           return;
        }
 
    }
 
-    if (ssn != INVALID_SSN && dissector_try_port(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree)) {
-               return;
+    if (ssn != INVALID_SSN && dissector_try_uint(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree)) {
+       return;
     }
 
-    if (other_ssn != INVALID_SSN && dissector_try_port(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree)) {
-               return;
+    if (other_ssn != INVALID_SSN && dissector_try_uint(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree)) {
+       return;
     }
 
     /* try heuristic subdissector list to see if there are any takers */
     if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree)) {
-               return;
+       return;
+    }
+
+    /* try user default subdissector */
+    if (default_handle) {
+        call_dissector(default_handle, tvb, pinfo, tree);
+        return;
     }
 
     /* No sub-dissection occured, treat it as raw data */
@@ -1782,26 +1880,17 @@ dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 static void
 dissect_sccp_segmentation_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
 {
-  guint8 first, class, remaining;
-  guint32 slrx;
   proto_item *param_item;
   proto_tree *param_tree;
 
-  first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
-  class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
-  remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
-
-  slrx = tvb_get_letoh24(tvb, 1);
-
   param_item = proto_tree_add_text(tree, tvb, 0, length, "%s",
                                   val_to_str(PARAMETER_SEGMENTATION,
-                                             sccp_parameter_values, "Unknown"));
+                                             sccp_parameter_values, "Unknown: %d"));
   param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
 
-  proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, 1, first);
-  proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, 1, class);
-  proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0, 1,
-                     remaining);
+  proto_tree_add_item(param_tree, hf_sccp_segmentation_first, tvb, 0, 1, ENC_NA);
+  proto_tree_add_item(param_tree, hf_sccp_segmentation_class, tvb, 0, 1, ENC_NA);
+  proto_tree_add_item(param_tree, hf_sccp_segmentation_remaining, tvb, 0, 1, ENC_NA);
 
   if (length-1 != 3) {
     proto_item *expert_item;
@@ -1811,8 +1900,7 @@ dissect_sccp_segmentation_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
     return;
   }
 
-  proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length-1,
-                     slrx);
+  proto_tree_add_item(param_tree, hf_sccp_segmentation_slr, tvb, 1, length-1, ENC_LITTLE_ENDIAN);
 }
 
 static void
@@ -1827,8 +1915,6 @@ dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint length)
 static void
 dissect_sccp_importance_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length)
 {
-  guint8 importance;
-
   if (length != 1) {
     proto_item *expert_item;
     expert_item = proto_tree_add_text(tree, tvb, 0, length, "Wrong length indicated. Expected 1, got %u", length);
@@ -1837,14 +1923,13 @@ dissect_sccp_importance_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
     return;
   }
 
-  importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
-  proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
+  proto_tree_add_item(tree, hf_sccp_importance, tvb, 0, length, ENC_NA);
 }
 
 static void
 dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
 {
-  guint8 mi, iri, ti, network;
+  guint8 ti;
   guint offset = 0;
   proto_item *param_item;
   proto_tree *param_tree;
@@ -1855,20 +1940,18 @@ dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
   param_tree = proto_item_add_subtree(param_item,
                                      ett_sccp_ansi_isni_routing_control);
 
-  mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
-  proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
-                     ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
+  proto_tree_add_item(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
+                     ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
 
-  iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
-  proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
-                     ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
+  proto_tree_add_item(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
+                     ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
 
   ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
   proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
                      ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
 
   proto_tree_add_item(param_tree, hf_sccp_ansi_isni_counter, tvb, offset,
-                     ANSI_ISNI_ROUTING_CONTROL_LENGTH, TRUE);
+                     ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA);
 
   offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
 
@@ -1880,14 +1963,12 @@ dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
 
   while (offset < length) {
 
-    network = tvb_get_guint8(tvb, offset);
-    proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
-                       "Network ID network: %d", network);
+    proto_tree_add_item(tree, hf_sccp_ansi_isni_network, tvb, offset,
+                       ANSI_NCM_LENGTH, ENC_NA);
     offset++;
 
-    network = tvb_get_guint8(tvb, offset);
-    proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
-                       "Network ID cluster: %d", network);
+    proto_tree_add_item(tree, hf_sccp_ansi_isni_cluster, tvb, offset,
+                       ANSI_NCM_LENGTH, ENC_NA);
     offset++;
   }
 
@@ -2021,11 +2102,7 @@ dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
       break;
 
     case PARAMETER_LONG_DATA:
-      if (decode_mtp3_standard != ANSI_STANDARD)
-                 dissect_sccp_data_param(parameter_tvb, pinfo, tree);
-      else
-                 dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
-                                  parameter_length);
+      dissect_sccp_data_param(parameter_tvb, pinfo, tree);
       break;
 
     case PARAMETER_ISNI:
@@ -2057,26 +2134,25 @@ dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
 {
   guint16 parameter_length;
   guint8 length_length;
+  proto_item *pi;
 
-  if (parameter_type != PARAMETER_LONG_DATA)
-  {
+  if (parameter_type != PARAMETER_LONG_DATA) {
     parameter_length = tvb_get_guint8(tvb, offset);
     length_length = PARAMETER_LENGTH_LENGTH;
-  }
-  else
-  {
+  } else {
     /* Long data parameter has 16 bit length */
     parameter_length = tvb_get_letohs(tvb, offset);
     length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
   }
 
-  if (sccp_tree && sccp_show_length)
-  {
-    proto_tree_add_text(sccp_tree, tvb, offset, length_length,
-                       "%s length: %d",
-                       val_to_str(parameter_type, sccp_parameter_values,
-                                  "Unknown"),
-                       parameter_length);
+  pi = proto_tree_add_uint_format(sccp_tree, hf_sccp_param_length, tvb, offset,
+                                 length_length, parameter_length, "%s length: %d",
+                                 val_to_str(parameter_type, sccp_parameter_values,
+                                            "Unknown: %d"),
+                                 parameter_length);
+  if (!sccp_show_length) {
+    /* The user doesn't want to see it... */
+    PROTO_ITEM_SET_HIDDEN(pi);
   }
 
   offset += length_length;
@@ -2112,7 +2188,9 @@ dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
 
 }
 
-static sccp_msg_info_t* new_ud_msg(packet_info* pinfo, guint32 msg_type _U_) {
+static sccp_msg_info_t *
+new_ud_msg(packet_info* pinfo, guint32 msg_type _U_)
+{
        sccp_msg_info_t* m = ep_alloc0(sizeof(sccp_msg_info_t));
        m->framenum = pinfo->fd->num;
        m->data.ud.calling_gt = NULL;
@@ -2134,7 +2212,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
   fragment_data *frag_msg = NULL;
   guint32 source_local_ref=0;
   guint8 more;
-  guint msg_offset = offset_from_real_beginning(tvb,0);
+  guint msg_offset = tvb_offset_from_real_beginning(tvb);
 
 /* Macro for getting pointer to mandatory variable parameters */
 #define VARIABLE_POINTER(var, hf_var, ptr_size) \
@@ -2167,17 +2245,15 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
   message_type   = tvb_get_guint8(tvb, SCCP_MSG_TYPE_OFFSET);
   offset = SCCP_MSG_TYPE_LENGTH;
 
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    /*  Do not change col_add_fstr() to col_append_fstr() here: we _want_
-     *  this call to overwrite whatever's currently in the INFO column (e.g.,
-     *  "DATA" from the SCTP dissector).
-     *
-     *  If there's something there that should not be overwritten, whoever
-     *  put that info there should call col_set_fence() to protect it.
-     */
-    col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
-                val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
-  };
+  /*  Do not change col_add_fstr() to col_append_fstr() here: we _want_
+   *  this call to overwrite whatever's currently in the INFO column (e.g.,
+   *  "DATA" from the SCTP dissector).
+   *
+   *  If there's something there that should not be overwritten, whoever
+   *  put that info there should call col_set_fence() to protect it.
+   */
+  col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+    val_to_str(message_type, sccp_message_type_acro_values, "Unknown: %d"));
 
   if (sccp_tree) {
     /* add the message type to the protocol tree */
@@ -2308,42 +2384,39 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     offset, SEGMENTING_REASSEMBLING_LENGTH);
     VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
 
-    /* Reasemble */
+    /* Reassemble */
     if (!sccp_xudt_desegment) {
-               proto_tree_add_text(sccp_tree, tvb, variable_pointer1,
-                                       tvb_get_guint8(tvb, variable_pointer1)+1,
-                                       "Segmented Data");
-               dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                               PARAMETER_DATA, variable_pointer1);
+       proto_tree_add_text(sccp_tree, tvb, variable_pointer1,
+                           tvb_get_guint8(tvb, variable_pointer1)+1,
+                           "Segmented Data");
+       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                       PARAMETER_DATA, variable_pointer1);
 
     } else {
-               save_fragmented = pinfo->fragmented;
-               pinfo->fragmented = TRUE;
-               frag_msg = fragment_add_seq_next(tvb, variable_pointer1 + 1, pinfo,
-                                        source_local_ref,                                              /* ID for fragments belonging together */
-                                        sccp_xudt_msg_fragment_table,                  /* list of message fragments */
-                                        sccp_xudt_msg_reassembled_table,               /* list of reassembled messages */
+       save_fragmented = pinfo->fragmented;
+       pinfo->fragmented = TRUE;
+       frag_msg = fragment_add_seq_next(tvb, variable_pointer1 + 1, pinfo,
+                                        source_local_ref,                      /* ID for fragments belonging together */
+                                        sccp_xudt_msg_fragment_table,          /* list of message fragments */
+                                        sccp_xudt_msg_reassembled_table,       /* list of reassembled messages */
                                         tvb_get_guint8(tvb,variable_pointer1), /* fragment length - to the end */
-                                        more);                                                                 /* More fragments? */
-
-               new_tvb = process_reassembled_data(tvb, variable_pointer1 + 1, pinfo,
-                                                  "Reassembled Message", frag_msg,
-                                                  &sccp_xudt_msg_frag_items, NULL,
-                                                  tree);
-
-               if (frag_msg && frag_msg->next) { /* Reassembled */
-                       if (check_col(pinfo->cinfo, COL_INFO))
-                               col_append_str(pinfo->cinfo, COL_INFO,
-                                          "(Message reassembled) ");
-               } else if (more) { /* Not last packet of reassembled message */
-                       if (check_col(pinfo->cinfo, COL_INFO))
-                               col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
-               }
+                                        more);                                 /* More fragments? */
+
+       new_tvb = process_reassembled_data(tvb, variable_pointer1 + 1, pinfo,
+                                          "Reassembled SCCP", frag_msg,
+                                          &sccp_xudt_msg_frag_items, NULL,
+                                          tree);
+
+       if (frag_msg && frag_msg->next) { /* Reassembled */
+           col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) ");
+       } else if (more) { /* Not last packet of reassembled message */
+           col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
+       }
 
-               pinfo->fragmented = save_fragmented;
+       pinfo->fragmented = save_fragmented;
 
-               if (new_tvb)
-                       dissect_sccp_data_param(new_tvb, pinfo, tree);
+       if (new_tvb)
+           dissect_sccp_data_param(new_tvb, pinfo, tree);
     }
 
     /* End reassemble */
@@ -2401,6 +2474,10 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
     break;
 
   case SCCP_MSG_TYPE_UDTS:
+  {
+    gboolean save_in_error_pkt = pinfo->in_error_pkt;
+    pinfo->in_error_pkt = TRUE;
+
     pinfo->sccp_info =  sccp_msg = new_ud_msg(pinfo,message_type);
 
     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
@@ -2423,7 +2500,9 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
 
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
                                    variable_pointer3);
+    pinfo->in_error_pkt = save_in_error_pkt;
     break;
+  }
 
   case SCCP_MSG_TYPE_ED:
     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
@@ -2530,68 +2609,69 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                    PARAMETER_CALLING_PARTY_ADDRESS,
                                    variable_pointer2);
 
-    if (tvb_get_guint8(tvb, optional_pointer) == PARAMETER_SEGMENTATION){
-               if (!sccp_xudt_desegment){
-                       proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data");
-               } else {
-                       guint8 octet;
-                       gboolean more_frag = TRUE;
-
-
-                   /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
-                    * Bit 8 of octet 1 is used for First segment indication
-                    * Bit 7 of octet 1 is used to keep in the message in sequence
-                    *       delivery option required by the SCCP user
-                    * Bits 6 and 5 in octet 1 are spare bits.
-                    * Bits 4-1 of octet 1 are used to indicate the number of
-                    *          remaining segments.
-                    * The values 0000 to 1111 are possible; the value 0000 indicates
-                    * the last segment.
-                    */
-                   octet = tvb_get_guint8(tvb,optional_pointer+2);
-                   source_local_ref = tvb_get_letoh24(tvb, optional_pointer+3);
-
-                   if ((octet&0x0f) == 0)
-                               more_frag = FALSE;
-
-                       save_fragmented = pinfo->fragmented;
-                       pinfo->fragmented = TRUE;
-                       frag_msg = fragment_add_seq_next(tvb, variable_pointer3 + 1, pinfo,
-                               source_local_ref,                               /* ID for fragments belonging together */
-                               sccp_xudt_msg_fragment_table,           /* list of message fragments */
-                               sccp_xudt_msg_reassembled_table,                /* list of reassembled messages */
-                               tvb_get_guint8(tvb,variable_pointer3),  /* fragment length - to the end */
-                               more_frag);                                     /* More fragments? */
-
-                       if ((octet&0x80) == 0x80) /*First segment, set number of segments*/
-                               fragment_set_tot_len(pinfo, source_local_ref, sccp_xudt_msg_fragment_table,(octet & 0xf));
-
-                       new_tvb = process_reassembled_data(tvb, variable_pointer3 + 1,
-                                              pinfo, "Reassembled Message",
+    if (tvb_get_guint8(tvb, optional_pointer) == PARAMETER_SEGMENTATION) {
+       if (!sccp_xudt_desegment){
+           proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data");
+       } else {
+           guint8 octet;
+           gboolean more_frag = TRUE;
+
+           /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713
+            * Bit 8 of octet 1 is used for First segment indication
+            * Bit 7 of octet 1 is used to keep in the message in sequence
+            *       delivery option required by the SCCP user
+            * Bits 6 and 5 in octet 1 are spare bits.
+            * Bits 4-1 of octet 1 are used to indicate the number of
+            *          remaining segments.
+            * The values 0000 to 1111 are possible; the value 0000 indicates
+            * the last segment.
+            */
+           octet = tvb_get_guint8(tvb,optional_pointer+2);
+           source_local_ref = tvb_get_letoh24(tvb, optional_pointer+3);
+
+           if ((octet&0x0f) == 0)
+               more_frag = FALSE;
+
+           save_fragmented = pinfo->fragmented;
+           pinfo->fragmented = TRUE;
+           frag_msg = fragment_add_seq_next(tvb, variable_pointer3 + 1, pinfo,
+                                            source_local_ref,                          /* ID for fragments belonging together */
+                                            sccp_xudt_msg_fragment_table,              /* list of message fragments */
+                                            sccp_xudt_msg_reassembled_table,           /* list of reassembled messages */
+                                            tvb_get_guint8(tvb,variable_pointer3),     /* fragment length - to the end */
+                                            more_frag);                                /* More fragments? */
+
+           if ((octet&0x80) == 0x80) /*First segment, set number of segments*/
+               fragment_set_tot_len(pinfo, source_local_ref, sccp_xudt_msg_fragment_table,(octet & 0xf));
+
+           new_tvb = process_reassembled_data(tvb, variable_pointer3 + 1,
+                                              pinfo, "Reassembled SCCP",
                                               frag_msg,
                                               &sccp_xudt_msg_frag_items,
                                               NULL, tree);
 
-                       if (frag_msg) { /* Reassembled */
-                               if (check_col(pinfo->cinfo, COL_INFO))
-                                       col_append_str(pinfo->cinfo, COL_INFO,"(Message reassembled) ");
-                       } else { /* Not last packet of reassembled message */
-                               if (check_col(pinfo->cinfo, COL_INFO))
-                                       col_append_str(pinfo->cinfo, COL_INFO,"(Message fragment) ");
-                       }
+           if (frag_msg) { /* Reassembled */
+               col_append_str(pinfo->cinfo, COL_INFO,"(Message reassembled) ");
+           } else { /* Not last packet of reassembled message */
+               col_append_str(pinfo->cinfo, COL_INFO,"(Message fragment) ");
+           }
 
-                       pinfo->fragmented = save_fragmented;
+           pinfo->fragmented = save_fragmented;
 
-                       if (new_tvb)
-                               dissect_sccp_data_param(new_tvb, pinfo, tree);
-               }
+           if (new_tvb)
+               dissect_sccp_data_param(new_tvb, pinfo, tree);
+       }
     } else {
-               dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                        PARAMETER_DATA, variable_pointer3);
     }
     break;
 
   case SCCP_MSG_TYPE_XUDTS:
+  {
+    gboolean save_in_error_pkt = pinfo->in_error_pkt;
+    pinfo->in_error_pkt = TRUE;
+
     pinfo->sccp_info =  sccp_msg = new_ud_msg(pinfo,message_type);
     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
                                     PARAMETER_RETURN_CAUSE, offset,
@@ -2614,7 +2694,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                    PARAMETER_CALLING_PARTY_ADDRESS,
                                    variable_pointer2);
 
-    if (tvb_get_guint8(tvb, optional_pointer) == PARAMETER_SEGMENTATION){
+    if (tvb_get_guint8(tvb, optional_pointer) == PARAMETER_SEGMENTATION) {
        if (!sccp_xudt_desegment){
            proto_tree_add_text(sccp_tree, tvb, variable_pointer3, tvb_get_guint8(tvb, variable_pointer3)+1, "Segmented Data");
 
@@ -2642,29 +2722,25 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
            save_fragmented = pinfo->fragmented;
            pinfo->fragmented = TRUE;
            frag_msg = fragment_add_seq_next(tvb, variable_pointer3 + 1, pinfo,
-                   source_local_ref,                           /* ID for fragments belonging together */
-                   sccp_xudt_msg_fragment_table,               /* list of message fragments */
-                   sccp_xudt_msg_reassembled_table,            /* list of reassembled messages */
-                   tvb_get_guint8(tvb,variable_pointer3),      /* fragment length - to the end */
-                   more_frag);                                 /* More fragments? */
+                                            source_local_ref,                          /* ID for fragments belonging together */
+                                            sccp_xudt_msg_fragment_table,              /* list of message fragments */
+                                            sccp_xudt_msg_reassembled_table,           /* list of reassembled messages */
+                                            tvb_get_guint8(tvb,variable_pointer3),     /* fragment length - to the end */
+                                            more_frag);                                /* More fragments? */
 
            if ((octet&0x80) == 0x80) /*First segment, set number of segments*/
                fragment_set_tot_len(pinfo, source_local_ref, sccp_xudt_msg_fragment_table,(octet & 0xf));
 
            new_tvb = process_reassembled_data(tvb, variable_pointer3 + 1,
-                                              pinfo, "Reassembled Message",
+                                              pinfo, "Reassembled SCCP",
                                               frag_msg,
                                               &sccp_xudt_msg_frag_items,
                                               NULL, tree);
 
            if (frag_msg) { /* Reassembled */
-               if (check_col(pinfo->cinfo, COL_INFO))
-                   col_append_str(pinfo->cinfo, COL_INFO,
-                                  "(Message reassembled) ");
+               col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) ");
            } else { /* Not last packet of reassembled message */
-               if (check_col(pinfo->cinfo, COL_INFO))
-                   col_append_str(pinfo->cinfo, COL_INFO,
-                                   "(Message fragment) ");
+               col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) ");
            }
 
            pinfo->fragmented = save_fragmented;
@@ -2676,66 +2752,60 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
        dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                        PARAMETER_DATA, variable_pointer3);
     }
+    pinfo->in_error_pkt = save_in_error_pkt;
     break;
-
+  }
   case SCCP_MSG_TYPE_LUDT:
-     pinfo->sccp_info =  sccp_msg = new_ud_msg(pinfo,message_type);
-   if (decode_mtp3_standard != ANSI_STANDARD)
-    {
-      offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
-                                      PARAMETER_CLASS, offset,
-                                      PROTOCOL_CLASS_LENGTH);
-      offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
-                                      PARAMETER_HOP_COUNTER, offset,
-                                      HOP_COUNTER_LENGTH);
-
-      VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
-      VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
-      VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
-      OPTIONAL_POINTER(POINTER_LENGTH_LONG)
-
-      assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
-
-      dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                     PARAMETER_CALLED_PARTY_ADDRESS,
-                                     variable_pointer1);
-      dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                     PARAMETER_CALLING_PARTY_ADDRESS,
-                                     variable_pointer2);
-      dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                     PARAMETER_LONG_DATA, variable_pointer3);
-    } else
-      dissect_sccp_unknown_message(tvb, sccp_tree);
+    pinfo->sccp_info =  sccp_msg = new_ud_msg(pinfo,message_type);
+
+    offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+                                    PARAMETER_CLASS, offset,
+                                    PROTOCOL_CLASS_LENGTH);
+    offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+                                    PARAMETER_HOP_COUNTER, offset,
+                                    HOP_COUNTER_LENGTH);
+
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
+    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
+    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
+    OPTIONAL_POINTER(POINTER_LENGTH_LONG)
+
+    assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
+
+    dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                   PARAMETER_CALLED_PARTY_ADDRESS,
+                                   variable_pointer1);
+    dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                   PARAMETER_CALLING_PARTY_ADDRESS,
+                                   variable_pointer2);
+    dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                   PARAMETER_LONG_DATA, variable_pointer3);
     break;
 
   case SCCP_MSG_TYPE_LUDTS:
-     pinfo->sccp_info =  sccp_msg = new_ud_msg(pinfo,message_type);
-   if (decode_mtp3_standard != ANSI_STANDARD)
-    {
-      offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
-                                      PARAMETER_RETURN_CAUSE, offset,
-                                      RETURN_CAUSE_LENGTH);
-      offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
-                                      PARAMETER_HOP_COUNTER, offset,
-                                      HOP_COUNTER_LENGTH);
-
-      VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
-      VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
-      VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
-      OPTIONAL_POINTER(POINTER_LENGTH_LONG)
-
-      assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
-
-      dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                     PARAMETER_CALLED_PARTY_ADDRESS,
-                                     variable_pointer1);
-      dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                     PARAMETER_CALLING_PARTY_ADDRESS,
-                                     variable_pointer2);
-      dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
-                                     PARAMETER_LONG_DATA, variable_pointer3);
-    } else
-      dissect_sccp_unknown_message(tvb, sccp_tree);
+    pinfo->sccp_info =  sccp_msg = new_ud_msg(pinfo,message_type);
+    offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+                                    PARAMETER_RETURN_CAUSE, offset,
+                                    RETURN_CAUSE_LENGTH);
+    offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+                                    PARAMETER_HOP_COUNTER, offset,
+                                    HOP_COUNTER_LENGTH);
+
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
+    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
+    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
+    OPTIONAL_POINTER(POINTER_LENGTH_LONG)
+
+    assoc = get_sccp_assoc(pinfo, msg_offset,  slr, dlr, message_type);
+
+    dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                   PARAMETER_CALLED_PARTY_ADDRESS,
+                                   variable_pointer1);
+    dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                   PARAMETER_CALLING_PARTY_ADDRESS,
+                                   variable_pointer2);
+    dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+                                   PARAMETER_LONG_DATA, variable_pointer3);
     break;
 
   default:
@@ -2747,16 +2817,16 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     optional_pointer);
 
   if (trace_sccp && assoc && assoc != &no_assoc) {
-         proto_item* pi = proto_tree_add_uint(sccp_tree,hf_sccp_assoc_id,tvb,0,0,assoc->id);
-         proto_tree* pt = proto_item_add_subtree(pi,ett_sccp_assoc);
+         proto_item *pi = proto_tree_add_uint(sccp_tree, hf_sccp_assoc_id, tvb, 0, 0, assoc->id);
+         proto_tree *pt = proto_item_add_subtree(pi, ett_sccp_assoc);
          PROTO_ITEM_SET_GENERATED(pi);
          if (assoc->msgs) {
                sccp_msg_info_t* m;
                  for(m = assoc->msgs; m ; m = m->data.co.next) {
-                       pi = proto_tree_add_uint( pt,hf_sccp_assoc_msg,tvb,0,0,m->framenum);
+                       pi = proto_tree_add_uint(pt, hf_sccp_assoc_msg, tvb, 0, 0, m->framenum);
 
                        if (assoc->payload != SCCP_PLOAD_NONE)
-                               proto_item_append_text(pi," %s", val_to_str(assoc->payload, assoc_protos, "Unknown"));
+                               proto_item_append_text(pi," %s", val_to_str(assoc->payload, assoc_protos, "Unknown: %d"));
 
                        if (m->data.co.label)
                                proto_item_append_text(pi," %s", m->data.co.label);
@@ -2780,8 +2850,7 @@ dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   const mtp3_addr_pc_t *mtp3_addr_p;
 
   if ((pinfo->src.type == AT_SS7PC) &&
-    ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD))
-  {
+      ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD)) {
     /*
      *  Allow a protocol beneath to specify how the SCCP layer should be
      *  dissected.
@@ -2792,41 +2861,37 @@ dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
      *  and at the same time ITU MTP3/ITU SCCP/ANSI TCAP/ANSI MAP.
      */
     decode_mtp3_standard = mtp3_addr_p->type;
-  }
-  else
-  {
+  } else {
     decode_mtp3_standard = mtp3_standard;
   }
 
   /* Make entry in the Protocol column on summary display */
-  if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    switch(decode_mtp3_standard) {
-      case ITU_STANDARD:
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
-       break;
-      case ANSI_STANDARD:
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
-       break;
-      case CHINESE_ITU_STANDARD:
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
-       break;
-      case JAPAN_STANDARD:
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)");
-       break;
-    };
+  switch(decode_mtp3_standard) {
+    case ITU_STANDARD:
+      col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
+      break;
+    case ANSI_STANDARD:
+         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
+         break;
+    case CHINESE_ITU_STANDARD:
+         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
+         break;
+    case JAPAN_STANDARD:
+         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)");
+         break;
+  };
 
   /* In the interest of speed, if "tree" is NULL, don't do any work not
      necessary to generate protocol tree items. */
   if (tree) {
     /* create the sccp protocol tree */
-    sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
+    sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, ENC_NA);
     sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
   }
 
   /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
 
-  if (pinfo->src.type == AT_SS7PC)
-  {
+  if (pinfo->src.type == AT_SS7PC) {
     /*
      * XXX - we assume that the "data" pointers of the source and destination
      * addresses are set to point to "mtp3_addr_pc_t" structures, so that
@@ -2834,21 +2899,16 @@ dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
      */
     mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data;
 
-    if (sccp_source_pc_global == mtp3_addr_p->pc)
-    {
+    if (sccp_source_pc_global == mtp3_addr_p->pc) {
        pinfo->p2p_dir = P2P_DIR_SENT;
-    }
-    else
-    {
+    } else {
       /* assuming if src was SS7 PC then dst will be too */
       mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->dst.data;
 
       if (sccp_source_pc_global == mtp3_addr_p->pc)
       {
         pinfo->p2p_dir = P2P_DIR_RECV;
-      }
-      else
-      {
+      } else {
         pinfo->p2p_dir = P2P_DIR_UNKNOWN;
       }
     }
@@ -2866,17 +2926,19 @@ static struct _sccp_ul {
        gboolean uses_tcap;
        dissector_handle_t* handlep;
        } user_list[] = {
-       {SCCP_USER_DATA,FALSE,&data_handle},
-       {SCCP_USER_TCAP,FALSE,&tcap_handle},
-       {SCCP_USER_RANAP,FALSE,&ranap_handle},
-       {SCCP_USER_BSSAP,FALSE,&bssap_handle},
-       {SCCP_USER_GSMMAP,TRUE,&gsmmap_handle},
-       {SCCP_USER_CAMEL,TRUE,&camel_handle},
-       {SCCP_USER_INAP,TRUE,&inap_handle},
-       {0,FALSE,NULL}
+       {SCCP_USER_DATA, FALSE, &data_handle},
+       {SCCP_USER_TCAP, FALSE, &tcap_handle},
+       {SCCP_USER_RANAP, FALSE, &ranap_handle},
+       {SCCP_USER_BSSAP, FALSE, &bssap_handle},
+       {SCCP_USER_GSMMAP, TRUE, &gsmmap_handle},
+       {SCCP_USER_CAMEL, TRUE, &camel_handle},
+       {SCCP_USER_INAP, TRUE, &inap_handle},
+       {0, FALSE, NULL}
 };
 
-static void sccp_users_update_cb(void* r, const char** err _U_) {
+static void
+sccp_users_update_cb(void* r, const char** err _U_)
+{
        sccp_user_t* u = r;
        struct _sccp_ul* c;
 
@@ -2892,7 +2954,9 @@ static void sccp_users_update_cb(void* r, const char** err _U_) {
        u->handlep = &data_handle;
 }
 
-static void* sccp_users_copy_cb(void* n, const void* o, unsigned siz _U_) {
+static void *
+sccp_users_copy_cb(void* n, const void* o, size_t siz _U_)
+{
        const sccp_user_t* u = o;
        sccp_user_t* un = n;
 
@@ -2906,7 +2970,9 @@ static void* sccp_users_copy_cb(void* n, const void* o, unsigned siz _U_) {
        return n;
 }
 
-static void sccp_users_free_cb(void*r) {
+static void
+sccp_users_free_cb(void*r)
+{
        sccp_user_t* u = r;
        if (u->called_pc) g_free(u->called_pc);
        if (u->called_ssn) g_free(u->called_ssn);
@@ -2914,14 +2980,16 @@ static void sccp_users_free_cb(void*r) {
 
 
 UAT_DEC_CB_DEF(sccp_users, ni, sccp_user_t)
-UAT_RANGE_CB_DEF(sccp_users,called_pc,sccp_user_t)
-UAT_RANGE_CB_DEF(sccp_users,called_ssn,sccp_user_t)
+UAT_RANGE_CB_DEF(sccp_users, called_pc,sccp_user_t)
+UAT_RANGE_CB_DEF(sccp_users, called_ssn,sccp_user_t)
 UAT_VS_DEF(sccp_users, user, sccp_user_t, SCCP_USER_DATA, "Data")
 
 /** End SccpUsersTable **/
 
 
-static void init_sccp(void) {
+static void
+init_sccp(void)
+{
     next_assoc_id = 1;
     fragment_table_init (&sccp_xudt_msg_fragment_table);
     reassembled_table_init(&sccp_xudt_msg_reassembled_table);
@@ -2954,6 +3022,10 @@ proto_register_sccp(void)
       { "Pointer to Optional parameter", "sccp.optional_pointer",
        FT_UINT16, BASE_DEC, NULL, 0x0,
        NULL, HFILL}},
+    { &hf_sccp_param_length,
+      { "Variable parameter length", "sccp.parameter_length",
+       FT_UINT16, BASE_DEC, NULL, 0x0,
+       NULL, HFILL}},
     { &hf_sccp_ssn,
       { "Called or Calling SubSystem Number", "sccp.ssn",
        FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
@@ -3056,10 +3128,15 @@ proto_register_sccp(void)
        FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
        NULL, HFILL }},
     { &hf_sccp_called_gt_digits,
-      { "GT Digits",
+      { "Called Party Digits",
        "sccp.called.digits",
        FT_STRING, BASE_NONE, NULL, 0x0,
        NULL, HFILL }},
+    { &hf_sccp_called_gt_digits_length,
+      { "Number of Called Party Digits",
+       "sccp.called.digits.length",
+       FT_UINT8, BASE_DEC, NULL, 0x0,
+       NULL, HFILL }},
     { &hf_sccp_calling_national_indicator,
       { "National Indicator", "sccp.calling.ni",
        FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
@@ -3153,10 +3230,15 @@ proto_register_sccp(void)
        FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
        NULL, HFILL }},
     { &hf_sccp_calling_gt_digits,
-      { "GT Digits",
+      { "Calling Party Digits",
        "sccp.calling.digits",
        FT_STRING, BASE_NONE, NULL, 0x0,
        NULL, HFILL }},
+    { &hf_sccp_calling_gt_digits_length,
+      { "Number of Calling Party Digits",
+       "sccp.calling.digits.length",
+       FT_UINT8, BASE_DEC, NULL, 0x0,
+       NULL, HFILL }},
     { &hf_sccp_dlr,
       { "Destination Local Reference", "sccp.dlr",
        FT_UINT24, BASE_HEX, NULL, 0x0,
@@ -3266,6 +3348,12 @@ proto_register_sccp(void)
       { "ISNI Counter", "sccp.isni.counter",
        FT_UINT8, BASE_DEC, NULL, ANSI_ISNI_COUNTER_MASK,
        NULL, HFILL}},
+    { &hf_sccp_ansi_isni_network,
+      { "Network ID network", "sccp.isni.network",
+       FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+    { &hf_sccp_ansi_isni_cluster,
+      { "Network ID cluster", "sccp.isni.cluster",
+       FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
     {&hf_sccp_xudt_msg_fragments,
        {"Message fragments", "sccp.msg.fragments",
        FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
@@ -3294,10 +3382,18 @@ proto_register_sccp(void)
        {"Message defragmentation error", "sccp.msg.fragment.error",
        FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
     },
+    {&hf_sccp_xudt_msg_fragment_count,
+       {"Message fragment count", "sccp.msg.fragment.count",
+       FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
+    },
     {&hf_sccp_xudt_msg_reassembled_in,
        {"Reassembled in", "sccp.msg.reassembled.in",
        FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
     },
+    {&hf_sccp_xudt_msg_reassembled_length,
+       {"Reassembled SCCP length", "sccp.msg.reassembled.length",
+       FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
+    },
     { &hf_sccp_assoc_id,
       { "Association ID", "sccp.assoc.id",
        FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
@@ -3315,41 +3411,35 @@ proto_register_sccp(void)
     &ett_sccp_called_ai,
     &ett_sccp_called_pc,
     &ett_sccp_called_gt,
+    &ett_sccp_called_gt_digits,
     &ett_sccp_calling,
     &ett_sccp_calling_ai,
     &ett_sccp_calling_pc,
     &ett_sccp_calling_gt,
+    &ett_sccp_calling_gt_digits,
     &ett_sccp_sequencing_segmenting,
     &ett_sccp_segmentation,
     &ett_sccp_ansi_isni_routing_control,
     &ett_sccp_xudt_msg_fragment,
     &ett_sccp_xudt_msg_fragments,
-    &ett_sccp_assoc,
-    &ett_sccp_digits
+    &ett_sccp_assoc
   };
 
 
   static uat_field_t users_flds[] = {
-               UAT_FLD_DEC(sccp_users,ni,"Network Indicator","Network Indicator"),
-               UAT_FLD_RANGE(sccp_users,called_pc,"Called DPCs",65535,"DPCs for which this protocol is to be used"),
-               UAT_FLD_RANGE(sccp_users,called_ssn,"Called SSNs",65535,"Called SSNs for which this protocol is to be used"),
-               UAT_FLD_VS(sccp_users,user,"User protocol",sccp_users_vals,"The User Protocol"),
+               UAT_FLD_DEC(sccp_users, ni, "Network Indicator", "Network Indicator"),
+               UAT_FLD_RANGE(sccp_users, called_pc, "Called DPCs", 0xFFFFFF, "DPCs for which this protocol is to be used"),
+               UAT_FLD_RANGE(sccp_users, called_ssn, "Called SSNs", 255, "Called SSNs for which this protocol is to be used"),
+               UAT_FLD_VS(sccp_users, user, "User protocol", sccp_users_vals, "The User Protocol"),
                UAT_END_FIELDS
   };
 
 
-  uat_t* users_uat = uat_new("SCCP Users Table",
-       sizeof(sccp_user_t),
-       "sccp_users",
-       TRUE,
-       (void*) &sccp_users,
-       &num_sccp_users,
-       UAT_CAT_PORTS,
-       "ChSccpUsers",
-       sccp_users_copy_cb,
-       sccp_users_update_cb,
-       sccp_users_free_cb,
-       users_flds );
+  uat_t* users_uat = uat_new("SCCP Users Table", sizeof(sccp_user_t),
+                            "sccp_users", TRUE, (void*) &sccp_users,
+                            &num_sccp_users, UAT_CAT_PORTS, "ChSccpUsers",
+                            sccp_users_copy_cb, sccp_users_update_cb,
+                            sccp_users_free_cb, NULL, users_flds );
 
  /* Register the protocol name and description */
   proto_sccp = proto_register_protocol("Signalling Connection Control Part",
@@ -3366,7 +3456,7 @@ proto_register_sccp(void)
 
   register_heur_dissector_list("sccp", &heur_subdissector_list);
 
-  sccp_module = prefs_register_protocol(proto_sccp, NULL);
+  sccp_module = prefs_register_protocol(proto_sccp, proto_reg_handoff_sccp);
 
   prefs_register_uint_preference(sccp_module, "source_pc",
                                 "Source PC (in hex)",
@@ -3398,6 +3488,14 @@ proto_register_sccp(void)
                                 "A table that enumerates user protocols to be used against specific PCs and SSNs",
                                 users_uat);
 
+  prefs_register_bool_preference(sccp_module, "set_addresses", "Set source and destination GT addresses",
+                                "Set the source and destination addresses to the GT digits (if RI=GT)."
+                                "  This may affect TCAP's ability to recognize which messages belong to which TCAP session.", &set_addresses);
+
+  prefs_register_string_preference(sccp_module, "default_payload", "Default Payload",
+                                  "The protocol which should be used to dissect the payload if nothing else has claimed it",
+                                  &default_payload);
+
   register_init_routine(&init_sccp);
 
   assocs = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sccp_associations");
@@ -3411,18 +3509,25 @@ proto_reg_handoff_sccp(void)
 {
   dissector_handle_t sccp_handle;
 
-  sccp_handle = find_dissector("sccp");
+  static gboolean initialised=FALSE;
 
-  dissector_add("wtap_encap", WTAP_ENCAP_SCCP, sccp_handle);
-  dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
-  dissector_add_string("tali.opcode", "sccp", sccp_handle);
+  if (!initialised) {
+    sccp_handle = find_dissector("sccp");
 
-  data_handle = find_dissector("data");
-  tcap_handle = find_dissector("tcap");
-  ranap_handle = find_dissector("ranap");
-  bssap_handle = find_dissector("bssap");
-  gsmmap_handle = find_dissector("gsm_map");
-  camel_handle = find_dissector("camel");
-  inap_handle = find_dissector("inap");
-}
+    dissector_add_uint("wtap_encap", WTAP_ENCAP_SCCP, sccp_handle);
+    dissector_add_uint("mtp3.service_indicator", SCCP_SI, sccp_handle);
+    dissector_add_string("tali.opcode", "sccp", sccp_handle);
+
+    data_handle = find_dissector("data");
+    tcap_handle = find_dissector("tcap");
+    ranap_handle = find_dissector("ranap");
+    bssap_handle = find_dissector("bssap");
+    gsmmap_handle = find_dissector("gsm_map");
+    camel_handle = find_dissector("camel");
+    inap_handle = find_dissector("inap");
 
+    initialised = TRUE;
+  }
+
+  default_handle = find_dissector(default_payload);
+}