8bb437cddaca6bbca570eeae00fb9f3b271d2516
[obnox/wireshark/wip.git] / packet-nbipx.c
1 /* packet-nbipx.c
2  * Routines for NetBIOS over IPX packet disassembly
3  * Gilbert Ramirez <gram@xiexie.org>
4  *
5  * $Id: packet-nbipx.c,v 1.23 2000/08/13 14:08:30 deniel Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <glib.h>
36 #include "packet.h"
37 #include "packet-ipx.h"
38 #include "packet-netbios.h"
39 #include "packet-smb.h"
40
41 static int proto_nbipx = -1;
42
43 static gint ett_nbipx = -1;
44 static gint ett_nbipx_name_type_flags = -1;
45
46 enum nbipx_protocol {
47         NETBIOS_NETWARE,
48         NETBIOS_NWLINK
49 };
50
51 static void
52 dissect_nbipx_ns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
53                 int max_data);
54 static void
55 dissect_nbipx_dg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
56                 int max_data);
57
58 /* There is no RFC or public specification of Netware or Microsoft
59  * NetBIOS over IPX packets. I have had to decode the protocol myself,
60  * so there are holes and perhaps errors in this code. (gram)
61  *
62  * A list of "NovelNetBIOS" packet types can be found at
63  *
64  *      http://www.protocols.com/pbook/novel.htm#NetBIOS
65  *
66  * and at least some of those packet types appear to match what's in
67  * some NBIPX packets.
68  *
69  * Note, however, that the offset of the packet type in an NBIPX packet
70  * *DEPENDS ON THE PACKET TYPE*; "Find name" and "Name recognized" have
71  * it at one offset, "Directed datagram" has it at another.  Does the
72  * NBIPX code base it on the length, or what?  Non-broadcast directed
73  * datagram packets have an IPX type of "IPX", just as "Find name" and
74  * "Name recognized" do....  For now, we base it on the length.
75  */
76 #define NBIPX_FIND_NAME         1
77 #define NBIPX_NAME_RECOGNIZED   2
78 #define NBIPX_CHECK_NAME        3
79 #define NBIPX_NAME_IN_USE       4
80 #define NBIPX_DEREGISTER_NAME   5
81 #define NBIPX_SESSION_DATA      6
82 #define NBIPX_SESSION_END       7
83 #define NBIPX_SESSION_END_ACK   8
84 #define NBIPX_STATUS_QUERY      9
85 #define NBIPX_STATUS_RESPONSE   10
86 #define NBIPX_DIRECTED_DATAGRAM 11
87
88 static const value_string nbipx_data_stream_type_vals[] = {
89         {NBIPX_FIND_NAME,               "Find name"},
90         {NBIPX_NAME_RECOGNIZED,         "Name recognized"},
91         {NBIPX_CHECK_NAME,              "Check name"},
92         {NBIPX_NAME_IN_USE,             "Name in use"},
93         {NBIPX_DEREGISTER_NAME,         "Deregister name"},
94         {NBIPX_SESSION_DATA,            "Session data"},
95         {NBIPX_SESSION_END,             "Session end"},
96         {NBIPX_SESSION_END_ACK,         "Session end ACK"},
97         {NBIPX_STATUS_QUERY,            "Status query"},
98         {NBIPX_STATUS_RESPONSE,         "Status response"},
99         {NBIPX_DIRECTED_DATAGRAM,       "Directed datagram"},
100         {0,                             NULL}
101 };
102
103 #define NWLINK_NAME_QUERY       1
104 #define NWLINK_SMB              2
105 #define NWLINK_NETBIOS_DATAGRAM 3
106
107 static const value_string nwlink_data_stream_type_vals[] = {
108         {NWLINK_NAME_QUERY,             "Name query"},
109         {NWLINK_SMB,                    "SMB"},
110         {NWLINK_NETBIOS_DATAGRAM,       "NetBIOS datagram"},
111         {0,                             NULL}
112 };
113
114 /* NetWare */
115 void
116 dissect_nbipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
117 {
118         int     max_data = pi.captured_len - offset;
119
120         OLD_CHECK_DISPLAY_AS_DATA(proto_nbipx, pd, offset, fd, tree);
121
122         if (check_col(fd, COL_PROTOCOL))
123                 col_add_str(fd, COL_PROTOCOL, "NBIPX");
124
125         /*
126          * As said above, we look at the length of the packet to decide
127          * whether to treat it as a name-service packet or a datagram
128          * (the packet type would tell us, but it's at a *DIFFERENT
129          * LOCATION* in different types of packet...).
130          */
131         if (END_OF_FRAME == 50)
132                 dissect_nbipx_ns(pd, offset, fd, tree, max_data);
133         else
134                 dissect_nbipx_dg(pd, offset, fd, tree, max_data);
135 }
136
137 static void
138 add_routers(proto_tree *tree, const u_char *pd, int offset)
139 {
140         int             i;
141         int             rtr_offset;
142         guint32         router;
143
144         /* Eight routers are listed */
145         for (i = 0; i < 8; i++) {
146                 rtr_offset = offset + (i << 2);
147                 memcpy(&router, &pd[rtr_offset], 4);
148                 if (router != 0) {
149                         proto_tree_add_text(tree, NullTVB, rtr_offset, 4, "IPX Network: %s",
150                                         ipxnet_to_string((guint8*)&router));
151                 }
152         }
153 }
154
155 static void
156 dissect_nbipx_ns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
157                 int max_data)
158 {
159         proto_tree              *nbipx_tree;
160         proto_item              *ti;
161         guint8                  packet_type;
162         guint8                  name_type_flag;
163         proto_tree              *name_type_flag_tree;
164         proto_item              *tf;
165         char                    name[(NETBIOS_NAME_LEN - 1)*4 + 1];
166         int                     name_type;
167
168         name_type_flag = pd[offset+32];
169         packet_type = pd[offset+33];
170         name_type = get_netbios_name(pd, offset+34, name);
171
172         if (check_col(fd, COL_INFO)) {
173                 switch (packet_type) {
174                 case NBIPX_FIND_NAME:
175                 case NBIPX_NAME_RECOGNIZED:
176                 case NBIPX_CHECK_NAME:
177                 case NBIPX_NAME_IN_USE:
178                 case NBIPX_DEREGISTER_NAME:
179                         col_add_fstr(fd, COL_INFO, "%s %s<%02x>",
180                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
181                                 name, name_type);
182                         break;
183
184                 default:
185                         col_add_fstr(fd, COL_INFO, "%s",
186                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
187                         break;
188                 }
189         }
190
191         if (tree) {
192                 ti = proto_tree_add_item(tree, proto_nbipx, NullTVB, offset, 50, FALSE);
193                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
194
195                 add_routers(nbipx_tree, pd, offset);
196
197                 tf = proto_tree_add_text(nbipx_tree, NullTVB, offset+32, 1,
198                         "Name type flag: 0x%02x", name_type_flag);
199                 name_type_flag_tree = proto_item_add_subtree(tf,
200                                 ett_nbipx_name_type_flags);
201                 proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
202                     1, "%s",
203                     decode_boolean_bitfield(name_type_flag, 0x80, 8,
204                       "Group name", "Unique name"));
205                 proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
206                     1, "%s",
207                     decode_boolean_bitfield(name_type_flag, 0x40, 8,
208                       "Name in use", "Name not used"));
209                 proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
210                     1, "%s",
211                     decode_boolean_bitfield(name_type_flag, 0x04, 8,
212                       "Name registered", "Name not registered"));
213                 proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
214                     1, "%s",
215                     decode_boolean_bitfield(name_type_flag, 0x02, 8,
216                       "Name duplicated", "Name not duplicated"));
217                 proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
218                     1, "%s",
219                     decode_boolean_bitfield(name_type_flag, 0x01, 8,
220                       "Name deregistered", "Name not deregistered"));
221
222                 proto_tree_add_text(nbipx_tree, NullTVB, offset+33, 1,
223                         "Packet Type: %s (%02X)",
224                         val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
225                         packet_type);
226
227                 netbios_add_name("Name", pd, offset + 34,
228                                 nbipx_tree);
229         }
230 }
231
232 static void
233 dissect_nbipx_dg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
234                 int max_data)
235 {
236         proto_tree                      *nbipx_tree;
237         proto_item                      *ti;
238
239         if (check_col(fd, COL_INFO))
240                 col_add_fstr(fd, COL_INFO, "NetBIOS datagram over NBIPX");
241
242         if (tree) {
243                 ti = proto_tree_add_item(tree, proto_nbipx, NullTVB, offset,
244                     2+NETBIOS_NAME_LEN+NETBIOS_NAME_LEN, FALSE);
245                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
246
247                 proto_tree_add_text(nbipx_tree, NullTVB, offset, 1,
248                     "Connection control: 0x%02x", pd[offset]);
249                 offset += 1;
250                 max_data -= 1;
251
252                 if (!BYTES_ARE_IN_FRAME(offset, 1))
253                         return;
254                 proto_tree_add_text(nbipx_tree, NullTVB, offset, 1,
255                                 "Packet Type: %s (%02X)",
256                                 val_to_str(pd[offset], nbipx_data_stream_type_vals, "Unknown"),
257                                 pd[offset]);
258                 offset += 1;
259                 max_data -= 1;
260
261                 if (!netbios_add_name("Receiver's Name", pd, offset,
262                     nbipx_tree))
263                         return;
264                 offset += NETBIOS_NAME_LEN;
265                 max_data -= NETBIOS_NAME_LEN;
266
267                 if (!netbios_add_name("Sender's Name", pd, offset,
268                     nbipx_tree))
269                         return;
270                 offset += NETBIOS_NAME_LEN;
271                 max_data -= NETBIOS_NAME_LEN;
272
273                 if (max_data != 0)
274                         dissect_smb(pd, offset, fd, tree, max_data);
275         }
276 }
277
278 static void
279 dissect_nwlink_dg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
280 {
281         int             max_data = pi.captured_len - offset;
282         proto_tree      *nbipx_tree;
283         proto_item      *ti;
284         guint8          packet_type;
285         guint8          name_type_flag;
286         proto_tree      *name_type_flag_tree;
287         proto_item      *tf;
288         char            name[(NETBIOS_NAME_LEN - 1)*4 + 1];
289         int             name_type;
290         char            node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
291         int             node_name_type = 0;
292
293         name_type_flag = pd[offset+32];
294         packet_type = pd[offset+33];
295         name_type = get_netbios_name(pd, offset+36, name);
296         node_name_type = get_netbios_name(pd, offset+52, node_name);
297
298         if (check_col(fd, COL_PROTOCOL))
299                 col_add_str(fd, COL_PROTOCOL, "NWLink");
300
301         if (check_col(fd, COL_INFO)) {
302                 /*
303                  * XXX - Microsoft Network Monitor thinks that the octet
304                  * at 32 is a packet type, e.g. "mailslot write" for
305                  * browser announcements, and that the octet at 33 is a
306                  * name type, in the sense of the 16th byte of a
307                  * NetBIOS name.
308                  *
309                  * A name type of 2 shows up in a "host announcement",
310                  * and a name type of 3 shows up in a "local master
311                  * annoumcement", so maybe that field really *is* a
312                  * name type - the fact that it's not associated with
313                  * any of the NetBIOS names in the packet nonwithstanding.
314                  *
315                  * I haven't seen any packets with the name type octet
316                  * being anything other than 2 or 3, so I don't know
317                  * whether those are name service operations; however,
318                  * given that NWLink, unlike socket-0x0455 NBIPX,
319                  * has separate sockets for name queries and datagrams,
320                  * it may be that this really is a name type, and that
321                  * these are all datagrams, not name queries.
322                  */
323                 switch (packet_type) {
324                 case NWLINK_NAME_QUERY:
325                         col_add_fstr(fd, COL_INFO, "Name Query for %s<%02x>",
326                                         name, name_type);
327                         break;
328
329                 case NWLINK_SMB:
330                         /* Session? */
331                         col_add_fstr(fd, COL_INFO, "SMB over NBIPX");
332                         break;
333
334                 case NWLINK_NETBIOS_DATAGRAM:
335                         /* Datagram? (Where did we see this?) */
336                         col_add_fstr(fd, COL_INFO, "NetBIOS datagram over NBIPX");
337                         break;
338                                 
339                 default:
340                         col_add_str(fd, COL_INFO, "NetBIOS over IPX (NWLink)");
341                         break;
342                 }
343         }
344
345         if (tree) {
346                 ti = proto_tree_add_item(tree, proto_nbipx, NullTVB, offset, 68, FALSE);
347                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
348
349                 add_routers(nbipx_tree, pd, offset);
350
351                 /*
352                  * XXX - is "packet_type" really a packet type?  See
353                  * above.
354                  */
355                 if (packet_type != NWLINK_SMB &&
356                       packet_type != NWLINK_NETBIOS_DATAGRAM) {
357                         tf = proto_tree_add_text(nbipx_tree, NullTVB, offset+32, 1,
358                                 "Name type flag: 0x%02x",
359                                 name_type_flag);
360                         name_type_flag_tree = proto_item_add_subtree(tf,
361                                         ett_nbipx_name_type_flags);
362                         proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
363                             1, "%s",
364                             decode_boolean_bitfield(name_type_flag, 0x80, 8,
365                               "Group name", "Unique name"));
366                         proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
367                             1, "%s",
368                             decode_boolean_bitfield(name_type_flag, 0x40, 8,
369                               "Name in use", "Name not used"));
370                         proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
371                             1, "%s",
372                             decode_boolean_bitfield(name_type_flag, 0x04, 8,
373                               "Name registered", "Name not registered"));
374                         proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
375                             1, "%s",
376                             decode_boolean_bitfield(name_type_flag, 0x02, 8,
377                               "Name duplicated", "Name not duplicated"));
378                         proto_tree_add_text(name_type_flag_tree, NullTVB, offset+32,
379                             1, "%s",
380                             decode_boolean_bitfield(name_type_flag, 0x01, 8,
381                               "Name deregistered", "Name not deregistered"));
382
383                         if (!netbios_add_name("Group name", pd, offset+36,
384                             nbipx_tree))
385                                 return;
386                         if (!netbios_add_name("Node name", pd, offset+52,
387                             nbipx_tree))
388                                 return;
389                         proto_tree_add_text(nbipx_tree, NullTVB, offset+33, 1,
390                             "Packet Type: %s (%02X)",
391                             val_to_str(packet_type, nwlink_data_stream_type_vals, "Unknown"),
392                             packet_type);
393                 } else {
394                         proto_tree_add_text(nbipx_tree, NullTVB, offset+32, 1,
395                             "Packet type: 0x%02x", name_type_flag);
396                         proto_tree_add_text(nbipx_tree, NullTVB, offset+33, 1,
397                             "Name Type: %s (0x%02x)",
398                             netbios_name_type_descr(packet_type),
399                             packet_type);
400                         proto_tree_add_text(nbipx_tree, NullTVB, offset+34, 2,
401                             "Message ID: 0x%04x", pletohs(&pd[offset+34]));
402                         if (!netbios_add_name("Requested name", pd, offset+36,
403                             nbipx_tree))
404                                 return;
405                         if (!netbios_add_name("Source name", pd, offset+52,
406                             nbipx_tree))
407                                 return;
408                 }
409         }
410
411         offset += 68;
412         max_data -= 68;
413
414         if (max_data != 0) {
415                 switch (packet_type) {
416                 case NWLINK_SMB:
417                 case NWLINK_NETBIOS_DATAGRAM:
418                         dissect_smb(pd, offset, fd, tree, max_data);
419                         break;
420                                 
421                 default:
422                         old_dissect_data(pd, offset, fd, tree);
423                         break;
424                 }
425         }
426 }
427
428 void
429 proto_register_nbipx(void)
430 {
431 /*        static hf_register_info hf[] = {
432                 { &variable,
433                 { "Name",           "nbipx.abbreviation", TYPE, VALS_POINTER }},
434         };*/
435         static gint *ett[] = {
436                 &ett_nbipx,
437                 &ett_nbipx_name_type_flags,
438         };
439
440         proto_nbipx = proto_register_protocol("NetBIOS over IPX", "nbipx");
441  /*       proto_register_field_array(proto_nbipx, hf, array_length(hf));*/
442         proto_register_subtree_array(ett, array_length(ett));
443 }
444
445 void
446 proto_reg_handoff_nbipx(void)
447 {
448         old_dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_DGRAM, dissect_nwlink_dg);
449 }