Update manuf to current IEEE entries.
[obnox/wireshark/wip.git] / packet-afp.c
index 7796c2cb743f742e04e535fc5393d6eba5237469..e438cea9c2975c5de0cd46de2ea6e10c75ecc222 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for afp packet dissection
  * Copyright 2002, Didier Gautheron <dgautheron@magic.fr>
  *
- * $Id: packet-afp.c,v 1.14 2002/05/03 21:25:43 guy Exp $
+ * $Id: packet-afp.c,v 1.28 2003/02/12 21:50:31 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * 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.
 
 #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
 
 
   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
-  
+  AFP3.1.pdf from http://www.apple.com
+
   The netatalk source code by Wesley Craig & Adrian Sun
        http://netatalk.sf.net
 */
 #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) 
+#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 AFP_GETFLDRPARAM       34
 #define AFP_SETFLDRPARAM       35
 #define AFP_CHANGEPW           36
+#define AFP_GETUSERINFO                37
 #define AFP_GETSRVRMSG         38
 #define AFP_CREATEID           39
 #define AFP_DELETEID           40
 #define AFP_GETCMT          58
 #define AFP_ADDICON        192
 
+/* AFP 3.0 new calls */
+#define AFP_BYTELOCK_EXT       59
+#define AFP_CATSEARCH_EXT      67
+#define AFP_ENUMERATE_EXT      66
+#define AFP_READ_EXT           60
+#define AFP_WRITE_EXT          61
+#define AFP_LOGIN_EXT          63
+#define AFP_GETSESSTOKEN       64
+#define AFP_DISCTOLDSESS        65
+
+/* AFP 3.1 new calls */
+#define AFP_ENUMERATE_EXT2     68
+
 /* ----------------------------- */
 static int proto_afp = -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_AFPVersion = -1;
+static int hf_afp_UAM = -1;
+static int hf_afp_user = -1;
+static int hf_afp_passwd = -1;
+static int hf_afp_random = -1;
+
+static int hf_afp_login_flags = -1;
 static int hf_afp_pad = -1;
 
+static int hf_afp_user_type = -1;
+static int hf_afp_user_len = -1;
+static int hf_afp_user_name = -1;
+
 static int hf_afp_vol_flag_passwd       = -1;
 static int hf_afp_vol_flag_unix_priv = -1;
 static int hf_afp_server_time           = -1;
@@ -205,10 +204,13 @@ static int hf_afp_dir_GroupID    = -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_start_index32 = -1;
 static int hf_afp_max_reply_size = -1;
+static int hf_afp_max_reply_size32 = -1;
 static int hf_afp_file_flag = -1;
 static int hf_afp_create_flag = -1;
 static int hf_afp_struct_size = -1;
+static int hf_afp_struct_size16 = -1;
 
 static int hf_afp_cat_count            = -1;
 static int hf_afp_cat_req_matches   = -1;
@@ -229,6 +231,8 @@ static int hf_afp_unix_privs_ua_permissions = -1;
 static int hf_afp_path_type = -1;
 static int hf_afp_path_len = -1;
 static int hf_afp_path_name = -1;
+static int hf_afp_path_unicode_hint = -1;
+static int hf_afp_path_unicode_len = -1;
 
 static int hf_afp_flag         = -1;
 static int hf_afp_dt_ref       = -1;
@@ -279,6 +283,21 @@ static gint ett_afp_cat_r_bitmap   = -1;
 static gint ett_afp_cat_spec           = -1;
 static gint ett_afp_vol_did    = -1;
 
