An NCP READ is now decoded. This is the first function to be decoded.
[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.4 1998/10/22 04:50:21 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
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" },
68         { 0x0000, NULL }
69 };
70
71
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" },
85         { 0,    NULL }
86 };
87
88 static char*
89 ncp2222_subfunc(u_short func, u_short subfunc) {
90         int i=0;
91         value_string    *info_ptr = NULL;
92
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" },
99                 { 0,    NULL }
100         };
101
102         /* Apple File Services */
103         static value_string     ncp_35[] = {
104                 { 1,    "AFP Create Directory" },
105                 { 2,    "AFP Create File" },
106                 { 3,    "AFP Delete" },
107                 { 4,    "AFP Get Entry ID from Name" },
108                 { 5,    "AFP Get File Information" },
109                 { 6,    "AFP Get Entry ID From NetWare Handle" },
110                 { 7,    "AFP Rename" },
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" },
123                 { 0,    NULL }
124         };
125
126         /* File services */ /* guess */
127         static value_string ncp_72[] = {
128                 { 0xbb, "Read" },
129                 { 0,    NULL }
130         };
131
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" },
137
138                 { 0,    NULL }
139         };
140
141         switch (func) {
142                 case 23:
143                         info_ptr = ncp_23;
144                         break;
145                 case 35:
146                         info_ptr = ncp_35;
147                         break;
148                 case 72:
149                         info_ptr = ncp_72;
150                         break;
151                 case 88:
152                         info_ptr = ncp_88;
153                         break;
154                 default:
155                         return "Unknown function";
156         }
157
158         return val_to_str(subfunc, info_ptr, "Unknown");
159 }
160
161
162 void
163 ncp_read(GtkWidget *tree, const u_char *pd, int offset)
164 {
165         struct ncp_read_header header;
166
167         memcpy(header.handle, &pd[offset], 6);
168         header.offset = pntohl(&pd[offset+6]);
169         header.bytes = pntohs(&pd[offset+10]);
170
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]);
175         
176         add_item_to_tree(tree, offset+6,    4,
177                         "Starting Offset: %d", header.offset);
178
179         add_item_to_tree(tree, offset+10,    2,
180                         "Bytes to Read: %d", header.bytes);
181
182 }
183
184 void
185 dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
186
187         GtkWidget       *ncp_tree, *ti;
188         guint16         ncp_type;
189         int                     ncp_hdr;
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" };
195
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];
202
203         if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 ||
204                 ncp_type == 0x7777) {
205                 ncp_hdr = 7;
206                 request.function = pd[offset+6];
207         }
208         else if (ncp_type == 0x3333 || ncp_type == 0x9999) {
209                 ncp_hdr = 8;
210                 reply.completion_code = pd[offset+6];
211                 reply.connection_state = pd[offset+7];
212         }
213         else {
214                 ncp_hdr = 6; /* in order to get ncp_type_text[0] */
215         }
216
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]);
222         }
223
224
225         if (tree) {
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);
230
231                 add_item_to_tree(ncp_tree, offset,      2,
232                         "Type: %s", val_to_str( header.type, request_reply_values,
233                                         "Unknown (%04X)"));
234
235                 add_item_to_tree(ncp_tree, offset+2,    1,
236                         "Sequence Number: %d", header.sequence);
237
238                 add_item_to_tree(ncp_tree, offset+3,    1,
239                         "Connection Number Low: %d", header.conn_low);
240
241                 add_item_to_tree(ncp_tree, offset+4,    1,
242                         "Task Number: %d", header.task);
243
244                 add_item_to_tree(ncp_tree, offset+5,    1,
245                         "Connection Number High: %d", header.conn_high);
246
247                 if (ncp_hdr == 8) {
248                         add_item_to_tree(ncp_tree, offset+6,    1,
249                                 "Completion Code: %d", reply.completion_code);
250
251                         add_item_to_tree(ncp_tree, offset+7,    1,
252                                 "Connection Status: %d", reply.connection_state);
253                 }
254                 else {
255                         add_item_to_tree(ncp_tree, offset+6,            1,
256                                 "Function Code: %s (%d)",
257                                 match_strval(request.function, ncp2222_func));
258                 }
259
260                 offset += ncp_hdr;
261
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]);
267
268                         if (request.function == 0x48) {
269                                 ncp_read(ncp_tree, pd, offset+1);
270                         }
271                         else {
272                                 dissect_data(pd, offset, fd, tree);
273                         }
274                 }
275                 else {
276                         dissect_data(pd, offset, fd, tree);
277                 }
278         }
279 }