60ae11bbe5f7b103bf525fc3baa0a1a081c95d47
[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.19 2002/07/29 06:35:12 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 # include "snprintf.h"
45 #endif
46
47 #include <string.h>
48 #include <glib.h>
49 #include <epan/packet.h>
50 #include <epan/strutil.h>
51 #include <epan/conversation.h>
52
53 #include "packet-afp.h"
54
55 /* The information in this module (AFP) comes from:
56
57   AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
58   available from http://www.apple.com
59  
60   AFP3.0.pdf from http://www.apple.com
61   
62   The netatalk source code by Wesley Craig & Adrian Sun
63         http://netatalk.sf.net
64 */
65 /* from netatalk/include/afp.h */
66 #define AFPTRANS_NONE          0
67 #define AFPTRANS_DDP          (1 << 0)
68 #define AFPTRANS_TCP          (1 << 1)
69 #define AFPTRANS_ALL          (AFPTRANS_DDP | AFPTRANS_TCP)
70
71 /* server flags */
72 #define AFPSRVRINFO_COPY                        (1<<0)  /* supports copyfile */
73 #define AFPSRVRINFO_PASSWD                      (1<<1)  /* supports change password */
74 #define AFPSRVRINFO_NOSAVEPASSWD        (1<<2)  /* don't allow save password */
75 #define AFPSRVRINFO_SRVMSGS             (1<<3)  /* supports server messages */
76 #define AFPSRVRINFO_SRVSIGNATURE        (1<<4)  /* supports server signature */
77 #define AFPSRVRINFO_TCPIP               (1<<5)  /* supports tcpip */
78 #define AFPSRVRINFO_SRVNOTIFY           (1<<6)  /* supports server notifications */ 
79 #define AFPSRVRINFO_FASTBOZO            (1<<15) /* fast copying */
80
81 /* AFP Attention Codes -- 4 bits */
82 #define AFPATTN_SHUTDOWN     (1 << 15)            /* shutdown/disconnect */
83 #define AFPATTN_CRASH        (1 << 14)            /* server crashed */
84 #define AFPATTN_MESG         (1 << 13)            /* server has message */
85 #define AFPATTN_NORECONNECT  (1 << 12)            /* don't reconnect */
86 /* server notification */
87 #define AFPATTN_NOTIFY       (AFPATTN_MESG | AFPATTN_NORECONNECT) 
88
89 /* extended bitmap -- 12 bits. volchanged is only useful w/ a server
90  * notification, and time is only useful for shutdown. */
91 #define AFPATTN_VOLCHANGED   (1 << 0)             /* volume has changed */
92 #define AFPATTN_TIME(x)      ((x) & 0xfff)        /* time in minutes */
93
94 /* AFP functions */
95 #define AFP_BYTELOCK         1
96 #define AFP_CLOSEVOL             2
97 #define AFP_CLOSEDIR             3
98 #define AFP_CLOSEFORK            4
99 #define AFP_COPYFILE             5
100 #define AFP_CREATEDIR            6
101 #define AFP_CREATEFILE           7
102 #define AFP_DELETE                   8
103 #define AFP_ENUMERATE            9
104 #define AFP_FLUSH                   10
105 #define AFP_FLUSHFORK           11
106 #define AFP_GETFORKPARAM        14
107 #define AFP_GETSRVINFO          15
108 #define AFP_GETSRVPARAM         16
109 #define AFP_GETVOLPARAM         17
110 #define AFP_LOGIN               18
111 #define AFP_LOGINCONT           19
112 #define AFP_LOGOUT              20
113 #define AFP_MAPID                   21
114 #define AFP_MAPNAME                 22
115 #define AFP_MOVE                    23
116 #define AFP_OPENVOL             24
117 #define AFP_OPENDIR                 25
118 #define AFP_OPENFORK            26
119 #define AFP_READ                    27
120 #define AFP_RENAME                  28
121 #define AFP_SETDIRPARAM         29
122 #define AFP_SETFILEPARAM        30
123 #define AFP_SETFORKPARAM        31
124 #define AFP_SETVOLPARAM         32
125 #define AFP_WRITE                   33
126 #define AFP_GETFLDRPARAM        34
127 #define AFP_SETFLDRPARAM        35
128 #define AFP_CHANGEPW            36
129 #define AFP_GETUSERINFO         37
130 #define AFP_GETSRVRMSG          38
131 #define AFP_CREATEID            39
132 #define AFP_DELETEID            40
133 #define AFP_RESOLVEID           41
134 #define AFP_EXCHANGEFILE        42
135 #define AFP_CATSEARCH           43
136 #define AFP_OPENDT                  48
137 #define AFP_CLOSEDT                 49
138 #define AFP_GETICON         51
139 #define AFP_GTICNINFO       52
140 #define AFP_ADDAPPL         53
141 #define AFP_RMVAPPL         54
142 #define AFP_GETAPPL         55
143 #define AFP_ADDCMT          56
144 #define AFP_RMVCMT          57
145 #define AFP_GETCMT          58
146 #define AFP_ADDICON        192
147
148 /* AFP 3.0 new calls */
149 #define AFP_BYTELOCK_EXT        59
150 #define AFP_CATSEARCH_EXT       67
151 #define AFP_ENUMERATE_EXT       66
152 #define AFP_READ_EXT            60
153 #define AFP_WRITE_EXT           61
154 #define AFP_GETSESSTOKEN        64
155 #define AFP_DISCTOLDSESS        65
156
157 /* ----------------------------- */
158 static int proto_afp = -1;
159 static int hf_afp_reserved = -1;
160
161 static int hf_afp_command = -1;         /* CommandCode */
162 static int hf_afp_AFPVersion = -1; 
163 static int hf_afp_UAM = -1; 
164 static int hf_afp_user = -1; 
165 static int hf_afp_passwd = -1; 
166 static int hf_afp_pad = -1;
167
168 static int hf_afp_vol_flag_passwd        = -1;
169 static int hf_afp_vol_flag_unix_priv = -1;
170 static int hf_afp_server_time            = -1;
171
172 static int hf_afp_vol_bitmap = -1;
173 static int hf_afp_vol_name_offset = -1;
174 static int hf_afp_vol_id = -1;
175 static int hf_afp_vol_attribute = -1;
176 static int hf_afp_vol_name = -1;
177 static int hf_afp_vol_signature = -1;
178 static int hf_afp_vol_creation_date = -1;
179 static int hf_afp_vol_modification_date = -1;
180 static int hf_afp_vol_backup_date = -1;
181 static int hf_afp_vol_bytes_free = -1;
182 static int hf_afp_vol_bytes_total = -1;
183 static int hf_afp_vol_ex_bytes_free = -1;
184 static int hf_afp_vol_ex_bytes_total = -1;
185 static int hf_afp_vol_block_size = -1;
186
187 /* desktop stuff */
188 static int hf_afp_comment               = -1;
189 static int hf_afp_file_creator  = -1;
190 static int hf_afp_file_type     = -1;
191 static int hf_afp_icon_type     = -1;
192 static int hf_afp_icon_length   = -1;
193 static int hf_afp_icon_tag              = -1;
194 static int hf_afp_icon_index    = -1;
195 static int hf_afp_appl_index    = -1;
196 static int hf_afp_appl_tag              = -1;
197
198 static int hf_afp_did                             = -1;
199 static int hf_afp_file_id                         = -1;
200 static int hf_afp_file_DataForkLen    = -1;
201 static int hf_afp_file_RsrcForkLen    = -1;
202 static int hf_afp_file_ExtDataForkLen = -1;
203 static int hf_afp_file_ExtRsrcForkLen = -1;
204
205 static int hf_afp_dir_bitmap     = -1;
206 static int hf_afp_dir_offspring  = -1;
207 static int hf_afp_dir_OwnerID    = -1;
208 static int hf_afp_dir_GroupID    = -1;
209
210 static int hf_afp_file_bitmap = -1;
211 static int hf_afp_req_count = -1;
212 static int hf_afp_start_index = -1;
213 static int hf_afp_max_reply_size = -1;
214 static int hf_afp_file_flag = -1;
215 static int hf_afp_create_flag = -1;
216 static int hf_afp_struct_size = -1;
217
218 static int hf_afp_cat_count             = -1;
219 static int hf_afp_cat_req_matches   = -1;
220 static int hf_afp_cat_position          = -1;
221
222 static int hf_afp_creation_date = -1;
223 static int hf_afp_modification_date = -1;
224 static int hf_afp_backup_date = -1;
225 static int hf_afp_finder_info = -1;
226 static int hf_afp_long_name_offset = -1;
227 static int hf_afp_short_name_offset = -1;
228 static int hf_afp_unicode_name_offset = -1;
229 static int hf_afp_unix_privs_uid = -1;
230 static int hf_afp_unix_privs_gid = -1;
231 static int hf_afp_unix_privs_permissions = -1;
232 static int hf_afp_unix_privs_ua_permissions = -1;
233
234 static int hf_afp_path_type = -1;
235 static int hf_afp_path_len = -1;
236 static int hf_afp_path_name = -1;
237
238 static int hf_afp_flag          = -1;
239 static int hf_afp_dt_ref        = -1;
240 static int hf_afp_ofork         = -1;
241 static int hf_afp_ofork_len     = -1;
242 static int hf_afp_offset        = -1;
243 static int hf_afp_rw_count      = -1;
244 static int hf_afp_newline_mask  = -1;
245 static int hf_afp_newline_char  = -1;
246 static int hf_afp_last_written  = -1;
247 static int hf_afp_actual_count  = -1;
248
249 static int hf_afp_fork_type                     = -1;
250 static int hf_afp_access_mode           = -1;
251 static int hf_afp_access_read           = -1;
252 static int hf_afp_access_write          = -1;
253 static int hf_afp_access_deny_read  = -1;
254 static int hf_afp_access_deny_write = -1;
255
256 static gint hf_afp_lock_op                      = -1;
257 static gint hf_afp_lock_from            = -1;
258 static gint hf_afp_lock_offset          = -1;
259 static gint hf_afp_lock_len             = -1;
260 static gint hf_afp_lock_range_start = -1;
261
262 static gint ett_afp = -1;
263
264 static gint ett_afp_vol_attribute = -1;
265 static gint ett_afp_enumerate = -1;
266 static gint ett_afp_enumerate_line = -1;
267 static gint ett_afp_access_mode = -1;
268
269 static gint ett_afp_vol_bitmap = -1;
270 static gint ett_afp_dir_bitmap = -1;
271 static gint ett_afp_dir_attribute = -1;
272 static gint ett_afp_file_attribute = -1;
273 static gint ett_afp_file_bitmap = -1;
274 static gint ett_afp_unix_privs = -1;
275 static gint ett_afp_path_name = -1;
276 static gint ett_afp_lock_flags = -1;
277 static gint ett_afp_dir_ar = -1;
278
279 static gint ett_afp_server_vol          = -1;
280 static gint ett_afp_vol_list            = -1;
281 static gint ett_afp_vol_flag            = -1;
282 static gint ett_afp_cat_search          = -1;
283 static gint ett_afp_cat_r_bitmap        = -1;
284 static gint ett_afp_cat_spec            = -1;
285 static gint ett_afp_vol_did     = -1;
286
287 /* AFP 3.0 parameters */
288 static gint hf_afp_lock_offset64        = -1;
289 static gint hf_afp_lock_len64           = -1;
290 static gint hf_afp_lock_range_start64   = -1;
291
292 static int hf_afp_offset64              = -1;
293 static int hf_afp_rw_count64            = -1;
294
295 static int hf_afp_last_written64        = -1;
296
297 static int hf_afp_session_token_type    = -1;
298 static int hf_afp_session_token_len     = -1;
299 static int hf_afp_session_token         = -1;
300
301 static dissector_handle_t data_handle;
302
303 static const value_string vol_signature_vals[] = {
304         {1, "Flat"},
305         {2, "Fixed Directory ID"},
306         {3, "Variable Directory ID (deprecated)"},
307         {0, NULL }
308 };
309
310 static const value_string CommandCode_vals[] = {
311   {AFP_BYTELOCK,        "FPByteRangeLock" },
312   {AFP_CLOSEVOL,        "FPCloseVol" },
313   {AFP_CLOSEDIR,        "FPCloseDir" },
314   {AFP_CLOSEFORK,       "FPCloseFork" },
315   {AFP_COPYFILE,        "FPCopyFile" },
316   {AFP_CREATEDIR,       "FPCreateDir" },
317   {AFP_CREATEFILE,      "FPCreateFile" },
318   {AFP_DELETE,          "FPDelete" },
319   {AFP_ENUMERATE,       "FPEnumerate" },
320   {AFP_FLUSH,           "FPFlush" },
321   {AFP_FLUSHFORK,       "FPFlushFork" },
322   {AFP_GETFORKPARAM,    "FPGetForkParms" },
323   {AFP_GETSRVINFO,      "FPGetSrvrInfo" },
324   {AFP_GETSRVPARAM,     "FPGetSrvrParms" },
325   {AFP_GETVOLPARAM,     "FPGetVolParms" },
326   {AFP_LOGIN,           "FPLogin" },
327   {AFP_LOGINCONT,       "FPLoginCont" },
328   {AFP_LOGOUT,          "FPLogout" },
329   {AFP_MAPID,           "FPMapID" },
330   {AFP_MAPNAME,         "FPMapName" },
331   {AFP_MOVE,            "FPMoveAndRename" },
332   {AFP_OPENVOL,         "FPOpenVol" },
333   {AFP_OPENDIR,         "FPOpenDir" },
334   {AFP_OPENFORK,        "FPOpenFork" },
335   {AFP_READ,            "FPRead" },
336   {AFP_RENAME,          "FPRename" },
337   {AFP_SETDIRPARAM,     "FPSetDirParms" },
338   {AFP_SETFILEPARAM,    "FPSetFileParms" },
339   {AFP_SETFORKPARAM,    "FPSetForkParms" },
340   {AFP_SETVOLPARAM,     "FPSetVolParms" },
341   {AFP_WRITE,           "FPWrite" },
342   {AFP_GETFLDRPARAM,    "FPGetFileDirParms" },
343   {AFP_SETFLDRPARAM,    "FPSetFileDirParms" },
344   {AFP_CHANGEPW,        "FPChangePassword" },
345   {AFP_GETUSERINFO,     "FPGetUserInfo" },
346   {AFP_GETSRVRMSG,      "FPGetSrvrMsg" },
347   {AFP_CREATEID,        "FPCreateID" },
348   {AFP_DELETEID,        "FPDeleteID" },
349   {AFP_RESOLVEID,       "FPResolveID" },
350   {AFP_EXCHANGEFILE,    "FPExchangeFiles" },
351   {AFP_CATSEARCH,       "FPCatSearch" },
352   {AFP_OPENDT,          "FPOpenDT" },
353   {AFP_CLOSEDT,         "FPCloseDT" },
354   {AFP_GETICON,         "FPGetIcon" },
355   {AFP_GTICNINFO,       "FPGetIconInfo" },
356   {AFP_ADDAPPL,         "FPAddAPPL" },
357   {AFP_RMVAPPL,         "FPRemoveAPPL" },
358   {AFP_GETAPPL,         "FPGetAPPL" },
359   {AFP_ADDCMT,          "FPAddComment" },
360   {AFP_RMVCMT,          "FPRemoveComment" },
361   {AFP_GETCMT,          "FPGetComment" },
362   {AFP_BYTELOCK_EXT,    "FPByteRangeLockExt" },
363   {AFP_CATSEARCH_EXT,   "FPCatSearchExt" },
364   {AFP_ENUMERATE_EXT,   "FPEnumerateExt" },
365   {AFP_READ_EXT,        "FPReadExt" },
366   {AFP_WRITE_EXT,       "FPWriteExt" },
367   {AFP_GETSESSTOKEN,    "FPGetSessionToken" },
368   {AFP_DISCTOLDSESS,    "FPDisconnectOldSession" },
369   {AFP_ADDICON,         "FPAddIcon" },
370   {0,                    NULL }
371 };
372
373
374 /* volume bitmap
375   from Apple AFP3.0.pdf 
376   Table 1-2 p. 20
377 */
378 #define kFPVolAttributeBit              (1 << 0)
379 #define kFPVolSignatureBit              (1 << 1)
380 #define kFPVolCreateDateBit             (1 << 2)
381 #define kFPVolModDateBit                (1 << 3)
382 #define kFPVolBackupDateBit             (1 << 4)
383 #define kFPVolIDBit                     (1 << 5)
384 #define kFPVolBytesFreeBit              (1 << 6)
385 #define kFPVolBytesTotalBit             (1 << 7)
386 #define kFPVolNameBit                   (1 << 8)
387 #define kFPVolExtBytesFreeBit           (1 << 9)
388 #define kFPVolExtBytesTotalBit          (1 << 10)
389 #define kFPVolBlockSizeBit              (1 << 11)
390
391 static int hf_afp_vol_bitmap_Attributes         = -1;
392 static int hf_afp_vol_bitmap_Signature          = -1;
393 static int hf_afp_vol_bitmap_CreateDate         = -1;
394 static int hf_afp_vol_bitmap_ModDate            = -1;
395 static int hf_afp_vol_bitmap_BackupDate         = -1;
396 static int hf_afp_vol_bitmap_ID                 = -1;
397 static int hf_afp_vol_bitmap_BytesFree          = -1;
398 static int hf_afp_vol_bitmap_BytesTotal         = -1;
399 static int hf_afp_vol_bitmap_Name               = -1;
400 static int hf_afp_vol_bitmap_ExtBytesFree       = -1;
401 static int hf_afp_vol_bitmap_ExtBytesTotal      = -1;
402 static int hf_afp_vol_bitmap_BlockSize          = -1;
403
404 static int hf_afp_vol_attribute_ReadOnly                        = -1;
405 static int hf_afp_vol_attribute_HasVolumePassword               = -1;
406 static int hf_afp_vol_attribute_SupportsFileIDs                 = -1;
407 static int hf_afp_vol_attribute_SupportsCatSearch               = -1;
408 static int hf_afp_vol_attribute_SupportsBlankAccessPrivs        = -1;
409 static int hf_afp_vol_attribute_SupportsUnixPrivs               = -1;
410 static int hf_afp_vol_attribute_SupportsUTF8Names               = -1;
411
412 static int hf_afp_dir_bitmap_Attributes     = -1;
413 static int hf_afp_dir_bitmap_ParentDirID    = -1;
414 static int hf_afp_dir_bitmap_CreateDate     = -1;
415 static int hf_afp_dir_bitmap_ModDate        = -1;
416 static int hf_afp_dir_bitmap_BackupDate     = -1;
417 static int hf_afp_dir_bitmap_FinderInfo     = -1;
418 static int hf_afp_dir_bitmap_LongName       = -1;
419 static int hf_afp_dir_bitmap_ShortName      = -1;
420 static int hf_afp_dir_bitmap_NodeID         = -1;
421 static int hf_afp_dir_bitmap_OffspringCount = -1;
422 static int hf_afp_dir_bitmap_OwnerID        = -1;
423 static int hf_afp_dir_bitmap_GroupID        = -1;
424 static int hf_afp_dir_bitmap_AccessRights   = -1;
425 static int hf_afp_dir_bitmap_UTF8Name       = -1;
426 static int hf_afp_dir_bitmap_UnixPrivs      = -1;
427
428 static int hf_afp_dir_attribute_Invisible     = -1;
429 static int hf_afp_dir_attribute_IsExpFolder   = -1;
430
431 static int hf_afp_dir_attribute_System        = -1;
432 static int hf_afp_dir_attribute_Mounted       = -1;
433 static int hf_afp_dir_attribute_InExpFolder   = -1;
434
435 static int hf_afp_dir_attribute_BackUpNeeded  = -1;
436 static int hf_afp_dir_attribute_RenameInhibit = -1;
437 static int hf_afp_dir_attribute_DeleteInhibit = -1;
438 static int hf_afp_dir_attribute_SetClear      = -1;
439
440 static int hf_afp_file_bitmap_Attributes     = -1;
441 static int hf_afp_file_bitmap_ParentDirID    = -1;
442 static int hf_afp_file_bitmap_CreateDate     = -1;
443 static int hf_afp_file_bitmap_ModDate        = -1;
444 static int hf_afp_file_bitmap_BackupDate     = -1;
445 static int hf_afp_file_bitmap_FinderInfo     = -1;
446 static int hf_afp_file_bitmap_LongName       = -1;
447 static int hf_afp_file_bitmap_ShortName      = -1;
448 static int hf_afp_file_bitmap_NodeID         = -1;
449 static int hf_afp_file_bitmap_DataForkLen    = -1;
450 static int hf_afp_file_bitmap_RsrcForkLen    = -1;
451 static int hf_afp_file_bitmap_ExtDataForkLen = -1;
452 static int hf_afp_file_bitmap_LaunchLimit    = -1;
453
454 static int hf_afp_file_bitmap_UTF8Name       = -1;
455 static int hf_afp_file_bitmap_ExtRsrcForkLen = -1;
456 static int hf_afp_file_bitmap_UnixPrivs      = -1;
457
458 static int hf_afp_file_attribute_Invisible     = -1;
459 static int hf_afp_file_attribute_MultiUser     = -1;
460 static int hf_afp_file_attribute_System        = -1;
461 static int hf_afp_file_attribute_DAlreadyOpen  = -1;
462 static int hf_afp_file_attribute_RAlreadyOpen  = -1;
463 static int hf_afp_file_attribute_WriteInhibit  = -1;
464 static int hf_afp_file_attribute_BackUpNeeded  = -1;
465 static int hf_afp_file_attribute_RenameInhibit = -1;
466 static int hf_afp_file_attribute_DeleteInhibit = -1;
467 static int hf_afp_file_attribute_CopyProtect   = -1;
468 static int hf_afp_file_attribute_SetClear      = -1;
469
470 static int hf_afp_map_name_type = -1;
471 static int hf_afp_map_name      = -1;
472 static int hf_afp_map_id        = -1;
473 static int hf_afp_map_id_type   = -1;
474
475 static const value_string vol_bitmap_vals[] = {
476   {kFPVolAttributeBit,          "VolAttribute"},
477   {kFPVolSignatureBit,          "VolSignature"},
478   {kFPVolCreateDateBit,         "VolCreateDate"},
479   {kFPVolModDateBit,            "VolModDate"},
480   {kFPVolBackupDateBit,         "VolBackupDate"},
481   {kFPVolIDBit,                 "VolID"},
482   {kFPVolBytesFreeBit,          "VolBytesFree"},
483   {kFPVolBytesTotalBit,         "VolBytesTotal"},
484   {kFPVolNameBit,               "VolNameBit"},
485   {kFPVolExtBytesFreeBit,       "VolExtBytesFree"},
486   {kFPVolExtBytesTotalBit,      "VolExtBytesTotal"},
487   {kFPVolBlockSizeBit,          "VolBlockSize"},
488   {0,                            NULL } };
489
490 static const value_string flag_vals[] = {
491   {0,   "Start" },
492   {1,   "End" },
493   {0,   NULL } };
494
495 static const value_string path_type_vals[] = {
496   {1,   "Short names" },
497   {2,   "Long names" },
498   {3,   "Unicode names" },
499   {0,   NULL } };
500
501 static const value_string map_name_type_vals[] = {
502   {1,   "Unicode user name to a user ID" },
503   {2,   "Unicode group name to a group ID" },
504   {3,   "Macintosh roman user name to a user ID" },
505   {4,   "Macintosh roman group name to a group ID" },
506   {0,   NULL } };
507
508 static const value_string map_id_type_vals[] = {
509   {1,   "User ID to a Macintosh roman user name" },
510   {2,   "Group ID to a Macintosh roman group name" },
511   {3,   "User ID to a unicode user name" },
512   {4,   "Group ID to a unicode group name" },
513   {0,   NULL } };
514
515 /*
516   volume attribute from Apple AFP3.0.pdf 
517   Table 1-3 p. 22
518 */
519 #define kReadOnly                               (1 << 0)
520 #define kHasVolumePassword                      (1 << 1)
521 #define kSupportsFileIDs                        (1 << 2)
522 #define kSupportsCatSearch                      (1 << 3)
523 #define kSupportsBlankAccessPrivs               (1 << 4)
524 #define kSupportsUnixPrivs                      (1 << 5)
525 #define kSupportsUTF8Names                      (1 << 6)
526
527 /*
528   directory bitmap from Apple AFP3.0.pdf 
529   Table 1-4 p. 31
530 */
531 #define kFPAttributeBit                 (1 << 0)
532 #define kFPParentDirIDBit               (1 << 1)
533 #define kFPCreateDateBit                (1 << 2)
534 #define kFPModDateBit                   (1 << 3)
535 #define kFPBackupDateBit                (1 << 4)
536 #define kFPFinderInfoBit                (1 << 5)
537 #define kFPLongNameBit                  (1 << 6)
538 #define kFPShortNameBit                 (1 << 7)
539 #define kFPNodeIDBit                    (1 << 8)
540 #define kFPOffspringCountBit            (1 << 9)
541 #define kFPOwnerIDBit                   (1 << 10)
542 #define kFPGroupIDBit                   (1 << 11)
543 #define kFPAccessRightsBit              (1 << 12)
544 #define kFPUTF8NameBit                  (1 << 13)
545 #define kFPUnixPrivsBit                 (1 << 14)
546
547 /*
548         directory Access Rights parameter AFP3.0.pdf
549         table 1-6 p. 34
550 */
551
552 #define AR_O_SEARCH     (1 << 0)        /* owner has search access */
553 #define AR_O_READ       (1 << 1)    /* owner has read access */
554 #define AR_O_WRITE      (1 << 2)    /* owner has write access */
555
556 #define AR_G_SEARCH     (1 << 8)    /* group has search access */
557 #define AR_G_READ       (1 << 9)    /* group has read access */
558 #define AR_G_WRITE      (1 << 10)   /* group has write access */
559
560 #define AR_E_SEARCH     (1 << 16)       /* everyone has search access */
561 #define AR_E_READ       (1 << 17)   /* everyone has read access */
562 #define AR_E_WRITE      (1 << 18)   /* everyone has write access */
563
564 #define AR_U_SEARCH     (1 << 24)   /* user has search access */
565 #define AR_U_READ       (1 << 25)   /* user has read access */
566 #define AR_U_WRITE      (1 << 26)       /* user has write access */ 
567
568 #define AR_BLANK        (1 << 28)       /* Blank Access Privileges (use parent dir privileges) */
569 #define AR_U_OWN        (1 << 31)       /* user is the owner */
570
571 static int hf_afp_dir_ar          = -1;
572 static int hf_afp_dir_ar_o_search = -1;
573 static int hf_afp_dir_ar_o_read   = -1;
574 static int hf_afp_dir_ar_o_write  = -1;
575 static int hf_afp_dir_ar_g_search = -1;
576 static int hf_afp_dir_ar_g_read   = -1;
577 static int hf_afp_dir_ar_g_write  = -1;
578 static int hf_afp_dir_ar_e_search = -1;
579 static int hf_afp_dir_ar_e_read   = -1;
580 static int hf_afp_dir_ar_e_write  = -1;
581 static int hf_afp_dir_ar_u_search = -1;
582 static int hf_afp_dir_ar_u_read   = -1;
583 static int hf_afp_dir_ar_u_write  = -1;
584 static int hf_afp_dir_ar_blank    = -1;
585 static int hf_afp_dir_ar_u_own    = -1;
586
587 static int hf_afp_user_flag       = -1;
588 static int hf_afp_user_ID         = -1;
589 static int hf_afp_group_ID        = -1;
590 static int hf_afp_user_bitmap     = -1;
591 static int hf_afp_user_bitmap_UID = -1;
592 static int hf_afp_user_bitmap_GID = -1;
593
594 static gint ett_afp_user_bitmap   = -1;
595
596 static const value_string user_flag_vals[] = {
597   {0,   "Use user ID" },
598   {1,   "Default user" },
599   {0,   NULL } };
600
601 /*
602   file bitmap AFP3.0.pdf 
603   Table 1-7 p. 36
604 same as dir
605 kFPAttributeBit                 (bit 0)
606 kFPParentDirIDBit               (bit 1)
607 kFPCreateDateBit                (bit 2)
608 kFPModDateBit                   (bit 3)
609 kFPBackupDateBit                (bit 4)
610 kFPFinderInfoBit                (bit 5)
611 kFPLongNameBit                  (bit 6)
612 kFPShortNameBit                 (bit 7)
613 kFPNodeIDBit                    (bit 8)
614
615 kFPUTF8NameBit                  (bit 13)
616 */
617
618 #define kFPDataForkLenBit               (1 << 9)
619 #define kFPRsrcForkLenBit               (1 << 10)
620 #define kFPExtDataForkLenBit            (1 << 11)
621 #define kFPLaunchLimitBit               (1 << 12)
622
623 #define kFPExtRsrcForkLenBit            (1 << 14)
624 #define kFPUnixPrivsBit_file            (1 << 15)       /* :( */
625
626 /*
627   file attribute AFP3.0.pdf 
628   Table 1-8 p. 37
629 */
630 #define kFPInvisibleBit                         (1 << 0)
631 #define kFPMultiUserBit                         (1 << 1)
632 #define kFPSystemBit                            (1 << 2)
633 #define kFPDAlreadyOpenBit                      (1 << 3)
634 #define kFPRAlreadyOpenBit                      (1 << 4)
635 #define kFPWriteInhibitBit                      (1 << 5)
636 #define kFPBackUpNeededBit                      (1 << 6)
637 #define kFPRenameInhibitBit                     (1 << 7)
638 #define kFPDeleteInhibitBit                     (1 << 8)
639 #define kFPCopyProtectBit                       (1 << 10)
640 #define kFPSetClearBit                          (1 << 15)
641
642 /* dir attribute */
643 #define kIsExpFolder    (1 << 1)
644 #define kMounted        (1 << 3)
645 #define kInExpFolder    (1 << 4)
646
647 #define hash_init_count 20
648
649 /* Hash functions */
650 static gint  afp_equal (gconstpointer v, gconstpointer v2);
651 static guint afp_hash  (gconstpointer v);
652  
653 static guint afp_packet_init_count = 200;
654
655 typedef struct {
656         guint32 conversation;
657         guint16 seq;
658 } afp_request_key;
659  
660 typedef struct {
661         guint8  command;
662 } afp_request_val;
663  
664 static GHashTable *afp_request_hash = NULL;
665 static GMemChunk *afp_request_keys = NULL;
666 static GMemChunk *afp_request_vals = NULL;
667
668 /* Hash Functions */
669 static gint  afp_equal (gconstpointer v, gconstpointer v2)
670 {
671         afp_request_key *val1 = (afp_request_key*)v;
672         afp_request_key *val2 = (afp_request_key*)v2;
673
674         if (val1->conversation == val2->conversation &&
675                         val1->seq == val2->seq) {
676                 return 1;
677         }
678         return 0;
679 }
680
681 static guint afp_hash  (gconstpointer v)
682 {
683         afp_request_key *afp_key = (afp_request_key*)v;
684         return afp_key->seq;
685 }
686
687 /* -------------------------- 
688 */
689 #define PAD(x)      { proto_tree_add_item(tree, hf_afp_pad, tvb, offset,  x, FALSE); offset += x; }
690
691 static guint16
692 decode_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
693 {
694         proto_tree *sub_tree = NULL;
695         proto_item *item;
696         guint16  bitmap;
697
698         bitmap = tvb_get_ntohs(tvb, offset);
699         if (tree) {
700                 item = proto_tree_add_item(tree, hf_afp_vol_bitmap, tvb, offset, 2,FALSE);
701                 sub_tree = proto_item_add_subtree(item, ett_afp_vol_bitmap);
702         }
703         
704         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Attributes,     tvb, offset, 2,FALSE);
705         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Signature,      tvb, offset, 2,FALSE);
706         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_CreateDate,     tvb, offset, 2,FALSE);
707         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ModDate,        tvb, offset, 2,FALSE);
708         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BackupDate,     tvb, offset, 2,FALSE);
709         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ID,             tvb, offset, 2,FALSE);
710         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesFree,      tvb, offset, 2,FALSE);
711         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesTotal,     tvb, offset, 2,FALSE);
712         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Name,           tvb, offset, 2,FALSE);
713         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesFree,   tvb, offset, 2,FALSE);
714         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesTotal,  tvb, offset, 2,FALSE);
715         proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BlockSize ,     tvb, offset, 2,FALSE);
716
717         return bitmap;
718 }
719
720 /* -------------------------- */
721 static guint16
722 decode_vol_attribute (proto_tree *tree, tvbuff_t *tvb, gint offset)
723 {
724         proto_tree *sub_tree = NULL;
725         proto_item *item;
726         guint16  bitmap;
727
728         bitmap = tvb_get_ntohs(tvb, offset);
729         if (tree) {
730                 item = proto_tree_add_item(tree, hf_afp_vol_attribute, tvb, offset, 2,FALSE);
731                 sub_tree = proto_item_add_subtree(item, ett_afp_vol_attribute);
732         }
733         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_ReadOnly                ,tvb, offset, 2,FALSE);
734         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_HasVolumePassword       ,tvb, offset, 2,FALSE);
735         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsFileIDs         ,tvb, offset, 2,FALSE);
736         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsCatSearch       ,tvb, offset, 2,FALSE);
737         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsBlankAccessPrivs,tvb, offset, 2,FALSE);
738         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUnixPrivs       ,tvb, offset, 2,FALSE);
739         proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUTF8Names       ,tvb, offset, 2,FALSE);
740                                                                                
741         return bitmap;                                                             
742 }                                                                              
743
744 /* -------------------------- 
745         cf AFP3.0.pdf page 38
746         date  are number of seconds from 12:00am on 01.01.2000 GMT
747         backup : 0x8000000 not set
748         from netatalk adouble.h 
749 */
750 #define DATE_NOT_SET         0x80000000 
751 #define AD_DATE_DELTA         946684800  
752 #define AD_DATE_TO_UNIX(x)    (x + AD_DATE_DELTA)  
753 static guint32
754 print_date(proto_tree *tree,int id, tvbuff_t *tvb, gint offset)
755 {
756         time_t date = tvb_get_ntohl(tvb, offset);
757         nstime_t tv;
758
759         tv.secs = AD_DATE_TO_UNIX(date);
760         tv.nsecs = 0;
761         proto_tree_add_time(tree, id, tvb, offset, 4, &tv);
762
763         return date;
764 }
765
766 /* -------------------------- */
767 static gint
768 parse_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
769 {
770         guint16 nameoff = 0;
771
772         if ((bitmap & kFPVolAttributeBit)) {
773                 decode_vol_attribute(tree,tvb,offset);
774                 offset += 2;
775         }
776         if ((bitmap & kFPVolSignatureBit)) {
777                 proto_tree_add_item(tree, hf_afp_vol_signature,tvb, offset, 2, FALSE);
778                 offset += 2;
779         }
780         if ((bitmap & kFPVolCreateDateBit)) {
781                 print_date(tree, hf_afp_vol_creation_date,tvb, offset);
782                 offset += 4;
783         }
784         if ((bitmap & kFPVolModDateBit)) {
785                 print_date(tree, hf_afp_vol_modification_date,tvb, offset);
786                 offset += 4;
787         }
788         if ((bitmap & kFPVolBackupDateBit)) {
789                 print_date(tree, hf_afp_vol_backup_date,tvb, offset);
790                 offset += 4;
791         }
792         if ((bitmap & kFPVolIDBit)) {
793                 proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
794                 offset += 2;
795         }
796         if ((bitmap & kFPVolBytesFreeBit)) {
797                 proto_tree_add_item(tree, hf_afp_vol_bytes_free,tvb, offset, 4, FALSE);
798                 offset += 4;
799         }
800         if ((bitmap & kFPVolBytesTotalBit)) {
801                 proto_tree_add_item(tree, hf_afp_vol_bytes_total,tvb, offset, 4, FALSE);
802                 offset += 4;
803         }
804         if ((bitmap & kFPVolNameBit)) {
805                 nameoff = tvb_get_ntohs(tvb, offset);
806                 proto_tree_add_item(tree, hf_afp_vol_name_offset,tvb, offset, 2, FALSE);
807                 offset += 2;
808         }
809         if ((bitmap & kFPVolExtBytesFreeBit)) {
810                 proto_tree_add_item(tree, hf_afp_vol_ex_bytes_free,tvb, offset, 8, FALSE);
811                 offset += 8;
812         }
813         if ((bitmap & kFPVolExtBytesTotalBit)) {
814                 proto_tree_add_item(tree, hf_afp_vol_ex_bytes_total,tvb, offset, 8, FALSE);
815                 offset += 8;
816         }
817         if ((bitmap & kFPVolBlockSizeBit)) {
818                 proto_tree_add_item(tree, hf_afp_vol_block_size,tvb, offset, 4, FALSE);
819                 offset += 4;
820         }
821         if (nameoff) {
822                 guint8 len;
823
824                 len = tvb_get_guint8(tvb, offset);
825                 proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
826                 offset += len +1;
827
828         }
829         return offset;
830 }
831
832 /* -------------------------- */
833 static guint16
834 decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
835 {
836         proto_tree *sub_tree = NULL;
837         proto_item *item;
838         guint16         bitmap;
839
840         bitmap = tvb_get_ntohs(tvb, offset);
841         if (tree) {
842                 item = proto_tree_add_item(tree, hf_afp_file_bitmap, tvb, offset, 2,FALSE);
843                 sub_tree = proto_item_add_subtree(item, ett_afp_file_bitmap);
844         }
845         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_Attributes      , tvb, offset, 2,FALSE);  
846         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ParentDirID    , tvb, offset, 2,FALSE);
847         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_CreateDate     , tvb, offset, 2,FALSE);
848         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ModDate        , tvb, offset, 2,FALSE);
849         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_BackupDate     , tvb, offset, 2,FALSE);
850         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_FinderInfo     , tvb, offset, 2,FALSE);
851         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LongName       , tvb, offset, 2,FALSE);
852         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ShortName      , tvb, offset, 2,FALSE);
853         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_NodeID         , tvb, offset, 2,FALSE);
854
855         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_DataForkLen    , tvb, offset, 2,FALSE);   
856         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_RsrcForkLen    , tvb, offset, 2,FALSE);
857         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtDataForkLen , tvb, offset, 2,FALSE);
858         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LaunchLimit    , tvb, offset, 2,FALSE);
859         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UTF8Name           , tvb, offset, 2,FALSE);
860
861         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtRsrcForkLen , tvb, offset, 2,FALSE);
862         proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UnixPrivs      , tvb, offset, 2,FALSE);
863
864         return bitmap;
865 }
866
867 /* -------------------------- */
868 static guint16 
869 decode_file_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset, int shared)
870 {
871         proto_tree *sub_tree = NULL;
872         proto_item *item;
873         guint16         attribute;
874         
875         attribute = tvb_get_ntohs(tvb, offset);
876         if (tree) {
877                 item = proto_tree_add_text(tree, tvb, offset, 2,
878                                         "File Attributes: 0x%04x", attribute);
879                 sub_tree = proto_item_add_subtree(item, ett_afp_file_attribute);
880         }
881         proto_tree_add_item(sub_tree, hf_afp_file_attribute_Invisible    , tvb, offset, 2,FALSE);  
882         if (!shared) 
883                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_MultiUser    , tvb, offset, 2,FALSE);
884
885         proto_tree_add_item(sub_tree, hf_afp_file_attribute_System       , tvb, offset, 2,FALSE);
886
887         if (!shared) {
888                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_DAlreadyOpen , tvb, offset, 2,FALSE);
889                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_RAlreadyOpen , tvb, offset, 2,FALSE);
890         }
891         /* writeinhibit is file only but Macs are setting it with FPSetFileDirParms too */
892         proto_tree_add_item(sub_tree, hf_afp_file_attribute_WriteInhibit , tvb, offset, 2,FALSE);
893         proto_tree_add_item(sub_tree, hf_afp_file_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
894         proto_tree_add_item(sub_tree, hf_afp_file_attribute_RenameInhibit, tvb, offset, 2,FALSE);
895         proto_tree_add_item(sub_tree, hf_afp_file_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
896
897         if (!shared) 
898                 proto_tree_add_item(sub_tree, hf_afp_file_attribute_CopyProtect  , tvb, offset, 2,FALSE);
899
900         proto_tree_add_item(sub_tree, hf_afp_file_attribute_SetClear     , tvb, offset, 2,FALSE);
901
902         return(attribute);
903 }
904
905 static void
906 decode_access_rights (proto_tree *tree, tvbuff_t *tvb, int hf, gint offset)
907 {
908         proto_tree *sub_tree;
909         proto_item *item;
910
911         if (tree) {
912                 item = proto_tree_add_item(tree, hf, tvb, offset, 4, FALSE);
913                 sub_tree = proto_item_add_subtree(item, ett_afp_dir_ar);
914
915                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_search, tvb, offset, 4,   FALSE);  
916                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_read  , tvb, offset, 4,   FALSE);  
917                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_write , tvb, offset, 4,   FALSE);  
918
919                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_search, tvb, offset, 4,   FALSE);  
920                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_read  , tvb, offset, 4,   FALSE);  
921                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_write , tvb, offset, 4,   FALSE);  
922
923                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_search, tvb, offset, 4,   FALSE);  
924                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_read  , tvb, offset, 4,   FALSE);  
925                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_write , tvb, offset, 4,   FALSE);  
926
927                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_search, tvb, offset, 4,   FALSE);  
928                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_read  , tvb, offset, 4,   FALSE);  
929                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_write , tvb, offset, 4,   FALSE);  
930
931                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_blank   , tvb, offset, 4,   FALSE);  
932                 proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_own   , tvb, offset, 4,   FALSE);  
933         }
934 }               
935
936 static void
937 decode_unix_privs (proto_tree *tree, tvbuff_t *tvb, gint offset)
938 {
939         proto_tree *sub_tree;
940         proto_item *item;
941
942         if (tree) {
943                 item = proto_tree_add_text(tree, tvb, offset, 16,
944                     "UNIX privileges");
945                 sub_tree = proto_item_add_subtree(item, ett_afp_unix_privs);
946
947                 proto_tree_add_item(sub_tree, hf_afp_unix_privs_uid, tvb, offset, 4, FALSE);
948                 proto_tree_add_item(sub_tree, hf_afp_unix_privs_gid, tvb, offset+4, 4, FALSE);
949                 proto_tree_add_item(sub_tree, hf_afp_unix_privs_permissions, tvb, offset+8, 4, FALSE);
950                 decode_access_rights(sub_tree, tvb, hf_afp_unix_privs_ua_permissions, offset+12);
951         }
952 }
953
954 /* -------------------------- */
955 static gint
956 parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap, int shared)
957 {
958         guint16 lnameoff = 0;
959         guint16 snameoff = 0;
960         guint16 unameoff = 0;
961         gint    max_offset = 0;
962
963         gint    org_offset = offset;
964
965         if ((bitmap & kFPAttributeBit)) {
966                 decode_file_attribute(tree, tvb, offset, shared);
967                 offset += 2;
968         }
969         if ((bitmap & kFPParentDirIDBit)) {
970                 proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
971                 offset += 4;
972         }
973         if ((bitmap & kFPCreateDateBit)) {
974                 print_date(tree, hf_afp_creation_date,tvb, offset);
975                 offset += 4;
976         }
977         if ((bitmap & kFPModDateBit)) {
978                 print_date(tree, hf_afp_modification_date,tvb, offset);
979                 offset += 4;
980         }
981         if ((bitmap & kFPBackupDateBit)) {
982                 print_date(tree, hf_afp_backup_date,tvb, offset);
983                 offset += 4;
984         }
985         if ((bitmap & kFPFinderInfoBit)) {
986                 proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
987                 offset += 32;
988         }
989         if ((bitmap & kFPLongNameBit)) {
990                 gint tp_ofs;
991                 guint8 len;
992
993                 lnameoff = tvb_get_ntohs(tvb, offset);
994                 if (lnameoff) {
995                         tp_ofs = lnameoff +org_offset;
996                         proto_tree_add_item(tree, hf_afp_long_name_offset,tvb, offset, 2, FALSE);
997                         len = tvb_get_guint8(tvb, tp_ofs);
998                         proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
999                         tp_ofs++;
1000                         proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
1001                         tp_ofs += len;
1002                         max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
1003                 }
1004                 offset += 2;
1005         }
1006         if ((bitmap & kFPShortNameBit)) {
1007                 snameoff = tvb_get_ntohs(tvb, offset);
1008                 proto_tree_add_item(tree, hf_afp_short_name_offset,tvb, offset, 2, FALSE);
1009                 offset += 2;
1010         }
1011         if ((bitmap & kFPNodeIDBit)) {
1012                 proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
1013                 offset += 4;
1014         }
1015
1016         if ((bitmap & kFPDataForkLenBit)) {
1017                 proto_tree_add_item(tree, hf_afp_file_DataForkLen, tvb, offset, 4,FALSE);
1018                 offset += 4;
1019         }
1020         
1021         if ((bitmap & kFPRsrcForkLenBit)) {
1022                 proto_tree_add_item(tree, hf_afp_file_RsrcForkLen, tvb, offset, 4,FALSE);
1023                 offset += 4;
1024         }
1025
1026         if ((bitmap & kFPExtDataForkLenBit)) {
1027                 proto_tree_add_item(tree, hf_afp_file_ExtDataForkLen, tvb, offset, 8,FALSE);
1028                 offset += 8;
1029         }
1030
1031         if ((bitmap & kFPLaunchLimitBit)) {
1032                 offset += 2;    /* ? */
1033         }
1034
1035         if ((bitmap & kFPUTF8NameBit)) {
1036                 unameoff = tvb_get_ntohs(tvb, offset);
1037                 proto_tree_add_item(tree, hf_afp_unicode_name_offset,tvb, offset, 2, FALSE);
1038                 offset += 2;
1039         }
1040
1041         if ((bitmap & kFPExtRsrcForkLenBit)) {
1042                 proto_tree_add_item(tree, hf_afp_file_ExtRsrcForkLen, tvb, offset, 8,FALSE);
1043                 offset += 8;
1044         }
1045
1046         if ((bitmap & kFPUnixPrivsBit_file)) {
1047                 /*
1048                  * XXX - the AFP 3.0 spec says this is "Four bytes", but
1049                  * also says the privileges are "stored in an FPUnixPrivs
1050                  * structure", which is 16 bytes long.
1051                  *
1052                  * We assume, for now, that the latter is true.
1053                  */
1054                 decode_unix_privs(tree, tvb, offset);
1055                 offset += 16;
1056         }
1057
1058         return (max_offset)?max_offset:offset;
1059 }
1060
1061 /* -------------------------- */
1062 static guint16 
1063 decode_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
1064 {
1065         proto_tree *sub_tree = NULL;
1066         proto_item *item;
1067         guint16         bitmap;
1068         
1069         bitmap = tvb_get_ntohs(tvb, offset);
1070         if (tree) {
1071                 item = proto_tree_add_item(tree, hf_afp_dir_bitmap, tvb, offset, 2,FALSE);
1072                 sub_tree = proto_item_add_subtree(item, ett_afp_dir_bitmap);
1073         }
1074         
1075         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_Attributes      , tvb, offset, 2,FALSE);  
1076         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ParentDirID    , tvb, offset, 2,FALSE);
1077         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_CreateDate     , tvb, offset, 2,FALSE);
1078         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ModDate        , tvb, offset, 2,FALSE);
1079         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_BackupDate     , tvb, offset, 2,FALSE);
1080         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_FinderInfo     , tvb, offset, 2,FALSE);
1081         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_LongName       , tvb, offset, 2,FALSE);
1082         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ShortName      , tvb, offset, 2,FALSE);
1083         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_NodeID         , tvb, offset, 2,FALSE);
1084         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OffspringCount , tvb, offset, 2,FALSE);
1085         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OwnerID        , tvb, offset, 2,FALSE);
1086         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_GroupID        , tvb, offset, 2,FALSE);
1087         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_AccessRights   , tvb, offset, 2,FALSE);
1088         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UTF8Name           , tvb, offset, 2,FALSE);
1089         proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UnixPrivs      , tvb, offset, 2,FALSE);
1090
1091         return bitmap;
1092 }
1093
1094 /* -------------------------- */
1095 static guint16 
1096 decode_dir_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset)
1097 {
1098         proto_tree *sub_tree = NULL;
1099         proto_item *item;
1100         guint16         attribute;
1101         
1102         attribute = tvb_get_ntohs(tvb, offset);
1103         if (tree) {
1104                 item = proto_tree_add_text(tree, tvb, offset, 2,
1105                                         "Directory Attributes: 0x%04x", attribute);
1106                 sub_tree = proto_item_add_subtree(item, ett_afp_dir_attribute);
1107         }
1108         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Invisible    , tvb, offset, 2,FALSE);  
1109         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_IsExpFolder  , tvb, offset, 2,FALSE);
1110         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_System       , tvb, offset, 2,FALSE);
1111         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Mounted      , tvb, offset, 2,FALSE);
1112         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_InExpFolder  , tvb, offset, 2,FALSE);
1113         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
1114         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_RenameInhibit, tvb, offset, 2,FALSE);
1115         proto_tree_add_item(sub_tree, hf_afp_dir_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
1116
1117         return(attribute);
1118 }
1119
1120 /* -------------------------- */
1121 static gint
1122 parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
1123 {
1124         guint16 lnameoff = 0;
1125         guint16 snameoff = 0;
1126         guint16 unameoff = 0;
1127         gint    max_offset = 0;
1128
1129         gint    org_offset = offset;
1130
1131         if ((bitmap & kFPAttributeBit)) {
1132                 decode_dir_attribute(tree, tvb, offset);
1133                 offset += 2;
1134         }
1135         if ((bitmap & kFPParentDirIDBit)) {
1136                 proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1137                 offset += 4;
1138         }
1139         if ((bitmap & kFPCreateDateBit)) {
1140                 print_date(tree, hf_afp_creation_date,tvb, offset);
1141                 offset += 4;
1142         }
1143         if ((bitmap & kFPModDateBit)) {
1144                 print_date(tree, hf_afp_modification_date,tvb, offset);
1145                 offset += 4;
1146         }
1147         if ((bitmap & kFPBackupDateBit)) {
1148                 print_date(tree, hf_afp_backup_date,tvb, offset);
1149                 offset += 4;
1150         }
1151         if ((bitmap & kFPFinderInfoBit)) {
1152                 proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
1153                 offset += 32;
1154         }
1155         if ((bitmap & kFPLongNameBit)) {
1156                 gint tp_ofs;
1157                 guint8 len;
1158                 lnameoff = tvb_get_ntohs(tvb, offset);
1159                 if (lnameoff) {
1160                         tp_ofs = lnameoff +org_offset;
1161                         proto_tree_add_item(tree, hf_afp_long_name_offset,tvb, offset, 2, FALSE);
1162                         len = tvb_get_guint8(tvb, tp_ofs);
1163                         proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
1164                         tp_ofs++;
1165                         proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
1166                         tp_ofs += len;
1167                         max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
1168                 }
1169                 offset += 2;
1170         }
1171         if ((bitmap & kFPShortNameBit)) {
1172                 snameoff = tvb_get_ntohs(tvb, offset);
1173                 proto_tree_add_item(tree, hf_afp_short_name_offset,tvb, offset, 2, FALSE);
1174                 offset += 2;
1175         }
1176         if ((bitmap & kFPNodeIDBit)) {
1177                 proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
1178                 offset += 4;
1179         }
1180         if ((bitmap & kFPOffspringCountBit)) {
1181                 proto_tree_add_item(tree, hf_afp_dir_offspring, tvb, offset, 2,FALSE);
1182                 offset += 2;            /* error in AFP3.0.pdf */
1183         }
1184         if ((bitmap & kFPOwnerIDBit)) {
1185                 proto_tree_add_item(tree, hf_afp_dir_OwnerID, tvb, offset, 4,   FALSE);  
1186                 offset += 4;
1187         }
1188         if ((bitmap & kFPGroupIDBit)) {
1189                 proto_tree_add_item(tree, hf_afp_dir_GroupID, tvb, offset, 4,   FALSE);  
1190                 offset += 4;
1191         }
1192         if ((bitmap & kFPAccessRightsBit)) {
1193                 decode_access_rights(tree, tvb, hf_afp_dir_ar, offset);
1194                 offset += 4;
1195         }
1196         if ((bitmap & kFPUTF8NameBit)) {
1197                 unameoff = tvb_get_ntohs(tvb, offset);
1198                 proto_tree_add_item(tree, hf_afp_unicode_name_offset,tvb, offset, 2, FALSE);
1199                 offset += 2;
1200         }
1201         if ((bitmap & kFPUnixPrivsBit)) {
1202                 /*
1203                  * XXX - the AFP 3.0 spec says this is "Four bytes", but
1204                  * also says the privileges are "stored in an FPUnixPrivs
1205                  * structure", which is 16 bytes long.
1206                  *
1207                  * We assume, for now, that the latter is true.
1208                  */
1209                 decode_unix_privs(tree, tvb, offset);
1210                 offset += 16;
1211         }
1212         return (max_offset)?max_offset:offset;
1213 }
1214
1215 /* -------------------------- */
1216 static gchar *
1217 name_in_bitmap(tvbuff_t *tvb, gint *offset, guint16 bitmap)
1218 {
1219         gchar *name;
1220         gint    org_offset = *offset;
1221         guint16 nameoff;
1222         guint8  len;
1223         gint    tp_ofs;
1224         
1225         name = NULL;
1226         if ((bitmap & kFPAttributeBit)) 
1227                 *offset += 2;
1228         if ((bitmap & kFPParentDirIDBit))
1229                 *offset += 4;
1230         if ((bitmap & kFPCreateDateBit)) 
1231                 *offset += 4;
1232         if ((bitmap & kFPModDateBit))
1233                 *offset += 4;
1234         if ((bitmap & kFPBackupDateBit)) 
1235                 *offset += 4;
1236         if ((bitmap & kFPFinderInfoBit)) 
1237                 *offset += 32;
1238         
1239         if ((bitmap & kFPLongNameBit)) {
1240                 nameoff = tvb_get_ntohs(tvb, *offset);
1241                 if (nameoff) {
1242                         tp_ofs = nameoff +org_offset;
1243                         len = tvb_get_guint8(tvb, tp_ofs);
1244                         tp_ofs++;
1245                         if (!(name = g_malloc(len +1)))
1246                                 return name;
1247                         tvb_memcpy(tvb, name, tp_ofs, len);
1248                         *(name +len) = 0;
1249                         return name;
1250                 }
1251         }
1252         /* short name ? */
1253         return name;
1254 }
1255
1256 /* -------------------------- */
1257 static gchar *
1258 name_in_dbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
1259 {
1260         gchar *name;
1261         
1262         name = name_in_bitmap(tvb, &offset, bitmap);
1263         if (name != NULL)
1264                 return name;
1265         /*
1266                 check UTF8 name 
1267         */
1268         
1269         return name;
1270 }
1271
1272 /* -------------------------- */
1273 static gchar *
1274 name_in_fbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
1275 {
1276         gchar *name;
1277         
1278         name = name_in_bitmap(tvb, &offset, bitmap);
1279         if (name != NULL)
1280                 return name;
1281         /*
1282                 check UTF8 name 
1283         */
1284         
1285         return name;
1286 }
1287
1288 /* -------------------------- */
1289 static gint
1290 decode_vol_did(proto_tree *tree, tvbuff_t *tvb, gint offset)
1291 {
1292         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1293         offset += 2;
1294
1295         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
1296         offset += 4;
1297         return offset;
1298 }
1299
1300 /* -------------------------- */
1301 static gint
1302 decode_vol_did_file_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
1303 {
1304         offset = decode_vol_did(tree, tvb, offset);
1305
1306         decode_file_bitmap(tree, tvb, offset);
1307         offset += 2;
1308         
1309         decode_dir_bitmap(tree, tvb, offset);
1310         offset += 2;
1311         
1312         return offset;
1313 }
1314
1315 /* ------------------------ */
1316 static gchar *
1317 get_name(tvbuff_t *tvb, int offset, int type)
1318 {
1319         guint8 len;
1320         gchar *string;
1321
1322         len = tvb_get_guint8(tvb, offset);
1323         offset++;
1324
1325         switch (type) {
1326         case 1:
1327         case 2:
1328                 string = tvb_format_text(tvb,offset, len);
1329                 break;
1330         case 3:
1331                 string = "error Unicode...,next time";
1332                 break;
1333         default:
1334                 string = "unknow type";
1335                 break;
1336         }
1337         return string;
1338 }
1339 /* -------------------------- */
1340 static gint
1341 decode_name_label (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, const gchar *label)
1342 {
1343         int len;
1344         gchar *name;
1345         guint8 type;
1346         proto_tree *sub_tree = NULL;
1347         proto_item *item;
1348                 
1349         type = tvb_get_guint8(tvb, offset);
1350         len = tvb_get_guint8(tvb, offset +1);
1351         name = get_name(tvb, offset +1, type);
1352
1353         if (pinfo && check_col(pinfo->cinfo, COL_INFO)) {
1354                 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", name);
1355         }
1356
1357         if (tree) {
1358                 item = proto_tree_add_text(tree, tvb, offset, len +2, label, name);
1359                 sub_tree = proto_item_add_subtree(item, ett_afp_path_name);
1360                 proto_tree_add_item(  sub_tree, hf_afp_path_type, tvb, offset,   1,FALSE);
1361                 offset++;
1362                 proto_tree_add_item(  sub_tree, hf_afp_path_len,  tvb, offset,   1,FALSE);
1363                 offset++;
1364                 proto_tree_add_string(sub_tree, hf_afp_path_name, tvb, offset, len,name);
1365         }
1366         else 
1367                 offset += 2;
1368
1369         return offset +len;
1370 }
1371
1372 /* -------------------------- */
1373 static gint
1374 decode_name (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset)
1375 {
1376         return decode_name_label(tree, pinfo, tvb, offset, "Path: %s");
1377 }
1378
1379 /* ************************** */
1380 static gint
1381 dissect_query_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1382 {
1383         int len;
1384         
1385         PAD(1);
1386
1387         decode_vol_bitmap(tree, tvb, offset);
1388         offset += 2;
1389         
1390         len = tvb_get_guint8(tvb, offset);
1391
1392         if (check_col(pinfo->cinfo, COL_INFO)) {
1393                 const gchar *rep;
1394                 rep = get_name(tvb, offset, 2);
1395                 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", rep);
1396         }
1397
1398         if (!tree)
1399                 return offset;
1400                 
1401         proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
1402         offset += len +1;
1403                 
1404         len = tvb_reported_length_remaining(tvb,offset);
1405         if (len >= 8) {
1406                 /* optionnal password */
1407                 proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, 8,FALSE);
1408                 offset += 8;
1409         }
1410         return offset;
1411 }
1412
1413 /* -------------------------- */
1414 static gint
1415 dissect_reply_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1416 {
1417         guint16 bitmap;
1418         
1419         if (!tree)
1420                 return offset;
1421         bitmap = decode_vol_bitmap(tree, tvb, offset);
1422         offset += 2;
1423         offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
1424
1425         return offset;
1426 }
1427
1428 /* ************************** */
1429 static gint
1430 dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1431 {
1432         guint8 num;
1433         guint8 len;
1434         guint8 flag;
1435         guint8 i;
1436         proto_tree *sub_tree = NULL;
1437         proto_tree *flag_tree;
1438         proto_item *item;
1439         proto_item *ti;
1440         
1441         if (!tree)
1442                 return offset;
1443
1444         print_date(tree, hf_afp_server_time,tvb, offset);
1445         offset += 4;
1446
1447         num = tvb_get_guint8(tvb, offset);
1448         item = proto_tree_add_text(tree, tvb, offset, 1, "Volumes : %d", num);
1449         sub_tree = proto_item_add_subtree(item, ett_afp_server_vol);
1450         offset++;
1451                 
1452         for (i = 0; i < num; i++) {
1453                 const gchar *rep;
1454                 
1455                 item = proto_tree_add_text(sub_tree, tvb, offset, -1,"Volume");
1456                 tree = proto_item_add_subtree(item, ett_afp_vol_list);
1457
1458                 flag = tvb_get_guint8(tvb, offset);
1459
1460                 ti = proto_tree_add_text(tree, tvb, offset , 1,"Flags : 0x%02x", flag);
1461                 flag_tree = proto_item_add_subtree(ti, ett_afp_vol_flag);
1462                 proto_tree_add_item(flag_tree, hf_afp_vol_flag_passwd, tvb, offset, 1,FALSE);
1463                 proto_tree_add_item(flag_tree, hf_afp_vol_flag_unix_priv ,tvb, offset, 1,FALSE);
1464                 offset++;
1465
1466                 len  = tvb_get_guint8(tvb, offset) +1;
1467                 rep = get_name(tvb, offset, 2);
1468                 proto_item_set_text(item, rep);
1469                 proto_item_set_len(item, len +1);     
1470
1471                 proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
1472
1473                 offset += len;
1474         }                       
1475         return offset;
1476 }
1477
1478 /* ************************** 
1479         next calls use the same format :
1480                 1 pad byte 
1481                 volume id
1482         AFP_FLUSH
1483         AFP_CLOSEVOL
1484         AFP_OPENDT
1485 */
1486 static gint
1487 dissect_query_afp_with_vol_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1488 {
1489
1490         if (!tree)
1491                 return offset;
1492         PAD(1);
1493         
1494         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1495         offset += 2;
1496         return offset;
1497 }
1498
1499 /* ************************** */
1500 static gint
1501 dissect_query_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1502 {
1503         proto_tree *sub_tree = NULL;
1504         proto_item *item;
1505
1506         proto_tree_add_item(tree, hf_afp_fork_type, tvb, offset, 1,FALSE);
1507         offset++;
1508
1509         offset = decode_vol_did(tree, tvb, offset);
1510         
1511         decode_file_bitmap(tree, tvb, offset);
1512         offset += 2;
1513         if (tree) {
1514                 item = proto_tree_add_item(tree, hf_afp_access_mode, tvb, offset, 2,FALSE);
1515                 sub_tree = proto_item_add_subtree(item, ett_afp_access_mode);
1516
1517                 proto_tree_add_item(sub_tree, hf_afp_access_read      , tvb, offset, 2,FALSE);
1518                 proto_tree_add_item(sub_tree, hf_afp_access_write     , tvb, offset, 2,FALSE);
1519                 proto_tree_add_item(sub_tree, hf_afp_access_deny_read , tvb, offset, 2,FALSE);
1520                 proto_tree_add_item(sub_tree, hf_afp_access_deny_write, tvb, offset, 2,FALSE);
1521         }
1522         offset += 2;
1523
1524         offset = decode_name(tree, pinfo, tvb, offset);
1525
1526         return offset;
1527 }
1528
1529 /* -------------------------- */
1530 static gint
1531 dissect_reply_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1532 {
1533         int f_bitmap;
1534
1535         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1536         offset += 2;
1537
1538         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1539         offset += 2;
1540
1541         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1542
1543         return offset;
1544 }
1545
1546 /* ************************** */
1547 static gint
1548 dissect_query_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1549 {
1550         
1551         PAD(1);
1552         offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
1553
1554         proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
1555         offset += 2;
1556
1557         proto_tree_add_item(tree, hf_afp_start_index, tvb, offset, 2,FALSE);
1558         offset += 2;
1559
1560         proto_tree_add_item(tree, hf_afp_max_reply_size, tvb, offset, 2,FALSE);
1561         offset += 2;
1562
1563         offset = decode_name(tree, pinfo, tvb, offset);
1564
1565         return offset;
1566 }
1567
1568 /* -------------------------- */
1569 static int
1570 loop_record(tvbuff_t *tvb, proto_tree *ptree, gint offset, 
1571                 int count, guint16 d_bitmap, guint16 f_bitmap, int add)
1572 {
1573         proto_tree *tree = NULL;
1574         proto_item *item;
1575         gchar   *name;
1576         guint8  flags;
1577         guint8  size;
1578         gint    org;
1579         int i;
1580
1581         for (i = 0; i < count; i++) {
1582                 org = offset;
1583                 name = NULL;
1584                 size = tvb_get_guint8(tvb, offset) +add;
1585                 flags = tvb_get_guint8(tvb, offset +1);
1586
1587                 if (ptree) {
1588                         if (flags) {
1589                                 name = name_in_dbitmap(tvb, offset +2, d_bitmap);
1590                         }       
1591                         else {
1592                                 name = name_in_fbitmap(tvb, offset +2, f_bitmap);
1593                         }
1594                         if (!name) {
1595                                 if (!(name = g_malloc(50))) { /* no memory ! */
1596                                 }
1597                                 snprintf(name, 50,"line %d", i +1);
1598                         }
1599                         item = proto_tree_add_text(ptree, tvb, offset, size, name);
1600                         tree = proto_item_add_subtree(item, ett_afp_enumerate_line);
1601                 }
1602                 proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
1603                 offset++;
1604
1605                 proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
1606                 offset++;
1607                 if (flags) {
1608                         offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
1609                 }
1610                 else {
1611                         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1612                 }
1613                 if ((offset & 1)) 
1614                         PAD(1);
1615                 offset = org +size;             /* play safe */
1616                 if (ptree)
1617                         g_free((gpointer)name);
1618         }       
1619         return offset;
1620 }
1621
1622 /* ------------------------- */
1623 static gint
1624 dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1625 {
1626         proto_tree *sub_tree = NULL;
1627         proto_item *item;
1628         int count;
1629         guint16 f_bitmap;
1630         guint16 d_bitmap;
1631         
1632         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1633         offset += 2;
1634         
1635         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
1636         offset += 2;
1637
1638         count = tvb_get_ntohs(tvb, offset);
1639         if (tree) {
1640                 item = proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
1641                 sub_tree = proto_item_add_subtree(item, ett_afp_enumerate);
1642         }
1643         offset += 2;
1644
1645         return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap,0);
1646
1647 }
1648 /* **************************/
1649 static gint
1650 dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ptree, gint offset)
1651 {
1652         proto_tree *tree = NULL;
1653         proto_item *item;
1654         guint16 f_bitmap;
1655         guint16 d_bitmap;
1656         guint32 r_bitmap;
1657         guint8  size;
1658         gint    org;
1659
1660         if (!ptree)
1661                 return offset;
1662         PAD(1);
1663         
1664         proto_tree_add_item(ptree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1665         offset += 2;
1666
1667         proto_tree_add_item(ptree, hf_afp_cat_req_matches, tvb, offset, 4,FALSE);
1668         offset += 4;
1669
1670         proto_tree_add_item(ptree, hf_afp_reserved, tvb, offset, 4,FALSE);
1671         offset += 4;
1672
1673         proto_tree_add_item(ptree, hf_afp_cat_position, tvb, offset, 16,FALSE);
1674         offset += 16;
1675         
1676         f_bitmap = decode_file_bitmap(ptree, tvb, offset);
1677         offset += 2;
1678         
1679         d_bitmap = decode_dir_bitmap(ptree, tvb, offset);
1680         offset += 2;
1681
1682         /* FIXME req bitmap */
1683         item = proto_tree_add_text(ptree, tvb, offset, 4, "Request bitmap");
1684         tree = proto_item_add_subtree(item, ett_afp_cat_r_bitmap);
1685         r_bitmap = decode_file_bitmap(tree, tvb, offset+2);
1686         offset += 4;
1687
1688         /* spec 1 */
1689         org = offset;
1690         size = tvb_get_guint8(tvb, offset) +2;
1691
1692         item = proto_tree_add_text(ptree, tvb, offset, size, "Spec 1");
1693         tree = proto_item_add_subtree(item, ett_afp_cat_spec);
1694
1695         proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
1696         offset++;
1697         PAD(1); 
1698
1699         offset = parse_file_bitmap(tree, tvb, offset, r_bitmap,0);
1700         offset = org +size;
1701
1702         /* spec 2 */
1703         org = offset;
1704         size = tvb_get_guint8(tvb, offset) +2;
1705
1706         item = proto_tree_add_text(ptree, tvb, offset, size, "Spec 2");
1707         tree = proto_item_add_subtree(item, ett_afp_cat_spec);
1708
1709         proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
1710         offset++;
1711         PAD(1);
1712         
1713         offset = parse_file_bitmap(tree, tvb, offset, r_bitmap,0);
1714         offset = org +size;
1715
1716         return offset;
1717 }
1718
1719 /* -------------------------- */
1720 static gint
1721 dissect_reply_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1722 {
1723         proto_tree *sub_tree = NULL;
1724         proto_item *item;
1725         guint16 f_bitmap;
1726         guint16 d_bitmap;
1727         int count;
1728         
1729         proto_tree_add_item(tree, hf_afp_cat_position, tvb, offset, 16,FALSE);
1730         offset += 16;
1731
1732         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1733         offset += 2;
1734         
1735         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
1736         offset += 2;
1737
1738         count = tvb_get_ntohl(tvb, offset);
1739         if (tree) {
1740                 item = proto_tree_add_item(tree, hf_afp_cat_count, tvb, offset, 4,FALSE);
1741                 sub_tree = proto_item_add_subtree(item, ett_afp_cat_search);
1742         }
1743         offset += 4;
1744         return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap, 2);
1745 }
1746
1747 /* **************************/
1748 static gint
1749 dissect_query_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1750 {
1751         PAD(1)
1752         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1753         offset += 2;
1754
1755         decode_vol_bitmap(tree, tvb, offset);
1756         offset += 2;
1757         
1758         return offset;  
1759 }
1760
1761 /* ------------------------ */
1762 static gint
1763 dissect_reply_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1764 {
1765         guint16 bitmap;
1766
1767         bitmap = decode_vol_bitmap(tree, tvb, offset);
1768         offset += 2;
1769
1770         offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
1771
1772         return offset;
1773 }
1774
1775 /* **************************/
1776 static gint
1777 dissect_query_afp_set_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1778 {
1779         guint16 bitmap;
1780
1781         PAD(1)
1782         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
1783         offset += 2;
1784
1785         bitmap = decode_vol_bitmap(tree, tvb, offset);
1786         offset += 2;
1787         
1788         offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
1789
1790         return offset;  
1791 }
1792
1793 /* ***************************/
1794 static gint
1795 dissect_query_afp_login(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1796 {
1797         int len;
1798         const char *uam;
1799     
1800         len = tvb_get_guint8(tvb, offset);
1801         proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
1802         offset += len +1;
1803         len = tvb_get_guint8(tvb, offset);
1804         uam = tvb_get_ptr(tvb, offset +1, len);
1805         proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
1806         offset += len +1;
1807
1808         if (!strncasecmp(uam, "Cleartxt passwrd", len)) {
1809                 /* clear text */
1810                 len = tvb_get_guint8(tvb, offset);
1811                 proto_tree_add_item(tree, hf_afp_user, tvb, offset, 1,FALSE);
1812                 offset += len +1;
1813
1814                 len = 8; /* tvb_strsize(tvb, offset);*/
1815                 proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
1816                 offset += len;
1817         }
1818         else if (!strncasecmp(uam, "No User Authent", len)) {
1819         }
1820         return(offset);
1821 }
1822
1823 /* ************************** */
1824 static gint
1825 dissect_query_afp_write(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1826 {
1827         proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
1828         offset += 1;
1829
1830         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1831         offset += 2;
1832
1833         proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
1834         offset += 4;
1835
1836         proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
1837         offset += 4;
1838
1839         return offset;
1840 }
1841
1842 static gint
1843 dissect_reply_afp_write(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1844 {
1845         proto_tree_add_item(tree, hf_afp_last_written, tvb, offset, 4, FALSE);
1846         offset += 4;
1847         
1848         return offset;
1849 }
1850
1851 /* ************************** */
1852 static gint
1853 dissect_query_afp_write_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1854 {
1855         proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
1856         offset += 1;
1857
1858         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1859         offset += 2;
1860
1861         proto_tree_add_item(tree, hf_afp_offset64, tvb, offset, 8,FALSE);
1862         offset += 8;
1863
1864         proto_tree_add_item(tree, hf_afp_rw_count64, tvb, offset, 8,FALSE);
1865         offset += 8;
1866
1867         return offset;
1868 }
1869
1870 static gint
1871 dissect_reply_afp_write_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1872 {
1873         proto_tree_add_item(tree, hf_afp_last_written64, tvb, offset, 8, FALSE);
1874         offset += 8;
1875         
1876         return offset;
1877 }
1878
1879 /* ************************** */
1880 static gint
1881 dissect_query_afp_read(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1882 {
1883         PAD(1);
1884         
1885         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1886         offset += 2;
1887
1888         proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
1889         offset += 4;
1890
1891         proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
1892         offset += 4;
1893
1894         proto_tree_add_item(tree, hf_afp_newline_mask, tvb, offset, 1,FALSE);
1895         offset++;
1896         
1897         proto_tree_add_item(tree, hf_afp_newline_char, tvb, offset, 1,FALSE);
1898         offset++;
1899
1900         return offset;
1901 }
1902
1903 /* ************************** */
1904 static gint
1905 dissect_query_afp_read_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1906 {
1907         PAD(1);
1908         
1909         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1910         offset += 2;
1911
1912         proto_tree_add_item(tree, hf_afp_offset64, tvb, offset, 8,FALSE);
1913         offset += 8;
1914
1915         proto_tree_add_item(tree, hf_afp_rw_count64, tvb, offset, 8,FALSE);
1916         offset += 8;
1917
1918         return offset;
1919 }
1920
1921 /* ************************** 
1922    Open desktop call 
1923    query is the same than       AFP_FLUSH, AFP_CLOSEVOL
1924
1925 */
1926 static gint
1927 dissect_reply_afp_open_dt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1928 {
1929         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
1930         offset += 2;
1931
1932         return offset;
1933 }
1934
1935 /* ************************** 
1936         no reply
1937 */
1938 static gint
1939 dissect_query_afp_close_dt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1940 {
1941         PAD(1);
1942         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
1943         offset += 2;
1944
1945         return offset;
1946 }
1947
1948 /* ************************** 
1949         calls using the same format :
1950                 1 pad byte 
1951                 fork number 
1952         AFP_FLUSHFORK
1953         AFP_CLOSEFORK
1954 */
1955 static gint
1956 dissect_query_afp_with_fork(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1957 {
1958         PAD(1);
1959         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
1960         offset += 2;
1961
1962         return offset;
1963 }
1964
1965 /* ************************** */
1966 static gint
1967 dissect_query_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
1968 {
1969         PAD(1);
1970         offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
1971
1972         offset = decode_name(tree, pinfo, tvb, offset);
1973
1974         return offset;
1975 }
1976
1977 /* -------------------------- */
1978 static gint
1979 dissect_reply_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
1980 {
1981         guint8  flags;
1982         guint16 f_bitmap, d_bitmap;
1983
1984         f_bitmap = decode_file_bitmap(tree, tvb, offset);
1985         offset += 2;
1986         
1987         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
1988         offset += 2;
1989
1990         flags = tvb_get_guint8(tvb, offset);
1991         proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
1992         offset++;
1993         PAD(1);
1994         if (flags) {
1995                 offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
1996         }
1997         else {
1998                 offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
1999         }
2000         return offset;
2001 }
2002
2003 /* ************************** 
2004         no reply
2005 */
2006 static gint
2007 dissect_query_afp_set_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2008 {
2009         guint16 f_bitmap;
2010         
2011         PAD(1);
2012         offset = decode_vol_did(tree, tvb, offset);
2013
2014         f_bitmap = decode_file_bitmap(tree, tvb, offset);
2015         offset += 2;
2016         
2017         offset = decode_name(tree, pinfo, tvb, offset);
2018
2019         if ((offset & 1))
2020                 PAD(1);
2021         /* did:name can be a file or a folder but only the intersection between 
2022          * file bitmap and dir bitmap can be set.
2023          * Well it's in afp spec, but clients (Mac) are setting 'file only' bits with this call
2024          * (WriteInhibit for example).
2025          */
2026         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 1);
2027
2028         return offset;
2029 }
2030
2031 /* ************************** 
2032         no reply
2033 */
2034 static gint
2035 dissect_query_afp_set_file_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2036 {
2037         guint16 f_bitmap;
2038         
2039         PAD(1);
2040         offset = decode_vol_did(tree, tvb, offset);
2041
2042         f_bitmap = decode_file_bitmap(tree, tvb, offset);
2043         offset += 2;
2044         
2045         offset = decode_name(tree, pinfo, tvb, offset);
2046
2047         if ((offset & 1))
2048                 PAD(1);
2049         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 0);
2050
2051         return offset;
2052 }
2053
2054 /* ************************** 
2055         no reply
2056 */
2057 static gint
2058 dissect_query_afp_set_dir_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2059 {
2060         guint16 d_bitmap;
2061
2062         PAD(1);
2063         offset = decode_vol_did(tree, tvb, offset);
2064
2065         d_bitmap = decode_dir_bitmap(tree, tvb, offset);
2066         offset += 2;
2067         
2068         offset = decode_name(tree, pinfo, tvb, offset);
2069
2070         if ((offset & 1))
2071                 PAD(1);
2072         offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
2073
2074         offset += 4;
2075         return offset;
2076 }
2077
2078 /* **************************
2079         AFP_DELETE
2080         AFP_CREATE_DIR
2081  */
2082 static gint
2083 dissect_query_afp_create_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2084 {
2085         PAD(1);
2086         offset = decode_vol_did(tree, tvb, offset);
2087
2088         offset = decode_name(tree, pinfo, tvb, offset);
2089         return offset;
2090 }
2091
2092 /* -------------------------- 
2093         AFP_MOVE
2094 */
2095 static gint
2096 dissect_reply_afp_create_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2097 {
2098         proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
2099         offset += 4;
2100         
2101         return offset;
2102 }
2103
2104 /* -------------------------- */
2105 static gint
2106 dissect_reply_afp_create_dir(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2107 {
2108         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2109         offset += 4;
2110         
2111         return offset;
2112 }
2113
2114 /* ************************** 
2115         no reply
2116 */
2117 static gint
2118 dissect_query_afp_delete_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2119 {
2120         PAD(1);
2121         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
2122         offset += 2;
2123         proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
2124         offset += 4;
2125         
2126         return offset;
2127 }
2128
2129 /* ************************** 
2130         same reply as get_fork_param
2131 */
2132 static gint
2133 dissect_query_afp_resolve_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2134 {
2135         PAD(1);
2136         proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
2137         offset += 2;
2138         proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
2139         offset += 4;
2140
2141         decode_file_bitmap(tree, tvb, offset);
2142         offset += 2;
2143
2144         return offset;
2145 }
2146
2147 /* ************************** */
2148 static gint
2149 dissect_query_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2150 {
2151
2152         PAD(1);
2153         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
2154         offset += 2;
2155
2156         decode_file_bitmap(tree, tvb, offset);
2157         offset += 2;
2158         return offset;
2159 }
2160
2161 /* -------------------------- */
2162 static gint
2163 dissect_reply_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2164 {
2165         guint16 f_bitmap;
2166
2167         f_bitmap = decode_file_bitmap(tree, tvb, offset);
2168         offset += 2;
2169
2170         offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
2171
2172         return offset;
2173 }
2174
2175 /* ************************** */
2176 static gint
2177 dissect_query_afp_set_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2178 {
2179
2180         PAD(1);
2181         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
2182         offset += 2;
2183
2184         decode_file_bitmap(tree, tvb, offset);
2185         offset += 2;
2186
2187         proto_tree_add_item(tree, hf_afp_ofork_len, tvb, offset, 4,FALSE);
2188         offset += 4;
2189         return offset;
2190 }
2191
2192 /* ************************** */
2193 static gint
2194 dissect_query_afp_move(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2195 {
2196                 
2197         PAD(1);
2198         offset = decode_vol_did(tree, tvb, offset);
2199
2200         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2201         offset += 4;
2202
2203         offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
2204         offset = decode_name_label(tree, NULL, tvb, offset,  "Dest dir:    %s");
2205         offset = decode_name_label(tree, NULL, tvb, offset,  "New name:    %s");
2206
2207         return offset;
2208 }
2209
2210 /* ************************** */
2211 static gint
2212 dissect_query_afp_exchange_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2213 {
2214                 
2215         PAD(1);
2216         offset = decode_vol_did(tree, tvb, offset);
2217
2218         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2219         offset += 4;
2220
2221         offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
2222         offset = decode_name_label(tree, NULL, tvb, offset,  "Dest path:   %s");
2223
2224         return offset;
2225 }
2226 /* ************************** */
2227 static gint
2228 dissect_query_afp_copy_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2229 {
2230         proto_tree *sub_tree = NULL;
2231         proto_item *item;
2232                 
2233         PAD(1);
2234         if (tree) {
2235                 item = proto_tree_add_text(tree, tvb, offset, 6,"Source volume");
2236                 sub_tree = proto_item_add_subtree(item, ett_afp_vol_did);
2237         }
2238         offset = decode_vol_did(sub_tree, tvb, offset);
2239
2240         if (tree) {
2241                 item = proto_tree_add_text(tree, tvb, offset, 6,"Dest volume");
2242                 sub_tree = proto_item_add_subtree(item, ett_afp_vol_did);
2243         }
2244         offset = decode_vol_did(sub_tree, tvb, offset);
2245
2246         offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
2247         offset = decode_name_label(tree, NULL, tvb, offset,  "Dest dir:    %s");
2248         offset = decode_name_label(tree, NULL, tvb, offset,  "New name:    %s");
2249
2250         return offset;
2251 }
2252
2253 /* ************************** */
2254 static gint
2255 dissect_query_afp_rename(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2256 {
2257                 
2258         PAD(1);
2259         offset = decode_vol_did(tree, tvb, offset);
2260
2261         offset = decode_name_label(tree, pinfo, tvb, offset, "Old name:     %s");
2262         offset = decode_name_label(tree, NULL, tvb, offset,  "New name:     %s");
2263
2264         return offset;
2265 }
2266
2267 /* ************************** */
2268 static gint
2269 dissect_query_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2270 {
2271         proto_tree *sub_tree = NULL;
2272         proto_item *item;
2273         guint8 flag;
2274         
2275         flag = tvb_get_guint8(tvb, offset);
2276         if (tree) {
2277                 item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
2278                 sub_tree = proto_item_add_subtree(item, ett_afp_lock_flags);
2279         }
2280
2281         proto_tree_add_item(sub_tree, hf_afp_lock_op, tvb, offset, 1,FALSE);
2282         proto_tree_add_item(sub_tree, hf_afp_lock_from, tvb, offset, 1,FALSE);
2283         offset += 1;
2284
2285         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
2286         offset += 2;
2287         
2288         proto_tree_add_item(tree, hf_afp_lock_offset, tvb, offset, 4,FALSE);
2289         offset += 4;
2290
2291         proto_tree_add_item(tree, hf_afp_lock_len, tvb, offset, 4,FALSE);
2292         offset += 4;
2293         return offset;
2294 }
2295
2296 /* -------------------------- */
2297 static gint
2298 dissect_reply_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2299 {
2300         proto_tree_add_item(tree, hf_afp_lock_range_start, tvb, offset, 4,FALSE);
2301         offset += 4;
2302
2303         return offset;
2304 }
2305
2306 /* ************************** */
2307 static gint
2308 dissect_query_afp_byte_lock_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2309 {
2310         proto_tree *sub_tree = NULL;
2311         proto_item *item;
2312         guint8 flag;
2313         
2314         flag = tvb_get_guint8(tvb, offset);
2315         if (tree) {
2316                 item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
2317                 sub_tree = proto_item_add_subtree(item, ett_afp_lock_flags);
2318         }
2319
2320         proto_tree_add_item(sub_tree, hf_afp_lock_op, tvb, offset, 1,FALSE);
2321         proto_tree_add_item(sub_tree, hf_afp_lock_from, tvb, offset, 1,FALSE);
2322         offset += 1;
2323
2324         proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
2325         offset += 2;
2326         
2327         proto_tree_add_item(tree, hf_afp_lock_offset64, tvb, offset, 8,FALSE);
2328         offset += 8;
2329
2330         proto_tree_add_item(tree, hf_afp_lock_len64, tvb, offset, 8,FALSE);
2331         offset += 8;
2332         return offset;
2333 }
2334
2335 /* -------------------------- */
2336 static gint
2337 dissect_reply_afp_byte_lock_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2338 {
2339         proto_tree_add_item(tree, hf_afp_lock_range_start64, tvb, offset, 8,FALSE);
2340         offset += 8;
2341
2342         return offset;
2343 }
2344
2345 /* ************************** */
2346 static gint
2347 dissect_query_afp_add_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2348 {
2349         guint8 len;
2350
2351         PAD(1);
2352         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2353         offset += 2;
2354
2355         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2356         offset += 4;
2357
2358         offset = decode_name(tree, pinfo, tvb, offset);
2359
2360         if ((offset & 1)) 
2361                 PAD(1);
2362
2363         len = tvb_get_guint8(tvb, offset);
2364         proto_tree_add_item(tree, hf_afp_comment, tvb, offset, 1,FALSE);
2365         offset += len +1;
2366
2367         return offset;
2368 }
2369
2370
2371 /* ************************** */
2372 static gint
2373 dissect_query_afp_get_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2374 {
2375
2376         PAD(1);
2377         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2378         offset += 2;
2379
2380         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2381         offset += 4;
2382
2383         offset = decode_name(tree, pinfo, tvb, offset);
2384         return offset;
2385 }
2386
2387 /* -------------------------- */
2388 static gint
2389 dissect_reply_afp_get_cmt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2390 {
2391         guint8 len;
2392
2393         len = tvb_get_guint8(tvb, offset);
2394         proto_tree_add_item(tree, hf_afp_comment, tvb, offset, 1,FALSE);
2395         offset += len +1;
2396
2397         return offset;
2398 }
2399
2400 /* ************************** */
2401 static gint
2402 dissect_query_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2403 {
2404
2405         PAD(1);
2406         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2407         offset += 2;
2408         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2409         offset += 4;
2410
2411         proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
2412         offset += 4;
2413         
2414         proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
2415         offset += 1;
2416         PAD(1);
2417
2418         proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
2419         offset += 2;
2420
2421         return offset;
2422 }
2423
2424 /* ************************** */
2425 static gint
2426 dissect_query_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2427 {
2428
2429         PAD(1);
2430         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2431         offset += 2;
2432         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2433         offset += 4;
2434
2435         proto_tree_add_item(tree, hf_afp_icon_index, tvb, offset, 2,FALSE);
2436         offset += 2;
2437
2438         return offset;
2439 }
2440
2441 /* -------------------------- */
2442 static gint
2443 dissect_reply_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2444 {
2445
2446         proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
2447         offset += 4;
2448
2449         proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
2450         offset += 4;
2451         
2452         proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
2453         offset += 1;
2454
2455         PAD(1);
2456         proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
2457         offset += 2;
2458
2459         return offset;
2460 }
2461
2462 /* ************************** */
2463 static gint
2464 dissect_query_afp_add_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2465 {
2466
2467         PAD(1);
2468         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2469         offset += 2;
2470         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2471         offset += 4;
2472
2473         proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
2474         offset += 4;
2475         
2476         proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
2477         offset += 1;
2478         
2479         PAD(1);
2480         proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
2481         offset += 4;
2482         
2483         proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
2484         offset += 2;
2485
2486         return offset;
2487 }
2488
2489 /* ************************** 
2490         no reply
2491 */
2492 static gint
2493 dissect_query_afp_add_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2494 {
2495
2496         PAD(1);
2497         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2498         offset += 2;
2499
2500         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2501         offset += 4;
2502
2503         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2504         offset += 4;
2505
2506         proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
2507         offset += 4;
2508         
2509         offset = decode_name(tree, pinfo, tvb, offset);
2510
2511         return offset;
2512 }
2513
2514 /* ************************** 
2515         no reply
2516 */
2517 static gint
2518 dissect_query_afp_rmv_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2519 {
2520
2521         PAD(1);
2522         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2523         offset += 2;
2524
2525         proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
2526         offset += 4;
2527
2528         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2529         offset += 4;
2530
2531         offset = decode_name(tree, pinfo, tvb, offset);
2532
2533         return offset;
2534 }
2535
2536 /* ************************** */
2537 static gint
2538 dissect_query_afp_get_appl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2539 {
2540
2541         PAD(1);
2542         proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
2543         offset += 2;
2544
2545         proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
2546         offset += 4;
2547
2548         proto_tree_add_item(tree, hf_afp_appl_index, tvb, offset, 2,FALSE);
2549         offset += 2;
2550
2551         decode_file_bitmap(tree, tvb, offset);
2552         offset += 2;
2553
2554         return offset;
2555 }
2556
2557 /* -------------------------- */
2558 static gint
2559 dissect_reply_afp_get_appl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2560 {
2561         proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
2562         offset += 4;
2563
2564         return offset;
2565 }
2566
2567 /* ************************** */
2568 static gint
2569 dissect_query_afp_create_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
2570 {
2571         proto_tree_add_item(tree, hf_afp_create_flag, tvb, offset, 1,FALSE);
2572         offset++;
2573
2574         offset = decode_vol_did(tree, tvb, offset);
2575
2576         offset = decode_name(tree, pinfo, tvb, offset);
2577
2578         return offset;
2579 }
2580
2581 /* ************************** */
2582 static gint
2583 dissect_query_afp_map_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2584 {
2585         proto_tree_add_item(tree, hf_afp_map_id_type, tvb, offset, 1,FALSE);
2586         offset++;
2587         
2588         proto_tree_add_item(tree, hf_afp_map_id, tvb, offset, 4,FALSE);
2589         offset += 4;
2590
2591         return offset;
2592 }
2593
2594 /* -------------------------- */
2595 static gint
2596 dissect_reply_afp_map_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2597 {
2598 int len;
2599
2600         len = tvb_get_guint8(tvb, offset);
2601         proto_tree_add_item(tree, hf_afp_map_name, tvb, offset, 1,FALSE);
2602         offset += len +1;
2603         return offset;
2604 }
2605
2606 /* ************************** */
2607 static gint
2608 dissect_query_afp_map_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2609 {
2610 int len;
2611         proto_tree_add_item(tree, hf_afp_map_name_type, tvb, offset, 1,FALSE);
2612         offset++;
2613
2614         len = tvb_get_guint8(tvb, offset);
2615         proto_tree_add_item(tree, hf_afp_map_name, tvb, offset, 1,FALSE);
2616         offset += len +1;
2617         
2618         return offset;
2619 }
2620
2621 /* -------------------------- */
2622 static gint
2623 dissect_reply_afp_map_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2624 {
2625
2626         proto_tree_add_item(tree, hf_afp_map_id, tvb, offset, 4,FALSE);
2627         offset += 4;
2628         return offset;
2629 }
2630
2631 /* ************************** */
2632 static gint
2633 dissect_query_afp_disconnect_old_session(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2634 {
2635 int len;
2636
2637         PAD(1);
2638
2639         proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
2640         offset += 2;
2641
2642         len = tvb_get_ntohl(tvb, offset);
2643         proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, 4,FALSE);
2644         offset += 4;
2645
2646         proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
2647         offset += len;
2648
2649         return offset;
2650 }
2651
2652 /* ************************** */
2653 static gint
2654 dissect_query_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2655 {
2656
2657         PAD(1);
2658         proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
2659         offset += 2;
2660
2661         return offset;
2662 }
2663
2664 /* -------------------------- */
2665 static gint
2666 dissect_reply_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2667 {
2668 int len;
2669
2670         proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
2671         offset += 2;
2672
2673         len = tvb_get_ntohl(tvb, offset);
2674         proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, 4,FALSE);
2675         offset += 4;
2676
2677         proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
2678         offset += len;
2679
2680         return offset;
2681 }
2682
2683 /* ************************** */
2684 static gint
2685 dissect_query_afp_get_user_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2686 {
2687         proto_tree *sub_tree = NULL;
2688         proto_item *item;
2689         guint16  bitmap;
2690
2691
2692         proto_tree_add_item(tree, hf_afp_user_flag, tvb, offset, 1,FALSE);
2693         offset++;
2694
2695         proto_tree_add_item(tree, hf_afp_user_ID, tvb, offset, 4,FALSE);
2696         offset += 4;
2697
2698         bitmap = tvb_get_ntohs(tvb, offset);
2699         if (tree) {
2700                 item = proto_tree_add_item(tree, hf_afp_user_bitmap, tvb, offset, 2,FALSE);
2701                 sub_tree = proto_item_add_subtree(item, ett_afp_user_bitmap);
2702                 proto_tree_add_item(sub_tree, hf_afp_user_bitmap_UID, tvb, offset, 2,FALSE);
2703                 proto_tree_add_item(sub_tree, hf_afp_user_bitmap_GID, tvb, offset, 2,FALSE);
2704         }
2705         offset += 2;
2706
2707         return offset;
2708 }
2709
2710 /* -------------------------- */
2711 static gint
2712 dissect_reply_afp_get_user_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
2713 {
2714         proto_tree *sub_tree = NULL;
2715         proto_item *item;
2716         guint16  bitmap;
2717
2718         bitmap = tvb_get_ntohs(tvb, offset);
2719         if (tree) {
2720                 item = proto_tree_add_item(tree, hf_afp_user_bitmap, tvb, offset, 2,FALSE);
2721                 sub_tree = proto_item_add_subtree(item, ett_afp_user_bitmap);
2722                 proto_tree_add_item(sub_tree, hf_afp_user_bitmap_UID, tvb, offset, 2,FALSE);
2723                 proto_tree_add_item(sub_tree, hf_afp_user_bitmap_GID, tvb, offset, 2,FALSE);
2724         }
2725
2726         offset += 2;
2727         if ((bitmap & 1)) {
2728                 proto_tree_add_item(tree, hf_afp_user_ID, tvb, offset, 4,FALSE);
2729                 offset += 4;
2730         }
2731
2732         if ((bitmap & 2)) {
2733                 proto_tree_add_item(tree, hf_afp_group_ID, tvb, offset, 4,FALSE);
2734                 offset += 4;
2735         }
2736         return offset;
2737 }
2738
2739 /* ************************** */
2740 static void
2741 dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2742 {
2743         struct aspinfo *aspinfo = pinfo->private_data;
2744         proto_tree      *afp_tree = NULL;
2745         proto_item      *ti;
2746         conversation_t  *conversation;
2747         gint            offset = 0;
2748         afp_request_key request_key, *new_request_key;
2749         afp_request_val *request_val;
2750         guint8  afp_command;
2751
2752         int     len =  tvb_reported_length_remaining(tvb,0);
2753         
2754         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2755                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFP");
2756         if (check_col(pinfo->cinfo, COL_INFO))
2757                 col_clear(pinfo->cinfo, COL_INFO);
2758
2759         conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
2760                 pinfo->srcport, pinfo->destport, 0);
2761
2762         if (conversation == NULL)
2763         {
2764                 conversation = conversation_new(&pinfo->src, &pinfo->dst,
2765                         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2766         }
2767
2768         request_key.conversation = conversation->index; 
2769         request_key.seq = aspinfo->seq;
2770
2771         request_val = (afp_request_val *) g_hash_table_lookup(
2772                                                                 afp_request_hash, &request_key);
2773
2774         if (!request_val && !aspinfo->reply)  {
2775                 afp_command = tvb_get_guint8(tvb, offset);
2776                 new_request_key = g_mem_chunk_alloc(afp_request_keys);
2777                 *new_request_key = request_key;
2778
2779                 request_val = g_mem_chunk_alloc(afp_request_vals);
2780                 request_val->command = tvb_get_guint8(tvb, offset);
2781
2782                 g_hash_table_insert(afp_request_hash, new_request_key,
2783                                                                 request_val);
2784         }
2785
2786         if (!request_val) {     /* missing request */
2787                 if (check_col(pinfo->cinfo, COL_INFO)) 
2788                         col_add_fstr(pinfo->cinfo, COL_INFO, "[Reply without query?]");
2789                 return;
2790         }
2791
2792         afp_command = request_val->command;
2793         if (check_col(pinfo->cinfo, COL_INFO)) {
2794                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2795                              val_to_str(afp_command, CommandCode_vals,
2796                                         "Unknown command (%u)"),
2797                              aspinfo->reply ? "reply" : "request");
2798                 if (aspinfo->reply && aspinfo->code != 0) {
2799                         col_append_fstr(pinfo->cinfo, COL_INFO, ": %s (%d)",
2800                                 val_to_str(aspinfo->code, asp_error_vals,
2801                                         "Unknown error (%u)"), aspinfo->code);
2802                 }
2803         }
2804
2805         if (tree)
2806         {
2807                 ti = proto_tree_add_item(tree, proto_afp, tvb, offset, -1,FALSE);
2808                 afp_tree = proto_item_add_subtree(ti, ett_afp);
2809         }
2810         if (!aspinfo->reply)  {
2811                 proto_tree_add_uint(afp_tree, hf_afp_command, tvb,offset, 1, afp_command);
2812                 offset++;
2813                 switch(afp_command) {
2814                 case AFP_BYTELOCK:
2815                         offset = dissect_query_afp_byte_lock(tvb, pinfo, afp_tree, offset);break; 
2816                 case AFP_BYTELOCK_EXT:
2817                         offset = dissect_query_afp_byte_lock_ext(tvb, pinfo, afp_tree, offset);break; 
2818                 case AFP_OPENDT:        /* same as close vol */
2819                 case AFP_FLUSH:         
2820                 case AFP_CLOSEVOL:
2821                         offset = dissect_query_afp_with_vol_id(tvb, pinfo, afp_tree, offset);break;
2822                 case AFP_CLOSEDIR:
2823                         /* offset = dissect_query_afp_close_dir(tvb, pinfo, afp_tree, offset);break; */
2824                         break;
2825                 case AFP_CLOSEDT:       
2826                         offset = dissect_query_afp_close_dt(tvb, pinfo, afp_tree, offset);break;
2827                 case AFP_FLUSHFORK: /* same packet as closefork */
2828                 case AFP_CLOSEFORK:
2829                         offset = dissect_query_afp_with_fork(tvb, pinfo, afp_tree, offset);break;
2830                 case AFP_COPYFILE:
2831                         offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break; 
2832                 case AFP_CREATEFILE:
2833                         offset = dissect_query_afp_create_file(tvb, pinfo, afp_tree, offset);break; 
2834                 case AFP_DISCTOLDSESS:
2835                         offset = dissect_query_afp_disconnect_old_session(tvb, pinfo, afp_tree, offset);break; 
2836                 case AFP_ENUMERATE_EXT:
2837                 case AFP_ENUMERATE:
2838                         offset = dissect_query_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
2839                 case AFP_GETFORKPARAM:
2840                         offset = dissect_query_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break; 
2841                 case AFP_GETSESSTOKEN:
2842                         offset = dissect_query_afp_get_session_token(tvb, pinfo, afp_tree, offset);break; 
2843                 case AFP_GETUSERINFO:
2844                         offset = dissect_query_afp_get_user_info(tvb, pinfo, afp_tree, offset);break; 
2845                 case AFP_GETSRVINFO:
2846                         /* offset = dissect_query_afp_get_server_info(tvb, pinfo, afp_tree, offset);break; */
2847                 case AFP_GETSRVPARAM:
2848                         break;                                  /* no parameters */
2849                 case AFP_GETVOLPARAM:
2850                         offset = dissect_query_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
2851                 case AFP_LOGIN:
2852                         offset = dissect_query_afp_login(tvb, pinfo, afp_tree, offset);break;
2853                 case AFP_LOGINCONT:
2854                 case AFP_LOGOUT:
2855                         break;
2856                 case AFP_MAPID:
2857                         offset = dissect_query_afp_map_id(tvb, pinfo, afp_tree, offset);break;
2858                 case AFP_MAPNAME:
2859                         offset = dissect_query_afp_map_name(tvb, pinfo, afp_tree, offset);break;
2860                 case AFP_MOVE:
2861                         offset = dissect_query_afp_move(tvb, pinfo, afp_tree, offset);break;
2862                 case AFP_OPENVOL:
2863                         offset = dissect_query_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
2864                 case AFP_OPENDIR:
2865                         break;
2866                 case AFP_OPENFORK:
2867                         offset = dissect_query_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
2868                 case AFP_READ:
2869                         offset = dissect_query_afp_read(tvb, pinfo, afp_tree, offset);break;
2870                 case AFP_READ_EXT:
2871                         offset = dissect_query_afp_read_ext(tvb, pinfo, afp_tree, offset);break;
2872                 case AFP_RENAME:
2873                         offset = dissect_query_afp_rename(tvb, pinfo, afp_tree, offset);break;
2874                 case AFP_SETDIRPARAM:
2875                         offset = dissect_query_afp_set_dir_param(tvb, pinfo, afp_tree, offset);break; 
2876                 case AFP_SETFILEPARAM:
2877                         offset = dissect_query_afp_set_file_param(tvb, pinfo, afp_tree, offset);break; 
2878                 case AFP_SETFORKPARAM:
2879                         offset = dissect_query_afp_set_fork_param(tvb, pinfo, afp_tree, offset);break; 
2880                 case AFP_SETVOLPARAM:
2881                         offset = dissect_query_afp_set_vol_param(tvb, pinfo, afp_tree, offset);break;
2882                 case AFP_WRITE:
2883                         offset = dissect_query_afp_write(tvb, pinfo, afp_tree, offset);break;
2884                 case AFP_WRITE_EXT:
2885                         offset = dissect_query_afp_write_ext(tvb, pinfo, afp_tree, offset);break;
2886                 case AFP_GETFLDRPARAM:
2887                         offset = dissect_query_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
2888                 case AFP_SETFLDRPARAM:
2889                         offset = dissect_query_afp_set_fldr_param(tvb, pinfo, afp_tree, offset);break;
2890                 case AFP_CHANGEPW:
2891                 case AFP_GETSRVRMSG:
2892                         break;
2893                 case AFP_DELETE:        /* same as create_id */
2894                 case AFP_CREATEDIR:
2895                 case AFP_CREATEID:
2896                         offset = dissect_query_afp_create_id(tvb, pinfo, afp_tree, offset);break; 
2897                 case AFP_DELETEID:
2898                         offset = dissect_query_afp_delete_id(tvb, pinfo, afp_tree, offset);break; 
2899                 case AFP_RESOLVEID:
2900                         offset = dissect_query_afp_resolve_id(tvb, pinfo, afp_tree, offset);break; 
2901                 case AFP_EXCHANGEFILE:
2902                         offset = dissect_query_afp_exchange_file(tvb, pinfo, afp_tree, offset);break; 
2903                 case AFP_CATSEARCH_EXT:
2904                 case AFP_CATSEARCH:
2905                         offset = dissect_query_afp_cat_search(tvb, pinfo, afp_tree, offset);break; 
2906                 case AFP_GETICON:       
2907                         offset = dissect_query_afp_get_icon(tvb, pinfo, afp_tree, offset);break; 
2908                 case AFP_GTICNINFO:
2909                         offset = dissect_query_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
2910                 case AFP_ADDAPPL:
2911                         offset = dissect_query_afp_add_appl(tvb, pinfo, afp_tree, offset);break; 
2912                 case AFP_RMVAPPL:
2913                         offset = dissect_query_afp_rmv_appl(tvb, pinfo, afp_tree, offset);break; 
2914                 case AFP_GETAPPL:
2915                         offset = dissect_query_afp_get_appl(tvb, pinfo, afp_tree, offset);break; 
2916                 case AFP_ADDCMT:
2917                         offset = dissect_query_afp_add_cmt(tvb, pinfo, afp_tree, offset);break; 
2918                 case AFP_RMVCMT: /* same as get_cmt */
2919                 case AFP_GETCMT:
2920                         offset = dissect_query_afp_get_cmt(tvb, pinfo, afp_tree, offset);break; 
2921                 case AFP_ADDICON:
2922                         offset = dissect_query_afp_add_icon(tvb, pinfo, afp_tree, offset);break; 
2923                         break;
2924                 }
2925         }
2926         else {
2927                 proto_tree_add_uint(afp_tree, hf_afp_command, tvb, 0, 0, afp_command);
2928                 if (!len) {
2929                         /* for some calls if the reply is an error there's no data
2930                         */
2931                         return;
2932                 }
2933                 switch(afp_command) {
2934                 case AFP_BYTELOCK:
2935                         offset = dissect_reply_afp_byte_lock(tvb, pinfo, afp_tree, offset);break; 
2936                 case AFP_BYTELOCK_EXT:
2937                         offset = dissect_reply_afp_byte_lock_ext(tvb, pinfo, afp_tree, offset);break; 
2938                 case AFP_ENUMERATE_EXT:
2939                 case AFP_ENUMERATE:
2940                         offset = dissect_reply_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
2941                 case AFP_OPENVOL:
2942                         offset = dissect_reply_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
2943                 case AFP_OPENFORK:
2944                         offset = dissect_reply_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
2945                 case AFP_RESOLVEID:
2946                 case AFP_GETFORKPARAM:
2947                         offset =dissect_reply_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break;
2948                 case AFP_GETUSERINFO:
2949                         offset = dissect_reply_afp_get_user_info(tvb, pinfo, afp_tree, offset);break;
2950                 case AFP_GETSRVPARAM:
2951                         offset = dissect_reply_afp_get_server_param(tvb, pinfo, afp_tree, offset);break;
2952                 case AFP_CREATEDIR:
2953                         offset = dissect_reply_afp_create_dir(tvb, pinfo, afp_tree, offset);break; 
2954                 case AFP_MAPID:
2955                         offset = dissect_reply_afp_map_id(tvb, pinfo, afp_tree, offset);break;
2956                 case AFP_MAPNAME:
2957                         offset = dissect_reply_afp_map_name(tvb, pinfo, afp_tree, offset);break;
2958                 case AFP_MOVE:          /* same as create_id */
2959                 case AFP_CREATEID:
2960                         offset = dissect_reply_afp_create_id(tvb, pinfo, afp_tree, offset);break; 
2961                 case AFP_GETSESSTOKEN:
2962                         offset = dissect_reply_afp_get_session_token(tvb, pinfo, afp_tree, offset);break; 
2963                 case AFP_GETVOLPARAM:
2964                         offset = dissect_reply_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
2965                 case AFP_GETFLDRPARAM:
2966                         offset = dissect_reply_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
2967                 case AFP_OPENDT:
2968                         offset = dissect_reply_afp_open_dt(tvb, pinfo, afp_tree, offset);break;
2969
2970                 case AFP_CATSEARCH_EXT:
2971                 case AFP_CATSEARCH:
2972                         offset = dissect_reply_afp_cat_search(tvb, pinfo, afp_tree, offset);break; 
2973                 case AFP_GTICNINFO:
2974                         offset = dissect_reply_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
2975                 case AFP_GETAPPL:
2976                         offset = dissect_reply_afp_get_appl(tvb, pinfo, afp_tree, offset);break; 
2977                 case AFP_GETCMT:
2978                         offset = dissect_reply_afp_get_cmt(tvb, pinfo, afp_tree, offset);break; 
2979                 case AFP_WRITE:
2980                         offset = dissect_reply_afp_write(tvb, pinfo, afp_tree, offset);break;
2981                 case AFP_WRITE_EXT:
2982                         offset = dissect_reply_afp_write_ext(tvb, pinfo, afp_tree, offset);break;
2983                 }
2984         }
2985         if (tree && offset < len) {
2986                 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
2987                     pinfo, afp_tree);
2988         }
2989 }
2990
2991 static void afp_reinit( void)
2992 {
2993
2994         if (afp_request_hash)
2995                 g_hash_table_destroy(afp_request_hash);
2996         if (afp_request_keys)
2997                 g_mem_chunk_destroy(afp_request_keys);
2998         if (afp_request_vals)
2999                 g_mem_chunk_destroy(afp_request_vals);
3000
3001         afp_request_hash = g_hash_table_new(afp_hash, afp_equal);
3002
3003         afp_request_keys = g_mem_chunk_new("afp_request_keys",
3004                 sizeof(afp_request_key),
3005                 afp_packet_init_count * sizeof(afp_request_key),
3006                 G_ALLOC_AND_FREE);
3007         afp_request_vals = g_mem_chunk_new("afp_request_vals",
3008                 sizeof(afp_request_val),
3009                 afp_packet_init_count * sizeof(afp_request_val),
3010                 G_ALLOC_AND_FREE);
3011
3012 }
3013
3014 void
3015 proto_register_afp(void)
3016 {
3017
3018   static hf_register_info hf[] = {
3019     { &hf_afp_command,
3020       { "Command",      "afp.command",
3021                 FT_UINT8, BASE_DEC, VALS(CommandCode_vals), 0x0,
3022         "AFP function", HFILL }},
3023
3024     { &hf_afp_pad,    
3025       { "Pad",          "afp.pad",    
3026                 FT_NONE,   BASE_NONE, NULL, 0, 
3027         "Pad Byte",     HFILL }},
3028
3029     { &hf_afp_AFPVersion,
3030       { "AFP Version",  "afp.AFPVersion",
3031                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3032         "Client AFP version", HFILL }},
3033
3034     { &hf_afp_UAM,
3035       { "UAM",          "afp.UAM",
3036                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3037         "User Authentication Method", HFILL }},
3038
3039     { &hf_afp_user,
3040       { "User",         "afp.user",
3041                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3042         "User", HFILL }},
3043
3044     { &hf_afp_passwd,
3045       { "Password",     "afp.passwd",
3046                 FT_STRINGZ, BASE_NONE, NULL, 0x0,
3047         "Password", HFILL }},
3048
3049     { &hf_afp_vol_bitmap,
3050       { "Bitmap",         "afp.vol_bitmap",
3051                 FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
3052         "Volume bitmap", HFILL }},
3053
3054     { &hf_afp_vol_bitmap_Attributes,
3055       { "Attributes",      "afp.vol_bitmap.attributes",
3056                 FT_BOOLEAN, 16, NULL, kFPVolAttributeBit,
3057         "Volume attributes", HFILL }},
3058
3059     { &hf_afp_vol_attribute,
3060       { "Attributes",         "afp.vol_attributes",
3061                 FT_UINT16, BASE_HEX, NULL, 0,
3062         "Volume attributes", HFILL }},
3063
3064     { &hf_afp_vol_attribute_ReadOnly, 
3065       { "Read only",         "afp.vol_attribute.read_only",
3066                  FT_BOOLEAN, 16, NULL, kReadOnly,
3067         "Read only volume", HFILL }},
3068
3069     { &hf_afp_vol_attribute_HasVolumePassword,
3070       { "Volume password",         "afp.vol_attribute.passwd",
3071                  FT_BOOLEAN, 16, NULL, kHasVolumePassword,
3072         "Has a volume password", HFILL }},
3073
3074     { &hf_afp_vol_attribute_SupportsFileIDs,
3075       { "File IDs",         "afp.vol_attribute.fileIDs",
3076                  FT_BOOLEAN, 16, NULL, kSupportsFileIDs,
3077         "Supports file IDs", HFILL }},
3078
3079     { &hf_afp_vol_attribute_SupportsCatSearch,
3080       { "Catalog search",         "afp.vol_attribute.cat_search",
3081                  FT_BOOLEAN, 16, NULL, kSupportsCatSearch,
3082         "Supports catalog search operations", HFILL }},
3083
3084     { &hf_afp_vol_attribute_SupportsBlankAccessPrivs,
3085       { "Blank access privileges",         "afp.vol_attribute.blank_access_privs",
3086                  FT_BOOLEAN, 16, NULL, kSupportsBlankAccessPrivs,
3087         "Supports blank access privileges", HFILL }},
3088
3089     { &hf_afp_vol_attribute_SupportsUnixPrivs,
3090       { "UNIX access privileges",         "afp.vol_attribute.unix_privs",
3091                  FT_BOOLEAN, 16, NULL, kSupportsUnixPrivs,
3092         "Supports UNIX access privileges", HFILL }},
3093
3094     { &hf_afp_vol_attribute_SupportsUTF8Names,
3095       { "UTF-8 names",         "afp.vol_attribute.utf8_names",
3096                  FT_BOOLEAN, 16, NULL, kSupportsUTF8Names,
3097         "Supports UTF-8 names", HFILL }},
3098
3099     { &hf_afp_vol_bitmap_Signature,
3100       { "Signature",         "afp.vol_bitmap.signature",
3101                 FT_BOOLEAN, 16, NULL, kFPVolSignatureBit,
3102         "Volume signature", HFILL }},
3103
3104     { &hf_afp_vol_bitmap_CreateDate,
3105       { "Creation date",      "afp.vol_bitmap.create_date",
3106                 FT_BOOLEAN, 16, NULL, kFPVolCreateDateBit,
3107         "Volume creation date", HFILL }},
3108
3109     { &hf_afp_vol_bitmap_ModDate,
3110       { "Modification date",  "afp.vol_bitmap.mod_date",
3111                 FT_BOOLEAN, 16, NULL, kFPVolModDateBit,
3112         "Volume modification date", HFILL }},
3113
3114     { &hf_afp_vol_bitmap_BackupDate,
3115       { "Backup date",        "afp.vol_bitmap.backup_date",
3116                 FT_BOOLEAN, 16, NULL, kFPVolBackupDateBit,
3117         "Volume backup date", HFILL }},
3118
3119     { &hf_afp_vol_bitmap_ID,
3120       { "ID",         "afp.vol_bitmap.id",
3121                 FT_BOOLEAN, 16, NULL,  kFPVolIDBit,
3122         "Volume ID", HFILL }},
3123
3124     { &hf_afp_vol_bitmap_BytesFree,
3125       { "Bytes free",         "afp.vol_bitmap.bytes_free",
3126                 FT_BOOLEAN, 16, NULL,  kFPVolBytesFreeBit,
3127         "Volume free bytes", HFILL }},
3128
3129     { &hf_afp_vol_bitmap_BytesTotal,
3130       { "Bytes total",         "afp.vol_bitmap.bytes_total",
3131                 FT_BOOLEAN, 16, NULL,  kFPVolBytesTotalBit,
3132         "Volume total bytes", HFILL }},
3133
3134     { &hf_afp_vol_bitmap_Name,
3135       { "Name",         "afp.vol_bitmap.name",
3136                 FT_BOOLEAN, 16, NULL,  kFPVolNameBit,
3137         "Volume name", HFILL }},
3138
3139     { &hf_afp_vol_bitmap_ExtBytesFree,
3140       { "Extended bytes free",         "afp.vol_bitmap.ex_bytes_free",
3141                 FT_BOOLEAN, 16, NULL,  kFPVolExtBytesFreeBit,
3142         "Volume extended (>2GB) free bytes", HFILL }},
3143
3144     { &hf_afp_vol_bitmap_ExtBytesTotal,
3145       { "Extended bytes total",         "afp.vol_bitmap.ex_bytes_total",
3146                 FT_BOOLEAN, 16, NULL,  kFPVolExtBytesTotalBit,
3147         "Volume extended (>2GB) total bytes", HFILL }},
3148
3149     { &hf_afp_vol_bitmap_BlockSize,
3150       { "Block size",         "afp.vol_bitmap.block_size",
3151                 FT_BOOLEAN, 16, NULL,  kFPVolBlockSizeBit,
3152         "Volume block size", HFILL }},
3153
3154     { &hf_afp_dir_bitmap_Attributes,        
3155       { "Attributes",         "afp.dir_bitmap.attributes",
3156             FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
3157         "Return attributes if directory", HFILL }},
3158
3159     { &hf_afp_dir_bitmap_ParentDirID,      
3160       { "DID",         "afp.dir_bitmap.did",
3161         FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
3162         "Return parent directory ID if directory", HFILL }},
3163
3164     { &hf_afp_dir_bitmap_CreateDate,       
3165       { "Creation date",         "afp.dir_bitmap.create_date",
3166             FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
3167         "Return creation date if directory", HFILL }},
3168
3169     { &hf_afp_dir_bitmap_ModDate,                  
3170       { "Modification date",         "afp.dir_bitmap.mod_date",
3171         FT_BOOLEAN, 16, NULL,  kFPModDateBit,
3172         "Return modification date if directory", HFILL }},
3173
3174     { &hf_afp_dir_bitmap_BackupDate,       
3175       { "Backup date",         "afp.dir_bitmap.backup_date",
3176             FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
3177         "Return backup date if directory", HFILL }},
3178
3179     { &hf_afp_dir_bitmap_FinderInfo,       
3180       { "Finder info",         "afp.dir_bitmap.finder_info",
3181         FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
3182         "Return finder info if directory", HFILL }},
3183
3184     { &hf_afp_dir_bitmap_LongName,                 
3185       { "Long name",         "afp.dir_bitmap.long_name",
3186             FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
3187         "Return long name if directory", HFILL }},
3188
3189     { &hf_afp_dir_bitmap_ShortName,                
3190       { "Short name",         "afp.dir_bitmap.short_name",
3191         FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
3192         "Return short name if directory", HFILL }},
3193
3194     { &hf_afp_dir_bitmap_NodeID,                   
3195       { "File ID",         "afp.dir_bitmap.fid",
3196             FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
3197         "Return file ID if directory", HFILL }},
3198
3199     { &hf_afp_dir_bitmap_OffspringCount,   
3200       { "Offspring count",         "afp.dir_bitmap.offspring_count",
3201         FT_BOOLEAN, 16, NULL,  kFPOffspringCountBit,
3202         "Return offspring count if directory", HFILL }},
3203
3204     { &hf_afp_dir_bitmap_OwnerID,                  
3205       { "Owner id",         "afp.dir_bitmap.owner_id",
3206             FT_BOOLEAN, 16, NULL,  kFPOwnerIDBit,
3207         "Return owner id if directory", HFILL }},
3208
3209     { &hf_afp_dir_bitmap_GroupID,                  
3210       { "Group id",         "afp.dir_bitmap.group_id",
3211         FT_BOOLEAN, 16, NULL,  kFPGroupIDBit,
3212         "Return group id if directory", HFILL }},
3213
3214     { &hf_afp_dir_bitmap_AccessRights,     
3215       { "Access rights",         "afp.dir_bitmap.access_rights",
3216             FT_BOOLEAN, 16, NULL,  kFPAccessRightsBit,
3217         "Return access rights if directory", HFILL }},
3218
3219     { &hf_afp_dir_bitmap_UTF8Name,                 
3220       { "UTF-8 name",         "afp.dir_bitmap.UTF8_name",
3221         FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
3222         "Return UTF-8 name if diectory", HFILL }},
3223
3224     { &hf_afp_dir_bitmap_UnixPrivs,                
3225       { "UNIX privileges",         "afp.dir_bitmap.unix_privs",
3226             FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit,
3227         "Return UNIX privileges if directory", HFILL }},
3228
3229     { &hf_afp_dir_attribute_Invisible,
3230       { "Invisible",         "afp.dir_attribute.invisible",
3231             FT_BOOLEAN, 16, NULL,  kFPInvisibleBit,
3232         "Directory is not visible", HFILL }},
3233
3234     { &hf_afp_dir_attribute_IsExpFolder,
3235       { "Share point",         "afp.dir_attribute.share",
3236             FT_BOOLEAN, 16, NULL,  kFPMultiUserBit,
3237         "Directory is a share point", HFILL }},
3238
3239     { &hf_afp_dir_attribute_System,
3240       { "System",                "afp.dir_attribute.system",
3241             FT_BOOLEAN, 16, NULL,  kFPSystemBit,
3242         "Directory is a system directory", HFILL }},
3243
3244     { &hf_afp_dir_attribute_Mounted,
3245       { "Mounted",         "afp.dir_attribute.mounted",
3246             FT_BOOLEAN, 16, NULL,  kFPDAlreadyOpenBit,
3247         "Directory is mounted", HFILL }},
3248
3249     { &hf_afp_dir_attribute_InExpFolder,
3250       { "Shared area",         "afp.dir_attribute.in_exported_folder",
3251             FT_BOOLEAN, 16, NULL,  kFPRAlreadyOpenBit,
3252         "Directory is in a shared area", HFILL }},
3253
3254     { &hf_afp_dir_attribute_BackUpNeeded,
3255       { "Backup needed",         "afp.dir_attribute.backup_needed",
3256             FT_BOOLEAN, 16, NULL,  kFPBackUpNeededBit,
3257         "Directory needs to be backed up", HFILL }},
3258
3259     { &hf_afp_dir_attribute_RenameInhibit,
3260       { "Rename inhibit",         "afp.dir_attribute.rename_inhibit",
3261             FT_BOOLEAN, 16, NULL,  kFPRenameInhibitBit,
3262         "Rename inhibit", HFILL }},
3263
3264     { &hf_afp_dir_attribute_DeleteInhibit,
3265       { "Delete inhibit",         "afp.dir_attribute.delete_inhibit",
3266             FT_BOOLEAN, 16, NULL,  kFPDeleteInhibitBit,
3267         "Delete inhibit", HFILL }},
3268
3269     { &hf_afp_dir_attribute_SetClear,
3270       { "Set",         "afp.dir_attribute.set_clear",
3271             FT_BOOLEAN, 16, NULL,  kFPSetClearBit,
3272         "Clear/set attribute", HFILL }},
3273
3274     { &hf_afp_file_bitmap_Attributes,
3275       { "Attributes",         "afp.file_bitmap.attributes",
3276             FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
3277         "Return attributes if file", HFILL }},
3278
3279     { &hf_afp_file_bitmap_ParentDirID,     
3280       { "DID",         "afp.file_bitmap.did",
3281         FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
3282         "Return parent directory ID if file", HFILL }},
3283
3284     { &hf_afp_file_bitmap_CreateDate,      
3285       { "Creation date",         "afp.file_bitmap.create_date",
3286             FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
3287         "Return creation date if file", HFILL }},
3288
3289     { &hf_afp_file_bitmap_ModDate,                 
3290       { "Modification date",         "afp.file_bitmap.mod_date",
3291         FT_BOOLEAN, 16, NULL,  kFPModDateBit,
3292         "Return modification date if file", HFILL }},
3293
3294     { &hf_afp_file_bitmap_BackupDate,      
3295       { "Backup date",         "afp.file_bitmap.backup_date",
3296             FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
3297         "Return backup date if file", HFILL }},
3298
3299     { &hf_afp_file_bitmap_FinderInfo,      
3300       { "Finder info",         "afp.file_bitmap.finder_info",
3301         FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
3302         "Return finder info if file", HFILL }},
3303
3304     { &hf_afp_file_bitmap_LongName,                
3305       { "Long name",         "afp.file_bitmap.long_name",
3306             FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
3307         "Return long name if file", HFILL }},
3308
3309     { &hf_afp_file_bitmap_ShortName,               
3310       { "Short name",         "afp.file_bitmap.short_name",
3311         FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
3312         "Return short name if file", HFILL }},
3313
3314     { &hf_afp_file_bitmap_NodeID,                  
3315       { "File ID",         "afp.file_bitmap.fid",
3316             FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
3317         "Return file ID if file", HFILL }},
3318
3319     { &hf_afp_file_bitmap_DataForkLen,
3320       { "Data fork size",         "afp.file_bitmap.data_fork_len",
3321             FT_BOOLEAN, 16, NULL,  kFPDataForkLenBit,
3322         "Return data fork size if file", HFILL }},
3323
3324     { &hf_afp_file_bitmap_RsrcForkLen,
3325       { "Resource fork size",         "afp.file_bitmap.resource_fork_len",
3326             FT_BOOLEAN, 16, NULL,  kFPRsrcForkLenBit,
3327         "Return resource fork size if file", HFILL }},
3328
3329     { &hf_afp_file_bitmap_ExtDataForkLen,
3330       { "Extended data fork size",         "afp.file_bitmap.ex_data_fork_len",
3331             FT_BOOLEAN, 16, NULL,  kFPExtDataForkLenBit,
3332         "Return extended (>2GB) data fork size if file", HFILL }},
3333
3334     { &hf_afp_file_bitmap_LaunchLimit,
3335       { "Launch limit",         "afp.file_bitmap.launch_limit",
3336             FT_BOOLEAN, 16, NULL,  kFPLaunchLimitBit,
3337         "Return launch limit if file", HFILL }},
3338
3339     { &hf_afp_file_bitmap_UTF8Name,                
3340       { "UTF-8 name",         "afp.file_bitmap.UTF8_name",
3341         FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
3342         "Return UTF-8 name if file", HFILL }},
3343
3344     { &hf_afp_file_bitmap_ExtRsrcForkLen,
3345         { "Extended resource fork size",         "afp.file_bitmap.ex_resource_fork_len",
3346             FT_BOOLEAN, 16, NULL,  kFPExtRsrcForkLenBit,
3347         "Return extended (>2GB) resource fork size if file", HFILL }},
3348
3349     { &hf_afp_file_bitmap_UnixPrivs,               
3350       { "UNIX privileges",    "afp.file_bitmap.unix_privs",
3351             FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit_file,
3352         "Return UNIX privileges if file", HFILL }},
3353
3354         /* ---------- */
3355     { &hf_afp_file_attribute_Invisible,
3356       { "Invisible",         "afp.file_attribute.invisible",
3357             FT_BOOLEAN, 16, NULL,  kFPInvisibleBit,
3358         "File is not visible", HFILL }},
3359
3360     { &hf_afp_file_attribute_MultiUser,
3361       { "Multi user",         "afp.file_attribute.multi_user",
3362             FT_BOOLEAN, 16, NULL,  kFPMultiUserBit,
3363         "multi user", HFILL }},
3364
3365     { &hf_afp_file_attribute_System,
3366       { "System",                "afp.file_attribute.system",
3367             FT_BOOLEAN, 16, NULL,  kFPSystemBit,
3368         "File is a system file", HFILL }},
3369
3370     { &hf_afp_file_attribute_DAlreadyOpen,
3371       { "Data fork open",         "afp.file_attribute.df_open",
3372             FT_BOOLEAN, 16, NULL,  kFPDAlreadyOpenBit,
3373         "Data fork already open", HFILL }},
3374
3375     { &hf_afp_file_attribute_RAlreadyOpen,
3376       { "Resource fork open",         "afp.file_attribute.rf_open",
3377             FT_BOOLEAN, 16, NULL,  kFPRAlreadyOpenBit,
3378         "Resource fork already open", HFILL }},
3379
3380     { &hf_afp_file_attribute_WriteInhibit,
3381       { "Write inhibit",         "afp.file_attribute.write_inhibit",
3382             FT_BOOLEAN, 16, NULL,  kFPWriteInhibitBit,
3383         "Write inhibit", HFILL }},
3384
3385     { &hf_afp_file_attribute_BackUpNeeded,
3386       { "Backup needed",         "afp.file_attribute.backup_needed",
3387             FT_BOOLEAN, 16, NULL,  kFPBackUpNeededBit,
3388         "File needs to be backed up", HFILL }},
3389
3390     { &hf_afp_file_attribute_RenameInhibit,
3391       { "Rename inhibit",         "afp.file_attribute.rename_inhibit",
3392             FT_BOOLEAN, 16, NULL,  kFPRenameInhibitBit,
3393         "rename inhibit", HFILL }},
3394
3395     { &hf_afp_file_attribute_DeleteInhibit,
3396       { "Delete inhibit",         "afp.file_attribute.delete_inhibit",
3397             FT_BOOLEAN, 16, NULL,  kFPDeleteInhibitBit,
3398         "delete inhibit", HFILL }},
3399
3400     { &hf_afp_file_attribute_CopyProtect,
3401       { "Copy protect",         "afp.file_attribute.copy_protect",
3402             FT_BOOLEAN, 16, NULL,  kFPCopyProtectBit,
3403         "copy protect", HFILL }},
3404
3405     { &hf_afp_file_attribute_SetClear,
3406       { "Set",         "afp.file_attribute.set_clear",
3407             FT_BOOLEAN, 16, NULL,  kFPSetClearBit,
3408         "Clear/set attribute", HFILL }},
3409         /* ---------- */
3410
3411     { &hf_afp_vol_name,
3412       { "Volume",         "afp.vol_name",
3413         FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3414         "Volume name", HFILL }},
3415
3416     { &hf_afp_vol_flag_passwd,
3417       { "Password",         "afp.vol_flag_passwd",
3418             FT_BOOLEAN, 8, NULL,  1,
3419         "Volume is password-protected", HFILL }},
3420
3421     { &hf_afp_vol_flag_unix_priv,
3422       { "Unix privs",         "afp.vol_flag_unix_priv",
3423             FT_BOOLEAN, 8, NULL,  2,
3424         "Volume has unix privileges", HFILL }},
3425
3426     { &hf_afp_vol_id,
3427       { "Volume id",         "afp.vol_id",
3428                 FT_UINT16, BASE_DEC, NULL, 0x0,
3429         "Volume id", HFILL }},
3430
3431     { &hf_afp_vol_signature,
3432       { "Signature",         "afp.vol_signature",
3433                 FT_UINT16, BASE_DEC, VALS(vol_signature_vals), 0x0,
3434         "Volume signature", HFILL }},
3435
3436     { &hf_afp_vol_name_offset,
3437       { "Volume name offset","afp.vol_name_offset",
3438                 FT_UINT16, BASE_DEC, NULL, 0x0,
3439         "Volume name offset in packet", HFILL }},
3440
3441     { &hf_afp_vol_creation_date,
3442       { "Creation date",         "afp.vol_creation_date",
3443                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3444         "Volume creation date", HFILL }},
3445
3446     { &hf_afp_vol_modification_date,
3447       { "Modification date",         "afp.vol_modification_date",
3448                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3449         "Volume modification date", HFILL }},
3450
3451     { &hf_afp_vol_backup_date,
3452       { "Backup date",         "afp.vol_backup_date",
3453                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3454         "Volume backup date", HFILL }},
3455
3456     { &hf_afp_vol_bytes_free,
3457       { "Bytes free",         "afp.vol_bytes_free",
3458                 FT_UINT32, BASE_DEC, NULL, 0x0,
3459         "Free space", HFILL }},
3460
3461     { &hf_afp_vol_bytes_total,
3462       { "Bytes total",         "afp.vol_bytes_total",
3463                 FT_UINT32, BASE_DEC, NULL, 0x0,
3464         "Volume size", HFILL }},
3465
3466     { &hf_afp_vol_ex_bytes_free,
3467       { "Extended bytes free",         "afp.vol_ex_bytes_free",
3468                 FT_UINT64, BASE_DEC, NULL, 0x0,
3469         "Extended (>2GB) free space", HFILL }},
3470
3471     { &hf_afp_vol_ex_bytes_total,
3472       { "Extended bytes total",         "afp.vol_ex_bytes_total",
3473                 FT_UINT64, BASE_DEC, NULL, 0x0,
3474         "Extended (>2GB) volume size", HFILL }},
3475
3476     { &hf_afp_vol_block_size,
3477       { "Block size",         "afp.vol_block_size",
3478                 FT_UINT32, BASE_DEC, NULL, 0x0,
3479         "Volume block size", HFILL }},
3480
3481     { &hf_afp_did,
3482       { "DID",         "afp.did",
3483                 FT_UINT32, BASE_DEC, NULL, 0x0,
3484         "Parent directory ID", HFILL }},
3485
3486     { &hf_afp_dir_bitmap,
3487       { "Directory bitmap",         "afp.dir_bitmap",
3488                 FT_UINT16, BASE_HEX, NULL, 0x0,
3489         "Directory bitmap", HFILL }},
3490
3491     { &hf_afp_dir_offspring,
3492       { "Offspring",         "afp.dir_offspring",
3493                 FT_UINT16, BASE_DEC, NULL, 0x0,
3494         "Directory offspring", HFILL }},
3495
3496     { &hf_afp_dir_OwnerID,
3497       { "Owner ID",         "afp.dir_owner_id",
3498                 FT_INT32, BASE_DEC, NULL, 0x0,
3499         "Directory owner ID", HFILL }},
3500
3501     { &hf_afp_dir_GroupID,
3502       { "Group ID",         "afp.dir_group_id",
3503                 FT_INT32, BASE_DEC, NULL, 0x0,
3504         "Directory group ID", HFILL }},
3505
3506     { &hf_afp_creation_date,
3507       { "Creation date",         "afp.creation_date",
3508                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3509         "Creation date", HFILL }},
3510
3511     { &hf_afp_modification_date,
3512       { "Modification date",         "afp.modification_date",
3513                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3514         "Modification date", HFILL }},
3515
3516     { &hf_afp_backup_date,
3517       { "Backup date",         "afp.backup_date",
3518                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3519         "Backup date", HFILL }},
3520
3521     { &hf_afp_finder_info,
3522       { "Finder info",         "afp.finder_info",
3523                 FT_BYTES, BASE_HEX, NULL, 0x0,
3524         "Finder info", HFILL }},
3525
3526     { &hf_afp_long_name_offset,
3527       { "Long name offset",    "afp.long_name_offset",
3528                 FT_UINT16, BASE_DEC, NULL, 0x0,
3529         "Long name offset in packet", HFILL }},
3530
3531     { &hf_afp_short_name_offset,
3532       { "Short name offset",   "afp.short_name_offset",
3533                 FT_UINT16, BASE_DEC, NULL, 0x0,
3534         "Short name offset in packet", HFILL }},
3535
3536     { &hf_afp_unicode_name_offset,
3537       { "Unicode name offset", "afp.unicode_name_offset",
3538                 FT_UINT16, BASE_DEC, NULL, 0x0,
3539         "Unicode name offset in packet", HFILL }},
3540
3541     { &hf_afp_unix_privs_uid,
3542       { "UID",             "afp.unix_privs.uid",
3543                 FT_UINT32, BASE_DEC, NULL, 0x0,
3544         "User ID", HFILL }},
3545
3546     { &hf_afp_unix_privs_gid,
3547       { "GID",             "afp.unix_privs.gid",
3548                 FT_UINT32, BASE_DEC, NULL, 0x0,
3549         "Group ID", HFILL }},
3550
3551     { &hf_afp_unix_privs_permissions,
3552       { "Permissions",     "afp.unix_privs.permissions",
3553                 FT_UINT32, BASE_OCT, NULL, 0x0,
3554         "Permissions", HFILL }},
3555
3556     { &hf_afp_unix_privs_ua_permissions,
3557       { "User's access rights",     "afp.unix_privs.ua_permissions",
3558                 FT_UINT32, BASE_HEX, NULL, 0x0,
3559         "User's access rights", HFILL }},
3560
3561     { &hf_afp_file_id,
3562       { "File ID",         "afp.file_id",
3563                 FT_UINT32, BASE_DEC, NULL, 0x0,
3564         "File/directory ID", HFILL }},
3565
3566     { &hf_afp_file_DataForkLen,
3567       { "Data fork size",         "afp.data_fork_len",
3568                 FT_UINT32, BASE_DEC, NULL, 0x0,
3569         "Data fork size", HFILL }},
3570
3571     { &hf_afp_file_RsrcForkLen,
3572       { "Resource fork size",         "afp.resource_fork_len",
3573                 FT_UINT32, BASE_DEC, NULL, 0x0,
3574         "Resource fork size", HFILL }},
3575
3576     { &hf_afp_file_ExtDataForkLen,
3577       { "Extended data fork size",         "afp.ext_data_fork_len",
3578                 FT_UINT64, BASE_DEC, NULL, 0x0,
3579         "Extended (>2GB) data fork length", HFILL }},
3580
3581     { &hf_afp_file_ExtRsrcForkLen,
3582       { "Extended resource fork size",         "afp.ext_resource_fork_len",
3583                 FT_UINT64, BASE_DEC, NULL, 0x0,
3584         "Extended (>2GB) resource fork length", HFILL }},
3585     
3586     { &hf_afp_file_bitmap,
3587       { "File bitmap",         "afp.file_bitmap",
3588                 FT_UINT16, BASE_HEX, NULL, 0x0,
3589         "File bitmap", HFILL }},
3590     
3591     { &hf_afp_req_count,
3592       { "Req count",         "afp.req_count",
3593                 FT_UINT16, BASE_DEC, NULL, 0x0,
3594         "Maximum number of structures returned", HFILL }},
3595
3596     { &hf_afp_start_index, 
3597       { "Start index",         "afp.start_index",
3598                 FT_UINT16, BASE_DEC, NULL, 0x0,
3599         "First structure returned", HFILL }},
3600     
3601     { &hf_afp_max_reply_size,
3602       { "Reply size",         "afp.reply_size",
3603                 FT_UINT16, BASE_DEC, NULL, 0x0,
3604         "First structure returned", HFILL }},
3605
3606     { &hf_afp_file_flag,
3607       { "Dir",         "afp.file_flag",
3608                 FT_BOOLEAN, 8, NULL, 0x80,
3609         "Is a dir", HFILL }},
3610
3611     { &hf_afp_create_flag,
3612       { "Hard create",         "afp.create_flag",
3613                 FT_BOOLEAN, 8, NULL, 0x80,
3614         "Soft/hard create file", HFILL }},
3615
3616     { &hf_afp_struct_size,
3617       { "Struct size",         "afp.struct_size",
3618                 FT_UINT8, BASE_DEC, NULL,0,
3619         "Sizeof of struct", HFILL }},
3620     
3621     { &hf_afp_flag,
3622       { "From",         "afp.flag",
3623                 FT_UINT8, BASE_HEX, VALS(flag_vals), 0x80,
3624         "Offset is relative to start/end of the fork", HFILL }},
3625
3626     { &hf_afp_dt_ref,
3627       { "DT ref",         "afp.dt_ref",
3628                 FT_UINT16, BASE_DEC, NULL, 0x0,
3629         "Desktop database reference num", HFILL }},
3630
3631     { &hf_afp_ofork,
3632       { "Fork",         "afp.ofork",
3633                 FT_UINT16, BASE_DEC, NULL, 0x0,
3634         "Open fork reference number", HFILL }},
3635
3636     { &hf_afp_offset,
3637       { "Offset",         "afp.offset",
3638                 FT_INT32, BASE_DEC, NULL, 0x0,
3639         "Offset", HFILL }},
3640     
3641     { &hf_afp_rw_count,
3642       { "Count",         "afp.rw_count",
3643                 FT_INT32, BASE_DEC, NULL, 0x0,
3644         "Number of bytes to be read/written", HFILL }},
3645     
3646     { &hf_afp_newline_mask,
3647       { "Newline mask",  "afp.newline_mask",
3648                 FT_UINT8, BASE_HEX, NULL, 0x0,
3649         "Value to AND bytes with when looking for newline", HFILL }},
3650     
3651     { &hf_afp_newline_char,
3652       { "Newline char",  "afp.newline_char",
3653                 FT_UINT8, BASE_HEX, NULL, 0x0,
3654         "Value to compare ANDed bytes with when looking for newline", HFILL }},
3655     
3656     { &hf_afp_last_written,
3657       { "Last written",  "afp.last_written",
3658                 FT_UINT32, BASE_DEC, NULL, 0x0,
3659         "Offset of the last byte written", HFILL }},
3660
3661     { &hf_afp_actual_count,
3662       { "Count",         "afp.actual_count",
3663                 FT_INT32, BASE_DEC, NULL, 0x0,
3664         "Number of bytes returned by read/write", HFILL }},
3665       
3666     { &hf_afp_ofork_len,
3667       { "New length",         "afp.ofork_len",
3668                 FT_INT32, BASE_DEC, NULL, 0x0,
3669         "New length", HFILL }},
3670
3671     { &hf_afp_path_type,
3672       { "Type",         "afp.path_type",
3673                 FT_UINT8, BASE_HEX, VALS(path_type_vals), 0,
3674         "Type of names", HFILL }},
3675
3676     { &hf_afp_path_len,
3677       { "Len",  "afp.path_len",
3678                 FT_UINT8, BASE_DEC, NULL, 0x0,
3679         "Path length", HFILL }},
3680
3681     { &hf_afp_path_name,
3682       { "Name",  "afp.path_name",
3683                 FT_STRING, BASE_NONE, NULL, 0x0,
3684         "Path name", HFILL }},
3685
3686     { &hf_afp_fork_type,
3687       { "Resource fork",         "afp.fork_type",
3688                 FT_BOOLEAN, 8, NULL, 0x80,
3689         "Data/resource fork", HFILL }},
3690
3691     { &hf_afp_access_mode,
3692       { "Access mode",         "afp.access",
3693                 FT_UINT8, BASE_HEX, NULL, 0x0,
3694         "Fork access mode", HFILL }},
3695
3696     { &hf_afp_access_read,
3697       { "Read",         "afp.access.read",
3698         FT_BOOLEAN, 8, NULL,  1,
3699         "Open for reading", HFILL }},
3700
3701     { &hf_afp_access_write,
3702       { "Write",         "afp.access.write",
3703         FT_BOOLEAN, 8, NULL,  2,
3704         "Open for writing", HFILL }},
3705
3706     { &hf_afp_access_deny_read,
3707       { "Deny read",         "afp.access.deny_read",
3708         FT_BOOLEAN, 8, NULL,  0x10,
3709         "Deny read", HFILL }},
3710
3711     { &hf_afp_access_deny_write,
3712       { "Deny write",         "afp.access.deny_write",
3713         FT_BOOLEAN, 8, NULL,  0x20,
3714         "Deny write", HFILL }},
3715
3716     { &hf_afp_comment,
3717       { "Comment",         "afp.comment",
3718                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3719         "File/folder comment", HFILL }},
3720
3721     { &hf_afp_file_creator,
3722       { "File creator",         "afp.file_creator",
3723                 FT_STRING, BASE_NONE, NULL, 0x0,
3724         "File creator", HFILL }},
3725
3726     { &hf_afp_file_type,
3727       { "File type",         "afp.file_type",
3728                 FT_STRING, BASE_NONE, NULL, 0x0,
3729         "File type", HFILL }},
3730
3731     { &hf_afp_icon_type,
3732       { "Icon type",         "afp.icon_type",
3733                 FT_UINT8, BASE_HEX, NULL , 0,
3734         "Icon type", HFILL }},
3735
3736     { &hf_afp_icon_length,
3737       { "Size",         "afp.icon_length",
3738                 FT_UINT16, BASE_DEC, NULL, 0x0,
3739         "Size for icon bitmap", HFILL }},
3740
3741     { &hf_afp_icon_index,
3742       { "Index",         "afp.icon_index",
3743                 FT_UINT16, BASE_DEC, NULL, 0x0,
3744         "Icon index in desktop database", HFILL }},
3745
3746     { &hf_afp_icon_tag,
3747       { "Tag",         "afp.icon_tag",
3748                 FT_UINT32, BASE_HEX, NULL, 0x0,
3749         "Icon tag", HFILL }},
3750
3751     { &hf_afp_appl_index,
3752       { "Index",         "afp.appl_index",
3753                 FT_UINT16, BASE_DEC, NULL, 0x0,
3754         "Application index", HFILL }},
3755
3756     { &hf_afp_appl_tag,
3757       { "Tag",         "afp.appl_tag",
3758                 FT_UINT32, BASE_HEX, NULL, 0x0,
3759         "Application tag", HFILL }},
3760         
3761     { &hf_afp_lock_op,
3762       { "unlock",         "afp.lock_op",
3763                 FT_BOOLEAN, 8, NULL, 0x1,
3764         "Lock/unlock op", HFILL }},
3765
3766     { &hf_afp_lock_from,
3767       { "End",         "afp.lock_from",
3768                 FT_BOOLEAN, 8, NULL, 0x80,
3769         "Offset is relative to the end of the fork", HFILL }},
3770     
3771     { &hf_afp_lock_offset,
3772       { "Offset",         "afp.lock_offset",
3773                 FT_INT32, BASE_DEC, NULL, 0x0,
3774         "First byte to be locked", HFILL }},
3775
3776     { &hf_afp_lock_len,
3777       { "Length",         "afp.lock_len",
3778                 FT_INT32, BASE_DEC, NULL, 0x0,
3779         "Number of bytes to be locked/unlocked", HFILL }},
3780
3781     { &hf_afp_lock_range_start,
3782       { "Start",         "afp.lock_range_start",
3783                 FT_INT32, BASE_DEC, NULL, 0x0,
3784         "First byte locked/unlocked", HFILL }},
3785
3786     { &hf_afp_dir_ar,
3787       { "Access rights",         "afp.dir_ar",
3788                 FT_UINT32, BASE_HEX, NULL, 0x0,
3789         "Directory access rights", HFILL }},
3790
3791     { &hf_afp_dir_ar_o_search,
3792       { "Owner has search access",      "afp.dir_ar.o_search",
3793                 FT_BOOLEAN, 32, NULL, AR_O_SEARCH,
3794         "Owner has search access", HFILL }},
3795
3796     { &hf_afp_dir_ar_o_read,
3797       { "Owner has read access",        "afp.dir_ar.o_read",
3798                 FT_BOOLEAN, 32, NULL, AR_O_READ,
3799         "Owner has read access", HFILL }},
3800
3801     { &hf_afp_dir_ar_o_write,
3802       { "Owner has write access",       "afp.dir_ar.o_write",
3803                 FT_BOOLEAN, 32, NULL, AR_O_WRITE,
3804         "Gwner has write access", HFILL }},
3805
3806     { &hf_afp_dir_ar_g_search,
3807       { "Group has search access",      "afp.dir_ar.g_search",
3808                 FT_BOOLEAN, 32, NULL, AR_G_SEARCH,
3809         "Group has search access", HFILL }},
3810
3811     { &hf_afp_dir_ar_g_read,
3812       { "Group has read access",        "afp.dir_ar.g_read",
3813                 FT_BOOLEAN, 32, NULL, AR_G_READ,
3814         "Group has read access", HFILL }},
3815
3816     { &hf_afp_dir_ar_g_write,
3817       { "Group has write access",       "afp.dir_ar.g_write",
3818                 FT_BOOLEAN, 32, NULL, AR_G_WRITE,
3819         "Group has write access", HFILL }},
3820
3821     { &hf_afp_dir_ar_e_search,
3822       { "Everyone has search access",   "afp.dir_ar.e_search",
3823                 FT_BOOLEAN, 32, NULL, AR_E_SEARCH,
3824         "Everyone has search access", HFILL }},
3825
3826     { &hf_afp_dir_ar_e_read,
3827       { "Everyone has read access",     "afp.dir_ar.e_read",
3828                 FT_BOOLEAN, 32, NULL, AR_E_READ,
3829         "Everyone has read access", HFILL }},
3830
3831     { &hf_afp_dir_ar_e_write,
3832       { "Everyone has write access",    "afp.dir_ar.e_write",
3833                 FT_BOOLEAN, 32, NULL, AR_E_WRITE,
3834         "Everyone has write access", HFILL }},
3835
3836     { &hf_afp_dir_ar_u_search,
3837       { "User has search access",   "afp.dir_ar.u_search",
3838                 FT_BOOLEAN, 32, NULL, AR_U_SEARCH,
3839         "User has search access", HFILL }},
3840
3841     { &hf_afp_dir_ar_u_read,
3842       { "User has read access",     "afp.dir_ar.u_read",
3843                 FT_BOOLEAN, 32, NULL, AR_U_READ,
3844         "User has read access", HFILL }},
3845
3846     { &hf_afp_dir_ar_u_write,
3847       { "User has write access",     "afp.dir_ar.u_write",
3848                 FT_BOOLEAN, 32, NULL, AR_U_WRITE,
3849         "User has write access", HFILL }},
3850
3851     { &hf_afp_dir_ar_blank,
3852       { "Blank access right",     "afp.dir_ar.blank",
3853                 FT_BOOLEAN, 32, NULL, AR_BLANK,
3854         "Blank access right", HFILL }},
3855
3856     { &hf_afp_dir_ar_u_own,
3857       { "User is the owner",     "afp.dir_ar.u_owner",
3858                 FT_BOOLEAN, 32, NULL, AR_U_OWN,
3859         "Current user is the directory owner", HFILL }},
3860
3861     { &hf_afp_server_time,
3862       { "Server time",         "afp.server_time",
3863                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3864         "Server time", HFILL }},
3865
3866     { &hf_afp_cat_req_matches,
3867       { "Max answers",         "afp.cat_req_matches",
3868                 FT_INT32, BASE_DEC, NULL, 0x0,
3869         "Maximum number of matches to return.", HFILL }},
3870
3871     { &hf_afp_reserved,
3872       { "Reserved",         "afp.reserved",
3873                 FT_BYTES, BASE_HEX, NULL, 0x0,
3874         "Reserved", HFILL }},
3875
3876     { &hf_afp_cat_count,
3877       { "Cat count",         "afp.cat_count",
3878                 FT_UINT32, BASE_DEC, NULL, 0x0,
3879         "Number of structures returned", HFILL }},
3880
3881     { &hf_afp_cat_position,
3882       { "Position",         "afp.cat_position",
3883                 FT_BYTES, BASE_HEX, NULL, 0x0,
3884         "Reserved", HFILL }},
3885
3886
3887     { &hf_afp_map_name_type,
3888       { "Type",      "afp.map_name_type",
3889                 FT_UINT8, BASE_DEC, VALS(map_name_type_vals), 0x0,
3890         "Map name type", HFILL }},
3891
3892     { &hf_afp_map_id_type,
3893       { "Type",      "afp.map_id_type",
3894                 FT_UINT8, BASE_DEC, VALS(map_id_type_vals), 0x0,
3895         "Map ID type", HFILL }},
3896
3897     { &hf_afp_map_id,
3898       { "ID",             "afp.map_id",
3899                 FT_UINT32, BASE_DEC, NULL, 0x0,
3900         "User/Group ID", HFILL }},
3901
3902     { &hf_afp_map_name,
3903       { "Name",             "afp.map_name",
3904                 FT_UINT_STRING, BASE_NONE, NULL, 0x0,
3905         "User/Group name", HFILL }},
3906
3907     /* AFP 3.0 */
3908     { &hf_afp_lock_offset64,
3909       { "Offset",         "afp.lock_offset64",
3910                 FT_INT64, BASE_DEC, NULL, 0x0,
3911         "First byte to be locked (64 bits)", HFILL }},
3912
3913     { &hf_afp_lock_len64,
3914       { "Length",         "afp.lock_len64",
3915                 FT_INT64, BASE_DEC, NULL, 0x0,
3916         "Number of bytes to be locked/unlocked (64 bits)", HFILL }},
3917
3918     { &hf_afp_lock_range_start64,
3919       { "Start",         "afp.lock_range_start64",
3920                 FT_INT64, BASE_DEC, NULL, 0x0,
3921         "First byte locked/unlocked (64 bits)", HFILL }},
3922
3923     { &hf_afp_offset64,
3924       { "Offset",         "afp.offset64",
3925                 FT_INT64, BASE_DEC, NULL, 0x0,
3926         "Offset (64 bits)", HFILL }},
3927     
3928     { &hf_afp_rw_count64,
3929       { "Count",         "afp.rw_count64",
3930                 FT_INT64, BASE_DEC, NULL, 0x0,
3931         "Number of bytes to be read/written (64 bits)", HFILL }},
3932
3933     { &hf_afp_last_written64,
3934       { "Last written",  "afp.last_written64",
3935                 FT_UINT64, BASE_DEC, NULL, 0x0,
3936         "Offset of the last byte written (64 bits)", HFILL }},
3937
3938     { &hf_afp_session_token_type,
3939       { "Type",         "afp.session_token_type",
3940                 FT_UINT16, BASE_HEX, NULL, 0x0,
3941         "Session token type", HFILL }},
3942
3943     { &hf_afp_session_token_len,
3944       { "Len",         "afp.session_token_len",
3945                 FT_UINT32, BASE_DEC, NULL, 0x0,
3946         "Session token length", HFILL }},
3947
3948     { &hf_afp_session_token,
3949       { "Token",         "afp.session_token",
3950                 FT_BYTES, BASE_HEX, NULL, 0x0,
3951         "Session token", HFILL }},
3952
3953     { &hf_afp_user_flag,
3954       { "Flag",         "afp.user_flag",
3955                 FT_UINT8, BASE_HEX, VALS(user_flag_vals), 0x01,
3956         "User Info flag", HFILL }},
3957
3958     { &hf_afp_user_ID,
3959       { "User ID",         "afp.user_ID",
3960                 FT_UINT32, BASE_DEC, NULL, 0x0,
3961         "User ID", HFILL }},
3962
3963     { &hf_afp_group_ID,
3964       { "Group ID",         "afp.group_ID",
3965                 FT_UINT32, BASE_DEC, NULL, 0x0,
3966         "Group ID", HFILL }},
3967
3968     { &hf_afp_user_bitmap,
3969       { "Bitmap",         "afp.user_bitmap",
3970                 FT_UINT16, BASE_HEX, NULL, 0,
3971         "User Info bitmap", HFILL }},
3972
3973     { &hf_afp_user_bitmap_UID,
3974       { "User ID",         "afp.user_bitmap.UID",
3975                 FT_BOOLEAN, 16, NULL, 0x01,
3976         "User ID", HFILL }},
3977
3978     { &hf_afp_user_bitmap_GID,
3979       { "Primary group ID",         "afp.user_bitmap.GID",
3980                 FT_BOOLEAN, 16, NULL, 0x02,
3981         "Primary group ID", HFILL }},
3982   };
3983
3984   static gint *ett[] = {
3985         &ett_afp,
3986         &ett_afp_server_vol,
3987         &ett_afp_vol_list,
3988         &ett_afp_vol_flag,
3989         &ett_afp_vol_bitmap,
3990         &ett_afp_vol_attribute,
3991         &ett_afp_dir_bitmap,
3992         &ett_afp_file_bitmap,
3993         &ett_afp_unix_privs,
3994         &ett_afp_enumerate,
3995         &ett_afp_enumerate_line,
3996         &ett_afp_access_mode,
3997         &ett_afp_dir_attribute,
3998         &ett_afp_file_attribute,
3999         &ett_afp_path_name,
4000         &ett_afp_lock_flags,
4001         &ett_afp_dir_ar,
4002         &ett_afp_cat_search,
4003         &ett_afp_cat_r_bitmap,
4004         &ett_afp_cat_spec,
4005         &ett_afp_vol_did,
4006         &ett_afp_user_bitmap,
4007   };
4008
4009   proto_afp = proto_register_protocol("AppleTalk Filing Protocol", "AFP", "afp");
4010   proto_register_field_array(proto_afp, hf, array_length(hf));
4011   proto_register_subtree_array(ett, array_length(ett));
4012
4013   register_init_routine( &afp_reinit);
4014
4015   register_dissector("afp", dissect_afp, proto_afp);
4016   data_handle = find_dissector("data");
4017 }
4018
4019 void
4020 proto_reg_handoff_afp(void)
4021 {
4022   data_handle = find_dissector("data");
4023 }
4024
4025 /* -------------------------------
4026    end
4027 */