+/* AFP 3.0 parameters */
+static gint hf_afp_lock_offset64       = -1;
+static gint hf_afp_lock_len64          = -1;
+static gint hf_afp_lock_range_start64  = -1;
+
+static int hf_afp_offset64             = -1;
+static int hf_afp_rw_count64           = -1;
+
+static int hf_afp_last_written64       = -1;
+
+static int hf_afp_ofork_len64           = -1;
+static int hf_afp_session_token_type   = -1;
+static int hf_afp_session_token_len    = -1;
+static int hf_afp_session_token                = -1;
+
 static dissector_handle_t data_handle;
 
 static const value_string vol_signature_vals[] = {
@@ -323,6 +342,7 @@ static const value_string CommandCode_vals[] = {
   {AFP_GETFLDRPARAM,   "FPGetFileDirParms" },
   {AFP_SETFLDRPARAM,   "FPSetFileDirParms" },
   {AFP_CHANGEPW,       "FPChangePassword" },
+  {AFP_GETUSERINFO,     "FPGetUserInfo" },
   {AFP_GETSRVRMSG,     "FPGetSrvrMsg" },
   {AFP_CREATEID,       "FPCreateID" },
   {AFP_DELETEID,       "FPDeleteID" },
@@ -339,13 +359,126 @@ static const value_string CommandCode_vals[] = {
   {AFP_ADDCMT,         "FPAddComment" },
   {AFP_RMVCMT,         "FPRemoveComment" },
   {AFP_GETCMT,         "FPGetComment" },
+  {AFP_BYTELOCK_EXT,   "FPByteRangeLockExt" },
+  {AFP_CATSEARCH_EXT,  "FPCatSearchExt" },
+  {AFP_ENUMERATE_EXT,  "FPEnumerateExt" },
+  {AFP_ENUMERATE_EXT2, "FPEnumerateExt2" },
+  {AFP_READ_EXT,       "FPReadExt" },
+  {AFP_WRITE_EXT,      "FPWriteExt" },
+  {AFP_LOGIN_EXT,      "FPLoginExt" },
+  {AFP_GETSESSTOKEN,   "FPGetSessionToken" },
+  {AFP_DISCTOLDSESS,    "FPDisconnectOldSession" },
   {AFP_ADDICON,                "FPAddIcon" },
   {0,                   NULL }
 };
 
+static const value_string unicode_hint_vals[] = {
+   { 0,           "MacRoman" },
+   { 1,           "MacJapanese" },
+   { 2,           "MacChineseTrad" },
+   { 3,           "MacKorean" },
+   { 4,           "MacArabic" },
+   { 5,           "MacHebrew" },
+   { 6,           "MacGreek" },
+   { 7,           "MacCyrillic" },
+   { 9,           "MacDevanagari" },
+   { 10,   "MacGurmukhi" },
+   { 11,   "MacGujarati" },
+   { 12,   "MacOriya" },
+   { 13,   "MacBengali" },
+   { 14,   "MacTamil" },
+   { 15,   "MacTelugu" },
+   { 16,   "MacKannada" },
+   { 17,   "MacMalayalam" },
+   { 18,   "MacSinhalese" },
+   { 19,   "MacBurmese" },
+   { 20,   "MacKhmer" },
+   { 21,   "MacThai" },
+   { 22,   "MacLaotian" },
+   { 23,   "MacGeorgian" },
+   { 24,   "MacArmenian" },
+   { 25,   "MacChineseSimp" },
+   { 26,   "MacTibetan" },
+   { 27,   "MacMongolian" },
+   { 28,   "MacEthiopic" },
+   { 29,   "MacCentralEurRoman" },
+   { 30,   "MacVietnamese" },
+   { 31,   "MacExtArabic" },
+   { 33,   "MacSymbol" },
+   { 34,   "MacDingbats" },
+   { 35,   "MacTurkish" },
+   { 36,   "MacCroatian" },
+   { 37,   "MacIcelandic" },
+   { 38,   "MacRomanian" },
+   { 39,   "MacCeltic" },
+   { 40,   "MacGaelic" },
+   { 41,   "MacKeyboardGlyphs" },
+   { 126,  "MacUnicode" },
+   { 140,  "MacFarsi" },
+   { 152,  "MacUkrainian" },
+   { 236,  "MacInuit" },
+   { 252,  "MacVT100" },
+   { 255,  "MacHFS" },
+   { 256,  "UnicodeDefault" },
+/* { 257,  "UnicodeV1_1" },  */
+   { 257,  "ISO10646_1993" },
+   { 259,  "UnicodeV2_0" },
+   { 259,  "UnicodeV2_1" },
+   { 260,  "UnicodeV3_0" },
+   { 513,  "ISOLatin1" },
+   { 514,  "ISOLatin2" },
+   { 515,  "ISOLatin3" },
+   { 516,  "ISOLatin4" },
+   { 517,  "ISOLatinCyrillic" },
+   { 518,  "ISOLatinArabic" },
+   { 519,  "ISOLatinGreek" },
+   { 520,  "ISOLatinHebrew" },
+   { 521,  "ISOLatin5" },
+   { 522,  "ISOLatin6" },
+   { 525,  "ISOLatin7" },
+   { 526,  "ISOLatin8" },
+   { 527,  "ISOLatin9" },
+   { 1024, "DOSLatinUS" },
+   { 1029, "DOSGreek" },
+   { 1030, "DOSBalticRim" },
+   { 1040, "DOSLatin1" },
+   { 1041, "DOSGreek1" },
+   { 1042, "DOSLatin2" },
+   { 1043, "DOSCyrillic" },
+   { 1044, "DOSTurkish" },
+   { 1045, "DOSPortuguese" },
+   { 1046, "DOSIcelandic" },
+   { 1047, "DOSHebrew" },
+   { 1048, "DOSCanadianFrench" },
+   { 1049, "DOSArabic" },
+   { 1050, "DOSNordic" },
+   { 1051, "DOSRussian" },
+   { 1052, "DOSGreek2" },
+   { 1053, "DOSThai" },
+   { 1056, "DOSJapanese" },
+   { 1057, "DOSChineseSimplif" },
+   { 1058, "DOSKorean" },
+   { 1059, "DOSChineseTrad" },
+   { 1280, "WindowsLatin1" },
+/* { 1280, "WindowsANSI" }, */
+   { 1281, "WindowsLatin2" },
+   { 1282, "WindowsCyrillic" },
+   { 1283, "WindowsGreek" },
+   { 1284, "WindowsLatin5" },
+   { 1285, "WindowsHebrew" },
+   { 1286, "WindowsArabic" },
+   { 1287, "WindowsBalticRim" },
+   { 1288, "WindowsVietnamese" },
+   { 1296, "WindowsKoreanJohab" },
+   { 1536, "US_ASCII" },
+   { 1568, "JIS_X0201_76" },
+   { 1569, "JIS_X0208_83" },
+   { 1570, "JIS_X0208_90" },
+   { 0,           NULL }
+};
 
 /* volume bitmap
-  from Apple AFP3.0.pdf 
+  from Apple AFP3.0.pdf
   Table 1-2 p. 20
 */
 #define kFPVolAttributeBit             (1 << 0)
@@ -440,6 +573,11 @@ static int hf_afp_file_attribute_DeleteInhibit = -1;
 static int hf_afp_file_attribute_CopyProtect   = -1;
 static int hf_afp_file_attribute_SetClear      = -1;
 
+static int hf_afp_map_name_type = -1;
+static int hf_afp_map_name     = -1;
+static int hf_afp_map_id       = -1;
+static int hf_afp_map_id_type  = -1;
+
 static const value_string vol_bitmap_vals[] = {
   {kFPVolAttributeBit,          "VolAttribute"},
   {kFPVolSignatureBit,         "VolSignature"},
@@ -466,8 +604,22 @@ static const value_string path_type_vals[] = {
   {3,  "Unicode names" },
   {0,  NULL } };
 
+static const value_string map_name_type_vals[] = {
+  {1,  "Unicode user name to a user ID" },
+  {2,  "Unicode group name to a group ID" },
+  {3,  "Macintosh roman user name to a user ID" },
+  {4,  "Macintosh roman group name to a group ID" },
+  {0,  NULL } };
+
+static const value_string map_id_type_vals[] = {
+  {1,  "User ID to a Macintosh roman user name" },
+  {2,  "Group ID to a Macintosh roman group name" },
+  {3,  "User ID to a unicode user name" },
+  {4,  "Group ID to a unicode group name" },
+  {0,  NULL } };
+
 /*
-  volume attribute from Apple AFP3.0.pdf 
+  volume attribute from Apple AFP3.0.pdf
   Table 1-3 p. 22
 */
 #define kReadOnly                              (1 << 0)
@@ -477,9 +629,11 @@ static const value_string path_type_vals[] = {
 #define kSupportsBlankAccessPrivs              (1 << 4)
 #define kSupportsUnixPrivs                     (1 << 5)
 #define kSupportsUTF8Names                     (1 << 6)
+/* AFP3.1 */
+#define kNoNetworkUserIDs                      (1 << 7)
 
 /*
-  directory bitmap from Apple AFP3.0.pdf 
+  directory bitmap from Apple AFP3.0.pdf
   Table 1-4 p. 31
 */
 #define kFPAttributeBit                (1 << 0)
@@ -517,7 +671,7 @@ static const value_string path_type_vals[] = {
 
 #define AR_U_SEARCH    (1 << 24)   /* user has search access */
 #define AR_U_READ      (1 << 25)   /* user has read access */
-#define AR_U_WRITE     (1 << 26)       /* user has write access */ 
+#define AR_U_WRITE     (1 << 26)       /* user has write access */
 
 #define AR_BLANK       (1 << 28)       /* Blank Access Privileges (use parent dir privileges) */
 #define AR_U_OWN       (1 << 31)       /* user is the owner */
@@ -538,8 +692,22 @@ static int hf_afp_dir_ar_u_write  = -1;
 static int hf_afp_dir_ar_blank    = -1;
 static int hf_afp_dir_ar_u_own    = -1;
 
+static int hf_afp_user_flag       = -1;
+static int hf_afp_user_ID         = -1;
+static int hf_afp_group_ID        = -1;
+static int hf_afp_user_bitmap     = -1;
+static int hf_afp_user_bitmap_UID = -1;
+static int hf_afp_user_bitmap_GID = -1;
+
+static gint ett_afp_user_bitmap   = -1;
+
+static const value_string user_flag_vals[] = {
+  {0,  "Use user ID" },
+  {1,  "Default user" },
+  {0,  NULL } };
+
 /*
-  file bitmap AFP3.0.pdf 
+  file bitmap AFP3.0.pdf
   Table 1-7 p. 36
 same as dir
 kFPAttributeBit                (bit 0)
@@ -564,7 +732,7 @@ kFPUTF8NameBit                      (bit 13)
 #define kFPUnixPrivsBit_file           (1 << 15)       /* :( */
 
 /*
-  file attribute AFP3.0.pdf 
+  file attribute AFP3.0.pdf
   Table 1-8 p. 37
 */
 #define kFPInvisibleBit                        (1 << 0)
@@ -589,27 +757,30 @@ kFPUTF8NameBit                    (bit 13)
 /* 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;
 
+static guint Vol;      /* volume */
+static guint Did;      /* parent directory ID */
+
 /* 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;
+       const afp_request_key *val1 = (const afp_request_key*)v;
+       const afp_request_key *val2 = (const afp_request_key*)v2;
 
        if (val1->conversation == val2->conversation &&
                        val1->seq == val2->seq) {
@@ -620,11 +791,11 @@ static gint  afp_equal (gconstpointer v, gconstpointer v2)
 
 static guint afp_hash  (gconstpointer v)
 {
-        afp_request_key *afp_key = (afp_request_key*)v;
+        const afp_request_key *afp_key = (const 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; }
 
@@ -640,7 +811,7 @@ decode_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
                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_Attributes,     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);
@@ -677,19 +848,19 @@ decode_vol_attribute (proto_tree *tree, tvbuff_t *tvb, gint offset)
        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;                                                             
-}                                                                              
 
-/* -------------------------- 
+       return bitmap;
+}
+
+/* --------------------------
        cf AFP3.0.pdf page 38
        date  are number of seconds from 12:00am on 01.01.2000 GMT
        backup : 0x8000000 not set
-       from netatalk adouble.h 
+       from netatalk adouble.h
 */
-#define DATE_NOT_SET         0x80000000 
-#define AD_DATE_DELTA         946684800  
-#define AD_DATE_TO_UNIX(x)    (x + AD_DATE_DELTA)  
+#define DATE_NOT_SET         0x80000000
+#define AD_DATE_DELTA         946684800
+#define AD_DATE_TO_UNIX(x)    (x + AD_DATE_DELTA)
 static guint32
 print_date(proto_tree *tree,int id, tvbuff_t *tvb, gint offset)
 {
@@ -782,7 +953,7 @@ decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
                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_Attributes      , tvb, offset, 2,FALSE);  
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_Attributes      , 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);
@@ -792,7 +963,7 @@ decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
        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_DataForkLen    , tvb, offset, 2,FALSE);   
+       proto_tree_add_item(sub_tree, hf_afp_file_bitmap_DataForkLen    , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_file_bitmap_RsrcForkLen    , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtDataForkLen , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LaunchLimit    , tvb, offset, 2,FALSE);
@@ -805,21 +976,21 @@ decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
 }
 
 /* -------------------------- */
-static guint16 
+static guint16
 decode_file_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset, int shared)
 {
        proto_tree *sub_tree = NULL;
        proto_item *item;
        guint16         attribute;
-       
+
        attribute = tvb_get_ntohs(tvb, offset);
        if (tree) {
                item = proto_tree_add_text(tree, tvb, offset, 2,
                                        "File Attributes: 0x%04x", attribute);
                sub_tree = proto_item_add_subtree(item, ett_afp_file_attribute);
        }
-       proto_tree_add_item(sub_tree, hf_afp_file_attribute_Invisible    , tvb, offset, 2,FALSE);  
-       if (!shared) 
+       proto_tree_add_item(sub_tree, hf_afp_file_attribute_Invisible    , tvb, offset, 2,FALSE);
+       if (!shared)
                proto_tree_add_item(sub_tree, hf_afp_file_attribute_MultiUser    , tvb, offset, 2,FALSE);
 
        proto_tree_add_item(sub_tree, hf_afp_file_attribute_System       , tvb, offset, 2,FALSE);
@@ -827,13 +998,14 @@ decode_file_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset, int shared)
        if (!shared) {
                proto_tree_add_item(sub_tree, hf_afp_file_attribute_DAlreadyOpen , tvb, offset, 2,FALSE);
                proto_tree_add_item(sub_tree, hf_afp_file_attribute_RAlreadyOpen , tvb, offset, 2,FALSE);
-               proto_tree_add_item(sub_tree, hf_afp_file_attribute_WriteInhibit , tvb, offset, 2,FALSE);
        }
+       /* writeinhibit is file only but Macs are setting it with FPSetFileDirParms too */
+       proto_tree_add_item(sub_tree, hf_afp_file_attribute_WriteInhibit , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_file_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_file_attribute_RenameInhibit, tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_file_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
 
-       if (!shared) 
+       if (!shared)
                proto_tree_add_item(sub_tree, hf_afp_file_attribute_CopyProtect  , tvb, offset, 2,FALSE);
 
        proto_tree_add_item(sub_tree, hf_afp_file_attribute_SetClear     , tvb, offset, 2,FALSE);
@@ -851,26 +1023,26 @@ decode_access_rights (proto_tree *tree, tvbuff_t *tvb, int hf, gint offset)
                item = proto_tree_add_item(tree, hf, tvb, offset, 4, FALSE);
                sub_tree = proto_item_add_subtree(item, ett_afp_dir_ar);
 
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_search, tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_read  , tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_write , tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_search, tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_read  , tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_write , tvb, offset, 4,   FALSE);
 
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_search, tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_read  , tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_write , tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_search, tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_read  , tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_write , tvb, offset, 4,   FALSE);
 
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_search, tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_read  , tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_write , tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_search, tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_read  , tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_write , tvb, offset, 4,   FALSE);
 
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_search, tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_read  , tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_write , tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_search, tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_read  , tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_write , tvb, offset, 4,   FALSE);
 
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_blank   , tvb, offset, 4,   FALSE);  
-               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_own   , tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_blank   , tvb, offset, 4,   FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_own   , tvb, offset, 4,   FALSE);
        }
-}              
+}
 
 static void
 decode_unix_privs (proto_tree *tree, tvbuff_t *tvb, gint offset)
@@ -890,13 +1062,59 @@ decode_unix_privs (proto_tree *tree, tvbuff_t *tvb, gint offset)
        }
 }
 
+/* -------------------------- */
+static gint
+parse_long_filename(proto_tree *tree, tvbuff_t *tvb, gint offset, gint org_offset)
+{
+       guint16 lnameoff;
+       gint tp_ofs = 0;
+       guint8 len;
+
+       lnameoff = tvb_get_ntohs(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_long_name_offset,tvb, offset, 2, FALSE);
+       if (lnameoff) {
+               tp_ofs = lnameoff +org_offset;
+               len = tvb_get_guint8(tvb, tp_ofs);
+               proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
+               tp_ofs++;
+               proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
+               tp_ofs += len;
+       }
+       return tp_ofs;
+}
+
+/* -------------------------- */
+static gint
+parse_UTF8_filename(proto_tree *tree, tvbuff_t *tvb, gint offset, gint org_offset)
+{
+       guint16 unameoff;
+       gint tp_ofs = 0;
+       guint16 len;
+
+       unameoff = tvb_get_ntohs(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_unicode_name_offset,tvb, offset, 2, FALSE);
+       offset += 2;
+       PAD(4);
+       if (unameoff) {
+               tp_ofs = unameoff +org_offset;
+               proto_tree_add_item( tree, hf_afp_path_unicode_hint, tvb, tp_ofs, 4,FALSE);
+               tp_ofs += 4;
+
+               len = tvb_get_ntohs(tvb, tp_ofs);
+               proto_tree_add_item( tree, hf_afp_path_unicode_len, tvb, tp_ofs, 2,FALSE);
+               tp_ofs += 2;
+
+               proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
+               tp_ofs += len;
+       }
+       return tp_ofs;
+}
+
 /* -------------------------- */
 static gint
 parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap, int shared)
 {
-       guint16 lnameoff = 0;
        guint16 snameoff = 0;
-       guint16 unameoff = 0;
        gint    max_offset = 0;
 
        gint    org_offset = offset;
@@ -927,20 +1145,12 @@ parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap,
        }
        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_long_name_offset,tvb, offset, 2, FALSE);
-                       len = tvb_get_guint8(tvb, tp_ofs);
-                       proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
-                       tp_ofs++;
-                       proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
-                       tp_ofs += len;
-                       max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
-               }
+               tp_ofs = parse_long_filename(tree, tvb, offset, org_offset);
+               max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+
                offset += 2;
