Squelch an MSVC++ complaint.
[obnox/wireshark/wip.git] / packet-x25.c
index d290b000c8f53a17b9d0d3e5eb54a82925e60c3b..01f71eb1f9719620b301d453ffe30f37a2e13b29 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for x25 packet disassembly
  * Olivier Abad <oabad@cybercable.fr>
  *
- * $Id: packet-x25.c,v 1.43 2001/01/03 23:30:50 oabad Exp $
+ * $Id: packet-x25.c,v 1.53 2001/07/18 15:49:29 oabad Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
-#include "etypes.h"
+#include "llcsaps.h"
 #include "packet.h"
-#include "packet-x25.h"
-#include "packet-ip.h"
-#include "packet-osi.h"
 #include "nlpid.h"
 
 #define FROM_DCE                       0x80
@@ -98,20 +95,12 @@ static int hf_x25_dbit = -1;
 static int hf_x25_mod = -1;
 static int hf_x25_lcn = -1;
 static int hf_x25_type = -1;
-static int hf_x25_p_r = -1;
-static int hf_x25_mbit = -1;
-static int hf_x25_p_s = -1;
-static int proto_ex25 = -1;
-static int hf_ex25_gfi = -1;
-static int hf_ex25_abit = -1;
-static int hf_ex25_qbit = -1;
-static int hf_ex25_dbit = -1;
-static int hf_ex25_mod = -1;
-static int hf_ex25_lcn = -1;
-static int hf_ex25_type = -1;
-static int hf_ex25_p_r = -1;
-static int hf_ex25_mbit = -1;
-static int hf_ex25_p_s = -1;
+static int hf_x25_p_r_mod8 = -1;
+static int hf_x25_p_r_mod128 = -1;
+static int hf_x25_mbit_mod8 = -1;
+static int hf_x25_mbit_mod128 = -1;
+static int hf_x25_p_s_mod8 = -1;
+static int hf_x25_p_s_mod128 = -1;
 
 static gint ett_x25 = -1;
 static gint ett_x25_gfi = -1;
@@ -386,10 +375,22 @@ static char *clear_code(unsigned char code)
        return "DTE Originated";
     if (code == 0x01)
        return "Number Busy";
+    if (code == 0x03)
+       return "Invalid Facility Requested";
+    if (code == 0x05)
+       return "Network Congestion";
     if (code == 0x09)
        return "Out Of Order";
+    if (code == 0x0B)
+       return "Access Barred";
+    if (code == 0x0D)
+       return "Not Obtainable";
     if (code == 0x11)
        return "Remote Procedure Error";
+    if (code == 0x13)
+       return "Local Procedure Error";
+    if (code == 0x15)
+       return "RPOA Out Of Order";
     if (code == 0x19)
        return "Reverse Charging Acceptance Not Subscribed";
     if (code == 0x21)
@@ -398,18 +399,6 @@ static char *clear_code(unsigned char code)
        return "Fast Select Acceptance Not Subscribed";
     if (code == 0x39)
        return "Destination Absent";
-    if (code == 0x03)
-       return "Invalid Facility Requested";
-    if (code == 0x0B)
-       return "Access Barred";
-    if (code == 0x13)
-       return "Local Procedure Error";
-    if (code == 0x05)
-       return "Network Congestion";
-    if (code == 0x0D)
-       return "Not Obtainable";
-    if (code == 0x15)
-       return "RPOA Out Of Order";
 
     sprintf(buffer, "Unknown %02X", code);
 
@@ -556,6 +545,87 @@ static char *clear_diag(unsigned char code)
        return "Unknown called DNIC";
     if (code == 122)
        return "Maintenance action";
