2 * Routines for NetWare Core Protocol
3 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * $Id: packet-ncp.c,v 1.3 1998/10/15 21:12:16 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
66 /* ================================================================= */
68 /* ================================================================= */
70 req_text(u_short req) {
73 static struct req_info reqs[] = {
74 { 0x1111, "Create a service connection" },
75 { 0x2222, "Service request" },
76 { 0x3333, "Service reply" },
77 { 0x5555, "Destroy service connection" },
78 { 0x7777, "Burst mode transfer" },
79 { 0x9999, "Request being processed" },
83 while (reqs[i].text != NULL) {
84 if (reqs[i].req == req) {
93 ncp2222_func(u_short func) {
96 static struct req_info ncp[] = {
97 { 17, "Print and Queue Services" },
98 { 21, "Message Services" },
99 { 22, "File and Directory Services" },
100 { 23, "Binding and Rights Services" },
101 { 34, "Transaction Tacking Services" },
102 { 35, "Apple File Services" },
103 { 72, "File Services" }, /* guess */
104 { 86, "Extended Attributes Services" },
105 { 87, "File and Directory Services" },
106 { 88, "Auditing Services" },
107 { 104, "Netware Directory Services" },
108 { 123, "Netware 4.x Statistical Information Services" },
112 while (ncp[i].text != NULL) {
113 if (ncp[i].req == func) {
122 ncp2222_subfunc(u_short func, u_short subfunc) {
124 struct req_info *info_ptr = NULL;
126 /* Accounting Services */
127 static struct req_info ncp_23[] = {
128 { 150, "Get Current Account Status" },
129 { 151, "Submit Account Charge" },
130 { 152, "Submit Account Hold" },
131 { 153, "Submit Account Note" },
135 /* Apple File Services */
136 static struct req_info ncp_35[] = {
137 { 1, "AFP Create Directory" },
138 { 2, "AFP Create File" },
140 { 4, "AFP Get Entry ID from Name" },
141 { 5, "AFP Get File Information" },
142 { 6, "AFP Get Entry ID From NetWare Handle" },
144 { 8, "AFP Open File Fork" },
145 { 9, "AFP Set File Information" },
146 { 10, "AFP Scan File Information" },
147 { 11, "AFP 2.0 Alloc Temporary Directory Handle" },
148 { 12, "AFP Get Entry ID from Name Path" },
149 { 13, "AFP 2.0 Create Directory" },
150 { 14, "AFP 2.0 Create File" },
151 /* ??? { 15, "AFP 2.0 Delete File" }, just guessing */
152 { 16, "AFP 2.0 Set File Information" },
153 { 17, "AFP 2.0 Scan File Information" },
154 { 18, "AFP Get DOS Name from Entry ID" },
155 { 19, "AFP Get Macintosh Info on Deleted File" },
159 /* File services */ /* guess */
160 static struct req_info ncp_72[] = {
165 /* Auditing Services */
166 static struct req_info ncp_88[] = {
167 { 1, "Query Volume Audit Status" },
168 { 2, "Add Audit Property" },
169 { 3, "Add Auditor Access" },
188 return "Unknown function";
192 while (info_ptr[i].text != NULL) {
193 if (info_ptr[i].req == subfunc) {
194 return info_ptr[i].text;
203 dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
205 GtkWidget *ncp_tree, *ti;
208 struct ncp_common_header header;
209 struct ncp_request_header request;
210 struct ncp_reply_header reply;
211 char *ncp_type_text[] = { "Request", "Reply" };
213 ncp_type = pntohs(&pd[offset]);
214 header.type = ncp_type;
215 header.sequence = pd[offset+2];
216 header.conn_low = pd[offset+3];
217 header.task = pd[offset+4];
218 header.conn_high = pd[offset+5];
220 if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 ||
221 ncp_type == 0x7777) {
223 request.function = pd[offset+6];
225 else if (ncp_type == 0x3333 || ncp_type == 0x9999) {
227 reply.completion_code = pd[offset+6];
228 reply.connection_state = pd[offset+7];
234 if (fd->win_info[COL_NUM]) {
235 strcpy(fd->win_info[COL_PROTOCOL], "NCP");
236 /* I take advantage of the ncp_hdr length to use as an index into
237 * ncp_type_text[]. Ugly hack, but quick. */
238 sprintf(fd->win_info[COL_INFO], "%s", ncp_type_text[ncp_hdr - 7]);
243 ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
244 "NetWare Core Protocol");
245 ncp_tree = gtk_tree_new();
246 add_subtree(ti, ncp_tree, ETT_NCP);
248 add_item_to_tree(ncp_tree, offset, 2,
249 "Type: %s", req_text( header.type ));
251 add_item_to_tree(ncp_tree, offset+2, 1,
252 "Sequence Number: %d", header.sequence);
254 add_item_to_tree(ncp_tree, offset+3, 1,
255 "Connection Number Low: %d", header.conn_low);
257 add_item_to_tree(ncp_tree, offset+4, 1,
258 "Task Number: %d", header.task);
260 add_item_to_tree(ncp_tree, offset+5, 1,
261 "Connection Number High: %d", header.conn_high);
264 add_item_to_tree(ncp_tree, offset+6, 1,
265 "Completion Code: %d", reply.completion_code);
267 add_item_to_tree(ncp_tree, offset+7, 1,
268 "Connection Status: %d", reply.connection_state);
271 add_item_to_tree(ncp_tree, offset+6, 1,
272 "Function Code: %s (%d)",
273 ncp2222_func(request.function), request.function);
278 if (ncp_type == 0x2222) {
279 /* my offset is different now */
280 add_item_to_tree(ncp_tree, offset+1, 1,
281 "Subfunction Code: %s (%d)",
282 ncp2222_subfunc(pd[offset-1], pd[offset]), pd[offset]);
286 dissect_data(pd, offset, fd, tree);