Remove a bunch of duplicate semicolons.
[obnox/wireshark/wip.git] / packet-sccp.c
index 239470c0cdf2756c66af046fc9eeda0686c6c5e6..de4982f9df7e0b0db0bbf01b141d960d4c861a12 100644 (file)
@@ -1,12 +1,14 @@
 /* packet-sccp.c
  * Routines for Signalling Connection Control Part (SCCP) dissection
+ *
  * It is hopefully compliant to:
  *   ANSI T1.112.3-1996
  *   ITU-T Q.713 7/1996
+ *   YDN 038-1997 (Chinese ITU variant)
  *
  * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
  *
- * $Id: packet-sccp.c,v 1.6 2002/08/02 23:36:00 jmayer Exp $
+ * $Id: packet-sccp.c,v 1.14 2003/09/06 00:04:45 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 
 #include <stdio.h>
 #include <stdlib.h>
-
 #include <string.h>
 
-#include "epan/packet.h"
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
 #include "packet-mtp3.h"
 
 #define SCCP_SI 3
@@ -46,6 +53,7 @@
 #define MESSAGE_TYPE_OFFSET 0
 #define MESSAGE_TYPE_LENGTH 1
 #define POINTER_LENGTH      1
+#define POINTER_LENGTH_LONG 2
 
 #define MESSAGE_TYPE_CR    0x01
 #define MESSAGE_TYPE_CC    0x02
@@ -93,7 +101,7 @@ static const value_string sccp_message_type_values[] = {
   { MESSAGE_TYPE_LUDTS,  "Long Unitdata Service (ITU)" },
   { 0,                   NULL } };
 
-/* Same as above but in acronym for (for the Info column) */
+/* Same as above but in acronym form (for the Info column) */
 static const value_string sccp_message_type_acro_values[] = {
   { MESSAGE_TYPE_CR,     "CR" },
   { MESSAGE_TYPE_CC,     "CC" },
@@ -564,6 +572,8 @@ static int hf_sccp_called_ssn = -1;
 static int hf_sccp_called_pc_member = -1;
 static int hf_sccp_called_pc_cluster = -1;
 static int hf_sccp_called_pc_network = -1;
+static int hf_sccp_called_ansi_pc = -1;
+static int hf_sccp_called_chinese_pc = -1;
 static int hf_sccp_called_itu_pc = -1;
 static int hf_sccp_called_gt_nai = -1;
 static int hf_sccp_called_gt_oe = -1;
@@ -585,6 +595,8 @@ static int hf_sccp_calling_ssn = -1;
 static int hf_sccp_calling_pc_member = -1;
 static int hf_sccp_calling_pc_cluster = -1;
 static int hf_sccp_calling_pc_network = -1;
+static int hf_sccp_calling_ansi_pc = -1;
+static int hf_sccp_calling_chinese_pc = -1;
 static int hf_sccp_calling_itu_pc = -1;
 static int hf_sccp_calling_gt_nai = -1;
 static int hf_sccp_calling_gt_oe = -1;
@@ -671,7 +683,7 @@ dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
 {
   guint32 reference;
 
-  reference = tvb_get_ntoh24(tvb, 0);
+  reference = tvb_get_letoh24(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, reference);
 }
 
@@ -680,7 +692,7 @@ dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
 {
   guint32 reference;
 
-  reference = tvb_get_ntoh24(tvb, 0);
+  reference = tvb_get_letoh24(tvb, 0);
   proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, reference);
 }
 
@@ -811,6 +823,59 @@ dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint8 length,
                                      called);
 }
 
