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