* Added column formatting functionality.
[obnox/wireshark/wip.git] / packet-ipx.c
index 0b33a949191c04e79644f5771ccceecc404fab72..7fb4139fca1b7ee11a6473dfc574fc9ee24d4581 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for NetWare's IPX
  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
  *
- * $Id: packet-ipx.c,v 1.4 1998/09/23 14:46:06 gram Exp $
+ * $Id: packet-ipx.c,v 1.13 1998/11/17 04:28:55 gerald Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@unicom.net>
@@ -29,7 +29,6 @@
 #endif
 
 #include <gtk/gtk.h>
-#include <pcap.h>
 
 #include <stdio.h>
 
 # include <sys/types.h>
 #endif
 
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
 #include "ethereal.h"
 #include "packet.h"
 #include "packet-ipx.h"
@@ -62,6 +57,9 @@ dissect_spx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree);
 static void
 dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree);
 
+static void
+dissect_sap(const u_char *pd, int offset, frame_data *fd, GtkTree *tree);
+
 struct port_info {
        guint16 port;
        void    (*func) (const u_char *, int, frame_data *, GtkTree *);
@@ -73,16 +71,25 @@ struct conn_info {
        char    *text;
 };
 
+struct server_info {
+       guint16 type;
+       char    *text;
+};
+
 /* ================================================================= */
 /* IPX                                                               */
 /* ================================================================= */
 static struct port_info        ports[] = {
        { 0x0451, dissect_ncp,          "NCP" },
-       { 0x0452, NULL,                         "SAP" },
+       { 0x0452, dissect_sap,          "SAP" },
        { 0x0453, dissect_ipxrip,       "RIP" },
        { 0x0455, NULL,                         "NetBIOS" },
        { 0x0456, NULL,                         "Diagnostic" },
        { 0x0457, NULL,                         "Serialization" },
+       { 0x0551, NULL,                         "NWLink SMB Name Query" },
+       { 0x0553, dissect_nwlink_dg,"NWLink SMB Datagram" },
+       { 0x055d, NULL,                         "Attachmate Gateway" },
+       { 0x4001, NULL,                         "IPX Message" },
        { 0x0000, NULL,                         NULL }
 };
 
@@ -125,7 +132,7 @@ ipx_packet_type(u_char val)
                return "NCP";
        }
        else if (val == 20) {
-               return "NetBIOS";
+               return "NetBIOS Broadcast";
        }
        else if (val >= 16 && val <= 31) {
                return "Experimental Protocol";
@@ -136,7 +143,7 @@ ipx_packet_type(u_char val)
 }
 
 gchar*
