Clean up field names and descriptions.
[obnox/wireshark/wip.git] / packet-afp.c
1 /* packet-afp.c
2  * Routines for afp packet dissection
3  * Copyright 2002, Didier Gautheron <dgautheron@magic.fr>
4  *
5  * $Id: packet-afp.c,v 1.4 2002/04/28 21:04:04 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from README.developer
12  * Copied from packet-dsi.c
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
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 #ifdef NEED_SNPRINTF_H
44 # ifdef HAVE_STDARG_H
45 #  include <stdarg.h>
46 # else
47 #  include <varargs.h>
48 # endif
49 # include "snprintf.h"
50 #endif
51
52 #include <string.h>
53 #include <glib.h>
54 #include <epan/packet.h>
55 #include <epan/strutil.h>
56 #include <epan/conversation.h>
57
58 #include "packet-afp.h"
59
60 /* The information in this module (AFP) comes from:
61
62   AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
63   available from http://www.apple.com
64  
65   AFP3.0.pdf from http://www.apple.com
66   
67   The netatalk source code by Wesley Craig & Adrian Sun
68         http://netatalk.sf.net
69 */
70 /* from netatalk/include/afp.h */
71 #define AFPTRANS_NONE          0
72 #define AFPTRANS_DDP          (1 << 0)
73 #define AFPTRANS_TCP          (1 << 1)
74 #define AFPTRANS_ALL          (AFPTRANS_DDP | AFPTRANS_TCP)
75
76 /* server flags */
77 #define AFPSRVRINFO_COPY                        (1<<0)  /* supports copyfile */
78 #define AFPSRVRINFO_PASSWD                      (1<<1)  /* supports change password */
79 #define AFPSRVRINFO_NOSAVEPASSWD        (1<<2)  /* don't allow save password */
80 #define AFPSRVRINFO_SRVMSGS             (1<<3)  /* supports server messages */
81 #define AFPSRVRINFO_SRVSIGNATURE        (1<<4)  /* supports server signature */
82 #define AFPSRVRINFO_TCPIP               (1<<5)  /* supports tcpip */
83 #define AFPSRVRINFO_SRVNOTIFY           (1<<6)  /* supports server notifications */ 
84 #define AFPSRVRINFO_FASTBOZO            (1<<15) /* fast copying */
85
86 /* AFP Attention Codes -- 4 bits */
87 #define AFPATTN_SHUTDOWN     (1 << 15)            /* shutdown/disconnect */
88 #define AFPATTN_CRASH        (1 << 14)            /* server crashed */
89 #define AFPATTN_MESG         (1 << 13)            /* server has message */
90 #define AFPATTN_NORECONNECT  (1 << 12)            /* don't reconnect */
91 /* server notification */
92 #define AFPATTN_NOTIFY       (AFPATTN_MESG | AFPATTN_NORECONNECT) 
93
94 /* extended bitmap -- 12 bits. volchanged is only useful w/ a server
95  * notification, and time is only useful for shutdown. */
96 #define AFPATTN_VOLCHANGED   (1 << 0)             /* volume has changed */
97 #define AFPATTN_TIME(x)      ((x) & 0xfff)        /* time in minutes */
98
99 /* AFP functions */
100 #define AFP_BYTELOCK         1
101 #define AFP_CLOSEVOL             2
102 #define AFP_CLOSEDIR             3
103 #define AFP_CLOSEFORK            4
104 #define AFP_COPYFILE             5
105 #define AFP_CREATEDIR            6
106 #define AFP_CREATEFILE           7
107 #define AFP_DELETE                   8
108 #define AFP_ENUMERATE            9
109 #define AFP_FLUSH                   10
110 #define AFP_FLUSHFORK           11
111 #define AFP_GETFORKPARAM        14
112 #define AFP_GETSRVINFO          15
113 #define AFP_GETSRVPARAM         16
114 #define AFP_GETVOLPARAM         17
115 #define AFP_LOGIN               18
116 #define AFP_LOGINCONT           19
117 #define AFP_LOGOUT              20
118 #define AFP_MAPID                   21
119 #define AFP_MAPNAME                 22
120 #define AFP_MOVE                    23
121 #define AFP_OPENVOL             24
122 #define AFP_OPENDIR                 25
123 #define AFP_OPENFORK            26
124 #define AFP_READ                    27
125 #define AFP_RENAME                  28
126 #define AFP_SETDIRPARAM         29
127 #define AFP_SETFILEPARAM        30
128 #define AFP_SETFORKPARAM        31
129 #define AFP_SETVOLPARAM         32
130 #define AFP_WRITE                   33
131 #define AFP_GETFLDRPARAM        34
132 #define AFP_SETFLDRPARAM        35
133 #define AFP_CHANGEPW            36
134 #define AFP_GETSRVRMSG          38
135 #define AFP_CREATEID            39
136 #define AFP_DELETEID            40
137 #define AFP_RESOLVEID           41
138 #define AFP_EXCHANGEFILE        42
139 #define AFP_CATSEARCH           43
140 #define AFP_OPENDT                  48
141 #define AFP_CLOSEDT                 49
142 #define AFP_GETICON         51
143 #define AFP_GTICNINFO       52
144 #define AFP_ADDAPPL         53
145 #define AFP_RMVAPPL         54
146 #define AFP_GETAPPL         55
147 #define AFP_ADDCMT          56
148 #define AFP_RMVCMT          57
149 #define AFP_GETCMT          58
150 #define AFP_ADDICON        192
151
152 /* ----------------------------- */
153 static int proto_afp = -1;
154 static int hf_afp_requestid = -1;
155 static int hf_afp_code = -1;
156 static int hf_afp_length = -1;
157 static int hf_afp_reserved = -1;
158
159 static int hf_afp_command = -1;         /* CommandCode */
160 static int hf_afp_AFPVersion = -1; 
161 static int hf_afp_UAM = -1; 
162 static int hf_afp_user = -1; 
163 static int hf_afp_passwd = -1; 
164 static int hf_afp_pad = -1;
165
166 static int hf_afp_vol_bitmap = -1;
167 static int hf_afp_bitmap_offset = -1;
168 static int hf_afp_vol_id = -1;
169 static int hf_afp_vol_attribute = -1;
170 static int hf_afp_vol_name = -1;
171 static int hf_afp_vol_signature = -1;
172 static int hf_afp_vol_creation_date = -1;
173 static int hf_afp_vol_modification_date = -1;
174 static int hf_afp_vol_backup_date = -1;
175 static int hf_afp_vol_bytes_free = -1;
176 static int hf_afp_vol_bytes_total = -1;
177 static int hf_afp_vol_ex_bytes_free = -1;
178 static int hf_afp_vol_ex_bytes_total = -1;
179 static int hf_afp_vol_block_size = -1;
180
181 /* desktop stuff */
182 static int hf_afp_comment               = -1;
183 static int hf_afp_file_creator  = -1;
184 static int hf_afp_file_type     = -1;
185 static int hf_afp_icon_type     = -1;
186 static int hf_afp_icon_length   = -1;
187 static int hf_afp_icon_tag              = -1;
188 static int hf_afp_icon_index    = -1;
189 static int hf_afp_appl_index    = -1;
190 static int hf_afp_appl_tag              = -1;
191
192 static int hf_afp_did                             = -1;
193 static int hf_afp_file_id                         = -1;
194 static int hf_afp_file_DataForkLen    = -1;
195 static int hf_afp_file_RsrcForkLen    = -1;
196 static int hf_afp_file_ExtDataForkLen = -1;
197 static int hf_afp_file_ExtRsrcForkLen = -1;
198 static int hf_afp_file_UnixPrivs      = -1;
199
200 static int hf_afp_dir_bitmap     = -1;
201 static int hf_afp_dir_offspring  = -1;
202 static int hf_afp_dir_OwnerID    = -1;
203 static int hf_afp_dir_GroupID    = -1;
204
205 static int hf_afp_file_bitmap = -1;
206 static int hf_afp_req_count = -1;
207 static int hf_afp_start_index = -1;
208 static int hf_afp_max_reply_size = -1;
209 static int hf_afp_file_flag = -1;
210 static int hf_afp_create_flag = -1;
211 static int hf_afp_struct_size = -1;
212
213 static int hf_afp_creation_date = -1;
214 static int hf_afp_modification_date = -1;
215 static int hf_afp_backup_date = -1;
216 static int hf_afp_finder_info = -1;
217
218 static int hf_afp_path_type = -1;
219 static int hf_afp_path_len = -1;
220 static int hf_afp_path_name = -1;
221
222 static int hf_afp_flag          = -1;
223 static int hf_afp_dt_ref        = -1;
224 static int hf_afp_ofork         = -1;
225 static int hf_afp_ofork_len     = -1;
226 static int hf_afp_offset        = -1;
227 static int hf_afp_rw_count      = -1;
228 static int hf_afp_last_written  = -1;
229 static int hf_afp_actual_count  = -1;
230
231 static int hf_afp_fork_type                     = -1;
232 static int hf_afp_access_mode           = -1;
233 static int hf_afp_access_read           = -1;
234 static int hf_afp_access_write          = -1;
235 static int hf_afp_access_deny_read  = -1;
236 static int hf_afp_access_deny_write = -1;
237
238 static gint hf_afp_lock_op                      = -1;
239 static gint hf_afp_lock_from            = -1;
240 static gint hf_afp_lock_offset          = -1;
241 static gint hf_afp_lock_len             = -1;
242 static gint hf_afp_lock_range_start = -1;
243
244 static gint ett_afp = -1;
245
246 static gint ett_afp_vol_attribute = -1;
247 static gint ett_afp_enumerate = -1;
248 static gint ett_afp_enumerate_line = -1;
249 static gint ett_afp_access_mode = -1;
250
251 static gint ett_afp_vol_bitmap = -1;
252 static gint ett_afp_dir_bitmap = -1;
253 static gint ett_afp_dir_attribute = -1;
254 static gint ett_afp_file_attribute = -1;
255 static gint ett_afp_file_bitmap = -1;
256 static gint ett_afp_path_name = -1;
257 static gint ett_afp_lock_flags = -1;
258 static gint ett_afp_dir_ar = -1;
259
260 static dissector_handle_t afp_handle;
261 static dissector_handle_t data_handle;
262
263 static const value_string vol_signature_vals[] = {
264         {1, "Flat"},
265         {2, "Fixed Directory ID"},
266         {3, "Variable Directory ID (deprecated)"},
267         {0, NULL }
268 };
269
270 static const value_string CommandCode_vals[] = {
271   {AFP_BYTELOCK,        "afpByteRangeLock" },
272   {AFP_CLOSEVOL,        "afpVolClose" },
273   {AFP_CLOSEDIR,        "afpDirClose" },
274   {AFP_CLOSEFORK,       "afpForkClose" },
275   {AFP_COPYFILE,        "afpCopyFile" },
276   {AFP_CREATEDIR,       "afpDirCreate" },
277   {AFP_CREATEFILE,      "afpFileCreate" },
278   {AFP_DELETE,          "afpDelete" },
279   {AFP_ENUMERATE,       "afpEnumerate" },
280   {AFP_FLUSH,           "afpFlush" },
281   {AFP_FLUSHFORK,       "afpForkFlush" },
282   {AFP_GETFORKPARAM,    "afpGetForkParms" },
283   {AFP_GETSRVINFO,      "afpGetSInfo" },
284   {AFP_GETSRVPARAM,     "afpGetSParms" },
285   {AFP_GETVOLPARAM,     "afpGetVolParms" },
286   {AFP_LOGIN,           "afpLogin" },
287   {AFP_LOGINCONT,       "afpContLogin" },
288   {AFP_LOGOUT,          "afpLogout" },
289   {AFP_MAPID,           "afpMapID" },
290   {AFP_MAPNAME,         "afpMapName" },
291   {AFP_MOVE,            "afpMove" },
292   {AFP_OPENVOL,         "afpOpenVol" },
293   {AFP_OPENDIR,         "afpOpenDir" },
294   {AFP_OPENFORK,        "afpOpenFork" },
295   {AFP_READ,            "afpRead" },
296   {AFP_RENAME,          "afpRename" },
297   {AFP_SETDIRPARAM,     "afpSetDirParms" },
298   {AFP_SETFILEPARAM,    "afpSetFileParms" },
299   {AFP_SETFORKPARAM,    "afpSetForkParms" },
300   {AFP_SETVOLPARAM,     "afpSetVolParms" },
301   {AFP_WRITE,           "afpWrite" },
302   {AFP_GETFLDRPARAM,    "afpGetFlDrParms" },
303   {AFP_SETFLDRPARAM,    "afpSetFlDrParms" },
304   {AFP_CHANGEPW,        "afpChangePw" },
305   {AFP_GETSRVRMSG,      "afpGetSrvrMsg" },
306   {AFP_CREATEID,        "afpCreateID" },
307   {AFP_DELETEID,        "afpDeleteID" },
308   {AFP_RESOLVEID,       "afpResolveID" },
309   {AFP_EXCHANGEFILE,    "afpExchangeFiles" },
310   {AFP_CATSEARCH,       "afpCatSearch" },
311   {AFP_OPENDT,          "afpDTOpen" },
312   {AFP_CLOSEDT,         "afpDTClose" },
313   {AFP_GETICON,         "afpGetIcon" },
314   {AFP_GTICNINFO,       "afpGtIcnInfo" },
315   {AFP_ADDAPPL,         "afpAddAPPL" },
316   {AFP_RMVAPPL,         "afpRmvAPPL" },
317   {AFP_GETAPPL,         "afpGetAPPL" },
318   {AFP_ADDCMT,          "afpAddCmt" },
319   {AFP_RMVCMT,          "afpRmvCmt" },
320   {AFP_GETCMT,          "afpGetCmt" },
321   {AFP_ADDICON,         "afpAddIcon" },
322   {0,                    NULL }
323 };
324
325
326 /* volume bitmap
327   from Apple AFP3.0.pdf 
328   Table 1-2 p. 20
329 */
330 #define kFPVolAttributeBit              (1 << 0)
331 #define kFPVolSignatureBit              (1 << 1)
332 #define kFPVolCreateDateBit             (1 << 2)
333 #define kFPVolModDateBit                (1 << 3)
334 #define kFPVolBackupDateBit             (1 << 4)
335 #define kFPVolIDBit                     (1 << 5)
336 #define kFPVolBytesFreeBit              (1 << 6)
337 #define kFPVolBytesTotalBit             (1 << 7)
338 #define kFPVolNameBit                   (1 << 8)
339 #define kFPVolExtBytesFreeBit           (1 << 9)
340 #define kFPVolExtBytesTotalBit          (1 << 10)
341 #define kFPVolBlockSizeBit              (1 << 11)
342
343 static int hf_afp_vol_bitmap_Attributes         = -1;
344 static int hf_afp_vol_bitmap_Signature          = -1;
345 static int hf_afp_vol_bitmap_CreateDate         = -1;
346 static int hf_afp_vol_bitmap_ModDate            = -1;
347 static int hf_afp_vol_bitmap_BackupDate         = -1;
348 static int hf_afp_vol_bitmap_ID                 = -1;
349 static int hf_afp_vol_bitmap_BytesFree          = -1;
350 static int hf_afp_vol_bitmap_BytesTotal         = -1;
351 static int hf_afp_vol_bitmap_Name               = -1;
352 static int hf_afp_vol_bitmap_ExtBytesFree       = -1;
353 static int hf_afp_vol_bitmap_ExtBytesTotal      = -1;
354 static int hf_afp_vol_bitmap_BlockSize          = -1;
355
356 static int hf_afp_vol_attribute_ReadOnly                        = -1;
357 static int hf_afp_vol_attribute_HasVolumePassword               = -1;
358 static int hf_afp_vol_attribute_SupportsFileIDs                 = -1;
359 static int hf_afp_vol_attribute_SupportsCatSearch               = -1;
360 static int hf_afp_vol_attribute_SupportsBlankAccessPrivs        = -1;
361 static int hf_afp_vol_attribute_SupportsUnixPrivs               = -1;
362 static int hf_afp_vol_attribute_SupportsUTF8Names               = -1;
363
364 static int hf_afp_dir_bitmap_Attributes     = -1;
365 static int hf_afp_dir_bitmap_ParentDirID    = -1;
366 static int hf_afp_dir_bitmap_CreateDate     = -1;
367 static int hf_afp_dir_bitmap_ModDate        = -1;
368 static int hf_afp_dir_bitmap_BackupDate     = -1;
369 static int hf_afp_dir_bitmap_FinderInfo     = -1;
370 static int hf_afp_dir_bitmap_LongName       = -1;
371 static int hf_afp_dir_bitmap_ShortName      = -1;
372 static int hf_afp_dir_bitmap_NodeID         = -1;
373 static int hf_afp_dir_bitmap_OffspringCount = -1;
374 static int hf_afp_dir_bitmap_OwnerID        = -1;
375 static int hf_afp_dir_bitmap_GroupID        = -1;
376 static int hf_afp_dir_bitmap_AccessRights   = -1;
377 static int hf_afp_dir_bitmap_UTF8Name       = -1;
378 static int hf_afp_dir_bitmap_UnixPrivs      = -1;
379
380 static int hf_afp_dir_attribute_Invisible     = -1;
381 static int hf_afp_dir_attribute_IsExpFolder   = -1;
382
383 static int hf_afp_dir_attribute_System        = -1;
384 static int hf_afp_dir_attribute_Mounted       = -1;
385 static int hf_afp_dir_attribute_InExpFolder   = -1;
386
387 static int hf_afp_dir_attribute_BackUpNeeded  = -1;
388 static int hf_afp_dir_attribute_RenameInhibit = -1;
389 static int hf_afp_dir_attribute_DeleteInhibit = -1;
390 static int hf_afp_dir_attribute_SetClear      = -1;
391
392 static int hf_afp_file_bitmap_Attributes     = -1;
393 static int hf_afp_file_bitmap_ParentDirID    = -1;
394 static int hf_afp_file_bitmap_CreateDate     = -1;
395 static int hf_afp_file_bitmap_ModDate        = -1;
396 static int hf_afp_file_bitmap_BackupDate     = -1;
397 static int hf_afp_file_bitmap_FinderInfo     = -1;
398 static int hf_afp_file_bitmap_LongName       = -1;
399 static int hf_afp_file_bitmap_ShortName      = -1;
400 static int hf_afp_file_bitmap_NodeID         = -1;
401 static int hf_afp_file_bitmap_DataForkLen    = -1;
402 static int hf_afp_file_bitmap_RsrcForkLen    = -1;
403 static int hf_afp_file_bitmap_ExtDataForkLen = -1;
404 static int hf_afp_file_bitmap_LaunchLimit    = -1;
405
406 static int hf_afp_file_bitmap_UTF8Name       = -1;
407 static int hf_afp_file_bitmap_ExtRsrcForkLen = -1;
408 static int hf_afp_file_bitmap_UnixPrivs      = -1;
409
410 static int hf_afp_file_attribute_Invisible     = -1;
411 static int hf_afp_file_attribute_MultiUser     = -1;
412 static int hf_afp_file_attribute_System        = -1;
413 static int hf_afp_file_attribute_DAlreadyOpen  = -1;
414 static int hf_afp_file_attribute_RAlreadyOpen  = -1;
415 static int hf_afp_file_attribute_WriteInhibit  = -1;
416 static int hf_afp_file_attribute_BackUpNeeded  = -1;
417 static int hf_afp_file_attribute_RenameInhibit = -1;
418 static int hf_afp_file_attribute_DeleteInhibit = -1;
419 static int hf_afp_file_attribute_CopyProtect   = -1;
420 static int hf_afp_file_attribute_SetClear      = -1;
421
422 static const value_string vol_bitmap_vals[] = {
423   {kFPVolAttributeBit,          "VolAttribute"},
424   {kFPVolSignatureBit,          "VolSignature"},
425   {kFPVolCreateDateBit,         "VolCreateDate"},
426   {kFPVolModDateBit,            "VolModDate"},
427   {kFPVolBackupDateBit,         "VolBackupDate"},
428   {kFPVolIDBit,                 "VolID"},
429   {kFPVolBytesFreeBit,          "VolBytesFree"},
430   {kFPVolBytesTotalBit,         "VolBytesTotal"},
431   {kFPVolNameBit,               "VolNameBit"},
432   {kFPVolExtBytesFreeBit,       "VolExtBytesFree"},
433   {kFPVolExtBytesTotalBit,      "VolExtBytesTotal"},
434   {kFPVolBlockSizeBit,          "VolBlockSize"},
435   {0,                            NULL } };
436
437 static const value_string flag_vals[] = {
438   {0,   "Start" },
439   {1,   "End" },
440   {0,   NULL } };
441
442 static const value_string path_type_vals[] = {
443   {1,   "Short names" },
444   {2,   "Long names" },
445   {3,   "Unicode names" },
446   {0,   NULL } };
447
448 /*
449   volume attribute from Apple AFP3.0.pdf 
450   Table 1-3 p. 22
451 */
452 #define kReadOnly                               (1 << 0)
453 #define kHasVolumePassword                      (1 << 1)
454 #define kSupportsFileIDs                        (1 << 2)
455 #define kSupportsCatSearch                      (1 << 3)
456 #define kSupportsBlankAccessPrivs               (1 << 4)
457 #define kSupportsUnixPrivs                      (1 << 5)
458 #define kSupportsUTF8Names                      (1 << 6)
459
460 /*
461   directory bitmap from Apple AFP3.0.pdf 
462   Table 1-4 p. 31
463 */
464 #define kFPAttributeBit                 (1 << 0)
465 #define kFPParentDirIDBit               (1 << 1)
466 #define kFPCreateDateBit                (1 << 2)
467 #define kFPModDateBit                   (1 << 3)
468 #define kFPBackupDateBit                (1 << 4)
469 #define kFPFinderInfoBit                (1 << 5)
470 #define kFPLongNameBit                  (1 << 6)
471 #define kFPShortNameBit                 (1 << 7)
472 #define kFPNodeIDBit                    (1 << 8)
473 #define kFPOffspringCountBit            (1 << 9)
474 #define kFPOwnerIDBit                   (1 << 10)
475 #define kFPGroupIDBit                   (1 << 11)
476 #define kFPAccessRightsBit              (1 << 12)
477 #define kFPUTF8NameBit                  (1 << 13)
478 #define kFPUnixPrivsBit                 (1 << 14)
479
480 /*
481         directory Access Rights parameter AFP3.0.pdf
482         table 1-6 p. 34
483 */
484
485 #define AR_O_SEARCH     (1 << 0)        /* owner has search access */
486 #define AR_O_READ       (1 << 1)    /* owner has read access */
487 #define AR_O_WRITE      (1 << 2)    /* owner has write access */
488
489 #define AR_G_SEARCH     (1 << 8)    /* group has search access */
490 #define AR_G_READ       (1 << 9)    /* group has read access */
491 #define AR_G_WRITE      (1 << 10)   /* group has write access */
492
493 #define AR_E_SEARCH     (1 << 16)       /* everyone has search access */
494 #define AR_E_READ       (1 << 17)   /* everyone has read access */
495 #define AR_E_WRITE      (1 << 18)   /* everyone has write access */
496
497 #define AR_U_SEARCH     (1 << 24)   /* user has search access */
498 #define AR_U_READ       (1 << 25)   /* user has read access */
499 #define AR_U_WRITE      (1 << 26)       /* user has write access */ 
500
501 #define AR_BLANK        (1 << 28)       /* Blank Access Privileges (use parent dir privileges) */
502 #define AR_U_OWN        (1 << 31)       /* user is the owner */
503
504 static int hf_afp_dir_ar          = -1;
505 static int hf_afp_dir_ar_o_search = -1;
506 static int hf_afp_dir_ar_o_read   = -1;
507 static int hf_afp_dir_ar_o_write  = -1;
508 static int hf_afp_dir_ar_g_search = -1;
509 static int hf_afp_dir_ar_g_read   = -1;
510 static int hf_afp_dir_ar_g_write  = -1;
511 static int hf_afp_dir_ar_e_search = -1;
512 static int hf_afp_dir_ar_e_read   = -1;
513 static int hf_afp_dir_ar_e_write  = -1;
514 static int hf_afp_dir_ar_u_search = -1;
515 static int hf_afp_dir_ar_u_read   = -1;
516 static int hf_afp_dir_ar_u_write  = -1;
517 static int hf_afp_dir_ar_blank    = -1;
518 static int hf_afp_dir_ar_u_own    = -1;
519
520 /*
521   file bitmap AFP3.0.pdf 
522   Table 1-7 p. 36
523 same as dir
524 kFPAttributeBit                 (bit 0)
525 kFPParentDirIDBit               (bit 1)
526 kFPCreateDateBit                (bit 2)
527 kFPModDateBit                   (bit 3)
528 kFPBackupDateBit                (bit 4)
529 kFPFinderInfoBit                (bit 5)
530 kFPLongNameBit                  (bit 6)
531 kFPShortNameBit                 (bit 7)
532 kFPNodeIDBit                    (bit 8)
533
534 kFPUTF8NameBit                  (bit 13)
535 */
536
537 #define kFPDataForkLenBit               (1 << 9)
538 #define kFPRsrcForkLenBit               (1 << 10)
539 #define kFPExtDataForkLenBit            (1 << 11)
540 #define kFPLaunchLimitBit               (1 << 12)
541
542 #define kFPExtRsrcForkLenBit            (1 << 14)
543 #define kFPUnixPrivsBit_file            (1 << 15)       /* :( */
544
545 /*
546   file attribute AFP3.0.pdf 
547   Table 1-8 p. 37
548 */
549 #define kFPInvisibleBit                         (1 << 0)
550 #define kFPMultiUserBit                         (1 << 1)
551 #define kFPSystemBit                            (1 << 2)
552 #define kFPDAlreadyOpenBit                      (1 << 3)
553 #define kFPRAlreadyOpenBit                      (1 << 4)
554 #define kFPWriteInhibitBit                      (1 << 5)
555 #define kFPBackUpNeededBit                      (1 << 6)
556 #define kFPRenameInhibitBit             (1 << 7)
557 #define kFPDeleteInhibitBit             (1 << 8)
558 #define kFPCopyProtectBit                       (1 << 10)
559 #define kFPSetClearBit                          (1 << 15)
560
561 /* dir attribute */
562 #define kIsExpFolder    (1 << 1)
563 #define kMounted                (1 << 3)
564 #define kInExpFolder    (1 << 4)
565
566 #define hash_init_count 20
567
568 /* Hash functions */
569 static gint  afp_equal (gconstpointer v, gconstpointer v2);
570 static guint afp_hash  (gconstpointer v);
571  
572 static guint afp_packet_init_count = 200;
573
574 typedef struct {
575         guint32 conversation;
576         guint16 seq;
577 } afp_request_key;
578  
579 typedef struct {
580         guint8  command;
581 } afp_request_val;
582  
583 static GHashTable *afp_request_hash = NULL;
584 static GMemChunk *afp_request_keys = NULL;
585 static GMemChunk *afp_request_vals = NULL;
586
587 /* Hash Functions */
588 static gint  afp_equal (gconstpointer v, gconstpointer v2)
589 {
590         afp_request_key *val1 = (afp_request_key*)v;
591         afp_request_key *val2 = (afp_request_key*)v2;
592
593         if (val1->conversation == val2->conversation &&
594                         val1->seq == val2->seq) {
595                 return 1;
596         }
597         return 0;
598 }
599
600 static guint afp_hash  (gconstpointer v)
601 {
602         afp_request_key *afp_key = (afp_request_key*)v;
603         return afp_key->seq;
604 }
605
606 /* -------------------------- 
607 */
608 #define PAD(x)      { proto_tree_add_item(tree, hf_afp_pad, tvb, offset,  x, FALSE); offset += x; }
609
610 static guint16
611 decode_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
612 {
613         proto_tree *sub_tree = NULL;
614         proto_item *item;
615         guint16  bitmap;
616
617         bitmap = tvb_get_ntohs(tvb, offset);
618         if (tree) {
619                 item = proto_tree_add_item(tree, hf_afp_vol_bitmap, tvb, offset, 2,FALSE);
620                 sub_tree = proto_item_add_subtree(item, ett_afp_vol_bitmap);
621         }
622         
623         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Attributes,     tvb, offset, 2,FALSE);
624         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Signature,      tvb, offset, 2,FALSE);
625         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_CreateDate,     tvb, offset, 2,FALSE);
626         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ModDate,        tvb, offset, 2,FALSE);
627         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BackupDate,     tvb, offset, 2,FALSE);
628         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ID,             tvb, offset, 2,FALSE);
629         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesFree,      tvb, offset, 2,FALSE);
630         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesTotal,     tvb, offset, 2,FALSE);
631         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Name,           tvb, offset, 2,FALSE);
632         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesFree,   tvb, offset, 2,FALSE);
633         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesTotal,  tvb, offset, 2,FALSE);
634         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BlockSize ,     tvb, offset, 2,FALSE);
635
636         return bitmap;
637 }
638
639 /* -------------------------- */
640 static guint16
641 decode_vol_attribute (proto_tree *tree, tvbuff_t *tvb, gint offset)
642 {
643         proto_tree *sub_tree = NULL;
644         proto_item *item;
645         guint16  bitmap;
646
647         bitmap = tvb_get_ntohs(tvb, offset);
648         if (tree) {
649                 item = proto_tree_add_item(tree, hf_afp_vol_attribute, tvb, offset, 2,FALSE);
650                 sub_tree = proto_item_add_subtree(item, ett_afp_vol_attribute);
651         }
652         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_ReadOnly                ,tvb, offset, 2,FALSE);
653         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_HasVolumePassword       ,tvb, offset, 2,FALSE);
654         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsFileIDs         ,tvb, offset, 2,FALSE);
655         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsCatSearch       ,tvb, offset, 2,FALSE);
656         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsBlankAccessPrivs,tvb, offset, 2,FALSE);
657         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUnixPrivs       ,tvb, offset, 2,FALSE);
658         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUTF8Names       ,tvb, offset, 2,FALSE);
659                                                                                
660         return bitmap;                                                             
661 }                                                                              
662
663 /* -------------------------- 
664         cf AFP3.0.pdf page 38
665         date  are number of seconds from 12:00am on 01.01.2000 GMT
666         backup : 0x8000000 not set
667         from netatalk adouble.h 
668 */
669 #define DATE_NOT_SET         0x80000000 
670 #define AD_DATE_DELTA         946684800  
671 #define AD_DATE_TO_UNIX(x)    (x + AD_DATE_DELTA)  
672 static guint32
673 print_date(proto_tree *tree,int id, tvbuff_t *tvb, gint offset)
674 {
675         time_t date = tvb_get_ntohl(tvb, offset);
676         nstime_t tv;
677
678         tv.secs = AD_DATE_TO_UNIX(date);
679         proto_tree_add_time(tree, id, tvb, offset, 4, &tv);
680
681         return date;
682 }
683
684 /* -------------------------- */
685 static gint
686 parse_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
687 {
688         guint16 nameoff = 0;
689
690         if ((bitmap & kFPVolAttributeBit)) {
691                 decode_vol_attribute(tree,tvb,offset);
692                 offset += 2;
693         }
694         if ((bitmap & kFPVolSignatureBit)) {
695                 proto_tree_add_item(tree, hf_afp_vol_signature,tvb, offset, 2, FALSE);
696                 offset += 2;
697         }
698         if ((bitmap & kFPVolCreateDateBit)) {
699                 print_date(tree, hf_afp_vol_creation_date,tvb, offset);
700                 offset += 4;
701         }
702         if ((bitmap & kFPVolModDateBit)) {
703                 print_date(tree, hf_afp_vol_modification_date,tvb, offset);
704                 offset += 4;
705         }
706         if ((bitmap & kFPVolBackupDateBit)) {
707                 print_date(tree, hf_afp_vol_backup_date,tvb, offset);
708                 offset += 4;
709         }
710         if ((bitmap & kFPVolIDBit)) {
711                 proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
712                 offset += 2;
713         }
714         if ((bitmap & kFPVolBytesFreeBit)) {
715                 proto_tree_add_item(tree, hf_afp_vol_bytes_free,tvb, offset, 4, FALSE);
716                 offset += 4;
717         }
718         if ((bitmap & kFPVolBytesTotalBit)) {
719                 proto_tree_add_item(tree, hf_afp_vol_bytes_total,tvb, offset, 4, FALSE);
720                 offset += 4;
721         }
722         if ((bitmap & kFPVolNameBit)) {
723                 nameoff = tvb_get_ntohs(tvb, offset);
724                 proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
725                 offset += 2;
726
727         }
728         if ((bitmap & kFPVolExtBytesFreeBit)) {
729                 proto_tree_add_item(tree, hf_afp_vol_ex_bytes_free,tvb, offset, 8, FALSE);
730                 offset += 8;
731         }
732         if ((bitmap & kFPVolExtBytesTotalBit)) {
733                 proto_tree_add_item(tree, hf_afp_vol_ex_bytes_total,tvb, offset, 8, FALSE);
734                 offset += 8;
735         }
736         if ((bitmap & kFPVolBlockSizeBit)) {
737                 proto_tree_add_item(tree, hf_afp_vol_block_size,tvb, offset, 4, FALSE);
738                 offset += 4;
739         }
740         if (nameoff) {
741         guint8 len;
742
743                 len = tvb_get_guint8(tvb, offset);
744                 proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
745                 offset += len +1;
746
747         }
748         return offset;
749 }
750
751 /* -------------------------- */
752 static guint16
753 decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
754 {
755         proto_tree *sub_tree = NULL;
756         proto_item *item;
757         guint16         bitmap;
758
759         bitmap = tvb_get_ntohs(tvb, offset);
760         if (tree) {
761                 item = proto_tree_add_item(tree, hf_afp_file_bitmap, tvb, offset, 2,FALSE);
762                 sub_tree = proto_item_add_subtree(item, ett_afp_file_bitmap);
763         }
764         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_Attributes      , tvb, offset, 2,FALSE);  
765         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ParentDirID    , tvb, offset, 2,FALSE);
766         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_CreateDate     , tvb, offset, 2,FALSE);
767         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ModDate        , tvb, offset, 2,FALSE);
768         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_BackupDate     , tvb, offset, 2,FALSE);
769         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_FinderInfo     , tvb, offset, 2,FALSE);
770         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LongName       , tvb, offset, 2,FALSE);
771         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ShortName      , tvb, offset, 2,FALSE);
772         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_NodeID         , tvb, offset, 2,FALSE);
773
774         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_DataForkLen    , tvb, offset, 2,FALSE);   
775         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_RsrcForkLen    , tvb, offset, 2,FALSE);
776         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtDataForkLen , tvb, offset, 2,FALSE);
777         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LaunchLimit    , tvb, offset, 2,FALSE);
778         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UTF8Name           , tvb, offset, 2,FALSE);
779
780         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtRsrcForkLen , tvb, offset, 2,FALSE);
781         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UnixPrivs      , tvb, offset, 2,FALSE);
782
783         return bitmap;
784 }
785
786 /* -------------------------- */
787 static guint16 
788 decode_file_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset, int shared)
789 {
790         proto_tree *sub_tree = NULL;
791         proto_item *item;
792         guint16         attribute;
793         
794         attribute = tvb_get_ntohs(tvb, offset);
795         if (tree) {
796                 item = proto_tree_add_text(tree, tvb, offset, 2,
797                                         "file Attributes: 0x%04x", attribute);
798                 sub_tree = proto_item_add_subtree(item, ett_afp_file_attribute);
799         }
800         proto_tree_add_item(sub_tree, hf_afp_file_attribute_Invisible    , tvb, offset, 2,FALSE);  
801         if (!shared) 
802                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_MultiUser    , tvb, offset, 2,FALSE);
803
804         proto_tree_add_item(sub_tree, hf_afp_file_attribute_System       , tvb, offset, 2,FALSE);
805
806         if (!shared) {
807                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_DAlreadyOpen , tvb, offset, 2,FALSE);
808                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_RAlreadyOpen , tvb, offset, 2,FALSE);
809                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_WriteInhibit , tvb, offset, 2,FALSE);
810         }
811         proto_tree_add_item(sub_tree, hf_afp_file_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
812         proto_tree_add_item(sub_tree, hf_afp_file_attribute_RenameInhibit, tvb, offset, 2,FALSE);
813         proto_tree_add_item(sub_tree, hf_afp_file_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
814
815         if (!shared) 
816                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_CopyProtect  , tvb, offset, 2,FALSE);
817
818         proto_tree_add_item(sub_tree, hf_afp_file_attribute_SetClear     , tvb, offset, 2,FALSE);
819
820         return(attribute);
821 }
822
823 /* -------------------------- */
824 static gint
825 parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap, int shared)
826 {
827         guint16 lnameoff = 0;
828         guint16 snameoff = 0;
829         guint16 unameoff = 0;
830         gint    max_offset = 0;
831
832         gint    org_offset = offset;
833
834         if ((bitmap & kFPAttributeBit)) {
835                 decode_file_attribute(tree, tvb, offset, shared);
836                 offset += 2;
837         }
838         if ((bitmap & kFPParentDirIDBit)) {
839                 proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
840                 offset += 4;
841         }
842         if ((bitmap & kFPCreateDateBit)) {
843                 print_date(tree, hf_afp_creation_date,tvb, offset);
844                 offset += 4;
845         }
846         if ((bitmap & kFPModDateBit)) {
847                 print_date(tree, hf_afp_modification_date,tvb, offset);
848                 offset += 4;
849         }
850         if ((bitmap & kFPBackupDateBit)) {
851                 print_date(tree, hf_afp_backup_date,tvb, offset);
852                 offset += 4;
853         }
854         if ((bitmap & kFPFinderInfoBit)) {
855                 proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
856                 offset += 32;
857         }
858         if ((bitmap & kFPLongNameBit)) {
859                 gint tp_ofs;
860                 guint8 len;
861
862                 lnameoff = tvb_get_ntohs(tvb, offset);
863                 if (lnameoff) {
864                         tp_ofs = lnameoff +org_offset;
865                         proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
866                         len = tvb_get_guint8(tvb, tp_ofs);
867                         proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
868                         tp_ofs++;
869                         proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
870                         tp_ofs += len;
871                         max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
872                 }
873                 offset += 2;
874         }
875         if ((bitmap & kFPShortNameBit)) {
876                 snameoff = tvb_get_ntohs(tvb, offset);
877                 proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
878                 offset += 2;
879         }
880         if ((bitmap & kFPNodeIDBit)) {
881                 proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
882                 offset += 4;
883         }
884
885         if ((bitmap & kFPDataForkLenBit)) {
886                 proto_tree_add_item(tree, hf_afp_file_DataForkLen, tvb, offset, 4,FALSE);
887                 offset += 4;
888         }
889         
890         if ((bitmap & kFPRsrcForkLenBit)) {
891                 proto_tree_add_item(tree, hf_afp_file_RsrcForkLen, tvb, offset, 4,FALSE);
892                 offset += 4;
893         }
894
895         if ((bitmap & kFPExtDataForkLenBit)) {
896                 proto_tree_add_item(tree, hf_afp_file_ExtDataForkLen, tvb, offset, 8,FALSE);
897                 offset += 8;
898         }
899
900         if ((bitmap & kFPLaunchLimitBit)) {
901                 offset += 2;    /* ? */
902         }
903
904         if ((bitmap & kFPUTF8NameBit)) {
905                 offset += 2;
906         }
907
908         if ((bitmap & kFPExtRsrcForkLenBit)) {
909                 proto_tree_add_item(tree, hf_afp_file_ExtRsrcForkLen, tvb, offset, 8,FALSE);
910                 offset += 8;
911         }
912
913         if ((bitmap & kFPUnixPrivsBit_file)) {
914                 proto_tree_add_item(tree, hf_afp_file_UnixPrivs, tvb, offset, 4,FALSE);
915                 offset += 4;
916         }
917
918         return (max_offset)?max_offset:offset;
919 }
920
921 /* -------------------------- */
922 static guint16 
923 decode_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
924 {
925         proto_tree *sub_tree = NULL;
926         proto_item *item;
927         guint16         bitmap;
928         
929         bitmap = tvb_get_ntohs(tvb, offset);
930         if (tree) {
931                 item = proto_tree_add_item(tree, hf_afp_dir_bitmap, tvb, offset, 2,FALSE);
932                 sub_tree = proto_item_add_subtree(item, ett_afp_dir_bitmap);
933         }
934         
935         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_Attributes      , tvb, offset, 2,FALSE);  
936         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ParentDirID    , tvb, offset, 2,FALSE);
937         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_CreateDate     , tvb, offset, 2,FALSE);
938         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ModDate        , tvb, offset, 2,FALSE);
939         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_BackupDate     , tvb, offset, 2,FALSE);
940         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_FinderInfo     , tvb, offset, 2,FALSE);
941         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_LongName       , tvb, offset, 2,FALSE);
942         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ShortName      , tvb, offset, 2,FALSE);
943         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_NodeID         , tvb, offset, 2,FALSE);
944         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OffspringCount , tvb, offset, 2,FALSE);
945         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OwnerID        , tvb, offset, 2,FALSE);
946         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_GroupID        , tvb, offset, 2,FALSE);
947         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_AccessRights   , tvb, offset, 2,FALSE);
948         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UTF8Name           , tvb, offset, 2,FALSE);
949         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UnixPrivs      , tvb, offset, 2,FALSE);
950
951         return bitmap;
952 }
953
954 /* -------------------------- */
955 static guint16 
956 decode_dir_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset)
957 {
958         proto_tree *sub_tree = NULL;
959         proto_item *item;
960         guint16         attribute;
961         
962         attribute = tvb_get_ntohs(tvb, offset);
963         if (tree) {
964                 item = proto_tree_add_text(tree, tvb, offset, 2,
965                                         "dir Attributes: 0x%04x", attribute);
966                 sub_tree = proto_item_add_subtree(item, ett_afp_dir_attribute);
967         }
968         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Invisible    , tvb, offset, 2,FALSE);  
969         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_IsExpFolder  , tvb, offset, 2,FALSE);
970         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_System       , tvb, offset, 2,FALSE);
971         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Mounted      , tvb, offset, 2,FALSE);
972         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_InExpFolder  , tvb, offset, 2,FALSE);
973         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
974         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_RenameInhibit, tvb, offset, 2,FALSE);
975         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
976
977         return(attribute);
978 }
979
980 /* -------------------------- */
981 static gint
982 parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
983 {
984         guint16 lnameoff = 0;
985         guint16 snameoff = 0;
986         guint16 unameoff = 0;
987         gint    max_offset = 0;
988
989         gint    org_offset = offset;
990
991         if ((bitmap & kFPAttributeBit)) {
992                 decode_dir_attribute(tree, tvb, offset);
993                 offset += 2;
994         }
995         if ((bitmap & kFPParentDirIDBit)) {
996                 proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
997                 offset += 4;
998         }
999         if ((bitmap & kFPCreateDateBit)) {
1000                 print_date(tree, hf_afp_creation_date,tvb, offset);
1001                 offset += 4;
1002         }
1003         if ((bitmap & kFPModDateBit)) {
1004                 print_date(tree, hf_afp_modification_date,tvb, offset);
1005                 offset += 4;
1006         }
1007         if ((bitmap & kFPBackupDateBit)) {
1008                 print_date(tree, hf_afp_backup_date,tvb, offset);
1009                 offset += 4;
1010         }
1011         if ((bitmap & kFPFinderInfoBit)) {
1012                 proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
1013                 offset += 32;
1014         }
1015         if ((bitmap & kFPLongNameBit)) {
1016                 gint tp_ofs;
1017                 guint8 len;
1018                 lnameoff = tvb_get_ntohs(tvb, offset);
1019                 if (lnameoff) {
1020                         tp_ofs = lnameoff +org_offset;
1021                         proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
1022                         len = tvb_get_guint8(tvb, tp_ofs);
1023                         proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
1024                         tp_ofs++;
1025                         proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
1026                         tp_ofs += len;
1027                         max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
1028                 }
1029                 offset += 2;
1030         }
1031         if ((bitmap & kFPShortNameBit)) {
1032                 snameoff = tvb_get_ntohs(tvb, offset);
1033                 proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
1034                 offset += 2;
1035         }
1036         if ((bitmap & kFPNodeIDBit)) {
1037                 proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
1038                 offset += 4;
1039         }
1040         if ((bitmap & kFPOffspringCountBit)) {
1041                 proto_tree_add_item(tree, hf_afp_dir_offspring, tvb, offset, 2,FALSE);
1042                 offset += 2;            /* error in AFP3.0.pdf */
1043         }
1044         if ((bitmap & kFPOwnerIDBit)) {
1045                 proto_tree_add_item(tree, hf_afp_dir_OwnerID, tvb, offset, 4,   FALSE);  
1046                 offset += 4;
1047         }
1048         if ((bitmap & kFPGroupIDBit)) {
1049                 proto_tree_add_item(tree, hf_afp_dir_GroupID, tvb, offset, 4,   FALSE);  
1050                 offset += 4;
1051         }
1052         if ((bitmap & kFPAccessRightsBit)) {
1053                 proto_tree *sub_tree = NULL;
1054                 proto_item *item;
1055                         
1056                 if (tree) {
1057                         item = proto_tree_add_item(tree, hf_afp_dir_ar, tvb, offset, 4, FALSE);
1058                         sub_tree = proto_item_add_subtree(item, ett_afp_dir_ar);
1059                 }
1060                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_search, tvb, offset, 4,   FALSE);  
1061                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_read  , tvb, offset, 4,   FALSE);  
1062                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_write , tvb, offset, 4,   FALSE);  
1063
1064                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_search, tvb, offset, 4,   FALSE);  
1065                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_read  , tvb, offset, 4,   FALSE);  
1066                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_write , tvb, offset, 4,   FALSE);  
1067
1068                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_search, tvb, offset, 4,   FALSE);  
1069                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_read  , tvb, offset, 4,   FALSE);  
1070                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_write , tvb, offset, 4,   FALSE);  
1071
1072                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_search, tvb, offset, 4,   FALSE);  
1073                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_read  , tvb, offset, 4,   FALSE);  
1074                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_write , tvb, offset, 4,   FALSE);  
1075
1076                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_blank   , tvb, offset, 4,   FALSE);  
1077                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_own   , tvb, offset, 4,   FALSE);  
1078                 
1079                 offset += 4;
1080         }
1081         if ((bitmap & kFPUTF8NameBit)) {
1082                 offset += 2;
1083         }
1084         if ((bitmap & kFPUnixPrivsBit)) {
1085                 offset += 4;
1086         }
1087         return (max_offset)?max_offset:offset;
1088 }
1089
1090 /* -------------------------- */
1091 static gchar *
1092 name_in_bitmap(tvbuff_t *tvb, gint *offset, guint16 bitmap)
1093 {
1094         gchar *name;
1095         gint    org_offset = *offset;
1096         guint16 nameoff;
1097         guint8  len;
1098         gint    tp_ofs;
1099         
1100         name = NULL;
1101         if ((bitmap & kFPAttributeBit)) 
1102                 *offset += 2;
1103         if ((bitmap & kFPParentDirIDBit))
1104                 *offset += 4;
1105         if ((bitmap & kFPCreateDateBit)) 
1106                 *offset += 4;
1107         if ((bitmap & kFPModDateBit))
1108                 *offset += 4;
1109         if ((bitmap & kFPBackupDateBit)) 
1110                 *offset += 4;
1111         if ((bitmap & kFPFinderInfoBit)) 
1112                 *offset += 32;
1113         
1114         if ((bitmap & kFPLongNameBit)) {
1115                 nameoff = tvb_get_ntohs(tvb, *offset);
1116                 if (nameoff) {
1117                         tp_ofs = nameoff +org_offset;
1118                         len = tvb_get_guint8(tvb, tp_ofs);
1119                         tp_ofs++;
1120                         if (!(name = g_malloc(len +1)))
1121                                 return name;
1122                         tvb_memcpy(tvb, name, tp_ofs, len);
1123                         *(name +len) = 0;
1124                         return name;
1125                 }
1126         }
1127         /* short name ? */
1128         return name;
1129 }
1130
1131 /* -------------------------- */
1132 static gchar *
1133 name_in_dbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
1134 {
1135         gchar *name;
1136         
1137         name = name_in_bitmap(tvb, &offset, bitmap);
1138         if (name != NULL)
1139                 return name;
1140         /*
1141                 check UTF8 name 
1142         */
1143         
1144         return name;
1145 }
1146
1147 /* -------------------------- */
1148 static gchar *
1149 name_in_fbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
1150 {
1151         gchar *name;
1152         
1153         name = name_in_bitmap(tvb, &offset, bitmap);
1154         if (name != NULL)
1155                 return name;
1156         /*
1157                 check UTF8 name 
1158         */
1159         
1160         return name;
1161 }
1162
1163 /* -------------------------- */
1164 static gint
1165 decode_vol_did(proto_tree *tree, tvbuff_t *tvb, gint offset)
1166 {
1167         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1168         offset += 2;
1169
1170         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1171         offset += 4;
1172         return offset;
1173 }
1174
1175 /* -------------------------- */
1176 static gint
1177 decode_vol_did_file_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
1178 {
1179         offset = decode_vol_did(tree, tvb, offset);
1180
1181         decode_file_bitmap(tree, tvb, offset);
1182         offset += 2;
1183         
1184         decode_dir_bitmap(tree, tvb, offset);
1185         offset += 2;
1186         
1187         return offset;
1188 }
1189
1190 /* ------------------------
1191  * idea from packet-smb
1192  *
1193  */
1194 static gchar *
1195 get_name(tvbuff_t *tvb, int offset, int type)
1196 {
1197         static gchar  str[3][256];
1198         static int    cur;
1199         gchar *string;
1200         guint8 len;
1201         int i;
1202         len = tvb_get_guint8(tvb, offset);
1203         offset++;
1204         string = str[cur];
1205         switch (type) {
1206         case 1:
1207         case 2:
1208         tvb_memcpy(tvb, (guint8 *)string, offset, len);
1209         string[len] = 0;
1210                 /* FIXME should use something else as separator ?
1211                 */
1212         for (i = 0; i < len; i++) if (!string[i])
1213                 string[i] = ':';        
1214         break;
1215     case 3:
1216         strcpy(string, "error Unicode...,next time ");
1217         break;
1218     }
1219
1220         cur = ++cur % 3;
1221         return string;
1222 }
1223
1224 /* -------------------------- */
1225 static gint
1226 decode_name_label (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, const gchar *label)
1227 {
1228         int len;
1229         gchar *name;
1230         guint8 type;
1231         proto_tree *sub_tree = NULL;
1232         proto_item *item;
1233                 
1234         type = tvb_get_guint8(tvb, offset);
1235         len = tvb_get_guint8(tvb, offset +1);
1236         name = get_name(tvb, offset +1, type);
1237
1238         if (pinfo && check_col(pinfo->cinfo, COL_INFO)) {
1239                 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", name);
1240         }
1241
1242         if (tree) {
1243                 item = proto_tree_add_text(tree, tvb, offset, len +2, label, name);
1244                 sub_tree = proto_item_add_subtree(item, ett_afp_path_name);
1245                 proto_tree_add_item(  sub_tree, hf_afp_path_type, tvb, offset,   1,FALSE);
1246                 offset++;
1247                 proto_tree_add_item(  sub_tree, hf_afp_path_len,  tvb, offset,   1,FALSE);
1248                 offset++;
1249                 proto_tree_add_string(sub_tree, hf_afp_path_name, tvb, offset, len,name);
1250         }
1251         else 
1252                 offset += 2;
1253
1254         return offset +len;
1255 }
1256
1257 /* -------------------------- */
1258 static gint
1259 decode_name (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset)
1260 {
1261         return decode_name_label(tree, pinfo, tvb, offset, "Path: %s");
1262 }
1263
1264 /* ************************** */
1265 static gint
1266 dissect_query_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1267 {
1268         int len;
1269         
1270         PAD(1);
1271
1272         decode_vol_bitmap(tree, tvb, offset);
1273         offset += 2;
1274         
1275         len = tvb_get_guint8(tvb, offset);
1276
1277         if (check_col(pinfo->cinfo, COL_INFO)) {
1278         const gchar *rep;
1279                 rep = get_name(tvb, offset, 2);
1280                 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", rep);
1281         }
1282
1283         if (!tree)
1284                 return offset;
1285                 
1286         proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
1287         offset += len +1;
1288                 
1289         len = tvb_reported_length_remaining(tvb,offset);
1290         if (len >= 8) {
1291                 /* optionnal password */
1292                 proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, 8,FALSE);
1293                 offset += 8;
1294         }
1295         return offset;
1296 }
1297
1298 /* -------------------------- */
1299 static gint
1300 dissect_reply_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1301 {
1302         guint16 bitmap;
1303         
1304         if (!tree)
1305                 return offset;
1306         bitmap = decode_vol_bitmap(tree, tvb, offset);
1307         offset += 2;
1308         offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
1309
1310         return offset;
1311 }
1312
1313 /* ************************** 
1314         next calls use the same format :
1315                 1 pad byte 
1316                 volume id
1317         AFP_FLUSH
1318         AFP_CLOSEVOL
1319         AFP_OPENDT
1320 */
1321 static gint
1322 dissect_query_afp_with_vol_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1323 {
1324
1325         if (!tree)
1326                 return offset;
1327         PAD(1);
1328         
1329         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1330         offset += 2;
1331         return offset;
1332 }
1333
1334 /* ************************** */
1335 static gint
1336 dissect_query_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1337 {
1338         proto_tree *sub_tree = NULL;
1339         proto_item *item;
1340
1341         proto_tree_add_item(tree, hf_afp_fork_type, tvb, offset, 1,FALSE);
1342         offset++;
1343
1344         offset = decode_vol_did(tree, tvb, offset);
1345         
1346         decode_file_bitmap(tree, tvb, offset);
1347         offset += 2;
1348         if (tree) {
1349                 item = proto_tree_add_item(tree, hf_afp_access_mode, tvb, offset, 2,FALSE);
1350                 sub_tree = proto_item_add_subtree(item, ett_afp_access_mode);
1351
1352                 proto_tree_add_item(sub_tree, hf_afp_access_read      , tvb, offset, 2,FALSE);
1353                 proto_tree_add_item(sub_tree, hf_afp_access_write     , tvb, offset, 2,FALSE);
1354                 proto_tree_add_item(sub_tree, hf_afp_access_deny_read , tvb, offset, 2,FALSE);
1355                 proto_tree_add_item(sub_tree, hf_afp_access_deny_write, tvb, offset, 2,FALSE);
1356         }
1357         offset += 2;
1358
1359         offset = decode_name(tree, pinfo, tvb, offset);
1360
1361         return offset;
1362 }
1363
1364 /* -------------------------- */
1365 static gint
1366 dissect_reply_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1367 {
1368         int f_bitmap;
1369
1370         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1371         offset += 2;
1372
1373         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1374         offset += 2;
1375
1376         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1377
1378         return offset;
1379 }
1380
1381 /* ************************** */
1382 static gint
1383 dissect_query_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1384 {
1385         
1386         PAD(1);
1387         offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
1388
1389         proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
1390         offset += 2;
1391
1392         proto_tree_add_item(tree, hf_afp_start_index, tvb, offset, 2,FALSE);
1393         offset += 2;
1394
1395         proto_tree_add_item(tree, hf_afp_max_reply_size, tvb, offset, 2,FALSE);
1396         offset += 2;
1397
1398         offset = decode_name(tree, pinfo, tvb, offset);
1399
1400         return offset;
1401 }
1402
1403 /* -------------------------- */
1404 static gint
1405 dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1406 {
1407         proto_tree *sub_tree = NULL;
1408         proto_item *item;
1409         int count;
1410         int f_bitmap;
1411         int d_bitmap;
1412         guint8  flags;
1413         guint8  size;
1414         gint    org;
1415         int i;
1416         gchar *name;
1417         
1418         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1419         offset += 2;
1420         
1421         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
1422         offset += 2;
1423
1424         count = tvb_get_ntohs(tvb, offset);
1425         if (tree) {
1426                 item = proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
1427                 sub_tree = proto_item_add_subtree(item, ett_afp_enumerate);
1428         }
1429         offset += 2;
1430         /* loop */
1431         for (i = 0; i < count; i++) {
1432                 org = offset;
1433                 name = NULL;
1434                 size = tvb_get_guint8(tvb, offset);
1435                 flags = tvb_get_guint8(tvb, offset +1);
1436
1437                 if (sub_tree) {
1438                         if (flags) {
1439                                 name = name_in_dbitmap(tvb, offset +2, d_bitmap);
1440                         }       
1441                         else {
1442                                 name = name_in_fbitmap(tvb, offset +2, f_bitmap);
1443                         }
1444                         if (!name) {
1445                                 if (!(name = g_malloc(50))) { /* no memory ! */
1446                                 }
1447                                 snprintf(name, 50,"line %d", i +1);
1448                         }
1449                         item = proto_tree_add_text(sub_tree, tvb, offset, size, name);
1450                         tree = proto_item_add_subtree(item, ett_afp_enumerate_line);
1451                 }
1452                 proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
1453                 offset++;
1454
1455                 proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
1456                 offset++;
1457                 if (flags) {
1458                         offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
1459                 }
1460                 else {
1461                         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1462                 }
1463                 if ((offset & 1)) 
1464                         PAD(1);
1465                 offset = org +size;             /* play safe */
1466                 if (sub_tree)
1467                         g_free((gpointer)name);
1468         }       
1469         return(offset);
1470
1471 }
1472
1473 /* **************************/
1474 static gint
1475 dissect_query_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1476 {
1477         PAD(1)
1478         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1479         offset += 2;
1480
1481         decode_vol_bitmap(tree, tvb, offset);
1482         offset += 2;
1483         
1484         return offset;  
1485 }
1486
1487 /* ------------------------ */
1488 static gint
1489 dissect_reply_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1490 {
1491         guint16 bitmap;
1492
1493         bitmap = decode_vol_bitmap(tree, tvb, offset);
1494         offset += 2;
1495
1496         offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
1497
1498         return offset;
1499 }
1500
1501 /* **************************/
1502 static gint
1503 dissect_query_afp_set_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1504 {
1505         guint16 bitmap;
1506
1507         PAD(1)
1508         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1509         offset += 2;
1510
1511         bitmap = decode_vol_bitmap(tree, tvb, offset);
1512         offset += 2;
1513         
1514         offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
1515
1516         return offset;  
1517 }
1518
1519 /* ***************************/
1520 static gint
1521 dissect_query_afp_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1522 {
1523         int len;
1524     const char *uam;
1525     
1526         len = tvb_get_guint8(tvb, offset);
1527         proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
1528         offset += len +1;
1529         len = tvb_get_guint8(tvb, offset);
1530         uam = tvb_get_ptr(tvb, offset +1, len);
1531         proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
1532         offset += len +1;
1533
1534         if (!strncmp(uam, "Cleartxt passwrd", len)) {
1535                 /* clear text */
1536                 len = tvb_get_guint8(tvb, offset);
1537                 proto_tree_add_item(tree, hf_afp_user, tvb, offset, 1,FALSE);
1538                 offset += len +1;
1539
1540                 len = tvb_strsize(tvb, offset);
1541                 proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
1542                 offset += len;
1543         }
1544         else if (!strncmp(uam, "No User Authent", len)) {
1545         }
1546         return(offset);
1547 }
1548
1549 /* ************************** */
1550 static gint
1551 dissect_query_afp_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1552 {
1553         int len;
1554         
1555         proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
1556         offset += 1;
1557
1558         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1559         offset += 2;
1560
1561         proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
1562         offset += 4;
1563
1564         proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
1565         offset += 4;
1566
1567         return offset;
1568 }
1569
1570 static gint
1571 dissect_reply_afp_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1572 {
1573         proto_tree_add_item(tree, hf_afp_last_written, tvb, offset, 4, FALSE);
1574         offset += 4;
1575         
1576         return offset;
1577 }
1578
1579 /* ************************** */
1580 static gint
1581 dissect_query_afp_read(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1582 {
1583         int len;
1584         
1585         PAD(1);
1586         
1587         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1588         offset += 2;
1589
1590         proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
1591         offset += 4;
1592
1593         proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
1594         offset += 4;
1595
1596         /* FIXME */
1597         offset++;
1598         
1599         offset++;
1600         return offset;
1601 }
1602
1603 /* ************************** 
1604    Open desktop call 
1605    query is the same than       AFP_FLUSH, AFP_CLOSEVOL
1606
1607 */
1608 static gint
1609 dissect_reply_afp_open_dt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1610 {
1611         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
1612         offset += 2;
1613
1614         return offset;
1615 }
1616
1617 /* ************************** 
1618         no reply
1619 */
1620 static gint
1621 dissect_query_afp_close_dt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1622 {
1623         PAD(1);
1624         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
1625         offset += 2;
1626
1627         return offset;
1628 }
1629
1630 /* ************************** 
1631         calls using the same format :
1632                 1 pad byte 
1633                 fork number 
1634         AFP_FLUSHFORK
1635         AFP_CLOSEFORK
1636 */
1637 static gint
1638 dissect_query_afp_with_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1639 {
1640         PAD(1);
1641         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1642         offset += 2;
1643
1644         return offset;
1645 }
1646
1647 /* ************************** */
1648 static gint
1649 dissect_query_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1650 {
1651         PAD(1);
1652         offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
1653
1654         offset = decode_name(tree, pinfo, tvb, offset);
1655
1656         return offset;
1657 }
1658
1659 /* -------------------------- */
1660 static gint
1661 dissect_reply_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1662 {
1663         guint8  flags;
1664         guint16 f_bitmap, d_bitmap;
1665
1666         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1667         offset += 2;
1668         
1669         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
1670         offset += 2;
1671
1672         flags = tvb_get_guint8(tvb, offset);
1673         proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
1674         offset++;
1675         PAD(1);
1676         if (flags) {
1677                 offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
1678         }
1679         else {
1680                 offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1681         }
1682         return offset;
1683 }
1684
1685 /* ************************** 
1686         no reply
1687 */
1688 static gint
1689 dissect_query_afp_set_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1690 {
1691         guint16 f_bitmap;
1692         
1693         PAD(1);
1694         offset = decode_vol_did(tree, tvb, offset);
1695
1696         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1697         offset += 2;
1698         
1699         offset = decode_name(tree, pinfo, tvb, offset);
1700
1701         if ((offset & 1))
1702                 PAD(1);
1703         /* did:name can be a file or a folder but only the intersection between 
1704          * file bitmap and dir bitmap can be set
1705          */
1706         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 1);
1707
1708         return offset;
1709 }
1710
1711 /* ************************** 
1712         no reply
1713 */
1714 static gint
1715 dissect_query_afp_set_file_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1716 {
1717         guint16 f_bitmap;
1718         
1719         PAD(1);
1720         offset = decode_vol_did(tree, tvb, offset);
1721
1722         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1723         offset += 2;
1724         
1725         offset = decode_name(tree, pinfo, tvb, offset);
1726
1727         if ((offset & 1))
1728                 PAD(1);
1729         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 0);
1730
1731         return offset;
1732 }
1733
1734 /* ************************** 
1735         no reply
1736 */
1737 static gint
1738 dissect_query_afp_set_dir_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1739 {
1740         guint16 d_bitmap;
1741
1742         PAD(1);
1743         offset = decode_vol_did(tree, tvb, offset);
1744
1745         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
1746         offset += 2;
1747         
1748         offset = decode_name(tree, pinfo, tvb, offset);
1749
1750         if ((offset & 1))
1751                 PAD(1);
1752         offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
1753
1754         offset += 4;
1755         return offset;
1756 }
1757
1758 /* **************************
1759         AFP_DELETE
1760         AFP_CREATE_DIR
1761  */
1762 static gint
1763 dissect_query_afp_create_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1764 {
1765         PAD(1);
1766         offset = decode_vol_did(tree, tvb, offset);
1767
1768         offset = decode_name(tree, pinfo, tvb, offset);
1769         return offset;
1770 }
1771
1772 /* -------------------------- 
1773         AFP_MOVE
1774 */
1775 static gint
1776 dissect_reply_afp_create_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1777 {
1778         proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
1779         offset += 4;
1780         
1781         return offset;
1782 }
1783
1784 /* -------------------------- */
1785 static gint
1786 dissect_reply_afp_create_dir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1787 {
1788         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1789         offset += 4;
1790         
1791         return offset;
1792 }
1793
1794 /* ************************** 
1795         no reply
1796 */
1797 static gint
1798 dissect_query_afp_delete_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1799 {
1800         PAD(1);
1801         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1802         offset += 2;
1803         proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
1804         offset += 4;
1805         
1806         return offset;
1807 }
1808
1809 /* ************************** 
1810         same reply as get_fork_param
1811 */
1812 static gint
1813 dissect_query_afp_resolve_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1814 {
1815         PAD(1);
1816         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1817         offset += 2;
1818         proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
1819         offset += 4;
1820
1821         decode_file_bitmap(tree, tvb, offset);
1822         offset += 2;
1823
1824         return offset;
1825 }
1826
1827 /* ************************** */
1828 static gint
1829 dissect_query_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1830 {
1831
1832         PAD(1);
1833         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1834         offset += 2;
1835
1836         decode_file_bitmap(tree, tvb, offset);
1837         offset += 2;
1838         return offset;
1839 }
1840
1841 /* -------------------------- */
1842 static gint
1843 dissect_reply_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1844 {
1845         guint16 f_bitmap;
1846
1847         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1848         offset += 2;
1849
1850         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1851
1852         return offset;
1853 }
1854
1855 /* ************************** */
1856 static gint
1857 dissect_query_afp_set_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1858 {
1859
1860         PAD(1);
1861         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1862         offset += 2;
1863
1864         decode_file_bitmap(tree, tvb, offset);
1865         offset += 2;
1866
1867         proto_tree_add_item(tree, hf_afp_ofork_len, tvb, offset, 4,FALSE);
1868         offset += 4;
1869         return offset;
1870 }
1871
1872 /* ************************** */
1873 static gint
1874 dissect_query_afp_move(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1875 {
1876                 
1877         PAD(1);
1878         offset = decode_vol_did(tree, tvb, offset);
1879
1880         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1881         offset += 4;
1882
1883         offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
1884         offset = decode_name_label(tree, NULL, tvb, offset,  "Dest dir:    %s");
1885         offset = decode_name_label(tree, NULL, tvb, offset,  "New name:    %s");
1886
1887         return offset;
1888 }
1889
1890 /* ************************** */
1891 static gint
1892 dissect_query_afp_rename(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1893 {
1894                 
1895         PAD(1);
1896         offset = decode_vol_did(tree, tvb, offset);
1897
1898         offset = decode_name_label(tree, pinfo, tvb, offset, "Old name:     %s");
1899         offset = decode_name_label(tree, NULL, tvb, offset,  "New name:     %s");
1900
1901         return offset;
1902 }
1903
1904 /* ************************** */
1905 static gint
1906 dissect_query_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1907 {
1908         proto_tree *sub_tree = NULL;
1909         proto_item *item;
1910         guint8 flag;
1911         
1912         flag = tvb_get_guint8(tvb, offset);
1913         if (tree) {
1914                 item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
1915                 sub_tree = proto_item_add_subtree(item, ett_afp_lock_flags);
1916         }
1917
1918         proto_tree_add_item(sub_tree, hf_afp_lock_op, tvb, offset, 1,FALSE);
1919         proto_tree_add_item(sub_tree, hf_afp_lock_from, tvb, offset, 1,FALSE);
1920         offset += 1;
1921
1922         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1923         offset += 2;
1924         
1925         proto_tree_add_item(tree, hf_afp_lock_offset, tvb, offset, 4,FALSE);
1926         offset += 4;
1927
1928         proto_tree_add_item(tree, hf_afp_lock_len, tvb, offset, 4,FALSE);
1929         offset += 4;
1930         return offset;
1931 }
1932
1933 /* -------------------------- */
1934 static gint
1935 dissect_reply_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1936 {
1937         proto_tree_add_item(tree, hf_afp_lock_range_start, tvb, offset, 4,FALSE);
1938         offset += 4;
1939
1940         return offset;
1941 }
1942
1943 /* ************************** */
1944 static gint
1945 dissect_query_afp_add_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1946 {
1947         guint8 len;
1948
1949         PAD(1);
1950         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
1951         offset += 2;
1952
1953         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1954         offset += 4;
1955
1956         offset = decode_name(tree, pinfo, tvb, offset);
1957
1958         if ((offset & 1)) 
1959                 PAD(1);
1960
1961         len = tvb_get_guint8(tvb, offset);
1962         proto_tree_add_item(tree, hf_afp_comment, tvb, offset, 1,FALSE);
1963         offset += len +1;
1964
1965         return offset;
1966 }
1967
1968
1969 /* ************************** */
1970 static gint
1971 dissect_query_afp_get_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1972 {
1973
1974         PAD(1);
1975         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
1976         offset += 2;
1977
1978         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1979         offset += 4;
1980
1981         offset = decode_name(tree, pinfo, tvb, offset);
1982         return offset;
1983 }
1984
1985 /* -------------------------- */
1986 static gint
1987 dissect_reply_afp_get_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1988 {
1989         guint8 len;
1990
1991         len = tvb_get_guint8(tvb, offset);
1992         proto_tree_add_item(tree, hf_afp_comment, tvb, offset, 1,FALSE);
1993         offset += len +1;
1994
1995         return offset;
1996 }
1997
1998 /* ************************** */
1999 static gint
2000 dissect_query_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2001 {
2002
2003         PAD(1);
2004         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2005         offset += 2;
2006         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2007         offset += 4;
2008
2009         proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
2010         offset += 4;
2011         
2012         proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
2013         offset += 1;
2014         PAD(1);
2015
2016         proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
2017         offset += 2;
2018
2019         return offset;
2020 }
2021
2022 /* -------------------------- 
2023         fallback to data in afp dissector
2024 */
2025 static gint
2026 dissect_reply_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2027 {
2028         return offset;
2029 }
2030
2031 /* ************************** */
2032 static gint
2033 dissect_query_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2034 {
2035
2036         PAD(1);
2037         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2038         offset += 2;
2039         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2040         offset += 4;
2041
2042         proto_tree_add_item(tree, hf_afp_icon_index, tvb, offset, 2,FALSE);
2043         offset += 2;
2044
2045         return offset;
2046 }
2047
2048 /* -------------------------- */
2049 static gint
2050 dissect_reply_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2051 {
2052
2053         proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
2054         offset += 4;
2055
2056         proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
2057         offset += 4;
2058         
2059         proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
2060         offset += 1;
2061
2062         PAD(1);
2063         proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
2064         offset += 2;
2065
2066         return offset;
2067 }
2068
2069 /* ************************** */
2070 static gint
2071 dissect_query_afp_add_icon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2072 {
2073
2074         PAD(1);
2075         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2076         offset += 2;
2077         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2078         offset += 4;
2079
2080         proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
2081         offset += 4;
2082         
2083         proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
2084         offset += 1;
2085         
2086         PAD(1);
2087         proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
2088         offset += 4;
2089         
2090         proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
2091         offset += 2;
2092
2093         return offset;
2094 }
2095
2096 /* ************************** 
2097         no reply
2098 */
2099 static gint
2100 dissect_query_afp_add_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2101 {
2102
2103         PAD(1);
2104         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2105         offset += 2;
2106
2107         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2108         offset += 4;
2109
2110         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2111         offset += 4;
2112
2113         proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
2114         offset += 4;
2115         
2116         offset = decode_name(tree, pinfo, tvb, offset);
2117
2118         return offset;
2119 }
2120
2121 /* ************************** 
2122         no reply
2123 */
2124 static gint
2125 dissect_query_afp_rmv_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2126 {
2127
2128         PAD(1);
2129         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2130         offset += 2;
2131
2132         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2133         offset += 4;
2134
2135         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2136         offset += 4;
2137
2138         offset = decode_name(tree, pinfo, tvb, offset);
2139
2140         return offset;
2141 }
2142
2143 /* ************************** */
2144 static gint
2145 dissect_query_afp_get_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2146 {
2147
2148         PAD(1);
2149         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2150         offset += 2;
2151
2152         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2153         offset += 4;
2154
2155         proto_tree_add_item(tree, hf_afp_appl_index, tvb, offset, 2,FALSE);
2156         offset += 2;
2157
2158         decode_file_bitmap(tree, tvb, offset);
2159         offset += 2;
2160
2161         return offset;
2162 }
2163
2164 /* -------------------------- */
2165 static gint
2166 dissect_reply_afp_get_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2167 {
2168         proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
2169         offset += 4;
2170
2171         return offset;
2172 }
2173
2174 /* ************************** */
2175 static gint
2176 dissect_query_afp_create_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2177 {
2178         proto_tree_add_item(tree, hf_afp_create_flag, tvb, offset, 1,FALSE);
2179         offset++;
2180
2181         offset = decode_vol_did(tree, tvb, offset);
2182
2183         offset = decode_name(tree, pinfo, tvb, offset);
2184
2185         return offset;
2186 }
2187
2188 /* -------------------------- */
2189 static gint
2190 dissect_reply_afp_create_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2191 {
2192         return offset;
2193 }
2194
2195 /* ************************** */
2196 static void
2197 dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2198 {
2199         struct aspinfo *aspinfo = pinfo->private_data;
2200         proto_tree      *afp_tree = NULL;
2201         proto_item      *ti;
2202         conversation_t  *conversation;
2203         gint            offset = 0;
2204         afp_request_key request_key, *new_request_key;
2205         afp_request_val *request_val;
2206
2207         gchar   *func_str;
2208
2209         guint8  afp_command;
2210         guint16 afp_requestid;
2211         gint32  afp_code;
2212         guint32 afp_length;
2213         guint32 afp_reserved;
2214         int     len =  tvb_reported_length_remaining(tvb,0);
2215         
2216         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2217                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFP");
2218         if (check_col(pinfo->cinfo, COL_INFO))
2219                 col_clear(pinfo->cinfo, COL_INFO);
2220
2221         conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
2222                 pinfo->srcport, pinfo->destport, 0);
2223
2224         if (conversation == NULL)
2225         {
2226                 conversation = conversation_new(&pinfo->src, &pinfo->dst,
2227                         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2228         }
2229
2230         request_key.conversation = conversation->index; 
2231         request_key.seq = aspinfo->seq;
2232
2233         request_val = (afp_request_val *) g_hash_table_lookup(
2234                                                                 afp_request_hash, &request_key);
2235
2236         if (!request_val && !aspinfo->reply)  {
2237                 afp_command = tvb_get_guint8(tvb, offset);
2238                 new_request_key = g_mem_chunk_alloc(afp_request_keys);
2239                 *new_request_key = request_key;
2240
2241                 request_val = g_mem_chunk_alloc(afp_request_vals);
2242                 request_val->command = tvb_get_guint8(tvb, offset);
2243
2244                 g_hash_table_insert(afp_request_hash, new_request_key,
2245                                                                 request_val);
2246         }
2247
2248         if (!request_val) {     /* missing request */
2249                 return;
2250         }
2251
2252         afp_command = request_val->command;
2253         if (check_col(pinfo->cinfo, COL_INFO)) {
2254                 gchar   *func_str;
2255
2256                 if ((func_str = match_strval(afp_command, CommandCode_vals)))
2257                 {
2258                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", func_str, aspinfo->reply?"reply":"");
2259                 }
2260         }
2261
2262         if (tree)
2263         {
2264                 ti = proto_tree_add_item(tree, proto_afp, tvb, offset, -1,FALSE);
2265                 afp_tree = proto_item_add_subtree(ti, ett_afp);
2266         }
2267         if (!aspinfo->reply)  {
2268                 proto_tree_add_uint(afp_tree, hf_afp_command, tvb,offset, 1, afp_command);
2269                 offset++;
2270                 switch(afp_command) {
2271                 case AFP_BYTELOCK:
2272                         offset = dissect_query_afp_byte_lock(tvb, pinfo, afp_tree, offset);break; 
2273                 case AFP_OPENDT:        /* same as close vol */
2274                 case AFP_FLUSH:         
2275                 case AFP_CLOSEVOL:
2276                         offset = dissect_query_afp_with_vol_id(tvb, pinfo, afp_tree, offset);break;
2277                 case AFP_CLOSEDIR:
2278                         /* offset = dissect_query_afp_close_dir(tvb, pinfo, afp_tree, offset);break; */
2279                         break;
2280                 case AFP_CLOSEDT:       
2281                         offset = dissect_query_afp_close_dt(tvb, pinfo, afp_tree, offset);break;
2282                 case AFP_FLUSHFORK: /* same packet as closefork */
2283                 case AFP_CLOSEFORK:
2284                         offset = dissect_query_afp_with_fork(tvb, pinfo, afp_tree, offset);break;
2285                 case AFP_COPYFILE:
2286                         /* offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break; */
2287                 case AFP_CREATEFILE:
2288                         offset = dissect_query_afp_create_file(tvb, pinfo, afp_tree, offset);break; 
2289                 case AFP_ENUMERATE:
2290                         offset = dissect_query_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
2291                 case AFP_GETFORKPARAM:
2292                         offset = dissect_query_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break; 
2293                 case AFP_GETSRVINFO:
2294                         /* offset = dissect_query_afp_get_server_info(tvb, pinfo, afp_tree, offset);break; */
2295                 case AFP_GETSRVPARAM:
2296                         break;                                  /* no parameters */
2297                 case AFP_GETVOLPARAM:
2298                         offset = dissect_query_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
2299                 case AFP_LOGIN:
2300                         offset = dissect_query_afp_login(tvb, pinfo, afp_tree, offset);break;
2301                 case AFP_LOGINCONT:
2302                 case AFP_LOGOUT:
2303                 case AFP_MAPID:
2304                 case AFP_MAPNAME:
2305                         break;
2306                 case AFP_MOVE:
2307                         offset = dissect_query_afp_move(tvb, pinfo, afp_tree, offset);break;
2308                 case AFP_OPENVOL:
2309                         offset = dissect_query_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
2310                 case AFP_OPENDIR:
2311                         break;
2312                 case AFP_OPENFORK:
2313                         offset = dissect_query_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
2314                 case AFP_READ:
2315                         offset = dissect_query_afp_read(tvb, pinfo, afp_tree, offset);break;
2316                 case AFP_RENAME:
2317                         offset = dissect_query_afp_rename(tvb, pinfo, afp_tree, offset);break;
2318                 case AFP_SETDIRPARAM:
2319                         offset = dissect_query_afp_set_dir_param(tvb, pinfo, afp_tree, offset);break; 
2320                 case AFP_SETFILEPARAM:
2321                         offset = dissect_query_afp_set_file_param(tvb, pinfo, afp_tree, offset);break; 
2322                 case AFP_SETFORKPARAM:
2323                         offset = dissect_query_afp_set_fork_param(tvb, pinfo, afp_tree, offset);break; 
2324                 case AFP_SETVOLPARAM:
2325                         offset = dissect_query_afp_set_vol_param(tvb, pinfo, afp_tree, offset);break;
2326                 case AFP_WRITE:
2327                         offset = dissect_query_afp_write(tvb, pinfo, afp_tree, offset);break;
2328                 case AFP_GETFLDRPARAM:
2329                         offset = dissect_query_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
2330                 case AFP_SETFLDRPARAM:
2331                         offset = dissect_query_afp_set_fldr_param(tvb, pinfo, afp_tree, offset);break;
2332                 case AFP_CHANGEPW:
2333                 case AFP_GETSRVRMSG:
2334                         break;
2335                 case AFP_DELETE:        /* same as create_id */
2336                 case AFP_CREATEDIR:
2337                 case AFP_CREATEID:
2338                         offset = dissect_query_afp_create_id(tvb, pinfo, afp_tree, offset);break; 
2339                 case AFP_DELETEID:
2340                         offset = dissect_query_afp_delete_id(tvb, pinfo, afp_tree, offset);break; 
2341                 case AFP_RESOLVEID:
2342                         offset = dissect_query_afp_resolve_id(tvb, pinfo, afp_tree, offset);break; 
2343                 case AFP_EXCHANGEFILE:
2344                 case AFP_CATSEARCH:
2345                         break;
2346                 case AFP_GETICON:
2347                         offset = dissect_query_afp_get_icon(tvb, pinfo, afp_tree, offset);break; 
2348                 case AFP_GTICNINFO:
2349                         offset = dissect_query_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
2350                 case AFP_ADDAPPL:
2351                         offset = dissect_query_afp_add_appl(tvb, pinfo, afp_tree, offset);break; 
2352                 case AFP_RMVAPPL:
2353                         offset = dissect_query_afp_rmv_appl(tvb, pinfo, afp_tree, offset);break; 
2354                 case AFP_GETAPPL:
2355                         offset = dissect_query_afp_get_appl(tvb, pinfo, afp_tree, offset);break; 
2356                 case AFP_ADDCMT:
2357                         offset = dissect_query_afp_add_cmt(tvb, pinfo, afp_tree, offset);break; 
2358                 case AFP_RMVCMT: /* same as get_cmt */
2359                 case AFP_GETCMT:
2360                         offset = dissect_query_afp_get_cmt(tvb, pinfo, afp_tree, offset);break; 
2361                 case AFP_ADDICON:
2362                         offset = dissect_query_afp_add_icon(tvb, pinfo, afp_tree, offset);break; 
2363                         break;
2364                 }
2365         }
2366         else {
2367                 switch(afp_command) {
2368                 case AFP_BYTELOCK:
2369                         offset = dissect_reply_afp_byte_lock(tvb, pinfo, afp_tree, offset);break; 
2370                 case AFP_ENUMERATE:
2371                         offset = dissect_reply_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
2372                 case AFP_OPENVOL:
2373                         offset = dissect_reply_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
2374                 case AFP_OPENFORK:
2375                         offset = dissect_reply_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
2376                 case AFP_RESOLVEID:
2377                 case AFP_GETFORKPARAM:
2378                         offset =dissect_reply_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break;
2379                 case AFP_GETSRVINFO:
2380                 case AFP_GETSRVPARAM:
2381                         break;
2382                 case AFP_CREATEDIR:
2383                         offset = dissect_reply_afp_create_dir(tvb, pinfo, afp_tree, offset);break; 
2384                 case AFP_MOVE:          /* same as create_id */
2385                 case AFP_CREATEID:
2386                         offset = dissect_reply_afp_create_id(tvb, pinfo, afp_tree, offset);break; 
2387                 case AFP_GETVOLPARAM:
2388                         offset = dissect_reply_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
2389                 case AFP_GETFLDRPARAM:
2390                         offset = dissect_reply_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
2391                 case AFP_OPENDT:
2392                         offset = dissect_reply_afp_open_dt(tvb, pinfo, afp_tree, offset);break;
2393                 case AFP_GETICON:
2394                         offset = dissect_reply_afp_get_icon(tvb, pinfo, afp_tree, offset);break; 
2395                 case AFP_GTICNINFO:
2396                         offset = dissect_reply_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
2397                 case AFP_GETAPPL:
2398                         offset = dissect_reply_afp_get_appl(tvb, pinfo, afp_tree, offset);break; 
2399                 case AFP_GETCMT:
2400                         offset = dissect_reply_afp_get_cmt(tvb, pinfo, afp_tree, offset);break; 
2401                 case AFP_WRITE:
2402                         offset = dissect_reply_afp_write(tvb, pinfo, afp_tree, offset);break;
2403                 }
2404         }
2405         if (tree && offset < len)
2406                 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, afp_tree);
2407 }
2408
2409 static void afp_reinit( void)
2410 {
2411
2412         if (afp_request_hash)
2413                 g_hash_table_destroy(afp_request_hash);
2414         if (afp_request_keys)
2415                 g_mem_chunk_destroy(afp_request_keys);
2416         if (afp_request_vals)
2417                 g_mem_chunk_destroy(afp_request_vals);
2418
2419         afp_request_hash = g_hash_table_new(afp_hash, afp_equal);
2420
2421         afp_request_keys = g_mem_chunk_new("afp_request_keys",
2422                 sizeof(afp_request_key),
2423                 afp_packet_init_count * sizeof(afp_request_key),
2424                 G_ALLOC_AND_FREE);
2425         afp_request_vals = g_mem_chunk_new("afp_request_vals",
2426                 sizeof(afp_request_val),
2427                 afp_packet_init_count * sizeof(afp_request_val),
2428                 G_ALLOC_AND_FREE);
2429
2430 }
2431
2432 void
2433 proto_register_afp(void)
2434 {
2435
2436   static hf_register_info hf[] = {
2437     { &hf_afp_command,
2438       { "Command",      "afp.command",
2439                 FT_UINT8, BASE_DEC, VALS(CommandCode_vals), 0x0,
2440         "AFP function", HFILL }},
2441
2442     { &hf_afp_pad,    
2443       { "Pad",          "afp.pad",    
2444                 FT_NONE,   BASE_NONE, NULL, 0, 
2445         "Pad Byte",     HFILL }},
2446
2447     { &hf_afp_AFPVersion,
2448       { "AFP Version",  "afp.AFPVersion",
2449                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2450         "Client AFP version", HFILL }},
2451
2452     { &hf_afp_UAM,
2453       { "UAM",          "afp.UAM",
2454                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2455         "User Authentication Method", HFILL }},
2456
2457     { &hf_afp_user,
2458       { "User",         "afp.user",
2459                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2460         "User", HFILL }},
2461
2462     { &hf_afp_passwd,
2463       { "Password",     "afp.passwd",
2464                 FT_STRINGZ, BASE_NONE, NULL, 0x0,
2465         "Password", HFILL }},
2466
2467     { &hf_afp_vol_bitmap,
2468       { "Bitmap",         "afp.vol_bitmap",
2469                 FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
2470         "Volume bitmap", HFILL }},
2471
2472     { &hf_afp_vol_bitmap_Attributes,
2473       { "Attributes",      "afp.vol_bitmap.attributes",
2474                 FT_BOOLEAN, 16, NULL, kFPVolAttributeBit,
2475         "Volume attributes", HFILL }},
2476
2477     { &hf_afp_vol_attribute,
2478       { "Attributes",         "afp.vol_attribute",
2479                 FT_UINT16, BASE_HEX, NULL, 0,
2480         "Volume attributes", HFILL }},
2481
2482     { &hf_afp_vol_attribute_ReadOnly, 
2483       { "Read only",         "afp.vol_attribute.read_only",
2484                  FT_BOOLEAN, 16, NULL, kReadOnly,
2485         "Read only volume", HFILL }},
2486
2487     { &hf_afp_vol_attribute_HasVolumePassword,
2488       { "Volume password",         "afp.vol_attribute.passwd",
2489                  FT_BOOLEAN, 16, NULL, kHasVolumePassword,
2490         "Has a volume password", HFILL }},
2491
2492     { &hf_afp_vol_attribute_SupportsFileIDs,
2493       { "File IDs",         "afp.vol_attribute.fileIDs",
2494                  FT_BOOLEAN, 16, NULL, kSupportsFileIDs,
2495         "Supports file IDs", HFILL }},
2496
2497     { &hf_afp_vol_attribute_SupportsCatSearch,
2498       { "Catalog search",         "afp.vol_attribute.cat_search",
2499                  FT_BOOLEAN, 16, NULL, kSupportsCatSearch,
2500         "Supports catalog search operations", HFILL }},
2501
2502     { &hf_afp_vol_attribute_SupportsBlankAccessPrivs,
2503       { "Blank access privileges",         "afp.vol_attribute.blank_access_privs",
2504                  FT_BOOLEAN, 16, NULL, kSupportsBlankAccessPrivs,
2505         "Supports blank access privileges", HFILL }},
2506
2507     { &hf_afp_vol_attribute_SupportsUnixPrivs,
2508       { "UNIX access privileges",         "afp.vol_attribute.unix_privs",
2509                  FT_BOOLEAN, 16, NULL, kSupportsUnixPrivs,
2510         "Supports UNIX access privileges", HFILL }},
2511
2512     { &hf_afp_vol_attribute_SupportsUTF8Names,
2513       { "UTF-8 names",         "afp.vol_attribute.utf8_names",
2514                  FT_BOOLEAN, 16, NULL, kSupportsUTF8Names,
2515         "Supports UTF-8 names", HFILL }},
2516
2517     { &hf_afp_vol_bitmap_Signature,
2518       { "Signature",         "afp.vol_bitmap.signature",
2519                 FT_BOOLEAN, 16, NULL, kFPVolSignatureBit,
2520         "Volume signature", HFILL }},
2521
2522     { &hf_afp_vol_bitmap_CreateDate,
2523       { "Creation date",      "afp.vol_bitmap.create_date",
2524                 FT_BOOLEAN, 16, NULL, kFPVolCreateDateBit,
2525         "Volume creation date", HFILL }},
2526
2527     { &hf_afp_vol_bitmap_ModDate,
2528       { "Modification date",  "afp.vol_bitmap.mod_date",
2529                 FT_BOOLEAN, 16, NULL, kFPVolModDateBit,
2530         "Volume modification date", HFILL }},
2531
2532     { &hf_afp_vol_bitmap_BackupDate,
2533       { "Backup date",        "afp.vol_bitmap.backup_date",
2534                 FT_BOOLEAN, 16, NULL, kFPVolBackupDateBit,
2535         "Volume backup date", HFILL }},
2536
2537     { &hf_afp_vol_bitmap_ID,
2538       { "ID",         "afp.vol_bitmap.id",
2539                 FT_BOOLEAN, 16, NULL,  kFPVolIDBit,
2540         "Volume ID", HFILL }},
2541
2542     { &hf_afp_vol_bitmap_BytesFree,
2543       { "Bytes free",         "afp.vol_bitmap.bytes_free",
2544                 FT_BOOLEAN, 16, NULL,  kFPVolBytesFreeBit,
2545         "Volume free bytes", HFILL }},
2546
2547     { &hf_afp_vol_bitmap_BytesTotal,
2548       { "Bytes total",         "afp.vol_bitmap.bytes_total",
2549                 FT_BOOLEAN, 16, NULL,  kFPVolBytesTotalBit,
2550         "Volume total bytes", HFILL }},
2551
2552     { &hf_afp_vol_bitmap_Name,
2553       { "Name",         "afp.vol_bitmap.name",
2554                 FT_BOOLEAN, 16, NULL,  kFPVolNameBit,
2555         "Volume name", HFILL }},
2556
2557     { &hf_afp_vol_bitmap_ExtBytesFree,
2558       { "Extended bytes free",         "afp.vol_bitmap.ex_bytes_free",
2559                 FT_BOOLEAN, 16, NULL,  kFPVolExtBytesFreeBit,
2560         "Volume extended (>2GB) free bytes", HFILL }},
2561
2562     { &hf_afp_vol_bitmap_ExtBytesTotal,
2563       { "Extended bytes total",         "afp.vol_bitmap.ex_bytes_total",
2564                 FT_BOOLEAN, 16, NULL,  kFPVolExtBytesTotalBit,
2565         "Volume extended (>2GB) total bytes", HFILL }},
2566
2567     { &hf_afp_vol_bitmap_BlockSize,
2568       { "Block size",         "afp.vol_bitmap.block_size",
2569                 FT_BOOLEAN, 16, NULL,  kFPVolBlockSizeBit,
2570         "Volume block size", HFILL }},
2571
2572     { &hf_afp_dir_bitmap_Attributes,        
2573       { "Attributes",         "afp.dir_bitmap.attributes",
2574             FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
2575         "Return attributes if directory", HFILL }},
2576
2577     { &hf_afp_dir_bitmap_ParentDirID,      
2578       { "DID",         "afp.dir_bitmap.did",
2579         FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
2580         "Return parent directory ID if directory", HFILL }},
2581
2582     { &hf_afp_dir_bitmap_CreateDate,       
2583       { "Creation date",         "afp.dir_bitmap.create_date",
2584             FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
2585         "Return creation date if directory", HFILL }},
2586
2587     { &hf_afp_dir_bitmap_ModDate,                  
2588       { "Modification date",         "afp.dir_bitmap.mod_date",
2589         FT_BOOLEAN, 16, NULL,  kFPModDateBit,
2590         "Return modification date if directory", HFILL }},
2591
2592     { &hf_afp_dir_bitmap_BackupDate,       
2593       { "Backup date",         "afp.dir_bitmap.backup_date",
2594             FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
2595         "Return backup date if directory", HFILL }},
2596
2597     { &hf_afp_dir_bitmap_FinderInfo,       
2598       { "Finder info",         "afp.dir_bitmap.finder_info",
2599         FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
2600         "Return finder info if directory", HFILL }},
2601
2602     { &hf_afp_dir_bitmap_LongName,                 
2603       { "Long name",         "afp.dir_bitmap.long_name",
2604             FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
2605         "Return long name if directory", HFILL }},
2606
2607     { &hf_afp_dir_bitmap_ShortName,                
2608       { "Short name",         "afp.dir_bitmap.short_name",
2609         FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
2610         "Return short name if directory", HFILL }},
2611
2612     { &hf_afp_dir_bitmap_NodeID,                   
2613       { "File ID",         "afp.dir_bitmap.fid",
2614             FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
2615         "Return file ID if directory", HFILL }},
2616
2617     { &hf_afp_dir_bitmap_OffspringCount,   
2618       { "Offspring count",         "afp.dir_bitmap.offspring_count",
2619         FT_BOOLEAN, 16, NULL,  kFPOffspringCountBit,
2620         "Return offspring count if directory", HFILL }},
2621
2622     { &hf_afp_dir_bitmap_OwnerID,                  
2623       { "Owner id",         "afp.dir_bitmap.owner_id",
2624             FT_BOOLEAN, 16, NULL,  kFPOwnerIDBit,
2625         "Return owner id if directory", HFILL }},
2626
2627     { &hf_afp_dir_bitmap_GroupID,                  
2628       { "Group id",         "afp.dir_bitmap.group_id",
2629         FT_BOOLEAN, 16, NULL,  kFPGroupIDBit,
2630         "Return group id if directory", HFILL }},
2631
2632     { &hf_afp_dir_bitmap_AccessRights,     
2633       { "Access rights",         "afp.dir_bitmap.access_rights",
2634             FT_BOOLEAN, 16, NULL,  kFPAccessRightsBit,
2635         "Return access rights if directory", HFILL }},
2636
2637     { &hf_afp_dir_bitmap_UTF8Name,                 
2638       { "UTF-8 name",         "afp.dir_bitmap.UTF8_name",
2639         FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
2640         "Return UTF-8 name if diectory", HFILL }},
2641
2642     { &hf_afp_dir_bitmap_UnixPrivs,                
2643       { "UNIX privileges",         "afp.dir_bitmap.unix_privs",
2644             FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit,
2645         "Return UNIX privileges if directory", HFILL }},
2646
2647     { &hf_afp_dir_attribute_Invisible,
2648       { "Invisible",         "afp.dir_attribute.invisible",
2649             FT_BOOLEAN, 16, NULL,  kFPInvisibleBit,
2650         "Directory is not visible", HFILL }},
2651
2652     { &hf_afp_dir_attribute_IsExpFolder,
2653       { "Share point",         "afp.dir_attribute.share",
2654             FT_BOOLEAN, 16, NULL,  kFPMultiUserBit,
2655         "Directory is a share point", HFILL }},
2656
2657     { &hf_afp_dir_attribute_System,
2658       { "System",                "afp.dir_attribute.system",
2659             FT_BOOLEAN, 16, NULL,  kFPSystemBit,
2660         "Directory is a system directory", HFILL }},
2661
2662     { &hf_afp_dir_attribute_Mounted,
2663       { "Mounted",         "afp.dir_attribute.mounted",
2664             FT_BOOLEAN, 16, NULL,  kFPDAlreadyOpenBit,
2665         "Directory is mounted", HFILL }},
2666
2667     { &hf_afp_dir_attribute_InExpFolder,
2668       { "Shared area",         "afp.dir_attribute.in_exported_folder",
2669             FT_BOOLEAN, 16, NULL,  kFPRAlreadyOpenBit,
2670         "Directory is in a shared area", HFILL }},
2671
2672     { &hf_afp_dir_attribute_BackUpNeeded,
2673       { "Backup needed",         "afp.dir_attribute.backup_needed",
2674             FT_BOOLEAN, 16, NULL,  kFPBackUpNeededBit,
2675         "Directory needs to be backed up", HFILL }},
2676
2677     { &hf_afp_dir_attribute_RenameInhibit,
2678       { "Rename inhibit",         "afp.dir_attribute.rename_inhibit",
2679             FT_BOOLEAN, 16, NULL,  kFPRenameInhibitBit,
2680         "Rename inhibit", HFILL }},
2681
2682     { &hf_afp_dir_attribute_DeleteInhibit,
2683       { "Delete inhibit",         "afp.dir_attribute.delete_inhibit",
2684             FT_BOOLEAN, 16, NULL,  kFPDeleteInhibitBit,
2685         "Delete inhibit", HFILL }},
2686
2687     { &hf_afp_dir_attribute_SetClear,
2688       { "Set",         "afp.dir_attribute.set_clear",
2689             FT_BOOLEAN, 16, NULL,  kFPSetClearBit,
2690         "Clear/set attribute", HFILL }},
2691
2692     { &hf_afp_file_bitmap_Attributes,
2693       { "Attributes",         "afp.file_bitmap.attributes",
2694             FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
2695         "Return attributes if file", HFILL }},
2696
2697     { &hf_afp_file_bitmap_ParentDirID,     
2698       { "DID",         "afp.file_bitmap.did",
2699         FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
2700         "Return parent directory ID if file", HFILL }},
2701
2702     { &hf_afp_file_bitmap_CreateDate,      
2703       { "Creation date",         "afp.file_bitmap.create_date",
2704             FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
2705         "Return creation date if file", HFILL }},
2706
2707     { &hf_afp_file_bitmap_ModDate,                 
2708       { "Modification date",         "afp.file_bitmap.mod_date",
2709         FT_BOOLEAN, 16, NULL,  kFPModDateBit,
2710         "Return modification date if file", HFILL }},
2711
2712     { &hf_afp_file_bitmap_BackupDate,      
2713       { "Backup date",         "afp.file_bitmap.backup_date",
2714             FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
2715         "Return backup date if file", HFILL }},
2716
2717     { &hf_afp_file_bitmap_FinderInfo,      
2718       { "Finder info",         "afp.file_bitmap.finder_info",
2719         FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
2720         "Return finder info if file", HFILL }},
2721
2722     { &hf_afp_file_bitmap_LongName,                
2723       { "Long name",         "afp.file_bitmap.long_name",
2724             FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
2725         "Return long name if file", HFILL }},
2726
2727     { &hf_afp_file_bitmap_ShortName,               
2728       { "Short name",         "afp.file_bitmap.short_name",
2729         FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
2730         "Return short name if file", HFILL }},
2731
2732     { &hf_afp_file_bitmap_NodeID,                  
2733       { "File ID",         "afp.file_bitmap.fid",
2734             FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
2735         "Return file ID if file", HFILL }},
2736
2737     { &hf_afp_file_bitmap_DataForkLen,
2738       { "Data fork size",         "afp.file_bitmap.data_fork_len",
2739             FT_BOOLEAN, 16, NULL,  kFPDataForkLenBit,
2740         "Return data fork size if file", HFILL }},
2741
2742     { &hf_afp_file_bitmap_RsrcForkLen,
2743       { "Resource fork size",         "afp.file_bitmap.resource_fork_len",
2744             FT_BOOLEAN, 16, NULL,  kFPRsrcForkLenBit,
2745         "Return resource fork size if file", HFILL }},
2746
2747     { &hf_afp_file_bitmap_ExtDataForkLen,
2748       { "Extended data fork size",         "afp.file_bitmap.ex_data_fork_len",
2749             FT_BOOLEAN, 16, NULL,  kFPExtDataForkLenBit,
2750         "Return extended (>2GB) data fork size if file", HFILL }},
2751
2752     { &hf_afp_file_bitmap_LaunchLimit,
2753       { "Launch limit",         "afp.file_bitmap.launch_limit",
2754             FT_BOOLEAN, 16, NULL,  kFPLaunchLimitBit,
2755         "Return launch limit if file", HFILL }},
2756
2757     { &hf_afp_file_bitmap_UTF8Name,                
2758       { "UTF-8 name",         "afp.file_bitmap.UTF8_name",
2759         FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
2760         "Return UTF-8 name if file", HFILL }},
2761
2762     { &hf_afp_file_bitmap_ExtRsrcForkLen,
2763         { "Extended resource fork size",         "afp.file_bitmap.ex_resource_fork_len",
2764             FT_BOOLEAN, 16, NULL,  kFPExtRsrcForkLenBit,
2765         "Return extended (>2GB) resource fork size if file", HFILL }},
2766
2767     { &hf_afp_file_bitmap_UnixPrivs,               
2768       { "UNIX privileges",    "afp.file_bitmap.unix_privs",
2769             FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit_file,
2770         "Return UNIX privileges if file", HFILL }},
2771
2772         /* ---------- */
2773     { &hf_afp_file_attribute_Invisible,
2774       { "Invisible",         "afp.file_attribute.invisible",
2775             FT_BOOLEAN, 16, NULL,  kFPInvisibleBit,
2776         "File is not visible", HFILL }},
2777
2778     { &hf_afp_file_attribute_MultiUser,
2779       { "Multi user",         "afp.file_attribute.multi_user",
2780             FT_BOOLEAN, 16, NULL,  kFPMultiUserBit,
2781         "multi user", HFILL }},
2782
2783     { &hf_afp_file_attribute_System,
2784       { "System",                "afp.file_attribute.system",
2785             FT_BOOLEAN, 16, NULL,  kFPSystemBit,
2786         "File is a system file", HFILL }},
2787
2788     { &hf_afp_file_attribute_DAlreadyOpen,
2789       { "Data fork open",         "afp.file_attribute.df_open",
2790             FT_BOOLEAN, 16, NULL,  kFPDAlreadyOpenBit,
2791         "Data fork already open", HFILL }},
2792
2793     { &hf_afp_file_attribute_RAlreadyOpen,
2794       { "Resource fork open",         "afp.file_attribute.rf_open",
2795             FT_BOOLEAN, 16, NULL,  kFPRAlreadyOpenBit,
2796         "Resource fork already open", HFILL }},
2797
2798     { &hf_afp_file_attribute_WriteInhibit,
2799       { "Write inhibit",         "afp.file_attribute.write_inhibit",
2800             FT_BOOLEAN, 16, NULL,  kFPWriteInhibitBit,
2801         "Write inhibit", HFILL }},
2802
2803     { &hf_afp_file_attribute_BackUpNeeded,
2804       { "Backup needed",         "afp.file_attribute.backup_needed",
2805             FT_BOOLEAN, 16, NULL,  kFPBackUpNeededBit,
2806         "File needs to be backed up", HFILL }},
2807
2808     { &hf_afp_file_attribute_RenameInhibit,
2809       { "Rename inhibit",         "afp.file_attribute.rename_inhibit",
2810             FT_BOOLEAN, 16, NULL,  kFPRenameInhibitBit,
2811         "rename inhibit", HFILL }},
2812
2813     { &hf_afp_file_attribute_DeleteInhibit,
2814       { "Delete inhibit",         "afp.file_attribute.delete_inhibit",
2815             FT_BOOLEAN, 16, NULL,  kFPDeleteInhibitBit,
2816         "delete inhibit", HFILL }},
2817
2818     { &hf_afp_file_attribute_CopyProtect,
2819       { "Copy protect",         "afp.file_attribute.copy_protect",
2820             FT_BOOLEAN, 16, NULL,  kFPCopyProtectBit,
2821         "copy protect", HFILL }},
2822
2823     { &hf_afp_file_attribute_SetClear,
2824       { "Set",         "afp.file_attribute.set_clear",
2825             FT_BOOLEAN, 16, NULL,  kFPSetClearBit,
2826         "Clear/set attribute", HFILL }},
2827         /* ---------- */
2828
2829     { &hf_afp_vol_name,
2830       { "Volume",         "afp.vol_name",
2831         FT_UINT_STRING, BASE_NONE, NULL, 0x0,
2832         "Volume name", HFILL }},
2833
2834     { &hf_afp_vol_id,
2835       { "Volume id",         "afp.vol_id",
2836                 FT_UINT16, BASE_DEC, NULL, 0x0,
2837         "Volume id", HFILL }},
2838
2839     { &hf_afp_vol_signature,
2840       { "Signature",         "afp.vol_signature",
2841                 FT_UINT16, BASE_DEC, VALS(vol_signature_vals), 0x0,
2842         "Volume signature", HFILL }},
2843
2844     { &hf_afp_bitmap_offset,
2845       { "Offset",         "afp.bitmap_offset",
2846                 FT_UINT16, BASE_DEC, NULL, 0x0,
2847         "Name offset in packet", HFILL }},
2848
2849     { &hf_afp_vol_creation_date,
2850       { "Creation date",         "afp.vol_creation_date",
2851                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2852         "Volume creation date", HFILL }},
2853
2854     { &hf_afp_vol_modification_date,
2855       { "Modification date",         "afp.vol_modification_date",
2856                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2857         "Volume modification date", HFILL }},
2858
2859     { &hf_afp_vol_backup_date,
2860       { "Backup date",         "afp.vol_backup_date",
2861                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2862         "Volume backup date", HFILL }},
2863
2864     { &hf_afp_vol_bytes_free,
2865       { "Bytes free",         "afp.vol_bytes_free",
2866                 FT_UINT32, BASE_DEC, NULL, 0x0,
2867         "Free space", HFILL }},
2868
2869     { &hf_afp_vol_bytes_total,
2870       { "Bytes total",         "afp.vol_bytes_total",
2871                 FT_UINT32, BASE_DEC, NULL, 0x0,
2872         "Volume size", HFILL }},
2873
2874     { &hf_afp_vol_ex_bytes_free,
2875       { "Extended bytes free",         "afp.vol_ex_bytes_free",
2876                 FT_UINT64, BASE_DEC, NULL, 0x0,
2877         "Extended (>2GB) free space", HFILL }},
2878
2879     { &hf_afp_vol_ex_bytes_total,
2880       { "Extended bytes total",         "afp.vol_ex_bytes_total",
2881                 FT_UINT64, BASE_DEC, NULL, 0x0,
2882         "Extended (>2GB) volume size", HFILL }},
2883
2884     { &hf_afp_vol_block_size,
2885       { "Block size",         "afp.vol_block_size",
2886                 FT_UINT32, BASE_DEC, NULL, 0x0,
2887         "Volume block size", HFILL }},
2888
2889     { &hf_afp_did,
2890       { "DID",         "afp.did",
2891                 FT_UINT32, BASE_DEC, NULL, 0x0,
2892         "Parent directory ID", HFILL }},
2893
2894     { &hf_afp_dir_bitmap,
2895       { "Directory bitmap",         "afp.dir_bitmap",
2896                 FT_UINT16, BASE_HEX, NULL, 0x0,
2897         "Directory bitmap", HFILL }},
2898
2899     { &hf_afp_dir_offspring,
2900       { "Offspring",         "afp.dir_offspring",
2901                 FT_UINT16, BASE_DEC, NULL, 0x0,
2902         "Directory offspring", HFILL }},
2903
2904     { &hf_afp_dir_OwnerID,
2905       { "Owner ID",         "afp.dir_owner_id",
2906                 FT_INT32, BASE_DEC, NULL, 0x0,
2907         "Directory owner ID", HFILL }},
2908
2909     { &hf_afp_dir_GroupID,
2910       { "Group ID",         "afp.dir_group_id",
2911                 FT_INT32, BASE_DEC, NULL, 0x0,
2912         "Directory group ID", HFILL }},
2913
2914     { &hf_afp_creation_date,
2915       { "Creation date",         "afp.creation_date",
2916                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2917         "Creation date", HFILL }},
2918
2919     { &hf_afp_modification_date,
2920       { "Modification date",         "afp.modification_date",
2921                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2922         "Modification date", HFILL }},
2923
2924     { &hf_afp_backup_date,
2925       { "Backup date",         "afp.backup_date",
2926                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
2927         "Backup date", HFILL }},
2928
2929     { &hf_afp_finder_info,
2930       { "Finder info",         "afp.finder_info",
2931                 FT_BYTES, BASE_HEX, NULL, 0x0,
2932         "Finder info", HFILL }},
2933
2934     { &hf_afp_file_id,
2935       { "File ID",         "afp.file_id",
2936                 FT_UINT32, BASE_DEC, NULL, 0x0,
2937         "File/directory ID", HFILL }},
2938
2939     { &hf_afp_file_DataForkLen,
2940       { "Data fork size",         "afp.data_fork_len",
2941                 FT_UINT32, BASE_DEC, NULL, 0x0,
2942         "Data fork size", HFILL }},
2943
2944     { &hf_afp_file_RsrcForkLen,
2945       { "Resource fork size",         "afp.resource_fork_len",
2946                 FT_UINT32, BASE_DEC, NULL, 0x0,
2947         "Resource fork size", HFILL }},
2948
2949     { &hf_afp_file_ExtDataForkLen,
2950       { "Extended data fork size",         "afp.ext_data_fork_len",
2951                 FT_UINT64, BASE_DEC, NULL, 0x0,
2952         "Extended (>2GB) data fork length", HFILL }},
2953
2954     { &hf_afp_file_ExtRsrcForkLen,
2955       { "Extended resource fork size",         "afp.ext_resource_fork_len",
2956                 FT_UINT64, BASE_DEC, NULL, 0x0,
2957         "Extended (>2GB) resource fork length", HFILL }},
2958
2959     { &hf_afp_file_UnixPrivs,
2960       { "UNIX privileges",         "afp.unix_privs",
2961                 FT_UINT32, BASE_DEC, NULL, 0x0,
2962         "UNIX privileges", HFILL }},
2963     
2964     { &hf_afp_file_bitmap,
2965       { "File bitmap",         "afp.file_bitmap",
2966                 FT_UINT16, BASE_HEX, NULL, 0x0,
2967         "File bitmap", HFILL }},
2968     
2969     { &hf_afp_req_count,
2970       { "Req count",         "afp.req_count",
2971                 FT_UINT16, BASE_DEC, NULL, 0x0,
2972         "Maximum number of structures returned", HFILL }},
2973
2974     { &hf_afp_start_index, 
2975       { "Start index",         "afp.start_index",
2976                 FT_UINT16, BASE_DEC, NULL, 0x0,
2977         "First structure returned", HFILL }},
2978     
2979     { &hf_afp_max_reply_size,
2980       { "Reply size",         "afp.reply_size",
2981                 FT_UINT16, BASE_DEC, NULL, 0x0,
2982         "First structure returned", HFILL }},
2983
2984     { &hf_afp_file_flag,
2985       { "Dir",         "afp.flag",
2986                 FT_BOOLEAN, 8, NULL, 0x80,
2987         "Is a dir", HFILL }},
2988
2989     { &hf_afp_create_flag,
2990       { "Hard create",         "afp.create_flag",
2991                 FT_BOOLEAN, 8, NULL, 0x80,
2992         "Soft/hard create file", HFILL }},
2993
2994     { &hf_afp_struct_size,
2995       { "Struct size",         "afp.struct_size",
2996                 FT_UINT8, BASE_DEC, NULL,0,
2997         "Sizeof of struct", HFILL }},
2998     
2999     { &hf_afp_flag,
3000       { "From",         "afp.flag",
3001                 FT_UINT8, BASE_HEX, VALS(flag_vals), 0x80,
3002         "Offset is relative to start/end of the fork", HFILL }},
3003
3004     { &hf_afp_dt_ref,
3005       { "DT ref",         "afp.dt_ref",
3006                 FT_UINT16, BASE_DEC, NULL, 0x0,
3007         "Desktop database reference num", HFILL }},
3008
3009     { &hf_afp_ofork,
3010       { "Fork",         "afp.ofork",
3011                 FT_UINT16, BASE_DEC, NULL, 0x0,
3012         "Open fork reference number", HFILL }},
3013
3014     { &hf_afp_offset,
3015       { "Offset",         "afp.offset",
3016                 FT_INT32, BASE_DEC, NULL, 0x0,
3017         "Offset", HFILL }},
3018     
3019     { &hf_afp_rw_count,
3020       { "Count",         "afp.rw_count",
3021                 FT_INT32, BASE_DEC, NULL, 0x0,
3022         "Number of bytes to be read/written", HFILL }},
3023     
3024     { &hf_afp_last_written,
3025       { "Last written",  "afp.last_written",
3026                 FT_UINT32, BASE_DEC, NULL, 0x0,
3027         "Offset of the last byte written", HFILL }},
3028
3029     { &hf_afp_actual_count,
3030       { "Count",         "afp.actual_count",
3031                 FT_INT32, BASE_DEC, NULL, 0x0,
3032         "Number of bytes returned by read/write", HFILL }},
3033       
3034     { &hf_afp_ofork_len,
3035       { "New length",         "afp.ofork_len",
3036                 FT_INT32, BASE_DEC, NULL, 0x0,
3037         "New length", HFILL }},
3038
3039     { &hf_afp_path_type,
3040       { "Type",         "afp.path_type",
3041                 FT_UINT8, BASE_HEX, VALS(path_type_vals), 0,
3042         "Type of names", HFILL }},
3043
3044     { &hf_afp_path_len,
3045       { "Len",  "afp.path_len",
3046                 FT_UINT8, BASE_DEC, NULL, 0x0,
3047         "Path length", HFILL }},
3048
3049     { &hf_afp_path_name,
3050       { "Name",  "afp.path_name",
3051                 FT_STRING, BASE_NONE, NULL, 0x0,
3052         "Path name", HFILL }},
3053
3054     { &hf_afp_fork_type,
3055       { "Resource fork",         "afp.fork_type",
3056                 FT_BOOLEAN, 8, NULL, 0x80,
3057         "Data/resource fork", HFILL }},
3058
3059     { &hf_afp_access_mode,
3060       { "Access mode",         "afp.access",
3061                 FT_UINT8, BASE_HEX, NULL, 0x0,
3062         "Fork access mode", HFILL }},
3063
3064     { &hf_afp_access_read,
3065       { "Read",         "afp.access.read",
3066         FT_BOOLEAN, 8, NULL,  1,
3067         "Open for reading", HFILL }},
3068
3069     { &hf_afp_access_write,
3070       { "Write",         "afp.access.write",
3071         FT_BOOLEAN, 8, NULL,  2,
3072         "Open for writing", HFILL }},
3073
3074     { &hf_afp_access_deny_read,
3075       { "Deny read",         "afp.access.deny_read",
3076         FT_BOOLEAN, 8, NULL,  0x10,
3077         "Deny read", HFILL }},
3078
3079     { &hf_afp_access_deny_write,
3080       { "Deny write",         "afp.access.deny_write",
3081         FT_BOOLEAN, 8, NULL,  0x20,
3082         "Deny write", HFILL }},
3083
3084     { &hf_afp_comment,
3085       { "Comment",         "afp.comment",
3086                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3087         "File/folder comment", HFILL }},
3088
3089     { &hf_afp_file_creator,
3090       { "File creator",         "afp.file_creator",
3091                 FT_STRING, BASE_NONE, NULL, 0x0,
3092         "File creator", HFILL }},
3093
3094     { &hf_afp_file_type,
3095       { "File type",         "afp.file_type",
3096                 FT_STRING, BASE_NONE, NULL, 0x0,
3097         "File type", HFILL }},
3098
3099     { &hf_afp_icon_type,
3100       { "Icon type",         "afp.icon_type",
3101                 FT_UINT8, BASE_HEX, NULL , 0,
3102         "Icon type", HFILL }},
3103
3104     { &hf_afp_icon_length,
3105       { "Size",         "afp.icon_length",
3106                 FT_UINT16, BASE_DEC, NULL, 0x0,
3107         "Size for icon bitmap", HFILL }},
3108
3109     { &hf_afp_icon_index,
3110       { "Index",         "afp.icon_index",
3111                 FT_UINT16, BASE_DEC, NULL, 0x0,
3112         "Icon index in desktop database", HFILL }},
3113
3114     { &hf_afp_icon_tag,
3115       { "Tag",         "afp.icon_tag",
3116                 FT_UINT32, BASE_HEX, NULL, 0x0,
3117         "Icon tag", HFILL }},
3118
3119     { &hf_afp_appl_index,
3120       { "Index",         "afp.appl_index",
3121                 FT_UINT16, BASE_DEC, NULL, 0x0,
3122         "Application index", HFILL }},
3123
3124     { &hf_afp_appl_tag,
3125       { "Tag",         "afp.appl_tag",
3126                 FT_UINT32, BASE_HEX, NULL, 0x0,
3127         "Application tag", HFILL }},
3128         
3129     { &hf_afp_lock_op,
3130       { "unlock",         "afp.lock_op",
3131                 FT_BOOLEAN, 8, NULL, 0x1,
3132         "Lock/unlock op", HFILL }},
3133
3134     { &hf_afp_lock_from,
3135       { "End",         "afp.lock_from",
3136                 FT_BOOLEAN, 8, NULL, 0x80,
3137         "Offset is relative to the end of the fork", HFILL }},
3138     
3139     { &hf_afp_lock_offset,
3140       { "Offset",         "afp.lock_offset",
3141                 FT_INT32, BASE_DEC, NULL, 0x0,
3142         "First byte to be locked", HFILL }},
3143
3144     { &hf_afp_lock_len,
3145       { "Length",         "afp.lock_len",
3146                 FT_INT32, BASE_DEC, NULL, 0x0,
3147         "Number of bytes to be locked/unlocked", HFILL }},
3148
3149     { &hf_afp_lock_range_start,
3150       { "Start",         "afp.lock_range_start",
3151                 FT_INT32, BASE_DEC, NULL, 0x0,
3152         "First byte locked/unlocked", HFILL }},
3153
3154     { &hf_afp_dir_ar,
3155       { "Access rights",         "afp.dir_ar",
3156                 FT_UINT32, BASE_HEX, NULL, 0x0,
3157         "Directory access rights", HFILL }},
3158
3159     { &hf_afp_dir_ar_o_search,
3160       { "Owner has search access",      "afp.dir_ar.o_search",
3161                 FT_BOOLEAN, 32, NULL, AR_O_SEARCH,
3162         "Owner has search access", HFILL }},
3163
3164     { &hf_afp_dir_ar_o_read,
3165       { "Owner has read access",        "afp.dir_ar.o_read",
3166                 FT_BOOLEAN, 32, NULL, AR_O_READ,
3167         "Owner has read access", HFILL }},
3168
3169     { &hf_afp_dir_ar_o_write,
3170       { "Owner has write access",       "afp.dir_ar.o_write",
3171                 FT_BOOLEAN, 32, NULL, AR_O_WRITE,
3172         "Gwner has write access", HFILL }},
3173
3174     { &hf_afp_dir_ar_g_search,
3175       { "Group has search access",      "afp.dir_ar.g_search",
3176                 FT_BOOLEAN, 32, NULL, AR_G_SEARCH,
3177         "Group has search access", HFILL }},
3178
3179     { &hf_afp_dir_ar_g_read,
3180       { "Group has read access",        "afp.dir_ar.g_read",
3181                 FT_BOOLEAN, 32, NULL, AR_G_READ,
3182         "Group has read access", HFILL }},
3183
3184     { &hf_afp_dir_ar_g_write,
3185       { "Group has write access",       "afp.dir_ar.g_write",
3186                 FT_BOOLEAN, 32, NULL, AR_G_WRITE,
3187         "Group has write access", HFILL }},
3188
3189     { &hf_afp_dir_ar_e_search,
3190       { "Everyone has search access",   "afp.dir_ar.e_search",
3191                 FT_BOOLEAN, 32, NULL, AR_E_SEARCH,
3192         "Everyone has search access", HFILL }},
3193
3194     { &hf_afp_dir_ar_e_read,
3195       { "Everyone has read access",     "afp.dir_ar.e_read",
3196                 FT_BOOLEAN, 32, NULL, AR_E_READ,
3197         "Everyone has read access", HFILL }},
3198
3199     { &hf_afp_dir_ar_e_write,
3200       { "Everyone has write access",    "afp.dir_ar.e_write",
3201                 FT_BOOLEAN, 32, NULL, AR_E_WRITE,
3202         "Everyone has write access", HFILL }},
3203
3204     { &hf_afp_dir_ar_u_search,
3205       { "User has search access",   "afp.dir_ar.u_search",
3206                 FT_BOOLEAN, 32, NULL, AR_U_SEARCH,
3207         "User has search access", HFILL }},
3208
3209     { &hf_afp_dir_ar_u_read,
3210       { "User has read access",     "afp.dir_ar.u_read",
3211                 FT_BOOLEAN, 32, NULL, AR_U_READ,
3212         "User has read access", HFILL }},
3213
3214     { &hf_afp_dir_ar_u_write,
3215       { "User has write access",     "afp.dir_ar.u_write",
3216                 FT_BOOLEAN, 32, NULL, AR_U_WRITE,
3217         "User has write access", HFILL }},
3218
3219     { &hf_afp_dir_ar_blank,
3220       { "Blank access right",     "afp.dir_ar.blank",
3221                 FT_BOOLEAN, 32, NULL, AR_BLANK,
3222         "Blank access right", HFILL }},
3223
3224     { &hf_afp_dir_ar_u_own,
3225       { "User is the owner",     "afp.dir_ar.u_owner",
3226                 FT_BOOLEAN, 32, NULL, AR_U_OWN,
3227         "Current user is the directory owner", HFILL }},
3228   };
3229
3230   static gint *ett[] = {
3231         &ett_afp,
3232         &ett_afp_vol_bitmap,
3233         &ett_afp_vol_attribute,
3234         &ett_afp_dir_bitmap,
3235         &ett_afp_file_bitmap,
3236         &ett_afp_enumerate,
3237         &ett_afp_enumerate_line,
3238         &ett_afp_access_mode,
3239         &ett_afp_dir_attribute,
3240         &ett_afp_file_attribute,
3241         &ett_afp_path_name,
3242         &ett_afp_lock_flags,
3243         &ett_afp_dir_ar,
3244   };
3245
3246   proto_afp = proto_register_protocol("AppleTalk Filing Protocol", "AFP", "afp");
3247   proto_register_field_array(proto_afp, hf, array_length(hf));
3248   proto_register_subtree_array(ett, array_length(ett));
3249
3250   register_init_routine( &afp_reinit);
3251
3252   register_dissector("afp", dissect_afp, proto_afp);
3253   data_handle = find_dissector("data");
3254 }
3255
3256 void
3257 proto_reg_handoff_afp(void)
3258 {
3259   data_handle = find_dissector("data");
3260 }
3261
3262 /* -------------------------------
3263    end
3264 */