ATP, ASP, and AFP support, from Didier Gautheron.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 25 Apr 2002 23:58:02 +0000 (23:58 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 25 Apr 2002 23:58:02 +0000 (23:58 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@5254 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
Makefile.am
Makefile.nmake
packet-afp.c [new file with mode: 0644]
packet-afp.h [new file with mode: 0644]
packet-atalk.c
packet-dsi.c

diff --git a/AUTHORS b/AUTHORS
index b8a06815ceb2f4534f6c37edd249cb6a2ab07aae..96327586ca14f7bf676e913cf17e0081624aa6b7 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1145,6 +1145,8 @@ Kikuchi Ayamura <ayamura[AT]ayamura.org> {
 
 Didier Gautheron <dgautheron[AT]magic.fr> {
        X11 bug fix
+       Appletalk Transaction Protocol, Appletalk Stream Protocol, and
+           Appletalk Filing Protocol support
 }
 
 Phil Williams <csypbw[AT]comp.leeds.ac.uk> {
index 02b366ab0cac77f7c85bde380c290e03dd1cd3d4..a3091afa4ea4b675a67bbadb4453e83d11f7b99e 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.424 2002/04/25 23:35:51 guy Exp $
+# $Id: Makefile.am,v 1.425 2002/04/25 23:58:02 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -73,6 +73,7 @@ sysconf_DATA = manuf dictionary.dtd dictionary.xml mobileipv4.xml \
 
 DISSECTOR_SRC = \
        packet-aarp.c  \
+       packet-afp.c   \
        packet-afs.c   \
        packet-aim.c   \
        packet-aodv.c  \
@@ -346,6 +347,7 @@ plugin_ldadd =
 endif
 
 noinst_HEADERS = \
+       packet-afp.h   \
        packet-afs.h   \
        packet-afs-macros.h \
        packet-afs-register-info.h \
index 298b67a7ff7076e397b3964d96e9359a42e1a1ec..1e7da2c26e97e914ce1c0aea9633d205ec2ba907 100644 (file)
@@ -1,7 +1,7 @@
 ## Makefile for building ethereal.exe with Microsoft C and nmake
 ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
 #
-# $Id: Makefile.nmake,v 1.181 2002/04/25 23:35:51 guy Exp $
+# $Id: Makefile.nmake,v 1.182 2002/04/25 23:58:02 guy Exp $
 
 include config.nmake
 include <win32.mak>
@@ -24,6 +24,7 @@ CVARSDLL=-DWIN32 -DNULL=0 -D_MT -D_DLL
 
 DISSECTOR_SRC = \
        packet-aarp.c  \
+       packet-afp.c   \
        packet-afs.c   \
        packet-aim.c   \
        packet-aodv.c  \
diff --git a/packet-afp.c b/packet-afp.c
new file mode 100644 (file)
index 0000000..cd74ece
--- /dev/null
@@ -0,0 +1,1852 @@
+/* packet-afp.c
+ * Routines for afp packet dissection
+ * Copyright 2002, Didier Gautheron <dgautheron@magic.fr>
+ *
+ * $Id: packet-afp.c,v 1.1 2002/04/25 23:58:02 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ * Copied from packet-dsi.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef NEED_SNPRINTF_H
+# ifdef HAVE_STDARG_H
+#  include <stdarg.h>
+# else
+#  include <varargs.h>
+# endif
+# include "snprintf.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+
+#include "packet-afp.h"
+
+/* The information in this module (AFP) comes from:
+
+  AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
+  available from http://www.apple.com
+  AFP3.0.pdf from http://www.apple.com
+  
+  The netatalk source code by Wesley Craig & Adrian Sun
+       http://netatalk.sf.net
+*/
+/* from netatalk/include/afp.h */
+#define AFPTRANS_NONE          0
+#define AFPTRANS_DDP          (1 << 0)
+#define AFPTRANS_TCP          (1 << 1)
+#define AFPTRANS_ALL          (AFPTRANS_DDP | AFPTRANS_TCP)
+
+/* server flags */
+#define AFPSRVRINFO_COPY                       (1<<0)  /* supports copyfile */
+#define AFPSRVRINFO_PASSWD                     (1<<1)  /* supports change password */
+#define AFPSRVRINFO_NOSAVEPASSWD       (1<<2)  /* don't allow save password */
+#define AFPSRVRINFO_SRVMSGS            (1<<3)  /* supports server messages */
+#define AFPSRVRINFO_SRVSIGNATURE       (1<<4)  /* supports server signature */
+#define AFPSRVRINFO_TCPIP              (1<<5)  /* supports tcpip */
+#define AFPSRVRINFO_SRVNOTIFY          (1<<6)  /* supports server notifications */ 
+#define AFPSRVRINFO_FASTBOZO           (1<<15) /* fast copying */
+
+/* AFP Attention Codes -- 4 bits */
+#define AFPATTN_SHUTDOWN     (1 << 15)            /* shutdown/disconnect */
+#define AFPATTN_CRASH        (1 << 14)            /* server crashed */
+#define AFPATTN_MESG         (1 << 13)            /* server has message */
+#define AFPATTN_NORECONNECT  (1 << 12)            /* don't reconnect */
+/* server notification */
+#define AFPATTN_NOTIFY       (AFPATTN_MESG | AFPATTN_NORECONNECT) 
+
+/* extended bitmap -- 12 bits. volchanged is only useful w/ a server
+ * notification, and time is only useful for shutdown. */
+#define AFPATTN_VOLCHANGED   (1 << 0)             /* volume has changed */
+#define AFPATTN_TIME(x)      ((x) & 0xfff)        /* time in minutes */
+
+/* AFP functions */
+#define AFP_BYTELOCK        1
+#define AFP_CLOSEVOL            2
+#define AFP_CLOSEDIR            3
+#define AFP_CLOSEFORK           4
+#define AFP_COPYFILE            5
+#define AFP_CREATEDIR           6
+#define AFP_CREATEFILE          7
+#define AFP_DELETE                  8
+#define AFP_ENUMERATE           9
+#define AFP_FLUSH                  10
+#define AFP_FLUSHFORK          11
+#define AFP_GETFORKPARAM       14
+#define AFP_GETSRVINFO         15
+#define AFP_GETSRVPARAM        16
+#define AFP_GETVOLPARAM                17
+#define AFP_LOGIN              18
+#define AFP_LOGINCONT          19
+#define AFP_LOGOUT             20
+#define AFP_MAPID                  21
+#define AFP_MAPNAME                22
+#define AFP_MOVE                   23
+#define AFP_OPENVOL            24
+#define AFP_OPENDIR                25
+#define AFP_OPENFORK           26
+#define AFP_READ                   27
+#define AFP_RENAME                 28
+#define AFP_SETDIRPARAM                29
+#define AFP_SETFILEPARAM       30
+#define AFP_SETFORKPARAM       31
+#define AFP_SETVOLPARAM                32
+#define AFP_WRITE                  33
+#define AFP_GETFLDRPARAM       34
+#define AFP_SETFLDRPARAM       35
+#define AFP_CHANGEPW           36
+#define AFP_GETSRVRMSG         38
+#define AFP_CREATEID           39
+#define AFP_DELETEID           40
+#define AFP_RESOLVEID          41
+#define AFP_EXCHANGEFILE       42
+#define AFP_CATSEARCH          43
+#define AFP_OPENDT                 48
+#define AFP_CLOSEDT                49
+#define AFP_GETICON         51
+#define AFP_GTICNINFO       52
+#define AFP_ADDAPPL         53
+#define AFP_RMVAPPL         54
+#define AFP_GETAPPL         55
+#define AFP_ADDCMT          56
+#define AFP_RMVCMT          57
+#define AFP_GETCMT          58
+#define AFP_ADDICON        192
+
+/* ----------------------------- */
+static int proto_afp = -1;
+static int hf_afp_flags = -1;
+static int hf_afp_requestid = -1;
+static int hf_afp_code = -1;
+static int hf_afp_length = -1;
+static int hf_afp_reserved = -1;
+
+static int hf_afp_command = -1;                /* CommandCode */
+static int hf_afp_AFPVersion = -1; 
+static int hf_afp_UAM = -1; 
+static int hf_afp_user = -1; 
+static int hf_afp_passwd = -1; 
+static int hf_afp_pad = -1;
+
+static int hf_afp_vol_bitmap = -1;
+static int hf_afp_bitmap_offset = -1;
+static int hf_afp_vol_id = -1;
+static int hf_afp_vol_attribute = -1;
+static int hf_afp_vol_name = -1;
+static int hf_afp_vol_signature = -1;
+static int hf_afp_vol_creation_date = -1;
+static int hf_afp_vol_modification_date = -1;
+static int hf_afp_vol_backup_date = -1;
+static int hf_afp_vol_bytes_free = -1;
+static int hf_afp_vol_bytes_total = -1;
+static int hf_afp_vol_ex_bytes_free = -1;
+static int hf_afp_vol_ex_bytes_total = -1;
+static int hf_afp_vol_block_size = -1;
+
+static int hf_afp_did = -1;
+static int hf_afp_file_id = -1;
+static int hf_afp_dir_bitmap = -1;
+static int hf_afp_dir_off_spring = -1;
+
+static int hf_afp_file_bitmap = -1;
+static int hf_afp_req_count = -1;
+static int hf_afp_start_index = -1;
+static int hf_afp_max_reply_size = -1;
+static int hf_afp_file_flag = -1;
+static int hf_afp_struct_size = -1;
+
+static int hf_afp_creation_date = -1;
+static int hf_afp_modification_date = -1;
+static int hf_afp_backup_date = -1;
+static int hf_afp_finder_info = -1;
+
+static int hf_afp_path_type = -1;
+static int hf_afp_path_name = -1;
+
+static int hf_afp_flag    = -1;
+static int hf_afp_ofork   = -1;
+static int hf_afp_offset  = -1;
+static int hf_afp_rw_count = 1;
+static int hf_afp_fork_type                    = -1;
+static int hf_afp_access_mode          = -1;
+static int hf_afp_access_read          = -1;
+static int hf_afp_access_write         = -1;
+static int hf_afp_access_deny_read  = -1;
+static int hf_afp_access_deny_write = -1;
+
+static gint ett_afp = -1;
+
+static gint ett_afp_vol_attribute = -1;
+static gint ett_afp_enumerate = -1;
+static gint ett_afp_enumerate_line = -1;
+static gint ett_afp_access_mode = -1;
+
+static gint ett_afp_vol_bitmap = -1;
+static gint ett_afp_dir_bitmap = -1;
+static gint ett_afp_file_bitmap = -1;
+
+static dissector_handle_t afp_handle;
+static dissector_handle_t data_handle;
+
+static const value_string vol_signature_vals[] = {
+       {1, "Flat"},
+       {2,  "Fixed Directory ID"},
+       {3,  "Variable Directory ID (deprecated)"},
+       {0,                              NULL } };
+
+static const value_string CommandCode_vals[] = {
+  {AFP_BYTELOCK,       "afpByteRangeLock" },
+  {AFP_CLOSEVOL,       "afpVolClose" },
+  {AFP_CLOSEDIR,       "afpDirClose" },
+  {AFP_CLOSEFORK,      "afpForkClose" },
+  {AFP_COPYFILE,       "afpCopyFile" },
+  {AFP_CREATEDIR,      "afpDirCreate" },
+  {AFP_CREATEFILE,     "afpFileCreate" },
+  {AFP_DELETE,         "afpDelete" },
+  {AFP_ENUMERATE,      "afpEnumerate" },
+  {AFP_FLUSH,          "afpFlush" },
+  {AFP_FLUSHFORK,      "afpForkFlush" },
+  {AFP_GETFORKPARAM,"afpGetForkParms" },
+  {AFP_GETSRVINFO,     "afpGetSInfo" },
+  {AFP_GETSRVPARAM,    "afpGetSParms" },
+  {AFP_GETVOLPARAM,    "afpGetVolParms" },
+  {AFP_LOGIN,          "afpLogin" },
+  {AFP_LOGINCONT,      "afpContLogin" },
+  {AFP_LOGOUT,         "afpLogout" },
+  {AFP_MAPID,          "afpMapID" },
+  {AFP_MAPNAME,                "afpMapName" },
+  {AFP_MOVE,           "afpMove" },
+  {AFP_OPENVOL,                "afpOpenVol" },
+  {AFP_OPENDIR,                "afpOpenDir" },
+  {AFP_OPENFORK,       "afpOpenFork" },
+  {AFP_READ,           "afpRead" },
+  {AFP_RENAME,         "afpRename" },
+  {AFP_SETDIRPARAM,    "afpSetDirParms" },
+  {AFP_SETFILEPARAM,"afpSetFileParms" },
+  {AFP_SETFORKPARAM,"afpSetForkParms" },
+  {AFP_SETVOLPARAM,    "afpSetVolParms" },
+  {AFP_WRITE,          "afpWrite" },
+  {AFP_GETFLDRPARAM,"afpGetFlDrParms" },
+  {AFP_SETFLDRPARAM,"afpSetFlDrParms" },
+  {AFP_CHANGEPW,       "afpChangePw" },
+  {AFP_GETSRVRMSG,     "afpGetSrvrMsg" },
+  {AFP_CREATEID,       "afpCreateID" },
+  {AFP_DELETEID,       "afpDeleteID" },
+  {AFP_RESOLVEID,      "afpResolveID" },
+  {AFP_EXCHANGEFILE,"afpExchangeFiles" },
+  {AFP_CATSEARCH,      "afpCatSearch" },
+  {AFP_OPENDT,         "afpDTOpen" },
+  {AFP_CLOSEDT,                "afpDTClose" },
+  {AFP_GETICON,                "afpGetIcon" },
+  {AFP_GTICNINFO,      "afpGtIcnInfo" },
+  {AFP_ADDAPPL,                "afpAddAPPL" },
+  {AFP_RMVAPPL,                "afpRmvAPPL" },
+  {AFP_GETAPPL,                "afpGetAPPL" },
+  {AFP_ADDCMT,         "afpAddCmt" },
+  {AFP_RMVCMT,         "afpRmvCmt" },
+  {AFP_GETCMT,         "afpGetCmt" },
+  {AFP_ADDICON,                "afpAddIcon" },
+  {0,                           NULL } };
+
+
+/* volume bitmap
+  from Apple AFP3.0.pdf 
+  Table 1-2 p. 20
+*/
+#define kFPVolAttributeBit             (1 << 0)
+#define kFPVolSignatureBit             (1 << 1)
+#define kFPVolCreateDateBit    (1 << 2)
+#define kFPVolModDateBit               (1 << 3)
+#define kFPVolBackupDateBit    (1 << 4)
+#define kFPVolIDBit                    (1 << 5)
+#define kFPVolBytesFreeBit     (1 << 6)
+#define kFPVolBytesTotalBit            (1 << 7)
+#define kFPVolNameBit                  (1 << 8)
+#define kFPVolExtBytesFreeBit  (1 << 9)
+#define kFPVolExtBytesTotalBit (1 << 10)
+#define kFPVolBlockSizeBit             (1 << 11)
+
+static int hf_afp_vol_bitmap_Attribute                 = -1;
+static int hf_afp_vol_bitmap_Signature                 = -1;
+static int hf_afp_vol_bitmap_CreateDate        = -1;
+static int hf_afp_vol_bitmap_ModDate           = -1;
+static int hf_afp_vol_bitmap_BackupDate        = -1;
+static int hf_afp_vol_bitmap_ID                        = -1;
+static int hf_afp_vol_bitmap_BytesFree                 = -1;
+static int hf_afp_vol_bitmap_BytesTotal        = -1;
+static int hf_afp_vol_bitmap_Name                      = -1;
+static int hf_afp_vol_bitmap_ExtBytesFree      = -1;
+static int hf_afp_vol_bitmap_ExtBytesTotal     = -1;
+static int hf_afp_vol_bitmap_BlockSize                 = -1;
+
+static int hf_afp_vol_attribute_ReadOnly                    = -1;
+static int hf_afp_vol_attribute_HasVolumePassword                      = -1;
+static int hf_afp_vol_attribute_SupportsFileIDs             = -1;
+static int hf_afp_vol_attribute_SupportsCatSearch           = -1;
+static int hf_afp_vol_attribute_SupportsBlankAccessPrivs    = -1;
+static int hf_afp_vol_attribute_SupportsUnixPrivs           = -1;
+static int hf_afp_vol_attribute_SupportsUTF8Names           = -1;
+
+static int hf_afp_dir_bitmap_Attribute         = -1;
+static int hf_afp_dir_bitmap_ParentDirID    = -1;
+static int hf_afp_dir_bitmap_CreateDate     = -1;
+static int hf_afp_dir_bitmap_ModDate        = -1;
+static int hf_afp_dir_bitmap_BackupDate     = -1;
+static int hf_afp_dir_bitmap_FinderInfo     = -1;
+static int hf_afp_dir_bitmap_LongName       = -1;
+static int hf_afp_dir_bitmap_ShortName      = -1;
+static int hf_afp_dir_bitmap_NodeID         = -1;
+static int hf_afp_dir_bitmap_OffspringCount = -1;
+static int hf_afp_dir_bitmap_OwnerID        = -1;
+static int hf_afp_dir_bitmap_GroupID        = -1;
+static int hf_afp_dir_bitmap_AccessRights   = -1;
+static int hf_afp_dir_bitmap_UTF8Name       = -1;
+static int hf_afp_dir_bitmap_UnixPrivs      = -1;
+
+static int hf_afp_file_bitmap_Attribute                 = -1;
+static int hf_afp_file_bitmap_ParentDirID    = -1;
+static int hf_afp_file_bitmap_CreateDate     = -1;
+static int hf_afp_file_bitmap_ModDate        = -1;
+static int hf_afp_file_bitmap_BackupDate     = -1;
+static int hf_afp_file_bitmap_FinderInfo     = -1;
+static int hf_afp_file_bitmap_LongName       = -1;
+static int hf_afp_file_bitmap_ShortName      = -1;
+static int hf_afp_file_bitmap_NodeID         = -1;
+static int hf_afp_file_bitmap_OffspringCount = -1;
+static int hf_afp_file_bitmap_UTF8Name       = -1;
+static int hf_afp_file_bitmap_UnixPrivs      = -1;
+
+static const value_string vol_bitmap_vals[] = {
+  {kFPVolAttributeBit,          "VolAttribute"},
+  {kFPVolSignatureBit,                 "VolSignature"},
+  {kFPVolCreateDateBit,                        "VolCreateDate"},
+  {kFPVolModDateBit,                   "VolModDate"},
+  {kFPVolBackupDateBit,                        "VolBackupDate"},
+  {kFPVolIDBit,                                        "VolID"},
+  {kFPVolBytesFreeBit,                 "VolBytesFree"},
+  {kFPVolBytesTotalBit,                        "VolBytesTotal"},
+  {kFPVolNameBit,                              "VolNameBit"},
+  {kFPVolExtBytesFreeBit,              "VolExtBytesFree"},
+  {kFPVolExtBytesTotalBit,             "VolExtBytesTotal"},
+  {kFPVolBlockSizeBit,                 "VolBlockSize"},
+  {0,                           NULL } };
+
+static const value_string flag_vals[] = {
+  {0,  "Start" },
+  {1,  "End" },
+  {0,                  NULL } };
+
+static const value_string path_type_vals[] = {
+  {1,  "Short names" },
+  {2,  "Long names" },
+  {3,  "Unicode names" },
+  {0,                  NULL } };
+
+/*
+  volume attribute from Apple AFP3.0.pdf 
+  Table 1-3 p. 22
+*/
+#define kReadOnly                                      (1 << 0)
+#define kHasVolumePassword                     (1 << 1)
+#define kSupportsFileIDs                       (1 << 2)
+#define kSupportsCatSearch                     (1 << 3)
+#define kSupportsBlankAccessPrivs      (1 << 4)
+#define kSupportsUnixPrivs                     (1 << 5)
+#define kSupportsUTF8Names                     (1 << 6)
+
+/*
+  directory bitmap from Apple AFP3.0.pdf 
+  Table 1-4 p. 31
+*/
+#define kFPAttributeBit                (1 << 0)
+#define kFPParentDirIDBit              (1 << 1)
+#define kFPCreateDateBit               (1 << 2)
+#define kFPModDateBit                  (1 << 3)
+#define kFPBackupDateBit               (1 << 4)
+#define kFPFinderInfoBit               (1 << 5)
+#define kFPLongNameBit                 (1 << 6)
+#define kFPShortNameBit                (1 << 7)
+#define kFPNodeIDBit                   (1 << 8)
+#define kFPOffspringCountBit   (1 << 9)
+#define kFPOwnerIDBit                  (1 << 10)
+#define kFPGroupIDBit                  (1 << 11)
+#define kFPAccessRightsBit             (1 << 12)
+#define kFPUTF8NameBit                         (1 << 13)
+#define kFPUnixPrivsBit                (1 << 14)
+
+/*
+  file bitmap AFP3.0.pdf 
+  Table 1-7 p. 36
+same as dir
+kFPAttributeBit                (bit 0)
+kFPParentDirIDBit              (bit 1)
+kFPCreateDateBit               (bit 2)
+kFPModDateBit                  (bit 3)
+kFPBackupDateBit               (bit 4)
+kFPFinderInfoBit               (bit 5)
+kFPLongNameBit                         (bit 6)
+kFPShortNameBit                (bit 7)
+kFPNodeIDBit                   (bit 8)
+
+kFPUTF8NameBit                         (bit 13)
+*/
+
+#define kFPDataForkLenBit                      (1 << 9)
+#define kFPRsrcForkLenBit                      (1 << 10)
+#define kFPExtDataForkLenBit           (1 << 11)
+#define kFPLaunchLimitBit                      (1 << 12)
+
+#define kFPExtRsrcForkLenBit           (1 << 14)
+#define kFPUnixPrivsBit_file           (1 << 15)       /* :( */
+
+#define hash_init_count 20
+
+/* Hash functions */
+static gint  afp_equal (gconstpointer v, gconstpointer v2);
+static guint afp_hash  (gconstpointer v);
+static guint afp_packet_init_count = 200;
+
+typedef struct {
+       guint32 conversation;
+       guint16 seq;
+} afp_request_key;
+typedef struct {
+       guint8  command;
+} afp_request_val;
+static GHashTable *afp_request_hash = NULL;
+static GMemChunk *afp_request_keys = NULL;
+static GMemChunk *afp_request_vals = NULL;
+
+/* Hash Functions */
+static gint  afp_equal (gconstpointer v, gconstpointer v2)
+{
+       afp_request_key *val1 = (afp_request_key*)v;
+       afp_request_key *val2 = (afp_request_key*)v2;
+
+       if (val1->conversation == val2->conversation &&
+                       val1->seq == val2->seq) {
+               return 1;
+       }
+       return 0;
+}
+
+static guint afp_hash  (gconstpointer v)
+{
+        afp_request_key *afp_key = (afp_request_key*)v;
+        return afp_key->seq;
+}
+
+/* -------------------------- 
+*/
+#define PAD(x)      { proto_tree_add_item(tree, hf_afp_pad, tvb, offset,  x, FALSE); offset += x; }
+
+static guint16
+decode_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       guint16  bitmap;
+
+       bitmap = tvb_get_ntohs(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_vol_bitmap, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_vol_bitmap);
+       }
+       
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Attribute,              tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Signature,              tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_CreateDate,     tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ModDate,                tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BackupDate,     tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ID,                     tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesFree,              tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesTotal,     tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Name,                   tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesFree,   tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesTotal,  tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BlockSize ,     tvb, offset, 2,FALSE);
+
+       return bitmap;
+}
+
+/* -------------------------- */
+static guint16
+decode_vol_attribute (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       guint16  bitmap;
+
+       bitmap = tvb_get_ntohs(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_vol_attribute, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_vol_attribute);
+       }
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_ReadOnly                ,tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_HasVolumePassword       ,tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsFileIDs         ,tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsCatSearch       ,tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsBlankAccessPrivs,tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUnixPrivs       ,tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUTF8Names       ,tvb, offset, 2,FALSE);
+                                                                               
+       return bitmap;                                                             
+}                                                                              
+                                                                               
+/* -------------------------- */
+static gint
+parse_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+guint16 nameoff = 0;
+
+       if ((bitmap & kFPVolAttributeBit)) {
+               decode_vol_attribute(tree,tvb,offset);
+               offset += 2;
+       }
+       if ((bitmap & kFPVolSignatureBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_signature,tvb, offset, 2, FALSE);
+               offset += 2;
+       }
+       if ((bitmap & kFPVolCreateDateBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_creation_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPVolModDateBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_modification_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPVolBackupDateBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_backup_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPVolIDBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+               offset += 2;
+       }
+       if ((bitmap & kFPVolBytesFreeBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_bytes_free,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPVolBytesTotalBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_bytes_total,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPVolNameBit)) {
+               nameoff = tvb_get_ntohs(tvb, offset);
+               proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
+               offset += 2;
+
+       }
+       if ((bitmap & kFPVolExtBytesFreeBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_ex_bytes_free,tvb, offset, 8, FALSE);
+               offset += 8;
+       }
+       if ((bitmap & kFPVolExtBytesTotalBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_ex_bytes_total,tvb, offset, 8, FALSE);
+               offset += 8;
+       }
+       if ((bitmap & kFPVolBlockSizeBit)) {
+               proto_tree_add_item(tree, hf_afp_vol_block_size,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if (nameoff) {
+       int len;
+
+               len = tvb_get_guint8(tvb, offset);
+               proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
+               offset += len +1;
+
+       }
+       return offset;
+}
+
+/* -------------------------- */
+static guint16
+decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       guint16         bitmap;
+
+       bitmap = tvb_get_ntohs(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_file_bitmap, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_file_bitmap);
+       }
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_Attribute      , tvb, offset, 2,FALSE);  
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ParentDirID    , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_CreateDate     , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ModDate        , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_BackupDate     , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_FinderInfo     , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LongName       , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ShortName      , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_NodeID         , tvb, offset, 2,FALSE);
+
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UTF8Name          , tvb, offset, 2,FALSE);
+
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UnixPrivs      , tvb, offset, 2,FALSE);
+
+       return bitmap;
+}
+
+/* -------------------------- */
+static gint
+parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+       guint16 lnameoff = 0;
+       guint16 snameoff = 0;
+       guint16 unameoff = 0;
+       gint    max_offset = 0;
+
+       gint    org_offset = offset;
+
+       if ((bitmap & kFPAttributeBit)) {
+               offset += 2;
+       }
+       if ((bitmap & kFPParentDirIDBit)) {
+               proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPCreateDateBit)) {
+               proto_tree_add_item(tree, hf_afp_creation_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPModDateBit)) {
+               proto_tree_add_item(tree, hf_afp_modification_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPBackupDateBit)) {
+               proto_tree_add_item(tree, hf_afp_backup_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPFinderInfoBit)) {
+               proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
+               offset += 32;
+       }
+       if ((bitmap & kFPLongNameBit)) {
+       gint tp_ofs;
+       guint8 len;
+               lnameoff = tvb_get_ntohs(tvb, offset);
+               if (lnameoff) {
+                       tp_ofs = lnameoff +org_offset;
+                       proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
+                       len = tvb_get_guint8(tvb, tp_ofs);
+                       proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, 1,FALSE);
+                       tp_ofs += len +1;
+                       max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+               }
+               offset += 2;
+       }
+       if ((bitmap & kFPShortNameBit)) {
+               snameoff = tvb_get_ntohs(tvb, offset);
+               proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
+               offset += 2;
+       }
+       if ((bitmap & kFPNodeIDBit)) {
+               proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
+
+       return offset;
+}
+
+/* -------------------------- */
+static guint16 
+decode_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       guint16         bitmap;
+       
+       bitmap = tvb_get_ntohs(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_dir_bitmap, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_dir_bitmap);
+       }
+       
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_Attribute      , tvb, offset, 2,FALSE);  
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ParentDirID    , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_CreateDate     , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ModDate        , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_BackupDate     , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_FinderInfo     , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_LongName       , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ShortName      , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_NodeID         , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OffspringCount , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OwnerID        , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_GroupID        , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_AccessRights   , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UTF8Name           , tvb, offset, 2,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UnixPrivs      , tvb, offset, 2,FALSE);
+
+       return bitmap;
+}
+
+/* -------------------------- */
+static gint
+parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+       guint16 lnameoff = 0;
+       guint16 snameoff = 0;
+       guint16 unameoff = 0;
+       gint    max_offset = 0;
+
+       gint    org_offset = offset;
+
+       if ((bitmap & kFPAttributeBit)) {
+               offset += 2;
+       }
+       if ((bitmap & kFPParentDirIDBit)) {
+               proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPCreateDateBit)) {
+               proto_tree_add_item(tree, hf_afp_creation_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPModDateBit)) {
+               proto_tree_add_item(tree, hf_afp_modification_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPBackupDateBit)) {
+               proto_tree_add_item(tree, hf_afp_backup_date,tvb, offset, 4, FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPFinderInfoBit)) {
+               proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
+               offset += 32;
+       }
+       if ((bitmap & kFPLongNameBit)) {
+               gint tp_ofs;
+               guint8 len;
+               lnameoff = tvb_get_ntohs(tvb, offset);
+               if (lnameoff) {
+                       tp_ofs = lnameoff +org_offset;
+                       proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
+                       len = tvb_get_guint8(tvb, tp_ofs);
+                       proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, 1,FALSE);
+                       tp_ofs += len +1;
+                       max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+               }
+               offset += 2;
+       }
+       if ((bitmap & kFPShortNameBit)) {
+               snameoff = tvb_get_ntohs(tvb, offset);
+               proto_tree_add_item(tree, hf_afp_bitmap_offset,tvb, offset, 2, FALSE);
+               offset += 2;
+       }
+       if ((bitmap & kFPNodeIDBit)) {
+               proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
+       if ((bitmap & kFPOffspringCountBit)) {
+               proto_tree_add_item(tree, hf_afp_dir_off_spring, tvb, offset, 2,FALSE);
+               offset += 2;            /* error in AFP3.0.pdf */
+       }
+       if ((bitmap & kFPOwnerIDBit)) {
+               offset += 4;
+       }
+       if ((bitmap & kFPGroupIDBit)) {
+               offset += 4;
+       }
+       if ((bitmap & kFPAccessRightsBit)) {
+               offset += 4;
+       }
+       if ((bitmap & kFPUTF8NameBit)) {
+               offset += 2;
+       }
+       if ((bitmap & kFPUnixPrivsBit)) {
+               unameoff = tvb_get_ntohs(tvb, offset);
+               offset += 4;
+       }
+       return (max_offset)?max_offset:offset;
+}
+
+/* -------------------------- */
+static gchar *
+name_in_bitmap(tvbuff_t *tvb, gint *offset, guint16 bitmap)
+{
+       gchar *name;
+       gint    org_offset = *offset;
+       guint16 nameoff;
+       guint8  len;
+       gint    tp_ofs;
+       
+       name = NULL;
+       if ((bitmap & kFPAttributeBit)) 
+               *offset += 2;
+       if ((bitmap & kFPParentDirIDBit))
+               *offset += 4;
+       if ((bitmap & kFPCreateDateBit)) 
+               *offset += 4;
+       if ((bitmap & kFPModDateBit))
+               *offset += 4;
+       if ((bitmap & kFPBackupDateBit)) 
+               *offset += 4;
+       if ((bitmap & kFPFinderInfoBit)) 
+               *offset += 32;
+       
+       if ((bitmap & kFPLongNameBit)) {
+               nameoff = tvb_get_ntohs(tvb, *offset);
+               if (nameoff) {
+                       tp_ofs = nameoff +org_offset;
+                       len = tvb_get_guint8(tvb, tp_ofs);
+                       tp_ofs++;
+                       if (!(name = g_malloc(len +1)))
+                               return name;
+                       tvb_memcpy(tvb, name, tp_ofs, len);
+                       *(name +len) = 0;
+                       return name;
+               }
+       }
+       /* short name ? */
+       return name;
+}
+
+/* -------------------------- */
+static gchar *
+name_in_dbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+       gchar *name;
+       
+       name = name_in_bitmap(tvb, &offset, bitmap);
+       if (name != NULL)
+               return name;
+       /*
+               check UTF8 name 
+       */
+       
+       return name;
+}
+
+/* -------------------------- */
+static gchar *
+name_in_fbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+       gchar *name;
+       
+       name = name_in_bitmap(tvb, &offset, bitmap);
+       if (name != NULL)
+               return name;
+       /*
+               check UTF8 name 
+       */
+       
+       return name;
+}
+
+/* -------------------------- */
+static gint
+decode_vol_did_file_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+       proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       decode_file_bitmap(tree, tvb, offset);
+       offset += 2;
+       
+       decode_dir_bitmap(tree, tvb, offset);
+       offset += 2;
+       
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+decode_name (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+       int len;
+
+       proto_tree_add_item(tree, hf_afp_path_type, tvb, offset, 1,FALSE);
+       offset += 1;
+
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_path_name, tvb, offset, 1,FALSE);
+       offset += len +1;
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       int len;
+       
+       PAD(1);
+
+       decode_vol_bitmap(tree, tvb, offset);
+       offset += 2;
+       
+       len = tvb_get_guint8(tvb, offset);
+#if 0  
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               gchar   *func_str;
+
+               if ((func_str = match_strval(afp_command, CommandCode_vals)))
+               {
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", func_str, aspinfo->reply?"reply":"");
+               }
+       }
+#endif 
+       proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
+       offset += len +1;
+               
+       len = tvb_reported_length_remaining(tvb,offset);
+       if (len >= 8) {
+               /* optionnal password */
+               proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, 8,FALSE);
+               offset += 8;
+       }
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       guint16 bitmap;
+
+       bitmap = decode_vol_bitmap(tree, tvb, offset);
+       offset += 2;
+       offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+
+       proto_tree_add_item(tree, hf_afp_fork_type, tvb, offset, 1,FALSE);
+       offset++;
+       
+       proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       decode_file_bitmap(tree, tvb, offset);
+       offset += 2;
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_access_mode, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_access_mode);
+       }
+       item = proto_tree_add_item(sub_tree, hf_afp_access_read      , tvb, offset, 2,FALSE);
+       item = proto_tree_add_item(sub_tree, hf_afp_access_write     , tvb, offset, 2,FALSE);
+       item = proto_tree_add_item(sub_tree, hf_afp_access_deny_read , tvb, offset, 2,FALSE);
+       item = proto_tree_add_item(sub_tree, hf_afp_access_deny_write, tvb, offset, 2,FALSE);
+
+       offset += 2;
+
+       offset = decode_name(tree,tvb, offset);
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       int f_bitmap;
+
+       f_bitmap = decode_file_bitmap(tree, tvb, offset);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       offset = parse_file_bitmap(tree, tvb, offset, f_bitmap);
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       
+       PAD(1);
+       offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
+
+       proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_start_index, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_max_reply_size, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       offset = decode_name(tree,tvb, offset);
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       int count;
+       int f_bitmap;
+       int d_bitmap;
+       guint8  flags;
+       guint8  size;
+       gint    org;
+       int i;
+       gchar *name;
+       
+       f_bitmap = decode_file_bitmap(tree, tvb, offset);
+       offset += 2;
+       
+       d_bitmap = decode_dir_bitmap(tree, tvb, offset);
+       offset += 2;
+
+       count = tvb_get_ntohs(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_enumerate);
+       }
+       offset += 2;
+       /* loop */
+       if (tree) for (i = 0; i < count; i++) {
+               org = offset;
+               name = NULL;
+               size = tvb_get_guint8(tvb, offset);
+               flags = tvb_get_guint8(tvb, offset +1);
+
+               if (flags) {
+                       name = name_in_dbitmap(tvb, offset +2, d_bitmap);
+               }
+               else {
+                       name = name_in_fbitmap(tvb, offset +2, f_bitmap);
+               }
+               if (!name) {
+                       if (!(name = g_malloc(50))) { /* no memory ! */
+                       }
+                       snprintf(name, 50,"line %d", i +1);
+               }
+               item = proto_tree_add_text(sub_tree, tvb, offset, size, name);
+               tree = proto_item_add_subtree(item, ett_afp_enumerate_line);
+
+               proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
+               offset++;
+
+               proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
+               offset++;
+               if (flags) {
+                       offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
+               }
+               else {
+                       offset = parse_file_bitmap(tree, tvb, offset, f_bitmap);
+               }
+               if ((offset & 1)) 
+                       PAD(1);
+               offset = org +size;             /* play safe */
+               g_free((gpointer)name);
+       }       
+       return(offset);
+
+}
+
+/* **************************/
+static gint
+dissect_query_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       if (!tree)
+               return offset;
+       PAD(1)
+       proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       decode_vol_bitmap(tree, tvb, offset);
+       offset += 2;
+       
+       return offset;  
+}
+
+/* ------------------------ */
+static gint
+dissect_reply_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       guint16 bitmap;
+
+       if (!tree)
+               return offset;
+       bitmap = decode_vol_bitmap(tree, tvb, offset);
+       offset += 2;
+
+       offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
+
+       return offset;
+}
+
+/* ***************************/
+static gint
+dissect_query_afp_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       int len;
+       
+       if (!tree)
+               return offset;
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
+       offset += len +1;
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
+       offset += len +1;
+
+       /* clear text */
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_user, tvb, offset, 1,FALSE);
+       offset += len +1;
+
+       len = tvb_strsize(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
+       offset += len;
+
+       return(offset);
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       int len;
+       
+       if (!tree)
+               return offset;
+       proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
+       offset += 1;
+
+       proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+       if (!tree)
+               return offset;
+       PAD(1);
+       offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
+
+       offset = decode_name(tree, tvb, offset);
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+guint8 flags;
+guint16 f_bitmap, d_bitmap;
+
+       if (!tree)
+               return offset;
+       f_bitmap = decode_file_bitmap(tree, tvb, offset);
+       offset += 2;
+       
+       d_bitmap = decode_dir_bitmap(tree, tvb, offset);
+       offset += 2;
+
+       flags = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
+       offset++;
+       PAD(1);
+       if (flags) {
+               offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
+       }
+       else {
+               offset = parse_file_bitmap(tree, tvb, offset, f_bitmap);
+       }
+       return offset;
+}
+
+/* ************************** */
+static void
+dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       struct aspinfo *aspinfo = pinfo->private_data;
+       proto_tree      *afp_tree = NULL;
+       proto_item      *ti;
+       conversation_t  *conversation;
+       gint            offset = 0;
+       afp_request_key request_key, *new_request_key;
+       afp_request_val *request_val;
+
+       gchar   *func_str;
+
+       guint8  afp_flags,afp_command;
+       guint16 afp_requestid;
+       gint32  afp_code;
+       guint32 afp_length;
+       guint32 afp_reserved;
+       int     len =  tvb_reported_length_remaining(tvb,0);
+       
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFP");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
+
+       conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+               pinfo->srcport, pinfo->destport, 0);
+
+       if (conversation == NULL)
+       {
+               conversation = conversation_new(&pinfo->src, &pinfo->dst,
+                       pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+       }
+
+       request_key.conversation = conversation->index; 
+       request_key.seq = aspinfo->seq;
+
+       request_val = (afp_request_val *) g_hash_table_lookup(
+                                                               afp_request_hash, &request_key);
+
+       if (!request_val && !aspinfo->reply)  {
+               afp_command = tvb_get_guint8(tvb, offset);
+               new_request_key = g_mem_chunk_alloc(afp_request_keys);
+               *new_request_key = request_key;
+
+               request_val = g_mem_chunk_alloc(afp_request_vals);
+               request_val->command = tvb_get_guint8(tvb, offset);
+
+               g_hash_table_insert(afp_request_hash, new_request_key,
+                                                               request_val);
+       }
+
+       if (!request_val) {     /* missing request */
+               return;
+       }
+
+       afp_command = request_val->command;
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               gchar   *func_str;
+
+               if ((func_str = match_strval(afp_command, CommandCode_vals)))
+               {
+                       col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", func_str, aspinfo->reply?"reply":"");
+               }
+       }
+
+       if (tree)
+       {
+               ti = proto_tree_add_item(tree, proto_afp, tvb, offset, -1,FALSE);
+               afp_tree = proto_item_add_subtree(ti, ett_afp);
+       }
+       if (!aspinfo->reply)  {
+               proto_tree_add_uint(afp_tree, hf_afp_command, tvb,offset, 1, afp_command);
+               offset++;
+               switch(afp_command) {
+               case AFP_BYTELOCK:
+               case AFP_CLOSEVOL:
+               case AFP_CLOSEDIR:
+               case AFP_CLOSEFORK:
+               case AFP_COPYFILE:
+               case AFP_CREATEDIR:
+               case AFP_CREATEFILE:
+               case AFP_DELETE:
+                       break;
+               case AFP_ENUMERATE:
+                       offset = dissect_query_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
+               case AFP_FLUSH:
+               case AFP_FLUSHFORK:
+               case AFP_GETFORKPARAM:
+               case AFP_GETSRVINFO:
+               case AFP_GETSRVPARAM:
+                       break;
+               case AFP_GETVOLPARAM:
+                       offset = dissect_query_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
+               case AFP_LOGIN:
+                       offset = dissect_query_afp_login(tvb, pinfo, afp_tree, offset);break;
+               case AFP_LOGINCONT:
+               case AFP_LOGOUT:
+               case AFP_MAPID:
+               case AFP_MAPNAME:
+               case AFP_MOVE:
+                       break;
+               case AFP_OPENVOL:
+                       offset = dissect_query_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
+               case AFP_OPENDIR:
+                       break;
+               case AFP_OPENFORK:
+                       offset = dissect_query_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
+               case AFP_READ:
+               case AFP_RENAME:
+               case AFP_SETDIRPARAM:
+               case AFP_SETFILEPARAM:
+               case AFP_SETFORKPARAM:
+               case AFP_SETVOLPARAM:
+                       break;
+               case AFP_WRITE:
+                       offset = dissect_query_afp_write(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETFLDRPARAM:
+                       offset = dissect_query_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
+               case AFP_SETFLDRPARAM:
+               case AFP_CHANGEPW:
+               case AFP_GETSRVRMSG:
+               case AFP_CREATEID:
+               case AFP_DELETEID:
+               case AFP_RESOLVEID:
+               case AFP_EXCHANGEFILE:
+               case AFP_CATSEARCH:
+               case AFP_OPENDT:
+               case AFP_CLOSEDT:
+               case AFP_GETICON:
+               case AFP_GTICNINFO:
+               case AFP_ADDAPPL:
+               case AFP_RMVAPPL:
+               case AFP_GETAPPL:
+               case AFP_ADDCMT:
+               case AFP_RMVCMT:
+               case AFP_GETCMT:
+               case AFP_ADDICON:
+                       break;
+               }
+       }
+       else {
+               switch(afp_command) {
+               case AFP_ENUMERATE:
+                       offset = dissect_reply_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
+               case AFP_OPENVOL:
+                       offset = dissect_reply_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
+               case AFP_OPENFORK:
+                       offset = dissect_reply_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
+               case AFP_FLUSH:
+               case AFP_FLUSHFORK:
+               case AFP_GETFORKPARAM:
+               case AFP_GETSRVINFO:
+               case AFP_GETSRVPARAM:
+                       break;
+               case AFP_GETVOLPARAM:
+                       offset = dissect_reply_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETFLDRPARAM:
+                       offset = dissect_reply_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
+               }
+       }
+       if (tree && offset < len)
+               call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, afp_tree);
+}
+
+static void afp_reinit( void)
+{
+
+       if (afp_request_hash)
+               g_hash_table_destroy(afp_request_hash);
+       if (afp_request_keys)
+               g_mem_chunk_destroy(afp_request_keys);
+       if (afp_request_vals)
+               g_mem_chunk_destroy(afp_request_vals);
+
+       afp_request_hash = g_hash_table_new(afp_hash, afp_equal);
+
+       afp_request_keys = g_mem_chunk_new("afp_request_keys",
+               sizeof(afp_request_key),
+               afp_packet_init_count * sizeof(afp_request_key),
+               G_ALLOC_AND_FREE);
+       afp_request_vals = g_mem_chunk_new("afp_request_vals",
+               sizeof(afp_request_val),
+               afp_packet_init_count * sizeof(afp_request_val),
+               G_ALLOC_AND_FREE);
+
+}
+
+void
+proto_register_afp(void)
+{
+
+  static hf_register_info hf[] = {
+    { &hf_afp_command,
+      { "Command",      "afp.command",
+               FT_UINT8, BASE_DEC, VALS(CommandCode_vals), 0x0,
+       "AFP function", HFILL }},
+
+       { &hf_afp_pad,    
+         { "pad",              "afp.pad",    
+               FT_NONE,   BASE_NONE, NULL, 0, 
+               "Pad Byte",     HFILL }},
+
+    { &hf_afp_AFPVersion,
+      { "AFP Version",  "afp.AFPVersion",
+               FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "client AFP version", HFILL }},
+
+    { &hf_afp_UAM,
+      { "UAM",          "afp.UAM",
+               FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "USer Authentication method", HFILL }},
+
+    { &hf_afp_user,
+      { "user",         "afp.user",
+               FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "User", HFILL }},
+
+    { &hf_afp_passwd,
+      { "password",     "afp.passwd",
+               FT_STRINGZ, BASE_NONE, NULL, 0x0,
+       "password", HFILL }},
+
+    { &hf_afp_vol_bitmap,
+      { "bitmap",         "afp.vol_bitmap",
+               FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
+       "Volume bitmap", HFILL }},
+
+       { &hf_afp_vol_bitmap_Attribute,
+      { "attribute",         "afp.vol_bitmap.attribute",
+               FT_BOOLEAN, 16, NULL, kFPVolAttributeBit,
+       "Volume attribute", HFILL }},
+
+           { &hf_afp_vol_attribute, { "attribute",         "afp.vol_attribute",
+                       FT_UINT16, BASE_HEX, NULL, 0 , "Volume attribute", HFILL }},
+
+           { &hf_afp_vol_attribute_ReadOnly, 
+            { "read only",         "afp.vol_attribute.read_only",
+                FT_BOOLEAN, 16, NULL, kReadOnly,
+        "Read only volume", HFILL }},
+
+           { &hf_afp_vol_attribute_HasVolumePassword,
+            { "volume password",         "afp.vol_attribute.passwd",
+                FT_BOOLEAN, 16, NULL, kHasVolumePassword,
+        "Has a volume password", HFILL }},
+
+           { &hf_afp_vol_attribute_SupportsFileIDs,
+            { "files ID",         "afp.vol_attribute.fileIDs",
+                FT_BOOLEAN, 16, NULL, kSupportsFileIDs,
+        "Supports files ID", HFILL }},
+
+           { &hf_afp_vol_attribute_SupportsCatSearch,
+            { "cat search",         "afp.vol_attribute.cat_search",
+                FT_BOOLEAN, 16, NULL, kSupportsCatSearch,
+        "Supports cat search call", HFILL }},
+
+           { &hf_afp_vol_attribute_SupportsBlankAccessPrivs,
+            { "blank access privs",         "afp.vol_attribute.blank_access_privs",
+                FT_BOOLEAN, 16, NULL, kSupportsBlankAccessPrivs,
+        "Supports blank access priv.", HFILL }},
+
+           { &hf_afp_vol_attribute_SupportsUnixPrivs,
+           { "blank access privs",         "afp.vol_attribute.unix_privs",
+                FT_BOOLEAN, 16, NULL, kSupportsUnixPrivs,
+        "Supports Unix access priv.", HFILL }},
+
+           { &hf_afp_vol_attribute_SupportsUTF8Names,
+           { "blank access privs",         "afp.vol_attribute.utf8_names",
+                FT_BOOLEAN, 16, NULL, kSupportsUTF8Names,
+        "Supports UTF8 names.", HFILL }},
+
+    { &hf_afp_vol_bitmap_Signature,
+      { "signature",         "afp.vol_bitmap.signature",
+               FT_BOOLEAN, 16, NULL, kFPVolSignatureBit,
+       "Volume signature", HFILL }},
+    { &hf_afp_vol_bitmap_CreateDate,
+      { "creation date",      "afp.vol_bitmap.create_date",
+               FT_BOOLEAN, 16, NULL, kFPVolCreateDateBit,
+       "Volume creation date", HFILL }},
+    { &hf_afp_vol_bitmap_ModDate,
+      { "modification date",  "afp.vol_bitmap.mod_date",
+               FT_BOOLEAN, 16, NULL, kFPVolModDateBit,
+       "Volume modification date", HFILL }},
+    { &hf_afp_vol_bitmap_BackupDate,
+      { "backup date",        "afp.vol_bitmap.backup_date",
+               FT_BOOLEAN, 16, NULL, kFPVolBackupDateBit,
+       "Volume backup date", HFILL }},
+    { &hf_afp_vol_bitmap_ID,
+      { "ID",         "afp.vol_bitmap.id",
+               FT_BOOLEAN, 16, NULL,  kFPVolIDBit,
+       "Volume ID", HFILL }},
+    { &hf_afp_vol_bitmap_BytesFree,
+      { "bytes free",         "afp.vol_bitmap.bytes_free",
+               FT_BOOLEAN, 16, NULL,  kFPVolBytesFreeBit,
+       "Volume free bytes", HFILL }},
+    { &hf_afp_vol_bitmap_BytesTotal,
+      { "bytes total",         "afp.vol_bitmap.bytes_total",
+               FT_BOOLEAN, 16, NULL,  kFPVolBytesTotalBit,
+       "Volume total bytes", HFILL }},
+    { &hf_afp_vol_bitmap_Name,
+      { "name",         "afp.vol_bitmap.name",
+               FT_BOOLEAN, 16, NULL,  kFPVolNameBit,
+       "Volume name", HFILL }},
+    { &hf_afp_vol_bitmap_ExtBytesFree,
+      { "ex. bytes free",         "afp.vol_bitmap.ex_bytes_free",
+               FT_BOOLEAN, 16, NULL,  kFPVolExtBytesFreeBit,
+       "Volume ext. free bytes", HFILL }},
+    { &hf_afp_vol_bitmap_ExtBytesTotal,
+      { "ex bytes total",         "afp.vol_bitmap.ex_bytes_total",
+               FT_BOOLEAN, 16, NULL,  kFPVolExtBytesTotalBit,
+       "Volume ex. total byte", HFILL }},
+    { &hf_afp_vol_bitmap_BlockSize,
+      { "block size",         "afp.vol_bitmap.block_size",
+               FT_BOOLEAN, 16, NULL,  kFPVolBlockSizeBit,
+       "Volume block size", HFILL }},
+
+    { &hf_afp_dir_bitmap_Attribute,        
+      { "attribute",         "afp.dir_bitmap.attribute",
+           FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
+       "directory attribute", HFILL }},
+    { &hf_afp_dir_bitmap_ParentDirID,     
+      { "DID",         "afp.dir_bitmap.did",
+       FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
+       "parent directory ID", HFILL }},
+    { &hf_afp_dir_bitmap_CreateDate,      
+      { "creation date",         "afp.dir_bitmap.create_date",
+           FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
+       "directory creation date", HFILL }},
+    { &hf_afp_dir_bitmap_ModDate,                 
+      { "modification date",         "afp.dir_bitmap.mod_date",
+       FT_BOOLEAN, 16, NULL,  kFPModDateBit,
+       "directory modification date", HFILL }},
+    { &hf_afp_dir_bitmap_BackupDate,      
+      { "backup date",         "afp.dir_bitmap.backup_date",
+           FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
+       "directory backup date", HFILL }},
+    { &hf_afp_dir_bitmap_FinderInfo,      
+      { "Finder info",         "afp.dir_bitmap.finder_info",
+       FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
+       "directory finder info", HFILL }},
+    { &hf_afp_dir_bitmap_LongName,                
+      { "long name",         "afp.dir_bitmap.long_name",
+           FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
+       "directory long name", HFILL }},
+    { &hf_afp_dir_bitmap_ShortName,               
+      { "short name",         "afp.dir_bitmap.short_name",
+       FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
+       "directory short name", HFILL }},
+    { &hf_afp_dir_bitmap_NodeID,                  
+      { "file ID",         "afp.dir_bitmap.fid",
+           FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
+       "directory file ID", HFILL }},
+    { &hf_afp_dir_bitmap_OffspringCount,   
+      { "offspring count",         "afp.dir_bitmap.off_spring_count",
+       FT_BOOLEAN, 16, NULL,  kFPOffspringCountBit,
+       "directory offSpring count", HFILL }},
+    { &hf_afp_dir_bitmap_OwnerID,                 
+      { "owner id",         "afp.dir_bitmap.owner_id",
+           FT_BOOLEAN, 16, NULL,  kFPOwnerIDBit,
+       "directory owner id", HFILL }},
+    { &hf_afp_dir_bitmap_GroupID,                 
+      { "group id",         "afp.dir_bitmap.group_id",
+       FT_BOOLEAN, 16, NULL,  kFPGroupIDBit,
+       "directory group id", HFILL }},
+    { &hf_afp_dir_bitmap_AccessRights,    
+      { "access rights",         "afp.dir_bitmap.access_rights",
+           FT_BOOLEAN, 16, NULL,  kFPAccessRightsBit,
+       "directory access rights", HFILL }},
+    { &hf_afp_dir_bitmap_UTF8Name,                
+      { "UTF8 name",         "afp.dir_bitmap.UTF8_name",
+       FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
+       "directory UTF8 name", HFILL }},
+    { &hf_afp_dir_bitmap_UnixPrivs,               
+      { "unix privs",         "afp.dir_bitmap.unix_privs",
+           FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit,
+       "directory unix privs", HFILL }},
+
+    { &hf_afp_file_bitmap_Attribute,        
+      { "attribute",         "afp.file_bitmap.attribute",
+           FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
+       "file attribute", HFILL }},
+    { &hf_afp_file_bitmap_ParentDirID,    
+      { "DID",         "afp.file_bitmap.did",
+       FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
+       "parent directory ID", HFILL }},
+    { &hf_afp_file_bitmap_CreateDate,     
+      { "creation date",         "afp.file_bitmap.create_date",
+           FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
+       "file creation date", HFILL }},
+    { &hf_afp_file_bitmap_ModDate,                
+      { "modification date",         "afp.file_bitmap.mod_date",
+       FT_BOOLEAN, 16, NULL,  kFPModDateBit,
+       "file modification date", HFILL }},
+    { &hf_afp_file_bitmap_BackupDate,     
+      { "backup date",         "afp.file_bitmap.backup_date",
+           FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
+       "file backup date", HFILL }},
+    { &hf_afp_file_bitmap_FinderInfo,     
+      { "Finder info",         "afp.file_bitmap.finder_info",
+       FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
+       "file finder info", HFILL }},
+    { &hf_afp_file_bitmap_LongName,               
+      { "long name",         "afp.file_bitmap.long_name",
+           FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
+       "file long name", HFILL }},
+    { &hf_afp_file_bitmap_ShortName,              
+      { "short name",         "afp.file_bitmap.short_name",
+       FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
+       "file short name", HFILL }},
+    { &hf_afp_file_bitmap_NodeID,                 
+      { "file ID",         "afp.file_bitmap.fid",
+           FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
+       "file file ID", HFILL }},
+    { &hf_afp_file_bitmap_UTF8Name,               
+      { "UTF8 name",         "afp.file_bitmap.UTF8_name",
+       FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
+       "file UTF8 name", HFILL }},
+    { &hf_afp_file_bitmap_UnixPrivs,              
+      { "unix privs",         "afp.file_bitmap.unix_privs",
+           FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit,
+       "file unix privs", HFILL }},
+
+    { &hf_afp_vol_name,
+      { "Volume",         "afp.vol_name",
+       FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "Volume name", HFILL }},
+    { &hf_afp_vol_id,
+      { "volume id",         "afp.vol_id",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "Volume id", HFILL }},
+    { &hf_afp_vol_signature,
+      { "signature",         "afp.vol_signature",
+               FT_UINT16, BASE_DEC, VALS(vol_signature_vals), 0x0,
+       "Volume signature", HFILL }},
+    { &hf_afp_bitmap_offset,
+      { "offset",         "afp.bitmap_offset",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "name offset in packet", HFILL }},
+    { &hf_afp_vol_creation_date,
+      { "creation date",         "afp.vol_creation_date",
+               FT_UINT32, BASE_HEX, NULL, 0x0,
+       "volume creation date", HFILL }},
+    { &hf_afp_vol_modification_date,
+      { "modification date",         "afp.vol_modification_date",
+               FT_UINT32, BASE_HEX, NULL, 0x0,
+       "volume modification date", HFILL }},
+    { &hf_afp_vol_backup_date,
+      { "backup date",         "afp.vol_backup_date",
+               FT_UINT32, BASE_HEX, NULL, 0x0,
+       "volume backup date", HFILL }},
+    { &hf_afp_vol_bytes_free,
+      { "bytes free",         "afp.vol_bytes_free",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "free space", HFILL }},
+    { &hf_afp_vol_bytes_total,
+      { "bytes total",         "afp.vol_bytes_total",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "volume size ", HFILL }},
+    { &hf_afp_vol_ex_bytes_free,
+      { "ex. bytes free",         "afp.vol_ex_bytes_free",
+               FT_UINT64, BASE_DEC, NULL, 0x0,
+       "ex. free space", HFILL }},
+    { &hf_afp_vol_ex_bytes_total,
+      { "ex. bytes total",         "afp.vol_ex_bytes_total",
+               FT_UINT64, BASE_DEC, NULL, 0x0,
+       "ex. volume size ", HFILL }},
+    { &hf_afp_vol_block_size,
+      { "block size",         "afp.vol_block_size",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "volume block size", HFILL }},
+
+    { &hf_afp_did,
+      { "did",         "afp.did",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "parent directory id", HFILL }},
+
+    { &hf_afp_dir_bitmap,
+      { "dir bitmap",         "afp.dir_bitmap",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
+       "directory bitmap", HFILL }},
+
+    { &hf_afp_dir_off_spring,
+      { "off spring",         "afp.dir_off_spring",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "directory offspring", HFILL }},
+
+    { &hf_afp_creation_date,
+      { "creation date",         "afp.creation_date",
+               FT_UINT32, BASE_HEX, NULL, 0x0,
+       "creation date", HFILL }},
+    { &hf_afp_modification_date,
+      { "modification date",         "afp.modification_date",
+               FT_UINT32, BASE_HEX, NULL, 0x0,
+       "modification date", HFILL }},
+    { &hf_afp_backup_date,
+      { "backup date",         "afp.backup_date",
+               FT_UINT32, BASE_HEX, NULL, 0x0,
+       "backup date", HFILL }},
+
+    { &hf_afp_finder_info,
+      { "finder info",         "afp.finder_info",
+               FT_BYTES, BASE_HEX, NULL, 0x0,
+       "finder info", HFILL }},
+
+    { &hf_afp_file_id,
+      { "file id",         "afp.file_id",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "file/directory id", HFILL }},
+    
+    { &hf_afp_file_bitmap,
+      { "file bitmap",         "afp.file_bitmap",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
+       "file bitmap", HFILL }},
+    
+    { &hf_afp_req_count,
+      { "req count",         "afp.req_count",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "Maximum number of structures returned", HFILL }},
+
+    { & hf_afp_start_index, 
+      { "start index",         "afp.start_index",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "first structure returned", HFILL }},
+    
+    { &hf_afp_max_reply_size,
+      { "reply size",         "afp.reply_size",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "first structure returned", HFILL }},
+
+    { &hf_afp_file_flag,
+      { "dir",         "afp.flag",
+               FT_BOOLEAN, 8, NULL, 0x80,
+       "is a dir", HFILL }},
+
+    { &hf_afp_struct_size,
+      { "struct size",         "afp.struct_size",
+               FT_UINT8, BASE_DEC, NULL,0,
+       "sizeof of struct", HFILL }},
+    
+    { &hf_afp_flag,
+      { "from",         "afp.flag",
+               FT_UINT8, BASE_HEX, VALS(flag_vals), 0x80,
+       "offset is relative to start/end of the fork", HFILL }},
+
+    { &hf_afp_ofork,
+      { "fork",         "afp.ofork",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "Open fork reference number", HFILL }},
+
+    { &hf_afp_offset,
+      { "offset",         "afp.offset",
+               FT_INT32, BASE_DEC, NULL, 0x0,
+       "offset ", HFILL }},
+    
+    { &hf_afp_rw_count,
+      { "count",         "afp.rw_count",
+               FT_INT32, BASE_DEC, NULL, 0x0,
+       "number of bytes to be written ", HFILL }},
+      
+    { &hf_afp_path_type,
+      { "path type ",         "afp.path_type",
+               FT_UINT8, BASE_HEX, VALS(path_type_vals), 0,
+       "type of names", HFILL }},
+
+    { &hf_afp_path_name,
+      { "Name ",  "afp.path_name",
+               FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "path name", HFILL }},
+
+    { &hf_afp_fork_type,
+      { "ressource fork",         "afp.fork_type",
+               FT_BOOLEAN, 8, NULL, 0x80,
+       "data/ressource fork", HFILL }},
+
+    { &hf_afp_access_mode,
+      { "access mode",         "afp.access",
+               FT_UINT8, BASE_HEX, NULL, 0x0,
+       "fork access mode", HFILL }},
+    { &hf_afp_access_read,
+      { "read",         "afp.access.read",
+       FT_BOOLEAN, 8, NULL,  1,
+       "open for reading", HFILL }},
+    { &hf_afp_access_write,
+      { "write",         "afp.access.write",
+       FT_BOOLEAN, 8, NULL,  1,
+       "open for writing", HFILL }},
+    { &hf_afp_access_deny_read,
+      { "deny read",         "afp.access.deny_read",
+       FT_BOOLEAN, 8, NULL,  1,
+       "deny read", HFILL }},
+    { &hf_afp_access_deny_write,
+      { "deny write",         "afp.access.deny_write",
+       FT_BOOLEAN, 8, NULL,  1,
+       "deny write", HFILL }},
+
+  };
+
+  static gint *ett[] = {
+    &ett_afp,
+       &ett_afp_vol_bitmap,
+       &ett_afp_vol_attribute,
+       &ett_afp_dir_bitmap,
+       &ett_afp_file_bitmap,
+       &ett_afp_enumerate,
+       &ett_afp_enumerate_line,
+       &ett_afp_access_mode,
+  };
+
+  proto_afp = proto_register_protocol("AppleTalk Filing Protocol", "AFP", "afp");
+  proto_register_field_array(proto_afp, hf, array_length(hf));
+  proto_register_subtree_array(ett, array_length(ett));
+
+  register_init_routine( &afp_reinit);
+
+  register_dissector("afp", dissect_afp, proto_afp);
+}
+
+void
+proto_reg_handoff_afp(void)
+{
+  data_handle = find_dissector("data");
+}
+
+/* -------------------------------
+   end
+*/
diff --git a/packet-afp.h b/packet-afp.h
new file mode 100644 (file)
index 0000000..1936902
--- /dev/null
@@ -0,0 +1,97 @@
+/* packet-afp.h
+ * Definitions for packet disassembly structures and routines
+ *
+ * $Id: packet-afp.h,v 1.1 2002/04/25 23:58:02 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef PACKET_AFP_H
+#define PACKET_AFP_H
+
+#define AFP_OK                         0
+#define AFPERR_ACCESS  -5000   /* permission denied */
+#define AFPERR_AUTHCONT        -5001   /* logincont */
+#define AFPERR_BADUAM  -5002   /* uam doesn't exist */
+#define AFPERR_BADVERS -5003   /* bad afp version number */
+#define AFPERR_BITMAP  -5004   /* invalid bitmap */
+#define AFPERR_CANTMOVE -5005   /* can't move file */
+#define AFPERR_DENYCONF        -5006   /* file synchronization locks conflict */
+#define AFPERR_DIRNEMPT        -5007   /* directory not empty */
+#define AFPERR_DFULL   -5008   /* disk full */
+#define AFPERR_EOF             -5009   /* end of file -- catsearch and afp_read */
+#define AFPERR_BUSY            -5010   /* FileBusy */
+#define AFPERR_FLATVOL  -5011   /* volume doesn't support directories */
+#define AFPERR_NOITEM  -5012   /* ItemNotFound */
+#define AFPERR_LOCK     -5013   /* LockErr */
+#define AFPERR_MISC     -5014   /* misc. err */
+#define AFPERR_NLOCK    -5015   /* no more locks */
+#define AFPERR_NOSRVR  -5016   /* no response by server at that address */
+#define AFPERR_EXIST   -5017   /* object already exists */
+#define AFPERR_NOOBJ   -5018   /* object not found */
+#define AFPERR_PARAM   -5019   /* parameter error */
+#define AFPERR_NORANGE  -5020   /* no range lock */
+#define AFPERR_RANGEOVR -5021   /* range overlap */
+#define AFPERR_SESSCLOS -5022   /* session closed */
+#define AFPERR_NOTAUTH -5023   /* user not authenticated */
+#define AFPERR_NOOP            -5024   /* command not supported */
+#define AFPERR_BADTYPE -5025   /* object is the wrong type */
+#define AFPERR_NFILE   -5026   /* too many files open */
+#define AFPERR_SHUTDOWN        -5027   /* server is going down */
+#define AFPERR_NORENAME -5028   /* can't rename */
+#define AFPERR_NODIR   -5029   /* couldn't find directory */
+#define AFPERR_ITYPE   -5030   /* wrong icon type */
+#define AFPERR_VLOCK   -5031   /* volume locked */
+#define AFPERR_OLOCK    -5032   /* object locked */
+#define AFPERR_CTNSHRD  -5033   /* share point contains a share point */
+#define AFPERR_NOID     -5034   /* file thread not found */
+#define AFPERR_EXISTID  -5035   /* file already has an id */
+#define AFPERR_DIFFVOL  -5036   /* different volume */
+#define AFPERR_CATCHNG  -5037   /* catalog has changed */
+#define AFPERR_SAMEOBJ  -5038   /* source file == destination file */
+#define AFPERR_BADID    -5039   /* non-existent file id */
+#define AFPERR_PWDSAME  -5040   /* same password/can't change password */
+#define AFPERR_PWDSHORT -5041   /* password too short */
+#define AFPERR_PWDEXPR  -5042   /* password expired */
+#define AFPERR_INSHRD   -5043   /* folder being shared is inside a shared folder. may be returned by
+                                                                  afpMoveAndRename. */
+#define AFPERR_INTRASH  -5044   /* shared folder in trash. */
+#define AFPERR_PWDCHNG  -5045   /* password needs to be changed */
+#define AFPERR_PWDPOLCY -5046   /* password fails policy check */
+#define AFPERR_USRLOGIN -5047   /* user already logged on */
+
+
+/*
+ * Private data passed from DSI,DDP dissectors to AFP dissector.
+ *                      DSI              DDP
+ * aspinfo.reply     dsi.flags       atp.function == 0x80
+ *         release                   atp.function == 0xc0
+ *         command       command     asp.function
+ *         seq           requestid   atp.tid
+ *         code          code
+ */
+struct aspinfo {
+       guint8  reply;                  /* 0 query  1 reply */
+       guint8  release;
+       guint16 command;                /* 2  6 write */
+       guint16 seq;                    /* sequence number */
+       gint32  code;                   /* error code/ offset NU */
+};
+
+#endif
index f96862feca4b90e6123bf9a8d247c5fc11e18796..5b5f1a97fb565b089a394042d0e6e6a72df195ce 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-atalk.c
  * Routines for Appletalk packet disassembly (DDP, currently).
  *
