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