Show the "More Fragments" indicator as such, rather than as a "this is
[obnox/wireshark/wip.git] / packet-nbipx.c
1 /* packet-nbipx.c
2  * Routines for NetBIOS over IPX packet disassembly
3  * Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * $Id: packet-nbipx.c,v 1.46 2002/01/21 07:36:37 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
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.
15  * 
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.
20  * 
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <string.h>
35 #include <glib.h>
36 #include <epan/packet.h>
37 #include "packet-ipx.h"
38 #include "packet-netbios.h"
39
40 static int proto_nbipx = -1;
41
42 static gint ett_nbipx = -1;
43 static gint ett_nbipx_conn_ctrl = -1;
44 static gint ett_nbipx_name_type_flags = -1;
45
46 static void dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree);
47 static void dissect_packet_type(tvbuff_t *tvb, int offset, guint8 packet_type,
48     proto_tree *tree);
49
50 /* There is no RFC or public specification of Netware or Microsoft
51  * NetBIOS over IPX packets. I have had to decode the protocol myself,
52  * so there are holes and perhaps errors in this code. (gram)
53  *
54  * A list of "NovelNetBIOS" packet types can be found at
55  *
56  *      http://www.protocols.com/pbook/novel.htm#NetBIOS
57  *
58  * and at least some of those packet types appear to match what's in
59  * some NBIPX packets.
60  *
61  * Note, however, that it appears that sometimes NBIPX packets have
62  * 8 IPX addresses at the beginning, and sometimes they don't.
63  *
64  * In the section on "NetBIOS Broadcasts", the document at
65  *
66  *      http://www.microsoft.com/technet/network/ipxrout.asp
67  *
68  * says that "the NetBIOS over IPX Broadcast header" contains 8 IPX
69  * network numbers in the "IPX WAN broadcast header", and that it's
70  * followed by a "Name Type Flags" byte (giving information about the
71  * name being registered, deregistered, or checked), a "Data Stream
72  * Type 2" byte giving the type of operation (NBIPX_FIND_NAME,
73  * NBIPX_NAME_RECOGNIZED, or NBIPX_CHECK_NAME - the latter is called
74  * "Add Name"), and a 16-byte NetBIOS name.
75  *
76  * It also says that "NetBIOS over IPX Broadcast packets" have a
77  * packet type of 0x14 (20, or IPX_PACKET_TYPE_WANBCAST) and a
78  * socket number of 0x455 (IPX_SOCKET_NETBIOS).
79  *
80  * However, there are also non-broadcast packets that *also* contain
81  * the 8 IPX network numbers; they appear to be replies to broadcast
82  * packets, and have a packet type of 0x4 (IPX_PACKET_TYPE_PEP).
83  *
84  * Other IPX_PACKET_TYPE_PEP packets to and from the IPX_SOCKET_NETBIOS
85  * socket, however, *don't* have the 8 IPX network numbers; there does
86  * not seem to be any obvious algorithm to determine whether the packet
87  * has the addresses or not.  Microsoft Knowledge Base article Q128335
88  * appears to show some code from the NBIPX implementation in NT that
89  * tries to determine the packet type - and it appears to use heuristics
90  * based on the packet length and on looking at what might be the NBIPX
91  * "Data Stream Type" byte depending on whether the packet has the 8
92  * IPX network numbers or not.
93  *
94  * So, for now, we treat *all* NBIPX packets as having a "Data Stream
95  * Type" byte, preceded by another byte of NBIPX information and
96  * followed by more NBIPX stuff, and assume that it's preceded by
97  * 8 IPX network numbers iff:
98  *
99  *      the packet is a WAN Broadcast packet
100  *
101  * or
102  *
103  *      the packet is the right size for one of those PEP name replies
104  *      (50 bytes) *and* has a name packet type as the Data Stream
105  *      Type byte at the offset where that byte would be if the packet
106  *      does have the 8 IPX network numbers at the beginning.
107  *
108  * The page at
109  *
110  *      http://ourworld.compuserve.com/homepages/TimothyDEvans/encap.htm
111  *
112  * indicates, under "NBIPX session packets", that "NBIPX session packets"
113  * have
114  *
115  *      1 byte of NBIPX connection control flag
116  *      1 byte of data stream type
117  *      2 bytes of source connection ID
118  *      2 bytes of destination connection ID
119  *      2 bytes of send sequence number
120  *      2 bytes of total data length
121  *      2 bytes of offset
122  *      2 bytes of data length
123  *      2 bytes of receive sequence number
124  *      2 bytes of "bytes received"
125  *
126  * followed by data.
127  *
128  * Packets with a data stream type of NBIPX_DIRECTED_DATAGRAM appear to
129  * have, following the data stream type, two NetBIOS names, the first
130  * of which is the receiver's NetBIOS name and the second of which is
131  * the sender's NetBIOS name.  The page at
132  *
133  *      http://support.microsoft.com/support/kb/articles/q203/0/51.asp
134  *
135  * speaks of type 4 (PEP) packets as being used for "SAP, NetBIOS sessions
136  * and directed datagrams" and type 20 (WAN Broadcast) as being used for
137  * "NetBIOS name resolution broadcasts" (but nothing about the non-broadcast
138  * type 4 name resolution stuff).
139  *
140  * We assume that this means that, once you get past the 8 IPX network
141  * numbers if present:
142  *
143  *      the first byte is a name type byte for the name packets
144  *      and a connection control flag for the other packets;
145  *
146  *      the second byte is a data stream type;
147  *
148  *      the rest of the bytes are:
149  *
150  *              the NetBIOS name being registered/deregistered/etc.,
151  *              for name packets;
152  *
153  *              the two NetBIOS names, followed by the NetBIOS
154  *              datagram, for NBIPX_DIRECTED_DATAGRAM packets;
155  *
156  *              the session packet header, possibly followed by
157  *              session data, for session packets.
158  *
159  * We don't know yet how to interpret NBIPX_STATUS_QUERY or
160  * NBIPX_STATUS_RESPONSE.
161  *
162  * For now, we treat the datagrams and session data as SMB stuff.
163  */
164 #define NBIPX_FIND_NAME         1
165 #define NBIPX_NAME_RECOGNIZED   2
166 #define NBIPX_CHECK_NAME        3
167 #define NBIPX_NAME_IN_USE       4
168 #define NBIPX_DEREGISTER_NAME   5
169 #define NBIPX_SESSION_DATA      6
170 #define NBIPX_SESSION_END       7
171 #define NBIPX_SESSION_END_ACK   8
172 #define NBIPX_STATUS_QUERY      9
173 #define NBIPX_STATUS_RESPONSE   10
174 #define NBIPX_DIRECTED_DATAGRAM 11
175
176 static const value_string nbipx_data_stream_type_vals[] = {
177         {NBIPX_FIND_NAME,               "Find name"},
178         {NBIPX_NAME_RECOGNIZED,         "Name recognized"},
179         {NBIPX_CHECK_NAME,              "Check name"},
180         {NBIPX_NAME_IN_USE,             "Name in use"},
181         {NBIPX_DEREGISTER_NAME,         "Deregister name"},
182         {NBIPX_SESSION_DATA,            "Session data"},
183         {NBIPX_SESSION_END,             "Session end"},
184         {NBIPX_SESSION_END_ACK,         "Session end ACK"},
185         {NBIPX_STATUS_QUERY,            "Status query"},
186         {NBIPX_STATUS_RESPONSE,         "Status response"},
187         {NBIPX_DIRECTED_DATAGRAM,       "Directed datagram"},
188         {0,                             NULL}
189 };
190
191 static void
192 add_routers(proto_tree *tree, tvbuff_t *tvb, int offset)
193 {
194         int             i;
195         int             rtr_offset;
196         guint32         router;
197
198         /* Eight routers are listed */
199         for (i = 0; i < 8; i++) {
200                 rtr_offset = offset + (i << 2);
201                 tvb_memcpy(tvb, (guint8 *)&router, rtr_offset, 4);
202                 if (router != 0) {
203                         proto_tree_add_text(tree, tvb, rtr_offset, 4,
204                             "IPX Network: %s",
205                             ipxnet_to_string((guint8*)&router));
206                 }
207         }
208 }
209
210 static void
211 dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
212 {
213         gboolean        has_routes;
214         proto_tree      *nbipx_tree = NULL;
215         proto_item      *ti = NULL;
216         int             offset = 0;
217         guint8          packet_type;
218         guint8          name_type_flag;
219         proto_tree      *name_type_flag_tree;
220         proto_item      *tf;
221         char            name[(NETBIOS_NAME_LEN - 1)*4 + 1];
222         int             name_type;
223         gboolean        has_payload;
224         tvbuff_t        *next_tvb;
225
226         if (check_col(pinfo->cinfo, COL_PROTOCOL))
227                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBIPX");
228         if (check_col(pinfo->cinfo, COL_INFO))
229                 col_clear(pinfo->cinfo, COL_INFO);
230
231         if (pinfo->ipxptype == IPX_PACKET_TYPE_WANBCAST) {
232                 /*
233                  * This is a WAN Broadcast packet; we assume it will have
234                  * 8 IPX addresses at the beginning.
235                  */
236                 has_routes = TRUE;
237         } else {
238                 /*
239                  * This isn't a WAN Broadcast packet, but it still might
240                  * have the 8 addresses.
241                  *
242                  * If it's the right length for a name operation,
243                  * and, if we assume it has routes, the packet type
244                  * is a name operation, assume it has routes.
245                  *
246                  * NOTE: this will throw an exception if the byte that
247                  * would be the packet type byte if this has the 8
248                  * addresses isn't present; if that's the case, we don't
249                  * know how to interpret this packet, so we can't dissect
250                  * it anyway.
251                  */
252                 has_routes = FALSE;     /* start out assuming it doesn't */
253                 if (tvb_reported_length(tvb) == 50) {
254                         packet_type = tvb_get_guint8(tvb, offset + 32 + 1);
255                         switch (packet_type) {
256
257                         case NBIPX_FIND_NAME:
258                         case NBIPX_NAME_RECOGNIZED:
259                         case NBIPX_CHECK_NAME:
260                         case NBIPX_NAME_IN_USE:
261                         case NBIPX_DEREGISTER_NAME:
262                                 has_routes = TRUE;
263                                 break;
264                         }
265                 }
266         }
267
268         if (tree) {
269                 ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0,
270                     -1, FALSE);
271                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
272         }
273
274         if (has_routes) {
275                 if (tree)
276                         add_routers(nbipx_tree, tvb, 0);
277                 offset += 32;
278         }
279
280         packet_type = tvb_get_guint8(tvb, offset + 1);
281
282         switch (packet_type) {
283
284         case NBIPX_FIND_NAME:
285         case NBIPX_NAME_RECOGNIZED:
286         case NBIPX_CHECK_NAME:
287         case NBIPX_NAME_IN_USE:
288         case NBIPX_DEREGISTER_NAME:
289                 name_type_flag = tvb_get_guint8(tvb, offset);
290                 name_type = get_netbios_name(tvb, offset+2, name);
291                 if (check_col(pinfo->cinfo, COL_INFO)) {
292                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>",
293                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
294                                 name, name_type);
295                 }
296                 if (nbipx_tree) {
297                         tf = proto_tree_add_text(nbipx_tree, tvb, offset, 1,
298                                 "Name type flag: 0x%02x", name_type_flag);
299                         name_type_flag_tree = proto_item_add_subtree(tf,
300                                         ett_nbipx_name_type_flags);
301                         proto_tree_add_text(name_type_flag_tree, tvb, offset,
302                             1, "%s",
303                             decode_boolean_bitfield(name_type_flag, 0x80, 8,
304                               "Group name", "Unique name"));
305                         proto_tree_add_text(name_type_flag_tree, tvb, offset,
306                             1, "%s",
307                             decode_boolean_bitfield(name_type_flag, 0x40, 8,
308                               "Name in use", "Name not used"));
309                         proto_tree_add_text(name_type_flag_tree, tvb, offset,
310                             1, "%s",
311                             decode_boolean_bitfield(name_type_flag, 0x04, 8,
312                               "Name registered", "Name not registered"));
313                         proto_tree_add_text(name_type_flag_tree, tvb, offset,
314                             1, "%s",
315                             decode_boolean_bitfield(name_type_flag, 0x02, 8,
316                               "Name duplicated", "Name not duplicated"));
317                         proto_tree_add_text(name_type_flag_tree, tvb, offset,
318                             1, "%s",
319                             decode_boolean_bitfield(name_type_flag, 0x01, 8,
320                               "Name deregistered", "Name not deregistered"));
321                 }
322                 offset += 1;
323
324                 dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
325                 offset += 1;
326
327                 if (nbipx_tree)
328                         netbios_add_name("Name", tvb, offset, nbipx_tree);
329                 offset += NETBIOS_NAME_LEN;
330
331                 /*
332                  * No payload to be interpreted by another protocol.
333                  */
334                 has_payload = FALSE;
335                 break;
336
337         case NBIPX_SESSION_DATA:
338         case NBIPX_SESSION_END:
339         case NBIPX_SESSION_END_ACK:
340                 if (check_col(pinfo->cinfo, COL_INFO)) {
341                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
342                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
343                 }
344                 dissect_conn_control(tvb, offset, nbipx_tree);
345                 offset += 1;
346
347                 dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
348                 offset += 1;
349
350                 if (nbipx_tree) {
351                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
352                             "Source connection ID: 0x%04X",
353                             tvb_get_letohs(tvb, offset));
354                 }
355                 offset += 2;
356
357                 if (nbipx_tree) {
358                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
359                             "Destination connection ID: 0x%04X",
360                             tvb_get_letohs(tvb, offset));
361                 }
362                 offset += 2;
363
364                 if (nbipx_tree) {
365                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
366                             "Send sequence number: %u",
367                             tvb_get_letohs(tvb, offset));
368                 }
369                 offset += 2;
370
371                 if (nbipx_tree) {
372                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
373                             "Total data length: %u",
374                             tvb_get_letohs(tvb, offset));
375                 }
376                 offset += 2;
377
378                 if (nbipx_tree) {
379                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
380                             "Offset: %u",
381                             tvb_get_letohs(tvb, offset));
382                 }
383                 offset += 2;
384
385                 if (nbipx_tree) {
386                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
387                             "Data length: %u",
388                             tvb_get_letohs(tvb, offset));
389                 }
390                 offset += 2;
391
392                 if (nbipx_tree) {
393                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
394                             "Receive sequence number: %u",
395                             tvb_get_letohs(tvb, offset));
396                 }
397                 offset += 2;
398
399                 if (nbipx_tree) {
400                         proto_tree_add_text(nbipx_tree, tvb, offset, 2,
401                             "Bytes received: %u",
402                             tvb_get_letohs(tvb, offset));
403                 }
404                 offset += 2;
405
406                 /*
407                  * We may have payload to dissect.
408                  */
409                 has_payload = TRUE;
410                 break;
411
412         case NBIPX_DIRECTED_DATAGRAM:
413                 if (check_col(pinfo->cinfo, COL_INFO)) {
414                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
415                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
416                 }
417                 dissect_conn_control(tvb, offset, nbipx_tree);
418                 offset += 1;
419
420                 dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
421                 offset += 1;
422
423                 if (nbipx_tree)
424                         netbios_add_name("Receiver's Name", tvb, offset,
425                             nbipx_tree);
426                 offset += NETBIOS_NAME_LEN;
427
428                 if (nbipx_tree)
429                         netbios_add_name("Sender's Name", tvb, offset,
430                             nbipx_tree);
431                 offset += NETBIOS_NAME_LEN;
432
433                 /*
434                  * We may have payload to dissect.
435                  */
436                 has_payload = TRUE;
437                 break;
438
439         default:
440                 if (check_col(pinfo->cinfo, COL_INFO)) {
441                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
442                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
443                 }
444
445                 /*
446                  * We don't know what the first byte is.
447                  */
448                 offset += 1;
449
450                 /*
451                  * The second byte is a data stream type byte.
452                  */
453                 dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
454                 offset += 1;
455
456                 /*
457                  * We don't know what the rest of the packet is.
458                  */
459                 has_payload = FALSE;
460         }
461
462         /*
463          * Set the length of the NBIPX tree item.
464          */
465         if (ti != NULL)
466                 proto_item_set_len(ti, offset);
467
468         if (has_payload && tvb_offset_exists(tvb, offset)) {
469                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
470                 dissect_netbios_payload(next_tvb, pinfo, tree);
471         }
472 }
473
474 static void
475 dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree)
476 {
477         guint8          conn_control;
478         proto_item      *ti;
479         proto_tree      *cc_tree;
480
481         if (tree) {
482                 conn_control = tvb_get_guint8(tvb, offset);
483                 ti = proto_tree_add_text(tree, tvb, offset, 1,
484                     "Connection control: 0x%02x", conn_control);
485                 cc_tree = proto_item_add_subtree(ti, ett_nbipx_conn_ctrl);
486                 proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
487                       decode_boolean_bitfield(conn_control, 0x80, 8,
488                               "System packet", "Non-system packet"));
489                 proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
490                       decode_boolean_bitfield(conn_control, 0x40, 8,
491                               "Acknowledgement required",
492                               "Acknowledgement not required"));
493                 proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
494                       decode_boolean_bitfield(conn_control, 0x20, 8,
495                               "Attention", "No attention"));
496                 proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
497                       decode_boolean_bitfield(conn_control, 0x10, 8,
498                               "End of message", "No end of message"));
499                 proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
500                       decode_boolean_bitfield(conn_control, 0x08, 8,
501                               "Resend", "No resend"));
502         }
503 }
504
505 static void
506 dissect_packet_type(tvbuff_t *tvb, int offset, guint8 packet_type,
507     proto_tree *tree)
508 {
509         if (tree) {
510                 proto_tree_add_text(tree, tvb, offset, 1,
511                                 "Packet Type: %s (%02X)",
512                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
513                                 packet_type);
514         }
515 }
516
517 void
518 proto_register_nbipx(void)
519 {
520 /*        static hf_register_info hf[] = {
521                 { &variable,
522                 { "Name",           "nbipx.abbreviation", TYPE, VALS_POINTER }},
523         };*/
524         static gint *ett[] = {
525                 &ett_nbipx,
526                 &ett_nbipx_conn_ctrl,
527                 &ett_nbipx_name_type_flags,
528         };
529
530         proto_nbipx = proto_register_protocol("NetBIOS over IPX",
531             "NBIPX", "nbipx");
532  /*       proto_register_field_array(proto_nbipx, hf, array_length(hf));*/
533         proto_register_subtree_array(ett, array_length(ett));
534 }
535
536 void
537 proto_reg_handoff_nbipx(void)
538 {
539         dissector_handle_t nbipx_handle;
540
541         nbipx_handle = create_dissector_handle(dissect_nbipx, proto_nbipx);
542         dissector_add("ipx.socket", IPX_SOCKET_NETBIOS, nbipx_handle);
543 }
544
545 /*
546  * Microsoft appear to have something they call "direct hosting", where
547  * SMB - and, I infer, related stuff, such as name resolution - runs
548  * directly over IPX.  (In Windows 2000, they also run SMB directly over
549  * TCP, on port 445, and that also appears to be called "direct hosting".
550  * Ethereal handles SMB-over-TCP.)
551  *
552  * The document at
553  *
554  *      http://support.microsoft.com/support/kb/articles/q203/0/51.asp
555  *
556  * speaks of NMPI - the "Name Management Protocol on IPX" - as being
557  * "Microsoft's protocol for name management support when you use IPX
558  * without the NetBIOS interface," and says that "This process of routing
559  * the SMB protocol directly through IPX is known as Direct Hosting."
560  *
561  * It speaks of IPX socket 0x551 as being for NMPI; we define it as
562  * IPX_SOCKET_NWLINK_SMB_NAMEQUERY.
563  *
564  * We also define IPX_SOCKET_NWLINK_SMB_DGRAM as 0x0553 and define
565  * IPX_SOCKET_NWLINK_SMB_BROWSE as 0x0555 (with a "? not sure on this"
566  * comment after the latter one).
567  *
568  * We have seen at least some browser announcements on IPX socket 0x553;
569  * those are WAN broadcast packets, complete with 8 IPX network
570  * numbers, and with the header containing the usual two NetBIOS names
571  * that show up in NetBIOS datagrams.
572  *
573  * Network Monitor calls those packets NMPI packets, even though they're
574  * on socket 0x553, not socket 0x551, and contain SMB datagrams, not name
575  * resolution packets.
576  *
577  * At least some of this is discussed in the "SMBPUB.DOC" Word document
578  * stored in
579  *
580  *      ftp://ftp.microsoft.com/developr/drg/CIFS/smbpub.zip
581  *
582  * which can also be found in text form at
583  *
584  *      http://www.samba.org/samba/ftp/specs/smbpub.txt
585  *
586  * which says that for "connectionless IPX transport" the sockets that
587  * are used are:
588  *
589  *      SMB_SERVER_SOCKET (0x550) - SMB requests from clients
590  *      SMB_NAME_SOCKET (0x551) - name claims and name query messages
591  *      REDIR_SOCKET (0x552) - used by the redirector (client) for
592  *              sending SMB requests and receiving SMB replies
593  *      MAILSLOT_SOCKET (0x553) - used by the redirector and browser
594  *              for mailslot datagrams
595  *      MESSENGER_SOCKET (0x554) - used by the redirector to send
596  *              messages from client to client          
597  *
598  * Name claim/query packets, and mailslot datagrams, are:
599  *
600  *      8 IPX network addresses
601  *      1 byte of opcode
602  *      1 byte of name type
603  *      2 bytes of message ID
604  *      16 bytes of name being sought or claimed
605  *      16 bytes of requesting machine
606  *
607  * The opcode is one of:
608  *
609  *      INAME_CLAIM (0xf1) - server name claim message
610  *      INAME_DELETE (0xf2) - relinquish server name
611  *      INAME_QUERY (0xf3) - locate server name
612  *      INAME_FOUND (0xf4) - response to INAME_QUERY
613  *      IMSG_HANGUP (0xf5) - messenger hangup
614  *      IMSLOT_SEND (0xfc) - mailslot write
615  *      IMSLOT_FIND (0xfd) - find name for mailslot write
616  *      IMSLOT_NAME (0xfe) - response to IMSLOT_FIND
617  *
618  * The name type is one of:
619  *
620  *      INTYPE_MACHINE  1
621  *      INTYPE_WKGROUP  2
622  *      INTYPE_BROWSER  3
623  */
624 static int proto_nmpi = -1;
625
626 static gint ett_nmpi = -1;
627 static gint ett_nmpi_name_type_flags = -1;
628
629 /*
630  * Opcodes.
631  */
632 #define INAME_CLAIM     0xf1
633 #define INAME_DELETE    0xf2
634 #define INAME_QUERY     0xf3
635 #define INAME_FOUND     0xf4
636 #define IMSG_HANGUP     0xf5
637 #define IMSLOT_SEND     0xfc
638 #define IMSLOT_FIND     0xfd
639 #define IMSLOT_NAME     0xfe
640
641 static const value_string nmpi_opcode_vals[] = {
642         {INAME_CLAIM,   "Claim name"},
643         {INAME_DELETE,  "Delete name"},
644         {INAME_QUERY,   "Query name"},
645         {INAME_FOUND,   "Name found"},
646         {IMSG_HANGUP,   "Messenger hangup"},
647         {IMSLOT_SEND,   "Mailslot write"},
648         {IMSLOT_FIND,   "Find mailslot name"},
649         {IMSLOT_NAME,   "Mailslot name found"},
650         {0,             NULL}
651 };
652
653 /*
654  * Name types.
655  */
656 #define INTYPE_MACHINE          1
657 #define INTYPE_WORKGROUP        2
658 #define INTYPE_BROWSER          3
659
660 static const value_string nmpi_name_type_vals[] = {
661         {INTYPE_MACHINE,        "Machine"},
662         {INTYPE_WORKGROUP,      "Workgroup"},
663         {INTYPE_BROWSER,        "Browser"},
664         {0,                     NULL}
665 };
666
667 static void
668 dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
669 {
670         proto_tree      *nmpi_tree = NULL;
671         proto_item      *ti;
672         int             offset = 0;
673         guint8          opcode;
674         guint8          nmpi_name_type;
675         char            name[(NETBIOS_NAME_LEN - 1)*4 + 1];
676         int             name_type;
677         char            node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
678         int             node_name_type = 0;
679         tvbuff_t        *next_tvb;
680
681         if (check_col(pinfo->cinfo, COL_PROTOCOL))
682                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMPI");
683         if (check_col(pinfo->cinfo, COL_INFO))
684                 col_clear(pinfo->cinfo, COL_INFO);
685
686         if (tree) {
687                 ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68,
688                     FALSE);
689                 nmpi_tree = proto_item_add_subtree(ti, ett_nmpi);
690
691                 add_routers(nmpi_tree, tvb, offset);
692         }
693         offset += 32;
694
695         /*
696          * XXX - we don't use "node_name" or "node_name_type".
697          */
698         opcode = tvb_get_guint8(tvb, offset);
699         nmpi_name_type = tvb_get_guint8(tvb, offset+1);
700         name_type = get_netbios_name(tvb, offset+4, name);
701         node_name_type = get_netbios_name(tvb, offset+20, node_name);
702
703         if (check_col(pinfo->cinfo, COL_INFO)) {
704                 switch (opcode) {
705
706                 case INAME_CLAIM:
707                         col_add_fstr(pinfo->cinfo, COL_INFO, "Claim name %s<%02x>",
708                                         name, name_type);
709                         break;
710
711                 case INAME_DELETE:
712                         col_add_fstr(pinfo->cinfo, COL_INFO, "Delete name %s<%02x>",
713                                         name, name_type);
714                         break;
715
716                 case INAME_QUERY:
717                         col_add_fstr(pinfo->cinfo, COL_INFO, "Query name %s<%02x>",
718                                         name, name_type);
719                         break;
720
721                 case INAME_FOUND:
722                         col_add_fstr(pinfo->cinfo, COL_INFO, "Name %s<%02x> found",
723                                         name, name_type);
724                         break;
725
726                 case IMSG_HANGUP:
727                         col_add_fstr(pinfo->cinfo, COL_INFO,
728                             "Messenger hangup on %s<%02x>", name, name_type);
729                         break;
730
731                 case IMSLOT_SEND:
732                         col_add_fstr(pinfo->cinfo, COL_INFO,
733                             "Mailslot write to %s<%02x>", name, name_type);
734                         break;
735
736                 case IMSLOT_FIND:
737                         col_add_fstr(pinfo->cinfo, COL_INFO,
738                             "Find mailslot name %s<%02x>", name, name_type);
739                         break;
740
741                 case IMSLOT_NAME:
742                         col_add_fstr(pinfo->cinfo, COL_INFO,
743                             "Mailslot name %s<%02x> found", name, name_type);
744                         break;
745
746                 default:
747                         col_add_fstr(pinfo->cinfo, COL_INFO,
748                             "Unknown NMPI op 0x%02x: name %s<%02x>",
749                             opcode, name, name_type);
750                         break;
751                 }
752         }
753
754         if (tree) {
755                 proto_tree_add_text(nmpi_tree, tvb, offset, 1,
756                     "Opcode: %s (0x%02x)",
757                     val_to_str(opcode, nmpi_opcode_vals, "Unknown"),
758                     opcode);
759                 proto_tree_add_text(nmpi_tree, tvb, offset+1, 1,
760                     "Name Type: %s (0x%02x)",
761                     val_to_str(nmpi_name_type, nmpi_name_type_vals, "Unknown"),
762                     nmpi_name_type);
763                 proto_tree_add_text(nmpi_tree, tvb, offset+2, 2,
764                     "Message ID: 0x%04x",
765                     tvb_get_letohs(tvb, offset+2));
766                 netbios_add_name("Requested name", tvb, offset+4, nmpi_tree);
767                 netbios_add_name("Source name", tvb, offset+20, nmpi_tree);
768         }
769
770         offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN;
771
772         if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) {
773                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
774                 dissect_netbios_payload(next_tvb, pinfo, tree);
775         }
776 }
777
778 void
779 proto_register_nmpi(void)
780 {
781 /*        static hf_register_info hf[] = {
782                 { &variable,
783                 { "Name",           "nmpi.abbreviation", TYPE, VALS_POINTER }},
784         };*/
785         static gint *ett[] = {
786                 &ett_nmpi,
787                 &ett_nmpi_name_type_flags,
788         };
789
790         proto_nmpi = proto_register_protocol("Name Management Protocol over IPX",
791             "NMPI", "nmpi");
792  /*       proto_register_field_array(proto_nmpi, hf, array_length(hf));*/
793         proto_register_subtree_array(ett, array_length(ett));
794 }
795
796 void
797 proto_reg_handoff_nmpi(void)
798 {
799         dissector_handle_t nmpi_handle;
800
801         nmpi_handle = create_dissector_handle(dissect_nmpi, proto_nmpi);
802         dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_NAMEQUERY,
803             nmpi_handle);
804         dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_MAILSLOT,
805             nmpi_handle);
806 }