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