- * $Id: packet-atalk.c,v 1.63 2002/04/24 06:03:33 guy Exp $
+ * $Id: packet-atalk.c,v 1.64 2002/04/25 23:58:02 guy Exp $
  *
  * Simon Wilkinson <sxw@dcs.ed.ac.uk>
  *
 #include "ppptypes.h"
 #include "aftypes.h"
 #include <epan/atalk-utils.h>
+#include <epan/conversation.h>
+
+#include "packet-afp.h"
+
+static dissector_handle_t afp_handle;
 
 static int proto_llap = -1;
 static int hf_llap_dst = -1;
@@ -60,6 +65,115 @@ static int hf_ddp_dst_socket = -1;
 static int hf_ddp_src_socket = -1;
 static int hf_ddp_type = -1;
 
+
+/* --------------------------------------
+ * ATP protocol parameters
+ * from netatalk/include/atalk/atp.h
+ */
+#define ATP_MAXDATA     (578+4)         /* maximum ATP data size */
+#define ATP_BUFSIZ      587             /* maximum packet size */
+#define ATP_HDRSIZE     5               /* includes DDP type field */
+#define ATP_TRELMASK    0x07            /* mask all but TREL */
+#define ATP_RELTIME     30              /* base release timer (in secs) */
+  
+#define ATP_TREL30      0x0             /* release time codes */
+#define ATP_TREL1M      0x1             /* these are passed in flags of */
+#define ATP_TREL2M      0x2             /* atp_sreq call, and set in the */
+#define ATP_TREL4M      0x3             /* packet control info. */
+#define ATP_TREL8M      0x4
+
+/* flags for ATP options (and control byte)
+*/
+#define ATP_NONE        0
+#define ATP_STS         1 /* (1<<3)          Transaction Status */
+#define ATP_EOM         2 /* (1<<4)          End Of Message */
+#define ATP_XO          4 /* (1<<5)          eXactly Once mode */
+/* function codes
+*/
+#define ATP_FUNCMASK    (3<<6)          /* mask all but function */
+  
+#define ATP_TREQ        1 /* (1<<6)        Trans. REQuest */
+#define ATP_TRESP       2 /* (2<<6)        Trans. RESPonse */
+#define ATP_TREL        3 /* (3<<6)        Trans. RELease */
+
+/* ------------------------- */    
+static dissector_handle_t asp_handle;
+
+static int proto_atp = -1;
+static int hf_atp_ctrlinfo = -1; /* u_int8_t  control information */
+static int hf_atp_function = -1; /* bits 7,6  function */
+static int hf_atp_option   = -1; /* bits 5,4,3  option */
+
+static int hf_atp_bitmap = -1;   /* u_int8_t  bitmap or sequence number */
+static int hf_atp_tid = -1;      /* u_int16_t transaction id. */
+
+/* --------------------------------
+ * from netatalk/include/atalk/ats.h
+ */
+#define ASPFUNC_CLOSE   1
+#define ASPFUNC_CMD     2
+#define ASPFUNC_STAT    3
+#define ASPFUNC_OPEN    4
+#define ASPFUNC_TICKLE  5
+#define ASPFUNC_WRITE   6
+#define ASPFUNC_WRTCONT 7
+#define ASPFUNC_ATTN    8
+
+#define ASP_HDRSIZ      4 
+#define ASPERR_OK       0x0000
+#define ASPERR_BADVERS  0xfbd6
+#define ASPERR_BUFSMALL 0xfbd5
+#define ASPERR_NOSESS   0xfbd4
+#define ASPERR_NOSERV   0xfbd3
+#define ASPERR_PARM     0xfbd2
+#define ASPERR_SERVBUSY 0xfbd1
+#define ASPERR_SESSCLOS 0xfbd0
+#define ASPERR_SIZERR   0xfbcf
+#define ASPERR_TOOMANY  0xfbce
+#define ASPERR_NOACK    0xfbcd
+
+static int proto_asp = -1;
+static int hf_asp_func = -1;
+static int hf_asp_error = -1;
+
+static guint asp_packet_init_count = 200;
+
+typedef struct {
+       guint32 conversation;
+       guint16 seq;
+} asp_request_key;
+typedef struct {
+       guint8  command;
+} asp_request_val;
+static GHashTable *asp_request_hash = NULL;
+static GMemChunk *asp_request_keys = NULL;
+static GMemChunk *asp_request_vals = NULL;
+
+/* Hash Functions */
+static gint  asp_equal (gconstpointer v, gconstpointer v2)
+{
+       asp_request_key *val1 = (asp_request_key*)v;
+       asp_request_key *val2 = (asp_request_key*)v2;
+
+       if (val1->conversation == val2->conversation &&
+                       val1->seq == val2->seq) {
+               return 1;
+       }
+       return 0;
+}
+
+static guint asp_hash  (gconstpointer v)
+{
+        asp_request_key *asp_key = (asp_request_key*)v;
+        return asp_key->seq;
+}
+
+/* ------------------------------------ */
 static int proto_nbp = -1;
 static int hf_nbp_op = -1;
 static int hf_nbp_info = -1;
