#include <epan/exceptions.h>
#include <epan/expert.h>
#include <epan/to_str.h>
+#include <epan/decode_as.h>
#include <wsutil/crc16.h>
#include <wsutil/crc32.h>
#include "packet-nfs.h"
/* NON-NFS-version-specific hf variables */
static int proto_nfs = -1;
+static int proto_nfs_unknown = -1;
+static int proto_nfs_svr4 = -1;
+static int proto_nfs_knfsd_le = -1;
+static int proto_nfs_nfsd_le = -1;
+static int proto_nfs_knfsd_new = -1;
+static int proto_nfs_ontap_v3 = -1;
+static int proto_nfs_ontap_v4 = -1;
+static int proto_nfs_ontap_gx_v3 = -1;
+static int proto_nfs_celerra_vnx = -1;
+static int proto_nfs_gluster = -1;
+static int proto_nfs_dcache = -1;
static int hf_nfs_access_check = -1;
static int hf_nfs_access_supported = -1;
static int hf_nfs_access_rights = -1;
static int hf_nfs_access_denied = -1;
static int hf_nfs_fh_length = -1;
static int hf_nfs_fh_hash = -1;
-static int hf_nfs_fh_decode_as = -1;
static int hf_nfs_fh_fhandle_data = -1;
static int hf_nfs_fh_mount_fileid = -1;
static int hf_nfs_fh_mount_generation = -1;
static int hf_nfs4_universal_address_ipv4 = -1;
static int hf_nfs4_universal_address_ipv6 = -1;
static int hf_nfs4_getdevinfo = -1;
-static int hf_nfs4_ffda_version = -1;
-static int hf_nfs4_ffda_minorversion = -1;
-static int hf_nfs4_ffda_tightly_coupled = -1;
-static int hf_nfs4_ffda_rsize = -1;
-static int hf_nfs4_ffda_wsize = -1;
+static int hf_nfs4_ff_version = -1;
+static int hf_nfs4_ff_minorversion = -1;
+static int hf_nfs4_ff_tightly_coupled = -1;
+static int hf_nfs4_ff_rsize = -1;
+static int hf_nfs4_ff_wsize = -1;
+static int hf_nfs4_fattr_clone_blocksize = -1;
+static int hf_nfs4_fattr_space_freed = -1;
+static int hf_nfs4_fattr_change_attr_type = -1;
+static int hf_nfs4_ff_layout_flags = -1;
+static int hf_nfs4_ff_layout_flags_no_layoutcommit = -1;
+static int hf_nfs4_ff_synthetic_owner = -1;
+static int hf_nfs4_ff_synthetic_owner_group = -1;
+static int hf_nfs4_ff_bytes_completed = -1;
+static int hf_nfs4_ff_bytes_not_delivered = -1;
+static int hf_nfs4_ff_bytes_requested = -1;
+static int hf_nfs4_ff_local = -1;
+static int hf_nfs4_ff_ops_completed = -1;
+static int hf_nfs4_ff_ops_requested = -1;
+static int hf_nfs4_io_bytes = -1;
+static int hf_nfs4_io_count = -1;
+static int hf_nfs4_layoutstats = -1;
+static int hf_nfs4_callback_stateids = -1;
+static int hf_nfs4_callback_stateids_index = -1;
+static int hf_nfs4_consecutive = -1;
+static int hf_nfs4_netloc = -1;
+static int hf_nfs4_netloc_type = -1;
+static int hf_nfs4_nl_name = -1;
+static int hf_nfs4_nl_url = -1;
+static int hf_nfs4_source_server_index = -1;
+static int hf_nfs4_source_servers = -1;
+static int hf_nfs4_synchronous = -1;
+static int hf_nfs4_device_error_count = -1;
+static int hf_nfs4_device_errors_index = -1;
+static int hf_nfs4_ff_ioerrs_count = -1;
+static int hf_nfs4_ff_ioerrs_index = -1;
+static int hf_nfs4_ff_ioerrs_length = -1;
+static int hf_nfs4_ff_ioerrs_offset = -1;
+static int hf_nfs4_ff_iostats_count = -1;
+static int hf_nfs4_ff_iostats_index = -1;
+static int hf_nfs4_io_error_op = -1;
+static int hf_nfs4_io_hints_mask = -1;
+static int hf_nfs4_io_hint_count = -1;
+static int hf_nfs4_io_advise_hint = -1;
+static int hf_nfs4_bytes_copied = -1;
+static int hf_nfs4_read_plus_content_type = -1;
+static int hf_nfs4_read_plus_content_count = -1;
+static int hf_nfs4_read_plus_content_index = -1;
+static int hf_nfs4_block_size = -1;
+static int hf_nfs4_block_count = -1;
+static int hf_nfs4_reloff_blocknum = -1;
+static int hf_nfs4_blocknum = -1;
+static int hf_nfs4_reloff_pattern = -1;
+static int hf_nfs4_pattern_hash = -1;
+
static gint ett_nfs = -1;
static gint ett_nfs_fh_encoding = -1;
static gint ett_nfs_fh_mount = -1;
static gint ett_nfs4_seek = -1;
static gint ett_nfs4_chan_attrs = -1;
static gint ett_nfs4_want_notify_flags = -1;
+static gint ett_nfs4_ff_layout_flags = -1;
+static gint ett_nfs4_layoutstats = -1;
+static gint ett_nfs4_io_info = -1;
+static gint ett_nfs4_io_latency = -1;
+static gint ett_nfs4_io_time = -1;
+static gint ett_nfs4_callback_stateids_sub = -1;
+static gint ett_nfs4_source_servers_sub = -1;
+static gint ett_nfs4_copy = -1;
+static gint ett_nfs4_copy_notify = -1;
+static gint ett_nfs4_device_errors_sub = -1;
+static gint ett_nfs4_layouterror = -1;
+static gint ett_nfs4_ff_ioerrs_sub = -1;
+static gint ett_nfs4_ff_iostats_sub = -1;
+static gint ett_nfs4_clone = -1;
+static gint ett_nfs4_offload_cancel = -1;
+static gint ett_nfs4_offload_status = -1;
+static gint ett_nfs4_io_advise = -1;
+static gint ett_nfs4_read_plus = -1;
+static gint ett_nfs4_read_plus_content_sub = -1;
+static gint ett_nfs4_write_same = -1;
static expert_field ei_nfs_too_many_ops = EI_INIT;
static expert_field ei_nfs_not_vnx_file = EI_INIT;
static expert_field ei_protocol_violation = EI_INIT;
+static expert_field ei_nfs_too_many_bitmaps = EI_INIT;
/* Types of fhandles we can dissect */
static dissector_table_t nfs_fhandle_table;
-#define FHT_UNKNOWN 0
-#define FHT_SVR4 1
-#define FHT_LINUX_KNFSD_LE 2
-#define FHT_LINUX_NFSD_LE 3
-#define FHT_LINUX_KNFSD_NEW 4
-#define FHT_NETAPP 5
-#define FHT_NETAPP_V4 6
-#define FHT_NETAPP_GX_V3 7
-#define FHT_CELERRA_VNX 8
-#define FHT_GLUSTER 9
-#define FHT_DCACHE 10
-
-static const enum_val_t nfs_fhandle_types[] = {
- { "unknown", "Unknown", FHT_UNKNOWN },
- { "svr4", "SVR4", FHT_SVR4 },
- { "knfsd_le", "KNFSD_LE", FHT_LINUX_KNFSD_LE },
- { "nfsd_le", "NFSD_LE", FHT_LINUX_NFSD_LE },
- { "knfsd_new", "KNFSD_NEW", FHT_LINUX_KNFSD_NEW },
- { "ontap_v3", "ONTAP_V3", FHT_NETAPP },
- { "ontap_v4", "ONTAP_V4", FHT_NETAPP_V4},
- { "ontap_gx_v3", "ONTAP_GX_V3", FHT_NETAPP_GX_V3},
- { "celerra_vnx", "CELERRA_VNX", FHT_CELERRA_VNX },
- { "gluster", "GLUSTER", FHT_GLUSTER },
- { "dcache", "dCache", FHT_DCACHE },
- { NULL, NULL, 0 }
-};
-/* decode all nfs filehandles as this type */
-static gint default_nfs_fhandle_type = FHT_UNKNOWN;
-
typedef struct nfs_fhandle_data {
int len;
const unsigned char *fh;
static int dissect_nfs4_stateid(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *hash);
-static void reg_callback(int cbprog);
+static void nfs_prompt(packet_info *pinfo _U_, gchar* result)
+{
+ g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Decode NFS file handles as");
+}
+
+static gpointer nfs_value(packet_info *pinfo _U_)
+{
+ return 0;
+}
/* This function will store one nfs filehandle in our global tree of
* filehandles.
}
-static gboolean
-nfs_name_snoop_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
+static void
+nfs_name_snoop_value_destroy(gpointer value)
{
nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
- if (nns->name) {
- g_free((gpointer)nns->name);
- nns->name = NULL;
- nns->name_len = 0;
- }
- if (nns->full_name) {
- g_free((gpointer)nns->full_name);
- nns->full_name = NULL;
- nns->full_name_len = 0;
- }
- if (nns->parent) {
- g_free((gpointer)nns->parent);
- nns->parent = NULL;
- nns->parent_len = 0;
- }
- if (nns->fh) {
- g_free((gpointer)nns->fh);
- nns->fh = NULL;
- nns->fh_length = 0;
- }
+ g_free((gpointer)nns->name);
+ g_free((gpointer)nns->full_name);
+ g_free((gpointer)nns->parent);
+ g_free((gpointer)nns->fh);
g_free(nns);
- return TRUE;
}
static void
nfs_name_snoop_init(void)
{
- if (nfs_name_snoop_unmatched != NULL) {
- g_hash_table_foreach_remove(nfs_name_snoop_unmatched,
- nfs_name_snoop_unmatched_free_all, NULL);
- } else {
- /* The fragment table does not exist. Create it */
- nfs_name_snoop_unmatched = g_hash_table_new(nfs_name_snoop_unmatched_hash,
- nfs_name_snoop_unmatched_equal);
- }
- if (nfs_name_snoop_matched != NULL) {
- g_hash_table_foreach_remove(nfs_name_snoop_matched,
- nfs_name_snoop_unmatched_free_all, NULL);
- } else {
- /* The fragment table does not exist. Create it */
- nfs_name_snoop_matched = g_hash_table_new(nfs_name_snoop_matched_hash,
- nfs_name_snoop_matched_equal);
- }
+ nfs_name_snoop_unmatched =
+ g_hash_table_new_full(nfs_name_snoop_unmatched_hash,
+ nfs_name_snoop_unmatched_equal,
+ NULL, nfs_name_snoop_value_destroy);
+ nfs_name_snoop_matched =
+ g_hash_table_new_full(nfs_name_snoop_matched_hash,
+ nfs_name_snoop_matched_equal,
+ NULL, nfs_name_snoop_value_destroy);
+}
+
+static void
+nfs_name_snoop_cleanup(void)
+{
+ g_hash_table_destroy(nfs_name_snoop_unmatched);
+ g_hash_table_destroy(nfs_name_snoop_matched);
}
/* file handle dissection */
-static const value_string names_fhtype[] =
-{
- { FHT_UNKNOWN, "unknown" },
- { FHT_SVR4, "System V R4" },
- { FHT_LINUX_KNFSD_LE, "Linux knfsd (little-endian)" },
- { FHT_LINUX_NFSD_LE, "Linux user-land nfsd (little-endian)" },
- { FHT_LINUX_KNFSD_NEW, "Linux knfsd (new)" },
- { FHT_NETAPP, "ONTAP 7G nfs v3 file handle" },
- { FHT_NETAPP_V4, "ONTAP 7G nfs v4 file handle" },
- { FHT_NETAPP_GX_V3, "ONTAP GX nfs v3 file handle" },
- { FHT_CELERRA_VNX, "Celerra|VNX NFS file handle" },
- { FHT_GLUSTER, "GlusterFS/NFS file handle" },
- { FHT_DCACHE, "dCache NFS file handle" },
- { 0, NULL }
-};
-static value_string_ext names_fhtype_ext = VALUE_STRING_EXT_INIT(names_fhtype);
-
-
static const true_false_string tfs_endianness = { "Little Endian", "Big Endian" };
static void
if (fhlen != 36)
return;
- ident = tvb_get_string_enc(NULL, tvb, offset, 4, ENC_ASCII);
+ ident = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 4, ENC_ASCII);
if (strncmp(":OGL", ident, 4))
return;
offset += 4;
guint8 *fh_array;
proto_item *fh_item = NULL;
- fh_array = tvb_get_string_enc(NULL, tvb, offset, fhlen, ENC_ASCII);
+ fh_array = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset, fhlen);
fhhash = crc32_ccitt(fh_array, fhlen);
- g_free(fh_array);
if (hidden) {
fh_item = proto_tree_add_uint(tree, hf_nfs_fh_hash, NULL, 0,
if (!hidden) {
tvbuff_t *fh_tvb;
- int real_length;
-
- proto_tree_add_uint(tree, hf_nfs_fh_decode_as, tvb, offset, 0, default_nfs_fhandle_type);
- real_length = fhlen;
- if (default_nfs_fhandle_type != FHT_UNKNOWN && real_length < tvb_captured_length_remaining(tvb, offset))
- real_length = tvb_captured_length_remaining(tvb, offset);
-
- fh_tvb = tvb_new_subset(tvb, offset, real_length, fhlen);
- if (!dissector_try_uint(nfs_fhandle_table, default_nfs_fhandle_type, fh_tvb, pinfo, tree))
+ /* Functionality for choosing subdissector is controlled through Decode As as NFS doesn't
+ have a unique identifier to determine subdissector */
+ fh_tvb = tvb_new_subset(tvb, offset, fhlen, fhlen);
+ if (!dissector_try_uint(nfs_fhandle_table, 0, fh_tvb, pinfo, tree))
dissect_fhandle_data_unknown(fh_tvb, pinfo, tree);
}
}
/* NFSv2 RFC 1094, Page 12..14 */
static int
-dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_rmdir_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
static int
-dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_symlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
static int
-dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_link_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
static int
-dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_rename_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
static int
-dissect_nfs2_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_remove_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv2 RFC 1094, Page 15 */
static int
-dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_statfs_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
static int
-dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_readlink_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
static int
-dissect_nfs2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_getattr_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 17,18 */
static int
-dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_write_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
- offset = dissect_attrstat(tvb, offset, tree, pinfo, "WRITE");
-
- return offset;
+ return dissect_attrstat(tvb, 0, tree, pinfo, "WRITE");
}
/* NFSv2 RFC 1094, Page 18 */
static int
-dissect_nfs2_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_setattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
- offset = dissect_attrstat(tvb, offset, tree, pinfo, "SETATTR");
-
- return offset;
+ return dissect_attrstat(tvb, 0, tree, pinfo, "SETATTR");
}
/* NFSv2 RFC 1094, Page 18 */
static int
-dissect_nfs2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+dissect_nfs2_getattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
- offset = dissect_attrstat(tvb, offset, tree, pinfo, "GETATTR");
-
- return offset;
+ return dissect_attrstat(tvb, 0, tree, pinfo, "GETATTR");
}
/* NFSv2 RFC 1094, Page 18 */
static int
-dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_rmdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 18 */
static int
-dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_remove_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 18 */
static int
-dissect_nfs2_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs2_lookup_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 18 */
static int
-dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_mkdir_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
- offset = dissect_diropres(tvb, offset, pinfo, tree, "MKDIR", (rpc_call_info_value*)data);
- return offset;
+ return dissect_diropres(tvb, 0, pinfo, tree, "MKDIR", (rpc_call_info_value*)data);
}
static int
-dissect_nfs2_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_create_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
{
- offset = dissect_diropres(tvb, offset, pinfo, tree, "CREATE", (rpc_call_info_value*)data);
- return offset;
+ return dissect_diropres(tvb, 0, pinfo, tree, "CREATE", (rpc_call_info_value*)data);
}
static int
-dissect_nfs2_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_lookup_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
{
- offset = dissect_diropres(tvb, offset, pinfo, tree, "LOOKUP", (rpc_call_info_value*)data);
- return offset;
+ return dissect_diropres(tvb, 0, pinfo, tree, "LOOKUP", (rpc_call_info_value*)data);
}
/* RFC 1094, Page 6 */
static int
-dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_setattr_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
offset = dissect_nfs2_sattr (tvb, offset, tree, "attributes");
/* NFSv2 RFC 1094, Page 6 */
static int
-dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs2_readlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
const char *name = NULL;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv2 RFC 1094, Page 7 */
static int
-dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_read_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 offset_value;
guint32 count;
guint32 totalcount;
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
proto_tree_add_item_ret_uint(tree, hf_nfs2_read_offset, tvb,
/* NFSv2 RFC 1094, Page 7 */
static int
-dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs2_read_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv2 RFC 1094, Page 8 */
static int
-dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_write_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 beginoffset;
guint32 offset_value;
guint32 totalcount;
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 8 */
static int
-dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_mkdir_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
offset = dissect_nfs2_sattr (tvb, offset, tree, "attributes");
}
static int
-dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_create_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
offset = dissect_nfs2_sattr (tvb, offset, tree, "attributes");
/* NFSv2 RFC 1094, Page 9 */
static int
-dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_rename_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 from_hash;
const char *from_name = NULL;
guint32 to_hash;
const char *to_name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 9 */
static int
-dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_link_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 from_hash;
guint32 to_hash;
const char *to_name = NULL;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash, (rpc_call_info_value*)data);
offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 10 */
static int
-dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_symlink_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 from_hash;
const char *from_name = NULL;
const char *to_name = NULL;
+ int offset = 0;
offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
/* NFSv2 RFC 1094, Page 11 */
static int
-dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_readdir_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash;
+ int offset = 0;
offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
/* NFSv2 RFC 1094, Page 11 */
static int
-dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs2_readdir_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
{
guint32 status;
guint32 eof_value;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
offset = dissect_rpc_list(tvb, pinfo, tree, offset,
dissect_readdir_entry, NULL);
- eof_value = tvb_get_ntohl(tvb, offset+0);
- if (tree)
- proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
- offset+ 0, 4, eof_value);
+ proto_tree_add_item_ret_uint(tree, hf_nfs_readdir_eof, tvb,
+ offset, 4, ENC_BIG_ENDIAN, &eof_value);
offset += 4;
break;
default:
/* NFSv2 RFC 1094, Page 12 */
static int
-dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs2_statfs_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs2_status(tvb, offset, tree, &status);
switch (status) {
/* proc number, "proc name", dissect_request, dissect_reply */
-/* NULL as function pointer means: type of arguments is "void". */
static const vsff nfs2_proc[] = {
{ 0, "NULL", /* OK */
- NULL, NULL },
+ dissect_rpc_void, dissect_rpc_void },
{ 1, "GETATTR", /* OK */
dissect_nfs2_getattr_call, dissect_nfs2_getattr_reply },
{ 2, "SETATTR", /* OK */
dissect_nfs2_setattr_call, dissect_nfs2_setattr_reply },
{ 3, "ROOT", /* OK */
- NULL, NULL },
+ dissect_rpc_void, dissect_rpc_void },
{ 4, "LOOKUP", /* OK */
dissect_nfs2_lookup_call, dissect_nfs2_lookup_reply },
{ 5, "READLINK", /* OK */
{ 6, "READ", /* OK */
dissect_nfs2_read_call, dissect_nfs2_read_reply },
{ 7, "WRITECACHE", /* OK */
- NULL, NULL },
+ dissect_rpc_void, dissect_rpc_void },
{ 8, "WRITE", /* OK */
dissect_nfs2_write_call, dissect_nfs2_write_reply },
{ 9, "CREATE", /* OK */
static int
-dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_remove_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name, (rpc_call_info_value*)data);
static int
-dissect_nfs3_null_call(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+dissect_nfs3_null_call(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
proto_item_append_text(tree, ", NULL Call");
- return offset;
+ return 0;
}
static int
-dissect_nfs3_null_reply(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+dissect_nfs3_null_reply(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
proto_item_append_text(tree, ", NULL Reply");
- return offset;
+ return 0;
}
static int
-dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_rmdir_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 32,33 */
static int
-dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_getattr_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 32,33 */
static int
-dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_getattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
proto_item_append_text(tree, ", GETATTR Reply");
/* NFSv3 RFC 1813, Page 33..36 */
static int
-dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_setattr_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh (tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
offset = dissect_nfs3_sattr (tvb, offset, tree, "new_attributes");
/* NFSv3 RFC 1813, Page 33..36 */
static int
-dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_setattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 37..39 */
static int
-dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_lookup_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 37..39 */
static int
-dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_lookup_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 status;
const char *err;
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 40..43 */
static int
-dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs3_access_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
+ int offset = 0;
guint32 fhhash = 0, *acc_request, amask;
rpc_call_info_value *civ = (rpc_call_info_value*)data;
/* NFSv3 RFC 1813, Page 40..43 */
static int
-dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_access_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
/* NFSv3 RFC 1813, Page 44,45 */
static int
-dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_readlink_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
static int
-dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_readlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
const char *name = NULL;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 46..48 */
static int
-dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_read_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint64 off;
guint32 len;
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 46..48 */
static int
-dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_read_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
guint32 len;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 49..54 */
static int
-dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_write_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint64 off;
guint32 len;
guint32 stable;
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 49..54 */
static int
-dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_write_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
guint32 len;
guint32 stable;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 54..58 */
static int
-dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_create_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 mode;
guint32 hash = 0;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
offset = dissect_createmode3(tvb, offset, tree, &mode);
/* NFSv3 RFC 1813, Page 54..58 */
static int
-dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_create_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 58..60 */
static int
-dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_mkdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash = 0;
const char *name = NULL;
+ int offset = 0;
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
offset = dissect_nfs3_sattr (tvb, offset, tree, "attributes");
static int
-dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_mkdir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 61..63 */
static int
-dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_symlink_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 from_hash = 0;
const char *from_name = NULL;
const char *to_name = NULL;
+ int offset = 0;
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name, (rpc_call_info_value*)data);
offset = dissect_nfs3_sattr (tvb, offset, tree, "symlink_attributes");
static int
-dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_symlink_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 63..66 */
static int
-dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_mknod_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 type;
guint32 hash = 0;
const char *name = NULL;
const char *type_str;
+ int offset = 0;
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
offset = dissect_ftype3(tvb, offset, tree, hf_nfs3_ftype, &type);
static int
-dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_mknod_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 67..69 */
static int
-dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_remove_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
static int
-dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_rmdir_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 71..74 */
static int
-dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_rename_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 from_hash = 0;
const char *from_name = NULL;
guint32 to_hash = 0;
const char *to_name = NULL;
+ int offset = 0;
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 71..74 */
static int
-dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+dissect_nfs3_rename_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 74..76 */
static int
-dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_link_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 from_hash = 0;
guint32 to_hash = 0;
const char *to_name = NULL;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &from_hash, (rpc_call_info_value*)data);
offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name, (rpc_call_info_value*)data);
/* NFSv3 RFC 1813, Page 74..76 */
static int
-dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_link_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 76..80 */
static int
-dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_readdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_cookie, offset);
/* NFSv3 RFC 1813, Page 76..80 */
static int
-dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_readdir_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
{
guint32 status;
guint32 eof_value;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 80..83 */
static int
-dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs3_readdirplus_call(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_cookie, offset);
/* NFSv3 RFC 1813, Page 80..83 */
static int
-dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 status;
guint32 eof_value;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 84..86 */
static int
-dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_fsstat_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
static int
-dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_fsstat_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
guint32 invarsec;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 86..90 */
static int
-dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_fsinfo_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
static int
-dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
static const int *properties[] = {
&hf_nfs3_fsinfo_properties_hardlinks,
NULL
};
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 90..92 */
static int
-dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_pathconf_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
static int
-dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_pathconf_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
guint32 linkmax;
guint32 name_max;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
/* NFSv3 RFC 1813, Page 92..95 */
static int
-dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, void *data)
+dissect_nfs3_commit_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint32 hash = 0;
+ int offset = 0;
offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_offset, offset);
/* NFSv3 RFC 1813, Page 92..95 */
static int
-dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
- proto_tree *tree, void *data _U_)
+dissect_nfs3_commit_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
guint32 status;
const char *err;
+ int offset = 0;
offset = dissect_nfs3_status(tvb, offset, tree, &status);
switch (status) {
{ 10085, "NFS4ERR_REJECT_DELEG" },
{ 10086, "NFS4ERR_RETURNCONFLICT" },
{ 10087, "NFS4ERR_DELEG_REVOKED" },
+ { 10088, "NFS4ERR_PARTNER_NOTSUPP" },
+ { 10089, "NFS4ERR_PARTNER_NO_AUTH" },
+ { 10090, "NFS4ERR_UNION_NOTSUPP" },
+ { 10091, "NFS4ERR_OFFLOAD_DENIED" },
+ { 10092, "NFS4ERR_WRONG_LFS" },
+ { 10093, "NFS4ERR_BADLABEL" },
+ { 10094, "NFS4ERR_OFFLOAD_NO_REQS" },
{ 0, NULL }
};
static value_string_ext names_nfs4_status_ext = VALUE_STRING_EXT_INIT(names_nfs4_status);
{ FATTR4_SUPPATTR_EXCLCREAT, "Suppattr_ExclCreat" },
#define FATTR4_FS_CHARSET_CAP 76
{ FATTR4_FS_CHARSET_CAP, "FS_Charset_Cap" },
+#define FATTR4_CLONE_BLOCKSIZE 77
+ { FATTR4_CLONE_BLOCKSIZE, "Clone_Block_Size" },
+#define FATTR4_SPACE_FREED 78
+ { FATTR4_SPACE_FREED, "Space_Freed" },
+#define FATTR4_CHANGE_ATTR_TYPE 79
+ { FATTR4_CHANGE_ATTR_TYPE, "Change_Attr_Type" },
#define FATTR4_SECURITY_LABEL 80
{ FATTR4_SECURITY_LABEL, "Security_Label" },
{ 0, NULL }
*/
#define MAX_BITMAPS 100
+static const value_string names_nfs_change_attr_types[] =
+{
+#define CHANGE_TYPE_IS_MONOTONIC_INCR 1
+ { CHANGE_TYPE_IS_MONOTONIC_INCR, "CHANGE_TYPE_IS_MONOTONIC_INCR" },
+#define CHANGE_TYPE_IS_VERSION_COUNTER 2
+ { CHANGE_TYPE_IS_VERSION_COUNTER, "CHANGE_TYPE_IS_VERSION_COUNTER" },
+#define CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS 3
+ { CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS, "CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS" },
+#define CHANGE_TYPE_IS_TIME_METADATA 4
+ { CHANGE_TYPE_IS_TIME_METADATA, "CHANGE_TYPE_IS_TIME_METADATA" },
+#define CHANGE_TYPE_IS_UNDEFINED 5
+ { CHANGE_TYPE_IS_UNDEFINED, "CHANGE_TYPE_IS_UNDEFINED" },
+ { 0, NULL }
+};
+
/* Display each attrmask bitmap and optionally dissect the value.
*/
static int
offset);
break;
+ case FATTR4_CLONE_BLOCKSIZE:
+ offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_clone_blocksize,
+ offset);
+ break;
+
+ case FATTR4_SPACE_FREED:
+ offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_freed,
+ offset);
+ break;
+
+ case FATTR4_CHANGE_ATTR_TYPE:
+ offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_change_attr_type,
+ offset);
+ break;
+
case FATTR4_SECURITY_LABEL:
offset = dissect_nfs4_security_label(tvb, attr_tree, offset);
break;
&b1, &b2, &b3, &b4, &b5, &b6) == 6) {
/* IPv4: h1.h2.h3.h4.p1.p2 */
port = (b5<<8) | b6;
- ipv4 = (b1<<24) | (b2<<16) | (b3<<8) | b4;
+ ipv4 = g_htonl((b1<<24) | (b2<<16) | (b3<<8) | b4);
SET_ADDRESS(&addr, AT_IPv4, 4, &ipv4);
ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, ipv4, "IPv4 address %s, protocol=%s, port=%u",
address_to_str(wmem_packet_scope(), &addr), protocol, port);
ipv6.bytes[0] = b1; ipv6.bytes[1] = b2; ipv6.bytes[2] = b3; ipv6.bytes[3] = b4;
ipv6.bytes[4] = b5; ipv6.bytes[5] = b6; ipv6.bytes[6] = b7; ipv6.bytes[7] = b8;
SET_ADDRESS(&addr, AT_IPv6, 16, &ipv6);
- ti = proto_tree_add_ipv6_format(tree, hf_nfs4_universal_address_ipv6, tvb, addr_offset, offset-addr_offset, ipv6.bytes, "IPv6 address %s, protocol=%s, port=%u",
+ ti = proto_tree_add_ipv6_format(tree, hf_nfs4_universal_address_ipv6, tvb, addr_offset, offset-addr_offset, &ipv6, "IPv6 address %s, protocol=%s, port=%u",
address_to_str(wmem_packet_scope(), &addr), protocol, port);
PROTO_ITEM_SET_GENERATED(ti);
} else {
{
proto_tree *cb_location;
proto_item *fitem;
- int cbprog, old_offset;
+ int old_offset;
- cbprog = tvb_get_ntohl(tvb, offset);
- reg_callback(cbprog);
offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_cb_program, offset);
old_offset = offset;
cb_location = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "cb_location");
{ NFS4_OP_DESTROY_CLIENTID, "DESTROY_CLIENTID" },
{ NFS4_OP_RECLAIM_COMPLETE, "RECLAIM_COMPLETE" },
{ NFS4_OP_ALLOCATE, "ALLOCATE" },
+ { NFS4_OP_COPY, "COPY" },
+ { NFS4_OP_COPY_NOTIFY, "COPY_NOTIFY" },
{ NFS4_OP_DEALLOCATE, "DEALLOCATE" },
- { NFS4_OP_SEEK, "SEEK" },
+ { NFS4_OP_IO_ADVISE, "IO_ADVISE" },
+ { NFS4_OP_LAYOUTERROR, "LAYOUTERROR" },
+ { NFS4_OP_LAYOUTSTATS, "LAYOUTSTATS" },
+ { NFS4_OP_OFFLOAD_CANCEL, "OFFLOAD_CANCEL" },
+ { NFS4_OP_OFFLOAD_STATUS, "OFFLOAD_STATUS" },
+ { NFS4_OP_READ_PLUS, "READ_PLUS" },
+ { NFS4_OP_SEEK, "SEEK" },
+ { NFS4_OP_WRITE_SAME, "WRITE_SAME" },
+ { NFS4_OP_CLONE, "CLONE" },
{ NFS4_OP_ILLEGAL, "ILLEGAL" },
{ 0, NULL }
};
&ett_nfs4_destroy_clientid,
&ett_nfs4_reclaim_complete,
&ett_nfs4_allocate,
- NULL,
- NULL,
+ &ett_nfs4_copy,
+ &ett_nfs4_copy_notify,
&ett_nfs4_deallocate,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ &ett_nfs4_io_advise,
+ &ett_nfs4_layouterror,
+ &ett_nfs4_layoutstats,
+ &ett_nfs4_offload_cancel,
+ &ett_nfs4_offload_status,
+ &ett_nfs4_read_plus,
&ett_nfs4_seek,
+ &ett_nfs4_write_same,
+ &ett_nfs4_clone,
};
return offset;
}
-
static int
dissect_nfs4_change_info(tvbuff_t *tvb, int offset,
proto_tree *tree, const char *name)
newftree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_nfs4_stateid, &fitem, "stateid");
- sidh_array = tvb_get_string_enc(NULL, tvb, offset, 16, ENC_ASCII);
+ sidh_array = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 16, ENC_ASCII);
sid_hash = crc16_ccitt(sidh_array, 16);
- g_free(sidh_array);
sh_item = proto_tree_add_uint(newftree, hf_nfs4_stateid_hash, tvb, offset, 16, sid_hash);
PROTO_ITEM_SET_GENERATED(sh_item);
return offset;
}
+static const value_string read_plus_content_names[] = {
+#define NFS4_CONTENT_DATA 0
+ { NFS4_CONTENT_DATA, "Data" },
+#define NFS4_CONTENT_HOLE 1
+ { NFS4_CONTENT_HOLE, "Hole" },
+ { 0, NULL }
+};
+static value_string_ext read_plus_content_names_ext = VALUE_STRING_EXT_INIT(read_plus_content_names);
+
+static int
+dissect_nfs4_read_plus_content(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *sub_fitem;
+ proto_tree *ss_tree;
+ proto_tree *subtree;
+ proto_item *ss_fitem;
+ guint i;
+ guint count;
+ guint type;
+
+ count = tvb_get_ntohl(tvb, offset);
+ sub_fitem = proto_tree_add_item(tree, hf_nfs4_read_plus_content_count,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_read_plus_content_sub);
+ for (i = 0; i < count; i++) {
+ ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_read_plus_content_index,
+ tvb, offset+0, 4, i, "Content [%u]", i);
+ ss_tree = proto_item_add_subtree(ss_fitem,
+ ett_nfs4_read_plus_content_sub);
+ offset += 4;
+
+ type = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(ss_tree, hf_nfs4_read_plus_content_type, tvb, offset, 0, type);
+ offset += 4;
+
+ switch (type) {
+ case NFS4_CONTENT_DATA:
+ offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_offset, offset);
+ dissect_rpc_uint32(tvb, ss_tree, hf_nfs4_read_data_length, offset); /* don't change offset */
+ offset = dissect_nfsdata(tvb, offset, ss_tree, hf_nfs_data);
+ break;
+ case NFS4_CONTENT_HOLE:
+ offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_offset, offset);
+ offset = dissect_rpc_uint32(tvb, ss_tree, hf_nfs4_count, offset);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
static int
dissect_nfs4_client_id(tvbuff_t *tvb, int offset, proto_tree *tree)
return offset;
}
+static const value_string io_advise_names[] = {
+#define IO_ADVISE4_NORMAL 0
+ { IO_ADVISE4_NORMAL, "Normal" },
+#define IO_ADVISE4_SEQUENTIAL 1
+ { IO_ADVISE4_SEQUENTIAL, "Sequential" },
+#define IO_ADVISE4_SEQUENTIAL_BACKWARDS 2
+ { IO_ADVISE4_SEQUENTIAL_BACKWARDS, "Sequential Backwards" },
+#define IO_ADVISE4_RANDOM 3
+ { IO_ADVISE4_RANDOM, "Random" },
+#define IO_ADVISE4_WILLNEED 4
+ { IO_ADVISE4_WILLNEED, "Will Need" },
+#define IO_ADVISE4_WILLNEED_OPPORTUNISTIC 5
+ { IO_ADVISE4_WILLNEED_OPPORTUNISTIC, "Will Need Opportunistic" },
+#define IO_ADVISE4_DONTNEED 6
+ { IO_ADVISE4_DONTNEED, "Don't Need" },
+#define IO_ADVISE4_NOREUSE 7
+ { IO_ADVISE4_NOREUSE, "No Reuse" },
+#define IO_ADVISE4_READ 8
+ { IO_ADVISE4_READ, "Read" },
+#define IO_ADVISE4_WRITE 9
+ { IO_ADVISE4_WRITE, "Write" },
+#define IO_ADVISE4_INIT_PROXIMITY 10
+ { IO_ADVISE4_INIT_PROXIMITY, "Init Proximity" },
+ { 0, NULL }
+};
+static value_string_ext io_advise_names_ext = VALUE_STRING_EXT_INIT(io_advise_names);
static int
-dissect_nfs4_layoutreturn(tvbuff_t *tvb, int offset, proto_tree *tree)
+dissect_nfs4_io_hints(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
- guint returntype;
+ int hints_mask_offset = 0;
+ guint32 i, j;
+ guint32 num_bitmaps;
+ guint32 count = 0;
+ guint32 hint_num;
+ guint32 *bitmaps = NULL;
+ guint32 bitmap, sl;
+ gboolean first_hint = TRUE;
+ gboolean no_idx = FALSE;
- returntype = tvb_get_ntohl(tvb, offset);
- offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_return_type, offset);
- if (returntype == 1) { /* RETURN_FILE */
- offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
- offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
- offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
- offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_lrf_body_content);
- }
+ proto_item *bitmap_item = NULL;
+ proto_tree *bitmap_tree = NULL;
+ proto_item *hitem = NULL;
- return offset;
-}
+ num_bitmaps = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ if (!num_bitmaps)
+ return offset;
-static int
-dissect_nfs_layoutreturn_stateid(tvbuff_t *tvb, proto_tree *tree, int offset)
-{
- guint lrs_present;
+ if (num_bitmaps > MAX_BITMAPS) {
+ proto_tree_add_uint(tree, hf_nfs4_huge_bitmap_length, tvb, offset, 4, num_bitmaps);
+ expert_add_info(pinfo, tree, &ei_nfs_too_many_bitmaps);
+ return offset;
+ }
- lrs_present = tvb_get_ntohl(tvb, offset);
- offset = dissect_rpc_bool(tvb, tree, hf_nfs4_lrs_present, offset);
+ bitmaps = (guint32 *)wmem_alloc(wmem_packet_scope(), num_bitmaps * sizeof(guint32));
+ hints_mask_offset = offset;
- if (lrs_present) {
- offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+ /* Load the array with the bitmap(s) */
+ for (i = 0; i < num_bitmaps; i++) {
+ bitmaps[i] = tvb_get_ntohl(tvb, hints_mask_offset + (i*4));
+ if (bitmaps[i] > 0)
+ count++;
}
- return offset;
-}
+ /* If there is only one non-zero bitmap, don't display the bitmap index "[x]". */
+ if (count <= 1)
+ no_idx = TRUE;
+ offset += (num_bitmaps * 4);
-static int
-dissect_nfs4_notification_bitmap(tvbuff_t *tvb, proto_tree *tree, int offset)
-{
- guint32 bitmap_num;
- guint i;
+ for (i = 0; i < num_bitmaps; i++) {
+ bitmap = bitmaps[i];
- bitmap_num = tvb_get_ntohl(tvb, offset);
- offset += 4;
+ if (bitmap) {
+ if (tree) {
+ /*
+ * Display the current Attr_mask bitmap (as of RFC 5661 NVSv4.1, there are up to 3) */
+ if (no_idx)
+ bitmap_item = proto_tree_add_uint_format_value(tree, hf_nfs4_io_hints_mask, tvb,
+ hints_mask_offset, 4, bitmap, "0x%08x", bitmap);
+ else
+ bitmap_item = proto_tree_add_uint_format(tree, hf_nfs4_io_hints_mask, tvb,
+ hints_mask_offset, 4, bitmap, "Hints mask[%u]: 0x%08x", i, bitmap);
- /* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8611 */
- if (!tree) {
- if ((guint)offset > offset + (bitmap_num * 4)) {
- return tvb_reported_length(tvb);
- }
- else {
- return offset + (bitmap_num * 4);
+ bitmap_tree = proto_item_add_subtree(bitmap_item, ett_nfs4_bitmap);
+ first_hint = TRUE;
+
+ /* Count the number of hint bits set */
+ for (count=0; bitmap; bitmap >>= 1)
+ count += (bitmap & 1);
+ bitmap = bitmaps[i];
+ hitem = proto_tree_add_uint_format(bitmap_tree, hf_nfs4_io_hint_count, tvb, hints_mask_offset, 4, count, "%u hint%s", count, plurality(count, "", "s"));
+ PROTO_ITEM_SET_HIDDEN(hitem);
+ PROTO_ITEM_SET_GENERATED(hitem);
+ }
+ } else {
+ hints_mask_offset += 4;
+ continue;
}
- }
- for (i = 0; i < bitmap_num; i++) {
- offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_notification_bitmap, offset);
- }
+ sl = 0x00000001;
- return offset;
-}
+ for (j = 0; j < 32; j++) {
+ hint_num = 32*i + j;
+ if (bitmap & sl) {
+ if (bitmap_tree) {
+ /*
+ * Append this attribute name to the 'Hints mask' header line */
+ proto_item_append_text (bitmap_tree, (first_hint ? " (%s" : ", %s"),
+ val_to_str_ext(hint_num, &io_advise_names_ext, "Unknown: %u"));
+ first_hint = FALSE;
-static int
-dissect_nfs4_devices_file(tvbuff_t *tvb, int offset, proto_tree *tree)
+ proto_tree_add_uint(bitmap_tree, hf_nfs4_io_advise_hint, tvb, offset, 0, hint_num);
+ }
+ }
+ sl <<= 1;
+ } /* End of inner loop: test the next bit in this mask */
+
+ if (bitmap_tree)
+ proto_item_append_text(bitmap_tree, ")");
+ hints_mask_offset += 4;
+ } /* End of outer loop, read the next mask */
+
+ return offset;
+}
+
+static int
+dissect_nfs4_app_data_block(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *hash)
+{
+ proto_item *fitem;
+
+ guint32 pattern_hash;
+ guint8 *pattern_array;
+ guint pattern_len;
+
+
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_block_size, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_block_count, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_reloff_blocknum, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_blocknum, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_reloff_pattern, offset);
+
+ pattern_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ pattern_array = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, pattern_len, ENC_ASCII);
+ pattern_hash = crc32_ccitt(pattern_array, pattern_len);
+ fitem = proto_tree_add_uint(tree, hf_nfs4_pattern_hash, tvb, offset, pattern_len, pattern_hash);
+ PROTO_ITEM_SET_GENERATED(fitem);
+ proto_item_set_len(fitem, pattern_len);
+
+ offset += pattern_len;
+
+ if (hash)
+ *hash = pattern_hash;
+
+ return offset;
+}
+
+static int
+dissect_nfs4_io_time(tvbuff_t *tvb, int offset, proto_tree *tree, const char *timer_mode)
+{
+ proto_tree *newtree;
+
+ newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_time, NULL, "%s", timer_mode);
+ offset = dissect_nfs4_nfstime(tvb, offset, newtree);
+
+ return offset;
+}
+
+static int
+dissect_nfs4_io_latency(tvbuff_t *tvb, int offset, proto_tree *tree, const char *io_mode)
+{
+ proto_tree *newtree;
+
+ newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_latency, NULL, "%s Latency", io_mode);
+
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ops_requested, offset);
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_requested, offset);
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ops_completed, offset);
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_completed, offset);
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_not_delivered, offset);
+
+ offset = dissect_nfs4_io_time(tvb, offset, newtree, "Busy time");
+ offset = dissect_nfs4_io_time(tvb, offset, newtree, "Completion time");
+
+ return offset;
+}
+
+static int
+dissect_nfs4_io_info(tvbuff_t *tvb, int offset, proto_tree *tree, const char *io_mode)
+{
+ proto_tree *newtree;
+
+ newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_info, NULL, "%s Info", io_mode);
+
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_io_count, offset);
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_io_bytes, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs4_layoutstats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ, gboolean has_layout_type)
+{
+ guint layout_type = LAYOUT4_NO_LAYOUT_TYPE;
+ proto_tree *netaddr;
+ proto_item *fitem;
+ int old_offset;
+ guint32 last_fh_hash = 0;
+
+ /* FIXME: Are these here or in the caller? Check for layoutcommit */
+ offset = dissect_nfs4_io_info(tvb, offset, tree, "Read");
+ offset = dissect_nfs4_io_info(tvb, offset, tree, "Write");
+ offset = dissect_nfs4_deviceid(tvb, offset, tree);
+
+ if (has_layout_type) {
+ layout_type = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
+ }
+
+ /* If not flex files layout type eat the rest and move on.. */
+ if (!has_layout_type || layout_type == LAYOUT4_FLEX_FILES) {
+
+ /* NFS Flex Files */
+ if (has_layout_type)
+ offset += 4; /* Skip past opaque count */
+
+ /* The netaddr */
+ old_offset = offset;
+ netaddr = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "DS address");
+
+ offset = dissect_nfs4_clientaddr(tvb, offset, netaddr);
+ proto_item_set_len(fitem, offset - old_offset);
+
+ /* The file handle */
+ offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "Filehandle", &last_fh_hash, civ);
+
+ /* Read Latency */
+ offset = dissect_nfs4_io_latency(tvb, offset, tree, "Read");
+
+ /* Write Latency */
+ offset = dissect_nfs4_io_latency(tvb, offset, tree, "Write");
+
+ /* Duration */
+ offset = dissect_nfs4_io_time(tvb, offset, tree, "Duration");
+
+ /* Local? */
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ff_local, offset);
+ } else {
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_layoutstats);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs4_ff_io_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
+{
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
+ offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+
+ /* Note that we've already determined that we are in the Flex File Layout Type */
+ offset = dissect_nfs4_layoutstats(tvb, offset, pinfo, tree, civ, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_nfs4_device_errors(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *sub_fitem;
+ proto_tree *ss_tree;
+ proto_tree *subtree;
+ proto_item *ss_fitem;
+ guint i;
+ guint count;
+
+ guint opcode;
+
+ count = tvb_get_ntohl(tvb, offset);
+ sub_fitem = proto_tree_add_item(tree, hf_nfs4_device_error_count,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_device_errors_sub);
+ for (i = 0; i < count; i++) {
+ ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_device_errors_index,
+ tvb, offset+0, 4, i, "Error [%u]", i);
+ ss_tree = proto_item_add_subtree(ss_fitem,
+ ett_nfs4_device_errors_sub);
+ offset = dissect_nfs4_deviceid(tvb, offset, ss_tree);
+ offset = dissect_nfs4_status(tvb, offset, ss_tree, NULL);
+
+ opcode = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(ss_tree, hf_nfs4_io_error_op, tvb, offset, 4, opcode);
+ offset += 4;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs4_ff_io_error(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree *newtree;
+
+ /* FIXME */
+ newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_latency, NULL, "IO errors");
+
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ioerrs_offset, offset);
+ offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ioerrs_length, offset);
+ offset = dissect_nfs4_stateid(tvb, offset, newtree, NULL);
+
+ offset = dissect_nfs4_device_errors(tvb, offset, newtree);
+
+ return offset;
+}
+
+static int
+dissect_nfs4_layoutreturn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
+{
+ guint returntype;
+ guint layout_type;
+
+ proto_item *sub_fitem;
+ proto_tree *ss_tree;
+ proto_tree *subtree;
+ proto_item *ss_fitem;
+ guint i;
+ guint count;
+
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs4_reclaim, offset);
+
+ layout_type = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_iomode, offset);
+
+ returntype = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_return_type, offset);
+ if (returntype == 1) { /* RETURN_FILE */
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
+ offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+
+ /* If not flex files layout type eat the rest and move on.. */
+ if (layout_type == LAYOUT4_FLEX_FILES) {
+ offset += 4; /* Skip past opaque count */
+
+ /* Get the errors */
+ count = tvb_get_ntohl(tvb, offset);
+ sub_fitem = proto_tree_add_item(tree, hf_nfs4_ff_ioerrs_count,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_ff_ioerrs_sub);
+ for (i = 0; i < count; i++) {
+ ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_ff_ioerrs_index,
+ tvb, offset+0, 4, i, "IO Error [%u]", i);
+ ss_tree = proto_item_add_subtree(ss_fitem,
+ ett_nfs4_ff_ioerrs_sub);
+
+ offset = dissect_nfs4_ff_io_error(tvb, offset, ss_tree);
+ }
+
+ /* Get the stats */
+ count = tvb_get_ntohl(tvb, offset);
+ sub_fitem = proto_tree_add_item(tree, hf_nfs4_ff_iostats_count,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_ff_iostats_sub);
+ for (i = 0; i < count; i++) {
+ ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_ff_iostats_index,
+ tvb, offset+0, 4, i, "IO Stat [%u]", i);
+ ss_tree = proto_item_add_subtree(ss_fitem,
+ ett_nfs4_ff_iostats_sub);
+
+ offset = dissect_nfs4_ff_io_stats(tvb, offset, pinfo, ss_tree, civ);
+ }
+
+ } else {
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_lrf_body_content);
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_layoutreturn_stateid(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ guint lrs_present;
+
+ lrs_present = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs4_lrs_present, offset);
+
+ if (lrs_present) {
+ offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_nfs4_notification_bitmap(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ guint32 bitmap_num;
+ guint i;
+
+ bitmap_num = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8611 */
+ if (!tree) {
+ if ((guint)offset > offset + (bitmap_num * 4)) {
+ return tvb_reported_length(tvb);
+ }
+ else {
+ return offset + (bitmap_num * 4);
+ }
+ }
+
+ for (i = 0; i < bitmap_num; i++) {
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_notification_bitmap, offset);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_nfs4_devices_file(tvbuff_t *tvb, int offset, proto_tree *tree)
{
guint i, j;
guint32 num_indices, num_multipath, num_addr;
{
guint i;
guint32 num_addr;
+ guint32 num_vers;
/* disect indices */
num_addr = tvb_get_ntohl(tvb, offset);
offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_addr, offset,
NULL);
}
- offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ffda_version, offset);
- offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ffda_minorversion,
+
+ num_vers = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ for (i = 0; i < num_vers; i++) {
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_version, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_minorversion,
offset);
- offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ffda_rsize,
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_rsize,
offset);
- offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ffda_wsize,
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_wsize,
offset);
- offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ffda_tightly_coupled,
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ff_tightly_coupled,
offset);
+ }
+
return offset;
}
return dissect_nfs4_status(tvb, offset, tree, NULL);
}
+static int
+dissect_nfs4_netloc(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint netloc_type;
+ proto_tree *netaddr;
+ int old_offset;
+ proto_item *fitem;
+
+ /* netloc type */
+ netloc_type = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_netloc_type, offset);
+
+ switch (netloc_type) {
+ case NL4_NAME:
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_nl_name, NULL);
+ break;
+ case NL4_URL:
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_nl_url, NULL);
+ break;
+ case NL4_NETADDR:
+ old_offset = offset;
+ netaddr = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "netaddr");
+
+ offset = dissect_nfs4_clientaddr(tvb, offset, netaddr);
+ proto_item_set_len(fitem, offset - old_offset);
+ break;
+ default:
+ /* back up to re-read the length field when treating as
+ * opaque */
+ offset -= 4;
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_netloc);
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs4_copy_reqs(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs4_consecutive, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs4_synchronous, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs4_write_response(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *sub_fitem;
+ proto_tree *ss_tree;
+ proto_tree *subtree;
+ proto_item *ss_fitem;
+ guint i;
+ guint32 count;
+
+ /* Number of callback stateids */
+ sub_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_callback_stateids,
+ tvb, offset, 4, ENC_BIG_ENDIAN, &count);
+ offset += 4;
+
+ subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_callback_stateids_sub);
+ for (i = 0; i < count; i++) {
+ ss_fitem = proto_tree_add_item(subtree,
+ hf_nfs4_callback_stateids_index,
+ tvb, offset, 4, i);
+
+ ss_tree = proto_item_add_subtree(ss_fitem,
+ ett_nfs4_callback_stateids_sub);
+
+ offset = dissect_nfs4_netloc(tvb, offset, ss_tree);
+ }
+
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
+ offset = dissect_nfs4_stable_how(tvb, offset, tree, "committed");
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs4_source_servers(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *sub_fitem;
+ proto_tree *ss_tree;
+ proto_tree *subtree;
+ proto_item *ss_fitem;
+ guint i;
+ guint32 source_servers;
+
+ /* Number of source servers */
+ sub_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_source_servers,
+ tvb, offset, 4, ENC_BIG_ENDIAN, &source_servers);
+ offset += 4;
+
+ subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_source_servers_sub);
+ for (i = 0; i < source_servers; i++) {
+ ss_fitem = proto_tree_add_item(subtree,
+ hf_nfs4_source_server_index,
+ tvb, offset, 4, i);
+
+ ss_tree = proto_item_add_subtree(ss_fitem,
+ ett_nfs4_source_servers_sub);
+
+ offset = dissect_nfs4_netloc(tvb, offset, ss_tree);
+ }
+
+ return offset;
+}
static int
dissect_nfs4_deviceaddr(tvbuff_t *tvb, int offset, proto_tree *tree)
return offset;
}
-
static int
-dissect_nfs4_layout(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
+dissect_nfs4_layoutget(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
{
guint layout_type;
guint sub_num;
proto_item *sub_fitem;
proto_tree *subtree;
+ static const int * layout_flags[] = {
+ &hf_nfs4_ff_layout_flags_no_layoutcommit,
+ NULL
+ };
+
lo_seg_count = tvb_get_ntohl(tvb, offset);
newtree = proto_tree_add_subtree_format(tree, tvb, offset, 4, ett_nfs4_layoutseg, NULL,
sub_num = tvb_get_ntohl(tvb, offset); /* Len of FH list */
sub_fitem = proto_tree_add_item(newtree, hf_nfs4_nfl_fhs,
- tvb, offset, 4, sub_num);
+ tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
subtree = proto_item_add_subtree(sub_fitem,
pinfo, ds_tree, "fh", NULL, civ);
offset = dissect_nfs_utf8string(tvb, offset,
- ds_tree, hf_nfs4_fattr_owner,
+ ds_tree, hf_nfs4_ff_synthetic_owner,
NULL);
offset = dissect_nfs_utf8string(tvb, offset,
- ds_tree, hf_nfs4_fattr_owner_group,
+ ds_tree, hf_nfs4_ff_synthetic_owner_group,
NULL);
}
}
+
+ proto_tree_add_bitmask(newtree, tvb, offset, hf_nfs4_ff_layout_flags,
+ ett_nfs4_ff_layout_flags, layout_flags, ENC_BIG_ENDIAN);
} else {
offset = dissect_nfsdata(tvb, offset, newtree, hf_nfs4_layout);
continue;
1 /* 58, NFS4_OP_RECLAIM_COMPLETE */,
/* Minor version 2 */
1 /* 59, NFS4_OP_ALLOCATE */,
+ 1 /* 60, NFS4_OP_COPY */,
+ 1 /* 61, NFS4_OP_COPY_NOTIFY */,
1 /* 62, NFS4_OP_DEALLOCATE */,
+ 1 /* 63, NFS4_OP_IO_ADVISE */,
+ 1 /* 64, NFS4_OP_LAYOUTERROR */,
+ 1 /* 65, NFS4_OP_LAYOUTSTATS */,
+ 1 /* 66, NFS4_OP_OFFLOAD_CANCEL */,
+ 1 /* 67, NFS4_OP_OFFLOAD_STATUS */,
+ 1 /* 68, NFS4_OP_READ_PLUS */,
1 /* 69, NFS4_OP_SEEK */,
+ 1 /* 70, NFS4_OP_WRITE_SAME */,
+ 1 /* 71, NFS4_OP_CLONE */,
};
#define NFS4_OPERATION_TIER(op) \
const char *source_name = NULL;
const char *dest_name = NULL;
const char *opname = NULL;
- int cbprog;
guint opcode;
guint highest_tier = 5;
guint current_tier = 5;
guint32 last_fh_hash = 0;
guint32 saved_fh_hash = 0;
guint32 length;
+ guint32 hash;
guint64 length64;
guint64 file_offset;
proto_item *fitem;
proto_tree *ftree;
proto_tree *newftree = NULL;
nfs4_operation_summary *op_summary;
+ guint16 dst_sid_hash;
+ guint64 dst_file_offset;
ops = tvb_get_ntohl(tvb, offset+0);
hf_nfs4_create_session_flags_csa);
offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csa_fore_chan_attrs");
offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csa_back_chan_attrs");
- cbprog = tvb_get_ntohl(tvb, offset);
- reg_callback(cbprog);
offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_cb_program, offset);
offset = dissect_rpc_secparms4(tvb, offset, newftree);
break;
break;
case NFS4_OP_LAYOUTRETURN:
- offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_reclaim, offset);
- offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_layout_type, offset);
- offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_iomode, offset);
- offset = dissect_nfs4_layoutreturn(tvb, offset, newftree);
+ offset = dissect_nfs4_layoutreturn(tvb, offset, pinfo, newftree, civ);
break;
case NFS4_OP_GETDEVINFO:
sid_hash, file_offset, length64);
break;
+ case NFS4_OP_COPY:
+
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &dst_sid_hash);
+ file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ dst_file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ length64 = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " Src StateID: 0x%04x"
+ " Offset: %" G_GINT64_MODIFIER "u"
+ " Len: %" G_GINT64_MODIFIER "u",
+ sid_hash, file_offset, length64);
+
+ offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_consecutive, offset);
+ offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_synchronous, offset);
+
+ /* FIXME: Report consecutive and sync? */
+
+ if (dst_sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " Dst StateID: 0x%04x"
+ " Offset: %" G_GINT64_MODIFIER "u",
+ dst_sid_hash, dst_file_offset);
+
+ offset = dissect_nfs4_source_servers(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_COPY_NOTIFY:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x",
+ sid_hash);
+
+ offset = dissect_nfs4_netloc(tvb, offset, newftree);
+
+ break;
+
case NFS4_OP_DEALLOCATE:
offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
file_offset = tvb_get_ntoh64(tvb, offset);
sid_hash, file_offset, length64);
break;
+ case NFS4_OP_IO_ADVISE:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ length64 = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x"
+ " Offset: %" G_GINT64_MODIFIER "u"
+ " Len: %" G_GINT64_MODIFIER "u",
+ sid_hash, file_offset, length64);
+ offset = dissect_nfs4_io_hints(tvb, offset, pinfo, tree);
+ break;
+
+ case NFS4_OP_OFFLOAD_CANCEL:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x",
+ sid_hash);
+ break;
+
+ case NFS4_OP_OFFLOAD_STATUS:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x",
+ sid_hash);
+ break;
+
+ case NFS4_OP_READ_PLUS:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ length = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
+ sid_hash, file_offset, length);
+ break;
+
+ case NFS4_OP_LAYOUTERROR:
+ file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ length = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
+ sid_hash, file_offset, length);
+ offset = dissect_nfs4_device_errors(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_LAYOUTSTATS:
+ file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ length = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
+ sid_hash, file_offset, length);
+ offset = dissect_nfs4_layoutstats(tvb, offset, pinfo, newftree, civ, TRUE);
+ break;
+
case NFS4_OP_SEEK:
offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
file_offset = tvb_get_ntoh64(tvb, offset);
sid_hash, file_offset);
break;
+ case NFS4_OP_WRITE_SAME:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ offset = dissect_nfs4_stable_how(tvb, offset, newftree, "stable");
+ offset = dissect_nfs4_app_data_block(tvb, offset, newftree, &hash);
+ wmem_strbuf_append_printf(op_summary[ops_counter].optext,
+ "Pattern Hash: 0x%08x", hash);
+
+ break;
+
+ case NFS4_OP_CLONE:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, &dst_sid_hash);
+ file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ dst_file_offset = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
+ length64 = tvb_get_ntoh64(tvb, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
+ if (sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " Src StateID: 0x%04x"
+ " Offset: %" G_GINT64_MODIFIER "u"
+ " Len: %" G_GINT64_MODIFIER "u",
+ sid_hash, file_offset, length64);
+
+ if (dst_sid_hash != 0)
+ wmem_strbuf_append_printf (op_summary[ops_counter].optext,
+ " Dst StateID: 0x%04x"
+ " Offset: %" G_GINT64_MODIFIER "u",
+ dst_sid_hash, dst_file_offset);
+ break;
+
/* In theory, it's possible to get this opcode */
case NFS4_OP_ILLEGAL:
break;
static int
-dissect_nfs4_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs4_compound_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
const char *tag = NULL;
+ int offset = 0;
offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
/*
proto_item *fitem;
proto_tree *secftree;
- flavor = tvb_get_ntohl(tvb, offset);
- fitem = proto_tree_add_uint(tree, hf_nfs4_secinfo_flavor, tvb, offset, 4,
- flavor);
+ fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_secinfo_flavor, tvb, offset, 4,
+ ENC_BIG_ENDIAN, &flavor);
offset += 4;
switch (flavor)
/*
* With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT,
- * NFS4_OP_SETATTR, and NFS4_OP_SETCLIENTID, all other
+ * NFS4_OP_SETATTR, NFS4_OP_SETCLIENTID, and NFS4_OP_COPY, all other
* ops do *not* return data with the failed status code.
*/
if (status != NFS4_OK
&& opcode != NFS4_OP_LOCK
&& opcode != NFS4_OP_LOCKT
&& opcode != NFS4_OP_SETATTR
- && opcode != NFS4_OP_SETCLIENTID) {
+ && opcode != NFS4_OP_SETCLIENTID
+ && opcode != NFS4_OP_COPY) {
op_summary[ops_counter].iserror = TRUE;
continue;
}
offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_return_on_close,
offset);
offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
- offset = dissect_nfs4_layout(tvb, offset, pinfo, newftree, civ);
+ offset = dissect_nfs4_layoutget(tvb, offset, pinfo, newftree, civ);
break;
case NFS4_OP_LAYOUTCOMMIT:
case NFS4_OP_ALLOCATE:
break;
+ case NFS4_OP_COPY:
+
+ if (status == NFS4_OK) {
+ offset = dissect_nfs4_write_response(tvb, offset, newftree);
+ offset = dissect_nfs4_copy_reqs(tvb, offset, newftree);
+ } else if (status == NFS4ERR_OFFLOAD_NO_REQS)
+ offset = dissect_nfs4_copy_reqs(tvb, offset, newftree);
+
+ break;
+
+ case NFS4_OP_COPY_NOTIFY:
+
+ offset = dissect_nfs4_nfstime(tvb, offset, newftree);
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
+ offset = dissect_nfs4_source_servers(tvb, offset, newftree);
+
+ break;
+
case NFS4_OP_DEALLOCATE:
break;
+ case NFS4_OP_OFFLOAD_CANCEL:
+ break;
+
+ case NFS4_OP_IO_ADVISE:
+ offset = dissect_nfs4_io_hints(tvb, offset, pinfo, tree);
+ break;
+
+ case NFS4_OP_OFFLOAD_STATUS:
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
+ break;
+
+ case NFS4_OP_READ_PLUS:
+ if (status == NFS4_OK) {
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
+ offset = dissect_nfs4_read_plus_content(tvb, offset, newftree);
+ }
+ break;
+
+ case NFS4_OP_LAYOUTERROR:
+ break;
+
+ case NFS4_OP_LAYOUTSTATS:
+ break;
+
case NFS4_OP_SEEK:
offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
break;
+ case NFS4_OP_WRITE_SAME:
+ if (status == NFS4_OK) {
+ offset = dissect_nfs4_write_response(tvb, offset, newftree);
+ }
+ break;
+
+ case NFS4_OP_CLONE:
+ break;
+
default:
break;
}
static int
-dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs4_compound_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data)
{
guint32 status;
const char *tag = NULL;
+ int offset = 0;
offset = dissect_nfs4_status(tvb, offset, tree, &status);
offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
/* proc number, "proc name", dissect_request, dissect_reply */
-/* NULL as function pointer means: type of arguments is "void". */
static const vsff nfs3_proc[] = {
{ 0, "NULL", /* OK */
dissect_nfs3_null_call, dissect_nfs3_null_reply },
{ 0, NULL }
};
+static const rpc_prog_vers_info nfs_vers_info[] = {
+ { 2, nfs2_proc, &hf_nfs2_procedure },
+ { 3, nfs3_proc, &hf_nfs3_procedure },
+ { 4, nfs4_proc, &hf_nfs4_procedure },
+};
+
/*
* Union of the NFSv2, NFSv3, and NFSv4 status codes.
* Used for the "nfs.status" hidden field and in packet-nfsacl.c.
{ 10085, "ERR_REJECT_DELEG" },
{ 10086, "ERR_RETURNCONFLICT" },
{ 10087, "ERR_DELEG_REVOKED" },
+ { 10088, "ERR_PARTNER_NOTSUPP" },
+ { 10089, "ERR_PARTNER_NO_AUTH" },
+ { 10090, "ERR_UNION_NOTSUPP" },
+ { 10091, "ERR_OFFLOAD_DENIED" },
+ { 10092, "ERR_WRONG_LFS" },
+ { 10093, "ERR_BADLABEL" },
+ { 10094, "ERR_OFFLOAD_NO_REQS" },
{ 0, NULL }
};
static value_string_ext names_nfs_nfsstat_ext = VALUE_STRING_EXT_INIT(names_nfs_nfsstat);
};
#endif
+static const value_string netloctype_names[] = {
+ { NL4_NAME, "NL4_NAME" },
+ { NL4_URL, "NL4_URL" },
+ { NL4_NETADDR, "NL4_NETADDR" },
+ { 0, NULL }
+};
+
static const value_string layouttype_names[] = {
{ 1, "LAYOUT4_NFSV4_1_FILES" },
{ 2, "LAYOUT4_OSD2_OBJECTS" },
{ NFS4_OP_CB_WANTS_CANCELLED, "CB_WANTS_CANCELLED" },
{ NFS4_OP_CB_NOTIFY_LOCK, "CB_NOTIFY_LOCK" },
{ NFS4_OP_CB_NOTIFY_DEVICEID, "CB_NOTIFY_DEVICEID" },
+ { NFS4_OP_CB_OFFLOAD, "CB_OFFLOAD" },
{ NFS4_OP_CB_ILLEGAL, "CB_ILLEGAL"},
{ 0, NULL }
};
dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
{
guint32 ops, ops_counter;
+ guint32 status;
guint opcode;
proto_item *fitem;
proto_tree *ftree;
offset += 4;
/* the opcodes are not contiguous */
- if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) &&
+ if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_OFFLOAD) &&
(opcode != NFS4_OP_CB_ILLEGAL))
break;
case NFS4_OP_CB_NOTIFY_LOCK:
case NFS4_OP_CB_NOTIFY_DEVICEID:
break;
+ case NFS4_OP_CB_OFFLOAD:
+ offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "filehandle", NULL, civ);
+ offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
+ offset = dissect_nfs4_status(tvb, offset, newftree, &status);
+ if (status == NFS4_OK) {
+ offset = dissect_nfs4_write_response(tvb, offset, newftree);
+ } else {
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_bytes_copied, offset);
+ }
+ break;
case NFS4_OP_ILLEGAL:
break;
default:
static int
-dissect_nfs4_cb_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_nfs4_cb_compound_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
const char *tag = NULL;
+ int offset = 0;
offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
opcode = tvb_get_ntohl(tvb, offset);
/* sanity check for bogus packets */
- if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_NOTIFY_DEVICEID) &&
+ if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_OFFLOAD) &&
(opcode != NFS4_OP_ILLEGAL))
break;
case NFS4_OP_CB_WANTS_CANCELLED:
case NFS4_OP_CB_NOTIFY_LOCK:
case NFS4_OP_CB_NOTIFY_DEVICEID:
+ case NFS4_OP_CB_OFFLOAD:
break;
case NFS4_OP_ILLEGAL:
break;
static int
-dissect_nfs4_cb_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+dissect_nfs4_cb_compound_reply(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
{
guint32 status;
const char *tag = NULL;
+ int offset = 0;
offset = dissect_nfs4_status(tvb, offset, tree, &status);
offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
{ 0, NULL }
};
-void reg_callback(int cbprog)
-{
- /* Register the protocol as RPC */
- rpc_init_prog(proto_nfs, cbprog, ett_nfs);
-
- /*
- * Register the procedure tables. The version should be 4,
- * but some Linux kernels set this field to 1. "Temporarily",
- * accommodate these servers.
- */
- rpc_init_proc_table(cbprog, 1, nfs_cb_proc, hf_nfs4_cb_procedure);
- rpc_init_proc_table(cbprog, 4, nfs_cb_proc, hf_nfs4_cb_procedure);
-}
+/*
+ * The version should be 4, but some Linux kernels set this field to 1.
+ * "Temporarily" accommodate these servers.
+ */
+static const rpc_prog_vers_info nfs_cb_vers_info[] = {
+ { 1, nfs_cb_proc, &hf_nfs4_cb_procedure },
+ { 4, nfs_cb_proc, &hf_nfs4_cb_procedure },
+};
void
proto_register_nfs(void)
{ &hf_nfs_fh_hash, {
"hash (CRC-32)", "nfs.fh.hash", FT_UINT32, BASE_HEX,
NULL, 0, "file handle hash", HFILL }},
- { &hf_nfs_fh_decode_as, {
- "decode type as", "nfs.fh.decode_as", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
- &names_fhtype_ext, 0, NULL, HFILL }},
{ &hf_nfs_fh_mount_fileid, {
"universal_address", "nfs.universal_address.ipv6", FT_IPv6, BASE_NONE,
NULL, 0, NULL, HFILL }},
-
{ &hf_nfs4_getdevinfo, {
"dev info", "nfs.devinfo", FT_BYTES,
BASE_NONE, NULL, 0, NULL, HFILL }},
- { &hf_nfs4_ffda_version, {
- "version", "nfs.ffda_version", FT_UINT32, BASE_DEC,
+ { &hf_nfs4_ff_version, {
+ "version", "nfs.ff.version", FT_UINT32, BASE_DEC,
NULL, 0, NULL, HFILL }},
- { &hf_nfs4_ffda_minorversion, {
- "minorversion", "nfs.ffda_minorversion", FT_UINT32,
+ { &hf_nfs4_ff_minorversion, {
+ "minorversion", "nfs.ff.minorversion", FT_UINT32,
BASE_DEC, NULL, 0, NULL, HFILL }},
- { &hf_nfs4_ffda_rsize, {
- "max_rsize", "nfs.ffda_rsize", FT_UINT32,
+ { &hf_nfs4_ff_rsize, {
+ "max_rsize", "nfs.ff.rsize", FT_UINT32,
BASE_DEC, NULL, 0, NULL, HFILL }},
- { &hf_nfs4_ffda_wsize, {
- "max_wsize", "nfs.ffda_wsize", FT_UINT32,
+ { &hf_nfs4_ff_wsize, {
+ "max_wsize", "nfs.ff.wsize", FT_UINT32,
BASE_DEC, NULL, 0, NULL, HFILL }},
- { &hf_nfs4_ffda_tightly_coupled, {
- "tightly coupled", "nfs.ffda_tightly_coupled",
+ { &hf_nfs4_ff_tightly_coupled, {
+ "tightly coupled", "nfs.ff.tightly_coupled",
FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
NULL, HFILL }},
+ { &hf_nfs4_ff_layout_flags, {
+ "layout flags", "nfs.ff.layout_flags", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_synthetic_owner, {
+ "synthetic owner", "nfs.ff.synthetic_owner", FT_STRING, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_synthetic_owner_group, {
+ "synthetic group", "nfs.ff.synthetic_owner_group", FT_STRING, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_layout_flags_no_layoutcommit, {
+ "FLAG_NO_LAYOUTCOMMIT", "nfs.ff.layout_flags.no_layoutcommit", FT_BOOLEAN, 32,
+ TFS(&tfs_set_notset), 0x00000001, NULL, HFILL}},
+
+ { &hf_nfs4_fattr_clone_blocksize, {
+ "clone block size", "nfs.fattr4.clone_block_size", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_fattr_space_freed, {
+ "space freed", "nfs.fattr4.space_freed", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_fattr_change_attr_type, {
+ "change attr type", "nfs.fattr4.change_attr_type", FT_UINT32, BASE_DEC,
+ VALS(names_nfs_change_attr_types), 0, NULL, HFILL }},
+
+ { &hf_nfs4_callback_stateids, {
+ "Callback StateIds", "nfs.callback_ids", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_callback_stateids_index, {
+ "Callback Id", "nfs.ff.callback_id_index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_consecutive, {
+ "copy consecutively?", "nfs.consecutive", FT_BOOLEAN, BASE_NONE,
+ TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
+
+ { &hf_nfs4_netloc, {
+ "net loc", "nfs.netloc", FT_BYTES,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_netloc_type, {
+ "netloc type", "nfs.netloctype", FT_UINT32, BASE_DEC,
+ VALS(netloctype_names), 0, NULL, HFILL }},
+
+ { &hf_nfs4_nl_name, {
+ "net loc name", "nfs.nl_name", FT_STRING, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_nl_url, {
+ "net loc url", "nfs.nl_url", FT_STRING, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_source_servers, {
+ "Source Server count", "nfs.source_servers", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_source_server_index, {
+ "Source Server", "nfs.ff.source_server_index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_synchronous, {
+ "copy synchronous?", "nfs.synchronous", FT_BOOLEAN, BASE_NONE,
+ TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
+
+ { &hf_nfs4_io_hints_mask, {
+ "Hint mask", "nfs.hint.mask", FT_UINT32, BASE_HEX,
+ NULL, 0, "ACL attribute mask", HFILL }},
+
+ { &hf_nfs4_io_hint_count, {
+ "Hint count", "nfs.hint.count", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_io_advise_hint, {
+ "Hint", "nfs.hint.hint", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
+ &io_advise_names_ext, 0, NULL, HFILL }},
+
+ { &hf_nfs4_bytes_copied, {
+ "bytes copied", "nfs.bytes_copied", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_read_plus_content_type, {
+ "Content Type", "nfs.content.type", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
+ &read_plus_content_names_ext, 0, NULL, HFILL }},
+
+ { &hf_nfs4_read_plus_content_count, {
+ "Content count", "nfs.content.count", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_read_plus_content_index, {
+ "Content index", "nfs.content.index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_block_size, {
+ "Content index", "nfs.content.index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_block_count, {
+ "Number of Blocks", "nfs.adb.block.count", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_reloff_blocknum, {
+ "Relative Offset Block Number", "nfs.adb.block.reloff_num", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_blocknum, {
+ "Block Number", "nfs.adb.block.num", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_reloff_pattern, {
+ "Relative Offset Pattern", "nfs.adb.pattern.reloff", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_pattern_hash, {
+ "hash (CRC-32)", "nfs.adb.pattern_hash", FT_UINT32, BASE_HEX,
+ NULL, 0, "ADB pattern hash", HFILL }},
+
+ { &hf_nfs4_ff_local, {
+ "client used cache?", "nfs.ff.local", FT_BOOLEAN, BASE_NONE,
+ TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
+
+ { &hf_nfs4_io_count, {
+ "count", "nfs.io_count", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_io_bytes, {
+ "bytes", "nfs.io_bytes", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_ops_requested, {
+ "ops requested", "nfs.ff.ops_requested", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_bytes_requested, {
+ "bytes requested", "nfs.ff.bytes_requested", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_ops_completed, {
+ "ops completed", "nfs.ff.ops_completed", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_bytes_completed, {
+ "bytes completed", "nfs.ff.bytes_completed", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_bytes_not_delivered, {
+ "bytes not delivered", "nfs.ff.bytes_not_delivered", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_layoutstats, {
+ "Layout Stats", "nfs.layoutstats", FT_BYTES, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_device_error_count, {
+ "Device Error count", "nfs.device_error_count", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_device_errors_index, {
+ "Device Error index", "nfs.device_errors_index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_ioerrs_count, {
+ "IO Errors count", "nfs.ff.ioerrs_count", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_ioerrs_index, {
+ "IO Errors index", "nfs.ff.ioerrs_index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_ioerrs_length, {
+ "length", "nfs.ff.ioerrs_length", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_ioerrs_offset, {
+ "offset", "nfs.ff.ioerrs_offset", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_iostats_count, {
+ "IO Stats count", "nfs.ff.iostats_count", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_ff_iostats_index, {
+ "IO Stats index", "nfs.ff.iostats_index", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_nfs4_io_error_op, {
+ "OP", "nfs.ff_ioerrs_op", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
+ &names_nfs4_operation_ext, 0, NULL, HFILL }},
+
/* Hidden field for v2, v3, and v4 status */
{ &hf_nfs_status, {
"Status", "nfs.status", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
&ett_nfs4_chan_attrs,
&ett_nfs4_create_session_flags,
&ett_nfs4_sequence_status_flags,
- &ett_nfs4_want_notify_flags
+ &ett_nfs4_want_notify_flags,
+ &ett_nfs4_ff_layout_flags,
+ &ett_nfs4_layoutstats,
+ &ett_nfs4_io_info,
+ &ett_nfs4_io_latency,
+ &ett_nfs4_io_time,
+ &ett_nfs4_callback_stateids_sub,
+ &ett_nfs4_source_servers_sub,
+ &ett_nfs4_copy,
+ &ett_nfs4_copy_notify,
+ &ett_nfs4_device_errors_sub,
+ &ett_nfs4_layouterror,
+ &ett_nfs4_ff_ioerrs_sub,
+ &ett_nfs4_ff_iostats_sub,
+ &ett_nfs4_clone,
+ &ett_nfs4_offload_cancel,
+ &ett_nfs4_offload_status,
+ &ett_nfs4_io_advise,
+ &ett_nfs4_read_plus,
+ &ett_nfs4_read_plus_content_sub,
+ &ett_nfs4_write_same
};
static ei_register_info ei[] = {
{ &ei_nfs_not_vnx_file, { "nfs.not_vnx_file", PI_UNDECODED, PI_WARN, "Not a Celerra|VNX file handle", EXPFILL }},
{ &ei_protocol_violation, { "nfs.protocol_violation", PI_PROTOCOL, PI_WARN,
"Per RFCs 3530 and 5661 an attribute mask is required but was not provided.", EXPFILL }},
+ { &ei_nfs_too_many_bitmaps, { "nfs.too_many_bitmaps", PI_PROTOCOL, PI_NOTE, "Too many bitmap array items", EXPFILL }},
};
module_t *nfs_module;
expert_module_t* expert_nfs;
+ /* Decode As handling */
+ static build_valid_func nfs_da_build_value[1] = {nfs_value};
+ static decode_as_value_t nfs_da_values = {nfs_prompt, 1, nfs_da_build_value};
+ static decode_as_t nfs_da = {"nfs", "NFS File Handle", "nfs_fhandle.type", 1, 0, &nfs_da_values, NULL, NULL,
+ decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
+
proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
+
+ /* "protocols" registered just for Decode As */
+ proto_nfs_unknown = proto_register_protocol("Unknown", "unknown", "nfs.unknown");
+ proto_nfs_svr4 = proto_register_protocol("SVR4", "svr4", "nfs.svr4");
+ proto_nfs_knfsd_le = proto_register_protocol("KNFSD_LE", "knfsd_le", "nfs.knfsd_le");
+ proto_nfs_nfsd_le = proto_register_protocol("NFSD_LE", "nfsd_le", "nfs.nfsd_le");
+ proto_nfs_knfsd_new = proto_register_protocol("KNFSD_NEW", "knfsd_new", "nfs.knfsd_new");
+ proto_nfs_ontap_v3 = proto_register_protocol("ONTAP_V3", "ontap_v3", "nfs.ontap_v3");
+ proto_nfs_ontap_v4 = proto_register_protocol("ONTAP_V4", "ontap_v4", "nfs.ontap_v4");
+ proto_nfs_ontap_gx_v3 = proto_register_protocol("ONTAP_GX_V3", "ontap_gx_v3", "nfs.ontap_gx_v3");
+ proto_nfs_celerra_vnx = proto_register_protocol("CELERRA_VNX", "celerra_vnx", "nfs.celerra_vnx");
+ proto_nfs_gluster = proto_register_protocol("GLUSTER", "gluster", "nfs.gluster");
+ proto_nfs_dcache = proto_register_protocol("dCache", "dcache", "nfs.dcache");
+
proto_register_field_array(proto_nfs, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_nfs = expert_register_protocol(proto_nfs);
nfs_fhandle_table = register_dissector_table("nfs_fhandle.type",
"NFS Filehandle types", FT_UINT8, BASE_HEX);
- prefs_register_enum_preference(nfs_module,
- "default_fhandle_type",
- "Decode NFS file handles as",
- "Decode all NFS file handles as if they are of this type",
- &default_nfs_fhandle_type,
- nfs_fhandle_types,
- FALSE);
+ prefs_register_obsolete_preference(nfs_module, "default_fhandle_type");
nfs_name_snoop_known = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
nfs_file_handles = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
nfs_fhandle_frame_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
register_init_routine(nfs_name_snoop_init);
+ register_cleanup_routine(nfs_name_snoop_cleanup);
+
+ register_decode_as(&nfs_da);
}
dissector_handle_t fhandle_handle;
/* Register the protocol as RPC */
- rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
+ rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs,
+ G_N_ELEMENTS(nfs_vers_info), nfs_vers_info);
- /* Register the procedure tables */
- rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs2_procedure);
- rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs3_procedure);
- rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs4_procedure);
+ /* Register the CB protocol as RPC */
+ rpc_init_prog(proto_nfs, NFS_CB_PROGRAM, ett_nfs,
+ G_N_ELEMENTS(nfs_cb_vers_info), nfs_cb_vers_info);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_SVR4, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs_svr4);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_LINUX_KNFSD_LE, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs_knfsd_le);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_LINUX_NFSD_LE, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs_nfsd_le);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_LINUX_KNFSD_NEW, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs_knfsd_new);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_NETAPP, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs_ontap_v3);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_V4, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_NETAPP_V4, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_V4, proto_nfs_ontap_v4);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_GX_v3, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_NETAPP_GX_V3, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_GX_v3, proto_nfs_ontap_gx_v3);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_CELERRA_VNX, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_CELERRA_VNX, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_CELERRA_VNX, proto_nfs_celerra_vnx);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_GLUSTER, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_GLUSTER, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_GLUSTER, proto_nfs_gluster);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_DCACHE, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_DCACHE, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_DCACHE, proto_nfs_dcache);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
- fhandle_handle = create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs);
- dissector_add_uint("nfs_fhandle.type", FHT_UNKNOWN, fhandle_handle);
+ fhandle_handle = create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs_unknown);
+ dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
}
/*