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