@@ -84,6 +198,11 @@ static int hf_rtmp_tuple_range_end = -1;
 static int hf_rtmp_tuple_dist = -1;
 static int hf_rtmp_function = -1;
 
+static gint ett_atp = -1;
+
+static gint ett_atp_info = -1;
+static gint ett_asp = -1;
+
 static gint ett_nbp = -1;
 static gint ett_nbp_info = -1;
 static gint ett_nbp_node = -1;
@@ -149,6 +268,86 @@ static const value_string nbp_op_vals[] = {
   {0, NULL}
 };
 
+static const value_string atp_function_vals[] = {
+  {ATP_TREQ        ,"REQuest"},
+  {ATP_TRESP       ,"RESPonse"},
+  {ATP_TREL        ,"RELease"},
+  {0, NULL}
+};
+
+static const value_string atp_option_vals[] = {
+  {ATP_NONE       ,"None"},
+  {ATP_STS         ,"Transaction Status"},
+  {ATP_EOM         ,"End Of Message"},
+  {ATP_XO          ,"eXactly Once mode"},
+  {0, NULL}
+};
+
+/*
+*/
+static const value_string asp_func_vals[] = {
+  {ASPFUNC_CLOSE,      "CloseSession" },
+  {ASPFUNC_CMD,                "Command" },
+  {ASPFUNC_STAT,       "GetStatus" },
+  {ASPFUNC_OPEN,       "OpenSession" },
+  {ASPFUNC_TICKLE,     "Tickle" },
+  {ASPFUNC_WRITE,      "Write" },
+  {ASPFUNC_WRTCONT, "Write Cont" },
+  {ASPFUNC_ATTN,       "Attention" },
+  {0,                  NULL } };
+
+static const value_string asp_error_vals[] = {
+  {AFP_OK                      , "success"},
+  {AFPERR_ACCESS       , "permission denied" },
+  {AFPERR_AUTHCONT     , "logincont" },
+  {AFPERR_BADUAM       , "uam doesn't exist" },
+  {AFPERR_BADVERS      , "bad afp version number" },
+  {AFPERR_BITMAP       , "invalid bitmap" },
+  {AFPERR_CANTMOVE     , "can't move file" },
+  {AFPERR_DENYCONF     , "file synchronization locks conflict" },
+  {AFPERR_DIRNEMPT     , "directory not empty" },
+  {AFPERR_DFULL                , "disk full" },
+  {AFPERR_EOF          , "end of file" },
+  {AFPERR_BUSY         , "FileBusy" },
+  {AFPERR_FLATVOL      , "volume doesn't support directories" },
+  {AFPERR_NOITEM       , "ItemNotFound" },
+  {AFPERR_LOCK         , "LockErr" },
+  {AFPERR_MISC         , "misc. err" },
+  {AFPERR_NLOCK        , "no more locks" },
+  {AFPERR_NOSRVR       , "no response by server at that address" },
+  {AFPERR_EXIST                , "object already exists" },
+  {AFPERR_NOOBJ                , "object not found" },
+  {AFPERR_PARAM                , "parameter error" },
+  {AFPERR_NORANGE      , "no range lock" },
+  {AFPERR_RANGEOVR     , "range overlap" },
+  {AFPERR_SESSCLOS     , "session closed" },
+  {AFPERR_NOTAUTH      , "user not authenticated" },
+  {AFPERR_NOOP         , "command not supported" },
+  {AFPERR_BADTYPE      , "object is the wrong type" },
+  {AFPERR_NFILE                , "too many files open" },
+  {AFPERR_SHUTDOWN     , "server is going down" },
+  {AFPERR_NORENAME     , "can't rename" },
+  {AFPERR_NODIR                , "couldn't find directory" },
+  {AFPERR_ITYPE                , "wrong icon type" },
+  {AFPERR_VLOCK                , "volume locked" },
+  {AFPERR_OLOCK        , "object locked" },
+  {AFPERR_CTNSHRD      , "share point contains a share point" },
+  {AFPERR_NOID         , "file thread not found" },
+  {AFPERR_EXISTID      , "file already has an id" },
+  {AFPERR_DIFFVOL      , "different volume" },
+  {AFPERR_CATCHNG      , "catalog has changed" },
+  {AFPERR_SAMEOBJ      , "source file == destination file" },
+  {AFPERR_BADID        , "non-existent file id" },
+  {AFPERR_PWDSAME      , "same password/can't change password" },
+  {AFPERR_PWDSHORT     , "password too short" },
+  {AFPERR_PWDEXPR      , "password expired" },
+  {AFPERR_INSHRD       , "folder being shared is inside a shared folder." },
+  {AFPERR_INTRASH   , "shared folder in trash." },
+  {AFPERR_PWDCHNG   , "password needs to be changed" },
+  {AFPERR_PWDPOLCY  , "password fails policy check" },
+  {AFPERR_USRLOGIN  , "user already logged on" },
+  {0,                  NULL } };
+
 /*
  * XXX - do this with an FT_UINT_STRING?
  * Unfortunately, you can't extract from an FT_UINT_STRING the string,
@@ -367,6 +566,179 @@ dissect_nbp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
   return;
 }
 
+/* ----------------------------- 
+   FIXME : need desegmentation 
+   atp.function == 0x80 (response)
+   atp.bitmap 0 .. 7
+   until atp.option == 0x10 (end of message)
+*/
+static void
+dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+  proto_tree *atp_tree;
+  proto_item *ti;
+  proto_tree *atp_info_tree;
+  proto_item *info_item;
+  int offset = 0;
+  guint8 ctrlinfo;
+  guint op;
+  guint16 tid;
+  struct aspinfo aspinfo;
+  tvbuff_t   *new_tvb;
+  int len;
+  
+  if (check_col(pinfo->cinfo, COL_PROTOCOL))
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATP");
+  if (check_col(pinfo->cinfo, COL_INFO))
+    col_clear(pinfo->cinfo, COL_INFO);
+
+  ctrlinfo = tvb_get_guint8(tvb, offset);
+  op = ctrlinfo >> 6;
+  tid = tvb_get_ntohs(tvb, offset +2);
+
+  if (check_col(pinfo->cinfo, COL_INFO)) {
+    col_add_fstr(pinfo->cinfo, COL_INFO, "%s transaction %d", 
+       val_to_str(op, atp_function_vals, "Unknown (0x%01x)"), 
+       tid);
+  }  
+  aspinfo.reply   = (0x80 == (ctrlinfo & 0xC0))?1:0;
+  aspinfo.release = (0xC0 == (ctrlinfo & 0xC0))?1:0;
+
+  aspinfo.seq = tid;
+  aspinfo.code = 0;
+
+  if (tree) {
+    ti = proto_tree_add_item(tree, proto_atp, tvb, offset, -1, FALSE);
+    atp_tree = proto_item_add_subtree(ti, ett_atp);
+       proto_item_set_len(atp_tree, ATP_HDRSIZE -1);
+
+    info_item = proto_tree_add_item(atp_tree, hf_atp_ctrlinfo, tvb, offset, 1, FALSE);
+    atp_info_tree = proto_item_add_subtree(info_item, ett_atp_info);
+
+       proto_tree_add_item(atp_info_tree, hf_atp_function, tvb, offset, 1, FALSE);
+       proto_tree_add_item(atp_info_tree, hf_atp_option, tvb, offset, 1, FALSE);
+
+       if (!aspinfo.reply) {
+               guint8 bitmap = tvb_get_guint8(tvb, offset +1);
+               guint8 nbe = 0;
+               guint8 t = bitmap;
+               
+               while(t) {
+                       nbe++;
+                       t >>= 1;
+               }
+               proto_tree_add_text(atp_tree, tvb, offset +1, 1, "Bitmap: 0x%02x  %d packet(s) max",
+                                                       bitmap, nbe);
+       }
+    else {
+       proto_tree_add_item(atp_tree, hf_atp_bitmap, tvb, offset +1, 1, FALSE);
+       }
+    proto_tree_add_item(atp_tree, hf_atp_tid, tvb, offset +2, 2, FALSE);
+  }
+
+  pinfo->private_data = &aspinfo;
+  len = tvb_reported_length_remaining(tvb,ATP_HDRSIZE -1);
+  new_tvb = tvb_new_subset(tvb, ATP_HDRSIZE -1,-1,len);
+  call_dissector(asp_handle, new_tvb, pinfo, tree);
+
+  return;
+}
+
+/* ----------------------------- */
+static void
+dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
+{
+  struct aspinfo *aspinfo = pinfo->private_data;
+  int offset = 0;
+  proto_tree *asp_tree = NULL;
+  proto_item *ti;
+  guint8 fn;
+  gint32 error;
+  int len;
+  conversation_t       *conversation;
+  asp_request_key request_key, *new_request_key;
+  asp_request_val *request_val;
+    
+  if (check_col(pinfo->cinfo, COL_PROTOCOL))
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASP");
+  if (check_col(pinfo->cinfo, COL_INFO))
+    col_clear(pinfo->cinfo, COL_INFO);
+
+  conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+               pinfo->srcport, pinfo->destport, 0);
+
+  if (conversation == NULL)
+  {
+       conversation = conversation_new(&pinfo->src, &pinfo->dst,
+                       pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+  }
+
+  request_key.conversation = conversation->index;      
+  request_key.seq = aspinfo->seq;
+
+  request_val = (asp_request_val *) g_hash_table_lookup(
+                                                               asp_request_hash, &request_key);
+
+  if (!request_val && !aspinfo->reply && !aspinfo->release)  {
+        fn = tvb_get_guint8(tvb, offset);
+     new_request_key = g_mem_chunk_alloc(asp_request_keys);
+        *new_request_key = request_key;
+
+        request_val = g_mem_chunk_alloc(asp_request_vals);
+        request_val->command = fn;
+
+        g_hash_table_insert(asp_request_hash, new_request_key,
+                                                               request_val);
+  }
+
+  if (!request_val) { 
+       return;
+  }
+
+  fn = request_val->command;
+
+  if (check_col(pinfo->cinfo, COL_INFO)) {
+       if (aspinfo->reply)
+       col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %d",aspinfo->seq);
+       else if (aspinfo->release)
+       col_add_fstr(pinfo->cinfo, COL_INFO, "Release tid %d",aspinfo->seq);
+    else
+       col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s  tid %d",
+                               val_to_str(fn, asp_func_vals, "Unknown (0x%01x)"), aspinfo->seq);
+  }
+
+  if (tree) {
+    ti = proto_tree_add_item(tree, proto_asp, tvb, offset, -1, FALSE);
+    asp_tree = proto_item_add_subtree(ti, ett_asp);
+    if (!aspinfo->reply && !aspinfo->release) {
+       proto_tree_add_item(asp_tree, hf_asp_func, tvb, offset, 1, FALSE);
+    }
+    else { /* error code */
+               error = tvb_get_ntohl(tvb, offset);
+               if (error <= 0) 
+               proto_tree_add_item(asp_tree, hf_asp_error, tvb, offset, 4, FALSE);
+    }
+  }
+  aspinfo->command = fn;
+  offset += 4;
+  len = tvb_reported_length_remaining(tvb,offset);
+  if (!aspinfo->release &&
+                  (fn == ASPFUNC_CMD || fn  == ASPFUNC_WRITE)) {
+       tvbuff_t   *new_tvb;
+
+       if (len) {
+
+               if (asp_tree)
+                       proto_item_set_len(asp_tree, 4); 
+               new_tvb = tvb_new_subset(tvb, offset,-1,len);
+               call_dissector(afp_handle, new_tvb, pinfo, tree);       
+       }
+  }
+  else {       
+       call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree); 
+  }
+}
+
+
 static void
 dissect_ddp_short(tvbuff_t *tvb, packet_info *pinfo, guint8 dnode,
                  guint8 snode, proto_tree *tree)
