2 * Routines for NetWare Core Protocol
3 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * $Id: packet-ncp.c,v 1.4 1998/10/22 04:50:21 gram Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
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.
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
46 #include "packet-ipx.h"
47 #include "packet-ncp.h"
49 /* The information in this module comes from:
50 NetWare LAN Analysis, Second Edition
51 Laura A. Chappell and Dan E. Hakes
53 Novell Press, San Jose.
56 And from the ncpfs source code by Volker Lendecke
61 static value_string request_reply_values[] = {
62 { 0x1111, "Create a service connection" },
63 { 0x2222, "Service request" },
64 { 0x3333, "Service reply" },
65 { 0x5555, "Destroy service connection" },
66 { 0x7777, "Burst mode transfer" },
67 { 0x9999, "Request being processed" },
72 static value_string ncp2222_func[] = {
73 { 17, "Print and Queue Services" },
74 { 21, "Message Services" },
75 { 22, "File and Directory Services" },
76 { 23, "Binding and Rights Services" },
77 { 34, "Transaction Tacking Services" },
78 { 35, "Apple File Services" },
79 { 72, "File Services" }, /* guess */
80 { 86, "Extended Attributes Services" },
81 { 87, "File and Directory Services" },
82 { 88, "Auditing Services" },
83 { 104, "Netware Directory Services" },
84 { 123, "Netware 4.x Statistical Information Services" },
89 ncp2222_subfunc(u_short func, u_short subfunc) {
91 value_string *info_ptr = NULL;
93 /* Accounting Services */
94 static value_string ncp_23[] = {
95 { 150, "Get Current Account Status" },
96 { 151, "Submit Account Charge" },
97 { 152, "Submit Account Hold" },
98 { 153, "Submit Account Note" },
102 /* Apple File Services */
103 static value_string ncp_35[] = {
104 { 1, "AFP Create Directory" },
105 { 2, "AFP Create File" },
107 { 4, "AFP Get Entry ID from Name" },
108 { 5, "AFP Get File Information" },
109 { 6, "AFP Get Entry ID From NetWare Handle" },
111 { 8, "AFP Open File Fork" },
112 { 9, "AFP Set File Information" },
113 { 10, "AFP Scan File Information" },
114 { 11, "AFP 2.0 Alloc Temporary Directory Handle" },
115 { 12, "AFP Get Entry ID from Name Path" },
116 { 13, "AFP 2.0 Create Directory" },
117 { 14, "AFP 2.0 Create File" },
118 /* ??? { 15, "AFP 2.0 Delete File" }, just guessing */
119 { 16, "AFP 2.0 Set File Information" },
120 { 17, "AFP 2.0 Scan File Information" },
121 { 18, "AFP Get DOS Name from Entry ID" },
122 { 19, "AFP Get Macintosh Info on Deleted File" },
126 /* File services */ /* guess */
127 static value_string ncp_72[] = {
132 /* Auditing Services */
133 static value_string ncp_88[] = {
134 { 1, "Query Volume Audit Status" },
135 { 2, "Add Audit Property" },
136 { 3, "Add Auditor Access" },
155 return "Unknown function";
158 return val_to_str(subfunc, info_ptr, "Unknown");
163 ncp_read(GtkWidget *tree, const u_char *pd, int offset)
165 struct ncp_read_header header;
167 memcpy(header.handle, &pd[offset], 6);
168 header.offset = pntohl(&pd[offset+6]);
169 header.bytes = pntohs(&pd[offset+10]);
171 add_item_to_tree(tree, offset, 6,
172 "File Handle: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X ",
173 header.handle[0], header.handle[1], header.handle[2],
174 header.handle[3], header.handle[4], header.handle[5]);
176 add_item_to_tree(tree, offset+6, 4,
177 "Starting Offset: %d", header.offset);
179 add_item_to_tree(tree, offset+10, 2,
180 "Bytes to Read: %d", header.bytes);
185 dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
187 GtkWidget *ncp_tree, *ti;
190 struct ncp_common_header header;
191 struct ncp_request_header request;
192 struct ncp_reply_header reply;
193 char *ncp_type_text[] = { "Unknown",
194 "Request", "Reply" };
196 ncp_type = pntohs(&pd[offset]);
197 header.type = ncp_type;
198 header.sequence = pd[offset+2];
199 header.conn_low = pd[offset+3];
200 header.task = pd[offset+4];
201 header.conn_high = pd[offset+5];
203 if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 ||
204 ncp_type == 0x7777) {
206 request.function = pd[offset+6];
208 else if (ncp_type == 0x3333 || ncp_type == 0x9999) {
210 reply.completion_code = pd[offset+6];
211 reply.connection_state = pd[offset+7];
214 ncp_hdr = 6; /* in order to get ncp_type_text[0] */
217 if (fd->win_info[COL_NUM]) {
218 strcpy(fd->win_info[COL_PROTOCOL], "NCP");
219 /* I take advantage of the ncp_hdr length to use as an index into
220 * ncp_type_text[]. Ugly hack, but quick. */
221 sprintf(fd->win_info[COL_INFO], "%s", ncp_type_text[ncp_hdr - 6]);
226 ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
227 "NetWare Core Protocol");
228 ncp_tree = gtk_tree_new();
229 add_subtree(ti, ncp_tree, ETT_NCP);
231 add_item_to_tree(ncp_tree, offset, 2,
232 "Type: %s", val_to_str( header.type, request_reply_values,
235 add_item_to_tree(ncp_tree, offset+2, 1,
236 "Sequence Number: %d", header.sequence);
238 add_item_to_tree(ncp_tree, offset+3, 1,
239 "Connection Number Low: %d", header.conn_low);
241 add_item_to_tree(ncp_tree, offset+4, 1,
242 "Task Number: %d", header.task);
244 add_item_to_tree(ncp_tree, offset+5, 1,
245 "Connection Number High: %d", header.conn_high);
248 add_item_to_tree(ncp_tree, offset+6, 1,
249 "Completion Code: %d", reply.completion_code);
251 add_item_to_tree(ncp_tree, offset+7, 1,
252 "Connection Status: %d", reply.connection_state);
255 add_item_to_tree(ncp_tree, offset+6, 1,
256 "Function Code: %s (%d)",
257 match_strval(request.function, ncp2222_func));
262 if (ncp_type == 0x2222) {
263 /* my offset is different now */
264 add_item_to_tree(ncp_tree, offset, 1,
265 "Subfunction Code: %s (%d)",
266 ncp2222_subfunc(pd[offset-1], pd[offset]), pd[offset]);
268 if (request.function == 0x48) {
269 ncp_read(ncp_tree, pd, offset+1);
272 dissect_data(pd, offset, fd, tree);
276 dissect_data(pd, offset, fd, tree);