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