@@ -560,6 +932,29 @@ dissect_llap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   call_dissector(data_handle,new_tvb, pinfo, tree);
 }
 
+static void asp_reinit( void)
+{
+
+       if (asp_request_hash)
+               g_hash_table_destroy(asp_request_hash);
+       if (asp_request_keys)
+               g_mem_chunk_destroy(asp_request_keys);
+       if (asp_request_vals)
+               g_mem_chunk_destroy(asp_request_vals);
+
+       asp_request_hash = g_hash_table_new(asp_hash, asp_equal);
+
+       asp_request_keys = g_mem_chunk_new("asp_request_keys",
+               sizeof(asp_request_key),
+               asp_packet_init_count * sizeof(asp_request_key),
+               G_ALLOC_AND_FREE);
+       asp_request_vals = g_mem_chunk_new("asp_request_vals",
+               sizeof(asp_request_val),
+               asp_packet_init_count * sizeof(asp_request_val),
+               G_ALLOC_AND_FREE);
+
+}
+
 void
 proto_register_atalk(void)
 {
@@ -682,16 +1077,50 @@ proto_register_atalk(void)
                VALS(rtmp_function_vals), 0x0, "Request Function", HFILL }}
   };
 
+  static hf_register_info hf_atp[] = {
+    { &hf_atp_ctrlinfo,
+      { "control info",                "atp.ctrlinfo", FT_UINT8,  BASE_HEX, 
+               NULL, 0, "control info", HFILL }},
+
+    { &hf_atp_function,
+      { "function",            "atp.function", FT_UINT8,  BASE_DEC, 
+               VALS(atp_function_vals), 0xC0, "function code", HFILL }},
+
+    
+    { &hf_atp_option,
+      { "option",              "atp.option",   FT_UINT8,  BASE_DEC, 
+               VALS(atp_option_vals), 0x38, "options", HFILL }},
+
+    { &hf_atp_bitmap,
+      { "Bitmap",              "atp.bitmap",   FT_UINT8,  BASE_HEX, 
+               NULL, 0x0, "bitmap or sequence number", HFILL }},
+    { &hf_atp_tid,
+      { "tid",         "atp.tid",      FT_UINT16,  BASE_DEC, 
+               NULL, 0,   "transaction id", HFILL }},
+  };
+
+  static hf_register_info hf_asp[] = {
+    { &hf_asp_func,
+      { "asp function",                "asp.function", FT_UINT8,  BASE_DEC, 
+               VALS(asp_func_vals), 0, "asp function", HFILL }},
 
+    { &hf_asp_error,
+      { "asp error",           "asp.error",    FT_INT32,  BASE_DEC, 
+               VALS(asp_error_vals), 0, "return error code", HFILL }},
+  };
+  
   static gint *ett[] = {
        &ett_llap,
        &ett_ddp,
+       &ett_atp,
+       &ett_atp_info,
+       &ett_asp,
        &ett_nbp,
        &ett_nbp_info,
        &ett_nbp_node,
        &ett_pstring,
        &ett_rtmp,
-       &ett_rtmp_tuple
+       &ett_rtmp_tuple,
   };
 
   proto_llap = proto_register_protocol("LocalTalk Link Access Protocol", "LLAP", "llap");