-network_to_string(const guint8 *ad)
+ipxnet_to_string(const guint8 *ad)
 {
        static gchar    str[3][12];
        static gchar    *cur;
@@ -163,15 +170,15 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
        guint16         dsocket, ssocket;
        void            (*dissect) (const u_char *, int, frame_data *, GtkTree *);
 
-       /* Calculate here for use in win_info[] and in tree */
-       dnet = network_to_string((guint8*)&pd[offset+6]);
-       snet = network_to_string((guint8*)&pd[offset+18]);
+       /* Calculate here for use in pinfo and in tree */
+       dnet = ipxnet_to_string((guint8*)&pd[offset+6]);
+       snet = ipxnet_to_string((guint8*)&pd[offset+18]);
        dsocket = pntohs(&pd[offset+16]);
 
-       if (fd->win_info[0]) {
-               strcpy(fd->win_info[3], "IPX");
-               sprintf(fd->win_info[4], "%s (0x%04X)", port_text(dsocket), dsocket);
-       }
+       if (check_col(fd, COL_PROTOCOL))
+               col_add_str(fd, COL_PROTOCOL, "IPX");
+       if (check_col(fd, COL_INFO))
+               col_add_fstr(fd, COL_INFO, "%s (0x%04X)", port_text(dsocket), dsocket);
 
        ipx_type = pd[offset+5];
 
@@ -206,10 +213,6 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
        offset += 30;
 
        switch (ipx_type) {
-               case 0: /* IPX */
-                       dissect_data(pd, offset, fd, tree);
-                       break;
-
                case 5: /* SPX */
                        dissect_spx(pd, offset, fd, tree);
                        break;
@@ -219,9 +222,13 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
                        break;
 
                case 20: /* NetBIOS */
-                       dissect_data(pd, offset, fd, tree);
-                       break;
+                       if (dsocket == 0x0455) {
+                               dissect_nbipx_ns(pd, offset, fd, tree);
+                               break;
+                       }
+                       /* else fall through */
 
+               case 0: /* IPX, fall through to default */
                default:
                        dissect = port_func(dsocket);
                        if (dissect) {
@@ -277,10 +284,10 @@ dissect_spx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
 
        GtkWidget       *spx_tree, *ti;
 
-       if (fd->win_info[0]) {
-               strcpy(fd->win_info[3], "SPX");
-               strcpy(fd->win_info[4], "SPX");
-       }
+       if (check_col(fd, COL_PROTOCOL))
+               col_add_str(fd, COL_PROTOCOL, "SPX");
+       if (check_col(fd, COL_INFO))
+               col_add_str(fd, COL_INFO, "SPX");
 
        if (tree) {
                ti = add_item_to_tree(GTK_WIDGET(tree), offset, 12,
@@ -331,14 +338,15 @@ dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
 
        operation = pntohs(&pd[offset]) - 1;
 
-       if (fd->win_info[0]) {
-               strcpy(fd->win_info[3], "IPX RIP");
-               if (operation < 2) {
-                       sprintf(fd->win_info[4], rip_type[operation]);
-               }
-               else {
-                       strcpy(fd->win_info[4], "IPX RIP");
-               }
+       if (check_col(fd, COL_PROTOCOL))
+        col_add_str(fd, COL_PROTOCOL, "IPX RIP");
+       if (check_col(fd, COL_PROTOCOL)) {
+        if (operation < 2) {
+                col_add_str(fd, COL_INFO, rip_type[operation]);
+        }
+        else {
+                col_add_str(fd, COL_INFO, "Unknown Packet Type");
+        }
        }
 
        if (tree) {
@@ -363,14 +371,14 @@ dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
                        if (operation == IPX_RIP_REQUEST - 1) {
                                add_item_to_tree(rip_tree, cursor,      8,
                                        "Route Vector: %s, %d hop%s, %d tick%s",
-                                       network_to_string((guint8*)&route.network),
+                                       ipxnet_to_string((guint8*)&route.network),
                                        route.hops,  route.hops  == 1 ? "" : "s",
                                        route.ticks, route.ticks == 1 ? "" : "s");
                        }
                        else {
                                add_item_to_tree(rip_tree, cursor,      8,
                                        "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
-                                       network_to_string((guint8*)&route.network),
+                                       ipxnet_to_string((guint8*)&route.network),
                                        route.hops,  route.hops  == 1 ? "" : "s",
                                        route.ticks, route.ticks == 1 ? "" : "s",
                                        route.ticks * 1000 / 18);
@@ -378,3 +386,136 @@ dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
                }
        }
 }
+
+
+
+/* ================================================================= */
+/* SAP                                                                                                                          */
+/* ================================================================= */
+static char*
+server_type(guint16 type)
+{
+       int i=0;
+
+       /* some of these are from ncpfs, others are from the book */
+       static struct server_info       servers[] = {
+               { 0x0001,       "User" },
+               { 0x0002,       "User Group" },
+               { 0x0003,       "Print Queue" },
+               { 0x0004,       "File server" },
+               { 0x0005,       "Job server" },
+               { 0x0007,       "Print server" },
+               { 0x0008,       "Archive server" },
+               { 0x0009,       "Archive server" },
+               { 0x000a,       "Job queue" },
+               { 0x000b,       "Administration" },
+               { 0x0021,       "NAS SNA gateway" },
+               { 0x0024,       "Remote bridge" },
+               { 0x0026,       "Bridge server" },
+               { 0x0027,       "TCP/IP gateway" },
+               { 0x002d,       "Time Synchronization VAP" },
+               { 0x002e,       "Archive Server Dynamic SAP" },
+               { 0x0047,       "Advertising print server" },
+               { 0x004b,       "Btrieve VAP 5.0" },
+               { 0x004c,       "SQL VAP" },
+               { 0x0050,       "Btrieve VAP" },
+               { 0x0053,       "Print Queue VAP" },
+               { 0x007a,       "TES NetWare for VMS" },
+               { 0x0098,       "NetWare access server" },
+               { 0x009a,       "Named Pipes server" },
+               { 0x009e,       "Portable NetWare Unix" },
+               { 0x0107,       "NetWare 386" },
+               { 0x0111,       "Test server" },
+               { 0x0133,       "NetWare Name Service" },
+               { 0x0166,       "NetWare management" },
+               { 0x026a,       "NetWare management" },
+               { 0x026b,       "Time synchronization" },
+               { 0x0278,       "NetWare Directory server" },
+               { 0x055d,       "Attachmate SNA gateway" },
+               { 0x0000,       NULL }
+       };
+
+       while (servers[i].text != NULL) {
+               if (servers[i].type == type) {
+                       return servers[i].text;
+               }
+               i++;
+       }
+       return "Unknown";
+}
+
+static void
+dissect_sap(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
+
+       GtkWidget       *sap_tree, *s_tree, *ti;
+       int                     cursor;
+       struct sap_query query;
+       struct sap_server_ident server;
+
+       char            *sap_type[4] = { "General Query", "General Response",
+               "Nearest Query", "Nearest Response" };
+
+       query.query_type = pntohs(&pd[offset]);
+       query.server_type = pntohs(&pd[offset+2]);
+
+       if (check_col(fd, COL_PROTOCOL))
+               col_add_str(fd, COL_PROTOCOL, "SAP");
+       if (check_col(fd, COL_INFO)) {
+               if (query.query_type < 4) {
+                       col_add_str(fd, COL_INFO, sap_type[query.query_type - 1]);
+               }
+               else {
+                       col_add_str(fd, COL_INFO, "Unknown Packet Type");
+               }
+       }
+
+       if (tree) {
+               ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
+                       "Service Advertising Protocol");
+               sap_tree = gtk_tree_new();
+               add_subtree(ti, sap_tree, ETT_IPXSAP);
+
+               if (query.query_type < 4) {
+                       add_item_to_tree(sap_tree, offset, 2, sap_type[query.query_type - 1]);
+               }
+               else {
+                       add_item_to_tree(sap_tree, 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 < fd->cap_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);
+                               memcpy(&server.server_node, &pd[cursor+54], 6);
+                               server.server_port = pntohs(&pd[cursor+60]);
+                               server.intermediate_network = pntohs(&pd[cursor+62]);
+
+                               ti = add_item_to_tree(GTK_WIDGET(sap_tree), cursor+2, 48,
+                                       "Server Name: %s", server.server_name);
+                               s_tree = gtk_tree_new();
+                               add_subtree(ti, s_tree, ETT_IPXSAP_SERVER);
+
+                               add_item_to_tree(s_tree, cursor, 2, "Server Type: %s (0x%04X)",
+                                               server_type(server.server_type), server.server_type);
+                               add_item_to_tree(s_tree, cursor+50, 4, "Network: %s",
+                                               ipxnet_to_string((guint8*)&pd[cursor+50]));
+                               add_item_to_tree(s_tree, cursor+54, 6, "Node: %s",
+                                               ether_to_str((guint8*)&pd[cursor+54]));
+                               add_item_to_tree(s_tree, cursor+60, 2, "Socket: %s (0x%04X)",
+                                               port_text(server.server_port), server.server_port);
+                               add_item_to_tree(s_tree, cursor+62, 2,
+                                               "Intermediate Networks: %d",
+                                               server.intermediate_network);
+                       }
+               }
+               else {  /* queries */
+                       add_item_to_tree(sap_tree, offset+2, 2, "Server Type: %s (0x%04X)",
+                                       server_type(query.server_type), query.server_type);
+               }
+       }
+}
+