+    if (code == 144)
+       return "Timer expired or retransmission count surpassed";
+    if (code == 145)
+       return "Timer expired or retransmission count surpassed for INTERRUPT";
+    if (code == 146)
+       return "Timer expired or retransmission count surpassed for DATA "
+              "packet transmission";
+    if (code == 147)
+       return "Timer expired or retransmission count surpassed for REJECT";
+    if (code == 160)
+       return "DTE-specific signals";
+    if (code == 161)
+       return "DTE operational";
+    if (code == 162)
+       return "DTE not operational";
+    if (code == 163)
+       return "DTE resource constraint";
+    if (code == 164)
+       return "Fast select not subscribed";
+    if (code == 165)
+       return "Invalid partially full DATA packet";
+    if (code == 166)
+       return "D-bit procedure not supported";
+    if (code == 167)
+       return "Registration/Cancellation confirmed";
+    if (code == 224)
+       return "OSI network service problem";
+    if (code == 225)
+       return "Disconnection (transient condition)";
+    if (code == 226)
+       return "Disconnection (permanent condition)";
+    if (code == 227)
+       return "Connection rejection - reason unspecified (transient "
+              "condition)";
+    if (code == 228)
+       return "Connection rejection - reason unspecified (permanent "
+              "condition)";
+    if (code == 229)
+       return "Connection rejection - quality of service not available "
+               "transient condition)";
+    if (code == 230)
+       return "Connection rejection - quality of service not available "
+               "permanent condition)";
+    if (code == 231)
+       return "Connection rejection - NSAP unreachable (transient condition)";
+    if (code == 232)
+       return "Connection rejection - NSAP unreachable (permanent condition)";
+    if (code == 233)
+       return "reset - reason unspecified";
+    if (code == 234)
+       return "reset - congestion";
+    if (code == 235)
+       return "Connection rejection - NSAP address unknown (permanent "
+               "condition)";
+    if (code == 240)
+       return "Higher layer initiated";
+    if (code == 241)
+       return "Disconnection - normal";
+    if (code == 242)
+       return "Disconnection - abnormal";
+    if (code == 243)
+       return "Disconnection - incompatible information in user data";
+    if (code == 244)
+       return "Connection rejection - reason unspecified (transient "
+               "condition)";
+    if (code == 245)
+       return "Connection rejection - reason unspecified (permanent "
+               "condition)";
+    if (code == 246)
+       return "Connection rejection - quality of service not available "
+               "(transient condition)";
+    if (code == 247)
+       return "Connection rejection - quality of service not available "
+               "(permanent condition)";
+    if (code == 248)
+       return "Connection rejection - incompatible information in user data";
+    if (code == 249)
+       return "Connection rejection - unrecognizable protocol indentifier "
+               "in user data";
+    if (code == 250)
+       return "Reset - user resynchronization";
 
     sprintf(buffer, "Unknown %d", code);
 
@@ -1299,7 +1369,7 @@ x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
 static int
 get_x25_pkt_len(tvbuff_t *tvb)
 {
-    int length, called_len, calling_len, dte_len, dce_len;
+    guint length, called_len, calling_len, dte_len, dce_len;
     guint8 byte2, bytex;
 
     byte2 = tvb_get_guint8(tvb, 2);
@@ -1316,6 +1386,11 @@ get_x25_pkt_len(tvbuff_t *tvb)
        return MIN(tvb_reported_length(tvb),length);
 
     case X25_CALL_ACCEPTED:
+       /* The calling/called address length byte (following the packet type)
+        * is not mandatory, so we must check the packet length before trying
+        * to read it */
+       if (tvb_reported_length(tvb) == 3)
+           return(3);
        bytex = tvb_get_guint8(tvb, 3);
        called_len  = (bytex >> 0) & 0x0F;
        calling_len = (bytex >> 4) & 0x0F;
@@ -1393,13 +1468,13 @@ static const value_string sharing_strategy_vals[] = {
         {0x00,            NULL}
 };
 
-void
+static void
 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
     proto_tree *x25_tree=0, *gfi_tree=0;
     proto_item *ti;
-    int localoffset=0;
-    int x25_pkt_len;
+    guint localoffset=0;
+    guint x25_pkt_len;
     int modulo;
     guint16 vc;
     dissector_handle_t dissect;
@@ -1408,8 +1483,6 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     guint8 pkt_type;
     tvbuff_t *next_tvb;
 
-    pinfo->current_proto = "X.25";
-
     if (check_col(pinfo->fd, COL_PROTOCOL))
        col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
 
@@ -1418,12 +1491,6 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
     vc     = (int)(bytes0_1 & 0x0FFF);
 
-    if (modulo == 8) {
-      CHECK_DISPLAY_AS_DATA(proto_x25, tvb, pinfo, tree);
-    } else {
-      CHECK_DISPLAY_AS_DATA(proto_ex25, tvb, pinfo, tree);
-    }
-
     if (bytes0_1 & 0x8000) toa = TRUE;
     else toa = FALSE;
 
@@ -1433,8 +1500,7 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if (check_col(pinfo->fd, COL_INFO))
            col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
        if (tree)
-           proto_tree_add_protocol_format(tree,
-                   (modulo == 8 ? proto_x25 : proto_ex25), tvb, 0,
+           proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
                    tvb_length(tvb), "Invalid/short X.25 packet");
        return;
     }