+static int
+dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint8 offset,
+                     gboolean called)
+{
+  guint32 dpc;
+  proto_item *call_pc_item = 0;
+  proto_tree *call_pc_tree = 0;
+  char pc[ANSI_PC_STRING_LENGTH];
+  int *hf_pc;
+
+  if (mtp3_standard == ANSI_STANDARD)
+  {
+    if (called)
+      hf_pc = &hf_sccp_called_ansi_pc;
+    else
+      hf_pc = &hf_sccp_calling_ansi_pc;
+  } else /* CHINESE_ITU_STANDARD */ {
+    if (called)
+      hf_pc = &hf_sccp_called_chinese_pc;
+    else
+      hf_pc = &hf_sccp_calling_chinese_pc;
+  }
+
+  /* create the DPC tree; modified from that in packet-mtp3.c */
+  dpc = tvb_get_ntoh24(tvb, offset);
+  snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
+                                      ((dpc & ANSI_CLUSTER_MASK) >> 8),
+                                      ((dpc & ANSI_MEMBER_MASK) >> 16));
+
+  call_pc_item = proto_tree_add_string_format(call_tree, *hf_pc,
+                                             tvb, offset, ANSI_PC_LENGTH,
+                                             pc, "PC (%s)", pc);
+
+  call_pc_tree = proto_item_add_subtree(call_pc_item,
+                                         called ? ett_sccp_called_pc
+                                                : ett_sccp_calling_pc);
+
+  proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
+                                          : hf_sccp_calling_pc_member,
+                     tvb, offset, ANSI_NCM_LENGTH, dpc);
+  offset += ANSI_NCM_LENGTH;
+  proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
+                                          : hf_sccp_calling_pc_cluster,
+                     tvb, offset, ANSI_NCM_LENGTH, dpc);
+  offset += ANSI_NCM_LENGTH;
+  proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
+                                          : hf_sccp_calling_pc_network,
+                     tvb, offset, ANSI_NCM_LENGTH, dpc);
+  offset += ANSI_NCM_LENGTH;
+
+  return(offset);
+}
+
 /*  FUNCTION dissect_sccp_called_calling_param():
  *  Dissect the Calling or Called Party Address parameters.
  *
@@ -829,8 +894,8 @@ static void
 dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
                                  guint8 length, gboolean called)
 {
-  proto_item *call_item = 0, *call_ai_item = 0, *call_pc_item = 0;
-  proto_tree *call_tree = 0, *call_ai_tree = 0, *call_pc_tree = 0;
+  proto_item *call_item = 0, *call_ai_item = 0;
+  proto_tree *call_tree = 0, *call_ai_tree = 0;
   guint8 offset;
   guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
   guint32 dpc;
@@ -864,7 +929,9 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
 
   gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
 
-  if (mtp3_standard == ITU_STANDARD || national == 0) {
+  if (mtp3_standard == ITU_STANDARD ||
+      mtp3_standard == CHINESE_ITU_STANDARD ||
+      national == 0) {
 
     proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
                                             : hf_sccp_called_itu_global_title_indicator,
@@ -884,11 +951,20 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
 
     /* Dissect PC (if present) */
     if (pci) {
-      dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
-      proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
-                                           : hf_sccp_calling_itu_pc,
-                         tvb, offset, ITU_PC_LENGTH, dpc);
-      offset += ITU_PC_LENGTH;
+      if (mtp3_standard == ITU_STANDARD)
+      {
+
+       dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
+       proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
+                                             : hf_sccp_calling_itu_pc,
+                           tvb, offset, ITU_PC_LENGTH, dpc);
+       offset += ITU_PC_LENGTH;
+
+      } else /* CHINESE_ITU_STANDARD */ {
+
+       offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
+
+      }
     }
 
     /* Dissect SSN (if present) */
@@ -961,31 +1037,7 @@ dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
 
     /* Dissect PC (if present) */
     if (pci) {
-      /* create the DPC tree; modified from that in packet-mtp3.c */
-      dpc = tvb_get_ntoh24(tvb, offset);
-      call_pc_item = proto_tree_add_text(call_tree, tvb, offset,
-                                          ANSI_PC_LENGTH,
-                                          "PC (%d-%d-%d)",
-                                          (dpc & ANSI_NETWORK_MASK),
-                                          ((dpc & ANSI_CLUSTER_MASK) >> 8),
-                                          ((dpc & ANSI_MEMBER_MASK) >> 16));
-
-      call_pc_tree = proto_item_add_subtree(call_pc_item,
-                                             called ? ett_sccp_called_pc
-                                                    : ett_sccp_calling_pc);
-
-      proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
-                                              : hf_sccp_calling_pc_member,
-                         tvb, offset, ANSI_NCM_LENGTH, dpc);
-      offset += ANSI_NCM_LENGTH;
-      proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
-                                              : hf_sccp_calling_pc_cluster,
-                         tvb, offset, ANSI_NCM_LENGTH, dpc);
-      offset += ANSI_NCM_LENGTH;
-      proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
-                                              : hf_sccp_calling_pc_network,
-                         tvb, offset, ANSI_NCM_LENGTH, dpc);
-      offset += ANSI_NCM_LENGTH;
+      offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
     }
 
     /* Dissect GT (if present) */
