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