@@ -703,6 +1132,12 @@ proto_register_atalk(void)
   proto_nbp = proto_register_protocol("Name Binding Protocol", "NBP", "nbp");
   proto_register_field_array(proto_nbp, hf_nbp, array_length(hf_nbp));
 
+  proto_atp = proto_register_protocol("AppleTalk Transaction Protocol packet", "ATP", "atp");
+  proto_register_field_array(proto_atp, hf_atp, array_length(hf_atp));
+
+  proto_asp = proto_register_protocol("AppleTalk Stream Protocol", "ASP", "asp");
+  proto_register_field_array(proto_asp, hf_asp, array_length(hf_asp));
+
   proto_rtmp = proto_register_protocol("Routing Table Maintenance Protocol",
                                       "RTMP", "rtmp");
   proto_register_field_array(proto_rtmp, hf_rtmp, array_length(hf_rtmp));
@@ -718,6 +1153,7 @@ void
 proto_reg_handoff_atalk(void)
 {
   dissector_handle_t ddp_handle, nbp_handle, rtmp_request_handle;
+  dissector_handle_t atp_handle;
   dissector_handle_t rtmp_data_handle, llap_handle;
 
   ddp_handle = create_dissector_handle(dissect_ddp, proto_ddp);
@@ -729,6 +1165,11 @@ proto_reg_handoff_atalk(void)
   nbp_handle = create_dissector_handle(dissect_nbp, proto_nbp);
   dissector_add("ddp.type", DDP_NBP, nbp_handle);
 
+  atp_handle = create_dissector_handle(dissect_atp, proto_atp);
+  dissector_add("ddp.type", DDP_ATP, atp_handle);
+
+  asp_handle = create_dissector_handle(dissect_asp, proto_asp);
+
   rtmp_request_handle = create_dissector_handle(dissect_rtmp_request, proto_rtmp);
   rtmp_data_handle = create_dissector_handle(dissect_rtmp_data, proto_rtmp);
   dissector_add("ddp.type", DDP_RTMPREQ, rtmp_request_handle);
@@ -737,5 +1178,8 @@ proto_reg_handoff_atalk(void)
   llap_handle = create_dissector_handle(dissect_llap, proto_llap);
   dissector_add("wtap_encap", WTAP_ENCAP_LOCALTALK, llap_handle);
 
+  register_init_routine( &asp_reinit);
+
+  afp_handle = find_dissector("afp");
   data_handle = find_dissector("data");
 }
