Give the IPX dissector dissector hash tables for the IPX type and socket
[obnox/wireshark/wip.git] / packet-ipx.c
index 4e8353431a8542ebb43d664df5308e3d1e2be798..1fb9db630be054715ad4b01266f243187bd49a3f 100644 (file)
@@ -1,11 +1,11 @@
 /* packet-ipx.c
  * Routines for NetWare's IPX
- * Gilbert Ramirez <gram@verdict.uthscsa.edu>
+ * Gilbert Ramirez <gram@xiexie.org>
  *
- * $Id: packet-ipx.c,v 1.39 1999/11/30 23:56:35 gram Exp $
+ * $Id: packet-ipx.c,v 1.60 2000/05/30 03:35:51 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@unicom.net>
+ * By Gerald Combs <gerald@zing.org>
  * Copyright 1998 Gerald Combs
  *
  * 
 
 #include <stdio.h>
 #include <glib.h>
+#include "etypes.h"
+#include "ppptypes.h"
+#include "llcsaps.h"
 #include "packet.h"
 #include "packet-ipx.h"
-#include "packet-ncp.h"
+#include "packet-nbipx.h"
 #include "resolv.h"
 
+#include "packet-snmp.h"
+
 /* The information in this module (IPX, SPX, NCP) comes from:
        NetWare LAN Analysis, Second Edition
        Laura A. Chappell and Dan E. Hakes
@@ -64,6 +69,9 @@ static int hf_ipx_ssocket = -1;
 
 static gint ett_ipx = -1;
 
+static dissector_table_t ipx_type_dissector_table;
+static dissector_table_t ipx_socket_dissector_table;
+
 static int proto_spx = -1;
 static int hf_spx_connection_control = -1;
 static int hf_spx_datastream_type = -1;
@@ -88,6 +96,11 @@ static int hf_sap_response = -1;
 static gint ett_ipxsap = -1;
 static gint ett_ipxsap_server = -1;
 
+static gint ett_ipxmsg = -1;
+static int proto_ipxmsg = -1;
+static int hf_msg_conn = -1;
+static int hf_msg_sigchar = -1;
+
 static void
 dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
 
@@ -97,11 +110,13 @@ dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
 static void
 dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
 
-typedef        void    (dissect_func_t)(const u_char *, int, frame_data *, proto_tree *);
+static void
+dissect_ipxmsg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
+
+#define UDP_PORT_IPX    213            /* RFC 1234 */
 
 struct port_info {
        guint16 port;
-       dissect_func_t *func;
        char    *text;
 };
 