@@ -1442,31 +1508,24 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     pkt_type = tvb_get_guint8(tvb, 2);
 
     if (tree) {
-       ti = proto_tree_add_protocol_format(tree,
-               (modulo == 8) ? proto_x25 : proto_ex25, tvb, 0, x25_pkt_len,
-               "X.25");
+       ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
        x25_tree = proto_item_add_subtree(ti, ett_x25);
-       ti = proto_tree_add_item(x25_tree,
-               (modulo == 8) ? hf_x25_gfi : hf_ex25_gfi, tvb, 0, 2, FALSE);
+       ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
        gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
        if ((pkt_type & 0x01) == X25_DATA)
-           proto_tree_add_boolean(gfi_tree,
-                   (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit, tvb, 0, 2,
+           proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
                    bytes0_1);
        else if (pkt_type == X25_CALL_REQUEST ||
                pkt_type == X25_CALL_ACCEPTED ||
                pkt_type == X25_CLEAR_REQUEST ||
                pkt_type == X25_CLEAR_CONFIRMATION)
-           proto_tree_add_boolean(gfi_tree,
-                   (modulo == 8) ? hf_x25_abit : hf_ex25_abit, tvb, 0, 2,
+           proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
                    bytes0_1);
        if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
                (pkt_type & 0x01) == X25_DATA)
-           proto_tree_add_boolean(gfi_tree,
-                   (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit, tvb, 0, 2,
+           proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
                    bytes0_1);
-       proto_tree_add_uint(gfi_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
-               tvb, 0, 2, bytes0_1);
+       proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
     }
 
     switch (pkt_type) {
@@ -1477,11 +1536,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                                                 : "Call req." ,
                     vc);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree,
-                   (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
                    0, 2, bytes0_1);
-           proto_tree_add_uint_format(x25_tree,
-                   (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
+           proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
                    X25_CALL_REQUEST,
                    (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
                                                                 : "Call request");
@@ -1503,8 +1560,11 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            spi = tvb_get_guint8(tvb, localoffset);
            switch (spi) {
 
-           /* XXX - handle other NLPIDs, e.g. PPP? */
-
+           /*
+            * XXX - handle other NLPIDs, e.g. PPP?
+            * See RFC 1356 for information on at least some other
+            * ways of running other protocols atop X.25.
+            */
            case NLPID_IP:
                x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
                                         pinfo->fd->abs_usecs, ip_handle);
@@ -1591,11 +1651,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                                                 : "Call acc." ,
                    vc);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
-                   tvb, 0, 2, bytes0_1);
-           proto_tree_add_uint_format(x25_tree,
-                   (modulo == 8) ? hf_x25_type : hf_ex25_type,
-                   tvb, 2, 1, X25_CALL_ACCEPTED,
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_CALL_ACCEPTED,
                    (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
                                                                 : "Call accepted");
        }
@@ -1623,11 +1681,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
        x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
-                   0, 2, bytes0_1);
-           proto_tree_add_uint_format(x25_tree,
-                   (modulo == 8) ? hf_x25_type : hf_ex25_type,
-                   tvb, localoffset+2, 1, X25_CLEAR_REQUEST,
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
+                   localoffset+2, 1, X25_CLEAR_REQUEST,
                    (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
                                                                 : "Clear request");
            proto_tree_add_text(x25_tree, tvb, 3, 1,
@@ -1641,10 +1697,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if(check_col(pinfo->fd, COL_INFO))
            col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
-                   0, 2, bytes0_1);
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_CLEAR_CONFIRMATION);
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_CLEAR_CONFIRMATION);
        }
        localoffset = x25_pkt_len;
 
