/* 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
*
*
#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
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);
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 {
/* 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
#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 */
{ 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 }
};
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" },
{ 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];
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) {
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;
/* 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]);
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;
}
}
+/* ================================================================= */
+/* 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 */
/* ================================================================= */
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,
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));