@@ -119,55 +134,29 @@ struct server_info {
 /* IPX                                                               */
 /* ================================================================= */
 
-#define IPX_SOCKET_NCP                 0x0451
-#define IPX_SOCKET_SAP                 0x0452
-#define IPX_SOCKET_IPXRIP              0x0453
-#define IPX_SOCKET_NETBIOS             0x0455
-#define IPX_SOCKET_DIAGNOSTIC          0x0456
-#define IPX_SOCKET_SERIALIZATION       0x0457
-#define IPX_SOCKET_NWLINK_SMB_NAMEQUERY        0x0551
-#define IPX_SOCKET_NWLINK_SMB_DGRAM    0x0553
-#define IPX_SOCKET_NWLINK_SMB_BROWSE   0x0555 /* ? not sure on this
-       but I guessed based on the content of the packet I saw */
-#define IPX_SOCKET_ATTACHMATE_GW       0x055d
-#define IPX_SOCKET_IPX_MESSAGE         0x4001
-#define IPX_SOCKET_ADSM                 0x8522 /* www.tivoli.com */
-#define IPX_SOCKET_SNMP_AGENT           0x900F /* RFC 1906 */
-#define IPX_SOCKET_SNMP_SINK            0x9010 /* RFC 1906 */
-#define IPX_SOCKET_TCP_TUNNEL           0x9091 /* RFC 1791 */
-#define IPX_SOCKET_UDP_TUNNEL           0x9092 /* RFC 1791 */
-
 static struct port_info        ports[] = {
-       { IPX_SOCKET_NCP,                       dissect_ncp,
-                               "NCP" },
-       { IPX_SOCKET_SAP,                       dissect_ipxsap,
-                               "SAP" },
-       { IPX_SOCKET_IPXRIP,                    dissect_ipxrip,
-                               "RIP" },
-       { IPX_SOCKET_NETBIOS,                   NULL,
-                               "NetBIOS" },
-       { IPX_SOCKET_DIAGNOSTIC,                NULL,
-                               "Diagnostic" },
-       { IPX_SOCKET_SERIALIZATION,             NULL,
-                               "Serialization" },
-       { IPX_SOCKET_NWLINK_SMB_NAMEQUERY,      NULL,
-                               "NWLink SMB Name Query" },
-       { IPX_SOCKET_NWLINK_SMB_DGRAM,          dissect_nwlink_dg,
-                               "NWLink SMB Datagram" },
-       { IPX_SOCKET_NWLINK_SMB_BROWSE, NULL,
-                               "NWLink SMB Browse" },
-       { IPX_SOCKET_ATTACHMATE_GW,             NULL,
-                               "Attachmate Gateway" },
-       { IPX_SOCKET_IPX_MESSAGE,               NULL,
-                               "IPX Message" },
-       { IPX_SOCKET_SNMP_AGENT, NULL, "SNMP Agent" },
-       { IPX_SOCKET_SNMP_SINK, NULL, "SNMP Sink" },
-       { IPX_SOCKET_UDP_TUNNEL, NULL, "UDP Tunnel" },
-       { IPX_SOCKET_TCP_TUNNEL, NULL, "TCP Tunnel" },
-       { IPX_SOCKET_TCP_TUNNEL, NULL, "TCP Tunnel" },
-       { IPX_SOCKET_ADSM, NULL, "ADSM" },
-       { 0x0000,                               NULL,
-                               NULL }
+       { IPX_SOCKET_PING_CISCO,                "CISCO PING" },
+       { IPX_SOCKET_NCP,                       "NCP" },
+       { IPX_SOCKET_SAP,                       "SAP" },
+       { IPX_SOCKET_IPXRIP,                    "RIP" },
+       { IPX_SOCKET_NETBIOS,                   "NetBIOS" },
+       { IPX_SOCKET_DIAGNOSTIC,                "Diagnostic" },
+       { IPX_SOCKET_SERIALIZATION,             "Serialization" },
+       { IPX_SOCKET_NWLINK_SMB_NAMEQUERY,      "NWLink SMB Name Query" },
+       { IPX_SOCKET_NWLINK_SMB_DGRAM,          "NWLink SMB Datagram" },
+       { IPX_SOCKET_NWLINK_SMB_BROWSE,         "NWLink SMB Browse" },
+       { IPX_SOCKET_ATTACHMATE_GW,             "Attachmate Gateway" },
+       { IPX_SOCKET_IPX_MESSAGE,               "IPX Message" },
+       { IPX_SOCKET_SNMP_AGENT,                "SNMP Agent" },
+       { IPX_SOCKET_SNMP_SINK,                 "SNMP Sink" },
+       { IPX_SOCKET_PING_NOVELL,               "NOVELL PING" },
+       { IPX_SOCKET_UDP_TUNNEL,                "UDP Tunnel" },
+       { IPX_SOCKET_TCP_TUNNEL,                "TCP Tunnel" },
+       { IPX_SOCKET_TCP_TUNNEL,                "TCP Tunnel" },
+       { IPX_SOCKET_ADSM,                      "ADSM" },
+       { IPX_SOCKET_EIGRP,                     "Cisco EIGRP for IPX" },
+       { IPX_SOCKET_WIDE_AREA_ROUTER,          "Wide Area Router" },
+       { 0x0000,                               NULL }
 };
 
 static char*
@@ -183,39 +172,6 @@ port_text(guint16 port) {
        return "Unknown";
 }
 
-static dissect_func_t*
-port_func(guint16 port) {
-       int i=0;
-
-       while (ports[i].text != NULL) {
-               if (ports[i].port == port) {
-                       return ports[i].func;
-               }
-               i++;
-       }
-       return NULL;
-}
-
-/*
- * From:
- *
- *     http://alr.base2co.com:457/netguide/dipxD.ipx_packet_struct.html
- *
- * which is part of SCO's "Network Programmer's Guide and Reference".
- *
- * It calls type 20 "NetBIOS name packet".  Microsoft Network Monitor
- * calls it "WAN Broadcast"; it's also used for SMB browser announcements,
- * i.e. NetBIOS (broadcast) datagrams.
- */
-#define IPX_PACKET_TYPE_IPX            0
-#define IPX_PACKET_TYPE_RIP            1
-#define        IPX_PACKET_TYPE_ECHO            2
-#define        IPX_PACKET_TYPE_ERROR           3
-#define IPX_PACKET_TYPE_PEP            4
-#define IPX_PACKET_TYPE_SPX            5
-#define IPX_PACKET_TYPE_NCP            17
-#define IPX_PACKET_TYPE_WANBCAST       20      /* propagated NetBIOS packet? */
-
 static const value_string ipx_packet_type_vals[] = {
        { IPX_PACKET_TYPE_IPX,          "IPX" },
        { IPX_PACKET_TYPE_RIP,          "RIP" },
@@ -242,6 +198,11 @@ static const value_string ipx_packet_type_vals[] = {
        { 0,                            NULL }
 };
 
+static const value_string ipxmsg_sigchar_vals[] = {
+       { '?', "Poll inactive station" },
+       { 0, NULL }
+};
+
 gchar*
 ipxnet_to_string(const guint8 *ad)
 {
@@ -316,7 +277,7 @@ ipxnet_to_str_punct(const guint32 ad, char punct) {
 }
 
 void
-capture_ipx(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld)
+capture_ipx(const u_char *pd, int offset, packet_counts *ld)
 {
        ld->ipx++;
 }
@@ -332,7 +293,6 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        guint8          *ipx_snode, *ipx_dnode, *ipx_snet, *ipx_dnet;
 
        guint16         ipx_dsocket, ipx_ssocket;
-       dissect_func_t  *dissect;
        guint32         ipx_dnet_val, ipx_snet_val;
 
        /* Calculate here for use in pinfo and in tree */
@@ -373,73 +333,51 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                ipx_checksum = pntohs(&pd[offset]);
                ipx_hops = pd[offset+4];
 
-               ti = proto_tree_add_item(tree, proto_ipx, offset, 30, NULL);
+               ti = proto_tree_add_item(tree, proto_ipx, NullTVB, offset, 30, NULL);
                ipx_tree = proto_item_add_subtree(ti, ett_ipx);
-               proto_tree_add_item(ipx_tree, hf_ipx_checksum, offset, 2, ipx_checksum);
-               proto_tree_add_item_format(ipx_tree, hf_ipx_len, offset+2, 2, ipx_length,
+               proto_tree_add_item(ipx_tree, hf_ipx_checksum, NullTVB, offset, 2, ipx_checksum);
+               proto_tree_add_uint_format(ipx_tree, hf_ipx_len, NullTVB, offset+2, 2, ipx_length,
                        "Length: %d bytes", ipx_length);
-               proto_tree_add_item_format(ipx_tree, hf_ipx_hops, offset+4, 1, ipx_hops,
+               proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, NullTVB, offset+4, 1, ipx_hops,
                        "Transport Control: %d hops", ipx_hops);
-               proto_tree_add_item(ipx_tree, hf_ipx_packet_type, offset+5, 1, ipx_type);
-               proto_tree_add_item(ipx_tree, hf_ipx_dnet, offset+6, 4, ipx_dnet_val);
-               proto_tree_add_item(ipx_tree, hf_ipx_dnode, offset+10, 6, ipx_dnode);
-               proto_tree_add_item_format(ipx_tree, hf_ipx_dsocket, offset+16, 2,
+               proto_tree_add_item(ipx_tree, hf_ipx_packet_type, NullTVB, offset+5, 1, ipx_type);
+               proto_tree_add_item(ipx_tree, hf_ipx_dnet, NullTVB, offset+6, 4, ipx_dnet_val);
+               proto_tree_add_item(ipx_tree, hf_ipx_dnode, NullTVB, offset+10, 6, ipx_dnode);
+               proto_tree_add_uint_format(ipx_tree, hf_ipx_dsocket, NullTVB, offset+16, 2,
                        ipx_dsocket, "Destination Socket: %s (0x%04X)",
                        port_text(ipx_dsocket), ipx_dsocket);
-               proto_tree_add_item(ipx_tree, hf_ipx_snet, offset+18, 4, ipx_snet_val);
-               proto_tree_add_item(ipx_tree, hf_ipx_snode, offset+22, 6, ipx_snode);
-               proto_tree_add_item_format(ipx_tree, hf_ipx_ssocket, offset+28, 2,
+               proto_tree_add_item(ipx_tree, hf_ipx_snet, NullTVB, offset+18, 4, ipx_snet_val);
+               proto_tree_add_item(ipx_tree, hf_ipx_snode, NullTVB, offset+22, 6, ipx_snode);
+               proto_tree_add_uint_format(ipx_tree, hf_ipx_ssocket, NullTVB, offset+28, 2,
                        ipx_ssocket, "Source Socket: %s (0x%04X)", port_text(ipx_ssocket),
                        ipx_ssocket);
        }
        offset += 30;
 
+       if (dissector_try_port(ipx_type_dissector_table, ipx_type, pd,
+           offset, fd, tree))
+               return;
        switch (ipx_type) {
-               case IPX_PACKET_TYPE_SPX:
-                       dissect_spx(pd, offset, fd, tree);
-                       break;
-
-               case IPX_PACKET_TYPE_NCP:
-                       /* Is the destination node 00:00:00:00:00:01 ? */
-                       if (pntohl(ipx_dnode) == 0 && pntohs(ipx_dnode + 4) == 1)
-                               nw_server_address = pntohl(ipx_dnet);
-
-                       /* Is the source node 00:00:00:00:00:01 ? */
-                       else if (pntohl(ipx_snode) == 0 && pntohs(ipx_snode + 4) == 1)
-                               nw_server_address = pntohl(ipx_snet);
-                       else
-                               nw_server_address = 0;
-
-                       dissect_ncp(pd, offset, fd, tree);
-                       break;
-
                case IPX_PACKET_TYPE_WANBCAST:
                case IPX_PACKET_TYPE_PEP:
                        if (ipx_dsocket == IPX_SOCKET_NETBIOS) {
                                dissect_nbipx(pd, offset, fd, tree);
-                               break;
+                               return;
                        }
                        /* else fall through */
 
                case 0: /* IPX, fall through to default */
                        /* XXX - should type 0's be dissected as NBIPX
                           if they're aimed at the NetBIOS socket? */
-               default:
-                       dissect = port_func(ipx_dsocket);
-                       if (dissect) {
-                               dissect(pd, offset, fd, tree);
-                       }
-                       else {
-                               dissect = port_func(ipx_ssocket);
-                               if (dissect) {
-                                       dissect(pd, offset, fd, tree);
-                               }
-                               else {
-                                       dissect_data(pd, offset, fd, tree);
-                               }
-                       }
                        break;
        }
+       if (dissector_try_port(ipx_socket_dissector_table, ipx_dsocket, pd,
+           offset, fd, tree))
+               return;
+       if (dissector_try_port(ipx_socket_dissector_table, ipx_ssocket, pd,
+           offset, fd, tree))
+               return;
+       dissect_data(pd, offset, fd, tree);
 }
 
 
@@ -492,40 +430,40 @@ dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                col_add_str(fd, COL_INFO, "SPX");
 
        if (tree) {
-               ti = proto_tree_add_item(tree, proto_spx, offset, 12, NULL);
+               ti = proto_tree_add_item(tree, proto_spx, NullTVB, offset, 12, NULL);
                spx_tree = proto_item_add_subtree(ti, ett_spx);
 
-               proto_tree_add_item_format(spx_tree, hf_spx_connection_control,
+               proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, NullTVB,
                                           offset,      1,
                                           pd[offset],
                                           "Connection Control: %s (0x%02X)",
                                           spx_conn_ctrl(pd[offset]), 
                                           pd[offset]);
 
-               proto_tree_add_item_format(spx_tree, hf_spx_datastream_type,
+               proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, NullTVB,
                                           offset+1,     1,
                                           pd[offset+1],
                                           "Datastream Type: %s (0x%02X)",
                                           spx_datastream(pd[offset+1]), 
                                           pd[offset+1]);
 
-               proto_tree_add_item(spx_tree, hf_spx_src_id, 
+               proto_tree_add_item(spx_tree, hf_spx_src_id, NullTVB, 
                                    offset+2,     2,
                                    pntohs( &pd[offset+2] ));
 
-               proto_tree_add_item(spx_tree, hf_spx_dst_id,
+               proto_tree_add_item(spx_tree, hf_spx_dst_id, NullTVB,
                                    offset+4,     2,
                                    pntohs( &pd[offset+4] ));
 
-               proto_tree_add_item(spx_tree, hf_spx_seq_nr, 
+               proto_tree_add_item(spx_tree, hf_spx_seq_nr, NullTVB, 
                                    offset+6,     2,
                                    pntohs( &pd[offset+6] ) );
 
-               proto_tree_add_item(spx_tree, hf_spx_ack_nr,
+               proto_tree_add_item(spx_tree, hf_spx_ack_nr, NullTVB,
                                    offset+8,     2,
                                    pntohs( &pd[offset+8] ) );
 
-               proto_tree_add_item(spx_tree, hf_spx_all_nr,
+               proto_tree_add_item(spx_tree, hf_spx_all_nr, NullTVB,
                                    offset+10,     2,
                                    pntohs( &pd[offset+10] ) );
 
@@ -534,6 +472,41 @@ dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        }
 }
 
+/* ================================================================= */
+/* IPX Message                                                       */
+/* ================================================================= */
+static void
+dissect_ipxmsg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
+       proto_tree      *msg_tree;
+       proto_item      *ti;
+       u_char conn_number, sig_char;
+
+       if ( ! BYTES_ARE_IN_FRAME(offset,2) )
+       {
+               return;
+       }
+
+       conn_number = pd[offset];
+       sig_char = pd[offset+1];
+
+       if (check_col(fd, COL_PROTOCOL))
+        col_add_str(fd, COL_PROTOCOL, "IPX MSG");
+       if (check_col(fd, COL_PROTOCOL)) {
+               col_add_fstr(fd, COL_INFO, 
+                       "%s, Connection %d", 
+                       val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
+       }
+
+       if (tree) {
+               ti = proto_tree_add_item(tree, proto_ipxmsg, NullTVB, offset, END_OF_FRAME, NULL);
+               msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
+
+               proto_tree_add_item(msg_tree, hf_msg_conn, NullTVB, offset, 1, conn_number);
+               proto_tree_add_item(msg_tree, hf_msg_sigchar, NullTVB, offset+1, 1, sig_char);
+       }
+}
+
+
 /* ================================================================= */
 /* IPX RIP                                                           */
 /* ================================================================= */
@@ -561,42 +534,42 @@ dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        }
 
        if (tree) {
-               ti = proto_tree_add_item(tree, proto_ipxrip, offset, END_OF_FRAME, NULL);
+               ti = proto_tree_add_item(tree, proto_ipxrip, NullTVB, offset, END_OF_FRAME, NULL);
                rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
 
                if (operation < 2) {
-                       proto_tree_add_text(rip_tree, offset, 2,
+                       proto_tree_add_text(rip_tree, NullTVB, offset, 2,
                        "RIP packet type: %s", rip_type[operation]);
 
                        if (operation == 0) {
                          proto_tree_add_item_hidden(rip_tree, 
                                                     hf_ipxrip_request, 
-                                                    offset, 2, 1);
+                                                    NullTVB, offset, 2, 1);
                        } else {
                          proto_tree_add_item_hidden(rip_tree, 
                                                     hf_ipxrip_response, 
-                                                    offset, 2, 1);
+                                                    NullTVB, offset, 2, 1);
                        }
 
                }
                else {
-                       proto_tree_add_text(rip_tree, offset, 2, "Unknown RIP packet type");
+                       proto_tree_add_text(rip_tree, NullTVB, offset, 2, "Unknown RIP packet type");
                }
 
-               for (cursor = offset + 2; cursor < fd->cap_len; cursor += 8) {
+               for (cursor = offset + 2; cursor < pi.captured_len; cursor += 8) {
                        memcpy(&route.network, &pd[cursor], 4);
                        route.hops = pntohs(&pd[cursor+4]);
                        route.ticks = pntohs(&pd[cursor+6]);
 
                        if (operation == IPX_RIP_REQUEST - 1) {
-                               proto_tree_add_text(rip_tree, cursor,      8,
+                               proto_tree_add_text(rip_tree, NullTVB, cursor,      8,
                                        "Route Vector: %s, %d hop%s, %d tick%s",
                                        ipxnet_to_string((guint8*)&route.network),
                                        route.hops,  route.hops  == 1 ? "" : "s",
                                        route.ticks, route.ticks == 1 ? "" : "s");
                        }
                        else {
-                               proto_tree_add_text(rip_tree, cursor,      8,
+                               proto_tree_add_text(rip_tree, NullTVB, cursor,      8,
                                        "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
                                        ipxnet_to_string((guint8*)&route.network),
                                        route.hops,  route.hops  == 1 ? "" : "s",
@@ -610,7 +583,7 @@ dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
 
 
 /* ================================================================= */
-/* SAP                                                                                                                          */
+/* SAP                                                                  */
 /* ================================================================= */
 static char*
 server_type(guint16 type)
@@ -709,30 +682,30 @@ dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        }
 
        if (tree) {
-               ti = proto_tree_add_item(tree, proto_sap, offset, END_OF_FRAME, NULL);
+               ti = proto_tree_add_item(tree, proto_sap, NullTVB, offset, END_OF_FRAME, NULL);
                sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
 
                if (query.query_type >= 1 && query.query_type <= 4) {
-                       proto_tree_add_text(sap_tree, offset, 2, sap_type[query.query_type - 1]);
+                       proto_tree_add_text(sap_tree, NullTVB, offset, 2, sap_type[query.query_type - 1]);
                        if ((query.query_type - 1) % 2) {
                          proto_tree_add_item_hidden(sap_tree, 
                                                     hf_sap_response, 
-                                                    offset, 2, 1);
+                                                    NullTVB, offset, 2, 1);
                        } else {
                          proto_tree_add_item_hidden(sap_tree, 
                                                     hf_sap_request, 
-                                                    offset, 2, 1);
+                                                    NullTVB, offset, 2, 1);
                        }
                }
                else {
-                       proto_tree_add_text(sap_tree, offset, 2,
+                       proto_tree_add_text(sap_tree, NullTVB, offset, 2,
                                        "Unknown SAP Packet Type %d", query.query_type);
                }
 
                if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
                                query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
 
-                       for (cursor = offset + 2; (cursor + 64) <= fd->cap_len; cursor += 64) {
+                       for (cursor = offset + 2; (cursor + 64) <= pi.captured_len; cursor += 64) {
                                server.server_type = pntohs(&pd[cursor]);
                                memcpy(server.server_name, &pd[cursor+2], 48);
                                memcpy(&server.server_network, &pd[cursor+50], 4);
@@ -740,31 +713,30 @@ dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                                server.server_port = pntohs(&pd[cursor+60]);
                                server.intermediate_network = pntohs(&pd[cursor+62]);
 
-                               ti = proto_tree_add_text(sap_tree, cursor+2, 48,
+                               ti = proto_tree_add_text(sap_tree, NullTVB, cursor+2, 48,
                                        "Server Name: %s", server.server_name);
                                s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
 
-                               proto_tree_add_text(s_tree, cursor, 2, "Server Type: %s (0x%04X)",
+                               proto_tree_add_text(s_tree, NullTVB, cursor, 2, "Server Type: %s (0x%04X)",
                                                server_type(server.server_type), server.server_type);
-                               proto_tree_add_text(s_tree, cursor+50, 4, "Network: %s",
+                               proto_tree_add_text(s_tree, NullTVB, cursor+50, 4, "Network: %s",
                                                ipxnet_to_string((guint8*)&pd[cursor+50]));
-                               proto_tree_add_text(s_tree, cursor+54, 6, "Node: %s",
+                               proto_tree_add_text(s_tree, NullTVB, cursor+54, 6, "Node: %s",
                                                ether_to_str((guint8*)&pd[cursor+54]));
-                               proto_tree_add_text(s_tree, cursor+60, 2, "Socket: %s (0x%04X)",
+                               proto_tree_add_text(s_tree, NullTVB, cursor+60, 2, "Socket: %s (0x%04X)",
                                                port_text(server.server_port), server.server_port);
-                               proto_tree_add_text(s_tree, cursor+62, 2,
+                               proto_tree_add_text(s_tree, NullTVB, cursor+62, 2,
                                                "Intermediate Networks: %d",
                                                server.intermediate_network);
                        }
                }
                else {  /* queries */
-                       proto_tree_add_text(sap_tree, offset+2, 2, "Server Type: %s (0x%04X)",
+                       proto_tree_add_text(sap_tree, NullTVB, offset+2, 2, "Server Type: %s (0x%04X)",
                                        server_type(query.server_type), query.server_type);
                }
        }
 }
 
-
 void
 proto_register_ipx(void)
 {
@@ -862,18 +834,32 @@ proto_register_ipx(void)
 
        static hf_register_info hf_sap[] = {
                { &hf_sap_request,
-               { "Request",                    "sap.request", 
+               { "Request",                    "ipxsap.request", 
                  FT_BOOLEAN,   BASE_NONE,      NULL,   0x0,
                  "TRUE if SAP request" }},
 
                { &hf_sap_response,
-               { "Response",                   "sap.response", 
+               { "Response",                   "ipxsap.response", 
                  FT_BOOLEAN,   BASE_NONE,      NULL,   0x0,
                  "TRUE if SAP response" }}
        };
+
+       static hf_register_info hf_ipxmsg[] = {
+               { &hf_msg_conn,
+               { "Connection Number",                  "ipxmsg.conn", 
+                 FT_UINT8,     BASE_NONE,      NULL,   0x0,
+                 "Connection Number" }},
+
+               { &hf_msg_sigchar,
+               { "Signature Char",                     "ipxmsg.sigchar", 
+                 FT_UINT8,     BASE_NONE,      VALS(ipxmsg_sigchar_vals),      0x0,
+                 "Signature Char" }}
+       };
+
        static gint *ett[] = {
                &ett_ipx,
                &ett_spx,
+               &ett_ipxmsg,
                &ett_ipxrip,
                &ett_ipxsap,
                &ett_ipxsap_server,
@@ -888,8 +874,27 @@ proto_register_ipx(void)
        proto_ipxrip = proto_register_protocol ("IPX Routing Information Protocol", "ipxrip");
        proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
 
-       proto_sap = proto_register_protocol ("Service Advertisement Protocol", "sap");
+       proto_ipxmsg = proto_register_protocol ("IPX Message", "ipxmsg");
+       proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
+
+       proto_sap = proto_register_protocol ("Service Advertisement Protocol", "ipxsap");
        proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
 
        proto_register_subtree_array(ett, array_length(ett));
+
+       ipx_type_dissector_table = register_dissector_table("ipx.packet_type");
+       ipx_socket_dissector_table = register_dissector_table("ipx.socket");
+}
+
+void
+proto_reg_handoff_ipx(void)
+{
+       dissector_add("udp.port", UDP_PORT_IPX, dissect_ipx);
+       dissector_add("ethertype", ETHERTYPE_IPX, dissect_ipx);
+       dissector_add("ppp.protocol", PPP_IPX, dissect_ipx);
+       dissector_add("llc.dsap", SAP_NETWARE, dissect_ipx);
+       dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, dissect_spx);
+       dissector_add("ipx.socket", IPX_SOCKET_SAP, dissect_ipxsap);
+       dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, dissect_ipxrip);
+       dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, dissect_ipxmsg);
 }