@@ -1660,8 +1715,8 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                    (int)tvb_get_guint8(tvb, 3));
        }
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_DIAGNOSTIC);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_DIAGNOSTIC);
            proto_tree_add_text(x25_tree, tvb, 3, 1,
                    "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
        }
@@ -1671,10 +1726,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if(check_col(pinfo->fd, COL_INFO))
            col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
-                   0, 2, bytes0_1);
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_INTERRUPT);
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_INTERRUPT);
        }
        localoffset = x25_pkt_len;
        break;
@@ -1682,10 +1736,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if(check_col(pinfo->fd, COL_INFO))
            col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
-                   0, 2, bytes0_1);
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_INTERRUPT_CONFIRMATION);
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_INTERRUPT_CONFIRMATION);
        }
        localoffset = x25_pkt_len;
        break;
@@ -1699,10 +1752,8 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
        x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
-                   0, 2, bytes0_1);
-           proto_tree_add_uint_format(x25_tree,
-                   (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
                    X25_RESET_REQUEST,
                    (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
                                                                  : "Reset request");
@@ -1717,10 +1768,9 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if(check_col(pinfo->fd, COL_INFO))
            col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
-                   0, 2, bytes0_1);
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_RESET_CONFIRMATION);
+           proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_RESET_CONFIRMATION);
        }
        localoffset = x25_pkt_len;
        break;
@@ -1733,8 +1783,7 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                    (int)tvb_get_guint8(tvb, 3));
        }
        if (x25_tree) {
-           proto_tree_add_uint_format(x25_tree,
-                   (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
+           proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
                    X25_RESTART_REQUEST,
                    (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
                                                                 : "Restart request");
@@ -1749,16 +1798,16 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if(check_col(pinfo->fd, COL_INFO))
            col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
        if (x25_tree)
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_RESTART_CONFIRMATION);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_RESTART_CONFIRMATION);
        localoffset = x25_pkt_len;
        break;
     case X25_REGISTRATION_REQUEST:
        if(check_col(pinfo->fd, COL_INFO))
            col_set_str(pinfo->fd, COL_INFO, "Registration req.");
        if (x25_tree)
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_REGISTRATION_REQUEST);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_REGISTRATION_REQUEST);
        localoffset = 3;
        if (localoffset < x25_pkt_len)
            x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
@@ -1779,8 +1828,8 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if(check_col(pinfo->fd, COL_INFO))
            col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
        if (x25_tree) {
-           proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
-                   2, 1, X25_REGISTRATION_CONFIRMATION);
+           proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+                   X25_REGISTRATION_CONFIRMATION);
            proto_tree_add_text(x25_tree, tvb, 3, 1,
                    "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
            proto_tree_add_text(x25_tree, tvb, 4, 1,
@@ -1821,32 +1870,32 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                            (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
            }
            if (x25_tree) {
-               proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
-                       tvb, localoffset-2, 2, bytes0_1);
+               proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+                       2, bytes0_1);
+               proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
+                       localoffset, 1, X25_DATA);
                if (modulo == 8) {
-                   proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
-                           localoffset, 1, X25_DATA);
-                   proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
                            localoffset, 1, pkt_type);
                    if (pkt_type & 0x10)
