forked from osmocom/wireshark
![Martin Kaiser](/assets/img/avatar_default.png)
Change-Id: If630e03f82add403cb978969a8ebbb6f0bbcbad0 Reviewed-on: https://code.wireshark.org/review/14064 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
3648 lines
98 KiB
C
3648 lines
98 KiB
C
/* packet-pvfs2.c
|
|
* Routines for pvfs2 packet dissection
|
|
* By Mike Frisch <mfrisch@platform.com>
|
|
* Joint and Several Copyright 2005, Mike Frisch and Platform Computing Inc.
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
|
|
#include <epan/packet.h>
|
|
#include <epan/exceptions.h>
|
|
#include <epan/prefs.h>
|
|
#include <epan/strutil.h>
|
|
#include <epan/expert.h>
|
|
#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_register_pvfs(void);
|
|
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_uid = -1;
|
|
static int hf_pvfs_gid = -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_distribution = -1;
|
|
static int hf_pvfs_dfile_count = -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;
|
|
static int hf_pvfs_permissions = -1;
|
|
static int hf_pvfs_server_mode = -1;
|
|
static int hf_pvfs_depth = -1;
|
|
static int hf_pvfs_num_nested_req = -1;
|
|
static int hf_pvfs_committed = -1;
|
|
static int hf_pvfs_refcount = -1;
|
|
static int hf_pvfs_numreq = -1;
|
|
static int hf_pvfs_truncate_request_flags = -1;
|
|
static int hf_pvfs_ds_position = -1;
|
|
static int hf_pvfs_dirent_limit = -1;
|
|
static int hf_pvfs_flush_request_flags = -1;
|
|
static int hf_pvfs_next_id = -1;
|
|
static int hf_pvfs_mgmt_perf_mon_request_count = -1;
|
|
static int hf_pvfs_mgmt_perf_mon_request_event_count = -1;
|
|
static int hf_pvfs_lookup_path_response_handle_count = -1;
|
|
static int hf_pvfs_getconfig_response_total_bytes = -1;
|
|
static int hf_pvfs_getconfig_response_lines = -1;
|
|
static int hf_pvfs_getconfig_response_config_bytes = -1;
|
|
static int hf_pvfs_mgmt_perf_mon_response_suggested_next_id = -1;
|
|
static int hf_pvfs_mgmt_perf_stat_valid_flag = -1;
|
|
static int hf_pvfs_mgmt_perf_stat_id = -1;
|
|
static int hf_pvfs_mgmt_perf_mon_response_perf_array_count = -1;
|
|
static int hf_pvfs_mgmt_iterate_handles_response_ds_position = -1;
|
|
static int hf_pvfs_mgmt_iterate_handles_response_handle_count = -1;
|
|
static int hf_pvfs_mgmt_dspace_info_list_response_dspace_info_count = -1;
|
|
static int hf_pvfs_mgmt_event_mon_response_api = -1;
|
|
static int hf_pvfs_mgmt_event_mon_response_operation = -1;
|
|
static int hf_pvfs_mgmt_event_mon_response_value = -1;
|
|
static int hf_pvfs_mgmt_event_mon_response_flags = -1;
|
|
static int hf_pvfs_mgmt_event_mon_response_tv_sec = -1;
|
|
static int hf_pvfs_mgmt_event_mon_response_tv_usec = -1;
|
|
static int hf_pvfs_fill_bytes = -1;
|
|
static int hf_pvfs_target_path_len = -1;
|
|
static int hf_pvfs_version2 = -1;
|
|
static int hf_pvfs_flow_data = -1;
|
|
static int hf_pvfs_getconfig_response_entry = -1;
|
|
static int hf_fhandle_data = -1;
|
|
static int hf_pvfs_opaque_length = -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;
|
|
|
|
static expert_field ei_pvfs_malformed = EI_INIT;
|
|
|
|
#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 int dissect_pvfs_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|
{
|
|
dissect_pvfs_common(tvb, pinfo, tree, FALSE);
|
|
return tvb_reported_length(tvb);
|
|
}
|
|
|
|
static guint get_pvfs_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
|
|
int offset, void *data _U_)
|
|
{
|
|
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, void *data)
|
|
{
|
|
guint32 magic_nr, mode;
|
|
guint64 size;
|
|
|
|
/* verify that this is indeed PVFS and that it looks sane */
|
|
if(tvb_reported_length(tvb)<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, data);
|
|
|
|
return tvb_reported_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)
|
|
{
|
|
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_tree *hcred_tree;
|
|
guint32 uid, gid;
|
|
|
|
uid = tvb_get_letohl(tvb, offset);
|
|
gid = tvb_get_letohl(tvb, offset + 4);
|
|
|
|
hcred_tree = proto_tree_add_subtree_format(parent_tree, tvb, offset, 8,
|
|
ett_pvfs_credentials, NULL, "Credentials (UID: %d, GID: %d)", uid, gid);
|
|
|
|
/* UID */
|
|
proto_tree_add_item(hcred_tree, hf_pvfs_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* GID */
|
|
proto_tree_add_item(hcred_tree, hf_pvfs_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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, i;
|
|
proto_item *attritem;
|
|
proto_tree *attrtree;
|
|
|
|
attrmask = tvb_get_letohl(tvb, offset);
|
|
|
|
attritem = proto_tree_add_uint(tree, hf_pvfs_attrmask, tvb, offset, 4, attrmask);
|
|
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;
|
|
|
|
ds_type = tvb_get_letohl(tvb, offset);
|
|
|
|
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, const 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;
|
|
const 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_captured_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_captured_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_string_enc(wmem_packet_scope(), tvb, data_offset,
|
|
string_length_copy, ENC_ASCII);
|
|
|
|
string_buffer = (char *)memcpy(wmem_alloc(wmem_packet_scope(), string_length_copy+1), tmpstr, string_length_copy);
|
|
} else {
|
|
string_buffer = (char *) tvb_memcpy(tvb,
|
|
wmem_alloc(wmem_packet_scope(), 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;
|
|
size_t string_buffer_size = 0;
|
|
char *string_buffer_temp;
|
|
|
|
formatted = format_text((guint8 *)string_buffer,
|
|
(int)strlen(string_buffer));
|
|
|
|
string_buffer_size = strlen(formatted) + 12 + 1;
|
|
|
|
/* alloc maximum data area */
|
|
string_buffer_temp = (char*) wmem_alloc(wmem_packet_scope(), string_buffer_size);
|
|
/* copy over the data */
|
|
g_snprintf(string_buffer_temp, (gulong)string_buffer_size,
|
|
"%s<TRUNCATED>", formatted);
|
|
/* append <TRUNCATED> */
|
|
/* 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).
|
|
*/
|
|
string_buffer_print = string_buffer_temp;
|
|
} else {
|
|
string_buffer_print="<DATA><TRUNCATED>";
|
|
}
|
|
} else {
|
|
if (string_data) {
|
|
string_buffer_print =
|
|
wmem_strdup(wmem_packet_scope(), format_text((guint8 *) string_buffer,
|
|
(int)strlen(string_buffer)));
|
|
} else {
|
|
string_buffer_print="<DATA>";
|
|
}
|
|
}
|
|
} else {
|
|
string_buffer_print="<EMPTY>";
|
|
}
|
|
|
|
string_item = proto_tree_add_string(tree, hfindex, tvb, offset+0, -1,
|
|
string_buffer_print);
|
|
|
|
string_tree = proto_item_add_subtree(string_item,
|
|
ett_pvfs_string);
|
|
|
|
if (!fixed_length) {
|
|
proto_tree_add_uint_format_value(string_tree, hf_pvfs_opaque_length, tvb, offset, 4,
|
|
string_length - 1, "%u (excl. NULL terminator)", string_length - 1);
|
|
offset += 4;
|
|
}
|
|
|
|
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_bytes_format_value(string_tree, hf_pvfs_fill_bytes, tvb,
|
|
offset, fill_length_copy, NULL,
|
|
"opaque data <TRUNCATED>");
|
|
}
|
|
else {
|
|
proto_tree_add_bytes_format_value(string_tree, hf_pvfs_fill_bytes, tvb,
|
|
offset, fill_length_copy, NULL,
|
|
"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, const 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 bytes_left = PVFS2_FH_LENGTH;
|
|
|
|
proto_tree_add_item(tree, hf_fhandle_data, tvb, offset, bytes_left, ENC_NA);
|
|
}
|
|
|
|
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_tree* ftree;
|
|
|
|
ftree = proto_tree_add_subtree(tree, tvb, offset, PVFS2_FH_LENGTH,
|
|
ett_pvfs_fh, NULL, name);
|
|
|
|
/* 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_tree *extent_tree;
|
|
|
|
extent_tree = proto_tree_add_subtree_format(tree, tvb, offset, 8,
|
|
ett_pvfs_extent_item, NULL, "Item %d", nCount);
|
|
|
|
/* 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;
|
|
guint32 nCount;
|
|
proto_tree *extent_array_tree;
|
|
|
|
/* extent count */
|
|
extent_count = tvb_get_letohl(tvb, offset);
|
|
|
|
extent_array_tree = proto_tree_add_subtree_format(tree, tvb, offset, 4,
|
|
ett_pvfs_extent_array_tree, NULL, "Handle Extent Array (count = %d)", extent_count);
|
|
|
|
offset += 4;
|
|
|
|
if (extent_count > 0)
|
|
{
|
|
/* 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;
|
|
proto_tree *time_tree;
|
|
|
|
ts.secs = seconds = tvb_get_letohl(tvb, offset);
|
|
ts.nsecs = nseconds = tvb_get_letohl(tvb, offset + 4);
|
|
|
|
time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8, &ts);
|
|
time_tree = proto_item_add_subtree(time_item, ett_pvfs_time);
|
|
|
|
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 = tvb_get_letoh64(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;
|
|
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_string_enc(wmem_packet_scope(), tvb, offset + 4, distlen, ENC_ASCII);
|
|
|
|
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) &&
|
|
(g_ascii_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_string(tree, hf_pvfs_distribution, tvb, offset,
|
|
total_len + 8, tmpstr);
|
|
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,
|
|
NULL);
|
|
|
|
/* 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_uint(tree, hf_pvfs_dfile_count, tvb, offset, 4, 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_tree *attr_tree;
|
|
|
|
attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_pvfs_attr_tree, NULL, "Attributes");
|
|
|
|
/* UID */
|
|
proto_tree_add_item(attr_tree, hf_pvfs_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* GID */
|
|
proto_tree_add_item(attr_tree, hf_pvfs_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* Permissions */
|
|
proto_tree_add_item(attr_tree, hf_pvfs_permissions, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(attr_tree, hf_pvfs_target_path_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_io_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_pvfs_flowproto_type(tvbuff_t *tvb, proto_tree *tree, int offset)
|
|
{
|
|
proto_tree_add_item(tree, hf_pvfs_flowproto_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_pvfs_server_param(tvbuff_t *tvb, proto_tree *tree, int offset,
|
|
packet_info *pinfo)
|
|
{
|
|
guint32 server_param;
|
|
proto_item* ti;
|
|
|
|
/* 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:
|
|
ti = proto_tree_add_item(tree, hf_pvfs_server_mode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
proto_item_set_len(ti, 8);
|
|
break;
|
|
|
|
case PVFS_SERV_PARAM_FSID_CHECK:
|
|
proto_tree_add_item(tree, hf_pvfs_fs_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
proto_tree_add_item(tree, hf_pvfs_unused, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
|
|
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)
|
|
{
|
|
proto_tree_add_item(tree, hf_pvfs_fs_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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)
|
|
{
|
|
/* offset */
|
|
proto_tree_add_item(tree, hf_pvfs_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* TODO: num_eregs */
|
|
proto_tree_add_item(tree, hf_pvfs_num_eregs, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* TODO: num_blocks */
|
|
proto_tree_add_item(tree, hf_pvfs_num_blocks, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* TODO: stride */
|
|
proto_tree_add_item(tree, hf_pvfs_stride, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* TODO: ub */
|
|
proto_tree_add_item(tree, hf_pvfs_ub, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* TODO: lb */
|
|
proto_tree_add_item(tree, hf_pvfs_lb, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* TODO: aggregate size */
|
|
proto_tree_add_item(tree, hf_pvfs_aggregate_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* num_contig_chunks */
|
|
proto_tree_add_item(tree, hf_pvfs_num_contig_chunks, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* depth */
|
|
proto_tree_add_item(tree, hf_pvfs_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* num_nested_req */
|
|
proto_tree_add_item(tree, hf_pvfs_num_nested_req, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* committed */
|
|
proto_tree_add_item(tree, hf_pvfs_committed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* refcount */
|
|
proto_tree_add_item(tree, hf_pvfs_refcount, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* documented */
|
|
offset += 4;
|
|
|
|
/* ereg */
|
|
proto_tree_add_item(tree, hf_pvfs_ereg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* sreg */
|
|
proto_tree_add_item(tree, hf_pvfs_sreg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_pvfs2_io_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);
|
|
|
|
/* 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_item(tree, hf_pvfs_server_nr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* server_ct */
|
|
proto_tree_add_item(tree, hf_pvfs_server_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* Distribution */
|
|
offset = dissect_pvfs_distribution(tvb, tree, offset);
|
|
|
|
proto_tree_add_item(tree, hf_pvfs_numreq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* */
|
|
offset += 4;
|
|
|
|
/*offset = */dissect_pvfs_pint_request(tvb, tree, offset);
|
|
|
|
/* TODO: remove this!!! */
|
|
offset = tvb_reported_length(tvb) - 16;
|
|
|
|
/* offset */
|
|
proto_tree_add_item(tree, hf_pvfs_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* size */
|
|
proto_tree_add_item(tree, hf_pvfs_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
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)
|
|
{
|
|
/* handle */
|
|
offset = dissect_pvfs_fh(tvb, offset, pinfo, tree, "handle", NULL);
|
|
|
|
/* fs_id */
|
|
offset = dissect_pvfs_fs_id(tvb, tree, offset);
|
|
|
|
offset += 4;
|
|
|
|
/* size */
|
|
proto_tree_add_item(tree, hf_pvfs_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
/* TODO: flags */
|
|
proto_tree_add_item(tree, hf_pvfs_truncate_request_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_ds_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* dirent_limit */
|
|
proto_tree_add_item(tree, hf_pvfs_dirent_limit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_flush_request_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_next_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* TODO: count */
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_perf_mon_request_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_mgmt_perf_mon_request_event_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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 void
|
|
pvfc_fmt_release_num(gchar *result, guint32 release_nr)
|
|
{
|
|
g_snprintf( result, ITEM_LABEL_LENGTH, "%d (%d.%d.%d)",
|
|
release_nr,
|
|
release_nr / 10000,
|
|
(release_nr % 10000) / 100,
|
|
(release_nr % 10000) % 100);
|
|
}
|
|
|
|
static int
|
|
dissect_pvfs2_common_header(tvbuff_t *tvb, proto_tree *tree, int offset)
|
|
{
|
|
/* PVFS release number */
|
|
proto_tree_add_item(tree, hf_pvfs_release_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* wire encoding type */
|
|
proto_tree_add_item(tree, hf_pvfs_encoding, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* server op */
|
|
proto_tree_add_item(tree, hf_pvfs_server_op, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_context_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_tree *attr_tree;
|
|
|
|
offset += 4;
|
|
|
|
/* handle_count */
|
|
handle_count = tvb_get_letohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_pvfs_lookup_path_response_handle_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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);
|
|
|
|
attr_tree = proto_tree_add_subtree_format(tree, tvb, offset, 4,
|
|
ett_pvfs_attr, NULL, "Attribute array (total items: %d)", attr_count);
|
|
|
|
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)
|
|
{
|
|
guint32 dirent_count = 0;
|
|
guint32 nCount = 0;
|
|
|
|
/* ds_position */
|
|
proto_tree_add_item(tree, hf_pvfs_ds_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
offset += 4;
|
|
|
|
/* directory_version */
|
|
proto_tree_add_item(tree, hf_pvfs_directory_version, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
offset += 8;
|
|
|
|
offset += 4;
|
|
|
|
/* dirent_count */
|
|
dirent_count = tvb_get_letohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_pvfs_dirent_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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, packet_info *pinfo)
|
|
{
|
|
guint32 i;
|
|
guint32 total_bytes = 0, total_config_bytes = 0, total_lines = 0;
|
|
guint32 bytes_processed = 0;
|
|
guint32 length_remaining = 0;
|
|
const char *ptr = NULL;
|
|
proto_tree *tree, *config_tree = NULL;
|
|
/*guint8 truncated = 0;*/
|
|
|
|
tree = proto_tree_add_subtree(parent_tree, tvb, offset, 12,
|
|
ett_pvfs_server_config, NULL, "Server Config");
|
|
|
|
/* Total number of bytes in server config (incl. entry count) */
|
|
total_bytes = tvb_get_letohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_pvfs_getconfig_response_total_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_getconfig_response_lines, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* Number of bytes in server config */
|
|
total_config_bytes = tvb_get_letohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_pvfs_getconfig_response_config_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* Get pointer to server config data */
|
|
ptr = tvb_get_ptr(tvb, offset, total_config_bytes);
|
|
|
|
/* Check if all data is available */
|
|
length_remaining = tvb_captured_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) && (!g_ascii_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_tree = proto_tree_add_subtree(tree, tvb, offset,
|
|
tmp_entry_length, ett_pvfs_server_config_branch, NULL, tmp_entry);
|
|
}
|
|
else
|
|
{
|
|
/* Closing token */
|
|
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_string_format(config_tree, hf_pvfs_getconfig_response_entry, tvb, offset, tmp_entry_length,
|
|
tmp_entry, "%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_expert(config_tree, pinfo, &ei_pvfs_malformed, 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)
|
|
{
|
|
/* old_value */
|
|
proto_tree_add_item(tree, hf_pvfs_prev_value, tvb, offset, 8, ENC_LITTLE_ENDIAN);
|
|
|
|
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_tree *stat_tree;
|
|
|
|
stat_tree = proto_tree_add_subtree_format(tree, tvb, offset, 48,
|
|
ett_pvfs_mgmt_perf_stat, NULL, "Stat Array - Element %d", nItem);
|
|
|
|
/* TODO: valid_flag */
|
|
proto_tree_add_item(stat_tree, hf_pvfs_mgmt_perf_stat_valid_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* TODO: id */
|
|
proto_tree_add_item(stat_tree, hf_pvfs_mgmt_perf_stat_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_mgmt_perf_mon_response_suggested_next_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_mgmt_perf_mon_response_perf_array_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_item(tree, hf_pvfs_mgmt_iterate_handles_response_ds_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* handle_count */
|
|
handle_count = tvb_get_letohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_iterate_handles_response_handle_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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_tree *arr_tree = NULL;
|
|
|
|
offset += 4;
|
|
|
|
/* dspace_info_count */
|
|
dspace_info_count = tvb_get_letohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_dspace_info_list_response_dspace_info_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
|
|
if ((dspace_info_count > 0) && (tree))
|
|
{
|
|
arr_tree = proto_tree_add_subtree_format(tree, tvb, offset,
|
|
dspace_info_count * 40, ett_pvfs_mgmt_dspace_info, NULL, "dspace_info Array (%d items)",
|
|
dspace_info_count);
|
|
}
|
|
|
|
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_item(tree, hf_pvfs_mgmt_event_mon_response_api, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* operation */
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_event_mon_response_operation, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* value */
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_event_mon_response_value, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* id */
|
|
offset = dissect_pvfs_uint64(tvb, tree, offset, hf_pvfs_id_gen_t,
|
|
NULL);
|
|
|
|
/* flags */
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_event_mon_response_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* tv_sec */
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_event_mon_response_tv_sec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* tv_usec */
|
|
proto_tree_add_item(tree, hf_pvfs_mgmt_event_mon_response_tv_usec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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, pinfo);
|
|
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 (guint) ((key->tag >> 32) ^ ((guint32) key->tag));
|
|
}
|
|
|
|
static void
|
|
pvfs2_io_tracking_init(void)
|
|
{
|
|
pvfs2_io_tracking_value_table = g_hash_table_new(pvfs2_io_tracking_hash,
|
|
pvfs2_io_tracking_equal);
|
|
}
|
|
|
|
static void
|
|
pvfs2_io_tracking_cleanup(void)
|
|
{
|
|
g_hash_table_destroy(pvfs2_io_tracking_value_table);
|
|
}
|
|
|
|
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 = wmem_new0(wmem_file_scope(), pvfs2_io_tracking_key_t);
|
|
newkey->tag = tag;
|
|
|
|
value = wmem_new0(wmem_file_scope(), pvfs2_io_tracking_value_t);
|
|
|
|
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;
|
|
proto_tree *pvfs_tree = NULL, *pvfs_htree = NULL;
|
|
int offset = 0;
|
|
guint64 tag;
|
|
guint32 server_op;
|
|
pvfs2_io_tracking_value_t *val = NULL;
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PVFS");
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
item = proto_tree_add_item(parent_tree, proto_pvfs, tvb, 0, -1, ENC_NA);
|
|
pvfs_tree = proto_item_add_subtree(item, ett_pvfs);
|
|
|
|
proto_tree_add_item(pvfs_tree, hf_pvfs_version2, tvb, 0, -1, ENC_NA);
|
|
|
|
/* PVFS packet header is 24 bytes */
|
|
pvfs_htree = proto_tree_add_subtree(pvfs_tree, tvb, 0, BMI_HEADER_SIZE,
|
|
ett_pvfs_hdr, NULL, "BMI Header");
|
|
|
|
/* Magic number */
|
|
proto_tree_add_item(pvfs_htree, hf_pvfs_magic_nr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
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->num);
|
|
}
|
|
else
|
|
{
|
|
pvfs2_io_tracking_key_t key;
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
key.tag = tag;
|
|
|
|
val = (pvfs2_io_tracking_value_t *)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->num;
|
|
else
|
|
{
|
|
/* If response HAS been seen, this frame is flow data */
|
|
if (val->flow_frame_num == 0)
|
|
val->flow_frame_num = pinfo->num;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (val && (val->flow_frame_num == pinfo->num))
|
|
{
|
|
/* This frame is marked as being flow data */
|
|
col_set_str(pinfo->cinfo, COL_INFO, "PVFS flow data");
|
|
|
|
proto_tree_add_item(pvfs_tree, hf_pvfs_flow_data, tvb, offset, -1, ENC_NA);
|
|
|
|
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 */
|
|
col_add_str(pinfo->cinfo, COL_INFO,
|
|
val_to_str(server_op, names_pvfs_server_op, "%u (unknown)"));
|
|
|
|
col_append_str(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
|
|
*/
|
|
|
|
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 Wireshark */
|
|
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, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_uid,
|
|
{ "UID", "pvfs.uid", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_gid,
|
|
{ "GID", "pvfs.gid", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mode,
|
|
{ "Mode", "pvfs.mode", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_mode), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_tag,
|
|
{ "Tag", "pvfs.tag", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_size,
|
|
{ "Size", "pvfs.size", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_release_number,
|
|
{ "Release Number", "pvfs.release_number", FT_UINT32, BASE_CUSTOM,
|
|
CF_FUNC(pvfc_fmt_release_num), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_encoding,
|
|
{ "Encoding", "pvfs.encoding", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_encoding), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_server_op,
|
|
{ "Server Operation", "pvfs.server_op", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_server_op), 0, NULL, HFILL }},
|
|
|
|
#if 0
|
|
{ &hf_pvfs_handle,
|
|
{ "Handle", "pvfs.handle", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
#endif
|
|
|
|
{ &hf_pvfs_fs_id,
|
|
{ "fs_id", "pvfs.fs_id", FT_UINT32, BASE_HEX,
|
|
NULL, 0, "File System ID", HFILL }},
|
|
|
|
{ &hf_pvfs_attrmask,
|
|
{ "Attribute Mask", "pvfs.attrmask", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, 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, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_atime,
|
|
{ "atime", "pvfs.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
|
|
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, ABSOLUTE_TIME_LOCAL,
|
|
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, ABSOLUTE_TIME_LOCAL,
|
|
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, ABSOLUTE_TIME_LOCAL,
|
|
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, ABSOLUTE_TIME_LOCAL,
|
|
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, ABSOLUTE_TIME_LOCAL,
|
|
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_dfile_count,
|
|
{ "dfile_count", "pvfs.dfile_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_distribution,
|
|
{ "Distribution", "pvfs.distribution", FT_STRING, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_dirent_count,
|
|
{ "Dir Entry Count", "pvfs.dirent_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, "Directory Entry Count", HFILL }},
|
|
|
|
{ &hf_pvfs_directory_version,
|
|
{ "Directory Version", "pvfs.directory_version", FT_UINT64, BASE_HEX,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_path,
|
|
{ "Path", "pvfs.path", FT_STRING, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_total_completed,
|
|
{ "Bytes Completed", "pvfs.bytes_completed", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_io_dist,
|
|
{ "Name", "pvfs.distribution.name", FT_STRING, BASE_NONE,
|
|
NULL, 0, "Distribution Name", HFILL }},
|
|
|
|
{ &hf_pvfs_aggregate_size,
|
|
{ "Aggregate Size", "pvfs.aggregate_size", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_io_type,
|
|
{ "I/O Type", "pvfs.io_type", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_io_type), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_flowproto_type,
|
|
{ "Flow Protocol Type", "pvfs.flowproto_type", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_flowproto_type), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_server_param,
|
|
{ "Server Parameter", "pvfs.server_param", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_server_param), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_prev_value,
|
|
{ "Previous Value", "pvfs.prev_value", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
#if 0
|
|
{ &hf_pvfs_ram_free_bytes,
|
|
{ "RAM Free Bytes", "pvfs.ram.free_bytes", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
#endif
|
|
|
|
{ &hf_pvfs_bytes_available,
|
|
{ "Bytes Available", "pvfs.bytes_available", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_bytes_total,
|
|
{ "Bytes Total", "pvfs.bytes_total", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_ram_bytes_total,
|
|
{ "RAM Bytes Total", "pvfs.ram_bytes_total", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_ram_bytes_free,
|
|
{ "RAM Bytes Free", "pvfs.ram_bytes_free", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_load_average_1s,
|
|
{ "Load Average (1s)", "pvfs.load_average.1s", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_load_average_5s,
|
|
{ "Load Average (5s)", "pvfs.load_average.5s", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_load_average_15s,
|
|
{ "Load Average (15s)", "pvfs.load_average.15s", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_uptime_seconds,
|
|
{ "Uptime (seconds)", "pvfs.uptime", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_handles_available,
|
|
{ "Handles Available", "pvfs.handles_available", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_handles_total,
|
|
{ "Total Handles", "pvfs.total_handles", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, 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", "pvfs.unused", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_context_id,
|
|
{ "Context ID", "pvfs.context_id", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_offset,
|
|
{ "Offset", "pvfs.offset", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_stride,
|
|
{ "Stride", "pvfs.stride", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_ub,
|
|
{ "ub", "pvfs.ub", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_lb,
|
|
{ "lb", "pvfs.lb", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_end_time_ms,
|
|
{ "end_time_ms", "pvfs.end_time_ms", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_cur_time_ms,
|
|
{ "cur_time_ms", "pvfs.cur_time_ms", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_start_time_ms,
|
|
{ "start_time_ms", "pvfs.start_time_ms", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_bytes_written,
|
|
{ "bytes_written", "pvfs.bytes_written", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_bytes_read,
|
|
{ "bytes_read", "pvfs.bytes_read", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_metadata_write,
|
|
{ "metadata_write", "pvfs.metadata_write", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_metadata_read,
|
|
{ "metadata_read", "pvfs.metadata_read", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, 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, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_attribute_key,
|
|
{ "Attribute key", "pvfs.attribute.key", FT_STRING, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_attribute_value,
|
|
{ "Attribute value", "pvfs.attribute.value", FT_STRING, BASE_NONE,
|
|
NULL, 0, NULL, 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, NULL, HFILL }},
|
|
|
|
/* TODO: need description */
|
|
{ &hf_pvfs_sreg,
|
|
{ "sreg", "pvfs.sreg", FT_INT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_num_eregs,
|
|
{ "Number of eregs", "pvfs.num_eregs", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_num_blocks,
|
|
{ "Number of blocks", "pvfs.num_blocks", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_num_contig_chunks,
|
|
{ "Number of contig_chunks", "pvfs.num_contig_chunks", FT_UINT32,
|
|
BASE_DEC, NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_server_nr,
|
|
{ "Server #", "pvfs.server_nr", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_server_count,
|
|
{ "Number of servers", "pvfs.server_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, 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 }},
|
|
|
|
{ &hf_pvfs_permissions,
|
|
{ "Permissions", "pvfs.permissions", FT_UINT32, BASE_OCT,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_server_mode,
|
|
{ "Server Mode", "pvfs.server_mode", FT_UINT32, BASE_DEC,
|
|
VALS(names_pvfs_server_mode), 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_depth,
|
|
{ "depth", "pvfs.depth", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_num_nested_req,
|
|
{ "num_nested_req", "pvfs.num_nested_req", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_committed,
|
|
{ "committed", "pvfs.committed", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_refcount,
|
|
{ "refcount", "pvfs.refcount", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_numreq,
|
|
{ "numreq", "pvfs.numreq", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_truncate_request_flags,
|
|
{ "flags", "pvfs.truncate_request_flags", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_ds_position,
|
|
{ "ds_position", "pvfs.ds_position", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_dirent_limit,
|
|
{ "dirent_limit", "pvfs.dirent_limit", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_flush_request_flags,
|
|
{ "flags", "pvfs.flush_request_flags", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_next_id,
|
|
{ "next_id", "pvfs.next_id", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_perf_mon_request_count,
|
|
{ "count", "pvfs.mgmt_perf_mon_request.count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_perf_mon_request_event_count,
|
|
{ "Event count", "pvfs.mgmt_perf_mon_request.event_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_lookup_path_response_handle_count,
|
|
{ "Handle Count", "pvfs.lookup_path_response.handle_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_getconfig_response_total_bytes,
|
|
{ "Total Bytes", "pvfs.getconfig_response.total_bytes", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_getconfig_response_lines,
|
|
{ "Lines", "pvfs.getconfig_response.lines", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_getconfig_response_config_bytes,
|
|
{ "Config Bytes", "pvfs.getconfig_response.config_bytes", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_perf_stat_valid_flag,
|
|
{ "valid_flag", "pvfs.mgmt_perf_stat.valid_flag", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_perf_stat_id,
|
|
{ "id", "pvfs.mgmt_perf_stat.id", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_perf_mon_response_suggested_next_id,
|
|
{ "suggested_next_id", "pvfs.mgmt_perf_mon_response.suggested_next_id", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_perf_mon_response_perf_array_count,
|
|
{ "perf_array_count", "pvfs.mgmt_perf_mon_response.perf_array_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_iterate_handles_response_ds_position,
|
|
{ "ds_position", "pvfs.mgmt_iterate_handles_response.ds_position", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_iterate_handles_response_handle_count,
|
|
{ "handle_count", "pvfs.mgmt_iterate_handles_response.handle_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_dspace_info_list_response_dspace_info_count,
|
|
{ "dspace_info_count", "pvfs.mgmt_dspace_info_list_response.dspace_info_count", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_event_mon_response_api,
|
|
{ "api", "pvfs.mgmt_event_mon_response.api", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_event_mon_response_operation,
|
|
{ "operation", "pvfs.mgmt_event_mon_response.operation", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_event_mon_response_value,
|
|
{ "value", "pvfs.mgmt_event_mon_response.value", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_event_mon_response_flags,
|
|
{ "flags", "pvfs.mgmt_event_mon_response.flags", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_event_mon_response_tv_sec,
|
|
{ "tv_sec", "pvfs.mgmt_event_mon_response.tv_sec", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_mgmt_event_mon_response_tv_usec,
|
|
{ "tv_usec", "pvfs.mgmt_event_mon_response.tv_usec", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_fill_bytes,
|
|
{ "fill_bytes", "pvfs.fill_bytes", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_target_path_len,
|
|
{ "target_path_len", "pvfs.target_path_len", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_version2,
|
|
{ "Version 2", "pvfs.version2", FT_NONE, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_flow_data,
|
|
{ "PVFC Flow Data", "pvfs.flow_data", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_getconfig_response_entry,
|
|
{ "GETCONFIG Response entry", "pvfs.getconfig_response_entry", FT_STRING, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_fhandle_data,
|
|
{ "data", "pvfs.fhandle_data", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL }},
|
|
|
|
{ &hf_pvfs_opaque_length,
|
|
{ "length", "pvfs.opaque_length", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, 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
|
|
};
|
|
|
|
static ei_register_info ei[] = {
|
|
{ &ei_pvfs_malformed, { "pvfs.malformed", PI_MALFORMED, PI_ERROR, "MALFORMED OR TRUNCATED DATA", EXPFILL }},
|
|
};
|
|
|
|
module_t *pvfs_module;
|
|
expert_module_t* expert_pvfs;
|
|
|
|
/* 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));
|
|
expert_pvfs = expert_register_protocol(proto_pvfs);
|
|
expert_register_field_array(expert_pvfs, ei, array_length(ei));
|
|
|
|
register_init_routine(pvfs2_io_tracking_init);
|
|
register_cleanup_routine(pvfs2_io_tracking_cleanup);
|
|
|
|
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 = create_dissector_handle(dissect_pvfs_heur, proto_pvfs);
|
|
dissector_add_uint("tcp.port", TCP_PORT_PVFS2, pvfs_handle);
|
|
|
|
heur_dissector_add("tcp", dissect_pvfs_heur, "PVFS over TCP", "pvfs_tcp", proto_pvfs, HEURISTIC_ENABLE);
|
|
}
|
|
|
|
/*
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 8
|
|
* tab-width: 8
|
|
* indent-tabs-mode: t
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
*/
|