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