-                       proto_tree_add_boolean(x25_tree, hf_x25_mbit, tvb, localoffset, 1,
-                           pkt_type);
-                   proto_tree_add_uint(x25_tree, hf_x25_p_s, tvb, localoffset, 1,
-                           pkt_type);
+                       proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
+                           localoffset, 1, pkt_type);
+                   proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
+                           localoffset, 1, pkt_type);
                    proto_tree_add_text(x25_tree, tvb, localoffset, 1,
                            decode_boolean_bitfield(pkt_type, 0x01, 1*8,
                                NULL, "DATA"));
                }
                else {
-                   proto_tree_add_uint_hidden(x25_tree, hf_ex25_type, tvb,
-                           localoffset, 1, X25_DATA);
-                   proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
                            localoffset, 1, pkt_type);
-                   proto_tree_add_uint(x25_tree, hf_x25_p_s, tvb,
-                           localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+                   proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
+                           localoffset+1, 1,
+                           tvb_get_guint8(tvb, localoffset+1));
                    if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
-                       proto_tree_add_boolean(x25_tree, hf_ex25_mbit, tvb,
-                               localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
+                       proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
+                               localoffset+1, 1,
+                               tvb_get_guint8(tvb, localoffset+1));
                }
            }
            localoffset += (modulo == 8) ? 1 : 2;
@@ -1864,18 +1913,18 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                            vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
            }
            if (x25_tree) {
-               proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
-                       tvb, localoffset-2, 2, bytes0_1);
+               proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+                       2, bytes0_1);
                if (modulo == 8) {
-                   proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
                            localoffset, 1, pkt_type);
                    proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
                            localoffset, 1, X25_RR);
                }
                else {
-                   proto_tree_add_uint(x25_tree, hf_ex25_type, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
                            localoffset, 1, X25_RR);
-                   proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
+                   proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
                            localoffset+1, 1, FALSE);
                }
            }
@@ -1891,18 +1940,18 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                            vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
            }
            if (x25_tree) {
-               proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
-                       tvb, localoffset-2, 2, bytes0_1);
+               proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+                       2, bytes0_1);
                if (modulo == 8) {
-                   proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
                            localoffset, 1, pkt_type);
                    proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
                            localoffset, 1, X25_RNR);
                }
                else {
-                   proto_tree_add_uint(x25_tree, hf_ex25_type, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
                            localoffset, 1, X25_RNR);
-                   proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
+                   proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
                            localoffset+1, 1, FALSE);
                }
            }
@@ -1918,18 +1967,18 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                            vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
            }
            if (x25_tree) {
-               proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
-                       tvb, localoffset-2, 2, bytes0_1);
+               proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+                       2, bytes0_1);
                if (modulo == 8) {
-                   proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
                            localoffset, 1, pkt_type);
                    proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
                            localoffset, 1, X25_REJ);
                }
                else {
-                   proto_tree_add_uint(x25_tree, hf_ex25_type, tvb,
+                   proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
                            localoffset, 1, X25_REJ);
-                   proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
+                   proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
                            localoffset+1, 1, FALSE);
                }
            }
