aboutsummaryrefslogtreecommitdiffstats
path: root/packet-nbipx.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-02-27 07:28:48 +0000
committerGuy Harris <guy@alum.mit.edu>2001-02-27 07:28:48 +0000
commita954a9d276678fb6ff357ffa7be0a1609415fc0d (patch)
tree1e1621e970bdac1ac966dc4619447aa2f54389c6 /packet-nbipx.c
parent30ab306064c35601b722bac0c8b13d01c6256556 (diff)
Fix up the handling of NBIPX packets, and of Microsoft "direct hosting"
name-server-over-IPX and mailslot-datagram-over-IPX packets, based on stuff dredged out of a pile of documents on the Web. svn path=/trunk/; revision=3079
Diffstat (limited to 'packet-nbipx.c')
-rw-r--r--packet-nbipx.c893
1 files changed, 607 insertions, 286 deletions
diff --git a/packet-nbipx.c b/packet-nbipx.c
index 462f129ebf..dc9b43f929 100644
--- a/packet-nbipx.c
+++ b/packet-nbipx.c
@@ -2,7 +2,7 @@
* Routines for NetBIOS over IPX packet disassembly
* Gilbert Ramirez <gram@xiexie.org>
*
- * $Id: packet-nbipx.c,v 1.36 2001/01/15 04:39:28 guy Exp $
+ * $Id: packet-nbipx.c,v 1.37 2001/02/27 07:28:47 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -45,16 +45,9 @@ static gint ett_nbipx = -1;
static gint ett_nbipx_conn_ctrl = -1;
static gint ett_nbipx_name_type_flags = -1;
-enum nbipx_protocol {
- NETBIOS_NETWARE,
- NETBIOS_NWLINK
-};
-
-static void
-dissect_nbipx_ns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
-
-static void
-dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree);
+static void dissect_packet_type(tvbuff_t *tvb, int offset, guint8 packet_type,
+ proto_tree *tree);
/* There is no RFC or public specification of Netware or Microsoft
* NetBIOS over IPX packets. I have had to decode the protocol myself,
@@ -67,12 +60,108 @@ dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
* and at least some of those packet types appear to match what's in
* some NBIPX packets.
*
- * Note, however, that the offset of the packet type in an NBIPX packet
- * *DEPENDS ON THE PACKET TYPE*; "Find name" and "Name recognized" have
- * it at one offset, "Directed datagram" has it at another. Does the
- * NBIPX code base it on the length, or what? Non-broadcast directed
- * datagram packets have an IPX type of "IPX", just as "Find name" and
- * "Name recognized" do.... For now, we base it on the length.
+ * Note, however, that it appears that sometimes NBIPX packets have
+ * 8 IPX addresses at the beginning, and sometimes they don't.
+ *
+ * In the section on "NetBIOS Broadcasts", the document at
+ *
+ * http://www.microsoft.com/technet/network/ipxrout.asp
+ *
+ * says that "the NetBIOS over IPX Broadcast header" contains 8 IPX
+ * network numbers in the "IPX WAN broadcast header", and that it's
+ * followed by a "Name Type Flags" byte (giving information about the
+ * name being registered, deregistered, or checked), a "Data Stream
+ * Type 2" byte giving the type of operation (NBIPX_FIND_NAME,
+ * NBIPX_NAME_RECOGNIZED, or NBIPX_CHECK_NAME - the latter is called
+ * "Add Name"), and a 16-byte NetBIOS name.
+ *
+ * It also says that "NetBIOS over IPX Broadcast packets" have a
+ * packet type of 0x14 (20, or IPX_PACKET_TYPE_WANBCAST) and a
+ * socket number of 0x455 (IPX_SOCKET_NETBIOS).
+ *
+ * However, there are also non-broadcast packets that *also* contain
+ * the 8 IPX network numbers; they appear to be replies to broadcast
+ * packets, and have a packet type of 0x4 (IPX_PACKET_TYPE_PEP).
+ *
+ * Other IPX_PACKET_TYPE_PEP packets to and from the IPX_SOCKET_NETBIOS
+ * socket, however, *don't* have the 8 IPX network numbers; there does
+ * not seem to be any obvious algorithm to determine whether the packet
+ * has the addresses or not. Microsoft Knowledge Base article Q128335
+ * appears to show some code from the NBIPX implementation in NT that
+ * tries to determine the packet type - and it appears to use heuristics
+ * based on the packet length and on looking at what might be the NBIPX
+ * "Data Stream Type" byte depending on whether the packet has the 8
+ * IPX network numbers or not.
+ *
+ * So, for now, we treat *all* NBIPX packets as having a "Data Stream
+ * Type" byte, preceded by another byte of NBIPX information and
+ * followed by more NBIPX stuff, and assume that it's preceded by
+ * 8 IPX network numbers iff:
+ *
+ * the packet is a WAN Broadcast packet
+ *
+ * or
+ *
+ * the packet is the right size for one of those PEP name replies
+ * (50 bytes) *and* has a name packet type as the Data Stream
+ * Type byte at the offset where that byte would be if the packet
+ * does have the 8 IPX network numbers at the beginning.
+ *
+ * The page at
+ *
+ * http://ourworld.compuserve.com/homepages/TimothyDEvans/encap.htm
+ *
+ * indicates, under "NBIPX session packets", that "NBIPX session packets"
+ * have
+ *
+ * 1 byte of NBIPX connection control flag
+ * 1 byte of data stream type
+ * 2 bytes of source connection ID
+ * 2 bytes of destination connection ID
+ * 2 bytes of send sequence number
+ * 2 bytes of total data length
+ * 2 bytes of offset
+ * 2 bytes of data length
+ * 2 bytes of receive sequence number
+ * 2 bytes of "bytes received"
+ *
+ * followed by data.
+ *
+ * Packets with a data stream type of NBIPX_DIRECTED_DATAGRAM appear to
+ * have, following the data stream type, two NetBIOS names, the first
+ * of which is the receiver's NetBIOS name and the second of which is
+ * the sender's NetBIOS name. The page at
+ *
+ * http://support.microsoft.com/support/kb/articles/q203/0/51.asp
+ *
+ * speaks of type 4 (PEP) packets as being used for "SAP, NetBIOS sessions
+ * and directed datagrams" and type 20 (WAN Broadcast) as being used for
+ * "NetBIOS name resolution broadcasts" (but nothing about the non-broadcast
+ * type 4 name resolution stuff).
+ *
+ * We assume that this means that, once you get past the 8 IPX network
+ * numbers if present:
+ *
+ * the first byte is a name type byte for the name packets
+ * and a connection control flag for the other packets;
+ *
+ * the second byte is a data stream type;
+ *
+ * the rest of the bytes are:
+ *
+ * the NetBIOS name being registered/deregistered/etc.,
+ * for name packets;
+ *
+ * the two NetBIOS names, followed by the NetBIOS
+ * datagram, for NBIPX_DIRECTED_DATAGRAM packets;
+ *
+ * the session packet header, possibly followed by
+ * session data, for session packets.
+ *
+ * We don't know yet how to interpret NBIPX_STATUS_QUERY or
+ * NBIPX_STATUS_RESPONSE.
+ *
+ * For now, we treat the datagrams and session data as SMB stuff.
*/
#define NBIPX_FIND_NAME 1
#define NBIPX_NAME_RECOGNIZED 2
@@ -101,42 +190,6 @@ static const value_string nbipx_data_stream_type_vals[] = {
{0, NULL}
};
-#define NWLINK_NAME_QUERY 1
-#define NWLINK_SMB 2
-#define NWLINK_NETBIOS_DATAGRAM 3
-
-static const value_string nwlink_data_stream_type_vals[] = {
- {NWLINK_NAME_QUERY, "Name query"},
- {NWLINK_SMB, "SMB"},
- {NWLINK_NETBIOS_DATAGRAM, "NetBIOS datagram"},
- {0, NULL}
-};
-
-/* NetWare */
-static void
-dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- CHECK_DISPLAY_AS_DATA(proto_nbipx, tvb, pinfo, tree);
-
- pinfo->current_proto = "NBIPX";
-
- if (check_col(pinfo->fd, COL_PROTOCOL))
- col_set_str(pinfo->fd, COL_PROTOCOL, "NBIPX");
- if (check_col(pinfo->fd, COL_INFO))
- col_clear(pinfo->fd, COL_INFO);
-
- /*
- * As said above, we look at the length of the packet to decide
- * whether to treat it as a name-service packet or a datagram
- * (the packet type would tell us, but it's at a *DIFFERENT
- * LOCATION* in different types of packet...).
- */
- if (tvb_reported_length(tvb) == 50)
- dissect_nbipx_ns(tvb, pinfo, tree);
- else
- dissect_nbipx_dg(tvb, pinfo, tree);
-}
-
static void
add_routers(proto_tree *tree, tvbuff_t *tvb, int offset)
{
@@ -157,105 +210,283 @@ add_routers(proto_tree *tree, tvbuff_t *tvb, int offset)
}
static void
-dissect_nbipx_ns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_tree *nbipx_tree;
- proto_item *ti;
- int offset = 0;
- guint8 packet_type;
- guint8 name_type_flag;
- proto_tree *name_type_flag_tree;
- proto_item *tf;
- char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
- int name_type;
-
- name_type_flag = tvb_get_guint8(tvb, offset+32);
- packet_type = tvb_get_guint8(tvb, offset+33);
- name_type = get_netbios_name(tvb, offset+34, name);
+ gboolean has_routes;
+ proto_tree *nbipx_tree = NULL;
+ proto_item *ti = NULL;
+ int offset = 0;
+ guint8 packet_type;
+ guint8 name_type_flag;
+ proto_tree *name_type_flag_tree;
+ proto_item *tf;
+ tvbuff_t *next_tvb;
+ const guint8 *next_pd;
+ int next_offset;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int name_type;
+ gboolean has_payload;
- if (check_col(pinfo->fd, COL_INFO)) {
- switch (packet_type) {
- case NBIPX_FIND_NAME:
- case NBIPX_NAME_RECOGNIZED:
- case NBIPX_CHECK_NAME:
- case NBIPX_NAME_IN_USE:
- case NBIPX_DEREGISTER_NAME:
+ if (check_col(pinfo->fd, COL_PROTOCOL))
+ col_set_str(pinfo->fd, COL_PROTOCOL, "NBIPX");
+ if (check_col(pinfo->fd, COL_INFO))
+ col_clear(pinfo->fd, COL_INFO);
+
+ if (pinfo->ipxptype == IPX_PACKET_TYPE_WANBCAST) {
+ /*
+ * This is a WAN Broadcast packet; we assume it will have
+ * 8 IPX addresses at the beginning.
+ */
+ has_routes = TRUE;
+ } else {
+ /*
+ * This isn't a WAN Broadcast packet, but it still might
+ * have the 8 addresses.
+ *
+ * If it's the right length for a name operation,
+ * and, if we assume it has routes, the packet type
+ * is a name operation, assume it has routes.
+ *
+ * NOTE: this will throw an exception if the byte that
+ * would be the packet type byte if this has the 8
+ * addresses isn't present; if that's the case, we don't
+ * know how to interpret this packet, so we can't dissect
+ * it anyway.
+ */
+ has_routes = FALSE; /* start out assuming it doesn't */
+ if (tvb_reported_length(tvb) == 50) {
+ packet_type = tvb_get_guint8(tvb, offset + 32 + 1);
+ switch (packet_type) {
+
+ case NBIPX_FIND_NAME:
+ case NBIPX_NAME_RECOGNIZED:
+ case NBIPX_CHECK_NAME:
+ case NBIPX_NAME_IN_USE:
+ case NBIPX_DEREGISTER_NAME:
+ has_routes = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0,
+ 0, FALSE);
+ nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
+ }
+
+ if (has_routes) {
+ if (tree)
+ add_routers(nbipx_tree, tvb, 0);
+ offset += 32;
+ }
+
+ packet_type = tvb_get_guint8(tvb, offset + 1);
+
+ switch (packet_type) {
+
+ case NBIPX_FIND_NAME:
+ case NBIPX_NAME_RECOGNIZED:
+ case NBIPX_CHECK_NAME:
+ case NBIPX_NAME_IN_USE:
+ case NBIPX_DEREGISTER_NAME:
+ name_type_flag = tvb_get_guint8(tvb, offset);
+ name_type = get_netbios_name(tvb, offset+2, name);
+ if (check_col(pinfo->fd, COL_INFO)) {
col_add_fstr(pinfo->fd, COL_INFO, "%s %s<%02x>",
val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
name, name_type);
- break;
+ }
+ if (nbipx_tree) {
+ tf = proto_tree_add_text(nbipx_tree, tvb, offset, 1,
+ "Name type flag: 0x%02x", name_type_flag);
+ name_type_flag_tree = proto_item_add_subtree(tf,
+ ett_nbipx_name_type_flags);
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x80, 8,
+ "Group name", "Unique name"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x40, 8,
+ "Name in use", "Name not used"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x04, 8,
+ "Name registered", "Name not registered"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x02, 8,
+ "Name duplicated", "Name not duplicated"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x01, 8,
+ "Name deregistered", "Name not deregistered"));
+ }
+ offset += 1;
- default:
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ if (nbipx_tree)
+ netbios_add_name("Name", tvb, offset, nbipx_tree);
+ offset += NETBIOS_NAME_LEN;
+
+ /*
+ * No payload to be interpreted by another protocol.
+ */
+ has_payload = FALSE;
+ break;
+
+ case NBIPX_SESSION_DATA:
+ case NBIPX_SESSION_END:
+ case NBIPX_SESSION_END_ACK:
+ if (check_col(pinfo->fd, COL_INFO)) {
col_add_fstr(pinfo->fd, COL_INFO, "%s",
val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
- break;
}
+ dissect_conn_control(tvb, offset, nbipx_tree);
+ offset += 1;
+
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Source connection ID: 0x%04X",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Destination connection ID: 0x%04X",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Send sequence number: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Total data length: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Offset: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Data length: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Receive sequence number: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Bytes received: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ /*
+ * We may have payload to dissect.
+ */
+ has_payload = TRUE;
+ break;
+
+ case NBIPX_DIRECTED_DATAGRAM:
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_add_fstr(pinfo->fd, COL_INFO, "%s",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
+ }
+ dissect_conn_control(tvb, offset, nbipx_tree);
+ offset += 1;
+
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ if (nbipx_tree)
+ netbios_add_name("Receiver's Name", tvb, offset,
+ nbipx_tree);
+ offset += NETBIOS_NAME_LEN;
+
+ if (nbipx_tree)
+ netbios_add_name("Sender's Name", tvb, offset,
+ nbipx_tree);
+ offset += NETBIOS_NAME_LEN;
+
+ /*
+ * We may have payload to dissect.
+ */
+ has_payload = TRUE;
+ break;
+
+ default:
+ if (check_col(pinfo->fd, COL_INFO)) {
+ col_add_fstr(pinfo->fd, COL_INFO, "%s",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
+ }
+
+ /*
+ * We don't know what the first byte is.
+ */
+ offset += 1;
+
+ /*
+ * The second byte is a data stream type byte.
+ */
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ /*
+ * We don't know what the rest of the packet is.
+ */
+ has_payload = FALSE;
}
- if (tree) {
- ti = proto_tree_add_item(tree, proto_nbipx, tvb, offset, 50,
- FALSE);
- nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
+ /*
+ * Set the length of the NBIPX tree item.
+ */
+ if (ti != NULL)
+ proto_item_set_len(ti, offset);
- add_routers(nbipx_tree, tvb, offset);
-
- tf = proto_tree_add_text(nbipx_tree, tvb, offset+32, 1,
- "Name type flag: 0x%02x", name_type_flag);
- name_type_flag_tree = proto_item_add_subtree(tf,
- ett_nbipx_name_type_flags);
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x80, 8,
- "Group name", "Unique name"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x40, 8,
- "Name in use", "Name not used"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x04, 8,
- "Name registered", "Name not registered"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x02, 8,
- "Name duplicated", "Name not duplicated"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x01, 8,
- "Name deregistered", "Name not deregistered"));
-
- proto_tree_add_text(nbipx_tree, tvb, offset+33, 1,
- "Packet Type: %s (%02X)",
- val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
- packet_type);
-
- netbios_add_name("Name", tvb, offset + 34, nbipx_tree);
+ if (has_payload && tvb_offset_exists(tvb, offset)) {
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ tvb_compat(next_tvb, &next_pd, &next_offset);
+ dissect_smb(next_pd, next_offset, pinfo->fd, tree,
+ tvb_length(next_tvb));
}
}
static void
-dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree)
{
- proto_tree *nbipx_tree = NULL;
- proto_item *ti;
- int offset = 0;
- guint8 conn_control;
- proto_tree *cc_tree;
- guint8 packet_type;
- tvbuff_t *next_tvb;
- const guint8 *next_pd;
- int next_offset;
-
- if (check_col(pinfo->fd, COL_INFO))
- col_add_fstr(pinfo->fd, COL_INFO, "NetBIOS datagram over NBIPX");
+ guint8 conn_control;
+ proto_item *ti;
+ proto_tree *cc_tree;
if (tree) {
- ti = proto_tree_add_item(tree, proto_nbipx, tvb, offset,
- 2+NETBIOS_NAME_LEN+NETBIOS_NAME_LEN, FALSE);
- nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
-
conn_control = tvb_get_guint8(tvb, offset);
- ti = proto_tree_add_text(nbipx_tree, tvb, offset, 1,
+ ti = proto_tree_add_text(tree, tvb, offset, 1,
"Connection control: 0x%02x", conn_control);
cc_tree = proto_item_add_subtree(ti, ett_nbipx_conn_ctrl);
proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
@@ -263,7 +494,8 @@ dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
"System packet", "Non-system packet"));
proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
decode_boolean_bitfield(conn_control, 0x40, 8,
- "Send acknowledge", "No send acknowledge"));
+ "Acknowledgement required",
+ "Acknowledgement not required"));
proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
decode_boolean_bitfield(conn_control, 0x20, 8,
"Attention", "No attention"));
@@ -274,43 +506,176 @@ dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
decode_boolean_bitfield(conn_control, 0x08, 8,
"Resend", "No resend"));
}
- offset += 1;
+}
- packet_type = tvb_get_guint8(tvb, offset);
+static void
+dissect_packet_type(tvbuff_t *tvb, int offset, guint8 packet_type,
+ proto_tree *tree)
+{
if (tree) {
- proto_tree_add_text(nbipx_tree, tvb, offset, 1,
+ proto_tree_add_text(tree, tvb, offset, 1,
"Packet Type: %s (%02X)",
val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
packet_type);
}
- offset += 1;
+}
- if (tree)
- netbios_add_name("Receiver's Name", tvb, offset, nbipx_tree);
- offset += NETBIOS_NAME_LEN;
+void
+proto_register_nbipx(void)
+{
+/* static hf_register_info hf[] = {
+ { &variable,
+ { "Name", "nbipx.abbreviation", TYPE, VALS_POINTER }},
+ };*/
+ static gint *ett[] = {
+ &ett_nbipx,
+ &ett_nbipx_conn_ctrl,
+ &ett_nbipx_name_type_flags,
+ };
- if (tree)
- netbios_add_name("Sender's Name", tvb, offset, nbipx_tree);
- offset += NETBIOS_NAME_LEN;
+ proto_nbipx = proto_register_protocol("NetBIOS over IPX",
+ "NBIPX", "nbipx");
+ /* proto_register_field_array(proto_nbipx, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
- if (tvb_offset_exists(tvb, offset)) {
- next_tvb = tvb_new_subset(tvb, offset, -1, -1);
- tvb_compat(next_tvb, &next_pd, &next_offset);
- dissect_smb(next_pd, next_offset, pinfo->fd, tree,
- tvb_length(next_tvb));
- }
+void
+proto_reg_handoff_nbipx(void)
+{
+ dissector_add("ipx.socket", IPX_SOCKET_NETBIOS, dissect_nbipx,
+ proto_nbipx);
}
+/*
+ * Microsoft appear to have something they call "direct hosting", where
+ * SMB - and, I infer, related stuff, such as name resolution - runs
+ * directly over IPX. (In Windows 2000, they also run SMB directly over
+ * TCP, on port 445, and that also appears to be called "direct hosting".
+ * Ethereal handles SMB-over-TCP.)
+ *
+ * The document at
+ *
+ * http://support.microsoft.com/support/kb/articles/q203/0/51.asp
+ *
+ * speaks of NMPI - the "Name Management Protocol on IPX" - as being
+ * "Microsoft's protocol for name management support when you use IPX
+ * without the NetBIOS interface," and says that "This process of routing
+ * the SMB protocol directly through IPX is known as Direct Hosting."
+ *
+ * It speaks of IPX socket 0x551 as being for NMPI; we define it as
+ * IPX_SOCKET_NWLINK_SMB_NAMEQUERY.
+ *
+ * We also define IPX_SOCKET_NWLINK_SMB_DGRAM as 0x0553 and define
+ * IPX_SOCKET_NWLINK_SMB_BROWSE as 0x0555 (with a "? not sure on this"
+ * comment after the latter one).
+ *
+ * We have seen at least some browser announcements on IPX socket 0x553;
+ * those are WAN broadcast packets, complete with 8 IPX network
+ * numbers, and with the header containing the usual two NetBIOS names
+ * that show up in NetBIOS datagrams.
+ *
+ * Network Monitor calls those packets NMPI packets, even though they're
+ * on socket 0x553, not socket 0x551, and contain SMB datagrams, not name
+ * resolution packets.
+ *
+ * At least some of this is discussed in the "SMBPUB.DOC" Word document
+ * stored in
+ *
+ * ftp://ftp.microsoft.com/developr/drg/CIFS/smbpub.zip
+ *
+ * which can also be found in text form at
+ *
+ * http://www.samba.org/samba/ftp/specs/smbpub.txt
+ *
+ * which says that for "connectionless IPX transport" the sockets that
+ * are used are:
+ *
+ * SMB_SERVER_SOCKET (0x550) - SMB requests from clients
+ * SMB_NAME_SOCKET (0x551) - name claims and name query messages
+ * REDIR_SOCKET (0x552) - used by the redirector (client) for
+ * sending SMB requests and receiving SMB replies
+ * MAILSLOT_SOCKET (0x553) - used by the redirector and browser
+ * for mailslot datagrams
+ * MESSENGER_SOCKET (0x554) - used by the redirector to send
+ * messages from client to client
+ *
+ * Name claim/query packets, and mailslot datagrams, are:
+ *
+ * 8 IPX network addresses
+ * 1 byte of opcode
+ * 1 byte of name type
+ * 2 bytes of message ID
+ * 16 bytes of name being sought or claimed
+ * 16 bytes of requesting machine
+ *
+ * The opcode is one of:
+ *
+ * INAME_CLAIM (0xf1) - server name claim message
+ * INAME_DELETE (0xf2) - relinquish server name
+ * INAME_QUERY (0xf3) - locate server name
+ * INAME_FOUND (0xf4) - response to INAME_QUERY
+ * IMSG_HANGUP (0xf5) - messenger hangup
+ * IMSLOT_SEND (0xfc) - mailslot write
+ * IMSLOT_FIND (0xfd) - find name for mailslot write
+ * IMSLOT_NAME (0xfe) - response to IMSLOT_FIND
+ *
+ * The name type is one of:
+ *
+ * INTYPE_MACHINE 1
+ * INTYPE_WKGROUP 2
+ * INTYPE_BROWSER 3
+ */
+static int proto_nmpi = -1;
+
+static gint ett_nmpi = -1;
+static gint ett_nmpi_name_type_flags = -1;
+
+/*
+ * Opcodes.
+ */
+#define INAME_CLAIM 0xf1
+#define INAME_DELETE 0xf2
+#define INAME_QUERY 0xf3
+#define INAME_FOUND 0xf4
+#define IMSG_HANGUP 0xf5
+#define IMSLOT_SEND 0xfc
+#define IMSLOT_FIND 0xfd
+#define IMSLOT_NAME 0xfe
+
+static const value_string nmpi_opcode_vals[] = {
+ {INAME_CLAIM, "Claim name"},
+ {INAME_DELETE, "Delete name"},
+ {INAME_QUERY, "Query name"},
+ {INAME_FOUND, "Name found"},
+ {IMSG_HANGUP, "Messenger hangup"},
+ {IMSLOT_SEND, "Mailslot write"},
+ {IMSLOT_FIND, "Find mailslot name"},
+ {IMSLOT_NAME, "Mailslot name found"},
+ {0, NULL}
+};
+
+/*
+ * Name types.
+ */
+#define INTYPE_MACHINE 1
+#define INTYPE_WORKGROUP 2
+#define INTYPE_BROWSER 3
+
+static const value_string nmpi_name_type_vals[] = {
+ {INTYPE_MACHINE, "Machine"},
+ {INTYPE_WORKGROUP, "Workgroup"},
+ {INTYPE_BROWSER, "Browser"},
+ {0, NULL}
+};
+
static void
-dissect_nwlink_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_tree *nbipx_tree;
+ proto_tree *nmpi_tree = NULL;
proto_item *ti;
int offset = 0;
- guint8 packet_type;
- guint8 name_type_flag;
- proto_tree *name_type_flag_tree;
- proto_item *tf;
+ guint8 opcode;
+ guint8 nmpi_name_type;
char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
int name_type;
char node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
@@ -319,172 +684,128 @@ dissect_nwlink_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
const guint8 *next_pd;
int next_offset;
- /*
- * XXX - we don't use "node_name" or "node_name_type".
- */
- name_type_flag = tvb_get_guint8(tvb, offset+32);
- packet_type = tvb_get_guint8(tvb, offset+33);
- name_type = get_netbios_name(tvb, offset+36, name);
- node_name_type = get_netbios_name(tvb, offset+52, node_name);
+ if (check_col(pinfo->fd, COL_PROTOCOL))
+ col_set_str(pinfo->fd, COL_PROTOCOL, "NMPI");
+ if (check_col(pinfo->fd, COL_INFO))
+ col_clear(pinfo->fd, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68,
+ FALSE);
+ nmpi_tree = proto_item_add_subtree(ti, ett_nmpi);
+
+ add_routers(nmpi_tree, tvb, offset);
+ }
+ offset += 32;
/*
- * XXX - if this is labeled as "NWLink", rather than "NBIPX",
- * should it be a separate protocol?
+ * XXX - we don't use "node_name" or "node_name_type".
*/
- if (check_col(pinfo->fd, COL_PROTOCOL))
- col_set_str(pinfo->fd, COL_PROTOCOL, "NWLink");
+ opcode = tvb_get_guint8(tvb, offset);
+ nmpi_name_type = tvb_get_guint8(tvb, offset+1);
+ name_type = get_netbios_name(tvb, offset+4, name);
+ node_name_type = get_netbios_name(tvb, offset+20, node_name);
if (check_col(pinfo->fd, COL_INFO)) {
- /*
- * XXX - Microsoft Network Monitor thinks that the octet
- * at 32 is a packet type, e.g. "mailslot write" for
- * browser announcements, and that the octet at 33 is a
- * name type, in the sense of the 16th byte of a
- * NetBIOS name.
- *
- * A name type of 2 shows up in a "host announcement",
- * and a name type of 3 shows up in a "local master
- * annoumcement", so maybe that field really *is* a
- * name type - the fact that it's not associated with
- * any of the NetBIOS names in the packet nonwithstanding.
- *
- * I haven't seen any packets with the name type octet
- * being anything other than 2 or 3, so I don't know
- * whether those are name service operations; however,
- * given that NWLink, unlike socket-0x0455 NBIPX,
- * has separate sockets for name queries and datagrams,
- * it may be that this really is a name type, and that
- * these are all datagrams, not name queries.
- */
- switch (packet_type) {
- case NWLINK_NAME_QUERY:
- col_add_fstr(pinfo->fd, COL_INFO, "Name Query for %s<%02x>",
+ switch (opcode) {
+
+ case INAME_CLAIM:
+ col_add_fstr(pinfo->fd, COL_INFO, "Claim name %s<%02x>",
name, name_type);
break;
- case NWLINK_SMB:
- /* Session? */
- col_add_fstr(pinfo->fd, COL_INFO, "SMB over NBIPX");
+ case INAME_DELETE:
+ col_add_fstr(pinfo->fd, COL_INFO, "Delete name %s<%02x>",
+ name, name_type);
break;
- case NWLINK_NETBIOS_DATAGRAM:
- /* Datagram? (Where did we see this?) */
- col_add_fstr(pinfo->fd, COL_INFO, "NetBIOS datagram over NBIPX");
+ case INAME_QUERY:
+ col_add_fstr(pinfo->fd, COL_INFO, "Query name %s<%02x>",
+ name, name_type);
break;
-
- default:
- col_set_str(pinfo->fd, COL_INFO, "NetBIOS over IPX (NWLink)");
+
+ case INAME_FOUND:
+ col_add_fstr(pinfo->fd, COL_INFO, "Name %s<%02x> found",
+ name, name_type);
break;
- }
- }
- if (tree) {
- ti = proto_tree_add_item(tree, proto_nbipx, tvb, offset, 68, FALSE);
- nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
+ case IMSG_HANGUP:
+ col_add_fstr(pinfo->fd, COL_INFO,
+ "Messenger hangup on %s<%02x>", name, name_type);
+ break;
- add_routers(nbipx_tree, tvb, offset);
+ case IMSLOT_SEND:
+ col_add_fstr(pinfo->fd, COL_INFO,
+ "Mailslot write to %s<%02x>", name, name_type);
+ break;
- /*
- * XXX - is "packet_type" really a packet type? See
- * above.
- */
- if (packet_type != NWLINK_SMB &&
- packet_type != NWLINK_NETBIOS_DATAGRAM) {
- tf = proto_tree_add_text(nbipx_tree, tvb, offset+32, 1,
- "Name type flag: 0x%02x",
- name_type_flag);
- name_type_flag_tree = proto_item_add_subtree(tf,
- ett_nbipx_name_type_flags);
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x80, 8,
- "Group name", "Unique name"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x40, 8,
- "Name in use", "Name not used"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x04, 8,
- "Name registered", "Name not registered"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x02, 8,
- "Name duplicated", "Name not duplicated"));
- proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
- 1, "%s",
- decode_boolean_bitfield(name_type_flag, 0x01, 8,
- "Name deregistered", "Name not deregistered"));
+ case IMSLOT_FIND:
+ col_add_fstr(pinfo->fd, COL_INFO,
+ "Find mailslot name %s<%02x>", name, name_type);
+ break;
- netbios_add_name("Group name", tvb, offset+36,
- nbipx_tree);
- netbios_add_name("Node name", tvb, offset+52,
- nbipx_tree);
- proto_tree_add_text(nbipx_tree, tvb, offset+33, 1,
- "Packet Type: %s (%02X)",
- val_to_str(packet_type, nwlink_data_stream_type_vals, "Unknown"),
- packet_type);
- } else {
- proto_tree_add_text(nbipx_tree, tvb, offset+32, 1,
- "Packet type: 0x%02x", name_type_flag);
- proto_tree_add_text(nbipx_tree, tvb, offset+33, 1,
- "Name Type: %s (0x%02x)",
- netbios_name_type_descr(packet_type),
- packet_type);
- proto_tree_add_text(nbipx_tree, tvb, offset+34, 2,
- "Message ID: 0x%04x",
- tvb_get_letohs(tvb, offset+34));
- netbios_add_name("Requested name", tvb, offset+36,
- nbipx_tree);
- netbios_add_name("Source name", tvb, offset+52,
- nbipx_tree);
+ case IMSLOT_NAME:
+ col_add_fstr(pinfo->fd, COL_INFO,
+ "Mailslot name %s<%02x> found", name, name_type);
+ break;
+
+ default:
+ col_add_fstr(pinfo->fd, COL_INFO,
+ "Unknown NMPI op 0x%02x: name %s<%02x>",
+ opcode, name, name_type);
+ break;
}
}
- offset += 68;
+ if (tree) {
+ proto_tree_add_text(nmpi_tree, tvb, offset, 1,
+ "Opcode: %s (0x%02x)",
+ val_to_str(opcode, nmpi_opcode_vals, "Unknown"),
+ opcode);
+ proto_tree_add_text(nmpi_tree, tvb, offset+1, 1,
+ "Name Type: %s (0x%02x)",
+ val_to_str(nmpi_name_type, nmpi_name_type_vals, "Unknown"),
+ nmpi_name_type);
+ proto_tree_add_text(nmpi_tree, tvb, offset+2, 2,
+ "Message ID: 0x%04x",
+ tvb_get_letohs(tvb, offset+2));
+ netbios_add_name("Requested name", tvb, offset+4, nmpi_tree);
+ netbios_add_name("Source name", tvb, offset+20, nmpi_tree);
+ }
+
+ offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN;
- if (tvb_offset_exists(tvb, offset)) {
+ if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) {
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
-
- switch (packet_type) {
- case NWLINK_SMB:
- case NWLINK_NETBIOS_DATAGRAM:
- tvb_compat(next_tvb, &next_pd, &next_offset);
- dissect_smb(next_pd, next_offset, pinfo->fd, tree,
- tvb_length(next_tvb));
- break;
-
- default:
- dissect_data(next_tvb, 0, pinfo, tree);
- break;
- }
+ tvb_compat(next_tvb, &next_pd, &next_offset);
+ dissect_smb(next_pd, next_offset, pinfo->fd, tree,
+ tvb_length(next_tvb));
}
}
void
-proto_register_nbipx(void)
+proto_register_nmpi(void)
{
/* static hf_register_info hf[] = {
{ &variable,
- { "Name", "nbipx.abbreviation", TYPE, VALS_POINTER }},
+ { "Name", "nmpi.abbreviation", TYPE, VALS_POINTER }},
};*/
static gint *ett[] = {
- &ett_nbipx,
- &ett_nbipx_conn_ctrl,
- &ett_nbipx_name_type_flags,
+ &ett_nmpi,
+ &ett_nmpi_name_type_flags,
};
- proto_nbipx = proto_register_protocol("NetBIOS over IPX",
- "NBIPX", "nbipx");
- /* proto_register_field_array(proto_nbipx, hf, array_length(hf));*/
+ proto_nmpi = proto_register_protocol("Name Management Protocol over IPX",
+ "NMPI", "nmpi");
+ /* proto_register_field_array(proto_nmpi, hf, array_length(hf));*/
proto_register_subtree_array(ett, array_length(ett));
-
- register_dissector("nbipx", dissect_nbipx, proto_nbipx);
}
void
-proto_reg_handoff_nbipx(void)
+proto_reg_handoff_nmpi(void)
{
- dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_DGRAM,
- dissect_nwlink_dg, proto_nbipx);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_NAMEQUERY,
+ dissect_nmpi, proto_nmpi);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_MAILSLOT,
+ dissect_nmpi, proto_nmpi);
}