@@ -1127,8 +1179,7 @@ dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
 
 /* This function is used for both data and long data (ITU only) parameters */
 static void
-dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo,
-                       proto_tree *sccp_tree, proto_tree *tree)
+dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
 
   /* Try subdissectors (if we found a valid SSN on the current message) */
@@ -1141,7 +1192,7 @@ dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo,
     return;
 
     /* No sub-dissection occured, treat it as raw data */
-    call_dissector(data_handle, tvb, pinfo, sccp_tree);
+    call_dissector(data_handle, tvb, pinfo, tree);
 }
 
 static void
@@ -1156,7 +1207,7 @@ dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
   class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
   remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
 
-  slr = tvb_get_ntoh24(tvb, 1);
+  slr = tvb_get_letoh24(tvb, 1);
 
   param_item = proto_tree_add_text(tree, tvb, 0, length,
                                   val_to_str(PARAMETER_SEGMENTATION,
@@ -1246,7 +1297,7 @@ dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
  */
 static guint16
 dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
-                      proto_tree *tree, guint8 parameter_type, guint8 offset,
+                      proto_tree *tree, guint8 parameter_type, guint16 offset,
                       guint16 parameter_length)
 {
     tvbuff_t *parameter_tvb;
@@ -1336,7 +1387,7 @@ dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
       break;
 
     case PARAMETER_DATA:
-      dissect_sccp_data_param(parameter_tvb, pinfo, sccp_tree, tree);
+      dissect_sccp_data_param(parameter_tvb, pinfo, tree);
 
       /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
       /* sccp_length = proto_item_get_len(sccp_item);
@@ -1354,7 +1405,7 @@ dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
       break;
 
     case PARAMETER_IMPORTANCE:
-      if (mtp3_standard == ITU_STANDARD)
+      if (mtp3_standard != ANSI_STANDARD)
        dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
       else
        dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
@@ -1362,19 +1413,19 @@ dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
       break;
 
     case PARAMETER_LONG_DATA:
-      if (mtp3_standard == ITU_STANDARD)
-       dissect_sccp_data_param(parameter_tvb, pinfo, sccp_tree, tree);
+      if (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);
       break;
 
     case PARAMETER_ISNI:
-      if (mtp3_standard == ANSI_STANDARD)
-       dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
-      else
+      if (mtp3_standard != ANSI_STANDARD)
        dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
                                   parameter_length);
+      else
+       dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
       break;
 
     default:
@@ -1394,7 +1445,7 @@ dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
 static guint16
 dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
                                proto_tree *sccp_tree, proto_tree *tree,
-                               guint8 parameter_type, guint8 offset)
+                               guint8 parameter_type, guint16 offset)
 {
   guint16 parameter_length;
   guint8 length_length;
@@ -1407,7 +1458,7 @@ dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
   else
   {
     /* Long data parameter has 16 bit length */
-    parameter_length = tvb_get_ntohs(tvb, offset);
+    parameter_length = tvb_get_letohs(tvb, offset);
     length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
   }
 
@@ -1436,7 +1487,7 @@ dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
 static void
 dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
                                 proto_tree *sccp_tree, proto_tree *tree,
-                                guint8 offset)
+                                guint16 offset)
 {
   guint8 parameter_type;
 
@@ -1460,34 +1511,40 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                     proto_tree *tree)
 {
   guint8 message_type;
-  guint8 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
-  guint8 optional_pointer = 0;
-  guint8 offset = 0;
+  guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
+  guint16 optional_pointer = 0;
+  guint16 offset = 0;
 
 /* Macro for getting pointer to mandatory variable parameters */
-#define VARIABLE_POINTER(var, hf_var) \
-    var = tvb_get_guint8(tvb, offset); \
+#define VARIABLE_POINTER(var, hf_var, ptr_size) \
+    if (ptr_size == POINTER_LENGTH) \
+       var = tvb_get_guint8(tvb, offset); \
+    else \
+       var = tvb_get_letohs(tvb, offset); \
     proto_tree_add_uint(sccp_tree, hf_var, tvb, \
-                       offset, POINTER_LENGTH, var); \
+                       offset, ptr_size, var); \
     var += offset; \