+
        }
        if ((bitmap & kFPShortNameBit)) {
                snameoff = tvb_get_ntohs(tvb, offset);
@@ -956,7 +1166,7 @@ parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap,
                proto_tree_add_item(tree, hf_afp_file_DataForkLen, tvb, offset, 4,FALSE);
                offset += 4;
        }
-       
+
        if ((bitmap & kFPRsrcForkLenBit)) {
                proto_tree_add_item(tree, hf_afp_file_RsrcForkLen, tvb, offset, 4,FALSE);
                offset += 4;
@@ -972,9 +1182,11 @@ parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap,
        }
 
        if ((bitmap & kFPUTF8NameBit)) {
-               unameoff = tvb_get_ntohs(tvb, offset);
-               proto_tree_add_item(tree, hf_afp_unicode_name_offset,tvb, offset, 2, FALSE);
-               offset += 2;
+               gint tp_ofs;
+
+               tp_ofs = parse_UTF8_filename(tree, tvb, offset, org_offset);
+               max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+               offset += 6;
        }
 
        if ((bitmap & kFPExtRsrcForkLenBit)) {
@@ -998,20 +1210,20 @@ parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap,
 }
 
 /* -------------------------- */
-static guint16 
+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_Attributes      , tvb, offset, 2,FALSE);  
+
+       proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_Attributes      , 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);
@@ -1031,20 +1243,20 @@ decode_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
 }
 
 /* -------------------------- */
-static guint16 
+static guint16
 decode_dir_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset)
 {
        proto_tree *sub_tree = NULL;
        proto_item *item;
        guint16         attribute;
-       
+
        attribute = tvb_get_ntohs(tvb, offset);
        if (tree) {
                item = proto_tree_add_text(tree, tvb, offset, 2,
                                        "Directory Attributes: 0x%04x", attribute);
                sub_tree = proto_item_add_subtree(item, ett_afp_dir_attribute);
        }
-       proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Invisible    , tvb, offset, 2,FALSE);  
+       proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Invisible    , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_dir_attribute_IsExpFolder  , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_dir_attribute_System       , tvb, offset, 2,FALSE);
        proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Mounted      , tvb, offset, 2,FALSE);
@@ -1060,9 +1272,7 @@ decode_dir_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset)
 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;
@@ -1093,18 +1303,10 @@ parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
        }
        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_long_name_offset,tvb, offset, 2, FALSE);
-                       len = tvb_get_guint8(tvb, tp_ofs);
-                       proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs,  1,FALSE);
-                       tp_ofs++;
-                       proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
-                       tp_ofs += len;
-                       max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
-               }
+
+               tp_ofs = parse_long_filename(tree, tvb, offset, org_offset);
+               max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+
                offset += 2;
        }
        if ((bitmap & kFPShortNameBit)) {
@@ -1121,11 +1323,11 @@ parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
                offset += 2;            /* error in AFP3.0.pdf */
        }
        if ((bitmap & kFPOwnerIDBit)) {
-               proto_tree_add_item(tree, hf_afp_dir_OwnerID, tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(tree, hf_afp_dir_OwnerID, tvb, offset, 4,   FALSE);
                offset += 4;
        }
        if ((bitmap & kFPGroupIDBit)) {
-               proto_tree_add_item(tree, hf_afp_dir_GroupID, tvb, offset, 4,   FALSE);  
+               proto_tree_add_item(tree, hf_afp_dir_GroupID, tvb, offset, 4,   FALSE);
                offset += 4;
        }
        if ((bitmap & kFPAccessRightsBit)) {
@@ -1133,9 +1335,11 @@ parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
                offset += 4;
        }
        if ((bitmap & kFPUTF8NameBit)) {
-               unameoff = tvb_get_ntohs(tvb, offset);
-               proto_tree_add_item(tree, hf_afp_unicode_name_offset,tvb, offset, 2, FALSE);
-               offset += 2;
+               gint tp_ofs;
+
+               tp_ofs = parse_UTF8_filename(tree, tvb, offset, org_offset);
+               max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+               offset += 6;
        }
        if ((bitmap & kFPUnixPrivsBit)) {
                /*
@@ -1153,30 +1357,31 @@ parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
 
 /* -------------------------- */
 static gchar *
-name_in_bitmap(tvbuff_t *tvb, gint *offset, guint16 bitmap)
+name_in_bitmap(tvbuff_t *tvb, gint offset, guint16 bitmap, int isdir)
 {
        gchar *name;
-       gint    org_offset = *offset;
+       gint    org_offset = offset;
        guint16 nameoff;
        guint8  len;
+       guint16 len16;
        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 ((bitmap & kFPAttributeBit))         /* 0 */
+               offset += 2;
+       if ((bitmap & kFPParentDirIDBit))       /* 1 */
+               offset += 4;
+       if ((bitmap & kFPCreateDateBit))        /* 2 */
+               offset += 4;
+       if ((bitmap & kFPModDateBit))           /* 3 */
+               offset += 4;
+       if ((bitmap & kFPBackupDateBit))        /* 4 */
+               offset += 4;
+       if ((bitmap & kFPFinderInfoBit))        /* 5 */
+               offset += 32;
+
+       if ((bitmap & kFPLongNameBit)) {        /* 6 */
+               nameoff = tvb_get_ntohs(tvb, offset);
                if (nameoff) {
                        tp_ofs = nameoff +org_offset;
                        len = tvb_get_guint8(tvb, tp_ofs);
@@ -1187,8 +1392,48 @@ name_in_bitmap(tvbuff_t *tvb, gint *offset, guint16 bitmap)
                        *(name +len) = 0;
                        return name;
                }
+               offset += 2;
+       }
+       
+       if ((bitmap & kFPShortNameBit))         /* 7 */
+               offset += 2;
+       if ((bitmap & kFPNodeIDBit))            /* 8 */
+               offset += 4;
+
+        if (isdir) {
+               if ((bitmap & kFPOffspringCountBit))    /* 9 */
+                       offset += 2;
+               if ((bitmap & kFPOwnerIDBit))           /* 10*/
+                       offset += 4;
+               if ((bitmap & kFPGroupIDBit))           /* 11*/
+                       offset += 4;
+               if ((bitmap & kFPAccessRightsBit))      /* 12*/
+                       offset += 4;
+        }
+        else {
+               if ((bitmap & kFPDataForkLenBit))       /* 9 */
+                       offset += 4;
+               if ((bitmap & kFPRsrcForkLenBit))       /* 10*/
+                       offset += 4;
+               if ((bitmap & kFPExtDataForkLenBit))    /* 11*/
+                       offset += 8;
+               if ((bitmap & kFPLaunchLimitBit))       /* 12*/
+                       offset += 2; /* FIXME ? */
+        }
+
+       if ((bitmap & kFPUTF8NameBit)) {                /* 13 */
+               nameoff = tvb_get_ntohs(tvb, offset);
+               if (nameoff) {
+                       tp_ofs = nameoff +org_offset +4;
+                       len16 = tvb_get_ntohs(tvb, tp_ofs);
+                       tp_ofs += 2;
+                       if (!(name = g_malloc(len16 +1)))
+                               return name;
+                       tvb_memcpy(tvb, name, tp_ofs, len16);
+                       *(name +len16) = 0;
+                       return name;
+               }
        }
-       /* short name ? */
        return name;
 }
 
@@ -1197,14 +1442,14 @@ static gchar *
 name_in_dbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
 {
        gchar *name;
-       
-       name = name_in_bitmap(tvb, &offset, bitmap);
+
+       name = name_in_bitmap(tvb, offset, bitmap, 1);
        if (name != NULL)
                return name;
        /*
-               check UTF8 name 
+               check UTF8 name
        */
-       
+
        return name;
 }
 
@@ -1213,14 +1458,14 @@ static gchar *
 name_in_fbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
 {
        gchar *name;
-       
-       name = name_in_bitmap(tvb, &offset, bitmap);
+
+       name = name_in_bitmap(tvb, offset, bitmap, 0);
        if (name != NULL)
                return name;
        /*
-               check UTF8 name 
+               check UTF8 name
        */
-       
+
        return name;
 }
 
@@ -1228,9 +1473,11 @@ name_in_fbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
 static gint
 decode_vol_did(proto_tree *tree, tvbuff_t *tvb, gint offset)
 {
+       Vol = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
        offset += 2;
 
+       Did = tvb_get_ntohl(tvb, offset);
        proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
        offset += 4;
        return offset;
@@ -1244,10 +1491,10 @@ decode_vol_did_file_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
 
        decode_file_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        decode_dir_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        return offset;
 }
 
@@ -1255,19 +1502,20 @@ decode_vol_did_file_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
 static gchar *
 get_name(tvbuff_t *tvb, int offset, int type)
 {
-       guint8 len;
+       int   len;
        gchar *string;
 
-       len = tvb_get_guint8(tvb, offset);
-       offset++;
-
        switch (type) {
        case 1:
        case 2:
+               len = tvb_get_guint8(tvb, offset);
+               offset++;
                string = tvb_format_text(tvb,offset, len);
                break;
        case 3:
-               string = "error Unicode...,next time";
+               len = tvb_get_ntohs(tvb, offset +4);
+               offset += 6;
+               string = tvb_format_text(tvb,offset, len);
                break;
        default:
                string = "unknow type";
@@ -1280,30 +1528,51 @@ static gint
 decode_name_label (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, const gchar *label)
 {
        int len;
+       int header;
        gchar *name;
        guint8 type;
        proto_tree *sub_tree = NULL;
        proto_item *item;
-               
+
        type = tvb_get_guint8(tvb, offset);
-       len = tvb_get_guint8(tvb, offset +1);
+       if (type == 3) {
+               header = 7;
+               len = tvb_get_ntohs(tvb, offset +5);
+       }
+       else {
+               header = 2;
+               len = tvb_get_guint8(tvb, offset +1);
+       }
        name = get_name(tvb, offset +1, type);
 
        if (pinfo && check_col(pinfo->cinfo, COL_INFO)) {
-               col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", name);
+               col_append_fstr(pinfo->cinfo, COL_INFO, ": Vol=%u Did=%u", Vol, Did);
+               if (len) {
+                       col_append_fstr(pinfo->cinfo, COL_INFO, " Name=%s", name);
+               }
        }
 
        if (tree) {
-               item = proto_tree_add_text(tree, tvb, offset, len +2, label, name);
+               item = proto_tree_add_text(tree, tvb, offset, len +header, label, name);
                sub_tree = proto_item_add_subtree(item, ett_afp_path_name);
+
                proto_tree_add_item(  sub_tree, hf_afp_path_type, tvb, offset,   1,FALSE);
                offset++;
-               proto_tree_add_item(  sub_tree, hf_afp_path_len,  tvb, offset,   1,FALSE);
-               offset++;
+               if (type == 3) {
+                       proto_tree_add_item( sub_tree, hf_afp_path_unicode_hint,  tvb, offset,  4,FALSE);
+                       offset += 4;
+                       proto_tree_add_item( sub_tree, hf_afp_path_unicode_len,  tvb, offset,   2,FALSE);
+                       offset += 2;
+               }
+               else {
+                       proto_tree_add_item( sub_tree, hf_afp_path_len,  tvb, offset,   1,FALSE);
+                       offset++;
+               }
+
                proto_tree_add_string(sub_tree, hf_afp_path_name, tvb, offset, len,name);
        }
-       else 
-               offset += 2;
+       else
+               offset += header;
 
        return offset +len;
 }
@@ -1315,17 +1584,41 @@ decode_name (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset)
        return decode_name_label(tree, pinfo, tvb, offset, "Path: %s");
 }
 
+/* -------------------------- */
+static void
+add_info_fork(tvbuff_t *tvb, packet_info *pinfo, gint offset)
+{
+       guint16 ofork;
+
+       ofork = tvb_get_ntohs(tvb, offset);
+       if (ofork && check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO, ": Fork=%u", ofork);
+       }
+}
+
+/* -------------------------- */
+static void
+add_info_vol(tvbuff_t *tvb, packet_info *pinfo, gint offset)
+{
+       guint16 vol;
+
+       vol = tvb_get_ntohs(tvb, offset);
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO, ": Vol=%u", vol);
+       }
+}
+
 /* ************************** */
 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 (check_col(pinfo->cinfo, COL_INFO)) {
@@ -1336,10 +1629,10 @@ dissect_query_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
        if (!tree)
                return offset;
-               
+
        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 */
@@ -1354,7 +1647,7 @@ static gint
 dissect_reply_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
 {
        guint16 bitmap;
-       
+
        if (!tree)
                return offset;
        bitmap = decode_vol_bitmap(tree, tvb, offset);
@@ -1376,7 +1669,7 @@ dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_
        proto_tree *flag_tree;
        proto_item *item;
        proto_item *ti;
-       
+
        if (!tree)
                return offset;
 
@@ -1387,10 +1680,10 @@ dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_
        item = proto_tree_add_text(tree, tvb, offset, 1, "Volumes : %d", num);
        sub_tree = proto_item_add_subtree(item, ett_afp_server_vol);
        offset++;
-               
+
        for (i = 0; i < num; i++) {
                const gchar *rep;
-               
+
                item = proto_tree_add_text(sub_tree, tvb, offset, -1,"Volume");
                tree = proto_item_add_subtree(item, ett_afp_vol_list);
 
@@ -1405,18 +1698,18 @@ dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_
                len  = tvb_get_guint8(tvb, offset) +1;
                rep = get_name(tvb, offset, 2);
                proto_item_set_text(item, rep);
-               proto_item_set_len(item, len +1);     
+               proto_item_set_len(item, len +1);
 
                proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
 
                offset += len;
-       }                       
+       }
        return offset;
 }
 