index b80e577d3013a2427d8fb7c4d89bbf32bc23ddbc..cb2d5f971dc9206b67f412dc4b2f96deee50836c 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for dsi packet dissection
  * Copyright 2001, Randy McEoin <rmceoin@pe.com>
  *
- * $Id: packet-dsi.c,v 1.11 2002/04/22 08:50:49 guy Exp $
+ * $Id: packet-dsi.c,v 1.12 2002/04/25 23:58:02 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -45,6 +45,8 @@
 #include "prefs.h"
 #include "packet-frame.h"
 
+#include "packet-afp.h"
+
 /* The information in this module (DSI) comes from:
 
   AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
@@ -79,9 +81,12 @@ static gint ett_dsi = -1;
 static gboolean dsi_desegment = TRUE;
 
 static dissector_handle_t data_handle;
+static dissector_handle_t afp_handle;
 
 #define TCP_PORT_DSI                   548
 
+#define DSI_BLOCKSIZ            16
+
 /* DSI flags */
 #define DSIFL_REQUEST    0x00
 #define DSIFL_REPLY      0x01
@@ -122,6 +127,7 @@ dissect_dsi_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        gint32          dsi_code;
        guint32         dsi_length;
        guint32         dsi_reserved;
+       struct          aspinfo aspinfo;
  
        if (check_col(pinfo->cinfo, COL_PROTOCOL))
                col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI");
