Fix files that had Gilbert's old e-mail address or that didn't have my
[obnox/wireshark/wip.git] / packet-ipx.c
index 12a3ff5bc0aca39d703f599244c3ddebf3221d08..8a58fd392d4ffd920c72f63f1c0f32ff39b10284 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.33 1999/11/17 02:17:06 guy Exp $
+ * $Id: packet-ipx.c,v 1.46 2000/01/22 06:22:13 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@unicom.net>
+ * By Gerald Combs <gerald@zing.org>
  * Copyright 1998 Gerald Combs
  *
  * 
@@ -37,6 +37,9 @@
 #include "packet.h"
 #include "packet-ipx.h"
 #include "packet-ncp.h"
+#include "resolv.h"
+
+#include "packet-snmp.h"
 
 /* The information in this module (IPX, SPX, NCP) comes from:
        NetWare LAN Analysis, Second Edition
@@ -87,6 +90,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);
 
@@ -96,6 +104,9 @@ 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);
 
+static void
+dissect_ipxmsg(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 *);
 
 struct port_info {
@@ -118,6 +129,11 @@ struct server_info {
 /* IPX                                                               */
 /* ================================================================= */
 
+/* info on these sockets can be found in this listing from Novell:
+
+       http://developer.novell.com/engsup/sample/tids/dsoc1b/dsoc1b.htm
+*/
+
 #define IPX_SOCKET_NCP                 0x0451
 #define IPX_SOCKET_SAP                 0x0452
 #define IPX_SOCKET_IPXRIP              0x0453