-/* ************************** 
+/* **************************
        next calls use the same format :
-               1 pad byte 
+               1 pad byte
                volume id
        AFP_FLUSH
        AFP_CLOSEVOL
@@ -1429,7 +1722,7 @@ dissect_query_afp_with_vol_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
        if (!tree)
                return offset;
        PAD(1);
-       
+
        proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
        offset += 2;
        return offset;
@@ -1446,7 +1739,7 @@ dissect_query_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        offset++;
 
        offset = decode_vol_did(tree, tvb, offset);
-       
+
        decode_file_bitmap(tree, tvb, offset);
        offset += 2;
        if (tree) {
@@ -1467,13 +1760,14 @@ dissect_query_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
 /* -------------------------- */
 static gint
-dissect_reply_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+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;
 
+        add_info_fork(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
 
@@ -1482,11 +1776,33 @@ dissect_reply_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
        return offset;
 }
 
+/* ************************** */
+static gint
+dissect_query_afp_enumerate_ext2(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_index32, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       proto_tree_add_item(tree, hf_afp_max_reply_size32, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       offset = decode_name(tree, pinfo, tvb, offset);
+
+       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);
 
@@ -1506,29 +1822,40 @@ dissect_query_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
 /* -------------------------- */
 static int
-loop_record(tvbuff_t *tvb, proto_tree *ptree, gint offset, 
-               int count, guint16 d_bitmap, guint16 f_bitmap, int add)
+loop_record(tvbuff_t *tvb, proto_tree *ptree, gint offset,
+               int count, guint16 d_bitmap, guint16 f_bitmap, int add, int ext)
 {
        proto_tree *tree = NULL;
        proto_item *item;
        gchar   *name;
        guint8  flags;
-       guint8  size;
+       guint   size;
        gint    org;
        int i;
+       int decal; 
 
        for (i = 0; i < count; i++) {
                org = offset;
-               name = NULL;
-               size = tvb_get_guint8(tvb, offset) +add;
-               flags = tvb_get_guint8(tvb, offset +1);
+               if (ext) {
+                       size = tvb_get_ntohs(tvb, offset);
+                       decal = 2;
+               }
+               else {
+                       size = tvb_get_guint8(tvb, offset) +add;
+                       decal = 1;
+               }
+               if (!size)
+                       return offset;  /* packet is malformed */
+               flags = tvb_get_guint8(tvb, offset +decal);
+
+               decal += (ext)?2:1;
 
                if (ptree) {
                        if (flags) {
-                               name = name_in_dbitmap(tvb, offset +2, d_bitmap);
-                       }       
+                               name = name_in_dbitmap(tvb, offset +decal, d_bitmap);
+                       }
                        else {
-                               name = name_in_fbitmap(tvb, offset +2, f_bitmap);
+                               name = name_in_fbitmap(tvb, offset +decal, f_bitmap);
                        }
                        if (!name) {
                                if (!(name = g_malloc(50))) { /* no memory ! */
@@ -1537,40 +1864,47 @@ loop_record(tvbuff_t *tvb, proto_tree *ptree, gint offset,
                        }
                        item = proto_tree_add_text(ptree, tvb, offset, size, name);
                        tree = proto_item_add_subtree(item, ett_afp_enumerate_line);
+                       g_free((gpointer)name);
+               }
+               if (ext) {
+                       proto_tree_add_item(tree, hf_afp_struct_size16, tvb, offset, 2,FALSE);
+                       offset += 2;
+               }
+               else {
+                       proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
+                       offset++;
                }
-               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 (ext) {
+                       PAD(1);
+               }
                if (flags) {
                        offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
                }
                else {
                        offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
                }
-               if ((offset & 1)) 
+               if ((offset & 1))
                        PAD(1);
                offset = org +size;             /* play safe */
-               if (ptree)
-                       g_free((gpointer)name);
-       }       
+       }
        return offset;
 }
-
 /* ------------------------- */
 static gint
-dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+reply_enumerate(tvbuff_t *tvb, proto_tree *tree, gint offset, int ext)
 {
        proto_tree *sub_tree = NULL;
        proto_item *item;
        int count;
        guint16 f_bitmap;
        guint16 d_bitmap;
-       
+
        f_bitmap = decode_file_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        d_bitmap = decode_dir_bitmap(tree, tvb, offset);
        offset += 2;
 
@@ -1581,8 +1915,21 @@ dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
        }
        offset += 2;
 
-       return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap,0);
+       return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap,0, ext);
+}
+
+/* ------------------------- */
+static gint
+dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       return reply_enumerate(tvb, tree, offset, 0);
+}
 
+/* **************************/
+static gint
+dissect_reply_afp_enumerate_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       return reply_enumerate(tvb, tree, offset, 1);
 }
 /* **************************/
 static gint
@@ -1599,7 +1946,7 @@ dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
        if (!ptree)
                return offset;
        PAD(1);
-       
+
        proto_tree_add_item(ptree, hf_afp_vol_id, tvb, offset, 2,FALSE);
        offset += 2;
 
@@ -1611,10 +1958,10 @@ dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
 
        proto_tree_add_item(ptree, hf_afp_cat_position, tvb, offset, 16,FALSE);
        offset += 16;
-       
+
        f_bitmap = decode_file_bitmap(ptree, tvb, offset);
        offset += 2;
-       
+
        d_bitmap = decode_dir_bitmap(ptree, tvb, offset);
        offset += 2;
 
@@ -1633,7 +1980,7 @@ dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
 
        proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
        offset++;
-       PAD(1); 
+       PAD(1);
 
        offset = parse_file_bitmap(tree, tvb, offset, r_bitmap,0);
        offset = org +size;
@@ -1648,7 +1995,7 @@ dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
        proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
        offset++;
        PAD(1);
-       
+
        offset = parse_file_bitmap(tree, tvb, offset, r_bitmap,0);
        offset = org +size;
 
@@ -1664,13 +2011,13 @@ dissect_reply_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
        guint16 f_bitmap;
        guint16 d_bitmap;
        int count;
-       
+
        proto_tree_add_item(tree, hf_afp_cat_position, tvb, offset, 16,FALSE);
        offset += 16;
 
        f_bitmap = decode_file_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        d_bitmap = decode_dir_bitmap(tree, tvb, offset);
        offset += 2;
 
@@ -1680,21 +2027,25 @@ dissect_reply_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
                sub_tree = proto_item_add_subtree(item, ett_afp_cat_search);
        }
        offset += 4;
-       return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap, 2);
+
+       return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap, 2, 0);
 }
 
 /* **************************/
 static gint
-dissect_query_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+dissect_query_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
+
        PAD(1)
+        add_info_vol(tvb, pinfo, offset);
+       
        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;  
+
+       return offset;
 }
 
 /* ------------------------ */
@@ -1713,59 +2064,150 @@ dissect_reply_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre
 
 /* **************************/
 static gint
-dissect_query_afp_set_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+dissect_query_afp_set_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
        guint16 bitmap;
 
        PAD(1)
+
+        add_info_vol(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
        offset += 2;
 
        bitmap = decode_vol_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
 
-       return offset;  
+       return offset;
 }
 
 /* ***************************/
 static gint