@@ -162,7 +168,28 @@ dissect_dsi_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        "Length: %u bytes", dsi_length);
                proto_tree_add_uint(dsi_tree, hf_dsi_reserved, tvb,
                        12, 4, dsi_reserved);
-               call_dissector(data_handle,tvb_new_subset(tvb, 16,-1,tvb_reported_length_remaining(tvb,16)), pinfo, dsi_tree);
+       }
+       else 
+               dsi_tree = tree;
+
+       if (dsi_command == DSIFUNC_CMD || dsi_command == DSIFUNC_WRITE) {
+               tvbuff_t   *new_tvb;
+               int len = tvb_reported_length_remaining(tvb,DSI_BLOCKSIZ);
+
+               if (len) {
+                       aspinfo.reply = dsi_flags & 1;
+                       aspinfo.command = dsi_command;
+                       aspinfo.seq = dsi_requestid;
+                       aspinfo.code = dsi_code;
+                       pinfo->private_data = &aspinfo;
+                       proto_item_set_len(dsi_tree, DSI_BLOCKSIZ);
+
+                       new_tvb = tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,len);
+                       call_dissector(afp_handle, new_tvb, pinfo, tree);
+               }
+       }
+       else if (tree) {        
+               call_dissector(data_handle,tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,tvb_reported_length_remaining(tvb,DSI_BLOCKSIZ)), pinfo, dsi_tree); 
        }
 }
 
@@ -339,4 +366,5 @@ proto_reg_handoff_dsi(void)
   dissector_add("tcp.port", TCP_PORT_DSI, dsi_handle);
 
   data_handle = find_dissector("data");
+  afp_handle = find_dissector("afp");
 }