-    offset += POINTER_LENGTH;
+    offset += ptr_size;
 
 /* Macro for getting pointer to optional parameters */
-#define OPTIONAL_POINTER \
-    optional_pointer = tvb_get_guint8(tvb, offset); \
+#define OPTIONAL_POINTER(ptr_size) \
+    if (ptr_size == POINTER_LENGTH) \
+       optional_pointer = tvb_get_guint8(tvb, offset); \
+    else \
+       optional_pointer = tvb_get_letohs(tvb, offset); \
     proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
-                       offset, POINTER_LENGTH, optional_pointer); \
+                       offset, ptr_size, optional_pointer); \
     optional_pointer += offset; \
-    offset += POINTER_LENGTH;
+    offset += ptr_size;
+
 
   /* Extract the message type;  all other processing is based on this */
   message_type   = tvb_get_guint8(tvb, MESSAGE_TYPE_OFFSET);
   offset = MESSAGE_TYPE_LENGTH;
 
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+  if (check_col(pinfo->cinfo, COL_INFO))
+    col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
                    val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
-  };
 
   if (sccp_tree) {
     /* add the message type to the protocol tree */
@@ -1509,8 +1566,8 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     PARAMETER_CLASS, offset,
                                     PROTOCOL_CLASS_LENGTH);
 
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-    OPTIONAL_POINTER
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+    OPTIONAL_POINTER(POINTER_LENGTH)
 
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                    PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1534,7 +1591,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
                                     PARAMETER_CLASS, offset,
                                     PROTOCOL_CLASS_LENGTH);
-    OPTIONAL_POINTER
+    OPTIONAL_POINTER(POINTER_LENGTH)
     break;
 
   case MESSAGE_TYPE_CREF:
@@ -1545,7 +1602,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
                                     PARAMETER_REFUSAL_CAUSE, offset,
                                     REFUSAL_CAUSE_LENGTH);
-    OPTIONAL_POINTER
+    OPTIONAL_POINTER(POINTER_LENGTH)
     break;
 
   case MESSAGE_TYPE_RLSD:
@@ -1560,7 +1617,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     PARAMETER_RELEASE_CAUSE, offset,
                                     RELEASE_CAUSE_LENGTH);
 
-    OPTIONAL_POINTER
+    OPTIONAL_POINTER(POINTER_LENGTH)
     break;
 
   case MESSAGE_TYPE_RLC:
@@ -1582,7 +1639,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     PARAMETER_SEGMENTING_REASSEMBLING,
                                     offset, SEGMENTING_REASSEMBLING_LENGTH);
 
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
                                    variable_pointer1);
     break;
@@ -1613,9 +1670,9 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
     offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
                                     PARAMETER_CLASS, offset,
                                     PROTOCOL_CLASS_LENGTH);
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
-    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
 
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                    PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1632,9 +1689,9 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     PARAMETER_RETURN_CAUSE, offset,
                                     RETURN_CAUSE_LENGTH);
 
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
-    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
 
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                    PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1654,7 +1711,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     offset,
                                     DESTINATION_LOCAL_REFERENCE_LENGTH);
 
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
                                    variable_pointer1);
     break;
@@ -1725,10 +1782,10 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     PARAMETER_HOP_COUNTER, offset,
                                     HOP_COUNTER_LENGTH);
 
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
-    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
-    OPTIONAL_POINTER
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+    OPTIONAL_POINTER(POINTER_LENGTH)
 
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                    PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1748,10 +1805,10 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                     PARAMETER_HOP_COUNTER, offset,
                                     HOP_COUNTER_LENGTH);
 
-    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
-    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
-    OPTIONAL_POINTER
+    VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+    VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+    OPTIONAL_POINTER(POINTER_LENGTH)
 
     dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                    PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1764,7 +1821,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
     break;
 
   case MESSAGE_TYPE_LUDT:
-    if (mtp3_standard == ITU_STANDARD)
+    if (mtp3_standard != ANSI_STANDARD)
     {
       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
                                       PARAMETER_CLASS, offset,
@@ -1773,10 +1830,10 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                       PARAMETER_HOP_COUNTER, offset,
                                       HOP_COUNTER_LENGTH);
 
