I'm preparing ncp for expansion (i.e., cleaning up my old code). I also
[obnox/wireshark/wip.git] / packet-ncp.c
1 /* packet-ncp.c
2  * Routines for NetWare Core Protocol
3  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
4  *
5  * $Id: packet-ncp.c,v 1.3 1998/10/15 21:12:16 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
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 #include <gtk/gtk.h>
32 #include <pcap.h>
33
34 #include <stdio.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
42 #endif
43
44 #include "ethereal.h"
45 #include "packet.h"
46 #include "packet-ipx.h"
47 #include "packet-ncp.h"
48
49 /* The information in this module comes from:
50         NetWare LAN Analysis, Second Edition
51         Laura A. Chappell and Dan E. Hakes
52         (c) 1994 Novell, Inc.
53         Novell Press, San Jose.
54         ISBN: 0-7821-1362-1
55
56   And from the ncpfs source code by Volker Lendecke
57 */
58
59
60 struct req_info {
61         u_short req;
62         char    *text;
63 };
64
65
66 /* ================================================================= */
67 /* NCP                                                               */
68 /* ================================================================= */
69 static char*
70 req_text(u_short req) {
71         int i=0;
72
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" },
80                 { 0x0000, NULL }
81         };
82
83         while (reqs[i].text != NULL) {
84                 if (reqs[i].req == req) {
85                         return reqs[i].text;
86                 }
87                 i++;
88         }
89         return "Unknown";
90 }
91
92 static char*
93 ncp2222_func(u_short func) {
94         int i=0;
95
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" },
109                 { 0,    NULL }
110         };
111
112         while (ncp[i].text != NULL) {
113                 if (ncp[i].req == func) {
114                         return ncp[i].text;
115                 }
116                 i++;
117         }
118         return "Unknown";
119 }
120
121 static char*
122 ncp2222_subfunc(u_short func, u_short subfunc) {
123         int i=0;
124         struct req_info *info_ptr = NULL;
125
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" },
132                 { 0,    NULL }
133         };
134
135         /* Apple File Services */
136         static struct req_info  ncp_35[] = {
137                 { 1,    "AFP Create Directory" },
138                 { 2,    "AFP Create File" },
139                 { 3,    "AFP Delete" },
140                 { 4,    "AFP Get Entry ID from Name" },
141                 { 5,    "AFP Get File Information" },
142                 { 6,    "AFP Get Entry ID From NetWare Handle" },
143                 { 7,    "AFP Rename" },
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" },
156                 { 0,    NULL }
157         };
158
159         /* File services */ /* guess */
160         static struct req_info ncp_72[] = {
161                 { 0xbb, "Read" },
162                 { 0,    NULL }
163         };
164
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" },
170
171                 { 0,    NULL }
172         };
173
174         switch (func) {
175                 case 23:
176                         info_ptr = ncp_23;
177                         break;
178                 case 35:
179                         info_ptr = ncp_35;
180                         break;
181                 case 72:
182                         info_ptr = ncp_72;
183                         break;
184                 case 88:
185                         info_ptr = ncp_88;
186                         break;
187                 default:
188                         return "Unknown function";
189         }
190
191
192         while (info_ptr[i].text != NULL) {
193                 if (info_ptr[i].req == subfunc) {
194                         return info_ptr[i].text;
195                 }
196                 i++;
197         }
198         return "Unknown";
199 }
200
201
202 void
203 dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
204
205         GtkWidget       *ncp_tree, *ti;
206         guint16         ncp_type;
207         int                     ncp_hdr;
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" };
212
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];
219
220         if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 ||
221                 ncp_type == 0x7777) {
222                 ncp_hdr = 7;
223                 request.function = pd[offset+6];
224         }
225         else if (ncp_type == 0x3333 || ncp_type == 0x9999) {
226                 ncp_hdr = 8;
227                 reply.completion_code = pd[offset+6];
228                 reply.connection_state = pd[offset+7];
229         }
230         else {
231                 ncp_hdr = 1; /* ? */
232         }
233
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]);
239         }
240
241
242         if (tree) {
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);
247
248                 add_item_to_tree(ncp_tree, offset,      2,
249                         "Type: %s", req_text( header.type ));
250
251                 add_item_to_tree(ncp_tree, offset+2,    1,
252                         "Sequence Number: %d", header.sequence);
253
254                 add_item_to_tree(ncp_tree, offset+3,    1,
255                         "Connection Number Low: %d", header.conn_low);
256
257                 add_item_to_tree(ncp_tree, offset+4,    1,
258                         "Task Number: %d", header.task);
259
260                 add_item_to_tree(ncp_tree, offset+5,    1,
261                         "Connection Number High: %d", header.conn_high);
262
263                 if (ncp_hdr == 8) {
264                         add_item_to_tree(ncp_tree, offset+6,    1,
265                                 "Completion Code: %d", reply.completion_code);
266
267                         add_item_to_tree(ncp_tree, offset+7,    1,
268                                 "Connection Status: %d", reply.connection_state);
269                 }
270                 else {
271                         add_item_to_tree(ncp_tree, offset+6,            1,
272                                 "Function Code: %s (%d)",
273                                 ncp2222_func(request.function), request.function);
274                 }
275
276                 offset += ncp_hdr;
277
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]);
283
284                 }
285
286                 dissect_data(pd, offset, fd, tree);
287         }
288 }