-dissect_query_afp_login(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+decode_uam_parameters(const char *uam, int len_uam, tvbuff_t *tvb, proto_tree *tree, gint offset)
 {
        int len;
-       const char *uam;
-    
-       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);
-       uam = tvb_get_ptr(tvb, offset +1, len);
-       proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
-       offset += len +1;
 
-       if (!strncmp(uam, "Cleartxt passwrd", len)) {
-               /* clear text */
-               len = tvb_get_guint8(tvb, offset);
-               proto_tree_add_item(tree, hf_afp_user, tvb, offset, 1,FALSE);
-               offset += len +1;
+       if (!strncasecmp(uam, "Cleartxt passwrd", len_uam)) {
+               if ((offset & 1))
+                       PAD(1);
 
-               len = tvb_strsize(tvb, offset);
+               len = 8; /* tvb_strsize(tvb, offset);*/
                proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
                offset += len;
        }
-       else if (!strncmp(uam, "No User Authent", len)) {
+       else if (!strncasecmp(uam, "DHCAST128", len_uam)) {
+               if ((offset & 1))
+                       PAD(1);
+
+               len = 16;
+               proto_tree_add_item(tree, hf_afp_random, tvb, offset, len,FALSE);
+               offset += len;
+        }
+       else if (!strncasecmp(uam, "2-Way Randnum exchange", len_uam)) {
+               /* nothing */
+               return offset;
+       }
+       return offset;
+}
+
+/* ---------------- */
+static gint
+dissect_query_afp_login(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       int len;
+       int len_uam;
+       const char *uam;
+
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
+       offset += len +1;
+       len_uam = tvb_get_guint8(tvb, offset);
+       uam = tvb_get_ptr(tvb, offset +1, len_uam);
+       proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
+       offset += len_uam +1;
+
+       if (!strncasecmp(uam, "No User Authent", len_uam)) {
+               return offset;
        }
-       return(offset);
+
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_user, tvb, offset, 1,FALSE);
+       offset += len +1;
+       
+       return decode_uam_parameters(uam, len_uam, tvb, tree, offset);
+}
+
+/* ***************************/
+static gint
+dissect_query_afp_login_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       int len;
+       int len_uam;
+       const char *uam;
+       guint8 type;
+
+       type = tvb_get_guint8(tvb, offset);
+
+       PAD(1);
+       proto_tree_add_item(tree, hf_afp_login_flags, tvb, offset, 2,FALSE);
+       offset += 2;
+       
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
+       offset += len +1;
+
+       len_uam = tvb_get_guint8(tvb, offset);
+       uam = tvb_get_ptr(tvb, offset +1, len_uam);
+       proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
+       offset += len_uam +1;
+
+       type = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_user_type, tvb, offset, 1,FALSE);
+       offset++;
+       /* only type 3 */
+       len = tvb_get_ntohs(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_user_len, tvb, offset, 2,FALSE);
+       offset += 2;
+       proto_tree_add_item(tree, hf_afp_user_name, tvb, offset, len,FALSE);
+       offset += len;
+
+       /* directory service */
+       type = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_path_type, tvb, offset, 1,FALSE);
+       offset++;
+       /* FIXME use 16 bit len + unicode from smb dissector */
+       switch (type) {
+       case 1:
+       case 2:
+               len = tvb_get_guint8(tvb, offset);
+               proto_tree_add_item(tree, hf_afp_path_len, tvb, offset,  1,FALSE);
+               offset++;
+               proto_tree_add_item(tree, hf_afp_path_name, tvb, offset, len,FALSE);
+               offset += len;
+               break;
+       case 3:
+               len = tvb_get_ntohs(tvb, offset);
+               proto_tree_add_item( tree, hf_afp_path_unicode_len, tvb, offset, 2,FALSE);
+               offset += 2;
+               proto_tree_add_item(tree, hf_afp_path_name, tvb, offset, len,FALSE);
+               offset += len;
+               break;
+       default:
+               break;
+       }
+       
+       return decode_uam_parameters(uam, len_uam, tvb, tree, offset);
 }
 
 /* ************************** */
 static gint
-dissect_query_afp_write(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+dissect_query_afp_write(tvbuff_t *tvb, packet_info *pinfo , proto_tree *tree, gint offset)
 {
        proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
        offset += 1;
 
+        add_info_fork(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
 
@@ -1783,7 +2225,36 @@ dissect_reply_afp_write(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
 {
        proto_tree_add_item(tree, hf_afp_last_written, tvb, offset, 4, FALSE);
        offset += 4;
-       
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_write_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
+       offset += 1;
+
+        add_info_fork(tvb, pinfo, offset);
+       proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_offset64, tvb, offset, 8,FALSE);
+       offset += 8;
+
+       proto_tree_add_item(tree, hf_afp_rw_count64, tvb, offset, 8,FALSE);
+       offset += 8;
+
+       return offset;
+}
+
+static gint
+dissect_reply_afp_write_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       proto_tree_add_item(tree, hf_afp_last_written64, tvb, offset, 8, FALSE);
+       offset += 8;
+
        return offset;
 }
 
@@ -1792,7 +2263,8 @@ static gint
 dissect_query_afp_read(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
 {
        PAD(1);
-       
+
+        add_info_fork(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
 
@@ -1804,15 +2276,34 @@ dissect_query_afp_read(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
 
        proto_tree_add_item(tree, hf_afp_newline_mask, tvb, offset, 1,FALSE);
        offset++;
-       
+
        proto_tree_add_item(tree, hf_afp_newline_char, tvb, offset, 1,FALSE);
        offset++;
 
        return offset;
 }
 
-/* ************************** 
-   Open desktop call 
+/* ************************** */
+static gint
+dissect_query_afp_read_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       PAD(1);
+
+        add_info_fork(tvb, pinfo, offset);
+       proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       proto_tree_add_item(tree, hf_afp_offset64, tvb, offset, 8,FALSE);
+       offset += 8;
+
+       proto_tree_add_item(tree, hf_afp_rw_count64, tvb, offset, 8,FALSE);
+       offset += 8;
+
+       return offset;
+}
+
+/* **************************
+   Open desktop call
    query is the same than      AFP_FLUSH, AFP_CLOSEVOL
 
 */
@@ -1825,7 +2316,7 @@ dissect_reply_afp_open_dt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
@@ -1838,17 +2329,18 @@ dissect_query_afp_close_dt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
        return offset;
 }
 
-/* ************************** 
+/* **************************
        calls using the same format :
-               1 pad byte 
-               fork number 
+               1 pad byte
+               fork number
        AFP_FLUSHFORK
        AFP_CLOSEFORK
 */
 static gint
-dissect_query_afp_with_fork(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+dissect_query_afp_with_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
        PAD(1);
+        add_info_fork(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
 
@@ -1876,7 +2368,7 @@ dissect_reply_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr
 
        f_bitmap = decode_file_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        d_bitmap = decode_dir_bitmap(tree, tvb, offset);
        offset += 2;
 
@@ -1893,46 +2385,48 @@ dissect_reply_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
 dissect_query_afp_set_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
        guint16 f_bitmap;
-       
+
        PAD(1);
        offset = decode_vol_did(tree, tvb, offset);
 
        f_bitmap = decode_file_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        offset = decode_name(tree, pinfo, tvb, offset);
 
        if ((offset & 1))
                PAD(1);
-       /* did:name can be a file or a folder but only the intersection between 
-        * file bitmap and dir bitmap can be set
+       /* did:name can be a file or a folder but only the intersection between
+        * file bitmap and dir bitmap can be set.
+        * Well it's in afp spec, but clients (Mac) are setting 'file only' bits with this call
+        * (WriteInhibit for example).
         */
        offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 1);
 
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
 dissect_query_afp_set_file_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
        guint16 f_bitmap;
-       
+
        PAD(1);
        offset = decode_vol_did(tree, tvb, offset);
 
        f_bitmap = decode_file_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        offset = decode_name(tree, pinfo, tvb, offset);
 
        if ((offset & 1))
@@ -1942,7 +2436,7 @@ dissect_query_afp_set_file_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
@@ -1955,7 +2449,7 @@ dissect_query_afp_set_dir_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
 
        d_bitmap = decode_dir_bitmap(tree, tvb, offset);
        offset += 2;
-       
+
        offset = decode_name(tree, pinfo, tvb, offset);
 
        if ((offset & 1))
@@ -1980,7 +2474,7 @@ dissect_query_afp_create_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        return offset;
 }
 
-/* -------------------------- 
+/* --------------------------
        AFP_MOVE
 */
 static gint
@@ -1988,7 +2482,7 @@ dissect_reply_afp_create_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
 {
        proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        return offset;
 }
 
@@ -1998,11 +2492,11 @@ dissect_reply_afp_create_dir(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
 {
        proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
@@ -2013,11 +2507,11 @@ dissect_query_afp_delete_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
        offset += 2;
        proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        return offset;
 }
 
-/* ************************** 
+/* **************************
        same reply as get_fork_param
 */
 static gint
@@ -2037,10 +2531,11 @@ dissect_query_afp_resolve_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
 
 /* ************************** */
 static gint
-dissect_query_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+dissect_query_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
 
        PAD(1);
+        add_info_fork(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
 
@@ -2065,18 +2560,26 @@ dissect_reply_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr
 
 /* ************************** */
 static gint
-dissect_query_afp_set_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+dissect_query_afp_set_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
+       guint16 bitmap;
 
        PAD(1);
+        add_info_fork(tvb, pinfo, offset);
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
 
-       decode_file_bitmap(tree, tvb, offset);
+       bitmap = decode_file_bitmap(tree, tvb, offset);
        offset += 2;
 
-       proto_tree_add_item(tree, hf_afp_ofork_len, tvb, offset, 4,FALSE);
-       offset += 4;
+       if ((bitmap & kFPExtDataForkLenBit) || (bitmap & kFPExtRsrcForkLenBit)) {
+               proto_tree_add_item(tree, hf_afp_ofork_len64, tvb, offset, 8, FALSE);
+               offset += 8;
+       }
+       else {
+               proto_tree_add_item(tree, hf_afp_ofork_len, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
        return offset;
 }
 
@@ -2084,7 +2587,7 @@ dissect_query_afp_set_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tr
 static gint
 dissect_query_afp_move(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
-               
+
        PAD(1);
        offset = decode_vol_did(tree, tvb, offset);
 
@@ -2098,13 +2601,29 @@ dissect_query_afp_move(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint
        return offset;
 }
 
+/* ************************** */
+static gint
+dissect_query_afp_exchange_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+       PAD(1);
+       offset = decode_vol_did(tree, tvb, offset);
+
+       proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
+       offset = decode_name_label(tree, NULL, tvb, offset,  "Dest path:   %s");
+
+       return offset;
+}
 /* ************************** */
 static gint
 dissect_query_afp_copy_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
        proto_tree *sub_tree = NULL;
        proto_item *item;
-               
+
        PAD(1);
        if (tree) {
                item = proto_tree_add_text(tree, tvb, offset, 6,"Source volume");
@@ -2129,12 +2648,12 @@ dissect_query_afp_copy_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 static gint
 dissect_query_afp_rename(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
 {
-               
+
        PAD(1);
        offset = decode_vol_did(tree, tvb, offset);
 
-       offset = decode_name_label(tree, pinfo, tvb, offset, "Old name:     %s");
-       offset = decode_name_label(tree, NULL, tvb, offset,  "New name:     %s");
+       offset = decode_name_label(tree, pinfo, tvb, offset, "Old name: %s");
+       offset = decode_name_label(tree, NULL, tvb, offset,  "New name: %s");
 
        return offset;
 }
@@ -2146,7 +2665,7 @@ dissect_query_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
        proto_tree *sub_tree = NULL;
        proto_item *item;
        guint8 flag;
-       
+
        flag = tvb_get_guint8(tvb, offset);
        if (tree) {
                item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
@@ -2159,7 +2678,7 @@ dissect_query_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
 
        proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
        offset += 2;
-       
+
        proto_tree_add_item(tree, hf_afp_lock_offset, tvb, offset, 4,FALSE);
        offset += 4;
 
@@ -2178,6 +2697,45 @@ dissect_reply_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
        return offset;
 }
 
+/* ************************** */
+static gint
+dissect_query_afp_byte_lock_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       guint8 flag;
+
+       flag = tvb_get_guint8(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
+               sub_tree = proto_item_add_subtree(item, ett_afp_lock_flags);
+       }
+
+       proto_tree_add_item(sub_tree, hf_afp_lock_op, tvb, offset, 1,FALSE);
+       proto_tree_add_item(sub_tree, hf_afp_lock_from, 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_lock_offset64, tvb, offset, 8,FALSE);
+       offset += 8;
+
+       proto_tree_add_item(tree, hf_afp_lock_len64, tvb, offset, 8,FALSE);
+       offset += 8;
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_byte_lock_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       proto_tree_add_item(tree, hf_afp_lock_range_start64, tvb, offset, 8,FALSE);
+       offset += 8;
+
+       return offset;
+}
+
 /* ************************** */
 static gint
 dissect_query_afp_add_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
@@ -2193,7 +2751,7 @@ dissect_query_afp_add_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
 
        offset = decode_name(tree, pinfo, tvb, offset);
 
-       if ((offset & 1)) 
+       if ((offset & 1))
                PAD(1);
 
        len = tvb_get_guint8(tvb, offset);
@@ -2246,7 +2804,7 @@ dissect_query_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
 
        proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
        offset += 1;
        PAD(1);
@@ -2284,7 +2842,7 @@ dissect_reply_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre
 
        proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
        offset += 1;
 
@@ -2308,21 +2866,21 @@ dissect_query_afp_add_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
 
        proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
        offset += 1;
-       
+
        PAD(1);
        proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
        offset += 2;
 
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
@@ -2341,13 +2899,13 @@ dissect_query_afp_add_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
        proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
        offset += 4;
-       
+
        offset = decode_name(tree, pinfo, tvb, offset);
 
        return offset;
 }
 
-/* ************************** 
+/* **************************
        no reply
 */
 static gint
@@ -2414,6 +2972,167 @@ dissect_query_afp_create_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
        return offset;
 }
 
+/* ************************** */
+static gint
+dissect_query_afp_map_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       proto_tree_add_item(tree, hf_afp_map_id_type, tvb, offset, 1,FALSE);
+       offset++;
+
+       proto_tree_add_item(tree, hf_afp_map_id, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_map_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_map_name, tvb, offset, 1,FALSE);
+       offset += len +1;
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_map_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+       proto_tree_add_item(tree, hf_afp_map_name_type, tvb, offset, 1,FALSE);
+       offset++;
+
+       len = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_map_name, tvb, offset, 1,FALSE);
+       offset += len +1;
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_map_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+       proto_tree_add_item(tree, hf_afp_map_id, tvb, offset, 4,FALSE);
+       offset += 4;
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_disconnect_old_session(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+
+       PAD(1);
+
+       proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       len = tvb_get_ntohl(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
+       offset += len;
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+       PAD(1);
+       proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+int size;
+
+       proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+       offset += 2;
+
+       /* FIXME spec and capture disagree : spec 4 bytes, capture 2 bytes? */
+       size = 2;
+       len = tvb_get_ntohs(tvb, offset);
+       proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, size,FALSE);
+       offset += size;
+
+       proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
+       offset += len;
+
+       return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_user_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+       proto_tree *sub_tree = NULL;
+       proto_item *item;
+       guint16  bitmap;
+
+
+       proto_tree_add_item(tree, hf_afp_user_flag, tvb, offset, 1,FALSE);
+       offset++;
+
+       proto_tree_add_item(tree, hf_afp_user_ID, tvb, offset, 4,FALSE);
+       offset += 4;
+
+       bitmap = tvb_get_ntohs(tvb, offset);
+       if (tree) {
+               item = proto_tree_add_item(tree, hf_afp_user_bitmap, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_user_bitmap);
+               proto_tree_add_item(sub_tree, hf_afp_user_bitmap_UID, tvb, offset, 2,FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_user_bitmap_GID, tvb, offset, 2,FALSE);
+       }
+       offset += 2;
+
+       return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_user_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, 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_user_bitmap, tvb, offset, 2,FALSE);
+               sub_tree = proto_item_add_subtree(item, ett_afp_user_bitmap);
+               proto_tree_add_item(sub_tree, hf_afp_user_bitmap_UID, tvb, offset, 2,FALSE);
+               proto_tree_add_item(sub_tree, hf_afp_user_bitmap_GID, tvb, offset, 2,FALSE);
+       }
+
+       offset += 2;
+       if ((bitmap & 1)) {
+               proto_tree_add_item(tree, hf_afp_user_ID, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
+
+       if ((bitmap & 2)) {
+               proto_tree_add_item(tree, hf_afp_group_ID, tvb, offset, 4,FALSE);
+               offset += 4;
+       }
+       return offset;
+}
+
 /* ************************** */
 static void
 dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -2428,7 +3147,7 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        guint8  afp_command;
 
        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))
@@ -2443,7 +3162,7 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
        }
 
-       request_key.conversation = conversation->index; 
+       request_key.conversation = conversation->index;
        request_key.seq = aspinfo->seq;
 
        request_val = (afp_request_val *) g_hash_table_lookup(
@@ -2462,7 +3181,7 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
 
        if (!request_val) {     /* missing request */
-               if (check_col(pinfo->cinfo, COL_INFO)) 
+               if (check_col(pinfo->cinfo, COL_INFO))
                        col_add_fstr(pinfo->cinfo, COL_INFO, "[Reply without query?]");
                return;
        }
@@ -2473,6 +3192,11 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                             val_to_str(afp_command, CommandCode_vals,
                                        "Unknown command (%u)"),
                             aspinfo->reply ? "reply" : "request");
+               if (aspinfo->reply && aspinfo->code != 0) {
+                       col_append_fstr(pinfo->cinfo, COL_INFO, ": %s (%d)",
+                               val_to_str(aspinfo->code, asp_error_vals,
+                                       "Unknown error (%u)"), aspinfo->code);
+               }
        }
 
        if (tree)