@@ -131,6 +147,7 @@ struct server_info {
 #define IPX_SOCKET_ATTACHMATE_GW       0x055d
 #define IPX_SOCKET_IPX_MESSAGE         0x4001
 #define IPX_SOCKET_ADSM                 0x8522 /* www.tivoli.com */
+#define IPX_SOCKET_WIDE_AREA_ROUTER    0x9001
 #define IPX_SOCKET_SNMP_AGENT           0x900F /* RFC 1906 */
 #define IPX_SOCKET_SNMP_SINK            0x9010 /* RFC 1906 */
 #define IPX_SOCKET_TCP_TUNNEL           0x9091 /* RFC 1791 */
@@ -152,19 +169,18 @@ static struct port_info   ports[] = {
        { 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" },
+                "NWLink SMB Datagram" },
+       { IPX_SOCKET_NWLINK_SMB_BROWSE, NULL, "NWLink SMB Browse" },
+       { IPX_SOCKET_ATTACHMATE_GW,             NULL, "Attachmate Gateway" },
+       { IPX_SOCKET_IPX_MESSAGE, dissect_ipxmsg, "IPX Message" },
+       { IPX_SOCKET_SNMP_AGENT, dissect_snmp, "SNMP Agent" },
+       { IPX_SOCKET_SNMP_SINK, dissect_snmp, "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" },
+       { IPX_SOCKET_WIDE_AREA_ROUTER, NULL, "Wide Area Router" },
        { 0x0000,                               NULL,
                                NULL }
 };
@@ -195,23 +211,38 @@ port_func(guint16 port) {
        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_IPX_4          4
+#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
+#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_IPX_4,        "IPX" },
-                               /* NetMon calls it "IPX" */
+       { IPX_PACKET_TYPE_RIP,          "RIP" },
+       { IPX_PACKET_TYPE_ECHO,         "Echo" },
+       { IPX_PACKET_TYPE_ERROR,        "Error" },
+       { IPX_PACKET_TYPE_PEP,          "PEP" }, /* Packet Exchange Packet */
        { IPX_PACKET_TYPE_SPX,          "SPX" },
        { 16,                           "Experimental Protocol" },
        { IPX_PACKET_TYPE_NCP,          "NCP" },
        { 18,                           "Experimental Protocol" },
        { 19,                           "Experimental Protocol" },
        { IPX_PACKET_TYPE_WANBCAST,     "NetBIOS Broadcast" },
-                               /* NetMon calls it "WAN Broadcast" */
        { 21,                           "Experimental Protocol" },
        { 22,                           "Experimental Protocol" },
        { 23,                           "Experimental Protocol" },
@@ -226,29 +257,29 @@ 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)
 {
-       static gchar    str[3][12];
-       static gchar    *cur;
-
-       if (cur == &str[0][0]) {
-               cur = &str[1][0];
-       } else if (cur == &str[1][0]) {
-               cur = &str[2][0];
-       } else {
-               cur = &str[0][0];
-       }
-
-       sprintf(cur, "%02X %02X %02X %02X", ad[0], ad[1], ad[2], ad[3]);
-       return cur;
+       guint32 addr = pntohl(ad);
+       return ipxnet_to_str_punct(addr, ' ');
 }
 
+/* We use a different representation of hardware addresses
+ * than ether_to_str(); we don't put punctuation between the hex
+ * digits.
+ */
+
 gchar*
 ipx_addr_to_str(guint32 net, const guint8 *ad)
 {
-       static gchar    str[3][22];
+       static gchar    str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
        static gchar    *cur;
+       char            *name;
 
        if (cur == &str[0][0]) {
                cur = &str[1][0];
@@ -258,11 +289,58 @@ ipx_addr_to_str(guint32 net, const guint8 *ad)
                cur = &str[0][0];
        }
 
-       sprintf(cur, "%X.%02x%02x%02x%02x%02x%02x", net, 
-               ad[0], ad[1], ad[2], ad[3], ad[4], ad[5]);
+       name = get_ether_name_if_known(ad);
+
+       if (name) {
+               sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
+       }
+       else {
+               sprintf(cur, "%s.%s", get_ipxnet_name(net), ether_to_str_punct(ad, '\0'));
+       }
        return cur;
 }
 
+gchar *
+ipxnet_to_str_punct(const guint32 ad, char punct) {
+  static gchar  str[3][12];
+  static gchar *cur;
+  gchar        *p;
+  int          i;
+  guint32      octet;
+  static const gchar hex_digits[16] = "0123456789ABCDEF";
+  static const guint32  octet_mask[4] =
+         { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
+
+  if (cur == &str[0][0]) {
+    cur = &str[1][0];
+  } else if (cur == &str[1][0]) {  
+    cur = &str[2][0];
+  } else {  
+    cur = &str[0][0];
+  }
+  p = &cur[12];
+  *--p = '\0';
+  i = 3;
+  for (;;) {
+    octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
+    *--p = hex_digits[octet&0xF];
+    octet >>= 4;
+    *--p = hex_digits[octet&0xF];
+    if (i == 0)
+      break;
+    if (punct)
+      *--p = punct;
+    i--;
+  }
+  return p;
+}
+
+void
+capture_ipx(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld)
+{
+       ld->ipx++;
+}
+
 void
 dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
 
@@ -273,7 +351,6 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        int             len;
        guint8          *ipx_snode, *ipx_dnode, *ipx_snet, *ipx_dnet;
 
-       gchar           *str_dnet, *str_snet;
        guint16         ipx_dsocket, ipx_ssocket;
        dissect_func_t  *dissect;
        guint32         ipx_dnet_val, ipx_snet_val;
@@ -281,8 +358,6 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        /* Calculate here for use in pinfo and in tree */
        ipx_dnet = (guint8*)&pd[offset+6];
        ipx_snet = (guint8*)&pd[offset+18];
-       str_dnet = ipxnet_to_string(ipx_dnet);
-       str_snet = ipxnet_to_string(ipx_snet);
        ipx_dnet_val = pntohl(ipx_dnet);
        ipx_snet_val = pntohl(ipx_snet);
        ipx_dsocket = pntohs(&pd[offset+16]);
@@ -359,7 +434,7 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                        break;
 
                case IPX_PACKET_TYPE_WANBCAST:
-               case IPX_PACKET_TYPE_IPX_4:
+               case IPX_PACKET_TYPE_PEP:
                        if (ipx_dsocket == IPX_SOCKET_NETBIOS) {
                                dissect_nbipx(pd, offset, fd, tree);
                                break;
@@ -479,6 +554,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, offset, END_OF_FRAME, NULL);
+               msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
+
+               proto_tree_add_item(msg_tree, hf_msg_conn, offset, 1, conn_number);
+               proto_tree_add_item(msg_tree, hf_msg_sigchar, offset+1, 1, sig_char);
+       }
+}
+
+
 /* ================================================================= */
 /* IPX RIP                                                           */
 /* ================================================================= */
@@ -816,9 +926,23 @@ proto_register_ipx(void)
                  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,
@@ -833,6 +957,9 @@ 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_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", "sap");
        proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));