From e4106ae5f806e58e51e365bbc077dd748657fc70 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Wed, 7 Dec 2005 09:51:31 +0000 Subject: Fix oroperties, get rid of CRs. svn path=/trunk/; revision=16719 --- epan/dissectors/packet-pvfs2.c | 7260 ++++++++++++++++++++-------------------- 1 file changed, 3630 insertions(+), 3630 deletions(-) mode change 100755 => 100644 epan/dissectors/packet-pvfs2.c (limited to 'epan') diff --git a/epan/dissectors/packet-pvfs2.c b/epan/dissectors/packet-pvfs2.c old mode 100755 new mode 100644 index dea34011e1..5f858c4f21 --- a/epan/dissectors/packet-pvfs2.c +++ b/epan/dissectors/packet-pvfs2.c @@ -1,3630 +1,3630 @@ -/* packet-pvfs.c - * Routines for pvfs2 packet dissection - * By Mike Frisch - * Joint and Several Copyright 2005, Mike Frisch and Platform Computing Inc. - * - * $Id: packet-pvfs.c,v 1.32 2005/10/05 21:13:30 mfrisch Exp $ - * - * Ethereal - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * Copied from packet-smb.c and others - * - * TODO - * - * - Add filename snooping (match file handles with file names), - * similar to how packet-rpc.c/packet-nfs.c implements it - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include "packet-tcp.h" - -#define TCP_PORT_PVFS2 3334 - -#define PVFS2_FH_LENGTH 8 - -/* Header incl. magic number, mode, tag, size */ -#define BMI_HEADER_SIZE 24 - -/* desegmentation of PVFS over TCP */ -static gboolean pvfs_desegment = TRUE; - -/* Forward declaration we need below */ -void proto_reg_handoff_pvfs(void); - -/* Initialize the protocol and registered fields */ -static int proto_pvfs = -1; -static int hf_pvfs_magic_nr = -1; -static int hf_pvfs_mode = -1; -static int hf_pvfs_tag = -1; -static int hf_pvfs_size = -1; -static int hf_pvfs_release_number = -1; -static int hf_pvfs_encoding = -1; -static int hf_pvfs_server_op = -1; -static int hf_pvfs_handle = -1; -static int hf_pvfs_fs_id = -1; -static int hf_pvfs_attrmask = -1; -static int hf_pvfs_attr = -1; -static int hf_pvfs_ds_type = -1; -static int hf_pvfs_error = -1; -static int hf_pvfs_atime = -1; -static int hf_pvfs_atime_sec = -1; -static int hf_pvfs_atime_nsec = -1; -static int hf_pvfs_mtime = -1; -static int hf_pvfs_mtime_sec = -1; -static int hf_pvfs_mtime_nsec = -1; -static int hf_pvfs_ctime = -1; -static int hf_pvfs_ctime_sec = -1; -static int hf_pvfs_ctime_nsec = -1; -static int hf_pvfs_parent_atime = -1; -static int hf_pvfs_parent_atime_sec = -1; -static int hf_pvfs_parent_atime_nsec = -1; -static int hf_pvfs_parent_mtime = -1; -static int hf_pvfs_parent_mtime_sec = -1; -static int hf_pvfs_parent_mtime_nsec = -1; -static int hf_pvfs_parent_ctime = -1; -static int hf_pvfs_parent_ctime_sec = -1; -static int hf_pvfs_parent_ctime_nsec = -1; -static int hf_pvfs_dirent_count = -1; -static int hf_pvfs_directory_version = -1; -static int hf_pvfs_path = -1; -static int hf_pvfs_total_completed = -1; -static int hf_pvfs_io_dist = -1; -static int hf_pvfs_aggregate_size = -1; -static int hf_pvfs_io_type = -1; -static int hf_pvfs_flowproto_type = -1; -static int hf_pvfs_server_param = -1; -static int hf_pvfs_prev_value = -1; -static int hf_pvfs_ram_free_bytes = -1; -static int hf_pvfs_bytes_available = -1; -static int hf_pvfs_bytes_total = -1; -static int hf_pvfs_ram_bytes_total = -1; -static int hf_pvfs_ram_bytes_free = -1; -static int hf_pvfs_load_average_1s = -1; -static int hf_pvfs_load_average_5s = -1; -static int hf_pvfs_load_average_15s = -1; -static int hf_pvfs_uptime_seconds = -1; -static int hf_pvfs_handles_available = -1; -static int hf_pvfs_handles_total = -1; -static int hf_pvfs_unused = -1; -static int hf_pvfs_context_id = -1; -static int hf_pvfs_offset = -1; -static int hf_pvfs_stride = -1; -static int hf_pvfs_lb = -1; -static int hf_pvfs_ub = -1; -static int hf_pvfs_end_time_ms = -1; -static int hf_pvfs_cur_time_ms = -1; -static int hf_pvfs_start_time_ms = -1; -static int hf_pvfs_bytes_written = -1; -static int hf_pvfs_bytes_read = -1; -static int hf_pvfs_metadata_write = -1; -static int hf_pvfs_metadata_read = -1; -static int hf_pvfs_b_size = -1; -static int hf_pvfs_k_size = -1; -static int hf_pvfs_id_gen_t = -1; -static int hf_pvfs_attribute_key = -1; -static int hf_pvfs_attribute_value = -1; -static int hf_pvfs_strip_size = -1; -static int hf_pvfs_ereg = -1; -static int hf_pvfs_sreg = -1; -static int hf_pvfs_num_eregs = -1; -static int hf_pvfs_num_blocks = -1; -static int hf_pvfs_num_contig_chunks = -1; -static int hf_pvfs_server_nr = -1; -static int hf_pvfs_server_count = -1; -static int hf_pvfs_fh_length = -1; -static int hf_pvfs_fh_hash = -1; - -/* Initialize the subtree pointers */ -static gint ett_pvfs = -1; -static gint ett_pvfs_hdr = -1; -static gint ett_pvfs_credentials = -1; -static gint ett_pvfs_server_config = -1; -static gint ett_pvfs_server_config_branch = -1; -static gint ett_pvfs_attrmask = -1; -static gint ett_pvfs_time = -1; -static gint ett_pvfs_extent_array_tree = -1; -static gint ett_pvfs_extent_item = -1; -static gint ett_pvfs_string = -1; -static gint ett_pvfs_attr_tree = -1; -static gint ett_pvfs_distribution = -1; -static gint ett_pvfs_mgmt_perf_stat = -1; -static gint ett_pvfs_mgmt_dspace_info = -1; -static gint ett_pvfs_attr = -1; -static gint ett_pvfs_fh = -1; - -#define BMI_MAGIC_NR 51903 - -static const value_string names_pvfs_mode[] = -{ -#define TCP_MODE_IMMED 1 - { TCP_MODE_IMMED, "TCP_MODE_IMMED" }, -#define TCP_MODE_UNEXP 2 - { TCP_MODE_UNEXP, "TCP_MODE_UNEXP" }, -#define TCP_MODE_EAGER 4 - { TCP_MODE_EAGER, "TCP_MODE_EAGER" }, -#define TCP_MODE_REND 8 - { TCP_MODE_REND, "TCP_MODE_REND" }, - { 0, NULL } -}; - -static const value_string names_pvfs_encoding[] = -{ -#define PVFS_ENCODING_DIRECT 1 - { PVFS_ENCODING_DIRECT, "ENCODING_DIRECT" }, -#define PVFS_ENCODING_LE_BFIELD 2 - { PVFS_ENCODING_LE_BFIELD, "ENCODING_LE_BFIELD" }, -#define PVFS_ENCODING_XDR 3 - { PVFS_ENCODING_XDR, "ENCODING_XDR" }, - { 0, NULL } -}; - -static const value_string names_pvfs_io_type[] = -{ -#define PVFS_IO_READ 1 - { PVFS_IO_READ, "PVFS_IO_READ" }, -#define PVFS_IO_WRITE 2 - { PVFS_IO_WRITE, "PVFS_IO_WRITE" }, - { 0, NULL } -}; - -static const value_string names_pvfs_flowproto_type[] = -{ -#define FLOWPROTO_DUMP_OFFSETS 1 - { FLOWPROTO_DUMP_OFFSETS, "FLOWPROTO_DUMP_OFFSETS" }, -#define FLOWPROTO_BMI_CACHE 2 - { FLOWPROTO_BMI_CACHE, "FLOWPROTO_BMI_CACHE" }, -#define FLOWPROTO_MULTIQUEUE 3 - { FLOWPROTO_MULTIQUEUE, "FLOWPROTO_MULTIQUEUE" }, - { 0, NULL } -}; - -static const value_string names_pvfs_server_param[] = -{ -#define PVFS_SERV_PARAM_INVALID 0 - { PVFS_SERV_PARAM_INVALID, "PVFS_SERV_PARAM_INVALID" }, -#define PVFS_SERV_PARAM_GOSSIP_MASK 1 - { PVFS_SERV_PARAM_GOSSIP_MASK, "PVFS_SERV_PARAM_GOSSIP_MASK" }, -#define PVFS_SERV_PARAM_FSID_CHECK 2 - { PVFS_SERV_PARAM_FSID_CHECK, "PVFS_SERV_PARAM_FSID_CHECK" }, -#define PVFS_SERV_PARAM_ROOT_CHECK 3 - { PVFS_SERV_PARAM_ROOT_CHECK, "PVFS_SERV_PARAM_ROOT_CHECK" }, -#define PVFS_SERV_PARAM_MODE 4 - { PVFS_SERV_PARAM_MODE, "PVFS_SERV_PARAM_MODE" }, -#define PVFS_SERV_PARAM_EVENT_ON 5 - { PVFS_SERV_PARAM_EVENT_ON, "PVFS_SERV_PARAM_EVENT_ON" }, -#define PVFS_SERV_PARAM_EVENT_MASKS 6 - { PVFS_SERV_PARAM_EVENT_MASKS, "PVFS_SERV_PARAM_EVENT_MASKS" }, - { 0, NULL } -}; - -static const value_string names_pvfs_server_mode[] = -{ -#define PVFS_SERVER_NORMAL_MODE 1 - { PVFS_SERVER_NORMAL_MODE, "PVFS_SERVER_NORMAL_MODE" }, -#define PVFS_SERVER_ADMIN_MODE 2 - { PVFS_SERVER_ADMIN_MODE, "PVFS_SERVER_ADMIN_MODE" }, - { 0, NULL } -}; - -/* Forward declaration */ -static gboolean -dissect_pvfs_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - gboolean dissect_other_as_continuation); - - -static void dissect_pvfs_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - dissect_pvfs_common(tvb, pinfo, tree, FALSE); - -} - -static guint get_pvfs_pdu_len(tvbuff_t *tvb, int offset) -{ - guint32 plen; - - /* - * Get the length of the PVFS-over-TCP packet. Ignore top 32 bits - */ - plen = tvb_get_letohl(tvb, offset + 16); - - return plen+24; -} - -static int -dissect_pvfs_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - guint32 magic_nr, mode; - guint64 size; - - /* verify that this is indeed PVFS and that it looks sane */ - if(tvb_length_remaining(tvb,0)<24){ - /* too few bytes remaining to verify the header */ - return 0; - } - - /* validate the magic number */ - magic_nr = tvb_get_letohl(tvb, 0); - if(magic_nr!=BMI_MAGIC_NR){ - return 0; - } - - /* Validate the TCP message mode (32-bit) */ - mode = tvb_get_letohl(tvb, 4); - switch(mode){ - case TCP_MODE_IMMED: - case TCP_MODE_UNEXP: - case TCP_MODE_EAGER: - case TCP_MODE_REND: - break; - default: - /* invalid mode, not a PVFS packet */ - return 0; - } - - /* validate the size : assume size must be >0 and less than 1000000 */ - size=tvb_get_letohl(tvb, 20); - size<<=32; - size|=tvb_get_letohl(tvb, 16); - if((size>1000000)||(size==0)){ - return 0; - } - - tcp_dissect_pdus(tvb, pinfo, tree, pvfs_desegment, 24, get_pvfs_pdu_len, - dissect_pvfs_pdu); - - return tvb_length(tvb); -} - -static const value_string names_pvfs_server_op[] = -{ -#define PVFS_SERV_INVALID 0 - { PVFS_SERV_INVALID, "PVFS_SERV_INVALID" }, -#define PVFS_SERV_CREATE 1 - { PVFS_SERV_CREATE, "PVFS_SERV_CREATE" }, -#define PVFS_SERV_REMOVE 2 - { PVFS_SERV_REMOVE, "PVFS_SERV_REMOVE" }, -#define PVFS_SERV_IO 3 - { PVFS_SERV_IO, "PVFS_SERV_IO" }, -#define PVFS_SERV_GETATTR 4 - { PVFS_SERV_GETATTR, "PVFS_SERV_GETATTR" }, -#define PVFS_SERV_SETATTR 5 - { PVFS_SERV_SETATTR, "PVFS_SERV_SETATTR" }, -#define PVFS_SERV_LOOKUP_PATH 6 - { PVFS_SERV_LOOKUP_PATH, "PVFS_SERV_LOOKUP_PATH" }, -#define PVFS_SERV_CRDIRENT 7 - { PVFS_SERV_CRDIRENT, "PVFS_SERV_CRDIRENT" }, -#define PVFS_SERV_RMDIRENT 8 - { PVFS_SERV_RMDIRENT, "PVFS_SERV_RMDIRENT" }, -#define PVFS_SERV_CHDIRENT 9 - { PVFS_SERV_CHDIRENT, "PVFS_SERV_CHDIRENT" }, -#define PVFS_SERV_TRUNCATE 10 - { PVFS_SERV_TRUNCATE, "PVFS_SERV_TRUNCATE" }, -#define PVFS_SERV_MKDIR 11 - { PVFS_SERV_MKDIR, "PVFS_SERV_MKDIR" }, -#define PVFS_SERV_READDIR 12 - { PVFS_SERV_READDIR, "PVFS_SERV_READDIR" }, -#define PVFS_SERV_GETCONFIG 13 - { PVFS_SERV_GETCONFIG, "PVFS_SERV_GETCONFIG" }, -#define PVFS_SERV_WRITE_COMPLETION 14 - { PVFS_SERV_WRITE_COMPLETION, "PVFS_SERV_WRITE_COMPLETION" }, -#define PVFS_SERV_FLUSH 15 - { PVFS_SERV_FLUSH, "PVFS_SERV_FLUSH" }, -#define PVFS_SERV_MGMT_SETPARAM 16 - { PVFS_SERV_MGMT_SETPARAM, "PVFS_SERV_MGMT_SETPARAM" }, -#define PVFS_SERV_MGMT_NOOP 17 - { PVFS_SERV_MGMT_NOOP, "PVFS_SERV_MGMT_NOOP" }, -#define PVFS_SERV_STATFS 18 - { PVFS_SERV_STATFS, "PVFS_SERV_STATFS" }, -#define PVFS_SERV_PERF_UPDATE 19 /* not a real protocol request */ - { PVFS_SERV_PERF_UPDATE, "PVFS_SERV_PERF_UPDATE" }, -#define PVFS_SERV_MGMT_PERF_MON 20 - { PVFS_SERV_MGMT_PERF_MON, "PVFS_SERV_MGMT_PERF_MON" }, -#define PVFS_SERV_MGMT_ITERATE_HANDLES 21 - { PVFS_SERV_MGMT_ITERATE_HANDLES, "PVFS_SERV_MGMT_ITERATE_HANDLES" }, -#define PVFS_SERV_MGMT_DSPACE_INFO_LIST 22 - { PVFS_SERV_MGMT_DSPACE_INFO_LIST, "PVFS_SERV_MGMT_DSPACE_INFO_LIST" }, -#define PVFS_SERV_MGMT_EVENT_MON 23 - { PVFS_SERV_MGMT_EVENT_MON, "PVFS_SERV_MGMT_EVENT_MON" }, -#define PVFS_SERV_MGMT_REMOVE_OBJECT 24 - { PVFS_SERV_MGMT_REMOVE_OBJECT, "PVFS_SERV_MGMT_REMOVE_OBJECT" }, -#define PVFS_SERV_MGMT_REMOVE_DIRENT 25 - { PVFS_SERV_MGMT_REMOVE_DIRENT, "PVFS_SERV_MGMT_REMOVE_DIRENT" }, -#define PVFS_SERV_MGMT_GET_DIRDATA_HANDLE 26 - { PVFS_SERV_MGMT_GET_DIRDATA_HANDLE, "PVFS_SERV_MGMT_GET_DIRDATA_HANDLE" }, -#define PVFS_SERV_JOB_TIMER 27 /* not a real protocol request */ - { PVFS_SERV_JOB_TIMER, "PVFS_SERV_JOB_TIMER" }, -#define PVFS_SERV_PROTO_ERROR 28 - { PVFS_SERV_PROTO_ERROR, "PVFS_SERV_PROTO_ERROR" }, -#define PVFS_SERV_GETEATTR 29 - { PVFS_SERV_GETEATTR, "PVFS_SERV_GETEATTR" }, -#define PVFS_SERV_SETEATTR 30 - { PVFS_SERV_SETEATTR, "PVFS_SERV_SETEATTR" }, -#define PVFS_SERV_DELEATTR 31 - { PVFS_SERV_DELEATTR, "PVFS_SERV_DELEATTR" }, - { 0, NULL } -}; - -/* special bits used to differentiate PVFS error codes from system - * * errno values - * */ -#define PVFS_ERROR_BIT (1 << 30) - -/* a shorthand to make the error code definitions more readable */ -#define E(num) (num|PVFS_ERROR_BIT) - -static const value_string names_pvfs_error[] = { - { 0, "Success" }, -#define PVFS_EPERM E(1) /* Operation not permitted */ - { PVFS_EPERM, "PVFS_EPERM" }, -#define PVFS_ENOENT E(2) /* No such file or directory */ - { PVFS_ENOENT, "PVFS_ENOENT" }, -#define PVFS_EINTR E(3) /* Interrupted system call */ - { PVFS_EINTR, "PVFS_EINTR" }, -#define PVFS_EIO E(4) /* I/O error */ - { PVFS_EIO, "PVFS_EIO" }, -#define PVFS_ENXIO E(5) /* No such device or address */ - { PVFS_ENXIO, "PVFS_ENXIO" }, -#define PVFS_EBADF E(6) /* Bad file number */ - { PVFS_EBADF, "PVFS_EBADF" }, -#define PVFS_EAGAIN E(7) /* Try again */ - { PVFS_EAGAIN, "PVFS_EAGAIN" }, -#define PVFS_ENOMEM E(8) /* Out of memory */ - { PVFS_ENOMEM, "PVFS_ENOMEM" }, -#define PVFS_EFAULT E(9) /* Bad address */ - { PVFS_EFAULT, "PVFS_EFAULT" }, -#define PVFS_EBUSY E(10) /* Device or resource busy */ - { PVFS_EBUSY, "PVFS_EBUSY" }, -#define PVFS_EEXIST E(11) /* File exists */ - { PVFS_EEXIST, "PVFS_EEXIST" }, -#define PVFS_ENODEV E(12) /* No such device */ - { PVFS_ENODEV, "PVFS_ENODEV" }, -#define PVFS_ENOTDIR E(13) /* Not a directory */ - { PVFS_ENOTDIR, "PVFS_ENOTDIR" }, -#define PVFS_EISDIR E(14) /* Is a directory */ - { PVFS_EISDIR, "PVFS_EISDIR" }, -#define PVFS_EINVAL E(15) /* Invalid argument */ - { PVFS_EINVAL, "PVFS_EINVAL" }, -#define PVFS_EMFILE E(16) /* Too many open files */ - { PVFS_EMFILE, "PVFS_EMFILE" }, -#define PVFS_EFBIG E(17) /* File too large */ - { PVFS_EFBIG, "PVFS_EFBIG" }, -#define PVFS_ENOSPC E(18) /* No space left on device */ - { PVFS_ENOSPC, "PVFS_ENOSPC" }, -#define PVFS_EROFS E(19) /* Read-only file system */ - { PVFS_EROFS, "PVFS_EROFS" }, -#define PVFS_EMLINK E(20) /* Too many links */ - { PVFS_EMLINK, "PVFS_EMLINK" }, -#define PVFS_EPIPE E(21) /* Broken pipe */ - { PVFS_EPIPE, "PVFS_EPIPE" }, -#define PVFS_EDEADLK E(22) /* Resource deadlock would occur */ - { PVFS_EDEADLK, "PVFS_EDEADLK" }, -#define PVFS_ENAMETOOLONG E(23) /* File name too long */ - { PVFS_ENAMETOOLONG, "PVFS_ENAMETOOLONG" }, -#define PVFS_ENOLCK E(24) /* No record locks available */ - { PVFS_ENOLCK, "PVFS_ENOLCK" }, -#define PVFS_ENOSYS E(25) /* Function not implemented */ - { PVFS_ENOSYS, "PVFS_ENOSYS" }, -#define PVFS_ENOTEMPTY E(26) /* Directory not empty */ - { PVFS_ENOTEMPTY, "PVFS_ENOTEMPTY" }, -#define PVFS_ELOOP E(27) /* Too many symbolic links encountered */ - { PVFS_ELOOP, "PVFS_ELOOP" }, -#define PVFS_EWOULDBLOCK E(28) /* Operation would block */ - { PVFS_EWOULDBLOCK, "PVFS_EWOULDBLOCK" }, -#define PVFS_ENOMSG E(29) /* No message of desired type */ - { PVFS_ENOMSG, "PVFS_ENOMSG" }, -#define PVFS_EUNATCH E(30) /* Protocol driver not attached */ - { PVFS_EUNATCH, "PVFS_EUNATCH" }, -#define PVFS_EBADR E(31) /* Invalid request descriptor */ - { PVFS_EBADR, "PVFS_EBADR" }, -#define PVFS_EDEADLOCK E(32) - { PVFS_EDEADLOCK, "PVFS_EDEADLOCK" }, -#define PVFS_ENODATA E(33) /* No data available */ - { PVFS_ENODATA, "PVFS_ENODATA" }, -#define PVFS_ETIME E(34) /* Timer expired */ - { PVFS_ETIME, "PVFS_ETIME" }, -#define PVFS_ENONET E(35) /* Machine is not on the network */ - { PVFS_ENONET, "PVFS_ENONET" }, -#define PVFS_EREMOTE E(36) /* Object is remote */ - { PVFS_EREMOTE, "PVFS_EREMOTE" }, -#define PVFS_ECOMM E(37) /* Communication error on send */ - { PVFS_ECOMM, "PVFS_ECOMM" }, -#define PVFS_EPROTO E(38) /* Protocol error */ - { PVFS_EPROTO, "PVFS_EPROTO" }, -#define PVFS_EBADMSG E(39) /* Not a data message */ - { PVFS_EBADMSG, "PVFS_EBADMSG" }, -#define PVFS_EOVERFLOW E(40) /* Value too large for defined data type */ - { PVFS_EOVERFLOW, "PVFS_EOVERFLOW" }, -#define PVFS_ERESTART E(41) /* Interrupted system call should be restarted */ - { PVFS_ERESTART, "PVFS_ERESTART" }, -#define PVFS_EMSGSIZE E(42) /* Message too long */ - { PVFS_EMSGSIZE, "PVFS_EMSGSIZE" }, -#define PVFS_EPROTOTYPE E(43) /* Protocol wrong type for socket */ - { PVFS_EPROTOTYPE, "PVFS_EPROTOTYPE" }, -#define PVFS_ENOPROTOOPT E(44) /* Protocol not available */ - { PVFS_ENOPROTOOPT, "PVFS_ENOPROTOOPT" }, -#define PVFS_EPROTONOSUPPORT E(45) /* Protocol not supported */ - { PVFS_EPROTONOSUPPORT, "PVFS_EPROTONOSUPPORT" }, -#define PVFS_EOPNOTSUPP E(46) /* Operation not supported on transport endpoint */ - { PVFS_EOPNOTSUPP, "PVFS_EOPNOTSUPP" }, -#define PVFS_EADDRINUSE E(47) /* Address already in use */ - { PVFS_EADDRINUSE, "PVFS_EADDRINUSE" }, -#define PVFS_EADDRNOTAVAIL E(48) /* Cannot assign requested address */ - { PVFS_EADDRNOTAVAIL, "PVFS_EADDRNOTAVAIL" }, -#define PVFS_ENETDOWN E(49) /* Network is down */ - { PVFS_ENETDOWN, "PVFS_ENETDOWN" }, -#define PVFS_ENETUNREACH E(50) /* Network is unreachable */ - { PVFS_ENETUNREACH, "PVFS_ENETUNREACH" }, -#define PVFS_ENETRESET E(51) /* Network dropped connection because of reset */ - { PVFS_ENETRESET, "PVFS_ENETRESET" }, -#define PVFS_ENOBUFS E(52) /* No buffer space available */ - { PVFS_ENOBUFS, "PVFS_ENOBUFS" }, -#define PVFS_ETIMEDOUT E(53) /* Connection timed out */ - { PVFS_ETIMEDOUT, "PVFS_ETIMEDOUT" }, -#define PVFS_ECONNREFUSED E(54) /* Connection refused */ - { PVFS_ECONNREFUSED, "PVFS_ECONNREFUSED" }, -#define PVFS_EHOSTDOWN E(55) /* Host is down */ - { PVFS_EHOSTDOWN, "PVFS_EHOSTDOWN" }, -#define PVFS_EHOSTUNREACH E(56) /* No route to host */ - { PVFS_EHOSTUNREACH, "PVFS_EHOSTUNREACH" }, -#define PVFS_EALREADY E(57) /* Operation already in progress */ - { PVFS_EALREADY, "PVFS_EALREADY" }, -#define PVFS_EACCES E(58) /* Operation already in progress */ - { PVFS_EACCES, "PVFS_EACCES" }, - { 0, NULL } -}; - -static int -dissect_pvfs2_error(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - gint32 err; - const char *errmsg = NULL; - - err = tvb_get_letohl(tvb, offset); - proto_tree_add_uint(tree, hf_pvfs_error, tvb, offset, 4, -err); - offset += 4; - - if ((err != 0) && check_col(pinfo->cinfo, COL_INFO)) - { - errmsg = val_to_str(-err, names_pvfs_error, "Unknown error: %u"); - col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", errmsg); - } - - return offset; -} - -static int -dissect_pvfs_credentials(tvbuff_t *tvb, proto_tree *parent_tree, - int offset) -{ - proto_item *item = NULL; - proto_tree *hcred_tree = NULL; - guint32 uid = 0, gid = 0; - - uid = tvb_get_letohl(tvb, offset); - gid = tvb_get_letohl(tvb, offset + 4); - - if (parent_tree) - { - item = proto_tree_add_text(parent_tree, tvb, offset, 8, - "Credentials (UID: %d, GID: %d)", uid, gid); - - if (item) - hcred_tree = proto_item_add_subtree(item, ett_pvfs_credentials); - } - - /* UID */ - proto_tree_add_text(hcred_tree, tvb, offset, 4, "UID: %d", uid); - offset += 4; - - /* GID */ - proto_tree_add_text(hcred_tree, tvb, offset, 4, "GID: %d", gid); - offset += 4; - - return offset; -} - -static const value_string names_pvfs_attr[] = -{ -#define PVFS_ATTR_COMMON_UID (1 << 0) -#define PVFS_ATTR_BIT_COMMON_UID 0 - { PVFS_ATTR_BIT_COMMON_UID, "PVFS_ATTR_COMMON_UID" }, - -#define PVFS_ATTR_COMMON_GID (1 << 1) -#define PVFS_ATTR_BIT_COMMON_GID 1 - { PVFS_ATTR_BIT_COMMON_GID, "PVFS_ATTR_COMMON_GID" }, - -#define PVFS_ATTR_COMMON_PERM (1 << 2) -#define PVFS_ATTR_BIT_COMMON_PERM 2 - { PVFS_ATTR_BIT_COMMON_PERM, "PVFS_ATTR_COMMON_PERM" }, - -#define PVFS_ATTR_COMMON_ATIME (1 << 3) -#define PVFS_ATTR_BIT_COMMON_ATIME 3 - { PVFS_ATTR_BIT_COMMON_ATIME, "PVFS_ATTR_COMMON_ATIME" }, - -#define PVFS_ATTR_COMMON_CTIME (1 << 4) -#define PVFS_ATTR_BIT_COMMON_CTIME 4 - { PVFS_ATTR_BIT_COMMON_CTIME, "PVFS_ATTR_COMMON_CTIME" }, - -#define PVFS_ATTR_COMMON_MTIME (1 << 5) -#define PVFS_ATTR_BIT_COMMON_MTIME 5 - { PVFS_ATTR_BIT_COMMON_MTIME, "PVFS_ATTR_COMMON_MTIME" }, - -#define PVFS_ATTR_COMMON_TYPE (1 << 6) -#define PVFS_ATTR_BIT_COMMON_TYPE 6 - { PVFS_ATTR_BIT_COMMON_TYPE, "PVFS_ATTR_COMMON_TYPE" }, - -#if 0 -#define PVFS_ATTR_COMMON_ALL \ - (PVFS_ATTR_COMMON_UID | PVFS_ATTR_COMMON_GID | \ - PVFS_ATTR_COMMON_PERM | PVFS_ATTR_COMMON_ATIME | \ - PVFS_ATTR_COMMON_CTIME | PVFS_ATTR_COMMON_MTIME | \ - PVFS_ATTR_COMMON_TYPE) -#endif - -/* internal attribute masks for metadata objects */ -#define PVFS_ATTR_META_DIST (1 << 10) -#define PVFS_ATTR_BIT_META_DIST 10 - { PVFS_ATTR_BIT_META_DIST, "PVFS_ATTR_META_DIST" }, - -#define PVFS_ATTR_META_DFILES (1 << 11) -#define PVFS_ATTR_BIT_META_DFILES 11 - { PVFS_ATTR_BIT_META_DFILES, "PVFS_ATTR_META_DFILES" }, - -#if 0 -#define PVFS_ATTR_META_ALL \ - (PVFS_ATTR_META_DIST | PVFS_ATTR_META_DFILES) -#endif - -/* internal attribute masks for datafile objects */ -#define PVFS_ATTR_DATA_SIZE (1 << 15) -#define PVFS_ATTR_BIT_DATA_SIZE 15 - { PVFS_ATTR_BIT_DATA_SIZE, "PVFS_ATTR_DATA_SIZE" }, - -#if 0 -#define PVFS_ATTR_DATA_ALL PVFS_ATTR_DATA_SIZE -#endif - -/* internal attribute masks for symlink objects */ -#define PVFS_ATTR_SYMLNK_TARGET (1 << 18) -#define PVFS_ATTR_BIT_SYMLINK_TARGET 18 - { PVFS_ATTR_BIT_SYMLINK_TARGET, "PVFS_ATTR_SYMLNK_TARGET" }, - -#if 0 -#define PVFS_ATTR_SYMLNK_ALL PVFS_ATTR_SYMLNK_TARGET -#endif - -/* internal attribute masks for directory objects */ -#define PVFS_ATTR_DIR_DIRENT_COUNT (1 << 19) -#define PVFS_ATTR_BIT_DIR_DIRENT_COUNT 19 - { PVFS_ATTR_BIT_DIR_DIRENT_COUNT, "PVFS_ATTR_DIR_DIRENT_COUNT" }, - -#if 0 -#define PVFS_ATTR_DIR_ALL PVFS_ATTR_DIR_DIRENT_COUNT -#endif - -/* attribute masks used by system interface callers */ -#define PVFS_ATTR_SYS_SIZE (1 << 20) -#define PVFS_ATTR_BIT_SYS_SIZE 20 - { PVFS_ATTR_BIT_SYS_SIZE, "PVFS_ATTR_SYS_SIZE" }, - -#define PVFS_ATTR_SYS_LNK_TARGET (1 << 24) -#define PVFS_ATTR_BIT_SYS_LNK_TARGET 24 - { PVFS_ATTR_BIT_SYS_LNK_TARGET, "PVFS_ATTR_SYS_LNK_TARGET" }, - -#define PVFS_ATTR_SYS_DFILE_COUNT (1 << 25) -#define PVFS_ATTR_BIT_SYS_DFILE_COUNT 25 - { PVFS_ATTR_BIT_SYS_DFILE_COUNT, "PVFS_ATTR_SYS_DFILE_COUNT" }, - -#define PVFS_ATTR_SYS_DIRENT_COUNT (1 << 26) -#define PVFS_ATTR_BIT_SYS_DIRENT_COUNT 26 - { PVFS_ATTR_BIT_SYS_DIRENT_COUNT, "PVFS_ATTR_SYS_DIRENT_COUNT" }, - -#if 0 -#define PVFS_ATTR_SYS_UID PVFS_ATTR_COMMON_UID -#define PVFS_ATTR_SYS_GID PVFS_ATTR_COMMON_GID -#define PVFS_ATTR_SYS_PERM PVFS_ATTR_COMMON_PERM -#define PVFS_ATTR_SYS_ATIME PVFS_ATTR_COMMON_ATIME -#define PVFS_ATTR_SYS_CTIME PVFS_ATTR_COMMON_CTIME -#define PVFS_ATTR_SYS_MTIME PVFS_ATTR_COMMON_MTIME -#define PVFS_ATTR_SYS_TYPE PVFS_ATTR_COMMON_TYPE -#endif - { 0, NULL } -}; - -#if 0 -#define PVFS_ATTR_SYS_ALL \ - (PVFS_ATTR_COMMON_ALL | PVFS_ATTR_SYS_SIZE | \ - PVFS_ATTR_SYS_LNK_TARGET | PVFS_ATTR_SYS_DFILE_COUNT | \ - PVFS_ATTR_SYS_DIRENT_COUNT) - -#define PVFS_ATTR_SYS_ALL_NOSIZE \ - (PVFS_ATTR_COMMON_ALL | PVFS_ATTR_SYS_LNK_TARGET | \ - PVFS_ATTR_SYS_DFILE_COUNT | PVFS_ATTR_SYS_DIRENT_COUNT) - -#define PVFS_ATTR_SYS_ALL_SETABLE \ - (PVFS_ATTR_COMMON_ALL-PVFS_ATTR_COMMON_TYPE) -#endif - - -static int -dissect_pvfs2_attrmask(tvbuff_t *tvb, proto_tree *tree, int offset, - guint32 *pattrmask) -{ - guint32 attrmask = 0, i = 0; - proto_item *attritem = NULL; - proto_tree *attrtree = NULL; - - attrmask = tvb_get_letohl(tvb, offset); - - attritem = proto_tree_add_text(tree, tvb, offset, 4, - "Attribute Mask: %d", attrmask); - - if (attritem) - attrtree = proto_item_add_subtree(attritem, ett_pvfs_attrmask); - - for (i = 0; i < 32; i++) - { - if (attrmask & (1 << i)) - proto_tree_add_uint(attrtree, hf_pvfs_attr, tvb, offset, 4, i); - } - - offset += 4; - - if (pattrmask) - *pattrmask = attrmask; - - return offset; -} - -static const value_string names_pvfs_ds_type[] = { -#define PVFS_TYPE_NONE 0 - { PVFS_TYPE_NONE, "PVFS_TYPE_NONE" }, -#define PVFS_TYPE_METAFILE (1 << 0) - { PVFS_TYPE_METAFILE, "PVFS_TYPE_METAFILE" }, -#define PVFS_TYPE_DATAFILE (1 << 1) - { PVFS_TYPE_DATAFILE, "PVFS_TYPE_DATAFILE" }, -#define PVFS_TYPE_DIRECTORY (1 << 2) - { PVFS_TYPE_DIRECTORY, "PVFS_TYPE_DIRECTORY" }, -#define PVFS_TYPE_SYMLINK (1 << 3) - { PVFS_TYPE_SYMLINK, "PVFS_TYPE_SYMLINK" }, -#define PVFS_TYPE_DIRDATA (1 << 4) - { PVFS_TYPE_DIRDATA, "PVFS_TYPE_DIRDATA" }, - { 0, NULL } -}; - -static int -dissect_pvfs2_ds_type(tvbuff_t *tvb, proto_tree *tree, int offset, - int *pds_type) -{ - guint32 ds_type = 0; - - ds_type = tvb_get_letohl(tvb, offset); - - if (tree) - proto_tree_add_uint(tree, hf_pvfs_ds_type, tvb, offset, 4, ds_type); - - offset += 4; - - if (pds_type) - *pds_type = ds_type; - - return offset; -} - -#define roundup4(x) (((x) + 3) & ~3) -#define roundup8(x) (((x) + 7) & ~7) - -static int -dissect_pvfs_opaque_data(tvbuff_t *tvb, int offset, - proto_tree *tree, - packet_info *pinfo _U_, - int hfindex, - gboolean fixed_length, guint32 length, - gboolean string_data, char **string_buffer_ret) -{ - int data_offset; - proto_item *string_item = NULL; - proto_tree *string_tree = NULL; - - guint32 string_length; - guint32 string_length_full; - guint32 string_length_packet; - guint32 string_length_captured; - guint32 string_length_copy; - - int fill_truncated; - guint32 fill_length; - guint32 fill_length_packet; - guint32 fill_length_captured; - guint32 fill_length_copy; - - int exception = 0; - - char *string_buffer = NULL; - char *string_buffer_print = NULL; - - if (fixed_length) { - string_length = length; - data_offset = offset; - } else { - string_length = tvb_get_letohl(tvb,offset+0); - data_offset = offset + 4; - - /* - * Variable-length strings include NULL terminator on-the-wire but - * NULL terminator is not included in string length. - */ - - if (string_data) - string_length += 1; - } - - string_length_captured = tvb_length_remaining(tvb, data_offset); - string_length_packet = tvb_reported_length_remaining(tvb, data_offset); - - /* - * Strangeness... the protocol basically says that the length plus - * the string must be padded out to an 8-byte boundary. - */ - - if (!string_data) - string_length_full = roundup4(string_length); - else - string_length_full = roundup8(4 + string_length); - - if (string_length_captured < string_length) { - /* truncated string */ - string_length_copy = string_length_captured; - fill_truncated = 2; - fill_length = 0; - fill_length_copy = 0; - - if (string_length_packet < string_length) - exception = ReportedBoundsError; - else - exception = BoundsError; - } - else { - /* full string data */ - string_length_copy = string_length; - - if (!string_data) - fill_length = string_length_full - string_length; - else - fill_length = string_length_full - string_length - 4; - - fill_length_captured = tvb_length_remaining(tvb, - data_offset + string_length); - fill_length_packet = tvb_reported_length_remaining(tvb, - data_offset + string_length); - - if (fill_length_captured < fill_length) { - /* truncated fill bytes */ - fill_length_copy = fill_length_packet; - fill_truncated = 1; - if (fill_length_packet < fill_length) - exception = ReportedBoundsError; - else - exception = BoundsError; - } - else { - /* full fill bytes */ - fill_length_copy = fill_length; - fill_truncated = 0; - } - } - - if (string_data) { - char *tmpstr; - - tmpstr = (char *) tvb_get_ephemeral_string(tvb, data_offset, - string_length_copy); - - string_buffer = memcpy(ep_alloc(string_length_copy+1), tmpstr, string_length_copy); - } else { - string_buffer = (char *) tvb_memcpy(tvb, - ep_alloc(string_length_copy+1), data_offset, string_length_copy); - } - - string_buffer[string_length_copy] = '\0'; - - /* calculate a nice printable string */ - if (string_length) { - if (string_length != string_length_copy) { - if (string_data) { - char *formatted; - guint16 string_buffer_size = 0; - - formatted = format_text((guint8 *)string_buffer, - strlen(string_buffer)); - - string_buffer_size = strlen(formatted) + 12 + 1; - - /* alloc maximum data area */ - string_buffer_print = (char*) ep_alloc(string_buffer_size); - /* copy over the data */ - g_snprintf(string_buffer_print, string_buffer_size - 1, - "%s", formatted); - /* append */ - /* This way, we get the TRUNCATED even - in the case of totally wrong packets, - where \0 are inside the string. - TRUNCATED will appear at the - first \0 or at the end (where we - put the securing \0). - */ - } else { - string_buffer_print=""; - } - } else { - if (string_data) { - string_buffer_print = (char *) - ep_strdup(format_text((guint8 *) string_buffer, - strlen(string_buffer))); - } else { - string_buffer_print=""; - } - } - } else { - string_buffer_print=""; - } - - if (tree) { - string_item = proto_tree_add_text(tree, tvb,offset+0, -1, - "%s: %s", proto_registrar_get_name(hfindex), - string_buffer_print); - - if (string_item) - string_tree = proto_item_add_subtree(string_item, - ett_pvfs_string); - } - if (!fixed_length) { - if (string_tree) - proto_tree_add_text(string_tree, tvb,offset+0,4, - "length: %u (excl. NULL terminator)", string_length - 1); - offset += 4; - } - - if (string_tree) { - if (string_data) { - proto_tree_add_string_format(string_tree, - hfindex, tvb, offset, string_length_copy, - string_buffer, - "contents: %s", string_buffer_print); - } else { - proto_tree_add_bytes_format(string_tree, - hfindex, tvb, offset, string_length_copy, - (guint8 *) string_buffer, - "contents: %s", string_buffer_print); - } - } - - offset += string_length_copy; - - if (fill_length) { - if (string_tree) { - if (fill_truncated) { - proto_tree_add_text(string_tree, tvb, - offset,fill_length_copy, - "fill bytes: opaque data"); - } - else { - proto_tree_add_text(string_tree, tvb, - offset,fill_length_copy, - "fill bytes: opaque data"); - } - } - offset += fill_length_copy; - } - - if (string_item) - proto_item_set_end(string_item, tvb, offset); - - if (string_buffer_ret != NULL) - *string_buffer_ret = string_buffer_print; - - /* - * If the data was truncated, throw the appropriate exception, - * so that dissection stops and the frame is properly marked. - */ - if (exception != 0) - THROW(exception); - - return offset; -} - -static int -dissect_pvfs_string(tvbuff_t *tvb, proto_tree *tree, int hfindex, - int offset, char **string_buffer_ret) -{ - return dissect_pvfs_opaque_data(tvb, offset, tree, NULL, hfindex, - FALSE, 0, TRUE, string_buffer_ret); -} - -static void -dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree) -{ - guint sublen; - guint bytes_left; - gboolean first_line; - - bytes_left = PVFS2_FH_LENGTH; - first_line = TRUE; - while (bytes_left != 0) { - sublen = 16; - if (sublen > bytes_left) - sublen = bytes_left; - proto_tree_add_text(tree, tvb, offset, sublen, - "%s%s", - first_line ? "data: " : - " ", - tvb_bytes_to_str(tvb,offset,sublen)); - bytes_left -= sublen; - offset += sublen; - first_line = FALSE; - } -} - -static void -dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, - proto_tree *tree, guint32 *hash) -{ - guint32 fhhash; - guint32 i; - - /* Not all bytes there. Any attempt to deduce the type would be - senseless. */ - if (!tvb_bytes_exist(tvb, offset, PVFS2_FH_LENGTH)) - goto type_ready; - - /* create a semiunique hash value for the filehandle */ - for(fhhash=0,i=0;i<(PVFS2_FH_LENGTH-3);i+=4){ - guint32 val; - val = tvb_get_ntohl(tvb, offset+i); - fhhash ^= val; - fhhash += val; - } - - proto_tree_add_uint(tree, hf_pvfs_fh_hash, tvb, offset, PVFS2_FH_LENGTH, - fhhash); - - if (hash) - *hash = fhhash; - - /* TODO: add file name snooping code here */ - -type_ready: - dissect_fhandle_data_unknown(tvb, offset, tree); -} - -static int -dissect_pvfs_fh(tvbuff_t *tvb, int offset, packet_info *pinfo, - proto_tree *tree, const char *name, guint32 *hash) -{ - proto_item* fitem = NULL; - proto_tree* ftree = NULL; - - if (tree) - { - fitem = proto_tree_add_text(tree, tvb, offset, PVFS2_FH_LENGTH, - "%s", name); - - if (fitem) - ftree = proto_item_add_subtree(fitem, ett_pvfs_fh); - } - - /* TODO: add fh to file name snooping code here */ - - proto_tree_add_uint(ftree, hf_pvfs_fh_length, tvb, offset, 0, - PVFS2_FH_LENGTH); - - dissect_fhandle_data(tvb, offset, pinfo, ftree, hash); - - offset += PVFS2_FH_LENGTH; - - return offset; -} - -static int -dissect_pvfs_handle_extent(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo, guint32 nCount) -{ - proto_item *extent_item = NULL; - proto_tree *extent_tree = NULL; - - if (tree) - { - extent_item = proto_tree_add_text(tree, tvb, offset, 8, - "Item %d", nCount); - - if (extent_item) - extent_tree = proto_item_add_subtree(extent_item, - ett_pvfs_extent_item); - } - - /* first handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, extent_tree, "first handle", - NULL); - - /* last handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, extent_tree, "last handle", - NULL); - - return offset; -} - -static int -dissect_pvfs_handle_extent_array(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint32 extent_count = 0; - guint32 nCount; - proto_item *extent_array_item = NULL; - proto_tree *extent_array_tree = NULL; - - /* extent count */ - extent_count = tvb_get_letohl(tvb, offset); - - if (tree) - extent_array_item = proto_tree_add_text(tree, tvb, offset, 4, - "Handle Extent Array (count = %d)", extent_count); - - offset += 4; - - if (extent_count > 0) - { - if (extent_array_item) - extent_array_tree = proto_item_add_subtree(extent_array_item, - ett_pvfs_extent_array_tree); - - /* Add extent array items */ - for (nCount = 0; nCount < extent_count; nCount++) - offset = dissect_pvfs_handle_extent(tvb, extent_array_tree, offset, - pinfo, nCount); - } - - return offset; -} - -static int -dissect_pvfs_time(tvbuff_t *tvb, proto_tree *tree, int offset, - int hf_time, int hf_time_sec, int hf_time_nsec) -{ - guint32 seconds; - guint32 nseconds; - nstime_t ts; - proto_item *time_item = NULL; - proto_tree *time_tree = NULL; - - ts.secs = seconds = tvb_get_letohl(tvb, offset); - ts.nsecs = nseconds = tvb_get_letohl(tvb, offset + 4); - - if (tree) - { - time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8, &ts); - - if (time_item) - time_tree = proto_item_add_subtree(time_item, ett_pvfs_time); - } - - if (time_tree) - { - proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4, seconds); - proto_tree_add_uint(time_tree, hf_time_nsec, tvb, offset + 4, 4, - nseconds); - } - - offset += 8; - return offset; -} - -static -int dissect_pvfs_uint64(tvbuff_t *tvb, proto_tree *tree, int offset, - int hfindex, guint64 *pvalue) -{ - guint64 val; - - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - - proto_tree_add_uint64(tree, hfindex, tvb, offset, 8, val); - - if (pvalue) - *pvalue = val; - - return offset + 8; -} - -/* Taken from pvfs2-dist-simple-stripe.h */ -#define PVFS_DIST_SIMPLE_STRIPE_NAME "simple_stripe" -#define PVFS_DIST_SIMPLE_STRIPE_NAME_SIZE 14 - -static int -dissect_pvfs_distribution(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - proto_item *dist_item = NULL; - proto_tree *dist_tree = NULL; - char *distname = NULL; - guint32 distlen = 0; - char *tmpstr = NULL; - guint8 issimplestripe = 0; - - /* Get distribution name length */ - distlen = tvb_get_letohl(tvb, offset); - - /* Get distribution name */ - tmpstr = (char *) tvb_get_ephemeral_string(tvb, offset + 4, distlen); - - if (tree) - { - guint32 total_len; - - /* 'distlen' does not include the NULL terminator */ - total_len = roundup8(4 + distlen + 1); - - if (((distlen + 1) == PVFS_DIST_SIMPLE_STRIPE_NAME_SIZE) && - (strncasecmp(tmpstr, PVFS_DIST_SIMPLE_STRIPE_NAME, - distlen) == 0)) - { - /* Parameter for 'simple_stripe' is 8 bytes */ - total_len += 8; - - issimplestripe = 1; - } - - dist_item = proto_tree_add_text(tree, tvb, offset, total_len + 8, - "Distribution: %s", tmpstr); - - if (dist_item) - dist_tree = proto_item_add_subtree(dist_item, ett_pvfs_distribution); - } - - /* io_dist */ - offset = dissect_pvfs_string(tvb, dist_tree, hf_pvfs_io_dist, offset, - &distname); - - /* TODO: only one distribution type is currently supported */ - if (issimplestripe) - offset = dissect_pvfs_uint64(tvb, dist_tree, offset, - hf_pvfs_strip_size, NULL); - - offset += 8; - - return offset; -} - -static int -dissect_pvfs_meta_attr_dfiles(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint32 dfile_count, i; - - /* dfile_count */ - dfile_count = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "dfile_count: %d", - dfile_count); - offset += 4; - - for (i = 0; i < dfile_count; i++) - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs_object_attr(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - gint32 ds_type = 0; - guint32 attrmask = 0; - proto_item *attr_item = NULL; - proto_tree *attr_tree = NULL; - - if (tree) - { - attr_item = proto_tree_add_text(tree, tvb, offset, -1, "Attributes"); - - if (attr_item) - attr_tree = proto_item_add_subtree(attr_item, ett_pvfs_attr_tree); - } - - /* UID */ - proto_tree_add_text(attr_tree, tvb, offset, 4, "UID: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* GID */ - proto_tree_add_text(attr_tree, tvb, offset, 4, "GID: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* Permissions */ - proto_tree_add_text(attr_tree, tvb, offset, 4, "Permissions: %o", - tvb_get_letohl(tvb, offset)); - offset += 4; - - offset += 4; - - /* atime */ - offset = dissect_pvfs_time(tvb, attr_tree, offset, hf_pvfs_atime, - hf_pvfs_atime_sec, hf_pvfs_atime_nsec); - - /* mtime */ - offset = dissect_pvfs_time(tvb, attr_tree, offset, hf_pvfs_mtime, - hf_pvfs_mtime_sec, hf_pvfs_mtime_nsec); - - /* ctime */ - offset = dissect_pvfs_time(tvb, attr_tree, offset, hf_pvfs_ctime, - hf_pvfs_ctime_sec, hf_pvfs_ctime_nsec); - - /* attrmask */ - offset = dissect_pvfs2_attrmask(tvb, attr_tree, offset, &attrmask); - - /* objtype */ - offset = dissect_pvfs2_ds_type(tvb, attr_tree, offset, &ds_type); - - if (attrmask & PVFS_ATTR_META_DIST) - { - offset = dissect_pvfs_distribution(tvb, attr_tree, offset); - - offset = dissect_pvfs_meta_attr_dfiles(tvb, attr_tree, offset, pinfo); - } - else - { - if (attrmask & PVFS_ATTR_META_DFILES) - { - offset = dissect_pvfs_meta_attr_dfiles(tvb, attr_tree, offset, pinfo); - } - else - { - if (attrmask & PVFS_ATTR_DATA_SIZE) - { - offset = dissect_pvfs_uint64(tvb, attr_tree, offset, hf_pvfs_size, - NULL); - } - else - { - if (attrmask & PVFS_ATTR_SYMLNK_TARGET) - { - /* target_path_len */ - proto_tree_add_text(attr_tree, tvb, offset, 4, - "target_path_len: %d", tvb_get_letohl(tvb, offset)); - offset += 4; - - offset += 4; - - /* target_path */ - offset = dissect_pvfs_string(tvb, attr_tree, hf_pvfs_path, - offset, NULL); - } - else - { - if (attrmask & PVFS_ATTR_DIR_DIRENT_COUNT) - { - offset = dissect_pvfs_uint64(tvb, attr_tree, offset, - hf_pvfs_size, NULL); - } - } - } - } - } - - return offset; -} - -static int -dissect_pvfs_io_type(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - proto_tree_add_uint(tree, hf_pvfs_io_type, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs_flowproto_type(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - proto_tree_add_uint(tree, hf_pvfs_flowproto_type, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs_server_param(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint32 server_param = 0; - guint32 lowpart; - - /* server_param */ - server_param = tvb_get_letohl(tvb, offset); - proto_tree_add_uint(tree, hf_pvfs_server_param, tvb, offset, 4, - server_param); - offset += 4; - - switch (server_param) - { - case PVFS_SERV_PARAM_MODE: - lowpart = tvb_get_letohl(tvb, offset); - - proto_tree_add_text(tree, tvb, offset, 8, - "Server Mode: %s (%u)", - val_to_str(lowpart, names_pvfs_server_mode, "%u"), lowpart); - break; - - case PVFS_SERV_PARAM_FSID_CHECK: - lowpart = tvb_get_letohl(tvb, offset); - proto_tree_add_uint(tree, hf_pvfs_fs_id, tvb, offset, 4, lowpart); - proto_tree_add_uint(tree, hf_pvfs_unused, tvb, offset + 4, 4, - tvb_get_letohl(tvb, offset + 4)); - break; - - case PVFS_SERV_PARAM_ROOT_CHECK: - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - break; - } - - offset += 8; - - return offset; -} - -static int -dissect_pvfs_fs_id(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - if (tree) - proto_tree_add_uint(tree, hf_pvfs_fs_id, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - - offset += 4; - - return offset; -} - -/* - * ======================================================================= - * Request handlers - * ======================================================================= - */ - -static int -dissect_pvfs2_create_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* type */ - offset = dissect_pvfs2_ds_type(tvb, tree, offset, NULL); - - offset += 4; - - offset = dissect_pvfs_handle_extent_array(tvb, tree, offset, pinfo); - - return offset; -} - -static int -dissect_pvfs2_remove_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - return offset; -} - -static int -dissect_pvfs_pint_request(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - guint64 val = 0; - gint32 ereg, sreg; - - /* offset */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_offset, tvb, offset, 8, val); - offset += 8; - - /* TODO: num_eregs */ - proto_tree_add_uint(tree, hf_pvfs_num_eregs, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* TODO: num_blocks */ - proto_tree_add_uint(tree, hf_pvfs_num_blocks, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* TODO: stride */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_stride, tvb, offset, 8, val); - offset += 8; - - /* TODO: ub */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_ub, tvb, offset, 8, val); - offset += 8; - - /* TODO: lb */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_lb, tvb, offset, 8, val); - offset += 8; - - /* TODO: aggregate size */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_aggregate_size, tvb, offset, 8, val); - offset += 8; - - /* num_contig_chunks */ - proto_tree_add_uint(tree, hf_pvfs_num_contig_chunks, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* depth */ - proto_tree_add_text(tree, tvb, offset, 4, "depth: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* num_nested_req */ - proto_tree_add_text(tree, tvb, offset, 4, "num_nested_req: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* committed */ - proto_tree_add_text(tree, tvb, offset, 4, "committed: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* refcount */ - proto_tree_add_text(tree, tvb, offset, 4, "refcount: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* documented */ - offset += 4; - - /* ereg */ - ereg = tvb_get_letohl(tvb, offset); - proto_tree_add_int(tree, hf_pvfs_ereg, tvb, offset, 4, ereg); - offset += 4; - - /* sreg */ - sreg = tvb_get_letohl(tvb, offset); - proto_tree_add_int(tree, hf_pvfs_sreg, tvb, offset, 4, sreg); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_io_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint64 val; - - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* skip4 as per source code */ - offset += 4; - - /* io_type */ - offset = dissect_pvfs_io_type(tvb, tree, offset); - - /* flow_type */ - offset = dissect_pvfs_flowproto_type(tvb, tree, offset); - - /* server_nr */ - proto_tree_add_uint(tree, hf_pvfs_server_nr, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* server_ct */ - proto_tree_add_uint(tree, hf_pvfs_server_count, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* Distribution */ - offset = dissect_pvfs_distribution(tvb, tree, offset); - - proto_tree_add_text(tree, tvb, offset, 4, "numreq: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* */ - offset += 4; - - offset = dissect_pvfs_pint_request(tvb, tree, offset); - - /* TODO: remove this!!! */ - offset = tvb_length(tvb) - 16; - - /* offset */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_offset, tvb, offset, 8, val); - offset += 8; - - /* size */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_size, tvb, offset, 8, val); - offset += 8; - - return offset; -} - -static int -dissect_pvfs2_getattr_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* attrmask */ - offset = dissect_pvfs2_attrmask(tvb, tree, offset, NULL); - - return offset; -} - -static int -dissect_pvfs2_setattr_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* parent_ref: fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - offset = dissect_pvfs_object_attr(tvb, tree, offset, pinfo); - - return offset; -} - -/* As per pvfs2-1.2.0/src/proto/pvfs2-req-proto.h */ -static int -dissect_pvfs2_lookup_path_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* Path */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - /* starting_handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* attribute mask */ - offset = dissect_pvfs2_attrmask(tvb, tree, offset, NULL); - - return offset; -} - -static int -dissect_pvfs2_crdirent_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* Filename */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); - - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "file handle", NULL); - - /* parent_handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "parent handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - /* atime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_atime, - hf_pvfs_atime_sec, hf_pvfs_atime_nsec); - - /* mtime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_mtime, - hf_pvfs_mtime_sec, hf_pvfs_mtime_nsec); - - /* ctime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_ctime, - hf_pvfs_ctime_sec, hf_pvfs_ctime_nsec); - - return offset; -} - -/* TODO: incomplete */ -static int -dissect_pvfs2_rmdirent_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* path */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); - - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - /* atime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_atime, - hf_pvfs_atime_sec, hf_pvfs_atime_nsec); - - /* mtime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_mtime, - hf_pvfs_mtime_sec, hf_pvfs_mtime_nsec); - - /* ctime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_ctime, - hf_pvfs_ctime_sec, hf_pvfs_ctime_nsec); - - return offset; -} - -static int -dissect_pvfs2_chdirent_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* path */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); - - /* New directory entry handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "new directory handle", - NULL); - - /* Parent handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "parent handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* Parent atime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_parent_atime, - hf_pvfs_parent_atime_sec, hf_pvfs_parent_atime_nsec); - - /* Parent mtime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_parent_mtime, - hf_pvfs_parent_mtime_sec, hf_pvfs_parent_mtime_nsec); - - /* Parent ctime */ - offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_parent_ctime, - hf_pvfs_parent_ctime_sec, hf_pvfs_parent_ctime_nsec); - - return offset; -} - -static int -dissect_pvfs2_truncate_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint64 val; - - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - /* size */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_size, tvb, offset, 8, val); - offset += 8; - - /* TODO: flags */ - proto_tree_add_text(tree, tvb, offset, 4, "flags: %u", - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_mkdir_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint count, i; - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - /* attr */ - offset = dissect_pvfs_object_attr(tvb, tree, offset, pinfo); - - /* handle_extent_array */ - count = tvb_get_letohl(tvb, offset); - offset += 4; - - for (i = 0; i < count; i++) - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_readdir_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* object_ref: handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* object_ref: fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* ds_position */ - proto_tree_add_text(tree, tvb, offset, 4, "ds_position: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* dirent_limit */ - proto_tree_add_text(tree, tvb, offset, 4, "dirent_limit: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_flush_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* flags */ - proto_tree_add_text(tree, tvb, offset, 4, "flags: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_mgmt_setparam_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* server_param */ - offset = dissect_pvfs_server_param(tvb, tree, offset, pinfo); - - return offset; -} - -static int -dissect_pvfs2_statfs_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo _U_) -{ - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - return offset; -} - -static int -dissect_pvfs2_mgmt_perf_mon_request(tvbuff_t *tvb _U_, proto_tree *tree _U_, - int offset, packet_info *pinfo _U_) -{ - /* TODO: next_id */ - proto_tree_add_text(tree, tvb, offset, 4, "next_id: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* TODO: count */ - proto_tree_add_text(tree, tvb, offset, 4, "count: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_mgmt_iterate_handles_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_mgmt_dspace_info_list_request(tvbuff_t *tvb, - proto_tree *tree, int offset, packet_info *pinfo) -{ - guint32 handle_count, i; - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* handle count */ - handle_count = tvb_get_letohl(tvb, offset); - offset += 4; - - for (i = 0; i < handle_count; i++) - { - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - } - - return offset; -} - -static int -dissect_pvfs2_mgmt_event_mon_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo _U_) -{ - /* event_count */ - proto_tree_add_text(tree, tvb, offset, 4, "Event count: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_mgmt_remove_object_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* Handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - return offset; -} - -static int -dissect_pvfs2_mgmt_remove_dirent_request(tvbuff_t *tvb, - proto_tree *tree, int offset, packet_info *pinfo) -{ - /* Handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* */ - offset += 4; - - /* entry */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); - - return offset; -} - -static int -dissect_pvfs2_mgmt_get_dirdata_handle_request(tvbuff_t *tvb, - proto_tree *tree, int offset, packet_info *pinfo) -{ - /* Handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - return offset; -} - -/* TODO: untested/incomplete */ -static int -dissect_pvfs_ds_keyval(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - /* attribute key */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_attribute_key, offset, - NULL); - - /* attribute value */ - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_attribute_value, offset, - NULL); - - return offset; -} - -/* TODO: incomplete/untested */ -static int -dissect_ds_keyval_array(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - guint32 nKey, i; - - /* number of keys and vals */ - nKey = tvb_get_letohl(tvb, offset); - offset += 4; - - for (i = 0; i < nKey; i++) - offset = dissect_pvfs_ds_keyval(tvb, tree, offset); - - return offset; -} - -/* TODO: incomplete/untested */ -static int -dissect_pvfs2_geteattr_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - offset = dissect_ds_keyval_array(tvb, tree, offset); - - return offset; -} - -/* TODO: incomplete/untested */ -static int -dissect_pvfs2_seteattr_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - offset += 4; - - offset = dissect_ds_keyval_array(tvb, tree, offset); - - return offset; -} - -/* TODO: untested */ -static int -dissect_pvfs2_deleattr_request(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* key */ - offset = dissect_pvfs_ds_keyval(tvb, tree, offset); - - return offset; -} - -static int -dissect_pvfs2_release_number(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - guint32 release_nr = tvb_get_letohl(tvb, offset); - - proto_tree_add_text(tree, tvb, offset, 4, - "PVFS2 Release Number: %d (%d.%d.%d)", - release_nr, - release_nr / 10000, - (release_nr % 10000) / 100, - (release_nr % 10000) % 100); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_common_header(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - /* PVFS release number */ - offset = dissect_pvfs2_release_number(tvb, tree, offset); - - /* wire encoding type */ - proto_tree_add_uint(tree, hf_pvfs_encoding, tvb, offset, - 4, tvb_get_letohl(tvb, offset)); - offset += 4; - - /* server op */ - proto_tree_add_uint(tree, hf_pvfs_server_op, tvb, offset, 4, - tvb_get_letohl(tvb, offset)); - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_request(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo, guint32 server_op) -{ - /* context_id */ - proto_tree_add_uint(tree, hf_pvfs_context_id, tvb, offset, - 4, tvb_get_letohl(tvb, offset)); - offset += 4; - - /* credentials */ - offset = dissect_pvfs_credentials(tvb, tree, offset); - - switch (server_op) - { - case PVFS_SERV_CREATE: - offset = dissect_pvfs2_create_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_REMOVE: - offset = dissect_pvfs2_remove_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_IO: - offset = dissect_pvfs2_io_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_GETATTR: - offset = dissect_pvfs2_getattr_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_SETATTR: - offset = dissect_pvfs2_setattr_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_LOOKUP_PATH: - offset = dissect_pvfs2_lookup_path_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_CRDIRENT: - offset = dissect_pvfs2_crdirent_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_RMDIRENT: - offset = dissect_pvfs2_rmdirent_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_CHDIRENT: - offset = dissect_pvfs2_chdirent_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_TRUNCATE: - offset = dissect_pvfs2_truncate_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_MKDIR: - offset = dissect_pvfs2_mkdir_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_READDIR: - offset = dissect_pvfs2_readdir_request(tvb, tree, offset, pinfo); - break; - -#if 0 - case PVFS_SERV_GETCONFIG: - /* No parameters in request */ - break; -#endif - -#if 0 - case PVFS_SERV_WRITE_COMPLETION: - /* No parameters in request */ - break; -#endif - - case PVFS_SERV_FLUSH: - offset = dissect_pvfs2_flush_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_MGMT_SETPARAM: - offset = dissect_pvfs2_mgmt_setparam_request(tvb, tree, offset, - pinfo); - break; - -#if 0 - case PVFS_SERV_MGMT_NOOP: - /* No parameters in request */ - break; -#endif - - case PVFS_SERV_STATFS: - offset = dissect_pvfs2_statfs_request(tvb, tree, offset, pinfo); - break; - -#if 0 - case PVFS_SERV_PERF_UPDATE: - /* No parameters in request */ - break; -#endif - - case PVFS_SERV_MGMT_PERF_MON: - offset = dissect_pvfs2_mgmt_perf_mon_request(tvb, tree, offset, - pinfo); - break; - - case PVFS_SERV_MGMT_ITERATE_HANDLES: - offset = dissect_pvfs2_mgmt_iterate_handles_request(tvb, tree, - offset, pinfo); - break; - - case PVFS_SERV_MGMT_DSPACE_INFO_LIST: - offset = dissect_pvfs2_mgmt_dspace_info_list_request(tvb, tree, - offset, pinfo); - break; - - case PVFS_SERV_MGMT_EVENT_MON: - offset = dissect_pvfs2_mgmt_event_mon_request(tvb, tree, offset, - pinfo); - break; - - case PVFS_SERV_MGMT_REMOVE_OBJECT: - offset = dissect_pvfs2_mgmt_remove_object_request(tvb, tree, offset, - pinfo); - break; - - case PVFS_SERV_MGMT_REMOVE_DIRENT: - offset = dissect_pvfs2_mgmt_remove_dirent_request(tvb, tree, offset, - pinfo); - break; - - case PVFS_SERV_MGMT_GET_DIRDATA_HANDLE: - offset = dissect_pvfs2_mgmt_get_dirdata_handle_request(tvb, tree, - offset, pinfo); - break; - -#if 0 - case PVFS_SERV_JOB_TIMER: - /* No parameters in request */ - break; -#endif - - case PVFS_SERV_PROTO_ERROR: - /* TODO: is this necessary? */ - break; - - case PVFS_SERV_GETEATTR: - offset = dissect_pvfs2_geteattr_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_SETEATTR: - offset = dissect_pvfs2_seteattr_request(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_DELEATTR: - offset = dissect_pvfs2_deleattr_request(tvb, tree, offset, pinfo); - break; - - default: - /* TODO: what should we do here? */ - break; - } - - return offset; -} - -/* - * ======================================================================= - * Response handlers - * ======================================================================= - */ - -static int -dissect_pvfs2_create_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* Handle */ - return dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); -} - -static int -dissect_pvfs2_io_response(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - return dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_size, NULL); -} - -static int -dissect_pvfs2_getattr_response(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - offset = dissect_pvfs_object_attr(tvb, tree, offset, pinfo); - - return offset; -} - -static int -dissect_pvfs2_lookup_path_response(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - guint32 nCount = 0; - guint32 handle_count = 0; - guint32 attr_count = 0; - proto_item *attr_item = NULL; - proto_tree *attr_tree = NULL; - - offset += 4; - - /* handle_count */ - handle_count = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Handle Count: %d", - handle_count); - offset += 4; - - /* TODO: add bounds checking */ - for (nCount = 0; nCount < handle_count; nCount++) - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - offset += 4; - - /* array of attributes */ - attr_count = tvb_get_letohl(tvb, offset); - - if (tree) - { - attr_item = proto_tree_add_text(tree, tvb, offset, 4, - "Attribute array (total items: %d)", attr_count); - - if (attr_item) - attr_tree = proto_item_add_subtree(attr_item, ett_pvfs_attr); - } - - offset += 4; - - /* Array of attributes */ - for (nCount = 0; nCount < attr_count; nCount++) - offset = dissect_pvfs_object_attr(tvb, attr_tree, offset, pinfo); - - return offset; -} - -static int -dissect_pvfs2_rmdirent_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* Handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_chdirent_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* Handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_mkdir_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - /* Handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_readdir_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - guint64 val; - guint32 dirent_count = 0; - guint32 nCount = 0; - - /* ds_position */ - proto_tree_add_text(tree, tvb, offset, 4, "ds_position: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - offset += 4; - - /* directory_version */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - proto_tree_add_uint64(tree, hf_pvfs_directory_version, tvb, offset, 8, - val); - offset += 8; - - offset += 4; - - /* dirent_count */ - dirent_count = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "dirent_count: %d", - dirent_count); - offset += 4; - - for (nCount = 0; nCount < dirent_count; nCount++) - { - offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - } - - return offset; -} - -/* - * TODO: this code needs work! Not finished yet! - */ -static int -dissect_pvfs2_getconfig_response(tvbuff_t *tvb, proto_tree *parent_tree, - int offset) -{ - guint32 i; - guint32 total_bytes = 0, total_config_bytes = 0, total_lines = 0; - guint32 bytes_processed = 0; - guint32 length_remaining = 0; - char *ptr = NULL; - proto_item *item = NULL, *config_item = NULL; - proto_tree *tree = NULL, *config_tree = NULL; - guint8 truncated = 0; - - if (parent_tree) - { - item = proto_tree_add_text(parent_tree, tvb, offset, 12, - "Server Config"); - - if (item) - tree = proto_item_add_subtree(item, ett_pvfs_server_config); - } - - /* Total number of bytes in server config (incl. entry count) */ - total_bytes = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Total Bytes: %d", - total_bytes); - offset += 4; - - /* There must be at least 4 bytes of data returned to determine the - * size of the server config data - */ - if (total_bytes < 4) - { - /* Server config not returned, bail out */ - return offset; - } - - /* Number of entries in server config */ - total_lines = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Lines: %d", total_lines); - offset += 4; - - /* Number of bytes in server config */ - total_config_bytes = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "Config Bytes: %d", - total_config_bytes); - offset += 4; - - /* Get pointer to server config data */ - ptr = (char *) tvb_get_ptr(tvb, offset, total_config_bytes); - - /* Check if all data is available */ - length_remaining = tvb_length_remaining(tvb, offset); - - if (length_remaining < total_config_bytes) - { - total_config_bytes = length_remaining; - - truncated = 1; - } - - bytes_processed = 0; - - for (i = 0; i < total_lines; i++) - { - guint8 entry[256], *pentry = entry, *tmp_entry = NULL; - guint32 entry_length = 0, tmp_entry_length = 0; - guint32 bufsiz = sizeof(entry); - - while ((*ptr != '\n') && (*ptr != '\0') && - (bytes_processed < total_config_bytes) && - (entry_length < bufsiz)) - { - *pentry++ = *ptr++; - - bytes_processed++; - entry_length++; - } - - if ((entry_length == bufsiz) && - ((entry[entry_length - 1] != '\n') || - (entry[entry_length - 1] != '\0'))) - { - /* - * Single line of config data doesn't fit into provided buffer, - * config data is malformed. - */ - - break; - } - - if (bytes_processed == total_config_bytes) - { - /* Oops... ran out of data before we could complete the entry */ - break; - } - - *pentry= '\0'; - - tmp_entry = entry; - tmp_entry_length = entry_length; - - /* Remove all whitespace from front of entry */ - while ((tmp_entry_length > 0) && (!isalnum(*tmp_entry)) && - (*tmp_entry != '<')) - { - tmp_entry++; - tmp_entry_length--; - } - - if (tmp_entry[0] == '<') - { - if (tmp_entry[tmp_entry_length - 1] == '>') - { - /* Token */ - if (tmp_entry[1] != '/') - { - /* Opening token, create new tree root */ - config_item = proto_tree_add_text(tree, tvb, offset, - tmp_entry_length, "%s", tmp_entry); - - if (config_item) - config_tree = proto_item_add_subtree(config_item, - ett_pvfs_server_config_branch); - } - else - { - /* Closing token */ - config_item = NULL; - config_tree = NULL; - } - } - else - { - /* Malformed token */ - break; - } - } - else - { - /* Insert items into the root config tree if there's no subtree - * defined. - */ - if (config_tree == NULL) - config_tree = tree; - - if (tmp_entry_length > 0) - { - proto_tree_add_text(config_tree, tvb, offset, tmp_entry_length, - "%s", tmp_entry); - } - } - - offset += entry_length + 1; - - ptr++; - bytes_processed++; - } - - if (bytes_processed < total_config_bytes) - { - /* We ran out of server config data */ - proto_tree_add_text(config_tree, tvb, offset, -1, - ""); - } - - return offset; -} - -static int -dissect_pvfs2_write_completion_response(tvbuff_t *tvb, proto_tree *tree, - int offset) -{ - /* size */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_total_completed, - NULL); - - return offset; -} - -static int -dissect_pvfs2_mgmt_setparam_response(tvbuff_t *tvb, proto_tree *tree, - int offset) -{ - guint64 val; - - /* old_value */ - val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | - tvb_get_letohl(tvb, offset); - - proto_tree_add_uint64(tree, hf_pvfs_prev_value, tvb, offset, 8, val); - - offset += 8; - - return offset; -} - -static int -dissect_pvfs2_statfs_response(tvbuff_t *tvb, proto_tree *tree, int offset) -{ - offset += 4; - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - /* bytes_available */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_bytes_available, - NULL); - - /* bytes_total */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_bytes_total, - NULL); - - /* RAM bytes total */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_ram_bytes_total, - NULL); - - /* RAM bytes free */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_ram_bytes_free, - NULL); - - /* load average (1s) */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_load_average_1s, - NULL); - - /* load average (5s) */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_load_average_5s, - NULL); - - /* load average (15s) */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_load_average_15s, - NULL); - - /* uptime (seconds) */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_uptime_seconds, - NULL); - - /* handles_available_count */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_handles_available, - NULL); - - /* handles_total_count */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_handles_total, - NULL); - - return offset; -} - -static int -dissect_pvfs_mgmt_perf_stat(tvbuff_t *tvb, proto_tree *tree, int offset, - int nItem) -{ - proto_item *stat_item = NULL; - proto_tree *stat_tree = NULL; - - if (tree) - { - stat_item = proto_tree_add_text(tree, tvb, offset, 48, - "Stat Array - Element %d", nItem); - - if (stat_item) - stat_tree = proto_item_add_subtree(stat_item, - ett_pvfs_mgmt_perf_stat); - } - - /* TODO: valid_flag */ - proto_tree_add_text(stat_tree, tvb, offset, 4, "valid_flag: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* TODO: id */ - proto_tree_add_text(stat_tree, tvb, offset, 4, "id: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_start_time_ms, - NULL); - offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_bytes_written, - NULL); - offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_bytes_read, - NULL); - offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_metadata_write, - NULL); - offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_metadata_read, - NULL); - - return offset; -} - -static int -dissect_pvfs2_mgmt_perf_mon_response(tvbuff_t *tvb, proto_tree *tree, - int offset) -{ - guint32 perf_array_count, i; - - /* TODO: suggested_next_id */ - proto_tree_add_text(tree, tvb, offset, 4, "suggested_next_id: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - offset += 4; - - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_end_time_ms, - NULL); - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_cur_time_ms, - NULL); - - offset += 4; - - /* TODO: perf_array_count */ - perf_array_count = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "perf_array_count: %d", - perf_array_count); - offset += 4; - - for (i = 0; i < perf_array_count; i++) - offset = dissect_pvfs_mgmt_perf_stat(tvb, tree, offset, i); - - return offset; -} - -static int -dissect_pvfs2_mgmt_iterate_handles_response(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - guint32 handle_count, i; - - /* ds_position */ - proto_tree_add_text(tree, tvb, offset, 4, "ds_position: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* handle_count */ - handle_count = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "handle_count: %d", - handle_count); - offset += 4; - - /* TODO: this could be improved */ - for (i = 0; i < handle_count; i++) - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_mgmt_dspace_info(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo) -{ - offset = dissect_pvfs2_error(tvb, tree, offset, pinfo); - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - offset = dissect_pvfs2_ds_type(tvb, tree, offset, NULL); - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_b_size, - NULL); - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_k_size, - NULL); - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -static int -dissect_pvfs2_mgmt_dspace_info_list_response(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - guint32 dspace_info_count, i; - proto_item *arr_item = NULL; - proto_tree *arr_tree = NULL; - - offset += 4; - - /* dspace_info_count */ - dspace_info_count = tvb_get_letohl(tvb, offset); - proto_tree_add_text(tree, tvb, offset, 4, "dspace_info_count: %d", - dspace_info_count); - - if ((dspace_info_count > 0) && (tree)) - { - arr_item = proto_tree_add_text(tree, tvb, offset, - dspace_info_count * 40, "dspace_info Array (%d items)", - dspace_info_count); - - if (arr_item) - arr_tree = proto_item_add_subtree(arr_item, - ett_pvfs_mgmt_dspace_info); - } - - for (i = 0; i < dspace_info_count; i++) - offset = dissect_pvfs2_mgmt_dspace_info(tvb, arr_tree, offset, pinfo); - - return offset; -} - -static int -dissect_pvfs2_mgmt_event_mon_response(tvbuff_t *tvb, proto_tree *tree, - int offset) -{ - /* api */ - proto_tree_add_text(tree, tvb, offset, 4, "api: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* operation */ - proto_tree_add_text(tree, tvb, offset, 4, "operation: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* value */ - proto_tree_add_text(tree, tvb, offset, 4, "value: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* id */ - offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_id_gen_t, - NULL); - - /* flags */ - proto_tree_add_text(tree, tvb, offset, 4, "flags: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* tv_sec */ - proto_tree_add_text(tree, tvb, offset, 4, "tv_sec: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - /* tv_usec */ - proto_tree_add_text(tree, tvb, offset, 4, "tv_usec: %d", - tvb_get_letohl(tvb, offset)); - offset += 4; - - offset += 4; - - return offset; -} - -static int -dissect_pvfs2_mgmt_remove_object_response(tvbuff_t *tvb, proto_tree *tree, - int offset, packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - /* fs_id */ - offset = dissect_pvfs_fs_id(tvb, tree, offset); - - return offset; -} - -static int -dissect_pvfs2_mgmt_get_dirdata_handle_response(tvbuff_t *tvb, - proto_tree *tree, int offset, packet_info *pinfo) -{ - /* handle */ - offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); - - return offset; -} - -/* TODO: untested */ -static int -dissect_pvfs2_geteattr_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo _U_) -{ - offset += 4; - - /* Dissect nKey & ds_keyval array */ - offset = dissect_ds_keyval_array(tvb, tree, offset); - - return offset; -} - -static int -dissect_pvfs2_response(tvbuff_t *tvb, proto_tree *tree, int offset, - packet_info *pinfo, guint32 server_op) -{ - /* error code */ - offset = dissect_pvfs2_error(tvb, tree, offset, pinfo); - - switch (server_op) - { - case PVFS_SERV_CREATE: - offset = dissect_pvfs2_create_response(tvb, tree, offset, pinfo); - break; - -#if 0 - case PVFS_SERV_REMOVE: - /* No result data */ - break; -#endif - - case PVFS_SERV_IO: - offset = dissect_pvfs2_io_response(tvb, tree, offset); - break; - - case PVFS_SERV_GETATTR: - offset = dissect_pvfs2_getattr_response(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_SETATTR: - /* No result data */ - break; - - case PVFS_SERV_LOOKUP_PATH: - offset = dissect_pvfs2_lookup_path_response(tvb, tree, offset, pinfo); - break; - -#if 0 - case PVFS_SERV_CRDIRENT: - /* No result data */ - break; -#endif - - case PVFS_SERV_RMDIRENT: - offset = dissect_pvfs2_rmdirent_response(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_CHDIRENT: - offset = dissect_pvfs2_chdirent_response(tvb, tree, offset, pinfo); - break; - -#if 0 - case PVFS_SERV_TRUNCATE: - /* No result data */ - break; -#endif - - case PVFS_SERV_MKDIR: - offset = dissect_pvfs2_mkdir_response(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_READDIR: - offset = dissect_pvfs2_readdir_response(tvb, tree, offset, pinfo); - break; - - case PVFS_SERV_GETCONFIG: - offset = dissect_pvfs2_getconfig_response(tvb, tree, offset); - break; - - case PVFS_SERV_WRITE_COMPLETION: - offset = dissect_pvfs2_write_completion_response(tvb, tree, offset); - break; - -#if 0 - case PVFS_SERV_FLUSH: - /* No result data */ - break; -#endif - - case PVFS_SERV_MGMT_SETPARAM: - offset = dissect_pvfs2_mgmt_setparam_response(tvb, tree, offset); - break; - -#if 0 - case PVFS_SERV_MGMT_NOOP: - /* No result data */ - break; -#endif - - case PVFS_SERV_STATFS: - offset = dissect_pvfs2_statfs_response(tvb, tree, offset); - break; - -#if 0 - case PVFS_SERV_PERF_UPDATE: - /* No result data */ - break; -#endif - - case PVFS_SERV_MGMT_PERF_MON: - offset = dissect_pvfs2_mgmt_perf_mon_response(tvb, tree, offset); - break; - - case PVFS_SERV_MGMT_ITERATE_HANDLES: - offset = dissect_pvfs2_mgmt_iterate_handles_response(tvb, tree, - offset, pinfo); - break; - - case PVFS_SERV_MGMT_DSPACE_INFO_LIST: - offset = dissect_pvfs2_mgmt_dspace_info_list_response(tvb, tree, - offset, pinfo); - break; - - case PVFS_SERV_MGMT_EVENT_MON: - offset = dissect_pvfs2_mgmt_event_mon_response(tvb, tree, offset); - break; - - case PVFS_SERV_MGMT_REMOVE_OBJECT: - offset = dissect_pvfs2_mgmt_remove_object_response(tvb, tree, offset, - pinfo); - break; - -#if 0 - case PVFS_SERV_MGMT_REMOVE_DIRENT: - /* No result data */ - break; -#endif - - case PVFS_SERV_MGMT_GET_DIRDATA_HANDLE: - offset = dissect_pvfs2_mgmt_get_dirdata_handle_response(tvb, tree, - offset, pinfo); - break; - -#if 0 - case PVFS_SERV_JOB_TIMER: - /* No result data */ - break; -#endif - - case PVFS_SERV_PROTO_ERROR: - /* No result data */ - break; - - /* TODO: untested */ - case PVFS_SERV_GETEATTR: - offset = dissect_pvfs2_geteattr_response(tvb, tree, offset, pinfo); - break; - -#if 0 - case PVFS_SERV_SETEATTR: - /* No result data */ - break; -#endif - -#if 0 - case PVFS_SERV_DELEATTR: - /* No result data */ - break; -#endif - - default: - /* TODO: what do we do here? */ - break; - } - - return offset; -} - -static GHashTable *pvfs2_io_tracking_value_table = NULL; - -typedef struct pvfs2_io_tracking_key -{ - guint64 tag; -} pvfs2_io_tracking_key_t; - -typedef struct pvfs2_io_tracking_value -{ - guint32 request_frame_num; - guint32 response_frame_num; - guint32 flow_frame_num; - -} pvfs2_io_tracking_value_t; - -static gint -pvfs2_io_tracking_equal(gconstpointer k1, gconstpointer k2) -{ - const pvfs2_io_tracking_key_t *key1 = (const pvfs2_io_tracking_key_t *) k1; - const pvfs2_io_tracking_key_t *key2 = (const pvfs2_io_tracking_key_t *) k2; - - return (key1->tag == key2->tag); -} - -static guint -pvfs2_io_tracking_hash(gconstpointer k) -{ - const pvfs2_io_tracking_key_t *key = (const pvfs2_io_tracking_key_t *) k; - - return (key->tag >> 32) ^ ((guint32) key->tag); -} - -static void -pvfs2_io_tracking_init(void) -{ - if (pvfs2_io_tracking_value_table != NULL) - g_hash_table_destroy(pvfs2_io_tracking_value_table); - - pvfs2_io_tracking_value_table = g_hash_table_new(pvfs2_io_tracking_hash, - pvfs2_io_tracking_equal); -} - -static pvfs2_io_tracking_value_t * -pvfs2_io_tracking_new_with_tag(guint64 tag, guint32 num) -{ - pvfs2_io_tracking_value_t *value; - pvfs2_io_tracking_key_t *newkey; - - newkey = (pvfs2_io_tracking_key_t *) se_alloc(sizeof(*newkey)); - memset(newkey, 0, sizeof(*newkey)); - newkey->tag = tag; - - value = se_alloc(sizeof(*value)); - memset(value, 0, sizeof(*value)); - - g_hash_table_insert(pvfs2_io_tracking_value_table, newkey, value); - - value->request_frame_num = num; - - return value; -} - -static gboolean -dissect_pvfs_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, - gboolean dissect_other_as_continuation _U_) -{ - guint32 mode = 0; - proto_item *item = NULL, *hitem = NULL; - proto_tree *pvfs_tree = NULL, *pvfs_htree = NULL; - int offset = 0; - guint64 tag; - guint32 server_op; - pvfs2_io_tracking_value_t *val = NULL; - - if (check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "PVFS"); - - if (check_col(pinfo->cinfo, COL_INFO)) - col_clear(pinfo->cinfo, COL_INFO); - - if (parent_tree) - { - item = proto_tree_add_item(parent_tree, proto_pvfs, tvb, 0, -1, FALSE); - - if (item) - pvfs_tree = proto_item_add_subtree(item, ett_pvfs); - } - - proto_tree_add_text(pvfs_tree, tvb, 0, -1, "Version: 2"); - - /* PVFS packet header is 24 bytes */ - hitem = proto_tree_add_text(pvfs_tree, tvb, 0, BMI_HEADER_SIZE, - "BMI Header"); - if (hitem) - pvfs_htree = proto_item_add_subtree(hitem, ett_pvfs_hdr); - - /* Magic number */ - proto_tree_add_item(pvfs_htree, hf_pvfs_magic_nr, tvb, offset, 4, TRUE); - offset += 4; - - /* TCP message mode (32-bit) */ - mode = tvb_get_letohl(tvb, offset); - proto_tree_add_uint(pvfs_htree, hf_pvfs_mode, tvb, offset, 4, mode); - offset += 4; - - /* tag (64-bit) */ - offset = dissect_pvfs_uint64(tvb, pvfs_htree, offset, hf_pvfs_tag, &tag); - - /* size (64-bit) */ - offset = dissect_pvfs_uint64(tvb, pvfs_htree, offset, hf_pvfs_size, NULL); - - /* Lookahead to get server_op (invalid if frame contains flow data) */ - server_op = tvb_get_letohl(tvb, offset + 8); - - if (mode == TCP_MODE_UNEXP) - { - /* Add entry to tracking table for PVFS_SERV_IO request */ - if ((server_op == PVFS_SERV_IO) && !pinfo->fd->flags.visited) - val = pvfs2_io_tracking_new_with_tag(tag, pinfo->fd->num); - } - else - { - pvfs2_io_tracking_key_t key; - - memset(&key, 0, sizeof(key)); - key.tag = tag; - - val = g_hash_table_lookup(pvfs2_io_tracking_value_table, &key); - - /* If this frame contains a known PVFS_SERV_IO tag, track it */ - if (val && !pinfo->fd->flags.visited) - { - /* If response HAS NOT been seen, mark this frame as response */ - if (val->response_frame_num == 0) - val->response_frame_num = pinfo->fd->num; - else - { - /* If response HAS been seen, this frame is flow data */ - if (val->flow_frame_num == 0) - val->flow_frame_num = pinfo->fd->num; - } - } - } - - if (val && (val->flow_frame_num == pinfo->fd->num)) - { - /* This frame is marked as being flow data */ - if (check_col(pinfo->cinfo, COL_INFO)) - col_set_str(pinfo->cinfo, COL_INFO, "PVFS flow data"); - - proto_tree_add_text(pvfs_tree, tvb, offset, -1, ""); - - return TRUE; - } - - /* Extract common part of packet found in requests and responses */ - offset = dissect_pvfs2_common_header(tvb, pvfs_htree, offset); - - /* Update column info display */ - if (check_col(pinfo->cinfo, COL_INFO)) - { - col_set_str(pinfo->cinfo, COL_INFO, - val_to_str(server_op, names_pvfs_server_op, "%u (unknown)")); - - col_append_fstr(pinfo->cinfo, COL_INFO, - (mode == TCP_MODE_UNEXP)? " (request)": " (response)"); - } - - /* TODO: handle all modes */ - if (mode == TCP_MODE_UNEXP) - { - /* Request */ - offset = dissect_pvfs2_request(tvb, pvfs_tree, offset, pinfo, server_op); - } - else - { - /* TODO: re-examine this! */ -#if 0 - if (mode == TCP_MODE_REND) - { - /* - * TODO: move this code outside so it's common for requests and - * responses - */ - - if (check_col(pinfo->cinfo, COL_INFO)) - col_set_str(pinfo->cinfo, COL_INFO, "PVFS2 DATA (request)"); - } - else -#endif - { - /* Response */ - offset = dissect_pvfs2_response(tvb, pvfs_tree, offset, pinfo, - server_op); - } - } - - return TRUE; -} - -/* Register the protocol with Ethereal */ -void -proto_register_pvfs(void) -{ - static hf_register_info hf[] = { - { &hf_pvfs_magic_nr, - { "Magic Number", "pvfs.magic_nr", FT_UINT32, BASE_HEX, - NULL, 0, "Magic Number", HFILL }}, - - { &hf_pvfs_mode, - { "Mode", "pvfs.mode", FT_UINT32, BASE_DEC, - VALS(names_pvfs_mode), 0, "Mode", HFILL }}, - - { &hf_pvfs_tag, - { "Tag", "pvfs.tag", FT_UINT64, BASE_DEC, - NULL, 0, "Tag", HFILL }}, - - { &hf_pvfs_size, - { "Size", "pvfs.size", FT_UINT64, BASE_DEC, - NULL, 0, "Size", HFILL }}, - - { &hf_pvfs_release_number, - { "Release Number", "pvfs.release_number", FT_UINT32, BASE_DEC, - NULL, 0, "Release Number", HFILL }}, - - { &hf_pvfs_encoding, - { "Encoding", "pvfs.encoding", FT_UINT32, BASE_DEC, - VALS(names_pvfs_encoding), 0, "Encoding", HFILL }}, - - { &hf_pvfs_server_op, - { "Server Operation", "pvfs.server_op", FT_UINT32, BASE_DEC, - VALS(names_pvfs_server_op), 0, "Server Operation", HFILL }}, - - { &hf_pvfs_handle, - { "Handle", "pvfs.handle", FT_BYTES, BASE_HEX, - NULL, 0, "Handle", HFILL }}, - - { &hf_pvfs_fs_id, - { "fs_id", "pvfs.fs_id", FT_UINT32, BASE_HEX, - NULL, 0, "File System ID", HFILL }}, - - { &hf_pvfs_attrmask, - { "attrmask", "pvfs.attrmask", FT_UINT32, BASE_HEX, - NULL, 0, "Attribute Mask", HFILL }}, - - { &hf_pvfs_attr, - { "attr", "pvfs.attribute", FT_UINT32, BASE_HEX, - VALS(names_pvfs_attr), 0, "Attribute", HFILL }}, - - { &hf_pvfs_ds_type, - { "ds_type", "pvfs.ds_type", FT_UINT32, BASE_HEX, - VALS(names_pvfs_ds_type), 0, "Type", HFILL }}, - - { &hf_pvfs_error, - { "Result", "pvfs.error", FT_UINT32, BASE_HEX, - VALS(names_pvfs_error), 0, "Result", HFILL }}, - - { &hf_pvfs_atime, - { "atime", "pvfs.atime", FT_ABSOLUTE_TIME, BASE_NONE, - NULL, 0, "Access Time", HFILL }}, - - { &hf_pvfs_atime_sec, - { "seconds", "pvfs.atime.sec", FT_UINT32, BASE_DEC, - NULL, 0, "Access Time (seconds)", HFILL }}, - - { &hf_pvfs_atime_nsec, - { "microseconds", "pvfs.atime.usec", FT_UINT32, BASE_DEC, - NULL, 0, "Access Time (microseconds)", HFILL }}, - - { &hf_pvfs_mtime, - { "mtime", "pvfs.mtime", FT_ABSOLUTE_TIME, BASE_NONE, - NULL, 0, "Modify Time", HFILL }}, - - { &hf_pvfs_mtime_sec, - { "seconds", "pvfs.mtime.sec", FT_UINT32, BASE_DEC, - NULL, 0, "Modify Time (seconds)", HFILL }}, - - { &hf_pvfs_mtime_nsec, - { "microseconds", "pvfs.mtime.usec", FT_UINT32, BASE_DEC, - NULL, 0, "Modify Time (microseconds)", HFILL }}, - - { &hf_pvfs_ctime, - { "ctime", "pvfs.ctime", FT_ABSOLUTE_TIME, BASE_NONE, - NULL, 0, "Creation Time", HFILL }}, - - { &hf_pvfs_ctime_sec, - { "seconds", "pvfs.ctime.sec", FT_UINT32, BASE_DEC, - NULL, 0, "Creation Time (seconds)", HFILL }}, - - { &hf_pvfs_ctime_nsec, - { "microseconds", "pvfs.ctime.usec", FT_UINT32, BASE_DEC, - NULL, 0, "Creation Time (microseconds)", HFILL }}, - - { &hf_pvfs_parent_atime, - { "Parent atime", "pvfs.parent_atime", FT_ABSOLUTE_TIME, BASE_NONE, - NULL, 0, "Access Time", HFILL }}, - - { &hf_pvfs_parent_atime_sec, - { "seconds", "pvfs.parent_atime.sec", FT_UINT32, BASE_DEC, - NULL, 0, "Access Time (seconds)", HFILL }}, - - { &hf_pvfs_parent_atime_nsec, - { "microseconds", "pvfs.parent_atime.usec", FT_UINT32, BASE_DEC, - NULL, 0, "Access Time (microseconds)", HFILL }}, - - { &hf_pvfs_parent_mtime, - { "Parent mtime", "pvfs.parent_mtime", FT_ABSOLUTE_TIME, BASE_NONE, - NULL, 0, "Modify Time", HFILL }}, - - { &hf_pvfs_parent_mtime_sec, - { "seconds", "pvfs.parent_mtime.sec", FT_UINT32, BASE_DEC, - NULL, 0, "Modify Time (seconds)", HFILL }}, - - { &hf_pvfs_parent_mtime_nsec, - { "microseconds", "pvfs.parent_mtime.usec", FT_UINT32, BASE_DEC, - NULL, 0, "Modify Time (microseconds)", HFILL }}, - - { &hf_pvfs_parent_ctime, - { "Parent ctime", "pvfs.parent_ctime", FT_ABSOLUTE_TIME, BASE_NONE, - NULL, 0, "Creation Time", HFILL }}, - - { &hf_pvfs_parent_ctime_sec, - { "seconds", "pvfs.parent_ctime.sec", FT_UINT32, BASE_DEC, - NULL, 0, "Creation Time (seconds)", HFILL }}, - - { &hf_pvfs_parent_ctime_nsec, - { "microseconds", "pvfs.parent_ctime.usec", FT_UINT32, BASE_DEC, - NULL, 0, "Creation Time (microseconds)", HFILL }}, - - { &hf_pvfs_dirent_count, - { "Dir Entry Count", "pvfs.dirent_count", FT_UINT64, BASE_DEC, - NULL, 0, "Directory Entry Count", HFILL }}, - - { &hf_pvfs_directory_version, - { "Directory Version", "pvfs.directory_version", FT_UINT64, BASE_HEX, - NULL, 0, "Directory Version", HFILL }}, - - { &hf_pvfs_path, - { "Path", "pvfs.path", FT_STRING, BASE_DEC, - NULL, 0, "Path", HFILL }}, - - { &hf_pvfs_total_completed, - { "Bytes Completed", "pvfs.bytes_completed", FT_UINT64, BASE_DEC, - NULL, 0, "Bytes Completed", HFILL }}, - - { &hf_pvfs_io_dist, - { "Name", "pvfs.distribution.name", FT_STRING, BASE_DEC, - NULL, 0, "Distribution Name", HFILL }}, - - { &hf_pvfs_aggregate_size, - { "Aggregate Size", "pvfs.aggregate_size", FT_UINT64, BASE_DEC, - NULL, 0, "Aggregate Size", HFILL }}, - - { &hf_pvfs_io_type, - { "I/O Type", "pvfs.io_type", FT_UINT32, BASE_DEC, - VALS(names_pvfs_io_type), 0, "I/O Type", HFILL }}, - - { &hf_pvfs_flowproto_type, - { "Flow Protocol Type", "pvfs.flowproto_type", FT_UINT32, BASE_DEC, - VALS(names_pvfs_flowproto_type), 0, "Flow Protocol Type", HFILL }}, - - { &hf_pvfs_server_param, - { "Server Parameter", "pvfs.server_param", FT_UINT32, BASE_DEC, - VALS(names_pvfs_server_param), 0, "Server Parameter", HFILL }}, - - { &hf_pvfs_prev_value, - { "Previous Value", "pvfs.prev_value", FT_UINT64, BASE_DEC, - NULL, 0, "Previous Value", HFILL }}, - - { &hf_pvfs_ram_free_bytes, - { "RAM Free Bytes", "pvfs.ram.free_bytes", FT_UINT64, BASE_DEC, - NULL, 0, "RAM Free Bytes", HFILL }}, - - { &hf_pvfs_bytes_available, - { "Bytes Available", "pvfs.bytes_available", FT_UINT64, BASE_DEC, - NULL, 0, "Bytes Available", HFILL }}, - - { &hf_pvfs_bytes_total, - { "Bytes Total", "pvfs.bytes_total", FT_UINT64, BASE_DEC, - NULL, 0, "Bytes Total", HFILL }}, - - { &hf_pvfs_ram_bytes_total, - { "RAM Bytes Total", "pvfs.ram_bytes_total", FT_UINT64, BASE_DEC, - NULL, 0, "RAM Bytes Total", HFILL }}, - - { &hf_pvfs_ram_bytes_free, - { "RAM Bytes Free", "pvfs.ram_bytes_free", FT_UINT64, BASE_DEC, - NULL, 0, "RAM Bytes Free", HFILL }}, - - { &hf_pvfs_load_average_1s, - { "Load Average (1s)", "pvfs.load_average.1s", FT_UINT64, BASE_DEC, - NULL, 0, "Load Average (1s)", HFILL }}, - - { &hf_pvfs_load_average_5s, - { "Load Average (5s)", "pvfs.load_average.5s", FT_UINT64, BASE_DEC, - NULL, 0, "Load Average (5s)", HFILL }}, - - { &hf_pvfs_load_average_15s, - { "Load Average (15s)", "pvfs.load_average.15s", FT_UINT64, BASE_DEC, - NULL, 0, "Load Average (15s)", HFILL }}, - - { &hf_pvfs_uptime_seconds, - { "Uptime (seconds)", "pvfs.uptime", FT_UINT64, BASE_DEC, - NULL, 0, "Uptime (seconds)", HFILL }}, - - { &hf_pvfs_handles_available, - { "Handles Available", "pvfs.handles_available", FT_UINT64, BASE_DEC, - NULL, 0, "Handles Available", HFILL }}, - - { &hf_pvfs_handles_total, - { "Total Handles", "pvfs.total_handles", FT_UINT64, BASE_DEC, - NULL, 0, "Total Handles", HFILL }}, - - /* - * This is used when the field returns 64-bits but we're only interested - * in the lower 32-bit bits. - */ - { &hf_pvfs_unused, - { "Unused", "", FT_UINT32, BASE_DEC, - NULL, 0, "Unused", HFILL }}, - - { &hf_pvfs_context_id, - { "Context ID", "pvfs.context_id", FT_UINT32, BASE_DEC, - NULL, 0, "Context ID", HFILL }}, - - { &hf_pvfs_offset, - { "Offset", "pvfs.offset", FT_UINT64, BASE_DEC, - NULL, 0, "Offset", HFILL }}, - - { &hf_pvfs_stride, - { "Stride", "pvfs.stride", FT_UINT64, BASE_DEC, - NULL, 0, "Stride", HFILL }}, - - { &hf_pvfs_ub, - { "ub", "pvfs.ub", FT_UINT64, BASE_DEC, - NULL, 0, "ub", HFILL }}, - - { &hf_pvfs_lb, - { "lb", "pvfs.lb", FT_UINT64, BASE_DEC, - NULL, 0, "lb", HFILL }}, - - { &hf_pvfs_end_time_ms, - { "end_time_ms", "pvfs.end_time_ms", FT_UINT64, BASE_DEC, - NULL, 0, "end_time_ms", HFILL }}, - - { &hf_pvfs_cur_time_ms, - { "cur_time_ms", "pvfs.cur_time_ms", FT_UINT64, BASE_DEC, - NULL, 0, "cur_time_ms", HFILL }}, - - { &hf_pvfs_start_time_ms, - { "start_time_ms", "pvfs.start_time_ms", FT_UINT64, BASE_DEC, - NULL, 0, "start_time_ms", HFILL }}, - - { &hf_pvfs_bytes_written, - { "bytes_written", "pvfs.bytes_written", FT_UINT64, BASE_DEC, - NULL, 0, "bytes_written", HFILL }}, - - { &hf_pvfs_bytes_read, - { "bytes_read", "pvfs.bytes_read", FT_UINT64, BASE_DEC, - NULL, 0, "bytes_read", HFILL }}, - - { &hf_pvfs_metadata_write, - { "metadata_write", "pvfs.metadata_write", FT_UINT64, BASE_DEC, - NULL, 0, "metadata_write", HFILL }}, - - { &hf_pvfs_metadata_read, - { "metadata_read", "pvfs.metadata_read", FT_UINT64, BASE_DEC, - NULL, 0, "metadata_read", HFILL }}, - - { &hf_pvfs_b_size, - { "Size of bstream (if applicable)", "pvfs.b_size", FT_UINT64, - BASE_DEC, NULL, 0, "Size of bstream", HFILL }}, - - { &hf_pvfs_k_size, - { "Number of keyvals (if applicable)", "pvfs.k_size", FT_UINT64, - BASE_DEC, NULL, 0, "Number of keyvals", HFILL }}, - - { &hf_pvfs_id_gen_t, - { "id_gen_t", "pvfs.id_gen_t", FT_UINT64, BASE_DEC, - NULL, 0, "id_gen_t", HFILL }}, - - { &hf_pvfs_attribute_key, - { "Attribute key", "pvfs.attribute.key", FT_STRING, BASE_DEC, - NULL, 0, "Attribute key", HFILL }}, - - { &hf_pvfs_attribute_value, - { "Attribute value", "pvfs.attribute.value", FT_STRING, BASE_DEC, - NULL, 0, "Attribute value", HFILL }}, - - { &hf_pvfs_strip_size, - { "Strip size", "pvfs.strip_size", FT_UINT64, BASE_DEC, - NULL, 0, "Strip size (bytes)", HFILL }}, - - /* TODO: need description */ - { &hf_pvfs_ereg, - { "ereg", "pvfs.ereg", FT_INT32, BASE_DEC, - NULL, 0, "ereg", HFILL }}, - - /* TODO: need description */ - { &hf_pvfs_sreg, - { "sreg", "pvfs.sreg", FT_INT32, BASE_DEC, - NULL, 0, "sreg", HFILL }}, - - { &hf_pvfs_num_eregs, - { "Number of eregs", "pvfs.num_eregs", FT_UINT32, BASE_DEC, - NULL, 0, "Number of eregs", HFILL }}, - - { &hf_pvfs_num_blocks, - { "Number of blocks", "pvfs.num_blocks", FT_UINT32, BASE_DEC, - NULL, 0, "Number of blocks", HFILL }}, - - { &hf_pvfs_num_contig_chunks, - { "Number of contig_chunks", "pvfs.num_contig_chunks", FT_UINT32, - BASE_DEC, NULL, 0, "Number of contig_chunks", HFILL }}, - - { &hf_pvfs_server_nr, - { "Server #", "pvfs.server_nr", FT_UINT32, BASE_DEC, - NULL, 0, "Server #", HFILL }}, - - { &hf_pvfs_server_count, - { "Number of servers", "pvfs.server_count", FT_UINT32, BASE_DEC, - NULL, 0, "Number of servers", HFILL }}, - - { &hf_pvfs_fh_length, - { "length", "pvfs.fh.length", FT_UINT32, BASE_DEC, - NULL, 0, "file handle length", HFILL }}, - - { &hf_pvfs_fh_hash, - { "hash", "pvfs.fh.hash", FT_UINT32, BASE_HEX, - NULL, 0, "file handle hash", HFILL }}, - }; - - /* Setup protocol subtree array */ - static gint *ett[] = { - &ett_pvfs, - &ett_pvfs_hdr, - &ett_pvfs_credentials, - &ett_pvfs_server_config, - &ett_pvfs_server_config_branch, - &ett_pvfs_attrmask, - &ett_pvfs_time, - &ett_pvfs_extent_array_tree, - &ett_pvfs_extent_item, - &ett_pvfs_string, - &ett_pvfs_attr_tree, - &ett_pvfs_distribution, - &ett_pvfs_mgmt_perf_stat, - &ett_pvfs_mgmt_dspace_info, - &ett_pvfs_attr, - &ett_pvfs_fh - }; - module_t *pvfs_module; - - /* Register the protocol name and description */ - proto_pvfs = proto_register_protocol("Parallel Virtual File System", - "PVFS", "pvfs"); - - /* - * Required function calls to register the header fields and - * subtrees used - */ - - proto_register_field_array(proto_pvfs, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); - - register_init_routine(pvfs2_io_tracking_init); - - pvfs_module = prefs_register_protocol(proto_pvfs, NULL); - prefs_register_bool_preference(pvfs_module, "desegment", - "Reassemble PVFS messages spanning multiple TCP segments", - "Whether the PVFS dissector should reassemble messages spanning multiple TCP segments. " - "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", - &pvfs_desegment); -} - -void -proto_reg_handoff_pvfs(void) -{ - dissector_handle_t pvfs_handle; - - pvfs_handle = new_create_dissector_handle(dissect_pvfs_heur, proto_pvfs); - dissector_add("tcp.port", TCP_PORT_PVFS2, pvfs_handle); - - heur_dissector_add("tcp", dissect_pvfs_heur, proto_pvfs); -} - +/* packet-pvfs.c + * Routines for pvfs2 packet dissection + * By Mike Frisch + * Joint and Several Copyright 2005, Mike Frisch and Platform Computing Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Copied from packet-smb.c and others + * + * TODO + * + * - Add filename snooping (match file handles with file names), + * similar to how packet-rpc.c/packet-nfs.c implements it + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include "packet-tcp.h" + +#define TCP_PORT_PVFS2 3334 + +#define PVFS2_FH_LENGTH 8 + +/* Header incl. magic number, mode, tag, size */ +#define BMI_HEADER_SIZE 24 + +/* desegmentation of PVFS over TCP */ +static gboolean pvfs_desegment = TRUE; + +/* Forward declaration we need below */ +void proto_reg_handoff_pvfs(void); + +/* Initialize the protocol and registered fields */ +static int proto_pvfs = -1; +static int hf_pvfs_magic_nr = -1; +static int hf_pvfs_mode = -1; +static int hf_pvfs_tag = -1; +static int hf_pvfs_size = -1; +static int hf_pvfs_release_number = -1; +static int hf_pvfs_encoding = -1; +static int hf_pvfs_server_op = -1; +static int hf_pvfs_handle = -1; +static int hf_pvfs_fs_id = -1; +static int hf_pvfs_attrmask = -1; +static int hf_pvfs_attr = -1; +static int hf_pvfs_ds_type = -1; +static int hf_pvfs_error = -1; +static int hf_pvfs_atime = -1; +static int hf_pvfs_atime_sec = -1; +static int hf_pvfs_atime_nsec = -1; +static int hf_pvfs_mtime = -1; +static int hf_pvfs_mtime_sec = -1; +static int hf_pvfs_mtime_nsec = -1; +static int hf_pvfs_ctime = -1; +static int hf_pvfs_ctime_sec = -1; +static int hf_pvfs_ctime_nsec = -1; +static int hf_pvfs_parent_atime = -1; +static int hf_pvfs_parent_atime_sec = -1; +static int hf_pvfs_parent_atime_nsec = -1; +static int hf_pvfs_parent_mtime = -1; +static int hf_pvfs_parent_mtime_sec = -1; +static int hf_pvfs_parent_mtime_nsec = -1; +static int hf_pvfs_parent_ctime = -1; +static int hf_pvfs_parent_ctime_sec = -1; +static int hf_pvfs_parent_ctime_nsec = -1; +static int hf_pvfs_dirent_count = -1; +static int hf_pvfs_directory_version = -1; +static int hf_pvfs_path = -1; +static int hf_pvfs_total_completed = -1; +static int hf_pvfs_io_dist = -1; +static int hf_pvfs_aggregate_size = -1; +static int hf_pvfs_io_type = -1; +static int hf_pvfs_flowproto_type = -1; +static int hf_pvfs_server_param = -1; +static int hf_pvfs_prev_value = -1; +static int hf_pvfs_ram_free_bytes = -1; +static int hf_pvfs_bytes_available = -1; +static int hf_pvfs_bytes_total = -1; +static int hf_pvfs_ram_bytes_total = -1; +static int hf_pvfs_ram_bytes_free = -1; +static int hf_pvfs_load_average_1s = -1; +static int hf_pvfs_load_average_5s = -1; +static int hf_pvfs_load_average_15s = -1; +static int hf_pvfs_uptime_seconds = -1; +static int hf_pvfs_handles_available = -1; +static int hf_pvfs_handles_total = -1; +static int hf_pvfs_unused = -1; +static int hf_pvfs_context_id = -1; +static int hf_pvfs_offset = -1; +static int hf_pvfs_stride = -1; +static int hf_pvfs_lb = -1; +static int hf_pvfs_ub = -1; +static int hf_pvfs_end_time_ms = -1; +static int hf_pvfs_cur_time_ms = -1; +static int hf_pvfs_start_time_ms = -1; +static int hf_pvfs_bytes_written = -1; +static int hf_pvfs_bytes_read = -1; +static int hf_pvfs_metadata_write = -1; +static int hf_pvfs_metadata_read = -1; +static int hf_pvfs_b_size = -1; +static int hf_pvfs_k_size = -1; +static int hf_pvfs_id_gen_t = -1; +static int hf_pvfs_attribute_key = -1; +static int hf_pvfs_attribute_value = -1; +static int hf_pvfs_strip_size = -1; +static int hf_pvfs_ereg = -1; +static int hf_pvfs_sreg = -1; +static int hf_pvfs_num_eregs = -1; +static int hf_pvfs_num_blocks = -1; +static int hf_pvfs_num_contig_chunks = -1; +static int hf_pvfs_server_nr = -1; +static int hf_pvfs_server_count = -1; +static int hf_pvfs_fh_length = -1; +static int hf_pvfs_fh_hash = -1; + +/* Initialize the subtree pointers */ +static gint ett_pvfs = -1; +static gint ett_pvfs_hdr = -1; +static gint ett_pvfs_credentials = -1; +static gint ett_pvfs_server_config = -1; +static gint ett_pvfs_server_config_branch = -1; +static gint ett_pvfs_attrmask = -1; +static gint ett_pvfs_time = -1; +static gint ett_pvfs_extent_array_tree = -1; +static gint ett_pvfs_extent_item = -1; +static gint ett_pvfs_string = -1; +static gint ett_pvfs_attr_tree = -1; +static gint ett_pvfs_distribution = -1; +static gint ett_pvfs_mgmt_perf_stat = -1; +static gint ett_pvfs_mgmt_dspace_info = -1; +static gint ett_pvfs_attr = -1; +static gint ett_pvfs_fh = -1; + +#define BMI_MAGIC_NR 51903 + +static const value_string names_pvfs_mode[] = +{ +#define TCP_MODE_IMMED 1 + { TCP_MODE_IMMED, "TCP_MODE_IMMED" }, +#define TCP_MODE_UNEXP 2 + { TCP_MODE_UNEXP, "TCP_MODE_UNEXP" }, +#define TCP_MODE_EAGER 4 + { TCP_MODE_EAGER, "TCP_MODE_EAGER" }, +#define TCP_MODE_REND 8 + { TCP_MODE_REND, "TCP_MODE_REND" }, + { 0, NULL } +}; + +static const value_string names_pvfs_encoding[] = +{ +#define PVFS_ENCODING_DIRECT 1 + { PVFS_ENCODING_DIRECT, "ENCODING_DIRECT" }, +#define PVFS_ENCODING_LE_BFIELD 2 + { PVFS_ENCODING_LE_BFIELD, "ENCODING_LE_BFIELD" }, +#define PVFS_ENCODING_XDR 3 + { PVFS_ENCODING_XDR, "ENCODING_XDR" }, + { 0, NULL } +}; + +static const value_string names_pvfs_io_type[] = +{ +#define PVFS_IO_READ 1 + { PVFS_IO_READ, "PVFS_IO_READ" }, +#define PVFS_IO_WRITE 2 + { PVFS_IO_WRITE, "PVFS_IO_WRITE" }, + { 0, NULL } +}; + +static const value_string names_pvfs_flowproto_type[] = +{ +#define FLOWPROTO_DUMP_OFFSETS 1 + { FLOWPROTO_DUMP_OFFSETS, "FLOWPROTO_DUMP_OFFSETS" }, +#define FLOWPROTO_BMI_CACHE 2 + { FLOWPROTO_BMI_CACHE, "FLOWPROTO_BMI_CACHE" }, +#define FLOWPROTO_MULTIQUEUE 3 + { FLOWPROTO_MULTIQUEUE, "FLOWPROTO_MULTIQUEUE" }, + { 0, NULL } +}; + +static const value_string names_pvfs_server_param[] = +{ +#define PVFS_SERV_PARAM_INVALID 0 + { PVFS_SERV_PARAM_INVALID, "PVFS_SERV_PARAM_INVALID" }, +#define PVFS_SERV_PARAM_GOSSIP_MASK 1 + { PVFS_SERV_PARAM_GOSSIP_MASK, "PVFS_SERV_PARAM_GOSSIP_MASK" }, +#define PVFS_SERV_PARAM_FSID_CHECK 2 + { PVFS_SERV_PARAM_FSID_CHECK, "PVFS_SERV_PARAM_FSID_CHECK" }, +#define PVFS_SERV_PARAM_ROOT_CHECK 3 + { PVFS_SERV_PARAM_ROOT_CHECK, "PVFS_SERV_PARAM_ROOT_CHECK" }, +#define PVFS_SERV_PARAM_MODE 4 + { PVFS_SERV_PARAM_MODE, "PVFS_SERV_PARAM_MODE" }, +#define PVFS_SERV_PARAM_EVENT_ON 5 + { PVFS_SERV_PARAM_EVENT_ON, "PVFS_SERV_PARAM_EVENT_ON" }, +#define PVFS_SERV_PARAM_EVENT_MASKS 6 + { PVFS_SERV_PARAM_EVENT_MASKS, "PVFS_SERV_PARAM_EVENT_MASKS" }, + { 0, NULL } +}; + +static const value_string names_pvfs_server_mode[] = +{ +#define PVFS_SERVER_NORMAL_MODE 1 + { PVFS_SERVER_NORMAL_MODE, "PVFS_SERVER_NORMAL_MODE" }, +#define PVFS_SERVER_ADMIN_MODE 2 + { PVFS_SERVER_ADMIN_MODE, "PVFS_SERVER_ADMIN_MODE" }, + { 0, NULL } +}; + +/* Forward declaration */ +static gboolean +dissect_pvfs_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + gboolean dissect_other_as_continuation); + + +static void dissect_pvfs_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + dissect_pvfs_common(tvb, pinfo, tree, FALSE); + +} + +static guint get_pvfs_pdu_len(tvbuff_t *tvb, int offset) +{ + guint32 plen; + + /* + * Get the length of the PVFS-over-TCP packet. Ignore top 32 bits + */ + plen = tvb_get_letohl(tvb, offset + 16); + + return plen+24; +} + +static int +dissect_pvfs_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint32 magic_nr, mode; + guint64 size; + + /* verify that this is indeed PVFS and that it looks sane */ + if(tvb_length_remaining(tvb,0)<24){ + /* too few bytes remaining to verify the header */ + return 0; + } + + /* validate the magic number */ + magic_nr = tvb_get_letohl(tvb, 0); + if(magic_nr!=BMI_MAGIC_NR){ + return 0; + } + + /* Validate the TCP message mode (32-bit) */ + mode = tvb_get_letohl(tvb, 4); + switch(mode){ + case TCP_MODE_IMMED: + case TCP_MODE_UNEXP: + case TCP_MODE_EAGER: + case TCP_MODE_REND: + break; + default: + /* invalid mode, not a PVFS packet */ + return 0; + } + + /* validate the size : assume size must be >0 and less than 1000000 */ + size=tvb_get_letohl(tvb, 20); + size<<=32; + size|=tvb_get_letohl(tvb, 16); + if((size>1000000)||(size==0)){ + return 0; + } + + tcp_dissect_pdus(tvb, pinfo, tree, pvfs_desegment, 24, get_pvfs_pdu_len, + dissect_pvfs_pdu); + + return tvb_length(tvb); +} + +static const value_string names_pvfs_server_op[] = +{ +#define PVFS_SERV_INVALID 0 + { PVFS_SERV_INVALID, "PVFS_SERV_INVALID" }, +#define PVFS_SERV_CREATE 1 + { PVFS_SERV_CREATE, "PVFS_SERV_CREATE" }, +#define PVFS_SERV_REMOVE 2 + { PVFS_SERV_REMOVE, "PVFS_SERV_REMOVE" }, +#define PVFS_SERV_IO 3 + { PVFS_SERV_IO, "PVFS_SERV_IO" }, +#define PVFS_SERV_GETATTR 4 + { PVFS_SERV_GETATTR, "PVFS_SERV_GETATTR" }, +#define PVFS_SERV_SETATTR 5 + { PVFS_SERV_SETATTR, "PVFS_SERV_SETATTR" }, +#define PVFS_SERV_LOOKUP_PATH 6 + { PVFS_SERV_LOOKUP_PATH, "PVFS_SERV_LOOKUP_PATH" }, +#define PVFS_SERV_CRDIRENT 7 + { PVFS_SERV_CRDIRENT, "PVFS_SERV_CRDIRENT" }, +#define PVFS_SERV_RMDIRENT 8 + { PVFS_SERV_RMDIRENT, "PVFS_SERV_RMDIRENT" }, +#define PVFS_SERV_CHDIRENT 9 + { PVFS_SERV_CHDIRENT, "PVFS_SERV_CHDIRENT" }, +#define PVFS_SERV_TRUNCATE 10 + { PVFS_SERV_TRUNCATE, "PVFS_SERV_TRUNCATE" }, +#define PVFS_SERV_MKDIR 11 + { PVFS_SERV_MKDIR, "PVFS_SERV_MKDIR" }, +#define PVFS_SERV_READDIR 12 + { PVFS_SERV_READDIR, "PVFS_SERV_READDIR" }, +#define PVFS_SERV_GETCONFIG 13 + { PVFS_SERV_GETCONFIG, "PVFS_SERV_GETCONFIG" }, +#define PVFS_SERV_WRITE_COMPLETION 14 + { PVFS_SERV_WRITE_COMPLETION, "PVFS_SERV_WRITE_COMPLETION" }, +#define PVFS_SERV_FLUSH 15 + { PVFS_SERV_FLUSH, "PVFS_SERV_FLUSH" }, +#define PVFS_SERV_MGMT_SETPARAM 16 + { PVFS_SERV_MGMT_SETPARAM, "PVFS_SERV_MGMT_SETPARAM" }, +#define PVFS_SERV_MGMT_NOOP 17 + { PVFS_SERV_MGMT_NOOP, "PVFS_SERV_MGMT_NOOP" }, +#define PVFS_SERV_STATFS 18 + { PVFS_SERV_STATFS, "PVFS_SERV_STATFS" }, +#define PVFS_SERV_PERF_UPDATE 19 /* not a real protocol request */ + { PVFS_SERV_PERF_UPDATE, "PVFS_SERV_PERF_UPDATE" }, +#define PVFS_SERV_MGMT_PERF_MON 20 + { PVFS_SERV_MGMT_PERF_MON, "PVFS_SERV_MGMT_PERF_MON" }, +#define PVFS_SERV_MGMT_ITERATE_HANDLES 21 + { PVFS_SERV_MGMT_ITERATE_HANDLES, "PVFS_SERV_MGMT_ITERATE_HANDLES" }, +#define PVFS_SERV_MGMT_DSPACE_INFO_LIST 22 + { PVFS_SERV_MGMT_DSPACE_INFO_LIST, "PVFS_SERV_MGMT_DSPACE_INFO_LIST" }, +#define PVFS_SERV_MGMT_EVENT_MON 23 + { PVFS_SERV_MGMT_EVENT_MON, "PVFS_SERV_MGMT_EVENT_MON" }, +#define PVFS_SERV_MGMT_REMOVE_OBJECT 24 + { PVFS_SERV_MGMT_REMOVE_OBJECT, "PVFS_SERV_MGMT_REMOVE_OBJECT" }, +#define PVFS_SERV_MGMT_REMOVE_DIRENT 25 + { PVFS_SERV_MGMT_REMOVE_DIRENT, "PVFS_SERV_MGMT_REMOVE_DIRENT" }, +#define PVFS_SERV_MGMT_GET_DIRDATA_HANDLE 26 + { PVFS_SERV_MGMT_GET_DIRDATA_HANDLE, "PVFS_SERV_MGMT_GET_DIRDATA_HANDLE" }, +#define PVFS_SERV_JOB_TIMER 27 /* not a real protocol request */ + { PVFS_SERV_JOB_TIMER, "PVFS_SERV_JOB_TIMER" }, +#define PVFS_SERV_PROTO_ERROR 28 + { PVFS_SERV_PROTO_ERROR, "PVFS_SERV_PROTO_ERROR" }, +#define PVFS_SERV_GETEATTR 29 + { PVFS_SERV_GETEATTR, "PVFS_SERV_GETEATTR" }, +#define PVFS_SERV_SETEATTR 30 + { PVFS_SERV_SETEATTR, "PVFS_SERV_SETEATTR" }, +#define PVFS_SERV_DELEATTR 31 + { PVFS_SERV_DELEATTR, "PVFS_SERV_DELEATTR" }, + { 0, NULL } +}; + +/* special bits used to differentiate PVFS error codes from system + * * errno values + * */ +#define PVFS_ERROR_BIT (1 << 30) + +/* a shorthand to make the error code definitions more readable */ +#define E(num) (num|PVFS_ERROR_BIT) + +static const value_string names_pvfs_error[] = { + { 0, "Success" }, +#define PVFS_EPERM E(1) /* Operation not permitted */ + { PVFS_EPERM, "PVFS_EPERM" }, +#define PVFS_ENOENT E(2) /* No such file or directory */ + { PVFS_ENOENT, "PVFS_ENOENT" }, +#define PVFS_EINTR E(3) /* Interrupted system call */ + { PVFS_EINTR, "PVFS_EINTR" }, +#define PVFS_EIO E(4) /* I/O error */ + { PVFS_EIO, "PVFS_EIO" }, +#define PVFS_ENXIO E(5) /* No such device or address */ + { PVFS_ENXIO, "PVFS_ENXIO" }, +#define PVFS_EBADF E(6) /* Bad file number */ + { PVFS_EBADF, "PVFS_EBADF" }, +#define PVFS_EAGAIN E(7) /* Try again */ + { PVFS_EAGAIN, "PVFS_EAGAIN" }, +#define PVFS_ENOMEM E(8) /* Out of memory */ + { PVFS_ENOMEM, "PVFS_ENOMEM" }, +#define PVFS_EFAULT E(9) /* Bad address */ + { PVFS_EFAULT, "PVFS_EFAULT" }, +#define PVFS_EBUSY E(10) /* Device or resource busy */ + { PVFS_EBUSY, "PVFS_EBUSY" }, +#define PVFS_EEXIST E(11) /* File exists */ + { PVFS_EEXIST, "PVFS_EEXIST" }, +#define PVFS_ENODEV E(12) /* No such device */ + { PVFS_ENODEV, "PVFS_ENODEV" }, +#define PVFS_ENOTDIR E(13) /* Not a directory */ + { PVFS_ENOTDIR, "PVFS_ENOTDIR" }, +#define PVFS_EISDIR E(14) /* Is a directory */ + { PVFS_EISDIR, "PVFS_EISDIR" }, +#define PVFS_EINVAL E(15) /* Invalid argument */ + { PVFS_EINVAL, "PVFS_EINVAL" }, +#define PVFS_EMFILE E(16) /* Too many open files */ + { PVFS_EMFILE, "PVFS_EMFILE" }, +#define PVFS_EFBIG E(17) /* File too large */ + { PVFS_EFBIG, "PVFS_EFBIG" }, +#define PVFS_ENOSPC E(18) /* No space left on device */ + { PVFS_ENOSPC, "PVFS_ENOSPC" }, +#define PVFS_EROFS E(19) /* Read-only file system */ + { PVFS_EROFS, "PVFS_EROFS" }, +#define PVFS_EMLINK E(20) /* Too many links */ + { PVFS_EMLINK, "PVFS_EMLINK" }, +#define PVFS_EPIPE E(21) /* Broken pipe */ + { PVFS_EPIPE, "PVFS_EPIPE" }, +#define PVFS_EDEADLK E(22) /* Resource deadlock would occur */ + { PVFS_EDEADLK, "PVFS_EDEADLK" }, +#define PVFS_ENAMETOOLONG E(23) /* File name too long */ + { PVFS_ENAMETOOLONG, "PVFS_ENAMETOOLONG" }, +#define PVFS_ENOLCK E(24) /* No record locks available */ + { PVFS_ENOLCK, "PVFS_ENOLCK" }, +#define PVFS_ENOSYS E(25) /* Function not implemented */ + { PVFS_ENOSYS, "PVFS_ENOSYS" }, +#define PVFS_ENOTEMPTY E(26) /* Directory not empty */ + { PVFS_ENOTEMPTY, "PVFS_ENOTEMPTY" }, +#define PVFS_ELOOP E(27) /* Too many symbolic links encountered */ + { PVFS_ELOOP, "PVFS_ELOOP" }, +#define PVFS_EWOULDBLOCK E(28) /* Operation would block */ + { PVFS_EWOULDBLOCK, "PVFS_EWOULDBLOCK" }, +#define PVFS_ENOMSG E(29) /* No message of desired type */ + { PVFS_ENOMSG, "PVFS_ENOMSG" }, +#define PVFS_EUNATCH E(30) /* Protocol driver not attached */ + { PVFS_EUNATCH, "PVFS_EUNATCH" }, +#define PVFS_EBADR E(31) /* Invalid request descriptor */ + { PVFS_EBADR, "PVFS_EBADR" }, +#define PVFS_EDEADLOCK E(32) + { PVFS_EDEADLOCK, "PVFS_EDEADLOCK" }, +#define PVFS_ENODATA E(33) /* No data available */ + { PVFS_ENODATA, "PVFS_ENODATA" }, +#define PVFS_ETIME E(34) /* Timer expired */ + { PVFS_ETIME, "PVFS_ETIME" }, +#define PVFS_ENONET E(35) /* Machine is not on the network */ + { PVFS_ENONET, "PVFS_ENONET" }, +#define PVFS_EREMOTE E(36) /* Object is remote */ + { PVFS_EREMOTE, "PVFS_EREMOTE" }, +#define PVFS_ECOMM E(37) /* Communication error on send */ + { PVFS_ECOMM, "PVFS_ECOMM" }, +#define PVFS_EPROTO E(38) /* Protocol error */ + { PVFS_EPROTO, "PVFS_EPROTO" }, +#define PVFS_EBADMSG E(39) /* Not a data message */ + { PVFS_EBADMSG, "PVFS_EBADMSG" }, +#define PVFS_EOVERFLOW E(40) /* Value too large for defined data type */ + { PVFS_EOVERFLOW, "PVFS_EOVERFLOW" }, +#define PVFS_ERESTART E(41) /* Interrupted system call should be restarted */ + { PVFS_ERESTART, "PVFS_ERESTART" }, +#define PVFS_EMSGSIZE E(42) /* Message too long */ + { PVFS_EMSGSIZE, "PVFS_EMSGSIZE" }, +#define PVFS_EPROTOTYPE E(43) /* Protocol wrong type for socket */ + { PVFS_EPROTOTYPE, "PVFS_EPROTOTYPE" }, +#define PVFS_ENOPROTOOPT E(44) /* Protocol not available */ + { PVFS_ENOPROTOOPT, "PVFS_ENOPROTOOPT" }, +#define PVFS_EPROTONOSUPPORT E(45) /* Protocol not supported */ + { PVFS_EPROTONOSUPPORT, "PVFS_EPROTONOSUPPORT" }, +#define PVFS_EOPNOTSUPP E(46) /* Operation not supported on transport endpoint */ + { PVFS_EOPNOTSUPP, "PVFS_EOPNOTSUPP" }, +#define PVFS_EADDRINUSE E(47) /* Address already in use */ + { PVFS_EADDRINUSE, "PVFS_EADDRINUSE" }, +#define PVFS_EADDRNOTAVAIL E(48) /* Cannot assign requested address */ + { PVFS_EADDRNOTAVAIL, "PVFS_EADDRNOTAVAIL" }, +#define PVFS_ENETDOWN E(49) /* Network is down */ + { PVFS_ENETDOWN, "PVFS_ENETDOWN" }, +#define PVFS_ENETUNREACH E(50) /* Network is unreachable */ + { PVFS_ENETUNREACH, "PVFS_ENETUNREACH" }, +#define PVFS_ENETRESET E(51) /* Network dropped connection because of reset */ + { PVFS_ENETRESET, "PVFS_ENETRESET" }, +#define PVFS_ENOBUFS E(52) /* No buffer space available */ + { PVFS_ENOBUFS, "PVFS_ENOBUFS" }, +#define PVFS_ETIMEDOUT E(53) /* Connection timed out */ + { PVFS_ETIMEDOUT, "PVFS_ETIMEDOUT" }, +#define PVFS_ECONNREFUSED E(54) /* Connection refused */ + { PVFS_ECONNREFUSED, "PVFS_ECONNREFUSED" }, +#define PVFS_EHOSTDOWN E(55) /* Host is down */ + { PVFS_EHOSTDOWN, "PVFS_EHOSTDOWN" }, +#define PVFS_EHOSTUNREACH E(56) /* No route to host */ + { PVFS_EHOSTUNREACH, "PVFS_EHOSTUNREACH" }, +#define PVFS_EALREADY E(57) /* Operation already in progress */ + { PVFS_EALREADY, "PVFS_EALREADY" }, +#define PVFS_EACCES E(58) /* Operation already in progress */ + { PVFS_EACCES, "PVFS_EACCES" }, + { 0, NULL } +}; + +static int +dissect_pvfs2_error(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + gint32 err; + const char *errmsg = NULL; + + err = tvb_get_letohl(tvb, offset); + proto_tree_add_uint(tree, hf_pvfs_error, tvb, offset, 4, -err); + offset += 4; + + if ((err != 0) && check_col(pinfo->cinfo, COL_INFO)) + { + errmsg = val_to_str(-err, names_pvfs_error, "Unknown error: %u"); + col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", errmsg); + } + + return offset; +} + +static int +dissect_pvfs_credentials(tvbuff_t *tvb, proto_tree *parent_tree, + int offset) +{ + proto_item *item = NULL; + proto_tree *hcred_tree = NULL; + guint32 uid = 0, gid = 0; + + uid = tvb_get_letohl(tvb, offset); + gid = tvb_get_letohl(tvb, offset + 4); + + if (parent_tree) + { + item = proto_tree_add_text(parent_tree, tvb, offset, 8, + "Credentials (UID: %d, GID: %d)", uid, gid); + + if (item) + hcred_tree = proto_item_add_subtree(item, ett_pvfs_credentials); + } + + /* UID */ + proto_tree_add_text(hcred_tree, tvb, offset, 4, "UID: %d", uid); + offset += 4; + + /* GID */ + proto_tree_add_text(hcred_tree, tvb, offset, 4, "GID: %d", gid); + offset += 4; + + return offset; +} + +static const value_string names_pvfs_attr[] = +{ +#define PVFS_ATTR_COMMON_UID (1 << 0) +#define PVFS_ATTR_BIT_COMMON_UID 0 + { PVFS_ATTR_BIT_COMMON_UID, "PVFS_ATTR_COMMON_UID" }, + +#define PVFS_ATTR_COMMON_GID (1 << 1) +#define PVFS_ATTR_BIT_COMMON_GID 1 + { PVFS_ATTR_BIT_COMMON_GID, "PVFS_ATTR_COMMON_GID" }, + +#define PVFS_ATTR_COMMON_PERM (1 << 2) +#define PVFS_ATTR_BIT_COMMON_PERM 2 + { PVFS_ATTR_BIT_COMMON_PERM, "PVFS_ATTR_COMMON_PERM" }, + +#define PVFS_ATTR_COMMON_ATIME (1 << 3) +#define PVFS_ATTR_BIT_COMMON_ATIME 3 + { PVFS_ATTR_BIT_COMMON_ATIME, "PVFS_ATTR_COMMON_ATIME" }, + +#define PVFS_ATTR_COMMON_CTIME (1 << 4) +#define PVFS_ATTR_BIT_COMMON_CTIME 4 + { PVFS_ATTR_BIT_COMMON_CTIME, "PVFS_ATTR_COMMON_CTIME" }, + +#define PVFS_ATTR_COMMON_MTIME (1 << 5) +#define PVFS_ATTR_BIT_COMMON_MTIME 5 + { PVFS_ATTR_BIT_COMMON_MTIME, "PVFS_ATTR_COMMON_MTIME" }, + +#define PVFS_ATTR_COMMON_TYPE (1 << 6) +#define PVFS_ATTR_BIT_COMMON_TYPE 6 + { PVFS_ATTR_BIT_COMMON_TYPE, "PVFS_ATTR_COMMON_TYPE" }, + +#if 0 +#define PVFS_ATTR_COMMON_ALL \ + (PVFS_ATTR_COMMON_UID | PVFS_ATTR_COMMON_GID | \ + PVFS_ATTR_COMMON_PERM | PVFS_ATTR_COMMON_ATIME | \ + PVFS_ATTR_COMMON_CTIME | PVFS_ATTR_COMMON_MTIME | \ + PVFS_ATTR_COMMON_TYPE) +#endif + +/* internal attribute masks for metadata objects */ +#define PVFS_ATTR_META_DIST (1 << 10) +#define PVFS_ATTR_BIT_META_DIST 10 + { PVFS_ATTR_BIT_META_DIST, "PVFS_ATTR_META_DIST" }, + +#define PVFS_ATTR_META_DFILES (1 << 11) +#define PVFS_ATTR_BIT_META_DFILES 11 + { PVFS_ATTR_BIT_META_DFILES, "PVFS_ATTR_META_DFILES" }, + +#if 0 +#define PVFS_ATTR_META_ALL \ + (PVFS_ATTR_META_DIST | PVFS_ATTR_META_DFILES) +#endif + +/* internal attribute masks for datafile objects */ +#define PVFS_ATTR_DATA_SIZE (1 << 15) +#define PVFS_ATTR_BIT_DATA_SIZE 15 + { PVFS_ATTR_BIT_DATA_SIZE, "PVFS_ATTR_DATA_SIZE" }, + +#if 0 +#define PVFS_ATTR_DATA_ALL PVFS_ATTR_DATA_SIZE +#endif + +/* internal attribute masks for symlink objects */ +#define PVFS_ATTR_SYMLNK_TARGET (1 << 18) +#define PVFS_ATTR_BIT_SYMLINK_TARGET 18 + { PVFS_ATTR_BIT_SYMLINK_TARGET, "PVFS_ATTR_SYMLNK_TARGET" }, + +#if 0 +#define PVFS_ATTR_SYMLNK_ALL PVFS_ATTR_SYMLNK_TARGET +#endif + +/* internal attribute masks for directory objects */ +#define PVFS_ATTR_DIR_DIRENT_COUNT (1 << 19) +#define PVFS_ATTR_BIT_DIR_DIRENT_COUNT 19 + { PVFS_ATTR_BIT_DIR_DIRENT_COUNT, "PVFS_ATTR_DIR_DIRENT_COUNT" }, + +#if 0 +#define PVFS_ATTR_DIR_ALL PVFS_ATTR_DIR_DIRENT_COUNT +#endif + +/* attribute masks used by system interface callers */ +#define PVFS_ATTR_SYS_SIZE (1 << 20) +#define PVFS_ATTR_BIT_SYS_SIZE 20 + { PVFS_ATTR_BIT_SYS_SIZE, "PVFS_ATTR_SYS_SIZE" }, + +#define PVFS_ATTR_SYS_LNK_TARGET (1 << 24) +#define PVFS_ATTR_BIT_SYS_LNK_TARGET 24 + { PVFS_ATTR_BIT_SYS_LNK_TARGET, "PVFS_ATTR_SYS_LNK_TARGET" }, + +#define PVFS_ATTR_SYS_DFILE_COUNT (1 << 25) +#define PVFS_ATTR_BIT_SYS_DFILE_COUNT 25 + { PVFS_ATTR_BIT_SYS_DFILE_COUNT, "PVFS_ATTR_SYS_DFILE_COUNT" }, + +#define PVFS_ATTR_SYS_DIRENT_COUNT (1 << 26) +#define PVFS_ATTR_BIT_SYS_DIRENT_COUNT 26 + { PVFS_ATTR_BIT_SYS_DIRENT_COUNT, "PVFS_ATTR_SYS_DIRENT_COUNT" }, + +#if 0 +#define PVFS_ATTR_SYS_UID PVFS_ATTR_COMMON_UID +#define PVFS_ATTR_SYS_GID PVFS_ATTR_COMMON_GID +#define PVFS_ATTR_SYS_PERM PVFS_ATTR_COMMON_PERM +#define PVFS_ATTR_SYS_ATIME PVFS_ATTR_COMMON_ATIME +#define PVFS_ATTR_SYS_CTIME PVFS_ATTR_COMMON_CTIME +#define PVFS_ATTR_SYS_MTIME PVFS_ATTR_COMMON_MTIME +#define PVFS_ATTR_SYS_TYPE PVFS_ATTR_COMMON_TYPE +#endif + { 0, NULL } +}; + +#if 0 +#define PVFS_ATTR_SYS_ALL \ + (PVFS_ATTR_COMMON_ALL | PVFS_ATTR_SYS_SIZE | \ + PVFS_ATTR_SYS_LNK_TARGET | PVFS_ATTR_SYS_DFILE_COUNT | \ + PVFS_ATTR_SYS_DIRENT_COUNT) + +#define PVFS_ATTR_SYS_ALL_NOSIZE \ + (PVFS_ATTR_COMMON_ALL | PVFS_ATTR_SYS_LNK_TARGET | \ + PVFS_ATTR_SYS_DFILE_COUNT | PVFS_ATTR_SYS_DIRENT_COUNT) + +#define PVFS_ATTR_SYS_ALL_SETABLE \ + (PVFS_ATTR_COMMON_ALL-PVFS_ATTR_COMMON_TYPE) +#endif + + +static int +dissect_pvfs2_attrmask(tvbuff_t *tvb, proto_tree *tree, int offset, + guint32 *pattrmask) +{ + guint32 attrmask = 0, i = 0; + proto_item *attritem = NULL; + proto_tree *attrtree = NULL; + + attrmask = tvb_get_letohl(tvb, offset); + + attritem = proto_tree_add_text(tree, tvb, offset, 4, + "Attribute Mask: %d", attrmask); + + if (attritem) + attrtree = proto_item_add_subtree(attritem, ett_pvfs_attrmask); + + for (i = 0; i < 32; i++) + { + if (attrmask & (1 << i)) + proto_tree_add_uint(attrtree, hf_pvfs_attr, tvb, offset, 4, i); + } + + offset += 4; + + if (pattrmask) + *pattrmask = attrmask; + + return offset; +} + +static const value_string names_pvfs_ds_type[] = { +#define PVFS_TYPE_NONE 0 + { PVFS_TYPE_NONE, "PVFS_TYPE_NONE" }, +#define PVFS_TYPE_METAFILE (1 << 0) + { PVFS_TYPE_METAFILE, "PVFS_TYPE_METAFILE" }, +#define PVFS_TYPE_DATAFILE (1 << 1) + { PVFS_TYPE_DATAFILE, "PVFS_TYPE_DATAFILE" }, +#define PVFS_TYPE_DIRECTORY (1 << 2) + { PVFS_TYPE_DIRECTORY, "PVFS_TYPE_DIRECTORY" }, +#define PVFS_TYPE_SYMLINK (1 << 3) + { PVFS_TYPE_SYMLINK, "PVFS_TYPE_SYMLINK" }, +#define PVFS_TYPE_DIRDATA (1 << 4) + { PVFS_TYPE_DIRDATA, "PVFS_TYPE_DIRDATA" }, + { 0, NULL } +}; + +static int +dissect_pvfs2_ds_type(tvbuff_t *tvb, proto_tree *tree, int offset, + int *pds_type) +{ + guint32 ds_type = 0; + + ds_type = tvb_get_letohl(tvb, offset); + + if (tree) + proto_tree_add_uint(tree, hf_pvfs_ds_type, tvb, offset, 4, ds_type); + + offset += 4; + + if (pds_type) + *pds_type = ds_type; + + return offset; +} + +#define roundup4(x) (((x) + 3) & ~3) +#define roundup8(x) (((x) + 7) & ~7) + +static int +dissect_pvfs_opaque_data(tvbuff_t *tvb, int offset, + proto_tree *tree, + packet_info *pinfo _U_, + int hfindex, + gboolean fixed_length, guint32 length, + gboolean string_data, char **string_buffer_ret) +{ + int data_offset; + proto_item *string_item = NULL; + proto_tree *string_tree = NULL; + + guint32 string_length; + guint32 string_length_full; + guint32 string_length_packet; + guint32 string_length_captured; + guint32 string_length_copy; + + int fill_truncated; + guint32 fill_length; + guint32 fill_length_packet; + guint32 fill_length_captured; + guint32 fill_length_copy; + + int exception = 0; + + char *string_buffer = NULL; + char *string_buffer_print = NULL; + + if (fixed_length) { + string_length = length; + data_offset = offset; + } else { + string_length = tvb_get_letohl(tvb,offset+0); + data_offset = offset + 4; + + /* + * Variable-length strings include NULL terminator on-the-wire but + * NULL terminator is not included in string length. + */ + + if (string_data) + string_length += 1; + } + + string_length_captured = tvb_length_remaining(tvb, data_offset); + string_length_packet = tvb_reported_length_remaining(tvb, data_offset); + + /* + * Strangeness... the protocol basically says that the length plus + * the string must be padded out to an 8-byte boundary. + */ + + if (!string_data) + string_length_full = roundup4(string_length); + else + string_length_full = roundup8(4 + string_length); + + if (string_length_captured < string_length) { + /* truncated string */ + string_length_copy = string_length_captured; + fill_truncated = 2; + fill_length = 0; + fill_length_copy = 0; + + if (string_length_packet < string_length) + exception = ReportedBoundsError; + else + exception = BoundsError; + } + else { + /* full string data */ + string_length_copy = string_length; + + if (!string_data) + fill_length = string_length_full - string_length; + else + fill_length = string_length_full - string_length - 4; + + fill_length_captured = tvb_length_remaining(tvb, + data_offset + string_length); + fill_length_packet = tvb_reported_length_remaining(tvb, + data_offset + string_length); + + if (fill_length_captured < fill_length) { + /* truncated fill bytes */ + fill_length_copy = fill_length_packet; + fill_truncated = 1; + if (fill_length_packet < fill_length) + exception = ReportedBoundsError; + else + exception = BoundsError; + } + else { + /* full fill bytes */ + fill_length_copy = fill_length; + fill_truncated = 0; + } + } + + if (string_data) { + char *tmpstr; + + tmpstr = (char *) tvb_get_ephemeral_string(tvb, data_offset, + string_length_copy); + + string_buffer = memcpy(ep_alloc(string_length_copy+1), tmpstr, string_length_copy); + } else { + string_buffer = (char *) tvb_memcpy(tvb, + ep_alloc(string_length_copy+1), data_offset, string_length_copy); + } + + string_buffer[string_length_copy] = '\0'; + + /* calculate a nice printable string */ + if (string_length) { + if (string_length != string_length_copy) { + if (string_data) { + char *formatted; + guint16 string_buffer_size = 0; + + formatted = format_text((guint8 *)string_buffer, + strlen(string_buffer)); + + string_buffer_size = strlen(formatted) + 12 + 1; + + /* alloc maximum data area */ + string_buffer_print = (char*) ep_alloc(string_buffer_size); + /* copy over the data */ + g_snprintf(string_buffer_print, string_buffer_size - 1, + "%s", formatted); + /* append */ + /* This way, we get the TRUNCATED even + in the case of totally wrong packets, + where \0 are inside the string. + TRUNCATED will appear at the + first \0 or at the end (where we + put the securing \0). + */ + } else { + string_buffer_print=""; + } + } else { + if (string_data) { + string_buffer_print = (char *) + ep_strdup(format_text((guint8 *) string_buffer, + strlen(string_buffer))); + } else { + string_buffer_print=""; + } + } + } else { + string_buffer_print=""; + } + + if (tree) { + string_item = proto_tree_add_text(tree, tvb,offset+0, -1, + "%s: %s", proto_registrar_get_name(hfindex), + string_buffer_print); + + if (string_item) + string_tree = proto_item_add_subtree(string_item, + ett_pvfs_string); + } + if (!fixed_length) { + if (string_tree) + proto_tree_add_text(string_tree, tvb,offset+0,4, + "length: %u (excl. NULL terminator)", string_length - 1); + offset += 4; + } + + if (string_tree) { + if (string_data) { + proto_tree_add_string_format(string_tree, + hfindex, tvb, offset, string_length_copy, + string_buffer, + "contents: %s", string_buffer_print); + } else { + proto_tree_add_bytes_format(string_tree, + hfindex, tvb, offset, string_length_copy, + (guint8 *) string_buffer, + "contents: %s", string_buffer_print); + } + } + + offset += string_length_copy; + + if (fill_length) { + if (string_tree) { + if (fill_truncated) { + proto_tree_add_text(string_tree, tvb, + offset,fill_length_copy, + "fill bytes: opaque data"); + } + else { + proto_tree_add_text(string_tree, tvb, + offset,fill_length_copy, + "fill bytes: opaque data"); + } + } + offset += fill_length_copy; + } + + if (string_item) + proto_item_set_end(string_item, tvb, offset); + + if (string_buffer_ret != NULL) + *string_buffer_ret = string_buffer_print; + + /* + * If the data was truncated, throw the appropriate exception, + * so that dissection stops and the frame is properly marked. + */ + if (exception != 0) + THROW(exception); + + return offset; +} + +static int +dissect_pvfs_string(tvbuff_t *tvb, proto_tree *tree, int hfindex, + int offset, char **string_buffer_ret) +{ + return dissect_pvfs_opaque_data(tvb, offset, tree, NULL, hfindex, + FALSE, 0, TRUE, string_buffer_ret); +} + +static void +dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree) +{ + guint sublen; + guint bytes_left; + gboolean first_line; + + bytes_left = PVFS2_FH_LENGTH; + first_line = TRUE; + while (bytes_left != 0) { + sublen = 16; + if (sublen > bytes_left) + sublen = bytes_left; + proto_tree_add_text(tree, tvb, offset, sublen, + "%s%s", + first_line ? "data: " : + " ", + tvb_bytes_to_str(tvb,offset,sublen)); + bytes_left -= sublen; + offset += sublen; + first_line = FALSE; + } +} + +static void +dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 *hash) +{ + guint32 fhhash; + guint32 i; + + /* Not all bytes there. Any attempt to deduce the type would be + senseless. */ + if (!tvb_bytes_exist(tvb, offset, PVFS2_FH_LENGTH)) + goto type_ready; + + /* create a semiunique hash value for the filehandle */ + for(fhhash=0,i=0;i<(PVFS2_FH_LENGTH-3);i+=4){ + guint32 val; + val = tvb_get_ntohl(tvb, offset+i); + fhhash ^= val; + fhhash += val; + } + + proto_tree_add_uint(tree, hf_pvfs_fh_hash, tvb, offset, PVFS2_FH_LENGTH, + fhhash); + + if (hash) + *hash = fhhash; + + /* TODO: add file name snooping code here */ + +type_ready: + dissect_fhandle_data_unknown(tvb, offset, tree); +} + +static int +dissect_pvfs_fh(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, const char *name, guint32 *hash) +{ + proto_item* fitem = NULL; + proto_tree* ftree = NULL; + + if (tree) + { + fitem = proto_tree_add_text(tree, tvb, offset, PVFS2_FH_LENGTH, + "%s", name); + + if (fitem) + ftree = proto_item_add_subtree(fitem, ett_pvfs_fh); + } + + /* TODO: add fh to file name snooping code here */ + + proto_tree_add_uint(ftree, hf_pvfs_fh_length, tvb, offset, 0, + PVFS2_FH_LENGTH); + + dissect_fhandle_data(tvb, offset, pinfo, ftree, hash); + + offset += PVFS2_FH_LENGTH; + + return offset; +} + +static int +dissect_pvfs_handle_extent(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo, guint32 nCount) +{ + proto_item *extent_item = NULL; + proto_tree *extent_tree = NULL; + + if (tree) + { + extent_item = proto_tree_add_text(tree, tvb, offset, 8, + "Item %d", nCount); + + if (extent_item) + extent_tree = proto_item_add_subtree(extent_item, + ett_pvfs_extent_item); + } + + /* first handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, extent_tree, "first handle", + NULL); + + /* last handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, extent_tree, "last handle", + NULL); + + return offset; +} + +static int +dissect_pvfs_handle_extent_array(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint32 extent_count = 0; + guint32 nCount; + proto_item *extent_array_item = NULL; + proto_tree *extent_array_tree = NULL; + + /* extent count */ + extent_count = tvb_get_letohl(tvb, offset); + + if (tree) + extent_array_item = proto_tree_add_text(tree, tvb, offset, 4, + "Handle Extent Array (count = %d)", extent_count); + + offset += 4; + + if (extent_count > 0) + { + if (extent_array_item) + extent_array_tree = proto_item_add_subtree(extent_array_item, + ett_pvfs_extent_array_tree); + + /* Add extent array items */ + for (nCount = 0; nCount < extent_count; nCount++) + offset = dissect_pvfs_handle_extent(tvb, extent_array_tree, offset, + pinfo, nCount); + } + + return offset; +} + +static int +dissect_pvfs_time(tvbuff_t *tvb, proto_tree *tree, int offset, + int hf_time, int hf_time_sec, int hf_time_nsec) +{ + guint32 seconds; + guint32 nseconds; + nstime_t ts; + proto_item *time_item = NULL; + proto_tree *time_tree = NULL; + + ts.secs = seconds = tvb_get_letohl(tvb, offset); + ts.nsecs = nseconds = tvb_get_letohl(tvb, offset + 4); + + if (tree) + { + time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8, &ts); + + if (time_item) + time_tree = proto_item_add_subtree(time_item, ett_pvfs_time); + } + + if (time_tree) + { + proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4, seconds); + proto_tree_add_uint(time_tree, hf_time_nsec, tvb, offset + 4, 4, + nseconds); + } + + offset += 8; + return offset; +} + +static +int dissect_pvfs_uint64(tvbuff_t *tvb, proto_tree *tree, int offset, + int hfindex, guint64 *pvalue) +{ + guint64 val; + + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + + proto_tree_add_uint64(tree, hfindex, tvb, offset, 8, val); + + if (pvalue) + *pvalue = val; + + return offset + 8; +} + +/* Taken from pvfs2-dist-simple-stripe.h */ +#define PVFS_DIST_SIMPLE_STRIPE_NAME "simple_stripe" +#define PVFS_DIST_SIMPLE_STRIPE_NAME_SIZE 14 + +static int +dissect_pvfs_distribution(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + proto_item *dist_item = NULL; + proto_tree *dist_tree = NULL; + char *distname = NULL; + guint32 distlen = 0; + char *tmpstr = NULL; + guint8 issimplestripe = 0; + + /* Get distribution name length */ + distlen = tvb_get_letohl(tvb, offset); + + /* Get distribution name */ + tmpstr = (char *) tvb_get_ephemeral_string(tvb, offset + 4, distlen); + + if (tree) + { + guint32 total_len; + + /* 'distlen' does not include the NULL terminator */ + total_len = roundup8(4 + distlen + 1); + + if (((distlen + 1) == PVFS_DIST_SIMPLE_STRIPE_NAME_SIZE) && + (strncasecmp(tmpstr, PVFS_DIST_SIMPLE_STRIPE_NAME, + distlen) == 0)) + { + /* Parameter for 'simple_stripe' is 8 bytes */ + total_len += 8; + + issimplestripe = 1; + } + + dist_item = proto_tree_add_text(tree, tvb, offset, total_len + 8, + "Distribution: %s", tmpstr); + + if (dist_item) + dist_tree = proto_item_add_subtree(dist_item, ett_pvfs_distribution); + } + + /* io_dist */ + offset = dissect_pvfs_string(tvb, dist_tree, hf_pvfs_io_dist, offset, + &distname); + + /* TODO: only one distribution type is currently supported */ + if (issimplestripe) + offset = dissect_pvfs_uint64(tvb, dist_tree, offset, + hf_pvfs_strip_size, NULL); + + offset += 8; + + return offset; +} + +static int +dissect_pvfs_meta_attr_dfiles(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint32 dfile_count, i; + + /* dfile_count */ + dfile_count = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "dfile_count: %d", + dfile_count); + offset += 4; + + for (i = 0; i < dfile_count; i++) + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs_object_attr(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + gint32 ds_type = 0; + guint32 attrmask = 0; + proto_item *attr_item = NULL; + proto_tree *attr_tree = NULL; + + if (tree) + { + attr_item = proto_tree_add_text(tree, tvb, offset, -1, "Attributes"); + + if (attr_item) + attr_tree = proto_item_add_subtree(attr_item, ett_pvfs_attr_tree); + } + + /* UID */ + proto_tree_add_text(attr_tree, tvb, offset, 4, "UID: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* GID */ + proto_tree_add_text(attr_tree, tvb, offset, 4, "GID: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* Permissions */ + proto_tree_add_text(attr_tree, tvb, offset, 4, "Permissions: %o", + tvb_get_letohl(tvb, offset)); + offset += 4; + + offset += 4; + + /* atime */ + offset = dissect_pvfs_time(tvb, attr_tree, offset, hf_pvfs_atime, + hf_pvfs_atime_sec, hf_pvfs_atime_nsec); + + /* mtime */ + offset = dissect_pvfs_time(tvb, attr_tree, offset, hf_pvfs_mtime, + hf_pvfs_mtime_sec, hf_pvfs_mtime_nsec); + + /* ctime */ + offset = dissect_pvfs_time(tvb, attr_tree, offset, hf_pvfs_ctime, + hf_pvfs_ctime_sec, hf_pvfs_ctime_nsec); + + /* attrmask */ + offset = dissect_pvfs2_attrmask(tvb, attr_tree, offset, &attrmask); + + /* objtype */ + offset = dissect_pvfs2_ds_type(tvb, attr_tree, offset, &ds_type); + + if (attrmask & PVFS_ATTR_META_DIST) + { + offset = dissect_pvfs_distribution(tvb, attr_tree, offset); + + offset = dissect_pvfs_meta_attr_dfiles(tvb, attr_tree, offset, pinfo); + } + else + { + if (attrmask & PVFS_ATTR_META_DFILES) + { + offset = dissect_pvfs_meta_attr_dfiles(tvb, attr_tree, offset, pinfo); + } + else + { + if (attrmask & PVFS_ATTR_DATA_SIZE) + { + offset = dissect_pvfs_uint64(tvb, attr_tree, offset, hf_pvfs_size, + NULL); + } + else + { + if (attrmask & PVFS_ATTR_SYMLNK_TARGET) + { + /* target_path_len */ + proto_tree_add_text(attr_tree, tvb, offset, 4, + "target_path_len: %d", tvb_get_letohl(tvb, offset)); + offset += 4; + + offset += 4; + + /* target_path */ + offset = dissect_pvfs_string(tvb, attr_tree, hf_pvfs_path, + offset, NULL); + } + else + { + if (attrmask & PVFS_ATTR_DIR_DIRENT_COUNT) + { + offset = dissect_pvfs_uint64(tvb, attr_tree, offset, + hf_pvfs_size, NULL); + } + } + } + } + } + + return offset; +} + +static int +dissect_pvfs_io_type(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + proto_tree_add_uint(tree, hf_pvfs_io_type, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs_flowproto_type(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + proto_tree_add_uint(tree, hf_pvfs_flowproto_type, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs_server_param(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint32 server_param = 0; + guint32 lowpart; + + /* server_param */ + server_param = tvb_get_letohl(tvb, offset); + proto_tree_add_uint(tree, hf_pvfs_server_param, tvb, offset, 4, + server_param); + offset += 4; + + switch (server_param) + { + case PVFS_SERV_PARAM_MODE: + lowpart = tvb_get_letohl(tvb, offset); + + proto_tree_add_text(tree, tvb, offset, 8, + "Server Mode: %s (%u)", + val_to_str(lowpart, names_pvfs_server_mode, "%u"), lowpart); + break; + + case PVFS_SERV_PARAM_FSID_CHECK: + lowpart = tvb_get_letohl(tvb, offset); + proto_tree_add_uint(tree, hf_pvfs_fs_id, tvb, offset, 4, lowpart); + proto_tree_add_uint(tree, hf_pvfs_unused, tvb, offset + 4, 4, + tvb_get_letohl(tvb, offset + 4)); + break; + + case PVFS_SERV_PARAM_ROOT_CHECK: + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + break; + } + + offset += 8; + + return offset; +} + +static int +dissect_pvfs_fs_id(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + if (tree) + proto_tree_add_uint(tree, hf_pvfs_fs_id, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + + offset += 4; + + return offset; +} + +/* + * ======================================================================= + * Request handlers + * ======================================================================= + */ + +static int +dissect_pvfs2_create_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* type */ + offset = dissect_pvfs2_ds_type(tvb, tree, offset, NULL); + + offset += 4; + + offset = dissect_pvfs_handle_extent_array(tvb, tree, offset, pinfo); + + return offset; +} + +static int +dissect_pvfs2_remove_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + return offset; +} + +static int +dissect_pvfs_pint_request(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + guint64 val = 0; + gint32 ereg, sreg; + + /* offset */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_offset, tvb, offset, 8, val); + offset += 8; + + /* TODO: num_eregs */ + proto_tree_add_uint(tree, hf_pvfs_num_eregs, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* TODO: num_blocks */ + proto_tree_add_uint(tree, hf_pvfs_num_blocks, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* TODO: stride */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_stride, tvb, offset, 8, val); + offset += 8; + + /* TODO: ub */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_ub, tvb, offset, 8, val); + offset += 8; + + /* TODO: lb */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_lb, tvb, offset, 8, val); + offset += 8; + + /* TODO: aggregate size */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_aggregate_size, tvb, offset, 8, val); + offset += 8; + + /* num_contig_chunks */ + proto_tree_add_uint(tree, hf_pvfs_num_contig_chunks, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* depth */ + proto_tree_add_text(tree, tvb, offset, 4, "depth: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* num_nested_req */ + proto_tree_add_text(tree, tvb, offset, 4, "num_nested_req: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* committed */ + proto_tree_add_text(tree, tvb, offset, 4, "committed: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* refcount */ + proto_tree_add_text(tree, tvb, offset, 4, "refcount: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* documented */ + offset += 4; + + /* ereg */ + ereg = tvb_get_letohl(tvb, offset); + proto_tree_add_int(tree, hf_pvfs_ereg, tvb, offset, 4, ereg); + offset += 4; + + /* sreg */ + sreg = tvb_get_letohl(tvb, offset); + proto_tree_add_int(tree, hf_pvfs_sreg, tvb, offset, 4, sreg); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_io_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint64 val; + + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* skip4 as per source code */ + offset += 4; + + /* io_type */ + offset = dissect_pvfs_io_type(tvb, tree, offset); + + /* flow_type */ + offset = dissect_pvfs_flowproto_type(tvb, tree, offset); + + /* server_nr */ + proto_tree_add_uint(tree, hf_pvfs_server_nr, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* server_ct */ + proto_tree_add_uint(tree, hf_pvfs_server_count, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* Distribution */ + offset = dissect_pvfs_distribution(tvb, tree, offset); + + proto_tree_add_text(tree, tvb, offset, 4, "numreq: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* */ + offset += 4; + + offset = dissect_pvfs_pint_request(tvb, tree, offset); + + /* TODO: remove this!!! */ + offset = tvb_length(tvb) - 16; + + /* offset */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_offset, tvb, offset, 8, val); + offset += 8; + + /* size */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_size, tvb, offset, 8, val); + offset += 8; + + return offset; +} + +static int +dissect_pvfs2_getattr_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* attrmask */ + offset = dissect_pvfs2_attrmask(tvb, tree, offset, NULL); + + return offset; +} + +static int +dissect_pvfs2_setattr_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* parent_ref: fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + offset = dissect_pvfs_object_attr(tvb, tree, offset, pinfo); + + return offset; +} + +/* As per pvfs2-1.2.0/src/proto/pvfs2-req-proto.h */ +static int +dissect_pvfs2_lookup_path_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* Path */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + /* starting_handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* attribute mask */ + offset = dissect_pvfs2_attrmask(tvb, tree, offset, NULL); + + return offset; +} + +static int +dissect_pvfs2_crdirent_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* Filename */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); + + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "file handle", NULL); + + /* parent_handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "parent handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + /* atime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_atime, + hf_pvfs_atime_sec, hf_pvfs_atime_nsec); + + /* mtime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_mtime, + hf_pvfs_mtime_sec, hf_pvfs_mtime_nsec); + + /* ctime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_ctime, + hf_pvfs_ctime_sec, hf_pvfs_ctime_nsec); + + return offset; +} + +/* TODO: incomplete */ +static int +dissect_pvfs2_rmdirent_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* path */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); + + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + /* atime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_atime, + hf_pvfs_atime_sec, hf_pvfs_atime_nsec); + + /* mtime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_mtime, + hf_pvfs_mtime_sec, hf_pvfs_mtime_nsec); + + /* ctime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_ctime, + hf_pvfs_ctime_sec, hf_pvfs_ctime_nsec); + + return offset; +} + +static int +dissect_pvfs2_chdirent_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* path */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); + + /* New directory entry handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "new directory handle", + NULL); + + /* Parent handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "parent handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* Parent atime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_parent_atime, + hf_pvfs_parent_atime_sec, hf_pvfs_parent_atime_nsec); + + /* Parent mtime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_parent_mtime, + hf_pvfs_parent_mtime_sec, hf_pvfs_parent_mtime_nsec); + + /* Parent ctime */ + offset = dissect_pvfs_time(tvb, tree, offset, hf_pvfs_parent_ctime, + hf_pvfs_parent_ctime_sec, hf_pvfs_parent_ctime_nsec); + + return offset; +} + +static int +dissect_pvfs2_truncate_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint64 val; + + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + /* size */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_size, tvb, offset, 8, val); + offset += 8; + + /* TODO: flags */ + proto_tree_add_text(tree, tvb, offset, 4, "flags: %u", + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_mkdir_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint count, i; + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + /* attr */ + offset = dissect_pvfs_object_attr(tvb, tree, offset, pinfo); + + /* handle_extent_array */ + count = tvb_get_letohl(tvb, offset); + offset += 4; + + for (i = 0; i < count; i++) + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_readdir_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* object_ref: handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* object_ref: fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* ds_position */ + proto_tree_add_text(tree, tvb, offset, 4, "ds_position: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* dirent_limit */ + proto_tree_add_text(tree, tvb, offset, 4, "dirent_limit: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_flush_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* flags */ + proto_tree_add_text(tree, tvb, offset, 4, "flags: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_mgmt_setparam_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* server_param */ + offset = dissect_pvfs_server_param(tvb, tree, offset, pinfo); + + return offset; +} + +static int +dissect_pvfs2_statfs_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo _U_) +{ + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + return offset; +} + +static int +dissect_pvfs2_mgmt_perf_mon_request(tvbuff_t *tvb _U_, proto_tree *tree _U_, + int offset, packet_info *pinfo _U_) +{ + /* TODO: next_id */ + proto_tree_add_text(tree, tvb, offset, 4, "next_id: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* TODO: count */ + proto_tree_add_text(tree, tvb, offset, 4, "count: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_mgmt_iterate_handles_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_mgmt_dspace_info_list_request(tvbuff_t *tvb, + proto_tree *tree, int offset, packet_info *pinfo) +{ + guint32 handle_count, i; + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* handle count */ + handle_count = tvb_get_letohl(tvb, offset); + offset += 4; + + for (i = 0; i < handle_count; i++) + { + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + } + + return offset; +} + +static int +dissect_pvfs2_mgmt_event_mon_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo _U_) +{ + /* event_count */ + proto_tree_add_text(tree, tvb, offset, 4, "Event count: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_mgmt_remove_object_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* Handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + return offset; +} + +static int +dissect_pvfs2_mgmt_remove_dirent_request(tvbuff_t *tvb, + proto_tree *tree, int offset, packet_info *pinfo) +{ + /* Handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* */ + offset += 4; + + /* entry */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); + + return offset; +} + +static int +dissect_pvfs2_mgmt_get_dirdata_handle_request(tvbuff_t *tvb, + proto_tree *tree, int offset, packet_info *pinfo) +{ + /* Handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + return offset; +} + +/* TODO: untested/incomplete */ +static int +dissect_pvfs_ds_keyval(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + /* attribute key */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_attribute_key, offset, + NULL); + + /* attribute value */ + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_attribute_value, offset, + NULL); + + return offset; +} + +/* TODO: incomplete/untested */ +static int +dissect_ds_keyval_array(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + guint32 nKey, i; + + /* number of keys and vals */ + nKey = tvb_get_letohl(tvb, offset); + offset += 4; + + for (i = 0; i < nKey; i++) + offset = dissect_pvfs_ds_keyval(tvb, tree, offset); + + return offset; +} + +/* TODO: incomplete/untested */ +static int +dissect_pvfs2_geteattr_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + offset = dissect_ds_keyval_array(tvb, tree, offset); + + return offset; +} + +/* TODO: incomplete/untested */ +static int +dissect_pvfs2_seteattr_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + offset += 4; + + offset = dissect_ds_keyval_array(tvb, tree, offset); + + return offset; +} + +/* TODO: untested */ +static int +dissect_pvfs2_deleattr_request(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* key */ + offset = dissect_pvfs_ds_keyval(tvb, tree, offset); + + return offset; +} + +static int +dissect_pvfs2_release_number(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + guint32 release_nr = tvb_get_letohl(tvb, offset); + + proto_tree_add_text(tree, tvb, offset, 4, + "PVFS2 Release Number: %d (%d.%d.%d)", + release_nr, + release_nr / 10000, + (release_nr % 10000) / 100, + (release_nr % 10000) % 100); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_common_header(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + /* PVFS release number */ + offset = dissect_pvfs2_release_number(tvb, tree, offset); + + /* wire encoding type */ + proto_tree_add_uint(tree, hf_pvfs_encoding, tvb, offset, + 4, tvb_get_letohl(tvb, offset)); + offset += 4; + + /* server op */ + proto_tree_add_uint(tree, hf_pvfs_server_op, tvb, offset, 4, + tvb_get_letohl(tvb, offset)); + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_request(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo, guint32 server_op) +{ + /* context_id */ + proto_tree_add_uint(tree, hf_pvfs_context_id, tvb, offset, + 4, tvb_get_letohl(tvb, offset)); + offset += 4; + + /* credentials */ + offset = dissect_pvfs_credentials(tvb, tree, offset); + + switch (server_op) + { + case PVFS_SERV_CREATE: + offset = dissect_pvfs2_create_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_REMOVE: + offset = dissect_pvfs2_remove_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_IO: + offset = dissect_pvfs2_io_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_GETATTR: + offset = dissect_pvfs2_getattr_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_SETATTR: + offset = dissect_pvfs2_setattr_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_LOOKUP_PATH: + offset = dissect_pvfs2_lookup_path_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_CRDIRENT: + offset = dissect_pvfs2_crdirent_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_RMDIRENT: + offset = dissect_pvfs2_rmdirent_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_CHDIRENT: + offset = dissect_pvfs2_chdirent_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_TRUNCATE: + offset = dissect_pvfs2_truncate_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_MKDIR: + offset = dissect_pvfs2_mkdir_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_READDIR: + offset = dissect_pvfs2_readdir_request(tvb, tree, offset, pinfo); + break; + +#if 0 + case PVFS_SERV_GETCONFIG: + /* No parameters in request */ + break; +#endif + +#if 0 + case PVFS_SERV_WRITE_COMPLETION: + /* No parameters in request */ + break; +#endif + + case PVFS_SERV_FLUSH: + offset = dissect_pvfs2_flush_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_MGMT_SETPARAM: + offset = dissect_pvfs2_mgmt_setparam_request(tvb, tree, offset, + pinfo); + break; + +#if 0 + case PVFS_SERV_MGMT_NOOP: + /* No parameters in request */ + break; +#endif + + case PVFS_SERV_STATFS: + offset = dissect_pvfs2_statfs_request(tvb, tree, offset, pinfo); + break; + +#if 0 + case PVFS_SERV_PERF_UPDATE: + /* No parameters in request */ + break; +#endif + + case PVFS_SERV_MGMT_PERF_MON: + offset = dissect_pvfs2_mgmt_perf_mon_request(tvb, tree, offset, + pinfo); + break; + + case PVFS_SERV_MGMT_ITERATE_HANDLES: + offset = dissect_pvfs2_mgmt_iterate_handles_request(tvb, tree, + offset, pinfo); + break; + + case PVFS_SERV_MGMT_DSPACE_INFO_LIST: + offset = dissect_pvfs2_mgmt_dspace_info_list_request(tvb, tree, + offset, pinfo); + break; + + case PVFS_SERV_MGMT_EVENT_MON: + offset = dissect_pvfs2_mgmt_event_mon_request(tvb, tree, offset, + pinfo); + break; + + case PVFS_SERV_MGMT_REMOVE_OBJECT: + offset = dissect_pvfs2_mgmt_remove_object_request(tvb, tree, offset, + pinfo); + break; + + case PVFS_SERV_MGMT_REMOVE_DIRENT: + offset = dissect_pvfs2_mgmt_remove_dirent_request(tvb, tree, offset, + pinfo); + break; + + case PVFS_SERV_MGMT_GET_DIRDATA_HANDLE: + offset = dissect_pvfs2_mgmt_get_dirdata_handle_request(tvb, tree, + offset, pinfo); + break; + +#if 0 + case PVFS_SERV_JOB_TIMER: + /* No parameters in request */ + break; +#endif + + case PVFS_SERV_PROTO_ERROR: + /* TODO: is this necessary? */ + break; + + case PVFS_SERV_GETEATTR: + offset = dissect_pvfs2_geteattr_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_SETEATTR: + offset = dissect_pvfs2_seteattr_request(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_DELEATTR: + offset = dissect_pvfs2_deleattr_request(tvb, tree, offset, pinfo); + break; + + default: + /* TODO: what should we do here? */ + break; + } + + return offset; +} + +/* + * ======================================================================= + * Response handlers + * ======================================================================= + */ + +static int +dissect_pvfs2_create_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* Handle */ + return dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); +} + +static int +dissect_pvfs2_io_response(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + return dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_size, NULL); +} + +static int +dissect_pvfs2_getattr_response(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + offset = dissect_pvfs_object_attr(tvb, tree, offset, pinfo); + + return offset; +} + +static int +dissect_pvfs2_lookup_path_response(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + guint32 nCount = 0; + guint32 handle_count = 0; + guint32 attr_count = 0; + proto_item *attr_item = NULL; + proto_tree *attr_tree = NULL; + + offset += 4; + + /* handle_count */ + handle_count = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Handle Count: %d", + handle_count); + offset += 4; + + /* TODO: add bounds checking */ + for (nCount = 0; nCount < handle_count; nCount++) + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + offset += 4; + + /* array of attributes */ + attr_count = tvb_get_letohl(tvb, offset); + + if (tree) + { + attr_item = proto_tree_add_text(tree, tvb, offset, 4, + "Attribute array (total items: %d)", attr_count); + + if (attr_item) + attr_tree = proto_item_add_subtree(attr_item, ett_pvfs_attr); + } + + offset += 4; + + /* Array of attributes */ + for (nCount = 0; nCount < attr_count; nCount++) + offset = dissect_pvfs_object_attr(tvb, attr_tree, offset, pinfo); + + return offset; +} + +static int +dissect_pvfs2_rmdirent_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* Handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_chdirent_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* Handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_mkdir_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + /* Handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_readdir_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + guint64 val; + guint32 dirent_count = 0; + guint32 nCount = 0; + + /* ds_position */ + proto_tree_add_text(tree, tvb, offset, 4, "ds_position: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + offset += 4; + + /* directory_version */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + proto_tree_add_uint64(tree, hf_pvfs_directory_version, tvb, offset, 8, + val); + offset += 8; + + offset += 4; + + /* dirent_count */ + dirent_count = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "dirent_count: %d", + dirent_count); + offset += 4; + + for (nCount = 0; nCount < dirent_count; nCount++) + { + offset = dissect_pvfs_string(tvb, tree, hf_pvfs_path, offset, NULL); + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + } + + return offset; +} + +/* + * TODO: this code needs work! Not finished yet! + */ +static int +dissect_pvfs2_getconfig_response(tvbuff_t *tvb, proto_tree *parent_tree, + int offset) +{ + guint32 i; + guint32 total_bytes = 0, total_config_bytes = 0, total_lines = 0; + guint32 bytes_processed = 0; + guint32 length_remaining = 0; + char *ptr = NULL; + proto_item *item = NULL, *config_item = NULL; + proto_tree *tree = NULL, *config_tree = NULL; + guint8 truncated = 0; + + if (parent_tree) + { + item = proto_tree_add_text(parent_tree, tvb, offset, 12, + "Server Config"); + + if (item) + tree = proto_item_add_subtree(item, ett_pvfs_server_config); + } + + /* Total number of bytes in server config (incl. entry count) */ + total_bytes = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Total Bytes: %d", + total_bytes); + offset += 4; + + /* There must be at least 4 bytes of data returned to determine the + * size of the server config data + */ + if (total_bytes < 4) + { + /* Server config not returned, bail out */ + return offset; + } + + /* Number of entries in server config */ + total_lines = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Lines: %d", total_lines); + offset += 4; + + /* Number of bytes in server config */ + total_config_bytes = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "Config Bytes: %d", + total_config_bytes); + offset += 4; + + /* Get pointer to server config data */ + ptr = (char *) tvb_get_ptr(tvb, offset, total_config_bytes); + + /* Check if all data is available */ + length_remaining = tvb_length_remaining(tvb, offset); + + if (length_remaining < total_config_bytes) + { + total_config_bytes = length_remaining; + + truncated = 1; + } + + bytes_processed = 0; + + for (i = 0; i < total_lines; i++) + { + guint8 entry[256], *pentry = entry, *tmp_entry = NULL; + guint32 entry_length = 0, tmp_entry_length = 0; + guint32 bufsiz = sizeof(entry); + + while ((*ptr != '\n') && (*ptr != '\0') && + (bytes_processed < total_config_bytes) && + (entry_length < bufsiz)) + { + *pentry++ = *ptr++; + + bytes_processed++; + entry_length++; + } + + if ((entry_length == bufsiz) && + ((entry[entry_length - 1] != '\n') || + (entry[entry_length - 1] != '\0'))) + { + /* + * Single line of config data doesn't fit into provided buffer, + * config data is malformed. + */ + + break; + } + + if (bytes_processed == total_config_bytes) + { + /* Oops... ran out of data before we could complete the entry */ + break; + } + + *pentry= '\0'; + + tmp_entry = entry; + tmp_entry_length = entry_length; + + /* Remove all whitespace from front of entry */ + while ((tmp_entry_length > 0) && (!isalnum(*tmp_entry)) && + (*tmp_entry != '<')) + { + tmp_entry++; + tmp_entry_length--; + } + + if (tmp_entry[0] == '<') + { + if (tmp_entry[tmp_entry_length - 1] == '>') + { + /* Token */ + if (tmp_entry[1] != '/') + { + /* Opening token, create new tree root */ + config_item = proto_tree_add_text(tree, tvb, offset, + tmp_entry_length, "%s", tmp_entry); + + if (config_item) + config_tree = proto_item_add_subtree(config_item, + ett_pvfs_server_config_branch); + } + else + { + /* Closing token */ + config_item = NULL; + config_tree = NULL; + } + } + else + { + /* Malformed token */ + break; + } + } + else + { + /* Insert items into the root config tree if there's no subtree + * defined. + */ + if (config_tree == NULL) + config_tree = tree; + + if (tmp_entry_length > 0) + { + proto_tree_add_text(config_tree, tvb, offset, tmp_entry_length, + "%s", tmp_entry); + } + } + + offset += entry_length + 1; + + ptr++; + bytes_processed++; + } + + if (bytes_processed < total_config_bytes) + { + /* We ran out of server config data */ + proto_tree_add_text(config_tree, tvb, offset, -1, + ""); + } + + return offset; +} + +static int +dissect_pvfs2_write_completion_response(tvbuff_t *tvb, proto_tree *tree, + int offset) +{ + /* size */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_total_completed, + NULL); + + return offset; +} + +static int +dissect_pvfs2_mgmt_setparam_response(tvbuff_t *tvb, proto_tree *tree, + int offset) +{ + guint64 val; + + /* old_value */ + val = ((guint64) tvb_get_letohl(tvb, offset + 4)) << 32 | + tvb_get_letohl(tvb, offset); + + proto_tree_add_uint64(tree, hf_pvfs_prev_value, tvb, offset, 8, val); + + offset += 8; + + return offset; +} + +static int +dissect_pvfs2_statfs_response(tvbuff_t *tvb, proto_tree *tree, int offset) +{ + offset += 4; + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + /* bytes_available */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_bytes_available, + NULL); + + /* bytes_total */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_bytes_total, + NULL); + + /* RAM bytes total */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_ram_bytes_total, + NULL); + + /* RAM bytes free */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_ram_bytes_free, + NULL); + + /* load average (1s) */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_load_average_1s, + NULL); + + /* load average (5s) */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_load_average_5s, + NULL); + + /* load average (15s) */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_load_average_15s, + NULL); + + /* uptime (seconds) */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_uptime_seconds, + NULL); + + /* handles_available_count */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_handles_available, + NULL); + + /* handles_total_count */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_handles_total, + NULL); + + return offset; +} + +static int +dissect_pvfs_mgmt_perf_stat(tvbuff_t *tvb, proto_tree *tree, int offset, + int nItem) +{ + proto_item *stat_item = NULL; + proto_tree *stat_tree = NULL; + + if (tree) + { + stat_item = proto_tree_add_text(tree, tvb, offset, 48, + "Stat Array - Element %d", nItem); + + if (stat_item) + stat_tree = proto_item_add_subtree(stat_item, + ett_pvfs_mgmt_perf_stat); + } + + /* TODO: valid_flag */ + proto_tree_add_text(stat_tree, tvb, offset, 4, "valid_flag: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* TODO: id */ + proto_tree_add_text(stat_tree, tvb, offset, 4, "id: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_start_time_ms, + NULL); + offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_bytes_written, + NULL); + offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_bytes_read, + NULL); + offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_metadata_write, + NULL); + offset = dissect_pvfs_uint64(tvb, stat_tree, offset, hf_pvfs_metadata_read, + NULL); + + return offset; +} + +static int +dissect_pvfs2_mgmt_perf_mon_response(tvbuff_t *tvb, proto_tree *tree, + int offset) +{ + guint32 perf_array_count, i; + + /* TODO: suggested_next_id */ + proto_tree_add_text(tree, tvb, offset, 4, "suggested_next_id: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + offset += 4; + + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_end_time_ms, + NULL); + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_cur_time_ms, + NULL); + + offset += 4; + + /* TODO: perf_array_count */ + perf_array_count = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "perf_array_count: %d", + perf_array_count); + offset += 4; + + for (i = 0; i < perf_array_count; i++) + offset = dissect_pvfs_mgmt_perf_stat(tvb, tree, offset, i); + + return offset; +} + +static int +dissect_pvfs2_mgmt_iterate_handles_response(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + guint32 handle_count, i; + + /* ds_position */ + proto_tree_add_text(tree, tvb, offset, 4, "ds_position: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* handle_count */ + handle_count = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "handle_count: %d", + handle_count); + offset += 4; + + /* TODO: this could be improved */ + for (i = 0; i < handle_count; i++) + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_mgmt_dspace_info(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo) +{ + offset = dissect_pvfs2_error(tvb, tree, offset, pinfo); + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + offset = dissect_pvfs2_ds_type(tvb, tree, offset, NULL); + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_b_size, + NULL); + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_k_size, + NULL); + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +static int +dissect_pvfs2_mgmt_dspace_info_list_response(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + guint32 dspace_info_count, i; + proto_item *arr_item = NULL; + proto_tree *arr_tree = NULL; + + offset += 4; + + /* dspace_info_count */ + dspace_info_count = tvb_get_letohl(tvb, offset); + proto_tree_add_text(tree, tvb, offset, 4, "dspace_info_count: %d", + dspace_info_count); + + if ((dspace_info_count > 0) && (tree)) + { + arr_item = proto_tree_add_text(tree, tvb, offset, + dspace_info_count * 40, "dspace_info Array (%d items)", + dspace_info_count); + + if (arr_item) + arr_tree = proto_item_add_subtree(arr_item, + ett_pvfs_mgmt_dspace_info); + } + + for (i = 0; i < dspace_info_count; i++) + offset = dissect_pvfs2_mgmt_dspace_info(tvb, arr_tree, offset, pinfo); + + return offset; +} + +static int +dissect_pvfs2_mgmt_event_mon_response(tvbuff_t *tvb, proto_tree *tree, + int offset) +{ + /* api */ + proto_tree_add_text(tree, tvb, offset, 4, "api: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* operation */ + proto_tree_add_text(tree, tvb, offset, 4, "operation: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* value */ + proto_tree_add_text(tree, tvb, offset, 4, "value: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* id */ + offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_id_gen_t, + NULL); + + /* flags */ + proto_tree_add_text(tree, tvb, offset, 4, "flags: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* tv_sec */ + proto_tree_add_text(tree, tvb, offset, 4, "tv_sec: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + /* tv_usec */ + proto_tree_add_text(tree, tvb, offset, 4, "tv_usec: %d", + tvb_get_letohl(tvb, offset)); + offset += 4; + + offset += 4; + + return offset; +} + +static int +dissect_pvfs2_mgmt_remove_object_response(tvbuff_t *tvb, proto_tree *tree, + int offset, packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + /* fs_id */ + offset = dissect_pvfs_fs_id(tvb, tree, offset); + + return offset; +} + +static int +dissect_pvfs2_mgmt_get_dirdata_handle_response(tvbuff_t *tvb, + proto_tree *tree, int offset, packet_info *pinfo) +{ + /* handle */ + offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL); + + return offset; +} + +/* TODO: untested */ +static int +dissect_pvfs2_geteattr_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo _U_) +{ + offset += 4; + + /* Dissect nKey & ds_keyval array */ + offset = dissect_ds_keyval_array(tvb, tree, offset); + + return offset; +} + +static int +dissect_pvfs2_response(tvbuff_t *tvb, proto_tree *tree, int offset, + packet_info *pinfo, guint32 server_op) +{ + /* error code */ + offset = dissect_pvfs2_error(tvb, tree, offset, pinfo); + + switch (server_op) + { + case PVFS_SERV_CREATE: + offset = dissect_pvfs2_create_response(tvb, tree, offset, pinfo); + break; + +#if 0 + case PVFS_SERV_REMOVE: + /* No result data */ + break; +#endif + + case PVFS_SERV_IO: + offset = dissect_pvfs2_io_response(tvb, tree, offset); + break; + + case PVFS_SERV_GETATTR: + offset = dissect_pvfs2_getattr_response(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_SETATTR: + /* No result data */ + break; + + case PVFS_SERV_LOOKUP_PATH: + offset = dissect_pvfs2_lookup_path_response(tvb, tree, offset, pinfo); + break; + +#if 0 + case PVFS_SERV_CRDIRENT: + /* No result data */ + break; +#endif + + case PVFS_SERV_RMDIRENT: + offset = dissect_pvfs2_rmdirent_response(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_CHDIRENT: + offset = dissect_pvfs2_chdirent_response(tvb, tree, offset, pinfo); + break; + +#if 0 + case PVFS_SERV_TRUNCATE: + /* No result data */ + break; +#endif + + case PVFS_SERV_MKDIR: + offset = dissect_pvfs2_mkdir_response(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_READDIR: + offset = dissect_pvfs2_readdir_response(tvb, tree, offset, pinfo); + break; + + case PVFS_SERV_GETCONFIG: + offset = dissect_pvfs2_getconfig_response(tvb, tree, offset); + break; + + case PVFS_SERV_WRITE_COMPLETION: + offset = dissect_pvfs2_write_completion_response(tvb, tree, offset); + break; + +#if 0 + case PVFS_SERV_FLUSH: + /* No result data */ + break; +#endif + + case PVFS_SERV_MGMT_SETPARAM: + offset = dissect_pvfs2_mgmt_setparam_response(tvb, tree, offset); + break; + +#if 0 + case PVFS_SERV_MGMT_NOOP: + /* No result data */ + break; +#endif + + case PVFS_SERV_STATFS: + offset = dissect_pvfs2_statfs_response(tvb, tree, offset); + break; + +#if 0 + case PVFS_SERV_PERF_UPDATE: + /* No result data */ + break; +#endif + + case PVFS_SERV_MGMT_PERF_MON: + offset = dissect_pvfs2_mgmt_perf_mon_response(tvb, tree, offset); + break; + + case PVFS_SERV_MGMT_ITERATE_HANDLES: + offset = dissect_pvfs2_mgmt_iterate_handles_response(tvb, tree, + offset, pinfo); + break; + + case PVFS_SERV_MGMT_DSPACE_INFO_LIST: + offset = dissect_pvfs2_mgmt_dspace_info_list_response(tvb, tree, + offset, pinfo); + break; + + case PVFS_SERV_MGMT_EVENT_MON: + offset = dissect_pvfs2_mgmt_event_mon_response(tvb, tree, offset); + break; + + case PVFS_SERV_MGMT_REMOVE_OBJECT: + offset = dissect_pvfs2_mgmt_remove_object_response(tvb, tree, offset, + pinfo); + break; + +#if 0 + case PVFS_SERV_MGMT_REMOVE_DIRENT: + /* No result data */ + break; +#endif + + case PVFS_SERV_MGMT_GET_DIRDATA_HANDLE: + offset = dissect_pvfs2_mgmt_get_dirdata_handle_response(tvb, tree, + offset, pinfo); + break; + +#if 0 + case PVFS_SERV_JOB_TIMER: + /* No result data */ + break; +#endif + + case PVFS_SERV_PROTO_ERROR: + /* No result data */ + break; + + /* TODO: untested */ + case PVFS_SERV_GETEATTR: + offset = dissect_pvfs2_geteattr_response(tvb, tree, offset, pinfo); + break; + +#if 0 + case PVFS_SERV_SETEATTR: + /* No result data */ + break; +#endif + +#if 0 + case PVFS_SERV_DELEATTR: + /* No result data */ + break; +#endif + + default: + /* TODO: what do we do here? */ + break; + } + + return offset; +} + +static GHashTable *pvfs2_io_tracking_value_table = NULL; + +typedef struct pvfs2_io_tracking_key +{ + guint64 tag; +} pvfs2_io_tracking_key_t; + +typedef struct pvfs2_io_tracking_value +{ + guint32 request_frame_num; + guint32 response_frame_num; + guint32 flow_frame_num; + +} pvfs2_io_tracking_value_t; + +static gint +pvfs2_io_tracking_equal(gconstpointer k1, gconstpointer k2) +{ + const pvfs2_io_tracking_key_t *key1 = (const pvfs2_io_tracking_key_t *) k1; + const pvfs2_io_tracking_key_t *key2 = (const pvfs2_io_tracking_key_t *) k2; + + return (key1->tag == key2->tag); +} + +static guint +pvfs2_io_tracking_hash(gconstpointer k) +{ + const pvfs2_io_tracking_key_t *key = (const pvfs2_io_tracking_key_t *) k; + + return (key->tag >> 32) ^ ((guint32) key->tag); +} + +static void +pvfs2_io_tracking_init(void) +{ + if (pvfs2_io_tracking_value_table != NULL) + g_hash_table_destroy(pvfs2_io_tracking_value_table); + + pvfs2_io_tracking_value_table = g_hash_table_new(pvfs2_io_tracking_hash, + pvfs2_io_tracking_equal); +} + +static pvfs2_io_tracking_value_t * +pvfs2_io_tracking_new_with_tag(guint64 tag, guint32 num) +{ + pvfs2_io_tracking_value_t *value; + pvfs2_io_tracking_key_t *newkey; + + newkey = (pvfs2_io_tracking_key_t *) se_alloc(sizeof(*newkey)); + memset(newkey, 0, sizeof(*newkey)); + newkey->tag = tag; + + value = se_alloc(sizeof(*value)); + memset(value, 0, sizeof(*value)); + + g_hash_table_insert(pvfs2_io_tracking_value_table, newkey, value); + + value->request_frame_num = num; + + return value; +} + +static gboolean +dissect_pvfs_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, + gboolean dissect_other_as_continuation _U_) +{ + guint32 mode = 0; + proto_item *item = NULL, *hitem = NULL; + proto_tree *pvfs_tree = NULL, *pvfs_htree = NULL; + int offset = 0; + guint64 tag; + guint32 server_op; + pvfs2_io_tracking_value_t *val = NULL; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PVFS"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + if (parent_tree) + { + item = proto_tree_add_item(parent_tree, proto_pvfs, tvb, 0, -1, FALSE); + + if (item) + pvfs_tree = proto_item_add_subtree(item, ett_pvfs); + } + + proto_tree_add_text(pvfs_tree, tvb, 0, -1, "Version: 2"); + + /* PVFS packet header is 24 bytes */ + hitem = proto_tree_add_text(pvfs_tree, tvb, 0, BMI_HEADER_SIZE, + "BMI Header"); + if (hitem) + pvfs_htree = proto_item_add_subtree(hitem, ett_pvfs_hdr); + + /* Magic number */ + proto_tree_add_item(pvfs_htree, hf_pvfs_magic_nr, tvb, offset, 4, TRUE); + offset += 4; + + /* TCP message mode (32-bit) */ + mode = tvb_get_letohl(tvb, offset); + proto_tree_add_uint(pvfs_htree, hf_pvfs_mode, tvb, offset, 4, mode); + offset += 4; + + /* tag (64-bit) */ + offset = dissect_pvfs_uint64(tvb, pvfs_htree, offset, hf_pvfs_tag, &tag); + + /* size (64-bit) */ + offset = dissect_pvfs_uint64(tvb, pvfs_htree, offset, hf_pvfs_size, NULL); + + /* Lookahead to get server_op (invalid if frame contains flow data) */ + server_op = tvb_get_letohl(tvb, offset + 8); + + if (mode == TCP_MODE_UNEXP) + { + /* Add entry to tracking table for PVFS_SERV_IO request */ + if ((server_op == PVFS_SERV_IO) && !pinfo->fd->flags.visited) + val = pvfs2_io_tracking_new_with_tag(tag, pinfo->fd->num); + } + else + { + pvfs2_io_tracking_key_t key; + + memset(&key, 0, sizeof(key)); + key.tag = tag; + + val = g_hash_table_lookup(pvfs2_io_tracking_value_table, &key); + + /* If this frame contains a known PVFS_SERV_IO tag, track it */ + if (val && !pinfo->fd->flags.visited) + { + /* If response HAS NOT been seen, mark this frame as response */ + if (val->response_frame_num == 0) + val->response_frame_num = pinfo->fd->num; + else + { + /* If response HAS been seen, this frame is flow data */ + if (val->flow_frame_num == 0) + val->flow_frame_num = pinfo->fd->num; + } + } + } + + if (val && (val->flow_frame_num == pinfo->fd->num)) + { + /* This frame is marked as being flow data */ + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "PVFS flow data"); + + proto_tree_add_text(pvfs_tree, tvb, offset, -1, ""); + + return TRUE; + } + + /* Extract common part of packet found in requests and responses */ + offset = dissect_pvfs2_common_header(tvb, pvfs_htree, offset); + + /* Update column info display */ + if (check_col(pinfo->cinfo, COL_INFO)) + { + col_set_str(pinfo->cinfo, COL_INFO, + val_to_str(server_op, names_pvfs_server_op, "%u (unknown)")); + + col_append_fstr(pinfo->cinfo, COL_INFO, + (mode == TCP_MODE_UNEXP)? " (request)": " (response)"); + } + + /* TODO: handle all modes */ + if (mode == TCP_MODE_UNEXP) + { + /* Request */ + offset = dissect_pvfs2_request(tvb, pvfs_tree, offset, pinfo, server_op); + } + else + { + /* TODO: re-examine this! */ +#if 0 + if (mode == TCP_MODE_REND) + { + /* + * TODO: move this code outside so it's common for requests and + * responses + */ + + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "PVFS2 DATA (request)"); + } + else +#endif + { + /* Response */ + offset = dissect_pvfs2_response(tvb, pvfs_tree, offset, pinfo, + server_op); + } + } + + return TRUE; +} + +/* Register the protocol with Ethereal */ +void +proto_register_pvfs(void) +{ + static hf_register_info hf[] = { + { &hf_pvfs_magic_nr, + { "Magic Number", "pvfs.magic_nr", FT_UINT32, BASE_HEX, + NULL, 0, "Magic Number", HFILL }}, + + { &hf_pvfs_mode, + { "Mode", "pvfs.mode", FT_UINT32, BASE_DEC, + VALS(names_pvfs_mode), 0, "Mode", HFILL }}, + + { &hf_pvfs_tag, + { "Tag", "pvfs.tag", FT_UINT64, BASE_DEC, + NULL, 0, "Tag", HFILL }}, + + { &hf_pvfs_size, + { "Size", "pvfs.size", FT_UINT64, BASE_DEC, + NULL, 0, "Size", HFILL }}, + + { &hf_pvfs_release_number, + { "Release Number", "pvfs.release_number", FT_UINT32, BASE_DEC, + NULL, 0, "Release Number", HFILL }}, + + { &hf_pvfs_encoding, + { "Encoding", "pvfs.encoding", FT_UINT32, BASE_DEC, + VALS(names_pvfs_encoding), 0, "Encoding", HFILL }}, + + { &hf_pvfs_server_op, + { "Server Operation", "pvfs.server_op", FT_UINT32, BASE_DEC, + VALS(names_pvfs_server_op), 0, "Server Operation", HFILL }}, + + { &hf_pvfs_handle, + { "Handle", "pvfs.handle", FT_BYTES, BASE_HEX, + NULL, 0, "Handle", HFILL }}, + + { &hf_pvfs_fs_id, + { "fs_id", "pvfs.fs_id", FT_UINT32, BASE_HEX, + NULL, 0, "File System ID", HFILL }}, + + { &hf_pvfs_attrmask, + { "attrmask", "pvfs.attrmask", FT_UINT32, BASE_HEX, + NULL, 0, "Attribute Mask", HFILL }}, + + { &hf_pvfs_attr, + { "attr", "pvfs.attribute", FT_UINT32, BASE_HEX, + VALS(names_pvfs_attr), 0, "Attribute", HFILL }}, + + { &hf_pvfs_ds_type, + { "ds_type", "pvfs.ds_type", FT_UINT32, BASE_HEX, + VALS(names_pvfs_ds_type), 0, "Type", HFILL }}, + + { &hf_pvfs_error, + { "Result", "pvfs.error", FT_UINT32, BASE_HEX, + VALS(names_pvfs_error), 0, "Result", HFILL }}, + + { &hf_pvfs_atime, + { "atime", "pvfs.atime", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Access Time", HFILL }}, + + { &hf_pvfs_atime_sec, + { "seconds", "pvfs.atime.sec", FT_UINT32, BASE_DEC, + NULL, 0, "Access Time (seconds)", HFILL }}, + + { &hf_pvfs_atime_nsec, + { "microseconds", "pvfs.atime.usec", FT_UINT32, BASE_DEC, + NULL, 0, "Access Time (microseconds)", HFILL }}, + + { &hf_pvfs_mtime, + { "mtime", "pvfs.mtime", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Modify Time", HFILL }}, + + { &hf_pvfs_mtime_sec, + { "seconds", "pvfs.mtime.sec", FT_UINT32, BASE_DEC, + NULL, 0, "Modify Time (seconds)", HFILL }}, + + { &hf_pvfs_mtime_nsec, + { "microseconds", "pvfs.mtime.usec", FT_UINT32, BASE_DEC, + NULL, 0, "Modify Time (microseconds)", HFILL }}, + + { &hf_pvfs_ctime, + { "ctime", "pvfs.ctime", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Creation Time", HFILL }}, + + { &hf_pvfs_ctime_sec, + { "seconds", "pvfs.ctime.sec", FT_UINT32, BASE_DEC, + NULL, 0, "Creation Time (seconds)", HFILL }}, + + { &hf_pvfs_ctime_nsec, + { "microseconds", "pvfs.ctime.usec", FT_UINT32, BASE_DEC, + NULL, 0, "Creation Time (microseconds)", HFILL }}, + + { &hf_pvfs_parent_atime, + { "Parent atime", "pvfs.parent_atime", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Access Time", HFILL }}, + + { &hf_pvfs_parent_atime_sec, + { "seconds", "pvfs.parent_atime.sec", FT_UINT32, BASE_DEC, + NULL, 0, "Access Time (seconds)", HFILL }}, + + { &hf_pvfs_parent_atime_nsec, + { "microseconds", "pvfs.parent_atime.usec", FT_UINT32, BASE_DEC, + NULL, 0, "Access Time (microseconds)", HFILL }}, + + { &hf_pvfs_parent_mtime, + { "Parent mtime", "pvfs.parent_mtime", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Modify Time", HFILL }}, + + { &hf_pvfs_parent_mtime_sec, + { "seconds", "pvfs.parent_mtime.sec", FT_UINT32, BASE_DEC, + NULL, 0, "Modify Time (seconds)", HFILL }}, + + { &hf_pvfs_parent_mtime_nsec, + { "microseconds", "pvfs.parent_mtime.usec", FT_UINT32, BASE_DEC, + NULL, 0, "Modify Time (microseconds)", HFILL }}, + + { &hf_pvfs_parent_ctime, + { "Parent ctime", "pvfs.parent_ctime", FT_ABSOLUTE_TIME, BASE_NONE, + NULL, 0, "Creation Time", HFILL }}, + + { &hf_pvfs_parent_ctime_sec, + { "seconds", "pvfs.parent_ctime.sec", FT_UINT32, BASE_DEC, + NULL, 0, "Creation Time (seconds)", HFILL }}, + + { &hf_pvfs_parent_ctime_nsec, + { "microseconds", "pvfs.parent_ctime.usec", FT_UINT32, BASE_DEC, + NULL, 0, "Creation Time (microseconds)", HFILL }}, + + { &hf_pvfs_dirent_count, + { "Dir Entry Count", "pvfs.dirent_count", FT_UINT64, BASE_DEC, + NULL, 0, "Directory Entry Count", HFILL }}, + + { &hf_pvfs_directory_version, + { "Directory Version", "pvfs.directory_version", FT_UINT64, BASE_HEX, + NULL, 0, "Directory Version", HFILL }}, + + { &hf_pvfs_path, + { "Path", "pvfs.path", FT_STRING, BASE_DEC, + NULL, 0, "Path", HFILL }}, + + { &hf_pvfs_total_completed, + { "Bytes Completed", "pvfs.bytes_completed", FT_UINT64, BASE_DEC, + NULL, 0, "Bytes Completed", HFILL }}, + + { &hf_pvfs_io_dist, + { "Name", "pvfs.distribution.name", FT_STRING, BASE_DEC, + NULL, 0, "Distribution Name", HFILL }}, + + { &hf_pvfs_aggregate_size, + { "Aggregate Size", "pvfs.aggregate_size", FT_UINT64, BASE_DEC, + NULL, 0, "Aggregate Size", HFILL }}, + + { &hf_pvfs_io_type, + { "I/O Type", "pvfs.io_type", FT_UINT32, BASE_DEC, + VALS(names_pvfs_io_type), 0, "I/O Type", HFILL }}, + + { &hf_pvfs_flowproto_type, + { "Flow Protocol Type", "pvfs.flowproto_type", FT_UINT32, BASE_DEC, + VALS(names_pvfs_flowproto_type), 0, "Flow Protocol Type", HFILL }}, + + { &hf_pvfs_server_param, + { "Server Parameter", "pvfs.server_param", FT_UINT32, BASE_DEC, + VALS(names_pvfs_server_param), 0, "Server Parameter", HFILL }}, + + { &hf_pvfs_prev_value, + { "Previous Value", "pvfs.prev_value", FT_UINT64, BASE_DEC, + NULL, 0, "Previous Value", HFILL }}, + + { &hf_pvfs_ram_free_bytes, + { "RAM Free Bytes", "pvfs.ram.free_bytes", FT_UINT64, BASE_DEC, + NULL, 0, "RAM Free Bytes", HFILL }}, + + { &hf_pvfs_bytes_available, + { "Bytes Available", "pvfs.bytes_available", FT_UINT64, BASE_DEC, + NULL, 0, "Bytes Available", HFILL }}, + + { &hf_pvfs_bytes_total, + { "Bytes Total", "pvfs.bytes_total", FT_UINT64, BASE_DEC, + NULL, 0, "Bytes Total", HFILL }}, + + { &hf_pvfs_ram_bytes_total, + { "RAM Bytes Total", "pvfs.ram_bytes_total", FT_UINT64, BASE_DEC, + NULL, 0, "RAM Bytes Total", HFILL }}, + + { &hf_pvfs_ram_bytes_free, + { "RAM Bytes Free", "pvfs.ram_bytes_free", FT_UINT64, BASE_DEC, + NULL, 0, "RAM Bytes Free", HFILL }}, + + { &hf_pvfs_load_average_1s, + { "Load Average (1s)", "pvfs.load_average.1s", FT_UINT64, BASE_DEC, + NULL, 0, "Load Average (1s)", HFILL }}, + + { &hf_pvfs_load_average_5s, + { "Load Average (5s)", "pvfs.load_average.5s", FT_UINT64, BASE_DEC, + NULL, 0, "Load Average (5s)", HFILL }}, + + { &hf_pvfs_load_average_15s, + { "Load Average (15s)", "pvfs.load_average.15s", FT_UINT64, BASE_DEC, + NULL, 0, "Load Average (15s)", HFILL }}, + + { &hf_pvfs_uptime_seconds, + { "Uptime (seconds)", "pvfs.uptime", FT_UINT64, BASE_DEC, + NULL, 0, "Uptime (seconds)", HFILL }}, + + { &hf_pvfs_handles_available, + { "Handles Available", "pvfs.handles_available", FT_UINT64, BASE_DEC, + NULL, 0, "Handles Available", HFILL }}, + + { &hf_pvfs_handles_total, + { "Total Handles", "pvfs.total_handles", FT_UINT64, BASE_DEC, + NULL, 0, "Total Handles", HFILL }}, + + /* + * This is used when the field returns 64-bits but we're only interested + * in the lower 32-bit bits. + */ + { &hf_pvfs_unused, + { "Unused", "", FT_UINT32, BASE_DEC, + NULL, 0, "Unused", HFILL }}, + + { &hf_pvfs_context_id, + { "Context ID", "pvfs.context_id", FT_UINT32, BASE_DEC, + NULL, 0, "Context ID", HFILL }}, + + { &hf_pvfs_offset, + { "Offset", "pvfs.offset", FT_UINT64, BASE_DEC, + NULL, 0, "Offset", HFILL }}, + + { &hf_pvfs_stride, + { "Stride", "pvfs.stride", FT_UINT64, BASE_DEC, + NULL, 0, "Stride", HFILL }}, + + { &hf_pvfs_ub, + { "ub", "pvfs.ub", FT_UINT64, BASE_DEC, + NULL, 0, "ub", HFILL }}, + + { &hf_pvfs_lb, + { "lb", "pvfs.lb", FT_UINT64, BASE_DEC, + NULL, 0, "lb", HFILL }}, + + { &hf_pvfs_end_time_ms, + { "end_time_ms", "pvfs.end_time_ms", FT_UINT64, BASE_DEC, + NULL, 0, "end_time_ms", HFILL }}, + + { &hf_pvfs_cur_time_ms, + { "cur_time_ms", "pvfs.cur_time_ms", FT_UINT64, BASE_DEC, + NULL, 0, "cur_time_ms", HFILL }}, + + { &hf_pvfs_start_time_ms, + { "start_time_ms", "pvfs.start_time_ms", FT_UINT64, BASE_DEC, + NULL, 0, "start_time_ms", HFILL }}, + + { &hf_pvfs_bytes_written, + { "bytes_written", "pvfs.bytes_written", FT_UINT64, BASE_DEC, + NULL, 0, "bytes_written", HFILL }}, + + { &hf_pvfs_bytes_read, + { "bytes_read", "pvfs.bytes_read", FT_UINT64, BASE_DEC, + NULL, 0, "bytes_read", HFILL }}, + + { &hf_pvfs_metadata_write, + { "metadata_write", "pvfs.metadata_write", FT_UINT64, BASE_DEC, + NULL, 0, "metadata_write", HFILL }}, + + { &hf_pvfs_metadata_read, + { "metadata_read", "pvfs.metadata_read", FT_UINT64, BASE_DEC, + NULL, 0, "metadata_read", HFILL }}, + + { &hf_pvfs_b_size, + { "Size of bstream (if applicable)", "pvfs.b_size", FT_UINT64, + BASE_DEC, NULL, 0, "Size of bstream", HFILL }}, + + { &hf_pvfs_k_size, + { "Number of keyvals (if applicable)", "pvfs.k_size", FT_UINT64, + BASE_DEC, NULL, 0, "Number of keyvals", HFILL }}, + + { &hf_pvfs_id_gen_t, + { "id_gen_t", "pvfs.id_gen_t", FT_UINT64, BASE_DEC, + NULL, 0, "id_gen_t", HFILL }}, + + { &hf_pvfs_attribute_key, + { "Attribute key", "pvfs.attribute.key", FT_STRING, BASE_DEC, + NULL, 0, "Attribute key", HFILL }}, + + { &hf_pvfs_attribute_value, + { "Attribute value", "pvfs.attribute.value", FT_STRING, BASE_DEC, + NULL, 0, "Attribute value", HFILL }}, + + { &hf_pvfs_strip_size, + { "Strip size", "pvfs.strip_size", FT_UINT64, BASE_DEC, + NULL, 0, "Strip size (bytes)", HFILL }}, + + /* TODO: need description */ + { &hf_pvfs_ereg, + { "ereg", "pvfs.ereg", FT_INT32, BASE_DEC, + NULL, 0, "ereg", HFILL }}, + + /* TODO: need description */ + { &hf_pvfs_sreg, + { "sreg", "pvfs.sreg", FT_INT32, BASE_DEC, + NULL, 0, "sreg", HFILL }}, + + { &hf_pvfs_num_eregs, + { "Number of eregs", "pvfs.num_eregs", FT_UINT32, BASE_DEC, + NULL, 0, "Number of eregs", HFILL }}, + + { &hf_pvfs_num_blocks, + { "Number of blocks", "pvfs.num_blocks", FT_UINT32, BASE_DEC, + NULL, 0, "Number of blocks", HFILL }}, + + { &hf_pvfs_num_contig_chunks, + { "Number of contig_chunks", "pvfs.num_contig_chunks", FT_UINT32, + BASE_DEC, NULL, 0, "Number of contig_chunks", HFILL }}, + + { &hf_pvfs_server_nr, + { "Server #", "pvfs.server_nr", FT_UINT32, BASE_DEC, + NULL, 0, "Server #", HFILL }}, + + { &hf_pvfs_server_count, + { "Number of servers", "pvfs.server_count", FT_UINT32, BASE_DEC, + NULL, 0, "Number of servers", HFILL }}, + + { &hf_pvfs_fh_length, + { "length", "pvfs.fh.length", FT_UINT32, BASE_DEC, + NULL, 0, "file handle length", HFILL }}, + + { &hf_pvfs_fh_hash, + { "hash", "pvfs.fh.hash", FT_UINT32, BASE_HEX, + NULL, 0, "file handle hash", HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_pvfs, + &ett_pvfs_hdr, + &ett_pvfs_credentials, + &ett_pvfs_server_config, + &ett_pvfs_server_config_branch, + &ett_pvfs_attrmask, + &ett_pvfs_time, + &ett_pvfs_extent_array_tree, + &ett_pvfs_extent_item, + &ett_pvfs_string, + &ett_pvfs_attr_tree, + &ett_pvfs_distribution, + &ett_pvfs_mgmt_perf_stat, + &ett_pvfs_mgmt_dspace_info, + &ett_pvfs_attr, + &ett_pvfs_fh + }; + module_t *pvfs_module; + + /* Register the protocol name and description */ + proto_pvfs = proto_register_protocol("Parallel Virtual File System", + "PVFS", "pvfs"); + + /* + * Required function calls to register the header fields and + * subtrees used + */ + + proto_register_field_array(proto_pvfs, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_init_routine(pvfs2_io_tracking_init); + + pvfs_module = prefs_register_protocol(proto_pvfs, NULL); + prefs_register_bool_preference(pvfs_module, "desegment", + "Reassemble PVFS messages spanning multiple TCP segments", + "Whether the PVFS dissector should reassemble messages spanning multiple TCP segments. " + "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", + &pvfs_desegment); +} + +void +proto_reg_handoff_pvfs(void) +{ + dissector_handle_t pvfs_handle; + + pvfs_handle = new_create_dissector_handle(dissect_pvfs_heur, proto_pvfs); + dissector_add("tcp.port", TCP_PORT_PVFS2, pvfs_handle); + + heur_dissector_add("tcp", dissect_pvfs_heur, proto_pvfs); +} + -- cgit v1.2.3