@@ -2481,44 +3205,74 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                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);
+               if (afp_command != tvb_get_guint8(tvb, offset))
+               {
+                       /* we have the same conversation for different connections eg:
+                        * ip1:2048 --> ip2:548
+                        * ip1:2048 --> ip2:548 <RST>
+                        * ....
+                        * ip1:2048 --> ip2:548 <SYN> use the same port but it's a new session!
+                        */
+                       if (check_col(pinfo->cinfo, COL_INFO)) {
+                               col_add_fstr(pinfo->cinfo, COL_INFO, 
+                                 "[Error!IP port reused, you need to split the capture file]");
+                               return;
+                       }
+               }
                offset++;
                switch(afp_command) {
                case AFP_BYTELOCK:
-                       offset = dissect_query_afp_byte_lock(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_byte_lock(tvb, pinfo, afp_tree, offset);break;
+               case AFP_BYTELOCK_EXT:
+                       offset = dissect_query_afp_byte_lock_ext(tvb, pinfo, afp_tree, offset);break;
                case AFP_OPENDT:        /* same as close vol */
-               case AFP_FLUSH:         
+               case AFP_FLUSH:
                case AFP_CLOSEVOL:
                        offset = dissect_query_afp_with_vol_id(tvb, pinfo, afp_tree, offset);break;
                case AFP_CLOSEDIR:
                        /* offset = dissect_query_afp_close_dir(tvb, pinfo, afp_tree, offset);break; */
                        break;
-               case AFP_CLOSEDT:       
+               case AFP_CLOSEDT:
                        offset = dissect_query_afp_close_dt(tvb, pinfo, afp_tree, offset);break;
                case AFP_FLUSHFORK: /* same packet as closefork */
                case AFP_CLOSEFORK:
                        offset = dissect_query_afp_with_fork(tvb, pinfo, afp_tree, offset);break;
                case AFP_COPYFILE:
-                       offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break;
                case AFP_CREATEFILE:
-                       offset = dissect_query_afp_create_file(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_create_file(tvb, pinfo, afp_tree, offset);break;
+               case AFP_DISCTOLDSESS:
+                       offset = dissect_query_afp_disconnect_old_session(tvb, pinfo, afp_tree, offset);break;
+               case AFP_ENUMERATE_EXT2:
+                       offset = dissect_query_afp_enumerate_ext2(tvb, pinfo, afp_tree, offset);break;
+               case AFP_ENUMERATE_EXT:
                case AFP_ENUMERATE:
                        offset = dissect_query_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
                case AFP_GETFORKPARAM:
-                       offset = dissect_query_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETSESSTOKEN:
+                       offset = dissect_query_afp_get_session_token(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETUSERINFO:
+                       offset = dissect_query_afp_get_user_info(tvb, pinfo, afp_tree, offset);break;
                case AFP_GETSRVINFO:
                        /* offset = dissect_query_afp_get_server_info(tvb, pinfo, afp_tree, offset);break; */
                case AFP_GETSRVPARAM:
                        break;                                  /* no parameters */
                case AFP_GETVOLPARAM:
                        offset = dissect_query_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
+               case AFP_LOGIN_EXT:
+                       offset = dissect_query_afp_login_ext(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:
+                       break;
                case AFP_MAPID:
+                       offset = dissect_query_afp_map_id(tvb, pinfo, afp_tree, offset);break;
                case AFP_MAPNAME:
-                       break;
+                       offset = dissect_query_afp_map_name(tvb, pinfo, afp_tree, offset);break;
                case AFP_MOVE:
                        offset = dissect_query_afp_move(tvb, pinfo, afp_tree, offset);break;
                case AFP_OPENVOL:
@@ -2529,18 +3283,22 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        offset = dissect_query_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
                case AFP_READ:
                        offset = dissect_query_afp_read(tvb, pinfo, afp_tree, offset);break;
+               case AFP_READ_EXT:
+                       offset = dissect_query_afp_read_ext(tvb, pinfo, afp_tree, offset);break;
                case AFP_RENAME:
                        offset = dissect_query_afp_rename(tvb, pinfo, afp_tree, offset);break;
                case AFP_SETDIRPARAM:
-                       offset = dissect_query_afp_set_dir_param(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_set_dir_param(tvb, pinfo, afp_tree, offset);break;
                case AFP_SETFILEPARAM:
-                       offset = dissect_query_afp_set_file_param(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_set_file_param(tvb, pinfo, afp_tree, offset);break;
                case AFP_SETFORKPARAM:
-                       offset = dissect_query_afp_set_fork_param(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_set_fork_param(tvb, pinfo, afp_tree, offset);break;
                case AFP_SETVOLPARAM:
                        offset = dissect_query_afp_set_vol_param(tvb, pinfo, afp_tree, offset);break;
                case AFP_WRITE:
                        offset = dissect_query_afp_write(tvb, pinfo, afp_tree, offset);break;
+               case AFP_WRITE_EXT:
+                       offset = dissect_query_afp_write_ext(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:
@@ -2551,32 +3309,33 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                case AFP_DELETE:        /* same as create_id */
                case AFP_CREATEDIR:
                case AFP_CREATEID:
-                       offset = dissect_query_afp_create_id(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_create_id(tvb, pinfo, afp_tree, offset);break;
                case AFP_DELETEID:
-                       offset = dissect_query_afp_delete_id(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_delete_id(tvb, pinfo, afp_tree, offset);break;
                case AFP_RESOLVEID:
-                       offset = dissect_query_afp_resolve_id(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_resolve_id(tvb, pinfo, afp_tree, offset);break;
                case AFP_EXCHANGEFILE:
-                       break;
+                       offset = dissect_query_afp_exchange_file(tvb, pinfo, afp_tree, offset);break;
+               case AFP_CATSEARCH_EXT:
                case AFP_CATSEARCH:
-                       offset = dissect_query_afp_cat_search(tvb, pinfo, afp_tree, offset);break; 
-               case AFP_GETICON:       
-                       offset = dissect_query_afp_get_icon(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_cat_search(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETICON:
+                       offset = dissect_query_afp_get_icon(tvb, pinfo, afp_tree, offset);break;
                case AFP_GTICNINFO:
-                       offset = dissect_query_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break;
                case AFP_ADDAPPL:
-                       offset = dissect_query_afp_add_appl(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_add_appl(tvb, pinfo, afp_tree, offset);break;
                case AFP_RMVAPPL:
-                       offset = dissect_query_afp_rmv_appl(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_rmv_appl(tvb, pinfo, afp_tree, offset);break;
                case AFP_GETAPPL:
-                       offset = dissect_query_afp_get_appl(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_get_appl(tvb, pinfo, afp_tree, offset);break;
                case AFP_ADDCMT:
-                       offset = dissect_query_afp_add_cmt(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_add_cmt(tvb, pinfo, afp_tree, offset);break;
                case AFP_RMVCMT: /* same as get_cmt */
                case AFP_GETCMT:
-                       offset = dissect_query_afp_get_cmt(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_get_cmt(tvb, pinfo, afp_tree, offset);break;
                case AFP_ADDICON:
-                       offset = dissect_query_afp_add_icon(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_query_afp_add_icon(tvb, pinfo, afp_tree, offset);break;
                        break;
                }
        }
@@ -2589,7 +3348,12 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                }
                switch(afp_command) {
                case AFP_BYTELOCK:
-                       offset = dissect_reply_afp_byte_lock(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_byte_lock(tvb, pinfo, afp_tree, offset);break;
+               case AFP_BYTELOCK_EXT:
+                       offset = dissect_reply_afp_byte_lock_ext(tvb, pinfo, afp_tree, offset);break;
+               case AFP_ENUMERATE_EXT2:
+               case AFP_ENUMERATE_EXT:
+                       offset = dissect_reply_afp_enumerate_ext(tvb, pinfo, afp_tree, offset);break;
                case AFP_ENUMERATE:
                        offset = dissect_reply_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
                case AFP_OPENVOL:
@@ -2599,33 +3363,47 @@ dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                case AFP_RESOLVEID:
                case AFP_GETFORKPARAM:
                        offset =dissect_reply_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETUSERINFO:
+                       offset = dissect_reply_afp_get_user_info(tvb, pinfo, afp_tree, offset);break;
                case AFP_GETSRVPARAM:
                        offset = dissect_reply_afp_get_server_param(tvb, pinfo, afp_tree, offset);break;
                case AFP_CREATEDIR:
-                       offset = dissect_reply_afp_create_dir(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_create_dir(tvb, pinfo, afp_tree, offset);break;
+               case AFP_MAPID:
+                       offset = dissect_reply_afp_map_id(tvb, pinfo, afp_tree, offset);break;
+               case AFP_MAPNAME:
+                       offset = dissect_reply_afp_map_name(tvb, pinfo, afp_tree, offset);break;
                case AFP_MOVE:          /* same as create_id */
                case AFP_CREATEID:
-                       offset = dissect_reply_afp_create_id(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_create_id(tvb, pinfo, afp_tree, offset);break;
+               case AFP_GETSESSTOKEN:
+                       offset = dissect_reply_afp_get_session_token(tvb, pinfo, afp_tree, offset);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;
                case AFP_OPENDT:
                        offset = dissect_reply_afp_open_dt(tvb, pinfo, afp_tree, offset);break;
+
+               case AFP_CATSEARCH_EXT:
                case AFP_CATSEARCH:
-                       offset = dissect_reply_afp_cat_search(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_cat_search(tvb, pinfo, afp_tree, offset);break;
                case AFP_GTICNINFO:
-                       offset = dissect_reply_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break;
                case AFP_GETAPPL:
-                       offset = dissect_reply_afp_get_appl(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_get_appl(tvb, pinfo, afp_tree, offset);break;
                case AFP_GETCMT:
-                       offset = dissect_reply_afp_get_cmt(tvb, pinfo, afp_tree, offset);break; 
+                       offset = dissect_reply_afp_get_cmt(tvb, pinfo, afp_tree, offset);break;
                case AFP_WRITE:
                        offset = dissect_reply_afp_write(tvb, pinfo, afp_tree, offset);break;
+               case AFP_WRITE_EXT:
+                       offset = dissect_reply_afp_write_ext(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);
+       if (tree && offset < len) {
+               call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
+                   pinfo, afp_tree);
+       }
 }
 
 static void afp_reinit( void)
@@ -2661,9 +3439,9 @@ proto_register_afp(void)
                FT_UINT8, BASE_DEC, VALS(CommandCode_vals), 0x0,
        "AFP function", HFILL }},
 
-    { &hf_afp_pad,    
-      { "Pad",         "afp.pad",    
-               FT_NONE,   BASE_NONE, NULL, 0, 
+    { &hf_afp_pad,
+      { "Pad",         "afp.pad",
+               FT_NONE,   BASE_NONE, NULL, 0,
        "Pad Byte",     HFILL }},
 
     { &hf_afp_AFPVersion,
@@ -2681,11 +3459,34 @@ proto_register_afp(void)
                FT_UINT_STRING, BASE_NONE, NULL, 0x0,
        "User", HFILL }},
 
+    { &hf_afp_user_type,
+      { "Type",         "afp.user_type",
+               FT_UINT8, BASE_HEX, VALS(path_type_vals), 0,
+       "Type of user name", HFILL }},
+    { &hf_afp_user_len,
+      { "Len",  "afp.user_len",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "User name length (unicode)", HFILL }},
+    { &hf_afp_user_name,
+      { "User",  "afp.user_name",
+               FT_STRING, BASE_NONE, NULL, 0x0,
+       "User name (unicode)", HFILL }},
+
     { &hf_afp_passwd,
       { "Password",     "afp.passwd",
                FT_STRINGZ, BASE_NONE, NULL, 0x0,
        "Password", HFILL }},
 
+    { &hf_afp_random,
+      { "Random number",         "afp.random",
+               FT_BYTES, BASE_HEX, NULL, 0x0,
+       "UAM random number", HFILL }},
+
+    { &hf_afp_login_flags,
+      { "Flags",         "afp.afp_login_flags",
+               FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
+       "Login flags", HFILL }},
+
     { &hf_afp_vol_bitmap,
       { "Bitmap",         "afp.vol_bitmap",
                FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
@@ -2701,7 +3502,7 @@ proto_register_afp(void)
                FT_UINT16, BASE_HEX, NULL, 0,
        "Volume attributes", HFILL }},
 
-    { &hf_afp_vol_attribute_ReadOnly, 
+    { &hf_afp_vol_attribute_ReadOnly,
       { "Read only",         "afp.vol_attribute.read_only",
                 FT_BOOLEAN, 16, NULL, kReadOnly,
         "Read only volume", HFILL }},
@@ -2791,77 +3592,77 @@ proto_register_afp(void)
                FT_BOOLEAN, 16, NULL,  kFPVolBlockSizeBit,
        "Volume block size", HFILL }},
 
-    { &hf_afp_dir_bitmap_Attributes,        
+    { &hf_afp_dir_bitmap_Attributes,
       { "Attributes",         "afp.dir_bitmap.attributes",
            FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
        "Return attributes if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_ParentDirID,     
+    { &hf_afp_dir_bitmap_ParentDirID,
       { "DID",         "afp.dir_bitmap.did",
        FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
        "Return parent directory ID if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_CreateDate,      
+    { &hf_afp_dir_bitmap_CreateDate,
       { "Creation date",         "afp.dir_bitmap.create_date",
            FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
        "Return creation date if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_ModDate,                 
+    { &hf_afp_dir_bitmap_ModDate,
       { "Modification date",         "afp.dir_bitmap.mod_date",
        FT_BOOLEAN, 16, NULL,  kFPModDateBit,
        "Return modification date if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_BackupDate,      
+    { &hf_afp_dir_bitmap_BackupDate,
       { "Backup date",         "afp.dir_bitmap.backup_date",
            FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
        "Return backup date if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_FinderInfo,      
+    { &hf_afp_dir_bitmap_FinderInfo,
       { "Finder info",         "afp.dir_bitmap.finder_info",
        FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
        "Return finder info if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_LongName,                
+    { &hf_afp_dir_bitmap_LongName,
       { "Long name",         "afp.dir_bitmap.long_name",
            FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
        "Return long name if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_ShortName,               
+    { &hf_afp_dir_bitmap_ShortName,
       { "Short name",         "afp.dir_bitmap.short_name",
        FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
        "Return short name if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_NodeID,                  
+    { &hf_afp_dir_bitmap_NodeID,
       { "File ID",         "afp.dir_bitmap.fid",
            FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
        "Return file ID if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_OffspringCount,   
+    { &hf_afp_dir_bitmap_OffspringCount,
       { "Offspring count",         "afp.dir_bitmap.offspring_count",
        FT_BOOLEAN, 16, NULL,  kFPOffspringCountBit,
        "Return offspring count if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_OwnerID,                 
+    { &hf_afp_dir_bitmap_OwnerID,
       { "Owner id",         "afp.dir_bitmap.owner_id",
            FT_BOOLEAN, 16, NULL,  kFPOwnerIDBit,
        "Return owner id if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_GroupID,                 
+    { &hf_afp_dir_bitmap_GroupID,
       { "Group id",         "afp.dir_bitmap.group_id",
        FT_BOOLEAN, 16, NULL,  kFPGroupIDBit,
        "Return group id if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_AccessRights,    
+    { &hf_afp_dir_bitmap_AccessRights,
       { "Access rights",         "afp.dir_bitmap.access_rights",
            FT_BOOLEAN, 16, NULL,  kFPAccessRightsBit,
        "Return access rights if directory", HFILL }},
 
-    { &hf_afp_dir_bitmap_UTF8Name,                
+    { &hf_afp_dir_bitmap_UTF8Name,
       { "UTF-8 name",         "afp.dir_bitmap.UTF8_name",
        FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
        "Return UTF-8 name if diectory", HFILL }},
 
-    { &hf_afp_dir_bitmap_UnixPrivs,               
+    { &hf_afp_dir_bitmap_UnixPrivs,
       { "UNIX privileges",         "afp.dir_bitmap.unix_privs",
            FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit,
        "Return UNIX privileges if directory", HFILL }},
@@ -2916,42 +3717,42 @@ proto_register_afp(void)
            FT_BOOLEAN, 16, NULL,  kFPAttributeBit,
        "Return attributes if file", HFILL }},
 
-    { &hf_afp_file_bitmap_ParentDirID,    
+    { &hf_afp_file_bitmap_ParentDirID,
       { "DID",         "afp.file_bitmap.did",
        FT_BOOLEAN, 16, NULL,  kFPParentDirIDBit,
        "Return parent directory ID if file", HFILL }},
 
-    { &hf_afp_file_bitmap_CreateDate,     
+    { &hf_afp_file_bitmap_CreateDate,
       { "Creation date",         "afp.file_bitmap.create_date",
            FT_BOOLEAN, 16, NULL,  kFPCreateDateBit,
        "Return creation date if file", HFILL }},
 
-    { &hf_afp_file_bitmap_ModDate,                
+    { &hf_afp_file_bitmap_ModDate,
       { "Modification date",         "afp.file_bitmap.mod_date",
        FT_BOOLEAN, 16, NULL,  kFPModDateBit,
        "Return modification date if file", HFILL }},
 
-    { &hf_afp_file_bitmap_BackupDate,     
+    { &hf_afp_file_bitmap_BackupDate,
       { "Backup date",         "afp.file_bitmap.backup_date",
            FT_BOOLEAN, 16, NULL,  kFPBackupDateBit,
        "Return backup date if file", HFILL }},
 
-    { &hf_afp_file_bitmap_FinderInfo,     
+    { &hf_afp_file_bitmap_FinderInfo,
       { "Finder info",         "afp.file_bitmap.finder_info",
        FT_BOOLEAN, 16, NULL,  kFPFinderInfoBit,
        "Return finder info if file", HFILL }},
 
-    { &hf_afp_file_bitmap_LongName,               
+    { &hf_afp_file_bitmap_LongName,
       { "Long name",         "afp.file_bitmap.long_name",
            FT_BOOLEAN, 16, NULL,  kFPLongNameBit,
        "Return long name if file", HFILL }},
 
-    { &hf_afp_file_bitmap_ShortName,              
+    { &hf_afp_file_bitmap_ShortName,
       { "Short name",         "afp.file_bitmap.short_name",
        FT_BOOLEAN, 16, NULL,  kFPShortNameBit,
        "Return short name if file", HFILL }},
 
-    { &hf_afp_file_bitmap_NodeID,                 
+    { &hf_afp_file_bitmap_NodeID,
       { "File ID",         "afp.file_bitmap.fid",
            FT_BOOLEAN, 16, NULL,  kFPNodeIDBit,
        "Return file ID if file", HFILL }},
@@ -2976,7 +3777,7 @@ proto_register_afp(void)
            FT_BOOLEAN, 16, NULL,  kFPLaunchLimitBit,
        "Return launch limit if file", HFILL }},
 
-    { &hf_afp_file_bitmap_UTF8Name,               
+    { &hf_afp_file_bitmap_UTF8Name,
       { "UTF-8 name",         "afp.file_bitmap.UTF8_name",
        FT_BOOLEAN, 16, NULL,  kFPUTF8NameBit,
        "Return UTF-8 name if file", HFILL }},
@@ -2986,7 +3787,7 @@ proto_register_afp(void)
            FT_BOOLEAN, 16, NULL,  kFPExtRsrcForkLenBit,
        "Return extended (>2GB) resource fork size if file", HFILL }},
 
-    { &hf_afp_file_bitmap_UnixPrivs,              
+    { &hf_afp_file_bitmap_UnixPrivs,
       { "UNIX privileges",    "afp.file_bitmap.unix_privs",
            FT_BOOLEAN, 16, NULL,  kFPUnixPrivsBit_file,
        "Return UNIX privileges if file", HFILL }},
@@ -3222,27 +4023,37 @@ proto_register_afp(void)
       { "Extended resource fork size",         "afp.ext_resource_fork_len",
                FT_UINT64, BASE_DEC, NULL, 0x0,
        "Extended (>2GB) resource fork length", 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, 
+    { &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,
+       "Reply size", HFILL }},
+
+    { &hf_afp_start_index32,
+      { "Start index",         "afp.start_index32",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
        "First structure returned", HFILL }},
 
+    { &hf_afp_max_reply_size32,
+      { "Reply size",         "afp.reply_size32",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "Reply size", HFILL }},
+
     { &hf_afp_file_flag,
       { "Dir",         "afp.file_flag",
                FT_BOOLEAN, 8, NULL, 0x80,
@@ -3257,7 +4068,12 @@ proto_register_afp(void)
       { "Struct size",         "afp.struct_size",
                FT_UINT8, BASE_DEC, NULL,0,
        "Sizeof of struct", HFILL }},
-    
+
+    { &hf_afp_struct_size16,
+      { "Struct size",         "afp.struct_size16",
+               FT_UINT16, BASE_DEC, NULL,0,
+       "Sizeof of struct", HFILL }},
+
     { &hf_afp_flag,
       { "From",         "afp.flag",
                FT_UINT8, BASE_HEX, VALS(flag_vals), 0x80,
@@ -3277,22 +4093,22 @@ proto_register_afp(void)
       { "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 read/written", HFILL }},
-    
+
     { &hf_afp_newline_mask,
       { "Newline mask",  "afp.newline_mask",
                FT_UINT8, BASE_HEX, NULL, 0x0,
        "Value to AND bytes with when looking for newline", HFILL }},
-    
+
     { &hf_afp_newline_char,
       { "Newline char",  "afp.newline_char",
                FT_UINT8, BASE_HEX, NULL, 0x0,
        "Value to compare ANDed bytes with when looking for newline", HFILL }},
-    
+
     { &hf_afp_last_written,
       { "Last written",  "afp.last_written",
                FT_UINT32, BASE_DEC, NULL, 0x0,
@@ -3302,7 +4118,7 @@ proto_register_afp(void)
       { "Count",         "afp.actual_count",
                FT_INT32, BASE_DEC, NULL, 0x0,
        "Number of bytes returned by read/write", HFILL }},
-      
+
     { &hf_afp_ofork_len,
       { "New length",         "afp.ofork_len",
                FT_INT32, BASE_DEC, NULL, 0x0,
@@ -3318,6 +4134,16 @@ proto_register_afp(void)
                FT_UINT8, BASE_DEC, NULL, 0x0,
        "Path length", HFILL }},
 
+    { &hf_afp_path_unicode_len,
+      { "Len",  "afp.path_unicode_len",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "Path length (unicode)", HFILL }},
+
+    { &hf_afp_path_unicode_hint,
+      { "Unicode hint",  "afp.path_unicode_hint",
+               FT_UINT32, BASE_HEX, VALS(unicode_hint_vals), 0x0,
+       "Unicode hint", HFILL }},
+
     { &hf_afp_path_name,
       { "Name",  "afp.path_name",
                FT_STRING, BASE_NONE, NULL, 0x0,
@@ -3397,7 +4223,7 @@ proto_register_afp(void)
       { "Tag",         "afp.appl_tag",
                FT_UINT32, BASE_HEX, NULL, 0x0,
        "Application tag", HFILL }},
-       
+
     { &hf_afp_lock_op,
       { "unlock",         "afp.lock_op",
                FT_BOOLEAN, 8, NULL, 0x1,
@@ -3407,7 +4233,7 @@ proto_register_afp(void)
       { "End",         "afp.lock_from",
                FT_BOOLEAN, 8, NULL, 0x80,
        "Offset is relative to the end of the fork", HFILL }},
-    
+
     { &hf_afp_lock_offset,
       { "Offset",         "afp.lock_offset",
                FT_INT32, BASE_DEC, NULL, 0x0,
@@ -3523,6 +4349,107 @@ proto_register_afp(void)
                FT_BYTES, BASE_HEX, NULL, 0x0,
        "Reserved", HFILL }},
 
+
+    { &hf_afp_map_name_type,
+      { "Type",      "afp.map_name_type",
+               FT_UINT8, BASE_DEC, VALS(map_name_type_vals), 0x0,
+       "Map name type", HFILL }},
+
+    { &hf_afp_map_id_type,
+      { "Type",      "afp.map_id_type",
+               FT_UINT8, BASE_DEC, VALS(map_id_type_vals), 0x0,
+       "Map ID type", HFILL }},
+
+    { &hf_afp_map_id,
+      { "ID",             "afp.map_id",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "User/Group ID", HFILL }},
+
+    { &hf_afp_map_name,
+      { "Name",             "afp.map_name",
+               FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+       "User/Group name", HFILL }},
+
+    /* AFP 3.0 */
+    { &hf_afp_lock_offset64,
+      { "Offset",         "afp.lock_offset64",
+               FT_INT64, BASE_DEC, NULL, 0x0,
+       "First byte to be locked (64 bits)", HFILL }},
+
+    { &hf_afp_lock_len64,
+      { "Length",         "afp.lock_len64",
+               FT_INT64, BASE_DEC, NULL, 0x0,
+       "Number of bytes to be locked/unlocked (64 bits)", HFILL }},
+
+    { &hf_afp_lock_range_start64,
+      { "Start",         "afp.lock_range_start64",
+               FT_INT64, BASE_DEC, NULL, 0x0,
+       "First byte locked/unlocked (64 bits)", HFILL }},
+
+    { &hf_afp_offset64,
+      { "Offset",         "afp.offset64",
+               FT_INT64, BASE_DEC, NULL, 0x0,
+       "Offset (64 bits)", HFILL }},
+
+    { &hf_afp_rw_count64,
+      { "Count",         "afp.rw_count64",
+               FT_INT64, BASE_DEC, NULL, 0x0,
+       "Number of bytes to be read/written (64 bits)", HFILL }},
+
+    { &hf_afp_last_written64,
+      { "Last written",  "afp.last_written64",
+               FT_UINT64, BASE_DEC, NULL, 0x0,
+       "Offset of the last byte written (64 bits)", HFILL }},
+
+    { &hf_afp_ofork_len64,
+      { "New length",         "afp.ofork_len64",
+               FT_INT64, BASE_DEC, NULL, 0x0,
+       "New length (64 bits)", HFILL }},
+    { &hf_afp_session_token_type,
+      { "Type",         "afp.session_token_type",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
+       "Session token type", HFILL }},
+
+    /* FIXME FT_UINT32 in specs */
+    { &hf_afp_session_token_len,
+      { "Len",         "afp.session_token_len",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+       "Session token length", HFILL }},
+
+    { &hf_afp_session_token,
+      { "Token",         "afp.session_token",
+               FT_BYTES, BASE_HEX, NULL, 0x0,
+       "Session token", HFILL }},
+
+    { &hf_afp_user_flag,
+      { "Flag",         "afp.user_flag",
+               FT_UINT8, BASE_HEX, VALS(user_flag_vals), 0x01,
+       "User Info flag", HFILL }},
+
+    { &hf_afp_user_ID,
+      { "User ID",         "afp.user_ID",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "User ID", HFILL }},
+
+    { &hf_afp_group_ID,
+      { "Group ID",         "afp.group_ID",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+       "Group ID", HFILL }},
+
+    { &hf_afp_user_bitmap,
+      { "Bitmap",         "afp.user_bitmap",
+               FT_UINT16, BASE_HEX, NULL, 0,
+       "User Info bitmap", HFILL }},
+
+    { &hf_afp_user_bitmap_UID,
+      { "User ID",         "afp.user_bitmap.UID",
+               FT_BOOLEAN, 16, NULL, 0x01,
+       "User ID", HFILL }},
+
+    { &hf_afp_user_bitmap_GID,
+      { "Primary group ID",         "afp.user_bitmap.GID",
+               FT_BOOLEAN, 16, NULL, 0x02,
+       "Primary group ID", HFILL }},
   };
 
   static gint *ett[] = {
@@ -3547,6 +4474,7 @@ proto_register_afp(void)
        &ett_afp_cat_r_bitmap,
        &ett_afp_cat_spec,
        &ett_afp_vol_did,
+       &ett_afp_user_bitmap,
   };
 
   proto_afp = proto_register_protocol("AppleTalk Filing Protocol", "AFP", "afp");