@@ -1959,70 +2008,46 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 void
 proto_register_x25(void)
 {
-    static hf_register_info hf8[] = {
+    static hf_register_info hf[] = {
        { &hf_x25_gfi,
          { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
-               "General format identifier" } },
+               "General format identifier", HFILL }},
        { &hf_x25_abit,
          { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
-               "Address Bit" } },
+               "Address Bit", HFILL }},
        { &hf_x25_qbit,
          { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
-               "Qualifier Bit" } },
+               "Qualifier Bit", HFILL }},
        { &hf_x25_dbit,
          { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
-               "Delivery Confirmation Bit" } },
+               "Delivery Confirmation Bit", HFILL }},
        { &hf_x25_mod,
          { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
-               "Specifies whether the frame is modulo 8 or 128" } },
+               "Specifies whether the frame is modulo 8 or 128", HFILL }},
        { &hf_x25_lcn,
          { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
-               "Logical Channel Number" } },
+               "Logical Channel Number", HFILL }},
        { &hf_x25_type,
          { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
-               "Packet Type" } },
-       { &hf_x25_p_r,
+               "Packet Type", HFILL }},
+       { &hf_x25_p_r_mod8,
          { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
-               "Packet Receive Sequence Number" } },
-       { &hf_x25_mbit,
+               "Packet Receive Sequence Number", HFILL }},
+       { &hf_x25_p_r_mod128,
+         { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
+               "Packet Receive Sequence Number", HFILL }},
+       { &hf_x25_mbit_mod8,
          { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
-               "More Bit" } },
-       { &hf_x25_p_s,
+               "More Bit", HFILL }},
+       { &hf_x25_mbit_mod128,
+         { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
+               "More Bit", HFILL }},
+       { &hf_x25_p_s_mod8,
          { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
-               "Packet Send Sequence Number" } },
-    };
-
-    static hf_register_info hf128[] = {
-       { &hf_ex25_gfi,
-         { "GFI", "ex.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
-               "General format identifier" } },
-       { &hf_ex25_abit,
-         { "A Bit", "ex.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
-               "Address Bit" } },
-       { &hf_ex25_qbit,
-         { "Q Bit", "ex.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
-               "Qualifier Bit" } },
-       { &hf_ex25_dbit,
-         { "D Bit", "ex.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
-               "Delivery Confirmation Bit" } },
-       { &hf_ex25_mod,
-         { "Modulo", "ex.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
-               "Specifies whether the frame is modulo 8 or 128" } },
-       { &hf_ex25_lcn,
-         { "Logical Channel", "ex.25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
-               "Logical Channel Number" } },
-       { &hf_ex25_type,
-         { "Packet Type", "ex.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
-               "Packet Type" } },
-       { &hf_ex25_p_r,
-         { "P(R)", "ex.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
-               "Packet Receive Sequence Number" } },
-       { &hf_ex25_mbit,
-         { "M Bit", "ex.25.m", FT_BOOLEAN, 8, NULL, 0x01,
-               "More Bit" } },
-       { &hf_ex25_p_s,
-         { "P(S)", "ex.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
-               "Packet Send Sequence Number" } },
+               "Packet Send Sequence Number", HFILL }},
+       { &hf_x25_p_s_mod128,
+         { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
+               "Packet Send Sequence Number", HFILL }},
     };
     static gint *ett[] = {
         &ett_x25,
@@ -2051,20 +2076,21 @@ proto_register_x25(void)
     };
 
     proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
-    proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)",
-        "Extended X.25", "ex.25");
-    proto_register_field_array (proto_x25, hf8, array_length(hf8));
-    proto_register_field_array (proto_ex25, hf128, array_length(hf128));
+    proto_register_field_array (proto_x25, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
     register_init_routine(&reinit_x25_hashtable);
+
+    register_dissector("x.25", dissect_x25, proto_x25);
 }
 
 void
 proto_reg_handoff_x25(void)
 {
     /*
-     * Get handles for the IP and OSI TP (COTP/CLTP) dissector.
+     * Get handles for the IP and OSI TP (COTP/CLTP) dissectors.
      */
     ip_handle = find_dissector("ip");
     ositp_handle = find_dissector("ositp");
+
+    dissector_add("llc.dsap", SAP_X25, dissect_x25, proto_x25);
 }