MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-nbipx.c
blob979f71b1e80f1622314b7f2e4b958528a6ecf3f0
1 /* packet-nbipx.c
2 * Routines for NetBIOS over IPX packet disassembly
3 * Gilbert Ramirez <gram@alumni.rice.edu>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
29 #include <epan/packet.h>
30 #include <epan/to_str.h>
31 #include "packet-ipx.h"
32 #include "packet-netbios.h"
34 static int proto_nbipx = -1;
35 static int hf_nbipx_packettype = -1;
36 static int hf_nbipx_name_flags = -1;
37 static int hf_nbipx_name_flags_group = -1;
38 static int hf_nbipx_name_flags_in_use = -1;
39 static int hf_nbipx_name_flags_registered = -1;
40 static int hf_nbipx_name_flags_duplicated = -1;
41 static int hf_nbipx_name_flags_deregistered = -1;
42 static int hf_nbipx_conn_control = -1;
43 static int hf_nbipx_conn_control_sys_packet = -1;
44 static int hf_nbipx_conn_control_ack = -1;
45 static int hf_nbipx_conn_control_attention = -1;
46 static int hf_nbipx_conn_control_end_msg = -1;
47 static int hf_nbipx_conn_control_resend = -1;
48 static int hf_nbipx_session_src_conn_id = -1;
49 static int hf_nbipx_session_dest_conn_id = -1;
50 static int hf_nbipx_session_send_seq_number = -1;
51 static int hf_nbipx_session_total_data_length = -1;
52 static int hf_nbipx_session_offset = -1;
53 static int hf_nbipx_session_data_length = -1;
54 static int hf_nbipx_session_recv_seq_number = -1;
55 static int hf_nbipx_session_bytes_received = -1;
57 static gint ett_nbipx = -1;
58 static gint ett_nbipx_conn_ctrl = -1;
59 static gint ett_nbipx_name_type_flags = -1;
61 static void dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree);
63 /* There is no RFC or public specification of Netware or Microsoft
64 * NetBIOS over IPX packets. I have had to decode the protocol myself,
65 * so there are holes and perhaps errors in this code. (gram)
67 * A list of "NovelNetBIOS" packet types can be found at
69 * http://www.protocols.com/pbook/novel.htm#NetBIOS
71 * and at least some of those packet types appear to match what's in
72 * some NBIPX packets.
74 * Note, however, that it appears that sometimes NBIPX packets have
75 * 8 IPX addresses at the beginning, and sometimes they don't.
77 * In the section on "NetBIOS Broadcasts", the document at
79 * http://www.microsoft.com/technet/network/ipxrout.asp
81 * says that "the NetBIOS over IPX Broadcast header" contains 8 IPX
82 * network numbers in the "IPX WAN broadcast header", and that it's
83 * followed by a "Name Type Flags" byte (giving information about the
84 * name being registered, deregistered, or checked), a "Data Stream
85 * Type 2" byte giving the type of operation (NBIPX_FIND_NAME,
86 * NBIPX_NAME_RECOGNIZED, or NBIPX_CHECK_NAME - the latter is called
87 * "Add Name"), and a 16-byte NetBIOS name.
89 * It also says that "NetBIOS over IPX Broadcast packets" have a
90 * packet type of 0x14 (20, or IPX_PACKET_TYPE_WANBCAST) and a
91 * socket number of 0x455 (IPX_SOCKET_NETBIOS).
93 * However, there are also non-broadcast packets that *also* contain
94 * the 8 IPX network numbers; they appear to be replies to broadcast
95 * packets, and have a packet type of 0x4 (IPX_PACKET_TYPE_PEP).
97 * Other IPX_PACKET_TYPE_PEP packets to and from the IPX_SOCKET_NETBIOS
98 * socket, however, *don't* have the 8 IPX network numbers; there does
99 * not seem to be any obvious algorithm to determine whether the packet
100 * has the addresses or not. Microsoft Knowledge Base article Q128335
101 * appears to show some code from the NBIPX implementation in NT that
102 * tries to determine the packet type - and it appears to use heuristics
103 * based on the packet length and on looking at what might be the NBIPX
104 * "Data Stream Type" byte depending on whether the packet has the 8
105 * IPX network numbers or not.
107 * So, for now, we treat *all* NBIPX packets as having a "Data Stream
108 * Type" byte, preceded by another byte of NBIPX information and
109 * followed by more NBIPX stuff, and assume that it's preceded by
110 * 8 IPX network numbers iff:
112 * the packet is a WAN Broadcast packet
114 * or
116 * the packet is the right size for one of those PEP name replies
117 * (50 bytes) *and* has a name packet type as the Data Stream
118 * Type byte at the offset where that byte would be if the packet
119 * does have the 8 IPX network numbers at the beginning.
121 * The page at
123 * http://ourworld.compuserve.com/homepages/TimothyDEvans/encap.htm
125 * indicates, under "NBIPX session packets", that "NBIPX session packets"
126 * have
128 * 1 byte of NBIPX connection control flag
129 * 1 byte of data stream type
130 * 2 bytes of source connection ID
131 * 2 bytes of destination connection ID
132 * 2 bytes of send sequence number
133 * 2 bytes of total data length
134 * 2 bytes of offset
135 * 2 bytes of data length
136 * 2 bytes of receive sequence number
137 * 2 bytes of "bytes received"
139 * followed by data.
141 * Packets with a data stream type of NBIPX_DIRECTED_DATAGRAM appear to
142 * have, following the data stream type, two NetBIOS names, the first
143 * of which is the receiver's NetBIOS name and the second of which is
144 * the sender's NetBIOS name. The page at
146 * http://support.microsoft.com/support/kb/articles/q203/0/51.asp
148 * speaks of type 4 (PEP) packets as being used for "SAP, NetBIOS sessions
149 * and directed datagrams" and type 20 (WAN Broadcast) as being used for
150 * "NetBIOS name resolution broadcasts" (but nothing about the non-broadcast
151 * type 4 name resolution stuff).
153 * We assume that this means that, once you get past the 8 IPX network
154 * numbers if present:
156 * the first byte is a name type byte for the name packets
157 * and a connection control flag for the other packets;
159 * the second byte is a data stream type;
161 * the rest of the bytes are:
163 * the NetBIOS name being registered/deregistered/etc.,
164 * for name packets;
166 * the two NetBIOS names, followed by the NetBIOS
167 * datagram, for NBIPX_DIRECTED_DATAGRAM packets;
169 * the session packet header, possibly followed by
170 * session data, for session packets.
172 * We don't know yet how to interpret NBIPX_STATUS_QUERY or
173 * NBIPX_STATUS_RESPONSE.
175 * For now, we treat the datagrams and session data as SMB stuff.
177 #define NBIPX_FIND_NAME 1
178 #define NBIPX_NAME_RECOGNIZED 2
179 #define NBIPX_CHECK_NAME 3
180 #define NBIPX_NAME_IN_USE 4
181 #define NBIPX_DEREGISTER_NAME 5
182 #define NBIPX_SESSION_DATA 6
183 #define NBIPX_SESSION_END 7
184 #define NBIPX_SESSION_END_ACK 8
185 #define NBIPX_STATUS_QUERY 9
186 #define NBIPX_STATUS_RESPONSE 10
187 #define NBIPX_DIRECTED_DATAGRAM 11
189 static const value_string nbipx_data_stream_type_vals[] = {
190 {NBIPX_FIND_NAME, "Find name"},
191 {NBIPX_NAME_RECOGNIZED, "Name recognized"},
192 {NBIPX_CHECK_NAME, "Check name"},
193 {NBIPX_NAME_IN_USE, "Name in use"},
194 {NBIPX_DEREGISTER_NAME, "Deregister name"},
195 {NBIPX_SESSION_DATA, "Session data"},
196 {NBIPX_SESSION_END, "Session end"},
197 {NBIPX_SESSION_END_ACK, "Session end ACK"},
198 {NBIPX_STATUS_QUERY, "Status query"},
199 {NBIPX_STATUS_RESPONSE, "Status response"},
200 {NBIPX_DIRECTED_DATAGRAM, "Directed datagram"},
201 {0, NULL}
204 static const true_false_string tfs_system_non_system = { "System packet", "Non-system packet" };
205 static const true_false_string tfs_required_not_required = { "Required", "Not required" };
207 static void
208 add_routers(proto_tree *tree, tvbuff_t *tvb, int offset)
210 int i;
211 int rtr_offset;
212 guint32 router;
214 /* Eight routers are listed */
215 for (i = 0; i < 8; i++) {
216 rtr_offset = offset + (i << 2);
217 tvb_memcpy(tvb, (guint8 *)&router, rtr_offset, 4);
218 if (router != 0) {
219 /* XXX - proto_tree_add_item with FT_IPXNET type? */
220 proto_tree_add_text(tree, tvb, rtr_offset, 4,
221 "IPX Network: %s",
222 ipxnet_to_string((guint8*)&router));
227 static int
228 dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
230 gboolean has_routes;
231 proto_tree *nbipx_tree = NULL;
232 proto_item *ti = NULL;
233 int offset = 0;
234 guint8 packet_type;
235 proto_tree *name_type_flag_tree;
236 proto_item *tf;
237 char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
238 int name_type;
239 gboolean has_payload;
240 tvbuff_t *next_tvb;
241 ipxhdr_t *ipxh = (ipxhdr_t*)data;
243 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBIPX");
244 col_clear(pinfo->cinfo, COL_INFO);
246 if (ipxh->ipx_type == IPX_PACKET_TYPE_WANBCAST) {
248 * This is a WAN Broadcast packet; we assume it will have
249 * 8 IPX addresses at the beginning.
251 has_routes = TRUE;
252 } else {
254 * This isn't a WAN Broadcast packet, but it still might
255 * have the 8 addresses.
257 * If it's the right length for a name operation,
258 * and, if we assume it has routes, the packet type
259 * is a name operation, assume it has routes.
261 * NOTE: this will throw an exception if the byte that
262 * would be the packet type byte if this has the 8
263 * addresses isn't present; if that's the case, we don't
264 * know how to interpret this packet, so we can't dissect
265 * it anyway.
267 has_routes = FALSE; /* start out assuming it doesn't */
268 if (tvb_reported_length(tvb) == 50) {
269 packet_type = tvb_get_guint8(tvb, offset + 32 + 1);
270 switch (packet_type) {
272 case NBIPX_FIND_NAME:
273 case NBIPX_NAME_RECOGNIZED:
274 case NBIPX_CHECK_NAME:
275 case NBIPX_NAME_IN_USE:
276 case NBIPX_DEREGISTER_NAME:
277 has_routes = TRUE;
278 break;
283 if (tree) {
284 ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0,
285 -1, ENC_NA);
286 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
289 if (has_routes) {
290 if (tree)
291 add_routers(nbipx_tree, tvb, 0);
292 offset += 32;
295 packet_type = tvb_get_guint8(tvb, offset + 1);
297 switch (packet_type) {
299 case NBIPX_FIND_NAME:
300 case NBIPX_NAME_RECOGNIZED:
301 case NBIPX_CHECK_NAME:
302 case NBIPX_NAME_IN_USE:
303 case NBIPX_DEREGISTER_NAME:
304 name_type = get_netbios_name(tvb, offset+2, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
305 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>",
306 val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"),
307 name, name_type);
309 if (nbipx_tree) {
310 tf = proto_tree_add_item(nbipx_tree, hf_nbipx_name_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
311 name_type_flag_tree = proto_item_add_subtree(tf, ett_nbipx_name_type_flags);
313 proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_group, tvb, offset, 1, ENC_LITTLE_ENDIAN);
314 proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_in_use, tvb, offset, 1, ENC_LITTLE_ENDIAN);
315 proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_registered, tvb, offset, 1, ENC_LITTLE_ENDIAN);
316 proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_duplicated, tvb, offset, 1, ENC_LITTLE_ENDIAN);
317 proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_deregistered, tvb, offset, 1, ENC_LITTLE_ENDIAN);
319 offset += 1;
321 proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
322 offset += 1;
324 if (nbipx_tree)
325 netbios_add_name("Name", tvb, offset, nbipx_tree);
326 offset += NETBIOS_NAME_LEN;
329 * No payload to be interpreted by another protocol.
331 has_payload = FALSE;
332 break;
334 case NBIPX_SESSION_DATA:
335 case NBIPX_SESSION_END:
336 case NBIPX_SESSION_END_ACK:
337 col_set_str(pinfo->cinfo, COL_INFO,
338 val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));
340 dissect_conn_control(tvb, offset, nbipx_tree);
341 offset += 1;
343 proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
344 offset += 1;
346 proto_tree_add_item(nbipx_tree, hf_nbipx_session_src_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
347 offset += 2;
349 proto_tree_add_item(nbipx_tree, hf_nbipx_session_dest_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
350 offset += 2;
352 proto_tree_add_item(nbipx_tree, hf_nbipx_session_send_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
353 offset += 2;
355 proto_tree_add_item(nbipx_tree, hf_nbipx_session_total_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
356 offset += 2;
358 proto_tree_add_item(nbipx_tree, hf_nbipx_session_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
359 offset += 2;
361 proto_tree_add_item(nbipx_tree, hf_nbipx_session_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
362 offset += 2;
364 proto_tree_add_item(nbipx_tree, hf_nbipx_session_recv_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
365 offset += 2;
367 proto_tree_add_item(nbipx_tree, hf_nbipx_session_bytes_received, tvb, offset, 2, ENC_LITTLE_ENDIAN);
368 offset += 2;
371 * We may have payload to dissect.
373 has_payload = TRUE;
374 break;
376 case NBIPX_DIRECTED_DATAGRAM:
377 col_set_str(pinfo->cinfo, COL_INFO,
378 val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));
380 dissect_conn_control(tvb, offset, nbipx_tree);
381 offset += 1;
383 proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
384 offset += 1;
386 if (nbipx_tree)
387 netbios_add_name("Receiver's Name", tvb, offset,
388 nbipx_tree);
389 offset += NETBIOS_NAME_LEN;
391 if (nbipx_tree)
392 netbios_add_name("Sender's Name", tvb, offset,
393 nbipx_tree);
394 offset += NETBIOS_NAME_LEN;
397 * We may have payload to dissect.
399 has_payload = TRUE;
400 break;
402 default:
403 col_set_str(pinfo->cinfo, COL_INFO,
404 val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));
407 * We don't know what the first byte is.
409 offset += 1;
412 * The second byte is a data stream type byte.
414 proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
415 offset += 1;
418 * We don't know what the rest of the packet is.
420 has_payload = FALSE;
424 * Set the length of the NBIPX tree item.
426 if (ti != NULL)
427 proto_item_set_len(ti, offset);
429 if (has_payload && tvb_offset_exists(tvb, offset)) {
430 next_tvb = tvb_new_subset_remaining(tvb, offset);
431 dissect_netbios_payload(next_tvb, pinfo, tree);
434 return tvb_length(tvb);
437 static void
438 dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree)
440 proto_item *ti;
441 proto_tree *cc_tree;
443 if (tree) {
444 ti = proto_tree_add_item(tree, hf_nbipx_conn_control, tvb, offset, 1, ENC_LITTLE_ENDIAN);
445 cc_tree = proto_item_add_subtree(ti, ett_nbipx_conn_ctrl);
446 proto_tree_add_item(cc_tree, hf_nbipx_conn_control_sys_packet, tvb, offset, 1, ENC_LITTLE_ENDIAN);
447 proto_tree_add_item(cc_tree, hf_nbipx_conn_control_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
448 proto_tree_add_item(cc_tree, hf_nbipx_conn_control_attention, tvb, offset, 1, ENC_LITTLE_ENDIAN);
449 proto_tree_add_item(cc_tree, hf_nbipx_conn_control_end_msg, tvb, offset, 1, ENC_LITTLE_ENDIAN);
450 proto_tree_add_item(cc_tree, hf_nbipx_conn_control_resend, tvb, offset, 1, ENC_LITTLE_ENDIAN);
454 void
455 proto_register_nbipx(void)
457 static hf_register_info hf[] = {
458 { &hf_nbipx_packettype,
459 { "Packet Type", "nmpi.packettype",
460 FT_UINT8, BASE_HEX, VALS(nbipx_data_stream_type_vals), 0,
461 NULL, HFILL }
463 { &hf_nbipx_name_flags,
464 { "Name type flag", "nmpi.name_flags",
465 FT_UINT8, BASE_HEX, NULL, 0,
466 NULL, HFILL }
468 { &hf_nbipx_name_flags_group,
469 { "Name", "nmpi.name_flags.group",
470 FT_BOOLEAN, 8, TFS(&tfs_group_unique_name), 0x80,
471 NULL, HFILL }
473 { &hf_nbipx_name_flags_in_use,
474 { "In use", "nmpi.name_flags.in_use",
475 FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x40,
476 NULL, HFILL }
478 { &hf_nbipx_name_flags_registered,
479 { "Registered", "nmpi.name_flags.registered",
480 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
481 NULL, HFILL }
483 { &hf_nbipx_name_flags_duplicated,
484 { "Duplicated", "nmpi.name_flags.duplicated",
485 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
486 NULL, HFILL }
488 { &hf_nbipx_name_flags_deregistered,
489 { "Deregistered", "nmpi.name_flags.deregistered",
490 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
491 NULL, HFILL }
493 { &hf_nbipx_conn_control,
494 { "Connection control", "nmpi.conn_control",
495 FT_UINT8, BASE_HEX, NULL, 0,
496 NULL, HFILL }
498 { &hf_nbipx_conn_control_sys_packet,
499 { "Packet", "nmpi.conn_control.sys_packet",
500 FT_BOOLEAN, 8, TFS(&tfs_system_non_system), 0x80,
501 NULL, HFILL }
503 { &hf_nbipx_conn_control_ack,
504 { "Acknowledgement", "nmpi.conn_control.ack",
505 FT_BOOLEAN, 8, TFS(&tfs_required_not_required), 0x40,
506 NULL, HFILL }
508 { &hf_nbipx_conn_control_attention,
509 { "Attention", "nmpi.conn_control.attention",
510 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
511 NULL, HFILL }
513 { &hf_nbipx_conn_control_end_msg,
514 { "End of message", "nmpi.conn_control.end_msg",
515 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
516 NULL, HFILL }
518 { &hf_nbipx_conn_control_resend,
519 { "Resend", "nmpi.conn_control.resend",
520 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
521 NULL, HFILL }
523 { &hf_nbipx_session_src_conn_id,
524 { "Source connection ID", "nmpi.session.src_conn_id",
525 FT_UINT16, BASE_HEX, NULL, 0,
526 NULL, HFILL }
528 { &hf_nbipx_session_dest_conn_id,
529 { "Destination connection ID", "nmpi.session.dest_conn_id",
530 FT_UINT16, BASE_HEX, NULL, 0,
531 NULL, HFILL }
533 { &hf_nbipx_session_send_seq_number,
534 { "Send sequence number", "nmpi.session.send_seq_number",
535 FT_UINT16, BASE_DEC, NULL, 0,
536 NULL, HFILL }
538 { &hf_nbipx_session_total_data_length,
539 { "Total data length", "nmpi.session.total_data_length",
540 FT_UINT16, BASE_DEC, NULL, 0,
541 NULL, HFILL }
543 { &hf_nbipx_session_offset,
544 { "Offset", "nmpi.session.offset",
545 FT_UINT16, BASE_DEC, NULL, 0,
546 NULL, HFILL }
548 { &hf_nbipx_session_data_length,
549 { "Data length", "nmpi.session.data_length",
550 FT_UINT16, BASE_DEC, NULL, 0,
551 NULL, HFILL }
553 { &hf_nbipx_session_recv_seq_number,
554 { "Receive sequence number", "nmpi.session.recv_seq_number",
555 FT_UINT16, BASE_DEC, NULL, 0,
556 NULL, HFILL }
558 { &hf_nbipx_session_bytes_received,
559 { "Bytes received", "nmpi.session.bytes_received",
560 FT_UINT16, BASE_DEC, NULL, 0,
561 NULL, HFILL }
565 static gint *ett[] = {
566 &ett_nbipx,
567 &ett_nbipx_conn_ctrl,
568 &ett_nbipx_name_type_flags,
571 proto_nbipx = proto_register_protocol("NetBIOS over IPX", "NBIPX", "nbipx");
572 proto_register_field_array(proto_nbipx, hf, array_length(hf));
573 proto_register_subtree_array(ett, array_length(ett));
576 void
577 proto_reg_handoff_nbipx(void)
579 dissector_handle_t nbipx_handle;
581 nbipx_handle = new_create_dissector_handle(dissect_nbipx, proto_nbipx);
582 dissector_add_uint("ipx.socket", IPX_SOCKET_NETBIOS, nbipx_handle);
586 * Microsoft appear to have something they call "direct hosting", where
587 * SMB - and, I infer, related stuff, such as name resolution - runs
588 * directly over IPX. (In Windows 2000, they also run SMB directly over
589 * TCP, on port 445, and that also appears to be called "direct hosting".
590 * Wireshark handles SMB-over-TCP.)
592 * The document at
594 * http://support.microsoft.com/support/kb/articles/q203/0/51.asp
596 * speaks of NMPI - the "Name Management Protocol on IPX" - as being
597 * "Microsoft's protocol for name management support when you use IPX
598 * without the NetBIOS interface," and says that "This process of routing
599 * the SMB protocol directly through IPX is known as Direct Hosting."
601 * It speaks of IPX socket 0x551 as being for NMPI; we define it as
602 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY.
604 * We also define IPX_SOCKET_NWLINK_SMB_DGRAM as 0x0553 and define
605 * IPX_SOCKET_NWLINK_SMB_BROWSE as 0x0555 (with a "? not sure on this"
606 * comment after the latter one).
608 * We have seen at least some browser announcements on IPX socket 0x553;
609 * those are WAN broadcast packets, complete with 8 IPX network
610 * numbers, and with the header containing the usual two NetBIOS names
611 * that show up in NetBIOS datagrams.
613 * Network Monitor calls those packets NMPI packets, even though they're
614 * on socket 0x553, not socket 0x551, and contain SMB datagrams, not name
615 * resolution packets.
617 * At least some of this is discussed in the "SMBPUB.DOC" Word document
618 * stored in
620 * ftp://ftp.microsoft.com/developr/drg/CIFS/smbpub.zip
622 * which can also be found in text form at
624 * http://www.samba.org/samba/ftp/specs/smbpub.txt
626 * which says that for "connectionless IPX transport" the sockets that
627 * are used are:
629 * SMB_SERVER_SOCKET (0x550) - SMB requests from clients
630 * SMB_NAME_SOCKET (0x551) - name claims and name query messages
631 * REDIR_SOCKET (0x552) - used by the redirector (client) for
632 * sending SMB requests and receiving SMB replies
633 * MAILSLOT_SOCKET (0x553) - used by the redirector and browser
634 * for mailslot datagrams
635 * MESSENGER_SOCKET (0x554) - used by the redirector to send
636 * messages from client to client
638 * Name claim/query packets, and mailslot datagrams, are:
640 * 8 IPX network addresses
641 * 1 byte of opcode
642 * 1 byte of name type
643 * 2 bytes of message ID
644 * 16 bytes of name being sought or claimed
645 * 16 bytes of requesting machine
647 * The opcode is one of:
649 * INAME_CLAIM (0xf1) - server name claim message
650 * INAME_DELETE (0xf2) - relinquish server name
651 * INAME_QUERY (0xf3) - locate server name
652 * INAME_FOUND (0xf4) - response to INAME_QUERY
653 * IMSG_HANGUP (0xf5) - messenger hangup
654 * IMSLOT_SEND (0xfc) - mailslot write
655 * IMSLOT_FIND (0xfd) - find name for mailslot write
656 * IMSLOT_NAME (0xfe) - response to IMSLOT_FIND
658 * The name type is one of:
660 * INTYPE_MACHINE 1
661 * INTYPE_WKGROUP 2
662 * INTYPE_BROWSER 3
664 static int proto_nmpi = -1;
666 static gint ett_nmpi = -1;
667 static gint ett_nmpi_name_type_flags = -1;
670 * Opcodes.
672 #define INAME_CLAIM 0xf1
673 #define INAME_DELETE 0xf2
674 #define INAME_QUERY 0xf3
675 #define INAME_FOUND 0xf4
676 #define IMSG_HANGUP 0xf5
677 #define IMSLOT_SEND 0xfc
678 #define IMSLOT_FIND 0xfd
679 #define IMSLOT_NAME 0xfe
681 static const value_string nmpi_opcode_vals[] = {
682 {INAME_CLAIM, "Claim name"},
683 {INAME_DELETE, "Delete name"},
684 {INAME_QUERY, "Query name"},
685 {INAME_FOUND, "Name found"},
686 {IMSG_HANGUP, "Messenger hangup"},
687 {IMSLOT_SEND, "Mailslot write"},
688 {IMSLOT_FIND, "Find mailslot name"},
689 {IMSLOT_NAME, "Mailslot name found"},
690 {0, NULL}
694 * Name types.
696 #define INTYPE_MACHINE 1
697 #define INTYPE_WORKGROUP 2
698 #define INTYPE_BROWSER 3
700 static const value_string nmpi_name_type_vals[] = {
701 {INTYPE_MACHINE, "Machine"},
702 {INTYPE_WORKGROUP, "Workgroup"},
703 {INTYPE_BROWSER, "Browser"},
704 {0, NULL}
707 static void
708 dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
710 proto_tree *nmpi_tree = NULL;
711 proto_item *ti;
712 int offset = 0;
713 guint8 opcode;
714 guint8 nmpi_name_type;
715 char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
716 int name_type;
717 char node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
718 /*int node_name_type = 0;*/
719 tvbuff_t *next_tvb;
721 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMPI");
722 col_clear(pinfo->cinfo, COL_INFO);
724 if (tree) {
725 ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68,
726 ENC_NA);
727 nmpi_tree = proto_item_add_subtree(ti, ett_nmpi);
729 add_routers(nmpi_tree, tvb, offset);
731 offset += 32;
734 * XXX - we don't use "node_name" or "node_name_type".
736 opcode = tvb_get_guint8(tvb, offset);
737 nmpi_name_type = tvb_get_guint8(tvb, offset+1);
738 name_type = get_netbios_name(tvb, offset+4, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
739 /*node_name_type = */get_netbios_name(tvb, offset+20, node_name, (NETBIOS_NAME_LEN - 1)*4 + 1);
741 switch (opcode) {
743 case INAME_CLAIM:
744 col_add_fstr(pinfo->cinfo, COL_INFO, "Claim name %s<%02x>",
745 name, name_type);
746 break;
748 case INAME_DELETE:
749 col_add_fstr(pinfo->cinfo, COL_INFO, "Delete name %s<%02x>",
750 name, name_type);
751 break;
753 case INAME_QUERY:
754 col_add_fstr(pinfo->cinfo, COL_INFO, "Query name %s<%02x>",
755 name, name_type);
756 break;
758 case INAME_FOUND:
759 col_add_fstr(pinfo->cinfo, COL_INFO, "Name %s<%02x> found",
760 name, name_type);
761 break;
763 case IMSG_HANGUP:
764 col_add_fstr(pinfo->cinfo, COL_INFO,
765 "Messenger hangup on %s<%02x>", name, name_type);
766 break;
768 case IMSLOT_SEND:
769 col_add_fstr(pinfo->cinfo, COL_INFO,
770 "Mailslot write to %s<%02x>", name, name_type);
771 break;
773 case IMSLOT_FIND:
774 col_add_fstr(pinfo->cinfo, COL_INFO,
775 "Find mailslot name %s<%02x>", name, name_type);
776 break;
778 case IMSLOT_NAME:
779 col_add_fstr(pinfo->cinfo, COL_INFO,
780 "Mailslot name %s<%02x> found", name, name_type);
781 break;
783 default:
784 col_add_fstr(pinfo->cinfo, COL_INFO,
785 "Unknown NMPI op 0x%02x: name %s<%02x>",
786 opcode, name, name_type);
787 break;
790 if (tree) {
791 proto_tree_add_text(nmpi_tree, tvb, offset, 1,
792 "Opcode: %s (0x%02x)",
793 val_to_str_const(opcode, nmpi_opcode_vals, "Unknown"),
794 opcode);
795 proto_tree_add_text(nmpi_tree, tvb, offset+1, 1,
796 "Name Type: %s (0x%02x)",
797 val_to_str_const(nmpi_name_type, nmpi_name_type_vals, "Unknown"),
798 nmpi_name_type);
799 proto_tree_add_text(nmpi_tree, tvb, offset+2, 2,
800 "Message ID: 0x%04x",
801 tvb_get_letohs(tvb, offset+2));
802 netbios_add_name("Requested name", tvb, offset+4, nmpi_tree);
803 netbios_add_name("Source name", tvb, offset+20, nmpi_tree);
806 offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN;
808 if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) {
809 next_tvb = tvb_new_subset_remaining(tvb, offset);
810 dissect_netbios_payload(next_tvb, pinfo, tree);
814 void
815 proto_register_nmpi(void)
817 /* static hf_register_info hf[] = {
818 { &variable,
819 { "Name", "nmpi.abbreviation", TYPE, VALS_POINTER }},
820 };*/
821 static gint *ett[] = {
822 &ett_nmpi,
823 &ett_nmpi_name_type_flags,
826 proto_nmpi = proto_register_protocol("Name Management Protocol over IPX",
827 "NMPI", "nmpi");
828 /* proto_register_field_array(proto_nmpi, hf, array_length(hf));*/
829 proto_register_subtree_array(ett, array_length(ett));
832 void
833 proto_reg_handoff_nmpi(void)
835 dissector_handle_t nmpi_handle;
837 nmpi_handle = create_dissector_handle(dissect_nmpi, proto_nmpi);
838 dissector_add_uint("ipx.socket", IPX_SOCKET_NWLINK_SMB_NAMEQUERY,
839 nmpi_handle);
840 dissector_add_uint("ipx.socket", IPX_SOCKET_NWLINK_SMB_MAILSLOT,
841 nmpi_handle);