* Routines for afp packet dissection
* Copyright 2002, Didier Gautheron <dgautheron@magic.fr>
*
- * $Id: packet-afp.c,v 1.24 2002/10/17 22:38:19 guy Exp $
+ * $Id: packet-afp.c,v 1.30 2003/05/15 05:53:43 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
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 AFP_ADDCMT 56
#define AFP_RMVCMT 57
#define AFP_GETCMT 58
+#define AFP_ZZZ 122
#define AFP_ADDICON 192
/* AFP 3.0 new calls */
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_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 int hf_afp_session_token_timestamp = -1;
static dissector_handle_t data_handle;
{AFP_LOGIN_EXT, "FPLoginExt" },
{AFP_GETSESSTOKEN, "FPGetSessionToken" },
{AFP_DISCTOLDSESS, "FPDisconnectOldSession" },
+ {AFP_ZZZ, "FPzzz" },
{AFP_ADDICON, "FPAddIcon" },
{0, NULL }
};
#define kMounted (1 << 3)
#define kInExpFolder (1 << 4)
+/* AFP 3.1 getsession token type */
+#define kLoginWithoutID 0
+#define kLoginWithID 1
+#define kReconnWithID 2
+#define kLoginWithTimeAndID 3
+#define kReconnWithTimeAndID 4
+
+static const value_string token_type_vals[] = {
+ {kLoginWithoutID, "LoginWithoutID"},
+ {kLoginWithID, "LoginWithID"},
+ {kReconnWithID, "ReconnWithID"},
+ {kLoginWithTimeAndID, "LoginWithTimeAndID"},
+ {kReconnWithTimeAndID, "ReconnWithTimeAndID"},
+ {0, NULL } };
+
#define hash_init_count 20
/* Hash functions */
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) {
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;
}
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) {
+ /* FIXME AFP3.x reuses PDINFO bit for UTF8.
+ * In enumerate_ext it's pad with 4 bytes, PDINFO was 6 bytes,
+ * but not in catsearch_ext.
+ * Last but not least there's a bug in OSX catsearch_ext for spec2
+ * offset is off by 2 bytes.
+ */
+
tp_ofs = unameoff +org_offset;
+ if (tp_ofs > offset) {
+ PAD(4);
+ }
+ else if (tp_ofs < offset) {
+ tp_ofs = offset;
+ }
proto_tree_add_item( tree, hf_afp_path_unicode_hint, tvb, tp_ofs, 4,FALSE);
tp_ofs += 4;
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;
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) {
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)
/* -------------------------- */
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;
for (i = 0; i < count; i++) {
org = offset;
if (ext) {
- size = tvb_get_ntohs(tvb, offset);
+ size = tvb_get_ntohs(tvb, offset) +add *2;
decal = 2;
}
else {
{
return reply_enumerate(tvb, tree, offset, 1);
}
+
/* **************************/
static gint
-dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ptree, gint offset)
+catsearch_spec(tvbuff_t *tvb, proto_tree *ptree, gint offset, int ext, guint32 bitmap, const gchar *label)
+{
+ proto_tree *tree = NULL;
+ proto_item *item;
+ guint16 size;
+ gint org;
+
+ org = offset;
+
+ if (ext) {
+ size = tvb_get_ntohs(tvb, offset) +2;
+ }
+ else {
+ size = tvb_get_guint8(tvb, offset) +2;
+ }
+
+ item = proto_tree_add_text(ptree, tvb, offset, size, label);
+ tree = proto_item_add_subtree(item, ett_afp_cat_spec);
+
+ 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++;
+ PAD(1);
+ }
+
+ offset = parse_file_bitmap(tree, tvb, offset, bitmap,0);
+ offset = org +size;
+
+ return offset;
+}
+
+/* ------------------------- */
+static gint
+query_catsearch(tvbuff_t *tvb, proto_tree *ptree, gint offset, int ext)
{
proto_tree *tree = NULL;
proto_item *item;
guint16 f_bitmap;
guint16 d_bitmap;
guint32 r_bitmap;
- guint8 size;
- gint org;
if (!ptree)
return offset;
d_bitmap = decode_dir_bitmap(ptree, tvb, offset);
offset += 2;
- /* FIXME req bitmap */
+ /* FIXME it's req bitmap and first bit is for partial match */
item = proto_tree_add_text(ptree, tvb, offset, 4, "Request bitmap");
tree = proto_item_add_subtree(item, ett_afp_cat_r_bitmap);
r_bitmap = decode_file_bitmap(tree, tvb, offset+2);
offset += 4;
/* spec 1 */
- org = offset;
- size = tvb_get_guint8(tvb, offset) +2;
-
- item = proto_tree_add_text(ptree, tvb, offset, size, "Spec 1");
- tree = proto_item_add_subtree(item, ett_afp_cat_spec);
-
- 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;
+ offset = catsearch_spec(tvb, ptree, offset, ext, r_bitmap, "Spec 1");
/* spec 2 */
- org = offset;
- size = tvb_get_guint8(tvb, offset) +2;
-
- item = proto_tree_add_text(ptree, tvb, offset, size, "Spec 2");
- tree = proto_item_add_subtree(item, ett_afp_cat_spec);
+ offset = catsearch_spec(tvb, ptree, offset, ext, r_bitmap, "Spec 2");
+
+ return offset;
+}
- proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
- offset++;
- PAD(1);
+/* ------------------------- */
+static gint
+dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ptree, gint offset)
+{
+ return query_catsearch(tvb, ptree, offset, 0);
- offset = parse_file_bitmap(tree, tvb, offset, r_bitmap,0);
- offset = org +size;
+}
+/* **************************/
+static gint
+dissect_query_afp_cat_search_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ptree, gint offset)
+{
+ return query_catsearch(tvb, ptree, offset, 1);
- return offset;
}
-/* -------------------------- */
+/* **************************/
static gint
-dissect_reply_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+reply_catsearch(tvbuff_t *tvb, proto_tree *tree, gint offset, int ext)
{
proto_tree *sub_tree = NULL;
proto_item *item;
}
offset += 4;
- return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap, 2, 0);
+ return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap, 2, ext);
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ return reply_catsearch(tvb, tree, offset, 0);
+}
+
+/* **************************/
+static gint
+dissect_reply_afp_cat_search_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ return reply_catsearch(tvb, tree, offset, 1);
}
/* **************************/
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;
/* **************************/
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;
/* ***************************/
static gint
+decode_uam_parameters(const char *uam, int len_uam, tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ int len;
+
+ if (!strncasecmp(uam, "Cleartxt passwrd", len_uam)) {
+ if ((offset & 1))
+ PAD(1);
+
+ len = 8; /* tvb_strsize(tvb, offset);*/
+ proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
+ offset += 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 = tvb_get_guint8(tvb, offset);
- uam = tvb_get_ptr(tvb, offset +1, len);
+ 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 +1;
-
- if (!strncasecmp(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;
+ offset += len_uam +1;
- len = 8; /* tvb_strsize(tvb, offset);*/
- proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
- offset += len;
- }
- else if (!strncasecmp(uam, "No User Authent", len)) {
+ 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);
}
/* ***************************/
default:
break;
}
- PAD(1);
- if (!strncasecmp(uam, "Cleartxt passwrd", len_uam)) {
- len = 8; /* tvb_strsize(tvb, offset);*/
- proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
- offset += len;
- }
- else if (!strncasecmp(uam, "No User Authent", len_uam)) {
- }
- return(offset);
+ 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;
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;
{
PAD(1);
+ add_info_fork(tvb, pinfo, offset);
proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
offset += 2;
{
PAD(1);
+ add_info_fork(tvb, pinfo, offset);
proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
offset += 2;
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;
/* ************************** */
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;
/* ************************** */
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;
}
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;
}
no reply
*/
static gint
-dissect_query_afp_add_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+decode_dt_did(proto_tree *tree, tvbuff_t *tvb, gint offset)
{
-
- PAD(1);
+ /* FIXME it's not volume but dt cf decode_name*/
+ Vol = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(tree, hf_afp_dt_ref, 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;
+}
+
+/* -------------------------- */
+static gint
+dissect_query_afp_add_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_dt_did(tree, tvb, offset);
proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
offset += 4;
{
PAD(1);
- proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
- offset += 2;
-
- proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
- offset += 4;
+ offset = decode_dt_did(tree, tvb, offset);
proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
offset += 4;
static gint
dissect_query_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
{
+guint16 token;
+int len;
PAD(1);
+ token = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
offset += 2;
+ if (token == kLoginWithoutID) /* 0 */
+ return offset;
+
+ len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ switch (token) {
+ case kLoginWithTimeAndID:
+ case kReconnWithTimeAndID:
+ proto_tree_add_item(tree, hf_afp_session_token_timestamp, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+
+ proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
+ offset += len;
return offset;
}
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 : or it's 4 bytes with no token type, or it's 2 bytes */
+ size = 4;
+ if (size == 2) {
+ proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+ offset += 2;
+ }
len = tvb_get_ntohl(tvb, offset);
- /* FIXME spec and capture differ : spec 4 bytes, capture 2 bytes? */
- 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_len, tvb, offset, size,FALSE);
+ offset += size;
proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
offset += len;
case AFP_EXCHANGEFILE:
offset = dissect_query_afp_exchange_file(tvb, pinfo, afp_tree, offset);break;
case AFP_CATSEARCH_EXT:
+ offset = dissect_query_afp_cat_search_ext(tvb, pinfo, afp_tree, offset);break;
case AFP_CATSEARCH:
offset = dissect_query_afp_cat_search(tvb, pinfo, afp_tree, offset);break;
case AFP_GETICON:
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:
+ offset = dissect_reply_afp_cat_search_ext(tvb, pinfo, afp_tree, offset);break;
case AFP_CATSEARCH:
offset = dissect_reply_afp_cat_search(tvb, pinfo, afp_tree, offset);break;
case AFP_GTICNINFO:
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*/,
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,
+ FT_UINT16, BASE_HEX, VALS(token_type_vals), 0x0,
"Session token type", HFILL }},
+ /* FIXME FT_UINT32 in specs */
{ &hf_afp_session_token_len,
{ "Len", "afp.session_token_len",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Session token length", HFILL }},
+ { &hf_afp_session_token_timestamp,
+ { "Time stamp", "afp.session_token_timestamp",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Session time stamp", HFILL }},
+
{ &hf_afp_session_token,
{ "Token", "afp.session_token",
FT_BYTES, BASE_HEX, NULL, 0x0,