2 * Routines for NetBIOS over IPX packet disassembly
3 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * $Id: packet-nbipx.c,v 1.11 1999/09/02 23:17:56 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
37 #include "packet-ipx.h" /* for ipxnet_to_string() */
38 #include "packet-netbios.h"
40 static int proto_nbipx = -1;
48 nbipx_ns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
49 enum nbipx_protocol nbipx, int max_data);
51 dissect_nbipx_dg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
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)
58 * A list of "NovelNetBIOS" packet types can be found at
60 * http://www.protocols.com/pbook/novel.htm#NetBIOS
62 * and at least some of those packet types appear to match what's in
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.
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
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"},
99 #define NWLINK_NAME_QUERY 1
101 #define NWLINK_NETBIOS_DATAGRAM 3
103 static const value_string nwlink_data_stream_type_vals[] = {
104 {NWLINK_NAME_QUERY, "Name query"},
106 {NWLINK_NETBIOS_DATAGRAM, "NetBIOS datagram"},
110 struct nbipx_ns_header {
111 /* Netware & NT NetBIOS over IPX */
118 /* NT NetBIOS over IPX */
127 dissect_nbipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
129 int max_data = pi.captured_len - offset;
132 * As said above, we look at the length of the packet to decide
133 * whether to treat it as a name-service packet or a datagram
134 * (the packet type would tell us, but it's at a *DIFFERENT
135 * LOCATION* in different types of packet...).
137 if (END_OF_FRAME == 50)
138 nbipx_ns(pd, offset, fd, tree, NETBIOS_NETWARE, max_data);
140 dissect_nbipx_dg(pd, offset, fd, tree, max_data);
144 dissect_nwlink_dg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
146 int max_data = pi.captured_len - offset;
148 nbipx_ns(pd, offset, fd, tree, NETBIOS_NWLINK, max_data);
153 nbipx_ns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
154 enum nbipx_protocol nbipx, int max_data)
156 proto_tree *nbipx_tree;
158 struct nbipx_ns_header header;
162 if (nbipx == NETBIOS_NETWARE) {
170 header.name_type = pd[offset+32];
171 header.packet_type = pd[offset+33];
172 memcpy(header.name, &pd[offset+name_offset], 16);
173 header.name[16] = 0; /* null-terminate the string */
175 if (nbipx == NETBIOS_NWLINK) {
176 memcpy(header.node_name, &pd[offset+52], 16);
177 header.node_name[17] = 0; /* null-terminate the string */
180 if (check_col(fd, COL_PROTOCOL)) {
181 if (nbipx == NETBIOS_NETWARE) {
182 col_add_str(fd, COL_PROTOCOL, "NBIPX");
185 col_add_str(fd, COL_PROTOCOL, "NWLink");
189 if (check_col(fd, COL_INFO)) {
190 if (nbipx == NETBIOS_NETWARE) {
191 switch (header.packet_type) {
192 case NBIPX_FIND_NAME:
193 case NBIPX_NAME_RECOGNIZED:
194 case NBIPX_CHECK_NAME:
195 case NBIPX_NAME_IN_USE:
196 case NBIPX_DEREGISTER_NAME:
197 col_add_fstr(fd, COL_INFO, "%s %s",
198 val_to_str(header.packet_type, nbipx_data_stream_type_vals, "Unknown"),
203 col_add_fstr(fd, COL_INFO, "%s",
204 val_to_str(header.packet_type, nbipx_data_stream_type_vals, "Unknown"));
209 switch (header.packet_type) {
210 case NWLINK_NAME_QUERY:
211 col_add_fstr(fd, COL_INFO, "Name Query for %s", header.name);
216 col_add_fstr(fd, COL_INFO, "SMB over NBIPX");
219 case NWLINK_NETBIOS_DATAGRAM:
220 /* Datagram? (Where did we see this?) */
221 col_add_fstr(fd, COL_INFO, "NetBIOS datagram over NBIPX");
225 col_add_str(fd, COL_INFO, "NetBIOS over IPX (NWLink)");
232 ti = proto_tree_add_item(tree, proto_nbipx, offset, 68, NULL);
233 nbipx_tree = proto_item_add_subtree(ti, ETT_NBIPX);
235 if (nbipx == NETBIOS_NETWARE) {
236 proto_tree_add_text(nbipx_tree, offset+33, 1,
237 "Packet Type: %s (%02X)",
238 val_to_str(header.packet_type, nbipx_data_stream_type_vals, "Unknown"),
241 proto_tree_add_text(nbipx_tree, offset+33, 1,
242 "Packet Type: %s (%02X)",
243 val_to_str(header.packet_type, nwlink_data_stream_type_vals, "Unknown"),
247 /* Eight routers are listed */
248 for (i = 0; i < 8; i++) {
249 rtr_offset = offset + (i << 2);
250 memcpy(&header.router[i], &pd[rtr_offset], 4);
251 if (header.router[i] != 0) {
252 proto_tree_add_text(nbipx_tree, rtr_offset, 4, "IPX Network: %s",
253 ipxnet_to_string((guint8*)&header.router[i]));
257 proto_tree_add_text(nbipx_tree, offset+32, 1, "Name Type: %02X",
260 if (nbipx == NETBIOS_NETWARE) {
261 netbios_add_name("Name", &pd[offset], offset,
262 name_offset, nbipx_tree);
265 netbios_add_name("Group name", &pd[offset], offset,
266 name_offset, nbipx_tree);
267 netbios_add_name("Node name", &pd[offset], offset,
272 if (nbipx == NETBIOS_NWLINK) {
273 switch (header.packet_type) {
275 case NWLINK_NETBIOS_DATAGRAM:
276 dissect_smb(pd, offset + 68, fd, tree, max_data - 68);
280 dissect_data(pd, offset + 68, fd, tree);
287 dissect_nbipx_dg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
290 proto_tree *nbipx_tree;
293 if (check_col(fd, COL_PROTOCOL))
294 col_add_str(fd, COL_PROTOCOL, "NetBIOS");
296 if (check_col(fd, COL_INFO))
297 col_add_fstr(fd, COL_INFO, "NetBIOS datagram over NBIPX");
300 ti = proto_tree_add_item(tree, proto_nbipx, offset, 68, NULL);
301 nbipx_tree = proto_item_add_subtree(ti, ETT_NBIPX);
303 proto_tree_add_text(nbipx_tree, offset+1, 1,
304 "Packet Type: %s (%02X)",
305 val_to_str(pd[offset+1], nbipx_data_stream_type_vals, "Unknown"),
307 proto_tree_add_text(nbipx_tree, offset, 1,
308 "Connection control: 0x%02x", pd[offset]);
309 netbios_add_name("Receiver's Name", &pd[offset],
310 offset, 2, nbipx_tree);
311 netbios_add_name("Sender's Name", &pd[offset],
312 offset, 2+16, nbipx_tree);
314 dissect_smb(pd, offset+2+16+16, fd, tree, max_data - 2+16+16);
319 proto_register_nbipx(void)
321 /* static hf_register_info hf[] = {
323 { "Name", "nbipx.abbreviation", TYPE, VALS_POINTER }},
326 proto_nbipx = proto_register_protocol("NetBIOS over IPX", "nbipx");
327 /* proto_register_field_array(proto_nbipx, hf, array_length(hf));*/