diff options
author | Jaap Keuter <jaap.keuter@xs4all.nl> | 2008-09-30 07:06:32 +0000 |
---|---|---|
committer | Jaap Keuter <jaap.keuter@xs4all.nl> | 2008-09-30 07:06:32 +0000 |
commit | 8b1a8faf1b2d41301e3fa2e2a1c3f0eee953dd0a (patch) | |
tree | 773763bf37f19bc68a8d85b0ac2aebd77cb64999 /epan/dissectors/packet-nfs.c | |
parent | e39ccb6987b146eb2e608e2bb1c1519c1a14a37b (diff) |
From Alex:
NFSV4 parsing of the GETATTR reply is broken. I'm not sure what is going on,
but I re-wrote the GETATTR parsing anyways and my version of the parsing does not
exibit the same problems.
svn path=/trunk/; revision=26304
Diffstat (limited to 'epan/dissectors/packet-nfs.c')
-rw-r--r-- | epan/dissectors/packet-nfs.c | 428 |
1 files changed, 421 insertions, 7 deletions
diff --git a/epan/dissectors/packet-nfs.c b/epan/dissectors/packet-nfs.c index 6c3fcc1611..a8ef3da3fb 100644 --- a/epan/dissectors/packet-nfs.c +++ b/epan/dissectors/packet-nfs.c @@ -477,6 +477,13 @@ static gint ett_nfs_create4 = -1; static gint ett_nfs_delegpurge4 = -1; static gint ett_nfs_delegreturn4 = -1; static gint ett_nfs_getattr4 = -1; +static gint ett_nfs_getattr4_args = -1; +static gint ett_nfs_getattr4_resp = -1; +static gint ett_nfs4_resok4 = -1; +static gint ett_nfs4_obj_attrs = -1; +static gint ett_nfs4_fattr4_new_attr_vals = -1; +static gint ett_nfs4_fattr4_attrmask = -1; +static gint ett_nfs4_attribute = -1; static gint ett_nfs_getfh4 = -1; static gint ett_nfs_link4 = -1; static gint ett_nfs_lock4 = -1; @@ -520,6 +527,7 @@ static gint ett_nfs_lock_owner4 = -1; static gint ett_nfs_cb_client4 = -1; static gint ett_nfs_client_id4 = -1; static gint ett_nfs_bitmap4 = -1; +static gint ett_nfs_attr_request = -1; static gint ett_nfs_fattr4 = -1; static gint ett_nfs_fsid4 = -1; static gint ett_nfs_fs_locations4 = -1; @@ -6323,7 +6331,7 @@ dissect_nfs_fattr4_fh_expire_type(tvbuff_t *tvb, int offset, proto_tree *tree) if (expire_type == FH4_PERSISTENT) { proto_tree_add_text(expire_type_tree, tvb, offset, 4, "%s", - decode_enumerated_bitfield(expire_type, FH4_PERSISTENT, 8, + decode_enumerated_bitfield(expire_type, 0xFFFFFFFF, 32, nfs4_fattr4_fh_expire_type_names, "%s")); } else @@ -6531,6 +6539,72 @@ static const value_string names_fattr4[] = { #define MAX_BITMAP_LEN 10 static int +dissect_nfs4_bitmap4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, + guint32 bitmap_size, guint32 **bitmap, guint32 *attr_count) { + guint32 i,j,count,attribute_number,current_bitmap; + guint32 bitmask = 0x00000000; + + proto_item *bitmap_item = NULL; + proto_tree *bitmap_tree = NULL; + + *attr_count = 0; + if(bitmap_size > 0) { + *bitmap = se_alloc_array(guint32, bitmap_size); + } + + for(i = 0; i < bitmap_size; i++) { + current_bitmap = tvb_get_ntohl(tvb, offset); + (*bitmap)[i] = current_bitmap; + bitmap_item = proto_tree_add_text(tree, tvb, offset, 4, "bitmap[%u] = 0x%08x", i, current_bitmap); + bitmap_tree = proto_item_add_subtree(bitmap_item, ett_nfs_bitmap4); + for(count = 0; current_bitmap; current_bitmap >>= 1) { + count += current_bitmap & 1; + } + current_bitmap = (*bitmap)[i]; + proto_tree_add_text(bitmap_tree, tvb, offset, 4, "[%u attribute%s requested]", count, plurality(count, "", "s")); + *attr_count += count; + bitmask = 0x00000001; + for(j = 0; j < 32; j++) { + attribute_number = 32*i + j; + if((current_bitmap & bitmask) == bitmask) { + proto_tree_add_uint(bitmap_tree, + (attribute_number < FATTR4_ACL) ? hf_nfs_mand_attr : hf_nfs_recc_attr, + tvb, offset, 4, attribute_number); + } + bitmask <<= 1; + } + offset += 4; + } + + return offset; +} + +static int +dissect_nfs4_attr_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint8 flag) +{ + guint32 bitmap_size = 0; + guint32 *bitmap = NULL; + guint32 attr_count = 0; + + proto_item *ar_item = NULL; + proto_tree *ar_tree = NULL; + + bitmap_size = tvb_get_ntohl(tvb, offset); + if(bitmap_size > MAX_BITMAP_LEN) { + proto_tree_add_text(tree, tvb, offset, 4, "attr_request length is too big: %u", bitmap_size); + THROW(ReportedBoundsError); + } + tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_size * 4); + offset += 4; + + ar_item = proto_tree_add_text(tree, tvb, offset, bitmap_size * 4, "%s", flag?"attr_request":"attrmask"); + ar_tree = proto_item_add_subtree(ar_item, ett_nfs_attr_request); + offset = dissect_nfs4_bitmap4(tvb, offset, pinfo, ar_tree, bitmap_size, &bitmap, &attr_count); + + return offset; +} + +static int dissect_nfs_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type) { @@ -6888,6 +6962,325 @@ dissect_nfs_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo, } static int +dissect_nfs4_attribute(tvbuff_t *tvb, int offset, packet_info *pinfo , proto_tree *tree, guint32 attribute_number) +{ + proto_item *attribute_item; + proto_tree *attribute_tree; + + attribute_item = proto_tree_add_uint(tree, + (attribute_number < FATTR4_ACL) ? hf_nfs_mand_attr : hf_nfs_recc_attr, + tvb, offset, 0, attribute_number); + attribute_tree = proto_item_add_subtree(attribute_item, ett_nfs4_attribute); + + switch(attribute_number) { + case FATTR4_SUPPORTED_ATTRS: + offset = dissect_nfs4_attr_request(tvb, offset, pinfo, attribute_tree, 0); + break; + + case FATTR4_TYPE: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_ftype4, offset); + break; + + case FATTR4_FH_EXPIRE_TYPE: + offset = dissect_nfs_fattr4_fh_expire_type(tvb, offset, attribute_tree); + break; + + case FATTR4_CHANGE: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_changeid4, offset); + break; + + case FATTR4_SIZE: + offset = dissect_rpc_uint64(tvb,attribute_tree, hf_nfs_fattr4_size, offset); + break; + + case FATTR4_LINK_SUPPORT: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_link_support, offset); + break; + + case FATTR4_SYMLINK_SUPPORT: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_symlink_support, offset); + break; + + case FATTR4_NAMED_ATTR: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_named_attr, offset); + break; + + case FATTR4_FSID: + offset = dissect_nfs_fsid4(tvb, offset, attribute_tree, "fattr4_fsid"); + break; + + case FATTR4_UNIQUE_HANDLES: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_unique_handles, offset); + break; + + case FATTR4_LEASE_TIME: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_lease_time, offset); + break; + + case FATTR4_RDATTR_ERROR: + offset = dissect_nfs_nfsstat4(tvb, offset, attribute_tree, NULL); + break; + + case FATTR4_ACL: + offset = dissect_nfs_fattr4_acl(tvb, offset, pinfo, attribute_tree); + break; + + case FATTR4_ACLSUPPORT: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_aclsupport, offset); + break; + + case FATTR4_ARCHIVE: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_archive, offset); + break; + + case FATTR4_CANSETTIME: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_cansettime, offset); + break; + + case FATTR4_CASE_INSENSITIVE: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_case_insensitive, offset); + break; + + case FATTR4_CASE_PRESERVING: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_case_preserving, offset); + break; + + case FATTR4_CHOWN_RESTRICTED: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_chown_restricted, offset); + break; + + case FATTR4_FILEID: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_fileid, offset); + break; + + case FATTR4_FILES_AVAIL: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_files_avail, offset); + break; + + case FATTR4_FILEHANDLE: + offset = dissect_nfs_fh4(tvb, offset, pinfo, attribute_tree, "fattr4_filehandle"); + break; + + case FATTR4_FILES_FREE: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_files_free, offset); + break; + + case FATTR4_FILES_TOTAL: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_files_total, offset); + break; + + case FATTR4_FS_LOCATIONS: + offset = dissect_nfs_fs_locations4(tvb, pinfo, offset, attribute_tree, "fattr4_fs_locations"); + break; + + case FATTR4_HIDDEN: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_hidden, offset); + break; + + case FATTR4_HOMOGENEOUS: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_homogeneous, offset); + break; + + case FATTR4_MAXFILESIZE: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_maxfilesize, offset); + break; + + case FATTR4_MAXLINK: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_maxlink, offset); + break; + + case FATTR4_MAXNAME: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_maxname, offset); + break; + + case FATTR4_MAXREAD: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_maxread, offset); + break; + + case FATTR4_MAXWRITE: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_maxwrite, offset); + break; + + case FATTR4_MIMETYPE: + offset = dissect_nfs_utf8string(tvb, offset, attribute_tree, hf_nfs_fattr4_mimetype, NULL); + break; + + case FATTR4_MODE: + offset = dissect_nfs_mode4(tvb, offset, attribute_tree, "fattr4_mode"); + break; + + case FATTR4_NO_TRUNC: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_no_trunc, offset); + break; + + case FATTR4_NUMLINKS: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_numlinks, offset); + break; + + case FATTR4_OWNER: + offset = dissect_nfs_utf8string(tvb, offset, attribute_tree, hf_nfs_fattr4_owner, NULL); + break; + + case FATTR4_OWNER_GROUP: + offset = dissect_nfs_utf8string(tvb, offset, attribute_tree, hf_nfs_fattr4_owner_group, NULL); + break; + + case FATTR4_QUOTA_AVAIL_HARD: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_quota_hard, offset); + break; + + case FATTR4_QUOTA_AVAIL_SOFT: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_quota_soft, offset); + break; + + case FATTR4_QUOTA_USED: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_quota_used, offset); + break; + + case FATTR4_RAWDEV: + offset = dissect_nfs_specdata4(tvb, offset, attribute_tree); + break; + + case FATTR4_SPACE_AVAIL: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_avail, offset); + break; + + case FATTR4_SPACE_FREE: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_free, offset); + break; + + case FATTR4_SPACE_TOTAL: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_total, offset); + break; + + case FATTR4_SPACE_USED: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_space_used, offset); + break; + + case FATTR4_SYSTEM: + offset = dissect_rpc_bool(tvb, attribute_tree, hf_nfs_fattr4_system, offset); + break; + + case FATTR4_TIME_ACCESS: + case FATTR4_TIME_BACKUP: + case FATTR4_TIME_CREATE: + case FATTR4_TIME_DELTA: + case FATTR4_TIME_METADATA: + case FATTR4_TIME_MODIFY: + offset = dissect_nfs_nfstime4(tvb, offset, attribute_tree); + break; + + case FATTR4_TIME_ACCESS_SET: + case FATTR4_TIME_MODIFY_SET: + offset = dissect_nfs_settime4(tvb, offset, attribute_tree, "settime4"); + break; + + case FATTR4_MOUNTED_ON_FILEID: + offset = dissect_rpc_uint64(tvb, attribute_tree, hf_nfs_fattr4_mounted_on_fileid, offset); + break; + + case FATTR4_FS_LAYOUT_TYPE: + offset = dissect_nfs_fs_layout_type(tvb, attribute_tree, offset); + break; + + case FATTR4_LAYOUT_BLKSIZE: + offset = dissect_rpc_uint32(tvb, attribute_tree, hf_nfs_fattr4_layout_blksize, offset); + break; + + default: + break; + } + + return offset; +} + +static int +dissect_nfs4_attrlist4(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_, + guint32 bitmap_size, guint32 *bitmap, guint32 attr_count _U_) +{ + + guint32 i,j,attribute_number; + guint32 bitmask = 0x00000000; + + for(i = 0; i < bitmap_size; i++) { + bitmask = 0x00000001; + for(j = 0; j < 32; j++) { + attribute_number = 32 * i + j; + if((bitmap[i] & bitmask) == bitmask) { + offset = dissect_nfs4_attribute(tvb, offset, pinfo, tree, attribute_number); + } + bitmask <<= 1; + } + } + + return offset; +} + +static int +dissect_nfs_fattr4_new(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) +{ + guint32 bitmap_size = 0; + guint32 *bitmap = NULL; + guint32 attr_count = 0; + guint32 attrlist4_size; + + proto_item *fattr_item; + proto_tree *fattr_tree; + + bitmap_size = tvb_get_ntohl(tvb, offset); + if(bitmap_size > MAX_BITMAP_LEN) { + proto_tree_add_text(tree, tvb, offset, 4, "attrmask length is too big: %u", bitmap_size); + THROW(ReportedBoundsError); + } + tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_size * 4); + offset += 4; + + fattr_item = proto_tree_add_text(tree, tvb, offset - 4, 4 + bitmap_size * 4, "attrmask"); + fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs4_fattr4_attrmask); + offset = dissect_nfs4_bitmap4(tvb, offset, pinfo, fattr_tree, bitmap_size, &bitmap, &attr_count); + + attrlist4_size = tvb_get_ntohl(tvb, offset); + offset += 4; + fattr_item = proto_tree_add_text(tree, tvb, offset, attrlist4_size, "attr_vals"); + fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs4_fattr4_new_attr_vals); + if(tree) { + offset = dissect_nfs4_attrlist4(tvb, offset, pinfo, fattr_tree, bitmap_size, bitmap, attr_count); + } else { + offset += attrlist4_size; + } + + return offset; +} + +static int +dissect_nfs4_attr_resp_ok(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { + + proto_item *getattr_res_item = NULL; + proto_tree *getattr_res_tree = NULL; + + getattr_res_item = proto_tree_add_text(tree, tvb, offset, 0, "obj_attributes"); + getattr_res_tree = proto_item_add_subtree(getattr_res_item, ett_nfs4_obj_attrs); + + offset = dissect_nfs_fattr4_new(tvb, offset, pinfo, getattr_res_tree); + + return offset; +} + +static int +dissect_nfs4_attr_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) +{ + proto_item *getattr_res_item = NULL; + proto_tree *getattr_res_tree = NULL; + + getattr_res_item = proto_tree_add_text(tree, tvb, offset, 0, "resok4"); + getattr_res_tree = proto_item_add_subtree(getattr_res_item, ett_nfs4_resok4); + + offset = dissect_nfs4_attr_resp_ok(tvb, offset, pinfo, getattr_res_tree); + + return offset; +} + +static int dissect_nfs_fattr4(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { @@ -8236,11 +8629,17 @@ dissect_nfs_argop4(tvbuff_t *tvb, int offset, packet_info *pinfo, offset = dissect_nfs_stateid4(tvb, offset, newftree); break; - case NFS4_OP_GETATTR: - offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree, - FATTR4_BITMAP_ONLY); + case NFS4_OP_GETATTR: + { + proto_item *getattr_req_item = NULL; + proto_tree *getattr_req_tree = NULL; + + getattr_req_item = proto_tree_add_text(newftree,tvb,offset,0,"%s","GETATTR4args"); + getattr_req_tree = proto_item_add_subtree(getattr_req_item,ett_nfs_getattr4_args); + offset = dissect_nfs4_attr_request(tvb, offset, pinfo, getattr_req_tree, 1); + } break; - + case NFS4_OP_GETFH: break; @@ -8664,8 +9063,15 @@ dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo, FATTR4_BITMAP_ONLY); break; - case NFS4_OP_GETATTR: - offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree); + case NFS4_OP_GETATTR: + { + proto_item *getattr_res_item = NULL; + proto_tree *getattr_res_tree = NULL; + + getattr_res_item = proto_tree_add_text(newftree,tvb,offset,0,"%s","GETATTR4res"); + getattr_res_tree = proto_item_add_subtree(getattr_res_item,ett_nfs_getattr4_resp); + offset = dissect_nfs4_attr_resp(tvb, offset, pinfo, getattr_res_tree); + } break; case NFS4_OP_GETFH: @@ -10474,6 +10880,13 @@ proto_register_nfs(void) &ett_nfs_delegpurge4, &ett_nfs_delegreturn4, &ett_nfs_getattr4, + &ett_nfs_getattr4_args, + &ett_nfs_getattr4_resp, + &ett_nfs4_resok4, + &ett_nfs4_obj_attrs, + &ett_nfs4_fattr4_new_attr_vals, + &ett_nfs4_fattr4_attrmask, + &ett_nfs4_attribute, &ett_nfs_getfh4, &ett_nfs_link4, &ett_nfs_lock4, @@ -10525,6 +10938,7 @@ proto_register_nfs(void) &ett_nfs_cb_client4, &ett_nfs_client_id4, &ett_nfs_bitmap4, + &ett_nfs_attr_request, &ett_nfs_fattr4, &ett_nfs_fsid4, &ett_nfs_fs_locations4, |