-      VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-      VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
-      VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
-      OPTIONAL_POINTER
+      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)
 
       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                      PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1791,7 +1848,7 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
     break;
 
   case MESSAGE_TYPE_LUDTS:
-    if (mtp3_standard == ITU_STANDARD)
+    if (mtp3_standard != ANSI_STANDARD)
     {
       offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
                                       PARAMETER_RETURN_CAUSE, offset,
@@ -1800,10 +1857,10 @@ dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
                                       PARAMETER_HOP_COUNTER, offset,
                                       HOP_COUNTER_LENGTH);
 
-      VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1)
-      VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2)
-      VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3)
-      OPTIONAL_POINTER
+      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)
 
       dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
                                      PARAMETER_CALLED_PARTY_ADDRESS,
@@ -1835,7 +1892,17 @@ dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
   /* Make entry in the Protocol column on summary display */
   if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP");
+    switch(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;
+    };      
 
   /* In the interest of speed, if "tree" is NULL, don't do any work not
      necessary to generate protocol tree items. */
@@ -1861,19 +1928,19 @@ proto_register_sccp(void)
        "", HFILL}},
     { &hf_sccp_variable_pointer1,
       { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
-       FT_UINT8, BASE_DEC, NULL, 0x0,
+       FT_UINT16, BASE_DEC, NULL, 0x0,
        "", HFILL}},
     { &hf_sccp_variable_pointer2,
       { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
-       FT_UINT8, BASE_DEC, NULL, 0x0,
+       FT_UINT16, BASE_DEC, NULL, 0x0,
        "", HFILL}},
     { &hf_sccp_variable_pointer3,
       { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
-       FT_UINT8, BASE_DEC, NULL, 0x0,
+       FT_UINT16, BASE_DEC, NULL, 0x0,
        "", HFILL}},
     { &hf_sccp_optional_pointer,
       { "Pointer to Optional parameter", "sccp.optional_pointer",
-       FT_UINT8, BASE_DEC, NULL, 0x0,
+       FT_UINT16, BASE_DEC, NULL, 0x0,
        "", HFILL}},
     { &hf_sccp_ssn,
       { "Called or Calling SubSystem Number", "sccp.ssn",
@@ -1925,6 +1992,14 @@ proto_register_sccp(void)
       { "PC", "sccp.called.pc",
        FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
        "", HFILL}},
+    { &hf_sccp_called_ansi_pc,
+      { "PC", "sccp.called.ansi_pc",
+       FT_STRING, BASE_NONE, NULL, 0x0,
+       "", HFILL}},
+    { &hf_sccp_called_chinese_pc,
+      { "PC", "sccp.called.chinese_pc",
+       FT_STRING, BASE_NONE, NULL, 0x0,
+       "", HFILL}},
     { &hf_sccp_called_pc_network,
       { "PC Network",
        "sccp.called.network",
@@ -2011,6 +2086,14 @@ proto_register_sccp(void)
       { "PC", "sccp.calling.pc",
        FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
        "", HFILL}},
+    { &hf_sccp_calling_ansi_pc,
+      { "PC", "sccp.calling.ansi_pc",
+       FT_STRING, BASE_NONE, NULL, 0x0,
+       "", HFILL}},
+    { &hf_sccp_calling_chinese_pc,
+      { "PC", "sccp.calling.chinese_pc",
+       FT_STRING, BASE_NONE, NULL, 0x0,
+       "", HFILL}},
     { &hf_sccp_calling_pc_network,
       { "PC Network",
        "sccp.calling.network",
@@ -2145,15 +2228,15 @@ proto_register_sccp(void)
     /* ISNI is ANSI only */
     { &hf_sccp_ansi_isni_mi,
       { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
-       FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_MI_MASK,
+       FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
        "", HFILL}},
     { &hf_sccp_ansi_isni_iri,
       { "ISNI Routing Indicator", "sccp.isni.iri",
-       FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_IRI_MASK,
+       FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
        "", HFILL}},
     { &hf_sccp_ansi_isni_ti,
       { "ISNI Type Indicator", "sccp.isni.ti",
-       FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_TI_MASK,
+       FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
        "", HFILL}},
     { &hf_sccp_ansi_isni_netspec,
       { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",