Fix "packet-netbios.h" to match the new "packet-netbios.c", so that it
[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.24 2000/11/10 21:09:49 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"
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(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
53
54 static void
55 dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
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(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
116 {
117         CHECK_DISPLAY_AS_DATA(proto_nbipx, tvb, pinfo, tree);
118
119         if (check_col(pinfo->fd, COL_PROTOCOL))
120                 col_add_str(pinfo->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 (tvb_reported_length(tvb) == 50)
129                 dissect_nbipx_ns(tvb, pinfo, tree);
130         else
131                 dissect_nbipx_dg(tvb, pinfo, tree);
132 }
133
134 static void
135 add_routers(proto_tree *tree, tvbuff_t *tvb, 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                 tvb_memcpy(tvb, (guint8 *)&router, rtr_offset, 4);
145                 if (router != 0) {
146                         proto_tree_add_text(tree, tvb, rtr_offset, 4,
147                             "IPX Network: %s",
148                             ipxnet_to_string((guint8*)&router));
149                 }
150         }
151 }
152
153 static void
154 dissect_nbipx_ns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
155 {
156         proto_tree              *nbipx_tree;
157         proto_item              *ti;
158         int                     offset = 0;
159         guint8                  packet_type;
160         guint8                  name_type_flag;
161         proto_tree              *name_type_flag_tree;
162         proto_item              *tf;
163         char                    name[(NETBIOS_NAME_LEN - 1)*4 + 1];
164         int                     name_type;
165
166         name_type_flag = tvb_get_guint8(tvb, offset+32);
167         packet_type = tvb_get_guint8(tvb, offset+33);
168         name_type = get_netbios_name(tvb, offset+34, name);
169
170         if (check_col(pinfo->fd, COL_INFO)) {
171                 switch (packet_type) {
172                 case NBIPX_FIND_NAME:
173                 case NBIPX_NAME_RECOGNIZED:
174                 case NBIPX_CHECK_NAME:
175                 case NBIPX_NAME_IN_USE:
176                 case NBIPX_DEREGISTER_NAME:
177                         col_add_fstr(pinfo->fd, COL_INFO, "%s %s<%02x>",
178                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
179                                 name, name_type);
180                         break;
181
182                 default:
183                         col_add_fstr(pinfo->fd, COL_INFO, "%s",
184                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
185                         break;
186                 }
187         }
188
189         if (tree) {
190                 ti = proto_tree_add_item(tree, proto_nbipx, tvb, offset, 50,
191                     FALSE);
192                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
193
194                 add_routers(nbipx_tree, tvb, offset);
195
196                 tf = proto_tree_add_text(nbipx_tree, tvb, offset+32, 1,
197                         "Name type flag: 0x%02x", name_type_flag);
198                 name_type_flag_tree = proto_item_add_subtree(tf,
199                                 ett_nbipx_name_type_flags);
200                 proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
201                     1, "%s",
202                     decode_boolean_bitfield(name_type_flag, 0x80, 8,
203                       "Group name", "Unique name"));
204                 proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
205                     1, "%s",
206                     decode_boolean_bitfield(name_type_flag, 0x40, 8,
207                       "Name in use", "Name not used"));
208                 proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
209                     1, "%s",
210                     decode_boolean_bitfield(name_type_flag, 0x04, 8,
211                       "Name registered", "Name not registered"));
212                 proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
213                     1, "%s",
214                     decode_boolean_bitfield(name_type_flag, 0x02, 8,
215                       "Name duplicated", "Name not duplicated"));
216                 proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
217                     1, "%s",
218                     decode_boolean_bitfield(name_type_flag, 0x01, 8,
219                       "Name deregistered", "Name not deregistered"));
220
221                 proto_tree_add_text(nbipx_tree, tvb, offset+33, 1,
222                         "Packet Type: %s (%02X)",
223                         val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
224                         packet_type);
225
226                 netbios_add_name("Name", tvb, offset + 34, nbipx_tree);
227         }
228 }
229
230 static void
231 dissect_nbipx_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
232 {
233         proto_tree                      *nbipx_tree;
234         proto_item                      *ti;
235         int                             offset = 0;
236         guint8                          packet_type;
237         tvbuff_t                        *next_tvb;
238         const guint8                    *next_pd;
239         int                             next_offset;
240
241         if (check_col(pinfo->fd, COL_INFO))
242                 col_add_fstr(pinfo->fd, COL_INFO, "NetBIOS datagram over NBIPX");
243
244         if (tree) {
245                 ti = proto_tree_add_item(tree, proto_nbipx, tvb, offset,
246                     2+NETBIOS_NAME_LEN+NETBIOS_NAME_LEN, FALSE);
247                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
248
249                 proto_tree_add_text(nbipx_tree, tvb, offset, 1,
250                     "Connection control: 0x%02x", tvb_get_guint8(tvb, offset));
251                 offset += 1;
252
253                 packet_type = tvb_get_guint8(tvb, offset);
254                 proto_tree_add_text(nbipx_tree, tvb, offset, 1,
255                                 "Packet Type: %s (%02X)",
256                                 val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
257                                 packet_type);
258                 offset += 1;
259
260                 if (!netbios_add_name("Receiver's Name", tvb, offset,
261                     nbipx_tree))
262                         return;
263                 offset += NETBIOS_NAME_LEN;
264
265                 if (!netbios_add_name("Sender's Name", tvb, offset,
266                     nbipx_tree))
267                         return;
268                 offset += NETBIOS_NAME_LEN;
269
270                 if (tvb_length_remaining(tvb, offset) != 0) {
271                         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
272                         tvb_compat(next_tvb, &next_pd, &next_offset);
273                         dissect_smb(next_pd, next_offset, pinfo->fd, tree,
274                             tvb_length(next_tvb));
275                 }
276         }
277 }
278
279 static void
280 dissect_nwlink_dg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
281 {
282         proto_tree      *nbipx_tree;
283         proto_item      *ti;
284         int             offset = 0;
285         guint8          packet_type;
286         guint8          name_type_flag;
287         proto_tree      *name_type_flag_tree;
288         proto_item      *tf;
289         char            name[(NETBIOS_NAME_LEN - 1)*4 + 1];
290         int             name_type;
291         char            node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
292         int             node_name_type = 0;
293         tvbuff_t        *next_tvb;
294         const guint8    *next_pd;
295         int             next_offset;
296
297         name_type_flag = tvb_get_guint8(tvb, offset+32);
298         packet_type = tvb_get_guint8(tvb, offset+33);
299         name_type = get_netbios_name(tvb, offset+36, name);
300         node_name_type = get_netbios_name(tvb, offset+52, node_name);
301
302         if (check_col(pinfo->fd, COL_PROTOCOL))
303                 col_add_str(pinfo->fd, COL_PROTOCOL, "NWLink");
304
305         if (check_col(pinfo->fd, COL_INFO)) {
306                 /*
307                  * XXX - Microsoft Network Monitor thinks that the octet
308                  * at 32 is a packet type, e.g. "mailslot write" for
309                  * browser announcements, and that the octet at 33 is a
310                  * name type, in the sense of the 16th byte of a
311                  * NetBIOS name.
312                  *
313                  * A name type of 2 shows up in a "host announcement",
314                  * and a name type of 3 shows up in a "local master
315                  * annoumcement", so maybe that field really *is* a
316                  * name type - the fact that it's not associated with
317                  * any of the NetBIOS names in the packet nonwithstanding.
318                  *
319                  * I haven't seen any packets with the name type octet
320                  * being anything other than 2 or 3, so I don't know
321                  * whether those are name service operations; however,
322                  * given that NWLink, unlike socket-0x0455 NBIPX,
323                  * has separate sockets for name queries and datagrams,
324                  * it may be that this really is a name type, and that
325                  * these are all datagrams, not name queries.
326                  */
327                 switch (packet_type) {
328                 case NWLINK_NAME_QUERY:
329                         col_add_fstr(pinfo->fd, COL_INFO, "Name Query for %s<%02x>",
330                                         name, name_type);
331                         break;
332
333                 case NWLINK_SMB:
334                         /* Session? */
335                         col_add_fstr(pinfo->fd, COL_INFO, "SMB over NBIPX");
336                         break;
337
338                 case NWLINK_NETBIOS_DATAGRAM:
339                         /* Datagram? (Where did we see this?) */
340                         col_add_fstr(pinfo->fd, COL_INFO, "NetBIOS datagram over NBIPX");
341                         break;
342                                 
343                 default:
344                         col_add_str(pinfo->fd, COL_INFO, "NetBIOS over IPX (NWLink)");
345                         break;
346                 }
347         }
348
349         if (tree) {
350                 ti = proto_tree_add_item(tree, proto_nbipx, tvb, offset, 68, FALSE);
351                 nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
352
353                 add_routers(nbipx_tree, tvb, offset);
354
355                 /*
356                  * XXX - is "packet_type" really a packet type?  See
357                  * above.
358                  */
359                 if (packet_type != NWLINK_SMB &&
360                       packet_type != NWLINK_NETBIOS_DATAGRAM) {
361                         tf = proto_tree_add_text(nbipx_tree, tvb, offset+32, 1,
362                                 "Name type flag: 0x%02x",
363                                 name_type_flag);
364                         name_type_flag_tree = proto_item_add_subtree(tf,
365                                         ett_nbipx_name_type_flags);
366                         proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
367                             1, "%s",
368                             decode_boolean_bitfield(name_type_flag, 0x80, 8,
369                               "Group name", "Unique name"));
370                         proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
371                             1, "%s",
372                             decode_boolean_bitfield(name_type_flag, 0x40, 8,
373                               "Name in use", "Name not used"));
374                         proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
375                             1, "%s",
376                             decode_boolean_bitfield(name_type_flag, 0x04, 8,
377                               "Name registered", "Name not registered"));
378                         proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
379                             1, "%s",
380                             decode_boolean_bitfield(name_type_flag, 0x02, 8,
381                               "Name duplicated", "Name not duplicated"));
382                         proto_tree_add_text(name_type_flag_tree, tvb, offset+32,
383                             1, "%s",
384                             decode_boolean_bitfield(name_type_flag, 0x01, 8,
385                               "Name deregistered", "Name not deregistered"));
386
387                         if (!netbios_add_name("Group name", tvb, offset+36,
388                             nbipx_tree))
389                                 return;
390                         if (!netbios_add_name("Node name", tvb, offset+52,
391                             nbipx_tree))
392                                 return;
393                         proto_tree_add_text(nbipx_tree, tvb, offset+33, 1,
394                             "Packet Type: %s (%02X)",
395                             val_to_str(packet_type, nwlink_data_stream_type_vals, "Unknown"),
396                             packet_type);
397                 } else {
398                         proto_tree_add_text(nbipx_tree, tvb, offset+32, 1,
399                             "Packet type: 0x%02x", name_type_flag);
400                         proto_tree_add_text(nbipx_tree, tvb, offset+33, 1,
401                             "Name Type: %s (0x%02x)",
402                             netbios_name_type_descr(packet_type),
403                             packet_type);
404                         proto_tree_add_text(nbipx_tree, tvb, offset+34, 2,
405                             "Message ID: 0x%04x",
406                             tvb_get_letohs(tvb, offset+34));
407                         if (!netbios_add_name("Requested name", tvb, offset+36,
408                             nbipx_tree))
409                                 return;
410                         if (!netbios_add_name("Source name", tvb, offset+52,
411                             nbipx_tree))
412                                 return;
413                 }
414         }
415
416         offset += 68;
417
418         if (tvb_length_remaining(tvb, offset) != 0) {
419                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
420
421                 switch (packet_type) {
422                 case NWLINK_SMB:
423                 case NWLINK_NETBIOS_DATAGRAM:
424                         tvb_compat(next_tvb, &next_pd, &next_offset);
425                         dissect_smb(next_pd, next_offset, pinfo->fd, tree,
426                             tvb_length(next_tvb));
427                         break;
428                                 
429                 default:
430                         dissect_data(next_tvb, pinfo, tree);
431                         break;
432                 }
433         }
434 }
435
436 void
437 proto_register_nbipx(void)
438 {
439 /*        static hf_register_info hf[] = {
440                 { &variable,
441                 { "Name",           "nbipx.abbreviation", TYPE, VALS_POINTER }},
442         };*/
443         static gint *ett[] = {
444                 &ett_nbipx,
445                 &ett_nbipx_name_type_flags,
446         };
447
448         proto_nbipx = proto_register_protocol("NetBIOS over IPX", "nbipx");
449  /*       proto_register_field_array(proto_nbipx, hf, array_length(hf));*/
450         proto_register_subtree_array(ett, array_length(ett));
451 }
452
453 void
454 proto_reg_handoff_nbipx(void)
455 {
456         dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_DGRAM, dissect_nwlink_dg);
457 }