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