More patches from Guy to make wiretap compile better. I definitely
[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.6 1998/11/12 00:06:34 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
33 #include <stdio.h>
34
35 #ifdef HAVE_SYS_TYPES_H
36 # include <sys/types.h>
37 #endif
38
39 #ifdef HAVE_NETINET_IN_H
40 # include <netinet/in.h>
41 #endif
42
43 #include "ethereal.h"
44 #include "packet.h"
45 #include "packet-ipx.h"
46 #include "packet-ncp.h"
47
48 /* The information in this module comes from:
49         NetWare LAN Analysis, Second Edition
50         Laura A. Chappell and Dan E. Hakes
51         (c) 1994 Novell, Inc.
52         Novell Press, San Jose.
53         ISBN: 0-7821-1362-1
54
55   And from the ncpfs source code by Volker Lendecke
56 */
57
58
59
60 static value_string request_reply_values[] = {
61         { 0x1111,       "Create a service connection" },
62         { 0x2222, "Service request" },
63         { 0x3333, "Service reply" },
64         { 0x5555, "Destroy service connection" },
65         { 0x7777, "Burst mode transfer" },
66         { 0x9999, "Request being processed" },
67         { 0x0000, NULL }
68 };
69
70
71 static value_string ncp2222_func[] = {
72         { 17,   "Print and Queue Services" },
73         { 21,   "Message Services" },
74         { 22,   "File and Directory Services" },
75         { 23,   "Binding and Rights Services" },
76         { 34,   "Transaction Tacking Services" },
77         { 35,   "Apple File Services" },
78         { 72,   "File Services" }, /* guess */
79         { 86,   "Extended Attributes Services" },
80         { 87,   "File and Directory Services" },
81         { 88,   "Auditing Services" },
82         { 104,  "Netware Directory Services" },
83         { 123,  "Netware 4.x Statistical Information Services" },
84         { 0,    NULL }
85 };
86
87 static char*
88 ncp2222_subfunc(u_short func, u_short subfunc) {
89         value_string    *info_ptr = NULL;
90
91         /* Accounting Services */
92         static value_string     ncp_23[] = {
93                 { 150,  "Get Current Account Status" },
94                 { 151,  "Submit Account Charge" },
95                 { 152,  "Submit Account Hold" },
96                 { 153,  "Submit Account Note" },
97                 { 0,    NULL }
98         };
99
100         /* Apple File Services */
101         static value_string     ncp_35[] = {
102                 { 1,    "AFP Create Directory" },
103                 { 2,    "AFP Create File" },
104                 { 3,    "AFP Delete" },
105                 { 4,    "AFP Get Entry ID from Name" },
106                 { 5,    "AFP Get File Information" },
107                 { 6,    "AFP Get Entry ID From NetWare Handle" },
108                 { 7,    "AFP Rename" },
109                 { 8,    "AFP Open File Fork" },
110                 { 9,    "AFP Set File Information" },
111                 { 10,   "AFP Scan File Information" },
112                 { 11,   "AFP 2.0 Alloc Temporary Directory Handle" },
113                 { 12,   "AFP Get Entry ID from Name Path" },
114                 { 13,   "AFP 2.0 Create Directory" },
115                 { 14,   "AFP 2.0 Create File" },
116 /* ???  { 15,   "AFP 2.0 Delete File" }, just guessing */
117                 { 16,   "AFP 2.0 Set File Information" },
118                 { 17,   "AFP 2.0 Scan File Information" },
119                 { 18,   "AFP Get DOS Name from Entry ID" },
120                 { 19,   "AFP Get Macintosh Info on Deleted File" },
121                 { 0,    NULL }
122         };
123
124         /* File services */ /* guess */
125         static value_string ncp_72[] = {
126                 { 0xbb, "Read" },
127                 { 0,    NULL }
128         };
129
130         /* Auditing Services */
131         static value_string     ncp_88[] = {
132                 { 1,    "Query Volume Audit Status" },
133                 { 2,    "Add Audit Property" },
134                 { 3,    "Add Auditor Access" },
135
136                 { 0,    NULL }
137         };
138
139         switch (func) {
140                 case 23:
141                         info_ptr = ncp_23;
142                         break;
143                 case 35:
144                         info_ptr = ncp_35;
145                         break;
146                 case 72:
147                         info_ptr = ncp_72;
148                         break;
149                 case 88:
150                         info_ptr = ncp_88;
151                         break;
152                 default:
153                         return "Unknown function";
154         }
155
156         return val_to_str(subfunc, info_ptr, "Unknown");
157 }
158
159
160 void
161 ncp_read(GtkWidget *tree, const u_char *pd, int offset)
162 {
163         struct ncp_read_header header;
164
165         memcpy(header.handle, &pd[offset], 6);
166         header.offset = pntohl(&pd[offset+6]);
167         header.bytes = pntohs(&pd[offset+10]);
168
169         add_item_to_tree(tree, offset,    6,
170                         "File Handle: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X ",
171                         header.handle[0], header.handle[1], header.handle[2],
172                         header.handle[3], header.handle[4], header.handle[5]);
173         
174         add_item_to_tree(tree, offset+6,    4,
175                         "Starting Offset: %d", header.offset);
176
177         add_item_to_tree(tree, offset+10,    2,
178                         "Bytes to Read: %d", header.bytes);
179
180 }
181
182 void
183 dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
184
185         GtkWidget       *ncp_tree, *ti;
186         guint16         ncp_type;
187         int                     ncp_hdr;
188         struct ncp_common_header        header;
189         struct ncp_request_header       request;
190         struct ncp_reply_header         reply;
191         char                                            *ncp_type_text[] = { "Unknown",
192                 "Request", "Reply" };
193
194         ncp_type = pntohs(&pd[offset]);
195         header.type = ncp_type;
196         header.sequence = pd[offset+2];
197         header.conn_low = pd[offset+3];
198         header.task = pd[offset+4];
199         header.conn_high = pd[offset+5];
200
201         if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 ||
202                 ncp_type == 0x7777) {
203                 ncp_hdr = 7;
204                 request.function = pd[offset+6];
205         }
206         else if (ncp_type == 0x3333 || ncp_type == 0x9999) {
207                 ncp_hdr = 8;
208                 reply.completion_code = pd[offset+6];
209                 reply.connection_state = pd[offset+7];
210         }
211         else {
212                 ncp_hdr = 6; /* in order to get ncp_type_text[0] */
213         }
214
215         if (fd->win_info[COL_NUM]) {
216                 strcpy(fd->win_info[COL_PROTOCOL], "NCP");
217                 /* I take advantage of the ncp_hdr length to use as an index into
218                  * ncp_type_text[]. Ugly hack, but quick.  */
219                 sprintf(fd->win_info[COL_INFO], "%s", ncp_type_text[ncp_hdr - 6]);
220         }
221
222
223         if (tree) {
224                 ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
225                         "NetWare Core Protocol");
226                 ncp_tree = gtk_tree_new();
227                 add_subtree(ti, ncp_tree, ETT_NCP);
228
229                 add_item_to_tree(ncp_tree, offset,      2,
230                         "Type: %s", val_to_str( header.type, request_reply_values,
231                                         "Unknown (%04X)"));
232
233                 add_item_to_tree(ncp_tree, offset+2,    1,
234                         "Sequence Number: %d", header.sequence);
235
236                 add_item_to_tree(ncp_tree, offset+3,    1,
237                         "Connection Number Low: %d", header.conn_low);
238
239                 add_item_to_tree(ncp_tree, offset+4,    1,
240                         "Task Number: %d", header.task);
241
242                 add_item_to_tree(ncp_tree, offset+5,    1,
243                         "Connection Number High: %d", header.conn_high);
244
245                 if (ncp_hdr == 8) {
246                         add_item_to_tree(ncp_tree, offset+6,    1,
247                                 "Completion Code: %d", reply.completion_code);
248
249                         add_item_to_tree(ncp_tree, offset+7,    1,
250                                 "Connection Status: %d", reply.connection_state);
251                 }
252                 else {
253                         add_item_to_tree(ncp_tree, offset+6,            1,
254                                 "Function Code: %s (%d)",
255                                 match_strval(request.function, ncp2222_func),
256                                 request.function);
257                 }
258
259                 offset += ncp_hdr;
260
261                 if (ncp_type == 0x2222) {
262                         /* my offset is different now */
263                         add_item_to_tree(ncp_tree, offset,      1,
264                                 "Subfunction Code: %s (%d)",
265                                 ncp2222_subfunc(pd[offset-1], pd[offset]), pd[offset]);
266
267                         if (request.function == 0x48) {
268                                 ncp_read(ncp_tree, pd, offset+1);
269                         }
270                         else {
271                                 dissect_data(pd, offset, fd, tree);
272                         }
273                 }
274                 else {
275                         dissect_data(pd, offset, fd, tree);
276                 }
277         }
278 }