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